From 82a900b438faa9f432ae4f8a1819776faf450737 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Wed, 13 Jul 2022 18:30:12 -0400 Subject: [PATCH] Initial commit to add Dilithium NIST PQC winner. Also: * added HAVE_FALCON guards as needed. * corrected minor falcon bugs as I found them. * handling OID sum collision between DILITHIUM_LEVEL5 and DILITHIUM_AES_LEVEL3 Tested with the following commands: examples/server/server -v 4 -l TLS_AES_256_GCM_SHA384 \ -c ~/tmp/dilithium_aes_level5_entity_cert.pem \ -k ~/tmp/dilithium_aes_level5_entity_key.pem \ -A ~/tmp/dilithium_aes_level5_root_cert.pem --pqc P521_KYBER_LEVEL5 examples/client/client -v 4 -l TLS_AES_256_GCM_SHA384 \ -c ~/tmp/dilithium_aes_level5_entity_cert.pem \ -k ~/tmp/dilithium_aes_level5_entity_key.pem \ -A ~/tmp/dilithium_aes_level5_root_cert.pem --pqc P521_KYBER_LEVEL5 with permutations of SHAKE,AES variants and levels 2,3,5 --- .../bench_dilithium_aes_level2_key.der | Bin 0 -> 3870 bytes .../bench_dilithium_aes_level3_key.der | Bin 0 -> 5982 bytes .../bench_dilithium_aes_level5_key.der | Bin 0 -> 7486 bytes .../dilithium/bench_dilithium_level2_key.der | Bin 0 -> 3870 bytes .../dilithium/bench_dilithium_level3_key.der | Bin 0 -> 5982 bytes .../dilithium/bench_dilithium_level5_key.der | Bin 0 -> 7486 bytes certs/dilithium/include.am | 11 + certs/include.am | 1 + gencertbuf.pl | 33 +- rpm/spec.in | 3 + src/include.am | 1 + src/internal.c | 528 ++- src/ssl.c | 401 +- src/tls13.c | 210 +- wolfcrypt/benchmark/benchmark.c | 261 +- wolfcrypt/benchmark/benchmark.h | 1 + wolfcrypt/src/asn.c | 1180 ++++-- wolfcrypt/src/dilithium.c | 1028 +++++ wolfcrypt/src/falcon.c | 162 +- wolfssl/certs_test.h | 3512 +++++++++++++++++ wolfssl/error-ssl.h | 1 + wolfssl/internal.h | 74 +- wolfssl/openssl/evp.h | 1 + wolfssl/wolfcrypt/asn.h | 67 +- wolfssl/wolfcrypt/asn_public.h | 41 +- wolfssl/wolfcrypt/dilithium.h | 142 + wolfssl/wolfcrypt/include.am | 1 + wolfssl/wolfcrypt/settings.h | 1 + wolfssl/wolfcrypt/types.h | 1 + 29 files changed, 7222 insertions(+), 439 deletions(-) create mode 100644 certs/dilithium/bench_dilithium_aes_level2_key.der create mode 100644 certs/dilithium/bench_dilithium_aes_level3_key.der create mode 100644 certs/dilithium/bench_dilithium_aes_level5_key.der create mode 100644 certs/dilithium/bench_dilithium_level2_key.der create mode 100644 certs/dilithium/bench_dilithium_level3_key.der create mode 100644 certs/dilithium/bench_dilithium_level5_key.der create mode 100644 certs/dilithium/include.am create mode 100644 wolfcrypt/src/dilithium.c create mode 100644 wolfssl/wolfcrypt/dilithium.h diff --git a/certs/dilithium/bench_dilithium_aes_level2_key.der b/certs/dilithium/bench_dilithium_aes_level2_key.der new file mode 100644 index 0000000000000000000000000000000000000000..1d6744e27694363ddbdb74231012afa532f95af0 GIT binary patch literal 3870 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 literal 0 HcmV?d00001 diff --git a/certs/dilithium/bench_dilithium_aes_level3_key.der b/certs/dilithium/bench_dilithium_aes_level3_key.der new file mode 100644 index 0000000000000000000000000000000000000000..d6dc3c22fe719d1a479bb280e0b8b13435bd88a1 GIT binary patch literal 5982 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 TpE7UWA-$XRkaSgD_enMYv43Jv literal 0 HcmV?d00001 diff --git a/certs/dilithium/bench_dilithium_aes_level5_key.der b/certs/dilithium/bench_dilithium_aes_level5_key.der new file mode 100644 index 0000000000000000000000000000000000000000..15d554ad089889617fbeb578b43db8268e6d2887 GIT binary patch literal 7486 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 bXFgw!@1DKlm(cNB#%h_(o-4TQK3o9+H~yF> literal 0 HcmV?d00001 diff --git a/certs/dilithium/include.am b/certs/dilithium/include.am new file mode 100644 index 000000000..0da9a802a --- /dev/null +++ b/certs/dilithium/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/dilithium/bench_dilithium_level2_key.der \ + certs/dilithium/bench_dilithium_level3_key.der \ + certs/dilithium/bench_dilithium_level5_key.der \ + certs/dilithium/bench_dilithium_aes_level2_key.der \ + certs/dilithium/bench_dilithium_aes_level3_key.der \ + certs/dilithium/bench_dilithium_aes_level5_key.der diff --git a/certs/include.am b/certs/include.am index 700927500..f81c2c36d 100644 --- a/certs/include.am +++ b/certs/include.am @@ -129,4 +129,5 @@ include certs/test-pathlen/include.am include certs/intermediate/include.am include certs/falcon/include.am include certs/rsapss/include.am +include certs/dilithium/include.am diff --git a/gencertbuf.pl b/gencertbuf.pl index fb84eb2b3..59c2c6253 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -105,6 +105,17 @@ my @fileList_falcon = ( ["certs/falcon/bench_falcon_level5_key.der", "bench_falcon_level5_key" ], ); +#Dilithium Post-Quantum Keys +#Used with HAVE_PQC +my @fileList_dilithium = ( + ["certs/dilithium/bench_dilithium_level2_key.der", "bench_dilithium_level2_key" ], + ["certs/dilithium/bench_dilithium_level3_key.der", "bench_dilithium_level3_key" ], + ["certs/dilithium/bench_dilithium_level5_key.der", "bench_dilithium_level5_key" ], + ["certs/dilithium/bench_dilithium_aes_level2_key.der", "bench_dilithium_aes_level2_key" ], + ["certs/dilithium/bench_dilithium_aes_level3_key.der", "bench_dilithium_aes_level3_key" ], + ["certs/dilithium/bench_dilithium_aes_level5_key.der", "bench_dilithium_aes_level5_key" ], + ); + # ---------------------------------------------------------------------------- my $num_ecc = @fileList_ecc; @@ -114,6 +125,7 @@ my $num_2048 = @fileList_2048; my $num_3072 = @fileList_3072; my $num_4096 = @fileList_4096; my $num_falcon = @fileList_falcon; +my $num_dilithium = @fileList_dilithium; # open our output file, "+>" creates and/or truncates open OUT_FILE, "+>", $outputFile or die $!; @@ -194,7 +206,7 @@ for (my $i = 0; $i < $num_4096; $i++) { print OUT_FILE "#endif /* USE_CERT_BUFFERS_4096 */\n\n"; # convert and print falcon keys -print OUT_FILE "#ifdef HAVE_PQC\n\n"; +print OUT_FILE "#ifdef HAVE_PQC && HAVE_FALCON\n\n"; for (my $i = 0; $i < $num_falcon; $i++) { my $fname = $fileList_falcon[$i][0]; @@ -208,7 +220,24 @@ for (my $i = 0; $i < $num_falcon; $i++) { print OUT_FILE "static const int sizeof_$sname = sizeof($sname);\n\n"; } -print OUT_FILE "#endif /* HAVE_PQC */\n\n"; +print OUT_FILE "#endif /* HAVE_PQC && HAVE_FALCON */\n\n"; + +# convert and print dilithium keys +print OUT_FILE "#ifdef HAVE_PQC && HAVE_DILITHIUM\n\n"; +for (my $i = 0; $i < $num_dilithium; $i++) { + + my $fname = $fileList_dilithium[$i][0]; + my $sname = $fileList_dilithium[$i][1]; + + print OUT_FILE "/* $fname */\n"; + print OUT_FILE "static const unsigned char $sname\[] =\n"; + print OUT_FILE "{\n"; + file_to_hex($fname); + print OUT_FILE "};\n"; + print OUT_FILE "static const int sizeof_$sname = sizeof($sname);\n\n"; +} + +print OUT_FILE "#endif /* HAVE_PQC && HAVE_DILITHIUM */\n\n"; # convert and print 256-bit cert/keys print OUT_FILE "#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)\n\n"; diff --git a/rpm/spec.in b/rpm/spec.in index bb38c9e6f..ca04a4d69 100644 --- a/rpm/spec.in +++ b/rpm/spec.in @@ -266,6 +266,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/ed448.h %{_includedir}/wolfssl/wolfcrypt/error-crypt.h %{_includedir}/wolfssl/wolfcrypt/falcon.h +%{_includedir}/wolfssl/wolfcrypt/dilithium.h %{_includedir}/wolfssl/wolfcrypt/fe_448.h %{_includedir}/wolfssl/wolfcrypt/fe_operations.h %{_includedir}/wolfssl/wolfcrypt/fips_test.h @@ -313,6 +314,8 @@ mkdir -p $RPM_BUILD_ROOT/ %{_libdir}/pkgconfig/wolfssl.pc %changelog +* Fri Jul 20 2022 Anthony Hu +- Add a new header dilithium.h. * Fri July 8 2022 Jacob Barthelmeh - Add missing sp_int.h file * Mon May 2 2022 Jacob Barthelmeh diff --git a/src/include.am b/src/include.am index 0781e4549..81e2b88ab 100644 --- a/src/include.am +++ b/src/include.am @@ -652,6 +652,7 @@ endif if BUILD_LIBOQS src_libwolfssl_la_SOURCES += wolfcrypt/src/falcon.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/dilithium.c endif if BUILD_LIBZ diff --git a/src/internal.c b/src/internal.c index 16506ead2..55f971b3c 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2094,10 +2094,17 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) } #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON if (ssl->options.side == WOLFSSL_CLIENT_END) { ssl->options.haveFalconSig = 1; /* always on client side */ } -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveDilithiumSig = 1; /* always on client side */ + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) if (ssl->options.side == WOLFSSL_CLIENT_END) { @@ -2173,8 +2180,13 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->eccTempKeySz = ECDHE_SIZE; #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON ctx->minFalconKeySz = MIN_FALCONKEY_SZ; -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + ctx->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ ctx->verifyDepth = MAX_CHAIN_DEPTH; #ifdef OPENSSL_EXTRA ctx->cbioFlag = WOLFSSL_CBIO_NONE; @@ -2234,10 +2246,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #endif /* WOLFSSL_USER_IO */ #ifdef HAVE_PQC +#ifdef HAVE_FALCON if (method->side == WOLFSSL_CLIENT_END) ctx->haveFalconSig = 1; /* always on client side */ /* server can turn on by loading key */ -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + if (method->side == WOLFSSL_CLIENT_END) + ctx->haveDilithiumSig = 1; /* always on client side */ + /* server can turn on by loading key */ +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #ifdef HAVE_ECC if (method->side == WOLFSSL_CLIENT_END) { ctx->haveECDSAsig = 1; /* always on client side */ @@ -2796,6 +2815,7 @@ static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, else #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON if (sigAlgo == falcon_level1_sa_algo) { suites->hashSigAlgo[*inOutIdx] = FALCON_LEVEL1_SA_MAJOR; *inOutIdx += 1; @@ -2810,7 +2830,52 @@ static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, *inOutIdx += 1; } else - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + if (sigAlgo == dilithium_level2_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL2_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL2_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == dilithium_level3_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL3_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL3_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == dilithium_level5_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL5_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_LEVEL5_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == dilithium_aes_level2_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL2_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL2_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == dilithium_aes_level3_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL3_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL3_SA_MINOR; + *inOutIdx += 1; + } + else + if (sigAlgo == dilithium_aes_level5_sa_algo) { + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL5_SA_MAJOR; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = DILITHIUM_AES_LEVEL5_SA_MINOR; + *inOutIdx += 1; + } + else + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #ifdef WC_RSA_PSS if (sigAlgo == rsa_pss_sa_algo) { /* RSA PSS is sig then mac */ @@ -2838,8 +2903,8 @@ static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, } void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, - int haveFalconSig, int haveAnon, int tls1_2, - int keySz) + int haveFalconSig, int haveDilithiumSig, + int haveAnon, int tls1_2, int keySz) { word16 idx = 0; @@ -2873,8 +2938,28 @@ void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, #endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */ if (haveFalconSig) { #if defined(HAVE_PQC) +#ifdef HAVE_FALCON AddSuiteHashSigAlgo(suites, no_mac, falcon_level1_sa_algo, keySz, &idx); AddSuiteHashSigAlgo(suites, no_mac, falcon_level5_sa_algo, keySz, &idx); +#endif /* HAVE_FALCON */ +#endif /* HAVE_PQC */ + } + if (haveDilithiumSig) { +#if defined(HAVE_PQC) +#ifdef HAVE_DILITHIUM + AddSuiteHashSigAlgo(suites, no_mac, dilithium_level2_sa_algo, keySz, + &idx); + AddSuiteHashSigAlgo(suites, no_mac, dilithium_level3_sa_algo, keySz, + &idx); + AddSuiteHashSigAlgo(suites, no_mac, dilithium_level5_sa_algo, keySz, + &idx); + AddSuiteHashSigAlgo(suites, no_mac, dilithium_aes_level2_sa_algo, keySz, + &idx); + AddSuiteHashSigAlgo(suites, no_mac, dilithium_aes_level3_sa_algo, keySz, + &idx); + AddSuiteHashSigAlgo(suites, no_mac, dilithium_aes_level5_sa_algo, keySz, + &idx); +#endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ } if (haveRSAsig) { @@ -2926,8 +3011,8 @@ void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveECDSAsig, word16 haveECC, word16 haveStaticRSA, word16 haveStaticECC, - word16 haveFalconSig, word16 haveAnon, word16 haveNull, - int side) + word16 haveFalconSig, word16 haveDilithiumSig, word16 haveAnon, + word16 haveNull, int side) { word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; @@ -2959,6 +3044,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, (void)haveAnon; /* anon ciphers optional */ (void)haveNull; (void)haveFalconSig; + (void)haveDilithiumSig; if (suites == NULL) { WOLFSSL_MSG("InitSuites pointer error"); @@ -3887,7 +3973,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, if (suites->hashSigAlgoSz == 0) { InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, haveRSAsig | haveRSA, haveFalconSig, - 0, tls1_2, keySz); + haveDilithiumSig, 0, tls1_2, keySz); } } @@ -3938,16 +4024,43 @@ static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsTy break; #ifdef HAVE_PQC case PQC_SA_MAJOR: + /* Hash performed as part of sign/verify operation. */ + #ifdef HAVE_FALCON if (input[1] == FALCON_LEVEL1_SA_MINOR) { *hsType = falcon_level1_sa_algo; - /* Hash performed as part of sign/verify operation. */ *hashAlgo = sha512_mac; } else if (input[1] == FALCON_LEVEL5_SA_MINOR) { *hsType = falcon_level5_sa_algo; - /* Hash performed as part of sign/verify operation. */ *hashAlgo = sha512_mac; } + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + if (input[1] == DILITHIUM_LEVEL2_SA_MINOR) { + *hsType = dilithium_level2_sa_algo; + *hashAlgo = sha512_mac; + } + else if (input[1] == DILITHIUM_LEVEL3_SA_MINOR) { + *hsType = dilithium_level3_sa_algo; + *hashAlgo = sha512_mac; + } + else if (input[1] == DILITHIUM_LEVEL5_SA_MINOR) { + *hsType = dilithium_level5_sa_algo; + *hashAlgo = sha512_mac; + } + else if (input[1] == DILITHIUM_AES_LEVEL2_SA_MINOR) { + *hsType = dilithium_aes_level2_sa_algo; + *hashAlgo = sha512_mac; + } + else if (input[1] == DILITHIUM_AES_LEVEL3_SA_MINOR) { + *hsType = dilithium_aes_level3_sa_algo; + *hashAlgo = sha512_mac; + } + else if (input[1] == DILITHIUM_AES_LEVEL5_SA_MINOR) { + *hsType = dilithium_aes_level5_sa_algo; + *hashAlgo = sha512_mac; + } + #endif /* HAVE_DILITHIUM */ break; #endif default: @@ -5905,14 +6018,15 @@ int InitSSL_Suites(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } else { InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, TRUE, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, ssl->options.haveFalconSig, - ssl->options.haveAnon, TRUE, ssl->options.side); + ssl->options.haveDilithiumSig, ssl->options.haveAnon, TRUE, + ssl->options.side); } #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) @@ -6119,12 +6233,13 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; - ssl->options.haveRSA = ctx->haveRSA; - ssl->options.haveDH = ctx->haveDH; - ssl->options.haveECDSAsig = ctx->haveECDSAsig; - ssl->options.haveECC = ctx->haveECC; - ssl->options.haveStaticECC = ctx->haveStaticECC; - ssl->options.haveFalconSig = ctx->haveFalconSig; + ssl->options.haveRSA = ctx->haveRSA; + ssl->options.haveDH = ctx->haveDH; + ssl->options.haveECDSAsig = ctx->haveECDSAsig; + ssl->options.haveECC = ctx->haveECC; + ssl->options.haveStaticECC = ctx->haveStaticECC; + ssl->options.haveFalconSig = ctx->haveFalconSig; + ssl->options.haveDilithiumSig = ctx->haveDilithiumSig; #ifndef NO_PSK ssl->options.havePSK = ctx->havePSK; @@ -6156,8 +6271,13 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.minEccKeySz = ctx->minEccKeySz; #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON ssl->options.minFalconKeySz = ctx->minFalconKeySz; -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + ssl->options.minDilithiumKeySz = ctx->minDilithiumKeySz; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) ssl->options.verifyDepth = ctx->verifyDepth; #endif @@ -6942,11 +7062,18 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_curve448_free((curve448_key*)*pKey); break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: wc_falcon_free((falcon_key*)*pKey); break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DYNAMIC_TYPE_DILITHIUM: + wc_dilithium_free((dilithium_key*)*pKey); + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #ifndef NO_DH case DYNAMIC_TYPE_DH: wc_FreeDhKey((DhKey*)*pKey); @@ -7009,10 +7136,17 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) sz = sizeof(curve448_key); break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: sz = sizeof(falcon_key); break; + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DYNAMIC_TYPE_DILITHIUM: + sz = sizeof(dilithium_key); + break; + #endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ #ifndef NO_DH case DYNAMIC_TYPE_DH: @@ -7059,12 +7193,20 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = 0; break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: wc_falcon_init((falcon_key*)*pKey); ret = 0; break; - #endif + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DYNAMIC_TYPE_DILITHIUM: + wc_dilithium_init((dilithium_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #ifdef HAVE_CURVE448 case DYNAMIC_TYPE_CURVE448: wc_curve448_init((curve448_key*)*pKey); @@ -7090,7 +7232,8 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ defined(HAVE_CURVE25519) || defined(HAVE_ED448) || \ - defined(HAVE_CURVE448) || (defined(HAVE_PQC) && defined(HAVE_FALCON)) + defined(HAVE_CURVE448) || (defined(HAVE_PQC) && defined(HAVE_FALCON)) || \ + (defined(HAVE_PQC) && defined(HAVE_DILITHIUM)) static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) { int ret = 0; @@ -12585,26 +12728,55 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) } break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: if (ssl->options.minFalconKeySz < 0 || - FALCON_LEVEL1_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { - WOLFSSL_MSG( - "Falcon key size in cert chain error"); + FALCON_LEVEL1_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { + WOLFSSL_MSG("Falcon key size in cert chain error"); ret = FALCON_KEY_SIZE_E; WOLFSSL_ERROR_VERBOSE(ret); } break; case FALCON_LEVEL5k: if (ssl->options.minFalconKeySz < 0 || - FALCON_LEVEL5_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { - WOLFSSL_MSG( - "Falcon key size in cert chain error"); + FALCON_LEVEL5_KEY_SIZE < (word16)ssl->options.minFalconKeySz) { + WOLFSSL_MSG("Falcon key size in cert chain error"); ret = FALCON_KEY_SIZE_E; WOLFSSL_ERROR_VERBOSE(ret); } break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #endif /* HAVE_PQC */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_AES_LEVEL2k: + if (ssl->options.minDilithiumKeySz < 0 || + DILITHIUM_LEVEL2_KEY_SIZE + < (word16)ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG("Dilithium key size in cert chain error"); + ret = DILITHIUM_KEY_SIZE_E; + } + break; + case DILITHIUM_LEVEL3k: + case DILITHIUM_AES_LEVEL3k: + if (ssl->options.minDilithiumKeySz < 0 || + DILITHIUM_LEVEL3_KEY_SIZE + < (word16)ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG( "Dilithium key size in cert chain error"); + ret = DILITHIUM_KEY_SIZE_E; + } + break; + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL5k: + if (ssl->options.minDilithiumKeySz < 0 || + DILITHIUM_LEVEL5_KEY_SIZE + < (word16)ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG("Dilithium key size in cert chain error"); + ret = DILITHIUM_KEY_SIZE_E; + } + break; + #endif /* HAVE_DILITHIUM */ default: WOLFSSL_MSG("Key size not checked"); /* key not being checked for size if not in @@ -13889,7 +14061,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: { @@ -13935,8 +14108,87 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ERROR_VERBOSE(ret); WOLFSSL_MSG("Peer Falcon key is too small"); } + break; } - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_LEVEL3k: + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL2k: + case DILITHIUM_AES_LEVEL3k: + case DILITHIUM_AES_LEVEL5k: + { + int keyRet = 0; + if (ssl->peerDilithiumKey == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_DILITHIUM, + (void**)&ssl->peerDilithiumKey); + } else if (ssl->peerDilithiumKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_DILITHIUM, + ssl->peerDilithiumKey); + ssl->peerDilithiumKeyPresent = 0; + } + + if (keyRet == 0) { + if (args->dCert->keyOID == DILITHIUM_LEVEL2k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 2, + SHAKE_VARIANT); + } + else if (args->dCert->keyOID == DILITHIUM_LEVEL3k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 3, + SHAKE_VARIANT); + } + else if (args->dCert->keyOID == DILITHIUM_LEVEL5k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 5, + SHAKE_VARIANT); + } + else if (args->dCert->keyOID + == DILITHIUM_AES_LEVEL2k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 2, + AES_VARIANT); + } + else if (args->dCert->keyOID + == DILITHIUM_AES_LEVEL3k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 3, + AES_VARIANT); + } + else if (args->dCert->keyOID + == DILITHIUM_AES_LEVEL5k) { + keyRet = wc_dilithium_set_level_and_sym( + ssl->peerDilithiumKey, 5, + AES_VARIANT); + } + } + + if (keyRet != 0 || + wc_dilithium_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerDilithiumKey) + != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerDilithiumKeyPresent = 1; + } + + /* check size of peer Dilithium key */ + if (ret == 0 && ssl->peerDilithiumKeyPresent && + !ssl->options.verifyNone && + DILITHIUM_MAX_KEY_SIZE < + ssl->options.minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("Peer Dilithium key is too small"); + } + break; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: break; } @@ -22566,6 +22818,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case FALCON_KEY_SIZE_E: return "Wrong key size for Falcon."; + case DILITHIUM_KEY_SIZE_E: + return "Wrong key size for Dilithium."; #ifdef WOLFSSL_QUIC case QUIC_TP_MISSING_E: @@ -23500,21 +23754,22 @@ ciphersuites introduced through the "bulk" ciphersuites. */ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { - int ret = 0; - int idx = 0; - int haveRSAsig = 0; - int haveECDSAsig = 0; - int haveFalconSig = 0; - int haveAnon = 0; + int ret = 0; + int idx = 0; + int haveRSAsig = 0; + int haveECDSAsig = 0; + int haveFalconSig = 0; + int haveDilithiumSig = 0; + int haveAnon = 0; #ifdef OPENSSL_EXTRA - int haveRSA = 0; - int haveDH = 0; - int haveECC = 0; - int haveStaticRSA = 1; /* allowed by default if compiled in */ - int haveStaticECC = 0; - int haveNull = 1; /* allowed by default if compiled in */ - int callInitSuites = 0; - int havePSK = 0; + int haveRSA = 0; + int haveDH = 0; + int haveECC = 0; + int haveStaticRSA = 1; /* allowed by default if compiled in */ + int haveStaticECC = 0; + int haveNull = 1; /* allowed by default if compiled in */ + int callInitSuites = 0; + int havePSK = 0; #endif const int suiteSz = GetCipherNamesSize(); const char* next = list; @@ -23735,8 +23990,13 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) haveECDSAsig = 1; #endif #if defined(HAVE_PQC) + #ifdef HAVE_FALCON haveFalconSig = 1; - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + haveDilithiumSig = 1; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ } else #endif @@ -23782,7 +24042,8 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) (word16)havePSK, (word16)haveDH, (word16)haveECDSAsig, (word16)haveECC, (word16)haveStaticRSA, (word16)haveStaticECC, (word16)haveFalconSig, - (word16)haveAnon, (word16)haveNull, ctx->method->side); + (word16)haveDilithiumSig, (word16)haveAnon, + (word16)haveNull, ctx->method->side); /* Restore user ciphers ahead of defaults */ XMEMMOVE(suites->suites + idx, suites->suites, min(suites->suiteSz, WOLFSSL_MAX_SUITE_SZ-idx)); @@ -23793,7 +24054,8 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { suites->suiteSz = (word16)idx; InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, - haveFalconSig, haveAnon, 1, keySz); + haveFalconSig, haveDilithiumSig, haveAnon, + 1, keySz); } suites->setSuites = 1; } @@ -23975,6 +24237,7 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) } #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON if (ssl->pkCurveOID == CTC_FALCON_LEVEL1) { /* Certificate has Falcon level 1 key, only match with Falcon level 1 * sig alg */ @@ -23985,7 +24248,34 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) * sig alg */ return sigAlgo == falcon_level5_sa_algo; } -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL2) { + /* Certificate has Dilithium level 2 key, only match with it. */ + return sigAlgo == dilithium_level2_sa_algo; + } + if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL3) { + /* Certificate has Dilithium level 3 key, only match with it. */ + return sigAlgo == dilithium_level3_sa_algo; + } + if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL5) { + /* Certificate has Dilithium level 5 key, only match with it. */ + return sigAlgo == dilithium_level5_sa_algo; + } + if (ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL2) { + /* Certificate has Dilithium AES level 2 key, only match with it. */ + return sigAlgo == dilithium_aes_level2_sa_algo; + } + if (ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL3) { + /* Certificate has Dilithium AES level 3 key, only match with it. */ + return sigAlgo == dilithium_aes_level3_sa_algo; + } + if (ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL5) { + /* Certificate has Dilithium AES level 5 key, only match with it. */ + return sigAlgo == dilithium_aes_level5_sa_algo; + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #ifdef WC_RSA_PSS /* RSA certificate and PSS sig alg. */ if (ssl->suites->sigAlgo == rsa_sa_algo) { @@ -24090,6 +24380,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) } #endif #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) if (ssl->pkCurveOID == CTC_FALCON_LEVEL1 || ssl->pkCurveOID == CTC_FALCON_LEVEL5 ) { /* Matched Falcon - set chosen and finished. */ @@ -24098,7 +24389,22 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) ret = 0; break; } - #endif + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL2 || + ssl->pkCurveOID == CTC_DILITHIUM_LEVEL3 || + ssl->pkCurveOID == CTC_DILITHIUM_LEVEL5 || + ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL2 || + ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL3 || + ssl->pkCurveOID == CTC_DILITHIUM_AES_LEVEL5 ) { + /* Matched Dilithium - set chosen and finished. */ + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = hashAlgo; + ret = 0; + break; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #if defined(WOLFSSL_ECDSA_MATCH_HASH) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) #error "WOLFSSL_ECDSA_MATCH_HASH and USE_ECDSA_KEYSZ_HASH_ALGO cannot " @@ -24463,8 +24769,8 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, } #endif /* WOLF_PRIVATE_KEY_ID && !NO_CHECK_PRIVATE_KEY */ -/* Decode the private key - RSA/ECC/Ed25519/Ed448/Falcon - and creates a key - * object. +/* Decode the private key - RSA/ECC/Ed25519/Ed448/Falcon/Dilithium - and + * creates a key object. * * The signature type is set as well. * The maximum length of a signature is returned. @@ -24786,7 +25092,8 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if (ssl->buffers.keyType == falcon_level1_sa_algo || ssl->buffers.keyType == falcon_level5_sa_algo || ssl->buffers.keyType == 0) { @@ -24846,7 +25153,93 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) goto exit_dpk; } } -#endif /* HAVE_PQC && HAVE_FALCON */ +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + if (ssl->buffers.keyType == dilithium_level2_sa_algo || + ssl->buffers.keyType == dilithium_level3_sa_algo || + ssl->buffers.keyType == dilithium_level5_sa_algo || + ssl->buffers.keyType == dilithium_aes_level2_sa_algo || + ssl->buffers.keyType == dilithium_aes_level3_sa_algo || + ssl->buffers.keyType == dilithium_aes_level5_sa_algo || + ssl->buffers.keyType == 0) { + + ssl->hsType = DYNAMIC_TYPE_DILITHIUM; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + if (ssl->buffers.keyType == dilithium_level2_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 2, SHAKE_VARIANT); + } + else if (ssl->buffers.keyType == dilithium_level3_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 3, SHAKE_VARIANT); + } + else if (ssl->buffers.keyType == dilithium_level5_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 5, SHAKE_VARIANT); + } + else if (ssl->buffers.keyType == dilithium_aes_level2_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 2, AES_VARIANT); + } + else if (ssl->buffers.keyType == dilithium_aes_level3_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 3, AES_VARIANT); + } + else if (ssl->buffers.keyType == dilithium_aes_level5_sa_algo) { + ret = wc_dilithium_set_level_and_sym((dilithium_key*)ssl->hsKey, + 5, AES_VARIANT); + } + else { + /* What if ssl->buffers.keyType is 0? We might want to do something + * more graceful here. */ + ret = ALGO_ID_E; + } + + if (ret != 0) { + goto exit_dpk; + } + + #if defined(HAVE_ED448) + WOLFSSL_MSG("Trying Dilithium private key, ED448 didn't work"); + #elif defined(HAVE_ED25519) + WOLFSSL_MSG("Trying Dilithium private key, ED25519 didn't work"); + #elif defined(HAVE_ECC) + WOLFSSL_MSG("Trying Dilithium private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying Dilithium private key, RSA didn't work"); + #elif defined(HAVE_FALCON) + WOLFSSL_MSG("Trying Dilithium private key, Falcon didn't work"); + #else + WOLFSSL_MSG("Trying Dilithium private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is a Dilithium private key. */ + ret = wc_dilithium_import_private_only(ssl->buffers.key->buffer, + ssl->buffers.key->length, + (dilithium_key*)ssl->hsKey); + if (ret == 0) { + WOLFSSL_MSG("Using Dilithium private key"); + + /* Check it meets the minimum Dilithium key size requirements. */ + if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG("Dilithium key size too small"); + ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = DILITHIUM_MAX_SIG_SIZE; + + goto exit_dpk; + } + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ (void)idx; (void)keySz; @@ -31477,8 +31870,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.haveAnon, + TRUE, ssl->options.side); } /* suite size */ @@ -31874,8 +32268,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.haveAnon, + TRUE, ssl->options.side); } /* check if option is set to not allow the current version @@ -31945,8 +32340,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.haveAnon, + TRUE, ssl->options.side); } } diff --git a/src/ssl.c b/src/ssl.c index de22ffec5..b304ebccb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -118,8 +118,13 @@ #include #include #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) #include - #endif + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + #include + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) #ifdef HAVE_OCSP #include @@ -2171,8 +2176,8 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); @@ -4198,8 +4203,13 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) cm->minEccKeySz = MIN_ECCKEY_SZ; #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON cm->minFalconKeySz = MIN_FALCONKEY_SZ; - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ cm->heap = heap; } @@ -4715,9 +4725,8 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); - + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); return WOLFSSL_SUCCESS; } #endif /* !leanpsk */ @@ -5152,7 +5161,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: if (cm->minFalconKeySz < 0 || FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) { @@ -5167,7 +5177,34 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) WOLFSSL_MSG("\tCA Falcon level 5 key size error"); } break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_AES_LEVEL2k: + if (cm->minDilithiumKeySz < 0 || + DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Dilithium level 2 key size error"); + } + break; + case DILITHIUM_LEVEL3k: + case DILITHIUM_AES_LEVEL3k: + if (cm->minDilithiumKeySz < 0 || + DILITHIUM_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Dilithium level 3 key size error"); + } + break; + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL5k: + if (cm->minDilithiumKeySz < 0 || + DILITHIUM_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Dilithium level 5 key size error"); + } + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: WOLFSSL_MSG("\tNo key size check done on CA"); @@ -6076,7 +6113,8 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der return ret; } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if (((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) || (*keyFormat == FALCON_LEVEL5k))) { /* make sure Falcon key can be used */ @@ -6142,7 +6180,119 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der if (ret != 0) return ret; } -#endif /* HAVE_PQC && HAVE_FALCON */ +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + if ((*keyFormat == 0) || + (*keyFormat == DILITHIUM_LEVEL2k) || + (*keyFormat == DILITHIUM_LEVEL3k) || + (*keyFormat == DILITHIUM_LEVEL5k) || + (*keyFormat == DILITHIUM_AES_LEVEL2k) || + (*keyFormat == DILITHIUM_AES_LEVEL3k) || + (*keyFormat == DILITHIUM_AES_LEVEL5k)) { + /* make sure Dilithium key can be used */ + dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), + heap, + DYNAMIC_TYPE_DILITHIUM); + if (key == NULL) { + return MEMORY_E; + } + ret = wc_dilithium_init(key); + if (ret == 0) { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ret = wc_dilithium_set_level_and_sym(key, 2, SHAKE_VARIANT); + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ret = wc_dilithium_set_level_and_sym(key, 3, SHAKE_VARIANT); + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ret = wc_dilithium_set_level_and_sym(key, 5, SHAKE_VARIANT); + } + else if (*keyFormat == DILITHIUM_AES_LEVEL2k) { + ret = wc_dilithium_set_level_and_sym(key, 2, AES_VARIANT); + } + else if (*keyFormat == DILITHIUM_AES_LEVEL3k) { + ret = wc_dilithium_set_level_and_sym(key, 3, AES_VARIANT); + } + else if (*keyFormat == DILITHIUM_AES_LEVEL5k) { + ret = wc_dilithium_set_level_and_sym(key, 5, AES_VARIANT); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + wc_dilithium_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + *idx = 0; + ret = wc_dilithium_import_private_only(der->buffer, der->length, + key); + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz; + *keySz = DILITHIUM_MAX_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("Dilithium private key too small"); + ret = DILITHIUM_KEY_SIZE_E; + } + if (ssl) { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ssl->buffers.keyType = dilithium_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ssl->buffers.keyType = dilithium_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ssl->buffers.keyType = dilithium_level5_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL2k) { + ssl->buffers.keyType = dilithium_aes_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL3k) { + ssl->buffers.keyType = dilithium_aes_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL5k) { + ssl->buffers.keyType = dilithium_aes_level5_sa_algo; + } + ssl->buffers.keySz = *keySz; + } + else { + if (*keyFormat == DILITHIUM_LEVEL2k) { + ctx->privateKeyType = dilithium_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ctx->privateKeyType = dilithium_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ctx->privateKeyType = dilithium_level5_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL2k) { + ctx->privateKeyType = dilithium_aes_level2_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL3k) { + ctx->privateKeyType = dilithium_aes_level3_sa_algo; + } + else if (*keyFormat == DILITHIUM_AES_LEVEL5k) { + ctx->privateKeyType = dilithium_aes_level5_sa_algo; + } + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + wc_dilithium_free(key); + } + XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); + if (ret != 0) { + return ret; + } + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ return ret; } @@ -6502,6 +6652,18 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) ctx->haveFalconSig = 1; break; + case CTC_DILITHIUM_LEVEL2: + case CTC_DILITHIUM_LEVEL3: + case CTC_DILITHIUM_LEVEL5: + case CTC_DILITHIUM_AES_LEVEL2: + case CTC_DILITHIUM_AES_LEVEL3: + case CTC_DILITHIUM_AES_LEVEL5: + WOLFSSL_MSG("Dilithium cert signature"); + if (ssl) + ssl->options.haveDilithiumSig = 1; + else if (ctx) + ctx->haveDilithiumSig = 1; + break; default: WOLFSSL_MSG("Not ECDSA cert signature"); break; @@ -6539,11 +6701,23 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON else if (cert->keyOID == FALCON_LEVEL1k || cert->keyOID == FALCON_LEVEL5k) { ssl->options.haveFalconSig = 1; } - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + else if (cert->keyOID == DILITHIUM_LEVEL2k || + cert->keyOID == DILITHIUM_LEVEL3k || + cert->keyOID == DILITHIUM_LEVEL5k || + cert->keyOID == DILITHIUM_AES_LEVEL2k || + cert->keyOID == DILITHIUM_AES_LEVEL3k || + cert->keyOID == DILITHIUM_AES_LEVEL5k) { + ssl->options.haveDilithiumSig = 1; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #else ssl->options.haveECC = ssl->options.haveECDSAsig; #endif @@ -6577,11 +6751,23 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON else if (cert->keyOID == FALCON_LEVEL1k || cert->keyOID == FALCON_LEVEL5k) { ctx->haveFalconSig = 1; } - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + else if (cert->keyOID == DILITHIUM_LEVEL2k || + cert->keyOID == DILITHIUM_LEVEL3k || + cert->keyOID == DILITHIUM_LEVEL5k || + cert->keyOID == DILITHIUM_AES_LEVEL2k || + cert->keyOID == DILITHIUM_AES_LEVEL3k || + cert->keyOID == DILITHIUM_AES_LEVEL5k) { + ctx->haveDilithiumSig = 1; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ #else ctx->haveECC = ctx->haveECDSAsig; #endif @@ -6692,7 +6878,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: /* Falcon is fixed key size */ @@ -6712,7 +6899,33 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_LEVEL3k: + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL2k: + case DILITHIUM_AES_LEVEL3k: + case DILITHIUM_AES_LEVEL5k: + /* Dilithium is fixed key size */ + keySz = DILITHIUM_MAX_KEY_SIZE; + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minDilithiumKeySz < 0 || + keySz < (int)ssl->options.minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Dilithium key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minDilithiumKeySz < 0 || + keySz < (int)ctx->minDilithiumKeySz) { + ret = DILITHIUM_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Dilithium key size error"); + } + } + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: WOLFSSL_MSG("No key size check done on certificate"); @@ -6775,8 +6988,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } return WOLFSSL_SUCCESS; @@ -8920,10 +9133,11 @@ static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out, #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ #ifdef HAVE_PQC + #ifdef HAVE_FALCON { int isFalcon = 0; #ifdef WOLFSSL_SMALL_STACK - falcon_key *falcon = (falcon_key *)MALLOC(sizeof(falcon_key), NULL, + falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL, DYNAMIC_TYPE_FALCON); if (falcon == NULL) { return NULL; @@ -8979,6 +9193,115 @@ static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out, } } + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + { + int isDilithium = 0; + #ifdef WOLFSSL_SMALL_STACK + dilithium_key *dilithium = (dilithium_key *) + XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM); + if (dilithium == NULL) { + return NULL; + } + #else + dilithium_key dilithium[1]; + #endif + + if (wc_dilithium_init(dilithium) == 0) { + /* Test if Dilithium key. Try all levels for both SHAKE and AES */ + if (priv) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2, + AES_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3, + AES_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5, + AES_VARIANT) == 0 && + wc_dilithium_import_private_only(mem, + (word32)memSz, dilithium) == 0; + } + } else { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5, + SHAKE_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2, + AES_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3, + AES_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + } + if (!isDilithium) { + isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5, + AES_VARIANT) == 0 && + wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0; + } + } + wc_dilithium_free(dilithium); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + if (isDilithium) { + /* Create a fake Dilithium EVP_PKEY. In the future, we might + * integrate Dilithium into the compatibility layer. */ + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("Dilithium wolfSSL_EVP_PKEY_new error"); + return NULL; + } + pkey->type = EVP_PKEY_DILITHIUM; + pkey->pkey.ptr = NULL; + pkey->pkey_sz = 0; + return pkey; + } + + } + #endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ if (pkey == NULL) { @@ -14597,8 +14920,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } #ifdef OPENSSL_EXTRA /** @@ -14650,8 +14973,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) @@ -22698,8 +23021,8 @@ long wolfSSL_set_options(WOLFSSL* ssl, long op) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); return ssl->options.mask; } @@ -25865,11 +26188,27 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { { NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"}, #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1", "Falcon Level 1"}, { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5", "Falcon Level 5"}, - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + { CTC_DILITHIUM_LEVEL2, DILITHIUM_LEVEL2k, oidKeyType, + "Dilithium Level 2", "Dilithium Level 2"}, + { CTC_DILITHIUM_LEVEL3, DILITHIUM_LEVEL3k, oidKeyType, + "Dilithium Level 3", "Dilithium Level 3"}, + { CTC_DILITHIUM_LEVEL5, DILITHIUM_LEVEL5k, oidKeyType, + "Dilithium Level 5", "Dilithium Level 5"}, + { CTC_DILITHIUM_AES_LEVEL2, DILITHIUM_AES_LEVEL2k, oidKeyType, + "Dilithium AES Level 2", "Dilithium AES Level 2"}, + { CTC_DILITHIUM_AES_LEVEL3, DILITHIUM_AES_LEVEL3k, oidKeyType, + "Dilithium AES Level 3", "Dilithium AES Level 3"}, + { CTC_DILITHIUM_AES_LEVEL5, DILITHIUM_AES_LEVEL5k, oidKeyType, + "Dilithium AES Level 5", "Dilithium AES Level 5"}, + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ /* oidCurveType */ #ifdef HAVE_ECC @@ -27537,9 +27876,19 @@ struct WOLFSSL_HashSigInfo { { no_mac, ed448_sa_algo, CTC_ED448 }, #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON { no_mac, falcon_level1_sa_algo, CTC_FALCON_LEVEL1 }, { no_mac, falcon_level5_sa_algo, CTC_FALCON_LEVEL5 }, -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + { no_mac, dilithium_level2_sa_algo, CTC_DILITHIUM_LEVEL2 }, + { no_mac, dilithium_level3_sa_algo, CTC_DILITHIUM_LEVEL3 }, + { no_mac, dilithium_level5_sa_algo, CTC_DILITHIUM_LEVEL5 }, + { no_mac, dilithium_aes_level2_sa_algo, CTC_DILITHIUM_AES_LEVEL2 }, + { no_mac, dilithium_aes_level3_sa_algo, CTC_DILITHIUM_AES_LEVEL3 }, + { no_mac, dilithium_aes_level5_sa_algo, CTC_DILITHIUM_AES_LEVEL5 }, +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #ifndef NO_DSA #ifndef NO_SHA { sha_mac, dsa_sa_algo, CTC_SHAwDSA }, diff --git a/src/tls13.c b/src/tls13.c index ea98ba57f..50a55c071 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -6038,7 +6038,7 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, ssl->options.buildingMsg = 1; if (ssl->options.side == WOLFSSL_SERVER_END) - InitSuitesHashSigAlgo(ssl->suites, 1, 1, 1, + InitSuitesHashSigAlgo(ssl->suites, 1, 1, 1, 1, 0, 1, ssl->buffers.keySz); ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS); @@ -6170,6 +6170,7 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON case falcon_level1_sa_algo: output[0] = FALCON_LEVEL1_SA_MAJOR; output[1] = FALCON_LEVEL1_SA_MINOR; @@ -6178,6 +6179,33 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = FALCON_LEVEL5_SA_MAJOR; output[1] = FALCON_LEVEL5_SA_MINOR; break; + #endif + #ifdef HAVE_DILITHIUM + case dilithium_level2_sa_algo: + output[0] = DILITHIUM_LEVEL2_SA_MAJOR; + output[1] = DILITHIUM_LEVEL2_SA_MINOR; + break; + case dilithium_level3_sa_algo: + output[0] = DILITHIUM_LEVEL3_SA_MAJOR; + output[1] = DILITHIUM_LEVEL3_SA_MINOR; + break; + case dilithium_level5_sa_algo: + output[0] = DILITHIUM_LEVEL5_SA_MAJOR; + output[1] = DILITHIUM_LEVEL5_SA_MINOR; + break; + case dilithium_aes_level2_sa_algo: + output[0] = DILITHIUM_AES_LEVEL2_SA_MAJOR; + output[1] = DILITHIUM_AES_LEVEL2_SA_MINOR; + break; + case dilithium_aes_level3_sa_algo: + output[0] = DILITHIUM_AES_LEVEL3_SA_MAJOR; + output[1] = DILITHIUM_AES_LEVEL3_SA_MINOR; + break; + case dilithium_aes_level5_sa_algo: + output[0] = DILITHIUM_AES_LEVEL5_SA_MAJOR; + output[1] = DILITHIUM_AES_LEVEL5_SA_MINOR; + break; + #endif #endif default: break; @@ -6224,17 +6252,47 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo, break; #ifdef HAVE_PQC case PQC_SA_MAJOR: +#if defined(HAVE_FALCON) if (input[1] == FALCON_LEVEL1_SA_MINOR) { *hsType = falcon_level1_sa_algo; /* Hash performed as part of sign/verify operation. */ *hashAlgo = sha512_mac; - } else - if (input[1] == FALCON_LEVEL5_SA_MINOR) { - *hsType = falcon_level1_sa_algo; + } else if (input[1] == FALCON_LEVEL5_SA_MINOR) { + *hsType = falcon_level5_sa_algo; /* Hash performed as part of sign/verify operation. */ *hashAlgo = sha512_mac; } - else { + else +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + if (input[1] == DILITHIUM_LEVEL2_SA_MINOR) { + *hsType = dilithium_level2_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else if (input[1] == DILITHIUM_LEVEL3_SA_MINOR) { + *hsType = dilithium_level3_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else if (input[1] == DILITHIUM_LEVEL5_SA_MINOR) { + *hsType = dilithium_level5_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else if (input[1] == DILITHIUM_AES_LEVEL2_SA_MINOR) { + *hsType = dilithium_aes_level2_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else if (input[1] == DILITHIUM_AES_LEVEL3_SA_MINOR) { + *hsType = dilithium_aes_level3_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } else if (input[1] == DILITHIUM_AES_LEVEL5_SA_MINOR) { + *hsType = dilithium_aes_level5_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + else +#endif /* HAVE_DILITHIUM */ + { ret = INVALID_PARAMETER; } break; @@ -7077,7 +7135,8 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) else if (ssl->hsType == DYNAMIC_TYPE_ED448) args->sigAlgo = ed448_sa_algo; #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) else if (ssl->hsType == DYNAMIC_TYPE_FALCON) { falcon_key* fkey = (falcon_key*)ssl->hsKey; byte level = 0; @@ -7088,13 +7147,45 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) args->sigAlgo = falcon_level1_sa_algo; } else if (level == 5) { - args->sigAlgo = falcon_level1_sa_algo; + args->sigAlgo = falcon_level5_sa_algo; } else { ERROR_OUT(ALGO_ID_E, exit_scv); } } - #endif + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + else if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { + dilithium_key* fkey = (dilithium_key*)ssl->hsKey; + byte level = 0; + byte sym = 0; + if (wc_dilithium_get_level_and_sym(fkey, &level, &sym) != 0) { + ERROR_OUT(ALGO_ID_E, exit_scv); + } + if ((level == 2) && (sym == SHAKE_VARIANT)) { + args->sigAlgo = dilithium_level2_sa_algo; + } + else if ((level == 3) && (sym == SHAKE_VARIANT)) { + args->sigAlgo = dilithium_level3_sa_algo; + } + else if ((level == 5) && (sym == SHAKE_VARIANT)) { + args->sigAlgo = dilithium_level5_sa_algo; + } + else if ((level == 2) && (sym == AES_VARIANT)) { + args->sigAlgo = dilithium_aes_level2_sa_algo; + } + else if ((level == 3) && (sym == AES_VARIANT)) { + args->sigAlgo = dilithium_aes_level3_sa_algo; + } + else if ((level == 5) && (sym == AES_VARIANT)) { + args->sigAlgo = dilithium_aes_level5_sa_algo; + } + else { + ERROR_OUT(ALGO_ID_E, exit_scv); + } + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ else { ERROR_OUT(ALGO_ID_E, exit_scv); } @@ -7171,11 +7262,18 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) sig->length = ED448_SIG_SIZE; } #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) if (ssl->hsType == DYNAMIC_TYPE_FALCON) { sig->length = FALCON_MAX_SIG_SIZE; } - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif + #if defined(HAVE_DILITHIUM) + if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { + sig->length = DILITHIUM_MAX_SIG_SIZE; + } + #endif + #endif /* HAVE_PQC */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -7227,7 +7325,8 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) args->length = (word16)sig->length; } #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) if (ssl->hsType == DYNAMIC_TYPE_FALCON) { ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz, args->verify + HASH_SIG_SIZE + @@ -7235,7 +7334,17 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) (falcon_key*)ssl->hsKey); args->length = (word16)sig->length; } - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif + #if defined(HAVE_DILITHIUM) + if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { + ret = wc_dilithium_sign_msg(args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + + VERIFY_HEADER, (word32*)&sig->length, + (dilithium_key*)ssl->hsKey); + args->length = (word16)sig->length; + } + #endif + #endif /* HAVE_PQC */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { ret = RsaSign(ssl, sig->buffer, (word32)sig->length, @@ -7603,12 +7712,42 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, if (args->sigAlgo == falcon_level1_sa_algo) { WOLFSSL_MSG("Peer sent Falcon Level 1 sig"); validSigAlgo = (ssl->peerFalconKey != NULL) && - ssl->peerFalconKeyPresent; + ssl->peerFalconKeyPresent; } if (args->sigAlgo == falcon_level5_sa_algo) { WOLFSSL_MSG("Peer sent Falcon Level 5 sig"); validSigAlgo = (ssl->peerFalconKey != NULL) && - ssl->peerFalconKeyPresent; + ssl->peerFalconKeyPresent; + } + if (args->sigAlgo == dilithium_level2_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium Level 2 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; + } + if (args->sigAlgo == dilithium_level3_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium Level 3 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; + } + if (args->sigAlgo == dilithium_level5_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium Level 5 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; + } + if (args->sigAlgo == dilithium_aes_level2_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium AES Level 2 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; + } + if (args->sigAlgo == dilithium_aes_level3_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium AES Level 3 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; + } + if (args->sigAlgo == dilithium_aes_level5_sa_algo) { + WOLFSSL_MSG("Peer sent Dilithium AES Level 5 sig"); + validSigAlgo = (ssl->peerDilithiumKey != NULL) && + ssl->peerDilithiumKeyPresent; } #endif #ifndef NO_RSA @@ -7697,6 +7836,19 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); ret = 0; } + + if (ssl->peerDilithiumKeyPresent) { + WOLFSSL_MSG("Doing Dilithium peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } #endif /* Advance state and proceed */ @@ -7805,6 +7957,24 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } } #endif /* HAVE_PQC && HAVE_FALCON */ + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if (ssl->peerDilithiumKeyPresent) { + int res = 0; + WOLFSSL_MSG("Doing Dilithium peer cert verify"); + ret = wc_dilithium_verify_msg(input + args->idx, args->sz, + args->sigData, args->sigDataSz, + &res, ssl->peerDilithiumKey); + + if ((ret >= 0) && (res == 1)) { + /* CLIENT/SERVER: data verified with public key from + * certificate. */ + ssl->options.peerAuthGood = 1; + FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM, + (void**)&ssl->peerDilithiumKey); + ssl->peerDilithiumKeyPresent = 0; + } + } + #endif /* HAVE_PQC && HAVE_DILITHIUM */ /* Check for error */ if (ret != 0) { @@ -10837,8 +11007,8 @@ void wolfSSL_set_psk_client_cs_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } /* Set the PSK callback that returns the cipher suite for a client to use @@ -10888,8 +11058,8 @@ void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } /* Set the PSK callback that returns the cipher suite for a server to use @@ -10936,8 +11106,8 @@ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveAnon, TRUE, - ssl->options.side); + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.haveAnon, TRUE, ssl->options.side); } /* Get name of first supported cipher suite that uses the hash indicated. diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 4b7ac2076..52b0c19c4 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -261,9 +261,17 @@ #ifdef HAVE_LIBOQS #include #endif -#if defined(HAVE_PQC) && defined(HAVE_FALCON) - #include +#if defined(HAVE_PQC) + #if defined(HAVE_FALCON) + #include + #endif #endif +#if defined(HAVE_PQC) + #if defined(HAVE_DILITHIUM) + #include + #endif +#endif + #ifdef HAVE_PQM4 #include #define PQM4_PUBLIC_KEY_LENGTH CRYPTO_PUBLICKEYBYTES @@ -440,34 +448,38 @@ #define BENCH_SAKKE 0x80000000 /* Post-Quantum Asymmetric algorithms. */ -#define BENCH_FALCON_LEVEL1_SIGN 0x00000001 -#define BENCH_FALCON_LEVEL5_SIGN 0x00000002 -#define BENCH_KYBER_LEVEL1_KEYGEN 0x00000004 -#define BENCH_KYBER_LEVEL1_ENCAP 0x00000008 -#define BENCH_KYBER_LEVEL3_KEYGEN 0x00000010 -#define BENCH_KYBER_LEVEL3_ENCAP 0x00000020 -#define BENCH_KYBER_LEVEL5_KEYGEN 0x00000040 -#define BENCH_KYBER_LEVEL5_ENCAP 0x00000080 -#define BENCH_KYBER90S_LEVEL1_KEYGEN 0x00000100 -#define BENCH_KYBER90S_LEVEL1_ENCAP 0x00000200 -#define BENCH_KYBER90S_LEVEL3_KEYGEN 0x00000400 -#define BENCH_KYBER90S_LEVEL3_ENCAP 0x00000800 -#define BENCH_KYBER90S_LEVEL5_KEYGEN 0x00001000 -#define BENCH_KYBER90S_LEVEL5_ENCAP 0x00002000 -#define BENCH_SABER_LEVEL1_KEYGEN 0x00004000 -#define BENCH_SABER_LEVEL1_ENCAP 0x00008000 -#define BENCH_SABER_LEVEL3_KEYGEN 0x00010000 -#define BENCH_SABER_LEVEL3_ENCAP 0x00020000 -#define BENCH_SABER_LEVEL5_KEYGEN 0x00040000 -#define BENCH_SABER_LEVEL5_ENCAP 0x00080000 -#define BENCH_NTRUHPS_LEVEL1_KEYGEN 0x00100000 -#define BENCH_NTRUHPS_LEVEL1_ENCAP 0x00200000 -#define BENCH_NTRUHPS_LEVEL3_KEYGEN 0x00400000 -#define BENCH_NTRUHPS_LEVEL3_ENCAP 0x00800000 -#define BENCH_NTRUHPS_LEVEL5_KEYGEN 0x01000000 -#define BENCH_NTRUHPS_LEVEL5_ENCAP 0x02000000 -#define BENCH_NTRUHRSS_LEVEL3_KEYGEN 0x04000000 -#define BENCH_NTRUHRSS_LEVEL3_ENCAP 0x08000000 +#define BENCH_FALCON_LEVEL1_SIGN 0x00000001 +#define BENCH_FALCON_LEVEL5_SIGN 0x00000002 +#define BENCH_KYBER_LEVEL1_KEYGEN 0x00000004 +#define BENCH_KYBER_LEVEL1_ENCAP 0x00000008 +#define BENCH_KYBER_LEVEL3_KEYGEN 0x00000010 +#define BENCH_KYBER_LEVEL3_ENCAP 0x00000020 +#define BENCH_KYBER_LEVEL5_KEYGEN 0x00000040 +#define BENCH_KYBER_LEVEL5_ENCAP 0x00000080 +#define BENCH_KYBER90S_LEVEL1_KEYGEN 0x00000100 +#define BENCH_KYBER90S_LEVEL1_ENCAP 0x00000200 +#define BENCH_KYBER90S_LEVEL3_KEYGEN 0x00000400 +#define BENCH_KYBER90S_LEVEL3_ENCAP 0x00000800 +#define BENCH_KYBER90S_LEVEL5_KEYGEN 0x00001000 +#define BENCH_KYBER90S_LEVEL5_ENCAP 0x00002000 +#define BENCH_SABER_LEVEL1_KEYGEN 0x00004000 +#define BENCH_SABER_LEVEL1_ENCAP 0x00008000 +#define BENCH_SABER_LEVEL3_KEYGEN 0x00010000 +#define BENCH_SABER_LEVEL3_ENCAP 0x00020000 +#define BENCH_SABER_LEVEL5_KEYGEN 0x00040000 +#define BENCH_SABER_LEVEL5_ENCAP 0x00080000 +#define BENCH_NTRUHPS_LEVEL1_KEYGEN 0x00100000 +#define BENCH_NTRUHPS_LEVEL1_ENCAP 0x00200000 +#define BENCH_NTRUHPS_LEVEL3_KEYGEN 0x00400000 +#define BENCH_NTRUHPS_LEVEL3_ENCAP 0x00800000 +#define BENCH_NTRUHPS_LEVEL5_KEYGEN 0x01000000 +#define BENCH_NTRUHPS_LEVEL5_ENCAP 0x02000000 +#define BENCH_DILITHIUM_LEVEL2_SIGN 0x04000000 +#define BENCH_DILITHIUM_LEVEL3_SIGN 0x08000000 +#define BENCH_DILITHIUM_LEVEL5_SIGN 0x10000000 +#define BENCH_DILITHIUM_AES_LEVEL2_SIGN 0x20000000 +#define BENCH_DILITHIUM_AES_LEVEL3_SIGN 0x40000000 +#define BENCH_DILITHIUM_AES_LEVEL5_SIGN 0x80000000 /* Other */ #define BENCH_RNG 0x00000001 @@ -734,10 +746,23 @@ static const bench_pq_alg bench_pq_asym_opt[] = { { "-kyber_level1-ed", BENCH_KYBER_LEVEL1_ENCAP, NULL }, #endif #ifdef HAVE_LIBOQS - { "-falcon_level1", BENCH_FALCON_LEVEL1_SIGN, + { "-falcon_level1", BENCH_FALCON_LEVEL1_SIGN, OQS_SIG_alg_falcon_512 }, - { "-falcon_level5", BENCH_FALCON_LEVEL5_SIGN, + { "-falcon_level5", BENCH_FALCON_LEVEL5_SIGN, OQS_SIG_alg_falcon_1024 }, + { "-dilithium_level2", BENCH_DILITHIUM_LEVEL2_SIGN, + OQS_SIG_alg_dilithium_2 }, + { "-dilithium_level3", BENCH_DILITHIUM_LEVEL3_SIGN, + OQS_SIG_alg_dilithium_3 }, + { "-dilithium_level5", BENCH_DILITHIUM_LEVEL5_SIGN, + OQS_SIG_alg_dilithium_5 }, + { "-dilithium_aes_level2", BENCH_DILITHIUM_AES_LEVEL2_SIGN, + OQS_SIG_alg_dilithium_2_aes }, + { "-dilithium_aes_level3", BENCH_DILITHIUM_AES_LEVEL3_SIGN, + OQS_SIG_alg_dilithium_3_aes }, + { "-dilithium_aes_level5", BENCH_DILITHIUM_AES_LEVEL5_SIGN, + OQS_SIG_alg_dilithium_5_aes }, + { "-kyber_level1-kg", BENCH_KYBER_LEVEL1_KEYGEN, OQS_KEM_alg_kyber_512 }, { "-kyber_level1-ed", BENCH_KYBER_LEVEL1_ENCAP, @@ -786,10 +811,6 @@ static const bench_pq_alg bench_pq_asym_opt[] = { OQS_KEM_alg_ntru_hps4096821 }, { "-ntruHPS_level5-ed", BENCH_NTRUHPS_LEVEL5_ENCAP, OQS_KEM_alg_ntru_hps4096821 }, - { "-ntruHRSS_level3-kg", BENCH_NTRUHRSS_LEVEL3_KEYGEN, - OQS_KEM_alg_ntru_hrss701 }, - { "-ntruHRSS_level3-ed", BENCH_NTRUHRSS_LEVEL3_ENCAP, - OQS_KEM_alg_ntru_hrss701 }, #endif { NULL, 0, NULL } }; @@ -2330,16 +2351,27 @@ static void* benchmarks_do(void* args) bench_pqcKemKeygen(BENCH_NTRUHPS_LEVEL5_KEYGEN); if (bench_all || (bench_pq_asym_algs & BENCH_NTRUHPS_LEVEL5_ENCAP)) bench_pqcKemEncapDecap(BENCH_NTRUHPS_LEVEL5_ENCAP); - if (bench_all || (bench_pq_asym_algs & BENCH_NTRUHRSS_LEVEL3_KEYGEN)) - bench_pqcKemKeygen(BENCH_NTRUHRSS_LEVEL3_KEYGEN); - if (bench_all || (bench_pq_asym_algs & BENCH_NTRUHRSS_LEVEL3_ENCAP)) - bench_pqcKemEncapDecap(BENCH_NTRUHRSS_LEVEL3_ENCAP); #ifdef HAVE_FALCON if (bench_all || (bench_pq_asym_algs & BENCH_FALCON_LEVEL1_SIGN)) bench_falconKeySign(1); if (bench_all || (bench_pq_asym_algs & BENCH_FALCON_LEVEL5_SIGN)) bench_falconKeySign(5); #endif +#ifdef HAVE_DILITHIUM + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_LEVEL2_SIGN)) + bench_dilithiumKeySign(2, SHAKE_VARIANT); + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_LEVEL3_SIGN)) + bench_dilithiumKeySign(3, SHAKE_VARIANT); + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_LEVEL5_SIGN)) + bench_dilithiumKeySign(5, SHAKE_VARIANT); + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_AES_LEVEL2_SIGN)) + bench_dilithiumKeySign(2, AES_VARIANT); + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_AES_LEVEL3_SIGN)) + bench_dilithiumKeySign(3, AES_VARIANT); + if (bench_all || (bench_pq_asym_algs & BENCH_DILITHIUM_AES_LEVEL5_SIGN)) + bench_dilithiumKeySign(5, AES_VARIANT); +#endif + #endif /* HAVE_LIBOQS */ #ifdef WOLFCRYPT_HAVE_SAKKE @@ -7249,12 +7281,12 @@ void bench_falconKeySign(byte level) if (ret == 0) { if (level == 1) { x = FALCON_LEVEL1_SIG_SIZE; - ret = wc_falcon_sign_msg(msg, sizeof(msg), sig, &x, &key); } else { x = FALCON_LEVEL5_SIG_SIZE; - ret = wc_falcon_sign_msg(msg, sizeof(msg), sig, &x, &key); } + + ret = wc_falcon_sign_msg(msg, sizeof(msg), sig, &x, &key); if (ret != 0) { printf("wc_falcon_sign_msg failed\n"); } @@ -7272,18 +7304,11 @@ void bench_falconKeySign(byte level) for (i = 0; i < agreeTimes; i++) { if (ret == 0) { int verify = 0; - if (level == 1) { - ret = wc_falcon_verify_msg(sig, x, msg, sizeof(msg), - &verify, &key); - } - else { - ret = wc_falcon_verify_msg(sig, x, msg, sizeof(msg), - &verify, &key); - } - + ret = wc_falcon_verify_msg(sig, x, msg, sizeof(msg), &verify, + &key); if (ret != 0 || verify != 1) { printf("wc_falcon_verify_msg failed %d, verify %d\n", - ret, verify); + ret, verify); ret = -1; } } @@ -7298,7 +7323,137 @@ void bench_falconKeySign(byte level) wc_falcon_free(&key); } #endif /* HAVE_FALCON */ -#endif /* HAVE_PQC && HAVE_LIBOQS */ + +#ifdef HAVE_DILITHIUM +void bench_dilithiumKeySign(byte level, byte sym) +{ + int ret = 0; + dilithium_key key; + double start; + int i, count; + byte sig[DILITHIUM_MAX_SIG_SIZE]; + byte msg[512]; + word32 x = 0; + const char**desc = bench_desc_words[lng_index]; + + ret = wc_dilithium_init(&key); + if (ret != 0) { + printf("wc_dilithium_init failed %d\n", ret); + return; + } + + ret = wc_dilithium_set_level_and_sym(&key, level, sym); + if (ret != 0) { + printf("wc_dilithium_set_level_and_sym() failed %d\n", ret); + } + + if (ret == 0) { + ret = -1; + if ((level == 2) && (sym == SHAKE_VARIANT)) { + ret = wc_dilithium_import_private_key(bench_dilithium_level2_key, + sizeof_bench_dilithium_level2_key, NULL, 0, &key); + } + else if ((level == 3) && (sym == SHAKE_VARIANT)) { + ret = wc_dilithium_import_private_key(bench_dilithium_level3_key, + sizeof_bench_dilithium_level3_key, NULL, 0, &key); + } + else if ((level == 5) && (sym == SHAKE_VARIANT)) { + ret = wc_dilithium_import_private_key(bench_dilithium_level5_key, + sizeof_bench_dilithium_level5_key, NULL, 0, &key); + } + else if ((level == 2) && (sym == AES_VARIANT)) { + ret = wc_dilithium_import_private_key( + bench_dilithium_aes_level2_key, + sizeof_bench_dilithium_level2_key, NULL, 0, &key); + } + else if ((level == 3) && (sym == AES_VARIANT)) { + ret = wc_dilithium_import_private_key( + bench_dilithium_aes_level3_key, + sizeof_bench_dilithium_level3_key, NULL, 0, &key); + } + else if ((level == 5) && (sym == AES_VARIANT)) { + ret = wc_dilithium_import_private_key( + bench_dilithium_aes_level5_key, + sizeof_bench_dilithium_level5_key, NULL, 0, &key); + } + + if (ret != 0) { + printf("wc_dilithium_import_private_key failed %d\n", ret); + } + } + + /* make dummy msg */ + for (i = 0; i < (int)sizeof(msg); i++) { + msg[i] = (byte)i; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + if (ret == 0) { + if (level == 2) { + x = DILITHIUM_LEVEL2_SIG_SIZE; + } + else if (level == 3) { + x = DILITHIUM_LEVEL3_SIG_SIZE; + } + else { + x = DILITHIUM_LEVEL5_SIG_SIZE; + } + + ret = wc_dilithium_sign_msg(msg, sizeof(msg), sig, &x, &key); + if (ret != 0) { + printf("wc_dilithium_sign_msg failed\n"); + } + } + } + count += i; + } while (bench_stats_sym_check(start)); + + if (ret == 0) { + if (sym == SHAKE_VARIANT) { + bench_stats_asym_finish("DILITHIUM", level, desc[4], 0, count, + start, ret); + } + else { + bench_stats_asym_finish("DILITHIUM-AES", level, desc[4], 0, count, + start, ret); + } + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + if (ret == 0) { + int verify = 0; + ret = wc_dilithium_verify_msg(sig, x, msg, sizeof(msg), &verify, + &key); + + if (ret != 0 || verify != 1) { + printf("wc_dilithium_verify_msg failed %d, verify %d\n", + ret, verify); + ret = -1; + } + } + } + count += i; + } while (bench_stats_sym_check(start)); + + if (ret == 0) { + if (sym == SHAKE_VARIANT) { + bench_stats_asym_finish("DILITHIUM", level, desc[5], 0, count, + start, ret); + } + else { + bench_stats_asym_finish("DILITHIUM-AES", level, desc[5], 0, count, + start, ret); + } + } + + wc_dilithium_free(&key); +} +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ #ifndef HAVE_STACK_SIZE #if defined(_WIN32) && !defined(INTIME_RTOS) diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 0481e9679..eafb262ab 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -108,6 +108,7 @@ void bench_blake2b(void); void bench_blake2s(void); void bench_pbkdf2(void); void bench_falconKeySign(byte level); +void bench_dilithiumKeySign(byte level, byte sym); void bench_pqcKemKeygen(word32 alg); void bench_pqcKemEncapDecap(word32 alg); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4d352b71c..6f8f35c30 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -90,7 +90,6 @@ ASN Options: */ #ifndef NO_ASN - #include #include #include @@ -143,7 +142,12 @@ ASN Options: #endif #ifdef HAVE_PQC + #if defined(HAVE_FALCON) #include + #endif + #if defined(HAVE_DILITHIUM) + #include + #endif #endif #ifdef WOLFSSL_QNX_CAAM @@ -3981,11 +3985,38 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte sigEd448Oid[] = {43, 101, 113}; #endif /* HAVE_ED448 */ #ifdef HAVE_PQC +#ifdef HAVE_FALCON /* Falcon Level 1: 1 3 9999 3 1 */ static const byte sigFalcon_Level1Oid[] = {43, 206, 15, 3, 1}; /* Falcon Level 5: 1 3 9999 3 4 */ static const byte sigFalcon_Level5Oid[] = {43, 206, 15, 3, 4}; +#endif /* HAVE_FACON */ +#ifdef HAVE_DILITHIUM + /* Dilithium Level 2: 1.3.6.1.4.1.2.267.7.4.4 */ + static const byte sigDilithium_Level2Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 4, 4}; + + /* Dilithium Level 3: 1.3.6.1.4.1.2.267.7.6.5 */ + static const byte sigDilithium_Level3Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 6, 5}; + + /* Dilithium Level 5: 1.3.6.1.4.1.2.267.7.8.7 */ + static const byte sigDilithium_Level5Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 8, 7}; + + /* Dilithium AES Level 2: 1.3.6.1.4.1.2.267.11.4.4 */ + static const byte sigDilithiumAes_Level2Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 4, 4}; + + /* Dilithium AES Level 3: 1.3.6.1.4.1.2.267.11.6.5 */ + static const byte sigDilithiumAes_Level3Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 6, 5}; + + /* Dilithium AES Level 5: 1.3.6.1.4.1.2.267.11.8.7 */ + static const byte sigDilithiumAes_Level5Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 8, 7}; +#endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ /* keyType */ @@ -4017,11 +4048,38 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; #endif /* !NO_DH */ #ifdef HAVE_PQC +#ifdef HAVE_FALCON /* Falcon Level 1: 1 3 9999 3 1 */ static const byte keyFalcon_Level1Oid[] = {43, 206, 15, 3, 1}; /* Falcon Level 5: 1 3 9999 3 4 */ static const byte keyFalcon_Level5Oid[] = {43, 206, 15, 3, 4}; +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + /* Dilithium Level 2: 1.3.6.1.4.1.2.267.7.4.4 */ + static const byte keyDilithium_Level2Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 4, 4}; + + /* Dilithium Level 3: 1.3.6.1.4.1.2.267.7.6.5 */ + static const byte keyDilithium_Level3Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 6, 5}; + + /* Dilithium Level 5: 1.3.6.1.4.1.2.267.7.8.7 */ + static const byte keyDilithium_Level5Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 7, 8, 7}; + + /* Dilithium AES Level 2: 1.3.6.1.4.1.2.267.11.4.4 */ + static const byte keyDilithiumAes_Level2Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 4, 4}; + + /* Dilithium AES Level 3: 1.3.6.1.4.1.2.267.11.6.5 */ + static const byte keyDilithiumAes_Level3Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 6, 5}; + + /* Dilithium AES Level 5: 1.3.6.1.4.1.2.267.11.8.7 */ + static const byte keyDilithiumAes_Level5Oid[] = + {43, 6, 1, 4, 1, 2, 130, 11, 11, 8, 7}; +#endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ /* curveType */ @@ -4520,6 +4578,7 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) break; #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON case CTC_FALCON_LEVEL1: oid = sigFalcon_Level1Oid; *oidSz = sizeof(sigFalcon_Level1Oid); @@ -4528,7 +4587,34 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = sigFalcon_Level5Oid; *oidSz = sizeof(sigFalcon_Level5Oid); break; - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + case CTC_DILITHIUM_LEVEL2: + oid = sigDilithium_Level2Oid; + *oidSz = sizeof(sigDilithium_Level2Oid); + break; + case CTC_DILITHIUM_LEVEL3: + oid = sigDilithium_Level3Oid; + *oidSz = sizeof(sigDilithium_Level3Oid); + break; + case CTC_DILITHIUM_LEVEL5: + oid = sigDilithium_Level5Oid; + *oidSz = sizeof(sigDilithium_Level5Oid); + break; + case CTC_DILITHIUM_AES_LEVEL2: + oid = sigDilithiumAes_Level2Oid; + *oidSz = sizeof(sigDilithiumAes_Level2Oid); + break; + case CTC_DILITHIUM_AES_LEVEL3: + oid = sigDilithiumAes_Level3Oid; + *oidSz = sizeof(sigDilithiumAes_Level3Oid); + break; + case CTC_DILITHIUM_AES_LEVEL5: + oid = sigDilithiumAes_Level5Oid; + *oidSz = sizeof(sigDilithiumAes_Level5Oid); + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: break; } @@ -4591,6 +4677,7 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) break; #endif /* !NO_DH */ #ifdef HAVE_PQC + #ifdef HAVE_FALCON case FALCON_LEVEL1k: oid = keyFalcon_Level1Oid; *oidSz = sizeof(keyFalcon_Level1Oid); @@ -4599,7 +4686,34 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = keyFalcon_Level5Oid; *oidSz = sizeof(keyFalcon_Level5Oid); break; - #endif + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + case DILITHIUM_LEVEL2k: + oid = keyDilithium_Level2Oid; + *oidSz = sizeof(keyDilithium_Level2Oid); + break; + case DILITHIUM_LEVEL3k: + oid = keyDilithium_Level3Oid; + *oidSz = sizeof(keyDilithium_Level3Oid); + break; + case DILITHIUM_LEVEL5k: + oid = keyDilithium_Level5Oid; + *oidSz = sizeof(keyDilithium_Level5Oid); + break; + case DILITHIUM_AES_LEVEL2k: + oid = keyDilithiumAes_Level2Oid; + *oidSz = sizeof(keyDilithiumAes_Level2Oid); + break; + case DILITHIUM_AES_LEVEL3k: + oid = keyDilithiumAes_Level3Oid; + *oidSz = sizeof(keyDilithiumAes_Level3Oid); + break; + case DILITHIUM_AES_LEVEL5k: + oid = keyDilithiumAes_Level5Oid; + *oidSz = sizeof(keyDilithiumAes_Level5Oid); + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: break; } @@ -5461,6 +5575,9 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, { int ret = 0; word32 idx = *inOutIdx; +#ifdef HAVE_PQC + int found_collision = 0; +#endif /* HAVE_PQC */ #ifndef NO_VERIFY_OID word32 actualOidSz; const byte* actualOid; @@ -5477,6 +5594,31 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, actualOidSz = (word32)length; #endif /* NO_VERIFY_OID */ +#ifdef HAVE_PQC + /* Since we are summing it up, there could be collisions...and indeed there + * are: + * + * DILITHIUM_LEVEL5 + * 1.3.6.1.4.1.2.267.7.6.7 + * {43, 6, 1, 4, 1, 2, 130, 11, 7, 8, 7} + * -> 220 + * DILITHIUM_AES_LEVEL3 + * 1.3.6.1.4.1.2.267.11.4.5 + * {43, 6, 1, 4, 1, 2, 130, 11, 11, 6, 5} + * -> 220 + * + * As a small hack, we're going to look for the special case of + * DILITHIUM_AES_LEVEL3k and if we find it, instead of *oid being set to 220 + * we will set it to 221. This hack will hopefully disappear when new + * standardized OIDs appear. Note that DILITHIUM_AES_LEVEL3k is defined to + * be 221. + */ + if (memcmp(sigDilithiumAes_Level3Oid, &input[idx], + sizeof(sigDilithiumAes_Level3Oid)) == 0) { + found_collision = 1; + } +#endif /* HAVE_PQC */ + /* Sum it up for now. */ while (length--) { /* odd HC08 compiler behavior here when input[idx++] */ @@ -5484,6 +5626,12 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, idx++; } +#ifdef HAVE_PQC + if (found_collision) { + *oid = DILITHIUM_AES_LEVEL3k; + } +#endif /* HAVE_PQC */ + /* Return the index after the OID data. */ *inOutIdx = idx; @@ -5585,6 +5733,7 @@ int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, /* Return the id/sum. */ *oid = dataASN[OBJECTIDASN_IDX_OID].data.oid.sum; } + return ret; #endif /* WOLFSSL_ASN_TEMPLATE */ } @@ -6322,7 +6471,7 @@ enum { #define pkcs8KeyASN_Length (sizeof(pkcs8KeyASN) / sizeof(ASNItem)) #endif -/* Remove PKCS #8 header around an RSA, ECDSA, Ed25519, Ed448, or Falcon key. +/* Remove PKCS #8 header around an RSA, ECDSA, Ed25519, or Ed448. * * @param [in] input Buffer holding BER data. * @param [in, out] inOutIdx On in, start of PKCS #8 encoding. @@ -6523,6 +6672,7 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, break; #endif /* DSAk not supported. */ + /* Falcon and Dilithium not supported. */ /* Ignore OID lookup failures. */ default: break; @@ -7031,7 +7181,8 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, } else #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) if ((ks == FALCON_LEVEL1k) || (ks == FALCON_LEVEL5k)) { #ifdef WOLFSSL_SMALL_STACK falcon_key* key_pair = NULL; @@ -7091,7 +7242,79 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, #endif } else - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + if ((ks == DILITHIUM_LEVEL2k) || + (ks == DILITHIUM_LEVEL3k) || + (ks == DILITHIUM_LEVEL5k) || + (ks == DILITHIUM_AES_LEVEL2k) || + (ks == DILITHIUM_AES_LEVEL3k) || + (ks == DILITHIUM_AES_LEVEL5k)) { + #ifdef WOLFSSL_SMALL_STACK + dilithium_key* key_pair = NULL; + #else + dilithium_key key_pair[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (dilithium_key*)XMALLOC(sizeof(dilithium_key), NULL, + DYNAMIC_TYPE_DILITHIUM); + if (key_pair == NULL) + return MEMORY_E; + #endif + ret = wc_dilithium_init(key_pair); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + return ret; + } + + if (ks == DILITHIUM_LEVEL2k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 2, SHAKE_VARIANT); + } + else if (ks == DILITHIUM_LEVEL3k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 3, SHAKE_VARIANT); + } + else if (ks == DILITHIUM_LEVEL5k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 5, SHAKE_VARIANT); + } + else if (ks == DILITHIUM_AES_LEVEL2k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 2, AES_VARIANT); + } + else if (ks == DILITHIUM_AES_LEVEL3k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 3, AES_VARIANT); + } + else if (ks == DILITHIUM_AES_LEVEL5k) { + ret = wc_dilithium_set_level_and_sym(key_pair, 5, AES_VARIANT); + } + + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + return ret; + } + if ((ret = wc_Dilithium_PrivateKeyDecode(privKey, &keyIdx, key_pair, + privKeySz)) == 0) { + WOLFSSL_MSG("Checking Dilithium_ key pair"); + keyIdx = 0; + if ((ret = wc_dilithium_import_public(pubKey, pubKeySz, + key_pair)) == 0) { + /* Public and private extracted successfully. Sanity check. */ + if ((ret = wc_dilithium_check_key(key_pair)) == 0) + ret = 1; + } + } + wc_dilithium_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + } + else + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ { ret = 0; } @@ -7395,6 +7618,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ #if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if (*algoID == 0) { falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(*falcon), heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -7428,6 +7652,84 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } XFREE(falcon, heap, DYNAMIC_TYPE_TMP_BUFFER); } +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + if (*algoID == 0) { + dilithium_key *dilithium = (dilithium_key *)XMALLOC(sizeof(*dilithium), + heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dilithium == NULL) + return MEMORY_E; + + if (wc_dilithium_init(dilithium) != 0) { + tmpIdx = 0; + if (wc_dilithium_set_level_and_sym(dilithium, 2, SHAKE_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_LEVEL2k; + } + else { + WOLFSSL_MSG("Not Dilithium Level 2 DER key"); + } + } + else if (wc_dilithium_set_level_and_sym(dilithium, 3, SHAKE_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_LEVEL3k; + } + else { + WOLFSSL_MSG("Not Dilithium Level 3 DER key"); + } + } + else if (wc_dilithium_set_level_and_sym(dilithium, 5, SHAKE_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_LEVEL5k; + } + else { + WOLFSSL_MSG("Not Dilithium Level 5 DER key"); + } + } + else if (wc_dilithium_set_level_and_sym(dilithium, 2, AES_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_AES_LEVEL2k; + } + else { + WOLFSSL_MSG("Not Dilithium AES Level 2 DER key"); + } + } + else if (wc_dilithium_set_level_and_sym(dilithium, 3, AES_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_AES_LEVEL3k; + } + else { + WOLFSSL_MSG("Not Dilithium AES Level 3 DER key"); + } + } + else if (wc_dilithium_set_level_and_sym(dilithium, 5, AES_VARIANT) + == 0) { + if (wc_Dilithium_PrivateKeyDecode(key, &tmpIdx, dilithium, + keySz) == 0) { + *algoID = DILITHIUM_AES_LEVEL5k; + } + else { + WOLFSSL_MSG("Not Dilithium AES Level 5 DER key"); + } + } + else { + WOLFSSL_MSG("GetKeyOID dilithium initialization failed"); + } + wc_dilithium_free(dilithium); + } + XFREE(dilithium, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ /* if flag is not set then this is not a key that we understand. */ @@ -11199,6 +11501,7 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx, break; #endif /* HAVE_ED448 */ #ifdef HAVE_PQC + #ifdef HAVE_FALCON case FALCON_LEVEL1k: cert->pkCurveOID = FALCON_LEVEL1k; ret = StoreKey(cert, source, &srcIdx, maxIdx); @@ -11207,6 +11510,33 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx, cert->pkCurveOID = FALCON_LEVEL5k; ret = StoreKey(cert, source, &srcIdx, maxIdx); break; + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + case DILITHIUM_LEVEL2k: + cert->pkCurveOID = DILITHIUM_LEVEL2k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case DILITHIUM_LEVEL3k: + cert->pkCurveOID = DILITHIUM_LEVEL3k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case DILITHIUM_LEVEL5k: + cert->pkCurveOID = DILITHIUM_LEVEL5k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case DILITHIUM_AES_LEVEL2k: + cert->pkCurveOID = DILITHIUM_AES_LEVEL2k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case DILITHIUM_AES_LEVEL3k: + cert->pkCurveOID = DILITHIUM_AES_LEVEL3k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + case DILITHIUM_AES_LEVEL5k: + cert->pkCurveOID = DILITHIUM_AES_LEVEL5k; + ret = StoreKey(cert, source, &srcIdx, maxIdx); + break; + #endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ #ifndef NO_DSA case DSAk: @@ -14141,7 +14471,8 @@ static WC_INLINE int IsSigAlgoECDSA(int algoOID) } #endif -/* Determines if OID is for an EC signing algorithm including ECDSA and EdDSA. +/* Determines if OID is for an EC signing algorithm including ECDSA and EdDSA + * and post-quantum algorithms. * * @param [in] algoOID Algorithm OID. * @return 1 when is EC signing algorithm. @@ -14168,9 +14499,19 @@ static WC_INLINE int IsSigAlgoECC(int algoOID) || (algoOID == X448k) #endif #ifdef HAVE_PQC + #ifdef HAVE_FACON || (algoOID == FALCON_LEVEL1k) || (algoOID == FALCON_LEVEL5k) #endif + #ifdef HAVE_DILITHIUM + || (algoOID == DILITHIUM_LEVEL2k) + || (algoOID == DILITHIUM_LEVEL3k) + || (algoOID == DILITHIUM_LEVEL5k) + || (algoOID == DILITHIUM_AES_LEVEL2k) + || (algoOID == DILITHIUM_AES_LEVEL3k) + || (algoOID == DILITHIUM_AES_LEVEL5k) + #endif + #endif /* HAVE_PQC */ ); } @@ -14459,7 +14800,8 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) sigCtx->key.ed448 = NULL; break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: wc_falcon_free(sigCtx->key.falcon); @@ -14467,7 +14809,21 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) DYNAMIC_TYPE_FALCON); sigCtx->key.falcon = NULL; break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_LEVEL3k: + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL2k: + case DILITHIUM_AES_LEVEL3k: + case DILITHIUM_AES_LEVEL5k: + wc_dilithium_free(sigCtx->key.dilithium); + XFREE(sigCtx->key.dilithium, sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + sigCtx->key.dilithium = NULL; + break; + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: break; } /* switch (keyOID) */ @@ -14606,11 +14962,23 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, break; #endif #ifdef HAVE_PQC + #ifdef HAVE_FALCON case CTC_FALCON_LEVEL1: case CTC_FALCON_LEVEL5: /* Hashes done in signing operation. */ break; #endif + #ifdef HAVE_DILITHIUM + case CTC_DILITHIUM_LEVEL2: + case CTC_DILITHIUM_LEVEL3: + case CTC_DILITHIUM_LEVEL5: + case CTC_DILITHIUM_AES_LEVEL2: + case CTC_DILITHIUM_AES_LEVEL3: + case CTC_DILITHIUM_AES_LEVEL5: + /* Hashes done in signing operation. */ + break; + #endif + #endif /* HAVE_PQC */ default: ret = HASH_TYPE_E; @@ -14952,7 +15320,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: { sigCtx->verify = 0; @@ -15003,7 +15372,160 @@ static int ConfirmSignature(SignatureCtx* sigCtx, } break; } - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 2, SHAKE_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 2"); + goto exit_cs; + } + break; + } + case DILITHIUM_LEVEL3k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 3, SHAKE_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 5"); + goto exit_cs; + } + break; + } + case DILITHIUM_LEVEL5k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 5, SHAKE_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 5"); + goto exit_cs; + } + break; + } + case DILITHIUM_AES_LEVEL2k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 2, AES_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 2"); + goto exit_cs; + } + break; + } + case DILITHIUM_AES_LEVEL3k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 3, AES_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 5"); + goto exit_cs; + } + break; + } + case DILITHIUM_AES_LEVEL5k: + { + sigCtx->verify = 0; + sigCtx->key.dilithium = + (dilithium_key*)XMALLOC(sizeof(dilithium_key), + sigCtx->heap, + DYNAMIC_TYPE_DILITHIUM); + if (sigCtx->key.dilithium == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_dilithium_init(sigCtx->key.dilithium)) < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_set_level_and_sym( + sigCtx->key.dilithium, 5, AES_VARIANT)) + < 0) { + goto exit_cs; + } + if ((ret = wc_dilithium_import_public(key, keySz, + sigCtx->key.dilithium)) < 0) { + WOLFSSL_MSG("ASN Key import error Dilithium Level 5"); + goto exit_cs; + } + break; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: WOLFSSL_MSG("Verify Key type unknown"); ret = ASN_UNKNOWN_OID_E; @@ -15113,7 +15635,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: { @@ -15122,7 +15645,22 @@ static int ConfirmSignature(SignatureCtx* sigCtx, sigCtx->key.falcon); break; } - #endif + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + case DILITHIUM_LEVEL3k: + case DILITHIUM_LEVEL5k: + case DILITHIUM_AES_LEVEL2k: + case DILITHIUM_AES_LEVEL3k: + case DILITHIUM_AES_LEVEL5k: + { + ret = wc_dilithium_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, + sigCtx->key.dilithium); + break; + } + #endif /* HAVE_DILITHIUM */ + #endif /* HAVE_PQC */ default: break; } /* switch (keyOID) */ @@ -15266,6 +15804,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx, } #endif /* HAVE_ED448 */ #ifdef HAVE_PQC + #ifdef HAVE_FALCON case FALCON_LEVEL1k: { if (sigCtx->verify == 1) { @@ -15290,6 +15829,75 @@ static int ConfirmSignature(SignatureCtx* sigCtx, } break; } + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + case DILITHIUM_LEVEL2k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_LEVEL2 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case DILITHIUM_LEVEL3k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_LEVEL3 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case DILITHIUM_LEVEL5k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_LEVEL5 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case DILITHIUM_AES_LEVEL2k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_AES_LEVEL2 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case DILITHIUM_AES_LEVEL3k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_AES_LEVEL3 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + case DILITHIUM_AES_LEVEL5k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("DILITHIUM_AES_LEVEL5 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ default: break; @@ -21290,11 +21898,28 @@ wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; #endif #if defined(HAVE_PQC) +#if defined(HAVE_FALCON) wcchar BEGIN_FALCON_LEVEL1_PRIV = "-----BEGIN FALCON_LEVEL1 PRIVATE KEY-----"; wcchar END_FALCON_LEVEL1_PRIV = "-----END FALCON_LEVEL1 PRIVATE KEY-----"; wcchar BEGIN_FALCON_LEVEL5_PRIV = "-----BEGIN FALCON_LEVEL5 PRIVATE KEY-----"; wcchar END_FALCON_LEVEL5_PRIV = "-----END FALCON_LEVEL5 PRIVATE KEY-----"; -#endif +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + wcchar BEGIN_DILITHIUM_LEVEL2_PRIV = "-----BEGIN DILITHIUM_LEVEL2 PRIVATE KEY-----"; + wcchar END_DILITHIUM_LEVEL2_PRIV = "-----END DILITHIUM_LEVEL2 PRIVATE KEY-----"; + wcchar BEGIN_DILITHIUM_LEVEL3_PRIV = "-----BEGIN DILITHIUM_LEVEL3 PRIVATE KEY-----"; + wcchar END_DILITHIUM_LEVEL3_PRIV = "-----END DILITHIUM_LEVEL3 PRIVATE KEY-----"; + wcchar BEGIN_DILITHIUM_LEVEL5_PRIV = "-----BEGIN DILITHIUM_LEVEL5 PRIVATE KEY-----"; + wcchar END_DILITHIUM_LEVEL5_PRIV = "-----END DILITHIUM_LEVEL5 PRIVATE KEY-----"; + + wcchar BEGIN_DILITHIUM_AES_LEVEL2_PRIV = "-----BEGIN DILITHIUM_AES_LEVEL2 PRIVATE KEY-----"; + wcchar END_DILITHIUM_AES_LEVEL2_PRIV = "-----END DILITHIUM_AES_LEVEL2 PRIVATE KEY-----"; + wcchar BEGIN_DILITHIUM_AES_LEVEL3_PRIV = "-----BEGIN DILITHIUM_AES_LEVEL3 PRIVATE KEY-----"; + wcchar END_DILITHIUM_AES_LEVEL3_PRIV = "-----END DILITHIUM_AES_LEVEL3 PRIVATE KEY-----"; + wcchar BEGIN_DILITHIUM_AES_LEVEL5_PRIV = "-----BEGIN DILITHIUM_AES_LEVEL5 PRIVATE KEY-----"; + wcchar END_DILITHIUM_AES_LEVEL5_PRIV = "-----END DILITHIUM_AES_LEVEL5 PRIVATE KEY-----"; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ const int pem_struct_min_sz = XSTR_SIZEOF("-----BEGIN X509 CRL-----" "-----END X509 CRL-----"); @@ -21390,6 +22015,7 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) break; #endif #ifdef HAVE_PQC +#ifdef HAVE_FALCON case FALCON_LEVEL1_TYPE: if (header) *header = BEGIN_FALCON_LEVEL1_PRIV; if (footer) *footer = END_FALCON_LEVEL1_PRIV; @@ -21400,7 +22026,40 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) if (footer) *footer = END_FALCON_LEVEL5_PRIV; ret = 0; break; -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + case DILITHIUM_LEVEL2_TYPE: + if (header) *header = BEGIN_DILITHIUM_LEVEL2_PRIV; + if (footer) *footer = END_DILITHIUM_LEVEL2_PRIV; + ret = 0; + break; + case DILITHIUM_LEVEL3_TYPE: + if (header) *header = BEGIN_DILITHIUM_LEVEL3_PRIV; + if (footer) *footer = END_DILITHIUM_LEVEL3_PRIV; + ret = 0; + break; + case DILITHIUM_LEVEL5_TYPE: + if (header) *header = BEGIN_DILITHIUM_LEVEL5_PRIV; + if (footer) *footer = END_DILITHIUM_LEVEL5_PRIV; + ret = 0; + break; + case DILITHIUM_AES_LEVEL2_TYPE: + if (header) *header = BEGIN_DILITHIUM_AES_LEVEL2_PRIV; + if (footer) *footer = END_DILITHIUM_AES_LEVEL2_PRIV; + ret = 0; + break; + case DILITHIUM_AES_LEVEL3_TYPE: + if (header) *header = BEGIN_DILITHIUM_AES_LEVEL3_PRIV; + if (footer) *footer = END_DILITHIUM_AES_LEVEL3_PRIV; + ret = 0; + break; + case DILITHIUM_AES_LEVEL5_TYPE: + if (header) *header = BEGIN_DILITHIUM_AES_LEVEL5_PRIV; + if (footer) *footer = END_DILITHIUM_AES_LEVEL5_PRIV; + ret = 0; + break; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ case PUBLICKEY_TYPE: case ECC_PUBLICKEY_TYPE: if (header) *header = BEGIN_PUB_KEY; @@ -23671,52 +24330,6 @@ int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen, return ret; } #endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ - -#if defined(HAVE_PQC) && defined(HAVE_FALCON) -/* Encode the public part of an Falcon key in DER. - * - * Pass NULL for output to get the size of the encoding. - * - * @param [in] key Falcon key object. - * @param [out] output Buffer to put encoded data in. - * @param [in] outLen Size of buffer in bytes. - * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. - * @return Size of encoded data in bytes on success. - * @return BAD_FUNC_ARG when key is NULL. - * @return MEMORY_E when dynamic memory allocation failed. - */ -int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen, - int withAlg) -{ - int ret; - byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; - word32 pubKeyLen = (word32)sizeof(pubKey); - int keytype = 0; - - if (key == NULL || output == NULL) { - return BAD_FUNC_ARG; - } - - if (key->level == 1) { - keytype = FALCON_LEVEL1k; - } - else if (key->level == 5) { - keytype = FALCON_LEVEL5k; - } - else { - return BAD_FUNC_ARG; - } - - ret = wc_falcon_export_public(key, pubKey, &pubKeyLen); - if (ret == 0) { - ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype, - withAlg); - } - - return ret; -} -#endif /* HAVE_PQC && HAVE_FALCON */ - #ifdef WOLFSSL_CERT_GEN #ifndef NO_ASN_TIME @@ -26023,7 +26636,8 @@ static int SetValidity(byte* before, byte* after, int daysValid) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, DsaKey* dsaKey, ed25519_key* ed25519Key, - ed448_key* ed448Key, falcon_key* falconKey) + ed448_key* ed448Key, falcon_key* falconKey, + dilithium_key* dilithiumKey) { int ret; @@ -26032,7 +26646,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* make sure at least one key type is provided */ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && - dsaKey == NULL && ed448Key == NULL && falconKey == NULL) { + dsaKey == NULL && ed448Key == NULL && falconKey == NULL && + dilithiumKey == NULL) { return PUBLIC_KEY_E; } @@ -26109,6 +26724,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, #endif #if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if ((cert->keyType == FALCON_LEVEL1_KEY) || (cert->keyType == FALCON_LEVEL5_KEY)) { if (falconKey == NULL) @@ -26118,7 +26734,23 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, wc_Falcon_PublicKeyToDer(falconKey, der->publicKey, (word32)sizeof(der->publicKey), 1); } -#endif +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + if ((cert->keyType == DILITHIUM_LEVEL2_KEY) || + (cert->keyType == DILITHIUM_LEVEL3_KEY) || + (cert->keyType == DILITHIUM_LEVEL5_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL2_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL3_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL5_KEY)) { + if (dilithiumKey == NULL) + return PUBLIC_KEY_E; + + der->publicKeySz = + wc_Dilithium_PublicKeyToDer(dilithiumKey, der->publicKey, + (word32)sizeof(der->publicKey), 1); + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -26512,7 +27144,7 @@ static int WriteCertBody(DerCert* der, byte* buf) static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, ed448_key* ed448Key, falcon_key* falconKey, - WC_RNG* rng, int sigAlgoType, void* heap) + dilithium_key* dilithiumKey, WC_RNG* rng, int sigAlgoType, void* heap) { int digestSz = 0, typeH = 0, ret = 0; @@ -26527,6 +27159,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, (void)ed25519Key; (void)ed448Key; (void)falconKey; + (void)dilithiumKey; (void)rng; (void)heap; @@ -26610,12 +27243,23 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, #endif /* HAVE_ED448 && HAVE_ED448_SIGN */ #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) if (!rsaKey && !eccKey && !ed25519Key && !ed448Key && falconKey) { word32 outSz = sigSz; ret = wc_falcon_sign_msg(buf, sz, sig, &outSz, falconKey); if (ret == 0) ret = outSz; } + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + if (!rsaKey && !eccKey && !ed25519Key && !ed448Key && !falconKey && + dilithiumKey) { + word32 outSz = sigSz; + ret = wc_dilithium_sign_msg(buf, sz, sig, &outSz, dilithiumKey); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_DILITHIUM */ #endif /* HAVE_PQC */ break; @@ -26796,7 +27440,8 @@ int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, DsaKey* dsaKey, ed25519_key* ed25519Key, - ed448_key* ed448Key, falcon_key* falconKey) + ed448_key* ed448Key, falcon_key* falconKey, + dilithium_key* dilithiumKey) { #ifndef WOLFSSL_ASN_TEMPLATE int ret; @@ -26820,11 +27465,33 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key) cert->keyType = ED448_KEY; #ifdef HAVE_PQC +#ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) cert->keyType = FALCON_LEVEL1_KEY; else if ((falconKey != NULL) && (falconKey->level == 5)) cert->keyType = FALCON_LEVEL5_KEY; -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL2_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL3_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL5_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL2_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL3_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL5_KEY; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ else return BAD_FUNC_ARG; @@ -26835,7 +27502,7 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, #endif ret = EncodeCert(cert, der, rsaKey, eccKey, rng, dsaKey, ed25519Key, - ed448Key, falconKey); + ed448Key, falconKey, dilithiumKey); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -26860,7 +27527,9 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, word32 issRawLen = 0; word32 sbjRawLen = 0; - (void)falconKey; /* Unused without OQS */ + (void)falconKey; /* Unused without OQS */ + (void)dilithiumKey; /* Unused without OQS */ + CALLOC_ASNSETDATA(dataASN, x509CertASN_Length, ret, cert->heap); if (ret == 0) { @@ -26880,14 +27549,42 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key) { cert->keyType = ED448_KEY; } - else if (falconKey != NULL) { - #ifdef HAVE_PQC - if (falconKey->level == 1) - cert->keyType = FALCON_LEVEL1_KEY; - else if (falconKey->level == 5) - cert->keyType = FALCON_LEVEL5_KEY; - #endif +#ifdef HAVE_PQC +#ifdef HAVE_FALCON + else if ((falconKey != NULL) && (falconKey->level == 1)) { + cert->keyType = FALCON_LEVEL1_KEY; } + else if ((falconKey != NULL) && (falconKey->level == 5)) { + cert->keyType = FALCON_LEVEL5_KEY; + } +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL2_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL3_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL5_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL2_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL3_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL5_KEY; + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ else { ret = BAD_FUNC_ARG; } @@ -27127,6 +27824,7 @@ int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, ed25519_key* ed25519Key = NULL; ed448_key* ed448Key = NULL; falcon_key* falconKey = NULL; + dilithium_key* dilithiumKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -27142,9 +27840,21 @@ int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, falconKey = (falcon_key*)key; else if (keyType == FALCON_LEVEL5_TYPE) falconKey = (falcon_key*)key; + else if (keyType == DILITHIUM_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, dsaKey, - ed25519Key, ed448Key, falconKey); + ed25519Key, ed448Key, falconKey, dilithiumKey); } /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ @@ -27152,7 +27862,7 @@ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, NULL, - NULL, NULL); + NULL, NULL, NULL); } #ifdef WOLFSSL_CERT_REQ @@ -27316,7 +28026,7 @@ static int SetCustomObjectId(Cert* cert, byte* output, word32 outSz, static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, DsaKey* dsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, ed448_key* ed448Key, - falcon_key* falconKey) + falcon_key* falconKey, dilithium_key* dilithiumKey) { int ret; @@ -27324,12 +28034,14 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, (void)ed25519Key; (void)ed448Key; (void)falconKey; + (void)dilithiumKey; if (cert == NULL || der == NULL) return BAD_FUNC_ARG; if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && - dsaKey == NULL && ed448Key == NULL && falconKey == NULL) { + dsaKey == NULL && ed448Key == NULL && falconKey == NULL && + falconKey == NULL) { return PUBLIC_KEY_E; } @@ -27412,6 +28124,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, } #endif #if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if ((cert->keyType == FALCON_LEVEL1_KEY) || (cert->keyType == FALCON_LEVEL5_KEY)) { if (falconKey == NULL) @@ -27420,6 +28133,20 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, der->publicKey, (word32)sizeof(der->publicKey), 1); } #endif +#if defined(HAVE_DILITHIUM) + if ((cert->keyType == DILITHIUM_LEVEL2_KEY) || + (cert->keyType == DILITHIUM_LEVEL3_KEY) || + (cert->keyType == DILITHIUM_LEVEL5_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL2_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL3_KEY) || + (cert->keyType == DILITHIUM_AES_LEVEL5_KEY)) { + if (dilithiumKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = wc_Dilithium_PublicKeyToDer(dilithiumKey, + der->publicKey, (word32)sizeof(der->publicKey), 1); + } +#endif +#endif /* HAVE_PQC */ if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -27703,7 +28430,7 @@ enum { static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, DsaKey* dsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, ed448_key* ed448Key, - falcon_key* falconKey) + falcon_key* falconKey, dilithium_key* dilithiumKey) { #ifndef WOLFSSL_ASN_TEMPLATE int ret; @@ -27724,11 +28451,33 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key) cert->keyType = ED448_KEY; #ifdef HAVE_PQC +#ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) cert->keyType = FALCON_LEVEL1_KEY; else if ((falconKey != NULL) && (falconKey->level == 5)) cert->keyType = FALCON_LEVEL5_KEY; -#endif +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL2_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL3_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == SHAKE_VARIANT)) + cert->keyType = DILITHIUM_LEVEL5_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL2_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL3_KEY; + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == AES_VARIANT)) + cert->keyType = DILITHIUM_AES_LEVEL5_KEY; +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ else return BAD_FUNC_ARG; @@ -27740,7 +28489,7 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, #endif ret = EncodeCertReq(cert, der, rsaKey, dsaKey, eccKey, ed25519Key, ed448Key, - falconKey); + falconKey, dilithiumKey); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -27765,7 +28514,10 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, word32 sbjRawSz; #endif - (void)falconKey; /* Unused without OQS */ + /* Unused without OQS */ + (void)falconKey; + (void)dilithiumKey; + CALLOC_ASNSETDATA(dataASN, certReqBodyASN_Length, ret, cert->heap); if (ret == 0) { @@ -27785,14 +28537,42 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key != NULL) { cert->keyType = ED448_KEY; } - else if (falconKey != NULL) { - #ifdef HAVE_PQC - if (falconKey->level == 1) - cert->keyType = FALCON_LEVEL1_KEY; - else if (falconKey->level == 5) - cert->keyType = FALCON_LEVEL5_KEY; - #endif +#ifdef HAVE_PQC +#ifdef HAVE_FALCON + else if ((falconKey != NULL) && (falconKey->level == 1)) { + cert->keyType = FALCON_LEVEL1_KEY; } + else if ((falconKey != NULL) && (falconKey->level == 5)) { + cert->keyType = FALCON_LEVEL5_KEY; + } +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL2_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL3_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == SHAKE_VARIANT)) { + cert->keyType = DILITHIUM_LEVEL5_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 2) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL2_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 3) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL3_KEY; + } + else if ((dilithiumKey != NULL) && (dilithiumKey->level == 5) + && (dilithiumKey->sym == AES_VARIANT)) { + cert->keyType = DILITHIUM_AES_LEVEL5_KEY; + } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ else { ret = BAD_FUNC_ARG; } @@ -27933,12 +28713,13 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, void* key) { - RsaKey* rsaKey = NULL; - DsaKey* dsaKey = NULL; - ecc_key* eccKey = NULL; - ed25519_key* ed25519Key = NULL; - ed448_key* ed448Key = NULL; - falcon_key* falconKey = NULL; + RsaKey* rsaKey = NULL; + DsaKey* dsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = NULL; + falcon_key* falconKey = NULL; + dilithium_key* dilithiumKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -27954,23 +28735,36 @@ int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, falconKey = (falcon_key*)key; else if (keyType == FALCON_LEVEL5_TYPE) falconKey = (falcon_key*)key; + else if (keyType == DILITHIUM_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; return MakeCertReq(cert, derBuffer, derSz, rsaKey, dsaKey, eccKey, - ed25519Key, ed448Key, falconKey); + ed25519Key, ed448Key, falconKey, dilithiumKey); } int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey) { return MakeCertReq(cert, derBuffer, derSz, rsaKey, NULL, eccKey, NULL, - NULL, NULL); + NULL, NULL, NULL); } #endif /* WOLFSSL_CERT_REQ */ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, - ed448_key* ed448Key, falcon_key* falconKey, WC_RNG* rng) + ed448_key* ed448Key, falcon_key* falconKey, + dilithium_key* dilithiumKey, WC_RNG* rng) { int sigSz = 0; void* heap = NULL; @@ -28024,7 +28818,7 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, sigSz = MakeSignature(certSignCtx, buf, requestSz, certSignCtx->sig, MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, - falconKey, rng, sType, heap); + falconKey, dilithiumKey, rng, sType, heap); #ifdef WOLFSSL_ASYNC_CRYPT if (sigSz == WC_PENDING_E) { /* Not free'ing certSignCtx->sig here because it could still be in use @@ -28055,6 +28849,7 @@ int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, ed25519_key* ed25519Key = NULL; ed448_key* ed448Key = NULL; falcon_key* falconKey = NULL; + dilithium_key* dilithiumKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -28068,17 +28863,28 @@ int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, falconKey = (falcon_key*)key; else if (keyType == FALCON_LEVEL5_TYPE) falconKey = (falcon_key*)key; - + else if (keyType == DILITHIUM_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key, - ed448Key, falconKey, rng); + ed448Key, falconKey, dilithiumKey, rng); } int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL, - NULL, rng); + NULL, NULL, rng); } int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz, @@ -28112,14 +28918,15 @@ int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert) /* Set KID from public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, ed25519_key* ed25519Key, ed448_key* ed448Key, - falcon_key* falconKey, int kid_type) + falcon_key* falconKey, + dilithium_key* dilithiumKey, int kid_type) { byte *buf; int bufferSz, ret; if (cert == NULL || (rsakey == NULL && eckey == NULL && ed25519Key == NULL && - ed448Key == NULL && falconKey == NULL) || + ed448Key == NULL && falconKey == NULL && dilithiumKey == NULL) || (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) return BAD_FUNC_ARG; @@ -28153,11 +28960,19 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, } #endif #if defined(HAVE_PQC) +#if defined(HAVE_FALCON) if (falconKey != NULL) { bufferSz = wc_Falcon_PublicKeyToDer(falconKey, buf, MAX_PUBLIC_KEY_SZ, 0); } #endif +#if defined(HAVE_DILITHIUM) + if (dilithiumKey != NULL) { + bufferSz = wc_Dilithium_PublicKeyToDer(dilithiumKey, buf, + MAX_PUBLIC_KEY_SZ, 0); + } +#endif +#endif /* HAVE_PQC */ if (bufferSz <= 0) { XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -28187,6 +29002,7 @@ int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) ed25519_key* ed25519Key = NULL; ed448_key* ed448Key = NULL; falcon_key* falconKey = NULL; + dilithium_key* dilithiumKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -28200,15 +29016,27 @@ int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) falconKey = (falcon_key*)key; else if (keyType == FALCON_LEVEL5_TYPE) falconKey = (falcon_key*)key; + else if (keyType == DILITHIUM_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, ed25519Key, ed448Key, - falconKey, SKID_TYPE); + falconKey, dilithiumKey, SKID_TYPE); } /* Set SKID from RSA or ECC public key */ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, NULL, SKID_TYPE); } @@ -28219,6 +29047,7 @@ int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) ed25519_key* ed25519Key = NULL; ed448_key* ed448Key = NULL; falcon_key* falconKey = NULL; + dilithium_key* dilithiumKey = NULL; if (keyType == RSA_TYPE) rsaKey = (RsaKey*)key; @@ -28230,15 +29059,29 @@ int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) ed448Key = (ed448_key*)key; else if (keyType == FALCON_LEVEL1_TYPE) falconKey = (falcon_key*)key; + else if (keyType == FALCON_LEVEL5_TYPE) + falconKey = (falcon_key*)key; + else if (keyType == DILITHIUM_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL2_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL3_TYPE) + dilithiumKey = (dilithium_key*)key; + else if (keyType == DILITHIUM_AES_LEVEL5_TYPE) + dilithiumKey = (dilithium_key*)key; return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, ed25519Key, ed448Key, - falconKey, AKID_TYPE); + falconKey, dilithiumKey, AKID_TYPE); } /* Set SKID from RSA or ECC public key */ int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, NULL, NULL, NULL, AKID_TYPE); } @@ -30968,9 +31811,10 @@ enum { || (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) \ || (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) \ || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ - || (defined(HAVE_PQC) && defined(HAVE_FALCON))) + || (defined(HAVE_PQC) && defined(HAVE_FALCON)) \ + || (defined(HAVE_PQC) && defined(HAVE_DILITHIUM))) -static int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, +int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType) { @@ -31304,7 +32148,7 @@ int wc_Curve25519PublicKeyDecode(const byte* input, word32* inOutIdx, * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. */ -static int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, +int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, const byte* pubKey, word32 pubKeyLen, byte* output, word32 outLen, int keyType) { @@ -31536,75 +32380,6 @@ int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) -int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx, - falcon_key* key, word32 inSz) -{ - int ret = 0; - byte privKey[FALCON_MAX_KEY_SIZE], pubKey[FALCON_MAX_PUB_KEY_SIZE]; - word32 privKeyLen = (word32)sizeof(privKey); - word32 pubKeyLen = (word32)sizeof(pubKey); - int keytype = 0; - - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { - return BAD_FUNC_ARG; - } - - if (key->level == 1) { - keytype = FALCON_LEVEL1k; - } - else if (key->level == 5) { - keytype = FALCON_LEVEL5k; - } - else { - return BAD_FUNC_ARG; - } - - ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, - pubKey, &pubKeyLen, keytype); - if (ret == 0) { - if (pubKeyLen == 0) { - ret = wc_falcon_import_private_only(input, inSz, key); - } - else { - ret = wc_falcon_import_private_key(privKey, privKeyLen, - pubKey, pubKeyLen, key); - } - } - return ret; -} - -int wc_Falcon_PublicKeyDecode(const byte* input, word32* inOutIdx, - falcon_key* key, word32 inSz) -{ - int ret = 0; - byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; - word32 pubKeyLen = (word32)sizeof(pubKey); - int keytype = 0; - - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { - return BAD_FUNC_ARG; - } - - if (key->level == 1) { - keytype = FALCON_LEVEL1k; - } - else if (key->level == 5) { - keytype = FALCON_LEVEL5k; - } - else { - return BAD_FUNC_ARG; - } - - ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen, - keytype); - if (ret == 0) { - ret = wc_falcon_import_public(pubKey, pubKeyLen, key); - } - return ret; -} -#endif /* HAVE_PQC && HAVE_FALCON */ - #if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) int wc_Curve448PrivateKeyDecode(const byte* input, word32* inOutIdx, curve448_key* key, word32 inSz) @@ -31670,47 +32445,6 @@ int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen) #endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) -int wc_Falcon_KeyToDer(falcon_key* key, byte* output, word32 inLen) -{ - if (key == NULL) { - return BAD_FUNC_ARG; - } - - if (key->level == 1) { - return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, key->p, - FALCON_LEVEL1_KEY_SIZE, output, inLen, - FALCON_LEVEL1k); - } - else if (key->level == 5) { - return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, key->p, - FALCON_LEVEL5_KEY_SIZE, output, inLen, - FALCON_LEVEL5k); - } - - return BAD_FUNC_ARG; -} - -int wc_Falcon_PrivateKeyToDer(falcon_key* key, byte* output, word32 inLen) -{ - if (key == NULL) { - return BAD_FUNC_ARG; - } - - if (key->level == 1) { - return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, NULL, 0, output, - inLen, FALCON_LEVEL1k); - } - else if (key->level == 5) { - return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, NULL, 0, output, - inLen, FALCON_LEVEL5k); - } - - return BAD_FUNC_ARG; -} - -#endif /* HAVE_PQC && HAVE_FALCON */ - #if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) /* Write private Curve448 key to DER format, * length on success else < 0 */ diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c new file mode 100644 index 000000000..c9ba12a1c --- /dev/null +++ b/wolfcrypt/src/dilithium.c @@ -0,0 +1,1028 @@ +/* dilithium.c + * + * Copyright (C) 2006-2022 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Based on ed448.c and Reworked for Dilithium by Anthony Hu. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_PQC there */ +#include + +#include + +#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + +#ifdef HAVE_LIBOQS +#include +#endif + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* Sign the message using the dilithium private key. + * + * in [in] Message to sign. + * inLen [in] Length of the message in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Dilithium key to use when signing + * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE, + * 0 otherwise. + */ +int wc_dilithium_sign_msg(const byte* in, word32 inLen, + byte* out, word32 *outLen, + dilithium_key* key) +{ + int ret = 0; +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + size_t localOutLen = 0; + + /* sanity check on arguments */ + if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (!key->prvKeySet)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((key->sym == SHAKE_VARIANT) && (key->level == 2)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); + } + else if ((key->sym == SHAKE_VARIANT) && (key->level == 3)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3); + } + else if ((key->sym == SHAKE_VARIANT) && (key->level == 5)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5); + } + else if ((key->sym == AES_VARIANT) && (key->level == 2)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2_aes); + } + else if ((key->sym == AES_VARIANT) && (key->level == 3)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3_aes); + } + else if ((key->sym == AES_VARIANT) && (key->level == 5)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5_aes); + } + + if (oqssig == NULL) { + ret = SIG_TYPE_E; + } + } + + /* check and set up out length */ + if (ret == 0) { + if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_SIG_SIZE)) { + *outLen = DILITHIUM_LEVEL2_SIG_SIZE; + ret = BUFFER_E; + } + else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_SIG_SIZE)) { + *outLen = DILITHIUM_LEVEL3_SIG_SIZE; + ret = BUFFER_E; + } + else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_SIG_SIZE)) { + *outLen = DILITHIUM_LEVEL5_SIG_SIZE; + ret = BUFFER_E; + } + localOutLen = *outLen; + } + + if ((ret == 0) && + (OQS_SIG_sign(oqssig, out, &localOutLen, in, inLen, key->k) + == OQS_ERROR)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + *outLen = (word32)localOutLen; + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } +#else + ret = NOT_COMPILED_IN; +#endif + return ret; +} + +/* Verify the message using the dilithium public key. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * res [out] *res is set to 1 on successful verification. + * key [in] Dilithium key to use to verify. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * BUFFER_E when sigLen is less than DILITHIUM_LEVEL2_SIG_SIZE, + * 0 otherwise. + */ +int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, dilithium_key* key) +{ + int ret = 0; +#ifdef HAVE_LIBOQS + OQS_SIG *oqssig = NULL; + + if (key == NULL || sig == NULL || msg == NULL || res == NULL) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (!key->pubKeySet)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((key->sym == SHAKE_VARIANT) && (key->level == 2)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); + } + else if ((key->sym == SHAKE_VARIANT) && (key->level == 3)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3); + } + else if ((key->sym == SHAKE_VARIANT) && (key->level == 5)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5); + } + else if ((key->sym == AES_VARIANT) && (key->level == 2)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2_aes); + } + else if ((key->sym == AES_VARIANT) && (key->level == 3)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3_aes); + } + else if ((key->sym == AES_VARIANT) && (key->level == 5)) { + oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5_aes); + } + + if (oqssig == NULL) { + ret = SIG_TYPE_E; + } + } + + if ((ret == 0) && + (OQS_SIG_verify(oqssig, msg, msgLen, sig, sigLen, key->p) + == OQS_ERROR)) { + ret = SIG_VERIFY_E; + } + + if (ret == 0) { + *res = 1; + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } +#else + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Initialize the dilithium private/public key. + * + * key [in] Dilithium key. + * returns BAD_FUNC_ARG when key is NULL + */ +int wc_dilithium_init(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ForceZero(key, sizeof(key)); + return 0; +} + +/* Set the level of the dilithium private/public key. + * + * key [out] Dilithium key. + * level [in] Either 2,3 or 5. + * sym [in] Either SHAKE_VARIANT or AES_VARIANT. + * returns BAD_FUNC_ARG when key is NULL or level or sym are bad values. + */ +int wc_dilithium_set_level_and_sym(dilithium_key* key, byte level, byte sym) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (level != 2 && level != 3 && level != 5) { + return BAD_FUNC_ARG; + } + + if (sym != SHAKE_VARIANT && sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + key->level = level; + key->sym = sym; + key->pubKeySet = 0; + key->prvKeySet = 0; + return 0; +} + +/* Get the level and symmetric variant of the dilithium private/public key. + * + * key [in] Dilithium key. + * level [out] The level. + * sym [out] The symetric variant. SHAKE_VARIANT or AES_VARIANT. + * returns BAD_FUNC_ARG when key is NULL or level has not been set. + */ +int wc_dilithium_get_level_and_sym(dilithium_key* key, byte* level, byte* sym) +{ + if (key == NULL || level == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level != 2 && key->level != 3 && key->level != 5) { + return BAD_FUNC_ARG; + } + + if (key->sym != SHAKE_VARIANT && key->sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + *level = key->level; + *sym = key->sym; + return 0; +} + +/* Clears the dilithium key data + * + * key [in] Dilithium key. + */ +void wc_dilithium_free(dilithium_key* key) +{ + if (key != NULL) { + ForceZero(key, sizeof(key)); + } +} + +/* Export the dilithium public key. + * + * key [in] Dilithium public key. + * out [in] Array to hold public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_dilithium_export_public(dilithium_key* key, + byte* out, word32* outLen) +{ + /* sanity check on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 1) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (!key->pubKeySet) { + return BAD_FUNC_ARG; + } + + /* check and set up out length */ + if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + return BUFFER_E; + } + + if (key->level == 2) { + *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + XMEMCPY(out, key->p, DILITHIUM_LEVEL2_PUB_KEY_SIZE); + } + else if (key->level == 3) { + *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + XMEMCPY(out, key->p, DILITHIUM_LEVEL3_PUB_KEY_SIZE); + } + else if (key->level == 5) { + *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + XMEMCPY(out, key->p, DILITHIUM_LEVEL5_PUB_KEY_SIZE); + } + + return 0; +} + +/* Import a dilithium public key from a byte array. + * Public key encoded in big-endian. + * + * in [in] Array holding public key. + * inLen [in] Number of bytes of data in array. + * key [in] Dilithium public key. + * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, + * 0 otherwise. + */ +int wc_dilithium_import_public(const byte* in, word32 inLen, + dilithium_key* key) +{ + /* sanity check on arguments */ + if ((in == NULL) || (key == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (key->sym != SHAKE_VARIANT && key->sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (inLen != DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 3) && (inLen != DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 5) && (inLen != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + XMEMCPY(key->p, in, inLen); + key->pubKeySet = 1; + + return 0; +} + +static int parse_private_key(const byte* priv, word32 privSz, + byte** out, word32 *outSz, + dilithium_key* key) { + word32 idx = 0; + int ret = 0; + int length = 0; + + /* sanity check on arguments */ + if ((priv == NULL) || (key == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (key->sym != SHAKE_VARIANT && key->sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + /* At this point, it is still a PKCS8 private key. */ + if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) { + return ret; + } + + /* Now it is a octet_string(concat(priv,pub)) */ + if ((ret = GetOctetString(priv, &idx, &length, privSz)) < 0) { + return ret; + } + + *out = (byte *)priv + idx; + *outSz = privSz - idx; + + /* And finally it is concat(priv,pub). Key size check. */ + if ((key->level == 2) && (*outSz != DILITHIUM_LEVEL2_KEY_SIZE + + DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 3) && (*outSz != DILITHIUM_LEVEL3_KEY_SIZE + + DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + else if ((key->level == 5) && (*outSz != DILITHIUM_LEVEL5_KEY_SIZE + + DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + return 0; +} + +/* Import a dilithium private key from a byte array. + * + * priv [in] Array holding private key. + * privSz [in] Number of bytes of data in array. + * key [in] Dilithium private key. + * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than + * DILITHIUM_LEVEL2_KEY_SIZE, + * 0 otherwise. + */ +int wc_dilithium_import_private_only(const byte* priv, word32 privSz, + dilithium_key* key) +{ + int ret = 0; + byte *newPriv = NULL; + word32 newPrivSz = 0; + + if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) + != 0) { + return ret; + } + + if (key->level == 2) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE); + } + else if (key->level == 3) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE); + } + else if (key->level == 5) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE); + } + key->prvKeySet = 1; + + return 0; +} + +/* Import a dilithium private and public keys from byte array(s). + * + * priv [in] Array holding private key or private+public keys + * privSz [in] Number of bytes of data in private key array. + * pub [in] Array holding public key (or NULL). + * pubSz [in] Number of bytes of data in public key array (or 0). + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid + * combination of keys/lengths is supplied, 0 otherwise. + */ +int wc_dilithium_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + dilithium_key* key) +{ + int ret = 0; + byte *newPriv = NULL; + word32 newPrivSz = 0; + + if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) + != 0) { + return ret; + } + + if (pub == NULL) { + if (pubSz != 0) { + return BAD_FUNC_ARG; + } + + if ((newPrivSz != DILITHIUM_LEVEL2_PRV_KEY_SIZE) && + (newPrivSz != DILITHIUM_LEVEL3_PRV_KEY_SIZE) && + (newPrivSz != DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + if (key->level == 2) { + pub = newPriv + DILITHIUM_LEVEL2_KEY_SIZE; + pubSz = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + } + else if (key->level == 3) { + pub = newPriv + DILITHIUM_LEVEL3_KEY_SIZE; + pubSz = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + } + else if (key->level == 5) { + pub = newPriv + DILITHIUM_LEVEL5_KEY_SIZE; + pubSz = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + } + } + else if ((pubSz != DILITHIUM_LEVEL2_PUB_KEY_SIZE) && + (pubSz != DILITHIUM_LEVEL3_PUB_KEY_SIZE) && + (pubSz != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + + /* import public key */ + ret = wc_dilithium_import_public(pub, pubSz, key); + + if (ret == 0) { + /* make the private key (priv + pub) */ + if (key->level == 2) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE); + } + else if (key->level == 3) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE); + } + else if (key->level == 5) { + XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE); + } + key->prvKeySet = 1; + } + + return ret; +} + +/* Export the dilithium private key. + * + * key [in] Dilithium private key. + * out [in] Array to hold private key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_KEY_SIZE, + * 0 otherwise. + */ +int wc_dilithium_export_private_only(dilithium_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (key->sym != SHAKE_VARIANT && key->sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + /* check and set up out length */ + if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL2_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL3_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL5_KEY_SIZE; + return BUFFER_E; + } + + if (key->level == 2) { + *outLen = DILITHIUM_LEVEL2_KEY_SIZE; + } + else if (key->level == 3) { + *outLen = DILITHIUM_LEVEL3_KEY_SIZE; + } + else if (key->level == 5) { + *outLen = DILITHIUM_LEVEL5_KEY_SIZE; + } + + XMEMCPY(out, key->k, *outLen); + + return 0; +} + +/* Export the dilithium private and public key. + * + * key [in] Dilithium private/public key. + * out [in] Array to hold private and public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE, + * 0 otherwise. + */ +int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + return BAD_FUNC_ARG; + } + + if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { + return BAD_FUNC_ARG; + } + + if (key->sym != SHAKE_VARIANT && key->sym != AES_VARIANT) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PRV_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PRV_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE; + return BUFFER_E; + } + else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { + *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE; + return BUFFER_E; + } + + + if (key->level == 2) { + *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE; + XMEMCPY(out, key->k, DILITHIUM_LEVEL2_PRV_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL2_PRV_KEY_SIZE, key->p, + DILITHIUM_LEVEL2_PUB_KEY_SIZE); + } + else if (key->level == 3) { + *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE; + XMEMCPY(out, key->k, DILITHIUM_LEVEL3_PRV_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL3_PRV_KEY_SIZE, key->p, + DILITHIUM_LEVEL3_PUB_KEY_SIZE); + } + else if (key->level == 5) { + *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE; + XMEMCPY(out, key->k, DILITHIUM_LEVEL5_PRV_KEY_SIZE); + XMEMCPY(out + DILITHIUM_LEVEL5_PRV_KEY_SIZE, key->p, + DILITHIUM_LEVEL5_PUB_KEY_SIZE); + } + + return 0; +} + +/* Export the dilithium private and public key. + * + * key [in] Dilithium private/public key. + * priv [in] Array to hold private key. + * privSz [in/out] On in, the number of bytes in private key array. + * pub [in] Array to hold public key. + * pubSz [in/out] On in, the number of bytes in public key array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when privSz is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE or pubSz is less + * than DILITHIUM_LEVEL2_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + int ret = 0; + + /* export private part */ + ret = wc_dilithium_export_private(key, priv, privSz); + if (ret == 0) { + /* export public part */ + ret = wc_dilithium_export_public(key, pub, pubSz); + } + + return ret; +} + +/* Check the public key of the dilithium key matches the private key. + * + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * PUBLIC_KEY_E when the public key is not set or doesn't match, + * other -ve value on hash failure, + * 0 otherwise. + */ +int wc_dilithium_check_key(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + /* Assume everything is fine. */ + return 0; +} + +/* Returns the size of a dilithium private key. + * + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * DILITHIUM_LEVEL2_KEY_SIZE otherwise. + */ +int wc_dilithium_size(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 2) { + return DILITHIUM_LEVEL2_KEY_SIZE; + } + else if (key->level == 3) { + return DILITHIUM_LEVEL3_KEY_SIZE; + } + else if (key->level == 5) { + return DILITHIUM_LEVEL5_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a dilithium private plus public key. + * + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * DILITHIUM_LEVEL2_PRV_KEY_SIZE otherwise. + */ +int wc_dilithium_priv_size(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 2) { + return DILITHIUM_LEVEL2_PRV_KEY_SIZE; + } + else if (key->level == 3) { + return DILITHIUM_LEVEL3_PRV_KEY_SIZE; + } + else if (key->level == 5) { + return DILITHIUM_LEVEL5_PRV_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a dilithium public key. + * + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * DILITHIUM_LEVEL2_PUB_KEY_SIZE otherwise. + */ +int wc_dilithium_pub_size(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 2) { + return DILITHIUM_LEVEL2_PUB_KEY_SIZE; + } + else if (key->level == 3) { + return DILITHIUM_LEVEL3_PUB_KEY_SIZE; + } + else if (key->level == 5) { + return DILITHIUM_LEVEL5_PUB_KEY_SIZE; + } + + return BAD_FUNC_ARG; +} + +/* Returns the size of a dilithium signature. + * + * key [in] Dilithium private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * DILITHIUM_LEVEL2_SIG_SIZE otherwise. + */ +int wc_dilithium_sig_size(dilithium_key* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 2) { + return DILITHIUM_LEVEL2_SIG_SIZE; + } + else if (key->level == 3) { + return DILITHIUM_LEVEL3_SIG_SIZE; + } + else if (key->level == 5) { + return DILITHIUM_LEVEL5_SIG_SIZE; + } + + return BAD_FUNC_ARG; +} + +int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, + dilithium_key* key, word32 inSz) +{ + int ret = 0; + byte privKey[DILITHIUM_MAX_KEY_SIZE], pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; + word32 privKeyLen = (word32)sizeof(privKey); + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL5k; + } + if ((key->level == 2) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + pubKey, &pubKeyLen, keytype); + if (ret == 0) { + if (pubKeyLen == 0) { + ret = wc_dilithium_import_private_only(input, inSz, key); + } + else { + ret = wc_dilithium_import_private_key(privKey, privKeyLen, + pubKey, pubKeyLen, key); + } + } + return ret; +} + +int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, + dilithium_key* key, word32 inSz) +{ + int ret = 0; + byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL5k; + } + if ((key->level == 2) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen, + keytype); + if (ret == 0) { + ret = wc_dilithium_import_public(pubKey, pubKeyLen, key); + } + return ret; +} + +#ifdef WC_ENABLE_ASYM_KEY_EXPORT +/* Encode the public part of an Dilithium key in DER. + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] key Dilithium key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] outLen Size of buffer in bytes. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. + * @return Size of encoded data in bytes on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + */ +int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 inLen, + int withAlg) +{ + int ret; + byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (key == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == SHAKE_VARIANT)) { + keytype = DILITHIUM_LEVEL5k; + } + if ((key->level == 2) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL2k; + } + else if ((key->level == 3) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL3k; + } + else if ((key->level == 5) && (key->sym == AES_VARIANT)) { + keytype = DILITHIUM_AES_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = wc_dilithium_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype, + withAlg); + } + + return ret; +} +#endif + +int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p, + DILITHIUM_LEVEL2_KEY_SIZE, output, inLen, + DILITHIUM_LEVEL2k); + } + else if ((key->level == 3) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p, + DILITHIUM_LEVEL3_KEY_SIZE, output, inLen, + DILITHIUM_LEVEL3k); + } + else if ((key->level == 5) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p, + DILITHIUM_LEVEL5_KEY_SIZE, output, inLen, + DILITHIUM_LEVEL5k); + } + else if ((key->level == 2) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p, + DILITHIUM_LEVEL2_KEY_SIZE, output, inLen, + DILITHIUM_AES_LEVEL2k); + } + else if ((key->level == 3) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p, + DILITHIUM_LEVEL3_KEY_SIZE, output, inLen, + DILITHIUM_AES_LEVEL3k); + } + else if ((key->level == 5) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p, + DILITHIUM_LEVEL5_KEY_SIZE, output, inLen, + DILITHIUM_AES_LEVEL5k); + } + + return BAD_FUNC_ARG; +} + +int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if ((key->level == 2) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_LEVEL2k); + } + else if ((key->level == 3) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_LEVEL3k); + } + else if ((key->level == 5) && (key->sym == SHAKE_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_LEVEL5k); + } + else if ((key->level == 2) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_AES_LEVEL2k); + } + else if ((key->level == 3) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_AES_LEVEL3k); + } + else if ((key->level == 5) && (key->sym == AES_VARIANT)) { + return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, output, + inLen, DILITHIUM_AES_LEVEL5k); + } + + return BAD_FUNC_ARG; +} +#endif /* HAVE_PQC && HAVE_DILITHIUM */ diff --git a/wolfcrypt/src/falcon.c b/wolfcrypt/src/falcon.c index 8bcbf436d..6755d3c3e 100644 --- a/wolfcrypt/src/falcon.c +++ b/wolfcrypt/src/falcon.c @@ -30,7 +30,7 @@ #include -#ifdef HAVE_PQC +#if defined(HAVE_PQC) && defined(HAVE_FALCON) #ifdef HAVE_LIBOQS #include @@ -114,6 +114,8 @@ int wc_falcon_sign_msg(const byte* in, word32 inLen, if (oqssig != NULL) { OQS_SIG_free(oqssig); } +#else + ret = NOT_COMPILED_IN; #endif return ret; } @@ -171,6 +173,8 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, if (oqssig != NULL) { OQS_SIG_free(oqssig); } +#else + ret = NOT_COMPILED_IN; #endif return ret; @@ -251,7 +255,7 @@ void wc_falcon_free(falcon_key* key) * outLen [in/out] On in, the number of bytes in array. * On out, the number bytes put into array. * returns BAD_FUNC_ARG when a parameter is NULL, - * ECC_BAD_ARG_E when outLen is less than FALCON_LEVEL1_PUB_KEY_SIZE, + * BUFFER_E when outLen is less than FALCON_LEVEL1_PUB_KEY_SIZE, * 0 otherwise. */ int wc_falcon_export_public(falcon_key* key, @@ -471,7 +475,7 @@ int wc_falcon_import_private_key(const byte* priv, word32 privSz, * outLen [in/out] On in, the number of bytes in array. * On out, the number bytes put into array. * returns BAD_FUNC_ARG when a parameter is NULL, - * ECC_BAD_ARG_E when outLen is less than FALCON_LEVEL1_KEY_SIZE, + * BUFFER_E when outLen is less than FALCON_LEVEL1_KEY_SIZE, * 0 otherwise. */ int wc_falcon_export_private_only(falcon_key* key, byte* out, word32* outLen) @@ -687,4 +691,154 @@ int wc_falcon_sig_size(falcon_key* key) return BAD_FUNC_ARG; } -#endif /* HAVE_PQC */ + +int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx, + falcon_key* key, word32 inSz) +{ + int ret = 0; + byte privKey[FALCON_MAX_KEY_SIZE], pubKey[FALCON_MAX_PUB_KEY_SIZE]; + word32 privKeyLen = (word32)sizeof(privKey); + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + pubKey, &pubKeyLen, keytype); + if (ret == 0) { + if (pubKeyLen == 0) { + ret = wc_falcon_import_private_only(input, inSz, key); + } + else { + ret = wc_falcon_import_private_key(privKey, privKeyLen, + pubKey, pubKeyLen, key); + } + } + return ret; +} + +int wc_Falcon_PublicKeyDecode(const byte* input, word32* inOutIdx, + falcon_key* key, word32 inSz) +{ + int ret = 0; + byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen, + keytype); + if (ret == 0) { + ret = wc_falcon_import_public(pubKey, pubKeyLen, key); + } + return ret; +} + +#ifdef WC_ENABLE_ASYM_KEY_EXPORT +/* Encode the public part of an Falcon key in DER. + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] key Falcon key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] outLen Size of buffer in bytes. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. + * @return Size of encoded data in bytes on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + */ +int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen, + int withAlg) +{ + int ret; + byte pubKey[FALCON_MAX_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + int keytype = 0; + + if (key == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + keytype = FALCON_LEVEL1k; + } + else if (key->level == 5) { + keytype = FALCON_LEVEL5k; + } + else { + return BAD_FUNC_ARG; + } + + ret = wc_falcon_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype, + withAlg); + } + + return ret; +} +#endif + +int wc_Falcon_KeyToDer(falcon_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, key->p, + FALCON_LEVEL1_KEY_SIZE, output, inLen, + FALCON_LEVEL1k); + } + else if (key->level == 5) { + return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, key->p, + FALCON_LEVEL5_KEY_SIZE, output, inLen, + FALCON_LEVEL5k); + } + + return BAD_FUNC_ARG; +} + +int wc_Falcon_PrivateKeyToDer(falcon_key* key, byte* output, word32 inLen) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (key->level == 1) { + return SetAsymKeyDer(key->k, FALCON_LEVEL1_KEY_SIZE, NULL, 0, output, + inLen, FALCON_LEVEL1k); + } + else if (key->level == 5) { + return SetAsymKeyDer(key->k, FALCON_LEVEL5_KEY_SIZE, NULL, 0, output, + inLen, FALCON_LEVEL5k); + } + + return BAD_FUNC_ARG; +} +#endif /* HAVE_PQC && HAVE_FALCON */ diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 3d59d1941..77e6ee584 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -3999,6 +3999,3518 @@ static const int sizeof_bench_falcon_level5_key = sizeof(bench_falcon_level5_key #endif /* HAVE_PQC */ +#ifdef HAVE_PQC + +/* certs/dilithium/bench_dilithium_level2_key.der */ +static const unsigned char bench_dilithium_level2_key[] = +{ + 0x30, 0x82, 0x0F, 0x1A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, + 0x04, 0x04, 0x04, 0x82, 0x0F, 0x04, 0x04, 0x82, 0x0F, 0x00, + 0xA2, 0xBD, 0x74, 0xB9, 0x8E, 0x34, 0xF0, 0xEC, 0xF7, 0x40, + 0x22, 0x33, 0xE8, 0x50, 0x43, 0x66, 0xF0, 0x25, 0x41, 0x20, + 0xD9, 0x3F, 0x8A, 0xC6, 0xAD, 0x69, 0xC6, 0x9C, 0xD9, 0xE0, + 0x0D, 0xFF, 0x77, 0x85, 0xCD, 0x88, 0x58, 0x17, 0x6B, 0x85, + 0xD2, 0x5D, 0xF0, 0x41, 0xCE, 0x6D, 0x94, 0x7F, 0xF4, 0xDB, + 0xD3, 0x60, 0x52, 0x1A, 0x83, 0x42, 0xD8, 0x7C, 0x2D, 0xD9, + 0x55, 0x7B, 0xFB, 0xB8, 0x87, 0xAA, 0xDA, 0x75, 0x42, 0x86, + 0x3E, 0x5A, 0xE4, 0xD4, 0x7D, 0xC3, 0x38, 0xA2, 0xEE, 0x0D, + 0xF5, 0xAD, 0xDA, 0x12, 0x5B, 0xD6, 0x3A, 0x89, 0x87, 0xED, + 0x57, 0xD1, 0xA9, 0xC2, 0xB3, 0xC0, 0xDC, 0x90, 0x88, 0x0C, + 0x86, 0x48, 0xD2, 0xA6, 0x60, 0x1B, 0x22, 0x8C, 0x03, 0x34, + 0x69, 0x19, 0x96, 0x24, 0x04, 0xB3, 0x65, 0x10, 0x34, 0x31, + 0x09, 0x38, 0x31, 0x5C, 0x10, 0x8C, 0x02, 0x15, 0x66, 0xD0, + 0x48, 0x50, 0x53, 0x22, 0x41, 0xC4, 0x98, 0x41, 0xE2, 0x42, + 0x62, 0x42, 0x38, 0x45, 0xC2, 0xB8, 0x08, 0x20, 0x31, 0x21, + 0x13, 0x10, 0x88, 0x00, 0xB9, 0x24, 0x93, 0x06, 0x6D, 0x44, + 0x20, 0x64, 0x98, 0x84, 0x29, 0x91, 0x12, 0x6A, 0xC9, 0x14, + 0x10, 0x11, 0x40, 0x2A, 0x24, 0xC9, 0x85, 0xCC, 0x42, 0x2A, + 0x1C, 0x44, 0x28, 0xE0, 0xB4, 0x00, 0x20, 0x99, 0x11, 0x0B, + 0x09, 0x61, 0x24, 0x14, 0x10, 0x41, 0x94, 0x20, 0xC9, 0x46, + 0x64, 0x43, 0x02, 0x6E, 0x08, 0x39, 0x71, 0x81, 0x06, 0x2D, + 0x63, 0x14, 0x71, 0x62, 0xC0, 0x11, 0x20, 0xB2, 0x61, 0xD1, + 0x30, 0x24, 0x44, 0x06, 0x89, 0x04, 0x16, 0x88, 0x10, 0x33, + 0x48, 0x51, 0xB8, 0x00, 0x4A, 0x12, 0x68, 0x14, 0x04, 0x10, + 0xD8, 0x92, 0x8D, 0x22, 0x32, 0x61, 0x0C, 0x23, 0x91, 0x10, + 0x39, 0x24, 0x51, 0x80, 0x08, 0x0B, 0x30, 0x61, 0x00, 0x89, + 0x01, 0x98, 0x34, 0x05, 0x9A, 0xA2, 0x70, 0xC4, 0x46, 0x40, + 0x52, 0x38, 0x42, 0xC0, 0x92, 0x6D, 0xCC, 0x08, 0x22, 0xD4, + 0x42, 0x4A, 0x02, 0x23, 0x40, 0x40, 0x92, 0x25, 0x12, 0x36, + 0x65, 0x42, 0x06, 0x10, 0x02, 0x10, 0x10, 0x20, 0xA3, 0x41, + 0x0A, 0x15, 0x10, 0x20, 0x23, 0x80, 0x99, 0xB6, 0x0C, 0x11, + 0x26, 0x11, 0x9B, 0xC8, 0x44, 0x1C, 0xC9, 0x05, 0xA4, 0x38, + 0x11, 0x1B, 0xB0, 0x05, 0xDC, 0x22, 0x00, 0xC8, 0x22, 0x72, + 0xA3, 0x30, 0x2E, 0xC1, 0xA8, 0x41, 0x1C, 0xA6, 0x20, 0xE2, + 0xB0, 0x21, 0x9B, 0x10, 0x01, 0x61, 0x32, 0x46, 0xC1, 0x92, + 0x61, 0x1C, 0xA4, 0x85, 0x0A, 0xB7, 0x70, 0xE4, 0x26, 0x6C, + 0x58, 0xA4, 0x00, 0x19, 0x86, 0x4C, 0xDC, 0xA6, 0x40, 0xA1, + 0x32, 0x12, 0x04, 0x81, 0x90, 0x8C, 0x04, 0x05, 0x10, 0x30, + 0x26, 0x09, 0x31, 0x2C, 0x50, 0x88, 0x89, 0x82, 0x44, 0x62, + 0x10, 0x23, 0x8A, 0x04, 0x44, 0x22, 0x0A, 0x30, 0x4E, 0xA4, + 0x34, 0x32, 0x4C, 0x18, 0x8C, 0x21, 0x21, 0x41, 0x23, 0x13, + 0x72, 0x08, 0x84, 0x24, 0x1A, 0x04, 0x24, 0x14, 0x06, 0x02, + 0xC4, 0x40, 0x70, 0xCA, 0x00, 0x6E, 0xC1, 0xC6, 0x09, 0x83, + 0x42, 0x62, 0xA0, 0x30, 0x12, 0x1B, 0x14, 0x0C, 0x08, 0x03, + 0x22, 0xCA, 0x46, 0x65, 0x64, 0x46, 0x26, 0x10, 0x39, 0x20, + 0xCA, 0x80, 0x28, 0x62, 0x14, 0x6D, 0x10, 0x26, 0x11, 0x49, + 0xA2, 0x45, 0x53, 0x98, 0x0D, 0x64, 0x40, 0x05, 0x0C, 0x31, + 0x09, 0x13, 0x11, 0x60, 0xD8, 0x02, 0x50, 0x11, 0x41, 0x41, + 0x23, 0xC1, 0x4C, 0x22, 0xC6, 0x30, 0x99, 0x06, 0x08, 0xCA, + 0x40, 0x81, 0xCC, 0x32, 0x0E, 0x11, 0xC4, 0x20, 0xD9, 0x92, + 0x41, 0xC4, 0x20, 0x08, 0xE4, 0xA0, 0x00, 0xCB, 0x88, 0x21, + 0x03, 0x03, 0x90, 0x54, 0x00, 0x49, 0x14, 0x98, 0x04, 0xC8, + 0xC0, 0x31, 0x11, 0x31, 0x69, 0x04, 0x93, 0x90, 0x00, 0xB9, + 0x21, 0x22, 0x38, 0x48, 0x00, 0x34, 0x0C, 0x61, 0x98, 0x00, + 0x01, 0xB4, 0x69, 0x60, 0x26, 0x81, 0x1C, 0xA4, 0x10, 0x22, + 0xB6, 0x10, 0x21, 0xC6, 0x20, 0x4A, 0x22, 0x26, 0xD0, 0x92, + 0x41, 0xDA, 0x84, 0x69, 0x03, 0x42, 0x2A, 0x04, 0x09, 0x02, + 0xE1, 0x24, 0x42, 0xA2, 0x46, 0x28, 0x10, 0xB1, 0x08, 0x82, + 0x86, 0x84, 0xE0, 0x24, 0x51, 0x0A, 0xC9, 0x28, 0x59, 0x86, + 0x20, 0xDB, 0xB6, 0x40, 0x13, 0xC3, 0x40, 0x1C, 0xA9, 0x09, + 0x80, 0x34, 0x50, 0xDC, 0x84, 0x2C, 0x53, 0x24, 0x08, 0xC0, + 0xB4, 0x6D, 0x88, 0x26, 0x30, 0x82, 0xC8, 0x0D, 0x62, 0x22, + 0x28, 0x64, 0xA2, 0x09, 0x10, 0x25, 0x26, 0xDB, 0x34, 0x02, + 0x4A, 0x04, 0x11, 0x53, 0xB8, 0x28, 0x82, 0x34, 0x11, 0xC2, + 0x12, 0x25, 0x20, 0xB5, 0x40, 0x19, 0xA8, 0x31, 0x80, 0x22, + 0x66, 0x21, 0xB2, 0x10, 0x0B, 0x42, 0x2A, 0x61, 0x20, 0x50, + 0x40, 0x24, 0x4C, 0x99, 0x12, 0x48, 0x21, 0xB4, 0x11, 0xD1, + 0x44, 0x48, 0x00, 0x40, 0x0C, 0x58, 0x46, 0x68, 0x04, 0x12, + 0x12, 0x93, 0x22, 0x20, 0xC2, 0x32, 0x4C, 0x01, 0xB0, 0x88, + 0xE3, 0x20, 0x8E, 0x03, 0x00, 0x6C, 0x52, 0x14, 0x30, 0xD2, + 0x44, 0x88, 0x10, 0x44, 0x4A, 0x61, 0x86, 0x29, 0x14, 0x42, + 0x24, 0x24, 0x35, 0x2E, 0x11, 0xC4, 0x0D, 0x23, 0x24, 0x66, + 0x0A, 0x90, 0x71, 0xE0, 0xC2, 0x69, 0x48, 0x38, 0x91, 0x82, + 0xC8, 0x08, 0x1C, 0x93, 0x31, 0xD9, 0x06, 0x51, 0x8A, 0xA4, + 0x6C, 0x50, 0x34, 0x68, 0x5A, 0x18, 0x89, 0x4A, 0x96, 0x85, + 0x8A, 0x18, 0x44, 0x4A, 0x34, 0x40, 0x5B, 0x36, 0x80, 0xCC, + 0x20, 0x6E, 0x09, 0x19, 0x89, 0x02, 0x38, 0x6A, 0x24, 0xA3, + 0x69, 0x58, 0x32, 0x6D, 0x21, 0x01, 0x84, 0x88, 0x86, 0x28, + 0xA3, 0x22, 0x89, 0x93, 0xA6, 0x80, 0x00, 0x88, 0x81, 0xE1, + 0x48, 0x70, 0xA2, 0x34, 0x60, 0x18, 0x02, 0x04, 0x18, 0x29, + 0x01, 0x1B, 0x31, 0x51, 0xD4, 0xA4, 0x49, 0xCC, 0x08, 0x8C, + 0xDA, 0x36, 0x11, 0x01, 0x39, 0x26, 0x42, 0x92, 0x88, 0xC8, + 0x46, 0x52, 0x8C, 0xA4, 0x08, 0x14, 0x11, 0x52, 0xCA, 0x40, + 0x66, 0x8B, 0x32, 0x8E, 0x89, 0x44, 0x02, 0x9B, 0x42, 0x02, + 0x93, 0xA4, 0x01, 0x1A, 0x00, 0x50, 0x94, 0x44, 0x42, 0x08, + 0x09, 0x8C, 0xE2, 0xA8, 0x81, 0x98, 0x00, 0x48, 0x63, 0x02, + 0x85, 0x1B, 0x05, 0x2D, 0xC1, 0xBE, 0x5F, 0xA4, 0xAC, 0xB4, + 0xF0, 0xC7, 0x94, 0xBD, 0xEC, 0xFB, 0x09, 0xAF, 0x16, 0xF1, + 0x23, 0x58, 0xAB, 0x82, 0xFA, 0x74, 0xD1, 0x84, 0x51, 0xD0, + 0x58, 0x9B, 0xFA, 0xF4, 0x11, 0xC1, 0x17, 0x2F, 0xCE, 0xD1, + 0xCA, 0xC6, 0xCE, 0x1C, 0x8F, 0x8F, 0x1B, 0x43, 0xBF, 0xB9, + 0x43, 0x41, 0x02, 0x3E, 0x5D, 0xFA, 0x24, 0x88, 0x0E, 0xA5, + 0x36, 0xA9, 0x9B, 0x25, 0x43, 0xD6, 0xEE, 0xDE, 0xAE, 0x93, + 0x54, 0xC8, 0x6C, 0x55, 0xE9, 0x5C, 0xC8, 0xC1, 0xA5, 0xD7, + 0xFC, 0xDA, 0xAF, 0xF8, 0x40, 0x1F, 0x02, 0x5C, 0x8E, 0x48, + 0x51, 0x4B, 0x3F, 0xFD, 0x76, 0x9A, 0xD0, 0x87, 0xF4, 0xD0, + 0x68, 0x9C, 0x44, 0x3B, 0xB4, 0x4A, 0xAB, 0x34, 0x2A, 0xD4, + 0x0C, 0xA4, 0x7A, 0xBB, 0x98, 0x7F, 0x8D, 0xF6, 0xA7, 0x6A, + 0x42, 0x8C, 0x7A, 0xB4, 0x32, 0xC6, 0x8A, 0xD6, 0x5E, 0x06, + 0x50, 0xC0, 0xDD, 0x3E, 0xE2, 0x44, 0x5C, 0xB9, 0x83, 0xCF, + 0x92, 0x0C, 0x3C, 0xFB, 0x53, 0x0D, 0xF0, 0xD1, 0xED, 0x77, + 0xF3, 0x02, 0x9F, 0xA6, 0xC6, 0xFA, 0x30, 0xA5, 0xC7, 0x42, + 0x06, 0x1F, 0x38, 0xE5, 0xE1, 0x56, 0x01, 0x7A, 0xD1, 0xE1, + 0xC1, 0x20, 0x44, 0x37, 0xE6, 0x18, 0x8A, 0x7E, 0x70, 0xBA, + 0x6B, 0x1C, 0x99, 0x4E, 0xFB, 0xCA, 0xCF, 0x3D, 0x29, 0x26, + 0xF4, 0x12, 0x95, 0x74, 0x11, 0x23, 0x0E, 0x2E, 0x31, 0xCF, + 0x73, 0xE6, 0x99, 0xD0, 0x72, 0x23, 0x4A, 0x46, 0x07, 0xA1, + 0x03, 0x4C, 0x3A, 0x79, 0x72, 0x3B, 0xD1, 0x79, 0x5A, 0x66, + 0x29, 0xCD, 0x34, 0xB6, 0x6A, 0xA5, 0x6A, 0x4C, 0x71, 0xE5, + 0xB3, 0xA6, 0xAC, 0x4D, 0x13, 0xDC, 0x70, 0xE4, 0x0C, 0x6A, + 0x98, 0x48, 0x1C, 0xA0, 0x6C, 0xFC, 0xDD, 0x6A, 0x3F, 0x10, + 0x3B, 0xBD, 0xC9, 0xC8, 0xEA, 0x01, 0x86, 0x5B, 0x3B, 0x19, + 0x3E, 0x6F, 0xA9, 0x4A, 0xD4, 0x38, 0x1D, 0x9C, 0x2B, 0x19, + 0xAE, 0x47, 0x54, 0xE2, 0x4E, 0xB5, 0xDF, 0xA7, 0xBD, 0x6F, + 0x01, 0x8A, 0x10, 0x5B, 0x83, 0x17, 0xB3, 0x77, 0xE1, 0x9D, + 0xBF, 0x6B, 0x25, 0xBF, 0x90, 0xC4, 0x92, 0xE1, 0x5E, 0xE1, + 0xC3, 0x0C, 0xC5, 0x05, 0x24, 0x40, 0x61, 0xA1, 0x01, 0x4A, + 0x7B, 0xE4, 0x65, 0x73, 0x1F, 0x3C, 0xA2, 0xD8, 0x54, 0xA4, + 0x64, 0xA3, 0x06, 0xDA, 0x18, 0x9A, 0xD7, 0xE4, 0x90, 0x59, + 0xAF, 0xBC, 0x1A, 0x79, 0xC4, 0x08, 0xE9, 0x87, 0x95, 0x04, + 0x48, 0x18, 0xD2, 0x33, 0x15, 0x38, 0x9C, 0x00, 0x7B, 0x72, + 0x35, 0xC1, 0x03, 0x77, 0xF1, 0x0B, 0xEC, 0x38, 0x33, 0xB7, + 0xB4, 0xBC, 0xC4, 0xBD, 0xB3, 0xBB, 0x9C, 0x34, 0x0B, 0x28, + 0x03, 0x1D, 0x99, 0x7A, 0x12, 0x0C, 0x95, 0xFE, 0x0D, 0x53, + 0x79, 0xE7, 0xE6, 0x99, 0x3F, 0xA1, 0x31, 0x9E, 0xA9, 0xB8, + 0x9B, 0xB7, 0xC0, 0x3F, 0x9C, 0x18, 0x1B, 0xA2, 0x73, 0xBC, + 0x10, 0xDB, 0x1B, 0x09, 0xE7, 0x5E, 0x67, 0x8E, 0x69, 0x92, + 0xCF, 0x99, 0xC3, 0x97, 0x58, 0xE8, 0x9A, 0x40, 0x83, 0xF2, + 0x14, 0xA3, 0x25, 0xB5, 0x51, 0x30, 0xDA, 0x91, 0x87, 0x91, + 0x1E, 0xF2, 0x5E, 0x55, 0x49, 0x68, 0x5E, 0xC9, 0x21, 0x67, + 0x03, 0xBC, 0x21, 0xE4, 0xD1, 0xFC, 0x79, 0xC7, 0xDB, 0x44, + 0xB9, 0xAB, 0x1E, 0xB4, 0x65, 0x3D, 0x63, 0xCB, 0x64, 0x76, + 0xE4, 0x1B, 0x93, 0x91, 0xB0, 0xF3, 0x4F, 0xBA, 0xD3, 0x20, + 0x47, 0x37, 0x5A, 0xCA, 0x1B, 0xDB, 0xCA, 0xA1, 0xE7, 0xED, + 0x7D, 0x8D, 0x4E, 0x7C, 0x19, 0xB2, 0x73, 0x67, 0x55, 0x11, + 0xE4, 0xA1, 0x98, 0x44, 0x5F, 0x58, 0xF7, 0xAA, 0x09, 0xFD, + 0x09, 0x4A, 0x54, 0x68, 0x32, 0xD4, 0xCA, 0xE1, 0x96, 0xFD, + 0x27, 0x05, 0x88, 0x78, 0x7B, 0x83, 0x74, 0x78, 0x6F, 0x09, + 0xC7, 0x3C, 0x66, 0xA8, 0x17, 0x3A, 0xCF, 0xB3, 0x6E, 0x5A, + 0xD7, 0x16, 0xE5, 0x2E, 0x40, 0xD7, 0x30, 0x18, 0x47, 0x5F, + 0x95, 0x19, 0x4E, 0x0F, 0x69, 0xD3, 0x11, 0xDE, 0xBB, 0x55, + 0x1B, 0xD1, 0x13, 0x71, 0x3D, 0x45, 0x3E, 0xDC, 0x72, 0x4F, + 0x89, 0x34, 0x72, 0x96, 0x77, 0xBB, 0x42, 0x29, 0x4A, 0x88, + 0x44, 0xFB, 0x05, 0x57, 0x38, 0xA6, 0xAC, 0x3E, 0x03, 0xF6, + 0xE1, 0x9D, 0xE3, 0xE9, 0x5A, 0x1B, 0x64, 0xCE, 0xC8, 0x6E, + 0x1B, 0xE8, 0xE3, 0x78, 0xF8, 0xE9, 0xF1, 0x47, 0x09, 0x0E, + 0x66, 0x50, 0x7A, 0x10, 0x51, 0xE1, 0x60, 0x73, 0x78, 0x95, + 0x00, 0x2E, 0xB8, 0x05, 0x8C, 0x22, 0x72, 0xD9, 0x88, 0xC8, + 0x8D, 0x16, 0xEF, 0x18, 0x8F, 0xC6, 0x51, 0x1E, 0xC3, 0xBA, + 0x27, 0x57, 0xB4, 0xFE, 0x74, 0x0F, 0x54, 0x45, 0x5A, 0x0B, + 0xAC, 0x6C, 0xA7, 0x46, 0x95, 0xC7, 0x35, 0x3D, 0x38, 0xBE, + 0xC5, 0x4E, 0xE0, 0x83, 0xED, 0x68, 0x8D, 0x01, 0x31, 0x7D, + 0x90, 0xA7, 0x38, 0xEE, 0x57, 0x8E, 0xD2, 0xFB, 0x87, 0x08, + 0x7A, 0x44, 0x34, 0x0B, 0x99, 0x5E, 0x2F, 0xA8, 0x4E, 0xC0, + 0x80, 0xEF, 0x62, 0xFE, 0xFB, 0x3C, 0x73, 0xF1, 0x8C, 0x56, + 0x12, 0x08, 0x8C, 0xD3, 0x9F, 0xBA, 0x44, 0x90, 0xB7, 0xDB, + 0x9C, 0xD9, 0xB4, 0x91, 0xBA, 0xFF, 0x4A, 0xB0, 0x1C, 0x91, + 0x44, 0x34, 0x52, 0xBE, 0x0D, 0xBA, 0x72, 0x33, 0x5C, 0x36, + 0xB5, 0x5E, 0x91, 0xB7, 0xE9, 0xCE, 0xD0, 0x01, 0x61, 0x19, + 0xEE, 0x2D, 0x1F, 0xBE, 0x97, 0x7C, 0x8C, 0x30, 0x91, 0x8C, + 0xB1, 0x8A, 0x04, 0xCA, 0xB8, 0x33, 0xCB, 0xA9, 0x9A, 0x2C, + 0x1B, 0x25, 0xD2, 0xDB, 0x73, 0x95, 0x3F, 0x02, 0x67, 0xEB, + 0x2C, 0xEC, 0xCC, 0x92, 0xCD, 0x1E, 0x1F, 0xC2, 0xF2, 0xA7, + 0x23, 0xAD, 0x7C, 0xA5, 0x50, 0x44, 0x76, 0x7D, 0x74, 0x13, + 0x20, 0x21, 0xF2, 0x09, 0xD9, 0x70, 0x82, 0xB0, 0x30, 0xA3, + 0x8A, 0xC0, 0x9D, 0xD2, 0x16, 0x4F, 0x65, 0xDF, 0x42, 0x37, + 0xC2, 0x63, 0xD6, 0x6C, 0xA9, 0xD1, 0x95, 0x5D, 0x84, 0xD2, + 0xB5, 0xC7, 0x7A, 0x87, 0x9B, 0x9B, 0xAF, 0x21, 0x65, 0x64, + 0xF7, 0x0B, 0x21, 0xC7, 0xF6, 0xA5, 0x27, 0xEB, 0xAA, 0x8D, + 0xF2, 0x10, 0x60, 0xFB, 0xC9, 0xB3, 0xB0, 0x32, 0x7C, 0x9F, + 0xC1, 0xDE, 0xA8, 0x77, 0x6F, 0xCC, 0x35, 0x1F, 0xBD, 0x74, + 0x0E, 0xA9, 0x84, 0x3C, 0x05, 0x9D, 0xFF, 0xBC, 0x46, 0x9A, + 0x8E, 0x43, 0xB5, 0x8B, 0x1C, 0x24, 0xB5, 0xC3, 0xB0, 0xFE, + 0x14, 0xCC, 0x3C, 0xCF, 0xF2, 0x26, 0xCE, 0x0B, 0x3A, 0x5B, + 0x5C, 0x8E, 0x59, 0xBF, 0x0D, 0xDC, 0xA6, 0xCA, 0x78, 0xE5, + 0xD9, 0xC5, 0x46, 0x56, 0x38, 0x98, 0xC4, 0xAC, 0x43, 0x64, + 0xB1, 0x78, 0x0A, 0x81, 0x34, 0x7D, 0x3D, 0xC0, 0xF5, 0x25, + 0x14, 0x66, 0xA2, 0x2A, 0x81, 0x64, 0x82, 0x62, 0x86, 0xD0, + 0x65, 0xCB, 0x2A, 0x09, 0x01, 0xF5, 0x03, 0xEC, 0xB5, 0xD1, + 0xED, 0xC7, 0x60, 0x62, 0x3D, 0x38, 0x28, 0x9C, 0x32, 0xEE, + 0x9F, 0x45, 0x72, 0x71, 0xA9, 0x6D, 0x9A, 0x54, 0x83, 0xF9, + 0xE7, 0x37, 0xC7, 0xCC, 0x28, 0xC0, 0xC2, 0x24, 0x09, 0xC3, + 0x96, 0xF6, 0xED, 0x9B, 0x60, 0xF3, 0x24, 0x4C, 0xFC, 0xAB, + 0xD0, 0x38, 0x7A, 0x1C, 0x68, 0xED, 0x63, 0x83, 0x5A, 0x28, + 0x37, 0x70, 0x31, 0xBB, 0x9D, 0xC7, 0xAA, 0x3A, 0x5B, 0xAF, + 0x88, 0x82, 0xE2, 0x30, 0xCB, 0xF5, 0xC1, 0x63, 0x9C, 0x59, + 0x41, 0xD3, 0x24, 0x92, 0xB1, 0x71, 0xA4, 0x16, 0x26, 0x0B, + 0x9C, 0x96, 0x0B, 0xE9, 0x0B, 0x69, 0xFC, 0x1F, 0xD2, 0x99, + 0xC2, 0xB6, 0x7A, 0x24, 0x28, 0x5A, 0x3D, 0x88, 0x2C, 0xF0, + 0x76, 0xFC, 0x25, 0x04, 0xBE, 0xB6, 0x19, 0x94, 0xD1, 0xBA, + 0x1A, 0x58, 0x0E, 0x9A, 0xFB, 0x4C, 0x9D, 0x21, 0x34, 0x8D, + 0x45, 0xEC, 0x50, 0xC6, 0x94, 0x1B, 0x0B, 0x87, 0x36, 0x4E, + 0xE4, 0x96, 0xF6, 0x9A, 0x34, 0xEC, 0xD8, 0x65, 0x6A, 0x46, + 0xFA, 0xC5, 0x40, 0x35, 0xD0, 0x07, 0x74, 0x02, 0xA3, 0xCF, + 0x23, 0x60, 0x15, 0xAC, 0x54, 0x98, 0x59, 0xEF, 0x94, 0x17, + 0x0A, 0xEF, 0xBB, 0xC2, 0x7B, 0x3B, 0xEF, 0xF5, 0xD1, 0x9C, + 0xB7, 0xB1, 0xDF, 0x45, 0xF5, 0x57, 0xD1, 0x18, 0x05, 0x97, + 0x8F, 0x8C, 0x30, 0x8C, 0x11, 0xF4, 0x81, 0x4D, 0x75, 0x18, + 0x97, 0x9F, 0x30, 0x64, 0xE2, 0x5B, 0x18, 0x95, 0xAC, 0x4E, + 0xDC, 0x47, 0xB5, 0x45, 0xAA, 0xD4, 0x7E, 0xF4, 0x70, 0x46, + 0x34, 0xF3, 0xB3, 0x85, 0xC2, 0x46, 0x98, 0xB5, 0xB5, 0x33, + 0x52, 0xF4, 0x36, 0x39, 0xCA, 0x23, 0xF9, 0x66, 0xB9, 0xA4, + 0x63, 0xC6, 0x3D, 0x02, 0xE7, 0x8F, 0x95, 0xF3, 0x25, 0xFD, + 0x21, 0xD0, 0x62, 0xC2, 0xEE, 0xE2, 0x2F, 0x69, 0x55, 0x31, + 0x42, 0x78, 0x2D, 0x53, 0xDC, 0x7F, 0x0E, 0x93, 0xD5, 0x4D, + 0x21, 0x64, 0x8B, 0x9E, 0x2C, 0xBE, 0xBA, 0xD3, 0x39, 0x41, + 0xE3, 0x10, 0xE5, 0x07, 0xE4, 0x0E, 0x20, 0x38, 0x63, 0xF7, + 0x02, 0xF2, 0x17, 0x99, 0xEB, 0xC6, 0xE7, 0x5F, 0xBE, 0xAE, + 0x53, 0xD1, 0x12, 0xB2, 0x9A, 0x90, 0x25, 0x6A, 0xAA, 0xFD, + 0x5D, 0x69, 0x2F, 0x32, 0x33, 0x53, 0x57, 0x1B, 0xC4, 0x24, + 0xC0, 0xC5, 0x90, 0x04, 0x04, 0x67, 0xCA, 0x85, 0x1E, 0x94, + 0x31, 0x95, 0x78, 0x76, 0x5D, 0xCF, 0x15, 0xE6, 0x06, 0x6B, + 0x1A, 0x1D, 0x0E, 0xF6, 0x64, 0x91, 0x84, 0xAE, 0xE4, 0xF0, + 0x1F, 0x0A, 0x76, 0x1C, 0x74, 0xF3, 0xC1, 0x97, 0x80, 0x5B, + 0xD9, 0xC6, 0xB6, 0x2B, 0xA8, 0xD7, 0xD8, 0xD2, 0xB5, 0x8E, + 0x05, 0xB5, 0x16, 0x6A, 0xF7, 0xCB, 0xD2, 0xFE, 0xE0, 0xA7, + 0x3E, 0x1C, 0x3E, 0x84, 0xDC, 0x89, 0x33, 0xD7, 0x2F, 0x2A, + 0x40, 0x41, 0x18, 0xB8, 0x58, 0xB6, 0x54, 0xC6, 0xC9, 0xDF, + 0x24, 0x91, 0xCD, 0x62, 0xA0, 0x9D, 0x17, 0xCC, 0xA6, 0xCF, + 0xD9, 0x25, 0xA1, 0xBC, 0x63, 0x09, 0xFB, 0xD1, 0x65, 0x5C, + 0xFC, 0xB8, 0x3A, 0x3D, 0x50, 0xEC, 0x1A, 0x26, 0x37, 0xCB, + 0x9C, 0x29, 0x9E, 0x15, 0x06, 0xC9, 0x14, 0x45, 0x41, 0x5F, + 0x6C, 0x41, 0x46, 0xEA, 0xC6, 0xF8, 0x18, 0x01, 0x7D, 0xCD, + 0x30, 0xEE, 0x5D, 0xB5, 0xA0, 0x96, 0x19, 0x80, 0x96, 0xB1, + 0x03, 0x55, 0x86, 0x57, 0xBE, 0x19, 0x13, 0x46, 0x88, 0x00, + 0xCE, 0x5E, 0xD0, 0xBE, 0xEC, 0x13, 0x2B, 0x93, 0x3C, 0xE1, + 0xEC, 0xBD, 0x15, 0x6F, 0xA5, 0xF5, 0x20, 0x59, 0x3C, 0xDD, + 0xBD, 0xFD, 0xDF, 0x9D, 0x9F, 0x07, 0x73, 0x25, 0x93, 0x42, + 0x41, 0xCF, 0x4A, 0xE5, 0x8F, 0x04, 0xAC, 0x5F, 0x6A, 0x56, + 0x87, 0x49, 0xD5, 0x64, 0x00, 0x9D, 0xF4, 0xA5, 0x6B, 0xBE, + 0x8F, 0xC8, 0xE8, 0xBC, 0xC7, 0x1C, 0x99, 0xC0, 0x2F, 0xA1, + 0xDA, 0xDF, 0x6B, 0xE5, 0x62, 0x9D, 0xC9, 0x73, 0x5B, 0x2A, + 0x3E, 0xD7, 0x8A, 0xBE, 0x0A, 0x5F, 0x2B, 0x0B, 0x61, 0xEF, + 0x4A, 0x09, 0x15, 0x70, 0xE6, 0x5C, 0xA1, 0xB6, 0xDE, 0x54, + 0x71, 0x74, 0x55, 0x63, 0x77, 0x8F, 0xC9, 0xAF, 0x22, 0x9A, + 0xFE, 0x2C, 0x09, 0x62, 0x3E, 0xA1, 0xAA, 0x89, 0xB8, 0x6B, + 0x50, 0x84, 0x20, 0x66, 0x5D, 0x8F, 0x39, 0x7F, 0xC1, 0x2D, + 0xFA, 0x78, 0x8F, 0x8E, 0xD0, 0x39, 0x33, 0xD4, 0x9A, 0x40, + 0x56, 0xBC, 0x86, 0x22, 0x07, 0xEB, 0x22, 0xB8, 0x52, 0xC0, + 0x1A, 0xD2, 0x35, 0x1F, 0x56, 0x7E, 0xDA, 0x2B, 0xC1, 0x08, + 0xD2, 0x39, 0x28, 0x46, 0x63, 0x9A, 0xAD, 0x44, 0xB3, 0xEF, + 0x1C, 0x2A, 0xD6, 0x68, 0x67, 0xE4, 0x63, 0x73, 0x78, 0x29, + 0xA7, 0xA0, 0x70, 0x2E, 0xD9, 0xB4, 0x14, 0x4D, 0x04, 0xD3, + 0x2D, 0x8A, 0x70, 0x07, 0xAD, 0x8A, 0xC0, 0xA5, 0x1D, 0xE7, + 0x17, 0xD8, 0xBB, 0xAA, 0xB5, 0xF7, 0xC8, 0x8D, 0x29, 0x8E, + 0x49, 0x32, 0xA0, 0x40, 0x34, 0xBB, 0x2E, 0x10, 0x30, 0xDD, + 0xEA, 0x3E, 0xCC, 0xC1, 0xB9, 0xF2, 0x42, 0xCC, 0x4A, 0xF2, + 0xF4, 0x93, 0x2E, 0x3F, 0x0C, 0xE8, 0xE4, 0x96, 0x1F, 0x33, + 0x2D, 0x67, 0x4F, 0x8E, 0x1B, 0x01, 0xD6, 0xE2, 0xF2, 0xFD, + 0x5D, 0xCC, 0xFD, 0x18, 0x9C, 0xD6, 0x50, 0x1F, 0xE1, 0xC5, + 0x7C, 0xBE, 0x59, 0x95, 0x7D, 0x21, 0x25, 0x3E, 0xF3, 0xBC, + 0xCE, 0x31, 0x80, 0x79, 0x34, 0x0F, 0x86, 0x78, 0x18, 0xA6, + 0x36, 0x17, 0xD9, 0x70, 0xA7, 0x22, 0xA7, 0xE8, 0xA2, 0xBD, + 0x74, 0xB9, 0x8E, 0x34, 0xF0, 0xEC, 0xF7, 0x40, 0x22, 0x33, + 0xE8, 0x50, 0x43, 0x66, 0xF0, 0x25, 0x41, 0x20, 0xD9, 0x3F, + 0x8A, 0xC6, 0xAD, 0x69, 0xC6, 0x9C, 0xD9, 0xE0, 0x0D, 0xFF, + 0x93, 0x32, 0x5D, 0x57, 0x45, 0xCC, 0xA4, 0xF9, 0x32, 0xD4, + 0x5A, 0x49, 0x17, 0x1B, 0xFB, 0x2F, 0x91, 0xAA, 0x5B, 0xC5, + 0xC8, 0xC8, 0x2B, 0x20, 0x30, 0x1B, 0xB2, 0x01, 0xC3, 0xA7, + 0x8E, 0x6C, 0xB8, 0xF7, 0xB3, 0x95, 0x4A, 0x28, 0x82, 0xAA, + 0x0C, 0x4B, 0xDA, 0x26, 0x4A, 0x34, 0x7F, 0x17, 0x55, 0x4C, + 0x5D, 0x3C, 0x0B, 0x16, 0xA2, 0xEB, 0x33, 0xFB, 0x38, 0x63, + 0xF2, 0x15, 0x7D, 0xFA, 0x52, 0xA9, 0x58, 0xDD, 0x41, 0x58, + 0xA0, 0x13, 0xD2, 0x55, 0x22, 0xF9, 0xC2, 0xF8, 0x4E, 0x3F, + 0xAC, 0xDC, 0x11, 0x0A, 0xBB, 0x7C, 0xB1, 0x2B, 0xFB, 0x60, + 0xC5, 0x08, 0xB9, 0xB0, 0xED, 0xE8, 0xB9, 0x88, 0xBD, 0x07, + 0xDE, 0x53, 0xD0, 0x6B, 0xE5, 0x6E, 0xA0, 0x17, 0x8C, 0xCF, + 0x02, 0xF0, 0x64, 0xDE, 0xCE, 0x8C, 0x91, 0xED, 0xB4, 0x4F, + 0xB0, 0xEE, 0x12, 0x26, 0xC6, 0x55, 0xA0, 0x4D, 0xCC, 0xF3, + 0x1A, 0x86, 0x5A, 0x01, 0x53, 0x01, 0xAA, 0xED, 0x6D, 0x11, + 0xCD, 0x8A, 0x4A, 0xCA, 0x85, 0x35, 0x35, 0xFA, 0x22, 0x55, + 0xF3, 0xB8, 0xFA, 0x43, 0xD6, 0x9E, 0xB5, 0x0D, 0xD3, 0x85, + 0x59, 0xC9, 0xAF, 0xCD, 0xAB, 0xFA, 0xB6, 0x65, 0x20, 0xCC, + 0x11, 0xF1, 0xDE, 0x87, 0x6F, 0x58, 0xA1, 0x41, 0xF2, 0x80, + 0x75, 0xEA, 0x26, 0x72, 0x8C, 0xE9, 0x17, 0x1C, 0x2B, 0x4D, + 0xA4, 0x9C, 0xAA, 0x32, 0xAA, 0x2C, 0x84, 0xBA, 0x87, 0xAA, + 0x81, 0x66, 0x56, 0x76, 0x0F, 0x1C, 0x58, 0xFE, 0xD1, 0x7F, + 0x33, 0x59, 0xF1, 0xF0, 0x56, 0x50, 0x00, 0x4F, 0x96, 0xF7, + 0x1C, 0x11, 0x7C, 0x36, 0xD8, 0xAD, 0x3E, 0x82, 0x15, 0x68, + 0x40, 0x83, 0xFE, 0x62, 0x94, 0xD5, 0x2A, 0x43, 0x88, 0xD8, + 0x12, 0xE2, 0x37, 0x8A, 0x3E, 0x9E, 0x24, 0x8B, 0x70, 0x3C, + 0xBD, 0x97, 0x0B, 0x59, 0xAC, 0x4B, 0x88, 0x36, 0x2D, 0x2F, + 0xE9, 0x49, 0x14, 0xC0, 0x28, 0x7F, 0x0D, 0xE8, 0x93, 0x76, + 0x22, 0xF3, 0x08, 0x17, 0x34, 0x91, 0x39, 0xA6, 0x84, 0xCA, + 0xF1, 0xD2, 0x8A, 0x9D, 0xF1, 0xD4, 0xA4, 0x85, 0xA6, 0x1E, + 0xFB, 0x6B, 0x75, 0x07, 0x80, 0x84, 0x32, 0xF5, 0x51, 0xD6, + 0x42, 0xA8, 0x69, 0x96, 0xC3, 0xBD, 0xEF, 0x2F, 0xA4, 0x23, + 0x58, 0x07, 0xBC, 0xDE, 0x45, 0xD4, 0x1E, 0x67, 0xF1, 0x00, + 0x65, 0xB5, 0x03, 0xF3, 0x83, 0x9D, 0xE8, 0xDE, 0x63, 0x42, + 0x2B, 0xB6, 0xED, 0x7F, 0x63, 0xF6, 0xCF, 0x53, 0x1B, 0xBD, + 0x9D, 0x6C, 0x26, 0xBC, 0xC2, 0xC3, 0xAF, 0x86, 0x06, 0x5F, + 0x49, 0xBF, 0x7E, 0x76, 0xF5, 0x6C, 0x5B, 0x41, 0xF7, 0xAF, + 0x02, 0x1F, 0x35, 0x43, 0x0D, 0x64, 0x65, 0xFE, 0xD7, 0x9A, + 0x3F, 0x21, 0xD5, 0x74, 0x6E, 0x8A, 0xA8, 0xAF, 0x3B, 0xCE, + 0x85, 0xBB, 0xF7, 0x7B, 0xCA, 0xF7, 0x9D, 0x02, 0x52, 0x55, + 0xE9, 0x3E, 0x4A, 0x4B, 0x62, 0x85, 0x35, 0xFA, 0xBD, 0xEB, + 0x92, 0x25, 0x24, 0x01, 0xFF, 0xEE, 0xFB, 0x94, 0xF6, 0xE6, + 0x9F, 0xE3, 0x3D, 0x93, 0xCF, 0x69, 0xEB, 0x3D, 0x8F, 0x1F, + 0xBE, 0xAE, 0x85, 0x6F, 0x8F, 0x0B, 0x22, 0x57, 0x00, 0x3D, + 0x8E, 0xF4, 0x6B, 0x4D, 0x82, 0x76, 0x91, 0x25, 0x4B, 0x2C, + 0xF1, 0xBC, 0x64, 0x96, 0x54, 0x35, 0xFD, 0xBD, 0xFC, 0x71, + 0xF7, 0x48, 0x40, 0xEB, 0x4C, 0x1C, 0xC4, 0xAB, 0x4F, 0xC9, + 0xC7, 0xB0, 0x8C, 0xBF, 0x27, 0xE2, 0x18, 0xCA, 0x78, 0xAA, + 0xA0, 0x04, 0xAB, 0x6B, 0x6D, 0xBC, 0x89, 0xCB, 0x71, 0xA7, + 0xF8, 0x81, 0x0D, 0x4F, 0x2A, 0x9A, 0x37, 0x60, 0xA0, 0x6A, + 0x14, 0xE7, 0x30, 0x2E, 0x72, 0xF9, 0xE2, 0x39, 0x27, 0xD9, + 0xC6, 0xB2, 0x9E, 0xBC, 0x3D, 0xD6, 0x2D, 0xE4, 0xCD, 0xC2, + 0x40, 0x15, 0xC5, 0x7B, 0x8A, 0x06, 0x42, 0x46, 0xF2, 0x45, + 0x14, 0x83, 0x82, 0xAB, 0x30, 0x6C, 0x73, 0x92, 0x55, 0x51, + 0xE7, 0x8B, 0x3C, 0xD1, 0x2C, 0x8A, 0xC0, 0x16, 0x79, 0xC9, + 0xFD, 0x7C, 0x78, 0x1E, 0xE9, 0xDF, 0xF4, 0x08, 0xEF, 0x38, + 0xEC, 0xCB, 0x81, 0xF1, 0x87, 0x53, 0x8A, 0x0B, 0xF3, 0x56, + 0x0C, 0xBC, 0xEE, 0x03, 0xAE, 0xBC, 0xF8, 0x43, 0x3E, 0xA2, + 0xEA, 0x84, 0x37, 0x72, 0x8A, 0x80, 0x8D, 0x61, 0x1C, 0x79, + 0x3E, 0x4A, 0x5A, 0xC2, 0x73, 0xA0, 0x95, 0xDC, 0x46, 0x2B, + 0x5E, 0x4B, 0x89, 0xE3, 0x9F, 0xD7, 0x14, 0x61, 0x8B, 0x59, + 0xD1, 0x71, 0xB0, 0x04, 0xAA, 0x4B, 0x2A, 0xCA, 0xEF, 0x8D, + 0x3B, 0x4B, 0x52, 0x8F, 0x0B, 0x76, 0xB8, 0x38, 0xF8, 0xDD, + 0xD2, 0xE6, 0x46, 0x53, 0x1C, 0xD5, 0xC8, 0x1E, 0x85, 0x54, + 0x67, 0xC0, 0x77, 0x7E, 0x28, 0x2F, 0x91, 0xC5, 0xE5, 0x28, + 0x54, 0x37, 0xF6, 0x77, 0xEC, 0x6C, 0x36, 0x1D, 0x91, 0xA9, + 0x45, 0xCC, 0x85, 0x61, 0xAB, 0x14, 0xBE, 0x81, 0x6C, 0xFF, + 0x35, 0x8C, 0x13, 0x61, 0xE7, 0x66, 0x83, 0xFF, 0x67, 0x6C, + 0x80, 0x59, 0xD5, 0x6D, 0xAB, 0x5B, 0x81, 0x76, 0x39, 0x1B, + 0xBB, 0xD2, 0xFF, 0x1B, 0x7B, 0x66, 0xD6, 0x42, 0xD0, 0x86, + 0x62, 0x4A, 0xA1, 0x4F, 0x00, 0x41, 0x7E, 0x9C, 0xE5, 0xD6, + 0x82, 0x31, 0xA7, 0x34, 0x16, 0x20, 0x62, 0xFA, 0x1F, 0x6B, + 0x21, 0xBE, 0x62, 0x19, 0xE9, 0x56, 0x7A, 0x4C, 0xF0, 0x7B, + 0xB4, 0x2E, 0x4A, 0xA7, 0x20, 0xC3, 0x5F, 0x7F, 0x5A, 0xA2, + 0xAF, 0xF5, 0xC5, 0xFD, 0x1A, 0x7C, 0xB6, 0x06, 0xCA, 0xE3, + 0x74, 0x72, 0x4E, 0x77, 0xC9, 0xDD, 0x3B, 0x44, 0x16, 0x8C, + 0x45, 0x46, 0xC5, 0xE3, 0x81, 0x1E, 0x3C, 0x4D, 0xAC, 0x1A, + 0x7F, 0xAA, 0x6D, 0xFD, 0xE1, 0x45, 0x59, 0x11, 0x44, 0x48, + 0xB5, 0x09, 0xEF, 0x7E, 0xF2, 0x75, 0x0C, 0xBF, 0xC7, 0x17, + 0xB4, 0x9E, 0x10, 0xC0, 0x11, 0xDD, 0xB2, 0x59, 0xCF, 0x25, + 0x3B, 0xA8, 0x97, 0x56, 0x08, 0xE0, 0x65, 0x27, 0xC5, 0x29, + 0x34, 0xBD, 0x38, 0xB1, 0x39, 0xAA, 0x27, 0xFC, 0x96, 0xCB, + 0x9A, 0x2B, 0x92, 0x74, 0xDF, 0x0A, 0x52, 0xE4, 0x93, 0xA8, + 0x18, 0x15, 0x2C, 0x8C, 0x61, 0xD3, 0xBC, 0xD0, 0x9E, 0x9D, + 0x40, 0x1C, 0x69, 0x95, 0x0D, 0x52, 0x76, 0x3F, 0xD7, 0xD7, + 0xC1, 0x1C, 0x34, 0xE7, 0xD4, 0xD4, 0x17, 0x2D, 0xF0, 0x6A, + 0x1C, 0xE2, 0x53, 0x18, 0x60, 0xC6, 0xA1, 0xCD, 0x4F, 0xAA, + 0x16, 0xA0, 0xC3, 0x3B, 0xCE, 0x4D, 0x73, 0x0B, 0x63, 0x02, + 0x1C, 0xEE, 0x18, 0xBF, 0xF9, 0x33, 0x24, 0xD3, 0x02, 0x34, + 0xCC, 0xB9, 0xD7, 0xC2, 0x00, 0x7F, 0xB4, 0x08, 0x4B, 0xFC, + 0x1D, 0xDF, 0x42, 0x8C, 0x75, 0xEE, 0x13, 0x90, 0x37, 0x14, + 0x0D, 0xD2, 0xE0, 0x50, 0x90, 0x6A, 0xB9, 0xEF, 0x7F, 0x70, + 0x38, 0x2E, 0xCD, 0x39, 0x2E, 0x09, 0x51, 0xDF, 0x58, 0xBE, + 0x8E, 0x82, 0x91, 0xEB, 0xBC, 0xB4, 0x6B, 0x12, 0x40, 0x4E, + 0x44, 0xB8, 0x08, 0x97, 0x57, 0xF0, 0xFE, 0x61, 0xBD, 0x77, + 0xED, 0x46, 0xDA, 0xB7, 0xA4, 0xF5, 0x4F, 0xB2, 0xA6, 0xF1, + 0x47, 0x2D, 0x11, 0x26, 0x74, 0x55, 0x81, 0xFF, 0xFB, 0xEA, + 0x00, 0x03, 0x96, 0xD8, 0xE6, 0x6B, 0xEA, 0x3F, 0x0B, 0x0C, + 0xC0, 0xE4, 0x0A, 0x3D, 0x21, 0x3C, 0x99, 0x51, 0x91, 0x11, + 0xF0, 0x91, 0x68, 0xEE, 0xEE, 0xCD, 0x71, 0x42, 0xAD, 0xBA, + 0x34, 0x68, 0x9F, 0x67, 0xB1, 0xEE, 0x1C, 0x70, 0x7A, 0xFC, + 0x1E, 0x86, 0xF8, 0x96, 0x6C, 0x13, 0xD6, 0x36, 0x57, 0x5F, + 0x11, 0x2E, 0x1B, 0x97, 0xAB, 0x8B, 0x65, 0x3E, 0x8E, 0x91, + 0x69, 0x1C, 0x76, 0xAD, 0xB5, 0x8C, 0xE6, 0x02, 0x93, 0x16, + 0xA4, 0xF5, 0x14, 0x86, 0xB5, 0x16, 0x07, 0xF5, 0x0C, 0x01, + 0xE9, 0xDC, 0xEA, 0x86, 0x58, 0x98, 0xBA, 0x2C, 0x04, 0x0A, + 0x16, 0x8A, 0xF3, 0x10, 0x25, 0x48, 0x51, 0x21, 0x77, 0x69, + 0xF1, 0x22, 0xC3, 0xF4, 0x1D, 0xD5, 0x6D, 0x59, 0x1B, 0x44, + 0x88, 0xFC, 0xE5, 0x4B, 0xE1, 0xD6, 0xF4, 0x46, 0x4C, 0x9D, + 0x45, 0x93, 0xE1, 0xB5, 0x26, 0xDF, 0x48, 0x90, 0x13, 0xA6, + 0x65, 0x7E, 0x18, 0x6A, 0x79, 0x19, 0x81, 0x10, 0x08, 0x80, + 0xA4, 0x99, 0xD3, 0x98, 0x3C, 0x9E, 0x91, 0x31, 0xE9, 0x71, + 0xA0, 0x6A, 0xF9, 0x2F, 0x61, 0xA5, 0x72, 0x13, 0x6C, 0x4C, + 0xD2, 0xAF, 0x40, 0x8B, 0x0D, 0x3D, 0xE4, 0x24, 0x7B, 0x30, + 0x9C, 0xD0, 0x62, 0x42, 0x67, 0x54, 0xC6, 0x34, 0xF2, 0x55, + 0x70, 0x95, 0xAE, 0x16, 0x9F, 0xCC, 0x6F, 0xEA, 0x0B, 0x40, + 0x38, 0xAE, 0x74, 0x89, 0xCB, 0x64, 0x79, 0xF7, 0x08, 0x68, + 0x2C, 0x1E, 0xEE, 0x28, 0xEA, 0x77, 0xA2, 0xA3, 0x8E, 0xF4, + 0xEE, 0xFE, 0x62, 0x25, 0x98, 0xB1, 0xDE, 0x4B, 0x3A, 0x62, + 0xD9, 0x12, 0xD6, 0x09, 0x32, 0x6C, 0x80, 0x27, 0x21, 0x0A, + 0xFE, 0x4D, 0xBF, 0x29, 0x90, 0xCD, 0x6C, 0xE0, 0xAF, 0x06, + 0xB3, 0xC2, 0xDF, 0xB8, 0x50, 0x59, 0xD8, 0x0A, 0xB5, 0x98, + 0xC1, 0xA8, 0x80, 0xD7, 0x61, 0xFC, 0x59, 0xDB, 0xB1, 0x2A, + 0xA5, 0xD7, 0xFA, 0x9E, 0x93, 0x60, 0xD4, 0xB0, 0x6B, 0x44, + 0xB3, 0xC3, 0x3F, 0x9B, 0xEA, 0xD4, 0x8C, 0x08, 0x4B, 0x09, + 0x97, 0xC6, 0x2B, 0xC0, 0x8A, 0x92, 0x35, 0xCA, 0x6F, 0x93, + 0xD6, 0x71, 0x1E, 0xAB, 0x0F, 0x65, 0x42, 0xC2, 0x97, 0x77, + 0x10, 0x6E, 0xD4, 0xEE, 0x2A, 0xDF, 0x54, 0x2A, 0x5F, 0xB4, + 0xD4, 0x72, 0x18, 0x90, 0x42, 0x09, 0xAA, 0xC3, 0x31, 0x89 + +}; +static const int sizeof_bench_dilithium_level2_key = sizeof(bench_dilithium_level2_key); + +/* certs/dilithium/bench_dilithium_level3_key.der */ +static const unsigned char bench_dilithium_level3_key[] = +{ + 0x30, 0x82, 0x17, 0x5A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, + 0x06, 0x05, 0x04, 0x82, 0x17, 0x44, 0x04, 0x82, 0x17, 0x40, + 0x2E, 0xFE, 0x07, 0xDF, 0x5E, 0xF9, 0x18, 0xB4, 0x0E, 0xBF, + 0x9C, 0x1C, 0xCA, 0x84, 0xBA, 0x62, 0xB9, 0xA2, 0x96, 0x76, + 0xB6, 0xB7, 0x77, 0x9C, 0xBE, 0x0C, 0xF8, 0xA5, 0xEF, 0x74, + 0xB1, 0xC2, 0x8D, 0x95, 0x6D, 0x38, 0x49, 0x01, 0xA8, 0x3D, + 0x63, 0x0B, 0xDF, 0x4B, 0x5D, 0xF4, 0xC4, 0x98, 0x27, 0x77, + 0x88, 0xA0, 0xA9, 0xF2, 0x38, 0x32, 0x62, 0x17, 0x11, 0xD6, + 0xBE, 0xA0, 0xFD, 0xEB, 0xBF, 0x4A, 0xF2, 0x6C, 0x44, 0x62, + 0x2D, 0x87, 0x3D, 0xAD, 0x0C, 0x47, 0x06, 0x00, 0x7E, 0xAF, + 0x52, 0xE7, 0xA1, 0x8E, 0x7A, 0xA7, 0x7D, 0x3C, 0xE5, 0xB2, + 0x59, 0xDA, 0x89, 0x76, 0xF7, 0xD4, 0x73, 0x16, 0x33, 0x67, + 0x88, 0x46, 0x51, 0x13, 0x12, 0x38, 0x64, 0x76, 0x73, 0x40, + 0x16, 0x55, 0x70, 0x06, 0x32, 0x84, 0x47, 0x25, 0x33, 0x44, + 0x70, 0x68, 0x36, 0x25, 0x62, 0x47, 0x76, 0x65, 0x73, 0x11, + 0x28, 0x00, 0x75, 0x33, 0x81, 0x13, 0x62, 0x51, 0x31, 0x33, + 0x11, 0x41, 0x51, 0x62, 0x55, 0x33, 0x07, 0x60, 0x14, 0x18, + 0x30, 0x58, 0x22, 0x67, 0x26, 0x86, 0x12, 0x78, 0x17, 0x47, + 0x30, 0x06, 0x05, 0x36, 0x37, 0x23, 0x08, 0x67, 0x05, 0x05, + 0x06, 0x85, 0x33, 0x83, 0x14, 0x63, 0x44, 0x35, 0x00, 0x04, + 0x56, 0x03, 0x23, 0x03, 0x33, 0x13, 0x02, 0x23, 0x25, 0x80, + 0x22, 0x00, 0x53, 0x73, 0x13, 0x70, 0x03, 0x84, 0x15, 0x50, + 0x14, 0x20, 0x06, 0x74, 0x03, 0x41, 0x26, 0x74, 0x63, 0x65, + 0x42, 0x03, 0x00, 0x72, 0x66, 0x44, 0x36, 0x88, 0x60, 0x85, + 0x76, 0x86, 0x17, 0x72, 0x16, 0x37, 0x23, 0x82, 0x15, 0x84, + 0x57, 0x14, 0x20, 0x72, 0x15, 0x55, 0x26, 0x42, 0x82, 0x66, + 0x40, 0x54, 0x03, 0x54, 0x62, 0x61, 0x83, 0x35, 0x20, 0x76, + 0x62, 0x14, 0x37, 0x35, 0x42, 0x04, 0x32, 0x72, 0x08, 0x35, + 0x42, 0x74, 0x51, 0x24, 0x54, 0x86, 0x36, 0x56, 0x11, 0x83, + 0x64, 0x44, 0x54, 0x78, 0x80, 0x50, 0x55, 0x72, 0x84, 0x16, + 0x48, 0x13, 0x04, 0x17, 0x06, 0x36, 0x25, 0x48, 0x21, 0x33, + 0x45, 0x71, 0x21, 0x54, 0x10, 0x26, 0x13, 0x72, 0x12, 0x30, + 0x03, 0x73, 0x48, 0x84, 0x16, 0x22, 0x11, 0x38, 0x26, 0x43, + 0x53, 0x36, 0x56, 0x12, 0x15, 0x70, 0x07, 0x57, 0x00, 0x65, + 0x72, 0x11, 0x73, 0x48, 0x01, 0x13, 0x31, 0x58, 0x82, 0x60, + 0x61, 0x17, 0x78, 0x44, 0x48, 0x15, 0x48, 0x26, 0x62, 0x43, + 0x72, 0x44, 0x62, 0x76, 0x40, 0x15, 0x63, 0x26, 0x10, 0x51, + 0x82, 0x21, 0x05, 0x82, 0x30, 0x56, 0x58, 0x62, 0x76, 0x48, + 0x67, 0x82, 0x86, 0x51, 0x32, 0x37, 0x78, 0x38, 0x13, 0x82, + 0x55, 0x22, 0x45, 0x22, 0x68, 0x66, 0x15, 0x30, 0x35, 0x77, + 0x04, 0x28, 0x45, 0x85, 0x72, 0x48, 0x30, 0x26, 0x06, 0x24, + 0x12, 0x75, 0x42, 0x53, 0x88, 0x14, 0x15, 0x07, 0x08, 0x86, + 0x05, 0x08, 0x01, 0x56, 0x77, 0x44, 0x38, 0x53, 0x22, 0x21, + 0x20, 0x56, 0x25, 0x15, 0x72, 0x68, 0x27, 0x03, 0x71, 0x25, + 0x64, 0x11, 0x44, 0x34, 0x77, 0x60, 0x68, 0x58, 0x44, 0x74, + 0x76, 0x63, 0x86, 0x16, 0x01, 0x40, 0x68, 0x51, 0x20, 0x12, + 0x36, 0x55, 0x01, 0x84, 0x61, 0x80, 0x46, 0x36, 0x28, 0x82, + 0x44, 0x66, 0x14, 0x80, 0x50, 0x32, 0x34, 0x46, 0x21, 0x34, + 0x63, 0x04, 0x22, 0x20, 0x17, 0x84, 0x88, 0x88, 0x47, 0x02, + 0x52, 0x60, 0x45, 0x35, 0x86, 0x72, 0x71, 0x43, 0x30, 0x58, + 0x24, 0x11, 0x11, 0x64, 0x45, 0x36, 0x25, 0x18, 0x82, 0x18, + 0x16, 0x80, 0x27, 0x76, 0x53, 0x08, 0x70, 0x87, 0x64, 0x43, + 0x68, 0x86, 0x07, 0x04, 0x34, 0x10, 0x68, 0x30, 0x21, 0x01, + 0x86, 0x66, 0x06, 0x50, 0x41, 0x72, 0x18, 0x00, 0x05, 0x40, + 0x36, 0x35, 0x60, 0x50, 0x82, 0x82, 0x24, 0x73, 0x31, 0x35, + 0x81, 0x35, 0x02, 0x50, 0x22, 0x76, 0x44, 0x52, 0x27, 0x43, + 0x82, 0x66, 0x51, 0x38, 0x86, 0x72, 0x18, 0x54, 0x20, 0x65, + 0x45, 0x26, 0x03, 0x42, 0x24, 0x25, 0x27, 0x36, 0x02, 0x04, + 0x38, 0x77, 0x18, 0x44, 0x17, 0x78, 0x46, 0x34, 0x68, 0x00, + 0x72, 0x57, 0x72, 0x67, 0x53, 0x82, 0x51, 0x06, 0x34, 0x56, + 0x71, 0x26, 0x73, 0x55, 0x58, 0x11, 0x44, 0x15, 0x26, 0x81, + 0x14, 0x88, 0x25, 0x45, 0x52, 0x84, 0x13, 0x60, 0x12, 0x26, + 0x12, 0x36, 0x11, 0x61, 0x30, 0x25, 0x32, 0x83, 0x00, 0x71, + 0x73, 0x04, 0x48, 0x40, 0x70, 0x21, 0x36, 0x54, 0x45, 0x33, + 0x43, 0x00, 0x76, 0x62, 0x63, 0x71, 0x15, 0x35, 0x27, 0x50, + 0x06, 0x16, 0x30, 0x45, 0x08, 0x12, 0x51, 0x68, 0x38, 0x21, + 0x71, 0x61, 0x61, 0x18, 0x35, 0x15, 0x25, 0x47, 0x14, 0x62, + 0x51, 0x14, 0x76, 0x12, 0x62, 0x60, 0x63, 0x16, 0x20, 0x68, + 0x62, 0x31, 0x56, 0x64, 0x05, 0x84, 0x56, 0x26, 0x40, 0x42, + 0x88, 0x05, 0x60, 0x84, 0x82, 0x10, 0x23, 0x87, 0x63, 0x33, + 0x60, 0x40, 0x58, 0x12, 0x83, 0x26, 0x03, 0x13, 0x85, 0x23, + 0x02, 0x73, 0x05, 0x27, 0x40, 0x02, 0x75, 0x85, 0x46, 0x51, + 0x83, 0x71, 0x37, 0x16, 0x05, 0x86, 0x35, 0x01, 0x45, 0x00, + 0x53, 0x68, 0x27, 0x11, 0x06, 0x08, 0x82, 0x60, 0x58, 0x28, + 0x50, 0x07, 0x32, 0x56, 0x26, 0x46, 0x78, 0x63, 0x71, 0x16, + 0x48, 0x46, 0x86, 0x41, 0x37, 0x75, 0x06, 0x01, 0x11, 0x46, + 0x45, 0x21, 0x03, 0x82, 0x42, 0x75, 0x83, 0x30, 0x66, 0x00, + 0x74, 0x74, 0x46, 0x05, 0x33, 0x82, 0x33, 0x07, 0x34, 0x53, + 0x07, 0x78, 0x53, 0x07, 0x41, 0x37, 0x78, 0x54, 0x06, 0x11, + 0x42, 0x47, 0x05, 0x02, 0x62, 0x34, 0x27, 0x17, 0x78, 0x70, + 0x70, 0x46, 0x00, 0x38, 0x75, 0x48, 0x74, 0x46, 0x83, 0x35, + 0x08, 0x46, 0x14, 0x12, 0x20, 0x68, 0x00, 0x73, 0x57, 0x81, + 0x84, 0x62, 0x43, 0x11, 0x28, 0x87, 0x13, 0x30, 0x06, 0x70, + 0x15, 0x46, 0x51, 0x14, 0x74, 0x13, 0x53, 0x26, 0x84, 0x78, + 0x86, 0x15, 0x84, 0x18, 0x70, 0x56, 0x41, 0x33, 0x61, 0x56, + 0x28, 0x11, 0x30, 0x73, 0x82, 0x00, 0x57, 0x68, 0x61, 0x44, + 0x04, 0x64, 0x78, 0x68, 0x14, 0x02, 0x83, 0x88, 0x86, 0x88, + 0x40, 0x16, 0x81, 0x20, 0x68, 0x72, 0x67, 0x05, 0x76, 0x06, + 0x54, 0x74, 0x35, 0x71, 0x02, 0x67, 0x45, 0x24, 0x73, 0x64, + 0x87, 0x31, 0x60, 0x37, 0x04, 0x11, 0x85, 0x63, 0x40, 0x71, + 0x38, 0x46, 0x65, 0x16, 0x10, 0x85, 0x06, 0x37, 0x25, 0x53, + 0x05, 0x58, 0x45, 0x87, 0x17, 0x47, 0x78, 0x10, 0x22, 0x26, + 0x24, 0x86, 0x44, 0x63, 0x45, 0x00, 0x14, 0x77, 0x60, 0x04, + 0x54, 0x45, 0x40, 0x32, 0x45, 0x03, 0x60, 0x87, 0x05, 0x02, + 0x18, 0x22, 0x20, 0x61, 0x07, 0x36, 0x72, 0x52, 0x53, 0x65, + 0x27, 0x26, 0x37, 0x54, 0x31, 0x34, 0x22, 0x54, 0x37, 0x25, + 0x83, 0x14, 0x74, 0x75, 0x17, 0x61, 0x48, 0x74, 0x24, 0x43, + 0x80, 0x81, 0x15, 0x06, 0x88, 0x23, 0x84, 0x55, 0x20, 0x11, + 0x87, 0x83, 0x64, 0x36, 0x48, 0x88, 0x32, 0x20, 0x28, 0x54, + 0x88, 0x85, 0x35, 0x61, 0x00, 0x21, 0x01, 0x31, 0x44, 0x13, + 0x71, 0x48, 0x23, 0x47, 0x31, 0x62, 0x40, 0x18, 0x21, 0x78, + 0x34, 0x12, 0x88, 0x10, 0x76, 0x46, 0x72, 0x37, 0x70, 0x84, + 0x15, 0x41, 0x84, 0x22, 0x20, 0x22, 0x27, 0x44, 0x81, 0x03, + 0x46, 0x48, 0x26, 0x16, 0x21, 0x15, 0x31, 0x85, 0x73, 0x74, + 0x73, 0x06, 0x55, 0x21, 0x12, 0x53, 0x13, 0x34, 0x01, 0x64, + 0x40, 0x83, 0x08, 0x57, 0x24, 0x04, 0x18, 0x33, 0x70, 0x18, + 0x17, 0x06, 0x14, 0x28, 0x12, 0x58, 0x00, 0x25, 0x57, 0x20, + 0x00, 0x76, 0x73, 0x45, 0x68, 0x16, 0x60, 0x22, 0x17, 0x22, + 0x37, 0x75, 0x53, 0x48, 0x40, 0x21, 0x64, 0x27, 0x52, 0x48, + 0x53, 0x61, 0x64, 0x87, 0x57, 0x61, 0x13, 0x75, 0x80, 0x08, + 0x63, 0x33, 0x60, 0x26, 0x10, 0x25, 0x61, 0x78, 0x47, 0x78, + 0x07, 0x16, 0x00, 0x52, 0x31, 0x30, 0x63, 0x66, 0x46, 0x80, + 0x07, 0x10, 0x45, 0x11, 0x13, 0x80, 0x25, 0x61, 0x25, 0x53, + 0x80, 0x71, 0x38, 0x31, 0x47, 0x55, 0x02, 0x25, 0x50, 0x87, + 0x57, 0x35, 0x74, 0x11, 0x46, 0x44, 0x53, 0x24, 0x60, 0x33, + 0x15, 0x12, 0x77, 0x20, 0x36, 0x24, 0x70, 0x04, 0x87, 0x05, + 0x71, 0x07, 0x77, 0x36, 0x47, 0x01, 0x73, 0x61, 0x32, 0x62, + 0x28, 0x81, 0x67, 0x17, 0x38, 0x45, 0x21, 0x03, 0x24, 0x72, + 0x82, 0x64, 0x84, 0x43, 0x07, 0x11, 0x20, 0x72, 0x71, 0x04, + 0x58, 0x36, 0x22, 0x21, 0x33, 0x67, 0x55, 0x48, 0x03, 0x68, + 0x32, 0x70, 0x04, 0x63, 0x11, 0x34, 0x27, 0x82, 0x42, 0x56, + 0x28, 0x74, 0x77, 0x72, 0x18, 0x27, 0x35, 0x87, 0x03, 0x18, + 0x40, 0x32, 0x78, 0x07, 0x14, 0x43, 0x73, 0x73, 0x84, 0x63, + 0x78, 0x68, 0x03, 0x22, 0x55, 0x30, 0x18, 0x88, 0x15, 0x86, + 0x18, 0x51, 0x12, 0x42, 0x13, 0x60, 0x22, 0x44, 0x61, 0x44, + 0x35, 0x73, 0x08, 0x85, 0x53, 0x02, 0x73, 0x83, 0x25, 0x85, + 0x64, 0x78, 0x16, 0x12, 0x13, 0x63, 0x48, 0x35, 0x02, 0x71, + 0x72, 0x58, 0x12, 0x10, 0x65, 0x42, 0x22, 0x54, 0x80, 0x60, + 0x57, 0x84, 0x72, 0x76, 0x67, 0x35, 0x25, 0x14, 0x73, 0x70, + 0x48, 0x03, 0x78, 0x07, 0x74, 0x48, 0x67, 0x48, 0x01, 0x62, + 0x78, 0x05, 0x37, 0x66, 0x42, 0x45, 0x33, 0x65, 0x08, 0x70, + 0x42, 0x15, 0x72, 0x53, 0x13, 0x20, 0x14, 0x38, 0x05, 0x53, + 0x00, 0x45, 0x25, 0x20, 0x80, 0x75, 0x01, 0x65, 0x80, 0x70, + 0x61, 0x50, 0x15, 0x10, 0x77, 0x23, 0x38, 0x31, 0x21, 0x51, + 0x78, 0x11, 0x88, 0x71, 0x18, 0x06, 0x45, 0x62, 0x47, 0x35, + 0x43, 0x00, 0x52, 0x34, 0x41, 0x75, 0x18, 0x13, 0x51, 0x35, + 0x72, 0x11, 0x78, 0x17, 0x30, 0x44, 0x83, 0x25, 0x64, 0x42, + 0x65, 0x23, 0x50, 0x32, 0x85, 0x30, 0x67, 0x10, 0x70, 0x01, + 0x16, 0x62, 0x36, 0x46, 0x18, 0x53, 0x53, 0x80, 0x13, 0x65, + 0x66, 0x53, 0x61, 0x55, 0x07, 0x71, 0x34, 0x56, 0x31, 0x67, + 0x64, 0x42, 0x64, 0x41, 0x22, 0x56, 0x44, 0x67, 0x25, 0x52, + 0x08, 0x17, 0x38, 0x45, 0x76, 0x83, 0x37, 0x15, 0x76, 0x31, + 0x83, 0x47, 0x30, 0x21, 0x55, 0x73, 0x37, 0x82, 0x11, 0x56, + 0x67, 0x27, 0x23, 0x44, 0x72, 0x82, 0x10, 0x80, 0x43, 0x11, + 0x16, 0x02, 0x21, 0x40, 0x42, 0x10, 0x12, 0x74, 0x58, 0x40, + 0x74, 0x00, 0x66, 0x02, 0x85, 0x76, 0x21, 0x17, 0x83, 0x78, + 0x80, 0x40, 0x46, 0x87, 0x66, 0x24, 0x35, 0x80, 0x31, 0x77, + 0x87, 0x10, 0x47, 0x02, 0x20, 0x65, 0x43, 0x73, 0x41, 0x61, + 0x72, 0x18, 0x21, 0x52, 0x32, 0x82, 0x08, 0x82, 0x00, 0x57, + 0x52, 0x41, 0x45, 0x10, 0x51, 0x41, 0x28, 0x37, 0x72, 0x45, + 0x77, 0x10, 0x56, 0x06, 0x54, 0x30, 0x03, 0x74, 0x13, 0x56, + 0x77, 0x54, 0x04, 0x86, 0x13, 0x77, 0x81, 0x77, 0x57, 0x15, + 0x76, 0x13, 0x51, 0x75, 0x4C, 0xD3, 0x8C, 0xF8, 0x0F, 0x87, + 0x37, 0xBC, 0x26, 0x1B, 0x7A, 0x1C, 0xDC, 0x05, 0xFD, 0x9B, + 0x97, 0x8C, 0x4D, 0xE5, 0x06, 0xFF, 0x57, 0x65, 0xDC, 0xFC, + 0xBF, 0x55, 0x20, 0x8F, 0xC9, 0xAB, 0x63, 0x4C, 0x37, 0x02, + 0xB5, 0x51, 0x79, 0x6B, 0xC2, 0x02, 0x74, 0xE5, 0x74, 0x72, + 0xC4, 0x3C, 0x8F, 0xD2, 0x79, 0xCB, 0x65, 0x3C, 0xBD, 0xA6, + 0xC5, 0x19, 0xDF, 0xFC, 0x24, 0xB9, 0x91, 0x81, 0x41, 0x4D, + 0xDF, 0x2E, 0x6A, 0xBD, 0x5A, 0xC4, 0x04, 0x03, 0x7F, 0x71, + 0x7D, 0x51, 0xDD, 0x2F, 0xAE, 0x4C, 0x9A, 0xF8, 0x98, 0x11, + 0xA0, 0xCE, 0xF7, 0xDE, 0xF5, 0xC6, 0x91, 0xD3, 0xDC, 0xE7, + 0xAA, 0xD0, 0x7D, 0xDF, 0x5F, 0xF2, 0x5B, 0x55, 0x9C, 0xD6, + 0x8D, 0xC9, 0x1E, 0xC7, 0x80, 0xD9, 0xC5, 0xFA, 0x15, 0xEB, + 0xCE, 0x6B, 0x99, 0x71, 0xBD, 0xED, 0x0C, 0x24, 0x1B, 0x97, + 0x52, 0xFA, 0x54, 0xF5, 0x72, 0x48, 0x97, 0x05, 0x8B, 0x04, + 0xE5, 0xAA, 0xE0, 0xDC, 0x98, 0x13, 0xD2, 0x27, 0xB0, 0x0B, + 0x49, 0x8B, 0xA0, 0xD1, 0x2C, 0x18, 0xA5, 0xFA, 0x2A, 0x80, + 0x4B, 0xF7, 0x4B, 0x8C, 0xE0, 0xA4, 0xCD, 0xD0, 0x75, 0xE9, + 0x4A, 0x75, 0x15, 0x1B, 0xB8, 0x51, 0xD8, 0x8D, 0x1E, 0xA4, + 0xD1, 0xCD, 0x0E, 0xEE, 0xD4, 0xAA, 0x55, 0x0C, 0x6A, 0xB3, + 0xC9, 0x51, 0x66, 0x72, 0x76, 0xF4, 0xF9, 0xA4, 0xC2, 0x56, + 0x9D, 0xF9, 0x7C, 0x4C, 0x91, 0x27, 0xAC, 0xB3, 0x3E, 0x6B, + 0x2D, 0x5B, 0x84, 0xF3, 0x68, 0xD7, 0x28, 0xAE, 0xB6, 0x75, + 0x41, 0x46, 0xF2, 0x50, 0xF4, 0x20, 0x04, 0x4E, 0xB3, 0x0D, + 0xC3, 0xAE, 0xA9, 0x87, 0x9E, 0xB2, 0x05, 0xAE, 0x33, 0x76, + 0x76, 0x1A, 0x7A, 0xAB, 0xFD, 0x55, 0x77, 0x64, 0xF0, 0x0A, + 0x7C, 0x4F, 0x75, 0xE7, 0xBC, 0x09, 0x2D, 0x99, 0x4B, 0x90, + 0x13, 0x42, 0x62, 0xBD, 0x70, 0x14, 0x39, 0x23, 0x3A, 0x8A, + 0x32, 0x30, 0xEA, 0x66, 0x24, 0x85, 0xAF, 0x0B, 0xD7, 0x72, + 0xC4, 0xFC, 0x89, 0xD9, 0xB6, 0x9A, 0x1D, 0xA4, 0x10, 0x50, + 0x69, 0x98, 0x8E, 0x00, 0xA1, 0xCF, 0x94, 0x6C, 0x1B, 0x79, + 0x3A, 0xB7, 0xD8, 0x86, 0x1C, 0xD1, 0x95, 0x72, 0x0A, 0x3A, + 0xDA, 0xEF, 0x26, 0x15, 0xA5, 0xE4, 0x67, 0xD6, 0x04, 0xC5, + 0x0A, 0xBA, 0x50, 0x21, 0x9C, 0xB7, 0x1A, 0xF1, 0x1F, 0x1D, + 0x90, 0x5A, 0x6E, 0x40, 0xF8, 0xC1, 0xAB, 0xBD, 0x88, 0xA7, + 0xB8, 0x25, 0xBD, 0xCB, 0x93, 0xFA, 0x79, 0xAE, 0xAF, 0x1A, + 0xBD, 0x7B, 0xC4, 0x9F, 0x89, 0x7C, 0xFF, 0xFB, 0x0E, 0x27, + 0x32, 0x20, 0x6D, 0x47, 0x6B, 0x0E, 0x0D, 0xA1, 0x6A, 0x55, + 0x7F, 0xFD, 0x73, 0x9B, 0xC5, 0x3F, 0xF8, 0x08, 0xAA, 0xFE, + 0x0F, 0x7E, 0xAD, 0xB8, 0x13, 0x50, 0x79, 0x8D, 0x58, 0xAF, + 0xB2, 0xC6, 0x66, 0x24, 0xA8, 0x19, 0xD6, 0x90, 0x81, 0x54, + 0x92, 0x7B, 0xAF, 0xA8, 0xB8, 0x3D, 0x27, 0xD0, 0xC0, 0x08, + 0xB6, 0x45, 0x3D, 0x24, 0x46, 0xA0, 0x04, 0x8A, 0x26, 0x95, + 0xCF, 0x3F, 0x3C, 0x31, 0x43, 0x5D, 0xCA, 0x7A, 0xED, 0xF7, + 0xD3, 0xB5, 0xA0, 0xEE, 0xDC, 0x97, 0x76, 0xB3, 0x2F, 0x89, + 0x18, 0x62, 0xAC, 0x4B, 0x8B, 0xFC, 0x06, 0x1E, 0x15, 0xE5, + 0x25, 0x72, 0x46, 0xB9, 0x02, 0xD9, 0x0C, 0x38, 0xCF, 0x82, + 0x13, 0x19, 0x6E, 0x18, 0x85, 0xC6, 0x76, 0xF9, 0x10, 0xF9, + 0xCD, 0x72, 0x05, 0xED, 0x5E, 0xAE, 0xBB, 0xD2, 0xAB, 0x64, + 0x13, 0x3E, 0x9F, 0x20, 0xCF, 0x8C, 0xC0, 0x37, 0x71, 0x38, + 0x22, 0x49, 0x38, 0x9C, 0x23, 0xCB, 0x0B, 0xC3, 0xE8, 0xE5, + 0xEB, 0x31, 0x61, 0x07, 0xFE, 0x2A, 0xAC, 0xDE, 0x90, 0x35, + 0x24, 0xEB, 0x6B, 0xB6, 0x34, 0x51, 0x9C, 0xE2, 0x7D, 0xD0, + 0x8B, 0x38, 0xDB, 0x81, 0x7B, 0x24, 0x7B, 0x69, 0x84, 0x1D, + 0x17, 0x9F, 0x64, 0x63, 0x6F, 0x3F, 0x43, 0xFC, 0xFE, 0x07, + 0x72, 0x66, 0x84, 0xE3, 0xCD, 0x4F, 0x25, 0x70, 0x81, 0x64, + 0x66, 0x2C, 0xA8, 0x35, 0x11, 0x1B, 0xF3, 0x03, 0x1B, 0x5B, + 0xDC, 0xFB, 0x7D, 0xAD, 0x14, 0x11, 0xC8, 0xB1, 0x0C, 0x7E, + 0x36, 0x79, 0x34, 0x79, 0x1A, 0x88, 0x8A, 0x8F, 0xF6, 0x66, + 0xB4, 0x95, 0xD4, 0xA1, 0x02, 0xF9, 0x1D, 0x26, 0x53, 0x7A, + 0x34, 0x00, 0x36, 0x0E, 0xE7, 0xFB, 0x7A, 0x60, 0xF9, 0xC3, + 0xCF, 0x30, 0xCB, 0xF0, 0x27, 0xB5, 0xD6, 0xCF, 0x15, 0x33, + 0x53, 0x88, 0x7C, 0x50, 0x07, 0xF4, 0x27, 0xE0, 0x40, 0x47, + 0xFE, 0x86, 0x0E, 0xFF, 0x07, 0x5F, 0x55, 0xB8, 0x3B, 0xAA, + 0xFB, 0xB0, 0x6B, 0x98, 0x47, 0x59, 0xB8, 0x33, 0xAA, 0x67, + 0x6B, 0x36, 0xEB, 0x76, 0x43, 0xAF, 0x31, 0x52, 0x62, 0x3D, + 0x7F, 0x64, 0x6A, 0xFC, 0x36, 0x92, 0x96, 0xF8, 0xD9, 0xE7, + 0x13, 0x77, 0x1D, 0xD0, 0xFB, 0x0D, 0x70, 0x29, 0x61, 0x52, + 0x82, 0xF4, 0xE4, 0xA7, 0x08, 0x47, 0x4C, 0x67, 0xEE, 0x36, + 0xD1, 0x1C, 0x18, 0x8B, 0xF1, 0x2D, 0xE2, 0x47, 0x16, 0x4D, + 0x1F, 0x05, 0xC6, 0x4E, 0xFB, 0x35, 0x51, 0x3A, 0x9E, 0xF9, + 0xE0, 0x1E, 0xC1, 0x64, 0x21, 0x0B, 0x8A, 0xF0, 0x1D, 0x32, + 0x78, 0x18, 0xF2, 0xB3, 0xB5, 0xBD, 0x66, 0x6B, 0xAD, 0x92, + 0x4F, 0x22, 0xDC, 0xB9, 0xCC, 0xF4, 0x98, 0x22, 0x99, 0xF6, + 0x3D, 0xC6, 0x8F, 0x28, 0x77, 0x60, 0x34, 0xD0, 0x73, 0xF5, + 0x4D, 0x9F, 0x6C, 0x5D, 0x94, 0xC2, 0x3D, 0x19, 0xCD, 0xC2, + 0x18, 0x41, 0x9B, 0x5F, 0x32, 0x2D, 0x5E, 0x3D, 0x92, 0xBE, + 0x26, 0x39, 0x85, 0x50, 0xE6, 0xE2, 0x49, 0x17, 0x19, 0xD3, + 0x57, 0xAF, 0x45, 0x85, 0x74, 0xF7, 0x16, 0x35, 0x0A, 0x94, + 0x54, 0x64, 0x45, 0xD5, 0x31, 0x51, 0x49, 0x8F, 0xA4, 0x4C, + 0x33, 0xBB, 0x62, 0x59, 0x6B, 0x08, 0xBD, 0x1C, 0xDD, 0x38, + 0x93, 0x22, 0x0B, 0xCF, 0x9B, 0x23, 0x87, 0x30, 0xA2, 0xA0, + 0x6D, 0x97, 0x2D, 0xD7, 0x2B, 0x16, 0x88, 0x72, 0x01, 0x9A, + 0x51, 0xBA, 0x56, 0xCE, 0xDC, 0xDD, 0xF9, 0x87, 0x41, 0xC8, + 0x44, 0xF1, 0xA2, 0x20, 0x9A, 0x11, 0x44, 0x13, 0xDF, 0x49, + 0x04, 0x85, 0x4C, 0x01, 0x46, 0x3E, 0xD6, 0xB8, 0xE2, 0xC2, + 0x2E, 0xED, 0xA4, 0x07, 0x29, 0x89, 0xA2, 0x46, 0x23, 0x98, + 0xA5, 0xEF, 0x59, 0x1A, 0xE7, 0x67, 0x64, 0x59, 0xF7, 0x2C, + 0x5B, 0x30, 0x29, 0x57, 0xE3, 0xDE, 0x5C, 0x84, 0x1B, 0x8F, + 0x3E, 0xB3, 0x5B, 0xF5, 0x0C, 0x6E, 0xB1, 0x4E, 0x2F, 0xB6, + 0xB6, 0x5B, 0x29, 0xCD, 0xBB, 0xB8, 0xC9, 0xF0, 0x39, 0xF9, + 0xB9, 0x11, 0x47, 0xEF, 0xF8, 0x90, 0xE0, 0x0F, 0x91, 0x70, + 0x97, 0xB4, 0xFC, 0xFD, 0xB5, 0x69, 0x8C, 0x61, 0x9A, 0x26, + 0xD2, 0xC9, 0x47, 0x67, 0xB7, 0xDB, 0x73, 0x11, 0xA3, 0xC1, + 0x3B, 0x4E, 0x5F, 0x60, 0xDA, 0x73, 0x39, 0x9B, 0xD4, 0x3D, + 0x24, 0xA6, 0x8A, 0xB5, 0x56, 0x5D, 0xBD, 0x27, 0xDE, 0x6C, + 0x67, 0xA1, 0x4A, 0x77, 0xB7, 0x44, 0x1D, 0x28, 0x44, 0xA0, + 0xA3, 0xF2, 0xEB, 0x3A, 0x9F, 0xE5, 0x5C, 0xF5, 0xE3, 0xFE, + 0xD0, 0xC3, 0xCA, 0x2A, 0x1A, 0x72, 0x86, 0xB3, 0x4E, 0x9D, + 0x25, 0x0B, 0x4C, 0xFF, 0x45, 0xB7, 0xDE, 0xE8, 0x8C, 0x0A, + 0x06, 0xED, 0x30, 0x26, 0x8F, 0xA1, 0xBF, 0x74, 0x22, 0x3D, + 0x50, 0x39, 0x17, 0xA9, 0x6B, 0x7C, 0xAC, 0xA0, 0x6A, 0xEA, + 0x14, 0x95, 0x5F, 0xAD, 0x3C, 0xB1, 0x4E, 0xE1, 0x30, 0x2F, + 0x4A, 0x77, 0x72, 0xC1, 0x1F, 0x4C, 0x91, 0x6B, 0xCF, 0x81, + 0x46, 0xAF, 0x2D, 0xEC, 0x59, 0x9E, 0x99, 0xD9, 0x60, 0x23, + 0x95, 0x08, 0x0D, 0xBB, 0xFD, 0xEC, 0x2A, 0xF7, 0x7B, 0x73, + 0x53, 0xF3, 0x88, 0xB7, 0xAF, 0x51, 0x69, 0xD5, 0x08, 0xFC, + 0xCC, 0x03, 0xD3, 0x61, 0x5C, 0xDD, 0x39, 0x56, 0x6B, 0xE4, + 0xEE, 0x1F, 0x0A, 0xD6, 0x1A, 0x84, 0x65, 0x45, 0x0C, 0x0A, + 0x34, 0xDE, 0x96, 0x24, 0xBB, 0x74, 0xF4, 0xB7, 0xE5, 0x2F, + 0xB5, 0x1F, 0x85, 0x9D, 0xD7, 0xEA, 0xB3, 0x33, 0xBE, 0xCF, + 0x19, 0x45, 0xCE, 0xF9, 0x13, 0xF5, 0xFD, 0x65, 0x5D, 0xBB, + 0xDB, 0x64, 0x94, 0xAC, 0xB8, 0x39, 0xAF, 0x9B, 0x56, 0xE4, + 0x5C, 0x95, 0x85, 0xFD, 0xB3, 0xF8, 0x3C, 0x98, 0xD3, 0x58, + 0xCE, 0xAB, 0x09, 0x0E, 0xA7, 0x42, 0x9B, 0x16, 0xA7, 0x63, + 0xEB, 0xB8, 0x7C, 0x01, 0xA2, 0xD4, 0x3C, 0x2B, 0xA7, 0xA3, + 0x52, 0x8C, 0x08, 0xA5, 0xA9, 0xAF, 0x63, 0x07, 0xDA, 0x45, + 0x86, 0x91, 0x64, 0xE6, 0x41, 0x75, 0x78, 0x46, 0x6F, 0xB9, + 0xB4, 0xEA, 0x6A, 0xDD, 0xC7, 0x1A, 0x1F, 0xC0, 0x8A, 0x00, + 0x81, 0x70, 0x74, 0x37, 0xC8, 0x84, 0x3F, 0xA8, 0xC9, 0xC1, + 0xC1, 0x60, 0x2B, 0x25, 0x9B, 0x66, 0x5F, 0x73, 0x15, 0x51, + 0xE2, 0xE4, 0x49, 0x5B, 0xEE, 0x20, 0xC8, 0x18, 0xE7, 0x65, + 0xED, 0x29, 0xEA, 0x96, 0x85, 0xB5, 0x63, 0xFB, 0xA6, 0x23, + 0x22, 0xB7, 0x4F, 0x6E, 0xE3, 0xF2, 0x9C, 0x01, 0x23, 0x7A, + 0xB9, 0x16, 0x2A, 0x93, 0xAF, 0x4F, 0xEA, 0x05, 0x15, 0x84, + 0x46, 0x32, 0x2F, 0x99, 0xB8, 0x78, 0x20, 0x78, 0x93, 0xC9, + 0x42, 0x6D, 0xBC, 0x70, 0xCE, 0x88, 0x6F, 0x12, 0x92, 0x3F, + 0xDE, 0xFB, 0xDE, 0x8E, 0xD3, 0x69, 0x09, 0x54, 0x7D, 0x0A, + 0xE1, 0x93, 0x3D, 0x10, 0x04, 0xDE, 0x66, 0x9D, 0x2D, 0xAD, + 0xA4, 0x53, 0x4C, 0xF6, 0xFC, 0x08, 0xE4, 0x58, 0x05, 0x09, + 0x78, 0x09, 0xE6, 0xF3, 0xEE, 0x83, 0xC2, 0xD0, 0xA9, 0x04, + 0xE6, 0xAC, 0x30, 0xD7, 0x34, 0x52, 0xEB, 0xCD, 0x1A, 0x7E, + 0xB9, 0xCF, 0x18, 0x68, 0x16, 0xB9, 0x9A, 0x18, 0xDA, 0xC8, + 0xE3, 0x1C, 0xF0, 0x9A, 0x2E, 0x64, 0x28, 0xBE, 0xA4, 0x9F, + 0xCB, 0xC0, 0x53, 0xE6, 0x2A, 0x88, 0xB5, 0xE7, 0xF3, 0x6F, + 0x46, 0x1C, 0xBA, 0xAD, 0x76, 0x17, 0x85, 0xAE, 0x95, 0x13, + 0x7B, 0xF9, 0xB8, 0xD3, 0x08, 0x6A, 0x38, 0x63, 0x67, 0xD8, + 0x8B, 0x51, 0x8F, 0x49, 0x44, 0xB4, 0x10, 0xB8, 0x74, 0x38, + 0xDD, 0x17, 0xEA, 0x52, 0x67, 0xB2, 0xCC, 0xC9, 0x77, 0xDD, + 0x44, 0x2E, 0xDF, 0x03, 0xC7, 0xF4, 0x87, 0xF4, 0xBC, 0x6F, + 0x94, 0x9F, 0x58, 0xDB, 0xE2, 0x09, 0xA1, 0x4C, 0xCA, 0x89, + 0x9D, 0x04, 0x5A, 0xAB, 0xDF, 0x8B, 0x82, 0x3F, 0x0E, 0xF2, + 0xE7, 0xBD, 0x9A, 0x16, 0x3A, 0xAF, 0x72, 0x18, 0xB9, 0x47, + 0xB3, 0xBC, 0xFE, 0x84, 0x43, 0x92, 0x98, 0xF4, 0x3A, 0x49, + 0x3A, 0x26, 0xB7, 0xF3, 0x37, 0x54, 0x06, 0xD8, 0x92, 0x09, + 0xE6, 0xFE, 0x9A, 0xDB, 0x68, 0x16, 0x6F, 0x5D, 0x5D, 0x8E, + 0xBB, 0xFC, 0xAC, 0x5A, 0x72, 0xFE, 0x0B, 0xEB, 0xDB, 0x90, + 0xA4, 0x6C, 0x37, 0x1A, 0x8B, 0x5A, 0xD8, 0xE9, 0xF6, 0x15, + 0xFC, 0x54, 0x1B, 0x95, 0xE3, 0xAE, 0x08, 0x46, 0xB5, 0xFB, + 0xC5, 0x66, 0xC5, 0x79, 0x17, 0x9D, 0x5C, 0x45, 0xE5, 0x4E, + 0xFF, 0xA2, 0x86, 0xD7, 0x4F, 0xD4, 0x1D, 0x17, 0xA3, 0x77, + 0x00, 0x54, 0x70, 0xDF, 0x12, 0xCA, 0xD6, 0x71, 0x05, 0x54, + 0xFA, 0x47, 0x96, 0x38, 0x2D, 0x4D, 0x70, 0x3E, 0x2E, 0x40, + 0xE7, 0x52, 0x32, 0x66, 0x4D, 0x92, 0x1B, 0x76, 0x66, 0xF1, + 0xD4, 0x38, 0x8B, 0x76, 0x47, 0xE1, 0x66, 0xDE, 0xA2, 0x06, + 0xD7, 0xA7, 0x96, 0x52, 0xED, 0xC9, 0xF3, 0xD6, 0x99, 0xDF, + 0x2F, 0x98, 0xC5, 0xBF, 0x16, 0x95, 0x80, 0x41, 0xE4, 0xEB, + 0x8B, 0x16, 0xEF, 0x6A, 0x76, 0x84, 0xE7, 0x5F, 0x6C, 0xBD, + 0x1D, 0x2A, 0x74, 0x08, 0x5B, 0x4E, 0xCA, 0xE1, 0xF5, 0xD0, + 0x42, 0x2C, 0x03, 0x9B, 0x80, 0xBD, 0x05, 0x5F, 0x87, 0xF0, + 0x84, 0x08, 0x96, 0xBE, 0xAC, 0xBF, 0xF1, 0x8F, 0x51, 0x69, + 0x9E, 0xC2, 0xE9, 0x96, 0x9D, 0x97, 0xCD, 0x56, 0x32, 0x29, + 0xC8, 0x53, 0xC2, 0x1A, 0x5A, 0xD3, 0xDA, 0x31, 0x94, 0x09, + 0x35, 0x08, 0x75, 0x27, 0x66, 0xC5, 0x10, 0x5F, 0xD1, 0x94, + 0x12, 0x03, 0x8A, 0x1B, 0x69, 0x81, 0xEB, 0xBE, 0xBC, 0x6B, + 0xE4, 0xB9, 0x84, 0x65, 0x7D, 0xE3, 0xFE, 0xFB, 0x45, 0x58, + 0x31, 0xF3, 0x66, 0x13, 0x64, 0xB2, 0xBD, 0xBC, 0xF6, 0xA5, + 0x07, 0x07, 0x8A, 0xC8, 0x43, 0xCA, 0x38, 0x94, 0x70, 0xC0, + 0x25, 0xDA, 0xC6, 0xD9, 0x74, 0x5A, 0x60, 0xE3, 0x9D, 0x74, + 0x6C, 0x72, 0xF5, 0xAF, 0xD3, 0xD7, 0xF5, 0xBD, 0x17, 0x02, + 0xE5, 0x17, 0xEC, 0xBD, 0xCB, 0x5D, 0x1A, 0x8F, 0x39, 0x31, + 0x7E, 0x4B, 0x1F, 0x1A, 0x87, 0xE2, 0x69, 0x65, 0x07, 0x42, + 0x6D, 0xD2, 0x2D, 0x04, 0x52, 0x51, 0xA7, 0xF2, 0x23, 0xC6, + 0x01, 0xD1, 0x47, 0x5F, 0x42, 0x44, 0x2A, 0x88, 0x5E, 0xBB, + 0x98, 0x5A, 0x34, 0xBB, 0x0E, 0x05, 0xA7, 0x1D, 0x7E, 0xFB, + 0x3E, 0x85, 0xD8, 0x74, 0x70, 0xE8, 0x71, 0xC2, 0x31, 0x80, + 0x37, 0xF9, 0x15, 0xA4, 0xC1, 0xFC, 0x9B, 0x68, 0x2B, 0x54, + 0x9B, 0x37, 0x9C, 0xE7, 0x62, 0x80, 0x20, 0x1E, 0x27, 0x78, + 0xBF, 0x11, 0xC4, 0x86, 0xAC, 0x7B, 0x34, 0x57, 0x76, 0x86, + 0x77, 0x15, 0x51, 0x7C, 0xDC, 0x32, 0xDF, 0x48, 0xB9, 0xC6, + 0x63, 0xC6, 0x9A, 0xDE, 0x5E, 0x9D, 0xAB, 0x4A, 0x92, 0xEE, + 0x0C, 0x10, 0x7E, 0xB5, 0x33, 0x17, 0xF6, 0x0C, 0x8D, 0x26, + 0x89, 0xCD, 0x2B, 0xB8, 0x49, 0x4A, 0x4D, 0x5D, 0x66, 0x38, + 0x86, 0x42, 0x37, 0xC5, 0x1B, 0xE7, 0x78, 0x90, 0x21, 0xAE, + 0x8F, 0xE7, 0x0C, 0x01, 0xB9, 0x31, 0x6A, 0x50, 0x1A, 0x2B, + 0xDA, 0xC2, 0x99, 0xCB, 0xEB, 0xF9, 0xAE, 0x91, 0x8B, 0xB7, + 0x08, 0x01, 0x1E, 0xCC, 0x9E, 0x20, 0x05, 0xEC, 0x45, 0x21, + 0xBE, 0xDE, 0xFE, 0x06, 0x7D, 0x92, 0x9C, 0xE7, 0x47, 0xD9, + 0x85, 0x63, 0xC3, 0xBB, 0x38, 0x15, 0x2D, 0x94, 0xCA, 0xAF, + 0xCF, 0xCA, 0x1D, 0x53, 0x1A, 0xBD, 0x23, 0xF1, 0x87, 0x99, + 0x24, 0xF3, 0x16, 0xE9, 0x7F, 0xBE, 0x00, 0x8A, 0x61, 0xA7, + 0x65, 0xF7, 0xA9, 0x53, 0x2A, 0x29, 0x20, 0x3E, 0x0B, 0xCF, + 0x12, 0x69, 0x22, 0x84, 0x27, 0x5D, 0x1C, 0xC8, 0x45, 0xA1, + 0xA5, 0x5A, 0xB0, 0xDB, 0x95, 0x5D, 0xF7, 0xCE, 0xAC, 0x98, + 0x44, 0x3B, 0xE1, 0x27, 0x9A, 0x93, 0x5D, 0x2B, 0x8A, 0x20, + 0xB1, 0x82, 0x2C, 0xDD, 0xB8, 0xCC, 0xFA, 0x77, 0x0F, 0xA7, + 0x80, 0x00, 0x87, 0x54, 0x1C, 0xCC, 0x0B, 0x1E, 0xF6, 0x52, + 0x89, 0x03, 0x65, 0x83, 0xF1, 0x97, 0x4E, 0x81, 0x99, 0xE1, + 0xDD, 0x73, 0x30, 0x31, 0xEC, 0xA7, 0xD5, 0x76, 0x28, 0xC3, + 0xCE, 0x29, 0x30, 0x7B, 0xB1, 0x27, 0x3F, 0xC4, 0x6D, 0x54, + 0xAF, 0xE2, 0x84, 0xEA, 0xF5, 0x91, 0xBD, 0xB9, 0x6C, 0x4E, + 0x98, 0x0F, 0xFB, 0xDE, 0x7C, 0x32, 0xF8, 0xED, 0xEF, 0xD0, + 0xE9, 0xA3, 0x57, 0xC0, 0x91, 0x06, 0x4C, 0x43, 0x3F, 0x32, + 0x21, 0xB5, 0xF2, 0x11, 0x5A, 0xDF, 0xFC, 0x7E, 0x91, 0x10, + 0xC0, 0x4D, 0xD4, 0x4E, 0xA8, 0x38, 0xD6, 0xE0, 0xB6, 0x27, + 0x38, 0x63, 0xF2, 0xD3, 0xFD, 0x68, 0x4C, 0xDD, 0x76, 0xA9, + 0x89, 0xCE, 0xBE, 0x7C, 0xAD, 0x45, 0x4C, 0x8C, 0x24, 0xCC, + 0x32, 0x66, 0x3A, 0x1A, 0x45, 0xDA, 0x47, 0x5C, 0x4C, 0xC6, + 0x8A, 0x9A, 0xC3, 0x99, 0xFB, 0x4C, 0x94, 0xE2, 0x20, 0xD7, + 0xE4, 0x37, 0x22, 0x99, 0x32, 0x6F, 0xFB, 0x1C, 0xE5, 0x9B, + 0xB5, 0xFC, 0xBD, 0xD2, 0xA1, 0xDD, 0x66, 0xD5, 0x47, 0x2F, + 0x6A, 0xAA, 0x50, 0xF5, 0xE8, 0x1A, 0xDC, 0x74, 0x50, 0x6A, + 0x92, 0x23, 0x93, 0xED, 0xB0, 0x58, 0x61, 0x7D, 0xB6, 0x5C, + 0x22, 0x7B, 0x54, 0x75, 0xF0, 0x69, 0xD4, 0x27, 0x0B, 0x70, + 0x3F, 0xBB, 0x76, 0x63, 0xB3, 0x1D, 0x7E, 0x33, 0x96, 0xD6, + 0x84, 0x2D, 0x28, 0x4F, 0x97, 0x65, 0xC9, 0x95, 0xCF, 0x30, + 0xBA, 0xEA, 0x08, 0xF5, 0xC6, 0x24, 0x45, 0x20, 0x85, 0x67, + 0x9F, 0x34, 0x37, 0x72, 0x44, 0x17, 0x98, 0x5F, 0xD0, 0xCE, + 0xA8, 0x6E, 0x0E, 0x50, 0x22, 0x14, 0xE1, 0x6B, 0xCB, 0xA5, + 0x12, 0x2A, 0x36, 0xF1, 0x6E, 0x81, 0x5C, 0x5A, 0x77, 0x4F, + 0xD7, 0xF9, 0xCE, 0x7A, 0xC9, 0x30, 0x2C, 0x1E, 0x7E, 0xFC, + 0x24, 0xCB, 0xE4, 0x53, 0xC3, 0x4A, 0x03, 0xED, 0xD5, 0x77, + 0xC6, 0x55, 0xEB, 0xA2, 0xB4, 0x92, 0x35, 0xE3, 0x20, 0xDA, + 0xD2, 0x58, 0xE2, 0xCC, 0xC4, 0x4E, 0xBB, 0xE3, 0x8F, 0x75, + 0xB1, 0xDB, 0x97, 0x15, 0x86, 0x43, 0xE5, 0xD4, 0x4F, 0x44, + 0x3F, 0x20, 0xE3, 0xB9, 0xA5, 0xFB, 0x3F, 0x36, 0xC9, 0x9C, + 0xEF, 0x8C, 0xD1, 0x46, 0x67, 0x16, 0xB6, 0xA6, 0x24, 0x8A, + 0xE9, 0xD7, 0x29, 0x4B, 0x5F, 0x7C, 0x06, 0xEF, 0xD7, 0xBB, + 0x88, 0xCB, 0x2C, 0xFB, 0x85, 0x19, 0x9F, 0x97, 0x74, 0xFE, + 0x76, 0x46, 0x44, 0x1E, 0xAD, 0xF3, 0x62, 0xD2, 0xAA, 0x24, + 0x37, 0xD0, 0x1E, 0xF3, 0xCB, 0x68, 0xE3, 0x17, 0xFF, 0x81, + 0x90, 0xA3, 0xD6, 0x28, 0xE6, 0xCE, 0x6D, 0x99, 0xF4, 0x2D, + 0xC6, 0xAE, 0x40, 0x52, 0x32, 0xE9, 0xC1, 0xC6, 0x79, 0x5C, + 0xF7, 0x69, 0x29, 0x0C, 0x75, 0x9F, 0x48, 0x57, 0x75, 0x1F, + 0x2F, 0x71, 0x9F, 0x24, 0x90, 0x14, 0xAE, 0xDC, 0x75, 0x2E, + 0x5E, 0xDD, 0x85, 0xE5, 0x6C, 0xC4, 0x72, 0x58, 0xF0, 0x35, + 0xDC, 0xFE, 0x03, 0xB7, 0x2F, 0xBD, 0xC3, 0x8A, 0xA3, 0x2C, + 0x62, 0xE0, 0xCD, 0x37, 0xFA, 0x9E, 0x11, 0xC0, 0x1D, 0xEF, + 0xB0, 0x58, 0x58, 0x12, 0xAF, 0x25, 0x6D, 0x75, 0x0D, 0x2F, + 0xBC, 0x89, 0xE9, 0x2E, 0x1E, 0x58, 0x64, 0x35, 0xA8, 0x90, + 0xC2, 0x61, 0x4D, 0xCE, 0x96, 0xC5, 0xF2, 0x37, 0xBD, 0xB8, + 0xDE, 0xB4, 0x0E, 0xEB, 0xDD, 0xED, 0xE6, 0x47, 0x24, 0xE6, + 0x36, 0xC9, 0x22, 0xD3, 0xE7, 0x1A, 0xEF, 0x9E, 0x16, 0x89, + 0xB9, 0x5C, 0xF4, 0x3B, 0x09, 0x7E, 0x9B, 0x87, 0x7F, 0xD6, + 0x84, 0x06, 0xCA, 0x0E, 0xA8, 0x54, 0x79, 0xCF, 0x02, 0xF6, + 0x1B, 0x57, 0x34, 0x9D, 0x97, 0x00, 0x05, 0x8B, 0x75, 0xA3, + 0x5C, 0x7C, 0xBA, 0xA7, 0x51, 0x85, 0xBC, 0xE6, 0xAC, 0xD9, + 0xD4, 0x31, 0xB3, 0x3A, 0xBD, 0x82, 0xC8, 0x60, 0x74, 0x46, + 0xA9, 0x2F, 0xC2, 0x29, 0x08, 0x59, 0x6B, 0x14, 0x19, 0x19, + 0x39, 0x7F, 0x8B, 0xA2, 0x2A, 0xFD, 0xE3, 0x09, 0x72, 0x50, + 0x74, 0x88, 0xEE, 0xC6, 0xED, 0x28, 0x37, 0xCD, 0xA9, 0xBA, + 0x2E, 0xFE, 0x07, 0xDF, 0x5E, 0xF9, 0x18, 0xB4, 0x0E, 0xBF, + 0x9C, 0x1C, 0xCA, 0x84, 0xBA, 0x62, 0xB9, 0xA2, 0x96, 0x76, + 0xB6, 0xB7, 0x77, 0x9C, 0xBE, 0x0C, 0xF8, 0xA5, 0xEF, 0x74, + 0xB1, 0xC2, 0x85, 0xCD, 0xD1, 0x25, 0xD5, 0xFC, 0xFB, 0x2C, + 0xC7, 0xD6, 0x2F, 0x30, 0x3F, 0x10, 0xEA, 0xA2, 0x99, 0xC4, + 0x22, 0x58, 0xB3, 0xC4, 0x46, 0x3C, 0x41, 0xE9, 0xE9, 0xA0, + 0x39, 0x6C, 0x09, 0x89, 0xE3, 0xAE, 0x4E, 0x35, 0xAB, 0x27, + 0x71, 0x43, 0xEB, 0xA7, 0xFA, 0x68, 0xA8, 0x42, 0x49, 0x3C, + 0x53, 0x70, 0x35, 0xCA, 0x14, 0xB7, 0x1D, 0xF8, 0x7E, 0x65, + 0x05, 0x33, 0xE3, 0x5A, 0x86, 0xCD, 0xA5, 0x18, 0x02, 0x24, + 0x23, 0xAD, 0x52, 0x6A, 0x47, 0x13, 0x14, 0x95, 0xD2, 0xF1, + 0xE1, 0x6F, 0x61, 0x70, 0x4F, 0xDC, 0x1A, 0x03, 0x0E, 0xD7, + 0x07, 0xBD, 0x84, 0x43, 0x65, 0x76, 0x9F, 0xFB, 0x1E, 0x89, + 0xEB, 0x92, 0x5E, 0xDE, 0x5B, 0xAA, 0x54, 0xEE, 0x0A, 0xF5, + 0x4A, 0x79, 0x46, 0xDA, 0xC1, 0xEC, 0x2F, 0xBC, 0xDD, 0xE5, + 0x61, 0xFA, 0xED, 0xB6, 0x97, 0x9C, 0x90, 0xD8, 0xF3, 0x2E, + 0x04, 0xCF, 0xB5, 0x89, 0x74, 0xC2, 0xD1, 0x70, 0xE0, 0x0F, + 0x53, 0x14, 0x09, 0x6A, 0x19, 0x5A, 0x65, 0xAC, 0xAA, 0x3C, + 0x25, 0x79, 0x43, 0x27, 0x47, 0x18, 0x19, 0x7A, 0x74, 0xD7, + 0x73, 0x43, 0xBD, 0x50, 0x1F, 0x68, 0xAF, 0xDF, 0x3E, 0x2A, + 0xC4, 0xDC, 0x6F, 0x85, 0x2A, 0xBC, 0x0F, 0x39, 0x4B, 0x97, + 0x6D, 0x2D, 0x87, 0x5F, 0x9A, 0x07, 0x82, 0xC7, 0x69, 0xB9, + 0xF2, 0xEF, 0xE3, 0x3C, 0x3C, 0x74, 0xB2, 0xFD, 0x81, 0x6F, + 0xC3, 0xAC, 0x93, 0x22, 0x49, 0xB5, 0x73, 0x5C, 0x58, 0x6E, + 0x5F, 0x7A, 0x6B, 0x91, 0x02, 0x25, 0x3B, 0xC8, 0x24, 0xD7, + 0xEF, 0xC8, 0x10, 0xD7, 0x54, 0xD4, 0xA7, 0xC1, 0x88, 0x77, + 0xDD, 0xCD, 0x3A, 0x92, 0xE5, 0x1D, 0xA1, 0x33, 0x10, 0xA4, + 0xF6, 0xB4, 0x43, 0xA4, 0xDB, 0x77, 0x4C, 0x91, 0x7C, 0xED, + 0xDD, 0xC7, 0xB9, 0x5A, 0xB4, 0x2A, 0x6C, 0x78, 0x54, 0xCA, + 0xBD, 0x16, 0x0C, 0x8C, 0x68, 0xE8, 0xBC, 0xDE, 0x65, 0x2F, + 0xAF, 0xEF, 0x09, 0xDC, 0x7C, 0x17, 0x7D, 0x05, 0xF7, 0xB1, + 0x8D, 0x09, 0x94, 0xDC, 0xF2, 0xAE, 0xF4, 0x21, 0x54, 0xF9, + 0x3E, 0xB0, 0x2A, 0x73, 0xFE, 0x9C, 0x51, 0xEB, 0x1E, 0x7B, + 0xFE, 0x65, 0xCB, 0x53, 0x80, 0x5B, 0xD2, 0x05, 0xA1, 0xE9, + 0xCB, 0x75, 0x60, 0x46, 0x08, 0x07, 0x83, 0x27, 0x4E, 0xD4, + 0xBF, 0x70, 0x83, 0xDE, 0xA9, 0xB4, 0x22, 0x55, 0xF1, 0x5F, + 0x91, 0x88, 0x4A, 0x43, 0xC1, 0xBF, 0x0A, 0xEF, 0xA7, 0xFF, + 0xE5, 0xA6, 0x50, 0xDD, 0xFD, 0x6E, 0x22, 0xFF, 0xC1, 0x55, + 0x82, 0x0B, 0x42, 0x86, 0x42, 0xA7, 0x91, 0xD3, 0x62, 0x69, + 0xB2, 0x8D, 0x11, 0xC5, 0xB8, 0x4F, 0xBF, 0x4D, 0xFE, 0x37, + 0x12, 0x1F, 0xBF, 0xDE, 0xA5, 0x86, 0xAD, 0xC7, 0x2C, 0x7F, + 0x27, 0x01, 0xB0, 0xA1, 0xED, 0x7D, 0xCE, 0x33, 0x68, 0x97, + 0x2E, 0xA4, 0xF4, 0xEE, 0xA4, 0x36, 0x67, 0xE3, 0xAB, 0x89, + 0xF8, 0xCE, 0xF7, 0x01, 0xB1, 0x83, 0xFB, 0x54, 0xAA, 0x69, + 0x05, 0x76, 0x24, 0xD9, 0x76, 0x9F, 0xA3, 0x9C, 0x52, 0x8C, + 0x2E, 0x27, 0xB9, 0xA3, 0x6E, 0xE2, 0xC0, 0x02, 0x09, 0xC6, + 0x18, 0xAD, 0x42, 0x88, 0x6B, 0x2F, 0x5D, 0xB4, 0xF7, 0xC6, + 0xB4, 0x18, 0xB7, 0x88, 0x0B, 0x81, 0x2C, 0x25, 0xCE, 0xC3, + 0x7E, 0x9E, 0xAE, 0xBB, 0x35, 0x3C, 0xEC, 0x78, 0x46, 0x8F, + 0x03, 0x16, 0x5E, 0x5B, 0x08, 0x63, 0xFB, 0xBC, 0x78, 0x75, + 0xAB, 0x07, 0x1A, 0xA7, 0x96, 0x41, 0xCD, 0xDC, 0x3B, 0x59, + 0xDB, 0x02, 0xBE, 0x42, 0x09, 0xF5, 0x87, 0x96, 0x5D, 0x63, + 0xC9, 0x8E, 0x06, 0xA2, 0xFF, 0xCE, 0xCD, 0xF3, 0xDE, 0x93, + 0x79, 0x63, 0x92, 0xD2, 0xB9, 0x1D, 0x76, 0x7E, 0x4F, 0x36, + 0x2A, 0x89, 0x7B, 0x93, 0xC1, 0x35, 0x0A, 0x83, 0x8B, 0xD6, + 0xF4, 0xEA, 0x2A, 0x72, 0xA9, 0xE7, 0x6A, 0x77, 0x43, 0x14, + 0x49, 0x5B, 0x01, 0xD9, 0xE7, 0x72, 0x15, 0xD9, 0x9C, 0xBE, + 0x87, 0x90, 0x2A, 0x7F, 0x68, 0x02, 0x1C, 0xB5, 0xA1, 0xC6, + 0x7B, 0x24, 0x49, 0xBF, 0x8E, 0x3D, 0xE0, 0xBA, 0x1C, 0x78, + 0x0A, 0x7C, 0x69, 0x82, 0xA1, 0x2F, 0xB6, 0x52, 0xC5, 0x25, + 0xD8, 0x9D, 0x4B, 0x38, 0xAA, 0xBA, 0xF7, 0x4C, 0xC4, 0xC2, + 0xAE, 0xED, 0x6C, 0x28, 0x1C, 0x76, 0xA9, 0x96, 0x08, 0xAB, + 0xC4, 0x15, 0xBC, 0x3E, 0xD7, 0xCC, 0xC4, 0xA2, 0xD4, 0x93, + 0xD1, 0x3A, 0xF4, 0x2F, 0x17, 0xDB, 0x1C, 0xBD, 0xCA, 0x0D, + 0x5C, 0xF9, 0x69, 0x32, 0xAF, 0xC5, 0x27, 0x37, 0xFC, 0x1B, + 0xBB, 0x8A, 0x5D, 0x41, 0xA9, 0xC7, 0xE7, 0xC5, 0x2E, 0x78, + 0xE3, 0x7A, 0x5A, 0x25, 0x49, 0x2A, 0x06, 0x3D, 0x15, 0x58, + 0x56, 0xFB, 0x66, 0xEC, 0x30, 0x7D, 0xF4, 0x02, 0xF3, 0x53, + 0x3D, 0x0D, 0xDD, 0xFE, 0xB5, 0x66, 0xB0, 0xD0, 0xAA, 0x0E, + 0x6A, 0x76, 0xA6, 0xAB, 0x87, 0x14, 0xFB, 0x47, 0xAC, 0x26, + 0x53, 0xA9, 0x2C, 0xF3, 0xD5, 0xA6, 0x4F, 0xF0, 0x3A, 0x7E, + 0x78, 0xC5, 0x69, 0x1F, 0xB7, 0xDC, 0xC4, 0xE8, 0xD7, 0x44, + 0x7B, 0xB2, 0xC4, 0x50, 0x68, 0xF4, 0x33, 0xFC, 0x65, 0x0D, + 0xDC, 0xCD, 0x71, 0xCB, 0x9C, 0x65, 0x3B, 0x72, 0xB7, 0x19, + 0x70, 0x45, 0xA7, 0x36, 0xA4, 0xCF, 0xE7, 0x6F, 0xC8, 0xF9, + 0x67, 0x52, 0x22, 0x8F, 0x8F, 0x64, 0x89, 0xD3, 0x3E, 0x50, + 0xCC, 0xBE, 0x2B, 0xF3, 0x0A, 0x22, 0x96, 0x33, 0x56, 0x30, + 0x27, 0x3F, 0x42, 0xDE, 0x69, 0xA3, 0x63, 0xDE, 0x41, 0x94, + 0x02, 0x97, 0x9D, 0x58, 0xF3, 0x27, 0xE3, 0xFE, 0x94, 0x10, + 0x20, 0x55, 0x52, 0xD2, 0x46, 0xFB, 0x5E, 0x8C, 0xDF, 0x71, + 0x9B, 0xBF, 0x33, 0x79, 0x7C, 0xF3, 0x78, 0xA3, 0x75, 0x84, + 0x6C, 0x13, 0xEF, 0xC0, 0x43, 0x82, 0xAC, 0xF0, 0x97, 0x7D, + 0x2A, 0xBC, 0xA3, 0xB7, 0xCD, 0x4C, 0x99, 0xB9, 0xB1, 0xE9, + 0x38, 0x5C, 0x97, 0xB3, 0xC0, 0x2C, 0xBD, 0x6F, 0xF7, 0x14, + 0x26, 0x3A, 0x27, 0x31, 0x52, 0x81, 0x04, 0x88, 0xE6, 0xD8, + 0x43, 0x21, 0x78, 0x87, 0x7C, 0x7E, 0x28, 0x26, 0x4F, 0x93, + 0x9D, 0x7B, 0x2D, 0x02, 0x6E, 0x91, 0x74, 0xD9, 0x2C, 0xF7, + 0x43, 0xD8, 0x66, 0x81, 0x91, 0x21, 0xA1, 0xEE, 0xBC, 0x78, + 0x71, 0x80, 0x78, 0x54, 0x16, 0x59, 0x37, 0xB8, 0x69, 0xD3, + 0x49, 0x40, 0xAB, 0x03, 0x47, 0x36, 0xFD, 0x5D, 0x60, 0x57, + 0x8F, 0xBE, 0xA8, 0xA0, 0x21, 0x38, 0x43, 0xA9, 0x5C, 0x9F, + 0xAD, 0xD8, 0xAE, 0x97, 0xA3, 0x0F, 0xFC, 0xE4, 0x4A, 0xCF, + 0x9F, 0xE9, 0x75, 0x3D, 0x60, 0x91, 0x55, 0x5C, 0x0A, 0xB9, + 0x18, 0xEF, 0xD4, 0x08, 0x58, 0x06, 0x64, 0xA1, 0x45, 0xA7, + 0x5D, 0x3F, 0x13, 0x87, 0x49, 0x76, 0x8B, 0x1B, 0x54, 0x9C, + 0x61, 0x05, 0xC6, 0x2C, 0xED, 0x24, 0x1B, 0x7F, 0x9E, 0x9B, + 0x17, 0xBB, 0x84, 0xD8, 0xE2, 0x55, 0x69, 0x0E, 0xCF, 0xB2, + 0xC3, 0x61, 0x35, 0x0D, 0x86, 0xD7, 0x81, 0x75, 0x43, 0x98, + 0x29, 0xDF, 0x19, 0x9C, 0xFB, 0xC0, 0xC0, 0x5A, 0x7E, 0xF7, + 0xC6, 0x86, 0xEF, 0x6E, 0xBA, 0x26, 0x1D, 0x07, 0xF9, 0xC0, + 0x1F, 0xC0, 0x8E, 0x41, 0x8F, 0x1A, 0xE3, 0x51, 0xE2, 0xD7, + 0xCA, 0x28, 0x7D, 0x7A, 0xA7, 0x57, 0xA3, 0x2D, 0x98, 0x56, + 0x32, 0x9D, 0xC0, 0xF8, 0x23, 0x1D, 0x2C, 0xF6, 0x64, 0x1E, + 0x70, 0x33, 0xD4, 0x8F, 0xF9, 0xB0, 0xF4, 0x57, 0x7F, 0xD1, + 0x9A, 0xD4, 0x1A, 0x7E, 0xB6, 0x07, 0xAA, 0x54, 0x19, 0x0D, + 0x5D, 0xB8, 0x26, 0x45, 0x1B, 0x38, 0x14, 0x20, 0xFB, 0xAA, + 0x09, 0x71, 0xAF, 0x96, 0xB1, 0x17, 0xF3, 0x45, 0xA3, 0xA6, + 0x90, 0x52, 0x3C, 0x3B, 0x43, 0x9A, 0x8D, 0xE3, 0xB1, 0xC5, + 0xE4, 0x32, 0x6C, 0xE0, 0x17, 0x98, 0x43, 0x34, 0x54, 0x10, + 0x17, 0x82, 0x27, 0xE8, 0x8F, 0x99, 0x88, 0x98, 0x26, 0x70, + 0x19, 0xD1, 0x2D, 0x23, 0x02, 0x5F, 0x44, 0x71, 0x2A, 0xF6, + 0x48, 0x83, 0x34, 0x3A, 0x37, 0x11, 0x9C, 0xA1, 0xCE, 0xF0, + 0xD7, 0x6E, 0xF7, 0x2B, 0xA3, 0xFC, 0x07, 0x40, 0x64, 0x1A, + 0xF1, 0xF6, 0xF8, 0x90, 0x21, 0x1C, 0x0E, 0x85, 0xAA, 0xC1, + 0xF7, 0x16, 0xF5, 0x4D, 0x27, 0x8E, 0x91, 0x4E, 0x84, 0x19, + 0xDB, 0x8C, 0xEA, 0x00, 0xEA, 0xA6, 0x86, 0x18, 0x2C, 0x8B, + 0x46, 0x5F, 0xED, 0x61, 0x38, 0x28, 0x31, 0x4A, 0x1A, 0x12, + 0x19, 0x6C, 0x2D, 0x43, 0x0E, 0xD0, 0xDD, 0x4B, 0xFA, 0xA0, + 0x39, 0xC2, 0x4B, 0x31, 0xD9, 0x56, 0xB4, 0x9E, 0xB5, 0xD1, + 0x79, 0xA3, 0x35, 0xC7, 0xAF, 0xFD, 0x0E, 0x11, 0xC7, 0x0F, + 0x55, 0x1D, 0xCA, 0x71, 0xD1, 0x37, 0x3B, 0xC2, 0x72, 0xA0, + 0xDB, 0xEE, 0xA0, 0xF2, 0x28, 0xF4, 0x77, 0x34, 0x7D, 0x9F, + 0xE8, 0x38, 0xD0, 0xF1, 0xEB, 0x51, 0x95, 0x93, 0x5D, 0x7B, + 0x4F, 0xE7, 0x1A, 0xD5, 0xA1, 0xF1, 0xF1, 0x85, 0xF7, 0x58, + 0x5C, 0x2C, 0x49, 0xAF, 0xDC, 0x93, 0xFE, 0x73, 0x0F, 0xC8, + 0xC8, 0x26, 0x1B, 0xDE, 0xD8, 0xA6, 0x8A, 0x44, 0xB4, 0x2B, + 0x67, 0xBD, 0x8E, 0xFF, 0xA5, 0x8C, 0x18, 0x95, 0xD3, 0x02, + 0x7F, 0x28, 0x93, 0xAE, 0x84, 0x1E, 0xB0, 0x5C, 0x70, 0x57, + 0x1C, 0xFF, 0x75, 0x95, 0xBF, 0xAD, 0x95, 0xF3, 0x3C, 0x19, + 0xA0, 0x7A, 0x0F, 0x62, 0x65, 0xF0, 0x0F, 0x18, 0x1E, 0x48, + 0xB3, 0x85, 0x5D, 0x11, 0x47, 0xC9, 0x95, 0x75, 0xBE, 0xFA, + 0x2D, 0x56, 0x35, 0xD0, 0x7A, 0x75, 0x68, 0xEA, 0x7D, 0x01, + 0x9E, 0xD5, 0x28, 0x9E, 0x80, 0x09, 0xE5, 0xE9, 0xF8, 0xD3, + 0x11, 0xA6, 0xC7, 0x5E, 0xD6, 0x38, 0x8B, 0x96, 0x7A, 0xFB, + 0xD8, 0x27, 0xD4, 0x47, 0x6B, 0x50, 0xAB, 0x21, 0x4E, 0xFB, + 0xC2, 0xA1, 0x8C, 0xB7, 0x50, 0xE2, 0xF7, 0xC3, 0x4C, 0x66, + 0x04, 0x28, 0x17, 0x5D, 0x6F, 0x48, 0x39, 0x9A, 0x0B, 0x4A, + 0xB0, 0x75, 0xDF, 0xA9, 0x6E, 0xE0, 0x72, 0x20, 0x68, 0xC5, + 0x9C, 0xDB, 0x41, 0xA4, 0xF9, 0xA4, 0xF5, 0x1D, 0xDD, 0x89, + 0x83, 0x11, 0xDD, 0x3A, 0xA4, 0x76, 0x38, 0x62, 0x75, 0x4C, + 0x5D, 0xC7, 0xF5, 0x99, 0x75, 0xFB, 0xB7, 0x87, 0xB8, 0x77, + 0x2B, 0x45, 0xEF, 0xC5, 0xE5, 0x10, 0xD9, 0x6B, 0x4C, 0x72, + 0x4B, 0x42, 0x13, 0x71, 0x3C, 0x9C, 0x2C, 0x2E, 0xFB, 0xA2, + 0x3A, 0xCD, 0x2B, 0x83, 0x12, 0xA7, 0xF3, 0xA5, 0xCE, 0x4B, + 0x77, 0x2B, 0xF5, 0x71, 0xA0, 0x1A, 0x40, 0x7F, 0xED, 0x97, + 0x4B, 0x0C, 0xA0, 0x55, 0x6B, 0x69, 0x73, 0x52, 0x47, 0x6A, + 0x20, 0xCB, 0xEE, 0xE0, 0xBE, 0x97, 0x8F, 0x05, 0xE0, 0x84, + 0x4A, 0x6E, 0x40, 0xCC, 0x02, 0x2C, 0xA8, 0x45, 0xD4, 0x6B, + 0xD4, 0xCD, 0x41, 0x29, 0xBE, 0x99, 0x3B, 0x51, 0x0F, 0x9C, + 0x70, 0x75, 0x83, 0x3D, 0x42, 0xCF, 0xA9, 0x02, 0xF3, 0x68, + 0x3C, 0x96, 0xE1, 0x36, 0x46, 0xB7, 0x86, 0x16, 0x03, 0x2C, + 0xBB, 0x71, 0x21, 0xBF, 0x13, 0x52, 0x03, 0x42, 0x31, 0xE3, + 0xA3, 0x26, 0xEE, 0xD7, 0x86, 0x78, 0xDA, 0x9E, 0x9A, 0x50, + 0xD1, 0x9C, 0x5B, 0xB7, 0xEB, 0xCF, 0x0A, 0x6D, 0x10, 0xA0, + 0xAB, 0x8C, 0x65, 0x4B, 0xFA, 0x9E, 0xAC, 0x0B, 0x66, 0x56, + 0xC7, 0x5D, 0x85, 0x88, 0x53, 0x1B, 0xC2, 0x37, 0xCC, 0x94, + 0x2E, 0xE1, 0xB1, 0xF7, 0xCC, 0x1F, 0x59, 0x24, 0xEC, 0x1A, + 0x27, 0xFA, 0x8D, 0xE5, 0x86, 0x9E, 0x3F, 0x21, 0xDA, 0x15, + 0xAE, 0xC7, 0x6C, 0xFB, 0x17, 0x0D, 0xF5, 0xCB, 0xE3, 0xB8, + 0x36, 0x95, 0x0F, 0xBD, 0x84, 0x19, 0x1D, 0xF5, 0x4F, 0x17, + 0xB8, 0x71, 0x9C, 0x0E, 0x3D, 0xD8, 0xFD, 0x9B, 0xD4, 0x0D, + 0x2D, 0x16, 0x5D, 0x75, 0xE7, 0x25, 0x94, 0x3D, 0xD3, 0x0C, + 0x07, 0x3D, 0x04, 0x46, 0xC8, 0x8F, 0x65, 0x06, 0xC7, 0x11, + 0xB2, 0xAB, 0x41, 0x5E, 0x96, 0x0C, 0x68, 0x76, 0x7D, 0x6D, + 0xB8, 0xB5, 0x27, 0x01, 0x2C, 0x00, 0xC2, 0xA0, 0x40, 0xB8, + 0xF7, 0xC6, 0x39, 0x56, 0xCF, 0x25, 0x56, 0xB3, 0x10, 0x04, + 0xE9, 0xC3, 0x85, 0x47, 0xE8, 0x6E, 0xC7, 0x89, 0xFE, 0x80, + 0x9A, 0x50, 0x9E, 0xBD, 0xF3, 0x2E, 0x5E, 0x96, 0x0A, 0xA8, + 0xB7, 0x6C, 0x5B, 0x9E, 0x32, 0x1E, 0x75, 0x68, 0x5E, 0x74, + 0x88, 0xFC, 0xC5, 0x3D, 0xB9, 0x21, 0x0A, 0xAD, 0x6D, 0xF6, + 0xBE, 0x2D, 0x9A, 0x8A, 0xA5, 0x2A, 0x40, 0x3C, 0xF6, 0x4C, + 0xFE, 0x18, 0xE3, 0x44, 0x7A, 0x5F, 0x31, 0x1A, 0xEE, 0x95, + 0x07, 0x96, 0xC1, 0x27, 0x7F, 0x64, 0x4E, 0xF0, 0x19, 0x2D, + 0x36, 0x33, 0x5D, 0x23, 0xC9, 0xC2, 0x36, 0x91, 0x22, 0xC9, + 0x58, 0x8C, 0xE4, 0xF1, 0x19, 0xD0, 0xBF, 0x51, 0xAA, 0x14, + 0x4C, 0x15, 0x4A, 0x93, 0xF3, 0x16, 0x6A, 0x21, 0xBE, 0xDE, + 0xA5, 0x4C, 0x84, 0xC5, 0x65, 0x06, 0xA7, 0x11, 0xDC, 0x00, + 0x5F, 0x0F, 0xF1, 0xDA, 0xA2, 0x11, 0xAB, 0x64, 0xE0, 0x1F, + 0x1A, 0x65, 0x32, 0xA7, 0x69, 0x65, 0xAF, 0x64, 0x95, 0x90, + 0xF1, 0xA5, 0xFA, 0x32, 0x4C, 0x59, 0x61, 0x87, 0x3D, 0x94, + 0x82, 0x7E, 0xE4, 0x04, 0x7B, 0x8A, 0xCD, 0x54, 0x00, 0x2A, + 0xC5, 0xC3, 0xB7, 0x2F, 0x8A, 0xA8, 0x19, 0x39, 0x93, 0x53, + 0x3E, 0xEB, 0xE7, 0x8F, 0xF7, 0xCF, 0xDA, 0x8A, 0x4E, 0xAB, + 0x91, 0x3D, 0xA3, 0x40, 0x55, 0x64, 0xE7, 0x48, 0x90, 0x03, + 0xE5, 0xE6, 0x03, 0xE8, 0x2A, 0x23, 0x78, 0x6F, 0xCA, 0xDE, + 0x7C, 0x6E, 0x56, 0x5B, 0xC8, 0x6D, 0x8C, 0x2F, 0xC8, 0x6C, + 0x7D, 0xD8, 0x60, 0x43, 0x8C, 0xF3, 0xE9, 0x9E, 0x70, 0x73, + 0xAC, 0x85, 0xB4, 0xA3, 0x29, 0x86, 0x88, 0x60, 0x6D, 0xDD, + 0x21, 0x07, 0x09, 0x8B, 0xFB, 0xA1, 0x67, 0xA5, 0xDA, 0x9D, + 0xCC, 0x2E, 0xE3, 0xBE, 0xAE, 0x06, 0x0E, 0x41, 0x4E, 0xBE, + 0x5F, 0xE4, 0x93, 0x81, 0xE8, 0x06, 0xAA, 0x2C, 0xC9, 0x1B, + 0x1C, 0x5A, 0x9E, 0x01, 0xEF, 0xFF, 0x82, 0x84, 0xD9, 0x2B, + 0x05, 0x20, 0x0D, 0xE1, 0x14, 0x6C, 0x0A, 0x85, 0x16, 0x2E, + 0x79, 0xA3, 0x64, 0xBF, 0xFC, 0x89, 0xB8, 0xFD, 0xB0, 0xC8, + 0x39, 0x9A, 0x83, 0x1B, 0x74, 0x41, 0x7C, 0xEA, 0xFD, 0x5F, + 0x83, 0x19 +}; +static const int sizeof_bench_dilithium_level3_key = sizeof(bench_dilithium_level3_key); + +/* certs/dilithium/bench_dilithium_level5_key.der */ +static const unsigned char bench_dilithium_level5_key[] = +{ + 0x30, 0x82, 0x1D, 0x3A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, + 0x08, 0x07, 0x04, 0x82, 0x1D, 0x24, 0x04, 0x82, 0x1D, 0x20, + 0x0A, 0xDB, 0x85, 0x3A, 0x41, 0x2C, 0x30, 0x56, 0x65, 0x04, + 0x0A, 0x20, 0x31, 0x2A, 0xF3, 0x88, 0x4C, 0x38, 0x64, 0x86, + 0x14, 0x06, 0xF5, 0xF0, 0x7F, 0x63, 0xC1, 0x87, 0x24, 0x39, + 0xFB, 0xC0, 0x28, 0x0C, 0xBE, 0x81, 0xF7, 0xCD, 0x25, 0x8B, + 0x86, 0x42, 0xAD, 0x74, 0x54, 0xCB, 0xA4, 0xDA, 0xC7, 0x94, + 0x70, 0xA3, 0x41, 0xDA, 0x1F, 0xD8, 0x4F, 0x94, 0x5C, 0x0B, + 0xA5, 0x35, 0x60, 0xB2, 0x8C, 0x50, 0xED, 0x0B, 0xCB, 0x75, + 0x6F, 0x14, 0x64, 0x48, 0x86, 0x21, 0xBC, 0x4A, 0x4C, 0xC5, + 0x22, 0xBC, 0x2D, 0x28, 0x32, 0x39, 0x13, 0x57, 0xC9, 0xE5, + 0x74, 0xF4, 0xE6, 0x3A, 0xC2, 0xE2, 0x49, 0x24, 0x31, 0x88, + 0x82, 0x08, 0x03, 0x89, 0x6C, 0x8B, 0x84, 0x08, 0x81, 0xC2, + 0x08, 0xDB, 0x44, 0x60, 0xA0, 0xB2, 0x91, 0x88, 0x36, 0x28, + 0x12, 0x89, 0x89, 0x4B, 0xA4, 0x01, 0x62, 0x12, 0x4C, 0x08, + 0x02, 0x44, 0x19, 0x15, 0x64, 0x8B, 0x04, 0x65, 0xE4, 0x14, + 0x06, 0x08, 0xC7, 0x04, 0x5B, 0x28, 0x81, 0x89, 0xC2, 0x70, + 0xD0, 0xB4, 0x71, 0x4C, 0x24, 0x80, 0xA1, 0x28, 0x86, 0xD1, + 0x06, 0x25, 0x13, 0x03, 0x84, 0x8C, 0x18, 0x41, 0x49, 0x34, + 0x09, 0xCB, 0x22, 0x71, 0x0C, 0xA3, 0x90, 0x22, 0x94, 0x51, + 0x58, 0x02, 0x2D, 0x53, 0x30, 0x00, 0xC2, 0x06, 0x42, 0x48, + 0xC4, 0x70, 0x8A, 0x32, 0x89, 0x80, 0x16, 0x06, 0x90, 0x44, + 0x91, 0xCB, 0xC8, 0x71, 0xA2, 0xB6, 0x64, 0xD0, 0x26, 0x0A, + 0x21, 0x05, 0x88, 0x0C, 0xB0, 0x6C, 0x03, 0x49, 0x24, 0x80, + 0x02, 0x11, 0xD1, 0x36, 0x06, 0x84, 0x32, 0x11, 0x81, 0x44, + 0x91, 0x9B, 0xB0, 0x01, 0x91, 0x02, 0x25, 0x44, 0x92, 0x69, + 0x5A, 0x08, 0x6C, 0x90, 0x00, 0x0D, 0x09, 0x17, 0x64, 0x89, + 0xB2, 0x2D, 0x02, 0x06, 0x2C, 0xDC, 0x92, 0x45, 0xE1, 0x34, + 0x31, 0x11, 0x03, 0x2D, 0x00, 0x94, 0x29, 0xCA, 0x34, 0x89, + 0xA3, 0x40, 0x22, 0xC4, 0x30, 0x08, 0x02, 0x33, 0x6E, 0x1C, + 0x85, 0x10, 0xE4, 0x92, 0x30, 0xC4, 0x46, 0x84, 0xE0, 0x26, + 0x28, 0xC3, 0x10, 0x65, 0x51, 0x06, 0x4A, 0x03, 0xC1, 0x11, + 0x48, 0x32, 0x4E, 0x9A, 0xC4, 0x6C, 0x91, 0x38, 0x40, 0xC0, + 0x92, 0x64, 0xE3, 0xA4, 0x85, 0x22, 0x32, 0x52, 0x92, 0x08, + 0x20, 0x82, 0x22, 0x12, 0x49, 0x20, 0x6C, 0x91, 0x06, 0x01, + 0x1B, 0x30, 0x06, 0x12, 0xC3, 0x41, 0x4B, 0x40, 0x42, 0x0B, + 0xA7, 0x01, 0x60, 0x12, 0x89, 0x24, 0x98, 0x30, 0x99, 0xA6, + 0x64, 0x61, 0x26, 0x6A, 0x91, 0xB0, 0x11, 0x03, 0xC2, 0x2D, + 0x41, 0xC8, 0x6D, 0xD8, 0x38, 0x28, 0x4B, 0x98, 0x04, 0x98, + 0x18, 0x09, 0x18, 0xA6, 0x65, 0x81, 0x38, 0x69, 0x5B, 0xC4, + 0x6D, 0x98, 0x26, 0x0D, 0x62, 0xC6, 0x71, 0xC3, 0xC6, 0x4C, + 0xC2, 0x02, 0x46, 0x5B, 0x94, 0x65, 0x09, 0x29, 0x0E, 0xA2, + 0xA2, 0x41, 0xE4, 0x02, 0x69, 0xA3, 0x90, 0x4D, 0x8B, 0xA6, + 0x70, 0xA3, 0x40, 0x85, 0x5C, 0x36, 0x48, 0x22, 0xC5, 0x84, + 0x19, 0x91, 0x25, 0x00, 0xC2, 0x65, 0xC4, 0x46, 0x2E, 0xDC, + 0xB0, 0x51, 0x94, 0x28, 0x01, 0x9B, 0x22, 0x66, 0x01, 0xA8, + 0x90, 0x9A, 0xC4, 0x08, 0xD1, 0x22, 0x41, 0x42, 0x34, 0x62, + 0x60, 0x40, 0x92, 0x93, 0xC8, 0x45, 0xD8, 0x04, 0x20, 0x8A, + 0x30, 0x25, 0xE1, 0x14, 0x40, 0x11, 0x13, 0x00, 0x54, 0x22, + 0x62, 0x50, 0x10, 0x22, 0x03, 0xA9, 0x85, 0x9B, 0x42, 0x4D, + 0x50, 0xB2, 0x41, 0x10, 0x13, 0x48, 0x63, 0x38, 0x68, 0xA1, + 0xB0, 0x0D, 0x1B, 0x88, 0x84, 0x8A, 0x28, 0x51, 0xD4, 0x38, + 0x2A, 0x12, 0x43, 0x61, 0x80, 0x38, 0x32, 0x18, 0xC6, 0x29, + 0x22, 0xB5, 0x21, 0x02, 0x99, 0x28, 0xCC, 0x18, 0x85, 0x83, + 0xB4, 0x8C, 0x81, 0x24, 0x51, 0x10, 0x83, 0x68, 0x1C, 0x47, + 0x71, 0x8C, 0x40, 0x6C, 0x00, 0xB6, 0x0D, 0x88, 0x22, 0x90, + 0x0C, 0xC7, 0x49, 0xC0, 0x82, 0x89, 0xDA, 0x22, 0x4A, 0xC8, + 0x18, 0x08, 0xD1, 0x00, 0x2C, 0xDA, 0x30, 0x49, 0x49, 0xC8, + 0x91, 0x5A, 0x96, 0x64, 0x11, 0x96, 0x20, 0xD2, 0xC4, 0x60, + 0xE0, 0x46, 0x6A, 0x02, 0xB5, 0x21, 0x19, 0xB9, 0x81, 0x23, + 0x00, 0x22, 0x11, 0x37, 0x32, 0x19, 0xA4, 0x0D, 0x51, 0x96, + 0x89, 0x1B, 0x11, 0x11, 0xC3, 0x14, 0x88, 0x4C, 0x96, 0x0C, + 0x01, 0x13, 0x72, 0x83, 0x16, 0x12, 0x24, 0x38, 0x51, 0x40, + 0x34, 0x89, 0xD9, 0x26, 0x01, 0x54, 0x42, 0x8D, 0x00, 0xC1, + 0x85, 0x13, 0x14, 0x84, 0x82, 0x16, 0x25, 0x88, 0xB0, 0x51, + 0x11, 0x80, 0x30, 0x23, 0x25, 0x46, 0x04, 0x27, 0x66, 0x11, + 0x28, 0x30, 0xD4, 0x94, 0x84, 0x10, 0xA0, 0x8C, 0xC1, 0x36, + 0x0C, 0x14, 0x98, 0x28, 0x5B, 0x02, 0x90, 0xD9, 0x90, 0x31, + 0xD3, 0x28, 0x68, 0x23, 0x90, 0x80, 0x24, 0xC7, 0x84, 0xA1, + 0x00, 0x09, 0xC1, 0x36, 0x84, 0x58, 0xB6, 0x28, 0x4A, 0xB0, + 0x69, 0x08, 0x10, 0x51, 0x1C, 0xB6, 0x84, 0x83, 0x84, 0x81, + 0x03, 0x39, 0x90, 0x81, 0x42, 0x12, 0x13, 0xB4, 0x49, 0x0A, + 0x20, 0x09, 0x93, 0x22, 0x42, 0xD4, 0x26, 0x21, 0xA3, 0x32, + 0x89, 0x89, 0x84, 0x81, 0x0B, 0x02, 0x21, 0x64, 0x28, 0x90, + 0x89, 0xB2, 0x29, 0xE1, 0x36, 0x2C, 0x11, 0x30, 0x51, 0x21, + 0x83, 0x2C, 0x04, 0x36, 0x26, 0x61, 0x12, 0x8C, 0x19, 0x43, + 0x52, 0x89, 0x90, 0x88, 0x43, 0xB8, 0x71, 0x0C, 0x43, 0x09, + 0x84, 0x26, 0x6A, 0x50, 0x36, 0x20, 0x00, 0xC3, 0x68, 0x91, + 0x38, 0x0E, 0x12, 0x12, 0x52, 0x82, 0xC4, 0x4D, 0x64, 0x90, + 0x4D, 0x8C, 0x30, 0x22, 0x14, 0x26, 0x6E, 0x10, 0x46, 0x8E, + 0x58, 0x34, 0x46, 0x22, 0x97, 0x68, 0x02, 0x43, 0x61, 0x41, + 0x06, 0x01, 0x88, 0x42, 0x40, 0x08, 0x06, 0x6D, 0x80, 0x42, + 0x22, 0x84, 0x48, 0x89, 0xDB, 0x84, 0x90, 0xC0, 0x22, 0x71, + 0x43, 0x96, 0x45, 0x0A, 0xA3, 0x30, 0x12, 0x28, 0x44, 0x51, + 0x00, 0x52, 0x99, 0xA0, 0x8D, 0xC2, 0x28, 0x00, 0xC8, 0x18, + 0x6E, 0xA2, 0x40, 0x8E, 0x03, 0x47, 0x31, 0x61, 0x22, 0x41, + 0xD3, 0xB4, 0x01, 0x48, 0x14, 0x40, 0x4C, 0x06, 0x0C, 0x41, + 0x06, 0x2A, 0x5B, 0x90, 0x25, 0xCC, 0xC6, 0x41, 0xC3, 0x86, + 0x28, 0x99, 0x26, 0x50, 0x11, 0xC4, 0x8D, 0x8C, 0x30, 0x68, + 0x8C, 0x08, 0x0C, 0x50, 0x38, 0x86, 0xDC, 0x10, 0x92, 0xD4, + 0x18, 0x72, 0x02, 0xA8, 0x2C, 0x42, 0x82, 0x44, 0x53, 0x36, + 0x0E, 0x90, 0x32, 0x49, 0x84, 0x24, 0x09, 0x12, 0xA2, 0x41, + 0x82, 0x10, 0x4D, 0x01, 0xA0, 0x8C, 0x11, 0xB2, 0x80, 0x21, + 0x89, 0x69, 0x24, 0x21, 0x28, 0x02, 0x03, 0x6E, 0x49, 0x32, + 0x0C, 0x08, 0x88, 0x84, 0x91, 0x80, 0x10, 0x0C, 0x33, 0x12, + 0x43, 0x24, 0x8A, 0x82, 0x26, 0x10, 0x60, 0xC6, 0x60, 0x48, + 0xA2, 0x10, 0x12, 0x83, 0x24, 0x0B, 0x03, 0x40, 0xCA, 0x08, + 0x20, 0x99, 0x36, 0x86, 0x5B, 0x24, 0x41, 0x10, 0x87, 0x04, + 0x0C, 0x15, 0x04, 0x14, 0xB2, 0x68, 0x0B, 0x89, 0x29, 0x99, + 0x16, 0x8D, 0x00, 0x42, 0x00, 0x9B, 0x48, 0x44, 0x12, 0x45, + 0x6C, 0x0A, 0x25, 0x92, 0xC0, 0xC4, 0x00, 0x1A, 0xC8, 0x31, + 0x21, 0x26, 0x8A, 0x81, 0xA0, 0x2C, 0x11, 0x85, 0x65, 0x9A, + 0x08, 0x61, 0xD9, 0x22, 0x12, 0xCB, 0x36, 0x71, 0xA2, 0x08, + 0x0A, 0xE4, 0x06, 0x32, 0x19, 0x19, 0x4A, 0x1B, 0x34, 0x45, + 0x51, 0x06, 0x6E, 0x48, 0x02, 0x68, 0x13, 0xB7, 0x10, 0x44, + 0xC8, 0x85, 0x13, 0x81, 0x2C, 0xC4, 0x40, 0x45, 0x42, 0x98, + 0x21, 0x62, 0x18, 0x92, 0x9B, 0x44, 0x25, 0xA1, 0x06, 0x28, + 0x52, 0x82, 0x11, 0x44, 0x24, 0x32, 0x02, 0xC6, 0x80, 0x10, + 0x45, 0x4E, 0x22, 0x93, 0x0D, 0x44, 0x02, 0x68, 0x4A, 0x30, + 0x81, 0xC9, 0x94, 0x85, 0x08, 0x07, 0x08, 0x24, 0x39, 0x64, + 0xD2, 0x08, 0x22, 0xD0, 0xA0, 0x41, 0x81, 0x92, 0x91, 0x8C, + 0x24, 0x6A, 0xCA, 0x36, 0x32, 0x1C, 0x12, 0x45, 0x92, 0x94, + 0x80, 0x82, 0x86, 0x4C, 0xDA, 0xA2, 0x84, 0x98, 0x24, 0x49, + 0x0A, 0x13, 0x90, 0x1B, 0xC3, 0x01, 0x49, 0x28, 0x60, 0x08, + 0x21, 0x92, 0x0B, 0xB0, 0x20, 0x52, 0x90, 0x84, 0x8A, 0x32, + 0x11, 0x50, 0x28, 0x8C, 0x5B, 0x38, 0x2E, 0xDC, 0xB4, 0x08, + 0x12, 0x20, 0x84, 0xD1, 0x12, 0x22, 0x99, 0x08, 0x11, 0x19, + 0x95, 0x10, 0x80, 0x44, 0x6A, 0xE1, 0x12, 0x85, 0xCC, 0xB0, + 0x24, 0x23, 0x15, 0x4C, 0x63, 0x34, 0x68, 0x5C, 0xB6, 0x65, + 0x42, 0xC2, 0x4D, 0x20, 0x95, 0x84, 0x8A, 0x42, 0x00, 0x4C, + 0x24, 0x50, 0x98, 0x02, 0x6C, 0x21, 0x44, 0x84, 0x20, 0x85, + 0x21, 0x80, 0x48, 0x6C, 0x9C, 0x14, 0x86, 0x81, 0x86, 0x91, + 0x1C, 0x09, 0x04, 0xDC, 0xC6, 0x28, 0x09, 0x27, 0x30, 0x4B, + 0x02, 0x64, 0x44, 0x46, 0x30, 0x9C, 0xA2, 0x8C, 0x20, 0x11, + 0x68, 0x11, 0x24, 0x51, 0x0B, 0x02, 0x00, 0xD2, 0x82, 0x4D, + 0xC3, 0x80, 0x71, 0xE0, 0x48, 0x2C, 0x4A, 0x88, 0x50, 0xA0, + 0x20, 0x49, 0x4B, 0xB4, 0x31, 0x08, 0x12, 0x71, 0x90, 0xA2, + 0x89, 0xCA, 0x46, 0x85, 0x91, 0x96, 0x91, 0x8A, 0x30, 0x31, + 0x0B, 0xC2, 0x21, 0x61, 0x10, 0x49, 0x10, 0x99, 0x81, 0x53, + 0x36, 0x0C, 0x23, 0x81, 0x88, 0x62, 0x28, 0x0A, 0x12, 0x43, + 0x70, 0x02, 0xC7, 0x51, 0x14, 0x34, 0x88, 0x23, 0x84, 0x49, + 0x23, 0x86, 0x08, 0x0C, 0x28, 0x28, 0x94, 0xA0, 0x8D, 0x11, + 0x33, 0x60, 0xA3, 0x38, 0x6E, 0xC0, 0x42, 0x2E, 0x52, 0xB4, + 0x40, 0x0A, 0x25, 0x4D, 0x1C, 0x10, 0x2A, 0x9A, 0x96, 0x64, + 0x10, 0xC1, 0x60, 0x8C, 0x46, 0x60, 0x5A, 0x24, 0x89, 0x42, + 0x40, 0x86, 0xD0, 0x34, 0x89, 0x5C, 0x02, 0x02, 0x00, 0x34, + 0x21, 0x00, 0x24, 0x00, 0xA0, 0x20, 0x60, 0x03, 0xA6, 0x40, + 0xDC, 0x30, 0x80, 0x4B, 0xA8, 0x20, 0x0B, 0xA2, 0x24, 0xE2, + 0xB0, 0x89, 0xA2, 0xB2, 0x65, 0xD4, 0xA6, 0x68, 0x20, 0xA3, + 0x04, 0x4C, 0xC2, 0x11, 0x4A, 0x38, 0x24, 0x08, 0x17, 0x4D, + 0xE2, 0xA2, 0x00, 0x02, 0xC8, 0x00, 0x08, 0x00, 0x30, 0xA4, + 0xB6, 0x25, 0x5A, 0x30, 0x01, 0x40, 0x92, 0x4C, 0xC8, 0x44, + 0x92, 0x43, 0xC8, 0x60, 0xA3, 0x86, 0x84, 0x18, 0x04, 0x70, + 0x53, 0xB2, 0x40, 0x4C, 0x04, 0x84, 0x09, 0xC8, 0x48, 0x21, + 0x13, 0x31, 0x04, 0xA5, 0x0D, 0x90, 0x92, 0x88, 0xC1, 0x10, + 0x8D, 0xE0, 0x88, 0x28, 0x0B, 0x06, 0x84, 0x23, 0x22, 0x6C, + 0xDB, 0xB2, 0x05, 0xC8, 0x08, 0x6E, 0x93, 0x86, 0x4C, 0x0C, + 0x37, 0x86, 0xDA, 0x16, 0x51, 0x9B, 0x08, 0x32, 0x00, 0x91, + 0x45, 0xA4, 0x00, 0x2D, 0x14, 0x02, 0x0E, 0x60, 0x90, 0x4C, + 0x23, 0xB4, 0x09, 0x00, 0xA5, 0x81, 0x19, 0x21, 0x32, 0xC2, + 0x00, 0x02, 0x18, 0x10, 0x50, 0x08, 0xA2, 0x6D, 0x20, 0x31, + 0x6A, 0x90, 0x46, 0x90, 0x8B, 0x94, 0x30, 0x21, 0x44, 0x52, + 0x10, 0x19, 0x51, 0x94, 0xC0, 0x29, 0xC8, 0x20, 0x4E, 0x48, + 0xA6, 0x4C, 0x11, 0xC4, 0x64, 0xDC, 0x34, 0x10, 0x48, 0xC4, + 0x84, 0xCA, 0x46, 0x0C, 0x58, 0x12, 0x49, 0x0B, 0x16, 0x00, + 0x20, 0x42, 0x50, 0x04, 0x00, 0x46, 0xF8, 0x68, 0xB1, 0xA7, + 0x5E, 0xA7, 0xE6, 0xCE, 0xF5, 0x88, 0x8A, 0x5F, 0x79, 0xC9, + 0x3A, 0x5F, 0xF2, 0x7F, 0x5A, 0xED, 0xB4, 0xB4, 0x25, 0x44, + 0xD2, 0x7E, 0xED, 0xCE, 0x46, 0x40, 0xAC, 0xC2, 0x53, 0xD0, + 0xD3, 0xE7, 0xF6, 0x1C, 0xFA, 0x23, 0x4A, 0xB0, 0xEA, 0x32, + 0x91, 0xB7, 0xDA, 0x8B, 0x72, 0x35, 0xB7, 0x74, 0xD5, 0x9A, + 0x9B, 0x22, 0x3D, 0x49, 0x08, 0xBA, 0xD1, 0x7D, 0x9F, 0x64, + 0xD5, 0xAD, 0x7A, 0x37, 0xBD, 0x11, 0xD0, 0xA0, 0x7C, 0x53, + 0x05, 0x1A, 0x66, 0x6C, 0x5D, 0x42, 0x45, 0x55, 0x34, 0xC0, + 0x1F, 0xCA, 0xDB, 0x0D, 0x4F, 0x75, 0x95, 0x9F, 0x10, 0x9A, + 0x8D, 0x54, 0xCE, 0xC2, 0x5C, 0xF0, 0xCE, 0xBD, 0x39, 0x70, + 0xB0, 0x52, 0x2E, 0x4B, 0x11, 0x0D, 0x25, 0xD7, 0xE5, 0x4B, + 0xF1, 0xE3, 0x4F, 0xBE, 0xF2, 0x73, 0xA6, 0xDE, 0xB6, 0xC4, + 0x61, 0x71, 0xCC, 0x5C, 0xFE, 0x55, 0xF0, 0x50, 0xBA, 0x9C, + 0x18, 0x44, 0x13, 0xDD, 0xCB, 0x7A, 0xD2, 0xA2, 0xDC, 0xBF, + 0xF2, 0xC8, 0x84, 0xFF, 0x5B, 0xA7, 0xFA, 0x8D, 0x18, 0xF2, + 0x55, 0xD0, 0x3C, 0x4E, 0xB3, 0x77, 0x7C, 0x95, 0x91, 0x98, + 0x52, 0xF2, 0xB6, 0xCF, 0xFC, 0x45, 0xF4, 0x71, 0x62, 0x24, + 0xE2, 0x7B, 0xF7, 0x85, 0x08, 0x17, 0x6A, 0x62, 0xB4, 0xE9, + 0x08, 0x3E, 0xA1, 0xC6, 0x27, 0x8E, 0xB3, 0x26, 0xA5, 0x95, + 0x91, 0x84, 0xD0, 0xA0, 0xCD, 0xBF, 0x45, 0xD0, 0xE2, 0x26, + 0x65, 0x74, 0xD6, 0x49, 0x50, 0xF2, 0x6B, 0xAE, 0xF1, 0x8A, + 0x2A, 0x18, 0xDA, 0xF0, 0xAD, 0xE7, 0xF3, 0x0A, 0x0E, 0x33, + 0xA5, 0xCA, 0x11, 0x16, 0xCC, 0xD6, 0x81, 0x89, 0x83, 0x27, + 0x32, 0x97, 0x61, 0x48, 0x0D, 0x89, 0x3E, 0xB7, 0x7E, 0x02, + 0xC8, 0x96, 0x93, 0xFA, 0xD0, 0x1D, 0x76, 0xB4, 0xA4, 0x38, + 0x4C, 0xE3, 0xB4, 0x6F, 0xCE, 0x66, 0x90, 0x53, 0xDC, 0xCE, + 0xD6, 0x10, 0x16, 0x3E, 0xB8, 0xBD, 0xD9, 0x8C, 0xA9, 0x90, + 0x54, 0xAF, 0x86, 0x07, 0xB3, 0xC1, 0x82, 0xFB, 0x41, 0x61, + 0xB8, 0x6D, 0x8E, 0xA5, 0xA8, 0xEB, 0xE3, 0xC0, 0xCF, 0x51, + 0xAA, 0x94, 0x7A, 0x7F, 0x9C, 0x48, 0xA3, 0x40, 0x83, 0x33, + 0x22, 0x41, 0x61, 0x4C, 0xD4, 0x62, 0xD7, 0xC6, 0xC6, 0x5B, + 0xF3, 0x48, 0x42, 0xA7, 0x18, 0xD5, 0xAF, 0x05, 0xF6, 0x7A, + 0xF6, 0x6D, 0x82, 0xFF, 0x89, 0x68, 0x21, 0x13, 0x62, 0xA5, + 0x7E, 0xC9, 0x43, 0x03, 0x73, 0xF7, 0xD1, 0x01, 0x7D, 0xD9, + 0x13, 0x03, 0x9C, 0x99, 0x74, 0xD4, 0x92, 0x2E, 0xD1, 0xD3, + 0xCB, 0x53, 0x6C, 0xF9, 0xFE, 0xB4, 0x3D, 0x51, 0xF1, 0x63, + 0x42, 0x5B, 0xB2, 0x5D, 0x70, 0x03, 0xE5, 0x46, 0x5B, 0xC1, + 0xEB, 0x27, 0x11, 0x22, 0x15, 0x73, 0x6C, 0xF8, 0x51, 0x0A, + 0xFF, 0xD8, 0xFE, 0xB6, 0xE1, 0xBD, 0x42, 0xC0, 0x4C, 0xEB, + 0xCD, 0x1E, 0x3C, 0xD5, 0x7C, 0xEA, 0xC6, 0xD4, 0x34, 0xD2, + 0x8D, 0x99, 0xC4, 0x99, 0xA8, 0x8E, 0x9F, 0x60, 0xA8, 0xE8, + 0x7B, 0x1E, 0x7E, 0x50, 0x14, 0xAD, 0xFC, 0xDB, 0xA6, 0x00, + 0xE9, 0x00, 0x7A, 0x5A, 0xCD, 0x01, 0x26, 0xBB, 0x4E, 0x00, + 0x9E, 0xCC, 0xD3, 0x2D, 0x49, 0x1B, 0xB8, 0x60, 0x2C, 0x59, + 0x2A, 0x95, 0x8C, 0x92, 0x4D, 0x1A, 0x57, 0x3B, 0xEF, 0x6E, + 0xC4, 0x91, 0xE4, 0x99, 0x5E, 0xAE, 0x1B, 0xAF, 0x1E, 0x14, + 0x51, 0x38, 0x19, 0xBC, 0x33, 0x5C, 0x21, 0x4D, 0xAD, 0xA1, + 0x12, 0x17, 0xE6, 0xF5, 0x37, 0x98, 0xF6, 0xE6, 0x38, 0x4D, + 0x07, 0x80, 0x1D, 0xD8, 0x5E, 0xCC, 0x58, 0xDB, 0x7E, 0x3A, + 0x8F, 0x90, 0xDF, 0x9E, 0x80, 0xFB, 0xFC, 0x10, 0xEC, 0x7E, + 0x81, 0x53, 0x37, 0xC1, 0x66, 0xEE, 0xD7, 0x80, 0x0F, 0x0C, + 0xEB, 0xE8, 0x85, 0x2E, 0x37, 0x61, 0x8B, 0x9C, 0x63, 0xF6, + 0x27, 0x77, 0x16, 0x44, 0x61, 0x66, 0xC9, 0x79, 0x31, 0xDD, + 0xB4, 0x94, 0x9D, 0x8C, 0x8B, 0x1D, 0x28, 0xC2, 0x84, 0xC9, + 0x30, 0x71, 0xF4, 0x9E, 0xEF, 0x00, 0x2B, 0xA2, 0x9F, 0x38, + 0x65, 0xE6, 0xD1, 0x80, 0x26, 0x9B, 0xC4, 0xE8, 0x83, 0xCE, + 0x64, 0xD0, 0x8A, 0x9A, 0x1E, 0xEF, 0xA3, 0xB6, 0xD2, 0x0B, + 0x9C, 0x14, 0xF3, 0x08, 0xF1, 0x73, 0xD1, 0x34, 0xAE, 0x83, + 0xE7, 0x97, 0x5B, 0x97, 0x35, 0x0E, 0x35, 0xDC, 0x22, 0xD5, + 0xAA, 0xD1, 0xBC, 0xC7, 0x40, 0x20, 0xAD, 0x43, 0x36, 0x24, + 0x66, 0x7A, 0xB7, 0x1F, 0xF9, 0x1A, 0x1F, 0x37, 0xCE, 0xC2, + 0xFC, 0x98, 0xB1, 0x6A, 0x9A, 0x81, 0xD9, 0x4B, 0x53, 0x68, + 0xC5, 0xF3, 0xE6, 0x69, 0x76, 0xA6, 0x8B, 0x98, 0xFB, 0x84, + 0x2E, 0xD3, 0x4F, 0x77, 0xF9, 0x24, 0xF9, 0x13, 0x89, 0x8D, + 0xF6, 0x80, 0x2E, 0x0E, 0xA1, 0xCD, 0x90, 0x58, 0xCE, 0x63, + 0x36, 0x95, 0x8C, 0xF6, 0x68, 0xC3, 0x84, 0xF8, 0xB4, 0x5E, + 0x9E, 0x6C, 0x19, 0x32, 0x90, 0xA7, 0xD0, 0x2D, 0x47, 0x6B, + 0xCB, 0xAF, 0x85, 0x65, 0x92, 0x83, 0x11, 0x8E, 0xCC, 0x88, + 0xB1, 0x0B, 0xB8, 0x1E, 0x55, 0x4F, 0x18, 0x2A, 0xC4, 0x02, + 0xA8, 0x45, 0x6A, 0xCD, 0x75, 0x58, 0x6A, 0xAF, 0x83, 0x94, + 0x38, 0x1D, 0xA9, 0x09, 0x29, 0x1E, 0x0E, 0x43, 0xA9, 0x04, + 0x26, 0xF6, 0x1C, 0xC7, 0xCB, 0xC1, 0x10, 0xB9, 0x86, 0xC1, + 0xA2, 0xEC, 0x03, 0xDE, 0xF7, 0x53, 0x67, 0x2B, 0xDF, 0xEE, + 0xAF, 0xD2, 0xF2, 0xA8, 0xBD, 0xD9, 0x21, 0xCC, 0x8C, 0x72, + 0x02, 0x44, 0xF5, 0xA5, 0xED, 0x88, 0x5B, 0xAC, 0x5F, 0x5A, + 0x15, 0x81, 0xCC, 0x95, 0x15, 0x2E, 0x34, 0x72, 0x59, 0x6C, + 0x03, 0x36, 0x5E, 0x22, 0x7E, 0x3F, 0x65, 0xA6, 0x8C, 0x4F, + 0x89, 0xC1, 0xE7, 0x63, 0xB6, 0x1B, 0xE5, 0x41, 0xC7, 0xF8, + 0x96, 0xA4, 0x8F, 0x4F, 0x47, 0x59, 0x3E, 0x9D, 0x45, 0xCE, + 0xE4, 0x1B, 0xF1, 0x69, 0x0C, 0x39, 0x34, 0x16, 0x77, 0x6A, + 0xF5, 0xB5, 0x9E, 0x8B, 0x63, 0x86, 0x35, 0xFD, 0x4F, 0x2A, + 0x4B, 0x49, 0x21, 0x7C, 0xE3, 0xEA, 0x5C, 0xDE, 0x98, 0xE4, + 0x58, 0x32, 0x67, 0x98, 0xFC, 0x8F, 0xAB, 0x01, 0x0E, 0xA4, + 0x8B, 0x39, 0xA3, 0x55, 0x4C, 0x8E, 0x98, 0xBA, 0xCD, 0x3B, + 0xDB, 0x91, 0x8D, 0x94, 0x98, 0xBE, 0x37, 0x7B, 0xDB, 0x58, + 0xFC, 0xC1, 0x88, 0x7D, 0xD3, 0xBC, 0x8F, 0xB4, 0x7C, 0xB2, + 0xFE, 0x3E, 0x26, 0x36, 0x95, 0x7E, 0xDB, 0xD1, 0x38, 0x29, + 0xD9, 0xCF, 0x5D, 0x0E, 0xD1, 0xDF, 0x7F, 0xD1, 0x68, 0x04, + 0x70, 0x6F, 0x61, 0x39, 0x49, 0x44, 0xD2, 0x5C, 0x0C, 0xC3, + 0xD6, 0xF8, 0x1E, 0x96, 0x36, 0x43, 0x79, 0xB2, 0xE5, 0x1A, + 0xF1, 0x32, 0x03, 0xE1, 0x22, 0x45, 0x20, 0x1B, 0x36, 0x6A, + 0xB8, 0x62, 0xA5, 0xC5, 0x85, 0x8B, 0xED, 0x42, 0x69, 0xC6, + 0x30, 0x36, 0xA1, 0xF6, 0x22, 0x8D, 0x37, 0xD8, 0xE4, 0xBD, + 0x26, 0x8B, 0x89, 0xC2, 0xA9, 0x10, 0x82, 0xDD, 0x0C, 0x2D, + 0x04, 0x39, 0xB7, 0x59, 0x0B, 0x30, 0x2A, 0x6D, 0x84, 0x4A, + 0x74, 0xB9, 0x3F, 0xEA, 0xA5, 0x34, 0x76, 0xFA, 0xAD, 0x99, + 0xB0, 0xEF, 0xA0, 0xF1, 0x85, 0x3D, 0x00, 0x76, 0x00, 0xF8, + 0xFA, 0x1B, 0xAA, 0xB7, 0x5A, 0x62, 0x0E, 0xFD, 0xDC, 0x7A, + 0xCA, 0x18, 0x43, 0x32, 0x02, 0xB7, 0x20, 0x38, 0x0B, 0x50, + 0x4E, 0x57, 0xBF, 0x88, 0xBA, 0x09, 0xD3, 0x9D, 0x8B, 0x3A, + 0x88, 0x82, 0xD9, 0xC3, 0x60, 0x89, 0x10, 0xF5, 0x09, 0x61, + 0x72, 0x41, 0x83, 0xCB, 0x29, 0x38, 0xB3, 0x75, 0xD8, 0xBB, + 0x7E, 0x3F, 0x4A, 0x3C, 0x6B, 0xE5, 0xAE, 0xB7, 0x18, 0xC1, + 0x52, 0x3C, 0x8D, 0x8B, 0xF3, 0x8B, 0x84, 0x98, 0x3E, 0xE3, + 0x5F, 0x5B, 0x89, 0xB7, 0x07, 0x58, 0xD3, 0x7B, 0x84, 0x38, + 0x57, 0x3B, 0xF7, 0x59, 0x22, 0x6B, 0xA7, 0x31, 0x1D, 0xAF, + 0xBF, 0xFA, 0x15, 0x8B, 0xE0, 0x72, 0xFA, 0xCA, 0xB6, 0xC2, + 0xD6, 0x42, 0x43, 0x27, 0xF6, 0xAA, 0x3E, 0x5B, 0x07, 0x12, + 0x5C, 0xEF, 0xED, 0xCB, 0xDF, 0xAA, 0x5F, 0xF8, 0x77, 0xD0, + 0x8E, 0xC7, 0x03, 0x1E, 0x23, 0x5A, 0xF1, 0x3A, 0xA9, 0x10, + 0x6F, 0x05, 0x46, 0x04, 0x72, 0x63, 0xAC, 0xAE, 0x4B, 0x3D, + 0x1E, 0x2D, 0xC2, 0xE9, 0x38, 0x6A, 0xA9, 0x11, 0x1E, 0xE0, + 0xCA, 0x06, 0x7A, 0x5A, 0x45, 0xB2, 0x82, 0x0C, 0x10, 0xEB, + 0x0D, 0x10, 0x26, 0x74, 0xA5, 0x07, 0x1B, 0xBA, 0x61, 0xFD, + 0x8C, 0x73, 0xCB, 0x96, 0xFC, 0xF8, 0x98, 0x2D, 0x83, 0x12, + 0x0B, 0x6A, 0x9C, 0xA4, 0x70, 0x95, 0x4B, 0xD8, 0x11, 0x71, + 0x8F, 0x22, 0x89, 0xA2, 0x6A, 0x0A, 0xB0, 0x17, 0x93, 0x46, + 0x89, 0x60, 0x58, 0x2E, 0x1F, 0x3B, 0xE1, 0x6F, 0x49, 0x47, + 0xBC, 0x93, 0xD2, 0x14, 0x3D, 0xF2, 0x21, 0xA4, 0xFA, 0x1F, + 0x9D, 0x3F, 0x08, 0x40, 0x17, 0x77, 0x58, 0x7F, 0x65, 0xB4, + 0xFD, 0x01, 0x67, 0xF1, 0x62, 0x77, 0xD8, 0x6D, 0x46, 0x42, + 0x30, 0x52, 0x64, 0x4C, 0x76, 0x64, 0x7E, 0x09, 0xDD, 0x57, + 0x04, 0xB8, 0x4A, 0x7F, 0x8A, 0x68, 0xC3, 0x0D, 0xD9, 0xBE, + 0xF6, 0x61, 0x1C, 0x4D, 0x30, 0x80, 0x18, 0x83, 0xD6, 0x3F, + 0xB9, 0x58, 0x52, 0x20, 0xB9, 0x60, 0xEA, 0x22, 0xD0, 0xD0, + 0x61, 0x1A, 0x3B, 0x32, 0x69, 0x35, 0x8B, 0x22, 0x6E, 0x27, + 0x2E, 0xE2, 0x6D, 0xBA, 0xC7, 0x17, 0x02, 0xDA, 0x83, 0x22, + 0x5C, 0x31, 0x60, 0xD6, 0x78, 0x78, 0xBF, 0x0B, 0xEE, 0xD4, + 0x68, 0x32, 0xAE, 0x17, 0x80, 0x04, 0x7F, 0xD9, 0xA9, 0xA0, + 0xC9, 0xB7, 0x98, 0xEE, 0x9C, 0x8C, 0x61, 0x70, 0xBB, 0x2F, + 0x10, 0x39, 0x3E, 0xCC, 0x6E, 0xC8, 0x0A, 0x0F, 0xA2, 0x1E, + 0x31, 0x01, 0x75, 0x1E, 0x41, 0x9E, 0x63, 0x14, 0xC2, 0x3A, + 0xD9, 0x1A, 0x8B, 0x52, 0x0D, 0xFD, 0xDC, 0xE6, 0x23, 0x35, + 0xF1, 0x17, 0xE4, 0xA6, 0xDB, 0xAC, 0x3F, 0x67, 0x59, 0x02, + 0x8E, 0x20, 0x6F, 0x55, 0x69, 0xF8, 0x16, 0xFC, 0x33, 0x53, + 0xCA, 0xE8, 0x4E, 0x3F, 0xA4, 0x5C, 0xA6, 0xA4, 0x95, 0xCD, + 0xB7, 0x9D, 0x14, 0x79, 0xAE, 0x82, 0xF8, 0x2F, 0xE2, 0x13, + 0x0D, 0xDE, 0x75, 0x19, 0xA4, 0x0C, 0x32, 0x83, 0xD0, 0x14, + 0x35, 0xE7, 0x77, 0xD0, 0x18, 0x9C, 0xEF, 0xCC, 0xD5, 0xDA, + 0x39, 0x3B, 0xFF, 0x11, 0x39, 0x20, 0x3D, 0x5A, 0xB1, 0x16, + 0x2A, 0x57, 0x6B, 0x27, 0xC1, 0xB6, 0x69, 0xB5, 0x9B, 0x78, + 0x6F, 0x6B, 0x8A, 0xEF, 0x3F, 0x8F, 0xB8, 0x37, 0xBF, 0xCA, + 0x2D, 0x27, 0x25, 0x12, 0xC9, 0x81, 0x3A, 0x4C, 0x1A, 0x94, + 0xDF, 0x6D, 0x27, 0xF8, 0x85, 0x26, 0xA0, 0x88, 0x56, 0x7B, + 0x62, 0x5E, 0x84, 0xCF, 0x84, 0xAB, 0x81, 0xA3, 0xD4, 0xEB, + 0xE9, 0x85, 0x96, 0xED, 0x27, 0x42, 0xF6, 0x86, 0x28, 0xF1, + 0x8C, 0x69, 0x81, 0xD9, 0xAC, 0x1E, 0x9F, 0x12, 0xA4, 0x9E, + 0x78, 0xC5, 0x2E, 0x07, 0x66, 0xFF, 0x2F, 0xED, 0x93, 0xD2, + 0x62, 0x30, 0x30, 0x81, 0xE5, 0x76, 0x7A, 0x2A, 0x8E, 0xF3, + 0xC0, 0x21, 0x9C, 0xE8, 0xE3, 0x51, 0x4F, 0xDA, 0x96, 0xCF, + 0x6A, 0x0A, 0xC9, 0x90, 0x64, 0x93, 0x70, 0xE2, 0xAD, 0x6E, + 0x17, 0x06, 0x5E, 0xBD, 0x5C, 0x40, 0x4B, 0x43, 0x78, 0x1F, + 0x40, 0x55, 0x36, 0xBD, 0x2B, 0xD6, 0x92, 0x88, 0x02, 0xAA, + 0x3E, 0xDF, 0x3B, 0xC9, 0x90, 0x69, 0x28, 0xE6, 0xE1, 0x7D, + 0xBD, 0x2A, 0xC1, 0x6F, 0x70, 0x6D, 0xB8, 0x1A, 0xAD, 0x66, + 0x4F, 0x78, 0xF7, 0x00, 0x57, 0xED, 0xA8, 0xC3, 0x87, 0x8A, + 0x27, 0x2E, 0xFC, 0xC4, 0x37, 0xB9, 0xED, 0xAE, 0x06, 0x05, + 0x19, 0x60, 0x53, 0x85, 0x54, 0x83, 0x52, 0xEC, 0xBF, 0xA5, + 0x79, 0xFC, 0x18, 0xC3, 0xD8, 0x98, 0xC5, 0xD8, 0x81, 0x78, + 0x4F, 0xDA, 0x24, 0xAD, 0x6F, 0xF4, 0x78, 0x56, 0x79, 0x9F, + 0x5D, 0xE3, 0x6D, 0x35, 0x93, 0xEA, 0xA8, 0xB5, 0x44, 0x1A, + 0xDA, 0x87, 0xBD, 0x06, 0x4D, 0xFF, 0x35, 0x2A, 0x76, 0x51, + 0xD3, 0xC2, 0x73, 0x20, 0x93, 0x33, 0xC0, 0xEA, 0x88, 0xA0, + 0xCD, 0xE1, 0xEA, 0x79, 0x86, 0x32, 0xA7, 0xCE, 0xBA, 0x73, + 0xE9, 0x82, 0x32, 0x64, 0x88, 0x44, 0x66, 0x8A, 0x8C, 0xCB, + 0xF1, 0xDB, 0x42, 0x91, 0x3E, 0x78, 0x3A, 0x77, 0xEB, 0x4C, + 0xFD, 0xFE, 0x43, 0xD8, 0xEA, 0x9E, 0xED, 0x19, 0xAD, 0xA8, + 0x64, 0x1A, 0x12, 0xC3, 0x81, 0x75, 0xA0, 0x61, 0xAF, 0x4F, + 0x71, 0x25, 0x94, 0x76, 0x31, 0x9A, 0xF6, 0x14, 0x3F, 0x6D, + 0x36, 0xC0, 0x2F, 0x52, 0x3B, 0x4B, 0xCB, 0x2B, 0xCF, 0xB8, + 0x70, 0x19, 0x0D, 0x15, 0x1A, 0xF9, 0x48, 0xA8, 0x3A, 0x55, + 0xAF, 0x18, 0x66, 0x50, 0xC8, 0x32, 0x97, 0x43, 0x1E, 0x9F, + 0x8B, 0x66, 0xC1, 0x2E, 0x37, 0x69, 0xB8, 0x97, 0xF9, 0x6A, + 0x1E, 0x69, 0xBA, 0x5C, 0xEC, 0x6F, 0xFD, 0x99, 0x71, 0xB8, + 0xC4, 0x05, 0xB9, 0xB9, 0xE6, 0x4D, 0xA7, 0x01, 0x2D, 0xEB, + 0x26, 0x23, 0x40, 0x4D, 0x79, 0x1B, 0xE4, 0xD9, 0xAB, 0x9F, + 0xE9, 0x9B, 0x35, 0x78, 0xC0, 0x32, 0x8E, 0xF7, 0x5F, 0x7E, + 0xB5, 0x56, 0xD2, 0xA1, 0x35, 0x81, 0x72, 0xD2, 0x6A, 0x0A, + 0xC9, 0x6D, 0x0D, 0xDB, 0x2B, 0xA4, 0x02, 0x92, 0x76, 0x26, + 0xAF, 0x36, 0x27, 0x01, 0xDF, 0xA5, 0x5B, 0x09, 0x97, 0x06, + 0x5E, 0x80, 0xB0, 0x32, 0xFC, 0x1F, 0x72, 0x4E, 0x93, 0x2F, + 0x12, 0xF3, 0xA2, 0x60, 0x19, 0x74, 0x69, 0x03, 0x8B, 0x7D, + 0x6B, 0x2C, 0xE9, 0x54, 0x91, 0xF1, 0x3F, 0x2B, 0xF1, 0x65, + 0x71, 0x0B, 0x24, 0xEF, 0xCC, 0xB8, 0x79, 0x8E, 0x9B, 0x03, + 0xC1, 0xFF, 0xAC, 0xF0, 0x04, 0xEA, 0x92, 0xA3, 0x86, 0x64, + 0x6B, 0x63, 0x43, 0xA6, 0xC3, 0xCB, 0x43, 0xBE, 0xB0, 0xA9, + 0x11, 0x1B, 0x74, 0xC0, 0x87, 0x61, 0x5C, 0xDB, 0xF4, 0xA3, + 0x0E, 0xA6, 0x36, 0xEE, 0x41, 0x7F, 0xA8, 0xA6, 0xDF, 0x1B, + 0x05, 0xAE, 0x77, 0x90, 0x6A, 0xD4, 0x5B, 0x8E, 0x27, 0xE2, + 0xC0, 0x3E, 0x99, 0xAB, 0xFD, 0xFE, 0x6B, 0x71, 0xB4, 0x22, + 0x77, 0x7A, 0xB0, 0x43, 0x8B, 0x81, 0x33, 0x4D, 0x51, 0xD4, + 0xAB, 0xD9, 0xA0, 0x7C, 0xA7, 0x8A, 0x39, 0x92, 0x45, 0x39, + 0xAC, 0x54, 0x13, 0x6E, 0xA5, 0x22, 0x28, 0xC8, 0xAD, 0x3D, + 0xB1, 0xB2, 0xF3, 0x6B, 0xF6, 0x51, 0x17, 0xA3, 0x37, 0xE9, + 0xC9, 0x94, 0x54, 0xD7, 0x64, 0xC6, 0x04, 0xE7, 0xFA, 0x93, + 0xC1, 0xFA, 0xBA, 0xCA, 0x21, 0x1B, 0xF0, 0x6C, 0x99, 0x22, + 0x52, 0x53, 0xEF, 0xC2, 0xA2, 0x19, 0xB3, 0xCA, 0xF5, 0x30, + 0xC1, 0xD1, 0x24, 0x7F, 0x3A, 0x28, 0x8F, 0xAA, 0x70, 0xD2, + 0xBB, 0x7A, 0xF5, 0x8A, 0x23, 0x57, 0xE9, 0x79, 0x00, 0xF4, + 0x1C, 0x1D, 0xB1, 0x42, 0x0C, 0x53, 0x99, 0x7B, 0x99, 0x68, + 0x6E, 0x71, 0xD9, 0xD4, 0xE9, 0xC1, 0xA7, 0x5B, 0x05, 0xA7, + 0x6F, 0xF2, 0xE7, 0x11, 0x3B, 0x70, 0x5F, 0x11, 0x98, 0xBE, + 0xB5, 0xF8, 0x78, 0x5F, 0x5C, 0x19, 0xAC, 0x92, 0x4D, 0x18, + 0x0D, 0x7B, 0x6F, 0x8C, 0x90, 0xAB, 0x6B, 0x32, 0x3D, 0x51, + 0x11, 0xBC, 0x80, 0xC4, 0xCF, 0x4A, 0xF4, 0x7F, 0xCC, 0x68, + 0x92, 0x76, 0xF7, 0x9D, 0xF7, 0x07, 0x44, 0x8C, 0xB5, 0x4D, + 0x53, 0x7E, 0xE2, 0x58, 0x42, 0xB5, 0x8E, 0xB3, 0xC7, 0x0C, + 0x2F, 0xCA, 0x77, 0x2D, 0x56, 0x84, 0xCA, 0x98, 0x05, 0x09, + 0x43, 0xA9, 0x0E, 0x92, 0x4B, 0x57, 0x27, 0x46, 0x31, 0xF0, + 0xE3, 0xA4, 0x48, 0xD9, 0x42, 0x51, 0x32, 0xF0, 0x70, 0xA1, + 0x72, 0xA9, 0x2B, 0x1D, 0xB1, 0x2A, 0x09, 0x96, 0xAE, 0x3E, + 0x83, 0x41, 0x7B, 0x9B, 0x28, 0x6E, 0x85, 0xB7, 0xAD, 0x7F, + 0x10, 0xA3, 0x54, 0xBF, 0x24, 0xB6, 0xFB, 0x6D, 0xA5, 0x9F, + 0xE6, 0xBB, 0x33, 0x8A, 0x04, 0x83, 0x53, 0xFB, 0xB9, 0x79, + 0xF7, 0x76, 0xC9, 0x43, 0xC7, 0xE4, 0xB5, 0xE7, 0x19, 0x56, + 0x72, 0x55, 0xAC, 0x1D, 0xA8, 0xE4, 0xD8, 0x0C, 0x66, 0x15, + 0x7F, 0x17, 0x08, 0xB9, 0x33, 0x4B, 0x9C, 0x84, 0xDA, 0x49, + 0x9F, 0x1B, 0x42, 0x85, 0x0F, 0x4B, 0xC0, 0x70, 0x35, 0x23, + 0x34, 0xD9, 0x3C, 0x76, 0xF9, 0x22, 0x5C, 0x1A, 0xE9, 0x81, + 0xE5, 0x31, 0xA3, 0xF1, 0xB7, 0x7F, 0xE2, 0x75, 0x42, 0x27, + 0x82, 0xC7, 0xBA, 0x68, 0x20, 0x0E, 0xAC, 0xD0, 0x32, 0x28, + 0xB5, 0x99, 0x71, 0xBA, 0x48, 0x2C, 0x95, 0xA5, 0xC8, 0x65, + 0x2E, 0x19, 0x70, 0xAD, 0x12, 0x3A, 0xAD, 0x83, 0x87, 0x15, + 0xA7, 0xEA, 0x9D, 0x6E, 0x11, 0x94, 0x95, 0x23, 0x51, 0xDA, + 0x5F, 0x67, 0xBD, 0xDD, 0xA7, 0xF9, 0xF8, 0x76, 0xE4, 0x3C, + 0x83, 0x0A, 0xAB, 0xBE, 0x6A, 0xB0, 0xC5, 0xA8, 0xBE, 0xD9, + 0xDD, 0xBC, 0x4E, 0xA6, 0xCF, 0x91, 0xB3, 0x42, 0x30, 0x96, + 0x8E, 0x45, 0xC6, 0x1F, 0x55, 0x6B, 0x2C, 0x0A, 0xBC, 0x9F, + 0x69, 0x65, 0x98, 0x34, 0x95, 0x6A, 0x1E, 0x86, 0x78, 0x8B, + 0x26, 0x4F, 0x05, 0x76, 0x03, 0x22, 0xCB, 0x72, 0xF1, 0xD0, + 0x1A, 0x64, 0x19, 0xC7, 0x21, 0x5C, 0x51, 0xD0, 0x6C, 0x0B, + 0xDA, 0xB9, 0x67, 0x7A, 0x83, 0xC3, 0x1E, 0x16, 0x27, 0x4A, + 0x00, 0x5F, 0xBA, 0x0E, 0x45, 0x81, 0x6E, 0xE7, 0x5B, 0x5A, + 0x8F, 0x0D, 0x6D, 0x47, 0xB1, 0x30, 0xA7, 0x42, 0x1E, 0xA9, + 0x8A, 0x27, 0x4A, 0xB0, 0x60, 0x2F, 0xA9, 0x12, 0x42, 0xD6, + 0x7F, 0x10, 0x01, 0xF3, 0x59, 0xD2, 0x40, 0x11, 0x19, 0x92, + 0xFE, 0x80, 0x25, 0x1B, 0x60, 0xDC, 0x02, 0x7B, 0x10, 0x45, + 0x17, 0x66, 0x70, 0xB9, 0x64, 0x4A, 0xBA, 0xAD, 0xBF, 0x55, + 0x7C, 0xB3, 0xD8, 0x18, 0x6D, 0x16, 0x53, 0xED, 0x89, 0xE5, + 0xD2, 0x50, 0xFA, 0xA8, 0xFE, 0x74, 0x67, 0xC4, 0x35, 0x4C, + 0xC4, 0xBE, 0x52, 0x9A, 0x8E, 0xBB, 0xB6, 0xE0, 0xAF, 0x52, + 0x57, 0x3D, 0x99, 0x79, 0x10, 0xB8, 0xE6, 0xAB, 0x24, 0x9E, + 0x75, 0xC2, 0x2A, 0xFB, 0xDB, 0xF8, 0xE0, 0x02, 0xCB, 0x49, + 0x56, 0x52, 0x6B, 0x8C, 0xFA, 0x8E, 0xCF, 0xFA, 0x18, 0x50, + 0xDD, 0x98, 0x49, 0xEC, 0xA8, 0x08, 0x6C, 0x60, 0xC0, 0x68, + 0xBF, 0x7B, 0x49, 0xB4, 0xE6, 0x49, 0x59, 0x6E, 0x65, 0x0E, + 0x41, 0xEA, 0x64, 0xC8, 0xD3, 0x1A, 0x9F, 0x39, 0xAE, 0xEB, + 0x3C, 0x88, 0xFB, 0x40, 0xDC, 0xB8, 0x07, 0x82, 0x56, 0x01, + 0xAC, 0x04, 0x0B, 0x6B, 0x0B, 0x15, 0xAA, 0x4F, 0xD2, 0x04, + 0xF3, 0x65, 0xCD, 0xF7, 0x32, 0xB1, 0x95, 0xC4, 0x91, 0xB8, + 0x63, 0x02, 0x26, 0x47, 0x1D, 0x6E, 0x6D, 0xCF, 0x3D, 0x39, + 0x3D, 0xDC, 0x18, 0x33, 0xD8, 0xF5, 0x8C, 0xB0, 0x69, 0x53, + 0x48, 0x86, 0x14, 0x50, 0xA3, 0x65, 0xEE, 0x2C, 0x2F, 0x72, + 0xF7, 0x43, 0xE7, 0xEA, 0xA0, 0x3E, 0x3C, 0x30, 0x33, 0xD9, + 0x1D, 0x6E, 0x5D, 0xCB, 0xE1, 0xE0, 0x8D, 0x95, 0xD2, 0x58, + 0x8D, 0xD5, 0xB3, 0x1C, 0x22, 0x28, 0x6A, 0xBB, 0xB3, 0x09, + 0xB1, 0x91, 0x60, 0xE2, 0xC6, 0x48, 0x11, 0xF0, 0x49, 0xB6, + 0xE9, 0xEF, 0x4B, 0xC6, 0xDB, 0xB1, 0xBF, 0x6C, 0xB2, 0x92, + 0x5C, 0x65, 0x91, 0x67, 0x81, 0x9C, 0x71, 0x5A, 0x2C, 0xFE, + 0xC8, 0xF9, 0xF5, 0x96, 0x7D, 0x3E, 0xBB, 0x7F, 0xEF, 0xF7, + 0xBF, 0xF8, 0xAC, 0xCF, 0xA6, 0x6F, 0x28, 0x9C, 0x09, 0x65, + 0x8F, 0xF7, 0xDC, 0xEF, 0x3E, 0x4B, 0xCD, 0x6D, 0x97, 0xD3, + 0xCC, 0x9C, 0xF7, 0xF2, 0x4C, 0xE6, 0x64, 0x31, 0xE8, 0x1E, + 0xDE, 0x56, 0xAE, 0xA6, 0x04, 0xFB, 0xED, 0x2E, 0x3F, 0x23, + 0x7D, 0xBC, 0x6D, 0xCC, 0x4B, 0xD4, 0x9E, 0x06, 0x83, 0xE1, + 0x95, 0xAE, 0xC4, 0xAA, 0x6E, 0xFF, 0x9E, 0x1C, 0xB9, 0x07, + 0x60, 0x6D, 0xD5, 0x09, 0x06, 0x30, 0x0C, 0x3F, 0xB5, 0xE8, + 0x8B, 0x01, 0x94, 0x1B, 0x84, 0xE9, 0xB7, 0x37, 0x03, 0xA7, + 0xAF, 0x4B, 0x63, 0x3F, 0xD2, 0x57, 0xBB, 0xB8, 0xBF, 0xE2, + 0x53, 0x4F, 0xA1, 0x9E, 0xC7, 0x4C, 0xDA, 0x89, 0x25, 0x0E, + 0x7E, 0xC9, 0x44, 0x7F, 0x4C, 0x02, 0x7F, 0xA4, 0x08, 0xEC, + 0x7F, 0x44, 0xEA, 0xF7, 0xCF, 0x1B, 0x19, 0xFA, 0x6A, 0x0A, + 0x3E, 0xE1, 0xF4, 0x78, 0xDF, 0x93, 0xAB, 0x86, 0x9E, 0xE1, + 0x31, 0xBF, 0x70, 0x20, 0x8B, 0x87, 0xCE, 0xFC, 0x84, 0x03, + 0x8D, 0xF1, 0x25, 0xE6, 0x88, 0x30, 0x79, 0x63, 0xAF, 0x5C, + 0x3B, 0x84, 0xA9, 0xB8, 0x89, 0xB4, 0x23, 0x58, 0x78, 0xF9, + 0xAB, 0x76, 0x1B, 0x20, 0x56, 0xDB, 0x9E, 0xFE, 0x59, 0x29, + 0xB9, 0x8C, 0xD7, 0x4E, 0xA4, 0x5C, 0x7F, 0x40, 0xA8, 0xEB, + 0x0D, 0x90, 0xBA, 0x30, 0x68, 0x5E, 0x9C, 0x90, 0xBE, 0xD4, + 0x43, 0x4B, 0x67, 0x27, 0xE7, 0x7D, 0x06, 0xB8, 0xF0, 0x96, + 0xEF, 0xF4, 0x47, 0x5F, 0x8E, 0xCA, 0x46, 0x85, 0x3C, 0x94, + 0x9E, 0xDE, 0x09, 0x40, 0x45, 0xB3, 0x69, 0xF1, 0x8F, 0x90, + 0xF5, 0x5C, 0x22, 0x69, 0xBF, 0x5F, 0x11, 0x66, 0xD9, 0xDC, + 0x37, 0x6A, 0x2C, 0xAF, 0x72, 0x66, 0xC8, 0x28, 0xEA, 0x59, + 0x71, 0xB1, 0x7F, 0x10, 0xA5, 0xBC, 0x42, 0x99, 0xF6, 0xD6, + 0xB4, 0xC4, 0x18, 0x49, 0x72, 0x37, 0xF3, 0xCD, 0x01, 0xD6, + 0xAB, 0x2A, 0xFE, 0x1A, 0xBC, 0x52, 0x15, 0x38, 0x30, 0xF2, + 0x4F, 0xC0, 0xD3, 0x5B, 0x91, 0x5A, 0x55, 0xD1, 0x82, 0x5A, + 0x50, 0xE8, 0x16, 0x8C, 0x3D, 0xC8, 0x97, 0x3D, 0x2A, 0xA9, + 0xF3, 0xEA, 0x48, 0x57, 0x51, 0x29, 0xB0, 0x81, 0x4D, 0x6B, + 0x69, 0xFE, 0xF8, 0xA8, 0xE0, 0x5F, 0xF4, 0x98, 0xBE, 0x3D, + 0x39, 0xB6, 0x10, 0x3E, 0x70, 0x16, 0x60, 0x46, 0xA1, 0x74, + 0x5C, 0xF5, 0x53, 0x24, 0xF4, 0x56, 0x33, 0x97, 0x18, 0xB6, + 0x4A, 0x91, 0xE1, 0xF4, 0x36, 0x11, 0x80, 0xCF, 0xDE, 0xE3, + 0x7C, 0x8C, 0x27, 0xC9, 0x29, 0xA6, 0xCC, 0xA2, 0xE3, 0x61, + 0xED, 0x46, 0x10, 0x0D, 0x43, 0x1D, 0x63, 0xB2, 0x4B, 0xC0, + 0xFF, 0x79, 0x2D, 0x6D, 0xD1, 0x0E, 0xD4, 0x73, 0x24, 0xE2, + 0xFE, 0x07, 0x15, 0xC4, 0xB3, 0xFC, 0xDA, 0x14, 0x44, 0x81, + 0x89, 0xA9, 0x16, 0xEF, 0x8C, 0x60, 0xEE, 0x2D, 0xBC, 0x81, + 0xF1, 0xD8, 0xE1, 0x37, 0x5D, 0xC0, 0xD2, 0xA5, 0x8C, 0xF9, + 0xAF, 0xAA, 0xBE, 0xF6, 0x46, 0x65, 0xEB, 0x53, 0x97, 0x2F, + 0xDA, 0x28, 0x66, 0x29, 0x67, 0x1F, 0x1F, 0x0A, 0x61, 0x61, + 0x66, 0x61, 0xF2, 0xA7, 0x1F, 0x1C, 0x30, 0x1F, 0xDD, 0xDE, + 0xAB, 0xC7, 0x6C, 0x1C, 0xED, 0xC8, 0xDC, 0x09, 0xBA, 0xF9, + 0x93, 0x76, 0x4C, 0xCC, 0xAE, 0xF5, 0x2D, 0xA4, 0xAB, 0x3F, + 0xA0, 0x42, 0x4E, 0x8F, 0x28, 0x87, 0xE1, 0x64, 0xCA, 0xF4, + 0xB6, 0xAC, 0x39, 0x1E, 0x1C, 0xF2, 0x69, 0xFF, 0x30, 0x3B, + 0x2F, 0x5C, 0xB2, 0x82, 0xD8, 0x28, 0x2D, 0xA8, 0x2C, 0xDA, + 0x6D, 0x76, 0x38, 0xFC, 0x50, 0x6F, 0xA4, 0xB9, 0x52, 0x9F, + 0xD5, 0xFA, 0x94, 0xDC, 0x54, 0xED, 0xD9, 0x10, 0x6F, 0xDA, + 0x7E, 0x5E, 0x8A, 0xFB, 0xB3, 0x68, 0xD0, 0xD1, 0x25, 0x77, + 0x7E, 0x8B, 0x91, 0x68, 0x4E, 0xF4, 0x74, 0x99, 0x77, 0xB8, + 0x5C, 0xCE, 0xCC, 0x3D, 0x54, 0xA8, 0xD8, 0x4F, 0x01, 0x30, + 0x37, 0xB0, 0x82, 0x42, 0xB9, 0xB1, 0xBF, 0x83, 0xC8, 0xB6, + 0x40, 0x7F, 0xF2, 0xD8, 0x3C, 0xBD, 0x63, 0xCB, 0x23, 0x34, + 0xA4, 0xFB, 0x4C, 0xE0, 0x8B, 0x85, 0xA4, 0xA9, 0x7B, 0xA4, + 0x78, 0x86, 0xD4, 0xE9, 0x68, 0xA4, 0x40, 0x8D, 0xBC, 0x56, + 0x44, 0x8B, 0x24, 0x80, 0x6B, 0xC1, 0x84, 0xEC, 0xB3, 0x70, + 0x01, 0x0A, 0xFE, 0xED, 0x7D, 0xD9, 0x7E, 0xAB, 0x89, 0xDB, + 0xE3, 0x90, 0x5C, 0x6A, 0x75, 0x8E, 0x16, 0xF2, 0x0A, 0xFE, + 0x9E, 0x08, 0xC8, 0xB2, 0x35, 0x3C, 0xC3, 0x20, 0x29, 0xD4, + 0x8A, 0xA6, 0x58, 0x25, 0x43, 0x9B, 0x27, 0xAE, 0xBF, 0xC7, + 0x50, 0x82, 0x9F, 0x04, 0x88, 0x4C, 0xB0, 0x4E, 0x38, 0xA5, + 0x84, 0xC1, 0xBA, 0x6A, 0xA7, 0x16, 0x85, 0x76, 0xF5, 0x21, + 0x15, 0x3F, 0x00, 0x2C, 0x0A, 0xBD, 0x18, 0x66, 0x0C, 0xD1, + 0x46, 0x33, 0x1A, 0xF3, 0x85, 0x34, 0x68, 0x49, 0x05, 0x10, + 0x85, 0xF9, 0x61, 0xD6, 0xB6, 0x97, 0xFC, 0xAA, 0x2C, 0xBC, + 0xF1, 0x75, 0xF3, 0xFC, 0x57, 0x20, 0x54, 0xF2, 0x02, 0x5E, + 0xAB, 0xDD, 0x19, 0x31, 0xAB, 0x97, 0x5F, 0x11, 0x4F, 0xCE, + 0x4F, 0xB9, 0xBB, 0xA2, 0x01, 0x51, 0x48, 0x5A, 0x2C, 0x52, + 0xAD, 0x58, 0x00, 0x22, 0x41, 0x4D, 0x24, 0x68, 0x9F, 0xD9, + 0x13, 0x5C, 0x55, 0x0A, 0x62, 0xAD, 0x3E, 0x29, 0x86, 0x34, + 0x3B, 0x2D, 0x34, 0xBE, 0x0A, 0xDB, 0x85, 0x3A, 0x41, 0x2C, + 0x30, 0x56, 0x65, 0x04, 0x0A, 0x20, 0x31, 0x2A, 0xF3, 0x88, + 0x4C, 0x38, 0x64, 0x86, 0x14, 0x06, 0xF5, 0xF0, 0x7F, 0x63, + 0xC1, 0x87, 0x24, 0x39, 0xFB, 0xC0, 0xC2, 0x6B, 0x57, 0xB3, + 0xA9, 0x7C, 0x21, 0xD7, 0x17, 0xB5, 0x23, 0x89, 0x8B, 0x9A, + 0x53, 0xC6, 0x26, 0xD6, 0xC1, 0xD8, 0x3B, 0xD2, 0x30, 0x0B, + 0x30, 0x76, 0xB3, 0x21, 0x2B, 0xCF, 0x64, 0xB8, 0xCD, 0x8C, + 0xB9, 0x33, 0x73, 0xA5, 0x19, 0x5C, 0xBB, 0x4A, 0x6F, 0x9E, + 0xA7, 0x62, 0x61, 0x1C, 0x32, 0xBB, 0x3E, 0x1B, 0x8A, 0xAC, + 0xE5, 0xE1, 0xA9, 0xDD, 0x50, 0xFB, 0x3B, 0xCF, 0xB6, 0x49, + 0x7B, 0xED, 0x1A, 0x7E, 0x8E, 0x73, 0xAE, 0x8B, 0x31, 0x06, + 0x11, 0xC4, 0x84, 0x4C, 0xCA, 0x6D, 0x5A, 0x79, 0x50, 0x2E, + 0x66, 0x90, 0x0A, 0x13, 0x86, 0x15, 0x78, 0x06, 0xAD, 0x5D, + 0x8C, 0x5E, 0xC8, 0x73, 0xB0, 0x82, 0xFB, 0x03, 0xE6, 0x30, + 0xE7, 0x0B, 0x99, 0xF0, 0xD9, 0x8C, 0x2C, 0xFA, 0x34, 0xAB, + 0x8B, 0xDD, 0x06, 0x2F, 0x39, 0xE0, 0x53, 0x37, 0x61, 0x3D, + 0xC3, 0x77, 0x4C, 0x9F, 0x66, 0x95, 0x81, 0x94, 0x0A, 0xE5, + 0xCE, 0x59, 0xA1, 0x83, 0x5C, 0x77, 0xBD, 0xF5, 0xAD, 0xE2, + 0x9C, 0x10, 0x64, 0x22, 0xAD, 0x99, 0x02, 0x3F, 0x6A, 0xB2, + 0x96, 0x2C, 0xF3, 0x21, 0xEB, 0x5A, 0x7D, 0xFC, 0x02, 0x9B, + 0x53, 0x94, 0xB1, 0x88, 0x3E, 0x07, 0x78, 0x31, 0x8F, 0xDF, + 0xDA, 0xAF, 0xB7, 0x55, 0xC9, 0x30, 0x74, 0x61, 0xD1, 0x75, + 0x15, 0xF1, 0x29, 0xB0, 0x8B, 0xD9, 0x19, 0xB3, 0x2E, 0x8C, + 0x3C, 0x4C, 0xED, 0x22, 0x0B, 0x07, 0xEC, 0xA8, 0x2B, 0x26, + 0xBA, 0x2A, 0xE3, 0xEB, 0x91, 0x2C, 0xDF, 0x28, 0xFD, 0xE3, + 0x12, 0x6D, 0xA8, 0x8C, 0xA9, 0xA0, 0x18, 0xAE, 0x18, 0xC4, + 0x05, 0x53, 0xF6, 0xF7, 0x69, 0xEF, 0xBB, 0xF8, 0xFF, 0x55, + 0xD9, 0x4E, 0xA0, 0xC9, 0x58, 0x38, 0x67, 0x31, 0xE7, 0x5C, + 0x46, 0x41, 0x58, 0x26, 0x48, 0x8C, 0x82, 0x91, 0xE4, 0x46, + 0x91, 0xE0, 0xA4, 0x4F, 0xA5, 0xFD, 0x28, 0x14, 0xC8, 0x07, + 0x73, 0xB9, 0x20, 0x7D, 0x94, 0xAF, 0xDC, 0xBF, 0x4A, 0x55, + 0xA8, 0x82, 0xBF, 0x6D, 0x22, 0xD2, 0xFF, 0x18, 0x5E, 0xFB, + 0xC4, 0xDE, 0x8B, 0x12, 0x58, 0x1E, 0x05, 0x51, 0x4A, 0x31, + 0x54, 0x26, 0xA5, 0xFD, 0x36, 0xED, 0x14, 0x80, 0x4E, 0x3F, + 0xB2, 0x4F, 0x43, 0x70, 0xAF, 0x63, 0x77, 0x86, 0x68, 0xF4, + 0x35, 0xC2, 0x4E, 0x57, 0x43, 0x63, 0x06, 0x07, 0x21, 0xCE, + 0x61, 0xDD, 0x5D, 0x1D, 0xA3, 0xF7, 0x24, 0x72, 0xED, 0x73, + 0x6A, 0xA0, 0xE6, 0x9C, 0x1A, 0xA3, 0xCF, 0x98, 0x47, 0xC2, + 0xE1, 0x29, 0x22, 0x1B, 0x7C, 0x14, 0x0E, 0xE2, 0x6B, 0x58, + 0x54, 0xA7, 0x3E, 0x0F, 0x07, 0x1D, 0xAB, 0xFD, 0x1C, 0x1E, + 0xE0, 0x24, 0xCB, 0x2B, 0xC8, 0x7D, 0x90, 0x83, 0x8D, 0x46, + 0x43, 0xB4, 0x30, 0x39, 0x26, 0x29, 0xEE, 0xAF, 0x67, 0x61, + 0x4C, 0x16, 0xF1, 0xF4, 0x01, 0x55, 0x71, 0x30, 0x1B, 0x18, + 0xC2, 0xF3, 0x8A, 0x26, 0x52, 0x63, 0xD0, 0xEA, 0x66, 0x04, + 0xD7, 0xCC, 0x09, 0xF1, 0x66, 0x62, 0xD1, 0x29, 0xFD, 0xCE, + 0x0A, 0x85, 0xD5, 0x2C, 0x5B, 0x0D, 0xC3, 0x53, 0x8F, 0x45, + 0xA1, 0x95, 0xEE, 0xAF, 0xC3, 0xC5, 0xEE, 0xE6, 0xCE, 0x4A, + 0x33, 0xDB, 0x8B, 0x29, 0x79, 0xBC, 0xF7, 0xC5, 0x33, 0xCD, + 0xC1, 0x74, 0x25, 0x69, 0xEC, 0x75, 0xA4, 0x05, 0x1D, 0x6D, + 0x6E, 0xEC, 0x77, 0xDC, 0xF9, 0x08, 0xB1, 0xFA, 0x38, 0x7F, + 0x8E, 0xDF, 0x74, 0x10, 0x27, 0x19, 0x52, 0xAB, 0x6B, 0x08, + 0xEB, 0x51, 0x22, 0xE7, 0x79, 0xDA, 0x9F, 0xC0, 0xD2, 0x5E, + 0x5C, 0x2A, 0xC7, 0xF8, 0x6B, 0xB6, 0x63, 0x06, 0x49, 0xB4, + 0xDD, 0xEB, 0x20, 0x6F, 0x5A, 0x5E, 0x78, 0x79, 0xA5, 0xAF, + 0x35, 0x6D, 0x36, 0xBA, 0xA4, 0x38, 0x98, 0x38, 0xD9, 0x59, + 0x81, 0x16, 0x8C, 0xCE, 0x78, 0xCA, 0xD1, 0x86, 0x8B, 0x3A, + 0xD9, 0xA5, 0x5B, 0x7C, 0x53, 0x24, 0xB8, 0xD2, 0x2B, 0x09, + 0x73, 0x04, 0x87, 0x3E, 0x39, 0x64, 0x42, 0x5A, 0xE1, 0xC8, + 0x72, 0xD5, 0x00, 0x06, 0x06, 0x81, 0x91, 0x7A, 0x12, 0xA1, + 0x91, 0xEC, 0xBF, 0xD6, 0xBC, 0xFD, 0x82, 0xDA, 0xEE, 0x3A, + 0xB7, 0xF1, 0x54, 0xE3, 0xBD, 0xE5, 0xC0, 0x18, 0xE9, 0x5C, + 0x49, 0x0C, 0xFA, 0x64, 0x80, 0x98, 0x5C, 0x44, 0x9B, 0x4A, + 0x48, 0x3E, 0x0C, 0xBE, 0x5E, 0xBB, 0x68, 0xDA, 0x09, 0xD7, + 0x00, 0x51, 0x5B, 0x13, 0x96, 0xC2, 0x8A, 0xCE, 0xB0, 0x8F, + 0xDF, 0x84, 0x77, 0x70, 0x4B, 0x0F, 0x6E, 0xC7, 0x62, 0x47, + 0xFA, 0xA8, 0x35, 0x18, 0x43, 0x93, 0x4C, 0x83, 0x13, 0x45, + 0x74, 0x76, 0x19, 0xA7, 0x71, 0x98, 0x8C, 0x2E, 0xFC, 0xA9, + 0x83, 0x64, 0xD1, 0xA3, 0x95, 0x33, 0x31, 0xDB, 0xA8, 0xC3, + 0xB9, 0x72, 0x80, 0x58, 0xEC, 0xEB, 0xFC, 0xF3, 0x03, 0x44, + 0xDC, 0x11, 0x06, 0x3A, 0x95, 0x81, 0x28, 0xDB, 0xAB, 0x36, + 0xC4, 0x37, 0x0C, 0xD4, 0x6B, 0xAF, 0x04, 0xD0, 0x23, 0x3F, + 0xDD, 0x08, 0x88, 0x06, 0x23, 0x39, 0xCF, 0xB2, 0xCF, 0x13, + 0x27, 0xE1, 0x4E, 0x21, 0xDA, 0x81, 0x58, 0x29, 0x70, 0x2B, + 0x26, 0xB7, 0xA7, 0x69, 0xA1, 0x86, 0xBC, 0xD9, 0x88, 0xED, + 0x70, 0x61, 0x94, 0x2D, 0xCD, 0x47, 0x57, 0xD0, 0xBD, 0x07, + 0x05, 0x7E, 0xA5, 0x35, 0x29, 0x15, 0xFA, 0x62, 0x7E, 0xB7, + 0x2A, 0xEB, 0x4F, 0xC4, 0x0D, 0x6D, 0x2E, 0x6D, 0x8F, 0x53, + 0x7C, 0x0B, 0x62, 0x72, 0xA5, 0x01, 0x5D, 0xD9, 0x52, 0xAF, + 0x60, 0x22, 0x90, 0xD0, 0xE6, 0x37, 0x25, 0x57, 0x73, 0x66, + 0xD5, 0x96, 0x6A, 0x23, 0x75, 0x43, 0xF7, 0x6A, 0xC8, 0x3E, + 0xAC, 0x20, 0xC8, 0x8A, 0xE3, 0xD1, 0xB4, 0x07, 0x87, 0x8E, + 0x3A, 0xEB, 0x43, 0x10, 0x91, 0x7F, 0x17, 0x96, 0x4B, 0x7A, + 0x31, 0x2A, 0x84, 0xFC, 0xFE, 0xB1, 0x26, 0x67, 0xD6, 0xAD, + 0xB8, 0xB7, 0x3D, 0x3A, 0x2F, 0xEE, 0x94, 0x2F, 0x05, 0xF1, + 0xD8, 0x8E, 0xD4, 0x97, 0xAF, 0x36, 0xCE, 0x01, 0x18, 0x0B, + 0x68, 0x41, 0x26, 0xEB, 0x38, 0x2B, 0xF6, 0xD2, 0x8A, 0x5A, + 0x79, 0x02, 0xA1, 0xE4, 0x49, 0x48, 0xCF, 0x55, 0x2B, 0x74, + 0x16, 0x63, 0x27, 0x9D, 0x25, 0xAA, 0x7F, 0x8A, 0x5D, 0x96, + 0x68, 0xF3, 0x58, 0x7C, 0x10, 0xCF, 0x6A, 0xE3, 0xE2, 0x80, + 0x90, 0xD3, 0x39, 0xF5, 0x62, 0x01, 0x33, 0x5F, 0xC2, 0xFD, + 0xAD, 0xE6, 0x2A, 0xB2, 0x3D, 0x89, 0x99, 0x7B, 0x17, 0x35, + 0xE4, 0x5C, 0x62, 0x10, 0x69, 0x10, 0x93, 0x57, 0x92, 0x15, + 0x53, 0xEC, 0x82, 0x17, 0x00, 0xFC, 0x13, 0x49, 0x58, 0x79, + 0x90, 0x36, 0x0D, 0x50, 0xA5, 0xFE, 0xAE, 0xE1, 0xB3, 0xAF, + 0x40, 0x98, 0x3C, 0xB7, 0xAB, 0xC9, 0x0B, 0x2B, 0xE8, 0x31, + 0x71, 0x0D, 0x47, 0xE1, 0xE0, 0x3D, 0xCB, 0xB0, 0x3E, 0x44, + 0x00, 0x18, 0x66, 0xD5, 0x44, 0xEF, 0x58, 0x6A, 0xC3, 0x98, + 0x86, 0x19, 0xBA, 0xCE, 0x24, 0xF0, 0x9A, 0xED, 0x55, 0xA9, + 0x1F, 0x52, 0xB2, 0xBA, 0x1A, 0x2C, 0x71, 0x9F, 0xD7, 0xE6, + 0xA1, 0x01, 0x64, 0x8B, 0x22, 0x22, 0x23, 0xC8, 0x2A, 0xBA, + 0x13, 0x5A, 0xDD, 0xC4, 0x0C, 0x1A, 0x3C, 0x4F, 0x1E, 0x0B, + 0x5B, 0xB5, 0x45, 0xA3, 0xDD, 0x4D, 0xE9, 0x00, 0x06, 0x60, + 0x59, 0xFC, 0x48, 0xB2, 0x3E, 0x32, 0xBF, 0xF8, 0x74, 0x4E, + 0x65, 0x9F, 0x89, 0x8D, 0xE4, 0x0C, 0xC1, 0x89, 0xCF, 0x19, + 0xF0, 0xBC, 0x75, 0xDC, 0xE4, 0xEA, 0x23, 0x18, 0x23, 0xC2, + 0xD2, 0xA4, 0x96, 0xA6, 0xC2, 0x73, 0x41, 0x1E, 0xD8, 0x9D, + 0x02, 0x02, 0x35, 0x16, 0x61, 0x9B, 0x6F, 0xCC, 0x16, 0x80, + 0x2B, 0xA5, 0xE2, 0x9B, 0x63, 0x9B, 0x4E, 0x75, 0xBD, 0xBD, + 0xF3, 0x36, 0x16, 0x53, 0x6B, 0x34, 0x33, 0xF4, 0xBC, 0x05, + 0x79, 0x8A, 0x1F, 0x23, 0xD8, 0x36, 0xCC, 0xDB, 0x37, 0x5A, + 0x1E, 0xCE, 0x6D, 0x27, 0x7B, 0x6C, 0x66, 0x11, 0xE3, 0x96, + 0xAD, 0xC3, 0xF9, 0x57, 0xF9, 0xA7, 0x4C, 0x4F, 0x8E, 0x97, + 0x70, 0xB1, 0x70, 0xE9, 0x77, 0xF0, 0xC2, 0xD0, 0x79, 0x12, + 0x79, 0x3F, 0xDB, 0x71, 0x66, 0x48, 0xDB, 0x5A, 0xFC, 0xA7, + 0x8E, 0xE4, 0x1A, 0x93, 0xFE, 0x49, 0xF5, 0x7D, 0xEF, 0xC4, + 0x4B, 0xC1, 0x10, 0x2A, 0xD6, 0xF0, 0x5D, 0xC4, 0x80, 0x8B, + 0x9C, 0x2E, 0x44, 0xFB, 0x71, 0xD3, 0xA3, 0x80, 0xFB, 0x77, + 0x60, 0x16, 0xAD, 0x0B, 0xEC, 0x75, 0x9A, 0x58, 0x4B, 0x6E, + 0xD8, 0xFD, 0xE9, 0x41, 0x46, 0x85, 0x43, 0xFD, 0x82, 0x53, + 0x51, 0x65, 0xF8, 0xD0, 0x26, 0x2B, 0xF2, 0xF9, 0xE9, 0x26, + 0xD7, 0x15, 0x84, 0x31, 0x80, 0xAE, 0xFD, 0xA5, 0x30, 0x65, + 0xEE, 0x52, 0xCA, 0x3C, 0x76, 0x16, 0x91, 0x5A, 0x26, 0x49, + 0x1A, 0x28, 0xC7, 0x81, 0x10, 0x95, 0xB8, 0x96, 0x09, 0x50, + 0x6D, 0xB1, 0x64, 0xA2, 0x87, 0xCF, 0x38, 0x3C, 0x3C, 0x6E, + 0x0B, 0x96, 0x97, 0xFC, 0x81, 0xBD, 0x7D, 0xE7, 0xCC, 0xB6, + 0xF7, 0xE8, 0x15, 0x05, 0xAF, 0xDE, 0x1C, 0x68, 0xC0, 0xCF, + 0xF8, 0x68, 0x94, 0x90, 0x7B, 0x7D, 0x98, 0x57, 0xDC, 0x86, + 0x6D, 0x69, 0xD6, 0x98, 0x62, 0x0F, 0x38, 0x99, 0x93, 0x99, + 0x55, 0xD6, 0xA5, 0x8C, 0x94, 0x62, 0xCB, 0xD9, 0xE8, 0xA4, + 0x7C, 0xDF, 0x21, 0xF4, 0x36, 0x65, 0xCF, 0x3F, 0xE4, 0x10, + 0xA5, 0xB4, 0x71, 0x08, 0x65, 0x98, 0x59, 0x70, 0x19, 0x7E, + 0x27, 0x13, 0x71, 0x3F, 0xD2, 0x91, 0x20, 0xFF, 0x53, 0xDB, + 0xD2, 0xD4, 0x07, 0x3A, 0x49, 0x72, 0x05, 0x66, 0xED, 0x7D, + 0xBC, 0x61, 0x70, 0x7F, 0x64, 0x41, 0xDD, 0xB3, 0x1B, 0x03, + 0xB8, 0x20, 0xE1, 0x5D, 0x07, 0x39, 0xFC, 0xD2, 0x30, 0x72, + 0xE8, 0x0F, 0xA7, 0xA2, 0x71, 0xE8, 0x3D, 0xD9, 0x2B, 0x5B, + 0xB4, 0x97, 0x2B, 0xC3, 0x58, 0xE1, 0x2B, 0x0F, 0xAA, 0x8C, + 0x5A, 0x72, 0xC7, 0xBB, 0xB6, 0x59, 0x2B, 0x73, 0x39, 0x9A, + 0x20, 0xE5, 0x9A, 0x70, 0x30, 0x7B, 0x28, 0xBE, 0xD6, 0x6A, + 0x04, 0x18, 0x41, 0xEF, 0x18, 0xCD, 0xB5, 0x69, 0xB6, 0x00, + 0x50, 0xEE, 0xF9, 0x45, 0x2F, 0x86, 0xEE, 0x04, 0xBE, 0xF8, + 0x88, 0x9E, 0x0D, 0xAC, 0x1B, 0xA9, 0xD1, 0xC1, 0xA5, 0x3E, + 0xF6, 0xD9, 0x78, 0x99, 0x9D, 0x2E, 0x26, 0x6C, 0xCA, 0x7C, + 0x4C, 0xC7, 0xAF, 0xAB, 0xF0, 0xBB, 0x93, 0x32, 0x03, 0x22, + 0xAF, 0x27, 0x6A, 0x9F, 0x53, 0x77, 0xA9, 0x6C, 0x83, 0xA2, + 0x46, 0x15, 0x61, 0x6C, 0xB3, 0x08, 0x6F, 0x5B, 0x85, 0x73, + 0x8A, 0xCD, 0x8A, 0xB0, 0x70, 0xAC, 0xA5, 0x22, 0x18, 0x87, + 0x54, 0x91, 0x6B, 0x34, 0x7F, 0x0B, 0x4E, 0xCA, 0x44, 0xB3, + 0xBE, 0xB0, 0x77, 0x28, 0x85, 0x73, 0xDD, 0x29, 0x70, 0x53, + 0xD9, 0xA2, 0x4F, 0x12, 0xCB, 0x41, 0xFD, 0x99, 0x27, 0xC7, + 0xA9, 0xCF, 0xB7, 0x5B, 0xFB, 0xCC, 0x77, 0xBA, 0x12, 0xE1, + 0xD6, 0xF6, 0x7C, 0x22, 0xB4, 0xED, 0xB0, 0xA0, 0x71, 0x59, + 0xD2, 0xF3, 0x14, 0xB2, 0x7C, 0x4A, 0x0A, 0xD6, 0x43, 0x10, + 0xA0, 0xF6, 0xC0, 0x6F, 0xB4, 0x31, 0x8F, 0x7B, 0xF8, 0x5A, + 0xC9, 0x91, 0x0F, 0x7A, 0xE5, 0xDF, 0x29, 0x11, 0x66, 0xFF, + 0x4C, 0x73, 0xA6, 0xC7, 0xA0, 0xCC, 0x7B, 0x73, 0x79, 0x36, + 0x1D, 0x5E, 0x7C, 0xE2, 0xC9, 0xF7, 0x56, 0xC4, 0x88, 0x71, + 0xC1, 0x03, 0xEE, 0xE7, 0xE0, 0xEE, 0x12, 0xD7, 0x3D, 0x3A, + 0xB2, 0x91, 0x51, 0xE1, 0x18, 0xFE, 0x66, 0x22, 0x84, 0xA6, + 0xC3, 0xD2, 0x54, 0xE9, 0xE5, 0xF8, 0xDB, 0xF1, 0xF9, 0x6A, + 0x01, 0x61, 0xCF, 0x3D, 0xDA, 0x89, 0x5B, 0xED, 0x89, 0x10, + 0xBA, 0x18, 0xB8, 0xBA, 0x66, 0x38, 0x0D, 0x37, 0xEC, 0x1E, + 0xF7, 0x06, 0xD6, 0xC0, 0x84, 0x06, 0x2F, 0x43, 0xBD, 0x50, + 0xA0, 0x05, 0x9B, 0x50, 0xCD, 0xBB, 0xB7, 0x93, 0xF0, 0x70, + 0x50, 0xB7, 0x03, 0x0F, 0x27, 0x70, 0x47, 0x8E, 0xEB, 0x14, + 0xE0, 0x81, 0xBC, 0x7F, 0xA5, 0x60, 0xB0, 0x09, 0xCA, 0x38, + 0xCB, 0x59, 0x85, 0x49, 0xB3, 0xD4, 0x29, 0x50, 0xE1, 0x04, + 0xBD, 0x9F, 0x6C, 0xA5, 0x76, 0xCB, 0xE6, 0x79, 0xED, 0xDD, + 0xB8, 0x98, 0xA9, 0x94, 0xDD, 0xD3, 0x2E, 0xE0, 0xEA, 0xCD, + 0xD3, 0x34, 0xDA, 0x78, 0xBE, 0x7A, 0xC9, 0x8C, 0xD6, 0x12, + 0x5B, 0xD0, 0x36, 0x11, 0x79, 0x52, 0xCA, 0xA1, 0xCC, 0x3D, + 0x5B, 0x1F, 0x35, 0x80, 0xCC, 0x56, 0xDA, 0xC9, 0x88, 0xB7, + 0xD3, 0x28, 0x86, 0x6F, 0x4E, 0x20, 0x56, 0x56, 0x62, 0x12, + 0x79, 0xDA, 0x3F, 0x75, 0xEC, 0x89, 0xDC, 0x90, 0x44, 0xAE, + 0xB8, 0x0E, 0x34, 0x76, 0xF9, 0xAE, 0xDF, 0x2C, 0x28, 0x0F, + 0xCF, 0x28, 0x0B, 0x7B, 0x8A, 0xC4, 0x9B, 0x0B, 0x3C, 0x3E, + 0xC2, 0x70, 0x88, 0x71, 0xED, 0x3B, 0x3D, 0x61, 0x73, 0xDC, + 0x1B, 0x1A, 0x89, 0x16, 0xE2, 0x36, 0x50, 0x96, 0x38, 0x44, + 0xB1, 0xB6, 0x23, 0xB1, 0x83, 0x51, 0x43, 0x7C, 0x37, 0x9C, + 0x83, 0xDB, 0x63, 0x3E, 0x02, 0x42, 0xFA, 0xE9, 0x0B, 0x22, + 0xCB, 0xA5, 0x1F, 0x09, 0x03, 0x1C, 0xD0, 0xAD, 0xCB, 0xEE, + 0xB5, 0x3F, 0xFC, 0xCD, 0x80, 0x04, 0x63, 0x44, 0x4F, 0x3F, + 0x2B, 0x17, 0x66, 0xE0, 0xA7, 0x1E, 0xA2, 0xB5, 0xE3, 0xD3, + 0x23, 0x76, 0xF9, 0x75, 0x7C, 0x39, 0x5C, 0x6A, 0x64, 0xF8, + 0x61, 0xDE, 0x66, 0x3F, 0xCD, 0x4F, 0x06, 0xEF, 0x9C, 0xCA, + 0x43, 0xA9, 0x32, 0x30, 0xDC, 0xB8, 0xA2, 0xE0, 0xAA, 0xEB, + 0x4D, 0x30, 0x8D, 0x0C, 0xD1, 0x5E, 0x04, 0xEE, 0xED, 0x46, + 0x07, 0x9C, 0xF4, 0xD8, 0xD5, 0x78, 0x9A, 0x51, 0x93, 0xC6, + 0x95, 0x5C, 0x12, 0x48, 0x2B, 0x92, 0x7A, 0xE4, 0x57, 0x3D, + 0x37, 0xEC, 0xA0, 0x19, 0xEC, 0x0A, 0x45, 0x0B, 0xFE, 0x9F, + 0x5F, 0xA0, 0xB3, 0x05, 0xEE, 0xF9, 0x87, 0x76, 0x5C, 0xC1, + 0xAD, 0x92, 0x79, 0x50, 0xAC, 0x70, 0xB6, 0xE8, 0xBB, 0x7C, + 0xCA, 0xC2, 0x49, 0xAD, 0xB0, 0xDA, 0xD0, 0x28, 0x90, 0xC2, + 0xEE, 0x3D, 0x4C, 0xCD, 0xC8, 0x41, 0x89, 0x5C, 0x65, 0xB9, + 0x1C, 0xCA, 0x67, 0x7B, 0xEF, 0x0D, 0x7B, 0x69, 0x4B, 0x8E, + 0x51, 0x0D, 0xF7, 0x70, 0xB7, 0xB3, 0x4E, 0xC8, 0x87, 0x8D, + 0xD1, 0xDD, 0x20, 0x11, 0x3C, 0x34, 0xA3, 0x3B, 0x6F, 0xDD, + 0xF5, 0xB2, 0xB1, 0x21, 0x9A, 0xE0, 0x4A, 0xF0, 0xB9, 0xEB, + 0x64, 0xDB, 0xC6, 0xD6, 0x64, 0x8F, 0x1A, 0x2C, 0x40, 0x0A, + 0x24, 0xF4, 0x0C, 0x0F, 0x60, 0x04, 0xBA, 0x9D, 0x3A, 0xE7, + 0x05, 0x58, 0xB5, 0x29, 0xD4, 0xD3, 0x64, 0xED, 0xCE, 0x47, + 0x7B, 0xB0, 0x6E, 0xCC, 0x2F, 0x46, 0x3A, 0xFE, 0x11, 0xC6, + 0x6B, 0x91, 0x51, 0x6A, 0x17, 0xCD, 0x03, 0x35, 0x0E, 0x1C, + 0x0E, 0x8B, 0xDD, 0x46, 0x4F, 0x5D, 0x9A, 0x5C, 0xE1, 0x14, + 0x99, 0xE8, 0xF2, 0xA4, 0xED, 0xCF, 0x6F, 0xC6, 0xC1, 0x67, + 0x36, 0x49, 0x1F, 0x1E, 0x42, 0x92, 0x4D, 0x32, 0x05, 0x4E, + 0xA6, 0xD7, 0xC0, 0xEC, 0xB0, 0x3E, 0xFD, 0xA1, 0xA7, 0x08, + 0x6B, 0xE8, 0x7F, 0xCD, 0xF8, 0x3C, 0x53, 0x58, 0x4C, 0x97, + 0xE6, 0x8D, 0xFE, 0xA9, 0x49, 0x61, 0xD1, 0xF0, 0xA0, 0xC7, + 0xB4, 0x4F, 0xBE, 0xDD, 0x90, 0x92, 0x0B, 0xA0, 0x5E, 0x69, + 0xAC, 0xDA, 0x26, 0x99, 0xF8, 0xE3, 0x07, 0xB5, 0xB9, 0xB7, + 0x48, 0xC7, 0xA3, 0x64, 0x3E, 0xA0, 0xB6, 0xC1, 0xF8, 0x6E, + 0x23, 0xA3, 0x11, 0x52, 0xA8, 0x26, 0xBD, 0x1C, 0xAD, 0xEB, + 0xF7, 0xDF, 0xC6, 0x35, 0xB4, 0x92, 0xE5, 0xB0, 0x5B, 0x53, + 0x55, 0xAA, 0x6E, 0xAD, 0x36, 0x4B, 0xF0, 0xE5, 0x9E, 0x32, + 0xB6, 0xFF, 0x1C, 0x01, 0x35, 0x20, 0x5E, 0xAD, 0x3E, 0xA3, + 0x01, 0x5D, 0xA0, 0xC5, 0x1B, 0xC8, 0x69, 0xB8, 0xF2, 0x2B, + 0x2B, 0x69, 0xC4, 0x4E, 0xA3, 0xC6, 0x1C, 0xFE, 0xCC, 0x0C, + 0x79, 0x6E, 0xDD, 0xD4, 0x59, 0x93, 0x51, 0xA2, 0x41, 0x3A, + 0x7A, 0x7D, 0x19, 0x5C, 0x1A, 0x91, 0x3C, 0x68, 0x00, 0x42, + 0x58, 0x51, 0x26, 0x11, 0x1A, 0x1E, 0xDE, 0x3B, 0x64, 0x16, + 0xBC, 0xDC, 0x5A, 0xF7, 0x7E, 0x80, 0x04, 0x63, 0xED, 0xDB, + 0x68, 0x74, 0xC2, 0x6B, 0x36, 0x67, 0xFC, 0x81, 0xB3, 0x64, + 0xBC, 0xAC, 0xA4, 0x56, 0x55, 0x77, 0x86, 0x74, 0xE2, 0x68, + 0x02, 0xD5, 0x5A, 0x84, 0x8F, 0x0E, 0x7F, 0xA1, 0xE9, 0xA5, + 0x30, 0xEB, 0xB4, 0x3E, 0x31, 0x09, 0x7F, 0xE2, 0x21, 0x35, + 0x4F, 0xFA, 0x61, 0xD2, 0x42, 0xB5, 0xCC, 0x31, 0xDE, 0x9C, + 0xDD, 0x39, 0x71, 0x90, 0x69, 0x9C, 0xF3, 0x7B, 0x91, 0xB1, + 0x65, 0x44, 0x10, 0xEC, 0x5C, 0x31, 0xF5, 0xA5, 0x37, 0xFF, + 0x52, 0xDF, 0x21, 0x85, 0x8A, 0x08, 0x77, 0xD7, 0xEE, 0xCC, + 0xD8, 0x58, 0xEF, 0x5B, 0xDD, 0x12, 0xC0, 0x4E, 0xC2, 0x20, + 0xAD, 0x5E, 0x74, 0x37, 0xE0, 0x70, 0x1B, 0xBA, 0xA3, 0x84, + 0x39, 0x2C, 0x4F, 0x63, 0x77, 0x69, 0x6C, 0x60, 0x69, 0x00, + 0xF0, 0xCE, 0x19, 0x29, 0x62, 0xDA, 0x10, 0xD9, 0x15, 0x79, + 0xC5, 0x2B, 0xB0, 0xB3, 0x97, 0x8C, 0x98, 0x83, 0x9F, 0x25, + 0x3F, 0x56, 0x1F, 0x2C, 0x63, 0x77, 0xFA, 0xDB, 0x27, 0xDF, + 0x94, 0xAE, 0x08, 0x44, 0x75, 0x8A, 0xE8, 0x91, 0x72, 0xB0, + 0xD0, 0x93, 0xC5, 0x7B, 0xB1, 0xD0, 0xEB, 0xD8, 0xDD, 0x88, + 0x29, 0xF8, 0x36, 0xE7, 0x7C, 0xFD, 0x88, 0xFE, 0xA1, 0xEE, + 0x12, 0x9A, 0x0E, 0x84, 0x75, 0x15, 0xA8, 0xA0, 0xD7, 0xBC, + 0x72, 0x75, 0x7D, 0x4E, 0xDF, 0xEE, 0x30, 0x30, 0x23, 0x6D, + 0xCC, 0xE5, 0xD7, 0xFD, 0x11, 0xE0, 0x87, 0x65, 0xDE, 0xAA, + 0xF4, 0x2C, 0x64, 0x74, 0x1A, 0x0C, 0x7A, 0x0A, 0x5B, 0x85, + 0xF3, 0x35, 0xB8, 0x41, 0x27, 0x14, 0xFC, 0x2A, 0x8D, 0x28, + 0xD0, 0xA7, 0xDB, 0xB0, 0xD9, 0x5A, 0xA9, 0x0F, 0x0B, 0x2F, + 0xE0, 0x8E, 0x37, 0x82, 0x5E, 0x8E, 0x1E, 0x2F, 0xC2, 0xA6, + 0xF5, 0x89, 0x54, 0x77, 0x49, 0x49, 0xDC, 0xF4, 0x03, 0xF2, + 0x04, 0xD6, 0xC0, 0x43, 0xB1, 0x13, 0x2B, 0x0C, 0xC2, 0x14, + 0x93, 0x5A, 0x90, 0x20, 0x87, 0xA0, 0x4A, 0xB2, 0xD7, 0x25, + 0x81, 0x79, 0x3C, 0x9C, 0xF6, 0x92, 0xBB, 0x26, 0xB0, 0x25, + 0x93, 0x05, 0x60, 0xEC, 0x56, 0x3C, 0x92, 0x41, 0x63, 0x52, + 0x0F, 0x95, 0x06, 0x7D, 0xE8, 0x46, 0x90, 0x39, 0x69, 0xEA, + 0x6B, 0xA6, 0x64, 0x09, 0x7B, 0x2F, 0x34, 0xE0, 0x21, 0x29, + 0xDA, 0xE3, 0xCF, 0xFE, 0xA7, 0x8E, 0x14, 0x3A, 0xD7, 0x53, + 0x26, 0xD7, 0x82, 0x0E, 0x2A, 0x00, 0x43, 0xEB, 0x6A, 0x23, + 0x75, 0x28, 0xD0, 0x9B, 0x85, 0xE0, 0xFB, 0x14, 0x19, 0xF3, + 0x6A, 0x73, 0x6C, 0x97, 0x0E, 0x21, 0xFC, 0x0F, 0x26, 0xC5, + 0xCE, 0xB7, 0xC6, 0x59, 0xA2, 0xE6, 0x4C, 0xF4, 0xC7, 0xBB, + 0x9B, 0xA8, 0xFA, 0x12, 0xC7, 0xDA, 0x33, 0x26, 0x69, 0x83, + 0x49, 0xA8, 0x0A, 0x3E, 0xF0, 0xD4 +}; +static const int sizeof_bench_dilithium_level5_key = sizeof(bench_dilithium_level5_key); + +/* certs/dilithium/bench_dilithium_aes_level2_key.der */ +static const unsigned char bench_dilithium_aes_level2_key[] = +{ + 0x30, 0x82, 0x0F, 0x1A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x0B, + 0x04, 0x04, 0x04, 0x82, 0x0F, 0x04, 0x04, 0x82, 0x0F, 0x00, + 0xDF, 0x3D, 0x6F, 0x4F, 0x6C, 0x02, 0x60, 0x28, 0x0D, 0xD1, + 0x31, 0xF7, 0xA6, 0xAF, 0x05, 0x6E, 0xCE, 0x17, 0xBC, 0x6A, + 0x1B, 0xF7, 0xCB, 0x0D, 0x3F, 0x06, 0x8A, 0x01, 0x9A, 0xF2, + 0x40, 0xF9, 0x70, 0xD7, 0x18, 0x17, 0xDF, 0xD2, 0x8D, 0x9A, + 0xFF, 0xC9, 0x44, 0x27, 0xDF, 0xCD, 0xAA, 0x41, 0x15, 0xBB, + 0xDF, 0x53, 0x98, 0x20, 0xC1, 0x26, 0x28, 0xC0, 0x3B, 0x58, + 0xFF, 0xA0, 0x34, 0x8A, 0xA2, 0x36, 0x8E, 0x9A, 0xA1, 0x87, + 0x8B, 0x55, 0xBF, 0x04, 0xA8, 0x3D, 0xA6, 0x23, 0x22, 0xF9, + 0x26, 0xA4, 0xC1, 0xF0, 0xEF, 0x11, 0x3D, 0xAA, 0x49, 0x91, + 0xAA, 0xAB, 0x90, 0xAF, 0x6C, 0x42, 0x0A, 0x38, 0x48, 0x21, + 0x17, 0x4C, 0x01, 0x41, 0x0C, 0x09, 0x06, 0x51, 0xD4, 0x20, + 0x00, 0xCC, 0xB2, 0x84, 0x49, 0x18, 0x24, 0xE3, 0x30, 0x66, + 0xD9, 0x06, 0x70, 0xC8, 0xB2, 0x44, 0x24, 0x08, 0x11, 0x0B, + 0x90, 0x29, 0xE2, 0x86, 0x81, 0xE3, 0x28, 0x0E, 0xA2, 0x92, + 0x50, 0x0C, 0x31, 0x6D, 0x10, 0xA9, 0x4C, 0xA4, 0x48, 0x60, + 0x03, 0x36, 0x10, 0x64, 0x80, 0x91, 0x43, 0xA8, 0x68, 0x60, + 0x42, 0x20, 0x19, 0x44, 0x80, 0x51, 0x82, 0x64, 0x18, 0x87, + 0x09, 0x51, 0x84, 0x29, 0x40, 0x34, 0x31, 0x91, 0x42, 0x8D, + 0x09, 0xB4, 0x6C, 0xD3, 0xC6, 0x68, 0x58, 0x00, 0x12, 0x82, + 0x44, 0x4C, 0x21, 0x29, 0x6C, 0x44, 0x12, 0x65, 0x14, 0x22, + 0x48, 0x24, 0x46, 0x2D, 0xC3, 0x02, 0x08, 0x43, 0xC4, 0x61, + 0x52, 0x04, 0x8D, 0x92, 0x44, 0x45, 0x91, 0x20, 0x50, 0x01, + 0x41, 0x84, 0x5A, 0xA0, 0x0C, 0x09, 0xC1, 0x05, 0xD2, 0x28, + 0x86, 0x22, 0x09, 0x84, 0x04, 0xA6, 0x29, 0x9C, 0x12, 0x2A, + 0x61, 0x16, 0x90, 0xC4, 0x22, 0x82, 0x80, 0x92, 0x65, 0x5B, + 0x00, 0x82, 0x40, 0xB0, 0x40, 0x04, 0xA6, 0x25, 0x1A, 0x36, + 0x09, 0xD3, 0x92, 0x10, 0x62, 0xA6, 0x10, 0xA1, 0x32, 0x51, + 0x11, 0x14, 0x20, 0x1C, 0xB4, 0x65, 0x94, 0x38, 0x06, 0x49, + 0x20, 0x01, 0x1A, 0x27, 0x0C, 0xD2, 0x84, 0x31, 0x02, 0x49, + 0x28, 0x1B, 0x44, 0x45, 0x0C, 0x01, 0x60, 0x5C, 0x00, 0x2E, + 0x23, 0x31, 0x41, 0x8B, 0x14, 0x4A, 0xC0, 0x48, 0x45, 0x04, + 0xC0, 0x4C, 0x40, 0x02, 0x92, 0x94, 0x48, 0x48, 0x5A, 0x36, + 0x91, 0x1C, 0xA2, 0x21, 0x8B, 0x42, 0x82, 0x09, 0x01, 0x46, + 0x11, 0x85, 0x6D, 0x1C, 0x35, 0x62, 0xC9, 0x34, 0x45, 0xC1, + 0x42, 0x6C, 0x40, 0x28, 0x6E, 0x1A, 0x27, 0x4C, 0x19, 0x09, + 0x6D, 0x92, 0xB8, 0x41, 0x04, 0x31, 0x4D, 0xC4, 0x20, 0x4A, + 0x8C, 0x84, 0x6D, 0xD1, 0x32, 0x02, 0xE1, 0x82, 0x21, 0x41, + 0x34, 0x44, 0xC3, 0x14, 0x49, 0xD9, 0x22, 0x8D, 0x63, 0x32, + 0x48, 0x99, 0xB8, 0x0C, 0x03, 0x21, 0x69, 0xCC, 0x30, 0x40, + 0xA4, 0x32, 0x4D, 0xD8, 0xB8, 0x09, 0x00, 0x17, 0x45, 0x02, + 0xC0, 0x68, 0xCA, 0xA4, 0x91, 0x02, 0x99, 0x8D, 0x9B, 0x46, + 0x24, 0x42, 0x28, 0x8C, 0x90, 0x94, 0x61, 0x1C, 0xC3, 0x0C, + 0x00, 0x37, 0x89, 0x1C, 0x99, 0x8D, 0x83, 0xB6, 0x64, 0x01, + 0xC1, 0x88, 0xC0, 0x30, 0x44, 0x9C, 0x82, 0x48, 0x82, 0x22, + 0x29, 0x9C, 0x96, 0x30, 0x4C, 0x10, 0x50, 0x24, 0x07, 0x6E, + 0x98, 0x46, 0x8A, 0xC4, 0x38, 0x89, 0x60, 0x90, 0x11, 0x24, + 0x46, 0x00, 0x58, 0x80, 0x69, 0x11, 0x33, 0x85, 0x43, 0xB2, + 0x90, 0xD1, 0x20, 0x4C, 0x44, 0xA6, 0x28, 0xA1, 0x44, 0x45, + 0x01, 0xB7, 0x85, 0x9B, 0x22, 0x6C, 0x11, 0x22, 0x04, 0x13, + 0x13, 0x05, 0x01, 0x22, 0x88, 0x4C, 0x30, 0x80, 0x00, 0xC8, + 0x20, 0x51, 0xC2, 0x28, 0x10, 0x04, 0x71, 0x00, 0x14, 0x0A, + 0x89, 0x94, 0x05, 0x4A, 0x28, 0x6E, 0x88, 0x24, 0x52, 0x03, + 0x22, 0x69, 0xDC, 0x16, 0x71, 0x0C, 0x25, 0x6D, 0x10, 0x07, + 0x10, 0xCB, 0x12, 0x85, 0x53, 0x32, 0x2C, 0x0B, 0x94, 0x40, + 0x54, 0x88, 0x11, 0x99, 0x42, 0x69, 0x40, 0x00, 0x65, 0xA2, + 0x12, 0x0A, 0x22, 0xC4, 0x88, 0x99, 0x32, 0x31, 0x0C, 0xA5, + 0x91, 0x11, 0xC5, 0x49, 0x1A, 0x37, 0x31, 0x0A, 0x11, 0x88, + 0xD1, 0x28, 0x0C, 0x09, 0x30, 0x49, 0x13, 0x04, 0x02, 0x01, + 0x91, 0x0C, 0x0A, 0x15, 0x25, 0xC8, 0xC6, 0x28, 0x24, 0x46, + 0x86, 0x82, 0x02, 0x42, 0x98, 0x00, 0x69, 0x11, 0x16, 0x32, + 0xE4, 0x24, 0x31, 0x04, 0x88, 0x31, 0xE2, 0x30, 0x61, 0x0B, + 0x01, 0x6D, 0x43, 0xA2, 0x00, 0x19, 0x42, 0x60, 0x12, 0xA0, + 0x61, 0x8C, 0x08, 0x31, 0x12, 0xA3, 0x90, 0x1A, 0x12, 0x8C, + 0x1A, 0xA5, 0x85, 0x0B, 0x34, 0x45, 0x03, 0x39, 0x51, 0x1B, + 0x14, 0x44, 0x99, 0x24, 0x10, 0x5B, 0xB8, 0x4D, 0x48, 0x96, + 0x84, 0x8C, 0x94, 0x84, 0x63, 0x28, 0x21, 0x53, 0x80, 0x80, + 0x23, 0x23, 0x86, 0xD3, 0x90, 0x31, 0xDB, 0x00, 0x28, 0x18, + 0x09, 0x48, 0x01, 0xA1, 0x91, 0x8C, 0x38, 0x09, 0xE0, 0xB8, + 0x20, 0xD0, 0x30, 0x22, 0x61, 0xB6, 0x71, 0xD3, 0xC8, 0x05, + 0x00, 0x80, 0x09, 0x9C, 0x28, 0x8D, 0x83, 0x00, 0x2A, 0x92, + 0x00, 0x41, 0x90, 0x12, 0x12, 0x40, 0x18, 0x46, 0x19, 0x03, + 0x8A, 0x19, 0x23, 0x66, 0x08, 0x09, 0x32, 0xD9, 0x46, 0x69, + 0xE0, 0x26, 0x2C, 0x04, 0x80, 0x85, 0x04, 0x94, 0x29, 0x1B, + 0x44, 0x01, 0x92, 0x34, 0x45, 0xD0, 0xC6, 0x50, 0x02, 0x46, + 0x45, 0x24, 0x22, 0x90, 0x5B, 0x34, 0x50, 0x23, 0x22, 0x24, + 0x18, 0x36, 0x0D, 0x1B, 0x04, 0x68, 0xD9, 0xB8, 0x11, 0x49, + 0xC0, 0x89, 0x19, 0xA5, 0x84, 0x00, 0x99, 0x0D, 0x22, 0xA6, + 0x88, 0x82, 0x90, 0x6C, 0x42, 0x80, 0x2D, 0xC0, 0x88, 0x40, + 0x93, 0x84, 0x51, 0x9C, 0x46, 0x40, 0xDA, 0x04, 0x32, 0xD9, + 0x02, 0x84, 0x02, 0x44, 0x2E, 0x08, 0xB5, 0x81, 0x20, 0xA6, + 0x71, 0xD0, 0x26, 0x0A, 0x23, 0xC7, 0x70, 0x41, 0x42, 0x41, + 0x0B, 0x43, 0x4C, 0x20, 0xC9, 0x30, 0x5A, 0x22, 0x8C, 0x14, + 0xC5, 0x20, 0xA3, 0x30, 0x66, 0xE4, 0x10, 0x85, 0xC3, 0xB2, + 0x91, 0xA1, 0xA6, 0x05, 0x98, 0xA2, 0x80, 0x00, 0x81, 0x29, + 0x24, 0x47, 0x32, 0x10, 0x26, 0x2E, 0xCC, 0xA0, 0x0D, 0x22, + 0x80, 0x51, 0xCB, 0x46, 0x4A, 0x91, 0x04, 0x85, 0xD0, 0x90, + 0x88, 0x94, 0xC6, 0x11, 0x86, 0x3F, 0xAE, 0xE7, 0xA7, 0xD2, + 0xAB, 0x91, 0x16, 0x25, 0x66, 0x80, 0x76, 0x84, 0x42, 0x9E, + 0xE2, 0xDB, 0x76, 0xE3, 0xE7, 0xF8, 0xB8, 0x6E, 0x21, 0x0E, + 0x36, 0x8D, 0xB7, 0xE4, 0xAD, 0x3C, 0xC0, 0xDD, 0xC2, 0xDB, + 0xC7, 0x78, 0xFA, 0x83, 0x8B, 0x46, 0xAF, 0xD7, 0x2C, 0xF9, + 0xC1, 0x55, 0xFA, 0x94, 0x80, 0x27, 0x33, 0xEF, 0x4B, 0x4E, + 0x2E, 0x3E, 0x8A, 0xDE, 0x83, 0x00, 0xDB, 0x61, 0x4A, 0x0D, + 0x8D, 0x6B, 0xEC, 0x73, 0xDE, 0x2F, 0xA1, 0xBC, 0xC5, 0x00, + 0xB9, 0xDF, 0x91, 0x0A, 0x3A, 0xD6, 0x2F, 0x9E, 0xE3, 0xED, + 0x7D, 0x9B, 0xEB, 0x9A, 0x70, 0xD0, 0x28, 0x0A, 0x7F, 0xDC, + 0x36, 0x38, 0x51, 0x0F, 0xDD, 0xD5, 0x3B, 0xFD, 0x0C, 0xA2, + 0x1A, 0xF0, 0x77, 0x92, 0x7F, 0x47, 0x92, 0x1C, 0x09, 0xDE, + 0x8B, 0xAD, 0x09, 0x82, 0x6F, 0x40, 0xC1, 0xDA, 0xE8, 0x01, + 0x19, 0x75, 0xC1, 0xE3, 0x74, 0xA4, 0x6E, 0x23, 0xEF, 0xBA, + 0xD0, 0x19, 0x4B, 0xDF, 0xB7, 0x15, 0x3C, 0x91, 0x59, 0x17, + 0xCD, 0x63, 0x44, 0x68, 0xDC, 0xBB, 0xBF, 0x6D, 0x81, 0xC5, + 0x05, 0x27, 0x94, 0x5C, 0x3E, 0xB1, 0x02, 0x07, 0x61, 0xE7, + 0x26, 0x70, 0xB6, 0x9A, 0x0B, 0x1F, 0x3F, 0x7D, 0x60, 0xE9, + 0xED, 0xDC, 0xB5, 0xCD, 0x63, 0x0E, 0x96, 0xB2, 0x65, 0x76, + 0x29, 0x10, 0xF3, 0x5D, 0xC2, 0x1D, 0xC6, 0x18, 0xE7, 0x07, + 0x3A, 0xE2, 0x19, 0xEC, 0xE5, 0xE7, 0x1A, 0xB6, 0xE1, 0xAE, + 0x38, 0xE6, 0xDB, 0xB8, 0x81, 0x42, 0x8E, 0x24, 0x2A, 0xF6, + 0xE7, 0x28, 0xBB, 0x3B, 0xF9, 0x3F, 0x0B, 0x8D, 0x4D, 0xE5, + 0x62, 0xC3, 0x82, 0x70, 0xD2, 0x67, 0x0C, 0x44, 0xFA, 0x9C, + 0x86, 0xF0, 0x72, 0x5E, 0x9F, 0xED, 0x42, 0x4E, 0xE8, 0xD8, + 0xAE, 0xB6, 0x45, 0xC8, 0xEA, 0x4A, 0xD8, 0xD7, 0x38, 0xDC, + 0xB6, 0x8D, 0x81, 0xF7, 0x2B, 0x2E, 0xF6, 0x5E, 0x03, 0xF3, + 0x45, 0x91, 0x9B, 0x5E, 0x5C, 0xF2, 0xDA, 0x86, 0x55, 0xB0, + 0x92, 0xC0, 0x88, 0x09, 0x00, 0x4F, 0xE2, 0x01, 0x0B, 0x3C, + 0xDC, 0x3C, 0x67, 0x38, 0xF0, 0x26, 0x01, 0x49, 0x35, 0x14, + 0x23, 0x52, 0x1D, 0x2D, 0x1E, 0x10, 0x72, 0x7D, 0x57, 0xB6, + 0x47, 0x08, 0xBA, 0x1E, 0x92, 0x0F, 0x94, 0x23, 0x18, 0x02, + 0x0F, 0x6E, 0x80, 0xEA, 0x12, 0xB4, 0xBC, 0x4E, 0x89, 0xA7, + 0x4C, 0x77, 0x63, 0x2E, 0x28, 0xB4, 0x11, 0xF1, 0x20, 0xD4, + 0xF1, 0xAE, 0x52, 0x09, 0x56, 0x65, 0xDB, 0xD2, 0xAA, 0xFF, + 0x2F, 0xCA, 0x23, 0x9A, 0xD1, 0x98, 0x91, 0x50, 0x4C, 0x79, + 0xDA, 0x56, 0x56, 0x4D, 0x04, 0x54, 0xAB, 0x74, 0x97, 0xDE, + 0xA2, 0xF2, 0xDF, 0xD0, 0x30, 0x13, 0x86, 0x9B, 0x0F, 0xC7, + 0xFE, 0xFF, 0x48, 0x7A, 0x8E, 0x33, 0x8C, 0x59, 0xBB, 0x07, + 0x16, 0x7D, 0x99, 0x4E, 0xA9, 0x88, 0x1A, 0xA1, 0xE1, 0x87, + 0x70, 0xFD, 0x13, 0xC7, 0xBB, 0x0D, 0xBD, 0x74, 0xAC, 0x93, + 0xDF, 0x84, 0x01, 0xA0, 0x8D, 0xB1, 0x0D, 0x9B, 0x0F, 0xE9, + 0x2A, 0xC3, 0x9F, 0xC8, 0x1E, 0xA6, 0xE5, 0x7A, 0x56, 0xCE, + 0xA2, 0xA8, 0x34, 0xCC, 0x55, 0x00, 0x89, 0x63, 0xA1, 0xE3, + 0x2C, 0x35, 0xE0, 0x36, 0x9D, 0x5A, 0x58, 0xFD, 0xF5, 0x9A, + 0x9B, 0x26, 0xF8, 0x8F, 0x97, 0x90, 0xAC, 0x91, 0xCD, 0x57, + 0x86, 0x28, 0x3B, 0x96, 0x3F, 0xED, 0xD6, 0x33, 0x41, 0x36, + 0x77, 0xC9, 0xD6, 0x7C, 0x86, 0x8C, 0x4C, 0xA9, 0xC1, 0xFC, + 0x9B, 0x3D, 0x9C, 0xAE, 0x61, 0x12, 0x44, 0x8A, 0x0F, 0x09, + 0x0F, 0x7E, 0x6E, 0xB2, 0x0C, 0x2B, 0x6F, 0xE8, 0xB6, 0xD0, + 0x8B, 0xF5, 0x6D, 0x75, 0xE3, 0x31, 0x7A, 0x67, 0x47, 0x78, + 0xEE, 0xA4, 0x95, 0x39, 0x7C, 0xF4, 0x37, 0x3A, 0xBC, 0xB7, + 0xC3, 0xAC, 0x45, 0x99, 0x84, 0xE2, 0xB4, 0xF4, 0xB0, 0x92, + 0xA4, 0x60, 0x1B, 0xCA, 0x77, 0x0F, 0xB3, 0x17, 0x58, 0x4F, + 0x40, 0x6D, 0xAB, 0x23, 0x1B, 0x22, 0x07, 0x7E, 0x23, 0xF5, + 0x8C, 0xB7, 0xAF, 0x01, 0xE1, 0x0E, 0x57, 0x5E, 0x9D, 0x37, + 0xDF, 0xDF, 0xF7, 0xC5, 0x72, 0xC5, 0x7A, 0xEA, 0x53, 0xD1, + 0x7C, 0x8D, 0x80, 0x90, 0x3D, 0x29, 0x72, 0x61, 0x93, 0x8F, + 0x0C, 0x54, 0xF9, 0x2E, 0x46, 0x48, 0x21, 0xF2, 0xB7, 0x97, + 0x50, 0xAD, 0x55, 0xD1, 0x1D, 0x5F, 0xFC, 0x5D, 0x76, 0x50, + 0x9E, 0x40, 0x1D, 0xF6, 0x82, 0xFE, 0x7A, 0xDA, 0xB8, 0x5C, + 0xCA, 0x1D, 0x53, 0xEB, 0xAE, 0x98, 0x60, 0x25, 0x5E, 0x59, + 0x39, 0x86, 0xE8, 0xCA, 0x8D, 0x28, 0x89, 0x45, 0x83, 0xD1, + 0xC7, 0x66, 0x7A, 0x2E, 0x30, 0x9A, 0x76, 0xD6, 0x21, 0xB5, + 0x33, 0x43, 0x9F, 0xAF, 0xBF, 0x9E, 0xAE, 0xE7, 0xD6, 0xAA, + 0x13, 0x70, 0x35, 0x5F, 0x36, 0xF3, 0xAE, 0x4F, 0xD5, 0xB5, + 0xEE, 0x39, 0x1E, 0x40, 0x4B, 0x2C, 0xE2, 0xDC, 0x0B, 0x91, + 0xED, 0x61, 0xB8, 0x47, 0xD2, 0x3A, 0xAF, 0x9D, 0x29, 0x65, + 0xA6, 0x35, 0xD2, 0xB0, 0x3B, 0x44, 0x6B, 0x21, 0x6C, 0x24, + 0x6D, 0x4A, 0x2C, 0xA6, 0xF5, 0x5C, 0xC7, 0x32, 0x83, 0x84, + 0x96, 0xBB, 0x54, 0xDD, 0x5B, 0x44, 0x78, 0x90, 0x90, 0xB0, + 0x75, 0x2B, 0x1A, 0x7B, 0xDD, 0xC8, 0x7D, 0x72, 0xBA, 0xAC, + 0xAD, 0x38, 0x3D, 0xBA, 0x46, 0x38, 0x06, 0x9C, 0xF3, 0xA8, + 0x6C, 0x36, 0x98, 0x0B, 0xB8, 0xDC, 0xE9, 0x22, 0x77, 0x53, + 0x03, 0xD6, 0xA6, 0xBF, 0x18, 0x0E, 0x60, 0x19, 0xA7, 0x16, + 0x5F, 0x9A, 0x04, 0x3D, 0x01, 0xDD, 0x06, 0xCD, 0xD7, 0xA3, + 0xD6, 0x0D, 0x5D, 0x49, 0xB1, 0x85, 0xEA, 0xEC, 0xF5, 0xA2, + 0x97, 0x82, 0x98, 0xCB, 0x8E, 0xFA, 0xF5, 0xFB, 0x59, 0x16, + 0x1B, 0x51, 0x43, 0xFA, 0xD5, 0x46, 0xA7, 0x07, 0x21, 0x92, + 0xBB, 0x56, 0x67, 0xD8, 0xF3, 0x9E, 0x94, 0x18, 0x00, 0x9E, + 0xFA, 0x36, 0x1C, 0x1B, 0x24, 0x37, 0x48, 0x07, 0x91, 0xF7, + 0xD1, 0x4C, 0x53, 0x11, 0xBE, 0x15, 0x5D, 0x77, 0x1E, 0x86, + 0xE9, 0xF4, 0xBD, 0x69, 0x63, 0x75, 0x3E, 0x41, 0x6B, 0xC0, + 0x99, 0xD2, 0xC4, 0x2F, 0x5E, 0xAC, 0x64, 0xB7, 0xB2, 0xA9, + 0xEB, 0x88, 0x32, 0xD6, 0x93, 0x39, 0xCD, 0xBD, 0x16, 0x3D, + 0x27, 0xCA, 0xD3, 0xF6, 0x5B, 0x41, 0x23, 0xAC, 0xC5, 0x4C, + 0x3F, 0x72, 0x6A, 0xF7, 0x08, 0x31, 0x6B, 0x61, 0x21, 0x47, + 0xA1, 0x67, 0x54, 0xCE, 0x17, 0x01, 0x07, 0x7F, 0x41, 0xA1, + 0x7A, 0xC2, 0x73, 0xFD, 0x08, 0xE1, 0xF9, 0x9E, 0xBB, 0xE2, + 0x91, 0x0C, 0x21, 0x1D, 0x93, 0x82, 0x9F, 0x5D, 0xE2, 0x10, + 0x9B, 0x8F, 0x4D, 0xEC, 0x22, 0x76, 0x29, 0xE5, 0xF1, 0x0C, + 0x15, 0x62, 0x50, 0x1B, 0xB7, 0x6F, 0x6C, 0xDB, 0xE2, 0xDD, + 0x7F, 0x15, 0xD6, 0xFE, 0x7E, 0x22, 0x31, 0x7B, 0x53, 0x8D, + 0xC7, 0xB6, 0x30, 0xBB, 0xDD, 0x07, 0x7B, 0x18, 0x97, 0x43, + 0x5E, 0x3D, 0xDE, 0xC7, 0xAB, 0xAD, 0x04, 0x4B, 0x26, 0xF0, + 0xD3, 0xB6, 0xC5, 0xE2, 0x65, 0x9A, 0xCA, 0xF1, 0xD7, 0xBD, + 0x25, 0xFF, 0x25, 0x58, 0x42, 0xD2, 0x42, 0xDD, 0x3A, 0x95, + 0xE1, 0xF5, 0xAA, 0xE1, 0xDF, 0x52, 0x8D, 0x7B, 0xAA, 0x91, + 0x4B, 0xB3, 0xF1, 0x4F, 0x02, 0xDC, 0xA2, 0xEF, 0x98, 0xCD, + 0xDE, 0xFF, 0x8F, 0xAD, 0x77, 0xB5, 0x9C, 0x66, 0x22, 0x4F, + 0x38, 0xE5, 0xC8, 0x9F, 0x4C, 0xA9, 0xC1, 0xFB, 0x1F, 0xBB, + 0xCA, 0x21, 0xD7, 0xF5, 0xCC, 0xDD, 0x65, 0x84, 0x11, 0x85, + 0x4D, 0xFB, 0xF3, 0x6A, 0x7E, 0x0C, 0xE9, 0x1C, 0x18, 0xD1, + 0x19, 0x7C, 0x4B, 0x0A, 0xC3, 0x7A, 0x4D, 0x9C, 0x82, 0x02, + 0xF9, 0xF2, 0x4B, 0xF7, 0xA2, 0xED, 0x46, 0x1A, 0x9F, 0x21, + 0x18, 0x19, 0x97, 0x4A, 0x3D, 0xD8, 0x02, 0xE1, 0x25, 0xF4, + 0xDA, 0x8F, 0x71, 0x0B, 0xD4, 0x8F, 0x65, 0x72, 0x44, 0x2F, + 0x00, 0x6F, 0x25, 0xD0, 0x91, 0x26, 0x0F, 0xC0, 0x3E, 0xFF, + 0xC7, 0x83, 0x6F, 0x44, 0xDE, 0x91, 0xC8, 0xFC, 0x9A, 0xE5, + 0x25, 0xF5, 0x6E, 0x24, 0xAB, 0x60, 0x3A, 0x93, 0x34, 0xFB, + 0x69, 0x4E, 0xFA, 0x33, 0x64, 0x34, 0x20, 0x86, 0x75, 0x91, + 0xEF, 0xAE, 0xDC, 0xD2, 0xCD, 0xB7, 0x75, 0x5D, 0xCF, 0x53, + 0xF1, 0xB7, 0x25, 0x58, 0x01, 0x51, 0x41, 0xA8, 0xFA, 0xE7, + 0x85, 0x93, 0x3F, 0x63, 0x65, 0x59, 0x4D, 0x2C, 0x36, 0xB5, + 0x68, 0x80, 0xD9, 0x0A, 0xFF, 0x24, 0xF4, 0xE6, 0x92, 0xAA, + 0xF1, 0xDE, 0x9D, 0x8A, 0x1C, 0x95, 0xB5, 0x2C, 0x4A, 0x65, + 0xFF, 0x36, 0x80, 0xCD, 0xB9, 0x66, 0xAB, 0x5C, 0x38, 0xA7, + 0x4A, 0xD4, 0xDC, 0x19, 0x05, 0x7E, 0xC5, 0x89, 0xAF, 0x62, + 0x3A, 0xF7, 0xBA, 0x37, 0x6A, 0x20, 0x56, 0xBB, 0x93, 0x36, + 0xAF, 0x72, 0x9F, 0xC2, 0x27, 0x95, 0xE0, 0x9D, 0xB3, 0x44, + 0xC5, 0xA7, 0xF9, 0xE6, 0x55, 0x65, 0xD6, 0xFA, 0x3E, 0xB5, + 0x1E, 0xF0, 0x1D, 0x14, 0x8D, 0xF2, 0x35, 0xF7, 0x01, 0xA0, + 0x8B, 0x6F, 0xED, 0x20, 0xC2, 0x10, 0x36, 0x4F, 0x24, 0x75, + 0x3A, 0xA6, 0x3F, 0x88, 0x06, 0x0F, 0x26, 0x6E, 0x06, 0x5C, + 0xC3, 0x59, 0x74, 0x05, 0x85, 0xC2, 0x5D, 0xB0, 0x91, 0x25, + 0x15, 0x13, 0xEE, 0x32, 0x2F, 0x86, 0x5D, 0x4F, 0x93, 0x50, + 0x80, 0x1F, 0x16, 0x8D, 0x35, 0xCC, 0x9F, 0xB5, 0xAB, 0xD3, + 0x84, 0x56, 0xEF, 0x26, 0x56, 0x25, 0x9B, 0x6C, 0xAF, 0x62, + 0xDE, 0xC2, 0x97, 0xF5, 0x51, 0x52, 0x97, 0x0A, 0x06, 0x90, + 0xF8, 0xB7, 0xCE, 0x38, 0xD8, 0xE2, 0xBC, 0x4E, 0x36, 0x67, + 0x50, 0xF9, 0xE7, 0x48, 0x84, 0x9B, 0x73, 0x98, 0x0C, 0xC4, + 0xF8, 0xC8, 0x87, 0x9B, 0x04, 0xBC, 0x5F, 0x3E, 0x32, 0x00, + 0x4E, 0x89, 0xF8, 0xCA, 0xFA, 0x88, 0x69, 0x63, 0xD6, 0x51, + 0x62, 0x89, 0x5C, 0x83, 0x5B, 0xC0, 0x6C, 0xD1, 0x84, 0x77, + 0x94, 0x9A, 0x91, 0xFE, 0x53, 0x4A, 0x53, 0x13, 0x4A, 0xF9, + 0x8F, 0xB9, 0x84, 0x9A, 0xC8, 0xB6, 0x40, 0xEC, 0xA4, 0x22, + 0xCE, 0x57, 0x52, 0x2B, 0x4F, 0x11, 0x79, 0x7C, 0x42, 0xE8, + 0x37, 0x42, 0x84, 0xE6, 0x07, 0x94, 0xFA, 0x32, 0x14, 0x3E, + 0x2C, 0x7B, 0x6D, 0xE4, 0xAC, 0x10, 0xBF, 0xF3, 0x57, 0x8A, + 0x8E, 0x42, 0xBF, 0xEB, 0x17, 0x3B, 0xAC, 0x15, 0xA4, 0xAC, + 0x8F, 0x0E, 0xDA, 0x83, 0xF2, 0x73, 0x39, 0x37, 0x11, 0x9B, + 0x51, 0x96, 0x02, 0xA5, 0x11, 0xD3, 0xF6, 0xB6, 0x06, 0x72, + 0xEB, 0xED, 0x8E, 0x28, 0x4E, 0x55, 0x37, 0xF0, 0x71, 0xF9, + 0xAB, 0x26, 0x75, 0x00, 0x50, 0x78, 0x5A, 0x90, 0xCD, 0xCB, + 0xE2, 0x42, 0x9C, 0xE4, 0xD3, 0x65, 0x48, 0x45, 0x14, 0xDD, + 0xB2, 0x4A, 0x83, 0x64, 0x94, 0x6E, 0x96, 0x0B, 0xB1, 0x57, + 0xFE, 0xBE, 0x51, 0x5C, 0x33, 0x77, 0x7C, 0x5D, 0xBF, 0xF3, + 0xD1, 0x27, 0x25, 0x8A, 0x4B, 0x92, 0x8E, 0x53, 0x63, 0x68, + 0xB8, 0xA1, 0x62, 0xAD, 0x7B, 0x86, 0x12, 0xF9, 0x24, 0xFD, + 0x8F, 0x61, 0xEC, 0xE9, 0x5B, 0x5F, 0xA3, 0xA7, 0x2C, 0xC2, + 0xFB, 0x0C, 0x25, 0x17, 0x8E, 0x82, 0x2B, 0x1B, 0xDA, 0x58, + 0xEF, 0xB8, 0x6E, 0x64, 0xC3, 0x8D, 0xC7, 0x82, 0x26, 0x72, + 0xED, 0xDC, 0x97, 0x89, 0xF2, 0xD4, 0x40, 0x7C, 0xA5, 0x1B, + 0x04, 0x24, 0xFC, 0x2C, 0x36, 0x57, 0xA7, 0xB8, 0x1A, 0xA2, + 0x28, 0xB3, 0x16, 0x56, 0x77, 0xF7, 0xA3, 0x50, 0x62, 0x5E, + 0xFE, 0x72, 0x74, 0xB3, 0x76, 0xD9, 0xF4, 0xD5, 0xCA, 0x7E, + 0x14, 0x80, 0x98, 0xB9, 0x50, 0xA8, 0x22, 0xB5, 0x5B, 0xD6, + 0xB3, 0x1D, 0x8B, 0xFC, 0xA5, 0xD0, 0x0F, 0x65, 0x33, 0x3B, + 0x21, 0x55, 0x19, 0x40, 0x2E, 0x9C, 0xCB, 0xB5, 0xE0, 0x0B, + 0x68, 0x63, 0x95, 0x2F, 0x97, 0xCC, 0xB0, 0x5C, 0xF3, 0xA4, + 0x5C, 0x05, 0x21, 0x55, 0x3F, 0xBF, 0x5F, 0xE6, 0xF1, 0x4D, + 0x75, 0xAA, 0x69, 0xE0, 0x98, 0x0F, 0x39, 0x95, 0x33, 0x99, + 0xCF, 0xEA, 0x53, 0x45, 0x9C, 0x08, 0xCF, 0x7F, 0x58, 0x27, + 0x64, 0x71, 0x64, 0x20, 0x42, 0xBD, 0xA2, 0x07, 0x5C, 0xA6, + 0xEB, 0x4C, 0x65, 0x69, 0x4F, 0x16, 0x46, 0x58, 0x80, 0xD3, + 0xC3, 0x75, 0x91, 0x1F, 0x55, 0xD7, 0xF2, 0x87, 0xB3, 0x17, + 0x82, 0xC8, 0x12, 0x59, 0x56, 0x1B, 0x9C, 0x3C, 0xDF, 0x3D, + 0x6F, 0x4F, 0x6C, 0x02, 0x60, 0x28, 0x0D, 0xD1, 0x31, 0xF7, + 0xA6, 0xAF, 0x05, 0x6E, 0xCE, 0x17, 0xBC, 0x6A, 0x1B, 0xF7, + 0xCB, 0x0D, 0x3F, 0x06, 0x8A, 0x01, 0x9A, 0xF2, 0x40, 0xF9, + 0x0D, 0x01, 0x8E, 0xCC, 0x24, 0x0C, 0xEC, 0x50, 0x44, 0xD5, + 0x2F, 0xD5, 0x51, 0x10, 0xF5, 0x20, 0x3D, 0x87, 0x5A, 0x39, + 0xEE, 0x55, 0x2B, 0x9C, 0x34, 0xD8, 0xDF, 0xF6, 0x12, 0xA7, + 0xE0, 0xBC, 0xB2, 0x3D, 0x5D, 0x42, 0x1B, 0x2F, 0x9C, 0x96, + 0xAD, 0x1F, 0x2F, 0x89, 0x8B, 0x26, 0x80, 0xF8, 0xA4, 0x07, + 0xF9, 0x2E, 0xD4, 0xDE, 0xF5, 0x5A, 0x4D, 0xF0, 0x98, 0x7C, + 0x78, 0xF1, 0x15, 0xBA, 0x16, 0xC7, 0x97, 0x37, 0xF5, 0x6B, + 0x6A, 0x21, 0x66, 0x61, 0xD1, 0x0C, 0x9E, 0x6C, 0x31, 0x4E, + 0x20, 0xCB, 0x93, 0x90, 0xD5, 0x3C, 0x2F, 0xCE, 0xF6, 0xEE, + 0x9E, 0x8F, 0x10, 0xB9, 0xFD, 0x45, 0x32, 0x2D, 0x78, 0x8E, + 0x1C, 0x19, 0xC5, 0x07, 0xD9, 0xE4, 0xC0, 0x07, 0xB3, 0x2F, + 0xB6, 0x1E, 0xCE, 0x27, 0x0F, 0xF5, 0x97, 0x46, 0x95, 0xE4, + 0xC0, 0xE9, 0x42, 0x4A, 0xF9, 0xED, 0x3D, 0xD5, 0x37, 0x1A, + 0x2B, 0x63, 0x2A, 0xBA, 0x22, 0xD4, 0xC5, 0x67, 0x4B, 0x77, + 0xB8, 0xD2, 0xEA, 0xE3, 0x42, 0xDE, 0x54, 0x3B, 0xE2, 0x42, + 0xA4, 0x96, 0xDF, 0xAD, 0xEB, 0x34, 0xB5, 0xDA, 0x7E, 0xEF, + 0xC9, 0xBF, 0xA2, 0x11, 0x01, 0xC2, 0xF2, 0x0C, 0x5D, 0x6C, + 0xA8, 0x9A, 0x2F, 0xA9, 0x9A, 0x47, 0x17, 0x9D, 0xF8, 0x34, + 0x01, 0xC0, 0x8F, 0xBA, 0xE2, 0xC9, 0xA5, 0xA3, 0x02, 0x6C, + 0x18, 0x01, 0x4B, 0xEA, 0x44, 0xD4, 0x88, 0x9C, 0x36, 0x32, + 0x55, 0xA2, 0x7E, 0xBF, 0x74, 0x0C, 0xEC, 0x8C, 0x16, 0x4F, + 0x2E, 0xFB, 0xC2, 0xA9, 0xB6, 0x0E, 0xE6, 0x26, 0x59, 0x40, + 0x21, 0xB2, 0x97, 0x4C, 0x99, 0xA8, 0xE4, 0xAE, 0xED, 0x66, + 0x4C, 0x22, 0xAD, 0xD3, 0x62, 0x5A, 0x51, 0x23, 0x2F, 0x3C, + 0x1D, 0x3A, 0xF5, 0x92, 0x00, 0x7B, 0x42, 0xFA, 0xC1, 0x49, + 0x37, 0x42, 0xB7, 0x64, 0x8E, 0x1F, 0x5F, 0xA9, 0xB2, 0x03, + 0xFA, 0xDA, 0xAC, 0x48, 0x3F, 0xF3, 0x80, 0xE0, 0xE1, 0x3D, + 0x07, 0x99, 0x31, 0x9E, 0x7D, 0x2C, 0x9B, 0x19, 0x6F, 0x81, + 0x0D, 0x1F, 0x95, 0x04, 0x44, 0x47, 0x80, 0xE0, 0xD6, 0x7C, + 0x96, 0xF8, 0x6B, 0x1A, 0x2B, 0xAC, 0xC7, 0x6B, 0x6E, 0x12, + 0xF8, 0x15, 0xA2, 0xB7, 0xFF, 0x2C, 0x94, 0x2E, 0xEF, 0xB0, + 0xF9, 0xF7, 0x3F, 0x41, 0xF5, 0x8B, 0x17, 0x22, 0x58, 0x72, + 0x00, 0xD1, 0xB8, 0x44, 0x5A, 0x75, 0xDC, 0x5D, 0xF5, 0x5F, + 0x7F, 0x4C, 0xD6, 0xFD, 0x6E, 0xE5, 0xBD, 0x80, 0xD6, 0x5C, + 0x59, 0x5F, 0x0E, 0x6A, 0xAA, 0x4A, 0x57, 0x40, 0x63, 0xB6, + 0xBD, 0x4F, 0xDF, 0xD8, 0x40, 0x07, 0x17, 0x8D, 0x85, 0x79, + 0xD2, 0x2F, 0x64, 0xC0, 0xC9, 0xA3, 0x73, 0x2F, 0xB2, 0xA9, + 0x23, 0x78, 0xE3, 0xB9, 0x21, 0x85, 0x91, 0x34, 0x45, 0xCF, + 0x0A, 0x1C, 0x55, 0x52, 0xF8, 0x5D, 0x2C, 0x42, 0x19, 0x10, + 0xDB, 0x4E, 0x1E, 0x33, 0x5C, 0xED, 0x8F, 0xD7, 0x94, 0x6A, + 0x43, 0x6A, 0xD2, 0xBF, 0x54, 0xB8, 0x8C, 0xFA, 0x6A, 0xEB, + 0xD0, 0x12, 0x65, 0xA4, 0x2F, 0x14, 0x51, 0xAC, 0xE4, 0x83, + 0x0F, 0xDC, 0x39, 0xB0, 0xCD, 0x31, 0xC4, 0x61, 0xEB, 0xE7, + 0x26, 0x9A, 0x4C, 0xCE, 0x49, 0x99, 0xD0, 0xBB, 0x90, 0x8A, + 0x30, 0xDF, 0x24, 0xA9, 0x50, 0x0B, 0xAA, 0xC8, 0xEB, 0x7D, + 0xD9, 0x72, 0xF8, 0x93, 0xCF, 0x76, 0x6A, 0x6F, 0x38, 0xCC, + 0x50, 0x88, 0x45, 0x2E, 0x78, 0xAD, 0xD4, 0xEC, 0xC1, 0xB8, + 0xBE, 0x7C, 0x4B, 0x79, 0xA1, 0xA1, 0xA8, 0x25, 0xD9, 0x72, + 0x20, 0x2D, 0x22, 0x20, 0x5E, 0x80, 0x92, 0x88, 0x08, 0x27, + 0xE5, 0xB4, 0xF4, 0xAA, 0xCC, 0xB0, 0x42, 0x67, 0x61, 0xD6, + 0x80, 0x31, 0x4A, 0xA8, 0xFF, 0xE4, 0xBA, 0x49, 0x7A, 0xF9, + 0x85, 0xD3, 0xE4, 0x96, 0xB6, 0x42, 0x87, 0x23, 0xF6, 0x81, + 0xBD, 0x1F, 0xB0, 0xC9, 0x02, 0xC2, 0x61, 0x9D, 0xA0, 0xCE, + 0xF6, 0x28, 0xF5, 0xA8, 0x3E, 0x97, 0xBB, 0xB9, 0xE5, 0x0D, + 0x2B, 0x8E, 0x32, 0x6A, 0x18, 0x06, 0xA5, 0xC4, 0xCF, 0xC0, + 0xF7, 0xB8, 0x12, 0x76, 0x91, 0xDE, 0xD1, 0xD6, 0xA8, 0x3A, + 0xF8, 0xEC, 0xCB, 0xD0, 0x26, 0x76, 0x31, 0xE3, 0xC9, 0x0A, + 0xC5, 0xB3, 0xEF, 0x00, 0x10, 0xEA, 0xED, 0x1D, 0x95, 0x30, + 0x6F, 0x0B, 0xA5, 0x44, 0xD9, 0xF1, 0x1E, 0x65, 0xE6, 0x0F, + 0xD1, 0x85, 0xC7, 0x77, 0xE2, 0x30, 0x21, 0x1A, 0x94, 0x26, + 0xF8, 0x4A, 0x54, 0x57, 0x48, 0x88, 0x03, 0x25, 0xF1, 0x67, + 0x21, 0x8E, 0xA9, 0xFD, 0x2F, 0x4F, 0x49, 0x06, 0xC5, 0x83, + 0x44, 0xC4, 0xC7, 0x33, 0x59, 0x59, 0x83, 0x59, 0x70, 0xA9, + 0x2C, 0xF6, 0xE9, 0x02, 0xA5, 0xF8, 0x07, 0xAF, 0x7C, 0xFD, + 0xCA, 0x6A, 0x53, 0x3B, 0xBF, 0x80, 0x15, 0x0C, 0xE8, 0xB7, + 0x15, 0xF9, 0xC3, 0x5A, 0x32, 0xF4, 0x26, 0x78, 0x03, 0xE7, + 0x7C, 0x1A, 0x0D, 0x52, 0x4A, 0x2B, 0x1F, 0xDE, 0x90, 0x30, + 0x2C, 0x4A, 0x48, 0x94, 0x4E, 0xB9, 0x74, 0x85, 0x00, 0x37, + 0xD9, 0xAF, 0xCE, 0x91, 0xC3, 0xEC, 0xC8, 0xDA, 0x64, 0x54, + 0xAE, 0x44, 0x34, 0x4E, 0xAA, 0x22, 0x29, 0xEE, 0xD5, 0x2B, + 0xAC, 0x40, 0x7F, 0x2E, 0x05, 0x98, 0x31, 0x85, 0xD1, 0x9E, + 0x3E, 0xE8, 0xDB, 0xFC, 0x18, 0x5C, 0x29, 0x61, 0x18, 0x9A, + 0x68, 0x56, 0x0E, 0x66, 0x78, 0x1B, 0x0A, 0x85, 0x7F, 0xD2, + 0x70, 0xD8, 0x67, 0xFC, 0x57, 0xB6, 0x60, 0x75, 0x8A, 0xF3, + 0xAE, 0x91, 0x4E, 0xEC, 0xC9, 0x14, 0x22, 0x3E, 0x8C, 0x08, + 0x84, 0x1B, 0x58, 0x3C, 0x95, 0x03, 0x7D, 0x33, 0x1A, 0x31, + 0x01, 0x26, 0xC8, 0x4B, 0x9D, 0x4D, 0x2A, 0x53, 0xAE, 0xB8, + 0xA3, 0xCF, 0x8C, 0x4F, 0xE6, 0x5C, 0x9A, 0x1A, 0xFD, 0xBC, + 0xE0, 0x03, 0x45, 0xB0, 0x96, 0xE7, 0xC5, 0x3B, 0xA3, 0x09, + 0x93, 0x08, 0x13, 0x6B, 0xF0, 0x68, 0x12, 0x13, 0x10, 0xE6, + 0x9B, 0xAF, 0x5D, 0x68, 0xEE, 0x31, 0x09, 0xD8, 0xC9, 0x5E, + 0xC8, 0xE3, 0x85, 0x0B, 0xE7, 0x1A, 0x3A, 0x2B, 0xFE, 0x80, + 0xAF, 0x13, 0x13, 0xED, 0xB3, 0xA4, 0xE7, 0x23, 0xE7, 0xA9, + 0x8E, 0xA3, 0x9E, 0xC5, 0x73, 0x1A, 0x47, 0x4E, 0x0A, 0xFB, + 0xDD, 0x17, 0x19, 0x9E, 0xCB, 0x29, 0x6D, 0x2D, 0x94, 0xB2, + 0xF8, 0x3E, 0x1B, 0x5F, 0x5C, 0xB1, 0x6E, 0x0A, 0x6B, 0x7B, + 0xEE, 0x9F, 0x35, 0x2C, 0xD8, 0x81, 0xDF, 0x25, 0xFA, 0x9B, + 0xCD, 0x28, 0xA6, 0x7D, 0x08, 0x3D, 0x54, 0xF3, 0x67, 0x30, + 0x36, 0xD2, 0xEE, 0x22, 0x13, 0xB9, 0xB2, 0x71, 0x07, 0xBF, + 0xB3, 0x81, 0x25, 0xB7, 0xFA, 0xDA, 0xEE, 0xCF, 0x04, 0xA9, + 0xC0, 0xF0, 0xC1, 0xC2, 0xFE, 0x77, 0x19, 0xA6, 0x3B, 0xCC, + 0x7C, 0xE1, 0x9A, 0x99, 0xDA, 0x11, 0xEF, 0x7B, 0x9D, 0x89, + 0xE0, 0x9F, 0x22, 0x8E, 0x93, 0x6D, 0x86, 0x60, 0x7E, 0x61, + 0xD4, 0xD9, 0xC9, 0x6B, 0x74, 0x6E, 0x17, 0xDC, 0x7A, 0xB5, + 0xF3, 0xFF, 0xD2, 0xDB, 0xFC, 0xCD, 0x34, 0x05, 0x96, 0xDE, + 0x62, 0xDF, 0x60, 0x8F, 0xBA, 0x29, 0x7C, 0xE2, 0x5A, 0xDB, + 0x21, 0x39, 0x3D, 0x27, 0x6B, 0x7B, 0x9E, 0xFC, 0x3F, 0x78, + 0xAA, 0xFA, 0xE7, 0x07, 0x64, 0xAB, 0xA0, 0x20, 0x72, 0x31, + 0xE5, 0x25, 0x53, 0x65, 0x91, 0x8A, 0x33, 0x4E, 0x0B, 0x84, + 0x30, 0xB4, 0x15, 0xD3, 0x28, 0x4D, 0xB5, 0x28, 0xF5, 0x20, + 0xF0, 0x4C, 0x8B, 0x7A, 0xC4, 0x74, 0x64, 0x54, 0xF0, 0x52, + 0x6D, 0x45, 0xF1, 0x79, 0xD4, 0xBB, 0xE0, 0xB6, 0xA7, 0x2C, + 0x38, 0x1A, 0x7B, 0xF3, 0x17, 0x6B, 0x53, 0x73, 0x3F, 0xC3, + 0x22, 0x55, 0x34, 0x92, 0x5D, 0xB5, 0x80, 0x5F, 0x37, 0xB8, + 0xAF, 0x2C, 0x12, 0xA1, 0xA1, 0x29, 0x1A, 0xDC, 0x31, 0xA5, + 0xA3, 0xE6, 0xED, 0xD9, 0x4C, 0x34, 0x53, 0x01, 0x79, 0xDE, + 0xF1, 0x48, 0x31, 0x80, 0x5D, 0x0D, 0x4C, 0x62, 0x70, 0xC1, + 0x3C, 0xB1, 0x0E, 0x4D, 0x72, 0x45, 0x25, 0x33, 0x0B, 0x38, + 0xB2, 0x3E, 0x95, 0xC0, 0xA8, 0x42, 0x51, 0xD9, 0x35, 0x75, + 0xFE, 0x10, 0x4A, 0x48, 0x11, 0x82, 0xE8, 0x87, 0x04, 0x6B, + 0x06, 0x60, 0xA8, 0x0E, 0xAC, 0x8B, 0xFA, 0x40, 0xB1, 0x63, + 0x63, 0x91, 0x17, 0x2A, 0x4F, 0x2A, 0xD8, 0x6C, 0x43, 0xAF, + 0xDC, 0xE2, 0x72, 0x76, 0xBE, 0x46, 0xCB, 0x12, 0xA4, 0x73, + 0x03, 0xAB, 0x11, 0x9E, 0x0D, 0x41, 0x27, 0x8C, 0x18, 0xEF, + 0xE6, 0xC2, 0xB3, 0x09, 0xF0, 0x36, 0xA6, 0xE4, 0xFF, 0xE5, + 0x91, 0xD8, 0xD7, 0xF5, 0x1E, 0x6D, 0x34, 0x19, 0xF1, 0xAF, + 0x9B, 0x9A, 0xF8, 0x10, 0x92, 0x11, 0x85, 0xEA, 0x38, 0xF6, + 0x89, 0x40, 0x6D, 0xB0, 0x84, 0xEB, 0xBA, 0xAD, 0xB1, 0x55, + 0xB0, 0x73, 0x52, 0xF6, 0xB8, 0xD2, 0xCF, 0xED, 0x6B, 0xF5, + 0xFA, 0x01, 0x2A, 0x8E, 0xC7, 0x06, 0x77, 0xEB, 0xF3, 0x84, + 0xFD, 0x9B, 0x17, 0x54, 0x31, 0x73, 0xFE, 0xC3, 0x71, 0xF8, + 0x41, 0xFF, 0xA4, 0xD3, 0x7D, 0xB2, 0xBD, 0xBA, 0xD6, 0xE9, + 0x1E, 0x8F, 0x5B, 0x8D, 0x3A, 0x3C, 0x0C, 0xB4, 0xFE, 0x9B, + 0x49, 0x69, 0x8C, 0x3D, 0xA7, 0xF5, 0x79, 0x46, 0xE9, 0x5E, + 0xE1, 0x07, 0x52, 0xB7, 0x24, 0x51, 0x6C, 0x59, 0x74, 0x2C, + 0xEC, 0x7C, 0x88, 0x41, 0x2E, 0x45, 0x91, 0x23, 0xA4, 0x81, + 0xC9, 0x37, 0xC0, 0xDE, 0xC0, 0x09, 0x5A, 0x00, 0xFD, 0x2D, + 0x97, 0x71, 0x6A, 0xAF, 0x6E, 0x5D, 0x03, 0x67, 0xAA, 0xFD + +}; +static const int sizeof_bench_dilithium_aes_level2_key = sizeof(bench_dilithium_aes_level2_key); + +/* certs/dilithium/bench_dilithium_aes_level3_key.der */ +static const unsigned char bench_dilithium_aes_level3_key[] = +{ + 0x30, 0x82, 0x17, 0x5A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x0B, + 0x06, 0x05, 0x04, 0x82, 0x17, 0x44, 0x04, 0x82, 0x17, 0x40, + 0x62, 0x93, 0x71, 0x4C, 0xCD, 0x7A, 0xD1, 0x75, 0xD1, 0xBB, + 0x2A, 0xC9, 0x54, 0xBF, 0xDA, 0xF1, 0x70, 0xE9, 0xEF, 0x8D, + 0x08, 0x66, 0xE9, 0xD6, 0xE3, 0x6F, 0x4B, 0x99, 0xEB, 0x44, + 0x51, 0x12, 0x64, 0x80, 0x0D, 0x29, 0x4B, 0x24, 0x6B, 0x6A, + 0xAC, 0xD9, 0x87, 0x9A, 0x2D, 0x49, 0xF6, 0xCC, 0x69, 0xC0, + 0xAE, 0xD9, 0xB2, 0xE1, 0xF5, 0xB8, 0xC1, 0x98, 0x77, 0x73, + 0x1F, 0x1E, 0xE6, 0x11, 0x0A, 0x1F, 0x51, 0xDF, 0xD1, 0x4A, + 0x32, 0x8D, 0xC2, 0x36, 0xA6, 0xAF, 0x6F, 0x01, 0x57, 0xA3, + 0x56, 0x17, 0x5F, 0x5E, 0xDC, 0x39, 0xD8, 0xC8, 0xB7, 0xE1, + 0x1B, 0x2F, 0x51, 0xC6, 0xAF, 0xC4, 0x65, 0x53, 0x34, 0x21, + 0x81, 0x28, 0x44, 0x82, 0x23, 0x80, 0x21, 0x17, 0x08, 0x42, + 0x88, 0x48, 0x17, 0x22, 0x31, 0x01, 0x42, 0x36, 0x83, 0x76, + 0x00, 0x45, 0x40, 0x23, 0x54, 0x85, 0x74, 0x11, 0x22, 0x85, + 0x31, 0x38, 0x81, 0x26, 0x38, 0x55, 0x15, 0x51, 0x42, 0x44, + 0x53, 0x81, 0x81, 0x47, 0x76, 0x70, 0x84, 0x15, 0x78, 0x70, + 0x34, 0x34, 0x02, 0x54, 0x65, 0x07, 0x35, 0x66, 0x51, 0x10, + 0x84, 0x03, 0x45, 0x33, 0x02, 0x51, 0x55, 0x20, 0x37, 0x76, + 0x00, 0x24, 0x58, 0x33, 0x24, 0x18, 0x67, 0x77, 0x31, 0x83, + 0x45, 0x17, 0x55, 0x12, 0x64, 0x07, 0x31, 0x08, 0x42, 0x56, + 0x45, 0x80, 0x32, 0x28, 0x61, 0x04, 0x83, 0x17, 0x10, 0x58, + 0x00, 0x18, 0x80, 0x85, 0x24, 0x15, 0x73, 0x38, 0x67, 0x84, + 0x68, 0x64, 0x85, 0x21, 0x32, 0x18, 0x41, 0x22, 0x34, 0x10, + 0x76, 0x05, 0x84, 0x47, 0x86, 0x26, 0x50, 0x86, 0x76, 0x72, + 0x25, 0x01, 0x36, 0x36, 0x67, 0x57, 0x42, 0x62, 0x10, 0x77, + 0x15, 0x66, 0x52, 0x20, 0x81, 0x86, 0x28, 0x42, 0x52, 0x73, + 0x44, 0x22, 0x04, 0x34, 0x15, 0x68, 0x65, 0x52, 0x30, 0x83, + 0x60, 0x20, 0x00, 0x57, 0x56, 0x28, 0x14, 0x16, 0x51, 0x87, + 0x57, 0x72, 0x01, 0x31, 0x31, 0x41, 0x58, 0x85, 0x80, 0x51, + 0x72, 0x27, 0x86, 0x11, 0x80, 0x76, 0x13, 0x66, 0x50, 0x18, + 0x75, 0x21, 0x06, 0x83, 0x20, 0x54, 0x44, 0x64, 0x44, 0x38, + 0x50, 0x56, 0x12, 0x78, 0x80, 0x71, 0x66, 0x20, 0x28, 0x83, + 0x50, 0x02, 0x46, 0x51, 0x86, 0x43, 0x55, 0x73, 0x38, 0x06, + 0x70, 0x06, 0x63, 0x43, 0x70, 0x81, 0x68, 0x21, 0x27, 0x14, + 0x75, 0x68, 0x68, 0x34, 0x03, 0x71, 0x34, 0x02, 0x28, 0x44, + 0x48, 0x46, 0x27, 0x16, 0x73, 0x60, 0x86, 0x86, 0x18, 0x80, + 0x05, 0x71, 0x88, 0x22, 0x13, 0x78, 0x50, 0x01, 0x60, 0x11, + 0x60, 0x77, 0x14, 0x66, 0x67, 0x66, 0x55, 0x56, 0x33, 0x53, + 0x28, 0x25, 0x54, 0x52, 0x31, 0x23, 0x56, 0x24, 0x44, 0x55, + 0x48, 0x67, 0x37, 0x64, 0x82, 0x02, 0x65, 0x88, 0x63, 0x41, + 0x83, 0x34, 0x30, 0x54, 0x63, 0x80, 0x07, 0x60, 0x81, 0x05, + 0x70, 0x83, 0x14, 0x60, 0x74, 0x04, 0x82, 0x38, 0x28, 0x24, + 0x84, 0x20, 0x68, 0x78, 0x81, 0x53, 0x71, 0x34, 0x81, 0x62, + 0x07, 0x63, 0x22, 0x45, 0x81, 0x74, 0x75, 0x03, 0x27, 0x26, + 0x50, 0x34, 0x47, 0x36, 0x86, 0x38, 0x17, 0x13, 0x10, 0x06, + 0x68, 0x43, 0x62, 0x33, 0x32, 0x53, 0x44, 0x48, 0x46, 0x08, + 0x87, 0x40, 0x27, 0x17, 0x68, 0x52, 0x38, 0x11, 0x57, 0x58, + 0x70, 0x83, 0x32, 0x70, 0x60, 0x45, 0x67, 0x64, 0x88, 0x73, + 0x01, 0x40, 0x71, 0x60, 0x60, 0x20, 0x13, 0x71, 0x23, 0x75, + 0x14, 0x32, 0x78, 0x60, 0x55, 0x84, 0x63, 0x11, 0x47, 0x82, + 0x64, 0x68, 0x48, 0x63, 0x04, 0x14, 0x64, 0x85, 0x64, 0x58, + 0x10, 0x62, 0x70, 0x07, 0x02, 0x88, 0x57, 0x67, 0x42, 0x35, + 0x30, 0x02, 0x56, 0x17, 0x41, 0x57, 0x54, 0x77, 0x06, 0x43, + 0x71, 0x48, 0x64, 0x34, 0x18, 0x42, 0x08, 0x12, 0x47, 0x70, + 0x78, 0x24, 0x85, 0x34, 0x68, 0x30, 0x02, 0x01, 0x24, 0x01, + 0x53, 0x17, 0x67, 0x58, 0x72, 0x68, 0x53, 0x61, 0x63, 0x30, + 0x36, 0x87, 0x60, 0x77, 0x35, 0x14, 0x31, 0x17, 0x47, 0x60, + 0x25, 0x47, 0x64, 0x06, 0x77, 0x13, 0x63, 0x48, 0x43, 0x85, + 0x40, 0x88, 0x62, 0x01, 0x07, 0x83, 0x03, 0x21, 0x86, 0x34, + 0x48, 0x44, 0x71, 0x72, 0x85, 0x77, 0x64, 0x82, 0x78, 0x66, + 0x73, 0x28, 0x30, 0x71, 0x74, 0x76, 0x21, 0x12, 0x26, 0x24, + 0x72, 0x24, 0x66, 0x58, 0x27, 0x66, 0x71, 0x20, 0x26, 0x30, + 0x07, 0x60, 0x26, 0x62, 0x05, 0x21, 0x83, 0x77, 0x61, 0x60, + 0x24, 0x55, 0x64, 0x73, 0x00, 0x52, 0x35, 0x21, 0x27, 0x01, + 0x78, 0x78, 0x45, 0x38, 0x87, 0x23, 0x51, 0x88, 0x31, 0x62, + 0x36, 0x20, 0x10, 0x67, 0x23, 0x53, 0x38, 0x18, 0x76, 0x71, + 0x40, 0x68, 0x08, 0x86, 0x80, 0x46, 0x25, 0x27, 0x84, 0x76, + 0x81, 0x00, 0x20, 0x06, 0x50, 0x85, 0x15, 0x32, 0x27, 0x77, + 0x30, 0x77, 0x21, 0x52, 0x05, 0x76, 0x24, 0x51, 0x18, 0x06, + 0x50, 0x26, 0x52, 0x86, 0x30, 0x27, 0x31, 0x11, 0x12, 0x31, + 0x34, 0x75, 0x48, 0x62, 0x45, 0x64, 0x08, 0x26, 0x23, 0x48, + 0x66, 0x41, 0x78, 0x26, 0x26, 0x40, 0x36, 0x44, 0x36, 0x34, + 0x00, 0x61, 0x34, 0x67, 0x31, 0x03, 0x11, 0x24, 0x32, 0x80, + 0x06, 0x44, 0x34, 0x48, 0x42, 0x27, 0x52, 0x48, 0x76, 0x04, + 0x83, 0x07, 0x36, 0x86, 0x40, 0x84, 0x72, 0x56, 0x50, 0x37, + 0x23, 0x51, 0x52, 0x64, 0x20, 0x16, 0x05, 0x17, 0x57, 0x26, + 0x22, 0x58, 0x32, 0x65, 0x47, 0x35, 0x51, 0x32, 0x04, 0x74, + 0x37, 0x00, 0x11, 0x01, 0x66, 0x17, 0x12, 0x14, 0x81, 0x02, + 0x07, 0x53, 0x72, 0x48, 0x43, 0x73, 0x20, 0x60, 0x70, 0x73, + 0x47, 0x56, 0x07, 0x76, 0x36, 0x66, 0x72, 0x40, 0x83, 0x66, + 0x07, 0x11, 0x13, 0x16, 0x40, 0x45, 0x53, 0x58, 0x75, 0x21, + 0x83, 0x15, 0x36, 0x67, 0x65, 0x83, 0x32, 0x82, 0x54, 0x41, + 0x71, 0x61, 0x60, 0x74, 0x30, 0x16, 0x35, 0x81, 0x33, 0x35, + 0x16, 0x06, 0x13, 0x37, 0x36, 0x24, 0x57, 0x54, 0x43, 0x44, + 0x85, 0x74, 0x38, 0x11, 0x27, 0x23, 0x33, 0x41, 0x70, 0x36, + 0x52, 0x87, 0x42, 0x23, 0x31, 0x08, 0x01, 0x50, 0x17, 0x80, + 0x64, 0x46, 0x06, 0x50, 0x23, 0x20, 0x88, 0x85, 0x05, 0x24, + 0x68, 0x44, 0x36, 0x32, 0x20, 0x84, 0x55, 0x07, 0x23, 0x70, + 0x52, 0x14, 0x61, 0x17, 0x20, 0x03, 0x25, 0x58, 0x74, 0x24, + 0x71, 0x48, 0x20, 0x51, 0x25, 0x24, 0x53, 0x28, 0x15, 0x37, + 0x57, 0x00, 0x76, 0x05, 0x13, 0x52, 0x82, 0x43, 0x64, 0x10, + 0x51, 0x15, 0x37, 0x57, 0x41, 0x50, 0x64, 0x60, 0x08, 0x60, + 0x83, 0x83, 0x27, 0x22, 0x77, 0x54, 0x88, 0x26, 0x12, 0x10, + 0x00, 0x27, 0x65, 0x86, 0x04, 0x67, 0x82, 0x65, 0x42, 0x30, + 0x50, 0x10, 0x15, 0x35, 0x03, 0x12, 0x50, 0x00, 0x63, 0x50, + 0x53, 0x65, 0x21, 0x48, 0x03, 0x52, 0x36, 0x78, 0x06, 0x01, + 0x20, 0x80, 0x01, 0x52, 0x68, 0x26, 0x80, 0x67, 0x06, 0x08, + 0x11, 0x80, 0x80, 0x74, 0x68, 0x75, 0x13, 0x00, 0x80, 0x12, + 0x28, 0x28, 0x02, 0x53, 0x06, 0x04, 0x54, 0x70, 0x46, 0x00, + 0x62, 0x82, 0x44, 0x71, 0x45, 0x67, 0x82, 0x37, 0x17, 0x58, + 0x32, 0x04, 0x17, 0x34, 0x52, 0x08, 0x83, 0x25, 0x32, 0x23, + 0x46, 0x61, 0x37, 0x53, 0x12, 0x35, 0x14, 0x35, 0x82, 0x17, + 0x76, 0x82, 0x74, 0x51, 0x32, 0x85, 0x71, 0x01, 0x62, 0x28, + 0x28, 0x22, 0x23, 0x27, 0x54, 0x00, 0x86, 0x16, 0x88, 0x27, + 0x62, 0x38, 0x87, 0x67, 0x84, 0x74, 0x45, 0x45, 0x33, 0x06, + 0x21, 0x67, 0x81, 0x63, 0x07, 0x87, 0x55, 0x43, 0x08, 0x32, + 0x36, 0x66, 0x48, 0x00, 0x48, 0x75, 0x14, 0x14, 0x68, 0x43, + 0x57, 0x10, 0x46, 0x15, 0x87, 0x84, 0x15, 0x87, 0x18, 0x34, + 0x24, 0x10, 0x41, 0x77, 0x87, 0x01, 0x64, 0x33, 0x10, 0x83, + 0x10, 0x15, 0x43, 0x40, 0x00, 0x26, 0x72, 0x76, 0x01, 0x12, + 0x68, 0x33, 0x05, 0x42, 0x14, 0x70, 0x75, 0x65, 0x64, 0x03, + 0x03, 0x31, 0x66, 0x38, 0x14, 0x20, 0x42, 0x74, 0x02, 0x40, + 0x84, 0x64, 0x65, 0x45, 0x00, 0x41, 0x86, 0x66, 0x27, 0x06, + 0x56, 0x02, 0x17, 0x41, 0x76, 0x45, 0x66, 0x85, 0x25, 0x43, + 0x28, 0x21, 0x01, 0x62, 0x70, 0x50, 0x75, 0x00, 0x24, 0x21, + 0x65, 0x70, 0x54, 0x16, 0x33, 0x62, 0x14, 0x28, 0x64, 0x86, + 0x24, 0x70, 0x36, 0x46, 0x50, 0x60, 0x11, 0x32, 0x46, 0x86, + 0x07, 0x23, 0x70, 0x53, 0x01, 0x43, 0x80, 0x84, 0x41, 0x61, + 0x34, 0x10, 0x24, 0x57, 0x06, 0x51, 0x60, 0x22, 0x66, 0x88, + 0x25, 0x74, 0x72, 0x74, 0x64, 0x44, 0x27, 0x03, 0x10, 0x23, + 0x20, 0x16, 0x22, 0x35, 0x28, 0x32, 0x10, 0x73, 0x22, 0x26, + 0x31, 0x20, 0x57, 0x65, 0x71, 0x58, 0x14, 0x14, 0x08, 0x87, + 0x85, 0x80, 0x45, 0x83, 0x77, 0x55, 0x20, 0x34, 0x86, 0x72, + 0x10, 0x76, 0x76, 0x01, 0x16, 0x33, 0x40, 0x83, 0x32, 0x86, + 0x04, 0x03, 0x12, 0x78, 0x46, 0x10, 0x88, 0x10, 0x33, 0x76, + 0x83, 0x14, 0x01, 0x37, 0x62, 0x78, 0x43, 0x21, 0x27, 0x22, + 0x16, 0x22, 0x55, 0x00, 0x11, 0x74, 0x81, 0x28, 0x60, 0x78, + 0x74, 0x80, 0x81, 0x80, 0x63, 0x05, 0x51, 0x35, 0x34, 0x70, + 0x61, 0x02, 0x77, 0x47, 0x40, 0x47, 0x40, 0x87, 0x75, 0x06, + 0x26, 0x46, 0x53, 0x36, 0x14, 0x66, 0x10, 0x20, 0x43, 0x52, + 0x47, 0x08, 0x55, 0x26, 0x65, 0x53, 0x28, 0x41, 0x43, 0x11, + 0x61, 0x27, 0x16, 0x46, 0x31, 0x08, 0x71, 0x26, 0x27, 0x15, + 0x05, 0x06, 0x66, 0x57, 0x41, 0x31, 0x37, 0x03, 0x15, 0x68, + 0x08, 0x88, 0x63, 0x34, 0x01, 0x61, 0x01, 0x11, 0x58, 0x66, + 0x14, 0x22, 0x44, 0x40, 0x02, 0x66, 0x35, 0x37, 0x54, 0x44, + 0x67, 0x44, 0x08, 0x43, 0x70, 0x20, 0x45, 0x70, 0x38, 0x04, + 0x65, 0x61, 0x57, 0x32, 0x15, 0x12, 0x83, 0x31, 0x58, 0x46, + 0x28, 0x08, 0x86, 0x55, 0x12, 0x16, 0x21, 0x70, 0x50, 0x88, + 0x07, 0x34, 0x32, 0x61, 0x18, 0x50, 0x86, 0x03, 0x58, 0x41, + 0x43, 0x40, 0x76, 0x63, 0x37, 0x43, 0x71, 0x18, 0x23, 0x25, + 0x06, 0x71, 0x62, 0x47, 0x16, 0x12, 0x77, 0x84, 0x01, 0x70, + 0x85, 0x41, 0x07, 0x42, 0x80, 0x71, 0x26, 0x05, 0x85, 0x73, + 0x14, 0x38, 0x66, 0x31, 0x25, 0x67, 0x82, 0x07, 0x22, 0x73, + 0x23, 0x34, 0x61, 0x65, 0x45, 0x46, 0x74, 0x64, 0x34, 0x57, + 0x47, 0x72, 0x75, 0x34, 0x76, 0x11, 0x31, 0x61, 0x77, 0x57, + 0x68, 0x42, 0x18, 0x18, 0x37, 0x80, 0x06, 0x77, 0x71, 0x30, + 0x85, 0x42, 0x67, 0x56, 0x42, 0x70, 0x32, 0x53, 0x55, 0x48, + 0x40, 0x32, 0x37, 0x21, 0x35, 0x15, 0x45, 0x27, 0x85, 0x36, + 0x61, 0x73, 0x21, 0x26, 0x81, 0x83, 0x64, 0x84, 0x75, 0x75, + 0x54, 0x68, 0x84, 0x54, 0x75, 0x17, 0x10, 0x35, 0x13, 0x37, + 0x55, 0x11, 0x62, 0x44, 0x38, 0x38, 0x70, 0x45, 0x84, 0x73, + 0x78, 0x75, 0x22, 0x42, 0x34, 0x0C, 0x86, 0xF0, 0x92, 0x29, + 0xBC, 0x51, 0xBB, 0x69, 0x5E, 0x8A, 0x57, 0x55, 0x1E, 0xE8, + 0x00, 0xF7, 0x97, 0xC7, 0xF5, 0x35, 0xEA, 0xDC, 0x86, 0xD5, + 0x95, 0x70, 0x09, 0x28, 0x44, 0x93, 0x8B, 0xE1, 0xE2, 0xCE, + 0xA6, 0x37, 0xAC, 0x68, 0x94, 0x2E, 0xC5, 0xD3, 0xC9, 0x6D, + 0xAA, 0xF0, 0x46, 0x12, 0xC6, 0xA2, 0xC9, 0x84, 0xD1, 0xB2, + 0x80, 0x32, 0xC5, 0xBD, 0x41, 0x6D, 0x7C, 0xF8, 0x9C, 0xCA, + 0x1F, 0xE6, 0x25, 0xBA, 0xDD, 0x18, 0x3F, 0xAE, 0xC3, 0x12, + 0x39, 0xA6, 0xF5, 0xF1, 0xA0, 0x5A, 0xF7, 0x67, 0x4F, 0x5C, + 0xF1, 0x72, 0x60, 0x7D, 0xB5, 0xC1, 0x63, 0x9E, 0x4F, 0x96, + 0x93, 0x6F, 0x56, 0xD3, 0xE1, 0x98, 0xED, 0xA0, 0x3A, 0x5D, + 0x85, 0x3C, 0x65, 0x57, 0x12, 0x28, 0x17, 0x54, 0x4D, 0x50, + 0x1B, 0x3C, 0x93, 0x81, 0x05, 0x53, 0x79, 0xFD, 0x1C, 0xC0, + 0x55, 0x1E, 0xC2, 0xC3, 0x5B, 0xE8, 0x10, 0xF3, 0x4D, 0x89, + 0x1C, 0x0A, 0xC9, 0xF9, 0x4E, 0x3D, 0x30, 0xF1, 0x52, 0xC3, + 0xE7, 0xE1, 0xF6, 0x59, 0xEC, 0xCF, 0xF6, 0x87, 0xA6, 0xAD, + 0xAD, 0x0A, 0x8A, 0x35, 0x84, 0xCB, 0x53, 0x7F, 0x4C, 0x5D, + 0xD2, 0xAD, 0xB4, 0xBE, 0x28, 0xC6, 0xCC, 0x35, 0xA8, 0x48, + 0x0A, 0xEA, 0xE9, 0x85, 0x89, 0xE6, 0xC1, 0xA2, 0x7E, 0x72, + 0x0F, 0xAF, 0xDC, 0xEA, 0x54, 0x4C, 0xF8, 0xA0, 0xB4, 0x4F, + 0x82, 0x6B, 0xEF, 0x7E, 0xC5, 0xFF, 0x82, 0x9D, 0xE7, 0x6D, + 0x7A, 0x64, 0x3E, 0xF8, 0x9F, 0x67, 0x34, 0x3D, 0x72, 0xC4, + 0x6B, 0x5B, 0xE8, 0xE9, 0xBF, 0x7E, 0x3C, 0xC8, 0xB6, 0xF5, + 0xCA, 0x0D, 0x9A, 0x2E, 0x76, 0xDE, 0xC6, 0x34, 0xCA, 0xEC, + 0xBC, 0x07, 0x0D, 0x5A, 0x0C, 0xD3, 0x3C, 0xCE, 0xB0, 0x31, + 0x20, 0xD4, 0x7C, 0x4C, 0x49, 0x52, 0xBA, 0xD2, 0x3C, 0x25, + 0x36, 0xF1, 0x8A, 0x7F, 0x51, 0x0B, 0x3C, 0xAA, 0xE4, 0xD0, + 0xA8, 0x07, 0x6B, 0x7E, 0x2C, 0xE0, 0xF0, 0x4B, 0xDE, 0x00, + 0xD8, 0xD0, 0xD0, 0xA0, 0x2A, 0x2C, 0x5A, 0xB5, 0x84, 0x9A, + 0x8A, 0x7C, 0x40, 0x41, 0x0B, 0xF3, 0x78, 0x33, 0xBC, 0xC9, + 0x84, 0xCE, 0x0B, 0xA3, 0x2E, 0x53, 0x43, 0xA5, 0x04, 0x2E, + 0xD4, 0xA0, 0x88, 0x9B, 0x7C, 0xA1, 0xDD, 0xF4, 0xE9, 0x64, + 0xCB, 0x13, 0x72, 0x0F, 0xE6, 0x9D, 0x52, 0xDD, 0x17, 0xC3, + 0x80, 0xEE, 0xD0, 0xB2, 0xD3, 0x34, 0xDF, 0xEC, 0xDE, 0x52, + 0x5A, 0xFE, 0x0A, 0x1F, 0x51, 0x14, 0x92, 0x56, 0xEC, 0xA4, + 0x89, 0x8C, 0x4C, 0x0F, 0xAB, 0xB3, 0x67, 0x65, 0x24, 0xAF, + 0x68, 0x68, 0x01, 0xBD, 0xF7, 0x51, 0x6F, 0x58, 0x59, 0x47, + 0x04, 0xE1, 0x12, 0xD1, 0x51, 0x42, 0x98, 0x88, 0xFA, 0xFF, + 0x2D, 0xE3, 0xB8, 0xB1, 0xAE, 0xE3, 0x82, 0xDC, 0xB2, 0x3A, + 0x4F, 0x2F, 0xBC, 0x99, 0xCD, 0x47, 0xD9, 0xF0, 0x81, 0xAB, + 0xCE, 0x61, 0x0A, 0x03, 0xC2, 0xF4, 0x7A, 0x09, 0x2F, 0xD3, + 0x2C, 0xE2, 0x3E, 0xBE, 0xFA, 0xB7, 0x0C, 0xA7, 0x3D, 0xF3, + 0x1C, 0x46, 0x4C, 0xDC, 0x87, 0xCF, 0x11, 0x47, 0xB2, 0xDE, + 0x2E, 0x05, 0x2F, 0x9C, 0x40, 0x87, 0x67, 0xF6, 0xE1, 0x49, + 0x89, 0x9B, 0x3C, 0x52, 0x86, 0x4D, 0x6C, 0xC8, 0x45, 0x90, + 0xC9, 0x30, 0x09, 0x79, 0xB7, 0x5D, 0xFA, 0x74, 0x4C, 0x9D, + 0x3C, 0x8B, 0x3C, 0x90, 0xD0, 0x96, 0x59, 0xBD, 0x3E, 0x61, + 0xD5, 0xC6, 0xCF, 0x05, 0xD7, 0xD3, 0x0F, 0x8A, 0x6E, 0x79, + 0xBA, 0x85, 0x9C, 0x53, 0x83, 0x28, 0xDC, 0x2C, 0x06, 0xE3, + 0x10, 0x4B, 0xD9, 0xED, 0x4C, 0xEA, 0x28, 0x9C, 0x3B, 0xF9, + 0xB1, 0x6B, 0x91, 0xEA, 0xF5, 0x1B, 0x14, 0x6E, 0x6E, 0xBF, + 0xBC, 0xF4, 0x61, 0x5D, 0x0A, 0x9A, 0xC4, 0x29, 0xC7, 0x50, + 0x91, 0x6D, 0x6C, 0x5F, 0x5D, 0xB0, 0xBB, 0x5C, 0x2B, 0x40, + 0xFF, 0x75, 0x73, 0xE3, 0xB6, 0x52, 0x78, 0x32, 0x33, 0x91, + 0x00, 0x3B, 0xF1, 0x11, 0xA6, 0xBF, 0x9A, 0x1A, 0xD2, 0x0E, + 0xE2, 0xBB, 0xDF, 0x4F, 0x55, 0x7E, 0x45, 0x4A, 0x1E, 0x45, + 0x22, 0x42, 0xCA, 0x87, 0x63, 0x9E, 0x82, 0xB7, 0x67, 0xE8, + 0x2A, 0xDE, 0x3A, 0x2E, 0x61, 0xF1, 0x56, 0xA4, 0x63, 0x9F, + 0x32, 0xD8, 0xD0, 0xA4, 0xFB, 0xAE, 0xCF, 0x6C, 0xEC, 0x66, + 0x4D, 0xA7, 0xA4, 0xE1, 0x8C, 0x39, 0xFF, 0x2E, 0xA3, 0xDB, + 0x01, 0x67, 0xA4, 0x80, 0x03, 0x73, 0xA7, 0x9C, 0x6B, 0x51, + 0x57, 0x35, 0x0D, 0x1A, 0x44, 0xCD, 0x80, 0x06, 0xA5, 0x2F, + 0xA0, 0xF3, 0x65, 0x7A, 0xCB, 0x34, 0x58, 0xD3, 0xCF, 0xF7, + 0x28, 0xBC, 0xB9, 0x1C, 0xE2, 0x22, 0x6C, 0x1E, 0xE5, 0x0D, + 0x73, 0x1F, 0x8C, 0xA6, 0xF2, 0x94, 0x9B, 0xE5, 0xDA, 0xE3, + 0x9B, 0x1A, 0xE1, 0x5E, 0x9D, 0xE3, 0x6F, 0x0F, 0x29, 0x57, + 0xE4, 0x12, 0x32, 0xC1, 0x5C, 0xD3, 0xE8, 0xDE, 0xC1, 0x44, + 0x40, 0x9B, 0x59, 0x4F, 0xDD, 0x7E, 0xA4, 0x32, 0x8E, 0xE0, + 0x0D, 0xDC, 0x3F, 0x67, 0x7A, 0xA7, 0x52, 0x67, 0xF1, 0xA1, + 0xF5, 0x8C, 0xEF, 0xB5, 0xFC, 0x9E, 0x48, 0x39, 0xAC, 0xEF, + 0xE6, 0x7A, 0x58, 0xFB, 0xEF, 0x2B, 0xBE, 0x80, 0x09, 0x85, + 0x53, 0x5E, 0x9D, 0x9B, 0x07, 0x18, 0xE8, 0x44, 0x5A, 0xE3, + 0xDD, 0xE5, 0x17, 0xE7, 0x8C, 0x9A, 0x55, 0x51, 0x14, 0xD9, + 0x1C, 0x2D, 0x41, 0x00, 0xBC, 0x1F, 0x78, 0x85, 0x44, 0x38, + 0xC7, 0x59, 0x71, 0x69, 0x81, 0x2D, 0x7A, 0x27, 0x3B, 0xC2, + 0x65, 0x00, 0xAC, 0x47, 0x0D, 0x81, 0xF7, 0x81, 0x50, 0x97, + 0x69, 0x98, 0xE7, 0x55, 0x2E, 0x77, 0xA4, 0x43, 0x7B, 0xF0, + 0x27, 0xCC, 0xB5, 0xC9, 0x9E, 0xEB, 0x8E, 0x7F, 0xE0, 0x7F, + 0xE7, 0x0A, 0x3B, 0xDF, 0x40, 0x3D, 0x5F, 0x43, 0xA4, 0x20, + 0x11, 0x06, 0x8C, 0xC9, 0x8D, 0xCA, 0xAD, 0xDD, 0xED, 0xD4, + 0x0F, 0xCA, 0xA2, 0xA5, 0x04, 0x8B, 0x59, 0x13, 0xBE, 0xE9, + 0xC2, 0x38, 0x23, 0x26, 0x64, 0x29, 0x08, 0xF6, 0xC2, 0xD0, + 0x92, 0x02, 0x6B, 0x45, 0x05, 0x53, 0xF0, 0xC6, 0xC6, 0x6C, + 0xB7, 0xDE, 0x94, 0xDE, 0x74, 0x5F, 0x24, 0x43, 0x85, 0x94, + 0x6F, 0x5B, 0xFC, 0xD8, 0x12, 0xC6, 0xF7, 0xA8, 0xF0, 0x15, + 0x4B, 0x05, 0x08, 0xD0, 0x49, 0xD0, 0xB5, 0xEB, 0x39, 0x67, + 0xCC, 0xD0, 0x28, 0xD7, 0xF3, 0x13, 0xC7, 0xDA, 0x93, 0xEE, + 0x93, 0x33, 0xAB, 0x7C, 0x7F, 0x92, 0xBD, 0x23, 0xC1, 0x35, + 0x3B, 0x59, 0xEE, 0x55, 0xE7, 0x25, 0xAC, 0x79, 0x61, 0xEF, + 0xE7, 0x19, 0xEF, 0x26, 0xDF, 0x67, 0x04, 0xD0, 0x57, 0xBF, + 0x8A, 0x34, 0x66, 0x8A, 0xD0, 0xFF, 0x04, 0x76, 0xF4, 0x52, + 0x4F, 0xC1, 0xA0, 0xE5, 0x18, 0x13, 0x14, 0x9B, 0xC7, 0x93, + 0x14, 0xAA, 0xCE, 0x12, 0x1A, 0x28, 0x04, 0x4A, 0xC4, 0xC6, + 0x32, 0x13, 0x38, 0xDA, 0x7D, 0x2A, 0x03, 0x00, 0x12, 0xB9, + 0x76, 0x33, 0x44, 0xFF, 0xEC, 0xC8, 0x7D, 0xFF, 0x01, 0x35, + 0xCF, 0xD0, 0x13, 0xEA, 0x7B, 0x54, 0x53, 0x44, 0x76, 0x8B, + 0xCB, 0x7E, 0xF1, 0xF5, 0x78, 0xEB, 0xEC, 0xE3, 0x11, 0xD8, + 0x29, 0xBB, 0x86, 0x1D, 0x98, 0xFB, 0xE6, 0x5E, 0x6E, 0xC2, + 0x29, 0xD6, 0x42, 0x8E, 0xE5, 0x8B, 0x1F, 0x11, 0x7E, 0x31, + 0x86, 0x4C, 0x21, 0x3E, 0x15, 0xD8, 0xE9, 0x3B, 0x32, 0x3D, + 0x1E, 0x59, 0xC5, 0x90, 0xF9, 0xFE, 0x8A, 0xF1, 0xCF, 0x51, + 0x26, 0x6A, 0xBD, 0xEB, 0xDC, 0x61, 0x4F, 0x39, 0x82, 0x17, + 0xB6, 0x48, 0x36, 0x01, 0xD7, 0xFE, 0x84, 0x28, 0x7A, 0x4E, + 0xC7, 0x85, 0x5A, 0x67, 0xDF, 0xAC, 0xD2, 0xC3, 0xFD, 0x43, + 0x5A, 0x5E, 0xFB, 0x27, 0x94, 0x86, 0x39, 0x57, 0xC1, 0xC3, + 0xB8, 0xB9, 0x6C, 0x42, 0x76, 0xCC, 0xF7, 0x92, 0xCC, 0xB4, + 0x66, 0xD7, 0x96, 0x36, 0xE6, 0x00, 0xCA, 0xE9, 0x1D, 0xDF, + 0xBB, 0x50, 0xF5, 0xCF, 0x19, 0xCF, 0x5D, 0x51, 0x79, 0xE2, + 0xE5, 0x97, 0xEC, 0xB0, 0x31, 0xC6, 0xE7, 0x85, 0xB2, 0x5F, + 0x2D, 0xB2, 0x19, 0x41, 0x9A, 0x2F, 0xB3, 0x77, 0xB9, 0x55, + 0xFE, 0x58, 0x66, 0xE9, 0x36, 0x28, 0x07, 0x02, 0xEC, 0xAA, + 0xD7, 0xC6, 0x7F, 0x86, 0x22, 0xF6, 0x4A, 0x99, 0x42, 0xD8, + 0x4E, 0xFC, 0x39, 0x18, 0xCE, 0x97, 0xF2, 0xE7, 0xCE, 0x58, + 0xB2, 0x4B, 0x4C, 0x84, 0x74, 0x60, 0xC1, 0xF8, 0x6C, 0xDD, + 0x81, 0x4D, 0x42, 0x8D, 0x3C, 0x90, 0x25, 0x3D, 0xF8, 0xCE, + 0x86, 0xEA, 0x44, 0x54, 0xE1, 0xB0, 0x62, 0x37, 0x6C, 0xE0, + 0x9B, 0xFC, 0x55, 0x7D, 0x71, 0x9E, 0x94, 0x82, 0xD4, 0x62, + 0x6B, 0x8A, 0x1C, 0xA4, 0xF1, 0x1E, 0x07, 0x3D, 0xF8, 0xB8, + 0x57, 0xAF, 0x40, 0x35, 0xDF, 0x8B, 0x37, 0x24, 0xDC, 0x67, + 0x35, 0x5B, 0x65, 0x66, 0x2C, 0x0D, 0x41, 0x40, 0x8A, 0xB1, + 0xE2, 0xFA, 0x8D, 0x3D, 0x23, 0xA6, 0x15, 0xDF, 0x5C, 0x88, + 0xA2, 0x40, 0xE0, 0x7C, 0xF1, 0x33, 0x39, 0x9B, 0xC7, 0x7E, + 0xD5, 0xC1, 0xA8, 0x21, 0x6B, 0xB4, 0x9C, 0x9E, 0xE1, 0x7A, + 0xAE, 0xDC, 0x30, 0x40, 0x54, 0x66, 0xA0, 0x60, 0xA0, 0x73, + 0xF9, 0x7D, 0xA1, 0xCC, 0x51, 0x33, 0x2C, 0x2E, 0x16, 0xA2, + 0x87, 0x98, 0x70, 0x43, 0xCF, 0x40, 0x09, 0x0D, 0xC2, 0x6E, + 0x20, 0xEF, 0xED, 0xE3, 0xDE, 0xF3, 0x35, 0x01, 0xB3, 0x21, + 0xC0, 0x37, 0x44, 0xB9, 0xE8, 0xDB, 0x4A, 0xD1, 0x7E, 0x7E, + 0x9F, 0x3D, 0xFE, 0x3A, 0xEF, 0x86, 0xD5, 0x4C, 0x4A, 0x03, + 0x6C, 0xFE, 0x0F, 0x76, 0x7B, 0xB2, 0xE5, 0x99, 0xAE, 0x34, + 0x34, 0xF9, 0x47, 0x97, 0x0F, 0x59, 0x24, 0xCD, 0xB1, 0x74, + 0x8D, 0xC8, 0x8A, 0x5D, 0x0A, 0xD6, 0x78, 0xA4, 0x9D, 0x10, + 0x87, 0xA7, 0xD4, 0x2B, 0x19, 0xA4, 0x45, 0x1F, 0xE9, 0x5D, + 0x6D, 0x14, 0x4D, 0xA0, 0x5E, 0x01, 0x64, 0xEE, 0x12, 0x89, + 0xD0, 0x77, 0xCC, 0x88, 0x5B, 0x00, 0x77, 0xE1, 0x09, 0xE6, + 0x32, 0x6A, 0xDF, 0x14, 0xE3, 0x2F, 0xF7, 0x14, 0x2A, 0x89, + 0x54, 0x4B, 0x07, 0xD9, 0x04, 0x3A, 0xFE, 0x22, 0xF2, 0x81, + 0x19, 0x92, 0x69, 0x70, 0xF7, 0x29, 0x2B, 0x5C, 0x74, 0x99, + 0x20, 0xF9, 0xEE, 0x69, 0x1C, 0xA5, 0x7E, 0x44, 0xBC, 0xEC, + 0x88, 0xBB, 0x0D, 0xC8, 0xAD, 0xE5, 0x47, 0x82, 0x9D, 0x9E, + 0xCF, 0xAD, 0x3B, 0x7F, 0xDD, 0xE8, 0x4C, 0x79, 0xDB, 0x1A, + 0xA5, 0x39, 0x76, 0x6F, 0x99, 0x6B, 0x32, 0x24, 0xAC, 0x39, + 0xEA, 0x98, 0x81, 0xA7, 0x9F, 0xD0, 0x10, 0x4C, 0xA7, 0xA5, + 0x39, 0x1D, 0x30, 0x05, 0xFA, 0xB7, 0xF7, 0x0A, 0x0D, 0xBA, + 0x8C, 0xA0, 0x90, 0xB1, 0x4A, 0x75, 0x17, 0x2C, 0x87, 0xBA, + 0x27, 0x41, 0x7F, 0xA5, 0xCF, 0x0B, 0xA4, 0x3B, 0x5F, 0xB6, + 0xCC, 0x6F, 0x0A, 0x0A, 0x25, 0x04, 0x67, 0xF5, 0x92, 0x7F, + 0xD2, 0xF6, 0x6A, 0xAF, 0xB2, 0x43, 0x93, 0xCB, 0x92, 0x7D, + 0xA6, 0xB4, 0x52, 0xBF, 0x76, 0x5A, 0xC2, 0xFB, 0xC1, 0x12, + 0xEB, 0x94, 0xC2, 0x49, 0x4C, 0x9C, 0x0B, 0x93, 0x0E, 0x68, + 0x83, 0x78, 0xA3, 0x72, 0xFE, 0xE9, 0x00, 0x65, 0x57, 0x55, + 0x07, 0xFA, 0xB8, 0xCF, 0x8E, 0xCF, 0x8E, 0xCF, 0x44, 0x01, + 0x4D, 0xDF, 0x66, 0x7E, 0x64, 0xE1, 0x1B, 0x19, 0x5C, 0x12, + 0xDD, 0x8E, 0x23, 0x68, 0x2B, 0xF0, 0xD3, 0xF5, 0x7A, 0x91, + 0x47, 0x5C, 0xE3, 0xF0, 0x85, 0x41, 0xD8, 0x9A, 0xFF, 0x24, + 0x26, 0x21, 0x6B, 0xA1, 0x6E, 0x62, 0x12, 0xFD, 0xD3, 0xD8, + 0x36, 0x5B, 0xCC, 0xB0, 0x59, 0x4F, 0x0C, 0x5A, 0xD6, 0x5B, + 0x11, 0xA6, 0x65, 0xB1, 0x3F, 0x0A, 0x96, 0xD2, 0x31, 0x00, + 0x9D, 0xD5, 0x73, 0x86, 0xE8, 0x82, 0x11, 0xFB, 0x71, 0x4B, + 0x92, 0xA1, 0x3E, 0x39, 0x6C, 0x42, 0x51, 0x2F, 0x69, 0x69, + 0x56, 0xC2, 0xED, 0xE3, 0x2E, 0x9F, 0xFD, 0x88, 0xC6, 0xA9, + 0xAC, 0xDC, 0xB9, 0xA6, 0x36, 0x57, 0xBD, 0x15, 0xF0, 0xE1, + 0x36, 0xEE, 0x90, 0xB0, 0xBD, 0x27, 0xED, 0xCB, 0x29, 0xBB, + 0x0C, 0x83, 0xB0, 0x18, 0x42, 0x36, 0x18, 0x98, 0x28, 0x0F, + 0xFC, 0xB0, 0x2A, 0xD5, 0x72, 0x10, 0x5A, 0x1A, 0x58, 0xE5, + 0x95, 0xA7, 0x86, 0x19, 0xAC, 0x92, 0xAD, 0x21, 0x53, 0x67, + 0x2E, 0x66, 0x59, 0xB0, 0x03, 0xF4, 0xE1, 0x29, 0x79, 0x0A, + 0xAA, 0x9D, 0x2D, 0x61, 0xC2, 0xE7, 0x36, 0x2D, 0x8B, 0x22, + 0x3E, 0x3D, 0x9F, 0xD8, 0xE3, 0x34, 0xD9, 0x47, 0x3C, 0x2E, + 0x9A, 0x97, 0x4F, 0x9F, 0x8E, 0x9A, 0xEA, 0x18, 0x2A, 0x8C, + 0xD5, 0x0D, 0x1A, 0xA1, 0x27, 0xBB, 0x95, 0xF2, 0xDF, 0xA5, + 0xB2, 0x7F, 0xFD, 0x8D, 0xC4, 0xB1, 0xA7, 0xFD, 0xA5, 0x82, + 0x78, 0x04, 0xFA, 0x92, 0xD1, 0x54, 0x0A, 0x40, 0x0D, 0x59, + 0x36, 0xC3, 0x16, 0x1D, 0xE7, 0xF8, 0x88, 0xBF, 0xE6, 0x74, + 0xD8, 0x26, 0xFC, 0x77, 0x4D, 0x3D, 0x68, 0xD6, 0x37, 0x0C, + 0x0F, 0x5A, 0xC5, 0x47, 0x02, 0x90, 0x7A, 0x5A, 0x96, 0x79, + 0x69, 0x30, 0x4F, 0xD5, 0xAA, 0x60, 0x3D, 0xE7, 0x5D, 0x09, + 0x41, 0x54, 0x06, 0xC2, 0xCA, 0xD5, 0xB8, 0xFB, 0x12, 0x15, + 0x22, 0x0E, 0x49, 0x8C, 0xD9, 0xB4, 0x3C, 0x36, 0x7C, 0xCB, + 0x3C, 0xFA, 0x97, 0xF4, 0x1C, 0xCF, 0x49, 0x81, 0x96, 0xF3, + 0x5E, 0xC8, 0x43, 0xB9, 0x28, 0xD6, 0xE9, 0x3D, 0x9E, 0xB3, + 0x4C, 0xE5, 0x87, 0x23, 0xDD, 0xC9, 0x93, 0x69, 0x3E, 0x5F, + 0x3B, 0xB6, 0xA8, 0x11, 0x3F, 0x70, 0x10, 0x3E, 0x13, 0xCF, + 0x69, 0x89, 0xAB, 0x58, 0xB0, 0x68, 0x74, 0x68, 0x4A, 0x61, + 0x0A, 0x6E, 0xFE, 0xF0, 0xDA, 0xA1, 0x11, 0x67, 0xC1, 0x90, + 0xAB, 0xE7, 0x23, 0x69, 0x73, 0xD2, 0xF0, 0xD8, 0x6F, 0x09, + 0x22, 0x35, 0xA3, 0xBA, 0x3A, 0x80, 0x6B, 0x45, 0x90, 0x2F, + 0x17, 0x68, 0xF6, 0x0D, 0x52, 0x32, 0x51, 0x67, 0xDE, 0x70, + 0x88, 0x7B, 0x33, 0xF9, 0x2C, 0xE0, 0xE1, 0x0C, 0x56, 0x26, + 0xE6, 0x86, 0xD9, 0x80, 0x6E, 0xD0, 0x86, 0xF1, 0xC9, 0x1A, + 0x08, 0x94, 0x1E, 0x01, 0x72, 0x51, 0x04, 0x73, 0x47, 0xAE, + 0x6C, 0xFC, 0x16, 0x48, 0x73, 0x30, 0xCF, 0xC6, 0xBD, 0x6E, + 0x26, 0xF6, 0x9F, 0xAE, 0xF3, 0x3D, 0x39, 0x12, 0xF3, 0x39, + 0x00, 0x87, 0x10, 0x30, 0x83, 0xDC, 0x75, 0x38, 0x2B, 0x83, + 0x43, 0xAB, 0xC0, 0x56, 0x08, 0x6F, 0x54, 0x9E, 0xCD, 0x78, + 0x05, 0x86, 0x38, 0xFC, 0x95, 0x18, 0x76, 0xC0, 0x19, 0x5A, + 0xCA, 0xAF, 0xEB, 0x1E, 0x07, 0x1A, 0x35, 0x12, 0x63, 0xF8, + 0x3F, 0xC8, 0x7F, 0xCE, 0x0A, 0x13, 0xBD, 0x9A, 0x6D, 0x03, + 0x77, 0xE3, 0xB9, 0x04, 0x84, 0xCD, 0x37, 0x95, 0x39, 0x25, + 0xA8, 0x73, 0x06, 0x1F, 0x99, 0x15, 0xBA, 0xA8, 0xFA, 0x97, + 0x8B, 0x44, 0x69, 0x01, 0xB2, 0xE5, 0xD1, 0x0B, 0xD6, 0x09, + 0x37, 0x3D, 0x2E, 0x06, 0x51, 0xEC, 0x62, 0x4B, 0x34, 0x50, + 0x80, 0xB6, 0xA4, 0xA6, 0x16, 0x3B, 0x2A, 0xE7, 0x97, 0x1D, + 0xA9, 0x8D, 0xE1, 0x11, 0xCB, 0x7C, 0xD4, 0xF0, 0x85, 0x61, + 0x80, 0xC9, 0x6C, 0x4C, 0x9F, 0x85, 0x6F, 0xA7, 0xA5, 0x23, + 0x5D, 0x7B, 0xB5, 0x47, 0xA2, 0xCA, 0xDC, 0x5D, 0x0B, 0x62, + 0xBA, 0x61, 0x0E, 0xD4, 0xE2, 0xD6, 0x96, 0xDF, 0xE7, 0x5C, + 0x7F, 0xED, 0x4B, 0x9A, 0x7F, 0xDB, 0x7A, 0x6F, 0x4F, 0x4C, + 0x88, 0x94, 0x26, 0x86, 0xA9, 0x58, 0x09, 0xB0, 0xB3, 0x49, + 0x40, 0xD2, 0xF4, 0x35, 0xDB, 0x90, 0x32, 0x5D, 0xCB, 0x9D, + 0xE5, 0x03, 0x8D, 0x97, 0x13, 0x8C, 0x2C, 0xEF, 0x16, 0x5B, + 0x47, 0x3E, 0xDD, 0x9D, 0x00, 0x45, 0x9D, 0x43, 0xB1, 0xC0, + 0x65, 0x36, 0x87, 0xE2, 0x72, 0x84, 0x70, 0xE4, 0x40, 0x2E, + 0xD3, 0x47, 0x19, 0xCD, 0x13, 0x57, 0x4D, 0x1F, 0xD6, 0x64, + 0x38, 0x5A, 0x14, 0xFA, 0xCE, 0xF0, 0x9E, 0x23, 0xF6, 0xA7, + 0x3E, 0x24, 0xBD, 0x03, 0xD4, 0x94, 0xFD, 0x9F, 0x91, 0x6F, + 0x04, 0x99, 0x57, 0xBA, 0x04, 0x6B, 0x7D, 0xFA, 0xB8, 0x69, + 0xC0, 0xCF, 0x95, 0x42, 0x29, 0xD7, 0x2A, 0x6D, 0x63, 0xC4, + 0x45, 0x14, 0x7B, 0xE9, 0x5E, 0x0B, 0x55, 0x54, 0x9C, 0x8D, + 0x7C, 0x65, 0x62, 0x33, 0xD2, 0x3B, 0xC6, 0xD1, 0xD3, 0xEB, + 0xBA, 0xA8, 0xE3, 0xEA, 0xBB, 0x73, 0xAF, 0x52, 0xFE, 0xB9, + 0x91, 0xD2, 0x34, 0xEA, 0xE9, 0x87, 0x62, 0x90, 0xA0, 0x7C, + 0x96, 0x73, 0x59, 0x0D, 0x7C, 0x25, 0x68, 0x34, 0xAF, 0x4B, + 0xCF, 0xE4, 0x78, 0xC0, 0xFF, 0x26, 0x6A, 0x42, 0xE0, 0xF4, + 0xEC, 0x1E, 0xA5, 0x05, 0xEE, 0xED, 0x4E, 0x68, 0xA4, 0x0B, + 0x3C, 0xF6, 0x7A, 0x41, 0x53, 0xE6, 0xCA, 0x1B, 0x1F, 0x8B, + 0xE4, 0xEA, 0xD2, 0x66, 0x40, 0xEF, 0x83, 0x74, 0xB3, 0x0C, + 0x6E, 0x66, 0x00, 0xF3, 0xE6, 0x94, 0xC3, 0x0B, 0x60, 0xFB, + 0x15, 0x7F, 0x39, 0x85, 0x60, 0x5F, 0xBF, 0xA8, 0x94, 0x45, + 0x86, 0x3F, 0xD4, 0x54, 0xC5, 0xA3, 0xE9, 0x51, 0x18, 0x51, + 0x40, 0x64, 0xFD, 0xEB, 0x9B, 0x11, 0x33, 0x8C, 0xDD, 0x9B, + 0xC8, 0xB2, 0xD7, 0x44, 0x2C, 0x56, 0xB0, 0x81, 0xEA, 0x0C, + 0x0B, 0x9F, 0xF7, 0x1D, 0x9C, 0x27, 0xD6, 0x76, 0x80, 0x01, + 0x68, 0xC2, 0xA8, 0x69, 0x80, 0x5E, 0xE8, 0x93, 0x32, 0xA0, + 0xB1, 0x43, 0x35, 0xE6, 0x73, 0x9E, 0x69, 0x60, 0xC8, 0x31, + 0x69, 0xE0, 0xAF, 0xFD, 0xD2, 0xE9, 0x25, 0x9E, 0x3D, 0xDA, + 0x66, 0xE6, 0xD7, 0x8E, 0xDB, 0x68, 0x04, 0xB0, 0xFE, 0x04, + 0xF8, 0x72, 0x01, 0x0B, 0xE1, 0x66, 0xC4, 0xA0, 0xE4, 0xF7, + 0xF3, 0x6E, 0x91, 0x60, 0xAD, 0x53, 0xE7, 0x9D, 0xBC, 0x6A, + 0xDF, 0x47, 0x8D, 0x25, 0x9F, 0xB3, 0x60, 0x6C, 0x87, 0x5C, + 0x60, 0x00, 0x98, 0xE3, 0x4A, 0x96, 0xA5, 0xAF, 0x1F, 0x96, + 0x0B, 0x96, 0x4F, 0xC6, 0x54, 0x1F, 0x48, 0x67, 0xC7, 0xA4, + 0x6E, 0xC0, 0x82, 0x8C, 0x43, 0x0D, 0x8D, 0x10, 0x84, 0x48, + 0xEA, 0x46, 0xF2, 0x15, 0x85, 0x70, 0x5A, 0x8F, 0x76, 0xD7, + 0x37, 0x82, 0xE4, 0x07, 0x09, 0x4D, 0xB7, 0xCF, 0xA3, 0xAA, + 0xE8, 0xD7, 0x3C, 0x8B, 0xE4, 0x86, 0xD4, 0xA9, 0xC9, 0x30, + 0x9A, 0xCE, 0xE4, 0x7B, 0x0C, 0x17, 0xC6, 0x2E, 0x4E, 0x4A, + 0x7C, 0x4E, 0xB3, 0xAD, 0xE3, 0x93, 0x8A, 0x31, 0x11, 0x2D, + 0x43, 0xBE, 0x02, 0x8D, 0x5C, 0xEA, 0x7D, 0x9A, 0x08, 0xAB, + 0x3D, 0x70, 0x84, 0x4F, 0x8F, 0xB0, 0x77, 0x02, 0x99, 0x85, + 0x62, 0x93, 0x71, 0x4C, 0xCD, 0x7A, 0xD1, 0x75, 0xD1, 0xBB, + 0x2A, 0xC9, 0x54, 0xBF, 0xDA, 0xF1, 0x70, 0xE9, 0xEF, 0x8D, + 0x08, 0x66, 0xE9, 0xD6, 0xE3, 0x6F, 0x4B, 0x99, 0xEB, 0x44, + 0x51, 0x12, 0xEE, 0x21, 0x34, 0xE1, 0xD1, 0x3A, 0x4D, 0x17, + 0xEF, 0xE7, 0x7F, 0x48, 0xD7, 0x35, 0x45, 0x05, 0xF0, 0x0E, + 0xFF, 0x32, 0xB5, 0x20, 0xF5, 0x19, 0xCF, 0x5A, 0x0E, 0xD8, + 0x2C, 0x85, 0x42, 0xF2, 0x60, 0xD0, 0xA1, 0x49, 0xD6, 0xEE, + 0x14, 0x3B, 0x2F, 0xCD, 0x0B, 0x2D, 0x8F, 0x11, 0x68, 0xF2, + 0x97, 0x22, 0xFF, 0x88, 0x76, 0x48, 0xF8, 0x3A, 0x10, 0x0F, + 0x66, 0x26, 0x73, 0x60, 0x68, 0x91, 0xEE, 0x54, 0xE2, 0xC8, + 0x04, 0xFB, 0xCD, 0x3E, 0xEB, 0x07, 0x84, 0xA1, 0x7A, 0x93, + 0x1B, 0x4A, 0xD7, 0xB6, 0xB2, 0x0E, 0xE4, 0x79, 0x1C, 0xB0, + 0x77, 0x1D, 0x86, 0x1D, 0x99, 0x9A, 0x40, 0x6F, 0x3E, 0x30, + 0xCD, 0xA1, 0xC2, 0x74, 0x55, 0x56, 0x1E, 0xE2, 0x05, 0x04, + 0x10, 0xDB, 0x88, 0xF6, 0xE3, 0x2E, 0x58, 0xF3, 0x35, 0x6E, + 0x05, 0x6B, 0xA9, 0x4F, 0x42, 0x9E, 0x8D, 0xA8, 0x99, 0x7F, + 0x15, 0x63, 0x41, 0x27, 0x81, 0xE7, 0x73, 0xDE, 0x1F, 0x0B, + 0x9B, 0xFE, 0xDF, 0x5E, 0xC7, 0x06, 0x8E, 0x33, 0x20, 0x19, + 0xA3, 0xFB, 0x9B, 0xD9, 0xA0, 0xBE, 0x5F, 0x44, 0x45, 0x1A, + 0x9C, 0x11, 0xAA, 0x6A, 0x8F, 0xA0, 0x20, 0x02, 0xCC, 0xBC, + 0xC9, 0xD9, 0x09, 0x46, 0x00, 0xF3, 0x50, 0xDC, 0x21, 0xEF, + 0xBB, 0x35, 0x18, 0xD7, 0x2A, 0x3A, 0x0F, 0x0D, 0x7D, 0x5F, + 0x1B, 0x57, 0xB0, 0x34, 0xFB, 0x55, 0xBD, 0xE9, 0x72, 0xBD, + 0x46, 0xBF, 0x90, 0x0D, 0xB0, 0xEE, 0x7D, 0x57, 0xB6, 0x4D, + 0x82, 0xB0, 0xD8, 0x27, 0xCC, 0xFC, 0xEB, 0xE9, 0x3C, 0x7B, + 0x98, 0xF3, 0x95, 0x15, 0xA6, 0xBE, 0x64, 0x77, 0x7D, 0x50, + 0xC0, 0x68, 0x09, 0x7D, 0x8F, 0x18, 0xEE, 0xB6, 0x76, 0xFF, + 0x0E, 0x87, 0xE3, 0xAE, 0x59, 0xD2, 0x27, 0xBA, 0x0A, 0xC2, + 0x96, 0x96, 0x5C, 0x2B, 0x93, 0x30, 0x36, 0x36, 0x7F, 0x70, + 0x82, 0xB3, 0x5C, 0x2C, 0x42, 0xD5, 0xFE, 0xDB, 0xC5, 0x58, + 0xA0, 0x71, 0xAB, 0x17, 0x06, 0x10, 0x0F, 0x49, 0x19, 0x42, + 0x65, 0x29, 0x22, 0xC4, 0x69, 0x58, 0xA8, 0xE1, 0xA9, 0xB3, + 0x51, 0xBA, 0x9B, 0xAD, 0x03, 0xE8, 0xCB, 0x34, 0xFF, 0x24, + 0x47, 0x9A, 0x1E, 0x0F, 0xFC, 0x1F, 0xE7, 0xDE, 0x68, 0x33, + 0xA4, 0x54, 0xBE, 0xF0, 0x7D, 0x16, 0x3C, 0x27, 0x79, 0x1F, + 0x24, 0x24, 0xEF, 0x41, 0xB8, 0xA7, 0x25, 0xC3, 0xE8, 0x93, + 0xF5, 0x9F, 0xC3, 0x3B, 0x08, 0xDE, 0xF0, 0x54, 0xF5, 0xE7, + 0x79, 0x71, 0x1F, 0x89, 0x7A, 0xA9, 0xB0, 0x47, 0xCA, 0x53, + 0x3C, 0xD2, 0xA8, 0xB7, 0x5C, 0xF5, 0xDD, 0xD4, 0x07, 0x6E, + 0xA5, 0xAB, 0x66, 0x91, 0x5B, 0x44, 0x91, 0xA7, 0x1F, 0x05, + 0xB1, 0x3D, 0x79, 0xEC, 0x9D, 0x12, 0x14, 0xF7, 0xEC, 0x46, + 0xEA, 0x51, 0x2A, 0xC8, 0xBD, 0x3C, 0xCB, 0xAE, 0x1D, 0x07, + 0x6D, 0xE2, 0x85, 0xB0, 0xC4, 0xAB, 0x42, 0x52, 0xD4, 0x1C, + 0x89, 0x1D, 0xDE, 0x5A, 0x5A, 0x20, 0x21, 0x19, 0x8C, 0xF8, + 0xD2, 0xF1, 0x25, 0x88, 0x79, 0xAF, 0x8F, 0x8E, 0xF0, 0xC5, + 0x35, 0x05, 0x15, 0x88, 0x04, 0x5C, 0x2F, 0xB3, 0xD2, 0x07, + 0x2F, 0x1B, 0x5D, 0x68, 0x71, 0x91, 0x94, 0x8C, 0xCE, 0x11, + 0x30, 0xA6, 0x48, 0x21, 0x2E, 0xE8, 0x52, 0xBE, 0xD0, 0xB3, + 0x8E, 0x4C, 0x16, 0xEB, 0x04, 0x6C, 0x45, 0x92, 0x08, 0xD4, + 0x45, 0x97, 0x60, 0xC6, 0xC5, 0x07, 0x4D, 0x3D, 0xAA, 0x90, + 0xD7, 0xE8, 0xBF, 0xA1, 0x17, 0xDC, 0xBF, 0x5E, 0x18, 0x44, + 0xE5, 0x97, 0xBB, 0x33, 0x23, 0x87, 0x71, 0x05, 0x83, 0x17, + 0x00, 0x69, 0x9E, 0x8B, 0x59, 0x3A, 0x30, 0x1F, 0x8B, 0x11, + 0xBC, 0xB8, 0xF2, 0x1A, 0x3E, 0x5F, 0xDB, 0x02, 0xE8, 0x05, + 0x73, 0xF9, 0x58, 0xE9, 0x8E, 0xB8, 0x62, 0xF4, 0x63, 0x70, + 0x7E, 0x46, 0xED, 0x51, 0xAB, 0x92, 0x66, 0x81, 0x06, 0xAC, + 0xC9, 0x3F, 0xCC, 0xB1, 0xF9, 0x38, 0x7C, 0xCB, 0x75, 0x85, + 0x65, 0x1D, 0x2B, 0x09, 0xF0, 0xB8, 0x10, 0x4B, 0xA7, 0xF1, + 0x2D, 0x99, 0xFB, 0xC5, 0xEA, 0xEA, 0xCE, 0x25, 0x5A, 0xFA, + 0x97, 0xF1, 0x1E, 0x70, 0x23, 0xB9, 0xA6, 0x79, 0x98, 0xEC, + 0x0D, 0xCE, 0x96, 0x0C, 0xB0, 0xF5, 0x50, 0x21, 0xB9, 0xF7, + 0x88, 0xAB, 0x40, 0x7E, 0xE8, 0x4A, 0xA4, 0x2C, 0x02, 0xED, + 0x83, 0xAB, 0x68, 0xDA, 0x21, 0x4D, 0x1C, 0x2A, 0xEB, 0xF9, + 0xD5, 0x5F, 0xB1, 0xDC, 0xFA, 0x75, 0xA3, 0x7D, 0xC6, 0x84, + 0x80, 0x73, 0xE8, 0xCE, 0x64, 0x11, 0xDE, 0x1B, 0x75, 0x9F, + 0xDD, 0xFB, 0xFE, 0x82, 0xA2, 0xE0, 0x45, 0xA3, 0xD4, 0x2C, + 0x46, 0xD0, 0xC6, 0x45, 0x5F, 0x1B, 0xD6, 0x93, 0x20, 0xAE, + 0xA4, 0x62, 0xDE, 0xB4, 0x24, 0xAD, 0x73, 0xD9, 0x46, 0x8D, + 0x4B, 0x6D, 0xF9, 0x49, 0xA9, 0xB5, 0x43, 0xDA, 0x34, 0xDD, + 0x72, 0x68, 0xB4, 0x82, 0x1B, 0x54, 0xA9, 0xC6, 0x0E, 0xB4, + 0x25, 0x0C, 0xDC, 0x97, 0x5F, 0xAB, 0x20, 0xFB, 0x4D, 0x33, + 0x15, 0xD1, 0xC3, 0x15, 0x27, 0xC4, 0x3A, 0x06, 0xE3, 0x72, + 0xD4, 0xF8, 0xFD, 0xB3, 0xE8, 0x04, 0x59, 0xBC, 0xAB, 0xA3, + 0x43, 0xBE, 0x60, 0x34, 0x09, 0x53, 0x78, 0x64, 0x9C, 0x8C, + 0x72, 0xE4, 0x74, 0x62, 0x83, 0x2D, 0xB1, 0xA9, 0x67, 0xEC, + 0x80, 0x92, 0x43, 0x94, 0x2E, 0x4B, 0xCE, 0x40, 0x16, 0xA5, + 0xD4, 0x1C, 0xE9, 0x5B, 0xF6, 0x47, 0x70, 0x55, 0x7B, 0x16, + 0xF1, 0x96, 0x29, 0x4F, 0x77, 0x83, 0x39, 0x80, 0x46, 0xD0, + 0x67, 0x96, 0x32, 0x22, 0xBC, 0x8A, 0x9E, 0x3B, 0xC3, 0xC1, + 0xD6, 0x8D, 0x0B, 0x35, 0xE3, 0x61, 0x27, 0x54, 0xEA, 0x6C, + 0x9B, 0x75, 0x8C, 0x58, 0x2A, 0x90, 0x9E, 0x28, 0xBC, 0xD8, + 0xAE, 0xBD, 0xDD, 0xA0, 0x7A, 0xE4, 0x2A, 0x11, 0xFE, 0xAA, + 0x7C, 0x64, 0x53, 0x69, 0x7B, 0xC9, 0xBB, 0xBB, 0xF3, 0x0A, + 0xE9, 0xAD, 0x44, 0x14, 0xD0, 0x2D, 0x82, 0x20, 0x3C, 0x82, + 0xBB, 0x03, 0x54, 0x54, 0x97, 0xEF, 0x86, 0xD3, 0xC8, 0xEB, + 0x37, 0x7D, 0x3A, 0xF4, 0x2E, 0xDE, 0x5F, 0x80, 0xB1, 0xBE, + 0xCC, 0x27, 0xA8, 0xD5, 0x0C, 0xB6, 0x69, 0xEF, 0xAC, 0x6A, + 0x50, 0x19, 0x68, 0xCA, 0xB2, 0x9F, 0x8E, 0x1E, 0x2B, 0x64, + 0x94, 0xA2, 0x8A, 0x32, 0x82, 0x4B, 0x6B, 0x4A, 0xB8, 0xF3, + 0x7D, 0xF0, 0xAC, 0xF0, 0x33, 0xFC, 0x2A, 0x3A, 0x93, 0x2B, + 0xF0, 0xE7, 0xB2, 0x73, 0x75, 0xB8, 0x89, 0xD9, 0x25, 0xA5, + 0xD1, 0x8C, 0x8E, 0x57, 0x49, 0x86, 0x58, 0x36, 0x76, 0xAA, + 0xE7, 0x4C, 0x76, 0x08, 0x7F, 0xFC, 0x9E, 0xF2, 0xC5, 0xB5, + 0xF3, 0xFD, 0xF2, 0xB3, 0x3B, 0x76, 0x29, 0xDB, 0x9B, 0x3B, + 0xA1, 0x09, 0xA9, 0x38, 0x5E, 0xE8, 0xC4, 0x9F, 0x88, 0x53, + 0x2E, 0xFB, 0x52, 0xBB, 0x3B, 0x2B, 0xE1, 0xE1, 0x28, 0x26, + 0x88, 0x14, 0x09, 0xF1, 0xCC, 0x98, 0xD9, 0xA4, 0x0C, 0xA0, + 0x54, 0xD0, 0xB7, 0x3C, 0x8C, 0xE9, 0x4F, 0x64, 0xCB, 0xBE, + 0xA5, 0x06, 0xAE, 0x27, 0xF0, 0x37, 0xB2, 0x60, 0x27, 0x9A, + 0x93, 0x67, 0xB2, 0x39, 0x54, 0x95, 0xA8, 0x6E, 0x93, 0x6C, + 0x09, 0x6C, 0xFF, 0xA1, 0xC2, 0x99, 0x66, 0x0A, 0x01, 0x2A, + 0x8C, 0x2D, 0x9C, 0x23, 0x0B, 0x19, 0x4E, 0xA1, 0x3E, 0x43, + 0x42, 0x1A, 0x72, 0x11, 0xAC, 0x92, 0x56, 0x32, 0xD4, 0xFE, + 0x5A, 0x0E, 0xDF, 0xEB, 0x7B, 0x1F, 0x61, 0x9B, 0xDA, 0x3C, + 0x2E, 0xAE, 0xFF, 0x12, 0x11, 0x3E, 0xB2, 0xC3, 0xAE, 0xD1, + 0xD9, 0xB2, 0xE8, 0xD5, 0x9E, 0x85, 0xA4, 0xF1, 0x49, 0x06, + 0x16, 0x73, 0xCA, 0x65, 0x3A, 0x2D, 0x51, 0x38, 0xBA, 0x37, + 0xF3, 0xCF, 0xDC, 0xDF, 0x40, 0xF5, 0x5D, 0x39, 0x74, 0x60, + 0x15, 0xF5, 0xDC, 0x73, 0xE2, 0x48, 0xF2, 0x2A, 0x2C, 0x4F, + 0x26, 0xD2, 0x61, 0x5B, 0x31, 0xA0, 0xF4, 0xEA, 0x80, 0xAE, + 0xB2, 0x57, 0x81, 0x64, 0xD1, 0xFB, 0xE9, 0xA0, 0x3B, 0xB7, + 0xDE, 0x17, 0x42, 0x7B, 0xCD, 0xDE, 0xE4, 0xA3, 0x45, 0x5E, + 0x88, 0x29, 0x85, 0x26, 0xB7, 0xD6, 0xA4, 0xE9, 0x73, 0x9E, + 0x1D, 0x73, 0x92, 0xF4, 0xFF, 0x66, 0xA8, 0xB9, 0x1D, 0x25, + 0x1B, 0x12, 0xB2, 0x9E, 0x6E, 0xE1, 0xA8, 0xB5, 0x73, 0x64, + 0x0B, 0x8D, 0xDC, 0xE3, 0x2C, 0x60, 0x32, 0x82, 0x4E, 0x9C, + 0x47, 0x0B, 0x5E, 0x92, 0xF0, 0x21, 0x62, 0x50, 0x8E, 0x1A, + 0xE4, 0x2B, 0x4B, 0x6F, 0xB5, 0xDA, 0xAB, 0xAB, 0x4A, 0xBE, + 0xB6, 0x6F, 0x09, 0x3A, 0xF4, 0x67, 0x75, 0x07, 0xB1, 0xB1, + 0xAA, 0xAD, 0x16, 0x3F, 0x5B, 0xD1, 0xA3, 0x9F, 0xF5, 0x7F, + 0xA8, 0xEA, 0xC8, 0x8D, 0x5A, 0xA9, 0xF3, 0x7B, 0xE8, 0x83, + 0xDB, 0xB0, 0xA7, 0xFD, 0x2C, 0xA1, 0xD6, 0x39, 0xDE, 0x65, + 0x2C, 0xE3, 0x4F, 0xA5, 0x0E, 0x2D, 0x47, 0xA0, 0x32, 0x8A, + 0x1F, 0x55, 0x3B, 0x92, 0x3D, 0x4A, 0x84, 0x67, 0xE2, 0x5A, + 0x10, 0x80, 0x1B, 0xA2, 0xFE, 0x4B, 0x8F, 0x73, 0xB5, 0xA5, + 0x6B, 0xFA, 0x5B, 0x86, 0x95, 0xB8, 0x89, 0x9B, 0x8E, 0xBF, + 0x39, 0xAF, 0x4F, 0x2B, 0x1A, 0xC6, 0x4E, 0xAC, 0xD6, 0xDA, + 0x34, 0xDA, 0x6B, 0xD6, 0x1A, 0x49, 0x99, 0xD0, 0x87, 0x4F, + 0x1A, 0x51, 0xA0, 0x46, 0x89, 0x0E, 0x0B, 0x81, 0x4C, 0x63, + 0xE2, 0xCA, 0x7C, 0xED, 0x81, 0x53, 0x11, 0x11, 0x5F, 0x8D, + 0xFD, 0xDD, 0x08, 0xEE, 0x6B, 0x8E, 0xF0, 0x8B, 0x39, 0x59, + 0x24, 0x13, 0xA4, 0x23, 0xF2, 0xFE, 0xDC, 0x0C, 0xEE, 0xDF, + 0xD7, 0xAA, 0x9D, 0x4E, 0x54, 0x1A, 0x27, 0xA3, 0xE5, 0x20, + 0xDE, 0x55, 0x37, 0xE2, 0xBF, 0x8E, 0x2F, 0xB9, 0x9C, 0x98, + 0xFE, 0x8F, 0x8D, 0xBD, 0x09, 0x91, 0x2D, 0xBF, 0x1E, 0x0B, + 0x26, 0x90, 0xDE, 0xE2, 0xB1, 0x5E, 0x81, 0x0A, 0x07, 0x5F, + 0xF1, 0x54, 0xFC, 0x31, 0xB0, 0x94, 0x2A, 0x13, 0x93, 0xA3, + 0x00, 0xEA, 0x43, 0xBE, 0xD7, 0x26, 0x15, 0x8A, 0x15, 0xA3, + 0x46, 0x84, 0xD5, 0x6A, 0x24, 0x9D, 0x8D, 0x1A, 0x07, 0xB2, + 0x87, 0x99, 0x6F, 0xFD, 0xF6, 0x1D, 0xD7, 0x88, 0xF2, 0x94, + 0xAA, 0xD1, 0x73, 0x7F, 0x69, 0x2F, 0x0A, 0x2A, 0x66, 0xDC, + 0x56, 0x1D, 0xFA, 0xF6, 0xC3, 0x47, 0xDF, 0x7A, 0x77, 0x0E, + 0xF2, 0x22, 0xA8, 0xDD, 0xE5, 0x6D, 0x04, 0xDA, 0x06, 0x1C, + 0xDB, 0x15, 0x07, 0xF9, 0x04, 0xD4, 0x56, 0xFF, 0x3E, 0x63, + 0x98, 0x08, 0xEB, 0xF3, 0x63, 0xC1, 0x29, 0x8E, 0xA5, 0xC7, + 0x40, 0x39, 0xD1, 0xE6, 0xFA, 0xA9, 0xF5, 0x0F, 0x63, 0x6D, + 0x85, 0x35, 0xC9, 0x0C, 0x9A, 0xA3, 0x02, 0xC3, 0x4A, 0x70, + 0x11, 0x5C, 0x9B, 0x9A, 0x7F, 0x81, 0xE2, 0x44, 0x91, 0x4E, + 0x7A, 0x6A, 0x14, 0x15, 0x2C, 0xCB, 0xC9, 0x1C, 0x69, 0x91, + 0x8C, 0x41, 0xE0, 0xBB, 0x85, 0xC8, 0x6E, 0xCC, 0x4A, 0x75, + 0x3B, 0xBB, 0x33, 0x1B, 0x6A, 0x2B, 0x95, 0xF9, 0x5E, 0x03, + 0xF2, 0x25, 0xD5, 0xD9, 0xFB, 0x9D, 0x38, 0x14, 0x1A, 0x31, + 0xB9, 0xE7, 0xE6, 0x9B, 0x4B, 0x0D, 0xE9, 0x7C, 0x59, 0x12, + 0xD2, 0x6B, 0x98, 0x0C, 0x41, 0x07, 0xDB, 0xC1, 0xA9, 0x95, + 0x53, 0xAE, 0xAD, 0xBB, 0x92, 0x36, 0xC1, 0x93, 0xF6, 0xBB, + 0x43, 0xFD, 0x16, 0xAC, 0x63, 0x27, 0x27, 0xC5, 0xF0, 0xC6, + 0x4E, 0x56, 0xE6, 0x39, 0x75, 0xC8, 0xF5, 0xDE, 0x79, 0xCE, + 0x11, 0x0F, 0x6F, 0x45, 0x70, 0xAB, 0xB4, 0x45, 0x75, 0x14, + 0xD7, 0x91, 0xD5, 0x97, 0x3F, 0xC0, 0xB9, 0x19, 0x25, 0xE6, + 0x35, 0x72, 0xB9, 0xB5, 0x8A, 0xFD, 0x24, 0x73, 0x9F, 0x1B, + 0x73, 0xE7, 0x6E, 0xE0, 0x3E, 0x9F, 0x55, 0x55, 0x29, 0x5C, + 0x6F, 0xDB, 0x6B, 0x95, 0x0C, 0x60, 0xB7, 0x52, 0xC4, 0x7E, + 0x8F, 0xDD, 0x0E, 0x8F, 0x5D, 0x7B, 0xEE, 0x17, 0x3E, 0xA1, + 0x1D, 0x84, 0xA5, 0xD8, 0x16, 0x61, 0x75, 0x88, 0xDA, 0xF3, + 0x27, 0x45, 0x0B, 0xB8, 0xDA, 0x8E, 0x96, 0xFC, 0x27, 0xFC, + 0xAA, 0x35, 0x6B, 0xAD, 0x0B, 0x0F, 0x0E, 0x8B, 0x92, 0x99, + 0x2F, 0xBF, 0x6F, 0x53, 0xC4, 0x2C, 0x84, 0x23, 0x57, 0xED, + 0xA9, 0x32, 0xCE, 0x06, 0x16, 0x4B, 0xEE, 0xF6, 0x1E, 0xA2, + 0x31, 0x39, 0x49, 0xCC, 0x65, 0xBC, 0x70, 0x6D, 0xBE, 0x69, + 0x0D, 0x24, 0x25, 0xBB, 0x63, 0x09, 0xCC, 0x11, 0x0B, 0x49, + 0x5F, 0xD5, 0xFB, 0x93, 0xF7, 0x48, 0x04, 0x09, 0xE0, 0x5D, + 0x4F, 0x7A, 0x20, 0x6C, 0x42, 0x29, 0x5C, 0x21, 0x83, 0x06, + 0x88, 0xB5, 0xEF, 0x4C, 0xAC, 0x00, 0x01, 0xC6, 0xA4, 0x48, + 0x24, 0xFC, 0x77, 0xFE, 0xEE, 0xBF, 0xF0, 0x4E, 0x0C, 0xC5, + 0x6B, 0x89, 0x57, 0xC7, 0xB9, 0xF5, 0x61, 0x27, 0x24, 0x09, + 0xDA, 0x45, 0x00, 0x0B, 0x10, 0xB8, 0x7D, 0xF3, 0xE9, 0x56, + 0x59, 0x62, 0x65, 0x8C, 0x5E, 0x03, 0xB4, 0xB1, 0x85, 0x20, + 0x60, 0x25, 0x1D, 0xA7, 0xF4, 0x28, 0xF6, 0xB0, 0x32, 0x7B, + 0xEB, 0x76, 0x85, 0x7B, 0xD4, 0xE2, 0x15, 0x1C, 0xCB, 0xF2, + 0x31, 0xBA, 0x00, 0xBB, 0xD0, 0x90, 0x16, 0xB6, 0x48, 0x1F, + 0x2F, 0x4F, 0xE4, 0x1C, 0x1D, 0xD7, 0x09, 0xB6, 0x54, 0x70, + 0x2D, 0x7F, 0x68, 0xB9, 0x87, 0xE7, 0xCB, 0xD4, 0xD5, 0xE6, + 0xB4, 0xFD, 0x0C, 0x68, 0x5C, 0x96, 0xF4, 0x06, 0x64, 0x3B, + 0x74, 0x6B, 0xD1, 0xAC, 0xB5, 0x41, 0xEE, 0xBD, 0x55, 0x07, + 0xBF, 0x29, 0x51, 0x2B, 0xC5, 0x4A, 0xCF, 0x2A, 0xF1, 0xEE, + 0x5A, 0x64, 0x2F, 0x0B, 0x80, 0x7E, 0xF4, 0x50, 0x14, 0x28, + 0xF4, 0x39, 0x04, 0xB5, 0xC7, 0xCF, 0x53, 0xEA, 0x6C, 0xBD, + 0x76, 0x6C, 0x67, 0x6E, 0x3E, 0x9F, 0xEF, 0x60, 0xD0, 0xF6, + 0x73, 0x90, 0xDD, 0x1E, 0xE9, 0x75, 0x8B, 0x34, 0x6A, 0xB2, + 0xCC, 0xD1, 0x0B, 0x51, 0x6E, 0x44, 0x55, 0x55, 0x22, 0xBB, + 0x3F, 0xD1, 0x9F, 0xF4, 0x1E, 0xB5, 0xD6, 0x89, 0x3C, 0xDB, + 0xB7, 0x07, 0x83, 0x5C, 0x63, 0x45, 0x78, 0x4B, 0xFA, 0x1E, + 0x7D, 0x3D, 0x44, 0x91, 0xD3, 0xDD, 0x57, 0x07, 0xD9, 0x0F, + 0x58, 0xC3, 0x20, 0x5E, 0xF0, 0x42, 0x05, 0x61, 0xE5, 0x03, + 0xB3, 0xB8, 0x1B, 0xBB, 0x05, 0xC2, 0x1B, 0x7A, 0x7E, 0x8B, + 0xC9, 0x06 +}; +static const int sizeof_bench_dilithium_aes_level3_key = sizeof(bench_dilithium_aes_level3_key); + +/* certs/dilithium/bench_dilithium_aes_level5_key.der */ +static const unsigned char bench_dilithium_aes_level5_key[] = +{ + 0x30, 0x82, 0x1D, 0x3A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, + 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x0B, + 0x08, 0x07, 0x04, 0x82, 0x1D, 0x24, 0x04, 0x82, 0x1D, 0x20, + 0x90, 0xBC, 0x63, 0x0F, 0xD4, 0xC2, 0x6D, 0x49, 0x01, 0xCD, + 0x1F, 0x92, 0xEC, 0xEE, 0xDB, 0x3B, 0x19, 0x0C, 0xFA, 0x4D, + 0x6C, 0x57, 0x16, 0xE0, 0x6E, 0x48, 0xB5, 0x5D, 0xB3, 0xE5, + 0xEA, 0xE6, 0xCA, 0x23, 0xD3, 0xE6, 0xE9, 0xEA, 0x3B, 0x1B, + 0x0C, 0x80, 0xD9, 0xFD, 0x2E, 0x9C, 0xD9, 0x1C, 0x44, 0x56, + 0xDD, 0xCC, 0x7C, 0x9F, 0x98, 0x1C, 0xEC, 0x7A, 0x3D, 0xB4, + 0x66, 0xCE, 0x91, 0x9F, 0x1E, 0x34, 0x96, 0xFB, 0xC6, 0x1D, + 0x3D, 0x93, 0x4A, 0x05, 0x43, 0xF8, 0xD7, 0x95, 0x10, 0x21, + 0x6C, 0xD4, 0x6F, 0xA6, 0x7B, 0x69, 0x3A, 0x1B, 0x9F, 0x0C, + 0x26, 0x84, 0x34, 0x39, 0xE6, 0xB5, 0x19, 0x83, 0x10, 0x92, + 0x30, 0x85, 0x19, 0x38, 0x31, 0x81, 0xB2, 0x51, 0x09, 0xB1, + 0x11, 0x19, 0xA6, 0x30, 0x9B, 0x80, 0x2D, 0x63, 0x26, 0x29, + 0x18, 0x93, 0x65, 0x84, 0x48, 0x72, 0x8C, 0x38, 0x81, 0xA3, + 0x18, 0x04, 0x19, 0x84, 0x20, 0x49, 0x40, 0x68, 0xA2, 0x82, + 0x80, 0x08, 0x19, 0x84, 0x4C, 0xC6, 0x90, 0x89, 0xA4, 0x80, + 0xC8, 0xA2, 0x85, 0xD2, 0x40, 0x04, 0x50, 0xA6, 0x81, 0x50, + 0xB4, 0x00, 0x18, 0x46, 0x30, 0x24, 0xC5, 0x80, 0x00, 0x93, + 0x84, 0x54, 0x22, 0x89, 0x21, 0x00, 0x88, 0xC8, 0x06, 0x64, + 0x8B, 0x20, 0x69, 0x9A, 0xB8, 0x6D, 0x58, 0x30, 0x02, 0x53, + 0x28, 0x6A, 0x20, 0xC9, 0x0C, 0x03, 0xC5, 0x60, 0x20, 0xA5, + 0x24, 0x5A, 0xC4, 0x29, 0x44, 0x38, 0x89, 0xD2, 0xB6, 0x11, + 0x24, 0x44, 0x6E, 0x12, 0x23, 0x2C, 0x99, 0x40, 0x26, 0x94, + 0x36, 0x20, 0xA2, 0x94, 0x6D, 0x49, 0x06, 0x2A, 0x52, 0x28, + 0x90, 0x09, 0x24, 0x25, 0x91, 0x20, 0x92, 0x49, 0x84, 0x0D, + 0x24, 0x83, 0x84, 0x61, 0xA4, 0x6C, 0x59, 0x32, 0x81, 0x21, + 0x34, 0x46, 0x09, 0x07, 0x05, 0xC0, 0x84, 0x8C, 0x62, 0x16, + 0x4D, 0x11, 0x90, 0x68, 0x11, 0xC8, 0x04, 0x40, 0x24, 0x41, + 0xC4, 0x14, 0x08, 0xCA, 0x38, 0x8A, 0x12, 0xB0, 0x25, 0x04, + 0xB5, 0x05, 0x22, 0x00, 0x2A, 0x48, 0x12, 0x2C, 0x1A, 0x29, + 0x20, 0xC8, 0x46, 0x4C, 0x22, 0x31, 0x60, 0xA3, 0x22, 0x6E, + 0x43, 0x12, 0x4C, 0x9B, 0xA8, 0x10, 0xD0, 0x32, 0x29, 0xE1, + 0x34, 0x82, 0x13, 0xA5, 0x31, 0x08, 0x45, 0x71, 0x01, 0x21, + 0x68, 0x12, 0xC4, 0x21, 0x0C, 0x82, 0x51, 0x40, 0x26, 0x11, + 0xDA, 0xA6, 0x09, 0x52, 0x92, 0x44, 0xC9, 0xB4, 0x51, 0x00, + 0x28, 0x8E, 0x24, 0x26, 0x42, 0xCB, 0xC4, 0x81, 0x09, 0x48, + 0x65, 0x23, 0xB9, 0x85, 0x01, 0xB2, 0x71, 0xC2, 0xC0, 0x2D, + 0x42, 0x06, 0x0D, 0x14, 0x93, 0x8C, 0x8B, 0xC0, 0x48, 0x60, + 0x82, 0x50, 0x18, 0x39, 0x50, 0x64, 0x12, 0x08, 0x11, 0x15, + 0x45, 0x02, 0x04, 0x8A, 0x0A, 0x21, 0x0D, 0x22, 0x35, 0x04, + 0xD0, 0x02, 0x41, 0x40, 0x14, 0x26, 0xCA, 0x20, 0x49, 0xA1, + 0xB0, 0x21, 0x18, 0x22, 0x64, 0xE0, 0x38, 0x11, 0x20, 0x87, + 0x8D, 0x50, 0x20, 0x6D, 0x11, 0x27, 0x42, 0x5C, 0x04, 0x41, + 0x09, 0x97, 0x88, 0xDA, 0x06, 0x91, 0x8A, 0x94, 0x0D, 0x9A, + 0x36, 0x42, 0xDC, 0x94, 0x2C, 0xCA, 0x32, 0x44, 0x52, 0x00, + 0x26, 0x02, 0x33, 0x92, 0xDA, 0x40, 0x30, 0x4A, 0xB0, 0x64, + 0xCC, 0xB2, 0x91, 0x24, 0x19, 0x08, 0x0A, 0x17, 0x88, 0xD8, + 0xB6, 0x01, 0xE4, 0x82, 0x09, 0xE4, 0xB0, 0x49, 0x12, 0x01, + 0x84, 0x09, 0xA0, 0x0D, 0xC8, 0x86, 0x8D, 0x0C, 0xA6, 0x31, + 0x1C, 0x07, 0x68, 0x43, 0x18, 0x04, 0xD8, 0x88, 0x69, 0x02, + 0x44, 0x41, 0x19, 0x23, 0x48, 0xA1, 0x18, 0x4D, 0xE0, 0xA4, + 0x68, 0x63, 0x38, 0x2A, 0x88, 0x18, 0x25, 0xE3, 0x90, 0x6D, + 0xD1, 0xB8, 0x04, 0x09, 0x44, 0x50, 0x14, 0xB4, 0x70, 0x0B, + 0x47, 0x8C, 0x1C, 0xC8, 0x6C, 0x43, 0xC0, 0x6C, 0xD0, 0x14, + 0x02, 0x22, 0xC2, 0x70, 0x04, 0x38, 0x49, 0x14, 0x33, 0x2C, + 0xCB, 0x16, 0x71, 0x1C, 0x05, 0x2C, 0x0A, 0x33, 0x81, 0xC0, + 0x90, 0x89, 0xA1, 0x38, 0x11, 0x1B, 0x36, 0x09, 0x62, 0x08, + 0x62, 0x24, 0xC1, 0x44, 0xCB, 0xC6, 0x01, 0xD4, 0x06, 0x31, + 0x44, 0x36, 0x2C, 0x54, 0xA0, 0x89, 0x1A, 0x80, 0x51, 0x0B, + 0x34, 0x91, 0x0B, 0xB1, 0x45, 0xA4, 0x24, 0x92, 0xA1, 0xC0, + 0x01, 0x09, 0xB2, 0x89, 0x8B, 0x40, 0x48, 0x09, 0xB0, 0x2C, + 0x1A, 0x33, 0x48, 0xA4, 0x04, 0x06, 0xD8, 0x00, 0x08, 0xA2, + 0xA2, 0x61, 0x04, 0x04, 0x64, 0x9A, 0xB2, 0x11, 0x11, 0x21, + 0x4E, 0x63, 0xC2, 0x20, 0x22, 0x31, 0x8E, 0xA2, 0xB2, 0x69, + 0x10, 0x10, 0x88, 0x88, 0x42, 0x4E, 0x41, 0xA2, 0x0D, 0x99, + 0x32, 0x44, 0x8C, 0xA6, 0x4D, 0x00, 0x16, 0x69, 0x13, 0x90, + 0x8C, 0xD4, 0x16, 0x51, 0x08, 0x29, 0x70, 0x83, 0x88, 0x68, + 0x90, 0x44, 0x28, 0x84, 0x10, 0x05, 0x1C, 0xA8, 0x01, 0x11, + 0xA6, 0x0D, 0x90, 0x06, 0x30, 0x4C, 0x44, 0x31, 0x14, 0x03, + 0x00, 0x54, 0xB2, 0x08, 0x5B, 0x20, 0x01, 0x10, 0x40, 0x0E, + 0x14, 0x86, 0x85, 0x60, 0x24, 0x71, 0xC3, 0xC0, 0x85, 0xE0, + 0x42, 0x0D, 0xE0, 0x46, 0x80, 0x5A, 0xC6, 0x45, 0x59, 0x98, + 0x28, 0xA4, 0x30, 0x8A, 0xDB, 0x06, 0x88, 0x43, 0x16, 0x04, + 0x1A, 0xA1, 0x31, 0xA2, 0x08, 0x02, 0x5A, 0x22, 0x41, 0x4A, + 0x42, 0x89, 0xA2, 0x82, 0x09, 0x90, 0xC2, 0x09, 0x03, 0x31, + 0x8A, 0xC4, 0xC8, 0x44, 0x21, 0xC5, 0x6C, 0x01, 0xB9, 0x10, + 0x09, 0x41, 0x29, 0x64, 0x30, 0x30, 0x44, 0x02, 0x65, 0x82, + 0x24, 0x68, 0xC2, 0x28, 0x0C, 0x0B, 0x90, 0x45, 0x11, 0xC2, + 0x70, 0x53, 0x86, 0x44, 0x10, 0x91, 0x81, 0x10, 0x21, 0x2E, + 0x99, 0x44, 0x04, 0xE0, 0xB0, 0x88, 0x18, 0x28, 0x4E, 0x64, + 0x22, 0x4D, 0x0B, 0x30, 0x71, 0xC2, 0x96, 0x80, 0x80, 0x08, + 0x89, 0x03, 0x46, 0x2C, 0x53, 0x96, 0x28, 0x10, 0x24, 0x89, + 0x09, 0x03, 0x2E, 0xC2, 0x04, 0x0C, 0x4B, 0xB6, 0x41, 0x89, + 0x84, 0x31, 0x0C, 0x08, 0x2C, 0xA4, 0x36, 0x04, 0x08, 0x85, + 0x05, 0x04, 0xC8, 0x2C, 0x03, 0xB8, 0x29, 0x0A, 0xB0, 0x45, + 0x93, 0x80, 0x20, 0x94, 0xC6, 0x30, 0x8A, 0x22, 0x09, 0xA2, + 0xC6, 0x60, 0x4A, 0x08, 0x8A, 0xC3, 0x42, 0x4C, 0x4B, 0x38, + 0x40, 0x02, 0xC3, 0x68, 0x0A, 0x09, 0x4E, 0x18, 0xC8, 0x44, + 0x12, 0x14, 0x6D, 0x53, 0x44, 0x25, 0x09, 0x27, 0x12, 0x11, + 0xB4, 0x91, 0xD2, 0x30, 0x8C, 0x0C, 0x10, 0x8C, 0x99, 0x38, + 0x05, 0x1A, 0xC8, 0x41, 0xA2, 0x10, 0x31, 0x0A, 0x33, 0x6C, + 0x9C, 0x42, 0x60, 0xA0, 0x38, 0x6D, 0x5A, 0x90, 0x89, 0x91, + 0x08, 0x46, 0x52, 0x10, 0x6C, 0x23, 0x02, 0x48, 0x0C, 0x36, + 0x4A, 0x59, 0x92, 0x41, 0x24, 0xA4, 0x21, 0x1B, 0x13, 0x62, + 0x02, 0xB1, 0x80, 0xC0, 0x86, 0x84, 0xC2, 0x28, 0x00, 0x4A, + 0x48, 0x0A, 0x61, 0x34, 0x62, 0x5A, 0xA6, 0x45, 0x08, 0x47, + 0x08, 0x21, 0x00, 0x6C, 0x20, 0x24, 0x90, 0xA1, 0x34, 0x91, + 0x09, 0x15, 0x28, 0x0A, 0x42, 0x6E, 0x21, 0x29, 0x49, 0x0B, + 0x24, 0x84, 0x1C, 0x86, 0x69, 0x59, 0x16, 0x10, 0x04, 0x12, + 0x70, 0xCB, 0x90, 0x08, 0x18, 0x24, 0x64, 0x02, 0x13, 0x8D, + 0x23, 0x38, 0x61, 0x1B, 0x34, 0x61, 0x0C, 0x80, 0x68, 0xCC, + 0xB8, 0x11, 0xC8, 0x24, 0x92, 0xC0, 0x88, 0x81, 0xC9, 0x48, + 0x6E, 0x09, 0x32, 0x2D, 0xA1, 0x08, 0x81, 0x0B, 0x30, 0x02, + 0x19, 0xA8, 0x84, 0xD2, 0x84, 0x11, 0x50, 0x86, 0x09, 0x04, + 0xA0, 0x20, 0x81, 0xA2, 0x41, 0x93, 0x24, 0x49, 0x03, 0x07, + 0x41, 0xC8, 0xA8, 0x60, 0x0A, 0x11, 0x61, 0x64, 0x08, 0x81, + 0x1B, 0x36, 0x62, 0xD4, 0x00, 0x4E, 0x44, 0xC6, 0x10, 0xDB, + 0x20, 0x4A, 0xA0, 0xB4, 0x29, 0x84, 0x00, 0x6E, 0x20, 0x47, + 0x4E, 0x23, 0x45, 0x51, 0xE2, 0xB6, 0x45, 0x18, 0xB5, 0x09, + 0x51, 0xC6, 0x2D, 0x99, 0x92, 0x89, 0x0A, 0x84, 0x51, 0x94, + 0x32, 0x24, 0x42, 0x24, 0x29, 0xD3, 0x94, 0x01, 0xC2, 0x80, + 0x24, 0xA2, 0x92, 0x6D, 0x09, 0x46, 0x11, 0x83, 0x12, 0x0D, + 0x03, 0x39, 0x84, 0xA1, 0xA2, 0x04, 0xC0, 0x24, 0x0D, 0x48, + 0x98, 0x30, 0x88, 0x10, 0x20, 0x9B, 0xA6, 0x21, 0x82, 0x46, + 0x6D, 0x0A, 0x96, 0x01, 0xA0, 0x14, 0x46, 0xE4, 0x08, 0x42, + 0x08, 0x43, 0x8D, 0x0A, 0x12, 0x0D, 0x13, 0x37, 0x20, 0x22, + 0x49, 0x21, 0x9C, 0x10, 0x66, 0xC0, 0x20, 0x31, 0x11, 0xB3, + 0x81, 0x1C, 0x29, 0x09, 0x03, 0xB0, 0x08, 0x5C, 0x18, 0x82, + 0x5C, 0xC2, 0x90, 0xD9, 0x44, 0x8C, 0xE2, 0x18, 0x85, 0x9A, + 0x08, 0x29, 0x21, 0x25, 0x48, 0x90, 0x10, 0x8D, 0x19, 0x17, + 0x60, 0x24, 0x39, 0x28, 0x19, 0x81, 0x45, 0x49, 0x32, 0x2D, + 0xCC, 0xB6, 0x81, 0x03, 0x81, 0x25, 0x99, 0x08, 0x11, 0x0C, + 0xA2, 0x81, 0x41, 0x18, 0x29, 0x91, 0x38, 0x12, 0x09, 0xB6, + 0x71, 0x02, 0x26, 0x81, 0x82, 0x48, 0x85, 0x19, 0x44, 0x6C, + 0x02, 0xC0, 0x49, 0x18, 0xA4, 0x65, 0x1B, 0x14, 0x6E, 0xA1, + 0x42, 0x11, 0x12, 0x30, 0x25, 0x61, 0xA6, 0x4C, 0xDC, 0x10, + 0x04, 0x88, 0x04, 0x30, 0x93, 0xB8, 0x2D, 0x23, 0x26, 0x52, + 0x14, 0xB3, 0x00, 0xCA, 0x32, 0x44, 0x52, 0x14, 0x90, 0xE4, + 0x26, 0x85, 0x24, 0xB7, 0x70, 0xDB, 0x28, 0x72, 0xE4, 0x96, + 0x25, 0x99, 0x00, 0x65, 0x23, 0x29, 0x2C, 0xA1, 0x98, 0x08, + 0x62, 0x16, 0x32, 0x09, 0x29, 0x52, 0x24, 0x19, 0x2A, 0x4A, + 0x90, 0x89, 0x1C, 0x88, 0x65, 0x98, 0x16, 0x52, 0x0C, 0x95, + 0x11, 0x11, 0x32, 0x4D, 0xD2, 0x86, 0x31, 0x92, 0x10, 0x6D, + 0x82, 0xC0, 0x04, 0xE3, 0x14, 0x0A, 0x04, 0x24, 0x61, 0x0C, + 0x93, 0x44, 0xC1, 0xC4, 0x2D, 0x4C, 0x16, 0x0A, 0x1A, 0x44, + 0x0A, 0x5A, 0x42, 0x46, 0x10, 0xC8, 0x8C, 0x5B, 0xC4, 0x4D, + 0xE2, 0xB4, 0x71, 0x61, 0xA8, 0x10, 0xC2, 0x02, 0x4E, 0xC4, + 0x08, 0x4E, 0x52, 0x94, 0x70, 0x20, 0x19, 0x84, 0xA4, 0x18, + 0x71, 0xC9, 0x10, 0x52, 0x9B, 0x40, 0x21, 0x4C, 0x80, 0x28, + 0x40, 0x44, 0x89, 0x20, 0x25, 0x11, 0x13, 0x91, 0x29, 0x1A, + 0x84, 0x10, 0x49, 0x14, 0x6E, 0x03, 0x27, 0x2D, 0x4C, 0x12, + 0x42, 0x04, 0x03, 0x04, 0x1C, 0x43, 0x72, 0x44, 0x16, 0x82, + 0x1B, 0x12, 0x46, 0x90, 0x94, 0x05, 0x93, 0xB8, 0x10, 0x64, + 0x00, 0x22, 0x83, 0x38, 0x69, 0x0B, 0x43, 0x52, 0x0C, 0xA9, + 0x6D, 0x19, 0xB3, 0x09, 0xD2, 0x32, 0x25, 0x9B, 0x46, 0x21, + 0x5B, 0xA8, 0x89, 0xE3, 0xC8, 0x65, 0x12, 0xA0, 0x28, 0x9A, + 0x18, 0x30, 0x54, 0xA8, 0x69, 0x88, 0x32, 0x10, 0x23, 0xB3, + 0x21, 0x22, 0x92, 0x48, 0x92, 0x38, 0x12, 0x9B, 0x24, 0x86, + 0xCB, 0x18, 0x02, 0x08, 0x25, 0x71, 0x9C, 0xC6, 0x69, 0x08, + 0x30, 0x11, 0x42, 0x36, 0x62, 0xCB, 0x30, 0x0C, 0x02, 0x12, + 0x90, 0xE1, 0x40, 0x8A, 0x90, 0x10, 0x42, 0x19, 0x83, 0x48, + 0xD4, 0x48, 0x32, 0xD9, 0x04, 0x46, 0x00, 0x05, 0x52, 0x1C, + 0x16, 0x92, 0x13, 0x23, 0x22, 0x08, 0xB6, 0x05, 0x1B, 0xC3, + 0x41, 0x18, 0x98, 0x50, 0xDC, 0x96, 0x00, 0xE4, 0x32, 0x2A, + 0x8B, 0x10, 0x25, 0x40, 0x14, 0x8A, 0xEC, 0x96, 0x58, 0x14, + 0xF8, 0xEE, 0xD7, 0x19, 0x19, 0x51, 0x76, 0xA9, 0xAD, 0xB7, + 0x18, 0x12, 0x37, 0x3C, 0xC2, 0xC8, 0x07, 0x57, 0x8B, 0xBE, + 0x1C, 0x27, 0x62, 0xE4, 0x68, 0xF6, 0x88, 0x23, 0xD2, 0x89, + 0xC0, 0x02, 0x09, 0xBE, 0x8D, 0x64, 0x93, 0x7B, 0xB3, 0x04, + 0xD4, 0x5C, 0x3C, 0xAE, 0xF1, 0xC5, 0x67, 0x34, 0x52, 0x34, + 0x1E, 0xEB, 0x72, 0x02, 0x09, 0x27, 0x5B, 0x39, 0xD0, 0x67, + 0xEE, 0x1E, 0x02, 0xC3, 0x7F, 0x98, 0x9A, 0xA8, 0x66, 0x7D, + 0x2B, 0x5B, 0xA7, 0x89, 0x74, 0xC7, 0xB6, 0x98, 0xC9, 0xFE, + 0x9B, 0x18, 0xCA, 0x8F, 0x21, 0xCB, 0x32, 0x01, 0x55, 0xD1, + 0x99, 0x53, 0x91, 0x31, 0x8E, 0x92, 0xFD, 0xD1, 0xCC, 0x25, + 0xDF, 0xCC, 0x68, 0x29, 0x2B, 0x91, 0x74, 0x18, 0x2F, 0x54, + 0xBC, 0x70, 0xD4, 0x06, 0xDA, 0xC2, 0x00, 0xA6, 0x6D, 0xE1, + 0x01, 0xDE, 0xD3, 0x55, 0x4A, 0x28, 0x21, 0x40, 0x72, 0x59, + 0x1A, 0x94, 0x10, 0xCD, 0xF4, 0xBB, 0x63, 0x2C, 0x01, 0xEA, + 0xCF, 0x42, 0x53, 0x54, 0x7C, 0xF4, 0x06, 0xE0, 0x89, 0x88, + 0xC4, 0x60, 0x9A, 0xDB, 0x72, 0x50, 0x81, 0x8C, 0x02, 0x57, + 0x7D, 0x14, 0x6E, 0x39, 0x64, 0x38, 0xF7, 0xB0, 0xB2, 0x4C, + 0x80, 0x70, 0x3A, 0x91, 0xDB, 0x31, 0xA5, 0x2A, 0x17, 0x02, + 0xC9, 0x2D, 0x41, 0x73, 0x22, 0x6C, 0x4F, 0xAA, 0xF3, 0x32, + 0x4B, 0xF3, 0x34, 0x2E, 0xB1, 0x0F, 0x86, 0x5F, 0xE1, 0x3D, + 0x2F, 0x42, 0x61, 0x6D, 0x75, 0x07, 0xB2, 0xDB, 0x4B, 0x0E, + 0x28, 0x41, 0x66, 0x15, 0xFE, 0xD9, 0x79, 0x7F, 0x2F, 0xEE, + 0xD2, 0xDC, 0xE5, 0x53, 0x32, 0x8E, 0x81, 0xA7, 0x06, 0x99, + 0xDC, 0x20, 0xEB, 0xCD, 0xD5, 0xDE, 0xCB, 0x39, 0x48, 0xA4, + 0xB6, 0x66, 0x47, 0xD5, 0xD5, 0x46, 0xE6, 0x5D, 0xEA, 0xFF, + 0xC1, 0x1E, 0xE7, 0xAB, 0x99, 0xAD, 0xE1, 0xD9, 0x47, 0x71, + 0x3A, 0x6D, 0xC6, 0x66, 0xCC, 0x7E, 0x5C, 0x9D, 0x25, 0xB0, + 0x2C, 0x3A, 0x72, 0x16, 0xE2, 0x67, 0x2F, 0xB2, 0xC5, 0x37, + 0x3C, 0xBF, 0xDF, 0xC7, 0xE9, 0x48, 0xB6, 0x2C, 0x3B, 0x2B, + 0x89, 0x76, 0xCB, 0x33, 0xCC, 0xCF, 0xF0, 0xE6, 0x32, 0x06, + 0xE7, 0x3C, 0x6A, 0xDF, 0x24, 0x50, 0x6E, 0xEA, 0xEF, 0x31, + 0xF7, 0x2C, 0xC3, 0xFA, 0x94, 0xBF, 0x4D, 0xF7, 0x1D, 0x03, + 0xEB, 0x70, 0x14, 0x0D, 0x25, 0x87, 0x95, 0x1D, 0x8C, 0x61, + 0x21, 0xC7, 0x05, 0x21, 0x2E, 0x2B, 0x6F, 0x9E, 0x87, 0x0D, + 0xF3, 0x0C, 0x62, 0x27, 0x65, 0x74, 0x6E, 0xEB, 0x1C, 0x07, + 0xDE, 0x62, 0x9B, 0xBA, 0x4F, 0xF0, 0x46, 0xD6, 0x6A, 0x18, + 0x03, 0x4B, 0x24, 0xEB, 0x07, 0x78, 0xD0, 0x81, 0x3D, 0x00, + 0xD6, 0xCB, 0x16, 0x60, 0x77, 0x91, 0xCC, 0xEE, 0xA5, 0x32, + 0x02, 0x7C, 0x36, 0xE4, 0x60, 0xDC, 0xED, 0xBC, 0x47, 0x48, + 0x59, 0xA5, 0x28, 0x02, 0x57, 0x75, 0xCE, 0xA0, 0x83, 0x45, + 0x9A, 0xBD, 0xB9, 0x48, 0xFB, 0x0F, 0x45, 0xD9, 0x95, 0xE8, + 0x2B, 0xFF, 0xAD, 0x32, 0xEF, 0x9D, 0x1D, 0x54, 0x4E, 0xCE, + 0xA1, 0x2D, 0x0A, 0x41, 0xCB, 0xD1, 0x08, 0xB9, 0x45, 0x17, + 0x97, 0xC1, 0x5C, 0x0D, 0x21, 0x5E, 0x27, 0xB8, 0x19, 0xB5, + 0x1E, 0x89, 0x80, 0xE3, 0xBA, 0x0B, 0x66, 0xCE, 0xEF, 0x5B, + 0x35, 0x38, 0xC2, 0xFB, 0x6E, 0xD9, 0x23, 0x18, 0xE1, 0x45, + 0x98, 0x64, 0x60, 0xF1, 0xD0, 0xE1, 0xAA, 0x50, 0xD3, 0xB1, + 0x8E, 0xEB, 0x08, 0x34, 0xC5, 0x99, 0x3F, 0xB4, 0x7F, 0x5A, + 0xE2, 0x80, 0xF6, 0x22, 0x06, 0x1F, 0xB7, 0x3D, 0x58, 0xE6, + 0xF6, 0x82, 0x3C, 0x15, 0x34, 0x2E, 0xC0, 0xE3, 0x80, 0x54, + 0xB3, 0x55, 0xE8, 0x37, 0xC5, 0x1D, 0x3A, 0x36, 0x26, 0x05, + 0x24, 0xFB, 0x65, 0xDE, 0x95, 0x63, 0xF0, 0xC3, 0xFA, 0x43, + 0x1D, 0xCE, 0x7B, 0x21, 0x0E, 0x52, 0x6F, 0xA7, 0x27, 0xBD, + 0x3E, 0x7A, 0xE7, 0x59, 0xD0, 0xC3, 0xFB, 0x4C, 0x56, 0xCB, + 0x2A, 0x20, 0x7F, 0xCC, 0x94, 0xFE, 0xC0, 0x58, 0xD0, 0xFC, + 0x99, 0xB9, 0x97, 0x1A, 0x37, 0xF0, 0xB1, 0x83, 0xF3, 0x52, + 0x1E, 0x50, 0x2C, 0x74, 0x67, 0xFF, 0x62, 0x83, 0xB0, 0x79, + 0xE4, 0xF3, 0x92, 0x45, 0xFA, 0x94, 0x73, 0xC4, 0x24, 0xD8, + 0xDE, 0x88, 0x8C, 0x85, 0xE2, 0xA7, 0x84, 0xD9, 0xB4, 0x58, + 0x02, 0xFF, 0x64, 0xDE, 0x2A, 0x9D, 0x41, 0xEB, 0xE7, 0xEE, + 0x2B, 0x0A, 0x4D, 0x8E, 0xDC, 0x39, 0x56, 0xE2, 0x00, 0xF0, + 0x9D, 0xE1, 0x4F, 0x33, 0xD1, 0x6C, 0xF9, 0xF5, 0x89, 0x45, + 0x78, 0xA4, 0x15, 0x86, 0xFD, 0x70, 0x7A, 0xEC, 0xA5, 0xDB, + 0x6B, 0x7A, 0x28, 0x2D, 0x81, 0x63, 0xD2, 0x04, 0xF6, 0xC6, + 0x95, 0x14, 0xD0, 0x6B, 0x22, 0x7C, 0x87, 0x63, 0x13, 0x93, + 0x43, 0x04, 0xB7, 0x85, 0x4C, 0x9F, 0xF3, 0xE1, 0x96, 0x23, + 0x0E, 0xC9, 0x9E, 0x2C, 0x86, 0xF0, 0x9A, 0xC1, 0xF9, 0x65, + 0x69, 0x40, 0x6D, 0x6E, 0x7C, 0xA1, 0x68, 0x72, 0x44, 0xEF, + 0x46, 0x7F, 0xFB, 0x18, 0x40, 0x17, 0xFC, 0x0B, 0x30, 0xEF, + 0x13, 0xFF, 0xAE, 0x92, 0x97, 0x52, 0xEB, 0x9F, 0xEE, 0x88, + 0x51, 0xDC, 0x8C, 0x93, 0xAD, 0xB8, 0x5E, 0x8A, 0xF8, 0x4A, + 0x57, 0x2C, 0xAD, 0x23, 0xA4, 0x06, 0x26, 0x80, 0x2F, 0xF7, + 0x4D, 0x7C, 0xE0, 0xF2, 0xE7, 0x0E, 0x60, 0xBE, 0x96, 0xE9, + 0x89, 0xCF, 0x73, 0x62, 0x40, 0xB5, 0x12, 0x8C, 0x5D, 0x91, + 0x29, 0x7E, 0x30, 0x91, 0x7E, 0xA5, 0x91, 0xF5, 0x5B, 0xA0, + 0x94, 0x96, 0x0C, 0x6A, 0x2A, 0x01, 0x87, 0x44, 0x05, 0xE4, + 0xFB, 0x81, 0x19, 0x3A, 0x96, 0x8B, 0xE8, 0x80, 0xF3, 0xA4, + 0x45, 0xD7, 0xF9, 0x29, 0x3F, 0xBB, 0x9F, 0x34, 0x35, 0x64, + 0xA9, 0x9A, 0xD4, 0x8D, 0xFE, 0xF8, 0xC1, 0x13, 0xF7, 0xDE, + 0x98, 0x9B, 0x31, 0xB4, 0x8F, 0x57, 0xBB, 0x93, 0x1B, 0xC2, + 0x64, 0x33, 0x8D, 0x97, 0x8C, 0x57, 0xB3, 0x23, 0x70, 0x72, + 0x14, 0xC2, 0x45, 0x7F, 0xF7, 0x16, 0xB2, 0xD5, 0x7D, 0xA2, + 0xB7, 0xAD, 0xC9, 0x86, 0x92, 0xD7, 0xF9, 0x2E, 0x20, 0x35, + 0x64, 0xC7, 0x74, 0x64, 0xFF, 0xC2, 0x85, 0x84, 0xBC, 0xBF, + 0xB0, 0x96, 0xC2, 0x37, 0x66, 0x56, 0x21, 0x8E, 0xDC, 0x0F, + 0x98, 0xEC, 0x9F, 0x78, 0xB2, 0x71, 0xA5, 0x88, 0xEE, 0xFD, + 0x03, 0xA8, 0xBA, 0xF6, 0x39, 0x77, 0xA0, 0x69, 0x99, 0x34, + 0x9B, 0x32, 0x3C, 0x69, 0x88, 0xBF, 0xB5, 0xB5, 0x50, 0x4D, + 0xB2, 0xA1, 0xE6, 0xDD, 0x1E, 0xA4, 0xA8, 0xF1, 0xA6, 0x9B, + 0xAF, 0x6A, 0xAE, 0x72, 0x92, 0x73, 0x33, 0x39, 0xDD, 0xC6, + 0xCE, 0xA0, 0x72, 0xFA, 0x66, 0x75, 0x3D, 0x9B, 0xA0, 0x04, + 0x88, 0x37, 0x2A, 0x88, 0x36, 0xE5, 0x43, 0x96, 0x68, 0x41, + 0x6D, 0x3B, 0x0E, 0xB8, 0xE9, 0x51, 0x92, 0x28, 0x72, 0x7D, + 0xC4, 0x27, 0x95, 0x7F, 0xBF, 0x66, 0x7B, 0x47, 0x77, 0xB7, + 0xA4, 0x75, 0x02, 0x43, 0x0B, 0x34, 0x2B, 0x2D, 0x6E, 0xD5, + 0xCD, 0x1C, 0x78, 0x56, 0x0B, 0x15, 0x4E, 0x80, 0xF2, 0x4D, + 0xB2, 0x1F, 0xAC, 0x82, 0x3B, 0xE7, 0x09, 0xC8, 0x41, 0x22, + 0xDD, 0xEA, 0xB1, 0xA8, 0x6B, 0xE8, 0x21, 0x12, 0x09, 0x19, + 0x19, 0xA2, 0x04, 0xDB, 0xFA, 0x59, 0x87, 0x85, 0x10, 0x44, + 0x1B, 0xE6, 0xA8, 0xD9, 0x33, 0x27, 0xF7, 0x05, 0x0D, 0x2D, + 0x98, 0xE2, 0x2A, 0x96, 0xD6, 0xEB, 0x32, 0x9D, 0x75, 0x8A, + 0xC5, 0x78, 0x30, 0x49, 0x19, 0x94, 0x7C, 0x33, 0xC4, 0xEF, + 0xA9, 0xA3, 0xD1, 0xB4, 0xF4, 0xB7, 0x6D, 0x13, 0x1E, 0x7D, + 0xE3, 0x60, 0x7C, 0x9F, 0x10, 0x93, 0x8C, 0xE4, 0x52, 0x07, + 0x58, 0x03, 0x57, 0xA1, 0x6A, 0x94, 0x66, 0xD3, 0xEC, 0xF0, + 0x14, 0x96, 0xBE, 0x2F, 0xA5, 0xB1, 0xA9, 0xEE, 0xC8, 0x25, + 0x39, 0xA5, 0xA0, 0x82, 0xFC, 0x40, 0xA5, 0x7D, 0x87, 0x48, + 0xD1, 0x1C, 0x88, 0xA5, 0x34, 0x29, 0xC9, 0x73, 0xC6, 0x5A, + 0xDC, 0x89, 0xDF, 0xCB, 0x0F, 0x67, 0xA8, 0x72, 0xB4, 0xF2, + 0x99, 0xDE, 0x9E, 0xBE, 0x1B, 0x76, 0xAB, 0x23, 0x9C, 0x5E, + 0xE3, 0xEC, 0xD9, 0x34, 0x70, 0x63, 0x32, 0x03, 0x74, 0xCB, + 0x1C, 0x76, 0x0D, 0x5B, 0xEB, 0xDD, 0x7E, 0xF5, 0x78, 0x9F, + 0xE6, 0xC8, 0x9F, 0x63, 0x47, 0x05, 0xAD, 0xD0, 0x21, 0xA8, + 0x44, 0xAA, 0x70, 0x93, 0xD3, 0xCE, 0x21, 0x79, 0xE9, 0x5B, + 0x2F, 0x07, 0x32, 0xE5, 0x42, 0xF9, 0xE8, 0x61, 0x33, 0x39, + 0xFA, 0x13, 0x03, 0x0C, 0x44, 0x80, 0x1D, 0x70, 0x70, 0xFE, + 0xF8, 0x3A, 0x46, 0x18, 0x15, 0x68, 0x01, 0xA7, 0x90, 0xDB, + 0x8E, 0xDF, 0xB9, 0x1B, 0x06, 0xE0, 0xD4, 0x2D, 0x68, 0x9B, + 0x72, 0xEA, 0xA9, 0xEA, 0x74, 0x67, 0x18, 0x62, 0x8E, 0x2D, + 0x21, 0x0D, 0x6F, 0xED, 0xA2, 0x64, 0x0C, 0x4F, 0x9D, 0xA3, + 0xD4, 0x3F, 0x28, 0xF5, 0xDA, 0x41, 0x80, 0xB0, 0x71, 0x5C, + 0xDE, 0xF3, 0xA4, 0xC1, 0x55, 0x46, 0x57, 0x9E, 0x6B, 0xA3, + 0xD1, 0x40, 0xED, 0x29, 0x37, 0x00, 0xB5, 0xF2, 0x88, 0x0A, + 0x85, 0xDE, 0x2B, 0x64, 0xBC, 0x07, 0x21, 0x43, 0xDF, 0x36, + 0xAA, 0xFD, 0x7B, 0x65, 0x2D, 0x1A, 0xA5, 0xB7, 0x06, 0xEE, + 0x18, 0xC6, 0x26, 0xB9, 0x47, 0x24, 0x21, 0xB1, 0x67, 0x6F, + 0xC8, 0x51, 0xA6, 0x6D, 0x8F, 0xF4, 0x4B, 0xCA, 0x26, 0x9D, + 0xA7, 0xED, 0xAF, 0x0B, 0x8A, 0x02, 0x1F, 0xDA, 0x93, 0x12, + 0xFE, 0x25, 0x02, 0xFE, 0x23, 0x06, 0x4F, 0x22, 0x2D, 0x61, + 0x52, 0xD6, 0xFC, 0x1E, 0x36, 0x50, 0x43, 0x30, 0x45, 0x31, + 0x38, 0x7D, 0xCF, 0xA4, 0xBF, 0xB2, 0xA7, 0xCA, 0x5D, 0x80, + 0xBB, 0xD3, 0xD0, 0x47, 0x14, 0xC3, 0x87, 0xA8, 0x7D, 0x0F, + 0x0D, 0x16, 0xCD, 0x4D, 0x54, 0xB5, 0x1F, 0x04, 0x2D, 0xC1, + 0x5E, 0x20, 0x5C, 0x8F, 0x52, 0x3F, 0x9A, 0x17, 0xE1, 0x9E, + 0x5E, 0xBB, 0x64, 0x5B, 0x2C, 0x80, 0x7D, 0x80, 0x3A, 0xE1, + 0x0D, 0xE1, 0x83, 0xEB, 0x70, 0xF2, 0xE0, 0x12, 0x94, 0x48, + 0xDF, 0x44, 0xFF, 0x5B, 0x1B, 0x27, 0xEE, 0x94, 0x01, 0x38, + 0xE2, 0x91, 0x8A, 0x5D, 0x1C, 0xEA, 0xC9, 0x5A, 0x42, 0xF8, + 0x62, 0x41, 0x8E, 0xCB, 0x86, 0x4D, 0x81, 0x10, 0xCD, 0x4B, + 0x0F, 0x2E, 0xBE, 0x80, 0x1B, 0xA6, 0x17, 0xB6, 0x13, 0xE6, + 0x85, 0xA6, 0x3D, 0x95, 0xE2, 0xFC, 0x69, 0xD8, 0x90, 0xFA, + 0x8B, 0x51, 0xE5, 0x56, 0xCA, 0x7A, 0xA4, 0x92, 0x83, 0x43, + 0xA1, 0x3D, 0xA4, 0xC5, 0xD6, 0x56, 0xAC, 0x6A, 0xEE, 0x37, + 0x73, 0x63, 0x71, 0xF1, 0x76, 0xBD, 0x70, 0x20, 0x0C, 0xE4, + 0xD7, 0xC9, 0x44, 0x47, 0x7E, 0xA6, 0x8B, 0xD3, 0x7F, 0x64, + 0x9F, 0xF0, 0x7F, 0x25, 0xAF, 0xF3, 0x0C, 0x9B, 0x03, 0x05, + 0x91, 0x9A, 0xCE, 0x7E, 0xA7, 0x26, 0x0F, 0x52, 0xA8, 0xDA, + 0xBE, 0x2D, 0x80, 0x31, 0xE7, 0x6D, 0x3C, 0xAE, 0xEF, 0xC6, + 0x64, 0x44, 0x84, 0x6B, 0xF1, 0xE0, 0x4B, 0x75, 0xF2, 0x76, + 0x6F, 0x58, 0x03, 0x45, 0xAC, 0x47, 0xBD, 0x66, 0xA3, 0x31, + 0x29, 0x87, 0xF7, 0xD2, 0x88, 0x63, 0xA3, 0x2B, 0x16, 0x1A, + 0xC2, 0x71, 0xEE, 0x9A, 0x09, 0x40, 0x3E, 0xC9, 0x5F, 0x49, + 0xFE, 0x18, 0xF0, 0x4E, 0x2C, 0x64, 0xEB, 0x11, 0xFB, 0x28, + 0xA1, 0xAD, 0xCE, 0x36, 0x6A, 0xC7, 0x38, 0xDD, 0x48, 0x34, + 0xC0, 0x69, 0x49, 0x25, 0x12, 0xDF, 0x6C, 0x46, 0x97, 0xF0, + 0xB5, 0x55, 0x97, 0x36, 0x66, 0x40, 0x4C, 0x4D, 0x36, 0xC4, + 0xD5, 0xFB, 0x3A, 0x22, 0x35, 0xCB, 0xDC, 0xA4, 0x50, 0xF6, + 0xBD, 0x40, 0x20, 0xB8, 0x24, 0xA3, 0xBA, 0x42, 0x27, 0x29, + 0x16, 0xB8, 0x41, 0xAD, 0xE0, 0x14, 0x01, 0x9A, 0x1C, 0x44, + 0xEE, 0x1C, 0xC1, 0x59, 0xEE, 0x0D, 0x13, 0xC4, 0x27, 0x4D, + 0x18, 0x7E, 0x28, 0x03, 0xAB, 0xF9, 0xEC, 0xFC, 0x9B, 0x00, + 0xAC, 0xFF, 0xA6, 0x0B, 0xB1, 0x15, 0x4B, 0xC8, 0x89, 0xF9, + 0x56, 0xA5, 0xB2, 0x8D, 0x24, 0x93, 0xB8, 0xA0, 0x51, 0xE2, + 0xF9, 0xE7, 0xEF, 0xBD, 0x67, 0x06, 0x15, 0x85, 0xB4, 0xB3, + 0xD3, 0x0A, 0x1F, 0xBA, 0xCD, 0x53, 0xB8, 0xB8, 0xD0, 0xE1, + 0x00, 0x2E, 0x3C, 0xC0, 0xD7, 0xFA, 0xB2, 0xAB, 0x40, 0xA2, + 0xFE, 0x63, 0x92, 0x5F, 0x97, 0xBF, 0x6F, 0xD6, 0xEA, 0x18, + 0x69, 0xE4, 0x2D, 0xE0, 0x50, 0x34, 0x74, 0x00, 0xE8, 0xB5, + 0xD1, 0xBC, 0x67, 0x0E, 0xAA, 0xCC, 0x0C, 0x6A, 0xCF, 0x02, + 0x4D, 0x86, 0x7D, 0x76, 0xE8, 0xD6, 0x60, 0xF0, 0xD3, 0x4F, + 0x37, 0x85, 0xAF, 0x3B, 0x68, 0xEB, 0xE6, 0x0F, 0x47, 0xA3, + 0xEA, 0xAE, 0xDE, 0xFA, 0xF8, 0x88, 0xFF, 0x90, 0xA8, 0x5C, + 0x33, 0x6F, 0x69, 0x90, 0x44, 0x84, 0x13, 0x1B, 0xE9, 0x69, + 0x5E, 0x37, 0x32, 0xFD, 0xD0, 0x13, 0xD8, 0xEA, 0x91, 0x42, + 0x24, 0x7E, 0xF1, 0x5A, 0xFD, 0xB7, 0xEB, 0x45, 0xBB, 0x1C, + 0xAA, 0xAA, 0xD1, 0x0B, 0xE0, 0xDB, 0x6D, 0xFF, 0xE5, 0xC0, + 0xF9, 0x63, 0x12, 0x8B, 0x1B, 0x66, 0x3B, 0x5E, 0x73, 0xC5, + 0x90, 0x67, 0xC8, 0xAE, 0x13, 0xAE, 0xBE, 0xBE, 0x37, 0x6F, + 0x12, 0xBE, 0x0F, 0x3E, 0x1B, 0xB7, 0x69, 0xD0, 0x29, 0x20, + 0xFD, 0x3D, 0x6D, 0x2F, 0x4D, 0xCF, 0xB9, 0x8F, 0x30, 0x4C, + 0x4F, 0x7E, 0x72, 0x83, 0x59, 0xB8, 0xD3, 0xF4, 0x01, 0x78, + 0x3E, 0x1B, 0xF7, 0xF9, 0x41, 0xCC, 0xAD, 0xC0, 0x5C, 0x9B, + 0x9A, 0xDE, 0xDD, 0xDF, 0x36, 0x07, 0xA0, 0x77, 0x16, 0x3F, + 0x6F, 0xC9, 0x44, 0x21, 0xAE, 0xA0, 0xD7, 0x84, 0x97, 0x26, + 0xCB, 0x7F, 0x84, 0xF1, 0x01, 0x18, 0xC0, 0x7C, 0xA1, 0x54, + 0x34, 0x91, 0xBE, 0xA7, 0x52, 0xC9, 0x8E, 0x23, 0xCE, 0x4D, + 0xE2, 0xF1, 0x72, 0xDD, 0x95, 0x43, 0xD4, 0x66, 0xBF, 0x1A, + 0xBF, 0x44, 0x68, 0xD0, 0xFC, 0xAE, 0xD9, 0x16, 0x12, 0x51, + 0x34, 0x86, 0x85, 0xB8, 0x0D, 0xF9, 0x68, 0x1C, 0x75, 0x3A, + 0x9B, 0x12, 0x27, 0xF8, 0x66, 0xF2, 0x1C, 0x89, 0xA8, 0xC0, + 0xC7, 0x91, 0x16, 0xD3, 0xDD, 0x52, 0xFB, 0xF8, 0x73, 0xA4, + 0xDE, 0x0F, 0xB1, 0x1F, 0x8E, 0xF8, 0x09, 0x28, 0x59, 0xD1, + 0x11, 0xD2, 0x22, 0xA1, 0x1E, 0x83, 0x82, 0x7A, 0xCA, 0xBE, + 0x56, 0xF2, 0x77, 0x4A, 0xFE, 0x2C, 0xD6, 0x37, 0x9E, 0x94, + 0x48, 0xF0, 0x19, 0x82, 0x88, 0x96, 0x7C, 0xDB, 0x9B, 0x42, + 0xC5, 0xD9, 0xC5, 0xBC, 0x80, 0x09, 0x49, 0xAA, 0xA4, 0x1F, + 0xB1, 0x1C, 0x52, 0xEE, 0x20, 0x58, 0xB3, 0x1F, 0x48, 0xF1, + 0xBD, 0x8F, 0x52, 0xCE, 0x65, 0x2F, 0xC2, 0x1C, 0x64, 0x39, + 0xE9, 0xDB, 0xF2, 0x4C, 0xEA, 0xED, 0x6C, 0x67, 0x6D, 0x3C, + 0x94, 0x79, 0x00, 0xA7, 0x05, 0x8F, 0x66, 0x0F, 0xE4, 0x5D, + 0xEB, 0x23, 0xFF, 0xCC, 0xFE, 0x98, 0x8B, 0xA4, 0x4F, 0x2A, + 0x2D, 0xC2, 0x8F, 0xB6, 0x2B, 0xAB, 0x06, 0xC0, 0x5B, 0xD5, + 0x24, 0x1F, 0x20, 0xE1, 0xCC, 0x12, 0x86, 0xD8, 0x94, 0xFC, + 0x2D, 0xDF, 0x42, 0xF8, 0x70, 0x53, 0xF2, 0xD5, 0x8F, 0x66, + 0xD3, 0x8B, 0x2C, 0xA7, 0x85, 0xAA, 0x74, 0x44, 0x14, 0x32, + 0x87, 0x9A, 0x8E, 0x92, 0x05, 0x31, 0x2F, 0xE0, 0x49, 0xFC, + 0xBC, 0x04, 0x1C, 0x57, 0x25, 0x8D, 0x56, 0x54, 0x0D, 0xA7, + 0x6D, 0xAD, 0x1E, 0x5A, 0x68, 0x48, 0x9D, 0xAD, 0xE0, 0x52, + 0xF5, 0xC0, 0x76, 0x9C, 0x5A, 0xAC, 0x17, 0xD6, 0x37, 0x16, + 0x89, 0xE6, 0x97, 0x75, 0x0E, 0x88, 0x3C, 0x53, 0xFC, 0x73, + 0x16, 0x14, 0xCA, 0x62, 0x07, 0x84, 0x95, 0xA6, 0x21, 0x20, + 0xDA, 0xAA, 0xC2, 0x26, 0x72, 0xEA, 0x6B, 0x5E, 0xE1, 0x17, + 0x01, 0xB6, 0x46, 0xA6, 0x55, 0x36, 0xFB, 0x25, 0xFD, 0xF0, + 0x37, 0xC6, 0xC6, 0x30, 0x29, 0xC7, 0x19, 0xEA, 0x32, 0xE1, + 0xFB, 0x92, 0x31, 0x87, 0x6D, 0xC7, 0x94, 0xC6, 0xB2, 0x89, + 0x20, 0xC4, 0x2F, 0x6C, 0x14, 0xB8, 0xAB, 0x1A, 0x3A, 0xD0, + 0x1F, 0x59, 0x55, 0x76, 0x70, 0x44, 0xC8, 0x5F, 0x33, 0x9F, + 0xA3, 0xE3, 0x2D, 0xF1, 0x0C, 0xCA, 0x33, 0xB9, 0xC3, 0xFD, + 0x66, 0xE8, 0xD9, 0x9A, 0xE9, 0x4A, 0xCD, 0xB9, 0x09, 0x04, + 0xDB, 0x6B, 0x39, 0x71, 0xA3, 0x04, 0x68, 0xE3, 0x20, 0xDD, + 0x3C, 0x59, 0xF8, 0x36, 0xD2, 0x5C, 0xE4, 0x8F, 0x5D, 0xBF, + 0x39, 0xDC, 0xB6, 0x23, 0x01, 0x0C, 0xDF, 0x2D, 0x83, 0xAE, + 0x2C, 0x27, 0xCE, 0xAE, 0x2A, 0x9D, 0x40, 0xC2, 0x55, 0x58, + 0x48, 0x3C, 0x9B, 0x5D, 0x9F, 0xC6, 0xA6, 0x54, 0x29, 0x5E, + 0x36, 0xAC, 0xDC, 0xDA, 0xED, 0x8C, 0x1D, 0x73, 0x7B, 0x62, + 0x7F, 0x8F, 0xF6, 0xCC, 0x8A, 0xF2, 0x9B, 0x43, 0x8E, 0x6C, + 0x46, 0xF2, 0x9B, 0x59, 0x38, 0xD4, 0x57, 0x0A, 0x83, 0x6C, + 0x9A, 0x78, 0x72, 0x31, 0x42, 0x53, 0x6A, 0x91, 0xE1, 0xE2, + 0xAF, 0x77, 0xE0, 0x86, 0x0C, 0x37, 0x12, 0xD7, 0xEC, 0x10, + 0x5C, 0x05, 0x29, 0x1A, 0x27, 0x0E, 0x48, 0x25, 0xF7, 0x5F, + 0x57, 0x50, 0x15, 0x4F, 0x41, 0x8B, 0xAB, 0x25, 0x0F, 0xDE, + 0x5F, 0x12, 0x64, 0xA3, 0xF0, 0x35, 0x38, 0x7C, 0xD8, 0xD8, + 0xC1, 0x88, 0x9A, 0x34, 0xB6, 0xAF, 0xA9, 0x22, 0x87, 0x62, + 0x1C, 0xE8, 0xF2, 0xD3, 0x25, 0x50, 0x92, 0x91, 0xFF, 0x32, + 0x07, 0xF7, 0xC5, 0x7B, 0xB4, 0x69, 0xB7, 0x00, 0x36, 0x8A, + 0x12, 0x7E, 0x4B, 0x35, 0xC2, 0x39, 0x9E, 0x90, 0x77, 0xBC, + 0x50, 0x33, 0x46, 0x02, 0x12, 0x09, 0xF2, 0xEC, 0x4C, 0x3D, + 0xBF, 0x7A, 0xBB, 0x7D, 0x99, 0x1A, 0x70, 0x55, 0x24, 0x34, + 0x68, 0xD2, 0xD6, 0x27, 0xEA, 0xED, 0x87, 0x3A, 0x04, 0xDF, + 0xC5, 0xE6, 0x4E, 0x88, 0xFE, 0x8B, 0xED, 0xE0, 0x4C, 0xFF, + 0x6E, 0x97, 0x42, 0x3C, 0x0F, 0x60, 0x1F, 0xDC, 0x62, 0x69, + 0xB2, 0xBC, 0xB4, 0x18, 0x3C, 0x6D, 0x69, 0x8B, 0xD8, 0xA5, + 0x15, 0x2F, 0xA4, 0xD8, 0x1C, 0x62, 0x3F, 0x9A, 0x8B, 0x15, + 0x22, 0xAE, 0x37, 0xB6, 0xB8, 0x4D, 0xC4, 0xA5, 0x65, 0x65, + 0x6D, 0x22, 0x59, 0x61, 0xE1, 0x08, 0xD5, 0xE2, 0x86, 0xB8, + 0xBA, 0xD5, 0x68, 0x53, 0xEE, 0x62, 0xD7, 0xF9, 0x46, 0x8C, + 0x51, 0x01, 0xC5, 0x55, 0x22, 0xE5, 0xFE, 0xA0, 0xAA, 0x6A, + 0x4D, 0xCA, 0xC3, 0x20, 0x64, 0x12, 0xDB, 0x6F, 0x63, 0xAE, + 0xDC, 0xF6, 0x8C, 0xEA, 0x24, 0x43, 0xCD, 0x61, 0x74, 0xDF, + 0x61, 0x19, 0x56, 0x8A, 0x55, 0x1C, 0x16, 0x67, 0x15, 0x68, + 0x78, 0xE3, 0x51, 0x63, 0x4F, 0x97, 0x9A, 0xC0, 0xE5, 0xC2, + 0xD4, 0xD3, 0x8C, 0xA0, 0x80, 0x3B, 0xFE, 0x07, 0x14, 0xAF, + 0x1C, 0x16, 0x0B, 0x2C, 0x52, 0x87, 0xFB, 0x8E, 0x91, 0xB4, + 0x30, 0x00, 0x22, 0xD1, 0x4D, 0xAE, 0x8A, 0x1F, 0x19, 0x3E, + 0xD8, 0x75, 0x83, 0x85, 0x84, 0x3E, 0xEA, 0xC5, 0x87, 0xB9, + 0x70, 0x53, 0x25, 0xB2, 0xAB, 0xD0, 0x9C, 0x17, 0x5E, 0xA0, + 0x3C, 0xB0, 0x95, 0x5C, 0xDF, 0x86, 0x02, 0x82, 0xEA, 0x7B, + 0xB2, 0xF1, 0x9B, 0x56, 0xAE, 0x47, 0xA0, 0xB6, 0x65, 0x96, + 0xF0, 0x40, 0x6D, 0x60, 0xE7, 0x57, 0xC7, 0xE4, 0x1B, 0x63, + 0x91, 0x0F, 0x1B, 0xA8, 0x1D, 0x05, 0xDA, 0x43, 0x7C, 0x94, + 0x9A, 0x02, 0x4D, 0xA4, 0x70, 0xFC, 0x6E, 0xFE, 0x5D, 0xA0, + 0x55, 0x5D, 0xE9, 0x90, 0x07, 0x6B, 0x58, 0x9A, 0xA2, 0x5C, + 0x79, 0xE3, 0x27, 0x90, 0x8C, 0x97, 0x2D, 0xAB, 0x9E, 0x6E, + 0x54, 0x66, 0x51, 0xAD, 0x76, 0x7D, 0x83, 0xDD, 0x26, 0x5B, + 0x68, 0x7D, 0x94, 0x7E, 0x34, 0xEC, 0x25, 0x8E, 0x91, 0x4D, + 0xB9, 0x38, 0xD2, 0xFE, 0xDD, 0x03, 0x92, 0xA3, 0x88, 0x5B, + 0xBD, 0xE4, 0xDB, 0xE4, 0x32, 0x8A, 0x30, 0xAA, 0x72, 0x83, + 0x3F, 0xBC, 0x9A, 0xC4, 0x47, 0x42, 0xD4, 0x1E, 0x4D, 0x4D, + 0xA1, 0x4D, 0x10, 0x61, 0x7D, 0x69, 0x65, 0xEC, 0x3E, 0xBE, + 0x57, 0x54, 0x5E, 0x97, 0x28, 0x1E, 0xAE, 0xFA, 0x33, 0x4F, + 0xD0, 0x55, 0x42, 0x1A, 0xA7, 0x02, 0xC1, 0xCC, 0x25, 0x45, + 0x5A, 0x95, 0x7A, 0x29, 0x95, 0x27, 0x1B, 0xF2, 0xE2, 0x6F, + 0x45, 0xDA, 0x48, 0x6E, 0x39, 0x26, 0xF7, 0xDD, 0x2A, 0x83, + 0x23, 0xDD, 0xA7, 0xEC, 0x3E, 0xC0, 0x27, 0xC0, 0xCF, 0x38, + 0xDD, 0x61, 0x71, 0xCC, 0xE0, 0xB6, 0x80, 0x84, 0x2E, 0x7C, + 0x82, 0x7F, 0x21, 0x17, 0xB4, 0xDC, 0x35, 0xC8, 0xAA, 0x23, + 0x58, 0xD0, 0x1E, 0x6B, 0xD0, 0xAB, 0x82, 0xCF, 0x49, 0xCB, + 0x91, 0x95, 0x64, 0x32, 0xA7, 0x2F, 0x1D, 0x3B, 0x00, 0x33, + 0xEA, 0x2A, 0x9E, 0x7B, 0x27, 0xB7, 0x0E, 0x8F, 0x5C, 0x61, + 0x03, 0x0F, 0xF7, 0x7F, 0xE8, 0xA9, 0x23, 0x10, 0x54, 0x47, + 0xCC, 0x8B, 0x08, 0x65, 0x0A, 0x9D, 0x23, 0x86, 0xD1, 0xB1, + 0xB4, 0x08, 0x0A, 0x9E, 0xBD, 0xC1, 0xAC, 0xF6, 0xDF, 0x59, + 0xDA, 0x81, 0xCC, 0x81, 0xF9, 0xF9, 0x51, 0x81, 0x0F, 0x2B, + 0x6D, 0x8D, 0x6B, 0x1D, 0x29, 0xD8, 0x3E, 0xFE, 0x2D, 0xBA, + 0x4F, 0xA5, 0xD6, 0x7B, 0x4B, 0x3F, 0x0E, 0x34, 0x80, 0x17, + 0x78, 0x13, 0xB7, 0xCF, 0x81, 0x1F, 0xE9, 0x12, 0xA1, 0x8F, + 0x84, 0xB8, 0x78, 0x82, 0xFC, 0xCC, 0xAB, 0xDF, 0x0C, 0x48, + 0xAC, 0x9A, 0x92, 0x6B, 0xA8, 0xEA, 0x20, 0x34, 0x81, 0x5E, + 0x6A, 0x83, 0x73, 0xA5, 0x0B, 0xAF, 0xCF, 0x53, 0x42, 0x2E, + 0xDC, 0x75, 0x37, 0x32, 0xCB, 0x52, 0x7B, 0x0E, 0xCA, 0x16, + 0x32, 0x81, 0x4F, 0xE7, 0x04, 0x13, 0xEB, 0x7A, 0xBA, 0xF0, + 0xDF, 0x1D, 0x61, 0x4B, 0x5F, 0x52, 0x08, 0x52, 0x2D, 0x87, + 0x7C, 0x1A, 0x5B, 0x6F, 0x04, 0x16, 0xE3, 0x8D, 0xE0, 0x63, + 0x0B, 0xBE, 0xC6, 0x16, 0xF0, 0x47, 0x03, 0x8A, 0xD6, 0x8D, + 0xC2, 0xA8, 0xFB, 0xA8, 0x34, 0x52, 0xB4, 0xBF, 0xFF, 0x48, + 0x82, 0xC3, 0x22, 0x03, 0xE5, 0xD0, 0x34, 0x4C, 0x6A, 0x8B, + 0x09, 0xB2, 0x37, 0x5B, 0x09, 0xAB, 0xE2, 0x25, 0xD0, 0xAE, + 0x67, 0x05, 0x37, 0xA1, 0x1C, 0x5E, 0x99, 0xAA, 0xD9, 0xE2, + 0x45, 0x53, 0x3E, 0x97, 0xBB, 0x27, 0x3C, 0x6B, 0x00, 0x1F, + 0x4D, 0xCE, 0x8C, 0x8B, 0xF1, 0xF3, 0x05, 0x57, 0xC0, 0x63, + 0x41, 0xC5, 0xFA, 0x14, 0x9D, 0xB8, 0xA0, 0x75, 0x96, 0xB3, + 0x72, 0xCF, 0x56, 0x28, 0x29, 0x05, 0xB0, 0x4C, 0xB6, 0x78, + 0xEA, 0x36, 0x6A, 0x12, 0x5B, 0xFF, 0x59, 0x2E, 0xBD, 0xDF, + 0xDA, 0x41, 0x75, 0xC5, 0xFA, 0x87, 0x3F, 0x2F, 0x96, 0x0C, + 0x18, 0xCC, 0x8B, 0x72, 0xE7, 0x29, 0xF5, 0xB8, 0x56, 0xE8, + 0x92, 0x10, 0xB0, 0xCE, 0x3D, 0x40, 0x10, 0x40, 0x13, 0x9B, + 0xAC, 0x63, 0xD9, 0x31, 0xB1, 0xF1, 0x4C, 0xFA, 0x51, 0x19, + 0x62, 0xE5, 0x2E, 0x7A, 0x3F, 0x9A, 0xF0, 0x85, 0x83, 0x04, + 0xC0, 0x07, 0xB8, 0x04, 0x1A, 0xAD, 0x53, 0x2A, 0xB7, 0xDD, + 0xD8, 0x86, 0x0D, 0x1F, 0x24, 0x8A, 0xE9, 0xDC, 0x1F, 0x46, + 0xDE, 0x1E, 0xDD, 0x4E, 0xD3, 0xF3, 0x92, 0x43, 0xBF, 0x98, + 0xC8, 0x57, 0xC0, 0xB7, 0xC4, 0xD7, 0xE7, 0xA8, 0x78, 0x53, + 0x93, 0x42, 0x4C, 0x9A, 0x71, 0x82, 0x20, 0x3C, 0x32, 0xB5, + 0x30, 0x51, 0x54, 0x5D, 0x45, 0x81, 0x1B, 0x61, 0x6E, 0x7B, + 0xCC, 0x2C, 0x44, 0x87, 0x6F, 0x2E, 0xFC, 0x9D, 0x79, 0x63, + 0x20, 0xCA, 0x0E, 0xB3, 0x36, 0x9E, 0xDB, 0x31, 0xA3, 0xD0, + 0xD9, 0x01, 0x56, 0xEC, 0xCF, 0x09, 0xBC, 0xAE, 0x4B, 0x2C, + 0xE6, 0x61, 0xFA, 0x9F, 0xDD, 0x39, 0x4A, 0x01, 0xFF, 0xBA, + 0x60, 0x2B, 0x07, 0x38, 0x64, 0x36, 0x33, 0xDB, 0xEA, 0x3E, + 0xC3, 0xC0, 0x93, 0xBD, 0x63, 0xC8, 0xC9, 0x47, 0x33, 0xB6, + 0x21, 0x10, 0x21, 0x4E, 0xD6, 0xCB, 0xEA, 0x23, 0x48, 0x14, + 0x30, 0x21, 0x0E, 0x7D, 0xDD, 0x63, 0xD7, 0xAA, 0xAB, 0xDE, + 0x8B, 0x6E, 0x7A, 0x25, 0x19, 0x89, 0x2A, 0xF4, 0x65, 0x52, + 0x42, 0xBD, 0xB4, 0xBB, 0x00, 0x4C, 0x48, 0x1B, 0x3F, 0xC5, + 0x58, 0xEE, 0xE8, 0xEB, 0x49, 0x74, 0x0A, 0xD8, 0x34, 0x5F, + 0xFF, 0xF7, 0x66, 0x9C, 0xF6, 0x9D, 0xA2, 0x56, 0x68, 0x73, + 0x14, 0x6B, 0x58, 0xE9, 0x5E, 0xC7, 0x75, 0x2D, 0xB3, 0x01, + 0x19, 0xAA, 0xCF, 0x4A, 0xE9, 0xB1, 0x5E, 0x33, 0xC4, 0x68, + 0xE2, 0xA3, 0xF5, 0x14, 0x7F, 0xBB, 0xC5, 0x82, 0x1D, 0xA6, + 0x7D, 0x94, 0x9E, 0x0B, 0x1E, 0xDE, 0xAE, 0x3A, 0x5F, 0x52, + 0xF9, 0x39, 0xFD, 0x70, 0x98, 0x35, 0x7B, 0x80, 0x4E, 0xA9, + 0xCA, 0xDF, 0xB1, 0xF3, 0x41, 0xE6, 0x88, 0x9A, 0x25, 0x59, + 0xF2, 0x1B, 0xE8, 0x57, 0x90, 0xBC, 0x63, 0x0F, 0xD4, 0xC2, + 0x6D, 0x49, 0x01, 0xCD, 0x1F, 0x92, 0xEC, 0xEE, 0xDB, 0x3B, + 0x19, 0x0C, 0xFA, 0x4D, 0x6C, 0x57, 0x16, 0xE0, 0x6E, 0x48, + 0xB5, 0x5D, 0xB3, 0xE5, 0xEA, 0xE6, 0xCC, 0x48, 0xD2, 0xF0, + 0x3A, 0x83, 0x63, 0x75, 0x01, 0x15, 0x9D, 0x41, 0xD5, 0x0B, + 0x99, 0x17, 0x9A, 0x0B, 0xEF, 0xBC, 0xE8, 0x6C, 0x29, 0xEF, + 0xE9, 0x2E, 0x97, 0x67, 0xA3, 0x8F, 0xEB, 0xD6, 0x57, 0xBF, + 0x8B, 0xB5, 0x2E, 0x4A, 0xAE, 0x23, 0x43, 0x1A, 0x46, 0x3C, + 0x9A, 0x48, 0x9C, 0x70, 0x89, 0x84, 0x4A, 0x42, 0x61, 0xAE, + 0x96, 0x1F, 0x7F, 0x00, 0xBF, 0x6C, 0x85, 0x3C, 0x41, 0x40, + 0xB3, 0x15, 0xE8, 0xC2, 0x05, 0x3E, 0x58, 0x0B, 0x1B, 0xEC, + 0x9F, 0x4F, 0x1E, 0x73, 0xD0, 0x8B, 0x9E, 0x45, 0x8A, 0x27, + 0xA2, 0x41, 0xF0, 0x18, 0xA5, 0x7A, 0x24, 0x64, 0x07, 0xA9, + 0xC0, 0x79, 0x2B, 0x02, 0x2D, 0xF0, 0xEC, 0x1E, 0xBD, 0xB0, + 0x1B, 0x16, 0x9C, 0x12, 0xBE, 0x7D, 0x58, 0xB2, 0x43, 0x1D, + 0xE6, 0x57, 0xBC, 0x8D, 0xC3, 0xD6, 0x78, 0xDC, 0xBB, 0xFD, + 0xE8, 0x4B, 0xC3, 0x05, 0x57, 0xA9, 0xC1, 0xEB, 0x2A, 0x6A, + 0xD3, 0xBC, 0x73, 0xFB, 0x1C, 0xE9, 0xE1, 0xC5, 0xBB, 0x89, + 0x15, 0xF0, 0xE1, 0x22, 0x11, 0x67, 0xC4, 0xF7, 0xD8, 0xD2, + 0x8A, 0xFB, 0x52, 0x25, 0xD2, 0x7B, 0x7C, 0x53, 0x29, 0x74, + 0xF4, 0x41, 0xB1, 0x50, 0x3B, 0x0F, 0x64, 0xFC, 0x1A, 0xEC, + 0x80, 0xCA, 0x2C, 0xF0, 0xE0, 0x37, 0x10, 0xA2, 0x83, 0x7E, + 0xE3, 0x46, 0x17, 0xB3, 0x56, 0x1C, 0x0A, 0x97, 0x65, 0xAC, + 0x23, 0x8D, 0xD8, 0x53, 0x3D, 0x0E, 0xA9, 0x7C, 0xC9, 0x04, + 0x7A, 0xE3, 0x1A, 0x3F, 0x73, 0x0D, 0x44, 0x4A, 0xA3, 0x65, + 0xC4, 0xF4, 0x6A, 0x78, 0x29, 0x3C, 0x7F, 0x4B, 0x05, 0xFF, + 0x29, 0x5B, 0x99, 0x89, 0x4F, 0xD5, 0x9A, 0x50, 0x1F, 0x52, + 0xB4, 0xB5, 0x2A, 0x1E, 0x6C, 0x7E, 0xEC, 0x5D, 0xDF, 0x15, + 0xDD, 0x96, 0x90, 0xF0, 0xD2, 0x5A, 0xA0, 0xB2, 0x0B, 0x05, + 0x50, 0x64, 0x41, 0xBB, 0x4B, 0xC9, 0x19, 0xD9, 0x10, 0xB7, + 0x18, 0x42, 0x57, 0x5B, 0x98, 0x87, 0x0E, 0x9B, 0x48, 0x33, + 0xD9, 0x5B, 0xEA, 0xA6, 0x77, 0x72, 0xEA, 0x1A, 0x9E, 0x54, + 0xBC, 0xF4, 0xED, 0x67, 0xAF, 0x58, 0x59, 0x97, 0xCD, 0x28, + 0xA3, 0xD3, 0x83, 0x8C, 0x0B, 0xFE, 0x76, 0x5B, 0xC6, 0x41, + 0xB3, 0x4B, 0x02, 0xB8, 0x89, 0x2E, 0x48, 0x2C, 0x6D, 0x4D, + 0x68, 0xA0, 0x50, 0x1A, 0x7D, 0x8A, 0x5D, 0x60, 0x24, 0xAC, + 0x69, 0x74, 0x3F, 0x76, 0x1B, 0xDA, 0x78, 0xE1, 0xEC, 0x1F, + 0x70, 0xAF, 0x6C, 0xFA, 0x9E, 0xF0, 0x4E, 0x32, 0x14, 0xBA, + 0x10, 0x38, 0xB5, 0xB8, 0xDA, 0x92, 0x03, 0xE6, 0xF6, 0x81, + 0x16, 0x78, 0x39, 0x5E, 0x2F, 0x79, 0x15, 0xAE, 0xE1, 0xA4, + 0x13, 0x02, 0x5E, 0x1D, 0x2D, 0x19, 0xE6, 0x07, 0x80, 0x80, + 0xAA, 0xB7, 0x1A, 0x7A, 0xF4, 0x2A, 0xDF, 0x9E, 0x7E, 0xAF, + 0x13, 0x07, 0xCC, 0x32, 0xA4, 0x0F, 0x77, 0xDF, 0x5D, 0xF1, + 0xD5, 0x3A, 0x6C, 0x06, 0xEE, 0x18, 0x84, 0x3E, 0xB1, 0x97, + 0x1F, 0x93, 0x1B, 0xF3, 0x8E, 0xC9, 0x01, 0x74, 0xC0, 0x97, + 0xE6, 0xFE, 0xFB, 0xF2, 0x90, 0xA1, 0x93, 0xA0, 0x06, 0xFE, + 0x1D, 0x40, 0x15, 0xFB, 0xE2, 0x68, 0xA0, 0xE2, 0xF9, 0x99, + 0xC3, 0xA9, 0xD7, 0xD9, 0x81, 0x98, 0x91, 0xE2, 0x6A, 0x13, + 0x81, 0xED, 0x1F, 0xFF, 0x63, 0x9B, 0x61, 0x9F, 0x44, 0xEC, + 0x66, 0x32, 0x1B, 0xCD, 0xE4, 0xD6, 0xD7, 0x2C, 0x28, 0xC1, + 0x2B, 0x16, 0xDD, 0x7D, 0x90, 0xFD, 0x8B, 0x7A, 0x1E, 0x06, + 0xD7, 0xEC, 0xBF, 0x4A, 0x24, 0x76, 0xD2, 0x46, 0xE0, 0x35, + 0x50, 0xCB, 0xD1, 0x2B, 0xA4, 0xC6, 0xFE, 0x72, 0xEC, 0x74, + 0xA3, 0x6D, 0x95, 0xA5, 0x3E, 0x38, 0x28, 0xD3, 0x6B, 0xCF, + 0x02, 0xF7, 0xF4, 0x8C, 0xBB, 0x8B, 0xB4, 0x19, 0x1E, 0x84, + 0xDC, 0xDD, 0x19, 0x31, 0x43, 0x07, 0x7F, 0xDE, 0x15, 0xE2, + 0xE9, 0x94, 0x27, 0x4F, 0x70, 0x81, 0x0D, 0x15, 0xAE, 0x24, + 0x02, 0x55, 0x25, 0xBE, 0x30, 0xEA, 0x69, 0xFA, 0x10, 0x05, + 0x54, 0xD0, 0x2F, 0x2C, 0xAF, 0x98, 0x56, 0x3B, 0x0F, 0xCB, + 0x4C, 0xED, 0xCE, 0x4E, 0x90, 0xA1, 0x18, 0xE0, 0x08, 0x71, + 0xA0, 0xF5, 0x5C, 0x87, 0xE6, 0x3F, 0x0A, 0x66, 0xC5, 0xB7, + 0x48, 0x58, 0x11, 0xF7, 0x2C, 0xF1, 0x78, 0xCC, 0x93, 0x92, + 0x6C, 0x39, 0x11, 0xFB, 0x68, 0xF9, 0x3C, 0x94, 0x43, 0x62, + 0xE4, 0x28, 0xD7, 0x4C, 0x73, 0x69, 0x78, 0x8F, 0x56, 0xEE, + 0x57, 0xD7, 0xDE, 0x00, 0x56, 0xB1, 0x1C, 0x50, 0x9C, 0x6C, + 0x10, 0xE8, 0x56, 0x2D, 0xD4, 0x64, 0x75, 0x29, 0xDF, 0xDB, + 0xC9, 0x50, 0x17, 0xC7, 0x2A, 0xA8, 0x3C, 0x79, 0x43, 0x73, + 0xE6, 0x23, 0x82, 0xEC, 0x56, 0x80, 0xA0, 0x9C, 0x25, 0x1F, + 0x3F, 0x2A, 0x67, 0x44, 0xC8, 0x93, 0x7F, 0x13, 0x62, 0x0C, + 0x2A, 0x6D, 0x4F, 0x8F, 0x02, 0x05, 0x7D, 0x0D, 0x0E, 0x71, + 0xC6, 0xF5, 0xB9, 0xB3, 0x92, 0x4C, 0xFC, 0x04, 0xE7, 0xB9, + 0xD6, 0x76, 0x88, 0xAB, 0xA3, 0x2F, 0xD1, 0x04, 0x96, 0x04, + 0xC1, 0xDB, 0x16, 0x04, 0x50, 0x4D, 0x65, 0x9D, 0x87, 0x0E, + 0x68, 0x3B, 0x28, 0x74, 0xDD, 0x88, 0x58, 0xBF, 0x22, 0xD3, + 0xD5, 0xD2, 0xEB, 0x2E, 0x78, 0xEC, 0xB3, 0xB6, 0x37, 0x53, + 0xC0, 0x29, 0x32, 0xE8, 0x7F, 0x0C, 0x56, 0x56, 0x12, 0x18, + 0x1E, 0x04, 0x90, 0x56, 0xAA, 0x32, 0x7B, 0xA2, 0xE0, 0x7D, + 0x20, 0x6E, 0x4D, 0x22, 0x66, 0x0F, 0xEE, 0xC3, 0x05, 0xD0, + 0x64, 0x25, 0xAE, 0x4D, 0x86, 0x3E, 0xC0, 0xC0, 0xC1, 0x35, + 0x5D, 0xD1, 0x5D, 0xD3, 0x9A, 0xC2, 0x83, 0x56, 0x35, 0x18, + 0x25, 0xE5, 0xCD, 0x39, 0x07, 0xA2, 0x11, 0x84, 0x51, 0xC5, + 0xF9, 0xB1, 0x12, 0xEC, 0x65, 0x0B, 0x1D, 0xBE, 0x76, 0x26, + 0x19, 0xA1, 0xA0, 0xF9, 0x7A, 0x82, 0x4E, 0xE6, 0x71, 0x43, + 0x60, 0x04, 0x10, 0xB5, 0x42, 0x75, 0xE1, 0x79, 0xF8, 0xD8, + 0x96, 0x0D, 0x91, 0xD8, 0x9C, 0x9E, 0x6B, 0xE6, 0xBA, 0x9C, + 0x3D, 0xE7, 0x51, 0xAC, 0xFB, 0xC4, 0x28, 0x80, 0x23, 0xCC, + 0xA4, 0xBE, 0x49, 0x33, 0xE5, 0x40, 0xDE, 0x72, 0xC0, 0x6B, + 0x32, 0xDE, 0x64, 0x99, 0x10, 0xB0, 0x39, 0x6F, 0x37, 0x5A, + 0xEB, 0xE8, 0xB6, 0x12, 0xEE, 0x03, 0xEF, 0x96, 0xE0, 0x4E, + 0x09, 0x83, 0xAF, 0xFA, 0x18, 0x94, 0x6E, 0x3C, 0x41, 0xDF, + 0x64, 0xF6, 0x92, 0xF8, 0x36, 0x2B, 0x77, 0xC7, 0x3E, 0x31, + 0x8A, 0x3B, 0x63, 0xE3, 0xBC, 0x4F, 0x3B, 0xBF, 0x7E, 0x35, + 0xFD, 0x87, 0x78, 0x55, 0xA8, 0x12, 0xC1, 0xAA, 0x79, 0x69, + 0xEC, 0xEC, 0x59, 0x41, 0x43, 0xA5, 0x2F, 0x88, 0x33, 0x83, + 0xF2, 0x11, 0x68, 0x6C, 0x96, 0xD3, 0x39, 0x20, 0x92, 0x3E, + 0xFF, 0x8F, 0xD6, 0xC1, 0x70, 0xA1, 0x78, 0x02, 0xCA, 0x7E, + 0xC3, 0x34, 0xB6, 0x04, 0x12, 0x8A, 0xB7, 0x53, 0x11, 0xB3, + 0x12, 0xAD, 0xA2, 0xBE, 0xDE, 0xE8, 0x3A, 0xED, 0xB1, 0x37, + 0xDB, 0x50, 0xE8, 0xCD, 0xCE, 0x9E, 0x6F, 0x2E, 0x05, 0xC6, + 0xFC, 0x98, 0xAE, 0xD7, 0xCF, 0x67, 0xF6, 0x4B, 0x74, 0x92, + 0xC2, 0xEF, 0x47, 0x09, 0xD1, 0x0C, 0xBC, 0x3C, 0x9D, 0xAC, + 0x19, 0xC1, 0x31, 0x48, 0x08, 0xFA, 0x34, 0xD5, 0x17, 0xDB, + 0xF2, 0x52, 0xF3, 0x65, 0x6A, 0xA3, 0xE8, 0x1F, 0xDD, 0x1F, + 0x9B, 0x7A, 0x9A, 0xC6, 0x4C, 0x48, 0x43, 0x2D, 0xC5, 0x91, + 0x89, 0xFF, 0x15, 0xB3, 0xD8, 0x65, 0xDA, 0xB1, 0xFE, 0xB5, + 0x65, 0xC9, 0xDD, 0xCA, 0xD3, 0x5B, 0x5C, 0xEC, 0xDA, 0x68, + 0x6B, 0xBB, 0xAF, 0x10, 0x8A, 0x9D, 0xF6, 0x0A, 0xDC, 0xCA, + 0xC8, 0xD4, 0xF0, 0xB9, 0x60, 0xBA, 0x58, 0x4C, 0x2A, 0x0B, + 0xD0, 0xC9, 0xDC, 0x58, 0x12, 0xD2, 0x8C, 0xC4, 0x7C, 0x05, + 0xC0, 0xFE, 0x59, 0x77, 0x64, 0x67, 0x62, 0x83, 0x4E, 0x72, + 0x04, 0x44, 0x76, 0x46, 0x0D, 0x3D, 0x56, 0xFB, 0xE3, 0x25, + 0xB8, 0x20, 0x14, 0x96, 0xD5, 0xF1, 0x36, 0x76, 0x5D, 0x8D, + 0xE6, 0xF7, 0xE7, 0x36, 0x32, 0x30, 0x30, 0x63, 0x84, 0x3A, + 0x7D, 0x00, 0x3A, 0x65, 0x1E, 0xB3, 0xD5, 0x50, 0xF1, 0x5D, + 0x2B, 0xC9, 0x48, 0x82, 0x9D, 0x0E, 0xC7, 0x53, 0xB1, 0xDD, + 0x51, 0xF3, 0x56, 0x29, 0x72, 0xE0, 0xFD, 0xA0, 0xAF, 0xB1, + 0x62, 0xF6, 0xA1, 0x24, 0x22, 0x99, 0x18, 0x64, 0xEF, 0x34, + 0x41, 0x2A, 0xFA, 0xC7, 0x6C, 0xF6, 0x5D, 0x72, 0x06, 0x12, + 0x83, 0xB2, 0x14, 0xEF, 0x5D, 0x25, 0x11, 0x48, 0xE1, 0xD5, + 0x01, 0xE8, 0xA5, 0x99, 0x62, 0x2C, 0xF4, 0xDD, 0x78, 0x9D, + 0x64, 0xF2, 0x3F, 0x41, 0x1C, 0xB0, 0x87, 0x0C, 0x19, 0x04, + 0x6D, 0x16, 0x72, 0x2F, 0x7B, 0x6D, 0xFE, 0xF3, 0x0C, 0x77, + 0x04, 0xCD, 0xEB, 0xE4, 0xC8, 0x0A, 0xC1, 0x9E, 0x41, 0x1E, + 0xAC, 0xF2, 0x5B, 0xED, 0xD1, 0xE5, 0x72, 0x8F, 0x0E, 0xBF, + 0x59, 0xA8, 0x1D, 0x1C, 0x1E, 0xED, 0xB7, 0xD2, 0xA6, 0x8B, + 0x23, 0x7F, 0x40, 0x39, 0xD6, 0xD8, 0xEE, 0x50, 0x0F, 0xC3, + 0x1B, 0x03, 0xAA, 0x0A, 0xA4, 0xFF, 0xB6, 0xC5, 0xB3, 0x97, + 0x4C, 0xB6, 0xA8, 0x01, 0x0D, 0xDC, 0x2B, 0xEE, 0x6C, 0x29, + 0xF9, 0x59, 0x06, 0x5F, 0xCC, 0xE3, 0x28, 0xED, 0xEB, 0xB2, + 0x9F, 0x7F, 0x43, 0xBB, 0x02, 0x5F, 0xC4, 0xC8, 0x48, 0xC8, + 0xF8, 0x2B, 0xB7, 0xCD, 0xC4, 0x64, 0x4B, 0xEF, 0xC9, 0x9C, + 0xEB, 0xC5, 0x41, 0xDF, 0xB4, 0xC3, 0x5D, 0x95, 0xCE, 0x1E, + 0xC7, 0x5C, 0xB2, 0x4D, 0x81, 0x25, 0xDD, 0x19, 0xF3, 0x39, + 0xE8, 0x1B, 0x0E, 0x4F, 0x71, 0xF5, 0xE5, 0x99, 0x90, 0x32, + 0x77, 0xA9, 0x73, 0x3E, 0x58, 0x9B, 0x41, 0x1B, 0x77, 0x06, + 0x92, 0xDF, 0x1A, 0x96, 0x93, 0x02, 0xFF, 0xE7, 0xDF, 0xD3, + 0x09, 0x9A, 0xB7, 0x12, 0xB7, 0xE0, 0xF1, 0x73, 0x47, 0x6A, + 0x48, 0x06, 0x42, 0x41, 0x93, 0x4C, 0x57, 0x61, 0xFF, 0x90, + 0xA3, 0x18, 0xCE, 0xBE, 0x35, 0x6B, 0x78, 0x05, 0x01, 0x5F, + 0x2F, 0x0F, 0xA8, 0x05, 0xB1, 0x6B, 0x22, 0x7E, 0xC9, 0x5E, + 0x4F, 0xB6, 0xEE, 0x4E, 0xEC, 0xF6, 0xF0, 0x9F, 0x74, 0x8B, + 0xE4, 0xFF, 0x5C, 0x69, 0xCB, 0xD2, 0x8F, 0x2D, 0x4B, 0x06, + 0x6C, 0x64, 0x76, 0xAE, 0x03, 0x12, 0xCB, 0x98, 0xD2, 0xBF, + 0x1E, 0xAB, 0x76, 0x24, 0x95, 0xD7, 0xB1, 0x62, 0x63, 0xBC, + 0x21, 0xC6, 0x16, 0xEA, 0x81, 0x2A, 0x01, 0xFC, 0x2E, 0x43, + 0x18, 0x62, 0xFD, 0xFB, 0x06, 0xF2, 0x17, 0xF1, 0xD5, 0x91, + 0x9A, 0x0E, 0x75, 0xFF, 0x53, 0x61, 0xE9, 0x8C, 0x51, 0x99, + 0x9B, 0x32, 0x5B, 0x2A, 0x56, 0x3E, 0xB1, 0x7D, 0x26, 0x1D, + 0x47, 0xFC, 0x05, 0x5A, 0x79, 0xC6, 0xEF, 0x62, 0x58, 0xA4, + 0xEF, 0xBB, 0xB8, 0xF7, 0x84, 0xEE, 0xA3, 0x12, 0x83, 0x28, + 0xA0, 0xD1, 0x9D, 0x1A, 0x8B, 0xD1, 0x56, 0x2A, 0xAA, 0x41, + 0xFD, 0xF2, 0x4F, 0xD9, 0x68, 0xF1, 0xB9, 0xEB, 0xB0, 0xEC, + 0xAF, 0x99, 0xDE, 0xE4, 0xDD, 0x26, 0xD2, 0xBA, 0x54, 0x29, + 0x6E, 0x31, 0xE4, 0x91, 0x40, 0x8B, 0x39, 0xC8, 0xDF, 0x8C, + 0x6F, 0xDF, 0xA6, 0x2D, 0xAE, 0x13, 0x5E, 0xF3, 0xD7, 0x62, + 0xC9, 0xE7, 0xC6, 0x51, 0xCA, 0x8E, 0xB2, 0xB3, 0x0B, 0x0C, + 0xA8, 0xC5, 0x95, 0x95, 0xFF, 0x72, 0x3C, 0xC7, 0x6E, 0xAA, + 0x44, 0x41, 0x82, 0xB6, 0x84, 0x78, 0xC7, 0x47, 0xC6, 0x18, + 0x31, 0x95, 0x08, 0x4D, 0xCE, 0x83, 0x80, 0x5B, 0x12, 0xF5, + 0xCB, 0x83, 0xD7, 0x60, 0x02, 0xFF, 0x22, 0xCD, 0x59, 0xB0, + 0xA8, 0x61, 0xDE, 0x50, 0x53, 0x9C, 0xF8, 0xF4, 0x12, 0xEB, + 0x33, 0x98, 0xCA, 0xC1, 0x63, 0x1D, 0x39, 0xA5, 0xC8, 0x89, + 0x39, 0x0A, 0x43, 0xFE, 0x67, 0x71, 0xC7, 0x91, 0x5B, 0xFA, + 0xA4, 0x76, 0x6C, 0x02, 0xF0, 0x23, 0xEB, 0x01, 0x43, 0xF5, + 0xDC, 0xD7, 0x3A, 0x2E, 0x54, 0xB4, 0xF6, 0xF3, 0x03, 0xE4, + 0x60, 0x62, 0x2B, 0xE4, 0x53, 0x5C, 0x6E, 0x17, 0x07, 0x0D, + 0x67, 0x18, 0x6B, 0xCD, 0x7D, 0xF9, 0x98, 0x0F, 0xAC, 0x17, + 0x9E, 0xD2, 0xB7, 0xE6, 0xE5, 0x89, 0xBD, 0xFF, 0x74, 0x06, + 0x0E, 0xE7, 0x52, 0x7F, 0x1C, 0xBA, 0x21, 0x14, 0xFB, 0xE7, + 0x86, 0x11, 0x53, 0x80, 0xC0, 0xCF, 0xD8, 0x4B, 0x13, 0x0F, + 0xF8, 0xC7, 0x12, 0xC2, 0x9D, 0x85, 0x2E, 0x58, 0xF1, 0x81, + 0xD6, 0x61, 0x64, 0x40, 0x20, 0xA2, 0x0A, 0xC4, 0x49, 0x6A, + 0x60, 0xE0, 0x47, 0x75, 0x02, 0x71, 0xEC, 0x54, 0x5E, 0x26, + 0x3E, 0x5A, 0xEA, 0x09, 0x25, 0x03, 0xDC, 0xBF, 0x9C, 0xFE, + 0xFA, 0x19, 0xFB, 0x90, 0x91, 0x93, 0x21, 0x13, 0x96, 0x4C, + 0x80, 0xAF, 0x48, 0x5B, 0xDD, 0x0D, 0xC5, 0x02, 0x1F, 0x77, + 0x3D, 0x49, 0xBF, 0xAD, 0xFE, 0x90, 0x59, 0x93, 0xEB, 0x17, + 0xDA, 0x42, 0x18, 0x65, 0xFE, 0x9D, 0x7E, 0x11, 0xFF, 0x5A, + 0x2C, 0xCA, 0x48, 0x32, 0x50, 0xFA, 0xC4, 0xFF, 0x43, 0xC5, + 0xE3, 0x66, 0x97, 0x88, 0x8A, 0x2A, 0x7F, 0x90, 0x4C, 0xDA, + 0x61, 0x79, 0xBF, 0xB1, 0xF5, 0x94, 0xF0, 0x46, 0x70, 0xB6, + 0x62, 0x4C, 0xC1, 0x1B, 0x32, 0x6E, 0x76, 0x63, 0xB2, 0x22, + 0x5C, 0x22, 0xC1, 0x20, 0x6C, 0xD4, 0xF0, 0x22, 0x02, 0xA0, + 0xCF, 0xE4, 0x17, 0x42, 0xCD, 0x2E, 0xF2, 0x38, 0xF9, 0xB4, + 0x6B, 0x50, 0xE9, 0x38, 0x20, 0x59, 0x8F, 0x67, 0xE5, 0x4F, + 0x03, 0xDC, 0xE3, 0x9F, 0x24, 0xA8, 0xAD, 0x5B, 0xF4, 0xC4, + 0x07, 0x5D, 0x0D, 0x65, 0x6A, 0xA5, 0xA8, 0x05, 0xB5, 0xAE, + 0xCB, 0xF4, 0xCB, 0xDF, 0xC9, 0x76, 0x54, 0xAC, 0x07, 0x23, + 0x28, 0x5C, 0x60, 0x58, 0x60, 0xB5, 0xBE, 0xBD, 0xAC, 0xEA, + 0x65, 0x69, 0x4F, 0x9B, 0x61, 0x9A, 0xDF, 0x25, 0x89, 0x16, + 0x4A, 0x25, 0x6E, 0xA6, 0xA5, 0x00, 0x0F, 0xAD, 0xA7, 0x73, + 0xD4, 0x02, 0x2D, 0x1D, 0x6C, 0x03, 0x8E, 0x5F, 0x09, 0x62, + 0xA8, 0x35, 0xA4, 0x4B, 0xB7, 0xDB, 0xC7, 0x31, 0x7C, 0xD9, + 0x1F, 0xBD, 0xE8, 0x9D, 0x05, 0x7D, 0xEC, 0xBD, 0x0A, 0x90, + 0x87, 0x99, 0xB0, 0x61, 0x04, 0x5D, 0xA3, 0x33, 0xF8, 0xFA, + 0x55, 0xBD, 0x5B, 0x90, 0xFE, 0x89, 0x83, 0x47, 0x96, 0xCF, + 0xCC, 0x0D, 0x80, 0x49, 0x1E, 0x9B, 0xF9, 0xEA, 0x13, 0x2C, + 0x13, 0xEA, 0xF0, 0xA5, 0x31, 0x0F, 0xE8, 0xB0, 0xF6, 0xA1, + 0x83, 0xC5, 0x1A, 0x02, 0x7A, 0x8B, 0x7A, 0x8C, 0x3A, 0x45, + 0x12, 0x30, 0x07, 0x71, 0x67, 0x47, 0xA7, 0x10, 0x6E, 0x18, + 0xE8, 0x8B, 0x7D, 0x86, 0xFF, 0x11, 0x6A, 0x3D, 0xAF, 0x9E, + 0x78, 0xC0, 0x71, 0x85, 0x22, 0x89, 0x73, 0x73, 0x5E, 0x8C, + 0x75, 0x29, 0xEE, 0x1F, 0x83, 0x1F, 0xF3, 0x7F, 0x90, 0xEC, + 0x0B, 0x12, 0x7D, 0x38, 0x86, 0xA7, 0x8D, 0xEA, 0xA3, 0xD8, + 0xFD, 0xD9, 0xED, 0x83, 0x92, 0xE6, 0xBE, 0x31, 0x40, 0xDC, + 0xEF, 0x9A, 0x06, 0x29, 0xF5, 0xA0, 0xF2, 0x14, 0x9F, 0x90, + 0xB5, 0x8F, 0x48, 0x4A, 0x25, 0x19, 0xB8, 0xA6, 0x17, 0xEF, + 0xC9, 0xDE, 0x48, 0x49, 0xD8, 0xEA, 0x15, 0xEE, 0x6C, 0xAB, + 0x10, 0xCE, 0x7F, 0xFC, 0x00, 0x54, 0x89, 0x1F, 0x8F, 0x1E, + 0x73, 0x14, 0x86, 0x10, 0x16, 0xB6, 0x38, 0xAC, 0x4B, 0x36, + 0x83, 0xCE, 0x65, 0xE2, 0xC3, 0x99, 0xEF, 0x26, 0x2B, 0xC0, + 0x09, 0x35, 0xF3, 0xCA, 0x99, 0x3B, 0x4D, 0x9D, 0xC4, 0x08, + 0x7A, 0x7B, 0x0D, 0xDD, 0x05, 0x1B, 0x42, 0x8B, 0x41, 0x0E, + 0x9B, 0x51, 0x08, 0x04, 0x1E, 0x1C, 0x76, 0x32, 0x6C, 0xA0, + 0x29, 0x52, 0xFB, 0x73, 0xB0, 0x6E, 0xE8, 0x0E, 0x40, 0x1E, + 0xCE, 0x0A, 0x8E, 0xF9, 0xE0, 0xC9, 0x18, 0xDC, 0x28, 0xCF, + 0xC5, 0x71, 0x9B, 0xCE, 0x3B, 0xA0, 0x22, 0x59, 0xBB, 0x3F, + 0x68, 0x97, 0xAA, 0x89, 0xD1, 0x8F, 0xC8, 0x8D, 0x63, 0xE3, + 0x1F, 0x0F, 0xD7, 0xFB, 0x07, 0x82, 0x2D, 0x44, 0x79, 0x6A, + 0x85, 0x15, 0xD9, 0xE1, 0x8E, 0xBB, 0x57, 0xF1, 0xFA, 0x80, + 0x8D, 0xB8, 0x71, 0xA3, 0x74, 0x60, 0x03, 0xFB, 0x5F, 0x5E, + 0x51, 0x88, 0x37, 0x41, 0x9A, 0x83, 0x6D, 0x84, 0xE5, 0x9A, + 0x8B, 0x34, 0xCA, 0x65, 0x7D, 0x27, 0xAF, 0x32, 0x4D, 0x00, + 0x3D, 0xC3, 0x40, 0x98, 0xCF, 0xB2, 0xDE, 0xE1, 0x71, 0x69, + 0xB5, 0xAB, 0xE6, 0xC3, 0x8D, 0x6C, 0xDE, 0x95, 0x5E, 0x16, + 0x12, 0x16, 0x19, 0xFA, 0x89, 0x6D, 0xD6, 0xAB, 0x90, 0xFC, + 0x15, 0x9B, 0xD3, 0x8D, 0x78, 0x8D, 0xBD, 0x7A, 0x0C, 0xF2, + 0xB9, 0xE7, 0x34, 0xDE, 0x63, 0x72, 0x0B, 0x33, 0xE1, 0xBC, + 0xF7, 0x43, 0xB2, 0xDA, 0x74, 0x1E, 0x7A, 0x4D, 0xF4, 0xEE, + 0xB4, 0xA1, 0x7E, 0x34, 0x12, 0xC7, 0xC7, 0x04, 0xA7, 0x60, + 0x83, 0xD1, 0x0A, 0xC0, 0xB9, 0xCA, 0x53, 0xFE, 0x0F, 0xF0, + 0xAF, 0xA3, 0x59, 0xED, 0x62, 0x21, 0x88, 0xCD, 0xD3, 0x3C, + 0xA4, 0x11, 0xFF, 0x28, 0xAD, 0xDA, 0xB1, 0xEA, 0x58, 0xFF, + 0xA9, 0x05, 0x88, 0xAA, 0x30, 0x77, 0xB5, 0x91, 0x9C, 0xD1, + 0x80, 0xC1, 0x88, 0x0D, 0xAA, 0x1E, 0x7A, 0xA7, 0x06, 0xDA, + 0xFB, 0xE2, 0x0A, 0x71, 0xE2, 0x24, 0xDF, 0xA9, 0xD7, 0x4F, + 0xD8, 0x2D, 0xAE, 0x81, 0x74, 0xB1, 0xDA, 0x13, 0x74, 0xB4, + 0x39, 0xCF, 0x16, 0xCE, 0x4C, 0xF5, 0xA4, 0x9C, 0x35, 0x32, + 0x80, 0x69, 0x9B, 0x3A, 0xC9, 0x27, 0x54, 0xA1, 0x5F, 0x98, + 0x79, 0xBE, 0x6A, 0x42, 0x8E, 0x04, 0xCE, 0x68, 0xDD, 0x05, + 0x82, 0xA4, 0xE4, 0x19, 0xEA, 0x3F, 0x27, 0xD8, 0x01, 0x0F, + 0x0B, 0x3D, 0x52, 0xFF, 0x7F, 0xC6, 0xD1, 0xED, 0x98, 0x38, + 0xFF, 0xC5, 0xA8, 0xBE, 0x47, 0x79, 0x45, 0x4B, 0x5D, 0x4A, + 0xA6, 0x7E, 0xCF, 0xA8, 0x7E, 0x24, 0xC9, 0x45, 0x6F, 0xAF, + 0x75, 0xB2, 0x95, 0x7F, 0x36, 0xB9, 0xA5, 0xAA, 0x36, 0x71, + 0x84, 0x01, 0xED, 0x65, 0x83, 0x8A, 0x70, 0x9F, 0xAB, 0xF7, + 0xBF, 0x8B, 0x99, 0x6F, 0xCF, 0xC3, 0x8B, 0xC5, 0x54, 0x74, + 0xE0, 0x01, 0x38, 0x0D, 0xF6, 0x1C, 0x54, 0x37, 0x3B, 0x1D, + 0xDE, 0xCA, 0x5B, 0x0D, 0xF7, 0x8E, 0xA7, 0x9C, 0xB9, 0xF7, + 0xD6, 0x91, 0x33, 0xB2, 0xCB, 0xB4, 0x0F, 0x71, 0xF8, 0x20, + 0xFA, 0xCD, 0x57, 0x7A, 0xA4, 0xE0, 0x8A, 0xC2, 0x6C, 0x3F, + 0xB9, 0xBF, 0x22, 0x77, 0xC3, 0x7B, 0xFB, 0x89, 0x17, 0x3F, + 0x61, 0xBC, 0xBF, 0xA1, 0x4C, 0xFC, 0x05, 0x21, 0xC1, 0x72, + 0x40, 0x1C, 0x88, 0xEC, 0xE9, 0x21, 0xA3, 0xCF, 0x4E, 0x17, + 0xFB, 0x85, 0x57, 0xCE, 0x85, 0x46, 0x5F, 0xD3, 0xE4, 0x3D, + 0x91, 0xC6, 0x86, 0x6B, 0x76, 0x44, 0xB4, 0xD2, 0x13, 0x6D, + 0xAA, 0xC2, 0x42, 0xE5, 0xD6, 0xEA, 0xE3, 0xD6, 0x5B, 0xF9, + 0x8F, 0xA6, 0x23, 0xA6, 0x82, 0xCC, 0x1D, 0xF6, 0xAF, 0x2F, + 0x06, 0x75, 0x7D, 0x9A, 0x26, 0x0E, 0x80, 0x42, 0xC4, 0xAB, + 0xF5, 0xFB, 0x46, 0x83, 0xBF, 0x35 +}; +static const int sizeof_bench_dilithium_aes_level5_key = sizeof(bench_dilithium_aes_level5_key); + +#endif /* HAVE_PQC */ + #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) /* ./certs/ecc-client-key.der, ECC */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index d165546ad..1e0bbb021 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -177,6 +177,7 @@ enum wolfSSL_ErrorCodes { UNSUPPORTED_PROTO_VERSION = -450, /* bad/unsupported protocol version*/ FALCON_KEY_SIZE_E = -451, /* Wrong key size for Falcon. */ QUIC_TP_MISSING_E = -452, /* QUIC transport parameter missing */ + DILITHIUM_KEY_SIZE_E = -453, /* Wrong key size for Dilithium. */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e8119c698..8566e4162 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -112,6 +112,7 @@ #endif #ifdef HAVE_PQC #include + #include #endif #ifdef HAVE_HKDF #include @@ -1277,7 +1278,7 @@ enum Misc { #endif #endif #ifdef HAVE_PQC - ENCRYPT_LEN = 1500, /* allow 1500 byte static buffer for falcon */ + ENCRYPT_LEN = 4600, /* allow 4600 byte buffer for dilithium. */ #else #ifndef NO_PSK ENCRYPT_LEN = (ENCRYPT_BASE_BITS / 8) + MAX_PSK_ID_LEN + 2, @@ -1487,20 +1488,33 @@ enum Misc { ED448_SA_MAJOR = 8, /* Most significant byte for ED448 */ ED448_SA_MINOR = 8, /* Least significant byte for ED448 */ - PQC_SA_MAJOR = 0xFE,/* Most significant byte used with PQC sig algos -*/ - /* These match what OQS has defined in their OpenSSL fork. */ + PQC_SA_MAJOR = 0xFE,/* Most significant byte used with PQC sig algs */ + + /* These values for falcon and dilithium match what OQS has defined in their OpenSSL fork. */ FALCON_LEVEL1_SA_MAJOR = 0xFE, FALCON_LEVEL1_SA_MINOR = 0x0B, FALCON_LEVEL5_SA_MAJOR = 0xFE, FALCON_LEVEL5_SA_MINOR = 0x0E, + DILITHIUM_LEVEL2_SA_MAJOR = 0xFE, + DILITHIUM_LEVEL2_SA_MINOR = 0xA0, + DILITHIUM_LEVEL3_SA_MAJOR = 0xFE, + DILITHIUM_LEVEL3_SA_MINOR = 0xA3, + DILITHIUM_LEVEL5_SA_MAJOR = 0xFE, + DILITHIUM_LEVEL5_SA_MINOR = 0xA5, + + DILITHIUM_AES_LEVEL2_SA_MAJOR = 0xFE, + DILITHIUM_AES_LEVEL2_SA_MINOR = 0xA7, + DILITHIUM_AES_LEVEL3_SA_MAJOR = 0xFE, + DILITHIUM_AES_LEVEL3_SA_MINOR = 0xAA, + DILITHIUM_AES_LEVEL5_SA_MAJOR = 0xFE, + DILITHIUM_AES_LEVEL5_SA_MINOR = 0xAC, MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */ MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */ #if defined(HAVE_PQC) - MAX_CERT_VERIFY_SZ = 1600, /* For Falcon */ + MAX_CERT_VERIFY_SZ = 6000, /* For Dilithium */ #elif !defined(NO_RSA) MAX_CERT_VERIFY_SZ = WOLFSSL_MAX_RSA_BITS / 8, /* max RSA bytes */ #elif defined(HAVE_ECC) @@ -1531,7 +1545,7 @@ enum Misc { #endif #if defined(HAVE_PQC) - MAX_X509_SIZE = 5120, /* max static x509 buffer size; falcon is big */ + MAX_X509_SIZE = 8*1024, /* max static x509 buffer size; dilithium is big */ #elif defined(WOLFSSL_HAPROXY) MAX_X509_SIZE = 3072, /* max static x509 buffer size */ #else @@ -1614,10 +1628,12 @@ enum Misc { #define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8) #ifdef HAVE_PQC -/* set minimum Falcon key size allowed */ #ifndef MIN_FALCONKEY_SZ #define MIN_FALCONKEY_SZ 897 #endif +#ifndef MIN_DILITHIUMKEY_SZ + #define MIN_DILITHIUMKEY_SZ 1312 +#endif #endif /* set minimum RSA key size allowed */ @@ -1993,16 +2009,16 @@ struct Suites { #endif }; - WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, int haveFalconSig, - int haveAnon, int tls1_2, int keySz); + int haveDilithiumSig, int haveAnon, + int tls1_2, int keySz); WOLFSSL_LOCAL void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveECDSAsig, word16 haveECC, word16 haveStaticRSA, word16 haveStaticECC, - word16 haveFalconSig, word16 haveAnon, - word16 haveNull, int side); + word16 haveFalconSig, word16 haveDilithiumSig, + word16 haveAnon, word16 haveNull, int side); WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, @@ -2214,6 +2230,7 @@ struct WOLFSSL_CERT_MANAGER { int refCount; /* reference count */ #ifdef HAVE_PQC short minFalconKeySz; /* minimum allowed Falcon key size */ + short minDilithiumKeySz; /* minimum allowed Dilithium key size */ #endif }; @@ -2933,6 +2950,7 @@ struct WOLFSSL_CTX { byte haveDH:1; /* server DH parms set by user */ byte haveECDSAsig:1; /* server cert signed w/ ECDSA */ byte haveFalconSig:1; /* server cert signed w/ Falcon */ + byte haveDilithiumSig:1;/* server cert signed w/ Dilithium */ byte haveStaticECC:1; /* static server ECC private key */ byte partialWrite:1; /* only one msg per write call */ byte autoRetry:1; /* retry read/write on a WANT_{READ|WRITE} */ @@ -3005,6 +3023,7 @@ struct WOLFSSL_CTX { #endif #ifdef HAVE_PQC short minFalconKeySz; /* minimum Falcon key size */ + short minDilithiumKeySz;/* minimum Dilithium key size */ #endif unsigned long mask; /* store SSL_OP_ flags */ #ifdef OPENSSL_EXTRA @@ -3302,17 +3321,23 @@ enum KeyExchangeAlgorithm { /* Supported Authentication Schemes */ enum SignatureAlgorithm { - anonymous_sa_algo = 0, - rsa_sa_algo = 1, - dsa_sa_algo = 2, - ecc_dsa_sa_algo = 3, - rsa_pss_sa_algo = 8, - ed25519_sa_algo = 9, - rsa_pss_pss_algo = 10, - ed448_sa_algo = 11, - falcon_level1_sa_algo = 12, - falcon_level5_sa_algo = 13, - invalid_sa_algo = 255 + anonymous_sa_algo = 0, + rsa_sa_algo = 1, + dsa_sa_algo = 2, + ecc_dsa_sa_algo = 3, + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9, + rsa_pss_pss_algo = 10, + ed448_sa_algo = 11, + falcon_level1_sa_algo = 12, + falcon_level5_sa_algo = 13, + dilithium_level2_sa_algo = 14, + dilithium_level3_sa_algo = 15, + dilithium_level5_sa_algo = 16, + dilithium_aes_level2_sa_algo = 17, + dilithium_aes_level3_sa_algo = 18, + dilithium_aes_level5_sa_algo = 19, + invalid_sa_algo = 255 }; #define PSS_RSAE_TO_PSS_PSS(macAlgo) \ @@ -3347,6 +3372,7 @@ enum ClientCertificateType { rsa_fixed_ecdh = 65, ecdsa_fixed_ecdh = 66, falcon_sign = 67, + dilithium_sign = 68, }; @@ -3872,6 +3898,7 @@ typedef struct Options { word16 haveECDSAsig:1; /* server ECDSA signed cert */ word16 haveStaticECC:1; /* static server ECC private key */ word16 haveFalconSig:1; /* server Falcon signed cert */ + word16 haveDilithiumSig:1; /* server Dilithium signed cert */ word16 havePeerCert:1; /* do we have peer's cert */ word16 havePeerVerify:1; /* and peer's cert verify */ word16 usingPSK_cipher:1; /* are using psk as cipher */ @@ -3996,6 +4023,7 @@ typedef struct Options { #endif #if defined(HAVE_PQC) short minFalconKeySz; /* minimum Falcon key size */ + short minDilithiumKeySz;/* minimum Dilithium key size */ #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) byte verifyDepth; /* maximum verification depth */ @@ -4702,6 +4730,8 @@ struct WOLFSSL { #ifdef HAVE_PQC falcon_key* peerFalconKey; byte peerFalconKeyPresent; + dilithium_key* peerDilithiumKey; + byte peerDilithiumKeyPresent; #endif #ifdef HAVE_LIBZ z_stream c_stream; /* compression stream */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 28772836d..c6cab8496 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -267,6 +267,7 @@ enum { EVP_PKEY_HMAC = NID_hmac, EVP_PKEY_HKDF = NID_hkdf, EVP_PKEY_FALCON = 300, /* Randomly picked value. */ + EVP_PKEY_DILITHIUM= 301, /* Randomly picked value. */ AES_128_CFB1_TYPE = 24, AES_192_CFB1_TYPE = 25, AES_256_CFB1_TYPE = 26, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f7d71451d..b14f61ce7 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1078,17 +1078,23 @@ enum Block_Sum { enum Key_Sum { - DSAk = 515, - RSAk = 645, - RSAPSSk = 654, - ECDSAk = 518, - ED25519k = 256, /* 1.3.101.112 */ - X25519k = 254, /* 1.3.101.110 */ - ED448k = 257, /* 1.3.101.113 */ - X448k = 255, /* 1.3.101.111 */ - DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ - FALCON_LEVEL1k = 268, /* 1.3.9999.3.1 */ - FALCON_LEVEL5k = 271 /* 1.3.9999.3.4 */ + DSAk = 515, + RSAk = 645, + RSAPSSk = 654, + ECDSAk = 518, + ED25519k = 256, /* 1.3.101.112 */ + X25519k = 254, /* 1.3.101.110 */ + ED448k = 257, /* 1.3.101.113 */ + X448k = 255, /* 1.3.101.111 */ + DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ + FALCON_LEVEL1k = 268, /* 1.3.9999.3.1 */ + FALCON_LEVEL5k = 271, /* 1.3.9999.3.4 */ + DILITHIUM_LEVEL2k = 213, /* 1.3.6.1.4.1.2.267.7.4.4 */ + DILITHIUM_LEVEL3k = 216, /* 1.3.6.1.4.1.2.267.7.6.5 */ + DILITHIUM_LEVEL5k = 220, /* 1.3.6.1.4.1.2.267.7.8.7 */ + DILITHIUM_AES_LEVEL2k = 217,/* 1.3.6.1.4.1.2.267.11.4.4 */ + DILITHIUM_AES_LEVEL3k = 221,/* 1.3.6.1.4.1.2.267.11.6.5 + 1 (See GetOID() in asn.c) */ + DILITHIUM_AES_LEVEL5k = 224,/* 1.3.6.1.4.1.2.267.11.8.7 */ }; #if !defined(NO_AES) || defined(HAVE_PKCS7) @@ -1404,6 +1410,7 @@ struct SignatureCtx { #endif #ifdef HAVE_PQC struct falcon_key* falcon; + struct dilithium_key* dilithium; #endif void* ptr; } key; @@ -2208,13 +2215,19 @@ WOLFSSL_LOCAL int wc_MIME_free_hdrs(MimeHdr* head); #ifdef WOLFSSL_CERT_GEN enum cert_enums { - RSA_KEY = 10, - ECC_KEY = 12, - ED25519_KEY = 13, - ED448_KEY = 14, - DSA_KEY = 15, - FALCON_LEVEL1_KEY = 16, - FALCON_LEVEL5_KEY = 17 + RSA_KEY = 10, + ECC_KEY = 12, + ED25519_KEY = 13, + ED448_KEY = 14, + DSA_KEY = 15, + FALCON_LEVEL1_KEY = 16, + FALCON_LEVEL5_KEY = 17, + DILITHIUM_LEVEL2_KEY = 18, + DILITHIUM_LEVEL3_KEY = 19, + DILITHIUM_LEVEL5_KEY = 20, + DILITHIUM_AES_LEVEL2_KEY = 21, + DILITHIUM_AES_LEVEL3_KEY = 22, + DILITHIUM_AES_LEVEL5_KEY = 23, }; #endif /* WOLFSSL_CERT_GEN */ @@ -2442,6 +2455,24 @@ WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL* dcrl); #endif /* !NO_ASN */ +#if ((defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)) \ + || (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) \ + || (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) \ + || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ + || (defined(HAVE_PQC) && defined(HAVE_FALCON)) \ + || (defined(HAVE_PQC) && defined(HAVE_DILITHIUM))) +WOLFSSL_LOCAL int DecodeAsymKey(const byte* input, word32* inOutIdx, + word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, + word32* pubKeyLen, int keyType); +#endif + +#ifdef WC_ENABLE_ASYM_KEY_EXPORT +WOLFSSL_LOCAL int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, + const byte* pubKey, word32 pubKeyLen, byte* output, word32 outLen, + int keyType); +#endif + + #if !defined(NO_ASN) || !defined(NO_PWDBASED) #ifndef PKCS_MAX_KEY_SIZE diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index f33b3ef93..0d927fc2f 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -72,6 +72,10 @@ This library defines the interface APIs for X509 certificates. typedef struct falcon_key falcon_key; #define WC_FALCONKEY_TYPE_DEFINED #endif +#ifndef WC_DILITHIUMKEY_TYPE_DEFINED + typedef struct dilithium_key dilithium_key; + #define WC_DILITHIUMKEY_TYPE_DEFINED +#endif enum Ecc_Sum { ECC_SECP112R1_OID = 182, @@ -137,6 +141,12 @@ enum CertType { X942_PARAM_TYPE, FALCON_LEVEL1_TYPE, FALCON_LEVEL5_TYPE, + DILITHIUM_LEVEL2_TYPE, + DILITHIUM_LEVEL3_TYPE, + DILITHIUM_LEVEL5_TYPE, + DILITHIUM_AES_LEVEL2_TYPE, + DILITHIUM_AES_LEVEL3_TYPE, + DILITHIUM_AES_LEVEL5_TYPE, }; @@ -173,7 +183,14 @@ enum Ctc_SigType { CTC_ED448 = 257, CTC_FALCON_LEVEL1 = 268, - CTC_FALCON_LEVEL5 = 271 + CTC_FALCON_LEVEL5 = 271, + + CTC_DILITHIUM_LEVEL2 = 213, + CTC_DILITHIUM_LEVEL3 = 216, + CTC_DILITHIUM_LEVEL5 = 220, + CTC_DILITHIUM_AES_LEVEL2 = 217, + CTC_DILITHIUM_AES_LEVEL3 = 221, + CTC_DILITHIUM_AES_LEVEL5 = 224, }; enum Ctc_Encoding { @@ -688,7 +705,7 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT)) || \ (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT)) || \ - (defined(HAVE_PQC) && defined(HAVE_FALCON))) + (defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)))) #define WC_ENABLE_ASYM_KEY_EXPORT #endif @@ -751,14 +768,28 @@ WOLFSSL_API int wc_Ed448PublicKeyToDer( #ifdef HAVE_PQC WOLFSSL_API int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx, - falcon_key* key, word32 inSz); + falcon_key* key, word32 inSz); WOLFSSL_API int wc_Falcon_PublicKeyDecode(const byte* input, word32* inOutIdx, - falcon_key* key, word32 inSz); -WOLFSSL_API int wc_Falcon_KeyToDer(falcon_key* key, byte* output, word32 inLen); + falcon_key* key, word32 inSz); +WOLFSSL_API int wc_Falcon_KeyToDer(falcon_key* key, byte* output, + word32 inLen); WOLFSSL_API int wc_Falcon_PrivateKeyToDer(falcon_key* key, byte* output, word32 inLen); WOLFSSL_API int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen, int withAlg); + +WOLFSSL_API int wc_Dilithium_PrivateKeyDecode(const byte* input, + word32* inOutIdx, + dilithium_key* key, word32 inSz); +WOLFSSL_API int wc_Dilithium_PublicKeyDecode(const byte* input, + word32* inOutIdx, + dilithium_key* key, word32 inSz); +WOLFSSL_API int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, + word32 inLen); +WOLFSSL_API int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, + word32 inLen); +WOLFSSL_API int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, + word32 inLen, int withAlg); #endif /* HAVE_PQC */ #ifdef HAVE_CURVE448 diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h new file mode 100644 index 000000000..8199c038d --- /dev/null +++ b/wolfssl/wolfcrypt/dilithium.h @@ -0,0 +1,142 @@ +/* dilithium.h + * + * Copyright (C) 2022 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/dilithium.h +*/ + +/* Interfaces for Dilithium NIST Level 1 (Dilithium512) and Dilithium NIST Level 5 + * (Dilithium1024). */ + +#ifndef WOLF_CRYPT_DILITHIUM_H +#define WOLF_CRYPT_DILITHIUM_H + +#include + +#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + +#ifdef HAVE_LIBOQS +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* Macros Definitions */ + +#ifdef HAVE_LIBOQS +#define DILITHIUM_LEVEL2_KEY_SIZE OQS_SIG_dilithium_2_length_secret_key +#define DILITHIUM_LEVEL2_SIG_SIZE OQS_SIG_dilithium_2_length_signature +#define DILITHIUM_LEVEL2_PUB_KEY_SIZE OQS_SIG_dilithium_2_length_public_key +#define DILITHIUM_LEVEL2_PRV_KEY_SIZE (DILITHIUM_LEVEL2_PUB_KEY_SIZE+DILITHIUM_LEVEL2_KEY_SIZE) + +#define DILITHIUM_LEVEL3_KEY_SIZE OQS_SIG_dilithium_3_length_secret_key +#define DILITHIUM_LEVEL3_SIG_SIZE OQS_SIG_dilithium_3_length_signature +#define DILITHIUM_LEVEL3_PUB_KEY_SIZE OQS_SIG_dilithium_3_length_public_key +#define DILITHIUM_LEVEL3_PRV_KEY_SIZE (DILITHIUM_LEVEL3_PUB_KEY_SIZE+DILITHIUM_LEVEL3_KEY_SIZE) + +#define DILITHIUM_LEVEL5_KEY_SIZE OQS_SIG_dilithium_5_length_secret_key +#define DILITHIUM_LEVEL5_SIG_SIZE OQS_SIG_dilithium_5_length_signature +#define DILITHIUM_LEVEL5_PUB_KEY_SIZE OQS_SIG_dilithium_5_length_public_key +#define DILITHIUM_LEVEL5_PRV_KEY_SIZE (DILITHIUM_LEVEL5_PUB_KEY_SIZE+DILITHIUM_LEVEL5_KEY_SIZE) +#endif + +#define DILITHIUM_MAX_KEY_SIZE DILITHIUM_LEVEL5_PRV_KEY_SIZE +#define DILITHIUM_MAX_SIG_SIZE DILITHIUM_LEVEL5_SIG_SIZE +#define DILITHIUM_MAX_PUB_KEY_SIZE DILITHIUM_LEVEL5_PUB_KEY_SIZE +#define DILITHIUM_MAX_PRV_KEY_SIZE DILITHIUM_LEVEL5_PRV_KEY_SIZE + +#define SHAKE_VARIANT 1 +#define AES_VARIANT 2 + +/* Structs */ + +struct dilithium_key { + bool pubKeySet; + bool prvKeySet; + byte level; /* 2,3 or 5 */ + byte sym; /* SHAKE_VARIANT or AES_VARIANT */ + byte p[DILITHIUM_MAX_PUB_KEY_SIZE]; + byte k[DILITHIUM_MAX_PRV_KEY_SIZE]; +}; + +#ifndef WC_DILITHIUMKEY_TYPE_DEFINED + typedef struct dilithium_key dilithium_key; + #define WC_DILITHIUMKEY_TYPE_DEFINED +#endif + +/* Functions */ + +WOLFSSL_API +int wc_dilithium_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, + dilithium_key* key); +WOLFSSL_API +int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, dilithium_key* key); + +WOLFSSL_API +int wc_dilithium_init(dilithium_key* key); +WOLFSSL_API +int wc_dilithium_set_level_and_sym(dilithium_key* key, byte level, byte sym); +WOLFSSL_API +int wc_dilithium_get_level_and_sym(dilithium_key* key, byte* level, byte *sym); +WOLFSSL_API +void wc_dilithium_free(dilithium_key* key); + +WOLFSSL_API +int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key); +WOLFSSL_API +int wc_dilithium_import_private_only(const byte* priv, word32 privSz, + dilithium_key* key); +WOLFSSL_API +int wc_dilithium_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + dilithium_key* key); + +WOLFSSL_API +int wc_dilithium_export_public(dilithium_key*, byte* out, word32* outLen); +WOLFSSL_API +int wc_dilithium_export_private_only(dilithium_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); + +WOLFSSL_API +int wc_dilithium_check_key(dilithium_key* key); + +WOLFSSL_API +int wc_dilithium_size(dilithium_key* key); +WOLFSSL_API +int wc_dilithium_priv_size(dilithium_key* key); +WOLFSSL_API +int wc_dilithium_pub_size(dilithium_key* key); +WOLFSSL_API +int wc_dilithium_sig_size(dilithium_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_PQC && HAVE_DILITHIUM */ +#endif /* WOLF_CRYPT_DILITHIUM_H */ diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index ff460c44a..9aea5a654 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -22,6 +22,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/curve448.h \ wolfssl/wolfcrypt/ed448.h \ wolfssl/wolfcrypt/falcon.h \ + wolfssl/wolfcrypt/dilithium.h \ wolfssl/wolfcrypt/fe_448.h \ wolfssl/wolfcrypt/ge_448.h \ wolfssl/wolfcrypt/eccsi.h \ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 0f86ec522..d17e3710b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2720,6 +2720,7 @@ extern void uITRON4_free(void *p) ; #ifdef HAVE_LIBOQS #define HAVE_PQC #define HAVE_FALCON +#define HAVE_DILITHIUM #define HAVE_KYBER #endif diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index cac7558ff..41479f385 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -947,6 +947,7 @@ typedef struct w64wrapper { DYNAMIC_TYPE_CMAC = 94, DYNAMIC_TYPE_FALCON = 95, DYNAMIC_TYPE_SESSION = 96, + DYNAMIC_TYPE_DILITHIUM = 97, DYNAMIC_TYPE_SNIFFER_SERVER = 1000, DYNAMIC_TYPE_SNIFFER_SESSION = 1001, DYNAMIC_TYPE_SNIFFER_PB = 1002,