From 755c02310277212c764ab94b6eb9348d500ba07d Mon Sep 17 00:00:00 2001 From: Basil Hess Date: Tue, 28 May 2024 16:25:59 +0200 Subject: [PATCH 01/10] Fix for incorrect macros in signatures. (#1799) Signed-off-by: Basil Hess --- .../src/sig/family/sig_family.h | 7 +++---- src/sig/ml_dsa/sig_ml_dsa.h | 21 ++++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/scripts/copy_from_upstream/src/sig/family/sig_family.h b/scripts/copy_from_upstream/src/sig/family/sig_family.h index b17d621635..94d3a78c15 100644 --- a/scripts/copy_from_upstream/src/sig/family/sig_family.h +++ b/scripts/copy_from_upstream/src/sig/family/sig_family.h @@ -18,12 +18,11 @@ OQS_API OQS_STATUS OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_verify(const uint {% if 'alias_scheme' in scheme %} #define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_length_public_key OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_public_key #define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_length_secret_key OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_secret_key -#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_length_ciphertext OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_ciphertext -#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_length_shared_secret OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_shared_secret +#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_length_signature OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_signature OQS_SIG *OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_new(void); #define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_keypair OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_keypair -#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_encaps OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_encaps -#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_decaps OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_decaps +#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_sign OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_sign +#define OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_verify OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_verify {% endif -%} #endif diff --git a/src/sig/ml_dsa/sig_ml_dsa.h b/src/sig/ml_dsa/sig_ml_dsa.h index e4b94a7902..fe95a2d7cf 100644 --- a/src/sig/ml_dsa/sig_ml_dsa.h +++ b/src/sig/ml_dsa/sig_ml_dsa.h @@ -17,12 +17,11 @@ OQS_API OQS_STATUS OQS_SIG_ml_dsa_44_ipd_verify(const uint8_t *message, size_t m #define OQS_SIG_ml_dsa_44_length_public_key OQS_SIG_ml_dsa_44_ipd_length_public_key #define OQS_SIG_ml_dsa_44_length_secret_key OQS_SIG_ml_dsa_44_ipd_length_secret_key -#define OQS_SIG_ml_dsa_44_length_ciphertext OQS_SIG_ml_dsa_44_ipd_length_ciphertext -#define OQS_SIG_ml_dsa_44_length_shared_secret OQS_SIG_ml_dsa_44_ipd_length_shared_secret +#define OQS_SIG_ml_dsa_44_length_signature OQS_SIG_ml_dsa_44_ipd_length_signature OQS_SIG *OQS_SIG_ml_dsa_44_new(void); #define OQS_SIG_ml_dsa_44_keypair OQS_SIG_ml_dsa_44_ipd_keypair -#define OQS_SIG_ml_dsa_44_encaps OQS_SIG_ml_dsa_44_ipd_encaps -#define OQS_SIG_ml_dsa_44_decaps OQS_SIG_ml_dsa_44_ipd_decaps +#define OQS_SIG_ml_dsa_44_sign OQS_SIG_ml_dsa_44_ipd_sign +#define OQS_SIG_ml_dsa_44_verify OQS_SIG_ml_dsa_44_ipd_verify #endif #if defined(OQS_ENABLE_SIG_ml_dsa_65_ipd) || defined(OQS_ENABLE_SIG_ml_dsa_65) @@ -37,12 +36,11 @@ OQS_API OQS_STATUS OQS_SIG_ml_dsa_65_ipd_verify(const uint8_t *message, size_t m #define OQS_SIG_ml_dsa_65_length_public_key OQS_SIG_ml_dsa_65_ipd_length_public_key #define OQS_SIG_ml_dsa_65_length_secret_key OQS_SIG_ml_dsa_65_ipd_length_secret_key -#define OQS_SIG_ml_dsa_65_length_ciphertext OQS_SIG_ml_dsa_65_ipd_length_ciphertext -#define OQS_SIG_ml_dsa_65_length_shared_secret OQS_SIG_ml_dsa_65_ipd_length_shared_secret +#define OQS_SIG_ml_dsa_65_length_signature OQS_SIG_ml_dsa_65_ipd_length_signature OQS_SIG *OQS_SIG_ml_dsa_65_new(void); #define OQS_SIG_ml_dsa_65_keypair OQS_SIG_ml_dsa_65_ipd_keypair -#define OQS_SIG_ml_dsa_65_encaps OQS_SIG_ml_dsa_65_ipd_encaps -#define OQS_SIG_ml_dsa_65_decaps OQS_SIG_ml_dsa_65_ipd_decaps +#define OQS_SIG_ml_dsa_65_sign OQS_SIG_ml_dsa_65_ipd_sign +#define OQS_SIG_ml_dsa_65_verify OQS_SIG_ml_dsa_65_ipd_verify #endif #if defined(OQS_ENABLE_SIG_ml_dsa_87_ipd) || defined(OQS_ENABLE_SIG_ml_dsa_87) @@ -57,12 +55,11 @@ OQS_API OQS_STATUS OQS_SIG_ml_dsa_87_ipd_verify(const uint8_t *message, size_t m #define OQS_SIG_ml_dsa_87_length_public_key OQS_SIG_ml_dsa_87_ipd_length_public_key #define OQS_SIG_ml_dsa_87_length_secret_key OQS_SIG_ml_dsa_87_ipd_length_secret_key -#define OQS_SIG_ml_dsa_87_length_ciphertext OQS_SIG_ml_dsa_87_ipd_length_ciphertext -#define OQS_SIG_ml_dsa_87_length_shared_secret OQS_SIG_ml_dsa_87_ipd_length_shared_secret +#define OQS_SIG_ml_dsa_87_length_signature OQS_SIG_ml_dsa_87_ipd_length_signature OQS_SIG *OQS_SIG_ml_dsa_87_new(void); #define OQS_SIG_ml_dsa_87_keypair OQS_SIG_ml_dsa_87_ipd_keypair -#define OQS_SIG_ml_dsa_87_encaps OQS_SIG_ml_dsa_87_ipd_encaps -#define OQS_SIG_ml_dsa_87_decaps OQS_SIG_ml_dsa_87_ipd_decaps +#define OQS_SIG_ml_dsa_87_sign OQS_SIG_ml_dsa_87_ipd_sign +#define OQS_SIG_ml_dsa_87_verify OQS_SIG_ml_dsa_87_ipd_verify #endif #endif From 982c762c242ef549c914891b47bf6e0ed6321f91 Mon Sep 17 00:00:00 2001 From: Basil Hess Date: Mon, 3 Jun 2024 15:26:57 +0200 Subject: [PATCH 02/10] Pull Kyber/ML-KEM CT-Fix from upstream Signed-off-by: Basil Hess --- docs/algorithms/kem/kyber.md | 4 ++-- docs/algorithms/kem/kyber.yml | 2 +- docs/algorithms/kem/ml_kem.md | 2 +- docs/algorithms/kem/ml_kem.yml | 2 +- .../copy_from_upstream/copy_from_upstream.yml | 4 ++-- .../pqcrystals-kyber_kyber1024_avx2/verify.h | 3 +++ .../pqcrystals-kyber_kyber1024_ref/poly.c | 6 +++--- .../pqcrystals-kyber_kyber1024_ref/verify.c | 17 +++++++++++++++++ .../pqcrystals-kyber_kyber1024_ref/verify.h | 3 +++ .../pqcrystals-kyber_kyber512_avx2/verify.h | 3 +++ .../kyber/pqcrystals-kyber_kyber512_ref/poly.c | 6 +++--- .../pqcrystals-kyber_kyber512_ref/verify.c | 17 +++++++++++++++++ .../pqcrystals-kyber_kyber512_ref/verify.h | 3 +++ .../pqcrystals-kyber_kyber768_avx2/verify.h | 3 +++ .../kyber/pqcrystals-kyber_kyber768_ref/poly.c | 6 +++--- .../pqcrystals-kyber_kyber768_ref/verify.c | 17 +++++++++++++++++ .../pqcrystals-kyber_kyber768_ref/verify.h | 3 +++ .../verify.h | 3 +++ .../poly.c | 6 +++--- .../verify.c | 18 ++++++++++++++++++ .../verify.h | 3 +++ .../verify.h | 3 +++ .../poly.c | 6 +++--- .../verify.c | 18 ++++++++++++++++++ .../verify.h | 3 +++ .../verify.h | 3 +++ .../poly.c | 6 +++--- .../verify.c | 18 ++++++++++++++++++ .../verify.h | 3 +++ 29 files changed, 166 insertions(+), 25 deletions(-) diff --git a/docs/algorithms/kem/kyber.md b/docs/algorithms/kem/kyber.md index a75c144a2d..0ae1cf3109 100644 --- a/docs/algorithms/kem/kyber.md +++ b/docs/algorithms/kem/kyber.md @@ -7,9 +7,9 @@ - **Authors' website**: https://pq-crystals.org/ - **Specification version**: NIST Round 3 submission. - **Primary Source**: - - **Source**: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e with copy_from_upstream patches + - **Source**: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0 -- **Optimized Implementation sources**: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e with copy_from_upstream patches +- **Optimized Implementation sources**: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc with copy_from_upstream patches - **oldpqclean-aarch64**: - **Source**: https://github.com/PQClean/PQClean/commit/8e220a87308154d48fdfac40abbb191ac7fce06a with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 and (CC0-1.0 or Apache-2.0) and (CC0-1.0 or MIT) and MIT diff --git a/docs/algorithms/kem/kyber.yml b/docs/algorithms/kem/kyber.yml index cde870c10b..c3561273a0 100644 --- a/docs/algorithms/kem/kyber.yml +++ b/docs/algorithms/kem/kyber.yml @@ -17,7 +17,7 @@ website: https://pq-crystals.org/ nist-round: 3 spec-version: NIST Round 3 submission primary-upstream: - source: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e + source: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc with copy_from_upstream patches spdx-license-identifier: CC0-1.0 or Apache-2.0 optimized-upstreams: diff --git a/docs/algorithms/kem/ml_kem.md b/docs/algorithms/kem/ml_kem.md index 92d1a5b4bd..7d5e0561ab 100644 --- a/docs/algorithms/kem/ml_kem.md +++ b/docs/algorithms/kem/ml_kem.md @@ -7,7 +7,7 @@ - **Authors' website**: https://pq-crystals.org/kyber/ and https://csrc.nist.gov/pubs/fips/203/ipd - **Specification version**: ML-KEM-ipd. - **Primary Source**: - - **Source**: https://github.com/pq-crystals/kyber/commit/11d00ff1f20cfca1f72d819e5a45165c1e0a2816 with copy_from_upstream patches + - **Source**: https://github.com/pq-crystals/kyber/commit/d1321ce5ac0b53f583eb47a040dc3625ee8e7e37 with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0 diff --git a/docs/algorithms/kem/ml_kem.yml b/docs/algorithms/kem/ml_kem.yml index 38b0a3ef24..58d2ce19b1 100644 --- a/docs/algorithms/kem/ml_kem.yml +++ b/docs/algorithms/kem/ml_kem.yml @@ -17,7 +17,7 @@ website: https://pq-crystals.org/kyber/ and https://csrc.nist.gov/pubs/fips/203/ nist-round: ipd spec-version: ML-KEM-ipd primary-upstream: - source: https://github.com/pq-crystals/kyber/commit/11d00ff1f20cfca1f72d819e5a45165c1e0a2816 + source: https://github.com/pq-crystals/kyber/commit/d1321ce5ac0b53f583eb47a040dc3625ee8e7e37 with copy_from_upstream patches spdx-license-identifier: CC0-1.0 or Apache-2.0 parameter-sets: diff --git a/scripts/copy_from_upstream/copy_from_upstream.yml b/scripts/copy_from_upstream/copy_from_upstream.yml index d8a9a4d121..3417180c7c 100644 --- a/scripts/copy_from_upstream/copy_from_upstream.yml +++ b/scripts/copy_from_upstream/copy_from_upstream.yml @@ -25,7 +25,7 @@ upstreams: name: pqcrystals-kyber git_url: https://github.com/pq-crystals/kyber.git git_branch: master - git_commit: b628ba78711bc28327dc7d2d5c074a00f061884e + git_commit: 441c0519a07e8b86c8d079954a6b10bd31d29efc kem_meta_path: '{pretty_name_full}_META.yml' kem_scheme_path: '.' patches: [pqcrystals-kyber-yml.patch, pqcrystals-kyber-ref-shake-aes.patch, pqcrystals-kyber-avx2-shake-aes.patch] @@ -33,7 +33,7 @@ upstreams: name: pqcrystals-kyber-standard git_url: https://github.com/pq-crystals/kyber.git git_branch: standard - git_commit: 11d00ff1f20cfca1f72d819e5a45165c1e0a2816 + git_commit: d1321ce5ac0b53f583eb47a040dc3625ee8e7e37 kem_meta_path: '{pretty_name_full}_META.yml' kem_scheme_path: '.' patches: [pqcrystals-ml_kem_ipd.patch] diff --git a/src/kem/kyber/pqcrystals-kyber_kyber1024_avx2/verify.h b/src/kem/kyber/pqcrystals-kyber_kyber1024_avx2/verify.h index f95ac1b84e..09f0ad5046 100644 --- a/src/kem/kyber/pqcrystals-kyber_kyber1024_avx2/verify.h +++ b/src/kem/kyber/pqcrystals-kyber_kyber1024_avx2/verify.h @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len); #define cmov KYBER_NAMESPACE(cmov) void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); +#define cmov_int16 KYBER_NAMESPACE(cmov_int16) +void cmov_int16(int16_t *r, int16_t v, uint16_t b); + #endif diff --git a/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/poly.c b/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/poly.c index 3e73579e68..9d3b1358fe 100644 --- a/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/poly.c +++ b/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/poly.c @@ -5,6 +5,7 @@ #include "reduce.h" #include "cbd.h" #include "symmetric.h" +#include "verify.h" /************************************************* * Name: poly_compress @@ -166,7 +167,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES]) void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) { unsigned int i,j; - int16_t mask; #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" @@ -174,8 +174,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/verify.c b/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/verify.c index 1c43071ca0..4bcb1e5f11 100644 --- a/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/verify.c +++ b/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/verify.c @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/kyber/pqcrystals-kyber_kyber512_ref/verify.c b/src/kem/kyber/pqcrystals-kyber_kyber512_ref/verify.c index 1c43071ca0..4bcb1e5f11 100644 --- a/src/kem/kyber/pqcrystals-kyber_kyber512_ref/verify.c +++ b/src/kem/kyber/pqcrystals-kyber_kyber512_ref/verify.c @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/kyber/pqcrystals-kyber_kyber768_ref/verify.c b/src/kem/kyber/pqcrystals-kyber_kyber768_ref/verify.c index 1c43071ca0..4bcb1e5f11 100644 --- a/src/kem/kyber/pqcrystals-kyber_kyber768_ref/verify.c +++ b/src/kem/kyber/pqcrystals-kyber_kyber768_ref/verify.c @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024-ipd_ref/verify.c b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024-ipd_ref/verify.c index ed4a6541f8..aad03b0297 100644 --- a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024-ipd_ref/verify.c +++ b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024-ipd_ref/verify.c @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512-ipd_ref/verify.c b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512-ipd_ref/verify.c index ed4a6541f8..aad03b0297 100644 --- a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512-ipd_ref/verify.c +++ b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512-ipd_ref/verify.c @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i> j)&1); - r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2); + r->coeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } } } diff --git a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768-ipd_ref/verify.c b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768-ipd_ref/verify.c index ed4a6541f8..aad03b0297 100644 --- a/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768-ipd_ref/verify.c +++ b/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768-ipd_ref/verify.c @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) for(i=0;i Date: Fri, 31 May 2024 12:03:58 +0100 Subject: [PATCH 03/10] Force gcc 13.2.0 over 13.3.0 Signed-off-by: Nigel Jones --- .github/workflows/unix.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index ab0213ef34..bc8991c370 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -212,6 +212,8 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies run: env HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja && pip3 install --break-system-packages pytest pytest-xdist pyyaml + - name: Patch GCC + run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb - name: Get system information run: sysctl -a | grep machdep.cpu - name: Configure @@ -268,4 +270,4 @@ jobs: working-directory: build - name: Run tests timeout-minutes: 60 - run: mkdir -p tmp && python3 -m pytest --verbose --ignore=tests/test_code_conventions.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py \ No newline at end of file + run: mkdir -p tmp && python3 -m pytest --verbose --ignore=tests/test_code_conventions.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py From 41699656cd22e842d69f00478ed27b936612ec7d Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Fri, 31 May 2024 12:20:10 +0100 Subject: [PATCH 04/10] remove gcc override to validate gcc change resulted in build success (and this fails) Signed-off-by: Nigel Jones --- .github/workflows/unix.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index bc8991c370..00f5430961 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -212,8 +212,8 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies run: env HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja && pip3 install --break-system-packages pytest pytest-xdist pyyaml - - name: Patch GCC - run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb + #- name: Patch GCC + #run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb - name: Get system information run: sysctl -a | grep machdep.cpu - name: Configure From 8066012110726b20960d58781b991ae70a6f4480 Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Fri, 31 May 2024 12:35:35 +0100 Subject: [PATCH 05/10] add back gcc override Signed-off-by: Nigel Jones --- .github/workflows/unix.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index 00f5430961..bc8991c370 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -212,8 +212,8 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies run: env HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja && pip3 install --break-system-packages pytest pytest-xdist pyyaml - #- name: Patch GCC - #run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb + - name: Patch GCC + run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb - name: Get system information run: sysctl -a | grep machdep.cpu - name: Configure From 0a89cf6fd4b8937c4d458ca333bfac00f70bbf52 Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Fri, 31 May 2024 13:27:26 +0100 Subject: [PATCH 06/10] ensure no autoupdate Signed-off-by: Nigel Jones --- .github/workflows/unix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index bc8991c370..a916f3633f 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -213,7 +213,7 @@ jobs: - name: Install dependencies run: env HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja && pip3 install --break-system-packages pytest pytest-xdist pyyaml - name: Patch GCC - run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && brew install --ignore-dependencies gcc@13.rb + run: env HOMEBREW_NO_AUTO_UPDATE=1 brew uninstall --ignore-dependencies gcc@13 && wget https://raw.githubusercontent.com/Homebrew/homebrew-core/eb6dd225d093b66054e18e07d56509cf670793b1/Formula/g/gcc%4013.rb && env HOMEBREW_NO_AUTO_UPDATE=1 brew install --ignore-dependencies gcc@13.rb - name: Get system information run: sysctl -a | grep machdep.cpu - name: Configure From 971173ad82327ede5027b6d48e81bcaff92f417c Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Wed, 5 Jun 2024 15:59:40 -0400 Subject: [PATCH 07/10] Add Stateful Signature (XMSS and LMS) (#1650) Add support for LMS and XMSS. Key generation and signing are disabled behind a feature flag labelled "hazardous experimental." --------- Signed-off-by: Duc Tri Nguyen Signed-off-by: Spencer Wilson Signed-off-by: Norman Ashley Signed-off-by: Douglas Stebila Co-authored-by: Duc Tri Nguyen Co-authored-by: Douglas Stebila Co-authored-by: Duc Nguyen <106774416+ducnguyen-sb@users.noreply.github.com> Co-authored-by: Douglas Stebila Co-authored-by: Duc Nguyen Co-authored-by: Spencer Wilson Co-authored-by: Jason Goertzen <133878263+jgoertzen-sb@users.noreply.github.com> --- .CMake/alg_support.cmake | 87 +- .circleci/config.yml | 1 + .github/workflows/android.yml | 4 +- .github/workflows/apple.yml | 5 +- .github/workflows/unix.yml | 23 +- .github/workflows/windows.yml | 8 +- .travis.yml | 4 +- CMakeLists.txt | 9 +- CONFIGURE.md | 53 +- CONTRIBUTORS | 1 + README.md | 9 +- docs/algorithms/sig_stfl/lms.md | 50 + docs/algorithms/sig_stfl/lms.yml | 216 +++ docs/algorithms/sig_stfl/sig_stfl.md | 29 + docs/algorithms/sig_stfl/xmss.md | 44 + docs/algorithms/sig_stfl/xmss.yml | 187 +++ scripts/build-android.sh | 9 +- .../copy_from_upstream/copy_from_upstream.py | 2 +- scripts/update_docs_from_yaml.py | 61 + src/CMakeLists.txt | 13 + src/common/common.c | 20 + src/common/common.h | 55 + src/common/sha2/sha2.c | 4 + src/common/sha2/sha2.h | 38 + src/common/sha2/sha2_armv8.c | 201 ++- src/common/sha2/sha2_c.c | 158 +- src/common/sha2/sha2_impl.c | 8 + src/common/sha2/sha2_local.h | 10 + src/common/sha2/sha2_ossl.c | 5 + src/common/sha3/ossl_sha3.c | 12 +- src/common/sha3/ossl_sha3x4.c | 12 +- src/common/sha3/xkcp_sha3.c | 25 +- src/common/sha3/xkcp_sha3x4.c | 10 +- src/oqs.h | 1 + src/oqsconfig.h.cmake | 51 + src/sig_stfl/lms/CMakeLists.txt | 44 + src/sig_stfl/lms/external/common_defs.h | 179 ++ src/sig_stfl/lms/external/config.h | 37 + src/sig_stfl/lms/external/endian.c | 24 + src/sig_stfl/lms/external/endian.h | 11 + src/sig_stfl/lms/external/hash.c | 123 ++ src/sig_stfl/lms/external/hash.h | 60 + src/sig_stfl/lms/external/hss.c | 170 ++ src/sig_stfl/lms/external/hss.h | 419 +++++ src/sig_stfl/lms/external/hss_alloc.c | 556 +++++++ src/sig_stfl/lms/external/hss_aux.c | 356 ++++ src/sig_stfl/lms/external/hss_aux.h | 61 + src/sig_stfl/lms/external/hss_common.c | 49 + src/sig_stfl/lms/external/hss_common.h | 24 + src/sig_stfl/lms/external/hss_compute.c | 175 ++ src/sig_stfl/lms/external/hss_derive.c | 326 ++++ src/sig_stfl/lms/external/hss_derive.h | 76 + src/sig_stfl/lms/external/hss_generate.c | 933 +++++++++++ src/sig_stfl/lms/external/hss_internal.h | 245 +++ src/sig_stfl/lms/external/hss_keygen.c | 375 +++++ src/sig_stfl/lms/external/hss_param.c | 154 ++ src/sig_stfl/lms/external/hss_reserve.c | 195 +++ src/sig_stfl/lms/external/hss_reserve.h | 23 + src/sig_stfl/lms/external/hss_sign.c | 737 +++++++++ src/sig_stfl/lms/external/hss_sign_inc.c | 222 +++ src/sig_stfl/lms/external/hss_sign_inc.h | 83 + src/sig_stfl/lms/external/hss_thread.h | 137 ++ .../lms/external/hss_thread_pthread.c | 299 ++++ src/sig_stfl/lms/external/hss_thread_single.c | 64 + src/sig_stfl/lms/external/hss_verify.c | 197 +++ src/sig_stfl/lms/external/hss_verify.h | 25 + src/sig_stfl/lms/external/hss_verify_inc.c | 204 +++ src/sig_stfl/lms/external/hss_verify_inc.h | 84 + src/sig_stfl/lms/external/hss_zeroize.c | 50 + src/sig_stfl/lms/external/hss_zeroize.h | 12 + src/sig_stfl/lms/external/license.txt | 29 + src/sig_stfl/lms/external/lm_common.c | 80 + src/sig_stfl/lms/external/lm_common.h | 22 + src/sig_stfl/lms/external/lm_ots.h | 66 + src/sig_stfl/lms/external/lm_ots_common.c | 100 ++ src/sig_stfl/lms/external/lm_ots_common.h | 18 + src/sig_stfl/lms/external/lm_ots_sign.c | 169 ++ src/sig_stfl/lms/external/lm_ots_verify.c | 123 ++ src/sig_stfl/lms/external/lm_ots_verify.h | 25 + src/sig_stfl/lms/external/lm_verify.c | 108 ++ src/sig_stfl/lms/external/lm_verify.h | 14 + src/sig_stfl/lms/external/lms_namespace.h | 95 ++ src/sig_stfl/lms/sig_stfl_lms.c | 293 ++++ src/sig_stfl/lms/sig_stfl_lms.h | 339 ++++ src/sig_stfl/lms/sig_stfl_lms_functions.c | 808 ++++++++++ src/sig_stfl/lms/sig_stfl_lms_wrap.h | 33 + src/sig_stfl/sig_stfl.c | 1434 +++++++++++++++++ src/sig_stfl/sig_stfl.h | 660 ++++++++ src/sig_stfl/xmss/CMakeLists.txt | 187 +++ src/sig_stfl/xmss/LICENSE | 22 + src/sig_stfl/xmss/external/core_hash.c | 39 + src/sig_stfl/xmss/external/core_hash.h | 24 + src/sig_stfl/xmss/external/hash.c | 154 ++ src/sig_stfl/xmss/external/hash.h | 48 + src/sig_stfl/xmss/external/hash_address.c | 67 + src/sig_stfl/xmss/external/hash_address.h | 49 + src/sig_stfl/xmss/external/namespace.h | 19 + src/sig_stfl/xmss/external/params.c | 754 +++++++++ src/sig_stfl/xmss/external/params.h | 79 + src/sig_stfl/xmss/external/utils.c | 31 + src/sig_stfl/xmss/external/utils.h | 20 + src/sig_stfl/xmss/external/wots.c | 208 +++ src/sig_stfl/xmss/external/wots.h | 41 + src/sig_stfl/xmss/external/xmss.c | 310 ++++ src/sig_stfl/xmss/external/xmss.h | 94 ++ src/sig_stfl/xmss/external/xmss_commons.c | 244 +++ src/sig_stfl/xmss/external/xmss_commons.h | 37 + src/sig_stfl/xmss/external/xmss_core.h | 86 + src/sig_stfl/xmss/external/xmss_core_fast.c | 1113 +++++++++++++ src/sig_stfl/xmss/sig_stfl_xmss.h | 590 +++++++ src/sig_stfl/xmss/sig_stfl_xmss_functions.c | 108 ++ .../xmss/sig_stfl_xmss_secret_key_functions.c | 174 ++ src/sig_stfl/xmss/sig_stfl_xmss_sha256_h10.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_sha256_h16.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_sha256_h20.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_sha512_h10.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_sha512_h16.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_sha512_h20.c | 7 + .../xmss/sig_stfl_xmss_shake128_h10.c | 7 + .../xmss/sig_stfl_xmss_shake128_h16.c | 7 + .../xmss/sig_stfl_xmss_shake128_h20.c | 7 + .../xmss/sig_stfl_xmss_shake256_h10.c | 7 + .../xmss/sig_stfl_xmss_shake256_h16.c | 7 + .../xmss/sig_stfl_xmss_shake256_h20.c | 7 + src/sig_stfl/xmss/sig_stfl_xmss_xmssmt.c | 84 + src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c | 109 ++ .../xmss/sig_stfl_xmssmt_sha256_h20_2.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h20_4.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h40_2.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h40_4.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h40_8.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h60_12.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h60_3.c | 7 + .../xmss/sig_stfl_xmssmt_sha256_h60_6.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h20_2.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h20_4.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h40_2.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h40_4.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h40_8.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h60_12.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h60_3.c | 7 + .../xmss/sig_stfl_xmssmt_shake128_h60_6.c | 7 + tests/CMakeLists.txt | 27 +- tests/KATs/sig_stfl/kats.json | 48 + tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W1.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W2.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4.rsp | 6 + .../sig_stfl/lms/LMS_SHA256_H10_W4_H5_W8.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W8.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W1.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W2.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W4.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W8.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W1.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W2.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W4.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W8.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W1.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W2.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W4.rsp | 6 + tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8.rsp | 6 + .../sig_stfl/lms/LMS_SHA256_H5_W8_H5_W8.rsp | 6 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_256.rsp | 12 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_512.rsp | 12 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_256.rsp | 12 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_512.rsp | 12 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_256.rsp | 12 + tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_512.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_10_256.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_10_512.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_16_256.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_16_512.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_20_256.rsp | 12 + .../KATs/sig_stfl/xmss/XMSS-SHAKE_20_512.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_20-2_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_20-4_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_40-2_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_40-4_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_40-8_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_60-12_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_60-3_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHA2_60-6_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_20-2_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_20-4_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_40-2_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_40-4_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_40-8_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_60-12_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_60-3_256.rsp | 12 + .../sig_stfl/xmss/XMSSMT-SHAKE_60-6_256.rsp | 12 + tests/dump_alg_info.c | 19 + tests/example_sig_stfl.c | 164 ++ tests/helpers.py | 59 +- tests/kat_sig_stfl.c | 494 ++++++ tests/test_cmdline.py | 16 + tests/test_hash.c | 64 +- tests/test_helpers.h | 1 + tests/test_kat.py | 16 + tests/test_leaks.py | 16 + tests/test_sig.c | 2 +- tests/test_sig_stfl.c | 1206 ++++++++++++++ 201 files changed, 19831 insertions(+), 202 deletions(-) create mode 100644 docs/algorithms/sig_stfl/lms.md create mode 100644 docs/algorithms/sig_stfl/lms.yml create mode 100644 docs/algorithms/sig_stfl/sig_stfl.md create mode 100644 docs/algorithms/sig_stfl/xmss.md create mode 100644 docs/algorithms/sig_stfl/xmss.yml create mode 100644 src/sig_stfl/lms/CMakeLists.txt create mode 100644 src/sig_stfl/lms/external/common_defs.h create mode 100644 src/sig_stfl/lms/external/config.h create mode 100644 src/sig_stfl/lms/external/endian.c create mode 100644 src/sig_stfl/lms/external/endian.h create mode 100644 src/sig_stfl/lms/external/hash.c create mode 100644 src/sig_stfl/lms/external/hash.h create mode 100644 src/sig_stfl/lms/external/hss.c create mode 100644 src/sig_stfl/lms/external/hss.h create mode 100644 src/sig_stfl/lms/external/hss_alloc.c create mode 100644 src/sig_stfl/lms/external/hss_aux.c create mode 100644 src/sig_stfl/lms/external/hss_aux.h create mode 100644 src/sig_stfl/lms/external/hss_common.c create mode 100644 src/sig_stfl/lms/external/hss_common.h create mode 100644 src/sig_stfl/lms/external/hss_compute.c create mode 100644 src/sig_stfl/lms/external/hss_derive.c create mode 100644 src/sig_stfl/lms/external/hss_derive.h create mode 100644 src/sig_stfl/lms/external/hss_generate.c create mode 100644 src/sig_stfl/lms/external/hss_internal.h create mode 100644 src/sig_stfl/lms/external/hss_keygen.c create mode 100644 src/sig_stfl/lms/external/hss_param.c create mode 100644 src/sig_stfl/lms/external/hss_reserve.c create mode 100644 src/sig_stfl/lms/external/hss_reserve.h create mode 100644 src/sig_stfl/lms/external/hss_sign.c create mode 100644 src/sig_stfl/lms/external/hss_sign_inc.c create mode 100644 src/sig_stfl/lms/external/hss_sign_inc.h create mode 100644 src/sig_stfl/lms/external/hss_thread.h create mode 100644 src/sig_stfl/lms/external/hss_thread_pthread.c create mode 100644 src/sig_stfl/lms/external/hss_thread_single.c create mode 100644 src/sig_stfl/lms/external/hss_verify.c create mode 100644 src/sig_stfl/lms/external/hss_verify.h create mode 100644 src/sig_stfl/lms/external/hss_verify_inc.c create mode 100644 src/sig_stfl/lms/external/hss_verify_inc.h create mode 100644 src/sig_stfl/lms/external/hss_zeroize.c create mode 100644 src/sig_stfl/lms/external/hss_zeroize.h create mode 100644 src/sig_stfl/lms/external/license.txt create mode 100644 src/sig_stfl/lms/external/lm_common.c create mode 100644 src/sig_stfl/lms/external/lm_common.h create mode 100644 src/sig_stfl/lms/external/lm_ots.h create mode 100644 src/sig_stfl/lms/external/lm_ots_common.c create mode 100644 src/sig_stfl/lms/external/lm_ots_common.h create mode 100644 src/sig_stfl/lms/external/lm_ots_sign.c create mode 100644 src/sig_stfl/lms/external/lm_ots_verify.c create mode 100644 src/sig_stfl/lms/external/lm_ots_verify.h create mode 100644 src/sig_stfl/lms/external/lm_verify.c create mode 100644 src/sig_stfl/lms/external/lm_verify.h create mode 100644 src/sig_stfl/lms/external/lms_namespace.h create mode 100644 src/sig_stfl/lms/sig_stfl_lms.c create mode 100644 src/sig_stfl/lms/sig_stfl_lms.h create mode 100644 src/sig_stfl/lms/sig_stfl_lms_functions.c create mode 100644 src/sig_stfl/lms/sig_stfl_lms_wrap.h create mode 100644 src/sig_stfl/sig_stfl.c create mode 100644 src/sig_stfl/sig_stfl.h create mode 100644 src/sig_stfl/xmss/CMakeLists.txt create mode 100644 src/sig_stfl/xmss/LICENSE create mode 100644 src/sig_stfl/xmss/external/core_hash.c create mode 100644 src/sig_stfl/xmss/external/core_hash.h create mode 100644 src/sig_stfl/xmss/external/hash.c create mode 100644 src/sig_stfl/xmss/external/hash.h create mode 100644 src/sig_stfl/xmss/external/hash_address.c create mode 100644 src/sig_stfl/xmss/external/hash_address.h create mode 100644 src/sig_stfl/xmss/external/namespace.h create mode 100644 src/sig_stfl/xmss/external/params.c create mode 100644 src/sig_stfl/xmss/external/params.h create mode 100644 src/sig_stfl/xmss/external/utils.c create mode 100644 src/sig_stfl/xmss/external/utils.h create mode 100644 src/sig_stfl/xmss/external/wots.c create mode 100644 src/sig_stfl/xmss/external/wots.h create mode 100644 src/sig_stfl/xmss/external/xmss.c create mode 100644 src/sig_stfl/xmss/external/xmss.h create mode 100644 src/sig_stfl/xmss/external/xmss_commons.c create mode 100644 src/sig_stfl/xmss/external/xmss_commons.h create mode 100644 src/sig_stfl/xmss/external/xmss_core.h create mode 100644 src/sig_stfl/xmss/external/xmss_core_fast.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss.h create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_functions.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha256_h10.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha256_h16.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha256_h20.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha512_h10.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha512_h16.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_sha512_h20.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake128_h10.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake128_h16.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake128_h20.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake256_h10.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake256_h16.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_shake256_h20.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmss_xmssmt.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_2.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_4.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_2.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_4.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_8.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_12.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_3.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_6.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_2.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_4.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_2.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_4.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_8.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_12.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_3.c create mode 100644 src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_6.c create mode 100644 tests/KATs/sig_stfl/kats.json create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W1.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W2.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4_H5_W8.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W8.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W1.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W2.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W4.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W8.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W1.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W2.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W4.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W8.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W1.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W2.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W4.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8.rsp create mode 100644 tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8_H5_W8.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_512.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-2_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-4_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-2_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-4_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-8_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-12_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-3_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-6_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-2_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-4_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-2_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-4_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-8_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-12_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-3_256.rsp create mode 100644 tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-6_256.rsp create mode 100644 tests/example_sig_stfl.c create mode 100644 tests/kat_sig_stfl.c create mode 100644 tests/test_sig_stfl.c diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index 3bdb103af7..2b0eec0c18 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -497,6 +497,91 @@ endif() ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_CONDITIONAL_END +option(OQS_ENABLE_SIG_STFL_XMSS "Enable XMSS algorithm family" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h10 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h16 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h20 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake128_h10 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake128_h16 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake128_h20 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha512_h10 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha512_h16 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha512_h20 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake256_h10 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake256_h16 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_shake256_h20 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) + + +option(OQS_ENABLE_SIG_STFL_LMS "Enable LMS algorithm family" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h25_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h25_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h25_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h25_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2_h10_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h10_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h10_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h10_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h15_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h5_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h10_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h15_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h20_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) + +option(OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN "Enable stateful key and signature generation for research and experimentation" OFF) +cmake_dependent_option(OQS_ALLOW_STFL_KEY_AND_SIG_GEN "" ON "OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN" OFF) + +if (${OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN} AND ${OQS_ENABLE_SIG_STFL_XMSS}) + set(OQS_ALLOW_XMSS_KEY_AND_SIG_GEN ON) +else() + set(OQS_ALLOW_XMSS_KEY_AND_SIG_GEN OFF) +endif() + +if (${OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN} AND ${OQS_ENABLE_SIG_STFL_LMS}) + set(OQS_ALLOW_LMS_KEY_AND_SIG_GEN ON) +else() + set(OQS_ALLOW_LMS_KEY_AND_SIG_GEN OFF) +endif() + +if(OQS_ALLOW_STFL_KEY_AND_SIG_GEN STREQUAL "ON") + message(STATUS "Experimental stateful key and signature generation is enabled. Ensure secret keys are securely stored to prevent multiple simultaneous sign operations.") +endif() + # Set XKCP (Keccak) required for Sphincs AVX2 code even if OpenSSL3 SHA3 is used: if (${OQS_ENABLE_SIG_SPHINCS} OR NOT ${OQS_USE_SHA3_OPENSSL}) set(OQS_ENABLE_SHA3_xkcp_low ON) @@ -509,4 +594,4 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") else() set(OQS_ENABLE_SHA3_xkcp_low_avx2 OFF) endif() -endif() \ No newline at end of file +endif() diff --git a/.circleci/config.yml b/.circleci/config.yml index 5c15e2dc37..a5a31cd1c0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -344,6 +344,7 @@ workflows: <<: *require_buildcheck name: arm64 PYTEST_ARGS: --numprocesses=auto --maxprocesses=10 --ignore=tests/test_kat_all.py + CMAKE_ARGS: -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON commit-to-main: when: diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 895ed7b171..930aec691f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -10,8 +10,10 @@ jobs: fail-fast: false matrix: abi: [armeabi-v7a, arm64-v8a, x86, x86_64] + stfl_opt: [ON, OFF] + steps: - name: Checkout code uses: actions/checkout@v3 - name: Build project - run: ./scripts/build-android.sh $ANDROID_NDK_HOME -a ${{ matrix.abi }} + run: ./scripts/build-android.sh $ANDROID_NDK_HOME -a ${{ matrix.abi }} -f "-DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=${{ matrix.stfl_opt }}" diff --git a/.github/workflows/apple.yml b/.github/workflows/apple.yml index 1ced2dea76..34dae893f5 100644 --- a/.github/workflows/apple.yml +++ b/.github/workflows/apple.yml @@ -10,10 +10,13 @@ jobs: fail-fast: false matrix: platform: [OS64, TVOS] + stfl_opt: [OFF, ON] steps: - name: Checkout code uses: actions/checkout@v3 - name: Generate project - run: cmake -B build --toolchain .CMake/apple.cmake -DOQS_USE_OPENSSL=OFF -DPLATFORM=${{ matrix.platform }} . + run: | + cmake -B build --toolchain .CMake/apple.cmake -DOQS_USE_OPENSSL=OFF -DPLATFORM=${{ matrix.platform }} \ + -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=${{ matrix.stfl_opt }} . - name: Build project run: cmake --build build diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index a916f3633f..bcb1e453c7 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -74,15 +74,19 @@ jobs: include: - name: alpine container: openquantumsafe/ci-alpine-amd64:latest - CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON + CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON + PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py + - name: alpine-no-stfl-key-sig-gen + container: openquantumsafe/ci-alpine-amd64:latest + CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=OFF -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: alpine-openssl-all container: openquantumsafe/ci-alpine-amd64:latest - CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_SHA2_OPENSSL=ON -DOQS_USE_SHA3_OPENSSL=ON + CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_SHA2_OPENSSL=ON -DOQS_USE_SHA3_OPENSSL=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: alpine-noopenssl container: openquantumsafe/ci-alpine-amd64:latest - CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=OFF + CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=OFF -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: focal-nistr4-openssl container: openquantumsafe/ci-ubuntu-focal-x86_64:latest @@ -98,7 +102,11 @@ jobs: PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py - name: address-sanitizer container: openquantumsafe/ci-ubuntu-focal-x86_64:latest - CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address + CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON + PYTEST_ARGS: --ignore=tests/test_distbuild.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py --numprocesses=auto --maxprocesses=10 + - name: address-sanitizer-no-stfl-key-sig-gen + container: openquantumsafe/ci-ubuntu-focal-x86_64:latest + CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=OFF -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_distbuild.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py --numprocesses=auto --maxprocesses=10 container: image: ${{ matrix.container }} @@ -137,7 +145,11 @@ jobs: include: - name: armhf ARCH: armhf - CMAKE_ARGS: -DOQS_ENABLE_SIG_SPHINCS=OFF -DOQS_USE_OPENSSL=OFF -DOQS_OPT_TARGET=generic + CMAKE_ARGS: -DOQS_ENABLE_SIG_SPHINCS=OFF -DOQS_USE_OPENSSL=OFF -DOQS_OPT_TARGET=generic -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON + PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py + - name: armhf-no-stfl-key-sig-gen + ARCH: armhf + CMAKE_ARGS: -DOQS_ENABLE_SIG_SPHINCS=OFF -DOQS_USE_OPENSSL=OFF -DOQS_OPT_TARGET=generic -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=OFF -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py # no longer supporting armel # - name: armel @@ -203,6 +215,7 @@ jobs: - macos-13 - macos-14 CMAKE_ARGS: + - -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON - -DCMAKE_C_COMPILER=gcc-13 - -DOQS_USE_OPENSSL=OFF - -DBUILD_SHARED_LIBS=ON -DOQS_DIST_BUILD=OFF diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 8b5716554f..d2552fae4c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -6,10 +6,13 @@ jobs: windows-arm64: runs-on: windows-2022 + strategy: + matrix: + stfl_opt: [ON, OFF] steps: - uses: actions/checkout@v3 - name: Generate Project - run: cmake -B build --toolchain .CMake/toolchain_windows_arm64.cmake . + run: cmake -B build --toolchain .CMake/toolchain_windows_arm64.cmake -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=${{ matrix.stfl_opt }} . - name: Build Project run: cmake --build build @@ -19,10 +22,11 @@ jobs: fail-fast: false matrix: toolchain: [.CMake/toolchain_windows_x86.cmake, .CMake/toolchain_windows_amd64.cmake] + stfl_opt: [ON, OFF] steps: - uses: actions/checkout@v3 - name: Generate Project - run: cmake -B build --toolchain ${{ matrix.toolchain }} . + run: cmake -B build --toolchain ${{ matrix.toolchain }} -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=${{ matrix.stfl_opt }} . - name: Build Project run: cmake --build build - name: Test dependencies diff --git a/.travis.yml b/.travis.yml index fd13edc301..1ebffdf879 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ jobs: compiler: gcc if: NOT branch =~ /^ghactionsonly-/ script: - - mkdir build && cd build && cmake -GNinja .. && cmake -LA .. && ninja + - mkdir build && cd build && cmake -GNinja -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_STFL_SIG_KEY_SIG_GEN=ON .. && cmake -LA .. && ninja - cd build & ninja run_tests - arch: s390x os: linux @@ -17,5 +17,5 @@ jobs: compiler: gcc if: NOT branch =~ /^ghactionsonly-/ script: - - mkdir build && cd build && cmake -GNinja .. && cmake -LA .. && ninja + - mkdir build && cd build && cmake -GNinja -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_STFL_SIG_KEY_SIG_GEN=ON .. && cmake -LA .. && ninja - cd build & ninja run_tests diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ca5543ed..5881ea3f73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,8 @@ set(PUBLIC_HEADERS ${PROJECT_SOURCE_DIR}/src/oqs.h ${PROJECT_SOURCE_DIR}/src/common/common.h ${PROJECT_SOURCE_DIR}/src/common/rand/rand.h ${PROJECT_SOURCE_DIR}/src/kem/kem.h - ${PROJECT_SOURCE_DIR}/src/sig/sig.h) + ${PROJECT_SOURCE_DIR}/src/sig/sig.h + ${PROJECT_SOURCE_DIR}/src/sig_stfl/sig_stfl.h) set(INTERNAL_HEADERS ${PROJECT_SOURCE_DIR}/src/common/aes/aes.h ${PROJECT_SOURCE_DIR}/src/common/rand/rand_nist.h @@ -196,6 +197,12 @@ if(OQS_ENABLE_SIG_SPHINCS) set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/sphincs/sig_sphincs.h) endif() ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_HEADERS_END +if(OQS_ENABLE_SIG_STFL_XMSS) + set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig_stfl/xmss/sig_stfl_xmss.h) +endif() +if(OQS_ENABLE_SIG_STFL_LMS) + set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig_stfl/lms/sig_stfl_lms.h) +endif() execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/include/oqs) execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${PUBLIC_HEADERS} ${PROJECT_BINARY_DIR}/include/oqs) execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${INTERNAL_HEADERS} ${PROJECT_BINARY_DIR}/include/oqs) diff --git a/CONFIGURE.md b/CONFIGURE.md index 6605c7f3c5..9bae9f5af2 100644 --- a/CONFIGURE.md +++ b/CONFIGURE.md @@ -8,10 +8,10 @@ The following options can be passed to CMake before the build file generation pr - [CMAKE_INSTALL_PREFIX](#CMAKE_INSTALL_PREFIX) - [OQS_ALGS_ENABLED](#OQS_ALGS_ENABLED) - [OQS_BUILD_ONLY_LIB](#OQS_BUILD_ONLY_LIB) -- [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG) +- [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG) - [OQS_MINIMAL_BUILD](#OQS_MINIMAL_BUILD) - [OQS_DIST_BUILD](#OQS_DIST_BUILD) -- [OQS_USE_CPUFEATURE_INSTRUCTIONS](OQS_USE_CPUFEATURE_INSTRUCTIONS) +- [OQS_USE_CPUFEATURE_INSTRUCTIONS](#OQS_USE_CPUFEATURE_INSTRUCTIONS) - [OQS_USE_OPENSSL](#OQS_USE_OPENSSL) - [OQS_OPT_TARGET](#OQS_OPT_TARGET) - [OQS_SPEED_USE_ARM_PMU](#OQS_SPEED_USE_ARM_PMU) @@ -42,23 +42,25 @@ Can be set to the following values: See the [CMake documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html). -## OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG +## OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG -Note: `ALG` in `OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG` should be replaced with the specific algorithm name as demonstrated below. +Note: `ALG` in `OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG` should be replaced with the specific algorithm name as demonstrated below. This can be set to `ON` or `OFF`, and is `ON` by default. When `OFF`, `ALG` and its code are excluded from the build process. When `ON`, made available are additional options whereby individual variants of `ALG` can be excluded from the build process. For example: if `OQS_ENABLE_KEM_BIKE` is set to `ON`, the options `OQS_ENABLE_KEM_bike_l1`, `OQS_ENABLE_KEM_bike_l3`, and `OQS_ENABLE_KEM_bike_l5` are made available (and are set to be `ON` by default). +To enable `XMSS` stateful signature, set `OQS_ENABLE_SIG_STFL_XMSS` to `ON`, the options `OQS_ENABLE_SIG_STFL_xmss_sha256_h10` and its variants are also set to be `ON` by default. Similarly, `LMS` stateful signature family can also be enabled by setting `OQS_ENABLE_SIG_STFL_LMS` to `ON`. + For a full list of such options and their default values, consult [.CMake/alg_support.cmake](https://github.com/open-quantum-safe/liboqs/blob/master/.CMake/alg_support.cmake). **Default**: Unset. ## OQS_ALGS_ENABLED -Selects algorithm set enabled. Possible values are "STD" selecting all algorithms standardized by NIST; "NIST_R4" selecting all algorithms evaluated in round 4 of the NIST PQC competition; "All" (or any other value) selecting all algorithms integrated into liboqs. Parameter setting "STD" minimizes library size but may require re-running code generator scripts in projects integrating `liboqs`; e.g., [oqs-provider](https://github.com/open-quantum-safe/oqs-provider) and [oqs-boringssl](https://github.com/open-quantum-safe/boringssl). +A selected algorithm set is enabled. Possible values are "STD" selecting all algorithms standardized by NIST; "NIST_R4" selecting all algorithms evaluated in round 4 of the NIST PQC competition; "All" (or any other value) selecting all algorithms integrated into liboqs. Parameter setting "STD" minimizes library size but may require re-running code generator scripts in projects integrating `liboqs`; e.g., [oqs-provider](https://github.com/open-quantum-safe/oqs-provider) and [oqs-boringssl](https://github.com/open-quantum-safe/boringssl). -**Attention**: If you use any predefined value (`STD` or `NIST_R4` as of now) for this variable, the values added via [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG) variables will be ignored. +**Attention**: If you use any predefined value (`STD` or `NIST_R4` as of now) for this variable, the values added via [OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG](#OQS_ENABLE_KEM_ALG/OQS_ENABLE_SIG_ALG/OQS_ENABLE_SIG_STFL_ALG) variables will be ignored. **Default**: `All`. @@ -70,9 +72,9 @@ Can be `ON` or `OFF`. When `ON`, only liboqs is built, and all the targets: `run ## OQS_MINIMAL_BUILD -If set, this defines a semicolon deliminated list of algorithms to be contained in a minimal build of `liboqs`: Only algorithms explicitly set here are included in a build: For example running `cmake -DOQS_MINIMAL_BUILD="KEM_kyber_768;SIG_dilithium_3" ..` will build a minimum-size `liboqs` library only containing support for Kyber768 and Dilithium3. +If set, this defines a semicolon-delimited list of algorithms to be contained in a minimal build of `liboqs`: Only algorithms explicitly set here are included in a build: For example running `cmake -DOQS_MINIMAL_BUILD="KEM_kyber_768;SIG_dilithium_3" ..` will build a minimum-size `liboqs` library only containing support for Kyber768 and Dilithium3. -The full list of identifiers that can set are listed [here for KEM algorithms](https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/kem.h#L34) and [here for Signature algorithms](https://github.com/open-quantum-safe/liboqs/blob/f3caccff9e6225e7c50ca27f5ee6e58b7bc74188/src/sig/sig.h#L34). Default setting is empty, thus including all [supported algorithms](https://github.com/open-quantum-safe/liboqs#supported-algorithms) in the build. +The full list of identifiers that can be set is listed [here for KEM algorithms](https://github.com/open-quantum-safe/liboqs/blob/main/src/kem/kem.h#L34) and [here for Signature algorithms](https://github.com/open-quantum-safe/liboqs/blob/f3caccff9e6225e7c50ca27f5ee6e58b7bc74188/src/sig/sig.h#L34). The default setting is empty, thus including all [supported algorithms](https://github.com/open-quantum-safe/liboqs#supported-algorithms) in the build. **Default**: Unset. @@ -92,13 +94,13 @@ When built for use on a single machine, the library will only include the best a Note: `CPUFEATURE` in `OQS_USE_CPUFEATURE_INSTRUCTIONS` should be replaced with the specific CPU feature as noted below. -These can be set to `ON` or `OFF` and take an effect if liboqs is built for use on a single machine. By default, the CPU features are automatically determined and set to `ON` or `OFF` based on the CPU features available on the build system. The default values can be overridden by providing CMake build options. The available options on x86-64 are: `OQS_USE_ADX_INSTRUCTIONS`, `OQS_USE_AES_INSTRUCTIONS`, `OQS_USE_AVX_INSTRUCTIONS`, `OQS_USE_AVX2_INSTRUCTIONS`, `OQS_USE_AVX512_INSTRUCTIONS`, `OQS_USE_BMI1_INSTRUCTIONS`, `OQS_USE_BMI2_INSTRUCTIONS`, `OQS_USE_PCLMULQDQ_INSTRUCTIONS`, `OQS_USE_VPCLMULQDQ_INSTRUCTIONS`, `OQS_USE_POPCNT_INSTRUCTIONS`, `OQS_USE_SSE_INSTRUCTIONS`, `OQS_USE_SSE2_INSTRUCTIONS` and `OQS_USE_SSE3_INSTRUCTIONS`. The available options on ARM64v8 are `OQS_USE_ARM_AES_INSTRUCTIONS`, `OQS_USE_ARM_SHA2_INSTRUCTIONS`, `OQS_USE_ARM_SHA3_INSTRUCTIONS` and `OQS_USE_ARM_NEON_INSTRUCTIONS`. +These can be set to `ON` or `OFF` and take effect if liboqs is built for use on a single machine. By default, the CPU features are automatically determined and set to `ON` or `OFF` based on the CPU features available on the build system. The default values can be overridden by providing CMake build options. The available options on x86-64 are: `OQS_USE_ADX_INSTRUCTIONS`, `OQS_USE_AES_INSTRUCTIONS`, `OQS_USE_AVX_INSTRUCTIONS`, `OQS_USE_AVX2_INSTRUCTIONS`, `OQS_USE_AVX512_INSTRUCTIONS`, `OQS_USE_BMI1_INSTRUCTIONS`, `OQS_USE_BMI2_INSTRUCTIONS`, `OQS_USE_PCLMULQDQ_INSTRUCTIONS`, `OQS_USE_VPCLMULQDQ_INSTRUCTIONS`, `OQS_USE_POPCNT_INSTRUCTIONS`, `OQS_USE_SSE_INSTRUCTIONS`, `OQS_USE_SSE2_INSTRUCTIONS` and `OQS_USE_SSE3_INSTRUCTIONS`. The available options on ARM64v8 are `OQS_USE_ARM_AES_INSTRUCTIONS`, `OQS_USE_ARM_SHA2_INSTRUCTIONS`, `OQS_USE_ARM_SHA3_INSTRUCTIONS` and `OQS_USE_ARM_NEON_INSTRUCTIONS`. **Default**: Options valid on the build machine. ## OQS_USE_OPENSSL -In order to save size and limit the amount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option. +To save size and limit the amount of different cryptographic code bases, it is possible to use OpenSSL as a crypto code provider by setting this configuration option. This can be set to `ON` or `OFF`. When `ON`, the additional options `OQS_USE_AES_OPENSSL`, `OQS_USE_SHA2_OPENSSL`, and `OQS_USE_SHA3_OPENSSL` are made available to control whether liboqs uses OpenSSL's AES, SHA-2, and SHA-3 implementations. @@ -107,7 +109,7 @@ By default, - `OQS_USE_SHA2_OPENSSL` is `ON` - `OQS_USE_SHA3_OPENSSL` is `OFF`. -These default choices have been made in order to optimize the default performance of all algorithms. Changing them implies performance penalties. +These default choices have been made to optimize the default performance of all algorithms. Changing them implies performance penalties. When `OQS_USE_OPENSSL` is `ON`, CMake also scans the filesystem to find the minimum version of OpenSSL required by liboqs (which happens to be 1.1.1). The [OPENSSL_ROOT_DIR](https://cmake.org/cmake/help/latest/module/FindOpenSSL.html) option can be set to aid CMake in its search. @@ -119,6 +121,27 @@ Dynamically load OpenSSL through `dlopen`. When using liboqs from other cryptogr Only has an effect if the system supports `dlopen` and ELF binary format, such as Linux or BSD family. +## Stateful Hash Based Signatures + +XMSS and LMS are the two supported Hash-Based Signatures schemes. +`OQS_ENABLE_SIG_STFL_XMSS` and `OQS_ENABLE_SIG_STFL_LMS` control these algorithms, which are disabled by default. +A third variable, `OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN`, also controls the ability to generate keys and signatures. This is also disabled by default. +Each of these variables can be set to `ON` or `OFF`. +When all three are `ON`, stateful signatures are fully functional and can generate key pairs, sign data, and verify signatures. +If `OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN` is `OFF` signature verification is the only functional operation. + +Standards bodies, such as NIST, recommend that key and signature generation only by done in hardware in order to best enforce the one-time use of secret keys. +Keys stored in a file system are extremely susceptible to simultaneous use. +When enabled in this library a warning message will be generated by the config process. +The name of the configuration variable has been chosen to make every user of this feature aware of its security risks. +The OQS team explicitly discourages enabling this variable and reserves the right to remove this feature in future releases if its use causes actual harm. +It remains present as long as it is responsibly used as per the stated warnings. + +By default, +- `OQS_ENABLE_SIG_STFL_XMSS` is `OFF` +- `OQS_ENABLE_SIG_STFL_LMS` is `OFF` +- `OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN` is `OFF`. + **Default**: `OFF`. ## OQS_OPT_TARGET @@ -133,7 +156,7 @@ An optimization target. Only has an effect if the compiler is GCC or Clang and ` Can be `ON` or `OFF`. When `ON`, the benchmarking script will try to use the ARMv8 Performance Monitoring Unit (PMU). This will make cycle counts on ARMv8 platforms significantly more accurate. -In order to use this option, user mode access to the PMU must be enabled via a kernel module. If user mode access is not enabled via kernel module, benchmarking will throw an `Illegal Instruction` error. A kernel module that has been found to work on several platforms can be found [here for linux](https://github.com/mupq/pqax#enable-access-to-performance-counters). Follow the instructions there (i.e., clone the repository, `cd enable_ccr` and `make install`) to load the kernel module, after which benchmarking should work. Superuser permissions are required. Linux header files must also be installed on your platform, which may not be present by default. +In order to use this option, user mode access to the PMU must be enabled via a kernel module. If user mode access is not enabled via the kernel module, benchmarking will throw an `Illegal Instruction` error. A kernel module that has been found to work on several platforms can be found [here for Linux](https://github.com/mupq/pqax#enable-access-to-performance-counters). Follow the instructions there (i.e., clone the repository, `cd enable_ccr` and `make install`) to load the kernel module, after which benchmarking should work. Superuser permissions are required. Linux header files must also be installed on your platform, which may not be present by default. Note that this option is not known to work on Apple M1 chips. @@ -141,7 +164,7 @@ Note that this option is not known to work on Apple M1 chips. ## USE_SANITIZER -This has effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) is `Debug`. Then, it can be set to: +This has an effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) is `Debug`. Then, it can be set to: - `Address`: This enables Clang's `AddressSanitizer` - `Memory`: This enables Clang's `MemorySanitizer` @@ -156,13 +179,13 @@ This has effect when the compiler is Clang and when [CMAKE_BUILD_TYPE](#CMAKE_BU This is used in conjunction with `tests/test_constant_time.py` to use Valgrind to look for instances of secret-dependent control flow. liboqs must also be compiled with [CMAKE_BUILD_TYPE](#CMAKE_BUILD_TYPE) set to `Debug`. -See the documentation in [`tests/test_constant_time.py`](https://github.com/open-quantum-safe/liboqs/blob/main/tests/test_constant_time.py) for more information on usage. +See the documentation in [`tests/test_constant_time.py`](https://github.com/open-quantum-safe/liboqs/blob/main/tests/test_constant_time.py) for more usage information. **Default**: `OFF`. ## OQS_STRICT_WARNINGS -Can be `ON` or `OFF`. When `ON`, all compiler warnings are enabled and treated as errors. This setting is recommended to be enabled prior to submission of a Pull Request as CI runs with this setting active. When `OFF`, significantly fewer compiler warnings are enabled such as to avoid undue build errors triggered by (future) compiler warning features/unknown at development time of this library. +Can be `ON` or `OFF`. When `ON`, all compiler warnings are enabled and treated as errors. This setting is recommended to be enabled prior to submission of a Pull Request as CI runs with this setting active. When `OFF`, significantly fewer compiler warnings are enabled such as to avoid undue build errors triggered by (future) compiler warning features/unknown at the development time of this library. **Default**: `OFF`. diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 918394b8c4..83d9337ca5 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -34,5 +34,6 @@ Karolin Varner Sebastian Verschoor (University of Waterloo) Thom Wiggers (Radboud University) Dindyal Jeevesh Rishi (University of Mauritius / cyberstorm.mu) +Duc Tri Nguyen See additional contributors at https://github.com/open-quantum-safe/liboqs/graphs/contributors diff --git a/README.md b/README.md index 53ef332e24..b47b82d660 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ All names other than `ML-KEM` and `ML-DSA` are subject to change. `liboqs` makes - **SPHINCS+-SHA2**: SPHINCS+-SHA2-128f-simple, SPHINCS+-SHA2-128s-simple, SPHINCS+-SHA2-192f-simple, SPHINCS+-SHA2-192s-simple, SPHINCS+-SHA2-256f-simple, SPHINCS+-SHA2-256s-simple - **SPHINCS+-SHAKE**: SPHINCS+-SHAKE-128f-simple, SPHINCS+-SHAKE-128s-simple, SPHINCS+-SHAKE-192f-simple, SPHINCS+-SHAKE-192s-simple, SPHINCS+-SHAKE-256f-simple, SPHINCS+-SHAKE-256s-simple +- **XMSS**: XMSS-SHA2_10_256, XMSS-SHA2_16_256, XMSS-SHA2_20_256, XMSS-SHAKE_10_256, XMSS-SHAKE_16_256, XMSS-SHAKE_20_256, XMSS-SHA2_10_512, XMSS-SHA2_16_512, XMSS-SHA2_20_512, XMSS-SHAKE_10_512, XMSS-SHAKE_16_512, XMSS-SHAKE_20_512, XMSSMT-SHA2_20/2_256, XMSSMT-SHA2_20/4_256, XMSSMT-SHA2_40/2_256, XMSSMT-SHA2_40/4_256, XMSSMT-SHA2_40/8_256, XMSSMT-SHA2_60/3_256, XMSSMT-SHA2_60/6_256, XMSSMT-SHA2_60/12_256, XMSSMT-SHAKE_20/2_256, XMSSMT-SHAKE_20/4_256, XMSSMT-SHAKE_40/2_256, XMSSMT-SHAKE_40/4_256, XMSSMT-SHAKE_40/8_256, XMSSMT-SHAKE_60/3_256, XMSSMT-SHAKE_60/6_256, XMSSMT-SHAKE_60/12_256 +- **LMS**: LMS_SHA256_H5_W1, LMS_SHA256_H5_W2, LMS_SHA256_H5_W4, LMS_SHA256_H5_W8, LMS_SHA256_H10_W1, LMS_SHA256_H10_W2, LMS_SHA256_H10_W4, LMS_SHA256_H10_W8, LMS_SHA256_H15_W1, LMS_SHA256_H15_W2, LMS_SHA256_H15_W4, LMS_SHA256_H15_W8, LMS_SHA256_H20_W1, LMS_SHA256_H20_W2, LMS_SHA256_H20_W4, LMS_SHA256_H20_W8, LMS_SHA256_H25_W1, LMS_SHA256_H25_W2, LMS_SHA256_H25_W4, LMS_SHA256_H25_W8, LMS_SHA256_H5_W8_H5_W8, LMS_SHA256_H10_W4_H5_W8, LMS_SHA256_H10_W8_H5_W8, LMS_SHA256_H10_W2_H10_W2, LMS_SHA256_H10_W4_H10_W4, LMS_SHA256_H10_W8_H10_W8, LMS_SHA256_H15_W8_H5_W8, LMS_SHA256_H15_W8_H10_W8, LMS_SHA256_H15_W8_H15_W8, LMS_SHA256_H20_W8_H5_W8, LMS_SHA256_H20_W8_H10_W8, LMS_SHA256_H20_W8_H15_W8, LMS_SHA256_H20_W8_H20_W8 Note that for algorithms marked with a dagger (†), liboqs contains at least one implementation that uses a large amount of stack space; this may cause failures when run in threads or in constrained environments. For more information, consult the algorithm information sheets in the [docs/algorithms](https://github.com/open-quantum-safe/liboqs/tree/main/docs/algorithms) folder. @@ -123,15 +125,18 @@ The following instructions assume we are in `build`. 3. By default the main build result is `lib/liboqs.a`, a static library. If you want to build a shared/dynamic library, append [`-DBUILD_SHARED_LIBS=ON`](CONFIGURE.md#build_shared_libs) to the `cmake -GNinja ..` command above and the result will be `lib/liboqs.so|dylib|dll`. The public headers are located in the `include` directory. There are also a variety of programs built under the `tests` directory: - `test_kem`: Simple test harness for key encapsulation mechanisms - - `test_sig`: Simple test harness for key signature schemes + - `test_sig`: Simple test harness for signature schemes + - `test_sig_stfl`: Simple test harness for stateful signature schemes - `test_kem_mem`: Simple test harness for checking memory consumption of key encapsulation mechanisms - - `test_sig_mem`: Simple test harness for checking memory consumption of key signature schemes + - `test_sig_mem`: Simple test harness for checking memory consumption of signature schemes - `kat_kem`: Program that generates known answer test (KAT) values for key encapsulation mechanisms using the same procedure as the NIST submission requirements, for checking against submitted KAT values using `tests/test_kat.py` - `kat_sig`: Program that generates known answer test (KAT) values for signature schemes using the same procedure as the NIST submission requirements, for checking against submitted KAT values using `tests/test_kat.py` + - `kat_sig_stfl`: Program for checking results against submitted KAT values using `tests/test_kat.py` - `speed_kem`: Benchmarking program for key encapsulation mechanisms; see `./speed_kem --help` for usage instructions - `speed_sig`: Benchmarking program for signature mechanisms; see `./speed_sig --help` for usage instructions - `example_kem`: Minimal runnable example showing the usage of the KEM API - `example_sig`: Minimal runnable example showing the usage of the signature API + - `example_sig_stfl`: Minimal runnable example showing the usage of the stateful signature API - `test_aes`, `test_sha3`: Simple test harnesses for crypto sub-components - `test_portability`: Simple test harnesses for checking cross-CPU code portability; requires presence of `qemu`; proper operation validated only on Ubuntu diff --git a/docs/algorithms/sig_stfl/lms.md b/docs/algorithms/sig_stfl/lms.md new file mode 100644 index 0000000000..d436b6b616 --- /dev/null +++ b/docs/algorithms/sig_stfl/lms.md @@ -0,0 +1,50 @@ +# LMS + +- **Algorithm type**: Digital signature scheme. +- **Main cryptographic assumption**: hash-based signatures. +- **Principal submitters**: Scott Fluhrer. +- **Auxiliary submitters**: C Martin, Maurice Hieronymus. +- **Authors' website**: https://www.rfc-editor.org/info/rfc8554 +- **Specification version**: None. +- **Primary Source**: + - **Source**: https://github.com/cisco/hash-sigs + - **Implementation license (SPDX-Identifier)**: MIT + + +## Parameter set summary + +| Parameter set | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | +|:------------------------:|:-----------------|:---------------------|--------------------------:|--------------------------:|-------------------------:| +| LMS_SHA256_H5_W1 | | | 60 | 64 | 8688 | +| LMS_SHA256_H5_W2 | | | 60 | 64 | 4464 | +| LMS_SHA256_H5_W4 | | | 60 | 64 | 2352 | +| LMS_SHA256_H5_W8 | | | 60 | 64 | 1296 | +| LMS_SHA256_H10_W1 | | | 60 | 64 | 8848 | +| LMS_SHA256_H10_W2 | | | 60 | 64 | 4624 | +| LMS_SHA256_H10_W4 | | | 60 | 64 | 2512 | +| LMS_SHA256_H10_W8 | | | 60 | 64 | 1456 | +| LMS_SHA256_H15_W1 | | | 60 | 64 | 9008 | +| LMS_SHA256_H15_W2 | | | 60 | 64 | 4784 | +| LMS_SHA256_H15_W4 | | | 60 | 64 | 2672 | +| LMS_SHA256_H15_W8 | | | 60 | 64 | 1616 | +| LMS_SHA256_H20_W1 | | | 60 | 64 | 9168 | +| LMS_SHA256_H20_W2 | | | 60 | 64 | 4944 | +| LMS_SHA256_H20_W4 | | | 60 | 64 | 2832 | +| LMS_SHA256_H20_W8 | | | 60 | 64 | 1776 | +| LMS_SHA256_H25_W1 | | | 60 | 64 | 9328 | +| LMS_SHA256_H25_W2 | | | 60 | 64 | 5104 | +| LMS_SHA256_H25_W4 | | | 60 | 64 | 2992 | +| LMS_SHA256_H25_W8 | | | 60 | 64 | 1936 | +| LMS_SHA256_H5_W8_H5_W8 | | | 60 | 64 | 2644 | +| LMS_SHA256_H10_W4_H5_W8 | | | 60 | 64 | 2804 | +| LMS_SHA256_H10_W8_H5_W8 | | | 60 | 64 | 3860 | +| LMS_SHA256_H10_W2_H10_W2 | | | 60 | 64 | 9300 | +| LMS_SHA256_H10_W4_H10_W4 | | | 60 | 64 | 5076 | +| LMS_SHA256_H10_W8_H10_W8 | | | 60 | 64 | 2964 | +| LMS_SHA256_H15_W8_H5_W8 | | | 60 | 64 | 2964 | +| LMS_SHA256_H15_W8_H10_W8 | | | 60 | 64 | 3124 | +| LMS_SHA256_H15_W8_H15_W8 | | | 60 | 64 | 3284 | +| LMS_SHA256_H20_W8_H5_W8 | | | 60 | 64 | 3124 | +| LMS_SHA256_H20_W8_H10_W8 | | | 60 | 64 | 3284 | +| LMS_SHA256_H20_W8_H15_W8 | | | 60 | 64 | 3444 | +| LMS_SHA256_H20_W8_H20_W8 | | | 60 | 64 | 3604 | diff --git a/docs/algorithms/sig_stfl/lms.yml b/docs/algorithms/sig_stfl/lms.yml new file mode 100644 index 0000000000..9293ff70c3 --- /dev/null +++ b/docs/algorithms/sig_stfl/lms.yml @@ -0,0 +1,216 @@ +name: LMS +type: stateful signature +principal-submitters: +- Scott Fluhrer +auxiliary-submitters: +- C Martin +- Maurice Hieronymus + +crypto-assumption: hash-based signatures +website: https://www.rfc-editor.org/info/rfc8554 +nist-round: +spec-version: +spdx-license-identifier: +primary-upstream: + source: https://github.com/cisco/hash-sigs + spdx-license-identifier: MIT + upstream-ancestors: +parameter-sets: +- name: LMS_SHA256_H5_W1 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 8688 +- name: LMS_SHA256_H5_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 4464 +- name: LMS_SHA256_H5_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2352 +- name: LMS_SHA256_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 1296 +- name: LMS_SHA256_H10_W1 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 8848 +- name: LMS_SHA256_H10_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 4624 +- name: LMS_SHA256_H10_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2512 +- name: LMS_SHA256_H10_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 1456 +- name: LMS_SHA256_H15_W1 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 9008 +- name: LMS_SHA256_H15_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 4784 +- name: LMS_SHA256_H15_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2672 +- name: LMS_SHA256_H15_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 1616 +- name: LMS_SHA256_H20_W1 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 9168 +- name: LMS_SHA256_H20_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 4944 +- name: LMS_SHA256_H20_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2832 +- name: LMS_SHA256_H20_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 1776 +- name: LMS_SHA256_H25_W1 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 9328 +- name: LMS_SHA256_H25_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 5104 +- name: LMS_SHA256_H25_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2992 +- name: LMS_SHA256_H25_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 1936 +- name: LMS_SHA256_H5_W8_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2644 +- name: LMS_SHA256_H10_W4_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2804 +- name: LMS_SHA256_H10_W8_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3860 +- name: LMS_SHA256_H10_W2_H10_W2 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 9300 +- name: LMS_SHA256_H10_W4_H10_W4 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 5076 +- name: LMS_SHA256_H10_W8_H10_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2964 +- name: LMS_SHA256_H15_W8_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 2964 +- name: LMS_SHA256_H15_W8_H10_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3124 +- name: LMS_SHA256_H15_W8_H15_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3284 +- name: LMS_SHA256_H20_W8_H5_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3124 +- name: LMS_SHA256_H20_W8_H10_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3284 +- name: LMS_SHA256_H20_W8_H15_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3444 +- name: LMS_SHA256_H20_W8_H20_W8 + claimed-nist-level: + claimed-security: + length-public-key: 60 + length-secret-key: 64 + length-signature: 3604 diff --git a/docs/algorithms/sig_stfl/sig_stfl.md b/docs/algorithms/sig_stfl/sig_stfl.md new file mode 100644 index 0000000000..dfd0403066 --- /dev/null +++ b/docs/algorithms/sig_stfl/sig_stfl.md @@ -0,0 +1,29 @@ + +# **Stateful Hash Based Signatures** + +The security of hash based signatures (HBS) is based on the underlying hash functions on which they are built. +NIST recommendation is that they are suitable for near term use to mitigate against attacks mounted by quantum computers. +While not a general purpose solution, they are useful means to authenticate boot or firmware images. + +**General** + +This package provides full support for a variety of variants for XMSS and LMS. +Key generation, signature generation, and signature verification. +Security of HBS also depends on the management of the state of the secret key. Secret keys can only used once to generate a signature. +Multiple signing with same key can reveal that key to an attacker. +Because of this, NIST recommends that key and signature generation be done in hardware security modules. +Having said that, this library is fully functional for research purposes. Secret keys are incremented after each sign operation. +However, secure storage and lifecycle management of the secret keys are left to applications using this feature. +Secret key storage is easily done by supplying a callback function to the library. This callback is invoked to store the secret key. + + +**Key State Management** + +Application writers have to supply callback functions to store and update secret keys. +After a sign operation the secret key index is advanced and stored. This ensures one-time use of the key. +Signing operations will fail without this callback set because the private key cannot be advanced (to prevent reuse). + +Stateful keys can generate a finite number of signatures. A counter tracks the limit when the key is created and is decremented after each signature is generated. +When the counter is down to 0, signature generation fails. Applications can query the remaining count via an API. + + diff --git a/docs/algorithms/sig_stfl/xmss.md b/docs/algorithms/sig_stfl/xmss.md new file mode 100644 index 0000000000..446adcd8e1 --- /dev/null +++ b/docs/algorithms/sig_stfl/xmss.md @@ -0,0 +1,44 @@ +# XMSS + +- **Algorithm type**: Digital signature scheme. +- **Main cryptographic assumption**: hash-based signatures. +- **Principal submitters**: Joost Rijneveld, A. Huelsing, David Cooper, Bas Westerbaan. +- **Authors' website**: https://www.rfc-editor.org/info/rfc8391 +- **Specification version**: None. +- **Primary Source**: + - **Source**: https://github.com/XMSS/xmss-reference + - **Implementation license (SPDX-Identifier)**: (Apache-2.0 OR MIT) AND CC0-1.0 + + +## Parameter set summary + +| Parameter set | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | +|:----------------------:|:-----------------|:---------------------|--------------------------:|--------------------------:|-------------------------:| +| XMSS-SHA2_10_256 | | | 64 | 1373 | 2500 | +| XMSS-SHA2_16_256 | | | 64 | 2093 | 2692 | +| XMSS-SHA2_20_256 | | | 64 | 2573 | 2820 | +| XMSS-SHAKE_10_256 | | | 64 | 1373 | 2500 | +| XMSS-SHAKE_16_256 | | | 64 | 2093 | 2692 | +| XMSS-SHAKE_20_256 | | | 64 | 2573 | 2820 | +| XMSS-SHA2_10_512 | | | 128 | 2653 | 9092 | +| XMSS-SHA2_16_512 | | | 128 | 4045 | 9476 | +| XMSS-SHA2_20_512 | | | 128 | 2653 | 9732 | +| XMSS-SHAKE_10_512 | | | 128 | 2653 | 9092 | +| XMSS-SHAKE_16_512 | | | 128 | 4045 | 9476 | +| XMSS-SHAKE_20_512 | | | 128 | 4973 | 9732 | +| XMSSMT-SHA2_20/2_256 | | | 64 | 5998 | 4963 | +| XMSSMT-SHA2_20/4_256 | | | 64 | 10938 | 9251 | +| XMSSMT-SHA2_40/2_256 | | | 64 | 9600 | 5605 | +| XMSSMT-SHA2_40/4_256 | | | 64 | 15252 | 9893 | +| XMSSMT-SHA2_40/8_256 | | | 64 | 24516 | 18469 | +| XMSSMT-SHA2_60/3_256 | | | 64 | 16629 | 8392 | +| XMSSMT-SHA2_60/6_256 | | | 64 | 24507 | 14824 | +| XMSSMT-SHA2_60/12_256 | | | 64 | 38095 | 27688 | +| XMSSMT-SHAKE_20/2_256 | | | 64 | 5998 | 4963 | +| XMSSMT-SHAKE_20/4_256 | | | 64 | 10938 | 9251 | +| XMSSMT-SHAKE_40/2_256 | | | 64 | 9600 | 5605 | +| XMSSMT-SHAKE_40/4_256 | | | 64 | 15252 | 9893 | +| XMSSMT-SHAKE_40/8_256 | | | 64 | 24516 | 18469 | +| XMSSMT-SHAKE_60/3_256 | | | 64 | 24516 | 8392 | +| XMSSMT-SHAKE_60/6_256 | | | 64 | 24507 | 14824 | +| XMSSMT-SHAKE_60/12_256 | | | 64 | 38095 | 27688 | diff --git a/docs/algorithms/sig_stfl/xmss.yml b/docs/algorithms/sig_stfl/xmss.yml new file mode 100644 index 0000000000..dccefa12f9 --- /dev/null +++ b/docs/algorithms/sig_stfl/xmss.yml @@ -0,0 +1,187 @@ +name: XMSS +type: stateful signature +principal-submitters: +- Joost Rijneveld +- A. Huelsing +- David Cooper +- Bas Westerbaan +auxiliary-submitters: + +crypto-assumption: hash-based signatures +website: https://www.rfc-editor.org/info/rfc8391 +nist-round: +spec-version: +spdx-license-identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +primary-upstream: + source: https://github.com/XMSS/xmss-reference + spdx-license-identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + upstream-ancestors: +parameter-sets: +- name: XMSS-SHA2_10_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 1373 + length-signature: 2500 +- name: XMSS-SHA2_16_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 2093 + length-signature: 2692 +- name: XMSS-SHA2_20_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 2573 + length-signature: 2820 +- name: XMSS-SHAKE_10_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 1373 + length-signature: 2500 +- name: XMSS-SHAKE_16_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 2093 + length-signature: 2692 +- name: XMSS-SHAKE_20_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 2573 + length-signature: 2820 +- name: XMSS-SHA2_10_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 2653 + length-signature: 9092 +- name: XMSS-SHA2_16_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 4045 + length-signature: 9476 +- name: XMSS-SHA2_20_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 2653 + length-signature: 9732 +- name: XMSS-SHAKE_10_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 2653 + length-signature: 9092 +- name: XMSS-SHAKE_16_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 4045 + length-signature: 9476 +- name: XMSS-SHAKE_20_512 + claimed-nist-level: + claimed-security: + length-public-key: 128 + length-secret-key: 4973 + length-signature: 9732 +- name: XMSSMT-SHA2_20/2_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 5998 + length-signature: 4963 +- name: XMSSMT-SHA2_20/4_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 10938 + length-signature: 9251 +- name: XMSSMT-SHA2_40/2_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 9600 + length-signature: 5605 +- name: XMSSMT-SHA2_40/4_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 15252 + length-signature: 9893 +- name: XMSSMT-SHA2_40/8_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 24516 + length-signature: 18469 +- name: XMSSMT-SHA2_60/3_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 16629 + length-signature: 8392 +- name: XMSSMT-SHA2_60/6_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 24507 + length-signature: 14824 +- name: XMSSMT-SHA2_60/12_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 38095 + length-signature: 27688 +- name: XMSSMT-SHAKE_20/2_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 5998 + length-signature: 4963 +- name: XMSSMT-SHAKE_20/4_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 10938 + length-signature: 9251 +- name: XMSSMT-SHAKE_40/2_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 9600 + length-signature: 5605 +- name: XMSSMT-SHAKE_40/4_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 15252 + length-signature: 9893 +- name: XMSSMT-SHAKE_40/8_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 24516 + length-signature: 18469 +- name: XMSSMT-SHAKE_60/3_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 24516 + length-signature: 8392 +- name: XMSSMT-SHAKE_60/6_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 24507 + length-signature: 14824 +- name: XMSSMT-SHAKE_60/12_256 + claimed-nist-level: + claimed-security: + length-public-key: 64 + length-secret-key: 38095 + length-signature: 27688 diff --git a/scripts/build-android.sh b/scripts/build-android.sh index 574c8d8ea4..54a03d21b3 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -6,12 +6,13 @@ set -e show_help() { echo "" - echo " Usage: ./build-android -a [abi] -b [build-directory] -s [sdk-version]" + echo " Usage: ./build-android -a [abi] -b [build-directory] -s [sdk-version] -f [extra-cmake-flags]" echo " ndk-dir: the directory of the Android NDK (required)" echo " abi: the Android ABI to target for the build" echo " build-directory: the directory in which to build the project" echo " sdk-version: the minimum Android SDK version to target" + echo " extra-cmake-flags: extra flags to use for CMake configuration" echo "" exit 0 } @@ -52,12 +53,13 @@ MINSDKVERSION=21 BUILDDIR="build" OPTIND=2 -while getopts "a:s:b:" flag +while getopts "a:s:b:f:" flag do case $flag in a) ABI=$OPTARG;; s) MINSDKVERSION=$OPTARG;; b) BUILDDIR=$OPTARG;; + f) EXTRAFLAGS="$OPTARG";; *) exit 1 esac done @@ -107,7 +109,8 @@ cmake .. -DOQS_USE_OPENSSL=OFF \ -DBUILD_SHARED_LIBS=ON \ -DCMAKE_TOOLCHAIN_FILE="$NDK"/build/cmake/android.toolchain.cmake \ -DANDROID_ABI="$ABI" \ - -DANDROID_NATIVE_API_LEVEL="$MINSDKVERSION" + -DANDROID_NATIVE_API_LEVEL="$MINSDKVERSION" \ + $EXTRAFLAGS cmake --build ./ # Provide rudimentary information following build diff --git a/scripts/copy_from_upstream/copy_from_upstream.py b/scripts/copy_from_upstream/copy_from_upstream.py index 0db38f54bf..9c4f8f2232 100755 --- a/scripts/copy_from_upstream/copy_from_upstream.py +++ b/scripts/copy_from_upstream/copy_from_upstream.py @@ -642,7 +642,7 @@ def verify_from_upstream(): '{}_{}_{}'.format(impl['upstream']['name'], scheme['pqclean_scheme'], impl)) verifydir = os.path.join(basedir, 'src', family['type'], family['name'], '{}_{}_{}'.format(impl['upstream']['name'], scheme['pqclean_scheme'], impl)) - if not os.path.isdir(oqsdir) and os.path.isdir(erifydir): + if not os.path.isdir(oqsdir) and os.path.isdir(verifydir): print('Available implementation in upstream that isn\'t integrated into LIBOQS: {}_{}_{}'.format(impl['upstream']['name'], scheme['pqclean_scheme'], impl)) else: diff --git a/scripts/update_docs_from_yaml.py b/scripts/update_docs_from_yaml.py index ef152d376a..a07a81c2d0 100644 --- a/scripts/update_docs_from_yaml.py +++ b/scripts/update_docs_from_yaml.py @@ -17,6 +17,7 @@ def file_get_contents(filename, encoding=None): kem_yamls = [] sig_yamls = [] +sig_stfl_yamls = [] ######################################## # Update the KEM markdown documentation. @@ -269,6 +270,66 @@ def do_it(liboqs_root): out_md.write('- **Large Stack Usage**: Implementations identified as having such may cause failures when running in threads or in constrained environments.') + ############################################## + # Update the stateful signature markdown documentation. + ############################################## + for sig_stfl_yaml_path in sorted(glob.glob(os.path.join(liboqs_root, 'docs', 'algorithms', 'sig_stfl', '*.yml'))): + sig_stfl_yaml = load_yaml(sig_stfl_yaml_path) + sig_stfl_yamls.append(sig_stfl_yaml) + sig_stfl_name = os.path.splitext(os.path.basename(sig_stfl_yaml_path))[0] + print('Updating {}/{}.md'.format(os.path.dirname(sig_stfl_yaml_path), sig_stfl_name)) + + with open(os.path.join(liboqs_root, 'docs', 'algorithms', 'sig_stfl', '{}.md'.format(sig_stfl_name)), mode='w', encoding='utf-8') as out_md: + out_md.write('# {}\n\n'.format(sig_stfl_yaml['name'])) + out_md.write('- **Algorithm type**: Digital signature scheme.\n') + out_md.write('- **Main cryptographic assumption**: {}.\n'.format(sig_stfl_yaml['crypto-assumption'])) + out_md.write('- **Principal submitters**: {}.\n'.format(', '.join(sig_stfl_yaml['principal-submitters']))) + if 'auxiliary-submitters' in sig_stfl_yaml and sig_stfl_yaml['auxiliary-submitters']: + out_md.write('- **Auxiliary submitters**: {}.\n'.format(', '.join(sig_stfl_yaml['auxiliary-submitters']))) + out_md.write('- **Authors\' website**: {}\n'.format(sig_stfl_yaml['website'])) + out_md.write('- **Specification version**: {}.\n'.format(sig_stfl_yaml['spec-version'])) + + out_md.write('- **Primary Source**:\n') + out_md.write(' - **Source**: {}\n'.format(sig_stfl_yaml['primary-upstream']['source'])) + out_md.write(' - **Implementation license (SPDX-Identifier)**: {}\n'.format(sig_stfl_yaml['primary-upstream']['spdx-license-identifier'])) + if 'optimized-upstreams' in sig_stfl_yaml: + out_md.write('- **Optimized Implementation sources**: {}\n'.format(sig_stfl_yaml['primary-upstream']['source'])) + for opt_upstream in sig_stfl_yaml['optimized-upstreams']: + out_md.write(' - **{}**:\n'.format(opt_upstream, opt_upstream)) + out_md.write(' - **Source**: {}\n'.format(sig_stfl_yaml['optimized-upstreams'][opt_upstream]['source'])) + out_md.write(' - **Implementation license (SPDX-Identifier)**: {}\n'.format(sig_stfl_yaml['optimized-upstreams'][opt_upstream]['spdx-license-identifier'])) + + if 'upstream-ancestors' in sig_stfl_yaml: + out_md.write(', which takes it from:\n') + for url in sig_stfl_yaml['upstream-ancestors'][:-1]: + out_md.write(' - {}, which takes it from:\n'.format(url)) + out_md.write(' - {}\n'.format(sig_stfl_yaml['upstream-ancestors'][-1])) + else: + out_md.write('\n') + + if 'advisories' in sig_stfl_yaml: + out_md.write('\n## Advisories\n\n') + for advisory in sig_stfl_yaml['advisories']: + out_md.write('- {}\n'.format(advisory)) + + out_md.write('\n## Parameter set summary\n\n') + table = [['Parameter set', + 'Security model', + 'Claimed NIST Level', + 'Public key size (bytes)', + 'Secret key size (bytes)', + 'Signature size (bytes)']] + for parameter_set in sig_stfl_yaml['parameter-sets']: + table.append([parameter_set['name'], + parameter_set['claimed-security'], + parameter_set['claimed-nist-level'], + parameter_set['length-public-key'], + parameter_set['length-secret-key'], + parameter_set['length-signature']]) + out_md.write(tabulate.tabulate(table, tablefmt="pipe", headers="firstrow", colalign=("center",))) + out_md.write('\n') + + #################### # Update the README. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0dfb6f043..a5b64fd294 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(common) # initialize KEM|SIG_OBJS for --warn-uninitialized set(KEM_OBJS "") set(SIG_OBJS "") +set(SIG_STFL_OBJS "") if(${OQS_ENABLE_KEM_BIKE}) add_subdirectory(kem/bike) @@ -56,10 +57,22 @@ if(OQS_ENABLE_SIG_SPHINCS) endif() ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_OBJECTS_END +if(OQS_ENABLE_SIG_STFL_XMSS) + add_subdirectory(sig_stfl/xmss) + set(SIG_STFL_OBJS ${SIG_STFL_OBJS} ${XMSS_OBJS}) +endif() + +if(OQS_ENABLE_SIG_STFL_LMS) + add_subdirectory(sig_stfl/lms) + set(SIG_STFL_OBJS ${SIG_STFL_OBJS} ${LMS_OBJS}) +endif() + add_library(oqs kem/kem.c ${KEM_OBJS} sig/sig.c ${SIG_OBJS} + sig_stfl/sig_stfl.c + ${SIG_STFL_OBJS} ${COMMON_OBJS}) # Internal library to be used only by test programs diff --git a/src/common/common.c b/src/common/common.c index 7074aa9fbf..6688b9b75a 100644 --- a/src/common/common.c +++ b/src/common/common.c @@ -273,6 +273,26 @@ OQS_API void OQS_MEM_cleanse(void *ptr, size_t len) { #endif } +void *OQS_MEM_checked_malloc(size_t len) { + void *ptr = malloc(len); + if (ptr == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + abort(); + } + + return ptr; +} + +void *OQS_MEM_checked_aligned_alloc(size_t alignment, size_t size) { + void *ptr = OQS_MEM_aligned_alloc(alignment, size); + if (ptr == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + abort(); + } + + return ptr; +} + OQS_API void OQS_MEM_secure_free(void *ptr, size_t len) { if (ptr != NULL) { OQS_MEM_cleanse(ptr, len); diff --git a/src/common/common.h b/src/common/common.h index 8ddeef6f8f..b092baa036 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -180,6 +180,59 @@ OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len); */ OQS_API void OQS_MEM_cleanse(void *ptr, size_t len); +/** + * Allocates memory of a specified size and checks for successful allocation. + * + * This function attempts to allocate a block of memory of the specified size. + * If the allocation is successful, it returns a pointer to the beginning of the + * memory block. If the allocation fails, it prints an error message to stderr + * and terminates the program. + * + * @param[in] len The size of the memory block to allocate, in bytes. + * + * @return A pointer to the allocated memory block if the allocation is successful. + * + * @note This function is intended to be used when the allocation must succeed, + * and failure to allocate memory is considered a fatal error. As such, + * it does not return if the allocation fails, but instead terminates the + * program with an exit status indicating failure. + * + * @note The memory block returned by this function is not initialized. The caller + * is responsible for initializing the memory if required. + * + * @note The allocated memory should be freed using the standard `free` function + * when it is no longer needed. + */ +void *OQS_MEM_checked_malloc(size_t len); + +/** + * Allocates memory of a specified size and alignment and checks for successful allocation. + * + * This function attempts to allocate a block of memory with the specified size + * and alignment. If the allocation is successful, it returns a pointer to the + * memory block. If the allocation fails, it prints an error message to stderr + * and terminates the program. + * + * Alignment must be a power of two and a multiple of sizeof(void *). + * + * @param[in] alignment The alignment of the memory block to allocate. + * @param[in] size The size of the memory block to allocate, in bytes. + * + * @return A pointer to the allocated memory block if the allocation is successful. + * + * @note This function is intended to be used when the allocation must succeed, + * and failure to allocate memory is considered a fatal error. As such, + * it does not return if the allocation fails, but instead terminates the + * program with an exit status indicating failure. + * + * @note The memory block returned by this function is not initialized. The caller + * is responsible for initializing the memory if required. + * + * @note The allocated memory should be freed with `OQS_MEM_aligned_free` when it + * is no longer needed. + */ +void *OQS_MEM_checked_aligned_alloc(size_t alignment, size_t size); + /** * Zeros out `len` bytes of memory starting at `ptr`, then frees `ptr`. * @@ -211,6 +264,8 @@ OQS_API void OQS_MEM_insecure_free(void *ptr); * Allocates size bytes of uninitialized memory with a base pointer that is * a multiple of alignment. Alignment must be a power of two and a multiple * of sizeof(void *). Size must be a multiple of alignment. + * @note The allocated memory should be freed with `OQS_MEM_aligned_free` when it + * is no longer needed. */ void *OQS_MEM_aligned_alloc(size_t alignment, size_t size); diff --git a/src/common/sha2/sha2.c b/src/common/sha2/sha2.c index 9cc732d1d3..b34e61273e 100644 --- a/src/common/sha2/sha2.c +++ b/src/common/sha2/sha2.c @@ -22,6 +22,10 @@ void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, s callbacks->SHA2_sha256_inc_blocks(state, in, inblocks); } +void OQS_SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len) { + callbacks->SHA2_sha256_inc(state, in, len); +} + void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) { callbacks->SHA2_sha256_inc_finalize(out, state, in, inlen); } diff --git a/src/common/sha2/sha2.h b/src/common/sha2/sha2.h index 41562f8f5e..cd993e69c8 100644 --- a/src/common/sha2/sha2.h +++ b/src/common/sha2/sha2.h @@ -24,6 +24,16 @@ extern "C" { #endif +/** Data structure for the state of the SHA-224 incremental hashing API. */ +typedef struct { + /** Internal state */ + void *ctx; + /** current number of bytes in data */ + size_t data_len; + /** unprocessed data buffer */ + uint8_t data[128]; +} OQS_SHA2_sha224_ctx; + /** * \brief Process a message with SHA-256 and return the hash code in the output byte array. * @@ -39,6 +49,10 @@ void OQS_SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen); typedef struct { /** Internal state */ void *ctx; + /** current number of bytes in data */ + size_t data_len; + /** unprocessed data buffer */ + uint8_t data[128]; } OQS_SHA2_sha256_ctx; /** @@ -74,6 +88,17 @@ void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha */ void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks); +/** + * \brief Process message bytes with SHA-256 and update the state. + * + * \warning The state must be initialized by OQS_SHA2_sha256_inc_init or OQS_SHA2_sha256_inc_ctx_clone. + * + * \param state The state to update + * \param in Message input byte array + * \param len The number of bytes of message to process + */ +void OQS_SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len); + /** * \brief Process more message bytes with SHA-256 and return the hash code in the output byte array. * @@ -113,6 +138,10 @@ void OQS_SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen); typedef struct { /** Internal state. */ void *ctx; + /** current number of bytes in data */ + size_t data_len; + /** unprocessed data buffer */ + uint8_t data[128]; } OQS_SHA2_sha384_ctx; /** @@ -187,6 +216,10 @@ void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen); typedef struct { /** Internal state. */ void *ctx; + /** current number of bytes in data */ + size_t data_len; + /** unprocessed data buffer */ + uint8_t data[128]; } OQS_SHA2_sha512_ctx; /** @@ -264,6 +297,11 @@ struct OQS_SHA2_callbacks { */ void (*SHA2_sha256_inc_ctx_clone)(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src); + /** + * Implementation of function OQS_SHA2_sha256_inc. + */ + void (*SHA2_sha256_inc)(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len); + /** * Implementation of function OQS_SHA2_sha256_inc_blocks. */ diff --git a/src/common/sha2/sha2_armv8.c b/src/common/sha2/sha2_armv8.c index 49a63448aa..65ea6750c3 100644 --- a/src/common/sha2/sha2_armv8.c +++ b/src/common/sha2/sha2_armv8.c @@ -3,7 +3,7 @@ #include #include "sha2_local.h" - +#include #include // ARM includes #ifndef WIN32 @@ -15,7 +15,6 @@ * from http://bench.cr.yp.to/supercop.html * by D. J. Bernstein */ - static uint64_t load_bigendian_64(const uint8_t *x) { return (uint64_t)(x[7]) | (((uint64_t)(x[6])) << 8) | (((uint64_t)(x[5])) << 16) | (((uint64_t)(x[4])) << 24) | @@ -24,21 +23,21 @@ static uint64_t load_bigendian_64(const uint8_t *x) { } static void store_bigendian_64(uint8_t *x, uint64_t u) { - x[7] = (uint8_t) u; + x[7] = (uint8_t)u; u >>= 8; - x[6] = (uint8_t) u; + x[6] = (uint8_t)u; u >>= 8; - x[5] = (uint8_t) u; + x[5] = (uint8_t)u; u >>= 8; - x[4] = (uint8_t) u; + x[4] = (uint8_t)u; u >>= 8; - x[3] = (uint8_t) u; + x[3] = (uint8_t)u; u >>= 8; - x[2] = (uint8_t) u; + x[2] = (uint8_t)u; u >>= 8; - x[1] = (uint8_t) u; + x[1] = (uint8_t)u; u >>= 8; - x[0] = (uint8_t) u; + x[0] = (uint8_t)u; } static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes, @@ -63,9 +62,9 @@ static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes, }; unsigned long long pos = 0; /* load constants */ - uint32x4_t c0 = vld1q_u32(s256cst + 0); - uint32x4_t c1 = vld1q_u32(s256cst + 4); - uint32x4_t c2 = vld1q_u32(s256cst + 8); + uint32x4_t c0 = vld1q_u32(s256cst + 0); + uint32x4_t c1 = vld1q_u32(s256cst + 4); + uint32x4_t c2 = vld1q_u32(s256cst + 8); uint32x4_t c3 = vld1q_u32(s256cst + 12); uint32x4_t c4 = vld1q_u32(s256cst + 16); uint32x4_t c5 = vld1q_u32(s256cst + 20); @@ -80,13 +79,13 @@ static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes, uint32x4_t ce = vld1q_u32(s256cst + 56); uint32x4_t cf = vld1q_u32(s256cst + 60); /* load state */ - uint32x4_t d0 = vld1q_u32((uint32_t *)(statebytes + 0)); + uint32x4_t d0 = vld1q_u32((uint32_t *)(statebytes + 0)); uint32x4_t d1 = vld1q_u32((uint32_t *)(statebytes + 16)); uint32x4_t s0, s1, h0, h1; /* make state big-endian */ d0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(d0))); d1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(d1))); - while (length >= 64) { + while (length >= 64) { /* load one block */ uint32x4_t i0 = vld1q_u32((const uint32_t *)(data + pos + 0)); uint32x4_t i1 = vld1q_u32((const uint32_t *)(data + pos + 16)); @@ -110,33 +109,33 @@ static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes, * using 16 constants in c0..c3 * we need h0,h1,x0,x1 as scratch */ -#define DO16ROUNDS(i0, i1, i2, i3, c0, c1, c2, c3) \ - h0 = vaddq_u32(i0, c0); \ - x0 = vsha256hq_u32(s0, s1, h0); \ - x1 = vsha256h2q_u32(s1, s0, h0); \ - h1 = vaddq_u32(i1, c1); \ - s0 = vsha256hq_u32(x0, x1, h1); \ - s1 = vsha256h2q_u32(x1, x0, h1); \ - h0 = vaddq_u32(i2, c2); \ - x0 = vsha256hq_u32(s0, s1, h0); \ - x1 = vsha256h2q_u32(s1, s0, h0); \ - h1 = vaddq_u32(i3, c3); \ - s0 = vsha256hq_u32(x0, x1, h1); \ - s1 = vsha256h2q_u32(x1, x0, h1) +#define DO16ROUNDS(i0, i1, i2, i3, c0, c1, c2, c3) \ + h0 = vaddq_u32(i0, c0); \ + x0 = vsha256hq_u32(s0, s1, h0); \ + x1 = vsha256h2q_u32(s1, s0, h0); \ + h1 = vaddq_u32(i1, c1); \ + s0 = vsha256hq_u32(x0, x1, h1); \ + s1 = vsha256h2q_u32(x1, x0, h1); \ + h0 = vaddq_u32(i2, c2); \ + x0 = vsha256hq_u32(s0, s1, h0); \ + x1 = vsha256h2q_u32(s1, s0, h0); \ + h1 = vaddq_u32(i3, c3); \ + s0 = vsha256hq_u32(x0, x1, h1); \ + s1 = vsha256h2q_u32(x1, x0, h1) /* * this expands the block (or previously * expanded) in i0..i3 to j0..j3 */ #define DO16EXPANDS(i0, i1, i2, i3, j0, j1, j2, j3) \ - j0 = vsha256su0q_u32(i0, i1); \ - j0 = vsha256su1q_u32(j0, i2, i3); \ - j1 = vsha256su0q_u32(i1, i2); \ - j1 = vsha256su1q_u32(j1, i3, j0); \ - j2 = vsha256su0q_u32(i2, i3); \ - j2 = vsha256su1q_u32(j2, j0, j1); \ - j3 = vsha256su0q_u32(i3, j0); \ - j3 = vsha256su1q_u32(j3, j1, j2) + j0 = vsha256su0q_u32(i0, i1); \ + j0 = vsha256su1q_u32(j0, i2, i3); \ + j1 = vsha256su0q_u32(i1, i2); \ + j1 = vsha256su1q_u32(j1, i3, j0); \ + j2 = vsha256su0q_u32(i2, i3); \ + j2 = vsha256su1q_u32(j2, j0, j1); \ + j3 = vsha256su0q_u32(i3, j0); \ + j3 = vsha256su1q_u32(j3, j1, j2) DO16ROUNDS(i0, i1, i2, i3, c0, c1, c2, c3); @@ -163,52 +162,71 @@ static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes, /* store back to little-endian */ d0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(d0))); d1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(d1))); - vst1q_u32((uint32_t *)(statebytes + 0), d0); + vst1q_u32((uint32_t *)(statebytes + 0), d0); vst1q_u32((uint32_t *)(statebytes + 16), d1); return length; - } + void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen) { uint8_t padded[128]; - uint64_t bytes = load_bigendian_64(state->ctx + 32) + inlen; - crypto_hashblocks_sha256_armv8(state->ctx, in, inlen); - in += inlen; - inlen &= 63; - in -= inlen; + size_t new_inlen = state->data_len + inlen; + size_t tmp_len = new_inlen; + const uint8_t *new_in; + uint8_t *tmp_in = NULL; + + if (new_inlen == inlen) { + new_in = in; + } else { + // Combine incremental data with final input + tmp_in = OQS_MEM_checked_malloc(tmp_len); + + memcpy(tmp_in, state->data, state->data_len); + if (in && inlen) { + memcpy(tmp_in + state->data_len, in, inlen); + } + new_in = tmp_in; + state->data_len = 0; + } + uint64_t bytes = load_bigendian_64(state->ctx + 32) + new_inlen; - for (size_t i = 0; i < inlen; ++i) { - padded[i] = in[i]; + crypto_hashblocks_sha256_armv8(state->ctx, new_in, new_inlen); + new_in += new_inlen; + new_inlen &= 63; + new_in -= new_inlen; + + for (size_t i = 0; i < new_inlen; ++i) { + padded[i] = new_in[i]; } - padded[inlen] = 0x80; + padded[new_inlen] = 0x80; - if (inlen < 56) { - for (size_t i = inlen + 1; i < 56; ++i) { + if (new_inlen < 56) { + for (size_t i = new_inlen + 1; i < 56; ++i) { padded[i] = 0; } - padded[56] = (uint8_t) (bytes >> 53); - padded[57] = (uint8_t) (bytes >> 45); - padded[58] = (uint8_t) (bytes >> 37); - padded[59] = (uint8_t) (bytes >> 29); - padded[60] = (uint8_t) (bytes >> 21); - padded[61] = (uint8_t) (bytes >> 13); - padded[62] = (uint8_t) (bytes >> 5); - padded[63] = (uint8_t) (bytes << 3); + padded[56] = (uint8_t)(bytes >> 53); + padded[57] = (uint8_t)(bytes >> 45); + padded[58] = (uint8_t)(bytes >> 37); + padded[59] = (uint8_t)(bytes >> 29); + padded[60] = (uint8_t)(bytes >> 21); + padded[61] = (uint8_t)(bytes >> 13); + padded[62] = (uint8_t)(bytes >> 5); + padded[63] = (uint8_t)(bytes << 3); crypto_hashblocks_sha256_armv8(state->ctx, padded, 64); } else { - for (size_t i = inlen + 1; i < 120; ++i) { + for (size_t i = new_inlen + 1; i < 120; ++i) { padded[i] = 0; } - padded[120] = (uint8_t) (bytes >> 53); - padded[121] = (uint8_t) (bytes >> 45); - padded[122] = (uint8_t) (bytes >> 37); - padded[123] = (uint8_t) (bytes >> 29); - padded[124] = (uint8_t) (bytes >> 21); - padded[125] = (uint8_t) (bytes >> 13); - padded[126] = (uint8_t) (bytes >> 5); - padded[127] = (uint8_t) (bytes << 3); + padded[120] = (uint8_t)(bytes >> 53); + padded[121] = (uint8_t)(bytes >> 45); + padded[122] = (uint8_t)(bytes >> 37); + padded[123] = (uint8_t)(bytes >> 29); + padded[124] = (uint8_t)(bytes >> 21); + padded[125] = (uint8_t)(bytes >> 13); + padded[126] = (uint8_t)(bytes >> 5); + padded[127] = (uint8_t)(bytes << 3); crypto_hashblocks_sha256_armv8(state->ctx, padded, 128); } @@ -216,6 +234,7 @@ void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const ui out[i] = state->ctx[i]; } oqs_sha2_sha256_inc_ctx_release_c(state); + OQS_MEM_secure_free(tmp_in, tmp_len); } void oqs_sha2_sha224_inc_finalize_armv8(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen) { @@ -229,15 +248,63 @@ void oqs_sha2_sha224_inc_finalize_armv8(uint8_t *out, sha224ctx *state, const ui void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_t inblocks) { uint64_t bytes = load_bigendian_64(state->ctx + 32); + const uint8_t *new_in; + size_t buf_len = 64 * inblocks; + uint8_t *tmp_in = NULL; + + /* Process any existing incremental data first */ + if (state->data_len) { + tmp_in = OQS_MEM_checked_malloc(buf_len); + + memcpy(tmp_in, state->data, state->data_len); + memcpy(tmp_in + state->data_len, in, buf_len - state->data_len); + + /* store the reminder input as incremental data */ + memcpy(state->data, in + (buf_len - state->data_len), state->data_len); + new_in = tmp_in; + } else { + new_in = in; + } - crypto_hashblocks_sha256_armv8(state->ctx, in, 64 * inblocks); + crypto_hashblocks_sha256_armv8(state->ctx, new_in, 64 * inblocks); bytes += 64 * inblocks; store_bigendian_64(state->ctx + 32, bytes); + OQS_MEM_secure_free(tmp_in, buf_len); +} + +void oqs_sha2_sha256_inc_armv8(sha256ctx *state, const uint8_t *in, size_t len) { + while (len) { + size_t incr = 64 - state->data_len; + if (incr > len) { + incr = len; + } + + memcpy(state->data + state->data_len, in, incr); + state->data_len += incr; + in += incr; + + if (state->data_len < 64) { + break; + } + + /* + * Process a complete block now + */ + uint64_t bytes = load_bigendian_64(state->ctx + 32) + 64; + crypto_hashblocks_sha256_armv8(state->ctx, state->data, 64); + store_bigendian_64(state->ctx + 32, bytes); + + /* + * update the remaining input + */ + len -= incr; + state->data_len = 0; + } } void oqs_sha2_sha224_inc_blocks_armv8(sha224ctx *state, const uint8_t *in, size_t inblocks) { - oqs_sha2_sha256_inc_blocks_armv8((sha256ctx *) state, in, inblocks); + oqs_sha2_sha256_inc_blocks_armv8((sha256ctx *)state, in, inblocks); } void oqs_sha2_sha256_armv8(uint8_t *out, const uint8_t *in, size_t inlen) { diff --git a/src/common/sha2/sha2_c.c b/src/common/sha2/sha2_c.c index 1de100c306..e5bd350889 100644 --- a/src/common/sha2/sha2_c.c +++ b/src/common/sha2/sha2_c.c @@ -502,86 +502,87 @@ static const uint8_t iv_512[64] = { }; void oqs_sha2_sha224_inc_init_c(sha224ctx *state) { - state->ctx = malloc(PQC_SHA256CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_malloc(PQC_SHA256CTX_BYTES); + for (size_t i = 0; i < 32; ++i) { state->ctx[i] = iv_224[i]; } for (size_t i = 32; i < 40; ++i) { state->ctx[i] = 0; } + state->data_len = 0; + memset(state->data, 0, 128); } void oqs_sha2_sha256_inc_init_c(sha256ctx *state) { - state->ctx = malloc(PQC_SHA256CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->data_len = 0; + state->ctx = OQS_MEM_checked_malloc(PQC_SHA256CTX_BYTES); + for (size_t i = 0; i < 32; ++i) { state->ctx[i] = iv_256[i]; } for (size_t i = 32; i < 40; ++i) { state->ctx[i] = 0; } + state->data_len = 0; + memset(state->data, 0, 128); } void oqs_sha2_sha384_inc_init_c(sha384ctx *state) { - state->ctx = malloc(PQC_SHA512CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_malloc(PQC_SHA512CTX_BYTES); + for (size_t i = 0; i < 64; ++i) { state->ctx[i] = iv_384[i]; } for (size_t i = 64; i < 72; ++i) { state->ctx[i] = 0; } + state->data_len = 0; + memset(state->data, 0, 128); } void oqs_sha2_sha512_inc_init_c(sha512ctx *state) { - state->ctx = malloc(PQC_SHA512CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_malloc(PQC_SHA512CTX_BYTES); + for (size_t i = 0; i < 64; ++i) { state->ctx[i] = iv_512[i]; } for (size_t i = 64; i < 72; ++i) { state->ctx[i] = 0; } + state->data_len = 0; + memset(state->data, 0, 128); } void oqs_sha2_sha224_inc_ctx_clone_c(sha224ctx *stateout, const sha224ctx *statein) { - stateout->ctx = malloc(PQC_SHA256CTX_BYTES); - if (stateout->ctx == NULL) { - exit(111); - } + stateout->ctx = OQS_MEM_checked_malloc(PQC_SHA256CTX_BYTES); + + stateout->data_len = statein->data_len; + memcpy(stateout->data, statein->data, 128); memcpy(stateout->ctx, statein->ctx, PQC_SHA256CTX_BYTES); } void oqs_sha2_sha256_inc_ctx_clone_c(sha256ctx *stateout, const sha256ctx *statein) { - stateout->ctx = malloc(PQC_SHA256CTX_BYTES); - if (stateout->ctx == NULL) { - exit(111); - } + stateout->ctx = OQS_MEM_checked_malloc(PQC_SHA256CTX_BYTES); + + stateout->data_len = statein->data_len; + memcpy(stateout->data, statein->data, 128); memcpy(stateout->ctx, statein->ctx, PQC_SHA256CTX_BYTES); } void oqs_sha2_sha384_inc_ctx_clone_c(sha384ctx *stateout, const sha384ctx *statein) { - stateout->ctx = malloc(PQC_SHA512CTX_BYTES); - if (stateout->ctx == NULL) { - exit(111); - } + stateout->ctx = OQS_MEM_checked_malloc(PQC_SHA512CTX_BYTES); + + stateout->data_len = statein->data_len; + memcpy(stateout->data, statein->data, 128); memcpy(stateout->ctx, statein->ctx, PQC_SHA512CTX_BYTES); } void oqs_sha2_sha512_inc_ctx_clone_c(sha512ctx *stateout, const sha512ctx *statein) { - stateout->ctx = malloc(PQC_SHA512CTX_BYTES); - if (stateout->ctx == NULL) { - exit(111); - } + stateout->ctx = OQS_MEM_checked_malloc(PQC_SHA512CTX_BYTES); + + stateout->data_len = statein->data_len; + memcpy(stateout->data, statein->data, 128); memcpy(stateout->ctx, statein->ctx, PQC_SHA512CTX_BYTES); } @@ -607,11 +608,59 @@ void oqs_sha2_sha512_inc_ctx_release_c(sha512ctx *state) { void oqs_sha2_sha256_inc_blocks_c(sha256ctx *state, const uint8_t *in, size_t inblocks) { uint64_t bytes = load_bigendian_64(state->ctx + 32); + size_t tmp_buflen = 64 * inblocks; + const uint8_t *new_in; + uint8_t *tmp_in = NULL; + + /* Process any existing incremental data first */ + if (state->data_len) { + tmp_in = OQS_MEM_checked_malloc(tmp_buflen); + + memcpy(tmp_in, state->data, state->data_len); + memcpy(tmp_in + state->data_len, in, tmp_buflen - state->data_len); + + /* store the reminder input as incremental data */ + memcpy(state->data, in + (tmp_buflen - state->data_len), state->data_len); + new_in = tmp_in; + } else { + new_in = in; + } - crypto_hashblocks_sha256_c(state->ctx, in, 64 * inblocks); + crypto_hashblocks_sha256_c(state->ctx, new_in, 64 * inblocks); bytes += 64 * inblocks; store_bigendian_64(state->ctx + 32, bytes); + OQS_MEM_secure_free(tmp_in, tmp_buflen); +} + +void oqs_sha2_sha256_inc_c(sha256ctx *state, const uint8_t *in, size_t len) { + while (len) { + size_t incr = 64 - state->data_len; + if (incr > len) { + incr = len; + } + + memcpy(state->data + state->data_len, in, incr); + state->data_len += incr; + in += incr; + + if (state->data_len < 64) { + break; + } + + /* + * Process a complete block now + */ + uint64_t bytes = load_bigendian_64(state->ctx + 32) + 64; + crypto_hashblocks_sha256_c(state->ctx, state->data, 64); + store_bigendian_64(state->ctx + 32, bytes); + + /* + * update the remaining input + */ + len -= incr; + state->data_len = 0; + } } void oqs_sha2_sha224_inc_blocks_c(sha224ctx *state, const uint8_t *in, size_t inblocks) { @@ -633,20 +682,39 @@ void oqs_sha2_sha384_inc_blocks_c(sha384ctx *state, const uint8_t *in, size_t in void oqs_sha2_sha256_inc_finalize_c(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen) { uint8_t padded[128]; - uint64_t bytes = load_bigendian_64(state->ctx + 32) + inlen; - crypto_hashblocks_sha256_c(state->ctx, in, inlen); - in += inlen; - inlen &= 63; - in -= inlen; + size_t new_inlen = state->data_len + inlen; + size_t tmp_len = new_inlen; + const uint8_t *new_in; + uint8_t *tmp_in = NULL; - for (size_t i = 0; i < inlen; ++i) { - padded[i] = in[i]; + if (new_inlen == inlen) { + new_in = in; + } else { //Combine incremental data with final input + tmp_in = OQS_MEM_checked_malloc(tmp_len); + + memcpy(tmp_in, state->data, state->data_len); + if (in && inlen) { + memcpy(tmp_in + state->data_len, in, inlen); + } + new_in = tmp_in; + state->data_len = 0; } - padded[inlen] = 0x80; - if (inlen < 56) { - for (size_t i = inlen + 1; i < 56; ++i) { + uint64_t bytes = load_bigendian_64(state->ctx + 32) + new_inlen; + + crypto_hashblocks_sha256_c(state->ctx, new_in, new_inlen); + new_in += new_inlen; + new_inlen &= 63; + new_in -= new_inlen; + + for (size_t i = 0; i < new_inlen; ++i) { + padded[i] = new_in[i]; + } + padded[new_inlen] = 0x80; + + if (new_inlen < 56) { + for (size_t i = new_inlen + 1; i < 56; ++i) { padded[i] = 0; } padded[56] = (uint8_t) (bytes >> 53); @@ -659,7 +727,7 @@ void oqs_sha2_sha256_inc_finalize_c(uint8_t *out, sha256ctx *state, const uint8_ padded[63] = (uint8_t) (bytes << 3); crypto_hashblocks_sha256_c(state->ctx, padded, 64); } else { - for (size_t i = inlen + 1; i < 120; ++i) { + for (size_t i = new_inlen + 1; i < 120; ++i) { padded[i] = 0; } padded[120] = (uint8_t) (bytes >> 53); @@ -677,6 +745,7 @@ void oqs_sha2_sha256_inc_finalize_c(uint8_t *out, sha256ctx *state, const uint8_ out[i] = state->ctx[i]; } oqs_sha2_sha256_inc_ctx_release_c(state); + OQS_MEM_secure_free(tmp_in, tmp_len); } void oqs_sha2_sha224_inc_finalize_c(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen) { @@ -774,4 +843,3 @@ void oqs_sha2_sha512_c(uint8_t *out, const uint8_t *in, size_t inlen) { oqs_sha2_sha512_inc_init_c(&state); oqs_sha2_sha512_inc_finalize_c(out, &state, in, inlen); } - diff --git a/src/common/sha2/sha2_impl.c b/src/common/sha2/sha2_impl.c index f7f01b24f5..33805989e8 100644 --- a/src/common/sha2/sha2_impl.c +++ b/src/common/sha2/sha2_impl.c @@ -31,6 +31,13 @@ static void SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_ oqs_sha2_sha256_inc_ctx_clone_c((sha256ctx *) dest, (const sha256ctx *) src); } +static void SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len) { + C_OR_ARM( + oqs_sha2_sha256_inc_c((sha256ctx *) state, in, len), + oqs_sha2_sha256_inc_armv8((sha256ctx *) state, in, len) + ); +} + static void SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { C_OR_ARM( oqs_sha2_sha256_inc_blocks_c((sha256ctx *) state, in, inblocks), @@ -105,6 +112,7 @@ struct OQS_SHA2_callbacks sha2_default_callbacks = { SHA2_sha256, SHA2_sha256_inc_init, SHA2_sha256_inc_ctx_clone, + SHA2_sha256_inc, SHA2_sha256_inc_blocks, SHA2_sha256_inc_finalize, SHA2_sha256_inc_ctx_release, diff --git a/src/common/sha2/sha2_local.h b/src/common/sha2/sha2_local.h index dcb1392841..969e791d20 100644 --- a/src/common/sha2/sha2_local.h +++ b/src/common/sha2/sha2_local.h @@ -23,18 +23,26 @@ extern "C" { typedef struct { uint8_t *ctx; + size_t data_len; /* current number of bytes in data */ + uint8_t data[128]; /* msg buffer */ } sha224ctx; typedef struct { uint8_t *ctx; + size_t data_len; /* current number of bytes in data */ + uint8_t data[128]; /* msg buffer */ } sha256ctx; typedef struct { uint8_t *ctx; + size_t data_len; /* current number of bytes in data */ + uint8_t data[128]; /* msg buffer */ } sha384ctx; typedef struct { uint8_t *ctx; + size_t data_len; /* current number of bytes in data */ + uint8_t data[128]; /* msg buffer */ } sha512ctx; void oqs_sha2_sha224_inc_init_c(sha224ctx *state); @@ -46,6 +54,7 @@ void oqs_sha2_sha224_inc_ctx_release_c(sha224ctx *state); void oqs_sha2_sha256_inc_init_c(sha256ctx *state); void oqs_sha2_sha256_inc_ctx_clone_c(sha256ctx *dest, const sha256ctx *src); void oqs_sha2_sha256_inc_blocks_c(sha256ctx *state, const uint8_t *in, size_t inblocks); +void oqs_sha2_sha256_inc_c(sha256ctx *state, const uint8_t *in, size_t len); void oqs_sha2_sha256_inc_finalize_c(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen); void oqs_sha2_sha256_inc_ctx_release_c(sha256ctx *state); @@ -66,6 +75,7 @@ void oqs_sha2_sha512_inc_ctx_release_c(sha512ctx *state); void oqs_sha2_sha224_inc_blocks_armv8(sha224ctx *state, const uint8_t *in, size_t inblocks); void oqs_sha2_sha224_armv8(uint8_t *out, const uint8_t *in, size_t inlen); void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_t inblocks); +void oqs_sha2_sha256_inc_armv8(sha256ctx *state, const uint8_t *in, size_t len); void oqs_sha2_sha256_armv8(uint8_t *out, const uint8_t *in, size_t inlen); void oqs_sha2_sha384_inc_init_armv8(sha384ctx *state); diff --git a/src/common/sha2/sha2_ossl.c b/src/common/sha2/sha2_ossl.c index 0953feb194..3aff58fab6 100644 --- a/src/common/sha2/sha2_ossl.c +++ b/src/common/sha2/sha2_ossl.c @@ -58,6 +58,10 @@ static void SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { state->ctx = mdctx; } +static void SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len) { + OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, len)); +} + static void SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks) { OQS_OPENSSL_GUARD(OSSL_FUNC(EVP_DigestUpdate)((EVP_MD_CTX *) state->ctx, in, inblocks * SHA2_BLOCK_SIZE)); } @@ -153,6 +157,7 @@ struct OQS_SHA2_callbacks sha2_default_callbacks = { SHA2_sha256, SHA2_sha256_inc_init, SHA2_sha256_inc_ctx_clone, + SHA2_sha256_inc, SHA2_sha256_inc_blocks, SHA2_sha256_inc_finalize, SHA2_sha256_inc_ctx_release, diff --git a/src/common/sha3/ossl_sha3.c b/src/common/sha3/ossl_sha3.c index 1b65b37662..5d36f2280c 100644 --- a/src/common/sha3/ossl_sha3.c +++ b/src/common/sha3/ossl_sha3.c @@ -198,11 +198,7 @@ static void SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_s if (s->n_out == 0) { OSSL_FUNC(EVP_DigestFinalXOF)(clone, output, outlen); } else { - uint8_t *tmp; - tmp = malloc(s->n_out + outlen); - if (tmp == NULL) { - exit(111); - } + uint8_t *tmp = OQS_MEM_checked_malloc(s->n_out + outlen); OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); memcpy(output, tmp + s->n_out, outlen); free(tmp); // IGNORE free-check @@ -276,11 +272,7 @@ static void SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_s if (s->n_out == 0) { OSSL_FUNC(EVP_DigestFinalXOF)(clone, output, outlen); } else { - uint8_t *tmp; - tmp = malloc(s->n_out + outlen); - if (tmp == NULL) { - exit(111); - } + uint8_t *tmp = OQS_MEM_checked_malloc(s->n_out + outlen); OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); memcpy(output, tmp + s->n_out, outlen); free(tmp); // IGNORE free-check diff --git a/src/common/sha3/ossl_sha3x4.c b/src/common/sha3/ossl_sha3x4.c index 971a26c4e8..1f6a03c615 100644 --- a/src/common/sha3/ossl_sha3x4.c +++ b/src/common/sha3/ossl_sha3x4.c @@ -81,11 +81,7 @@ static void SHA3_shake128_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t * OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); OSSL_FUNC(EVP_DigestFinalXOF)(clone, out3, outlen); } else { - uint8_t *tmp; - tmp = malloc(s->n_out + outlen); - if (tmp == NULL) { - exit(111); - } + uint8_t *tmp = OQS_MEM_checked_malloc(s->n_out + outlen); OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); memcpy(out0, tmp + s->n_out, outlen); @@ -206,11 +202,7 @@ static void SHA3_shake256_x4_inc_squeeze(uint8_t *out0, uint8_t *out1, uint8_t * OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx3); OSSL_FUNC(EVP_DigestFinalXOF)(clone, out3, outlen); } else { - uint8_t *tmp; - tmp = malloc(s->n_out + outlen); - if (tmp == NULL) { - exit(111); - } + uint8_t *tmp = OQS_MEM_checked_malloc(s->n_out + outlen); OSSL_FUNC(EVP_MD_CTX_copy_ex)(clone, s->mdctx0); OSSL_FUNC(EVP_DigestFinalXOF)(clone, tmp, s->n_out + outlen); memcpy(out0, tmp + s->n_out, outlen); diff --git a/src/common/sha3/xkcp_sha3.c b/src/common/sha3/xkcp_sha3.c index 2fce9d9fe0..196652d85d 100644 --- a/src/common/sha3/xkcp_sha3.c +++ b/src/common/sha3/xkcp_sha3.c @@ -199,10 +199,7 @@ static void SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { } static void SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); keccak_inc_reset((uint64_t *)state->ctx); } @@ -238,10 +235,7 @@ static void SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) { } static void SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); keccak_inc_reset((uint64_t *)state->ctx); } @@ -277,10 +271,7 @@ static void SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) { } static void SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); keccak_inc_reset((uint64_t *)state->ctx); } @@ -319,10 +310,7 @@ static void SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, /* SHAKE128 incremental */ static void SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); keccak_inc_reset((uint64_t *)state->ctx); } @@ -364,10 +352,7 @@ static void SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, /* SHAKE256 incremental */ static void SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES); keccak_inc_reset((uint64_t *)state->ctx); } diff --git a/src/common/sha3/xkcp_sha3x4.c b/src/common/sha3/xkcp_sha3x4.c index 8ed5da878b..bd441a01ff 100644 --- a/src/common/sha3/xkcp_sha3x4.c +++ b/src/common/sha3/xkcp_sha3x4.c @@ -167,10 +167,7 @@ static void SHA3_shake128_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_ /* SHAKE128 incremental */ static void SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); keccak_x4_inc_reset((uint64_t *)state->ctx); } @@ -212,10 +209,7 @@ static void SHA3_shake256_x4(uint8_t *out0, uint8_t *out1, uint8_t *out2, uint8_ /* SHAKE256 incremental */ static void SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state) { - state->ctx = OQS_MEM_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); - if (state->ctx == NULL) { - exit(111); - } + state->ctx = OQS_MEM_checked_aligned_alloc(KECCAK_X4_CTX_ALIGNMENT, KECCAK_X4_CTX_BYTES); keccak_x4_inc_reset((uint64_t *)state->ctx); } diff --git a/src/oqs.h b/src/oqs.h index 3acedd11bf..6d1923c78b 100644 --- a/src/oqs.h +++ b/src/oqs.h @@ -17,5 +17,6 @@ #include #include #include +#include #endif // OQS_H diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index f3b2e7c425..0617d30661 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -190,3 +190,54 @@ #cmakedefine OQS_ENABLE_SIG_sphincs_shake_256s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake_256s_simple_avx2 1 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_ENABLE_DEFINES_END + +#cmakedefine OQS_ENABLE_SIG_STFL_XMSS 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha256_h10 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha256_h16 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha256_h20 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake128_h10 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake128_h16 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake128_h20 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha512_h10 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha512_h16 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_sha512_h20 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake256_h10 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake256_h16 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmss_shake256_h20 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 1 +#cmakedefine OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 1 + + +#cmakedefine OQS_ENABLE_SIG_STFL_LMS 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w1 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h15_w1 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h15_w2 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h15_w4 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 1 + +#cmakedefine OQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN 1 +#cmakedefine OQS_ALLOW_STFL_KEY_AND_SIG_GEN 1 +#cmakedefine OQS_ALLOW_XMSS_KEY_AND_SIG_GEN 1 +#cmakedefine OQS_ALLOW_LMS_KEY_AND_SIG_GEN 1 diff --git a/src/sig_stfl/lms/CMakeLists.txt b/src/sig_stfl/lms/CMakeLists.txt new file mode 100644 index 0000000000..e47452eb50 --- /dev/null +++ b/src/sig_stfl/lms/CMakeLists.txt @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: MIT + +set(_LMS_OBJS "") + +set(SRCS + external/endian.c + external/hash.c + external/hss.c + external/hss_alloc.c + external/hss_aux.c + external/hss_common.c + external/hss_compute.c + external/hss_derive.c + external/hss_generate.c + external/hss_keygen.c + external/hss_param.c + external/hss_reserve.c + external/hss_sign.c + external/hss_sign_inc.c + external/hss_thread_single.c + external/hss_verify.c + external/hss_verify_inc.c + external/hss_zeroize.c + external/lm_common.c + external/lm_ots_common.c + external/lm_ots_sign.c + external/lm_ots_verify.c + external/lm_verify.c + sig_stfl_lms.c + sig_stfl_lms_functions.c + ) + +#if (OQS_ENABLE_SIG_STFL_lms) +# add_compile_definitions(OQS_ENABLE_SIG_STFL_lms) +# set (SRCS ${SRCS} sig_stfl_lms.c sig_stfl_lms_functions.c) +#endif() + + +add_library(lms OBJECT ${SRCS}) +set(_LMS_OBJS ${_LMS_OBJS} $) +set(LMS_OBJS ${_LMS_OBJS} PARENT_SCOPE) + + + diff --git a/src/sig_stfl/lms/external/common_defs.h b/src/sig_stfl/lms/external/common_defs.h new file mode 100644 index 0000000000..1c7c85d382 --- /dev/null +++ b/src/sig_stfl/lms/external/common_defs.h @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +#if !defined( COMMON_DEFS_H_ ) +#define COMMON_DEFS_H_ + +/* + * These are defintions for the LMS implementation that are common throughout + * the system (and so are collected in one place) + */ + +#include +#include + +#define MAX_HASH 32 /* Length of the largest hash we support */ + +/* The I (Merkle tree identifier) value is 16 bytes long */ +#define I_LEN 16 + +/* The maximum height of a Merkle tree */ +#define MAX_MERKLE_HEIGHT 25 + +/* The mininum height of a Merkle tree. Some of our update logic assumes */ +/* this isn't too small */ +#define MIN_MERKLE_HEIGHT 5 + +/* The minimum/maximum number of levels of Merkle trees within an HSS trees */ +#define MIN_HSS_LEVELS 1 /* Minumum levels we allow */ +#define MAX_HSS_LEVELS 8 /* Maximum levels we allow */ + +/* This is the length of our internal seed values */ +#define SEED_LEN 32 /* Enough to make Grover's infeasible */ + +/* Here are some internal types used within the code. They are listed more */ +/* for documentation ("this is what this variable is expected to be") rather */ +/* than to let the compiler do any sort of type checking */ + + /* This is an index into a Merkle tree */ + /* Used for both the leaf index (0..N-1) and the node number (1..2*N-1), */ + /* where N is the size 2**h of the tre */ +#if MAX_MERKLE_HEIGHT > 31 + /* We need to express more than 32 bits in this type */ +typedef uint_fast64_t merkle_index_t; +#error We need to extend the id we place within a hash to more than 4 bytes +#else +typedef uint_fast32_t merkle_index_t; +#endif + + /* This is the name of a parameter set */ + /* Used for both an OTS parameter set or an LM parameter set */ + /* Both are 32 bits */ +typedef uint_fast32_t param_set_t; + + /* This is a sequence number over an HSS tree */ + /* This means we can never generate more than 2**64 signatures from a */ + /* private key (even if the parameter set would, in theory, allow us */ + /* to do more) */ +typedef uint_fast64_t sequence_t; + +/* Defined LM parameter sets */ +#define LMS_SHA256_N32_H5 0x00000005 +#define LMS_SHA256_N32_H10 0x00000006 +#define LMS_SHA256_N32_H15 0x00000007 +#define LMS_SHA256_N32_H20 0x00000008 +#define LMS_SHA256_N32_H25 0x00000009 + +/* LM-OTS registry */ +#define LMOTS_SHA256_N32_W1 0x00000001 +#define LMOTS_SHA256_N32_W2 0x00000002 +#define LMOTS_SHA256_N32_W4 0x00000003 +#define LMOTS_SHA256_N32_W8 0x00000004 + +/* + * Internal formats of various hashes + * + * We do a number of different hashes as a part of this package; some + * specified by the draft, some specific to us. + * For each such hash, we list the values being hashed, and the offset + * from the start where they go. We treat them as indicies into unsigned char + * arrays, and not structs, to avoid any potential padding issues with structs + * + * For a hash of type XXXX, XXXX_Z is the offset where component Z goes, + * XXXX_LEN(hash_len) is the length being hashed (assuming that hash length), + * XXXX_MAXLEN is the maximum length it can be (for allocation), and D_XXXX + * is the hash distinguisher (the value that makes it different from any other + * hash) + */ + +/* The initial message hashing */ +#define MESG_I 0 +#define MESG_Q 16 +#define MESG_D 20 /* The fixed D_MESG value */ +#define MESG_C 22 +#define MESG_PREFIX_LEN(n) (MESG_C + (n)) /* Length not counting the actual */ + /* message being signed */ +#define MESG_PREFIX_MAXLEN MESG_PREFIX_LEN(MAX_HASH) +#define D_MESG 0x8181 + +/* The Winternitz iteration hashes */ +#define ITER_I 0 +#define ITER_Q 16 +#define ITER_K 20 /* The RFC uses i here */ +#define ITER_J 22 +#define ITER_PREV 23 /* Hash from previous iteration; RFC uses tmp */ +#define ITER_LEN(hash_len) (ITER_PREV + (hash_len)) +#define ITER_MAX_LEN ITER_LEN(MAX_HASH) + +/* Hashing the OTS public key */ +#define PBLC_I 0 +#define PBLC_Q 16 +#define PBLC_D 20 /* The fixed D_PBLC value */ +#define PBLC_PREFIX_LEN 22 /* Not counting the OTS public keys */ +#define D_PBLC 0x8080 + +/* Hashing Merkle tree leaf nodes */ +#define LEAF_I 0 +#define LEAF_R 16 +#define LEAF_D 20 +#define LEAF_PK 22 +#define LEAF_LEN(root_len) (LEAF_PK + (root_len)) +#define LEAF_MAX_LEN LEAF_LEN(MAX_HASH) +#define D_LEAF 0x8282 + +/* Hashing Merkle tree internal nodes */ +#define INTR_I 0 +#define INTR_R 16 +#define INTR_D 20 +#define INTR_PK 22 +#define INTR_LEN(root_len) (INTR_PK + 2 * (root_len)) +#define INTR_MAX_LEN INTR_LEN(MAX_HASH) +#define D_INTR 0x8383 + +/* The determanistic key generation */ +/* Also used to generate subkeys in the j-tree hierarchy */ +/* As we'll always do either one or the other, we can reuse the structure */ +/* for both purposes */ +#define PRG_I 0 +#define PRG_Q 16 +#define PRG_J 20 +#define PRG_FF 22 /* A fixed 0xff goes here */ +#define PRG_SEED 23 +#define PRG_LEN(seed_len) (23 + (seed_len)) +#define PRG_MAX_LEN PRG_LEN(MAX_HASH) + +/* The below are hash formats that the draft does not list, but we */ +/* implement ourselves (largely because we need to be determanistic */ +/* based on the seed) */ + +/* Hash used to generate subkeys in the q tree hierarchy */ +#define QTREE_I 0 +#define QTREE_Q 16 +#define QTREE_D 20 /* D_QTREE goes here */ +#define QTREE_SEED 22 +#define QTREE_LEN (22 + 32) /* We assume a fixed length seed */ +#define QTREE_MAX_LEN QTREE_LEN +#define D_QTREE 0xffff + +/* Hash used to generate the master seed for the top level Merkle tree */ +#define TOPSEED_I 0 /* 16 0's here (we don't have an I value) */ +#define TOPSEED_Q 16 /* 0's here (as we don't have a Q value) */ +#define TOPSEED_D 20 /* D_TOPSEED */ +#define TOPSEED_WHICH 22 /* 0 -> Gen Master seed (used as seed for */ + /* the next two) */ + /* 1 -> Create top level seed */ + /* 2 -> Create top level I */ +#define TOPSEED_SEED 23 /* 32 bytes long */ +#define TOPSEED_LEN (TOPSEED_SEED + 32) +#define D_TOPSEED 0xfefe + +/* Hash used to generate the key used for the authenticating the aux values */ +#define DAUX_I 0 /* 16 0's here (no I value) */ +#define DAUX_Q 16 /* 4 more 0's here (no Q value) */ +#define DAUX_D 20 /* D_AUX_SEED_DERIVE */ +#define DAUX_PREFIX_LEN 22 /* Not counting the seed value */ +#define D_DAUX 0xfdfd + +/* Macro to set the D_XXXX value to the XXXX_D offset */ +#define SET_D(p, value) (void)(((p)[0] = (value) >> 8), \ + ((p)[1] = (value) & 0xff)) + +#endif /* COMMON_DEFS_H_ */ diff --git a/src/sig_stfl/lms/external/config.h b/src/sig_stfl/lms/external/config.h new file mode 100644 index 0000000000..f9549858a9 --- /dev/null +++ b/src/sig_stfl/lms/external/config.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +#if !defined( CONFIG_H_ ) +#define CONFIG_H_ + +#define LMS_UNUSED(x) (void)(x) + +/* + * This file has #define's that specify how this package operates, and + * are designed to be tweaked by the user. + * + * These can be adjusted to be appropriate for what the application and + * the operating environment needs + */ + +/* + * This modifies which seed generation logic we use + * Note that changing these parameters will change the mapping + * between private keys. + * + * 0 -> We generate seeds using the process defined in Appendix A of the draft + * This is slightly faster + * 1 -> We use a side channel resistant process, never using any single secret + * seed in more than a defined number of distinct hashes + * 2 -> We generate seeds and secrets in a way which is compatible with ACVP + */ +#define SECRET_METHOD 2 + +/* + * If we're using the side channel resistant method, this defines the max + * number of times we'll use a single secret. Note that this is the log2 + * of the max number of times, and so 3 means 'no more than 8 times' + * Reducing SECRET_MAX is a bit more costly; however I don't know that if + * it is significant + */ +#define SECRET_MAX 4 /* Never use a seed more than 16 times */ + +#endif /* CONFIG_H_ */ diff --git a/src/sig_stfl/lms/external/endian.c b/src/sig_stfl/lms/external/endian.c new file mode 100644 index 0000000000..52f8439baf --- /dev/null +++ b/src/sig_stfl/lms/external/endian.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +#include "endian.h" + +void put_bigendian( void *target, unsigned long long value, size_t bytes ) { + unsigned char *b = target; + int i; + + for (i = (int)(bytes-1); i >= 0; i--) { + b[i] = value & 0xff; + value >>= 8; + } +} + +unsigned long long get_bigendian( const void *target, size_t bytes ) { + const unsigned char *b = target; + unsigned long long result = 0; + size_t i; + + for (i=0; i +#include "lms_namespace.h" + +void put_bigendian( void *target, unsigned long long value, size_t bytes ); +unsigned long long get_bigendian( const void *target, size_t bytes ); + +#endif /* ENDIAN_H_ */ diff --git a/src/sig_stfl/lms/external/hash.c b/src/sig_stfl/lms/external/hash.c new file mode 100644 index 0000000000..090dafd66c --- /dev/null +++ b/src/sig_stfl/lms/external/hash.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +#include +#include "hash.h" +#include "hss_zeroize.h" + +#define ALLOW_VERBOSE 0 /* 1 -> we allow the dumping of intermediate */ + /* states. Useful for debugging; horrid */ + /* for security */ + +/* + * This is the file that implements the hashing APIs we use internally. + * At the present, our parameter sets support only one hash function + * (SHA-256, using full 256 bit output), however, that is likely to change + * in the future + */ + +#if ALLOW_VERBOSE +#include +#include +/* + * Debugging flag; if this is set, we chat about what we're hashing, and what + * the result is it's useful when debugging; however we probably don't want to + * do this if we're multithreaded... + */ +bool hss_verbose = false; +#endif + +/* + * This will hash the message, given the hash type. It assumes that the result + * buffer is large enough for the hash + */ +void hss_hash_ctx(void *result, int hash_type, union hash_context *ctx, + const void *message, size_t message_len) { +#if ALLOW_VERBOSE + if (hss_verbose) { + int i; for (i=0; i< message_len; i++) printf( " %02x%s", ((unsigned char*)message)[i], (i%16 == 15) ? "\n" : "" ); + } +#endif + + switch (hash_type) { + case HASH_SHA256: { + OQS_SHA2_sha256_inc_init(&ctx->sha256); + OQS_SHA2_sha256_inc(&ctx->sha256, message, message_len); + SHA256_Final(result, &ctx->sha256); +#if ALLOW_VERBOSE + if (hss_verbose) { + printf( " ->" ); + int i; for (i=0; i<32; i++) printf( " %02x", ((unsigned char *)result)[i] ); printf( "\n" ); + } +#endif + break; + } + } +} + +void hss_hash(void *result, int hash_type, + const void *message, size_t message_len) { + union hash_context ctx; + hss_hash_ctx(result, hash_type, &ctx, message, message_len); + hss_zeroize(&ctx, sizeof ctx); +} + + +/* + * This provides an API to do incremental hashing. We use it when hashing the + * message; since we don't know how long it could be, we don't want to + * allocate a buffer that's long enough for that, plus the decoration we add + */ +void hss_init_hash_context(int h, union hash_context *ctx) { + switch (h) { + case HASH_SHA256: + OQS_SHA2_sha256_inc_init( &ctx->sha256 ); + break; + } +} + +void hss_update_hash_context(int h, union hash_context *ctx, + const void *msg, size_t len_msg) { +#if ALLOW_VERBOSE + if (hss_verbose) { + int i; for (i=0; isha256, msg, len_msg); + break; + } +} + +void hss_finalize_hash_context(int h, union hash_context *ctx, void *buffer) { + switch (h) { + case HASH_SHA256: + SHA256_Final(buffer, &ctx->sha256); +#if ALLOW_VERBOSE + if (hss_verbose) { + printf( " -->" ); + int i; for (i=0; i<32; i++) printf( " %02x", ((unsigned char*)buffer)[i] ); + printf( "\n" ); + } +#endif + break; + } +} + + +unsigned hss_hash_length(int hash_type) { + switch (hash_type) { + case HASH_SHA256: return 32; + } + return 0; +} + +unsigned hss_hash_blocksize(int hash_type) { + switch (hash_type) { + case HASH_SHA256: return 64; + } + return 0; +} + +void SHA256_Final(unsigned char *output, OQS_SHA2_sha256_ctx *ctx) { + OQS_SHA2_sha256_inc_finalize(output, ctx, NULL, 0); +} diff --git a/src/sig_stfl/lms/external/hash.h b/src/sig_stfl/lms/external/hash.h new file mode 100644 index 0000000000..bd42d3f0e9 --- /dev/null +++ b/src/sig_stfl/lms/external/hash.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +#if !defined( HASH_H__ ) +#define HASH_H__ +#include +#include +#include +#include "lms_namespace.h" + +/* + * This defines the hash interface used within HSS. + * All globals are prefixed with hss_ to avoid name conflicts + * Gee, C++ namespaces would be nice... + */ + +/* + * Hash types + */ +enum { + HASH_SHA256 = 1, /* SHA256 */ +}; + +union hash_context { + OQS_SHA2_sha256_ctx sha256; + /* Any other hash contexts would go here */ +}; + +/* Hash the message */ +void hss_hash(void *result, int hash_type, + const void *message, size_t message_len); + +/* Does the same, but with the passed hash context (which isn't zeroized) */ +/* This is here to save time; let the caller use the same ctx for multiple */ +/* hashes, and then finally zeroize it if necessary */ +void hss_hash_ctx(void *result, int hash_type, union hash_context *ctx, + const void *message, size_t message_len); + +/* + * This is a debugging flag; turning this on will cause the system to dump + * the inputs and the outputs of all hash functions. It only works if + * debugging is allowed in hash.c (it's off by default), and it is *real* + * chatty; however sometimes you really need it for debugging + */ +extern bool hss_verbose; + +/* + * This constant has migrated to common_defs.h + */ +/* #define MAX_HASH 32 */ /* Length of the largest hash we support */ + +unsigned hss_hash_length(int hash_type); +unsigned hss_hash_blocksize(int hash_type); + +void hss_init_hash_context( int h, union hash_context *ctx ); +void hss_update_hash_context( int h, union hash_context *ctx, + const void *msg, size_t len_msg ); +void hss_finalize_hash_context( int h, union hash_context *ctx, + void *buffer); +void SHA256_Final(unsigned char *output, OQS_SHA2_sha256_ctx *ctx); + +#endif /* HASH_H__ */ diff --git a/src/sig_stfl/lms/external/hss.c b/src/sig_stfl/lms/external/hss.c new file mode 100644 index 0000000000..fd5342a982 --- /dev/null +++ b/src/sig_stfl/lms/external/hss.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT +/* + * This is an implementation of the HSS signature scheme from LMS + * This is designed to be full-featured + * + * Currently, this file consists of functions that don't have a better home + */ +#include +#include +#include "common_defs.h" +#include "hss.h" +#include "hash.h" +#include "endian.h" +#include "hss_internal.h" +#include "hss_aux.h" +#include "hss_derive.h" +#include "config.h" +#include "lm_ots_common.h" + +/* + * Allocate and load an ephemeral key + */ +struct hss_working_key *hss_load_private_key( + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + size_t memory_target, + const unsigned char *aux_data, size_t len_aux_data, + struct hss_extra_info *info ) { + + /* Step 1: determine the parameter set */ + unsigned levels; + param_set_t lm[ MAX_HSS_LEVELS ]; + param_set_t ots[ MAX_HSS_LEVELS ]; + if (!hss_get_parameter_set( &levels, lm, ots, read_private_key, context)) { + /* Can't read private key, or private key invalid */ + return 0; + } + + /* Step 2: allocate the ephemeral key */ + struct hss_working_key *w = allocate_working_key(levels, lm, ots, + memory_target, info); + if (!w) { + /* Memory allocation failure, most likely (we've already vetted */ + /* the parameter sets) */ + return 0; + } + + /* Step 3: load the ephemeral key */ + if (! hss_generate_working_key( read_private_key, context, + aux_data, len_aux_data, w, info )) { + /* About the only thing I can see failing here is perhaps */ + /* attempting to reread the private key failed the second time; */ + /* seems unlikely, but not impossible */ + hss_free_working_key( w ); + return 0; + } + + /* Success! */ + return w; +} + +/* + * Internal function to generate the root seed and I value (based on the + * private seed). We do this (rather than select seed, I at random) so that + * we don't need to store it in our private key; we can recompute them + */ +bool hss_generate_root_seed_I_value(unsigned char *seed, unsigned char *I, + const unsigned char *master_seed) { +#if SECRET_METHOD == 2 + /* In ACVP mode, we use the master seed as the source for both the */ + /* root seed, and the root I value */ + memcpy( seed, master_seed, SEED_LEN ); + memcpy( I, master_seed + SEED_LEN, I_LEN ); +#else + /* + * We use a two-level hashing scheme so that we end up using the master + * seed only twice throughout the system (once here, once to generate the + * aux hmac key) + */ + unsigned char hash_preimage[ TOPSEED_LEN ]; + unsigned char hash_postimage[ MAX_HASH ]; + + memset( hash_preimage + TOPSEED_I, 0, I_LEN ); + memset( hash_preimage + TOPSEED_Q, 0, 4 ); + SET_D( hash_preimage + TOPSEED_D, D_TOPSEED ); + hash_preimage[TOPSEED_WHICH] = 0x00; + memcpy( hash_preimage + TOPSEED_SEED, master_seed, SEED_LEN ); + + /* We use a fixed SHA256 hash; we don't care about interoperability */ + /* so we don't need to worry about what parameter set the */ + /* user specified */ +#if I_LEN > 32 || SEED_LEN != 32 +#error This logic needs to be reworked +#endif + union hash_context ctx; + + hss_hash_ctx(hash_postimage, HASH_SHA256, &ctx, hash_preimage, + TOPSEED_LEN ); + memcpy( hash_preimage + TOPSEED_SEED, hash_postimage, SEED_LEN ); + + /* Now compute the top level seed */ + hash_preimage[TOPSEED_WHICH] = 0x01; + hss_hash_ctx(seed, HASH_SHA256, &ctx, hash_preimage, TOPSEED_LEN ); + + /* Now compute the top level I value */ + hash_preimage[TOPSEED_WHICH] = 0x02; + hss_hash_ctx(hash_postimage, HASH_SHA256, &ctx, hash_preimage, + TOPSEED_LEN ); + memcpy( I, hash_postimage, I_LEN ); + + hss_zeroize( hash_preimage, sizeof hash_preimage ); /* There's keying */ + /* data here */ + hss_zeroize( &ctx, sizeof ctx ); +#endif + return true; +} + +/* + * Internal function to generate the child I value (based on the parent's + * I value). While this needs to be determanistic (so that we can create the + * same I values between reboots), there's no requirement for interoperability. + * So we use a fixed SHA256; when we support a hash function other than SHA256, + * we needn't update this. + */ +bool hss_generate_child_seed_I_value( unsigned char *seed, unsigned char *I, + const unsigned char *parent_seed, + const unsigned char *parent_I, + merkle_index_t index, + param_set_t lm, param_set_t ots) { + struct seed_derive derive; + if (!hss_seed_derive_init( &derive, lm, ots, parent_I, parent_seed )) { + return false; + } + + hss_seed_derive_set_q( &derive, index ); + + /* Compute the child seed value */ + hss_seed_derive_set_j( &derive, SEED_CHILD_SEED ); + hss_seed_derive( seed, &derive, true ); + /* True sets the j value to SEED_CHILD_I */ + + /* Compute the child I value; with increment_j set to true in the */ + /* above call, derive has been set to the SEED_CHILD_I position */ + unsigned char postimage[ SEED_LEN ]; + hss_seed_derive( postimage, &derive, false ); + memcpy( I, postimage, I_LEN ); + + hss_seed_derive_done( &derive ); + + return true; +} + +void hss_init_extra_info( struct hss_extra_info *p ) { + if (p) memset( p, 0, sizeof *p ); +} + +void hss_extra_info_set_threads( struct hss_extra_info *p, int num_threads ) { + if (p) p->num_threads = num_threads; +} + +bool hss_extra_info_test_last_signature( struct hss_extra_info *p ) { + if (!p) return false; + return p->last_signature; +} + +enum hss_error_code hss_extra_info_test_error_code( struct hss_extra_info *p ) { + if (!p) return hss_error_got_null; + return p->error_code; +} diff --git a/src/sig_stfl/lms/external/hss.h b/src/sig_stfl/lms/external/hss.h new file mode 100644 index 0000000000..675089ddf0 --- /dev/null +++ b/src/sig_stfl/lms/external/hss.h @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: MIT +#if !defined(HSS_H_) +#define HSS_H_ + +#include +#include +#include "common_defs.h" +#include "lms_namespace.h" + +/* + * This is intended to be a usable (nontoy) implementation of the LMS + * signature scheme. The public data (public keys, signatures) are + * precisely the same as the standard LMS implmentation; however it + * strives to be more usable, in the following ways: + * + * - During signature generation time, it incrementally computes the next + * trees; that means that it doesn't need to generate the next Merkle tree + * from scratch on the 1025th signature. + * - It doesn't try to hold the entire Merkle tree in memory; hence a level + * 25 Merkle tree doesn't need to save 2**25 internal node values. This + * does increase the time to generate the next siganture (as we will need + * to recompute some internal nodes); however by only a small constant factor + * - It divides the private key into three parts, only one of which needs to + * be kept secret, and updated dynamically; the other parts are a working + * copy (that can be kept in RAM, and can be dynamically regenerated as + * needed), and some optional static (nonprivate) data (which can speed up + * the regeneration process) + * - API to explicitly reserve the next N signatures (so that we don't need + * to update the secure storage copy quite as often) + * + * + * We use a nonflat memory structure for the working_key. Part of the reason + * we use a flat representation elsewhere is so that they can be written (and + * later read) to/from disk as required; we specifically assume that the + * working_key is never written to disk. And, being able to use C structures + * makes this rather nontrivial structure a bit more transparent + * + * Here is the intended order of usage: + * Step 1: generate the private/public keypair: + * The API to do this is hss_generate_private_key; this is done once per + * private key; and you should write the private key to secure storage + * (which the passed update_private_key function could do) + * + * Step 2: (which you can do per restart): + * Load the private keypair into memory: hss_load_private_key + * + * Step 3: generate signatures (which you can do lots of time after you've + * loaded the key into memory): + * The API to do this is hss_generate_signature. Note that this needs + * to update the private key state; the update_private_key function pointer + * can be useful here + * + * Step 4: (when you're done with the loaded private key; optional) + * Free the ephemeral copy (hss_free_working_key). Note that this is not + * required for correctness; this just does a free() + * + * + * One can also verify signatures at any time; all that needs is a public + * key, a signature and a message; it's not a part of the intended order + * of usage + */ + +struct hss_extra_info; + +/* + * This will generate a fresh (unadorned) private key, with the selected + * parameter set, the corresponding public key, and (optionally) the aux_data + * that is associated with the private key. + * + * The generate_random function will be called when this function needs + * random values; it is assumed to generate cryptographically secure ones. + * We ask you to pass a function, rather than an array of random values, + * to emphasize that we really do need fresh random data here; the security + * of this entire system depends on it. + * + * levels, lm_type, lm_ots_type is the parameter set for the new key. + * levels is the number of levels in the HSS hierarchy (1-8), while + * lm_type[], lm_ots_type[] are arrays giving the parameter set of each + * individual level; level i of the hierarchy will have LMS parameter set + * lm_type[i] and OTS parameter set lm_ots_type[i] (where i=0 is the topmost + * Merkle tree. + * + * The update_private_key function will be called when the private key is + * generated; it is expected to write the private key to secure storage (and + * the context pointer is a value that is passed to the update_private_key + * function; it can be used to tell the update_private_key function where + * in the secure storage to place the key). If the passed update_private_key + * function pointer is NULL, the private will will be written to the context + * pointer (which is expected to hold 48 bytes of data) + * + * public_key is where the freshly generated public key will be placed, and + * len_public_key is the size of the array (and this will generate an error + * if the public key is larger than the array). See the hss_get_public_key_len + * function for the expected length of the public key + * + * aux_data is where to place internal nodes of the Merkle tree, and + * len_aux_data is the length of the provided buffer. This aux_data + * is optional (pass in a NULL if it's not being used), but does significantly + * speed the generate_working_key process. It's envisioned use is to write + * this aux_data to disk, and reread it when it's time to regenerate the + * ephemeral key; it need not be kept in secure storage; revealing it doesn't + * help an attacker to generate forgeries, and if an attacker does manage to + * corrupt it, the regeneration process will detect the corruption and ignore + * it. Also, even if writing it to disk is not possible, passing in a + * small array here and passing that to the initial regeneration call will + * speed that up (and later ones can omit it; those will go slow, but at + * least you got the speed up benefit the first time). + * + * One slightly tricky thing about aux data is that the required length of the + * aux data; there are several different possible time/memory trade-offs. + * Depending on the length, we'll automatically pick the fastest option that + * fits. If we have N bytes available total, see hss_get_aux_data_len for + * the amount of data we'll actually use (and so the amount you need to write + * to disk) + */ +bool hss_generate_private_key( + bool (*generate_random)(void *output, size_t length), + unsigned levels, + const param_set_t *lm_type, const param_set_t *lm_ots_type, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned char *public_key, size_t len_public_key, + unsigned char *aux_data, size_t len_aux_data, + struct hss_extra_info *info); + +/* + * This is the routine to load a private key into memory, and + * initialize the working data structures; these data structures + * allow us to generate signtures quickly + * + * The read_private_key is a function to read the private key from secure + * storage, with context being a value passed to that function. + * If the read_private_key pointer is NULL, we assume that the context + * pointer points to the private key. + * This assumes that the key has already been generated by + * hss_generate_private_key + * + * memory_target is a value which gives a goal for the amount of memory (in + * bytes) that this structure should take up. There are a number of + * time/memory trade-offs possible; the function uses this parameter as a + * guide as to what trade-offs it should take. This structure tries to + * allocate no more than memory_target bytes; however it is considered + * advisatory; this function will never fail beccause memory_target was too + * small (so passing 0 will work, and will minimize the memory used) + * + * aux_data points to a buffer containing the auxiliary data generated + * during the key generation process, with len_aux_data being the length + * of the buffer. Passing it a NULL means that we're not providing that + * data (which is fine; it just means this will take longer) + * + * On success, this malloc's the ephemeral key (struct hss_working_key*) and + * retursn it. Because it mallocs it, it asssumes that the caller will + * eventually free it (via the hss_free_working_key function, don't try + * calling free() yourself) + */ +struct hss_working_key; +struct hss_working_key *hss_load_private_key( + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + size_t memory_target, + const unsigned char *aux_data, size_t len_aux_data, /* Optional */ + struct hss_extra_info *info); + +/* + * Corresponding function to free the working key + */ +void hss_free_working_key( struct hss_working_key * ); + +/* + * This will actually generate a signature + * + * working_key is the key that has been allocated by allocate_working_key and + * initialied by hss_generate_working_key + * + * The update_private_key function will be called when the private key is + * updated; it is expected to write the private key to secure storage (and the + * context pointer is a value that is passed to the update_private_key + * function; it can be used to tell the update_private_key function where + * in the secure storage to place the key). And, if it is NULL, the context + * is expected to point to a copy of the private_key in RAM. + * One distinction is that, on an update, len_private_key will be 8; + * the update_private_key can choose to update only the first 8 bytes + * of the private key (the rest will be unchanged), or write all + * 48 bytes (private_key will point to the full 48 byte value) + * + * message, message_len are the message being signed + * + * signature is where the signature will be written, with signature_len being + * the length of the buffer. See the hss_get_signature_len function for the + * expected signature length for this parameter set; if signature_len is too + * short for the signature to fit, this will fail. + */ +bool hss_generate_signature( + struct hss_working_key *working_key, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + const void *message, size_t message_len, + unsigned char *signature, size_t signature_len, + struct hss_extra_info *info); + +/* + * See hss_verify.h for the signature verfication routine; it's in a + * separate file for those programs that only need to verify a signature + */ +#include "hss_verify.h" + +/* + * Lower level routines to allocate and initialize a working key. + * + * hss_load_working_key will do the work of the below routines; these are + * provided separately in case you need more control (e.g. reuse an already + * allocated working key) + * + * First, the routine to allocate (but not initialize) a working key. + * + * The levels/lm_type/lm_ots_type are the same parameter sets as in the + * generate public/private keypair call; the parameter set must match the + * values for the private key. + * + * memory_target is a value which gives a goal for the amount of memory that + * this structure should take up. There are a number of time/memory trade-offs + * possible; the function uses this parameter as a guide as to what trade-offs + * it should take. This structure tries to allocate no more than memory_target + * bytes; however it is considered advisatory; this function will never fail + * beccause memory_target was too small (so passing 0 will work, and will + * minimize the memory used) + */ +struct hss_working_key *allocate_working_key( + unsigned levels, + const param_set_t *lm_type, const param_set_t *lm_ots_type, + size_t memory_target, + struct hss_extra_info *info); + +/* + * This is called on reload (or initial key generation), it'll take the + * working key that's been allocated by allocate_working_key, and initialize + * it based on the private key; this working key is what we need to actually + * generate signatures. + * + * The read_private_key is a function to read the private key from secure + * storage, with context being a value passed to that function. + * If NULL, we assume that the context pointer points to the private key + * + * aux_data points to a buffer containing the auxiliary data generated + * during the key generation process, with len_aux_data being the length + * of the buffer. Passing it a NULL means that we're not providing that + * data (which is fine; it just means this will take longer) + * + * working_key is a pointer to the allocated working key + */ +bool hss_generate_working_key( + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + const unsigned char *aux_data, size_t len_aux_data, /* Optional */ + struct hss_working_key *working_key, + struct hss_extra_info *info); + +/* + * This will make sure that (at least) N signatures are reserved; that is, we + * won't need to actually call the update function for the next N signatures + * generated + * + * This can be useful if the update_private_key function is expensive. + * + * Note that if, N (or more) signatures are already reserved, this won't do + * anything. + */ +bool hss_reserve_signature( + struct hss_working_key *w, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned sigs_to_reserve, + struct hss_extra_info *info); + +/* + * This will set the autoreserve, so that when the signing process runs out, + * it will automatically reserve N more signatures (in addition to the one + * that is being used for the current signature) + * + * This can be useful if the update_private_key function is expensive, + * setting sigs_to_autoreserve=99 means will actually update the private + * key once every 100 signatures + */ +bool hss_set_autoreserve( + struct hss_working_key *w, + unsigned sigs_to_autoreserve, + struct hss_extra_info *info); + +/* + * This returns the required lengths for the various objects we export + * + * This is the length of the private key (which is written to secure storage) + */ +size_t hss_get_private_key_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type); +#define HSS_MAX_PRIVATE_KEY_LEN (8 + 8 + SEED_LEN + 16) + +/* + * This include file has the functions that contains the lengths of the other + * public objects + */ +#include "hss_common.h" + +/* + * Get the signature length. We don't put this in hss_common because we + * assume we have a loaded private key + * Returns 0 on error + */ +size_t hss_get_signature_len_from_working_key( + struct hss_working_key *working_key); + +/* + * This returns the amount of aux data we use + * This is slightly different from the above routines; given the bound on the + * amount of data the aux_data is allowed to take (max_length), this returns + * the amount of data we'll actually use + */ +size_t hss_get_aux_data_len(size_t max_length, + unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type); + +/* + * This returns the parameter set for a given private key. + * This is here to solve a chicken-and-egg problem: the hss_working_key + * must be initialized to the same parameter set as the private key, + * but (other than this function, or somehow remembering it) there's + * no way to retreive the parameter set. + * + * read_private_key/context will read the private key (if read_private_key is + * NULL, context is assumed to point to the private key) + * + * On success, *levels will be set to the number of levels, and lm_type[] + * and lm_ots_type[] will be set to the lm/ots parameter sets + * + * On success, this returns true; on failure (can't read the private key, or + * the * private key is invalid), returns false + */ +bool hss_get_parameter_set( unsigned *levels, + param_set_t lm_type[ MAX_HSS_LEVELS ], + param_set_t lm_ots_type[ MAX_HSS_LEVELS ], + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context); + +enum hss_error_code { + hss_error_none = 0, /* I don't know nothing about any error */ + + hss_range_normal_failures, /* There errors happen during normal use */ + /* of the signature scheme */ + hss_error_bad_signature, /* Invalid signature */ + hss_error_private_key_expired, /* This private key has generated all */ + /* the signatures it is allowed */ + hss_error_not_that_many_sigs_left, /* Reservation request failed */ + /* because the key couldn't do that many */ + /* signatures */ + + hss_range_bad_parameters, /* These errors are cause by the */ + /* application passing in a bad parameter */ + hss_error_no_randomness, /* No RNG supplied */ + hss_error_bad_param_set, /* Application asked for an illegal parmaeter */ + /* set */ + hss_error_buffer_overflow, /* Buffer provide not big enough */ + hss_error_got_null, /* Application passed in a NULL pointer */ + hss_error_bad_aux, /* Error with provided aux buffer */ + hss_error_no_private_buffer, /* Application didn't provide a place */ + /* to put the private key */ + hss_error_incompatible_param_set, /* The parameter set of the working */ + /* set didn't agree with the private key */ + hss_error_key_uninitialized, /* The working key used had never been */ + /* initialized with a private key */ + hss_error_key_mismatch, /* The working set and the private key */ + /* do not correspond */ + hss_error_ctx_uninitialized, /* The incremental ctx wasn't initialized */ + /* properly */ + hss_error_ctx_already_used, /* The ctx has already been used */ + hss_error_bad_public_key, /* Somehow, we got an invalid public key */ + + hss_range_processing_error, /* These errors are cause by an */ + /* error while processing */ + hss_error_bad_randomness, /* The RNG claimed failure */ + hss_error_private_key_write_failed, /* The write of the private key */ + /* to NVRAM failed */ + hss_error_private_key_read_failed, /* The read of the private key */ + /* from NVRAM failed */ + hss_error_out_of_memory, /* A malloc failure caused us to fail */ + + hss_range_my_problem, /* These are caused by internal errors */ + /* within the HSS implementation */ + hss_error_internal, /* Some internal assertion failed (should */ + /* never happen) */ +}; + +/* + * This is the structure that allows us to pass noncritical information + * to and from the above routines (without requiring us to add each + * one as an additional parameter + */ +struct hss_extra_info { + int num_threads; /* Number of threads we're allowed to ues */ + bool last_signature; /* Set if we just signed the last signature */ + /* allowed by this private key */ + enum hss_error_code error_code; /* The more recent error detected */ +}; + +/* Accessor APIs in case someone doesn't feel comfortable about reaching */ +/* into the structure */ +void hss_init_extra_info( struct hss_extra_info * ); +void hss_extra_info_set_threads( struct hss_extra_info *, int ); +bool hss_extra_info_test_last_signature( struct hss_extra_info * ); +enum hss_error_code hss_extra_info_test_error_code( struct hss_extra_info * ); + +#endif /* HSS_H_ */ diff --git a/src/sig_stfl/lms/external/hss_alloc.c b/src/sig_stfl/lms/external/hss_alloc.c new file mode 100644 index 0000000000..53eaa762e2 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_alloc.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code which allocates a working key (and initializes the fields + * that are independent of the key) + */ +#include +#include +#include +#include "hss.h" +#include "hss_internal.h" +#include "lm_common.h" + +#define MALLOC_OVERHEAD 8 /* Our simplistic model about the overhead */ + /* that malloc takes up is that it adds 8 */ + /* bytes to any request we make. This isn't */ + /* precise (especially if we consider external */ + /* fragmentation), it's just a guideline */ + +/* + * Function to estimate the amount of memory we'd use at a particular level, + * if we went with a particular subtree size + * - i is which tree in the scheme we're talking about; 0 is the root tree + * We have this because we allocate less for the root tree + * - subtree_size is the size of the subtrees we're considering + * - total_length is the size of the trees + * - size_hash is the length of the hash output (always 32 currently) + * - if psubtree_levels is non-NULL, we'll return the number of subtree levels + * here + * - if pstack_total is non-NULL, we'll return the bytes of stack space needed + * by the subtrees of this level here + * The value returned is the amount of space used by the merkle + * level structures, the subtree structures, plus the additional stack + * space required + */ +static size_t compute_level_memory_usage(int i, unsigned subtree_size, + unsigned total_height, unsigned size_hash, + unsigned *psubtree_levels, + size_t *pstack_total) { + /* Compute the number of subtree levels we'd have */ + unsigned subtree_levels = (total_height + subtree_size - 1) / subtree_size; + unsigned top_subtree_size = total_height - (subtree_levels-1)*subtree_size; + /* The top level tree has no next subtrees */ + int have_next_subtree = (i == 0) ? 0 : 1; + size_t stack_total = 0; + + /* Compute the memory this would use */ + size_t memory_used = sizeof(struct merkle_level) + MALLOC_OVERHEAD; + unsigned j; + for (j=0; j 2 +#error We assume that a subtree of size 2 is allowed +#endif + return 2; +} + +/* + * This allocates a working key for a particular parameter set, and sets up + * the data fields that are key independent; it doesn't set anything that + * does depend on the key. memory_target is used to guide time/memory + * trade-offs; it's the target memory budget that we try to stay below if + * possible + */ +struct hss_working_key *allocate_working_key( + unsigned levels, + const param_set_t *lm_type, const param_set_t *lm_ots_type, + size_t memory_target, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) { + info->error_code = hss_error_bad_param_set; + return 0; + } + + /* Assign the memory target to a *signed* variable; signed so that it */ + /* can take on negative values meaningfully (to account for cases where */ + /* we are "overbudget") */ + unsigned long mem_target; + if (memory_target > LONG_MAX) { + mem_target = LONG_MAX; + } else { + mem_target = (unsigned long)memory_target; + } +#if 0 +signed long initial_mem_target = mem_target; /* DEBUG HACK */ +#endif + + struct hss_working_key *w = malloc( sizeof *w ); + if (!w) { + info->error_code = hss_error_out_of_memory; + return NULL; + } + mem_target -= (unsigned long)sizeof(*w) + MALLOC_OVERHEAD; + unsigned i; + w->levels = levels; + w->status = hss_error_key_uninitialized; /* Not usable until we see a */ + /* private key */ + w->autoreserve = 0; + + /* Initialize all the allocated data structures to NULL */ + /* We do this up front so that if we hit an error in the middle, we can */ + /* just free everything */ + for (i=0; isigned_pk[i] = NULL; + } + for (i=0; itree[i] = NULL; + } + w->stack = NULL; + + /* Allocate all the memory for the level signatures */ + size_t signature_len = 4; /* At the same time, ocmpute the sig length */ + for (i=0; i < levels; i++) { + w->siglen[i] = lm_get_signature_len( lm_type[i], lm_ots_type[i] ); + signature_len += w->siglen[i]; + /* Size of this level's Merkle public key */ + size_t pklen = lm_get_public_key_len(lm_type[i]); + if (i != 0) signature_len += pklen; + if (w->siglen[i] == 0) { + hss_free_working_key(w); + info->error_code = hss_error_bad_param_set; + return 0; + } + /* We don't need a allocate a signature for the topmost */ + if (i == 0) continue; + + w->signed_pk_len[i] = w->siglen[i-1] + pklen; + + w->signed_pk[i] = malloc( w->signed_pk_len[i] ); + if (!w->signed_pk[i]) { + hss_free_working_key(w); + info->error_code = hss_error_out_of_memory; + return 0; + } + mem_target -= (unsigned long)w->signed_pk_len[i] + MALLOC_OVERHEAD; + } + w->signature_len = signature_len; + + /* Also account for the overhead for the stack allocation (the memory */ + /* used by the stack will be accounted as a part of the tree level size */ + mem_target -= (unsigned long)MALLOC_OVERHEAD; + + /* + * Plot out how many subtree sizes we have at each level. We start by + * computing how much memory we'd use if we minimize each level + */ + unsigned subtree_size[MAX_HSS_LEVELS]; + unsigned subtree_levels[MAX_HSS_LEVELS]; + unsigned level_hash[MAX_HSS_LEVELS]; + unsigned level_height[MAX_HSS_LEVELS]; + unsigned hash_size[MAX_HSS_LEVELS]; + unsigned total_height = 0; + + /* Parse the parameter sets */ + for (i=0; ierror_code = hss_error_bad_param_set; + return 0; + } + + total_height += level_height[i]; /* Also track the number of */ + /* signatures we can generate with this parm set */ + } + + /* + * Select which subtree sizes that is faster, and fit within the memory + * we've been given. For the nonbottom levels, we always use what's the + * smallest for that particular tree height; there's no point in wasting + * extra memory to make them faster (in that each one can be done during + * the time the bottom level BUILDING subtrees don't need updating). + */ + size_t stack_usage = 0; + for (i=0; i mem_target) { + /* This would use more memory than we'd like; accept it if */ + /* either we have no solution, or it uses less memory than what */ + /* we've seen */ + if (search_status != nothing_yet && mem > best_mem) continue; + + /* This solution is the best so far (however, it doesn't fit) */ + search_status = found_overbudget; + } else { + /* This is within our budget; accept it if we haven't seen a */ + /* previous solution within our budget, or this uses fewer */ + /* levels than the previous solution */ + if (search_status == found_plenty_memory) { + if (sub_levels > best_levels) { + /* We've already seen a faster solution */ + continue; + } + if (sub_levels == best_levels && mem > best_mem) { + /* We've already seen an equally fast solution that */ + /* uses less memory */ + continue; + } + } + + /* This solution is the best so far (and it fits) */ + search_status = found_plenty_memory; + } + /* This is the best option so far; record it */ + best_j = j; + best_mem = mem; + best_levels = sub_levels; + best_stack_used = stack_used; + } + + if (search_status == nothing_yet) { + /* This can't really happen */ + hss_free_working_key(w); + info->error_code = hss_error_internal; + return 0; + } +#if 0 +printf( "Allocation = %ld\n", initial_mem_target - mem_target + best_mem ); /* DEBUG HACK */ +#endif + + subtree_size[i] = best_j; + subtree_levels[i] = (level_height[i] + best_j - 1) / best_j; + stack_usage += best_stack_used; + + unsigned char *stack; + if (stack_usage == 0) { + stack = NULL; /* Hey! No stack required */ + /* Avoid the malloc, as malloc(0) is allowed to fail */ + } else { + stack = malloc(stack_usage); + if (!stack) { + hss_free_working_key(w); + info->error_code = hss_error_out_of_memory; + return 0; + } + } + w->stack = stack; + size_t stack_index = 0; + + /* + * Ok, we've figured out the sizes for everything; now do the actual + * allocations + */ + for (i = 0; ierror_code = hss_error_out_of_memory; + return 0; + } + unsigned h0 = level_height[i]; + tree->level = h0; + tree->h = level_hash[i]; + tree->hash_size = hash_size[i]; + tree->lm_type = lm_type[i]; + tree->lm_ots_type = lm_ots_type[i]; + /* We'll initialize current_index from the private key */ + tree->max_index = (1L << tree->level) - 1; + tree->sublevels = subtree_levels[i]; + tree->subtree_size = subtree_size[i]; + unsigned top_subtree_size = h0 - (subtree_levels[i]-1)*subtree_size[i]; + tree->top_subtree_size = top_subtree_size; + + unsigned k; + for (j=0; jsubtree[j][k] = NULL; + w->tree[i] = tree; + + unsigned subtree_level = 0; + unsigned levels_below = h0; + for (j=0; jerror_code = hss_error_out_of_memory; + return 0; + } + + s->level = subtree_level; + s->levels_below = levels_below; + tree->subtree[j][k] = s; + if (k == ACTIVE_TREE) { + /* Active trees don't need no stack */ + s->stack = NULL; + } else if (levels_below == 0) { + /* Bottom level subtrees don't need no stack */ + s->stack = NULL; + } else { + s->stack = &stack[stack_index]; + stack_index += hash_size[i] * levels_below; + } + } + + subtree_level += height; + } + } + +/* SANITY CHECK */ + if (stack_index != stack_usage) { + hss_free_working_key(w); + info->error_code = hss_error_internal; + return 0; + } +/* SANITY CHECK */ + + /* Compute the max number of signatures we can generate */ + if (total_height > 64) total_height = 64; /* (bounded by 2**64) */ + w->max_count = ((sequence_t)2 << (total_height-1)) - 1; /* height-1 so */ + /* we don't try to shift by 64, and hit undefined behavior */ + + /* We use the count 0xffff..ffff to signify 'we've used up all our */ + /* signatures'. Make sure that is above max_count, even for */ + /* parameter sets that can literally generate 2**64 signatures (by */ + /* letting them generate only 2**64-1) */ + if (total_height == 64) w->max_count--; + + return w; +} + +void hss_free_working_key(struct hss_working_key *w) { + int i; + if (!w) return; + for (i=0; itree[i]; + if (tree) { + unsigned j, k; + for (j=0; jsubtree[j][k]); // IGNORE free-check + hss_zeroize( tree, sizeof *tree ); /* We have seeds here */ + } + free(tree); // IGNORE free-check + } + for (i=0; isigned_pk[i]); // IGNORE free-check + } + free(w->stack); // IGNORE free-check + hss_zeroize( w, sizeof *w ); /* We have secret information here */ + free(w); // IGNORE free-check +} diff --git a/src/sig_stfl/lms/external/hss_aux.c b/src/sig_stfl/lms/external/hss_aux.c new file mode 100644 index 0000000000..a53b73a42b --- /dev/null +++ b/src/sig_stfl/lms/external/hss_aux.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: MIT +/* + * This is the implementation of the aux data within the HSS tree + */ + +#include +#include "hss_aux.h" +#include "hss_internal.h" +#include "common_defs.h" +#include "lm_common.h" +#include "endian.h" +#include "hash.h" +#include "hss_zeroize.h" + +/* + * The structure of aux data + * + * The current format of the file is: + * [4 bytes of marker]: + * - bit 31 is set (to indicate that the aux data is nonempty; a 0 first byte + * indicates that, yes, we have no bananas); because we store the marker + * in bigendian format, this bit 31 is in the first byte. + * - bit i is set if we have the hashes for intermediate level i + * For each set bit i (in ascending sequence): + * - 1<= len_this_level) { + /* This level fits; add it */ + max_length -= len_this_level; + /* We also set the MSBit to signify that we're saving something */ + aux_level |= 0x80000000UL | ((aux_level_t)1<>= 1) { + if (aux_level & 1) { + temp->data[h] = (void *)aux_data; + aux_data += (size_t)size_hash << h; + } else { + temp->data[h] = 0; /* No data at this level */ + } + } + + /* Now, check if the data is valid */ + if (w) { + /* Check to see if the data is valid */ + size_t expected_len = (aux_data - orig_aux_data) + size_hash; + if (expected_len > len_aux_data) { + /* Either the first 4 bytes were messed up, or the file was */ + /* truncated */ + return 0; + } + if (len_aux_data < 4 + size_hash) return 0; + + /* Now, MAC the entire aux file */ + union hash_context ctx; + unsigned char key[ MAX_HASH ]; + compute_seed_derive( key, w->tree[0]->h, w->working_key_seed, &ctx ); + unsigned char expected_mac[ MAX_HASH ]; + compute_hmac( expected_mac, w->tree[0]->h, size_hash, &ctx, key, + orig_aux_data, aux_data - orig_aux_data ); + hss_zeroize( key, size_hash ); + hss_zeroize( &ctx, sizeof ctx ); + if (0 != memcmp_consttime( expected_mac, aux_data, size_hash)) { + /* The MAC did not agree; ignore the aux data */ + return 0; + } + } + return temp; +} + +/* + * This returns the amount of aux data we would use, given the maximum bound + * on how much aux data we are allowed, and the parameter sets + */ +size_t hss_get_aux_data_len(size_t max_length, + unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type) { + size_t len = 0; + LMS_UNUSED(levels); + if (!hss_optimal_aux_level( max_length, lm_type, lm_ots_type, &len )) { + return 1; /* 1 byte marker to say 'we're not using it */ + } + + return len; +} + +/* + * Save the marker within the aux data + */ +void hss_store_aux_marker( unsigned char *aux_data, aux_level_t aux_level ) { + if (aux_level == 0) { + /* Aux data doesn't help; mark it as unused */ + aux_data[AUX_DATA_MARKER] = NO_AUX_DATA; + } else { + put_bigendian( &aux_data[AUX_DATA_MARKER], aux_level, 4 ); + } +} + +/* + * This is called while we are building the initial top level Merkle tree (to + * compute the root). This is called for each internal node, and allows the + * aux data a chance to save the intermediate value + */ +void hss_save_aux_data( struct expanded_aux_data *data, unsigned level, + unsigned size_hash, merkle_index_t q, + const unsigned char *cur_val ) { + if (!data) return; /* We're not recording anything */ + if (!data->data[level]) return; /* We're not recording anything for */ + /* this level */ + + /* We are recording it; save a copy in the aux data */ + memcpy( data->data[level] + size_hash * q, cur_val, size_hash ); +} + +/* + * This generates the derived value that we'll use as a key the authenticate + * the aux data. We pass the ctx (rather than using a local one) so we have + * one less thing to zeroize + * + * We use a derived key (rather than using the seed directly) because the + * outer hash within the HMAC don't use the diversification factors that every + * other hash within this packet does; hence for HMAC, we use a key that + * is independent of every other hash used + */ +static void compute_seed_derive( unsigned char *result, unsigned hash, + const unsigned char *seed, union hash_context *ctx) { + hss_init_hash_context( hash, ctx ); + unsigned char prefix[ DAUX_PREFIX_LEN ]; + memset( prefix, 0, DAUX_D ); + SET_D( prefix + DAUX_D, D_DAUX ); + hss_update_hash_context( hash, ctx, prefix, sizeof prefix ); + hss_update_hash_context( hash, ctx, seed, SEED_LEN ); + hss_finalize_hash_context( hash, ctx, result ); + + hss_zeroize( &ctx, sizeof ctx ); +} + +static void xor_key( unsigned char *key, unsigned xor_val, unsigned len_key) { + unsigned i; + for (i = 0; idata[i]) { + total_length += (size_t)size_hash << i; + if (!aux) { + aux = data->data[i] - 4; + } + } + } + if (aux) { + compute_hmac( aux+total_length, hash, size_hash, &ctx, aux_seed, + aux, total_length ); + } + + hss_zeroize( &ctx, sizeof ctx ); + hss_zeroize( aux_seed, size_hash ); +} + +/* + * This is called when we need to use aux data; it checks to see if we've + * stored the nodes within the aux data; if we have, it extracts them, + * and returns true + */ +bool hss_extract_aux_data(const struct expanded_aux_data *aux, unsigned level, + const struct hss_working_key *w, unsigned char *dest, + merkle_index_t node_offset, /* Offset of node on this level */ + merkle_index_t node_count) { /* # of nodes to restore */ + if (!aux) return false; /* No aux data */ + if (!aux->data[level]) return false; /* We don't have that specific */ + /* level saved */ + unsigned hash_size = w->tree[0]->hash_size; + + /* We do have the data; copy it to the destination */ + memcpy( dest, + aux->data[level] + node_offset*hash_size, + node_count * hash_size ); + + return true; +} diff --git a/src/sig_stfl/lms/external/hss_aux.h b/src/sig_stfl/lms/external/hss_aux.h new file mode 100644 index 0000000000..8e5386b5b3 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_aux.h @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_AUX_H_ ) +#define HSS_AUX_H_ + +/* + * This is the internal API to the subsystem that deals with aux data + * This should not be included by files outside this subsystem + */ + +#include "common_defs.h" +#include +#include +#include "lms_namespace.h" + +struct hss_working_key; + +/* This is a bitmap that lists which aux levels we have */ +typedef uint_fast32_t aux_level_t; + +/* This is the expanded version of the aux data */ +struct expanded_aux_data { + unsigned char *data[ MAX_MERKLE_HEIGHT+1 ]; +}; + +/* + * These are some internal routines that handle aux data + */ +/* Internal function used to compute the optimal aux level */ +aux_level_t hss_optimal_aux_level( size_t max_length, + const param_set_t *lm_type, + const param_set_t *lm_ots_type, + size_t *actual_len ); + +/* Generate pointers into a saved aux data */ +/* If w is provided, we do sanity checking on the data within aux_data */ +struct expanded_aux_data *hss_expand_aux_data( const unsigned char *aux_data, + size_t len_aux_data, + struct expanded_aux_data *temp, unsigned size_hash, + struct hss_working_key *w ); + +/* + * Save the marker within the aux data + */ +void hss_store_aux_marker( unsigned char *aux_data, aux_level_t aux_level ); + +/* Save an intermediate node */ +void hss_save_aux_data( struct expanded_aux_data *data, unsigned level, + unsigned size_hash, merkle_index_t q, + const unsigned char *cur_val ); + +/* Do the final touches on the aux data */ +void hss_finalize_aux_data(struct expanded_aux_data *data, + unsigned size_hash, unsigned hash, + const unsigned char *seed); + +/* Get a set of intermediate nodes from the aux data */ +bool hss_extract_aux_data(const struct expanded_aux_data *aux, unsigned level, + const struct hss_working_key *w, unsigned char *dest, + merkle_index_t node_offset, merkle_index_t node_count); + +#endif /* HSS_AUX_H_ */ diff --git a/src/sig_stfl/lms/external/hss_common.c b/src/sig_stfl/lms/external/hss_common.c new file mode 100644 index 0000000000..4c764d6650 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_common.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that is common between an HSS verifier, and a full HSS + * implementation that both signs and verifies + */ +#include +#include "common_defs.h" +#include "hss_common.h" +#include "lm_common.h" +#include "config.h" +/* + * Get the length of the public key, given this particular parameter set + */ +size_t hss_get_public_key_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type) { + LMS_UNUSED(lm_ots_type); + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) return 0; + + size_t first_pubkey = lm_get_public_key_len(lm_type[0]); + if (first_pubkey == 0) return 0; + + return 4 + first_pubkey; +} + +/* + * Get the length of a signature, given this particular parameter set + */ +size_t hss_get_signature_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type) { + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) return 0; + + unsigned i; + size_t tot_len = 4; + for (i=0; i 0 */ + if (i > 0) { + size_t next_pub_len = lm_get_public_key_len(lm_type[i]); + if (next_pub_len == 0) return 0; + tot_len += next_pub_len; + } + } + return tot_len; +} diff --git a/src/sig_stfl/lms/external/hss_common.h b/src/sig_stfl/lms/external/hss_common.h new file mode 100644 index 0000000000..17729a6a97 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_common.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_COMMON_H_ ) +#define HSS_COMMON_H_ + +#include +#include "common_defs.h" +#include "lms_namespace.h" + +/* + * This returns the length of the public key for the given parameter set + */ +size_t hss_get_public_key_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type); +#define HSS_MAX_PUBLIC_KEY_LEN (4 + 8 + ((I_LEN+3) & ~3) + MAX_HASH) + +/* + * This returns the length of the signature for the given parameter set + */ +size_t hss_get_signature_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type); + +#endif /* HSS_COMMON_H_ */ diff --git a/src/sig_stfl/lms/external/hss_compute.c b/src/sig_stfl/lms/external/hss_compute.c new file mode 100644 index 0000000000..f4b1f3c1cd --- /dev/null +++ b/src/sig_stfl/lms/external/hss_compute.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT +/* + * This includes some computation methods that are shared between different + * subsystems of the HSS signature package + */ + +#include +#include "hss_internal.h" +#include "hss.h" +#include "hash.h" +#include "hss_thread.h" +#include "lm_ots_common.h" +#include "lm_ots.h" +#include "endian.h" +#include "hss_derive.h" + +/* Count the number of 1 bits at the end (lsbits) of the integer */ +/* Do it in the obvious way; straightline code may be faster (no */ +/* unpredictable jumps, which are costly), but that would be less scrutable */ +/* (and this code is "fast enough") */ +static int trailing_1_bits(merkle_index_t n) { + int i; + for (i=0; n&1; n>>=1, i++) + ; + return i; +} + +/* + * Compute the value of an internal node within a Merkle tree + */ +static enum hss_error_code hss_compute_internal_node( unsigned char *dest, + merkle_index_t node_num, + const unsigned char *seed, + param_set_t lm_type, + param_set_t lm_ots_type, + unsigned h, + unsigned leaf_level, + const unsigned char *I) { + unsigned hash_size = hss_hash_length(h); + + /* We're store intermediate nodes here */ + unsigned char stack[ MAX_HASH * MAX_MERKLE_HEIGHT]; + + merkle_index_t tree_size = (merkle_index_t)1 << leaf_level; + merkle_index_t r = node_num; + int levels_to_bottom = 0; + if (r == 0) return hss_error_internal; /* So no to infinite loops */ + while (r < tree_size) { + r <<= 1; + levels_to_bottom++; + } + merkle_index_t q = r - tree_size; + + merkle_index_t i; + unsigned ots_len = (unsigned)lm_ots_get_public_key_len(lm_ots_type); + unsigned char pub_key[ LEAF_MAX_LEN ]; + memcpy( pub_key + LEAF_I, I, I_LEN ); + SET_D( pub_key + LEAF_D, D_LEAF ); + + struct seed_derive derive; + if (!hss_seed_derive_init( &derive, lm_type, lm_ots_type, + I, seed)) { + return hss_error_bad_param_set; + } + + for (i=0;; i++, r++, q++) { + /* Generate the next OTS public key */ + hss_seed_derive_set_q( &derive, q ); + if (!lm_ots_generate_public_key(lm_ots_type, I, + q, &derive, pub_key + LEAF_PK, ots_len)) { + return hss_error_bad_param_set; /* The only reason the above */ + /* could fail */ + } + + /* + * For the subtree which this leaf node forms the final piece, put the + * destination to where we'll want it, either on the stack, or if this + * is the final piece, to where the caller specified + */ + unsigned char *current_buf; + int stack_offset = trailing_1_bits( i ); + if (stack_offset == levels_to_bottom) { + current_buf = dest; + } else { + current_buf = &stack[stack_offset * hash_size ]; + } + + /* Hash it to form the leaf node */ + put_bigendian( pub_key + LEAF_R, r, 4); + union hash_context ctx; + hss_hash_ctx( current_buf, h, &ctx, pub_key, LEAF_LEN(hash_size) ); + + /* Work up the stack, combining right nodes with the left nodes */ + /* that we've already computed */ + int sp; + for (sp = 1; sp <= stack_offset; sp++) { + hss_combine_internal_nodes( current_buf, + &stack[(sp-1) * hash_size], current_buf, + h, I, hash_size, + r >> sp ); + } + + /* We're not at a left branch, or at the target node */ + + /* Because we've set current_buf to point to where we want to place */ + /* the result of this loop, we don't need to memcpy it */ + + /* Check if this was the last leaf (and so we've just computed the */ + /* target node) */ + if (stack_offset == levels_to_bottom) { + /* We're at the target node; the node we were asked to compute */ + /* We've already placed the value into dest, so we're all done */ + break; + } + } + + hss_seed_derive_done( &derive ); + + return hss_error_none; +} + +/* + * Combine adjacent left and right nodes within the Merkle tree + * together + */ +void hss_combine_internal_nodes( unsigned char *dest, + const unsigned char *left_node, const unsigned char *right_node, + int h, const unsigned char *I, unsigned hash_size, + merkle_index_t node_num) { + unsigned char hash_val[ INTR_MAX_LEN ]; + memcpy( hash_val + INTR_I, I, I_LEN ); + put_bigendian( hash_val + INTR_R, node_num, 4 ); + SET_D( hash_val + INTR_D, D_INTR ); + + memcpy( hash_val + INTR_PK, left_node, hash_size ); + memcpy( hash_val + INTR_PK + hash_size, right_node, hash_size ); + union hash_context ctx; + hss_hash_ctx( dest, h, &ctx, hash_val, INTR_LEN(hash_size) ); +} + +/* + * This computes an array of intermediate Merkle nodes given by data + * This may be run in a worker (non-main) thread + */ +void hss_gen_intermediate_tree(const void *data, + struct thread_collection *col) { + const struct intermed_tree_detail *d = data; + unsigned hash_len = hss_hash_length(d->h); + unsigned i; + + for (i=0; inode_count; i++) { + unsigned char result[ MAX_HASH ]; + enum hss_error_code status = hss_compute_internal_node( result, + d->node_num + i, + d->seed, + d->lm_type, + d->lm_ots_type, + d->h, + d->tree_height, + d->I); + + /* Report the results */ + hss_thread_before_write(col); + if (status == hss_error_none) { + /* Copy out the resulting hash */ + memcpy( d->dest + i*hash_len, result, hash_len ); + } else { + /* Something went wrong; report the bad news */ + *d->got_error = status; + hss_thread_after_write(col); /* No point in working more */ + return; + } + hss_thread_after_write(col); + } +} diff --git a/src/sig_stfl/lms/external/hss_derive.c b/src/sig_stfl/lms/external/hss_derive.c new file mode 100644 index 0000000000..d978fc5a66 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_derive.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: MIT +/* + * This is the file that contains the routines that generate various 'random' + * values from the master seed. + * + * Values generated by this routine: + * - OTS private keys + * - Message randomizers (the random value we hash with the message when we + * sign it) + * - I values + * - SEED values (which are the secret to derive all the above for a specific + * LMS tree) + * + * We do things determanisticly, rather than picking things from random, so + * that if we reload from scratch, the values we use after the reload are + * consistent with what we used previously + * + * This provides several different possible derivation methods; they can be + * selected by setting SECRET_METHOD in config.h + */ +#include +#include "hss_derive.h" +#include "hss_internal.h" +#include "hash.h" +#include "endian.h" +#include "config.h" + +#if SECRET_METHOD == 2 + /* We use a hash function based on the parameter set */ +#include "lm_common.h" /* To get the prototype for the parameter set -> */ + /* hash function mapping */ +#else +#if SEED_LEN == 32 +#define HASH HASH_SHA256 /* We always use SHA-256 to derive seeds */ +#else +#error We need to define a hash function for this seed length +#endif +#endif + +#if SECRET_METHOD == 0 || SECRET_METHOD == 2 +/* + * This is the method of deriving LM-OTS keys that conforms to the + * Appendix A method + * As you can see, it's fairly simple + */ + +/* This creates a seed derivation object */ +bool hss_seed_derive_init( struct seed_derive *derive, + param_set_t lm, param_set_t ots, + const unsigned char *I, const unsigned char *seed ) { + derive->I = I; + derive->master_seed = seed; + LMS_UNUSED(ots); + /* q, j will be set later */ +#if SECRET_METHOD == 2 + /* Grab the hash function to use */ + if (!lm_look_up_parameter_set(lm, &derive->hash, &derive->m, 0)) { + return false; + } + + /* Note: currently, this assumes that the hash length is always 256 */ + /* bits; error out if that isn't the case */ + if (derive->m != SEED_LEN) { + return false; + } +#endif + + return true; +} + +/* This sets the internal 'q' value for seed derivation object */ +void hss_seed_derive_set_q( struct seed_derive *derive, merkle_index_t q ) { + derive->q = q; +} + +/* This sets the internal 'j' value for seed derivation object */ +void hss_seed_derive_set_j( struct seed_derive *derive, unsigned j ) { + derive->j = j; +} + + +/* This derives the current seed value. If increment_j is set, it'll then */ +/* reset the object to the next j value */ +void hss_seed_derive( unsigned char *seed, struct seed_derive *derive, + bool increment_j ) { + unsigned char buffer[ PRG_MAX_LEN ]; + memcpy( buffer + PRG_I, derive->I, I_LEN ); + put_bigendian( buffer + PRG_Q, derive->q, 4 ); + put_bigendian( buffer + PRG_J, derive->j, 2 ); + buffer[PRG_FF] = 0xff; + memcpy( buffer + PRG_SEED, derive->master_seed, SEED_LEN ); + +#if SECRET_METHOD == 2 + int hash = derive->hash; /* Our the parameter set's hash function */ +#else + int hash = HASH; /* Use our standard one */ +#endif + + hss_hash( seed, hash, buffer, PRG_LEN(SEED_LEN) ); + + hss_zeroize( buffer, PRG_LEN(SEED_LEN) ); + + if (increment_j) derive->j += 1; +} + +/* This is called when we're done with a seed derivation object */ +void hss_seed_derive_done( struct seed_derive *derive ) { + /* No secrets here */ + LMS_UNUSED(derive); +} + +#elif SECRET_METHOD == 1 +/* + * This is a method of deriving LM-OTS keys that tries to be more + * side-channel resistant; in particular, we never include any + * specific secret value in more than 2**SECRET_MAX distinct + * hashes. + * We do this by deriving subseeds using a tree-based structure; + * each node in the tree has up to 2**SECRET_MAX children, and we use any + * seed within the node (including the root) in no other hash. + * We actually have two levels of trees; one based on q (Merkle tree index), + * the other based on j (Winternitz digit); we could design a single level + * tree that could incorporate both, but it'd be more complex + * + * Much of the complexity that does exist is there to avoid recomputation + */ +#include "lm_common.h" +#include "lm_ots_common.h" +static unsigned my_log2(merkle_index_t n); + +/* This creates a seed derivation object */ +bool hss_seed_derive_init( struct seed_derive *derive, + param_set_t lm, param_set_t ots, + const unsigned char *I, const unsigned char *seed ) { + derive->I = I; + derive->master_seed = seed; + + /* These parameter sets will define the size of the trees we'll use */ + unsigned height, p; + if (!lm_look_up_parameter_set(lm, 0, 0, &height) || + !lm_ots_look_up_parameter_set(ots, 0, 0, 0, &p, 0)) { + return false; + } + + p += NUM_ARTIFICIAL_SEEDS; /* We use one artifical value for the */ + /* randomizer and two artificial values to generate seed, I */ + /* for child trees */ + + /* Compute the number of r-levels we have */ + derive->q_levels = (height + SECRET_MAX - 1)/SECRET_MAX; + + /* And which bit to set when converting 'q' to 'r' */ + derive->r_mask = (merkle_index_t)1 << height; + + /* Compute the number of j-levels we have */ + unsigned j_height = my_log2(p); + derive->j_levels = (j_height + SECRET_MAX - 1)/SECRET_MAX; + + /* And which bit to set when writing q values into the hash */ + derive->j_mask = 1 << j_height; + + /* We reset the current 'q' value to am impossible value; we do this so */ + /* that the initial 'q' value given to use by the application will */ + /* rebuild the entire path through the tree */ + derive->q = derive->r_mask; + + return true; +} + +/* This sets the internal 'q' value for seed derivation object */ +/* This also updates our internal q-path (the q_index/q_seed arrays) */ +/* to reflect the new 'q' value, while minimizing the number of hashes */ +/* done (by reusing as much of the previous path as possible) */ +void hss_seed_derive_set_q( struct seed_derive *derive, merkle_index_t q ) { + merkle_index_t change = q ^ derive->q; + derive->q = q; + unsigned bits_change = my_log2(change); + unsigned q_levels = derive->q_levels; + + /* levels_change will be the number of levels of the q-tree we'll */ + /* need to recompute */ + unsigned levels_change = (bits_change + SECRET_MAX - 1) / SECRET_MAX; + if (levels_change > q_levels) levels_change = q_levels; + + int i; + union hash_context ctx; + unsigned char buffer[ QTREE_MAX_LEN ]; + merkle_index_t r = q | derive->r_mask; + + for (i = levels_change; i > 0; i--) { + int j = q_levels - i; + int shift = (i-1) * SECRET_MAX; + + memcpy( buffer + QTREE_I, derive->I, I_LEN ); + put_bigendian( buffer + QTREE_Q, r >> shift, 4 ); + SET_D( buffer + QTREE_D, D_QTREE ); + if (j == 0) { + memcpy( buffer + QTREE_SEED, derive->master_seed, SEED_LEN ); + } else { + memcpy( buffer + QTREE_SEED, derive->q_seed[j-1], SEED_LEN ); + } + + hss_hash_ctx( derive->q_seed[j], HASH, &ctx, buffer, QTREE_LEN ); + } + + hss_zeroize( buffer, PRG_LEN(SEED_LEN) ); + hss_zeroize( &ctx, sizeof ctx ); +} + +/* Helper function to recompute the j_seed[i] value, based on the */ +/* j_value[i] already set */ +/* ctx, buffer are passed are areas this function can use; we reuse those */ +/* areas so we need to zeroize those buffers only once */ +static void set_j_seed( struct seed_derive *derive, int i, + union hash_context *ctx, unsigned char *buffer) { + + memcpy( buffer + PRG_I, derive->I, I_LEN ); + put_bigendian( buffer + PRG_Q, derive->q, 4 ); + put_bigendian( buffer + PRG_J, derive->j_value[i], 2 ); + buffer[PRG_FF] = 0xff; + if (i == 0) { + /* The root of this tree; it gets its seed from the bottom level */ + /* of the q-tree */ + memcpy( buffer + PRG_SEED, derive->q_seed[ derive->q_levels-1], + SEED_LEN ); + } else { + /* Non-root node; it gets its seed from its parent */ + memcpy( buffer + PRG_SEED, derive->j_seed[i-1], SEED_LEN ); + } + + hss_hash_ctx( derive->j_seed[i], HASH, ctx, buffer, PRG_LEN(SEED_LEN) ); +} + +/* This sets the internal 'j' value for seed derivation object */ +/* This computes the entire path to the 'j' value. Because this is used */ +/* immediately after resetting the q value, we don't try to reuse the */ +/* previous hashes (as there won't be anything there we could reuse) */ +/* Note that we don't try to take advantage of any preexisting hashes */ +/* in the j_seed array; we don't bother because this function is typically */ +/* used only immediately after a set_q call, and so there aren't any */ +/* hashes we could take advantage of */ +void hss_seed_derive_set_j( struct seed_derive *derive, unsigned j ) { + int i; + unsigned j_levels = derive->j_levels; + unsigned shift = SECRET_MAX * j_levels; + + unsigned j_mask = derive->j_mask; + j &= j_mask-1; /* Set the high-order bit; clear any bits above that */ + j |= j_mask; /* This ensures that when we do the hashes, that the */ + /* prefix for the hashes at two different levels of the */ + /* tree are distinct */ + + union hash_context ctx; + unsigned char buffer[ PRG_MAX_LEN ]; + + for (i = 0; ij_value[i] = (j >> shift); + set_j_seed( derive, i, &ctx, buffer ); + } + + hss_zeroize( &ctx, sizeof ctx ); + hss_zeroize( buffer, PRG_LEN(SEED_LEN) ); +} + +/* This derives the current seed value (actually, we've already computed */ +/* it); we just need to copy it to the buffer) */ +/* If increment_j is set, it'll then reset the object to the next j value */ +/* (which means incrementally computing that path) */ +void hss_seed_derive( unsigned char *seed, struct seed_derive *derive, + bool increment_j ) { + memcpy( seed, derive->j_seed[ derive->j_levels - 1], SEED_LEN ); + + if (increment_j) { + int i; + + /* Update the j_values, and figure out which hashes we'll need */ + /* to recompute */ + for (i = derive->j_levels-1;; i--) { + unsigned index = derive->j_value[i]; + index += 1; + derive->j_value[i] = index; + if (0 != (index & SECRET_MAX_MASK)) { + /* The increment didn't cause a carry to the next level; */ + /* we can stop propogating the increment here (and we */ + /* also know this is the top level that we need to */ + /* recompute the hashes */ + break; + } + if (i == 0) { + /* This is the top level; stop here */ + break; + } + } + + /* Recompute the hashes that need updating; we need to do it */ + /* top-down, as each hash depends on the previous one */ + union hash_context ctx; + unsigned char buffer[ PRG_MAX_LEN ]; + for (; i < derive->j_levels; i++) { + set_j_seed( derive, i, &ctx, buffer ); + } + hss_zeroize( &ctx, sizeof ctx ); + hss_zeroize( buffer, PRG_LEN(SEED_LEN) ); + } +} + +/* This is called when we're done with a seed derivation object */ +/* This makes sure any secret values are zeroized */ +void hss_seed_derive_done( struct seed_derive *derive ) { + /* These values are secret, and should never be leaked */ + hss_zeroize( derive->q_seed, sizeof derive->q_seed ); + hss_zeroize( derive->j_seed, sizeof derive->j_seed ); +} + +static unsigned my_log2(merkle_index_t n) { + unsigned lg; + for (lg = 0; n > 0; lg++) n >>= 1; + return lg; +} + +#else + +#error Unknown secret method + +#endif diff --git a/src/sig_stfl/lms/external/hss_derive.h b/src/sig_stfl/lms/external/hss_derive.h new file mode 100644 index 0000000000..4886ab3f6a --- /dev/null +++ b/src/sig_stfl/lms/external/hss_derive.h @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_DERIVE_H_ ) +#define HSS_DERIVE_H_ + +#include "common_defs.h" + +#include "config.h" +#include "lms_namespace.h" + +#if SECRET_MAX > 31 +#error The code is not designed for a SECRET_MAX that high +#endif +#define SECRET_MAX_MASK (((merkle_index_t)1 << SECRET_MAX) - 1) + +struct seed_derive { + const unsigned char *I; + const unsigned char *master_seed; + merkle_index_t q; + unsigned j; +#if SECRET_METHOD == 2 + unsigned hash; /* Hash function to use */ + unsigned m; /* Length of hash function */ +#endif + +#if SECRET_METHOD == 1 + unsigned q_levels, j_levels; + merkle_index_t r_mask; + unsigned j_mask; +#define MAX_Q_HEIGHT ((MAX_MERKLE_HEIGHT + SECRET_MAX - 1) / SECRET_MAX) +#define MAX_J_HEIGHT (( 9 + SECRET_MAX - 1) / SECRET_MAX) + /* '9' is the number of bits a maximum 'p' can take up */ + + unsigned j_value[MAX_J_HEIGHT]; /* these are the values we insert */ + /* into the hash. The lower SECRET_MAX bits are which child of */ + /* the parent it is; the higher bits indicate the parents' */ + /* identities */ + + unsigned char q_seed[MAX_Q_HEIGHT][SEED_LEN]; + unsigned char j_seed[MAX_Q_HEIGHT][SEED_LEN]; +#endif +}; + +bool hss_seed_derive_init( struct seed_derive *derive, + param_set_t lm, param_set_t ots, + const unsigned char *I, const unsigned char *seed ); + +/* This sets the internal 'q' value */ +/* If we've already have a 'q' value set, it'll try to minimize the number */ +/* of hashes done */ +/* Once you've done that, you'll need to reset the 'h' */ +void hss_seed_derive_set_q( struct seed_derive *derive, merkle_index_t q ); + +/* This sets the internal 'j' value */ +void hss_seed_derive_set_j( struct seed_derive *derive, unsigned j ); + +#define NUM_ARTIFICIAL_SEEDS 3 /* 3 seeds are listed below */ + /* This is the j value used when we're deriving the seed value */ + /* for child Merkle trees */ +#define SEED_CHILD_SEED (~1) + /* This is the j value used when we're deriving the I value */ + /* used; either in the context of the parent tree, or of this tree */ +#define SEED_CHILD_I (SEED_CHILD_SEED + 1) + /* This is the j value used when we're asking for the randomizer C */ + /* for signing a message */ +#define SEED_RANDOMIZER_INDEX (~2) + +/* This generates the current seed. If increment_j is set, this will set */ +/* up for the next j value */ +void hss_seed_derive( unsigned char *seed, struct seed_derive *derive, + bool increment_j ); + +/* This needs to be called when we done with a seed_derive */ +/* That structure contains keying data, this makes sure those are cleaned */ +void hss_seed_derive_done( struct seed_derive *derive ); + +#endif /* HSS_DERIVE_H_ */ diff --git a/src/sig_stfl/lms/external/hss_generate.c b/src/sig_stfl/lms/external/hss_generate.c new file mode 100644 index 0000000000..28fcc9eaee --- /dev/null +++ b/src/sig_stfl/lms/external/hss_generate.c @@ -0,0 +1,933 @@ +// SPDX-License-Identifier: MIT +/* + * This is the routine that generates the ephemeral ("working") key from the + * short private value. It builds all the various current, building and + * next subtrees for the various levels (to at least the extent required + * for the current count within the key). + * + * The code is made considerably more complex because we try to take + * advantage of parallelism. To do this, we explicitly list the parts + * of the subtrees we need to build (which is most of the computation), and + * have different worker threads build the various parts, + * + * However, it turns out that this is sometimes insufficient; sometimes, + * the work consists of one or two expensive nodes (perhaps the top level + * subtree), and a lot of comparatively cheap ones; in this case, we'd have + * most of our threads go through the cheap ones quickly, and have one or + * two threads working on the expensive one, and everyone will end up waiting + * for that. To mitigate that, we attempt to subdivide the most expensive + * requests; instead of having a single thread computing the expensive node, + * we may issue four or eight threads to compute the nodes two or three + * levels below (and have the main thread do the final computation when + * all the threads are completed). + * + * This works out pretty good; however man does add complexity :-( + */ +#include +#include +#include "hss.h" +#include "hss_internal.h" +#include "hss_aux.h" +#include "hash.h" +#include "hss_thread.h" +#include "hss_reserve.h" +#include "lm_ots_common.h" +#include "endian.h" + +#define DO_FLOATING_POINT 1 /* If clear, we avoid floating point operations */ + /* You can turn this off for two reasons: */ + /* - Your platform doesn't implement floating point */ + /* - Your platform is single threaded (we use floating point to figure */ + /* out how to split up tasks between threads; if the same thread */ + /* will do all the work, dividing it cleverly doesn't buy anything */ + /* (and that's a quite a bit of code that gets eliminated) */ + /* On the other hand, if you are threaded, you'd really want this if */ + /* at all possible; without this, one thread ends up doing the bulk of */ + /* the work, and so we end up going not that much faster than single */ + /* threaded mode */ + +/* + * This routine assumes that we have filled in the bottom node_count nodes of + * the subtree; it tries to compute as many internal nodes as possible + */ +static void fill_subtree(const struct merkle_level *tree, + struct subtree *subtree, + merkle_index_t node_count, + const unsigned char *I) { + if (node_count <= 1) return; /* If we can't compute any more nodes, */ + /* don't bother trying */ + unsigned h_subtree = (subtree->level == 0) ? tree->top_subtree_size : + tree->subtree_size; + + /* Index into the node array where we're starting */ + merkle_index_t lower_index = ((merkle_index_t)1 << h_subtree) - 1; + + unsigned hash_size = tree->hash_size; + + /* The node identier (initially of the bottom left node of the */ + /* subtree */ + merkle_index_t node_id = (((merkle_index_t)1 << tree->level) + + subtree->left_leaf) + >> subtree->levels_below; + + /* Fill in as many levels of internal nodes as possible */ + int sublevel; + for (sublevel = h_subtree-1; sublevel >= 0; sublevel--) { + node_count >>= 1; + if (node_count == 0) break; /* Can't do any more */ + merkle_index_t prev_lower_index = lower_index; + lower_index >>= 1; + node_id >>= 1; + + merkle_index_t i; + for (i=0; inodes[ hash_size *(lower_index + i)], + &subtree->nodes[ hash_size *(prev_lower_index + 2*i)], + &subtree->nodes[ hash_size *(prev_lower_index + 2*i+1)], + tree->h, I, hash_size, + node_id + i); + } + } +} + +/* + * This routine takes the 2**num_level hashes, and computes up num_level's, + * returning the value of the top node. This is sort of like fill_tree, + * except that it returns only the top node, not the intermediate ones + * One warning: this does modify the passed value of hashes; our current + * caller doesn't care about that. + */ +static void hash_subtree( unsigned char *dest, + unsigned char *hashes, + unsigned num_level, merkle_index_t node_index, + unsigned hash_size, + int h, const unsigned char *I) { + + /* Combine the nodes to form the tree, until we get to the two top nodes */ + /* This will overwrite the hashes array; that's OK, because we don't */ + /* need those anymore */ + for (; num_level > 1; num_level--) { + unsigned i; + merkle_index_t this_level_node_index = node_index << (num_level-1); + for (i = 0; i < ((unsigned)1<<(num_level-1)); i++) { + hss_combine_internal_nodes( + &hashes[ hash_size * i ], + &hashes[ hash_size * (2*i) ], + &hashes[ hash_size * (2*i + 1) ], + h, I, hash_size, + this_level_node_index + i); + } + } + + /* Combine the top two nodes to form our actual target */ + hss_combine_internal_nodes( + dest, + &hashes[ 0 ], + &hashes[ hash_size ], + h, I, hash_size, + node_index); +} + +#if DO_FLOATING_POINT +/* + * This structure is a note reminding us that we've decided to split this + * init_order into several requests, which can be run on independent threads + */ +struct sub_order { + unsigned num_hashes; /* The number of hashes this suborder is */ + /* split up into */ + unsigned level; /* Levels deep into the tree we go */ + merkle_index_t node_num_first_target; /* The node number of the left */ + /* most hash that we're standing in for */ + unsigned char h[1]; /* The hashes go here; we'll malloc */ + /* enough space to let them fit */ +}; +#endif + +/* + * This is an internal request to compute the bottom N nodes (starting from the + * left) of a subtree (and to contruct the internal nodes that based solely on + * those N leaf nodes) + */ +struct init_order { + const struct merkle_level *tree; + struct subtree *subtree; + merkle_index_t count_nodes; /* # of bottom level nodes we need to */ + /* generate */ + const unsigned char *prev_node; /* For nonbottom subtrees, sometimes one */ + /* of the nodes is the root of the */ + /* next level subtree that we compute in */ + /* its entirety. If so, this is a pointer */ + /* to where we will find the precomputed */ + /* value. This allows us to avoid */ + /* computing that specific node */ + merkle_index_t prev_index; /* This is the index of the */ + /* precomputed node, where 0 is the */ + /* leftmost bottom node of this subtree */ + char next_tree; /* If clear, we do this on the current */ + /* tree level (seed, I values); if set, */ + /* we do this on the next */ + char already_computed_lower; /* If set, we've already computed the */ + /* lower nodes (and all we need to do is */ + /* fill the upper); no need to ask the */ + /* threads do do anything */ + /* We may still need to build the */ + /* interiors of the subtrees, of course */ +#if DO_FLOATING_POINT + float cost; /* Approximate number of hash compression */ + /* operations per node */ + struct sub_order *sub; /* If non-NULL, this gives details on how */ + /* we want to subdivide the order between */ + /* different threads */ +#endif +}; + +#if DO_FLOATING_POINT + /* This comparison function sorts the most expensive orders first */ +static int compare_order_by_cost(const void *a, const void *b) { + const struct init_order *p = a; + const struct init_order *q = b; + + if (p->cost > q->cost) return -1; + if (p->cost < q->cost) return 1; + + return 0; +} +#else + /* This comparison function sorts the higher level subtrees first */ +static int compare_order_by_subtree_level(const void *a, const void *b) { + const struct init_order *p = a; + unsigned p_subtree = p->subtree->level; + const struct init_order *q = b; + unsigned q_subtree = q->subtree->level; + + if (p_subtree < q_subtree) return -1; + if (p_subtree > q_subtree) return 1; + + return 0; +} +#endif + +#if DO_FLOATING_POINT +static float estimate_total_cost(struct init_order *order, + unsigned count_order); + +/* + * This is a simple minded log function, returning an int. Yes, using the + * built-in log() function would be easier, however I don't want to pull in + * the -lm library just for this + */ +static unsigned my_log2(float f) { +#define MAX_LOG 10 + unsigned n; + for (n=1; f > 2 && n < MAX_LOG; n++) + f /= 2; + return n; +} +#endif + +/* + * This is the point of this entire file. + * + * It fills in an already allocated working key, based on the private key + */ +bool hss_generate_working_key( + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + const unsigned char *aux_data, size_t len_aux_data, /* Optional */ + struct hss_working_key *w, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + + if (!w) { + info->error_code = hss_error_got_null; + return false; + } + w->status = hss_error_key_uninitialized; /* In case we detect an */ + /* error midway */ + + if (!read_private_key && !context) { + info->error_code = hss_error_no_private_buffer; + return false; + } + + /* Read the private key */ + unsigned char private_key[ PRIVATE_KEY_LEN ]; + if (read_private_key) { + if (!read_private_key( private_key, PRIVATE_KEY_LEN, context)) { + info->error_code = hss_error_private_key_read_failed; + goto failed; + } + } else { + memcpy( private_key, context, PRIVATE_KEY_LEN ); + } + + /* + * Make sure that the private key and the allocated working key are + * compatible; that the working_key was initialized with the same + * parameter set + */ + { + if (w->levels > MAX_HSS_LEVELS) { + info->error_code = hss_error_internal; + goto failed; + } + unsigned char compressed[PRIVATE_KEY_PARAM_SET_LEN]; + param_set_t lm_type[MAX_HSS_LEVELS], lm_ots_type[MAX_HSS_LEVELS]; + unsigned i; + for (i=0; ilevels; i++) { + lm_type[i] = w->tree[i]->lm_type; + lm_ots_type[i] = w->tree[i]->lm_ots_type; + } + + if (!hss_compress_param_set( compressed, w->levels, + lm_type, lm_ots_type, + sizeof compressed )) { + /* We're passed an unsupported param set */ + info->error_code = hss_error_internal; + goto failed; + } + if (0 != memcmp( private_key + PRIVATE_KEY_PARAM_SET, compressed, + PRIVATE_KEY_PARAM_SET_LEN )) { + /* The working set was initiallized with a different parmset */ + info->error_code = hss_error_incompatible_param_set; + goto failed; + } + } + + sequence_t current_count = get_bigendian( + private_key + PRIVATE_KEY_INDEX, PRIVATE_KEY_INDEX_LEN ); + if (current_count > w->max_count) { + info->error_code = hss_error_private_key_expired; /* Hey! We */ + goto failed; /* can't generate any more signatures */ + } + hss_set_reserve_count(w, current_count); + + memcpy( w->private_key, private_key, PRIVATE_KEY_LEN ); + + /* Initialize all the levels of the tree */ + + /* Initialize the current count for each level (from the bottom-up) */ + sequence_t i; + sequence_t count = current_count; + for (i = w->levels; i >= 1 ; i--) { + struct merkle_level *tree = w->tree[i-1]; + unsigned index = count & tree->max_index; + count >>= tree->level; + tree->current_index = index; + } + + /* Initialize the I values */ + for (i = 0; i < w->levels; i++) { + struct merkle_level *tree = w->tree[i]; + + /* Initialize the I, I_next elements */ + if (i == 0) { + /* The root seed, I value is derived from the secret key */ + hss_generate_root_seed_I_value( tree->seed, tree->I, + private_key+PRIVATE_KEY_SEED ); + /* We don't use the I_next value */ + } else { + /* The seed, I is derived from the parent's values */ + + /* Where we are in the Merkle tree */ + struct merkle_level *parent = w->tree[i-1]; + merkle_index_t index = parent->current_index; + + hss_generate_child_seed_I_value( tree->seed, tree->I, + parent->seed, parent->I, + index, parent->lm_type, + parent->lm_ots_type ); + /* The next seed, I is derived from either the parent's I */ + /* or the parent's next value */ + if (index == tree->max_index) { + hss_generate_child_seed_I_value( tree->seed_next, tree->I_next, + parent->seed_next, parent->I_next, + 0, parent->lm_type, + parent->lm_ots_type); + } else { + hss_generate_child_seed_I_value( tree->seed_next, tree->I_next, + parent->seed, parent->I, + index+1, parent->lm_type, + parent->lm_ots_type); + } + } + } + + /* Generate the expanded aux data structure (or NULL if we don't have a */ + /* viable aux structure */ + struct expanded_aux_data *expanded_aux, temp_aux; + expanded_aux = hss_expand_aux_data( aux_data, len_aux_data, &temp_aux, + w->tree[0]->hash_size, w ); + + /* + * Now, build all the subtrees within the tree + * + * We initialize the various data structures, and create a list of + * the nodes on the bottom levels of the subtrees that need to be + * initialized + */ + /* There are enough structures in this array to handle the maximum */ + /* number of orders we'll ever see */ + struct init_order order[MAX_HSS_LEVELS * MAX_SUBLEVELS * NUM_SUBTREE]; + struct init_order *p_order = order; + int count_order = 0; + + /* Step through the levels, and for each Merkle tree, compile a list of */ + /* the orders to initialize the bottoms of the subtrees that we'll need */ + for (i = w->levels; i >= 1 ; i--) { + struct merkle_level *tree = w->tree[i-1]; + unsigned hash_size = tree->hash_size; + /* The current count within this tree */ + merkle_index_t tree_count = tree->current_index; + /* The index of the leaf we're on */ + merkle_index_t leaf_index = tree_count; + + /* Generate the active subtrees */ + int j; + /*int bot_level_subtree = (int)tree->level;*/ /* The level of the bottom of */ + /* the subtree */ + unsigned char *active_prev_node = 0; + unsigned char *next_prev_node = 0; + for (j=tree->sublevels-1; j>=0; j--) { + /* The height of this subtree */ + int h_subtree = (j == 0) ? tree->top_subtree_size : + tree->subtree_size; + + /* Initialize the active tree */ + struct subtree *active = tree->subtree[j][ACTIVE_TREE]; + + /* Total number of leaf nodes below this subtree */ + merkle_index_t size_subtree = (merkle_index_t)1 << + (h_subtree + active->levels_below); + /* Fill in the leaf index that's on the left side of this subtree */ + /* This is the index of the leaf that we did when we first */ + /* entered the active subtree */ + merkle_index_t left_leaf = leaf_index & ~(size_subtree - 1); + /* This is the number of leaves we've done in this subtree */ + merkle_index_t subtree_count = leaf_index - left_leaf; + /* If we're not in the bottom tree, it's possible that the */ + /* update process will miss the very first update before we */ + /* need to sign. To account for that, generate one more */ + /* node than what our current count would suggest */ + if (i != w->levels - 1) { + subtree_count++; + } + active->current_index = 0; + active->left_leaf = left_leaf; + merkle_index_t num_bottom_nodes = (merkle_index_t)1 << h_subtree; + + /* Check if we have aux data at this level */ + int already_computed_lower = 0; + if (i == 0) { + merkle_index_t lower_index = num_bottom_nodes-1; + merkle_index_t node_offset = active->left_leaf>>active->levels_below; + if (hss_extract_aux_data(expanded_aux, active->level+h_subtree, + w, &active->nodes[ hash_size * lower_index ], + node_offset, num_bottom_nodes)) { + /* We do have it precomputed in our aux data */ + already_computed_lower = 1; + } + } + /* No aux data at this level; schedule the bottom row to be computed */ + /* Schedule the creation of the entire active tree */ + p_order->tree = tree; + p_order->subtree = active; + p_order->count_nodes = (merkle_index_t)1 << h_subtree; /* All */ + /* the nodes in this subtree */ + p_order->next_tree = 0; + /* Mark the root we inherented from the subtree just below us */ + p_order->prev_node = already_computed_lower ? NULL : active_prev_node; + p_order->prev_index = (tree->current_index >> active->levels_below) & (num_bottom_nodes-1); + + p_order->already_computed_lower = already_computed_lower; + p_order++; count_order++; + + /* For the next subtree, here's where our root will be */ + active_prev_node = &active->nodes[0]; + + /* And initialize the building tree, assuming there is one, and */ + /* assuming that the active subtree isn't at the right edge of */ + /* the Merkle tree */ + if (j > 0 && (leaf_index + size_subtree <= tree->max_index )) { + struct subtree *building = tree->subtree[j][BUILDING_TREE]; + + /* The number of leaves that make up one bottom node */ + /* of this subtree */ + merkle_index_t size_below_tree = (merkle_index_t)1 << building->levels_below; + /* We need to initialize the building tree current index */ + /* to a value at least as large as subtree_count */ + /* We'd prefer not to have to specificallly initialize */ + /* the stack, and so we round up to the next place the */ + /* stack is empty */ + merkle_index_t building_count = + (subtree_count + size_below_tree - 1) & + ~(size_below_tree - 1); + /* # of bottom level nodes we've building right now */ + merkle_index_t num_nodes = building_count >> building->levels_below; + building->left_leaf = left_leaf + size_subtree; + building->current_index = building_count; + + /* Check if this is already in the aux data */ + already_computed_lower = 0; + if (i == 0) { + merkle_index_t lower_index = num_bottom_nodes-1; + merkle_index_t node_offset = building->left_leaf>>building->levels_below; + if (hss_extract_aux_data(expanded_aux, building->level+h_subtree, + w, &building->nodes[ hash_size * lower_index ], + node_offset, num_nodes)) { + /* We do have it precomputed in our aux data */ + already_computed_lower = 1; + } + } + + /* Schedule the creation of the subset of the building tree */ + p_order->tree = tree; + p_order->subtree = building; + /* # of nodes to construct */ + p_order->count_nodes = num_nodes; + p_order->next_tree = 0; + /* We generally can't use the prev_node optimization */ + p_order->prev_node = NULL; + p_order->prev_index = 0; + + p_order->already_computed_lower = already_computed_lower; + p_order++; count_order++; + } else if (j > 0) { + tree->subtree[j][BUILDING_TREE]->current_index = 0; + } + + /* And the NEXT_TREE (which is always left-aligned) */ + if ((i-1) > 0) { + struct subtree *next = tree->subtree[j][NEXT_TREE]; + next->left_leaf = 0; + merkle_index_t leaf_size = + (merkle_index_t)1 << next->levels_below; + + merkle_index_t next_index = tree_count; + /* If we're not in the bottom tree, it's possible that the */ + /* update process will miss the very first update before we */ + /* need to sign. To account for that, potetially generate */ + /* one more node than what our current count would suggest */ + if ((i-1) != w->levels - 1) { + next_index++; + } + + /* Make next_index the # of leaves we'll need to process to */ + /* forward this NEXT subtree to this state */ + next_index = (next_index + leaf_size - 1)/leaf_size; + + /* This is set if we have a previous subtree */ + merkle_index_t prev_subtree = (next->levels_below ? 1 : 0); + merkle_index_t num_nodes; + unsigned char *next_next_node = 0; + + /* If next_index == 1, then if we're on a nonbottom subtree */ + /* the previous subtree is still building (and so we */ + /* needn't do anything). The exception is if we're on the */ + /* bottom level, then there is no subtree, and so we still */ + /* need to build the initial left leaf */ + if (next_index <= prev_subtree) { + /* We're not started on this subtree yet */ + next->current_index = 0; + num_nodes = 0; + } else if (next_index < num_bottom_nodes) { + /* We're in the middle of building this tree */ + next->current_index = next_index << next->levels_below; + num_nodes = next_index; + } else { + /* We've completed building this tree */ + /* How we note "we've generated this entire subtree" */ + next->current_index = MAX_SUBINDEX; + num_nodes = num_bottom_nodes; + /* We've generated this entire tree; allow it to */ + /* be inhereited for the next one */ + next_next_node = &next->nodes[0]; + } + if (num_nodes > 0) { + /* Schedule the creation of these nodes */ + p_order->tree = tree; + p_order->subtree = next; + /* # of nodes to construct */ + p_order->count_nodes = num_nodes; + p_order->next_tree = 1; + p_order->prev_node = next_prev_node; + p_order->prev_index = 0; + + p_order->already_computed_lower = 0; + p_order++; count_order++; + } + next_prev_node = next_next_node; + } + +// bot_level_subtree -= h_subtree; + if (j == 0) break; //This is a single level tree + } + if (i == 0) break; //This is a single level tree + } + +#if DO_FLOATING_POINT + /* Fill in the cost estimates */ + for (i=0; i<(sequence_t)count_order; i++) { + p_order = &order[i]; + + /* + * While we're here, NULL out all the suborders; we'll fill them in + * later if necessary + */ + p_order->sub = 0; + if (p_order->already_computed_lower) { + /* If we pulled the data from the aux, no work required */ + p_order->cost = 0; + continue; + } + unsigned winternitz = 8; + unsigned p = 128; + (void)lm_ots_look_up_parameter_set(p_order->tree->lm_ots_type, 0, 0, + &winternitz, &p, 0); + + struct subtree *subtree = p_order->subtree; + unsigned levels_below = subtree->levels_below; + + /* + * Estimate the number of hashes that we'll need to compute to compute + * one node; this is the number of leaf nodes times the number of + * hashes used during a winternitz computation. This ignores a few + * other hashes, but gets the vast bulk of them + */ + p_order->cost = (float)((merkle_index_t)1<num_threads); + if (num_tracks == 0) num_tracks = 4; /* Divide by 0; just say no */ + float est_max_per_work_item = est_total / num_tracks; + + /* Scan through the items, and see which ones should be subdivided */ + for (i=0; i<(sequence_t)count_order; i++) { + p_order = &order[i]; + if (p_order->cost <= est_max_per_work_item) { + break; /* Break because once we hit this point, the rest of the */ + /* items will be cheaper */ + } + + /* Try to subdivide each item into subdiv pieces */ + unsigned subdiv = my_log2(p_order->cost / est_max_per_work_item); + struct subtree *subtree = p_order->subtree; + /* Make sure we don't try to subdivide lower than what the */ + /* Merkle tree structure allows */ + if (subdiv > subtree->levels_below) subdiv = subtree->levels_below; + if (subdiv == 0) continue; + merkle_index_t max_subdiv = (merkle_index_t)1 << subtree->levels_below; + if (subdiv > max_subdiv) subdiv = max_subdiv; + if (subdiv <= 1) continue; + + const struct merkle_level *tree = p_order->tree; + size_t hash_len = tree->hash_size; + merkle_index_t count_nodes = p_order->count_nodes; + size_t total_hash = (hash_len * count_nodes) << subdiv; + unsigned h_subtree = (subtree->level == 0) ? tree->top_subtree_size : + tree->subtree_size; + struct sub_order *sub = malloc( sizeof *sub + total_hash ); + if (!sub) continue; /* On malloc failure, don't bother trying */ + /* to subdivide */ + + /* Fill in the details of this suborder */ + sub->level = subdiv; + sub->num_hashes = 1 << subdiv; + sub->node_num_first_target = + (subtree->left_leaf >> subtree->levels_below) + + ((merkle_index_t)1 << (h_subtree + subtree->level)); + p_order->sub = sub; + } +#endif + + /* Now, generate all the nodes we've listed in parallel */ + struct thread_collection *col = hss_thread_init(info->num_threads); + enum hss_error_code got_error = hss_error_none; + + /* We use this to decide the granularity of the requests we make */ +#if DO_FLOATING_POINT + unsigned core_target = 5 * hss_thread_num_tracks(info->num_threads); + float prev_cost = 0; +#endif + + for (i=0; i<(sequence_t)count_order; i++) { + p_order = &order[i]; + if (p_order->already_computed_lower) continue; /* If it's already */ + /* done, we needn't bother */ + /* If this work order is cheaper than what we've issued, allow */ + /* for a greater amount of consolidation */ +#if DO_FLOATING_POINT + if (prev_cost > 0) { + if (p_order->cost <= 2 * prev_cost) { + /* The cost per node has decreased by a factor of 2 (at */ + /* least); allow a single core to do more of the work */ + float ratio = prev_cost / p_order->cost; + if (ratio > 1000) { + core_target = 1; + } else { + core_target = (unsigned)(core_target / ratio); + if (core_target == 0) core_target = 1; + } + prev_cost = p_order->cost; + } + } else { + prev_cost = p_order->cost; + } +#endif + + const struct merkle_level *tree = p_order->tree; + struct subtree *subtree = p_order->subtree; + unsigned h_subtree = (subtree->level == 0) ? tree->top_subtree_size : + tree->subtree_size; + merkle_index_t lower_index = ((merkle_index_t)1 << h_subtree) - 1; + unsigned hash_size = tree->hash_size; +#if DO_FLOATING_POINT + unsigned max_per_request = p_order->count_nodes / core_target; + if (max_per_request == 0) max_per_request = 1; +#else + unsigned max_per_request = UINT_MAX; +#endif + + /* If we're skipping a value, make sure we compute up to there */ + merkle_index_t right_side = p_order->count_nodes; + if (p_order->prev_node && right_side > p_order->prev_index) { + right_side = p_order->prev_index; + } + + merkle_index_t n; + struct intermed_tree_detail detail; + + detail.seed = (p_order->next_tree ? tree->seed_next : tree->seed); + detail.lm_type = tree->lm_type; + detail.lm_ots_type = tree->lm_ots_type; + detail.h = tree->h; + detail.tree_height = tree->level; + detail.I = (p_order->next_tree ? tree->I_next : tree->I); + detail.got_error = &got_error; + +#if DO_FLOATING_POINT + /* Check if we're actually doing a suborder */ + struct sub_order *sub = p_order->sub; + if (sub) { + /* Issue all the orders separately */ + unsigned hash_len = tree->hash_size; + for (n = 0; n < p_order->count_nodes; n++ ) { + if (n == right_side) continue; /* Skip the omitted value */ + unsigned char *dest = &sub->h[ n * sub->num_hashes * hash_len ]; + merkle_index_t node_num = (sub->node_num_first_target+n) << sub->level; + unsigned k; + for (k=0; k < sub->num_hashes; k++) { + detail.dest = dest; + dest += hash_len; + detail.node_num = node_num; + node_num++; + detail.node_count = 1; + + hss_thread_issue_work(col, hss_gen_intermediate_tree, + &detail, sizeof detail ); + } + } + continue; + } +#endif + { + /* We're not doing a suborder; issue the request in as large of */ + /* a chunk as we're allowed */ + for (n = 0; n < p_order->count_nodes; ) { + merkle_index_t this_req = right_side - n; + if (this_req > max_per_request) this_req = max_per_request; + if (this_req == 0) { + /* We hit the value we're skipping; skip it, and go on to */ + /* the real right side */ + n++; + right_side = p_order->count_nodes; + continue; + } + + /* Issue a work order for the next this_req elements */ + detail.dest = &subtree->nodes[ hash_size * (lower_index + n)]; + detail.node_num = (subtree->left_leaf >> subtree->levels_below) + + n + ((merkle_index_t)1 << (h_subtree + subtree->level)); + detail.node_count = this_req; + + hss_thread_issue_work(col, hss_gen_intermediate_tree, + &detail, sizeof detail ); + + n += this_req; + } + } + } + + /* We've issued all the order; now wait until all the work is done */ + hss_thread_done(col); + if (got_error != hss_error_none) { + /* One of the worker threads detected an error */ +#if DO_FLOATING_POINT + /* Don't leak suborders on an intermediate error */ + for (i=0; i<(sequence_t)count_order; i++) { + free( order[i].sub ); // IGNORE free-check + } +#endif + info->error_code = got_error; + goto failed; + } + +#if DO_FLOATING_POINT + /* + * Now, if we did have suborders, recombine them into what was actually + * wanted + */ + for (i=0; i<(sequence_t)count_order; i++) { + p_order = &order[i]; + struct sub_order *sub = p_order->sub; + if (!sub) continue; /* This order wasn't subdivided */ + + const struct merkle_level *tree = p_order->tree; + const unsigned char *I = (p_order->next_tree ? tree->I_next : tree->I); + struct subtree *subtree = p_order->subtree; + unsigned hash_size = tree->hash_size; + unsigned h_subtree = (subtree->level == 0) ? tree->top_subtree_size : + tree->subtree_size; + merkle_index_t lower_index = ((merkle_index_t)1 << h_subtree) - 1; + + merkle_index_t n; + for (n = 0; n < p_order->count_nodes; n++ ) { + if (p_order->prev_node && n == p_order->prev_index) continue; + + hash_subtree( &subtree->nodes[ hash_size * (lower_index + n)], + &sub->h[ hash_size * sub->num_hashes * n ], + sub->level, sub->node_num_first_target + n, + hash_size, tree->h, I); + } + + free( sub ); // IGNORE free-check + p_order->sub = 0; + } +#endif + + /* + * Now we have generated the lower level nodes of the subtrees; go back and + * fill in the higher level nodes. + * We do this in backwards order, so that we do the lower levels of the trees + * first (as lower levels are cheaper, they'll be listed later in the + * array; that's how we sorted, them, remember?). + * That means if any subtrees inherit the root values of lower trees, + * we compute those root values first + */ + for (i=count_order; i>0; i--) { + p_order = &order[i-1]; + const struct merkle_level *tree = p_order->tree; + const unsigned char *I = (p_order->next_tree ? tree->I_next : tree->I); + struct subtree *subtree = p_order->subtree; + + if (p_order->prev_node) { + /* This subtree did have a bottom node that was the root node */ + /* of a lower subtree; fill it in */ + unsigned hash_size = tree->hash_size; + unsigned h_subtree = (subtree->level == 0) ? tree->top_subtree_size : + tree->subtree_size; + merkle_index_t lower_index = ((merkle_index_t)1 << h_subtree) - 1; + + /* Where in the subtree we place the previous root */ + unsigned set_index = (lower_index + p_order->prev_index) * hash_size; + memcpy( &subtree->nodes[ set_index ], p_order->prev_node, hash_size ); + } + + /* Now, fill in all the internal nodes of the subtree */ + fill_subtree(tree, subtree, p_order->count_nodes, I); + } + + /* + * Hey; we've initialized all the subtrees (at least, as far as what + * they'd be expected to be given the current count); hurray! + */ + + /* + * Now, create all the signed public keys + * Again, we could parallelize this; it's also fast enough not to be worth + * the complexity + */ + for (i = 1; i < w->levels; i++) { + if (!hss_create_signed_public_key( w->signed_pk[i], w->siglen[i-1], + w->tree[i], w->tree[i-1], w )) { + info->error_code = hss_error_internal; /* Really shouldn't */ + /* happen */ + goto failed; + } + } + hss_zeroize( private_key, sizeof private_key ); + + /* + * And, we make each level as not needing an update from below (as we've + * initialized them as already having the first update) + */ + for (i = 0; i < w->levels - 1; i++) { + w->tree[i]->update_count = UPDATE_DONE; + } + + w->status = hss_error_none; /* This working key has been officially */ + /* initialized, and now can be used */ + return true; + +failed: + hss_zeroize( private_key, sizeof private_key ); + return false; +} + +#if DO_FLOATING_POINT +/* + * This goes through the order, and estimates the total amount + * This assumes that the highest cost element is listed first + * + * It returns the estimated number of hash compression operations total + * + * We use floating point because the number of hash compression functions can + * vary a *lot*; floating point has great dynamic range. + */ +static float estimate_total_cost( struct init_order *order, + unsigned count_order ) { + if (count_order == 0) return 0; + float total_cost = 0; + + unsigned i; + + for (i=0; i +#include "common_defs.h" +#include "hss.h" +#include "config.h" +#include "lms_namespace.h" + +/* + * This is the central internal include file for the functions that make up + * this subsystem. It should not be used by applications + */ + +#define PARAM_SET_COMPRESS_LEN 1 /* We assume that we can compress the */ + /* lm_type and the lm_ots type for a */ + /* single level into 1 byte */ + +#define PARM_SET_END 0xff /* We set this marker in the parameter set */ + /* when fewer than the maximum levels are used */ + + +/* + * The internal structure of a private key + */ +#define PRIVATE_KEY_INDEX 0 +#define PRIVATE_KEY_INDEX_LEN 8 /* 2**64 signatures should be enough for */ + /* everyone */ +#define PRIVATE_KEY_PARAM_SET (PRIVATE_KEY_INDEX + PRIVATE_KEY_INDEX_LEN) +#define PRIVATE_KEY_PARAM_SET_LEN (PARAM_SET_COMPRESS_LEN * MAX_HSS_LEVELS) +#define PRIVATE_KEY_SEED (PRIVATE_KEY_PARAM_SET + PRIVATE_KEY_PARAM_SET_LEN) +#if SECRET_METHOD == 2 +#define PRIVATE_KEY_SEED_LEN (SEED_LEN + I_LEN) +#else +#define PRIVATE_KEY_SEED_LEN SEED_LEN +#endif +#define PRIVATE_KEY_LEN (PRIVATE_KEY_SEED + PRIVATE_KEY_SEED_LEN) /* That's */ + /* 48 bytes */ + +struct merkle_level; +struct hss_working_key { + unsigned levels; + enum hss_error_code status; /* What is the status of this key */ + /* hss_error_none if everything looks ok */ + /* Otherwise, the error code we report if */ + /* we try to use this key to sign */ + sequence_t reserve_count; /* The value written to the private key */ + /* Will be higher than the 'current count' */ + /* if some signaures are 'reserved' */ + sequence_t max_count; /* The maximum count we can ever have */ + unsigned autoreserve; /* How many signatures to attempt to */ + /* reserve if the signing process hits */ + /* the end of the current reservation */ + + size_t signature_len; /* The length of the HSS signature */ + + unsigned char *stack; /* The stack memory used by the subtrees */ + + /* The private key (in its entirety) */ + unsigned char private_key[PRIVATE_KEY_LEN]; + /* The pointer to the seed (contained within the private key) */ + /* Warning: nonsyntaxic macro; need to be careful how we use this */ +#define working_key_seed private_key + PRIVATE_KEY_SEED + + size_t siglen[MAX_HSS_LEVELS]; /* The lengths of the signatures */ + /* generated by the various levels */ + size_t signed_pk_len[MAX_HSS_LEVELS]; /* The lengths of the signed */ + /* public keys for the various levels */ + unsigned char *signed_pk[MAX_HSS_LEVELS]; /* The current signed public */ + /* keys for the nontop levels */ + /* Each array element is that level's */ + /* current root value, signed by the */ + /* previous level. Unused for the */ + /* topmost level */ + struct merkle_level *tree[MAX_HSS_LEVELS]; /* The structures that manage */ + /* each individual level */ +}; + +#define MIN_SUBTREE 2 /* All subtrees (other than the root subtree) have */ + /* at least 2 levels */ +#define MAX_SUBLEVELS ((MAX_MERKLE_HEIGHT + MIN_SUBTREE - 1) / MIN_SUBTREE) +#if MAX_SUBLEVELS > (1 << (MIN_MERKLE_HEIGHT-1)) - 2 +#error We need to rethink our parent tree update logic, as there is a +#error possibility we do not give the tree enough updates between signatures +/* One possible fix would be to increase the subtree size for extremely */ +/* tall trees */ +#endif + +struct merkle_level { + unsigned level; /* Total number of levels */ + unsigned h, hash_size; /* Hash function, width */ + param_set_t lm_type; + param_set_t lm_ots_type; /* OTS parameter */ + merkle_index_t current_index; /* The number of signatures this tree has */ + /* generated so far */ + merkle_index_t max_index; /* 1<levels) */ + unsigned level; /* The level that the root of this subtree */ + /* is within the larger Merkle tree */ + unsigned levels_below; /* The number of levels below this subtree */ + /* in the Merkle tree */ + unsigned char *stack; /* Pointer to the stack used when */ + /* generating nodes; will be a pointer */ + /* into the hss_working_key::stack array */ + /* Used to incrementally compute bottom */ + /* node values */ + unsigned char nodes[1]; /* The actual subtree node values */ + /* 2*(1< +#include +#include "common_defs.h" +#include "hss.h" +#include "hss_internal.h" +#include "hss_aux.h" +#include "endian.h" +#include "hash.h" +#include "hss_thread.h" +#include "lm_common.h" +#include "lm_ots_common.h" +#include + +/* Count the number of 1 bits at the end (lsbits) of the integer */ +/* Do it in the obvious way; straightline code may be faster (no */ +/* unpredictable jumps, which are costly), but that would be less scrutable */ +static int trailing_1_bits(merkle_index_t n) { + int i; + for (i=0; n&1; n>>=1, i++) + ; + return i; +} + +/* + * This creates a private key (and the correspond public key, and optionally + * the aux data for that key) + * Parameters: + * generate_random - the function to be called to generate randomness. This + * is assumed to be a pointer to a cryptographically secure rng, + * otherwise all security is lost. This function is expected to fill + * output with 'length' uniformly distributed bits, and return 1 on + * success, 0 if something went wrong + * levels - the number of levels for the key pair (2-8) + * lm_type - an array of the LM registry entries for the various levels; + * entry 0 is the topmost + * lm_ots_type - an array of the LM-OTS registry entries for the various + * levels; again, entry 0 is the topmost + * update_private_key, context - the function that is called when the + * private key is generated; it is expected to store it to secure NVRAM + * If this is NULL, then the context pointer is reinterpretted to mean + * where in RAM the private key is expected to be placed + * public_key - where to store the public key + * len_public_key - length of the above buffer; see hss_get_public_key_len + * if you need a hint. + * aux_data - where to store the optional aux data. This is not required, but + * if provided, can be used to speed up the hss_generate_working_key + * process; + * len_aux_data - the length of the above buffer. This is not fixed length; + * the function will run different time/memory trade-offs based on the + * length provided + * + * This returns true on success, false on failure + */ +#ifdef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +bool hss_generate_private_key( + bool (*generate_random)(void *output, size_t length), + unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned char *public_key, size_t len_public_key, + unsigned char *aux_data, size_t len_aux_data, + struct hss_extra_info *info) { + + struct hss_extra_info info_temp = { 0 }; + if (!info) info = &info_temp; + + if (!generate_random) { + /* We *really* need random numbers */ + info->error_code = hss_error_no_randomness; + return false; + } + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) { + /* parameter out of range */ + info->error_code = hss_error_bad_param_set; + return false; + } + + unsigned h0; /* The height of the root tree */ + unsigned h; /* The hash function used */ + unsigned size_hash; /* The size of each hash that would appear in the */ + /* aux data */ + if (!lm_look_up_parameter_set(lm_type[0], &h, &size_hash, &h0)) { + info->error_code = hss_error_bad_param_set; + return false; + } + + /* Check the public_key_len */ + if (4 + 4 + 4 + I_LEN + size_hash > len_public_key) { + info->error_code = hss_error_buffer_overflow; + /* public key won't fit in the buffer we're given */ + return false; + } + + /* If you provide an aux_data buffer, we have to write something */ + /* into it (at least, enough to mark it as 'we're not really using */ + /* aux data) */ + if (aux_data && len_aux_data == 0) { + /* not enough aux data buffer to mark it as 'not really used' */ + info->error_code = hss_error_bad_aux; + return false; + } + + unsigned len_ots_pub = (unsigned)lm_ots_get_public_key_len(lm_ots_type[0]); + if (len_ots_pub == 0) { + info->error_code = hss_error_bad_param_set; + return false; + } + + unsigned char private_key[ PRIVATE_KEY_LEN ]; + + /* First step: format the private key */ + put_bigendian( private_key + PRIVATE_KEY_INDEX, 0, + PRIVATE_KEY_INDEX_LEN ); + if (!hss_compress_param_set( private_key + PRIVATE_KEY_PARAM_SET, + levels, lm_type, lm_ots_type, + PRIVATE_KEY_PARAM_SET_LEN )) { + info->error_code = hss_error_bad_param_set; + return false; + } + if (!(*generate_random)( private_key + PRIVATE_KEY_SEED, + PRIVATE_KEY_SEED_LEN )) { + info->error_code = hss_error_bad_randomness; + return false; + } + + /* Now make sure that the private key is written to NVRAM */ + if (update_private_key) { + if (!(*update_private_key)( private_key, PRIVATE_KEY_LEN, context)) { + /* initial write of private key didn't take */ + info->error_code = hss_error_private_key_write_failed; + hss_zeroize( private_key, sizeof private_key ); + return false; + } + } else { + if (context == 0) { + /* We weren't given anywhere to place the private key */ + info->error_code = hss_error_no_private_buffer; + hss_zeroize( private_key, sizeof private_key ); + return false; + } + memcpy( context, private_key, PRIVATE_KEY_LEN ); + } + + /* Figure out what would be the best trade-off for the aux level */ + struct expanded_aux_data *expanded_aux_data = 0, aux_data_storage; + if (aux_data != NULL) { + aux_level_t aux_level = hss_optimal_aux_level( len_aux_data, lm_type, + lm_ots_type, NULL ); + hss_store_aux_marker( aux_data, aux_level ); + + /* Set up the aux data pointers */ + expanded_aux_data = hss_expand_aux_data( aux_data, len_aux_data, + &aux_data_storage, size_hash, 0 ); + } + + unsigned char I[I_LEN]; + unsigned char seed[SEED_LEN]; + if (!hss_generate_root_seed_I_value( seed, I, private_key+PRIVATE_KEY_SEED)) { + info->error_code = hss_error_internal; + hss_zeroize( private_key, sizeof private_key ); + return false; + } + + /* Now, it's time to generate the public key, which means we need to */ + /* compute the entire top level Merkle tree */ + + /* First of all, figure out the appropriate level to compute up to */ + /* in parallel. We'll do the lower of the bottom-most level that */ + /* appears in the aux data, and 4*log2 of the number of core we have */ + unsigned num_cores = hss_thread_num_tracks(info->num_threads); + unsigned level; + unsigned char *dest = 0; /* The area we actually write to */ + void *temp_buffer = 0; /* The buffer we need to free when done */ + for (level = h0-1; level > 2; level--) { + /* If our bottom-most aux data is at this level, we want it */ + if (expanded_aux_data && expanded_aux_data->data[level]) { + /* Write directly into the aux area */ + dest = expanded_aux_data->data[level]; + break; + } + + /* If going to a higher levels would mean that we wouldn't */ + /* effectively use all the cores we have, use this level */ + if (((unsigned)1<num_threads); + + struct intermed_tree_detail details; + /* Set the values in the details structure that are constant */ + details.seed = seed; + details.lm_type = lm_type[0]; + details.lm_ots_type = lm_ots_type[0]; + details.h = h; + details.tree_height = h0; + details.I = I; + enum hss_error_code got_error = hss_error_none; /* This flag is set */ + /* on an error */ + details.got_error = &got_error; + + merkle_index_t j; + /* # of nodes at this level */ + merkle_index_t level_nodes = (merkle_index_t)1 << level; + /* the index of the node we're generating right now */ + merkle_index_t node_num = level_nodes; + /* + * We'd prefer not to issue a separate work item for every node; we + * might be doing millions of node (if we have a large aux data space) + * and we end up malloc'ing a large structure for every work order. + * So, if we do have a large number of requires, aggregate them + */ + merkle_index_t increment = level_nodes / (10 * num_cores); +#define MAX_INCREMENT 20000 + if (increment > MAX_INCREMENT) increment = MAX_INCREMENT; + if (increment == 0) increment = 1; + for (j=0; j < level_nodes; ) { + unsigned this_increment; + if (level_nodes - j < increment) { + this_increment = level_nodes - j; + } else { + this_increment = increment; + } + + /* Set the particulars of this specific work item */ + details.dest = dest + j*size_hash; + details.node_num = node_num; + details.node_count = this_increment; + + /* Issue a separate work request for every node at this level */ + hss_thread_issue_work(col, hss_gen_intermediate_tree, + &details, sizeof details ); + + j += this_increment; + node_num += this_increment; + } + /* Now wait for all those work items to complete */ + hss_thread_done(col); + + hss_zeroize( seed, sizeof seed ); + + /* Check if something went wrong. It really shouldn't have, however if */ + /* something returns an error code, we really should try to handle it */ + if (got_error != hss_error_none) { + /* We failed; give up */ + info->error_code = got_error; + hss_zeroize( private_key, sizeof private_key ); + if (update_private_key) { + (void)(*update_private_key)(private_key, PRIVATE_KEY_LEN, context); + } else { + hss_zeroize( context, PRIVATE_KEY_LEN ); + } + free(temp_buffer); // IGNORE free-check + return false; + } + + /* Now, we complete the rest of the tree. This is actually fairly fast */ + /* (one hash per node) so we don't bother to parallelize it */ + + unsigned char stack[ MAX_HASH * (MAX_MERKLE_HEIGHT+1) ]; + unsigned char root_hash[ MAX_HASH ]; + + /* Generate the top levels of the tree, ending with the root node */ + merkle_index_t r, leaf_node; + for (r=level_nodes, leaf_node = 0; leaf_node < level_nodes; r++, leaf_node++) { + + /* Walk up the stack, combining the current node with what's on */ + /* the atack */ + merkle_index_t q = leaf_node; + + /* + * For the subtree which this leaf node forms the final piece, put the + * destination to where we'll want it, either on the stack, or if this + * is the final piece, to where the caller specified + */ + unsigned char *current_buf; + unsigned stack_offset = trailing_1_bits( leaf_node ); + if (stack_offset == level) { + current_buf = root_hash; + } else { + current_buf = &stack[stack_offset * size_hash ]; + } + memcpy( current_buf, dest + leaf_node * size_hash, size_hash ); + + unsigned sp; + unsigned cur_lev = level; + for (sp = 1;; sp++, cur_lev--, q >>= 1) { + /* Give the aux data routines a chance to save the */ + /* intermediate value. Note that we needn't check for the */ + /* bottommost level; if we're saving aux data at that level, */ + /* we've already placed it there */ + if (sp > 1) { + hss_save_aux_data( expanded_aux_data, cur_lev, + size_hash, q, current_buf ); + } + + if (sp > stack_offset) break; + + + hss_combine_internal_nodes( current_buf, + &stack[(sp-1) * size_hash], current_buf, + h, I, size_hash, + r >> sp ); + } + } + /* The top entry in the stack is the root value (aka the public key) */ + + /* Complete the computation of the aux data */ + hss_finalize_aux_data( expanded_aux_data, size_hash, h, + private_key+PRIVATE_KEY_SEED ); + + /* We have the root value; now format the public key */ + put_bigendian( public_key, levels, 4 ); + public_key += 4; len_public_key -= 4; + put_bigendian( public_key, lm_type[0], 4 ); + public_key += 4; len_public_key -= 4; + put_bigendian( public_key, lm_ots_type[0], 4 ); + public_key += 4; len_public_key -= 4; + memcpy( public_key, I, I_LEN ); + public_key += I_LEN; len_public_key -= I_LEN; + memcpy( public_key, root_hash, size_hash ); + public_key += size_hash; len_public_key -= size_hash; + /* Address static analysis issue*/ + LMS_UNUSED(public_key); + LMS_UNUSED(len_public_key); + + /* Hey, what do you know -- it all worked! */ + hss_zeroize( private_key, sizeof private_key ); /* Zeroize local copy of */ + /* the private key */ + free(temp_buffer); // IGNORE free-check + return true; +} +#endif + +/* + * The length of the private key + */ +size_t hss_get_private_key_len(unsigned levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type) { + /* A private key is a 'public object'? Yes, in the sense that we */ + /* export it outside this module */ + LMS_UNUSED(levels); + LMS_UNUSED(lm_type); + LMS_UNUSED(lm_ots_type); + return PRIVATE_KEY_LEN; +} diff --git a/src/sig_stfl/lms/external/hss_param.c b/src/sig_stfl/lms/external/hss_param.c new file mode 100644 index 0000000000..838f7a8381 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_param.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +#include +#include "hss.h" +#include "hss_internal.h" +#include "endian.h" +#include "hss_zeroize.h" + +/* + * Convert a parameter set into the compressed version we use within a private + * key. This is the private key that'll end up being updated constantly, and + * so we try to make it as small as possible + */ +bool hss_compress_param_set( unsigned char *compressed, + int levels, + const param_set_t *lm_type, + const param_set_t *lm_ots_type, + size_t len_compressed ) { + int i; + + for (i=0; i 0x0e || b > 0x0e) return false; + /* Make sure the parm sets are supported */ + switch (a) { + case LMS_SHA256_N32_H5: case LMS_SHA256_N32_H10: + case LMS_SHA256_N32_H15: case LMS_SHA256_N32_H20: + case LMS_SHA256_N32_H25: + break; + default: + return false; + } + switch (b) { + case LMOTS_SHA256_N32_W1: case LMOTS_SHA256_N32_W2: + case LMOTS_SHA256_N32_W4: case LMOTS_SHA256_N32_W8: + break; + default: + return false; + } + + *compressed++ = (a<<4) + b; + len_compressed--; + } + + while (len_compressed) { + *compressed++ = PARM_SET_END; + len_compressed--; + } + + return true; +} + +/* + * This returns the parameter set for a given private key. + * This is here to solve a chicken-and-egg problem: the hss_working_key + * must be initialized to the same parameter set as the private key, + * but (other than this function, or somehow remembering it) there's + * no way to retreive the parameter set. + * + * read_private_key/context will read the private key (if read_private_key is + * NULL, context is assumed to point to the private key) + * + * On success, *levels will be set to the number of levels, and lm_type[] + * and lm_ots_type[] will be set to the lm/ots parameter sets + * + * On success, this returns true; on failure (can't read the private key, or + * the private key is invalid), returns false + */ +bool hss_get_parameter_set( unsigned *levels, + param_set_t lm_type[ MAX_HSS_LEVELS ], + param_set_t lm_ots_type[ MAX_HSS_LEVELS ], + bool (*read_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context) { + unsigned char private_key[ PRIVATE_KEY_LEN ]; + bool success = false; + + if (read_private_key) { + if (!read_private_key( private_key, PRIVATE_KEY_SEED, context )) { + goto failed; + } + } else { + if (!context) return false; + memcpy( private_key, context, PRIVATE_KEY_SEED ); + } + + /* Scan through the private key to recover the parameter sets */ + unsigned total_height = 0; + unsigned level; + for (level=0; level < MAX_HSS_LEVELS; level++) { + unsigned char c = private_key[PRIVATE_KEY_PARAM_SET + level]; + if (c == PARM_SET_END) break; + /* Decode this level's parameter set */ + param_set_t lm = (c >> 4); + param_set_t ots = (c & 0x0f); + /* Make sure both are supported */ + /* While we're here, add up the total Merkle height */ + switch (lm) { + case LMS_SHA256_N32_H5: total_height += 5; break; + case LMS_SHA256_N32_H10: total_height += 10; break; + case LMS_SHA256_N32_H15: total_height += 15; break; + case LMS_SHA256_N32_H20: total_height += 20; break; + case LMS_SHA256_N32_H25: total_height += 25; break; + default: goto failed; + } + switch (ots) { + case LMOTS_SHA256_N32_W1: + case LMOTS_SHA256_N32_W2: + case LMOTS_SHA256_N32_W4: + case LMOTS_SHA256_N32_W8: + break; + default: goto failed; + } + lm_type[level] = lm; + lm_ots_type[level] = ots; + } + + if (level < MIN_HSS_LEVELS || level > MAX_HSS_LEVELS) goto failed; + + *levels = level; + + /* Make sure that the rest of the private key has PARM_SET_END */ + unsigned i; + for (i = level+1; i 64) total_height = 64; /* (bounded by 2**64) */ + sequence_t max_count = ((sequence_t)2 << (total_height-1)) - 1; + /* height-1 so we don't try to shift by 64, and hit U.B. */ + + /* We use the count 0xffff..ffff to signify 'we've used up all our */ + /* signatures'. Make sure that is above max_count, even for */ + /* parameter sets that can literally generate 2**64 signatures (by */ + /* letting them generate only 2**64-1) */ + if (total_height == 64) max_count--; + sequence_t current_count = get_bigendian( + private_key + PRIVATE_KEY_INDEX, PRIVATE_KEY_INDEX_LEN ); + + if (current_count > max_count) goto failed; /* Private key expired */ + + success = true; /* It worked! */ +failed: + /* There might be private keying material here */ + hss_zeroize( private_key, sizeof private_key ); + return success; +} diff --git a/src/sig_stfl/lms/external/hss_reserve.c b/src/sig_stfl/lms/external/hss_reserve.c new file mode 100644 index 0000000000..662df26628 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_reserve.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +#include +#include "common_defs.h" +#include "hss_internal.h" +#include "hss_reserve.h" +#include "endian.h" + +/* + * Initialize the reservation count to the given value + */ +void hss_set_reserve_count(struct hss_working_key *w, sequence_t count) { + w->reserve_count = count; +} + +/* + * Set the autoreserve count + */ +bool hss_set_autoreserve(struct hss_working_key *w, + unsigned sigs_to_autoreserve, struct hss_extra_info *info) { + if (!w) { + if (info) info->error_code = hss_error_got_null; + return false; + } + + /* Note: we do not check if the working key is in a usable state */ + /* There are a couple of odd-ball scenarios (e.g. when they've */ + /* manually allocated the key, but haven't loaded it yet) that we */ + /* don't have a good reason to disallow */ + + w->autoreserve = sigs_to_autoreserve; + return true; +} + +/* + * This is called when we generate a signature; it checks if we need + * to write out a new private key (and advance the reservation); if it + * decides it needs to write out a new private key, it also decides how + * far it needs to advance it + */ +bool hss_advance_count(struct hss_working_key *w, sequence_t cur_count, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + struct hss_extra_info *info, bool *trash_private_key) { + + if (cur_count == w->max_count) { + /* We hit the end of the root; this will be the last signature */ + /* this private key can do */ + w->status = hss_error_private_key_expired; /* Fail if they try to */ + /* sign any more */ + info->last_signature = true; + /* Make sure we zeroize the private key */ + *trash_private_key = true; /* We can't trash our copy of the */ + /* private key until after we've generated the signature */ + /* We can trash the copy in secure storage, though */ + if (update_private_key) { + unsigned char private_key[PRIVATE_KEY_LEN]; + memset( private_key, PARM_SET_END, PRIVATE_KEY_LEN ); + if (!update_private_key(private_key, PRIVATE_KEY_LEN, context)) { + info->error_code = hss_error_private_key_write_failed; + return false; + } + } else { + memset( context, PARM_SET_END, PRIVATE_KEY_LEN ); + } + return true; + } + sequence_t new_count = cur_count + 1; + + if (new_count > w->reserve_count) { + /* We need to advance the reservation */ + + /* Check if we have enough space to do the entire autoreservation */ + if (w->max_count - new_count > w->autoreserve) { + new_count += w->autoreserve; + } else { + /* If we don't have enough space, reserve what we can */ + new_count = w->max_count; + } + + put_bigendian( w->private_key + PRIVATE_KEY_INDEX, new_count, + PRIVATE_KEY_INDEX_LEN ); + if (update_private_key) { + if (!update_private_key(w->private_key, PRIVATE_KEY_INDEX_LEN, + context)) { + /* Oops, we couldn't write the private key; undo the */ + /* reservation advance (and return an error) */ + info->error_code = hss_error_private_key_write_failed; + put_bigendian( w->private_key + PRIVATE_KEY_INDEX, + w->reserve_count, PRIVATE_KEY_INDEX_LEN ); + return false; + } + } else { + put_bigendian( context, new_count, PRIVATE_KEY_INDEX_LEN ); + } + w->reserve_count = new_count; + } + + return true; +} + +/* + * This will make sure that (at least) N signatures are reserved; that is, we + * won't need to actually call the update function for the next N signatures + * generated + * + * This can be useful if the update_private_key function is expensive. + * + * Note that if, N (or more) signatures are already reserved, this won't do + * anything. + */ +bool hss_reserve_signature( + struct hss_working_key *w, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned sigs_to_reserve, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + if (!w) { + info->error_code = hss_error_got_null; + return false; + } + if (w->status != hss_error_none) { + info->error_code = w->status;; + return false; + } + + if (sigs_to_reserve > w->max_count) { + info->error_code = hss_error_not_that_many_sigs_left; + return false; /* Very funny */ + } + + /* + * If we're given a raw private key, make sure it's the one we're + * thinking of. + * I have no idea why someone would reserve signatures if they have + * a raw private key (which is cheap to update), however there's no + * reason we shouldn't support it + */ + if (!update_private_key) { + if (0 != memcmp( context, w->private_key, PRIVATE_KEY_LEN)) { + info->error_code = hss_error_key_mismatch; + return false; /* Private key mismatch */ + } + } + + /* Figure out what the current count is */ + sequence_t current_count = 0; + unsigned i; + for (i = 0; ilevels; i++) { + struct merkle_level *tree = w->tree[i]; + /* -1 because the current_index counts the signatures to the */ + /* current next level */ + current_count = (current_count << tree->level) + + tree->current_index - 1; + } + current_count += 1; /* The bottom-most tree isn't advanced */ + + sequence_t new_reserve_count; /* This is what the new reservation */ + /* setting would be (if we accept the reservation) */ + if (current_count > w->max_count - sigs_to_reserve) { + /* Not that many sigantures left */ + /* Reserve as many as we can */ + new_reserve_count = w->max_count; + } else { + new_reserve_count = current_count + sigs_to_reserve; + } + + if (new_reserve_count <= w->reserve_count) { + /* We already have (at least) that many reserved; do nothing */ + return true; + } + + /* Attempt to update the count in the private key */ + put_bigendian( w->private_key + PRIVATE_KEY_INDEX, new_reserve_count, + PRIVATE_KEY_INDEX_LEN ); + /* Update the copy in NV storage */ + if (update_private_key) { + if (!update_private_key(w->private_key, PRIVATE_KEY_INDEX_LEN, + context)) { + /* Oops, couldn't update it */ + put_bigendian( w->private_key + PRIVATE_KEY_INDEX, + w->reserve_count, PRIVATE_KEY_INDEX_LEN ); + info->error_code = hss_error_private_key_write_failed; + return false; + } + } else { + memcpy( context, w->private_key, PRIVATE_KEY_INDEX_LEN ); + } + w->reserve_count = new_reserve_count; + + return true; +} diff --git a/src/sig_stfl/lms/external/hss_reserve.h b/src/sig_stfl/lms/external/hss_reserve.h new file mode 100644 index 0000000000..d5c8284cf9 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_reserve.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_RESERVE_H_ ) +#define HSS_RESERVE_H_ + +/* + * This is the internal include file for the reservation functions for this + * subsystem. It should not be used by applications + */ + +#include "common_defs.h" +#include "lms_namespace.h" + +struct hss_working_key; + +void hss_set_reserve_count(struct hss_working_key *w, sequence_t count); + +bool hss_advance_count(struct hss_working_key *w, sequence_t new_count, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + struct hss_extra_info *info, bool *trash_private_key); + +#endif /* HSS_RESERVE_H_ */ diff --git a/src/sig_stfl/lms/external/hss_sign.c b/src/sig_stfl/lms/external/hss_sign.c new file mode 100644 index 0000000000..44e850424e --- /dev/null +++ b/src/sig_stfl/lms/external/hss_sign.c @@ -0,0 +1,737 @@ +// SPDX-License-Identifier: MIT +/* + * This is an implementation of the HSS signature scheme from LMS + * This is the part that actually generates the signature + */ +#include +#include +#include "common_defs.h" +#include "hss.h" +#include "hash.h" +#include "endian.h" +#include "hss_internal.h" +#include "hss_aux.h" +#include "hss_thread.h" +#include "hss_reserve.h" +#include "lm_ots.h" +#include "lm_ots_common.h" +#include "hss_derive.h" + +/* + * This adds one leaf to the building and next subtree. + */ +enum subtree_build_status { + subtree_got_error, /* Oops, something broke */ + subtree_more_to_do, /* Processed node, still more to do */ + subtree_did_last_node, /* Processed last node */ + subtree_all_done /* We're good */ +}; +static enum subtree_build_status subtree_add_next_node( + struct subtree *subtree, + struct merkle_level *tree, + int next_tree, + struct thread_collection *col) { + unsigned subtree_size = (subtree->level>0 ? tree->subtree_size : + tree->top_subtree_size); + unsigned log_leafs = subtree_size + subtree->levels_below; + merkle_index_t max_index = (merkle_index_t)1 << log_leafs; + /* Check if there is anything more to do */ + if (subtree->current_index == max_index) return subtree_all_done; + unsigned hash_size = tree->hash_size; + unsigned char cur_val[MAX_HASH]; + + /* Compute the leaf node */ + merkle_index_t i; + unsigned ots_len = (unsigned int)lm_ots_get_public_key_len(tree->lm_ots_type); + unsigned char pub_key[ LEAF_MAX_LEN ]; + const unsigned char *I = (next_tree ? tree->I_next : tree->I); + memcpy( pub_key + LEAF_I, I, I_LEN ); + SET_D( pub_key + LEAF_D, D_LEAF ); + merkle_index_t r = subtree->left_leaf + subtree->current_index; + merkle_index_t q = r | ((merkle_index_t)1 << tree->level); + put_bigendian( pub_key + LEAF_R, q, 4); + + const unsigned char *seed = (next_tree ? tree->seed_next : tree->seed); + struct seed_derive derive; + if (!hss_seed_derive_init( &derive, tree->lm_type, tree->lm_ots_type, + I, seed )) return subtree_got_error; + hss_seed_derive_set_q(&derive, r); + if (!lm_ots_generate_public_key(tree->lm_ots_type, I, + r, &derive, pub_key + LEAF_PK, ots_len)) { + hss_seed_derive_done(&derive); + return subtree_got_error; + } + hss_seed_derive_done(&derive); + + /* Hash it to form the leaf node */ + union hash_context ctx; + hss_hash_ctx( cur_val, tree->h, &ctx, pub_key, LEAF_LEN(hash_size)); + + /* Where in the subtree we store the values */ + merkle_index_t subtree_index = subtree->current_index + + ((merkle_index_t)1 << log_leafs); + enum subtree_build_status status = subtree_more_to_do; + + /* Walk up the stack, and then up the tree */ + for (i=0;; i++) { + if (i >= subtree->levels_below) { + /* This node is within the subtree; save it */ + memcpy( &subtree->nodes[ (subtree_index-1) * hash_size ], cur_val, hash_size ); + } + if (subtree_index == 1) { /* Hit the root */ + status = subtree_did_last_node; + break; + } + if ((q & 1) == 0) break; /* Hit a left node */ + q >>= 1; + + /* This is a right node; combine it with the left node */ + unsigned char *left_node; + if (i >= subtree->levels_below) { + /* The left node is in the tree */ + left_node = &subtree->nodes[ (subtree_index-2) * hash_size ]; + } else { + /* The left node is on the stack */ + left_node = subtree->stack + (i * hash_size); + } + hss_combine_internal_nodes( cur_val, + left_node, cur_val, + tree->h, I, hash_size, + q); + subtree_index >>= 1; + } + + /* If we haven't got out of the stack, put the value there */ + if (i < subtree->levels_below) { + if (col) hss_thread_before_write(col); + memcpy( subtree->stack + (i * hash_size), cur_val, hash_size ); + if (col) hss_thread_after_write(col); + } + + /* Ok, we've done another node */ + subtree->current_index += 1; + + return status; +} + +/* + * This steps the next tree by one. We need to do this 2**tree->level times, + * and then the next tree will be ready + */ +static int hss_step_next_tree (struct merkle_level *tree, + const struct hss_working_key *w, + struct thread_collection *col) { + struct subtree *prev_subtree = 0; + struct subtree *subtree = 0; + int j; + + LMS_UNUSED(w); + /* Search for the subtree to update */ + for (j = tree->sublevels-1; j>=0; j--) { + subtree = tree->subtree[j][NEXT_TREE]; + if (subtree->current_index < MAX_SUBINDEX) break; + prev_subtree = subtree; + } + unsigned height_subtree = (j == 0) ? tree->top_subtree_size : + tree->subtree_size; + if (j >= 0) { + /* For subtrees other than the bottom one, we get the first */ + /* node 'for free' (as it's the root of the previous subtree */ + if (subtree->current_index == 0 && prev_subtree) { + /* For the initial node of the subtree, reuse the root */ + /* of the previous one */ + unsigned hash_size = tree->hash_size; + memcpy( &subtree->nodes[ hash_size * (((merkle_index_t)1<nodes[ 0 ], + hash_size ); + subtree->current_index = ((merkle_index_t)1 << subtree->levels_below); + } + + /* Add the next node */ + switch (subtree_add_next_node( subtree, tree, 1, col )) { + case subtree_got_error: default: return 0; /* Huh? */ + case subtree_more_to_do: + break; + case subtree_did_last_node: + case subtree_all_done: + /* Mark this subtree as 'all processed' */ + subtree->current_index = MAX_SUBINDEX; + break; + } + } + + return 1; +} + +/* + * Generate the next Merkle signature for a given level + */ +static int generate_merkle_signature( + unsigned char *signature, unsigned signature_len, + struct merkle_level *tree, + const struct hss_working_key *w, + const void *message, size_t message_len) { + /* First off, write the index value */ + LMS_UNUSED(w); + if (signature_len < 4) return 0; + merkle_index_t current_index = tree->current_index; + put_bigendian( signature, current_index, 4 ); + signature += 4; signature_len -= 4; + + /* Write the OTS signature */ + size_t ots_sig_size = lm_ots_get_signature_len( tree->lm_ots_type ); + if (ots_sig_size == 0 || ots_sig_size > signature_len) return 0; + if (message == NULL) { + /* Internal interface: if message = NULL, we're supposed to */ + /* generate everything *except* the OTS signature */ + memset( signature, 0, ots_sig_size ); + } else { + struct seed_derive derive; + if (!hss_seed_derive_init( &derive, + tree->lm_type, tree->lm_ots_type, + tree->I, tree->seed )) return 0; + hss_seed_derive_set_q(&derive, current_index); + bool success = lm_ots_generate_signature( tree->lm_ots_type, tree->I, + current_index, &derive, + message, message_len, false, + signature, ots_sig_size); + hss_seed_derive_done(&derive); + if (!success) return 0; + } + signature += ots_sig_size; signature_len -= (unsigned)ots_sig_size; + + /* Write the LM parameter set */ + if (signature_len < 4) return 0; + put_bigendian( signature, tree->lm_type, 4 ); + signature += 4; signature_len -= 4; + + /* Now, write the authentication path */ + int i, j; + merkle_index_t index = current_index; + unsigned n = tree->hash_size; + for (i = tree->sublevels-1; i>=0; i--) { + int height = (i == 0) ? tree->top_subtree_size : tree->subtree_size; + struct subtree *subtree = tree->subtree[i][ACTIVE_TREE]; + merkle_index_t subtree_index = (index & + (((merkle_index_t)1 << height) - 1)) + + ((merkle_index_t)1 << height); + for (j = height-1; j>=0; j--) { + if (signature_len < n) return 0; + memcpy( signature, subtree->nodes + n * ((subtree_index^1) - 1), n ); + signature += n; signature_len -= n; + subtree_index >>= 1; + } + index >>= height; + } + + /* Mark that we've generated a signature */ + tree->current_index = current_index + 1; + + return 1; +} + +/* + * This signed the root of tree with the parent; it places both the signature + * and the public key into signed_key + */ +bool hss_create_signed_public_key(unsigned char *signed_key, + size_t len_signature, + struct merkle_level *tree, + struct merkle_level *parent, + struct hss_working_key *w) { + /* Where we place the public key */ + unsigned char *public_key = signed_key + len_signature; + + /* Place the public key there */ + put_bigendian( public_key + 0, tree->lm_type, 4 ); + put_bigendian( public_key + 4, tree->lm_ots_type, 4 ); + memcpy( public_key + 8, tree->I, I_LEN ); + unsigned hash_size = tree->hash_size; + /* This is where the root hash is */ + memcpy( public_key + 8 + I_LEN, + tree->subtree[0][ACTIVE_TREE]->nodes, + hash_size ); + unsigned len_public_key = 8 + I_LEN + hash_size; + + /* Now, generate the signature */ + if (!generate_merkle_signature( signed_key, (unsigned)len_signature, + parent, w, public_key, len_public_key)) { + return false; + } + + parent->update_count = UPDATE_NEXT; /* The parent has generated a */ + /* signature; it's now eligible for another */ + /* round of updates */ + + return true; +} + +struct gen_sig_detail { + unsigned char *signature; + size_t signature_len; + const unsigned char *message; + size_t message_len; + struct hss_working_key *w; + enum hss_error_code *got_error; +}; +/* This does the actual signature generation */ +/* It is (potentially) run within a thread */ +static void do_gen_sig( const void *detail, struct thread_collection *col) { + const struct gen_sig_detail *d = detail; + size_t signature_len = d->signature_len; + unsigned char *signature = d->signature; + struct hss_working_key *w = d->w; + unsigned levels = w->levels; + + /* The number of signed public keys */ + if (signature_len < 4) goto failed; + put_bigendian( signature, levels - 1, 4 ); + signature += 4; signature_len -= 4; + /* The signed public keys */ + unsigned i; + for (i=1; isigned_pk_len[i]; + if (signature_len < len_signed_pk) goto failed; + memcpy( signature, w->signed_pk[i], len_signed_pk ); + signature += len_signed_pk; signature_len -= len_signed_pk; + } + /* And finally the signature of the actual message */ + if (signature_len < w->siglen[levels-1]) goto failed; /* Oops, not enough room */ + + const unsigned char *message = d->message; + size_t message_len = d->message_len; + + if (!generate_merkle_signature(signature, (unsigned)signature_len, + w->tree[ levels-1 ], w, message, message_len)) { + goto failed; + } + + /* Success! */ + return; + +failed: + /* Report failure */ + hss_thread_before_write(col); + *d->got_error = hss_error_internal; + hss_thread_after_write(col); +} + +struct step_next_detail { + struct hss_working_key *w; + struct merkle_level *tree; + enum hss_error_code *got_error; +}; +/* This steps the next tree */ +/* It is (potentially) run within a thread */ +static void do_step_next( const void *detail, struct thread_collection *col) { + const struct step_next_detail *d = detail; + struct hss_working_key *w = d->w; + struct merkle_level *tree = d->tree; + + if (!hss_step_next_tree( tree, w, col )) { + /* Report failure */ + hss_thread_before_write(col); + *d->got_error = hss_error_internal; + hss_thread_after_write(col); + } +} + +struct step_building_detail { + struct merkle_level *tree; + struct subtree *subtree; + enum hss_error_code *got_error; +}; +/* This steps the building tree */ +/* It is (potentially) run within a thread */ +static void do_step_building( const void *detail, + struct thread_collection *col) { + const struct step_building_detail *d = detail; + struct merkle_level *tree = d->tree; + struct subtree *subtree = d->subtree; + + switch (subtree_add_next_node( subtree, tree, 0, col )) { + case subtree_got_error: default: + /* Huh? Report failure */ + hss_thread_before_write(col); + *d->got_error = hss_error_internal; + hss_thread_after_write(col); + break; + case subtree_more_to_do: + case subtree_did_last_node: + case subtree_all_done: + break; + } +} + +struct update_parent_detail { + struct hss_working_key *w; + enum hss_error_code *got_error; +}; +/* + * This gives an update to the parent (non-bottom Merkle trees) + */ +static void do_update_parent( const void *detail, + struct thread_collection *col) { + const struct update_parent_detail *d = detail; + struct hss_working_key *w = d->w; + unsigned levels = w->levels; + unsigned current_level = levels - 2; /* We start with the first */ + /* non-bottom level */ + for (;;) { + struct merkle_level *tree = w->tree[current_level]; + switch (tree->update_count) { + case UPDATE_DONE: return; /* No more updates needed */ + case UPDATE_NEXT: /* Our job is to update the next tree */ + tree->update_count = UPDATE_PARENT; + if (current_level == 0) return; /* No next tree to update */ + if (!hss_step_next_tree( tree, w, col )) goto failed; + return; + case UPDATE_PARENT: /* Our job is to update our parent */ + tree->update_count = UPDATE_BUILDING + 0; + if (current_level == 0) return; /* No parent to update */ + current_level -= 1; + continue; + default: { + /* Which building tree we need to update */ + unsigned level_to_update = + (tree->update_count - UPDATE_BUILDING) + 1; + if (level_to_update >= tree->sublevels) { + /* We've completed all the updates we need to do (until */ + /* the next time we need to sign something) */ + tree->update_count = UPDATE_DONE; + return; + } + + /* Next time, update the next BUILDING subtree */ + tree->update_count += 1; + + struct subtree *subtree = + tree->subtree[level_to_update][BUILDING_TREE]; + + /* The number of leaves in this tree */ + merkle_index_t tree_leaves = (merkle_index_t)1 << tree->level; + + /* Check if we'd actually use the building tree */ + if (subtree->left_leaf >= tree_leaves) { + /* We'll never use it; don't bother updating it */ + return; + } + + /* We'll use the BUILDING_TREE, actually add a node */ + switch (subtree_add_next_node( subtree, tree, 0, col )) { + case subtree_got_error: default: goto failed; /* Huh? */ + case subtree_did_last_node: + case subtree_all_done: + case subtree_more_to_do: + /* We're done everything we need to do for this step */ + return; + } + } + } + } + +failed: + /* Huh? Report failure */ + hss_thread_before_write(col); + *d->got_error = hss_error_internal; + hss_thread_after_write(col); +} + +/* + * Code to actually generate the signature + */ +bool hss_generate_signature( + struct hss_working_key *w, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + const void *message, size_t message_len, + unsigned char *signature, size_t signature_buf_len, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + unsigned i; + bool trash_private_key = false; + + info->last_signature = false; + + if (!w) { + info->error_code = hss_error_got_null; + goto failed; + } + if (w->status != hss_error_none) { + info->error_code = w->status; + goto failed; + } + + /* If we're given a raw private key, make sure it's the one we're */ + /* thinking of */ + if (!update_private_key) { + if (0 != memcmp( context, w->private_key, PRIVATE_KEY_LEN)) { + info->error_code = hss_error_key_mismatch; + return false; /* Private key mismatch */ + } + } + + /* Check if the buffer we were given is too short */ + if (w->signature_len > signature_buf_len) { + /* The signature would overflow the buffer */ + info->error_code = hss_error_buffer_overflow; + goto failed; + } + + unsigned levels = w->levels; + /* + * Compile the current count + */ + sequence_t current_count = 0; + for (i=0; i < levels; i++) { + struct merkle_level *tree = w->tree[i]; + current_count <<= tree->level; + /* We subtract 1 because the nonbottom trees are already advanced */ + current_count += (sequence_t)tree->current_index - 1; + } + current_count += 1; /* Bottom most tree isn't already advanced */ + + /* Ok, try to advance the private key */ + if (!hss_advance_count(w, current_count, + update_private_key, context, info, + &trash_private_key)) { + /* hss_advance_count fills in the error reason */ + goto failed; + } + + /* Ok, now actually generate the signature */ + + /* We'll be doing several things in parallel */ + struct thread_collection *col = hss_thread_init(info->num_threads); + enum hss_error_code got_error = hss_error_none; + + /* Generate the signature */ + { + struct gen_sig_detail gen_detail; + gen_detail.signature = signature; + gen_detail.signature_len = w->signature_len; + gen_detail.message = message; + gen_detail.message_len = message_len; + gen_detail.w = w; + gen_detail.got_error = &got_error; + + hss_thread_issue_work(col, do_gen_sig, &gen_detail, sizeof gen_detail); + } + + /* Update the bottom level next tree */ + if (levels > 1) { + struct step_next_detail step_detail; + step_detail.w = w; + step_detail.tree = w->tree[levels-1]; + step_detail.got_error = &got_error; + + hss_thread_issue_work(col, do_step_next, &step_detail, sizeof step_detail); + } + + /* Issue orders to step each of the building subtrees in the bottom tree */ + int skipped_a_level = 0; /* Set if the below issued didn't issue an */ + /* order for at least one level */ + { + struct merkle_level *tree = w->tree[levels-1]; + merkle_index_t updates_before_end = tree->max_index - tree->current_index + 1; + int h_subtree = tree->subtree_size; + for (i=1; isublevels; i++) { + struct subtree *subtree = tree->subtree[i][BUILDING_TREE]; + /* Check if there is a building tree */ + if (updates_before_end < (merkle_index_t)1 << + (subtree->levels_below + h_subtree)) { + /* No; we're at the last subtree within this tree */ + skipped_a_level = 1; + continue; + } + struct step_building_detail step_detail; + step_detail.tree = tree; + step_detail.subtree = subtree; + step_detail.got_error = &got_error; + + hss_thread_issue_work(col, do_step_building, &step_detail, sizeof step_detail); + + } + /* If there's only one sublevel, act as if we always skipped a sublevel */ + if (tree->sublevels == 1) skipped_a_level = 1; + } + + /* + * And, if we're allowed to give the parent a chance to update, and + * there's a parent with some updating that needs to be done, schedule + * that to be done + */ + if (skipped_a_level && + levels > 1 && w->tree[levels-2]->update_count != UPDATE_DONE) { + struct update_parent_detail detail; + detail.w = w; + detail.got_error = &got_error; + hss_thread_issue_work(col, do_update_parent, &detail, sizeof detail); + } + + /* Wait for all of them to finish */ + hss_thread_done(col); + + /* Check if any of them reported a failure */ + if (got_error != hss_error_none) { + info->error_code = got_error; + goto failed; + } + + current_count += 1; /* The new count is one more than what is */ + /* implied by the initial state of the Merkle trees */ + + /* + * Now, we scan to see if we exhausted a Merkle tree, and need to update it + * At the same time, we check to see if we need to advance the subtrees + */ + sequence_t cur_count = current_count; + unsigned merkle_levels_below = 0; + int switch_merkle = w->levels; + struct merkle_level *tree; + for (i = w->levels; i>=1; i--, merkle_levels_below += tree->level) { + tree = w->tree[i-1]; + + if (0 == (cur_count & (((sequence_t)1 << (merkle_levels_below + tree->level))-1))) { + /* We exhausted this tree */ + if ((i-1) == 0) { + /* We've run out of signatures; we've already caught this */ + /* above; just make *sure* we've marked the key as */ + /* unusable, and give up */ + w->status = hss_error_private_key_expired; + break; + } + + /* Remember we'll need to switch to the NEXT_TREE */ + switch_merkle = i-1; + continue; + } + + /* Check if we need to advance any of the subtrees */ + unsigned subtree_levels_below = 0; + unsigned j; + for (j = tree->sublevels-1; j>0; j--) { + subtree_levels_below += tree->subtree_size; + if (0 != (cur_count & (((sequence_t)1 << (merkle_levels_below + subtree_levels_below))-1))) { + /* We're in the middle of this subtree */ + goto done_advancing; + } + + /* Switch to the building subtree */ + struct subtree *next = tree->subtree[j][BUILDING_TREE]; + struct subtree *prev = tree->subtree[j][ACTIVE_TREE]; + unsigned char *stack = next->stack; /* Stack stays with */ + /* building tree */ + tree->subtree[j][ACTIVE_TREE] = next; + /* We need to reset the parameters on the new building subtree */ + prev->current_index = 0; + prev->left_leaf += (merkle_index_t)2 << subtree_levels_below; + tree->subtree[j][BUILDING_TREE] = prev; + next->stack = NULL; + prev->stack = stack; + } + } +done_advancing: + /* Check if we used up any Merkle trees; if we have, switch to the */ + /* NEXT_TREE (which we've built in our spare time) */ + for (i = switch_merkle; i < w->levels; i++) { + struct merkle_level *tree_l = w->tree[i]; + struct merkle_level *parent = w->tree[i-1]; + unsigned j; + + /* Rearrange the subtrees */ + for (j=0; jsublevels; j++) { + /* Make the NEXT_TREE active; replace it with the current active */ + struct subtree *active = tree_l->subtree[j][NEXT_TREE]; + struct subtree *next = tree_l->subtree[j][ACTIVE_TREE]; + unsigned char *stack = active->stack; /* Stack stays with */ + /* next tree */ + + active->left_leaf = 0; + next->current_index = 0; + next->left_leaf = 0; + tree_l->subtree[j][ACTIVE_TREE] = active; + tree_l->subtree[j][NEXT_TREE] = next; + active->stack = NULL; + next->stack = stack; + if (j > 0) { + /* Also reset the building tree */ + struct subtree *building = tree->subtree[j][BUILDING_TREE]; + building->current_index = 0; + merkle_index_t size_subtree = (merkle_index_t)1 << + (tree->subtree_size + building->levels_below); + building->left_leaf = size_subtree; + } + } + + /* Copy in the value of seed, I we'll use for the new tree */ + memcpy( tree_l->seed, tree->seed_next, SEED_LEN ); + memcpy( tree_l->I, tree->I_next, I_LEN ); + + /* Compute the new next I, which is derived from either the parent's */ + /* I or the parent's I_next value */ + merkle_index_t index = parent->current_index; + if (index == parent->max_index) { + hss_generate_child_seed_I_value(tree->seed_next, tree->I_next, + parent->seed_next, parent->I_next, 0, + parent->lm_type, + parent->lm_ots_type); + } else { + hss_generate_child_seed_I_value( tree->seed_next, tree->I_next, + parent->seed, parent->I, index+1, + parent->lm_type, + parent->lm_ots_type); + } + + tree_l->current_index = 0; /* We're starting this from scratch */ + + /* Generate the signature of the new level */ + if (!hss_create_signed_public_key( w->signed_pk[i], w->siglen[i-1], + tree_l, parent, w )) { + info->error_code = hss_error_internal; + goto failed; + } + } + + /* And we've set things up for the next signature... */ + + if (trash_private_key) { + memset( w->private_key, PARM_SET_END, PRIVATE_KEY_LEN ); + } + + return true; + +failed: + + if (trash_private_key) { + memset( w->private_key, PARM_SET_END, PRIVATE_KEY_LEN ); + } + + /* On failure, make sure that we don't return anything that might be */ + /* misconstrued as a real signature */ + memset( signature, 0, signature_buf_len ); + return false; +} + +/* + * Get the signature length + */ +size_t hss_get_signature_len_from_working_key(struct hss_working_key *w) { + if (!w || w->status != hss_error_none) return 0; + + int levels = w->levels; + if (levels > MAX_HSS_LEVELS) return 0; + param_set_t lm[MAX_HSS_LEVELS], ots[MAX_HSS_LEVELS]; + int i; + for (i=0; itree[i]->lm_type; + ots[i] = w->tree[i]->lm_ots_type; + } + + return hss_get_signature_len(levels, lm, ots); +} diff --git a/src/sig_stfl/lms/external/hss_sign_inc.c b/src/sig_stfl/lms/external/hss_sign_inc.c new file mode 100644 index 0000000000..ab3112ee03 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_sign_inc.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the hierarchical part of the LMS hash + * based signatures; in this case, incremental signing + */ +#include +#include "hss.h" +#include "common_defs.h" +#include "hss_verify_inc.h" +#include "lm_verify.h" +#include "lm_common.h" +#include "lm_ots.h" +#include "lm_ots_verify.h" +#include "hash.h" +#include "endian.h" +#include "hss_internal.h" +#include "hss_sign_inc.h" +#include "hss_derive.h" +#include + +/* + * Start the process of creating an HSS signature incrementally. Parameters: + * ctx - The state we'll use to track the incremental signature + * working_key - the in-memory version of the in-memory private key + * update_private_key - function to call to update the master private key + * context - context pointer for above + * siganture - the buffer to hold the signature + * signature_len - the length of the buffer + * this_is_the_last_signature - if non-NULL, this will be set if this + * signature is the last for this private key + */ +#ifdef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +bool hss_sign_init( + struct hss_sign_inc *ctx, + struct hss_working_key *w, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned char *signature, size_t signature_len, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 };; + if (!info) info = &temp_info; + + if (!ctx) { + info->error_code = hss_error_got_null; + return false; + } + ctx->status = hss_error_ctx_uninitialized; /* Until we hear otherwise, */ + /* we got a failure */ + + if (!w) { + info->error_code = hss_error_got_null; + return false; + } + if (w->status != hss_error_none) { + info->error_code = w->status; + return false; + } + + struct merkle_level *bottom = w->tree[ w->levels - 1 ]; + + unsigned char I[I_LEN]; + memcpy( I, bottom->I, I_LEN ); + + /* Compute the value of C we'll use */ + merkle_index_t q = bottom->current_index; + ctx->q = q; + int h = bottom->h; + ctx->h = h; + + struct seed_derive derive; + if (!hss_seed_derive_init( &derive, bottom->lm_type, bottom->lm_ots_type, + bottom->I, bottom->seed )) return false; + hss_seed_derive_set_q(&derive, q); + lm_ots_generate_randomizer( ctx->c, bottom->hash_size, &derive ); + hss_seed_derive_done(&derive); + + /* + * Ask the signature generation process to do everything *except* + * the bottom level OTS signature + */ + bool success = hss_generate_signature( w, + update_private_key, context, + NULL, 0, /* <--- we don't have the message yet */ + signature, signature_len, info ); + if (!success) { + /* On failure, hss_generate_signature fills in the failure reason */ + ctx->status = info->error_code; + hss_zeroize( &ctx->c, sizeof ctx->c ); /* People don't get to */ + /* learn what randomizer we would have used */ + return false; + } + + /* Now, initialize the context */ + hss_init_hash_context( h, &ctx->hash_ctx ); + { + unsigned char prefix[ MESG_PREFIX_MAXLEN ]; + memcpy( prefix + MESG_I, I, I_LEN ); + unsigned q_bin[4]; put_bigendian( q_bin, q, 4 ); + memcpy( prefix + MESG_Q, q_bin, 4 ); /* q */ + SET_D( prefix + MESG_D, D_MESG ); + int n = bottom->hash_size; + memcpy( prefix + MESG_C, ctx->c, n ); /* C */ + hss_update_hash_context(h, &ctx->hash_ctx, prefix, MESG_PREFIX_LEN(n) ); + } + + /* It succeeded so far... */ + ctx->status = hss_error_none; + return true; +} + +/* This adds another piece of the message to validate */ +bool hss_sign_update( + struct hss_sign_inc *ctx, + const void *message_segment, + size_t len_message_segment) { + if (!ctx || ctx->status != hss_error_none) return false; + + hss_update_hash_context(ctx->h, &ctx->hash_ctx, + message_segment, len_message_segment ); + + return true; +} + +/* We've added all the pieces of the messages, now do the validation */ +bool hss_sign_finalize( + struct hss_sign_inc *ctx, + const struct hss_working_key *working_key, + unsigned char *signature, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + + if (!ctx) { + info->error_code = hss_error_got_null; + return false; + } + if (ctx->status != hss_error_none) { + info->error_code = ctx->status; + return false; + } + + /* Success or fail, we can't use the context any more */ + ctx->status = hss_error_ctx_already_used; + + int L = working_key->levels; + + /* Step through the signature, looking for the place to put the OTS */ + /* signature, and (while we're at it) recovering the I and seed values */ + const unsigned char *I = working_key->tree[0]->I; + const unsigned char *seed = working_key->tree[0]->seed; + /* Note: we alternate buffers during generation in case */ + /* hss_generate_child_seed_I_value doesn't allow new values to */ + /* overwrite old ones */ + unsigned char I_buff[2][I_LEN]; + unsigned char seed_buff[2][SEED_LEN]; + + /* Q: should we double check the various fixed fields of the signatures */ + /* (e.g. the number of signed keys, the parameter sets? */ + + signature += 4; + + int i; + for (i=0; i working_key->tree[i]->max_index) { + hss_zeroize( seed_buff, sizeof seed_buff ); + return 0; + } + if (!hss_generate_child_seed_I_value( seed_buff[i&1], I_buff[i&1], + seed, I, q, + working_key->tree[i]->lm_type, + working_key->tree[i]->lm_ots_type )) { + hss_zeroize( seed_buff, sizeof seed_buff ); + info->error_code = hss_error_internal; + return false; + } + + seed = seed_buff[i&1]; + I = I_buff[i&1]; + + /* Step to the end of this signed key */ + signature += lm_get_signature_len( working_key->tree[i]->lm_type, + working_key->tree[i]->lm_ots_type); + signature += lm_get_public_key_len(working_key->tree[i+1]->lm_type); + } + + /* Now, signature points to where the bottom LMS signature should go */ + /* It starts with the q value */ + put_bigendian( signature, ctx->q, 4 ); + signature += 4; + /* And then the LM-OTS signature */ + + /* Copy in the C value into the signature */ + memcpy( signature+4, ctx->c, 32 ); + + /* Generate the final hash */ + unsigned char hash[ MAX_HASH ]; + hss_finalize_hash_context( ctx->h, &ctx->hash_ctx, hash ); + + /* And the final OTS signature based on that hash */ + param_set_t lm_type = working_key->tree[i]->lm_type; + param_set_t ots_type = working_key->tree[i]->lm_ots_type; + struct seed_derive derive; + bool success = hss_seed_derive_init( &derive, lm_type, ots_type, + I, seed ); + if (success) { + hss_seed_derive_set_q( &derive, ctx->q ); + success = lm_ots_generate_signature( + ots_type, I, ctx->q, &derive, hash, 0, true, + signature, lm_ots_get_signature_len( ots_type )); + + hss_seed_derive_done( &derive ); + } + if (!success) { + info->error_code = hss_error_internal; + } + + hss_zeroize( seed_buff, sizeof seed_buff ); + return success; +} +#endif diff --git a/src/sig_stfl/lms/external/hss_sign_inc.h b/src/sig_stfl/lms/external/hss_sign_inc.h new file mode 100644 index 0000000000..ddca5ea63e --- /dev/null +++ b/src/sig_stfl/lms/external/hss_sign_inc.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_SIGN_INC_H_ ) +#define HSS_SIGN_INC_H_ +#include +#include +#include "hash.h" +#include "common_defs.h" +#include "lms_namespace.h" + +/* + * These are the functions to sign a message incrementally. + * That is, we assume that we don't have the entire message at + * once, instead, we have it in pieces (for example, the signature + * is of a multigigabyte file) + * + * Usage: + * struct hss_sign_inc ctx; + * bool success = hss_sign_init( &ctx, working_key, + * update_private_key, private_key_context, + * signature, signature_buffer_len, + * &lsat_signature ); + * hss_sign_update( &ctx, message_part_1, len_1 ); + * hss_sign_update( &ctx, message_part_2, len_2 ); + * hss_sign_update( &ctx, message_part_3, len_3 ); + * success = hss_sign_finalize( &ctx, working_key, signature ); + * if (success) printf( "We generated the signature\n" ); + * + * This is in its own include file because we need to import some + * 'not-generally-for-general-consumption' include files to make + * it work (as they're in the hss_sign_inc structure) + */ + +/* + * This is the context structure that holds the intermedate results of an + * in-process signature + * It's a application-visible structure for ease of use: the application can + * allocate it as an automatic, and if the application aborts in the middle of + * signing, it doesn't cause a memory leak + */ +struct hss_sign_inc { + enum hss_error_code status; /* Either hss_error_none if we're in */ + /* process, or the reason why we'd fail */ + + int h; /* The hash function */ + merkle_index_t q; /* The index of the bottom level signature */ + union hash_context hash_ctx; /* For the running hash we use */ + + unsigned char c[MAX_HASH]; /* The C value we used */ +}; + +struct hss_extra_info; + +/* Starts off the process of incrementally signing a message */ +/* If it detects a failure, this returns false */ +/* Handing the return code is optional; if this fails, the finalization */ +/* step will fail too */ +bool hss_sign_init( + struct hss_sign_inc *ctx, + struct hss_working_key *working_key, + bool (*update_private_key)(unsigned char *private_key, + size_t len_private_key, void *context), + void *context, + unsigned char *signature, size_t signature_len, + struct hss_extra_info *info); + +/* This adds another piece of the message to sign */ +/* Again, the result code is optional */ +bool hss_sign_update( + struct hss_sign_inc *ctx, + const void *message_segment, + size_t len_message_segment); + +/* This finalizes the signature generation */ +/* This returns true if the signature was generated properly */ +/* We ask the caller to pass in the working key again, we need to review */ +/* the private key (we don't want to place it in the context) */ +bool hss_sign_finalize( + struct hss_sign_inc *ctx, + const struct hss_working_key *working_key, + unsigned char *signature, + struct hss_extra_info *info); + +#endif /* HSS_SIGN_INC_H_ */ diff --git a/src/sig_stfl/lms/external/hss_thread.h b/src/sig_stfl/lms/external/hss_thread.h new file mode 100644 index 0000000000..d2dcd8a3ea --- /dev/null +++ b/src/sig_stfl/lms/external/hss_thread.h @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_THREAD_H_ ) +#define HSS_THREAD_H_ +/* + * This is our internal abstraction of multithreading; this allows the + * "application" (in this case, the HSS code) to issue multiple requests that + * can potentially run on different threads, in a way that doesn't depend on + * the actual threading capability of the OS. If we don't actually have + * multiple threads avaiable (either because the OS doesn't provide us with + * multiple threads, or we hit an internal error trying to generate new + * threads), this will just have the main thread do all the work (and hence + * the application doesn't have to worry its pretty little head about error + * handling, or whether we actually implement threads in the first place) + * + * This is designed to handle this sort of task: we have a series of + * computational problems to do; each can be done independently of the others, + * and each problem results in a fairly short answer. All the children do is + * computation; there's no I/O or any other interaction with the OS at all. + * + * The general paradigm is: + * - The main thread generates a thread collection (via the hss_thread_init + * call) + * - The main thread then issues a series of tasks (via the + * hss_thread_issue_work call). This may spawn off other threads (which + * will then call the function passed); alternatively, the main thread may + * call the function. + * - The main thread then waits for all the tasks to be done (via the + * hss_thread_done call) + * The function(s) passed to the hss_thread_issue_work call will be completed + * by the time hss_thread_done returns + */ +#include +#include "lms_namespace.h" + +/* This is our abstract object that stands for a set of threads */ +struct thread_collection; + +/* + * This is called to initialize a set of threads, and returns the identifier. + * Note that this cannot fail; if it returns 0, it's not a failure; instead, + * it's a valid return (which essentially means we're running in nonthreaded + * mode) + * The integer passed is a recommendation on the number of threads + */ +struct thread_collection *hss_thread_init(int); + +/* + * This issues another work item to our collection of threads. At some point + * (between when hss_thread_issue_work is called and when hss_thread_done + * returns), we'll have function called, with a pointer to a copy of the detail + * structure. function may be called by this thread, or it may be called by a + * different one. + * + * The passed detail structure will not be referenced after this returns, and + * hence it is safe if the caller modifies (or frees) it afterwards. If the + * function isn't completed by the time hss_thread_issue_work returns, we'll + * squirrel away a copy of detail (which is why we ask the caller to + * pass size_detail_structure; so we know how much to copy) + * + * We suggest that the application issue the work orders in largest-to-smallest + * order. The ordering doesn't matter for correctness (the API makes no + * guarrantees about when the requests will be completed), however we suggest + * this for expected performance reasons. hss_thread_done will not return + * until all threads are done; what we want to avoid is scenarios where all but + * one of the threads are done, and that last thread is working on an expensive + * function; that would slow things down, and the entire point of this thread + * library is to speed things up. Assigning work items to threads optimally is + * an NP-hard problem, however the simple heuristic of packing 'largest first' + * works fairly well in practice (and is easy to implement). The thread library + * does try to make a best effort attempt to preserve the issue order (assuming + * no intermediate malloc or thread spawn issues; in those cases, the library + * prioritizes correctness over efficiency) + */ +void hss_thread_issue_work(struct thread_collection *col, + void (*function)(const void *detail, + struct thread_collection *col), + const void *detail, size_t size_detail_structure); + +/* + * This waits for all the work items we have issued (via hss_thread_issue_work) + * to be completed (that is, 'function' has returned, and cleans up the + * collection + * + * col must not be used after this; if it was malloc'ed, this will free it + */ +void hss_thread_done(struct thread_collection *col); + +/* + * This should be called before a thread writes to common data + * + * We do this because we sometimes have different threads write data to + * adjacent memory locations; if the compiler has the CPU do a + * read/modify/write to the entire word (or however the CPU has memory + * organized), this could cause a race condition. Forcing those writes to be + * serialized avoids the issue; such a race condition would actually be fairly + * unlikely, but would be a *really* difficult bug to track down if it did + * occur, so it makes sense to go the extra mile to avoid the possibility + * + * Doing this locking also means that the working thread can safely do things + * such as incrementing a global [1] counter to report its results, should + * that be appropriate + * + * We don't bother doing this if we're writing into a malloc'ed region, *if* + * we're the only thread that will be writing into that specific region; we + * assume that the malloc infrastructure will separate distinct malloc'ed + * regions enough to avoid such race conditions + * + * [1] actually, automatic to the main thread; there are no literal globals + * in this package, apart from the verbose debugging flag + */ +void hss_thread_before_write(struct thread_collection *collect); + +/* + * This should be called after a thread writes to common data; it releases + * the lock + */ +void hss_thread_after_write(struct thread_collection *collect); + +/* + * This gives the application guidance for how many worker threads we have + * available, that is, how many work items we can expect to run at once + * + * This is used to decide the level of granularity we need; we we have only 2 + * cores, there's no point is splitting the job up to 50 separate requests; + * however if there are 100 cores, we want (if possible) to do at least 100 + * + * The issue with having not enough requests is that we will have idle threads + * (which could potentially do useful work, if we are able to divide the work + * further). The issue with having too many requests is that the requests use + * up some memory, and we'd prefer not to use up too much memory (we don't + * fail on malloc failure, however we do drop back to a single threaded model) + * + * The value passed is the value we'll pass to hss_thread_init + */ +unsigned hss_thread_num_tracks(int num_threads); + +#endif /* HSS_THREAD_H_ */ diff --git a/src/sig_stfl/lms/external/hss_thread_pthread.c b/src/sig_stfl/lms/external/hss_thread_pthread.c new file mode 100644 index 0000000000..1ea90cc161 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_thread_pthread.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: MIT +#include "hss_thread.h" + +#include +#include + +/* + * This is an implementation of our threaded abstraction using the + * POSIX pthread API + * + * C11 has a similar (but not precisely identical) API to the one that POSIX + * defines (at least for what we do; all we need is thread create/join and + * mutex's, which *any* thread library should provide). I'd code up the + * support for that API as well (using the same base logic, with typedef's and + * helper inlines to isolate the differences), however I don't have a C11 + * implementation handy to test it + */ + +#define MAX_THREAD 16 /* Number try to create more than 16 threads, no */ + /* matter what the application tries to tell us */ +#define DEFAULT_THREAD 16 /* The number of threads to run if the */ + /* application doesn't tell us otherwise (e.g. */ + /* passes in 0) */ + +#define MIN_DETAIL 16 /* So the alignment kludge we do doesn't waste space */ + +/* The information we track about a thread we may have launched */ +struct thread_state { + pthread_t thread_id; + enum { never_was, alive, dead } state; +}; + +struct work_item { + struct work_item *link; /* They're in a linked list */ + + void (*function)(const void *detail, /* Function to call */ + struct thread_collection *col); + + /* These two items are used to pass the thread state to the thread */ + /* if this is the first work item for the thread to process */ + struct thread_collection *col; /* The parent thread_collection */ + struct thread_state *state; /* The pointer into the thread collection */ + /* state for the state of this thread */ + + /* The detail structure that we pass to the function */ + /* We'll malloc enough space to hold the entire structure */ + union { /* union here so that the detail array is */ + void *align1; /* correctly aligned for various datatypes */ + long long align2; + void (*align3)(void); + unsigned char detail[MIN_DETAIL]; + } x; +}; + +struct thread_collection { + pthread_mutex_t lock; /* Must be locked before this structure is */ + /* accessed if there might be a thread */ + pthread_mutex_t write_lock; /* Must be locked before common user data is */ + /* written */ + + unsigned num_thread; + unsigned current_ptr; /* There two are here to avoid O(N) table */ + unsigned num_alive; /* scanning in the most common scenarios */ + + /* Information about the worker threads we may have created */ + struct thread_state threads[MAX_THREAD]; + + /* + * Queue (FIFO) of work items submitted, and which can't be processed + * immedately. We do a FIFO, rather than a stack, so that we perform + * the requests in the order they were issued (which isn't something + * the interface guarantees; however it doesn't interfere with the + * request ordering we ask applications to make) + */ + struct work_item *top_work_queue; + struct work_item *end_work_queue; +}; + +/* + * Allocate a thread control structure + */ +struct thread_collection *hss_thread_init(int num_thread) { + if (num_thread == 0) num_thread = DEFAULT_THREAD; + if (num_thread <= 1) return 0; /* Not an error: an indication to run */ + /* single threaded */ + if (num_thread > MAX_THREAD) num_thread = MAX_THREAD; + + struct thread_collection *col = malloc( sizeof *col ); + if (!col) return 0; /* On malloc failure, run single threaded */ + + col->num_thread = num_thread; + + if (0 != pthread_mutex_init( &col->lock, 0 )) { + free(col); // IGNORE free-check + return 0; + } + + if (0 != pthread_mutex_init( &col->write_lock, 0 )) { + pthread_mutex_destroy( &col->lock ); + free(col); // IGNORE free-check + return 0; + } + + col->current_ptr = 0; + col->num_alive = 0; + int i; + for (i=0; ithreads[i].state = never_was; + } + col->top_work_queue = 0; + col->end_work_queue = 0; + + return col; +} + +/* + * This is the base routine that a worker thread runs + */ +static void *worker_thread( void *arg ) { + struct work_item *w = arg; /* The initial work item */ + struct thread_collection *col = w->col; + struct thread_state *state = w->state; + + for (;;) { + /* Perform the work item in front of us */ + (w->function)(w->x.detail, col); + + /* Ok, we did that */ + free(w); // IGNORE free-check + + /* Check if there's anything else to do */ + pthread_mutex_lock( &col->lock ); + + w = col->top_work_queue; + if (w) { + /* More work; pull it off the queue */ + col->top_work_queue = w->link; + if (w == col->end_work_queue) col->end_work_queue = 0; + + /* And go handle it */ + pthread_mutex_unlock( &col->lock ); + continue; + } + + /* No more work for us to do; post our obituary */ + state->state = dead; + col->num_alive -= 1; + pthread_mutex_unlock( &col->lock ); + + /* And that's all folks */ + return 0; + } +} + +/* + * This adds function/details to the list of things that need to be done + * It either creates a thread to do it, or (if we're maxed out) add it to + * our honey-do list (or, as last resort, just does it itself) + */ +void hss_thread_issue_work(struct thread_collection *col, + void (*function)(const void *detail, + struct thread_collection *col), + const void *detail, size_t size_detail_structure) { + + /* If we're running in single-threaded mode */ + if (!col) { + function( detail, col ); + return; + } + + /* Allocate a work structure to hold this request */ + size_t extra_space; + if (size_detail_structure < MIN_DETAIL) extra_space = 0; + else extra_space = size_detail_structure - MIN_DETAIL; + struct work_item *w = malloc(sizeof *w + extra_space); + + if (!w) { + /* Can't allocate the work structure; fall back to single-threaded */ + function( detail, col ); + return; + } + w->col = col; + w->function = function; + memcpy( w->x.detail, detail, size_detail_structure ); + + unsigned num_thread = col->num_thread; + + pthread_mutex_lock( &col->lock ); + + /* Check if we can spawn a new thread */ + if (col->num_alive < num_thread) { + /* There's supposed to be room for another */ + /* Look for the empty slot */ + unsigned i, j; + j = col->current_ptr; /* Do round-robin (so we don't bang on */ + /* slot 0 whenever we try to start a thread) */ + for (i=0; ithreads[j]; + switch (p->state) { + case alive: continue; /* This one's busy */ + case dead: + { + /* This one just died; grab its status (not that we care, */ + /* however that'll tell the thread library it can clean up) */ + pthread_t thread_id = p->thread_id; + void *status; /* Ignored, but we need to place thread */ + /* status somewhere */ + pthread_mutex_unlock( &col->lock ); + pthread_join( thread_id, &status ); + pthread_mutex_lock( &col->lock ); + p->state = never_was; + } + /* FALL THROUGH */ + case never_was: + /* Now, we can spawn a new thread */ + w->state = p; + if (0 != pthread_create( &p->thread_id, + NULL, worker_thread, w )) { + /* Hmmm, couldn't spawn it; fall back */ + default: /* On error condition */ + pthread_mutex_unlock( &col->lock ); + free(w); // IGNORE free-check + function( detail, col ); + return; + } + + /* We've kicked off the thread */ + p->state = alive; + col->num_alive += 1; + /* For the next request, start scanning at the next */ + /* thread object */ + col->current_ptr = (j+1) % num_thread; + pthread_mutex_unlock( &col->lock ); + return; + } + } + col->num_alive = num_thread; /* Hmmmm, everything was alive??? */ + } + + /* We can't create any more threads; enqueue this (and someone will get */ + /* to it) */ + w->link = 0; + if (col->end_work_queue) { + col->end_work_queue->link = w; + } + col->end_work_queue = w; + if (!col->top_work_queue) col->top_work_queue = w; + + pthread_mutex_unlock( &col->lock ); +} + +/* + * This will wait for all the work items we'e issued to complete + */ +void hss_thread_done(struct thread_collection *col) { + if (!col) return; + + unsigned i; + pthread_mutex_lock( &col->lock ); + for (i=0; inum_thread; i++) { + /* + * Wait for each thread that we have spawned. + * We're the only one that will spawn them, and so we don't have to + * worry about any new ones appearing while we scan through the list + */ + if (col->threads[i].state != never_was) { + void *status; + pthread_t thread_id = col->threads[i].thread_id; + pthread_mutex_unlock( &col->lock ); + pthread_join( thread_id, &status ); + pthread_mutex_lock( &col->lock ); + } + } + pthread_mutex_unlock( &col->lock ); + + /* Ok, all the threads have finished; tear things down */ + + pthread_mutex_destroy( &col->lock ); + pthread_mutex_destroy( &col->write_lock ); + free(col); // IGNORE free-check +} + +void hss_thread_before_write(struct thread_collection *col) { + if (!col) return; + pthread_mutex_lock( &col->write_lock ); +} + +void hss_thread_after_write(struct thread_collection *col) { + if (!col) return; + pthread_mutex_unlock( &col->write_lock ); +} + + +unsigned hss_thread_num_tracks(int num_thread) { + if (num_thread == 0) num_thread = DEFAULT_THREAD; + if (num_thread <= 1) return 1; + if (num_thread >= MAX_THREAD) return MAX_THREAD; + return num_thread; +} diff --git a/src/sig_stfl/lms/external/hss_thread_single.c b/src/sig_stfl/lms/external/hss_thread_single.c new file mode 100644 index 0000000000..698e2dba6a --- /dev/null +++ b/src/sig_stfl/lms/external/hss_thread_single.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +#include "hss_thread.h" +#include "config.h" + +/* + * This is a trivial implementation of our threading abstraction. + * It's used if we don't have any threading support + */ + +/* + * This requests that an object that tracks the threads be created. We have + * no threads, hence we don't need such an object + */ +struct thread_collection *hss_thread_init(int num_thread) { + LMS_UNUSED(num_thread); + return 0; +} + +/* + * This asks that function be called sometime between now, and when + * hss_thread_done is called. We just go ahead, and do it now + */ +void hss_thread_issue_work(struct thread_collection *collect, + void (*function)(const void *detail, + struct thread_collection *col), + const void *detail, size_t size_detail_structure) { + LMS_UNUSED(size_detail_structure); + /* If we were asked to make sure something is done, just do it */ + function( detail, collect ); +} + +/* + * This asks for all the work requests we've issued to completed, and that + * the collection object be freed. We did all the work when it was + * requested, and we never allocated a collection object in the first place + */ +void hss_thread_done(struct thread_collection *collect) { + LMS_UNUSED(collect); +} + +/* + * A thread calls this when it will write into a common area (so that no + * other thread will access it at the same time). No threads means that + * there is no need to lock + */ +void hss_thread_before_write(struct thread_collection *collect) { + LMS_UNUSED(collect); +} + +/* + * This releases the above lock + */ +void hss_thread_after_write(struct thread_collection *collect) { + LMS_UNUSED(collect); +} + +/* + * This tells the application that we really have only one thread + * (the main one) + */ +unsigned hss_thread_num_tracks(int num_thread) { + LMS_UNUSED(num_thread); + return 1; +} diff --git a/src/sig_stfl/lms/external/hss_verify.c b/src/sig_stfl/lms/external/hss_verify.c new file mode 100644 index 0000000000..1b993aa9b4 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_verify.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the hierarchical part of the LMS hash + * based signatures + */ +#include +#include "common_defs.h" +#include "hss_verify.h" +#include "lm_verify.h" +#include "lm_common.h" +#include "lm_ots_verify.h" +#include "hash.h" +#include "endian.h" +#include "hss_thread.h" +#include "hss_internal.h" +#include "hss.h" + +/* The HSS public key consists of: */ +/* Number of levels (1-8) (4 bytes) */ +/* The top level LM public key */ + +/* The HSS signature consists of: */ +/* A word giving the number of levels - 1 == L-1 */ +/* L-1 iterations of (i = 1..L-1): */ +/* - LMS Signature of public key i (signed by the pub key of level i-1) */ +/* - LMS Public key (of level i) */ +/* - LMS Signature of the message, signed by the bottomost pub key */ + +/* This is the routine that runs on a thread to validate an LMS signature */ +void validate_internal_sig(const void *data, + struct thread_collection *col) { + const struct verify_detail *d = data; + + bool success = lm_validate_signature(d->public_key, + d->message, d->message_len, false, + d->signature, d->signature_len); + + if (!success) { + /* Drat, it failed; call the failure in */ + hss_thread_before_write(col); + *d->got_error = hss_error_bad_signature; + hss_thread_after_write(col); + } +} + +/* + * Validate an HSS signature, using a public key. Parameters: + * public_key - pointer to the public key + * message - the mmessage that was supposedly signed + * message_len - the size of the message + * siganture - the signature we're checking + * signature_len - the length of the signature + * + * This returns true if everything checks out and the signature verifies + * false on error (whether the error is because the signature didn't verify, + * or we hit some sort of error on the way) + */ +bool hss_validate_signature( + const unsigned char *public_key, + const void *message, size_t message_len, + const unsigned char *signature, size_t signature_len, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + unsigned i; + + /* Get the number of levels the signature claims */ + if (signature_len < 4) { + info->error_code = hss_error_bad_signature; + return false; + } + uint_fast32_t levels = (uint_fast32_t)get_bigendian( signature, 4 ) + 1; + /* +1 because what's in the signature is levels-1 */ + signature += 4; signature_len -= 4; + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS || + levels != (uint_fast32_t)get_bigendian( public_key, 4 )) { + info->error_code = hss_error_bad_signature; + return false; + } + + /* Compare that to what the public key says */ + uint_fast32_t pub_levels = (uint_fast32_t)get_bigendian( public_key, 4 ); + if (levels != pub_levels) { + /* Signature and public key don't agree */ + info->error_code = hss_error_bad_signature; + return false; + } + /* We'll use the LMS public key embedded in the HSS public key as the */ + /* key to use to validate the top level signature */ + public_key += 4; + + struct thread_collection *col = hss_thread_init(info->num_threads); + enum hss_error_code got_error = hss_error_none; + struct verify_detail detail; + detail.got_error = &got_error; + + /* Parse through the signature, kicking off the tasks to validate */ + /* individual LMS signatures within it as we go */ + for (i=0; i + * where: + * - Signature A is the LMS signature of Public Key B + * - Public Key B is the message we're verifying (and will be + * interpreted as a public key in the next iteration) + * public_key points to Public Key A, which is the public key that + * we use to verify Signature A + */ + + /* Get the length of Signature A */ + param_set_t lm_type = (param_set_t)get_bigendian( public_key, 4 ); + param_set_t lm_ots_type = (param_set_t)get_bigendian( public_key+4, 4 ); + unsigned l_siglen = (unsigned)lm_get_signature_len(lm_type, lm_ots_type); + if (l_siglen == 0 || l_siglen > signature_len) { + info->error_code = hss_error_bad_signature; + goto failed; + } + + /* Retain a pointer to Signature A, and advance the current */ + /* pointer to Public Key B */ + const unsigned char *l_sig = signature; + signature += l_siglen; signature_len -= l_siglen; + + /* The next thing is the next level public key (Public Key B) */ + /* which we need to validate) */ + if (signature_len < 4) { + info->error_code = hss_error_bad_signature; + goto failed; + } + /* + * Get how long Public Key B would be, assuming it is a valid + * public key. If it's not a valid public key (that is, if + * someone other than the valid signer modified it), then + * Signature A will not validate, and so we'll catch that + */ + lm_type = (param_set_t)get_bigendian( signature, 4 ); + unsigned l_pubkeylen = (unsigned)lm_get_public_key_len(lm_type); + if (l_pubkeylen == 0 || l_pubkeylen > signature_len) { + info->error_code = hss_error_bad_signature; + goto failed; + } + + /* Retain a pointer to Public Key B, and advance the current */ + /* pointer past it (to the data the next iteration cares about) */ + const unsigned char *l_pubkey = signature; + signature += l_pubkeylen; signature_len -= l_pubkeylen; + + /* Now, schedule the validation of Signature A */ + detail.public_key = public_key; /* Public key A */ + detail.message = l_pubkey; /* Public key B, that is, */ + /* the message to validate */ + detail.message_len = l_pubkeylen; + detail.signature = l_sig; /* Signature A */ + detail.signature_len = l_siglen; + hss_thread_issue_work( col, validate_internal_sig, + &detail, sizeof detail ); + + /* We validated this level's public key (or, at least, scheduled */ + /* it, if it turns out not to validate, we'll catch it below) */ + /* Use the current Public Key B as the next level's Public Key A */ + public_key = l_pubkey; + } + + /* + * We're at the bottom level; now, the current position in the signature + * looks like (or, rather, is *supposed to look like*) this: + * + * where: + * - Signature A is the bottom signature, which signs the actual + * message + * public_key points to the bottom level public key, which is used to + * validate the signature + * + * Just go ahead and schedule the validation + */ + detail.public_key = public_key; /* Public key to use */ + detail.message = message; /* The user's message that needs */ + detail.message_len = message_len; /* validation */ + detail.signature = signature; /* Bottom level LMS signature */ + detail.signature_len = signature_len; + hss_thread_issue_work( col, validate_internal_sig, + &detail, sizeof detail ); + + /* Wait for all the threads to complete */ + hss_thread_done(col); + + /* It succeeded if none of the threads reported an error */ + if (got_error == hss_error_none) return true; + info->error_code = got_error; + return false; + +failed: /* If we get an intermediate failure */ + hss_thread_done(col); + return false; +} diff --git a/src/sig_stfl/lms/external/hss_verify.h b/src/sig_stfl/lms/external/hss_verify.h new file mode 100644 index 0000000000..d806900fe4 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_verify.h @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_VERIFY_H_ ) +#define HSS_VERIFY_H_ + +#include +#include "lms_namespace.h" + +struct hss_extra_info; +/* + * This is the function to validate a signature; return true if it validates, + * false if it doesn't + * + * public_key is the pointer to the public key + * + * message, message_len is the message to validate + * + * signature, signature_len is the signature to validate + */ +bool hss_validate_signature( + const unsigned char *public_key, + const void *message, size_t message_len, + const unsigned char *signature, size_t signature_len, + struct hss_extra_info *info); + +#endif /* HSS_VERIFY_H_ */ diff --git a/src/sig_stfl/lms/external/hss_verify_inc.c b/src/sig_stfl/lms/external/hss_verify_inc.c new file mode 100644 index 0000000000..e12cf5c021 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_verify_inc.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the hierarchical part of the LMS hash + * based signatures; in this case, incremental verification + */ +#include +#include "common_defs.h" +#include "hss_verify_inc.h" +#include "lm_verify.h" +#include "lm_common.h" +#include "lm_ots_verify.h" +#include "hash.h" +#include "endian.h" +#include "hss_thread.h" +#include "hss_internal.h" +#include "lm_ots_common.h" +#include "hss.h" + +/* + * Start the process of validating an HSS signature incrementally. Parameters: + * ctx - The state we'll use to track the incremental validation + * public_key - pointer to the public key + * siganture - the signature we're checking + * signature_len - the length of the signature + */ +bool hss_validate_signature_init( + struct hss_validate_inc *ctx, + const unsigned char *public_key, + const unsigned char *signature, size_t signature_len, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + unsigned i; + if (!ctx) { + info->error_code = hss_error_got_null; + return false; + } + ctx->status = hss_error_ctx_uninitialized; /* Until we hear otherwise, */ + /* we got a failure */ + + const unsigned char *orig_signature = signature; +; + /* Get the number of levels the signature claims */ + if (signature_len < 4) { + ctx->status = info->error_code = hss_error_bad_signature; + return false; + } + uint_fast32_t levels = (uint_fast32_t)get_bigendian( signature, 4 ) + 1; + /* +1 because what's in the signature is levels-1 */ + signature += 4; signature_len -= 4; + if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS || + levels != (uint_fast32_t)get_bigendian( public_key, 4 )) { + ctx->status = info->error_code = hss_error_bad_signature; + return false; + } + uint_fast32_t pub_levels = (uint_fast32_t)get_bigendian( public_key, 4 ); + if (levels != pub_levels) { + /* Signature and public key don't agree */ + ctx->status = info->error_code = hss_error_bad_signature; + return false; + } + public_key += 4; + + /* Validate the upper levels of the signature */ + struct thread_collection *col = NULL; + if (levels > 1) { + col = hss_thread_init(info->num_threads); + enum hss_error_code got_error = hss_error_none; + struct verify_detail detail; + detail.got_error = &got_error; + + /* Scan through the signature, kicking off the tasks to validate it */ + /* as we go. Note that we don't validate the bottom level yet */ + for (i=0; i signature_len) goto failed; + const unsigned char *l_sig = signature; + signature += l_siglen; signature_len -= l_siglen; + + /* The next thing is the next level public key (which we need */ + /* to validate) */ + if (signature_len < 4) goto failed; + lm_type = (param_set_t)get_bigendian( signature, 4 ); + unsigned l_pubkeylen = (unsigned)lm_get_public_key_len(lm_type); + if (l_pubkeylen == 0 || l_pubkeylen > signature_len) goto failed; + const unsigned char *l_pubkey = signature; + signature += l_pubkeylen; signature_len -= l_pubkeylen; + + /* Validate the signature of this level's public key */ + detail.public_key = public_key; + detail.message = l_pubkey; + detail.message_len = l_pubkeylen; + detail.signature = l_sig; + detail.signature_len = l_siglen; + hss_thread_issue_work( col, validate_internal_sig, + &detail, sizeof detail ); + + /* We validated this level's public key (or, at least, */ + /* scheduled it, if it turns out not to validate, we'll catch */ + /* it below), use it to validate the next level */ + public_key = l_pubkey; + } + + /* Wait for all the threads to complete */ + hss_thread_done(col); + col = NULL; + + if (got_error != hss_error_none) { + ctx->status = info->error_code = got_error; + return false; + } + } + + ctx->signature_offset = signature - orig_signature; + ctx->signature_len = signature_len; + + /* We have the public key in front of us; stash a copy */ + /* Right now, we have a fixed length public key */ + /* If that changes, we'll need to investigate the parmaeter set */ + memcpy( ctx->final_public_key, public_key, 8 + I_LEN + MAX_HASH ); + + /* Now, initialize the context */ + param_set_t ots_type = (param_set_t)get_bigendian( public_key+4, 4 ); + + unsigned h, n; + if (!lm_ots_look_up_parameter_set(ots_type, &h, &n, NULL, NULL, NULL)) { + /* Because we're checking in parallel, this may be caused by */ + /* a bad signature */ + ctx->status = info->error_code = hss_error_bad_signature; + return false; + } + ctx->h = h; + hss_init_hash_context( h, &ctx->hash_ctx ); + { + unsigned char prefix[ MESG_PREFIX_MAXLEN ]; + memcpy( prefix + MESG_I, ctx->final_public_key+8, I_LEN ); + memcpy( prefix + MESG_Q, signature, 4 ); /* q */ + SET_D( prefix + MESG_D, D_MESG ); + memcpy( prefix + MESG_C, signature+8, n ); /* C */ + hss_update_hash_context(h, &ctx->hash_ctx, prefix, MESG_PREFIX_LEN(n) ); + } + + /* It succeeded so far... */ + ctx->status = hss_error_none; + return true; + +failed: /* If we get an intermediate failure */ + if (col) hss_thread_done(col); + ctx->status = info->error_code = hss_error_bad_signature; + return false; +} + +/* This adds another piece of the message to validate */ +bool hss_validate_signature_update( + struct hss_validate_inc *ctx, + const void *message_segment, + size_t len_message_segment) { + if (!ctx || ctx->status != hss_error_none) return false; + + hss_update_hash_context(ctx->h, &ctx->hash_ctx, + message_segment, len_message_segment ); + + return true; +} + +/* We've added all the pieces of the messages, now do the validation */ +bool hss_validate_signature_finalize( + struct hss_validate_inc *ctx, + const unsigned char *signature, + struct hss_extra_info *info) { + struct hss_extra_info temp_info = { 0 }; + if (!info) info = &temp_info; + + if (!ctx) { + info->error_code = hss_error_got_null; + return false; + } + if (ctx->status != hss_error_none) { + info->error_code = ctx->status; + return false; + } + + /* Success or fail, we can't use the context any more */ + ctx->status = hss_error_ctx_already_used; + + /* Generate the final hash */ + unsigned char hash[ MAX_HASH ]; + unsigned h = ctx->h; + hss_finalize_hash_context( h, &ctx->hash_ctx, hash ); + + /* It passes iff the final signature validates */ + if (lm_validate_signature( + ctx->final_public_key, + hash, sizeof hash, true, + signature + ctx->signature_offset, ctx->signature_len)) { + return true; + } + + info->error_code = hss_error_bad_signature; + return false; +} diff --git a/src/sig_stfl/lms/external/hss_verify_inc.h b/src/sig_stfl/lms/external/hss_verify_inc.h new file mode 100644 index 0000000000..c09d006e4a --- /dev/null +++ b/src/sig_stfl/lms/external/hss_verify_inc.h @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_VERIFY_INC_H_ ) +#define HSS_VERIFY_INC_H_ +#include +#include +#include "hash.h" +#include "common_defs.h" +#include "hss.h" +#include "lms_namespace.h" + +/* + * These are the functions to validate a signature incrementally. + * That is, we assume that we don't have the entire message at + * once, instead, we have it in pieces (for example, the signature + * is of a multigigabyte file) + * + * Usage: + * struct hss_validate_inc ctx; + * bool success = hss_validate_init( &ctx, public_key, signature ); + * hss_validate_update( &ctx, message_part_1, len_1 ); + * hss_validate_update( &ctx, message_part_2, len_2 ); + * hss_validate_update( &ctx, message_part_3, len_3 ); + * success = hss_validate_finalize( &ctx, signature ); + * if (success) printf( "The signature validated\n" ); + * + * This is in its own include file because we need to import some + * 'not-generally-for-general-consumption' include files to make + * it work (as they're in the hss_validate_inc structure) + */ + +/* + * This is the context structure that holds the intermedate results of an + * in-process validation + * It's a application-visible structure for ease of use: the application can + * allocate it as an automatic, and if the application aborts in the middle of + * the validation, it doesn't cause a memory leak + */ +struct hss_validate_inc { + enum hss_error_code status; /* Either hss_error_none if we're in */ + /* process, or the reason why we'd fail */ + size_t signature_offset; /* Offset of the final signature within the */ + /* HSS signature */ + size_t signature_len; /* Length of the final signature */ + + unsigned h; /* Hash function used */ + + /* The final public key. We need this at finalization time, */ + /* however they might not be in the signature (L=1 case) */ + unsigned char final_public_key[8 + I_LEN + MAX_HASH]; + + union hash_context hash_ctx; /* For the running hash we use */ +}; + +struct hss_extra_info; + +/* Starts off the process of incrementally validating a signature */ +/* If it detects a failure, this returns false */ +/* Handing the return code is optional; if this fails, the finalization */ +/* step will fail too */ +bool hss_validate_signature_init( + struct hss_validate_inc *ctx, + const unsigned char *public_key, + const unsigned char *signature, size_t signature_len, + struct hss_extra_info *info); + +/* This adds another piece of the message to validate */ +/* Again, the result code is optional */ +bool hss_validate_signature_update( + struct hss_validate_inc *ctx, + const void *message_segment, + size_t len_message_segment); + +/* This finalizes the signature validation */ +/* This returns true if the signature validates (and we didn't detect any */ +/* intermediate failures) */ +/* We ask the caller to pass in the signature again, because we'd prefer */ +/* not having to place the final LMS signature in the ctx structure; that'd */ +/* make it larger than we'd like */ +bool hss_validate_signature_finalize( + struct hss_validate_inc *ctx, + const unsigned char *signature, + struct hss_extra_info *info); + +#endif /* HSS_VERIFY_INC_H_ */ diff --git a/src/sig_stfl/lms/external/hss_zeroize.c b/src/sig_stfl/lms/external/hss_zeroize.c new file mode 100644 index 0000000000..9c31168069 --- /dev/null +++ b/src/sig_stfl/lms/external/hss_zeroize.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +#include "hss_zeroize.h" +#include + +/* + * This is a function to zeroize a section of memory + * + * We do this because when we release a section of memory (either because it's + * a local variable going out of scope, or we free it), it's possible that + * the memory will retain its contents after another allocation (possibly + * done by someone outside this module). So, to avoid this potential security + * issue, we scrub the memory (at least, the parts that have data that would + * make it possible to forge if it leaked) before releasing it. + * + * Now, there's a bunch of things we don't mind being exposed (e.g. internal + * node values of Merkle trees), so we don't use this everywhere; only where + * it is needed + * + * We use this, rather than having routines simply call memset, to avoid + * potential problems with overenthusiastic optimizers. Generally, we zeroize + * an area immediately before it goes out of scope or we free it, however an + * optimizer might conclude "they're about to release the memory, there's no + * need to write to it first" + * + * For similar reasons, this function is in its own source file (so that a + * compiler optimizer who doesn't examine more than one source at a time can't + * eliminate it). If we are worried about optimizers who can be even more + * enthusiastic, there are other things we can try; however we're not going to + * worry about that right now + */ +void hss_zeroize( void *area, size_t len ) { +#if defined( __STDC_LIB_EXT1__ ) + /* + * C11 defines a version of memset that does precisely what we want, and is + * guaranteed not to be molested by the optimizer + * Note that the first 'len' is supposed to be the length of the buffer + * we're cleaning and the second 'len' is the area to clear. Since we + * expect the caller to ask us to clear the entire area (and hence gives + * us only one length), we use the same for both + */ + memset_s( area, len, 0, len ); +#else + /* + * Fallback code for pre-C11 versions + */ + volatile unsigned char *p = area; + + while (len--) *p++ = 0; +#endif +} diff --git a/src/sig_stfl/lms/external/hss_zeroize.h b/src/sig_stfl/lms/external/hss_zeroize.h new file mode 100644 index 0000000000..6571c4233d --- /dev/null +++ b/src/sig_stfl/lms/external/hss_zeroize.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +#if !defined( HSS_ZEROIZE_H_ ) +#define HSS_ZEROIZE_H_ + +#include +#include "lms_namespace.h" + +/* Zeroize an area, that is, scrub it from holding any potentially secret */ +/* information */ +void hss_zeroize( void *area, size_t len ); + +#endif /* HSS_ZEROIZE_H_ */ diff --git a/src/sig_stfl/lms/external/license.txt b/src/sig_stfl/lms/external/license.txt new file mode 100644 index 0000000000..4e5a9b9b1e --- /dev/null +++ b/src/sig_stfl/lms/external/license.txt @@ -0,0 +1,29 @@ +****************************************************************************** +Copyright (c) 2017 Cisco Systems, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +Neither the name of the Cisco Systems, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. +****************************************************************************** diff --git a/src/sig_stfl/lms/external/lm_common.c b/src/sig_stfl/lms/external/lm_common.c new file mode 100644 index 0000000000..6f37af627e --- /dev/null +++ b/src/sig_stfl/lms/external/lm_common.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the tree part of the LMS hash + * based signatures + */ +#include +#include "lm_common.h" +#include "hash.h" +#include "common_defs.h" +#include "lm_ots_common.h" + +/* + * Internal utility to convert encoded parameter sets into what they represent + */ +bool lm_look_up_parameter_set(param_set_t parameter_set, + unsigned *h, unsigned *n, unsigned *height) { + unsigned v_h, v_n, v_height; + switch (parameter_set) { + case LMS_SHA256_N32_H5: + v_h = HASH_SHA256; v_n = 32; v_height = 5; break; + case LMS_SHA256_N32_H10: + v_h = HASH_SHA256; v_n = 32; v_height = 10; break; + case LMS_SHA256_N32_H15: + v_h = HASH_SHA256; v_n = 32; v_height = 15; break; + case LMS_SHA256_N32_H20: + v_h = HASH_SHA256; v_n = 32; v_height = 20; break; + case LMS_SHA256_N32_H25: + v_h = HASH_SHA256; v_n = 32; v_height = 25; break; + default: return false; + } + + if (h) *h = v_h; + if (n) *n = v_n; + if (height) *height = v_height; + + return true; +} + +/* The LM public key consists of: */ +#define LM_PUB_PARM_SET 0 /* The parameter set (4 bytes) */ +#define LM_PUB_OTS_PARM_SET 4 /* The OTS parameter set (4 bytes) */ +#define LM_PUB_I 8 /* Our nonce (I) value (16 bytes) */ +/* The root value comes here */ + +/* + * XDR requires us to pad the I value out to a multiple of 4 + * This computes how long the field will be after padding + * That is, it rounds len_I up to the next multiple of 4 + */ +#define padded_length(len_I) (((len_I) + 3) & ~3) + +/* The public key just consists of the parameter sets, plus I, plus root hash */ +size_t lm_get_public_key_len(param_set_t lm_type) { + unsigned n; + if (!lm_look_up_parameter_set( lm_type, 0, &n, 0)) + return 0; + + return LM_PUB_I + padded_length(I_LEN) + n; +} + +/* + * The amount of space we use for signature + */ +size_t lm_get_signature_len(param_set_t lm_type, + param_set_t lm_ots_type) { + unsigned n, height; + if (!lm_look_up_parameter_set( lm_type, 0, &n, &height )) + return 0; + + int ots_sig_len = (int)lm_ots_get_signature_len(lm_ots_type); + if (ots_sig_len == 0) + return 0; + + /* + * The LM signature consists of the type code, the diversification factor, + * the LM-OTS signature (which includes the OTS type code), and the + * authentication path (which is an array of height hashes) + */ + return 4 + 4 + ots_sig_len + n*height; +} diff --git a/src/sig_stfl/lms/external/lm_common.h b/src/sig_stfl/lms/external/lm_common.h new file mode 100644 index 0000000000..c7197fd5a0 --- /dev/null +++ b/src/sig_stfl/lms/external/lm_common.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +#if !defined(LM_COMMON_H_) +#define LM_COMMON_H_ + +#include +#include "common_defs.h" +#include "lms_namespace.h" + +size_t lm_get_public_key_len(param_set_t lm_type); +size_t lm_get_signature_len(param_set_t lm_type, + param_set_t lm_ots_type); + +bool lm_look_up_parameter_set(param_set_t parameter_set, + unsigned *h, unsigned *n, unsigned *height); + +/* The format of an LM public key; it consists of: */ +#define LM_PUB_PARM_SET 0 /* The parameter set (4 bytes) */ +#define LM_PUB_OTS_PARM_SET 4 /* The OTS parameter set (4 bytes) */ +#define LM_PUB_I 8 /* Our nonce (I) value (32 or 64 bytes) */ +/* The root value comes here */ + +#endif /* LM_COMMON_H_ */ diff --git a/src/sig_stfl/lms/external/lm_ots.h b/src/sig_stfl/lms/external/lm_ots.h new file mode 100644 index 0000000000..f0cc42d11f --- /dev/null +++ b/src/sig_stfl/lms/external/lm_ots.h @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +#if !defined( LM_OTS_H_ ) +#define LM_OTS_H_ + +#include "common_defs.h" +#include +#include "lms_namespace.h" + +/* + * These are routines that implement the OTS signature scheme. These routines + * never actually form a "private key"; instead, the signer passes the 'seed' + * (and public data) to form the public key and to do the actual signature. + * We do this because the LM routines are actually better suited for doing + * seed management. + */ +struct seed_derive; + +/* + * Compute the public key. Note that it doesn't compute a 'private key'; + * the signature algorithm gets that data when we pass the parameters again + * Parameters: + * lm_ots_type - The parameter set + * I - The I public identifier to use + * q - The diversification string, passed as a 4 byte integer + * seed - The structure used to generate seeds + * public_key - Where to place the public key + * public_key_len - The length of the above buffer + * This returns true on success + */ +bool lm_ots_generate_public_key( + param_set_t lm_ots_type, + const unsigned char *I, /* Public key identifier */ + merkle_index_t q, /* Diversification string, 4 bytes value */ + struct seed_derive *seed, + unsigned char *public_key, size_t public_key_len); + +/* + * Sign a message. Warning: the caller is expected to make sure that it signs + * only one message with a given seed/I/q set + * Parameters: + * lm_ots_type - The parameter set + * I - The I public identifier to use + * q - The diversification string, passed as a 4 byte integer + * seed - The structure used to generate seeds + * message - Message to sign + * message_len - Length of the message + * prehashed - Set if the message hashing has already taken place + * signature - Where to place the signature + * signature_len - The length of the above buffer + * This returns true on success + */ +bool lm_ots_generate_signature( + param_set_t lm_ots_type, + const unsigned char *I, + merkle_index_t q, + struct seed_derive *seed, + const void *message, size_t message_len, bool prehashed, + unsigned char *signature, size_t signature_len); + +/* The include file for the verification routine */ +#include "lm_ots_verify.h" + +/* The include file for the common access routines */ +#include "lm_ots_common.h" + +#endif /* LM_OTS_H_ */ diff --git a/src/sig_stfl/lms/external/lm_ots_common.c b/src/sig_stfl/lms/external/lm_ots_common.c new file mode 100644 index 0000000000..100eff606a --- /dev/null +++ b/src/sig_stfl/lms/external/lm_ots_common.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the one-time-signature part of the LMS hash + * based signatures + */ +#include "lm_ots_common.h" +#include "common_defs.h" +#include "hash.h" + +/* + * Convert the external name of a parameter set into the set of values we care + * about + */ +bool lm_ots_look_up_parameter_set(param_set_t parameter_set, + unsigned *h, unsigned *n, unsigned *w, unsigned *p, unsigned *ls) { + unsigned v_h, v_n, v_w, v_p, v_ls; + switch (parameter_set) { + case LMOTS_SHA256_N32_W1: + v_h = HASH_SHA256; v_n = 32; v_w = 1; v_p = 265; v_ls = 7; break; + case LMOTS_SHA256_N32_W2: + v_h = HASH_SHA256; v_n = 32; v_w = 2; v_p = 133; v_ls = 6; break; + case LMOTS_SHA256_N32_W4: + v_h = HASH_SHA256; v_n = 32; v_w = 4; v_p = 67; v_ls = 4; break; + case LMOTS_SHA256_N32_W8: + v_h = HASH_SHA256; v_n = 32; v_w = 8; v_p = 34; v_ls = 0; break; + default: return false; + } + + if (h) *h = v_h; + if (n) *n = v_n; + if (w) *w = v_w; + if (p) *p = v_p; + if (ls) *ls = v_ls; + + return true; +} + +/* The public key just consists of the bare hash */ +size_t lm_ots_get_public_key_len(param_set_t lm_ots_type) { + unsigned n; + if (!lm_ots_look_up_parameter_set( lm_ots_type, 0, &n, 0, 0, 0 )) + return 0; + + return n; +} + +/* Return the length of a signature */ +size_t lm_ots_get_signature_len(param_set_t lm_ots_type) { + unsigned n, p; + + if (!lm_ots_look_up_parameter_set( lm_ots_type, 0, &n, 0, &p, 0 )) + return 0; + + return 4 + n + p*n; +} + +/* Return the number of hashes we need to compute to generate a public key */ +unsigned lm_ots_hashes_per_public_key(param_set_t lm_ots_type) { + unsigned wint, num_dig; + if (!lm_ots_look_up_parameter_set(lm_ots_type, + NULL, NULL, &wint, &num_dig, NULL)) { + return 0; + } + + /* Total number of hash invocations: + * For each digit, we expand the seed (1), and then perform (2**wint-1) + * haashes to obtain the end of the chain + * Then, we hash all the ends of the chains together + * If we were to return the number of hash compression operations, + * the final 1 would be a bit larger + */ + return num_dig * (1 << wint) + 1; +} + +/* Todo: some of these values depend only on w; why do we need to recompute */ +/* them each time??? */ +unsigned lm_ots_coef(const unsigned char *Q, unsigned i, unsigned w) { + unsigned index = (i * w) / 8; /* Which byte holds the coefficient */ + /* we want */ + unsigned digits_per_byte = 8/w; + unsigned shift = w * (~i & (digits_per_byte-1)); /* Where in the byte */ + /* the coefficient is */ + unsigned mask = (1<> shift) & mask; +} + +/* This returns the Winternitz checksum to append to the hash */ +unsigned lm_ots_compute_checksum(const unsigned char *Q, unsigned Q_len, + unsigned w, unsigned ls) { + unsigned sum = 0; + unsigned i; + unsigned u = 8 * Q_len / w; + unsigned max_digit = (1< +#include "common_defs.h" +#include "lms_namespace.h" + +bool lm_ots_look_up_parameter_set(param_set_t parameter_set, + unsigned *h, unsigned *n, unsigned *w, unsigned *p, unsigned *ls); +size_t lm_ots_get_public_key_len(param_set_t lm_ots_type); +size_t lm_ots_get_signature_len(param_set_t lm_ots_type); +unsigned lm_ots_hashes_per_public_key(param_set_t lm_ots_type); +unsigned lm_ots_compute_checksum(const unsigned char *Q, unsigned Q_len, + unsigned w, unsigned ls); +unsigned lm_ots_coef(const unsigned char *Q, unsigned i, unsigned w); + +#endif /* LM_OTS_COMMON_H_ */ diff --git a/src/sig_stfl/lms/external/lm_ots_sign.c b/src/sig_stfl/lms/external/lm_ots_sign.c new file mode 100644 index 0000000000..7e0950c564 --- /dev/null +++ b/src/sig_stfl/lms/external/lm_ots_sign.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the one-time-signature part of the LMS hash + * based signatures + */ +#include +#include "common_defs.h" +#include "lm_ots.h" +#include "lm_ots_common.h" +#include "hash.h" +#include "endian.h" +#include "hss_zeroize.h" +#include "hss_derive.h" +#include "hss_internal.h" + +bool lm_ots_generate_public_key( + param_set_t lm_ots_type, + const unsigned char *I, /* Public key identifier */ + merkle_index_t q, /* Diversification string, 4 bytes value */ + struct seed_derive *seed, + unsigned char *public_key, size_t public_key_len) { + + /* Look up the parameter set */ + unsigned h, n, w, p, ls; + LMS_UNUSED(public_key_len); + if (!lm_ots_look_up_parameter_set( lm_ots_type, &h, &n, &w, &p, &ls )) + return false; + + /* Start the hash that computes the final value */ + union hash_context public_ctx; + hss_init_hash_context(h, &public_ctx); + { + unsigned char prehash_prefix[ PBLC_PREFIX_LEN ]; + memcpy( prehash_prefix + PBLC_I, I, I_LEN ); + put_bigendian( prehash_prefix + PBLC_Q, q, 4 ); + SET_D( prehash_prefix + PBLC_D, D_PBLC ); + hss_update_hash_context(h, &public_ctx, prehash_prefix, + PBLC_PREFIX_LEN ); + } + + /* Now generate the public key */ + /* This is where we spend the majority of the time during key gen and */ + /* signing operations; it would make sense to attempt to try to take */ + /* advantage of parallel (SIMD) hardware; even if we use it nowhere */ + /* else, we'd get a significant speed up */ + unsigned i, j; + + unsigned char buf[ ITER_MAX_LEN ]; + memcpy( buf + ITER_I, I, I_LEN ); + put_bigendian( buf + ITER_Q, q, 4 ); + union hash_context ctx; + + hss_seed_derive_set_j( seed, 0 ); + + for (i=0; i +#include "lm_ots_verify.h" +#include "lm_ots_common.h" +#include "hash.h" +#include "endian.h" +#include "common_defs.h" + +/* + * This validate a OTS signature for a message. It doesn't actually use the + * public key explicitly; instead, it just produces the root key, based on the + * message; the caller is assumed to compare it to the expected value + * Parameters: + * - computed_public_key - where to place the reconstructed root. It is + * assumed that the caller has allocated enough space + * - I: the nonce value ("I") to use + * - q: diversification string + * - message - the message to verify + * - message_len - the length of the message + * - message_prehashed - true if the message has already undergone the initial + * (D_MESG) hash + * - signature - the signature + * - signature_len - the length of the signature + * - parameter_set - what we expect the parameter set to be + * + * This returns true on successfully recomputing a root value; whether it is + * the right one is something the caller would need to verify + */ +bool lm_ots_validate_signature_compute( + unsigned char *computed_public_key, + const unsigned char *I, merkle_index_t q, + const void *message, size_t message_len, bool message_prehashed, + const unsigned char *signature, size_t signature_len, + param_set_t expected_parameter_set) { + if (signature_len < 4) return false; /* Ha, ha, very funny... */ + + /* We don't trust the parameter set that's in the signature; verify it */ + param_set_t parameter_set = (param_set_t)get_bigendian( signature, 4 ); + if (parameter_set != expected_parameter_set) { + return false; + } + + unsigned h, n, w, p, ls; + if (!lm_ots_look_up_parameter_set( parameter_set, &h, &n, &w, &p, &ls )) + return false; + + if (signature_len != 4 + n * (p+1)) return false; + + const unsigned char *C = signature + 4; + const unsigned char *y = C + n; + + unsigned char Q[MAX_HASH + 2]; + if (message_prehashed) { + memcpy( Q, message, n ); + } else { + union hash_context ctx; + /* Compute the initial hash */ + hss_init_hash_context(h, &ctx); + /* Hash the message prefix */ + { + unsigned char prefix[ MESG_PREFIX_MAXLEN ]; + memcpy( prefix + MESG_I, I, I_LEN ); + put_bigendian( prefix + MESG_Q, q, 4 ); + SET_D( prefix + MESG_D, D_MESG ); + memcpy( prefix + MESG_C, C, n ); + hss_update_hash_context(h, &ctx, prefix, MESG_PREFIX_LEN(n) ); + } + /* Then, the message */ + hss_update_hash_context(h, &ctx, message, message_len ); + + hss_finalize_hash_context( h, &ctx, Q ); + } + + /* Append the checksum to the randomized hash */ + put_bigendian( &Q[n], lm_ots_compute_checksum(Q, n, w, ls), 2 ); + + /* And, start building the parts for the final hash */ + union hash_context final_ctx; + hss_init_hash_context(h, &final_ctx); + { + unsigned char prehash_prefix[ PBLC_PREFIX_LEN ]; + memcpy( prehash_prefix + PBLC_I, I, I_LEN ); + put_bigendian( prehash_prefix + PBLC_Q, q, 4 ); + SET_D( prehash_prefix + PBLC_D, D_PBLC ); + hss_update_hash_context(h, &final_ctx, prehash_prefix, + PBLC_PREFIX_LEN ); + } + + unsigned i; + unsigned char tmp[ITER_MAX_LEN]; + + /* Preset the parts of tmp that don't change */ + memcpy( tmp + ITER_I, I, I_LEN ); + put_bigendian( tmp + ITER_Q, q, 4 ); + + unsigned max_digit = (1< +#include "common_defs.h" +#include "lms_namespace.h" + +/* + * This validates an OTS signature, but instead of producing a SUCCESS/FAILURE + * return, it generates the root value (which the caller is expected to check). + * It can return false (failure), for things such as unrecognized parameter + * set It also makes sure that the parameter set of the signature is that + * value (as we need to make sure that the attacker didn't substitute a + * weaker one) + */ +bool lm_ots_validate_signature_compute( + unsigned char *computed_public_key, + const unsigned char *I, + merkle_index_t q, /* Diversification string, 4 bytes value */ + const void *message, size_t message_len, bool prehashed, + const unsigned char *signature, size_t signature_len, + param_set_t expected_parameter_set); + +#endif /* LM_OTS_VERIFY_H_ */ diff --git a/src/sig_stfl/lms/external/lm_verify.c b/src/sig_stfl/lms/external/lm_verify.c new file mode 100644 index 0000000000..50fa54f475 --- /dev/null +++ b/src/sig_stfl/lms/external/lm_verify.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +/* + * This is the code that implements the tree part of the LMS hash + * based signatures + */ +#include +#include "lm_verify.h" +#include "lm_common.h" +#include "lm_ots_common.h" +#include "lm_ots_verify.h" +#include "hash.h" +#include "endian.h" +#include "common_defs.h" + +/* + * XDR requires us to pad the I value out to a multiple of 4 + * This computes how long the field will be after padding + * That is, it rounds len_I up to the next multiple of 4 + */ +#define padded_length(len_I) (((len_I) + 3) & ~3) + +/* + * This validate an LM signature for a message. It does take an XDR-encoded + * signature, and verify against it. + * Parameters: + * - public_key - the XDR-encoded public ley + * - message - the message to verify + * - message_len - the length of the message + * - signature - the signature + * - signature_len - the length of the signature + * + * This returns true if the signature verifies + */ +bool lm_validate_signature( + const unsigned char *public_key, + const void *message, size_t message_len, bool prehashed, + const unsigned char *signature, size_t signature_len) { + union hash_context ctx; + + param_set_t lm_type = (param_set_t)get_bigendian( public_key + LM_PUB_PARM_SET, 4 ); + param_set_t ots_type = (param_set_t)get_bigendian( public_key + LM_PUB_OTS_PARM_SET, 4 ); + + unsigned h, n, height; + if (!lm_look_up_parameter_set(lm_type, &h, &n, &height)) return false; + + unsigned char computed_public_key[MAX_HASH]; + + const unsigned char *I = public_key + LM_PUB_I; + + if (signature_len < 8) return false; + merkle_index_t count = (param_set_t)get_bigendian( signature, 4 ); + signature += 4; signature_len -= 4; /* 4 bytes, rather then 8 */ + /* the OTS type is expected to be a part of the OTS signature, */ + /* which lm_ots_validate_signature_compute will expect */ + + /* Compute the OTS root */ + size_t ots_publen = lm_ots_get_public_key_len(ots_type); + size_t ots_siglen = lm_ots_get_signature_len(ots_type); + if (ots_publen == 0 || ots_siglen == 0) return false; + if (signature_len < ots_siglen) return false; + + unsigned char ots_sig[LEAF_MAX_LEN]; + if (!lm_ots_validate_signature_compute(ots_sig + LEAF_PK, I, count, + message, message_len, prehashed, + signature, ots_siglen, ots_type)) return false; + signature += ots_siglen; signature_len -= ots_siglen; + + /* Get the parameter set declared in the sigature; make sure it matches */ + /* what we expect */ + if (signature_len < 4) return false; + param_set_t parameter_set = (param_set_t)get_bigendian( signature, 4 ); + if (parameter_set != lm_type) return false; + signature += 4; signature_len -= 4; + + merkle_index_t count_nodes = (merkle_index_t)1 << height; + + if (signature_len != n * height) return false; /* We expect the auth */ + /* path to be there as the last element */ + if (count >= count_nodes) return false; /* Index out of range */ + merkle_index_t node_num = count + count_nodes; + + memcpy( ots_sig + LEAF_I, I, I_LEN ); + put_bigendian( ots_sig + LEAF_R, node_num, 4 ); + SET_D( ots_sig + LEAF_D, D_LEAF ); + hss_hash_ctx( computed_public_key, h, &ctx, ots_sig, LEAF_LEN(n) ); + + unsigned char prehash[ INTR_MAX_LEN ]; + memcpy( prehash + INTR_I, I, I_LEN ); + SET_D( prehash + INTR_D, D_INTR ); + while (node_num > 1) { + if (node_num % 2) { + memcpy( prehash + INTR_PK + 0, signature, n ); + memcpy( prehash + INTR_PK + n, computed_public_key, n ); + } else { + memcpy( prehash + INTR_PK + 0, computed_public_key, n ); + memcpy( prehash + INTR_PK + n, signature, n ); + } + signature += n; + node_num /= 2; + put_bigendian( prehash + INTR_R, node_num, 4 ); + hss_hash_ctx( computed_public_key, h, &ctx, prehash, INTR_LEN(n) ); + } + + /* Now, check to see if the root we computed matches the root we should have */ + unsigned offset = LM_PUB_I + padded_length(I_LEN); + + return 0 == memcmp( computed_public_key, public_key + offset, n ); +} diff --git a/src/sig_stfl/lms/external/lm_verify.h b/src/sig_stfl/lms/external/lm_verify.h new file mode 100644 index 0000000000..ff67f51ac8 --- /dev/null +++ b/src/sig_stfl/lms/external/lm_verify.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +#if !defined(LM_VERIFY_H_) +#define LM_VERIFY_H_ + +#include +#include +#include "lms_namespace.h" + +bool lm_validate_signature( + const unsigned char *public_key, + const void *message, size_t message_len, bool prehashed, + const unsigned char *signature, size_t signature_len); + +#endif /* LM_VERIFY_H_ */ diff --git a/src/sig_stfl/lms/external/lms_namespace.h b/src/sig_stfl/lms/external/lms_namespace.h new file mode 100644 index 0000000000..099a37c19b --- /dev/null +++ b/src/sig_stfl/lms/external/lms_namespace.h @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +#ifndef _LMS_NAMESPACE_H +#define _LMS_NAMESPACE_H + +#define LMS_NAMESPACE(s) OQS_LMS_NAMESPACE_##s + +#define get_bigendian LMS_NAMESPACE(get_bigendian) +#define put_bigendian LMS_NAMESPACE(put_bigendian) +#define hss_finalize_hash_context LMS_NAMESPACE(hss_finalize_hash_context) +#define hss_hash LMS_NAMESPACE(hss_hash) +#define hss_hash_blocksize LMS_NAMESPACE(hss_hash_blocksize) +#define hss_hash_ctx LMS_NAMESPACE(hss_hash_ctx) +#define hss_hash_length LMS_NAMESPACE(hss_hash_length) +#define hss_init_hash_context LMS_NAMESPACE(hss_init_hash_context) +#define hss_update_hash_context LMS_NAMESPACE(hss_update_hash_context) +#define hss_extra_info_set_threads LMS_NAMESPACE(hss_extra_info_set_threads) +#define hss_extra_info_test_error_code LMS_NAMESPACE(hss_extra_info_test_error_code) +#define hss_extra_info_test_last_signature LMS_NAMESPACE(hss_extra_info_test_last_signature) +#define hss_generate_child_seed_I_value LMS_NAMESPACE(hss_generate_child_seed_I_value) +#define hss_generate_root_seed_I_value LMS_NAMESPACE(hss_generate_root_seed_I_value) +#define hss_init_extra_info LMS_NAMESPACE(hss_init_extra_info) +#define hss_load_private_key LMS_NAMESPACE(hss_load_private_key) + +#define allocate_working_key LMS_NAMESPACE(allocate_working_key) + +#define hss_free_working_key LMS_NAMESPACE(hss_free_working_key) +#define hss_smallest_subtree_size LMS_NAMESPACE(hss_smallest_subtree_size) +#define hss_expand_aux_data LMS_NAMESPACE(hss_expand_aux_data) +#define hss_extract_aux_data LMS_NAMESPACE(hss_extract_aux_data) +#define hss_finalize_aux_data LMS_NAMESPACE(hss_finalize_aux_data) +#define hss_get_aux_data_len LMS_NAMESPACE(hss_get_aux_data_len) +#define hss_optimal_aux_level LMS_NAMESPACE(hss_optimal_aux_level) +#define hss_save_aux_data LMS_NAMESPACE(hss_save_aux_data) +#define hss_store_aux_marker LMS_NAMESPACE(hss_store_aux_marker) + +#define hss_get_public_key_len LMS_NAMESPACE(hss_get_public_key_len) +#define hss_get_signature_len LMS_NAMESPACE(hss_get_signature_len) +#define hss_combine_internal_nodes LMS_NAMESPACE(hss_combine_internal_nodes) +#define hss_gen_intermediate_tree LMS_NAMESPACE(hss_gen_intermediate_tree) +#define hss_seed_derive LMS_NAMESPACE(hss_seed_derive) +#define hss_seed_derive_done LMS_NAMESPACE(hss_seed_derive_done) +#define hss_seed_derive_init LMS_NAMESPACE(hss_seed_derive_init) +#define hss_seed_derive_set_j LMS_NAMESPACE(hss_seed_derive_set_j) +#define hss_seed_derive_set_q LMS_NAMESPACE(hss_seed_derive_set_q) +#define hss_generate_working_key LMS_NAMESPACE(hss_generate_working_key) + +#define hss_generate_private_key LMS_NAMESPACE(hss_generate_private_key) +#define hss_get_private_key_len LMS_NAMESPACE(hss_get_private_key_len) +#define hss_compress_param_set LMS_NAMESPACE(hss_compress_param_set) +#define hss_get_parameter_set LMS_NAMESPACE(hss_get_parameter_set) +#define hss_advance_count LMS_NAMESPACE(hss_advance_count) +#define hss_reserve_signature LMS_NAMESPACE(hss_reserve_signature) +#define hss_set_autoreserve LMS_NAMESPACE(hss_set_autoreserve) +#define hss_set_reserve_count LMS_NAMESPACE(hss_set_reserve_count) +#define hss_create_signed_public_key LMS_NAMESPACE(hss_create_signed_public_key) +#define hss_generate_signature LMS_NAMESPACE(hss_generate_signature) +#define hss_get_signature_len_from_working_key LMS_NAMESPACE(hss_get_signature_len_from_working_key) +#define hss_sign_finalize LMS_NAMESPACE(hss_sign_finalize) +#define hss_sign_init LMS_NAMESPACE(hss_sign_init) +#define hss_sign_update LMS_NAMESPACE(hss_sign_update) +#define hss_thread_after_write LMS_NAMESPACE(hss_thread_after_write) +#define hss_thread_before_write LMS_NAMESPACE(hss_thread_before_write) +#define hss_thread_done LMS_NAMESPACE(hss_thread_done) +#define hss_thread_init LMS_NAMESPACE(hss_thread_init) +#define hss_thread_issue_work LMS_NAMESPACE(hss_thread_issue_work) +#define hss_thread_num_tracks LMS_NAMESPACE(hss_thread_num_tracks) +#define hss_validate_signature LMS_NAMESPACE(hss_validate_signature) + +#define validate_internal_sig LMS_NAMESPACE(validate_internal_sig) + +#define hss_validate_signature_finalize LMS_NAMESPACE(hss_validate_signature_finalize) +#define hss_validate_signature_init LMS_NAMESPACE(hss_validate_signature_init) +#define hss_validate_signature_update LMS_NAMESPACE(hss_validate_signature_update) +#define hss_zeroize LMS_NAMESPACE(hss_zeroize) + +#define lm_get_public_key_len LMS_NAMESPACE(lm_get_public_key_len) +#define lm_get_signature_len LMS_NAMESPACE(lm_get_signature_len) +#define lm_look_up_parameter_set LMS_NAMESPACE(lm_look_up_parameter_set) + +#define lm_ots_coef LMS_NAMESPACE(lm_ots_coef) +#define lm_ots_compute_checksum LMS_NAMESPACE(lm_ots_compute_checksum) +#define lm_ots_get_public_key_len LMS_NAMESPACE(lm_ots_get_public_key_len) +#define lm_ots_get_signature_len LMS_NAMESPACE(lm_ots_get_signature_len) +#define lm_ots_hashes_per_public_key LMS_NAMESPACE(lm_ots_hashes_per_public_key) +#define lm_ots_look_up_parameter_set LMS_NAMESPACE(lm_ots_look_up_parameter_set) +#define lm_ots_generate_public_key LMS_NAMESPACE(lm_ots_generate_public_key) +#define lm_ots_generate_randomizer LMS_NAMESPACE(lm_ots_generate_randomizer) +#define lm_ots_generate_signature LMS_NAMESPACE(lm_ots_generate_signature) +#define lm_ots_validate_signature_compute LMS_NAMESPACE(lm_ots_validate_signature_compute) +#define lm_validate_signature LMS_NAMESPACE(lm_validate_signature) + +#define SHA256_Final LMS_NAMESPACE(SHA256_Final) +#define LMS_randombytes LMS_NAMESPACE(LMS_randombytes) + +#endif //_LMS_NAMESPACE_H diff --git a/src/sig_stfl/lms/sig_stfl_lms.c b/src/sig_stfl/lms/sig_stfl_lms.c new file mode 100644 index 0000000000..acc218a6ba --- /dev/null +++ b/src/sig_stfl/lms/sig_stfl_lms.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: MIT + +#include +#include +#include +#include "./external/config.h" +#include "sig_stfl_lms_wrap.h" +#include "sig_stfl_lms.h" + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h25_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h25_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h25_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h25_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w1_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_STATUS OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +/* Convert LMS secret key object to byte string */ +static OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk); + +/* Insert lms byte string in an LMS secret key object */ +static OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, void *context); + +static void OQS_SECRET_KEY_LMS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context); + +// ======================== LMS Maccros ======================== // +// macro to en/disable OQS_SIG_STFL-only structs used only in sig&gen case: +#ifdef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +#define LMS_SIGGEN(lms_variant, LMS_VARIANT) \ + sig->oid = OQS_LMS_ID_##lms_variant; \ + sig->sigs_remaining = OQS_SIG_STFL_lms_sigs_left; \ + sig->sigs_total = OQS_SIG_STFL_lms_sigs_total; \ + sig->keypair = OQS_SIG_STFL_alg_lms_##lms_variant##_keypair; \ + sig->sign = OQS_SIG_STFL_alg_lms_sign; +#else +#define LMS_SIGGEN(lms_variant, LMS_VARIANT) +#endif +// generator for all alg-specific functions: +#define LMS_ALG(lms_variant, LMS_VARIANT) \ +OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_##lms_variant##_new(void) { \ +\ + OQS_SIG_STFL *sig = (OQS_SIG_STFL *)malloc(sizeof(OQS_SIG_STFL)); \ + if (sig == NULL) { \ + return NULL; \ + } \ + memset(sig, 0, sizeof(OQS_SIG_STFL)); \ +\ + LMS_SIGGEN(lms_variant, ) \ + sig->method_name = OQS_SIG_STFL_alg_lms_##lms_variant; \ + sig->alg_version = "https://datatracker.ietf.org/doc/html/rfc8554"; \ + sig->euf_cma = true; \ +\ + sig->length_public_key = OQS_SIG_STFL_alg_lms_length_public_key; \ + sig->length_secret_key = OQS_SIG_STFL_alg_lms_length_private_key; \ + sig->length_signature = OQS_SIG_STFL_alg_lms_##lms_variant##_length_signature; \ +\ + sig->verify = OQS_SIG_STFL_alg_lms_verify; \ +\ + return sig;\ +} \ +\ +OQS_STATUS OQS_SIG_STFL_alg_lms_##lms_variant##_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key) {\ + if (secret_key == NULL || public_key == NULL) {\ + return OQS_ERROR;\ + }\ +\ + if (oqs_sig_stfl_lms_keypair(public_key, secret_key, (const uint32_t)OQS_LMS_ID_##lms_variant) != 0) {\ + return OQS_ERROR;\ + }\ + return OQS_SUCCESS;\ +}\ +\ +OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_##LMS_VARIANT##_new(void) {\ +\ + OQS_SIG_STFL_SECRET_KEY *sk = malloc(sizeof(OQS_SIG_STFL_SECRET_KEY));\ + if (sk == NULL) {\ + return NULL;\ + }\ + memset(sk, 0, sizeof(OQS_SIG_STFL_SECRET_KEY));\ +\ + sk->length_secret_key = OQS_SIG_STFL_alg_lms_length_private_key;\ +\ + sk->serialize_key = OQS_SECRET_KEY_LMS_serialize_key;\ +\ + sk->deserialize_key = OQS_SECRET_KEY_LMS_deserialize_key;\ +\ + sk->lock_key = NULL;\ +\ + sk->unlock_key = NULL;\ +\ + sk->secure_store_scrt_key = NULL;\ +\ + sk->free_key = OQS_SECRET_KEY_LMS_free;\ +\ + sk->set_scrt_key_store_cb = OQS_SECRET_KEY_LMS_set_store_cb;\ +\ + return sk;\ +} + +// ======================== LMS-SHA256 H5/W1 ======================== // +LMS_ALG(sha256_h5_w1, SHA256_H5_W1) + +// ======================== LMS-SHA256 H5/W2 ======================== // + +LMS_ALG(sha256_h5_w2, SHA256_H5_W2) + +// ======================== LMS-SHA256 H5/W4 ======================== // + +LMS_ALG(sha256_h5_w4, SHA256_H5_W4) + +// ======================== LMS-SHA256 H5/W8 ======================== // + +LMS_ALG(sha256_h5_w8, SHA256_H5_W8) + +// ======================== LMS-SHA256 H10/W1 ======================== // + +LMS_ALG(sha256_h10_w1, SHA256_H10_W1) + +// ======================== LMS-SHA256 H10/W2 ======================== // + +LMS_ALG(sha256_h10_w2, SHA256_H10_W2) + +// ======================== LMS-SHA256 H10/W4 ======================== // + +LMS_ALG(sha256_h10_w4, SHA256_H10_W4) + +// ======================== LMS-SHA256 H10/W8 ======================== // + +LMS_ALG(sha256_h10_w8, SHA256_H10_W8) + +// ======================== LMS-SHA256 H15/W1 ======================== // + +LMS_ALG(sha256_h15_w1, SHA256_H15_W1) + +// ======================== LMS-SHA256 H15/W2 ======================== // + +LMS_ALG(sha256_h15_w2, SHA256_H15_W2) + +// ======================== LMS-SHA256 H15/W4 ======================== // + +LMS_ALG(sha256_h15_w4, SHA256_H15_W4) + +// ======================== LMS-SHA256 H15/W8 ======================== // + +LMS_ALG(sha256_h15_w8, SHA256_H15_W8) + +// ======================== LMS-SHA256 H20/W1 ======================== // + +LMS_ALG(sha256_h20_w1, SHA256_H20_W1) + +// // ======================== LMS-SHA256 H20/W2 ======================== // + +LMS_ALG(sha256_h20_w2, SHA256_H20_W2) + +// ======================== LMS-SHA256 H20/W4 ======================== // + +LMS_ALG(sha256_h20_w4, SHA256_H20_W4) + +// ======================== LMS-SHA256 H20/W8 ======================== // + +LMS_ALG(sha256_h20_w8, SHA256_H20_W8) + +// ======================== LMS-SHA256 H25/W1 ======================== // + +LMS_ALG(sha256_h25_w1, SHA256_H25_W1) + +// ======================== LMS-SHA256 H25/W2 ======================== // + +LMS_ALG(sha256_h25_w2, SHA256_H25_W2) + +// ======================== LMS-SHA256 H25/W4 ======================== // + +LMS_ALG(sha256_h25_w4, SHA256_H25_W4) + +// ======================== LMS-SHA256 H25/W8 ======================== // + +LMS_ALG(sha256_h25_w8, SHA256_H25_W8) + +// +//2-Level LMS +// ======================== LMS-SHA256 H5/W8, H5/W8 ======================== // + +LMS_ALG(sha256_h5_w8_h5_w8, SHA256_H5_W8_H5_W8) + +// ======================== LMS-SHA256 H10/W2, H10/W2 ======================== // + +LMS_ALG(sha256_h10_w2_h10_w2, SHA256_H10_W2_H10_W2) + +// ======================== LMS-SHA256 H10/W4, H5/W8 ======================== // + +LMS_ALG(sha256_h10_w4_h5_w8, SHA256_H10_W4_H5_W8) + +// ======================== LMS-SHA256 H10/W4, H10/W4 ======================== // + +LMS_ALG(sha256_h10_w4_h10_w4, SHA256_H10_W4_H10_W4) + +// ======================== LMS-SHA256 H10/W8, H5/W8 ======================== // + +LMS_ALG(sha256_h10_w8_h5_w8, SHA256_H10_W8_H5_W8) + +// ======================== LMS-SHA256 H10/W8, H10/W8 ======================== // + +LMS_ALG(sha256_h10_w8_h10_w8, SHA256_H10_W8_H10_W8) + +// ======================== LMS-SHA256 H15/W8, H5/W8 ======================== // + +LMS_ALG(sha256_h15_w8_h5_w8, SHA256_H15_W8_H5_W8) + +// ======================== LMS-SHA256 H15/W8, H10/W8 ======================== // + +LMS_ALG(sha256_h15_w8_h10_w8, SHA256_H15_W8_H10_W8) + +// ======================== LMS-SHA256 H15/W8, H15/W8 ======================== // + +LMS_ALG(sha256_h15_w8_h15_w8, SHA256_H15_W8_H15_W8) + +// ======================== LMS-SHA256 H20/W8, H5/W8 ======================== // + +LMS_ALG(sha256_h20_w8_h5_w8, SHA256_H20_W8_H5_W8) + +// ======================== LMS-SHA256 H20/W8, H10/W8 ======================== // + +LMS_ALG(sha256_h20_w8_h10_w8, SHA256_H20_W8_H10_W8) + +// ======================== LMS-SHA256 H20/W8, H15/W8 ======================== // + +LMS_ALG(sha256_h20_w8_h15_w8, SHA256_H20_W8_H15_W8) + +// ======================== LMS-SHA256 H20/W8, H20/W8 ======================== // + +LMS_ALG(sha256_h20_w8_h20_w8, SHA256_H20_W8_H20_W8) +//2-Level LMS + +void OQS_SECRET_KEY_LMS_free(OQS_SIG_STFL_SECRET_KEY *sk) { + oqs_secret_lms_key_free(sk); +} + +/* Convert LMS secret key object to byte string */ +static OQS_STATUS OQS_SECRET_KEY_LMS_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk) { + OQS_STATUS status; + if (sk->lock_key && sk->mutex) { + sk->lock_key(sk->mutex); + } + + status = oqs_serialize_lms_key(sk_buf_ptr, sk_len, sk); + + if (sk->unlock_key && sk->mutex) { + sk->unlock_key(sk->mutex); + } + return status; +} + +/* Insert lms byte string in an LMS secret key object */ +static OQS_STATUS OQS_SECRET_KEY_LMS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, void *context) { + return oqs_deserialize_lms_key(sk, sk_buf, sk_len, context); +} + +static void OQS_SECRET_KEY_LMS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) { + if (sk && store_cb && context) { + oqs_lms_key_set_store_cb(sk, store_cb, context); + } +} diff --git a/src/sig_stfl/lms/sig_stfl_lms.h b/src/sig_stfl/lms/sig_stfl_lms.h new file mode 100644 index 0000000000..13ef40f704 --- /dev/null +++ b/src/sig_stfl/lms/sig_stfl_lms.h @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: MIT + +#ifndef OQS_SIG_STFL_LMS_H +#define OQS_SIG_STFL_LMS_H + +#include + +//OQS LMS parameter identifiers +/* Defined LM parameter sets */ +/* + * Convention + * Where ... + * L = number of Levels + * H = LMS H ID + * LMS_SHA256_M32_H5 0x05 + * LMS_SHA256_M32_H10 0x06 + * LMS_SHA256_M32_H15 0x07 + * LMS_SHA256_M32_H20 0x08 + * LMS_SHA256_M32_H25 0x09 + * + * W = Winternitz value + * LMOTS_SHA256_N32_W1 0x01 + * LMOTS_SHA256_N32_W2 0x02 + * LMOTS_SHA256_N32_W4 0x03 + * LMOTS_SHA256_N32_W8 0x04 + * + * e.g. + * OQS_LMS_ID_sha256_h5_w1 -- "5/1" ----- 0x0151 + * "5/1,5/2" ----- 0x025152 + * Number of levels L {1, 2, 3, ..., 8} + * 0x0LH(l1))W(l1)H(l2)W(l2) + * e.g + * For OQS_LMS_ID_sha256_h5_w1 the oid is 0x0151 + * Number of levels is.....0x01 + * H5 ID is.........5 + * W1 ID is..........1 + * +* For OQS_LMS_ID_sha256_h10_w4_h5_w8 the is 0x026354 + * Number of levels is.......0x02 + * Level 1 H10 ID is...........6 + * Level 1 W4 ID is............3 + * Level 2 H5 ID is.............5 + * Level 2 W8 ID is..............4 + */ +#define OQS_LMS_ID_sha256_h5_w1 0x0151 //"5/1" +#define OQS_LMS_ID_sha256_h5_w2 0x0152 //"5/2" +#define OQS_LMS_ID_sha256_h5_w4 0x0153 //"5/4" +#define OQS_LMS_ID_sha256_h5_w8 0x0154 //"5/8" + +#define OQS_LMS_ID_sha256_h10_w1 0x0161 //"10/1" +#define OQS_LMS_ID_sha256_h10_w2 0x0162 //"10/2" +#define OQS_LMS_ID_sha256_h10_w4 0x0163 //"10/4" +#define OQS_LMS_ID_sha256_h10_w8 0x0164 //"10/8" + +#define OQS_LMS_ID_sha256_h15_w1 0x0171 //"15/1" +#define OQS_LMS_ID_sha256_h15_w2 0x0172 //"15/2" +#define OQS_LMS_ID_sha256_h15_w4 0x0173 //"15/4" +#define OQS_LMS_ID_sha256_h15_w8 0x0174 //"15/8" + +#define OQS_LMS_ID_sha256_h20_w1 0x0181 //"20/1" +#define OQS_LMS_ID_sha256_h20_w2 0x0182 //"20/2" +#define OQS_LMS_ID_sha256_h20_w4 0x0183 //"20/4" +#define OQS_LMS_ID_sha256_h20_w8 0x0184 //"20/8" + +#define OQS_LMS_ID_sha256_h25_w1 0x0191 //"25/1" +#define OQS_LMS_ID_sha256_h25_w2 0x0192 //"25/2" +#define OQS_LMS_ID_sha256_h25_w4 0x0193 //"25/4" +#define OQS_LMS_ID_sha256_h25_w8 0x0194 //"25/8" + +//2-Level LMS + +//RFC 8554 example +#define OQS_LMS_ID_sha256_h5_w8_h5_w8 0x025454 //"5/8,5/8" + +//RFC 8554 example +#define OQS_LMS_ID_sha256_h10_w4_h5_w8 0x026354 //"10/4,5/8" + +//Wolf +#define OQS_LMS_ID_sha256_h10_w2_h10_w2 0x026262 //"10/2,10/2" +#define OQS_LMS_ID_sha256_h10_w4_h10_w4 0x026363 //"10/4,10/4" + +#define OQS_LMS_ID_sha256_h10_w8_h5_w8 0x026454 //"10/8,5/8" +//Wolf +#define OQS_LMS_ID_sha256_h10_w8_h10_w8 0x026464 //"10/8,10/8" +#define OQS_LMS_ID_sha256_h15_w8_h5_w8 0x027454 //"15/8,5/8" +#define OQS_LMS_ID_sha256_h15_w8_h10_w8 0x027464 //"15/8,10/8" +#define OQS_LMS_ID_sha256_h15_w8_h15_w8 0x027474 //"15/8,15/8" +#define OQS_LMS_ID_sha256_h20_w8_h5_w8 0x028454 //"20/8,5/8" +#define OQS_LMS_ID_sha256_h20_w8_h10_w8 0x028464 //"20/8,10/8" +#define OQS_LMS_ID_sha256_h20_w8_h15_w8 0x028474 //"20/8,15/8" +#define OQS_LMS_ID_sha256_h20_w8_h20_w8 0x028484 //"20/8,20/8" + +//H5 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w1_length_signature 8688 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w1_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w1_length_sk 64 +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w1_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W1_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h5_w2_length_signature 4464 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w2_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w2_length_sk 64 +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w2_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W2_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h5_w4_length_signature 2352 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w4_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w4_length_sk 64 +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w4_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W4_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8_length_signature 1296 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8_length_sk 64 +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w8_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W8_new(void); + +//H10 +// H10 W1 60 8848 64 +// H10 W2 60 4624 64 +// H10 W4 60 2512 64 +// H10 W8 60 1456 64 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w1_length_signature 8848 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w1_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w1_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W1_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w1_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2_length_signature 4624 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W2_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w2_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_length_signature 2512 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W4_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w4_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_length_signature 1456 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w8_new(void); + +//H15 +// H15 W1 60 9008 64 +// H15 W2 60 4784 64 +// H15 W4 60 2672 64 +// H15 W8 60 1616 64 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w1_length_signature 9008 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w1_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w1_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W1_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w1_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w2_length_signature 4784 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w2_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w2_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W2_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w2_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w4_length_signature 2672 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w4_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w4_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W4_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w4_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_length_signature 1616 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w8_new(void); + +//H20 +// H20 W1 60 9168 64 +// H20 W2 60 4944 64 +// H20 W4 60 2832 64 +// H20 W8 60 1776 64 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w1_length_signature 9168 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w1_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w1_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W1_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w1_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w2_length_signature 4944 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w2_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w2_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W2_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w2_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w4_length_signature 2832 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w4_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w4_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W4_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w4_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_length_signature 1776 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w8_new(void); + +//H25 +// H25 W1 60 9328 64 +// H25 W2 60 5104 64 +// H25 W4 60 2992 64 +// H25 W8 60 1936 64 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w1_length_signature 9328 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w1_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w1_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H25_W1_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h25_w1_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h25_w2_length_signature 5104 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w2_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w2_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H25_W2_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h25_w2_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h25_w4_length_signature 2992 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w4_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w4_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H25_W4_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h25_w4_new(void); + +#define OQS_SIG_STFL_alg_lms_sha256_h25_w8_length_signature 1936 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w8_length_pk 60 +#define OQS_SIG_STFL_alg_lms_sha256_h25_w8_length_sk 64 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H25_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h25_w8_new(void); + +OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_left(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_total(unsigned long long *totaln, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +void OQS_SECRET_KEY_LMS_free(OQS_SIG_STFL_SECRET_KEY *sk); + +//2-Level LMS +#define OQS_SIG_STFL_alg_lms_length_private_key 64 +#define OQS_SIG_STFL_alg_lms_length_public_key 60 +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8_length_signature 2644 + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8_length_signature 2804 + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8_length_signature 3860 + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2_length_signature 9300 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4_length_signature 5076 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8_length_signature 2964 + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8_length_signature 2964 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8_length_signature 3124 +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8_length_signature 3284 + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8_length_signature 3124 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8_length_signature 3284 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8_length_signature 3444 +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8_length_signature 3604 + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H5_W8_H5_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W4_H5_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W8_H5_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W2_H10_W2_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W4_H10_W4_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H10_W8_H10_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W8_H5_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W8_H10_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H15_W8_H15_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W8_H5_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W8_H10_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W8_H15_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8_new(void); + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_LMS_SHA256_H20_W8_H20_W8_new(void); +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8_new(void); + +// ----------------------------------- WRAPPER FUNCTIONS ------------------------------------------------ +int oqs_sig_stfl_lms_keypair(uint8_t *pk, OQS_SIG_STFL_SECRET_KEY *sk, const uint32_t oid); + +int oqs_sig_stfl_lms_sign(OQS_SIG_STFL_SECRET_KEY *sk, uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen); + +int oqs_sig_stfl_lms_verify(const uint8_t *m, size_t mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +void oqs_secret_lms_key_free(OQS_SIG_STFL_SECRET_KEY *sk); + +OQS_STATUS oqs_serialize_lms_key(uint8_t **sk_key, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk); +OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, void *context); +void oqs_lms_key_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context); + +// ---------------------------- FUNCTIONS INDEPENDENT OF VARIANT ----------------------------------------- + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signature_length, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); + +// -------------------------------------------------------------------------------------------------------- + +#endif /* OQS_SIG_STFL_LMS_H */ diff --git a/src/sig_stfl/lms/sig_stfl_lms_functions.c b/src/sig_stfl/lms/sig_stfl_lms_functions.c new file mode 100644 index 0000000000..60d1d0c60b --- /dev/null +++ b/src/sig_stfl/lms/sig_stfl_lms_functions.c @@ -0,0 +1,808 @@ +// SPDX-License-Identifier: MIT + +#include +#include +#include "sig_stfl_lms.h" +#include "external/config.h" +#include "external/hss_verify_inc.h" +#include "external/hss_sign_inc.h" +#include "external/hss.h" +#include "external/endian.h" +#include "external/hss_internal.h" +#include "sig_stfl_lms_wrap.h" + +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +#define DEFAULT_AUX_DATA 10916 /* Use 10+k of aux data (which works well */ +/* with the above default parameter set) */ +/** + * @brief OQS_LMS_KEY object for HSS key pair + */ + +typedef struct OQS_LMS_KEY_DATA { + + /* Tree levels. */ + uint32_t levels; + + /* Array, 8 levels max, of LMS types */ + param_set_t lm_type[8]; + + /* Array, 8 levels max, of LM OTS types */ + param_set_t lm_ots_type[8]; + + /* LMS public key */ + uint8_t public_key[60]; + + /* Length of aux data */ + size_t len_aux_data; + /* internal nodes info of the Merkle tree */ + uint8_t *aux_data; + + /* Length of sec_key */ + size_t len_sec_key; + + /* secret key data */ + uint8_t *sec_key; + + /* app specific */ + void *context; +} oqs_lms_key_data; + +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(UNUSED uint8_t *signature, UNUSED size_t *signature_length, UNUSED const uint8_t *message, + UNUSED size_t message_len, UNUSED OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signature_length, const uint8_t *message, + size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { + OQS_STATUS status = OQS_ERROR; + OQS_STATUS rc_keyupdate = OQS_ERROR; + oqs_lms_key_data *lms_key_data = NULL; + uint8_t *sk_key_buf = NULL; + size_t sk_key_buf_len = 0; + void *context; + + if (secret_key == NULL || message == NULL || signature == NULL || signature_length == NULL) { + return OQS_ERROR; + } + + /* Lock secret to ensure OTS use */ + if ((secret_key->lock_key) && (secret_key->mutex)) { + secret_key->lock_key(secret_key->mutex); + } + + /* + * Don't even attempt signing without a way to safe the updated private key + */ + if (secret_key->secure_store_scrt_key == NULL) { + fprintf(stderr, "No Secure-store set for secret key.\n."); + goto err; + } + + lms_key_data = (oqs_lms_key_data *)secret_key->secret_key_data; + if (lms_key_data == NULL) { + goto err; + } + + if (oqs_sig_stfl_lms_sign(secret_key, signature, + signature_length, + message, message_len) != 0) { + goto err; + } + + /* + * serialize and securely store the updated private key + * but, delete signature and the serialized key other wise + */ + + rc_keyupdate = oqs_serialize_lms_key(&sk_key_buf, &sk_key_buf_len, secret_key); + if (rc_keyupdate != OQS_SUCCESS) { + goto err; + } + + context = secret_key->context; + rc_keyupdate = secret_key->secure_store_scrt_key(sk_key_buf, sk_key_buf_len, context); + if (rc_keyupdate != OQS_SUCCESS) { + goto err; + } + + status = OQS_SUCCESS; + goto passed; + +err: + if (*signature_length) { + OQS_MEM_cleanse(signature, *signature_length); + } + *signature_length = 0; + +passed: + OQS_MEM_secure_free(sk_key_buf, sk_key_buf_len); + + /* Unlock secret to ensure OTS use */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } + return status; +} +#endif + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_verify(const uint8_t *message, size_t message_len, + const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + + if (message == NULL || signature == NULL || public_key == NULL) { + return OQS_ERROR; + } + + if (oqs_sig_stfl_lms_verify(message, message_len, + signature, signature_len, + public_key) != 0 ) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_left(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + OQS_STATUS status; + uint8_t *priv_key = NULL; + unsigned long long total_sigs = 0; + sequence_t current_count = 0; + oqs_lms_key_data *oqs_key_data = NULL; + + if (remain == NULL || secret_key == NULL) { + return OQS_ERROR; + } + + status = OQS_SIG_STFL_lms_sigs_total(&total_sigs, secret_key); + if (status != OQS_SUCCESS) { + return OQS_ERROR; + } + + /* Lock secret key to ensure data integrity use */ + if ((secret_key->lock_key) && (secret_key->mutex)) { + secret_key->lock_key(secret_key->mutex); + } + + oqs_key_data = secret_key->secret_key_data; + if (oqs_key_data == NULL) { + goto err; + } + priv_key = oqs_key_data->sec_key; + if (priv_key == NULL) { + goto err; + } + + current_count = get_bigendian(priv_key + PRIVATE_KEY_INDEX, PRIVATE_KEY_INDEX_LEN /*0, 8 */); + *remain = (total_sigs - (unsigned long long)current_count); + +err: + /* Unlock secret key */ + if ((secret_key->unlock_key) && (secret_key->mutex)) { + secret_key->unlock_key(secret_key->mutex); + } + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_lms_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + + uint8_t *priv_key = NULL; + oqs_lms_key_data *oqs_key_data = NULL; + struct hss_working_key *working_key = NULL; + + if (total == NULL || secret_key == NULL) { + return OQS_ERROR; + } + + oqs_key_data = secret_key->secret_key_data; + if (!oqs_key_data) { + return OQS_ERROR; + } + + priv_key = oqs_key_data->sec_key; + if (!priv_key) { + return OQS_ERROR; + } + + working_key = hss_load_private_key(NULL, priv_key, + 0, + NULL, + 0, + 0); + if (!working_key) { + return OQS_ERROR; + } + + *total = (unsigned long long)working_key->max_count; + hss_free_working_key(working_key); + return OQS_SUCCESS; +} + +/* LMS wrapper functions use internal OIDs to + * identify the parameter set to be used + */ + +bool LMS_randombytes(void *buffer, size_t length) { + + OQS_randombytes((uint8_t *)buffer, length); + return true; +} + +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +int oqs_sig_stfl_lms_keypair(UNUSED uint8_t *pk, UNUSED OQS_SIG_STFL_SECRET_KEY *sk, UNUSED const uint32_t oid) { + return -1; +} +#else +int oqs_sig_stfl_lms_keypair(uint8_t *pk, OQS_SIG_STFL_SECRET_KEY *sk, const uint32_t oid) { + + int ret = -1; + bool b_ret; + int parse_err = 0; + + size_t len_public_key = 60; + oqs_lms_key_data *oqs_key_data = NULL; + + if (!pk || !sk || !oid) { + return -1; + } + + if (sk->secret_key_data) { + //this means a key pair has already been recreated + return -1; + } + + oqs_key_data = malloc(sizeof(oqs_lms_key_data)); + if (oqs_key_data == NULL) { + return -1; + } + + memset(oqs_key_data, 0, sizeof(oqs_lms_key_data)); + if (sk->length_secret_key == 0) { + OQS_MEM_insecure_free(oqs_key_data); + oqs_key_data = NULL; + return -1; + } + + oqs_key_data->levels = 1; + oqs_key_data->len_sec_key = sk->length_secret_key; + oqs_key_data->sec_key = (uint8_t *)malloc(sk->length_secret_key * sizeof(uint8_t)); + if (oqs_key_data->sec_key == NULL) { + OQS_MEM_insecure_free(oqs_key_data); + oqs_key_data = NULL; + return -1; + } + + memset(oqs_key_data->sec_key, 0, sk->length_secret_key); + + //Aux Data + size_t len_aux_data = DEFAULT_AUX_DATA; + uint8_t *aux_data = calloc(len_aux_data, sizeof(uint8_t)); + if (aux_data == NULL) { + OQS_MEM_insecure_free( oqs_key_data->sec_key); + OQS_MEM_insecure_free(oqs_key_data); + return -1; + } + + oqs_key_data->aux_data = aux_data; + oqs_key_data->len_aux_data = len_aux_data; + oqs_key_data->context = sk->context; + + /* Set lms param set */ + switch (oid) { + case OQS_LMS_ID_sha256_h5_w1: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W1; + break; + case OQS_LMS_ID_sha256_h5_w2: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h5_w4: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h5_w8: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + break; + + case OQS_LMS_ID_sha256_h10_w1: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W1; + break; + case OQS_LMS_ID_sha256_h10_w2: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h10_w4: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h10_w8: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + break; + + case OQS_LMS_ID_sha256_h15_w1: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W1; + break; + case OQS_LMS_ID_sha256_h15_w2: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h15_w4: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h15_w8: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + break; + + case OQS_LMS_ID_sha256_h20_w1: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W1; + break; + case OQS_LMS_ID_sha256_h20_w2: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h20_w4: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h20_w8: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + break; + + case OQS_LMS_ID_sha256_h25_w1: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H25; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W1; + break; + case OQS_LMS_ID_sha256_h25_w2: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H25; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h25_w4: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H25; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h25_w8: + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H25; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h5_w8_h5_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h10_w8_h5_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h10_w2_h10_w2: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W2; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W2; + break; + case OQS_LMS_ID_sha256_h10_w4_h5_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h10_w4_h10_w4: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W4; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W4; + break; + case OQS_LMS_ID_sha256_h10_w8_h10_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h15_w8_h5_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h15_w8_h10_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h15_w8_h15_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h20_w8_h5_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H5; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h20_w8_h10_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H10; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h20_w8_h15_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H15; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + case OQS_LMS_ID_sha256_h20_w8_h20_w8: + oqs_key_data->levels = 2; + oqs_key_data->lm_type[0] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[0] = LMOTS_SHA256_N32_W8; + oqs_key_data->lm_type[1] = LMS_SHA256_N32_H20; + oqs_key_data->lm_ots_type[1] = LMOTS_SHA256_N32_W8; + break; + default: + oqs_key_data->lm_type[0] = 0; + oqs_key_data->lm_ots_type[0] = 0; + parse_err = 1; + break; + } + + if (parse_err) { + OQS_MEM_insecure_free(oqs_key_data->sec_key); + OQS_MEM_insecure_free(oqs_key_data->aux_data); + OQS_MEM_insecure_free(oqs_key_data); + oqs_key_data = NULL; + return -1; + } + + /* + * This creates a private key (and the correspond public key, and optionally + * the aux data for that key) + * Parameters: + * generate_random - the function to be called to generate randomness. This + * is assumed to be a pointer to a cryptographically secure rng, + * otherwise all security is lost. This function is expected to fill + * output with 'length' uniformly distributed bits, and return 1 on + * success, 0 if something went wrong + * levels - the number of levels for the key pair (2-8) + * lm_type - an array of the LM registry entries for the various levels; + * entry 0 is the topmost + * lm_ots_type - an array of the LM-OTS registry entries for the various + * levels; again, entry 0 is the topmost + * update_private_key, context - the function that is called when the + * private key is generated; it is expected to store it to secure NVRAM + * If this is NULL, then the context pointer is reinterpretted to mean + * where in RAM the private key is expected to be placed + * public_key - where to store the public key + * len_public_key - length of the above buffer; see hss_get_public_key_len + * if you need a hint. + * aux_data - where to store the optional aux data. This is not required, but + * if provided, can be used to speed up the hss_generate_working_key + * process; + * len_aux_data - the length of the above buffer. This is not fixed length; + * the function will run different time/memory trade-offs based on the + * length provided + * + * This returns true on success, false on failure + */ + b_ret = hss_generate_private_key( + LMS_randombytes, + oqs_key_data->levels, + oqs_key_data->lm_type, + oqs_key_data->lm_ots_type, + NULL, //File handler function? + oqs_key_data->sec_key, + oqs_key_data->public_key, len_public_key, + oqs_key_data->aux_data, oqs_key_data->len_aux_data, + NULL); + if (b_ret) { + memcpy(pk, oqs_key_data->public_key, len_public_key); + sk->secret_key_data = oqs_key_data; + } else { + OQS_MEM_secure_free(oqs_key_data->sec_key, sk->length_secret_key * sizeof(uint8_t)); + OQS_MEM_insecure_free(oqs_key_data->aux_data); + OQS_MEM_insecure_free(oqs_key_data); + oqs_key_data = NULL; + return -1; + } + + ret = 0; + return ret; +} +#endif + +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +int oqs_sig_stfl_lms_sign(UNUSED OQS_SIG_STFL_SECRET_KEY *sk, UNUSED uint8_t *signature, UNUSED size_t *signature_len, + UNUSED const uint8_t *m, UNUSED size_t mlen) { + return -1; +} +#else +int oqs_sig_stfl_lms_sign(OQS_SIG_STFL_SECRET_KEY *sk, + uint8_t *signature, size_t *signature_len, + const uint8_t *m, size_t mlen) { + + size_t sig_len; + bool status; + uint8_t *sig = NULL; + uint8_t *priv_key = NULL; + oqs_lms_key_data *oqs_key_data = NULL; + struct hss_working_key *w = NULL; + struct hss_sign_inc ctx; + if (sk) { + oqs_key_data = sk->secret_key_data; + priv_key = oqs_key_data->sec_key; + } else { + return -1; + } + w = hss_load_private_key(NULL, priv_key, + 0, + NULL, + 0, + 0); + if (!w) { + hss_free_working_key(w); + return 0; + } + + /* Now, go through the file list, and generate the signatures for each */ + + /* Look up the signature length */ + + sig_len = hss_get_signature_len_from_working_key(w); + if (sig_len == 0) { + hss_free_working_key(w); + return 0; + } + + sig = malloc(sig_len); + if (!sig) { + hss_free_working_key(w); + return -1; + } + + (void)hss_sign_init( + &ctx, /* Incremental signing context */ + w, /* Working key */ + NULL, /* Routine to update the */ + priv_key, /* private key */ + sig, sig_len, /* Where to place the signature */ + 0); + + (void)hss_sign_update( + &ctx, /* Incremental signing context */ + m, /* Next piece of the message */ + mlen); /* Length of this piece */ + + status = hss_sign_finalize( + &ctx, /* Incremental signing context */ + w, /* Working key */ + sig, /* Signature */ + 0); + + if (!status) { + hss_free_working_key(w); + OQS_MEM_insecure_free(sig); + return -1; + } + + *signature_len = sig_len; + memcpy(signature, sig, sig_len); + OQS_MEM_insecure_free(sig); + hss_free_working_key(w); + + return 0; +} +#endif + +int oqs_sig_stfl_lms_verify(const uint8_t *m, size_t mlen, + const uint8_t *signature, size_t signature_len, + const uint8_t *pk) { + + struct hss_validate_inc ctx; + (void)hss_validate_signature_init( + &ctx, /* Incremental validate context */ + (const unsigned char *)pk, /* Public key */ + (const unsigned char *)signature, + (size_t)signature_len, /* Signature */ + 0); /* Use the defaults for extra info */ + + (void)hss_validate_signature_update( + &ctx, /* Incremental validate context */ + (const void *) m, /* Next piece of the message */ + (size_t)mlen); /* Length of this piece */ + + bool status = hss_validate_signature_finalize( + &ctx, /* Incremental validate context */ + (const unsigned char *)signature, /* Signature */ + 0); /* Use the defaults for extra info */ + + if (status) { + /* Signature verified */ + return 0; + } else { + /* signature NOT verified */ + return -1; + } +} + +void oqs_secret_lms_key_free(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return; + } + + if (sk->secret_key_data) { + oqs_lms_key_data *key_data = (oqs_lms_key_data *)sk->secret_key_data; + if (key_data) { + OQS_MEM_secure_free(key_data->sec_key, key_data->len_sec_key); + key_data->sec_key = NULL; + + OQS_MEM_secure_free(key_data->aux_data, key_data->len_aux_data); + } + + OQS_MEM_insecure_free(key_data); + sk->secret_key_data = NULL; + } +} + +/* + * Convert LMS secret key object to byte string + * Writes secret key + aux data if present + */ +OQS_STATUS oqs_serialize_lms_key(uint8_t **sk_key, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk) { + + if (sk == NULL || sk_len == NULL || sk_key == NULL) { + return OQS_ERROR; + } + + oqs_lms_key_data *lms_key_data = sk->secret_key_data; + + if (lms_key_data == NULL || lms_key_data->sec_key == NULL) { + return OQS_ERROR; + } + + size_t key_len = lms_key_data->len_aux_data + lms_key_data->len_sec_key; + + if (key_len == 0) { + return OQS_ERROR; + } + + uint8_t *sk_key_buf = malloc(key_len * sizeof(uint8_t)); + + if (sk_key_buf == NULL) { + return OQS_ERROR; + } + /* pass back serialized data */ + /* + * Serialized data is sec_key followed by aux data + * So aux data begins after buffer top + sec_key length + */ + if (lms_key_data->len_sec_key != 0) { + memcpy(sk_key_buf, lms_key_data->sec_key, lms_key_data->len_sec_key); + } + + if (lms_key_data->len_aux_data != 0) { + memcpy(sk_key_buf + lms_key_data->len_sec_key, lms_key_data->aux_data, lms_key_data->len_aux_data); + } + + *sk_key = sk_key_buf; + *sk_len = sk->length_secret_key + lms_key_data->len_aux_data; + + return OQS_SUCCESS; +} + +/* + * Convert LMS byte string to secret key object + * Writes secret key + aux data if present + * key_len is priv key length + aux length + */ +OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, void *context) { + + oqs_lms_key_data *lms_key_data = NULL; + uint8_t *lms_sk = NULL; + uint8_t *lms_aux = NULL; + size_t aux_buf_len = 0; + size_t lms_sk_len = hss_get_private_key_len((unsigned )(1), NULL, NULL); + + if (sk == NULL || sk_buf == NULL || (sk_len == 0) || (sk_len < lms_sk_len )) { + return OQS_ERROR; + } + +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + return OQS_ERROR; +#endif + + aux_buf_len = sk_len - lms_sk_len; + if (sk->secret_key_data) { + // Key data already present + // We dont want to trample over data + return OQS_ERROR; + } + + unsigned levels = 0; + + param_set_t lm_type[ MAX_HSS_LEVELS ]; + param_set_t lm_ots_type[ MAX_HSS_LEVELS ]; + + // validate sk_buf for lms params + if (!hss_get_parameter_set(&levels, + lm_type, + lm_ots_type, + NULL, + (void *)sk_buf)) { + return OQS_ERROR; + } + + lms_key_data = malloc(sizeof(oqs_lms_key_data)); + lms_sk = malloc(lms_sk_len * sizeof(uint8_t)); + + if (lms_key_data == NULL || lms_sk == NULL) { + goto err; + } + + memcpy(lms_sk, sk_buf, lms_sk_len); + lms_key_data->sec_key = lms_sk; + lms_key_data->len_sec_key = lms_sk_len; + lms_key_data->context = context; + + if (aux_buf_len) { + lms_aux = malloc(aux_buf_len * sizeof(uint8_t)); + + if (lms_aux == NULL) { + goto err; + } + + memcpy(lms_aux, sk_buf + lms_sk_len, aux_buf_len); + lms_key_data->aux_data = lms_aux; + lms_key_data->len_aux_data = aux_buf_len; + } + + sk->context = context; + sk->secret_key_data = lms_key_data; + goto success; + +err: + OQS_MEM_secure_free(lms_key_data, sizeof(oqs_lms_key_data)); + OQS_MEM_secure_free(lms_sk, lms_sk_len); + OQS_MEM_secure_free(lms_aux, aux_buf_len); + return OQS_ERROR; + +success: + return OQS_SUCCESS; +} + +void oqs_lms_key_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) { + + if (sk == NULL) { + return; + } + sk->secure_store_scrt_key = store_cb; + sk->context = context; +} diff --git a/src/sig_stfl/lms/sig_stfl_lms_wrap.h b/src/sig_stfl/lms/sig_stfl_lms_wrap.h new file mode 100644 index 0000000000..e113a16ed6 --- /dev/null +++ b/src/sig_stfl/lms/sig_stfl_lms_wrap.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT + +#ifndef OQS_SIG_STFL_LMS_WRAP_H +#define OQS_SIG_STFL_LMS_WRAP_H + +//#include +#include "external/hss.h" +#include "external/hss_sign_inc.h" + +/** + * @brief OQS_LMS_KEY object for HSS key pair + */ +typedef struct OQS_LMS_KEY_DATA oqs_lms_key_data; + +typedef struct OQS_LMS_SIG_DATA oqs_lms_sig_data; + +typedef struct OQS_LMS_SIG_DATA { + + /* message buffer */ + unsigned char *message; + + /* Length of msg buffer */ + size_t len_msg_buf; + + /* signature buffer */ + unsigned char *signature; + + /* Length of sig buffer */ + size_t len_sig_buf; + +} oqs_lms_sig_data; + +#endif //OQS_SIG_STFL_LMS_H diff --git a/src/sig_stfl/sig_stfl.c b/src/sig_stfl/sig_stfl.c new file mode 100644 index 0000000000..51d7865373 --- /dev/null +++ b/src/sig_stfl/sig_stfl.c @@ -0,0 +1,1434 @@ +// SPDX-License-Identifier: MIT + +#include +#include +#if defined(_WIN32) +#include +#define strcasecmp _stricmp +#else +#include +#endif + +#include + +#ifdef OQS_ENABLE_SIG_STFL_XMSS +#include +#endif // OQS_ENABLE_SIG_STFL_XMSS + +#ifdef OQS_ENABLE_SIG_STFL_LMS +#include +#endif // OQS_ENABLE_SIG_STFL_LMS + +OQS_API const char *OQS_SIG_STFL_alg_identifier(size_t i) { + + const char *a[OQS_SIG_STFL_algs_length] = { + // XMSS + OQS_SIG_STFL_alg_xmss_sha256_h10, + OQS_SIG_STFL_alg_xmss_sha256_h16, + OQS_SIG_STFL_alg_xmss_sha256_h20, + OQS_SIG_STFL_alg_xmss_shake128_h10, + OQS_SIG_STFL_alg_xmss_shake128_h16, + OQS_SIG_STFL_alg_xmss_shake128_h20, + OQS_SIG_STFL_alg_xmss_sha512_h10, + OQS_SIG_STFL_alg_xmss_sha512_h16, + OQS_SIG_STFL_alg_xmss_sha512_h20, + OQS_SIG_STFL_alg_xmss_shake256_h10, + OQS_SIG_STFL_alg_xmss_shake256_h16, + OQS_SIG_STFL_alg_xmss_shake256_h20, + OQS_SIG_STFL_alg_xmssmt_sha256_h20_2, + OQS_SIG_STFL_alg_xmssmt_sha256_h20_4, + OQS_SIG_STFL_alg_xmssmt_sha256_h40_2, + OQS_SIG_STFL_alg_xmssmt_sha256_h40_4, + OQS_SIG_STFL_alg_xmssmt_sha256_h40_8, + OQS_SIG_STFL_alg_xmssmt_sha256_h60_3, + OQS_SIG_STFL_alg_xmssmt_sha256_h60_6, + OQS_SIG_STFL_alg_xmssmt_sha256_h60_12, + OQS_SIG_STFL_alg_xmssmt_shake128_h20_2, + OQS_SIG_STFL_alg_xmssmt_shake128_h20_4, + OQS_SIG_STFL_alg_xmssmt_shake128_h40_2, + OQS_SIG_STFL_alg_xmssmt_shake128_h40_4, + OQS_SIG_STFL_alg_xmssmt_shake128_h40_8, + OQS_SIG_STFL_alg_xmssmt_shake128_h60_3, + OQS_SIG_STFL_alg_xmssmt_shake128_h60_6, + OQS_SIG_STFL_alg_xmssmt_shake128_h60_12, + // LMS + OQS_SIG_STFL_alg_lms_sha256_h5_w1, + OQS_SIG_STFL_alg_lms_sha256_h5_w2, + OQS_SIG_STFL_alg_lms_sha256_h5_w4, + OQS_SIG_STFL_alg_lms_sha256_h5_w8, + + OQS_SIG_STFL_alg_lms_sha256_h10_w1, + OQS_SIG_STFL_alg_lms_sha256_h10_w2, + OQS_SIG_STFL_alg_lms_sha256_h10_w4, + OQS_SIG_STFL_alg_lms_sha256_h10_w8, + + OQS_SIG_STFL_alg_lms_sha256_h15_w1, + OQS_SIG_STFL_alg_lms_sha256_h15_w2, + OQS_SIG_STFL_alg_lms_sha256_h15_w4, + OQS_SIG_STFL_alg_lms_sha256_h15_w8, + + OQS_SIG_STFL_alg_lms_sha256_h20_w1, + OQS_SIG_STFL_alg_lms_sha256_h20_w2, + OQS_SIG_STFL_alg_lms_sha256_h20_w4, + OQS_SIG_STFL_alg_lms_sha256_h20_w8, + + OQS_SIG_STFL_alg_lms_sha256_h25_w1, + OQS_SIG_STFL_alg_lms_sha256_h25_w2, + OQS_SIG_STFL_alg_lms_sha256_h25_w4, + OQS_SIG_STFL_alg_lms_sha256_h25_w8, + + //2-Level LMS + OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8, + OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8, + + OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8, + OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2, + OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4, + OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8, + + OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8, + OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8, + OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8, + + OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8, + OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8, + OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8, + OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8, + }; + + if (i >= OQS_SIG_STFL_algs_length) { + return NULL; + } else { + return a[i]; + } +} + +OQS_API int OQS_SIG_STFL_alg_count(void) { + return OQS_SIG_STFL_algs_length; +} + +OQS_API int OQS_SIG_STFL_alg_is_enabled(const char *method_name) { + assert(method_name != NULL); + + if (0) { + + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h10 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h16 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h20 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h10 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h16 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h20 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h10 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h16 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h20 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h10 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h16 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h20 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 + return 1; +#else + return 0; +#endif + } +//#ifdef OQS_ENABLE_SIG_STFL_LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8 + return 1; +#else + return 0; +#endif + } + + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8 + return 1; +#else + return 0; +#endif + } + + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8 + return 1; +#else + return 0; +#endif + } + + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w8 + return 1; +#else + return 0; +#endif + } + //2-Level LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2_h10_w2 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h10_w4 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h10_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h10_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h15_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h5_w8 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return 1; +#else + return 0; +#endif + } +//#endif //OQS_ENABLE_SIG_STFL_LMS + else { + return 0; + } +} + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_new(const char *method_name) { + assert(method_name != NULL); + + if (0) { + + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h10 + return OQS_SIG_STFL_alg_xmss_sha256_h10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h16 + return OQS_SIG_STFL_alg_xmss_sha256_h16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h20 + return OQS_SIG_STFL_alg_xmss_sha256_h20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h10 + return OQS_SIG_STFL_alg_xmss_shake128_h10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h16 + return OQS_SIG_STFL_alg_xmss_shake128_h16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h20 + return OQS_SIG_STFL_alg_xmss_shake128_h20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h10 + return OQS_SIG_STFL_alg_xmss_sha512_h10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h16 + return OQS_SIG_STFL_alg_xmss_sha512_h16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h20 + return OQS_SIG_STFL_alg_xmss_sha512_h20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h10 + return OQS_SIG_STFL_alg_xmss_shake256_h10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h16 + return OQS_SIG_STFL_alg_xmss_shake256_h16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h20 + return OQS_SIG_STFL_alg_xmss_shake256_h20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 + return OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 + return OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 + return OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 + return OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 + return OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 + return OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 + return OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 + return OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 + return OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 + return OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 + return OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 + return OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 + return OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 + return OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 + return OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 + return OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_new(); +#else + return NULL; +#endif + } +//#ifdef OQS_ENABLE_SIG_STFL_LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return OQS_SIG_STFL_alg_lms_sha256_h5_w1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 + return OQS_SIG_STFL_alg_lms_sha256_h5_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 + return OQS_SIG_STFL_alg_lms_sha256_h5_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w1 + return OQS_SIG_STFL_alg_lms_sha256_h10_w1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2 + return OQS_SIG_STFL_alg_lms_sha256_h10_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4 + return OQS_SIG_STFL_alg_lms_sha256_h10_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8 + return OQS_SIG_STFL_alg_lms_sha256_h10_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w1 + return OQS_SIG_STFL_alg_lms_sha256_h15_w1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w2 + return OQS_SIG_STFL_alg_lms_sha256_h15_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w4 + return OQS_SIG_STFL_alg_lms_sha256_h15_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8 + return OQS_SIG_STFL_alg_lms_sha256_h15_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w1 + return OQS_SIG_STFL_alg_lms_sha256_h20_w1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w2 + return OQS_SIG_STFL_alg_lms_sha256_h20_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w4 + return OQS_SIG_STFL_alg_lms_sha256_h20_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8 + return OQS_SIG_STFL_alg_lms_sha256_h20_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h28_w1 + return OQS_SIG_STFL_alg_lms_sha256_h25_w1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h28_w2 + return OQS_SIG_STFL_alg_lms_sha256_h25_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w4 + return OQS_SIG_STFL_alg_lms_sha256_h25_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w8 + return OQS_SIG_STFL_alg_lms_sha256_h25_w8_new(); +#else + return NULL; +#endif + } +//2-Level LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2_h10_w2 + return OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h10_w4 + return OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h10_w8 + return OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h10_w8 + return OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h15_w8 + return OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h5_w8 + return OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h10_w8 + return OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h15_w8 + return OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h20_w8 + return OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8_new(); +#else + return NULL; +#endif + } +//#endif //OQS_ENABLE_SIG_STFL_LMS + else { + return NULL; + } +} + +OQS_API OQS_STATUS OQS_SIG_STFL_keypair(const OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + (void)sig; + (void)public_key; + (void)secret_key; + return OQS_ERROR; +#else + if (sig == NULL || sig->keypair == NULL || sig->keypair(public_key, secret_key) != 0) { + return OQS_ERROR; + } else { + return OQS_SUCCESS; + } + return OQS_ERROR; +#endif +} + +OQS_API OQS_STATUS OQS_SIG_STFL_sign(const OQS_SIG_STFL *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, + size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + (void)sig; + (void)signature; + (void)signature_len; + (void)message; + (void)message_len; + (void)secret_key; + return OQS_ERROR; +#else + if (sig == NULL || sig->sign == NULL || sig->sign(signature, signature_len, message, message_len, secret_key) != 0) { + return OQS_ERROR; + } else { + return OQS_SUCCESS; + } +#endif +} + +OQS_API OQS_STATUS OQS_SIG_STFL_verify(const OQS_SIG_STFL *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + if (sig == NULL || sig->verify == NULL || sig->verify(message, message_len, signature, signature_len, public_key) != 0) { + return OQS_ERROR; + } else { + return OQS_SUCCESS; + } +} + +OQS_API OQS_STATUS OQS_SIG_STFL_sigs_remaining(const OQS_SIG_STFL *sig, unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + (void)sig; + (void)remain; + (void)secret_key; + return OQS_ERROR; +#else + if (sig == NULL || sig->sigs_remaining == NULL || sig->sigs_remaining(remain, secret_key) != 0) { + return OQS_ERROR; + } else { + return OQS_SUCCESS; + } +#endif //OQS_ALLOW_STFL_KEY_AND_SIG_GEN +} + +OQS_API OQS_STATUS OQS_SIG_STFL_sigs_total(const OQS_SIG_STFL *sig, unsigned long long *max, const OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + (void)sig; + (void)max; + (void)secret_key; + return OQS_ERROR; +#else + if (sig == NULL || sig->sigs_total == NULL || sig->sigs_total(max, secret_key) != 0) { + return OQS_ERROR; + } else { + return OQS_SUCCESS; + } +#endif //OQS_ALLOW_STFL_KEY_AND_SIG_GEN +} + +OQS_API void OQS_SIG_STFL_free(OQS_SIG_STFL *sig) { + OQS_MEM_insecure_free(sig); +} + +// ================================= OQS_SIG_STFL_SECRET_KEY FUNCTION =============================================== + +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SIG_STFL_SECRET_KEY_new(const char *method_name) { + assert(method_name != NULL); + + if (0) { + + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h10 + return OQS_SECRET_KEY_XMSS_SHA256_H10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h16 + return OQS_SECRET_KEY_XMSS_SHA256_H16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h20 + return OQS_SECRET_KEY_XMSS_SHA256_H20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h10 + return OQS_SECRET_KEY_XMSS_SHAKE128_H10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h16 + return OQS_SECRET_KEY_XMSS_SHAKE128_H16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake128_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h20 + return OQS_SECRET_KEY_XMSS_SHAKE128_H20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h10 + return OQS_SECRET_KEY_XMSS_SHA512_H10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h16 + return OQS_SECRET_KEY_XMSS_SHA512_H16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_sha512_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h20 + return OQS_SECRET_KEY_XMSS_SHA512_H20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h10)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h10 + return OQS_SECRET_KEY_XMSS_SHAKE256_H10_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h16)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h16 + return OQS_SECRET_KEY_XMSS_SHAKE256_H16_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmss_shake256_h20)) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h20 + return OQS_SECRET_KEY_XMSS_SHAKE256_H20_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 + return OQS_SECRET_KEY_XMSSMT_SHA256_H20_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 + return OQS_SECRET_KEY_XMSSMT_SHA256_H20_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 + return OQS_SECRET_KEY_XMSSMT_SHA256_H40_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 + return OQS_SECRET_KEY_XMSSMT_SHA256_H40_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 + return OQS_SECRET_KEY_XMSSMT_SHA256_H40_8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 + return OQS_SECRET_KEY_XMSSMT_SHA256_H60_3_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 + return OQS_SECRET_KEY_XMSSMT_SHA256_H60_6_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 + return OQS_SECRET_KEY_XMSSMT_SHA256_H60_12_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H20_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H20_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_2)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_4)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_8)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_3)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_3_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_6)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_6_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_12)) { +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 + return OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_12_new(); +#else + return NULL; +#endif + } +//#ifdef OQS_ENABLE_SIG_STFL_LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 + return OQS_SECRET_KEY_LMS_SHA256_H5_W1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 + return OQS_SECRET_KEY_LMS_SHA256_H5_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 + return OQS_SECRET_KEY_LMS_SHA256_H5_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w1 + return OQS_SECRET_KEY_LMS_SHA256_H10_W1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2 + return OQS_SECRET_KEY_LMS_SHA256_H10_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4 + return OQS_SECRET_KEY_LMS_SHA256_H10_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8 + return OQS_SECRET_KEY_LMS_SHA256_H10_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w1 + return OQS_SECRET_KEY_LMS_SHA256_H15_W1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w2 + return OQS_SECRET_KEY_LMS_SHA256_H15_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w4 + return OQS_SECRET_KEY_LMS_SHA256_H15_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8 + return OQS_SECRET_KEY_LMS_SHA256_H15_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w1 + return OQS_SECRET_KEY_LMS_SHA256_H20_W1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w2 + return OQS_SECRET_KEY_LMS_SHA256_H20_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w4 + return OQS_SECRET_KEY_LMS_SHA256_H20_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8 + return OQS_SECRET_KEY_LMS_SHA256_H20_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w1)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w1 + return OQS_SECRET_KEY_LMS_SHA256_H25_W1_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w2 + return OQS_SECRET_KEY_LMS_SHA256_H25_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w4 + return OQS_SECRET_KEY_LMS_SHA256_H25_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h25_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h25_w4 + return OQS_SECRET_KEY_LMS_SHA256_H25_W8_new(); +#else + return NULL; +#endif + } +//2-Level LMS + else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H5_W8_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H10_W8_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w2_h10_w2 + return OQS_SECRET_KEY_LMS_SHA256_H10_W2_H10_W2_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h10_w4 + return OQS_SECRET_KEY_LMS_SHA256_H10_W4_H10_W4_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H10_W4_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h10_w8 + return OQS_SECRET_KEY_LMS_SHA256_H10_W8_H10_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H15_W8_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h10_w8_h10_w8 + return OQS_SECRET_KEY_LMS_SHA256_H15_W8_H10_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h15_w8_h15_w8 + return OQS_SECRET_KEY_LMS_SHA256_H15_W8_H15_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h5_w8 + return OQS_SECRET_KEY_LMS_SHA256_H20_W8_H5_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h10_w8 + return OQS_SECRET_KEY_LMS_SHA256_H20_W8_H10_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h15_w8 + return OQS_SECRET_KEY_LMS_SHA256_H20_W8_H15_W8_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8)) { +#ifdef OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h20_w8 + return OQS_SECRET_KEY_LMS_SHA256_H20_W8_H20_W8_new(); +#else + return NULL; +#endif + } +//#endif //OQS_ENABLE_SIG_STFL_LMS + else { + return NULL; + } +} + +OQS_API void OQS_SIG_STFL_SECRET_KEY_free(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL || sk->free_key == NULL) { + return; + } + + /* Call object specific free */ + sk->free_key(sk); + + /* Free sk object */ + OQS_MEM_secure_free(sk, sizeof(*sk)); +} + +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) { + if (sk == NULL || sk->set_scrt_key_store_cb == NULL) { + return; + } + sk->set_scrt_key_store_cb(sk, store_cb, context); +} + +/* Convert secret key object to byte string */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_serialize(uint8_t **sk_buf_ptr, size_t *sk_buf_len, const OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL || sk_buf_len == NULL || sk_buf_ptr == NULL || sk->serialize_key == NULL) { + return OQS_ERROR; + } + + return sk->serialize_key(sk_buf_ptr, sk_buf_len, sk); +} + +/* Insert secret key byte string in an Stateful secret key object */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_deserialize(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_buf_len, void *context) { + if (sk == NULL || sk_buf == NULL || sk->deserialize_key == NULL) { + return OQS_ERROR; + } + + return sk->deserialize_key(sk, sk_buf, sk_buf_len, context); +} + +/* OQS_SIG_STFL_SECRET_KEY_SET_lock callback function*/ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_lock(OQS_SIG_STFL_SECRET_KEY *sk, lock_key lock) { + if (sk == NULL) { + return; + } + sk->lock_key = lock; +} + +/* OQS_SIG_STFL_SECRET_KEY_SET_unlock callback function */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_unlock(OQS_SIG_STFL_SECRET_KEY *sk, unlock_key unlock) { + if (sk == NULL) { + return; + } + sk->unlock_key = unlock; +} + +/* OQS_SIG_STFL_SECRET_KEY_SET_mutex */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_mutex(OQS_SIG_STFL_SECRET_KEY *sk, void *mutex) { + if (sk == NULL) { + return; + } + sk->mutex = mutex; +} + +/* OQS_SIG_STFL_SECRET_KEY_lock */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_lock(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + if (sk->lock_key == NULL) { + return OQS_SUCCESS; + } + + // Try to lock the private key but the mutex is unset. + if (sk->mutex == NULL) { + return OQS_ERROR; + } + + return (sk->lock_key(sk->mutex)); +} + +/* OQS_SIG_STFL_SECRET_KEY_unlock */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + if (sk->unlock_key == NULL) { + return OQS_SUCCESS; + } + + // Try to unlock the private key but the mutex is unset. + if (sk->mutex == NULL) { + return OQS_ERROR; + } + + return (sk->unlock_key(sk->mutex)); +} diff --git a/src/sig_stfl/sig_stfl.h b/src/sig_stfl/sig_stfl.h new file mode 100644 index 0000000000..6154f47a64 --- /dev/null +++ b/src/sig_stfl/sig_stfl.h @@ -0,0 +1,660 @@ +/** + * \file sig_stfl.h + * \brief Stateful Signature schemes + * + * The file `tests/example_sig_stfl.c` contains an example on using the OQS_SIG_STFL API. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef OQS_SIG_STATEFUL_H +#define OQS_SIG_STATEFUL_H + +#include +#include +#include + +#include + +/* + * Developer's Notes: + * Stateful signatures are based on the one-time use of a secret key. A pool of secret keys is created for this purpose. + * The state of these keys is tracked to ensure that they are used only once to generate a signature. + * + * As such, product-specific environments do play a role in ensuring the safety of the keys. + * Secret keys must be stored securely. + * The key index/counter must be updated after each signature generation. + * The secret key must be protected in a thread-safe manner. + * + * Applications therefore are required to provide environment-specific callback functions to + * - store private key + * - lock/unlock private key + * + * See below for details + * OQS_SIG_STFL_SECRET_KEY_SET_lock + * OQS_SIG_STFL_SECRET_KEY_SET_unlock + * OQS_SIG_STFL_SECRET_KEY_SET_mutex + * OQS_SIG_STFL_SECRET_KEY_SET_store_cb + * + */ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Algorithm identifier for XMSS-SHA2_10_256 */ +#define OQS_SIG_STFL_alg_xmss_sha256_h10 "XMSS-SHA2_10_256" +#define OQS_SIG_STFL_alg_xmss_sha256_h16 "XMSS-SHA2_16_256" +#define OQS_SIG_STFL_alg_xmss_sha256_h20 "XMSS-SHA2_20_256" +#define OQS_SIG_STFL_alg_xmss_shake128_h10 "XMSS-SHAKE_10_256" +#define OQS_SIG_STFL_alg_xmss_shake128_h16 "XMSS-SHAKE_16_256" +#define OQS_SIG_STFL_alg_xmss_shake128_h20 "XMSS-SHAKE_20_256" +#define OQS_SIG_STFL_alg_xmss_sha512_h10 "XMSS-SHA2_10_512" +#define OQS_SIG_STFL_alg_xmss_sha512_h16 "XMSS-SHA2_16_512" +#define OQS_SIG_STFL_alg_xmss_sha512_h20 "XMSS-SHA2_20_512" +#define OQS_SIG_STFL_alg_xmss_shake256_h10 "XMSS-SHAKE_10_512" +#define OQS_SIG_STFL_alg_xmss_shake256_h16 "XMSS-SHAKE_16_512" +#define OQS_SIG_STFL_alg_xmss_shake256_h20 "XMSS-SHAKE_20_512" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_2 "XMSSMT-SHA2_20/2_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_4 "XMSSMT-SHA2_20/4_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_2 "XMSSMT-SHA2_40/2_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_4 "XMSSMT-SHA2_40/4_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_8 "XMSSMT-SHA2_40/8_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_3 "XMSSMT-SHA2_60/3_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_6 "XMSSMT-SHA2_60/6_256" +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_12 "XMSSMT-SHA2_60/12_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_2 "XMSSMT-SHAKE_20/2_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_4 "XMSSMT-SHAKE_20/4_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_2 "XMSSMT-SHAKE_40/2_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_4 "XMSSMT-SHAKE_40/4_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_8 "XMSSMT-SHAKE_40/8_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_3 "XMSSMT-SHAKE_60/3_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_6 "XMSSMT-SHAKE_60/6_256" +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_12 "XMSSMT-SHAKE_60/12_256" + +/* Defined LMS parameter identifiers */ +#define OQS_SIG_STFL_alg_lms_sha256_h5_w1 "LMS_SHA256_H5_W1" //"5/1" +#define OQS_SIG_STFL_alg_lms_sha256_h5_w2 "LMS_SHA256_H5_W2" //"5/2" +#define OQS_SIG_STFL_alg_lms_sha256_h5_w4 "LMS_SHA256_H5_W4" //"5/4" +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8 "LMS_SHA256_H5_W8" //"5/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w1 "LMS_SHA256_H10_W1" //"10/1" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2 "LMS_SHA256_H10_W2" //"10/2" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4 "LMS_SHA256_H10_W4" //"10/4" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8 "LMS_SHA256_H10_W8" //"10/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w1 "LMS_SHA256_H15_W1" //"15/1" +#define OQS_SIG_STFL_alg_lms_sha256_h15_w2 "LMS_SHA256_H15_W2" //"15/2" +#define OQS_SIG_STFL_alg_lms_sha256_h15_w4 "LMS_SHA256_H15_W4" //"15/4" +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8 "LMS_SHA256_H15_W8" //"15/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w1 "LMS_SHA256_H20_W1" //"20/1" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w2 "LMS_SHA256_H20_W2" //"20/2" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w4 "LMS_SHA256_H20_W4" //"20/4" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8 "LMS_SHA256_H20_W8" //"20/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h25_w1 "LMS_SHA256_H25_W1" //"25/1" +#define OQS_SIG_STFL_alg_lms_sha256_h25_w2 "LMS_SHA256_H25_W2" //"25/2" +#define OQS_SIG_STFL_alg_lms_sha256_h25_w4 "LMS_SHA256_H25_W4" //"25/4" +#define OQS_SIG_STFL_alg_lms_sha256_h25_w8 "LMS_SHA256_H25_W8" //"25/8" + +// 2-Level LMS +#define OQS_SIG_STFL_alg_lms_sha256_h5_w8_h5_w8 "LMS_SHA256_H5_W8_H5_W8" //"5/8, 5/8" + +// RFC 6554 +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_h5_w8 "LMS_SHA256_H10_W4_H5_W8" //"10/4, 5/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_h5_w8 "LMS_SHA256_H10_W8_H5_W8" //"10/8, 5/8" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w2_h10_w2 "LMS_SHA256_H10_W2_H10_W2" //"10/2, 10/2" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w4_h10_w4 "LMS_SHA256_H10_W4_H10_W4" //"10/4, 10/4" +#define OQS_SIG_STFL_alg_lms_sha256_h10_w8_h10_w8 "LMS_SHA256_H10_W8_H10_W8" //"10/8, 10/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h5_w8 "LMS_SHA256_H15_W8_H5_W8" //"15/8, 5/8" +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h10_w8 "LMS_SHA256_H15_W8_H10_W8" //"15/8, 10/8" +#define OQS_SIG_STFL_alg_lms_sha256_h15_w8_h15_w8 "LMS_SHA256_H15_W8_H15_W8" //"15/8, 15/8" + +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h5_w8 "LMS_SHA256_H20_W8_H5_W8" //"20/8, 5/8" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h10_w8 "LMS_SHA256_H20_W8_H10_W8" //"20/8, 10/8" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h15_w8 "LMS_SHA256_H20_W8_H15_W8" //"20/8, 15/8" +#define OQS_SIG_STFL_alg_lms_sha256_h20_w8_h20_w8 "LMS_SHA256_H20_W8_H20_W8" //"20/8, 20/8" + +/* + * Total number of stateful variants defined above, used to create the tracking array + */ +#define OQS_SIG_STFL_algs_length 61 + +typedef struct OQS_SIG_STFL_SECRET_KEY OQS_SIG_STFL_SECRET_KEY; + +/** + * Application provided function to securely store data + * @param[in] sk_buf pointer to the data to be saved + * @param[in] buf_len length of the data to be stored + * @param[out] context pass back application data related to secret key data storage. + * return OQS_SUCCESS if successful, otherwise OQS_ERROR + */ +typedef OQS_STATUS (*secure_store_sk)(uint8_t *sk_buf, size_t buf_len, void *context); + +/** + * Application provided function to lock secret key object serialize access + * @param[in] mutex pointer to mutex struct + * return OQS_SUCCESS if successful, otherwise OQS_ERROR + */ +typedef OQS_STATUS (*lock_key)(void *mutex); + +/** + * Application provided function to unlock secret key object + * @param[in] mutex pointer to mutex struct + * return OQS_SUCCESS if successful, otherwise OQS_ERROR + */ +typedef OQS_STATUS (*unlock_key)(void *mutex); + +/** + * Returns identifiers for available signature schemes in liboqs. Used with `OQS_SIG_STFL_new`. + * + * Note that algorithm identifiers are present in this list even when the algorithm is disabled + * at compile time. + * + * @param[in] i Index of the algorithm identifier to return, 0 <= i < OQS_SIG_algs_length + * @return Algorithm identifier as a string, or NULL. + */ +OQS_API const char *OQS_SIG_STFL_alg_identifier(size_t i); + +/** + * Returns the number of stateful signature mechanisms in liboqs. They can be enumerated with + * OQS_SIG_STFL_alg_identifier. + * + * Note that some mechanisms may be disabled at compile time. + * + * @return The number of stateful signature mechanisms. + */ +OQS_API int OQS_SIG_STFL_alg_count(void); + +/** + * Indicates whether the specified algorithm was enabled at compile-time or not. + * + * @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_STFL_algs`. + * @return 1 if enabled, 0 if disabled or not found + */ +OQS_API int OQS_SIG_STFL_alg_is_enabled(const char *method_name); + +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN +#define OQS_SIG_STFL OQS_SIG +#else +/** + * Stateful signature scheme object + */ +typedef struct OQS_SIG_STFL { + + /** + * A local ordinal representing the LMS/XMSS OID parameter of the signature scheme. + * This OID is unrelated to ASN.1 OID, it's only for LMS/XMSS internal usage. + */ + uint32_t oid; + + /** Printable string representing the name of the signature scheme. */ + const char *method_name; + + /** + * Printable string representing the version of the cryptographic algorithm. + * + * Implementations with the same method_name and same alg_version will be interoperable. + * See README.md for information about algorithm compatibility. + */ + const char *alg_version; + + /** Whether the signature offers EUF-CMA security (TRUE) or not (FALSE). */ + bool euf_cma; + + /** The (maximum) length, in bytes, of public keys for this signature scheme. */ + size_t length_public_key; + /** The (maximum) length, in bytes, of secret keys for this signature scheme. */ + size_t length_secret_key; + /** The (maximum) length, in bytes, of signatures for this signature scheme. */ + size_t length_signature; + + /** + * Keypair generation algorithm. + * + * Caller is responsible for allocating sufficient memory for `public_key` + * based on the `length_*` members in this object or the per-scheme + * compile-time macros `OQS_SIG_STFL_*_length_*`. + * + * @param[out] public_key The public key is represented as a byte string. + * @param[out] secret_key The secret key object + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*keypair)(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + + /** + * Signature generation algorithm. + * + * For stateful signatures, there is always a limited number of signatures that can be used, + * The private key signature counter is increased by one once a signature is successfully generated, + * When the signature counter reaches the maximum number of available signatures, the signature generation always fails. + * + * Caller is responsible for allocating sufficient memory for `signature`, + * based on the `length_*` members in this object or the per-scheme + * compile-time macros `OQS_SIG_STFL_*_length_*`. + * + * @param[out] signature The signature on the message is represented as a byte string. + * @param[out] signature_len The length of the signature. + * @param[in] message The message to sign is represented as a byte string. + * @param[in] message_len The length of the message to sign. + * @param[in] secret_key The secret key object pointer. + * @return OQS_SUCCESS or OQS_ERROR + * + * @note Internally, if `lock/unlock` functions and `mutex` are set, it will attempt to lock the private key and unlock + * the private key after the Signing operation is completed. + */ + OQS_STATUS (*sign)(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); + + /** + * Signature verification algorithm. + * + * @param[in] message The message is represented as a byte string. + * @param[in] message_len The length of the message. + * @param[in] signature The signature on the message is represented as a byte string. + * @param[in] signature_len The length of the signature. + * @param[in] public_key The public key is represented as a byte string. + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*verify)(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); + + /** + * Query the number of remaining signatures. + * + * The remaining signatures are the number of signatures available before the private key runs out of its total signature and expires. + * + * @param[out] remain The number of remaining signatures + * @param[in] secret_key The secret key object pointer. + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*sigs_remaining)(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); + + /** + * Query the total number of signatures. + * + * The total number of signatures is the constant number present in how many signatures can be generated from a private key. + * + * @param[out] total The total number of signatures + * @param[in] secret_key The secret key key object pointer. + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*sigs_total)(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +} OQS_SIG_STFL; +#endif //OQS_ALLOW_STFL_KEY_AND_SIG_GEN + +/** + * @brief OQS_SIG_STFL_SECRET_KEY object for stateful signature schemes + */ + +typedef struct OQS_SIG_STFL_SECRET_KEY { + + /* The (maximum) length, in bytes, of secret keys for this signature scheme. */ + size_t length_secret_key; + + /* The variant-specific secret key data must be allocated at the initialization. */ + void *secret_key_data; + + /* The mutual exclusion struct */ + void *mutex; + + /* Application-managed data related to secure storage of secret key data */ + void *context; + + /** + * Serialize the stateful secret key. + * + * This function encodes the stateful secret key represented by `sk` into a byte stream + * for storage or transfer. The `sk_buf_ptr` will point to the allocated memory containing + * the byte stream. Users must free the `sk_buf_ptr` using `OQS_MEM_secure_free` after use. + * The `sk_len` will contain the length of the byte stream. + * + * @param[out] sk_buf_ptr Pointer to the byte stream representing the serialized secret key. + * @param[out] sk_buf_len Pointer to the length of the serialized byte stream. + * @param[in] sk Pointer to the `OQS_SIG_STFL_SECRET_KEY` object to serialize. + * @return The number of bytes in the serialized byte stream upon success, or an OQS error code on failure. + * + * @attention The caller is responsible for ensuring that `sk` is a valid object before calling this function. + */ + OQS_STATUS (*serialize_key)(uint8_t **sk_buf_ptr, size_t *sk_buf_len, const OQS_SIG_STFL_SECRET_KEY *sk); + + /** + * Deserialize a byte stream into the internal representation of a stateful secret key. + * + * This function takes a series of bytes representing a stateful secret key and initializes + * the internal `OQS_SIG_STFL_SECRET_KEY` object with the key material. This is particularly + * useful for reconstructing key objects from persisted or transmitted state. + * + * @param[out] sk Pointer to an uninitialized `OQS_SIG_STFL_SECRET_KEY` object to hold the secret key. + * @param[in] sk_buf Pointer to the byte stream containing the serialized secret key data. + * @param[in] sk_buf_len The length of the secret key byte stream. + * @param[in] context Pointer to application-specific data, handled externally, associated with the key. + * @returns OQS_SUCCESS if the deserialization succeeds, with the `sk` object populated with the key material. + * + * @attention The caller is responsible for ensuring that `sk_buf` is securely deallocated when it's no longer needed. + */ + OQS_STATUS (*deserialize_key)(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_buf_len, void *context); + + /** + * Secret Key Locking Function + * + * @param[in] mutex application defined mutex + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*lock_key)(void *mutex); + + /** + * Secret Key Unlocking / Releasing Function + * + * @param[in] mutex application defined mutex + * @return OQS_SUCCESS or OQS_ERROR + */ + OQS_STATUS (*unlock_key)(void *mutex); + + /** + * Store Secret Key Function + * + * Callback function used to securely store key data after a signature generation. + * When populated, this pointer points to the application-supplied secure storage function. + * @param[in] sk_buf The serialized secret key data to secure store + * @param[in] sk_buf_len length of data to secure + * @param[in] context application supplied data used to locate where this secret key + * is stored (passed in at the time the function pointer was set). + * + * @return OQS_SUCCESS or OQS_ERROR + * Ideally written to a secure device. + */ + OQS_STATUS (*secure_store_scrt_key)(uint8_t *sk_buf, size_t sk_buf_len, void *context); + + /** + * Free internal variant-specific data + * + * @param[in] sk The secret key represented as OQS_SIG_STFL_SECRET_KEY object. + * @return None. + */ + void (*free_key)(OQS_SIG_STFL_SECRET_KEY *sk); + + /** + * Set Secret Key Store Callback Function + * + * This function is used to establish a callback mechanism for secure storage + * of private keys involved in stateful signature Signing operation. The secure storage + * and the management of private keys is the responsibility of the adopting application. + * Therefore, before invoking stateful signature generation, a callback function and + * associated context data must be provided by the application to manage the storage. + * + * The `context` argument is designed to hold information requisite for private key storage, + * such as a hardware security module (HSM) context, a file path, or other relevant data. + * This context is passed to the libOQS when the callback function is registered. + * + * @param[in] sk A pointer to the secret key object that requires secure storage management + * after signature Signing operations. + * @param[in] store_cb A pointer to the callback function provided by the application + * for storing and updating the private key securely. + * @param[in] context Application-specific context information for the private key storage, + * furnished when setting the callback function via + * OQS_SIG_STFL_SECRET_KEY_set_store_cb(). + * @return None. + */ + void (*set_scrt_key_store_cb)(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context); +} OQS_SIG_STFL_SECRET_KEY; + +/** + * Constructs an OQS_SIG_STFL object for a particular algorithm. + * + * Callers should always check whether the return value is `NULL`, which indicates either than an + * invalid algorithm name was provided, or that the requested algorithm was disabled at compile-time. + * + * @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_STFL_algs`. + * @return An OQS_SIG_STFL for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time. + */ +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_new(const char *method_name); + +/** + * Keypair generation algorithm. + * + * Caller is responsible for allocating sufficient memory for `public_key` based + * on the `length_*` members in this object or the per-scheme compile-time macros + * `OQS_SIG_STFL_*_length_*`. The caller is also responsible for initializing + * `secret_key` using the OQS_SIG_STFL_SECRET_KEY(*) function. + * + * @param[in] sig The OQS_SIG_STFL object representing the signature scheme. + * @param[out] public_key The public key is represented as a byte string. + * @param[out] secret_key The secret key object pointer. + * @return OQS_SUCCESS or OQS_ERROR + */ +OQS_API OQS_STATUS OQS_SIG_STFL_keypair(const OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); + +/** + * Signature generation algorithm. + * + * For stateful signatures, there is always a limited number of signatures that can be used, + * The private key signature counter is increased by one once a signature is successfully generated, + * When the signature counter reaches the maximum number of available signatures, the signature generation always fails. + * + * Caller is responsible for allocating sufficient memory for `signature`, + * based on the `length_*` members in this object or the per-scheme + * compile-time macros `OQS_SIG_STFL_*_length_*`. + * + * @param[in] sig The OQS_SIG_STFL object representing the signature scheme. + * @param[out] signature The signature on the message is represented as a byte string. + * @param[out] signature_len The length of the signature. + * @param[in] message The message to sign is represented as a byte string. + * @param[in] message_len The length of the message to sign. + * @param[in] secret_key The secret key object pointer. + * @return OQS_SUCCESS or OQS_ERROR + * + * @note Internally, if `lock/unlock` functions and `mutex` are set, it will attempt to lock the private key and unlock + * the private key after the Signing operation is completed. + */ +OQS_API OQS_STATUS OQS_SIG_STFL_sign(const OQS_SIG_STFL *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); + +/** + * Signature verification algorithm. + * + * @param[in] sig The OQS_SIG_STFL object representing the signature scheme. + * @param[in] message The message is represented as a byte string. + * @param[in] message_len The length of the message. + * @param[in] signature The signature on the message is represented as a byte string. + * @param[in] signature_len The length of the signature. + * @param[in] public_key The public key is represented as a byte string. + * @return OQS_SUCCESS or OQS_ERROR + */ +OQS_API OQS_STATUS OQS_SIG_STFL_verify(const OQS_SIG_STFL *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); + +/** + * Query the number of remaining signatures. + * + * The remaining signatures are the number of signatures available before the private key runs out of its total signature and expires. + * + * @param[in] sig The OQS_SIG_STFL object representing the signature scheme. + * @param[in] secret_key The secret key object. + * @return OQS_SUCCESS or OQS_ERROR + */ +OQS_API OQS_STATUS OQS_SIG_STFL_sigs_remaining(const OQS_SIG_STFL *sig, unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +/** + * Query the total number of signatures. + * + * The total number of signatures is the constant number present in how many signatures can be generated from a private key. + * + * @param[in] sig The OQS_SIG_STFL object representing the signature scheme. + * @param[out] max The number of remaining signatures + * @param[in] secret_key The secret key object. + * @return OQS_SUCCESS or OQS_ERROR + */ +OQS_API OQS_STATUS OQS_SIG_STFL_sigs_total(const OQS_SIG_STFL *sig, unsigned long long *max, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +/** + * Free an OQS_SIG_STFL object that was constructed by OQS_SIG_STFL_new. + * + */ +OQS_API void OQS_SIG_STFL_free(OQS_SIG_STFL *sig); + +/** + * Construct an OQS_SIG_STFL_SECRET_KEY object for a particular algorithm. + * + * Callers should always check whether the return value is `NULL`, which indicates either than an + * invalid algorithm name was provided, or that the requested algorithm was disabled at compile-time. + * + * @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_STFL_algs`. + * @return An OQS_SIG_STFL_SECRET_KEY for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time. + */ +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SIG_STFL_SECRET_KEY_new(const char *method_name); + +/** + * Free an OQS_SIG_STFL_SECRET_KEY object that was constructed by OQS_SECRET_KEY_new. + * + * @param[in] sig The OQS_SIG_STFL_SECRET_KEY object to free. + * @return OQS_SUCCESS if successful, or OQS_ERROR if the object cannot be freed. + */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_free(OQS_SIG_STFL_SECRET_KEY *sk); + +/** + * Attach a locking mechanism to a secret key object. + * + * This allows for proper synchronization in a multi-threaded or multi-process environment, + * by ensuring that a secret key is not used concurrently by multiple entities, which could otherwise lead to security issues. + * + * @param[in] sk Pointer to the secret key object whose lock function is to be set. + * @param[in] lock Function pointer to the locking routine provided by the application. + * @return None. + * + * @note It's not required to set the lock and unlock functions in a single-threaded environment. + * + * @note Once the `lock` function is set, users must also set the `mutex` and `unlock` functions. + * + * @note By default, the internal value of `sk->lock` is NULL, which does nothing to lock the private key. + */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_lock(OQS_SIG_STFL_SECRET_KEY *sk, lock_key lock); + +/** + * Attach an unlock mechanism to a secret key object. + * + * This allows for proper synchronization in a multi-threaded or multi-process environment, + * by ensuring that a secret key is not used concurrently by multiple entities, which could otherwise lead to security issues. + * + * @param[in] sk Pointer to the secret key object whose unlock function is to be set. + * @param[in] unlock Function pointer to the unlock routine provided by the application. + * @return None. + * + * @note It's not required to set the lock and unlock functions in a single-threaded environment. + * + * @note Once the `unlock` function is set, users must also set the `mutex` and `lock` functions. + * + * @note By default, the internal value of `sk->unlock` is NULL, which does nothing to unlock the private key. + */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_unlock(OQS_SIG_STFL_SECRET_KEY *sk, unlock_key unlock); + +/** + * Assign a mutex function to handle concurrency control over the secret key. + * + * This is to ensure that only one process can access or modify the key at any given time. + * + * @param[in] sk A pointer to the secret key that the mutex functionality will protect. + * @param[in] mutex A function pointer to the desired concurrency control mechanism. + * @return None. + * + * @note It's not required to set the lock and unlock functions in a single-threaded environment. + * + * @note By default, the internal value of `sk->mutex` is NULL, it must be set to be used in `lock` or `unlock` the private key. + */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_mutex(OQS_SIG_STFL_SECRET_KEY *sk, void *mutex); + +/** + * Lock the secret key to ensure exclusive access in a concurrent environment. + * + * If the `mutex` is not set, this lock operation will fail. + * This lock operation is essential in multi-threaded or multi-process contexts + * to prevent simultaneous Signing operations that could compromise the stateful signature security. + * + * @warning If the `lock` function is set and `mutex` is not set, this lock operation will fail. + * + * @param[in] sk Pointer to the secret key to be locked. + * @return OQS_SUCCESS if the lock is successfully applied; OQS_ERROR otherwise. + * + * @note It's not necessary to use this function in either Keygen or Verifying operations. + * In a concurrent environment, the user is responsible for locking and unlocking the private key, + * to make sure that only one thread can access the private key during a Signing operation. + * + * @note If the `lock` function and `mutex` are both set, proceed to lock the private key. + */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_lock(OQS_SIG_STFL_SECRET_KEY *sk); + +/** + * Unlock the secret key, making it accessible to other processes. + * + * This function is crucial in environments where multiple processes need to coordinate access to + * the secret key, as it allows a process to signal that it has finished using the key, so + * others can safely use it. + * + * @warning If the `unlock` function is set and `mutex` is not set, this unlock operation will fail. + * + * @param[in] sk Pointer to the secret key whose lock should be released. + * @return OQS_SUCCESS if the lock was successfully released; otherwise, OQS_ERROR. + * + * @note It's not necessary to use this function in either Keygen or Verifying operations. + * In a concurrent environment, the user is responsible for locking and unlocking the private key, + * to make sure that only one thread can access the private key during a Signing operation. + * + * @note If the `unlock` function and `mutex` are both set, proceed to unlock the private key. + */ +OQS_STATUS OQS_SIG_STFL_SECRET_KEY_unlock(OQS_SIG_STFL_SECRET_KEY *sk); + +/** + * Set the callback and context for securely storing a stateful secret key. + * + * This function is designed to be called after a new stateful secret key + * has been generated. It enables the library to securely store secret key + * and update it every time a Signing operation occurs. + * Without properly setting this callback and context, signature generation + * will not succeed as the updated state of the secret key cannot be preserved. + * + * @param[in] sk Pointer to the stateful secret key to be managed. + * @param[in] store_cb Callback function that handles the secure storage of the key. + * @param[in] context Application-specific context that assists in the storage of secret key data. + * This context is managed by the application, which allocates it, keeps track of it, + * and deallocates it as necessary. + * @return None. + */ +OQS_API void OQS_SIG_STFL_SECRET_KEY_SET_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context); + +/** + * Serialize the stateful secret key data into a byte array. + * + * Converts an OQS_SIG_STFL_SECRET_KEY object into a byte array for storage or transmission. + * + * @param[out] sk_buf_ptr Pointer to the allocated byte array containing the serialized key. + * @param[out] sk_buf_len Length of the serialized key byte array. + * @param[in] sk Pointer to the OQS_SIG_STFL_SECRET_KEY object to be serialized. + * @return OQS_SUCCESS on success, or an OQS error code on failure. + * + * @note The function allocates memory for the byte array, and it is the caller's responsibility to free this memory after use. + */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_serialize(uint8_t **sk_buf_ptr, size_t *sk_buf_len, const OQS_SIG_STFL_SECRET_KEY *sk); + +/** + * Deserialize a byte array into an OQS_SIG_STFL_SECRET_KEY object. + * + * Transforms a binary representation of a secret key into an OQS_SIG_STFL_SECRET_KEY structure. + * After deserialization, the secret key object can be used for subsequent cryptographic operations. + * + * @param[out] sk A pointer to the secret key object that will be populated from the binary data. + * @param[in] sk_buf The buffer containing the serialized secret key data. + * @param[in] sk_buf_len The length of the binary secret key data in bytes. + * @param[in] context Application-specific data used to maintain context about the secret key. + * @return OQS_SUCCESS if deserialization was successful; otherwise, OQS_ERROR. + * + * @attention The caller is responsible for freeing the `sk_buf` memory when it is no longer needed. + */ +OQS_API OQS_STATUS OQS_SIG_STFL_SECRET_KEY_deserialize(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, size_t sk_buf_len, void *context); + +#if defined(__cplusplus) +// extern "C" +} +#endif + +#endif /* OQS_SIG_STATEFUL_H */ diff --git a/src/sig_stfl/xmss/CMakeLists.txt b/src/sig_stfl/xmss/CMakeLists.txt new file mode 100644 index 0000000000..f9fc4fc08d --- /dev/null +++ b/src/sig_stfl/xmss/CMakeLists.txt @@ -0,0 +1,187 @@ +# SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +set(_XMSS_OBJS "") + +set(SRCS external/core_hash.c + external/hash.c + external/hash_address.c + external/params.c + external/utils.c + external/wots.c + external/xmss.c + external/xmss_commons.c + external/xmss_core_fast.c +) + +add_library(sig_stfl_xmss_secret_key_functions OBJECT sig_stfl_xmss_secret_key_functions.c) +set(_XMSS_OBJS ${_XMSS_OBJS} $) + +if (OQS_ENABLE_SIG_STFL_xmss_sha256_h10) + add_library(xmss_sha256_h10 OBJECT sig_stfl_xmss_sha256_h10.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha256_h10 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha256_h10 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_sha256_h16) + add_library(xmss_sha256_h16 OBJECT sig_stfl_xmss_sha256_h16.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha256_h16 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha256_h16 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_sha256_h20) + add_library(xmss_sha256_h20 OBJECT sig_stfl_xmss_sha256_h20.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha256_h20 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha256_h20 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake128_h10) + add_library(xmss_shake128_h10 OBJECT sig_stfl_xmss_shake128_h10.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake128_h10 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake128_h10 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake128_h16) + add_library(xmss_shake128_h16 OBJECT sig_stfl_xmss_shake128_h16.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake128_h16 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake128_h16 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake128_h20) + add_library(xmss_shake128_h20 OBJECT sig_stfl_xmss_shake128_h20.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake128_h20 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake128_h20 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_sha512_h10) + add_library(xmss_sha512_h10 OBJECT sig_stfl_xmss_sha512_h10.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha512_h10 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha512_h10 -DHASH=6) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_sha512_h16) + add_library(xmss_sha512_h16 OBJECT sig_stfl_xmss_sha512_h16.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha512_h16 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha512_h16 -DHASH=6) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_sha512_h20) + add_library(xmss_sha512_h20 OBJECT sig_stfl_xmss_sha512_h20.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_sha512_h20 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_sha512_h20 -DHASH=6) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake256_h10) + add_library(xmss_shake256_h10 OBJECT sig_stfl_xmss_shake256_h10.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake256_h10 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake256_h10 -DHASH=7) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake256_h16) + add_library(xmss_shake256_h16 OBJECT sig_stfl_xmss_shake256_h16.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake256_h16 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake256_h16 -DHASH=7) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmss_shake256_h20) + add_library(xmss_shake256_h20 OBJECT sig_stfl_xmss_shake256_h20.c sig_stfl_xmss_functions.c ${SRCS}) + target_compile_options(xmss_shake256_h20 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmss_shake256_h20 -DHASH=7) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2) + add_library(xmssmt_sha256_h20_2 OBJECT sig_stfl_xmssmt_sha256_h20_2.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h20_2 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h20_2 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4) + add_library(xmssmt_sha256_h20_4 OBJECT sig_stfl_xmssmt_sha256_h20_4.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h20_4 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h20_4 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2) + add_library(xmssmt_sha256_h40_2 OBJECT sig_stfl_xmssmt_sha256_h40_2.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h40_2 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h40_2 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4) + add_library(xmssmt_sha256_h40_4 OBJECT sig_stfl_xmssmt_sha256_h40_4.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h40_4 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h40_4 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8) + add_library(xmssmt_sha256_h40_8 OBJECT sig_stfl_xmssmt_sha256_h40_8.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h40_8 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h40_8 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3) + add_library(xmssmt_sha256_h60_3 OBJECT sig_stfl_xmssmt_sha256_h60_3.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h60_3 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h60_3 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6) + add_library(xmssmt_sha256_h60_6 OBJECT sig_stfl_xmssmt_sha256_h60_6.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h60_6 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h60_6 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12) + add_library(xmssmt_sha256_h60_12 OBJECT sig_stfl_xmssmt_sha256_h60_12.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_sha256_h60_12 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_sha256_h60_12 -DHASH=3) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2) + add_library(xmssmt_shake128_h20_2 OBJECT sig_stfl_xmssmt_shake128_h20_2.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h20_2 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h20_2 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4) + add_library(xmssmt_shake128_h20_4 OBJECT sig_stfl_xmssmt_shake128_h20_4.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h20_4 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h20_4 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2) + add_library(xmssmt_shake128_h40_2 OBJECT sig_stfl_xmssmt_shake128_h40_2.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h40_2 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h40_2 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4) + add_library(xmssmt_shake128_h40_4 OBJECT sig_stfl_xmssmt_shake128_h40_4.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h40_4 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h40_4 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8) + add_library(xmssmt_shake128_h40_8 OBJECT sig_stfl_xmssmt_shake128_h40_8.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h40_8 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h40_8 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3) + add_library(xmssmt_shake128_h60_3 OBJECT sig_stfl_xmssmt_shake128_h60_3.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h60_3 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h60_3 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6) + add_library(xmssmt_shake128_h60_6 OBJECT sig_stfl_xmssmt_shake128_h60_6.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h60_6 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h60_6 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +if (OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12) + add_library(xmssmt_shake128_h60_12 OBJECT sig_stfl_xmssmt_shake128_h60_12.c sig_stfl_xmssmt_functions.c ${SRCS}) + target_compile_options(xmssmt_shake128_h60_12 PRIVATE -DXMSS_PARAMS_NAMESPACE=xmssmt_shake128_h60_12 -DHASH=4) + set(_XMSS_OBJS ${_XMSS_OBJS} $) +endif() + +set(XMSS_OBJS ${_XMSS_OBJS} PARENT_SCOPE) diff --git a/src/sig_stfl/xmss/LICENSE b/src/sig_stfl/xmss/LICENSE new file mode 100644 index 0000000000..6fc799ea78 --- /dev/null +++ b/src/sig_stfl/xmss/LICENSE @@ -0,0 +1,22 @@ +## License + +This XMSS reference implementation is Copyright (c) 2024 SandboxAQ and licensed under the CC0-1.0 AND ([Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt) OR MIT License) at your option. + +--------------------------------- +The MIT License (MIT) + +Copyright © 2024 SandboxAQ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------- + +This XMSS reference implementation is based on the [XMSS reference implementation written by Andreas Hülsing and Joost Rijneveld](https://github.com/XMSS/xmss-reference#license) provided under the CC0 1.0 Universal Public Domain Dedication. + + +## Disclaimer + +The software and documentation are provided "as is" and SandboxAQ hereby disclaims all warranties, whether express, implied, statutory, or otherwise. SandboxAQ specifically disclaims, without limitation, all implied warranties of merchantability, fitness for a particular purpose, title, and non-infringement, and all warranties arising from course of dealing, usage, or trade practice. SandboxAQ makes no warranty of any kind that the software and documentation, or any products or results of the use thereof, will meet any person's requirements, operate without interruption, achieve any intended result, be compatible or work with any software, system or other services, or be secure, accurate, complete, free of harmful code, or error-free. \ No newline at end of file diff --git a/src/sig_stfl/xmss/external/core_hash.c b/src/sig_stfl/xmss/external/core_hash.c new file mode 100644 index 0000000000..7c80f3f860 --- /dev/null +++ b/src/sig_stfl/xmss/external/core_hash.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include +#include "core_hash.h" +#include + +int core_hash(const xmss_params *params, + unsigned char *out, + const unsigned char *in, unsigned long long inlen) { + + (void)params; +#if HASH == XMSS_CORE_HASH_SHA256_N24 + unsigned char buf[32]; + OQS_SHA2_sha256(buf, in, inlen); + memcpy(out, buf, 24); + +#elif HASH == XMSS_CORE_HASH_SHAKE256_N24 + OQS_SHA3_shake256(out, 24, in, inlen); + +#elif HASH == XMSS_CORE_HASH_SHA256_N32 + OQS_SHA2_sha256(out, in, inlen); + +#elif HASH == XMSS_CORE_HASH_SHAKE128_N32 + OQS_SHA3_shake128(out, 32, in, inlen); + +#elif HASH == XMSS_CORE_HASH_SHAKE256_N32 + OQS_SHA3_shake256(out, 32, in, inlen); + +#elif HASH == XMSS_CORE_HASH_SHA512_N64 + OQS_SHA2_sha512(out, in, inlen); + +#elif HASH == XMSS_CORE_HASH_SHAKE256_N64 + OQS_SHA3_shake256(out, 64, in, inlen); +#else + return -1; +#endif + + return 0; +} diff --git a/src/sig_stfl/xmss/external/core_hash.h b/src/sig_stfl/xmss/external/core_hash.h new file mode 100644 index 0000000000..dbbeecca83 --- /dev/null +++ b/src/sig_stfl/xmss/external/core_hash.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef CORE_HASH +#define CORE_HASH + +#include "namespace.h" +#include "params.h" + +// N = 24 +#define XMSS_CORE_HASH_SHA256_N24 1 +#define XMSS_CORE_HASH_SHAKE256_N24 2 +// N = 32 +#define XMSS_CORE_HASH_SHA256_N32 3 +#define XMSS_CORE_HASH_SHAKE128_N32 4 +#define XMSS_CORE_HASH_SHAKE256_N32 5 +// N = 64 +#define XMSS_CORE_HASH_SHA512_N64 6 +#define XMSS_CORE_HASH_SHAKE256_N64 7 + +#define core_hash XMSS_PARAMS_INNER_CORE_HASH(core_hash) +int core_hash(const xmss_params *params, + unsigned char *out, + const unsigned char *in, unsigned long long inlen); + +#endif diff --git a/src/sig_stfl/xmss/external/hash.c b/src/sig_stfl/xmss/external/hash.c new file mode 100644 index 0000000000..6330c5871a --- /dev/null +++ b/src/sig_stfl/xmss/external/hash.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include + +#include +#include + +#include "hash_address.h" +#include "utils.h" +#include "params.h" +#include "hash.h" + +#define XMSS_HASH_PADDING_F 0 +#define XMSS_HASH_PADDING_H 1 +#define XMSS_HASH_PADDING_HASH 2 +#define XMSS_HASH_PADDING_PRF 3 +#define XMSS_HASH_PADDING_PRF_KEYGEN 4 + +void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]) +{ + int i; + for (i = 0; i < 8; i++) { + ull_to_bytes(bytes + i*4, 4, addr[i]); + } +} + +/* + * Computes PRF(key, in), for a key of params->n bytes, and a 32-byte input. + */ +int prf(const xmss_params *params, + unsigned char *out, const unsigned char in[32], + const unsigned char *key, + unsigned char *buf) +{ + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF); + memcpy(buf + params->padding_len, key, params->n); + memcpy(buf + params->padding_len + params->n, in, 32); + + int ret = core_hash(params, out, buf, params->padding_len + params->n + 32); + + + return ret; +} + +/* + * Computes PRF_keygen(key, in), for a key of params->n bytes, and an input + * of 32 + params->n bytes + */ +int prf_keygen(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *key, + unsigned char *buf) +{ + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF_KEYGEN); + memcpy(buf + params->padding_len, key, params->n); + memcpy(buf + params->padding_len + params->n, in, params->n + 32); + + int ret = core_hash(params, out, buf, params->padding_len + 2*params->n + 32); + + return ret; +} + +/* + * Computes the message hash using R, the public root, the index of the leaf + * node, and the message. Notably, it requires m_with_prefix to have 3*n plus + * the length of the padding as free space available before the message, + * to use for the prefix. This is necessary to prevent having to move the + * message around (and thus allocate memory for it). + */ +int hash_message(const xmss_params *params, unsigned char *out, + const unsigned char *R, const unsigned char *root, + unsigned long long idx, + unsigned char *m_with_prefix, unsigned long long mlen) +{ + /* We're creating a hash using input of the form: + toByte(X, 32) || R || root || index || M */ + ull_to_bytes(m_with_prefix, params->padding_len, XMSS_HASH_PADDING_HASH); + memcpy(m_with_prefix + params->padding_len, R, params->n); + memcpy(m_with_prefix + params->padding_len + params->n, root, params->n); + ull_to_bytes(m_with_prefix + params->padding_len + 2*params->n, params->n, idx); + + return core_hash(params, out, m_with_prefix, mlen + params->padding_len + 3*params->n); +} + +/** + * We assume the left half is in in[0]...in[n-1] + */ +int thash_h(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buf) +{ + unsigned char *bitmask = buf + (params->padding_len + 3 * params->n); + unsigned char *prf_buf = bitmask + 2*params->n; + + unsigned char addr_as_bytes[32]; + unsigned int i; + + /* Set the function padding. */ + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_H); + + /* Generate the n-byte key. */ + set_key_and_mask(addr, 0); + addr_to_bytes(addr_as_bytes, addr); + prf(params, buf + params->padding_len, addr_as_bytes, pub_seed, prf_buf); + + /* Generate the 2n-byte mask. */ + set_key_and_mask(addr, 1); + addr_to_bytes(addr_as_bytes, addr); + prf(params, bitmask, addr_as_bytes, pub_seed, prf_buf); + + set_key_and_mask(addr, 2); + addr_to_bytes(addr_as_bytes, addr); + prf(params, bitmask + params->n, addr_as_bytes, pub_seed, prf_buf); + + for (i = 0; i < 2 * params->n; i++) { + buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i]; + } + int ret = core_hash(params, out, buf, params->padding_len + 3 * params->n); + + return ret; +} + +int thash_f(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buf) +{ + unsigned char *bitmask = buf + (params->padding_len + 2 * params->n); + unsigned char *prf_buf = bitmask + params->n; + + unsigned char addr_as_bytes[32]; + unsigned int i; + + /* Set the function padding. */ + ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_F); + + /* Generate the n-byte key. */ + set_key_and_mask(addr, 0); + addr_to_bytes(addr_as_bytes, addr); + prf(params, buf + params->padding_len, addr_as_bytes, pub_seed, prf_buf); + + /* Generate the n-byte mask. */ + set_key_and_mask(addr, 1); + addr_to_bytes(addr_as_bytes, addr); + prf(params, bitmask, addr_as_bytes, pub_seed, prf_buf); + + for (i = 0; i < params->n; i++) { + buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i]; + } + int ret = core_hash(params, out, buf, params->padding_len + 2 * params->n); + + return ret; +} diff --git a/src/sig_stfl/xmss/external/hash.h b/src/sig_stfl/xmss/external/hash.h new file mode 100644 index 0000000000..e0b06eba98 --- /dev/null +++ b/src/sig_stfl/xmss/external/hash.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_HASH_H +#define XMSS_HASH_H + +#include +#include "params.h" +#include "core_hash.h" + +#define addr_to_bytes XMSS_INNER_NAMESPACE(addr_to_bytes) +void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]); + +#define prf XMSS_INNER_NAMESPACE(prf) +int prf(const xmss_params *params, + unsigned char *out, const unsigned char in[32], + const unsigned char *key, + unsigned char *buf); + +#define prf_keygen XMSS_INNER_NAMESPACE(prf_keygen) +int prf_keygen(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *key, + unsigned char *buf); + +#define h_msg XMSS_INNER_NAMESPACE(h_msg) +int h_msg(const xmss_params *params, + unsigned char *out, + const unsigned char *in, unsigned long long inlen, + const unsigned char *key, const unsigned int keylen); + +#define thash_h XMSS_INNER_NAMESPACE(thash_h) +int thash_h(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buf); + +#define thash_f XMSS_INNER_NAMESPACE(thash_f) +int thash_f(const xmss_params *params, + unsigned char *out, const unsigned char *in, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buf); + +#define hash_message XMSS_INNER_NAMESPACE(hash_message) +int hash_message(const xmss_params *params, unsigned char *out, + const unsigned char *R, const unsigned char *root, + unsigned long long idx, + unsigned char *m_with_prefix, unsigned long long mlen); + +#endif diff --git a/src/sig_stfl/xmss/external/hash_address.c b/src/sig_stfl/xmss/external/hash_address.c new file mode 100644 index 0000000000..eaa5ff6fc9 --- /dev/null +++ b/src/sig_stfl/xmss/external/hash_address.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include "hash_address.h" + +void set_layer_addr(uint32_t addr[8], uint32_t layer) +{ + addr[0] = layer; +} + +void set_tree_addr(uint32_t addr[8], uint64_t tree) +{ + addr[1] = (uint32_t) (tree >> 32); + addr[2] = (uint32_t) tree; +} + +void set_type(uint32_t addr[8], uint32_t type) +{ + addr[3] = type; +} + +void set_key_and_mask(uint32_t addr[8], uint32_t key_and_mask) +{ + addr[7] = key_and_mask; +} + +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +/* These functions are used for OTS addresses. */ + +void set_ots_addr(uint32_t addr[8], uint32_t ots) +{ + addr[4] = ots; +} + +void set_chain_addr(uint32_t addr[8], uint32_t chain) +{ + addr[5] = chain; +} + +void set_hash_addr(uint32_t addr[8], uint32_t hash) +{ + addr[6] = hash; +} + +/* This function is used for L-tree addresses. */ + +void set_ltree_addr(uint32_t addr[8], uint32_t ltree) +{ + addr[4] = ltree; +} + +/* These functions are used for hash tree addresses. */ + +void set_tree_height(uint32_t addr[8], uint32_t tree_height) +{ + addr[5] = tree_height; +} + +void set_tree_index(uint32_t addr[8], uint32_t tree_index) +{ + addr[6] = tree_index; +} diff --git a/src/sig_stfl/xmss/external/hash_address.h b/src/sig_stfl/xmss/external/hash_address.h new file mode 100644 index 0000000000..3929558546 --- /dev/null +++ b/src/sig_stfl/xmss/external/hash_address.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_HASH_ADDRESS_H +#define XMSS_HASH_ADDRESS_H + +#include +#include "namespace.h" + +#define XMSS_ADDR_TYPE_OTS 0 +#define XMSS_ADDR_TYPE_LTREE 1 +#define XMSS_ADDR_TYPE_HASHTREE 2 + +#define set_layer_addr XMSS_INNER_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr XMSS_INNER_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type XMSS_INNER_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +#define set_key_and_mask XMSS_INNER_NAMESPACE(set_key_and_mask) +void set_key_and_mask(uint32_t addr[8], uint32_t key_and_mask); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr XMSS_INNER_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for OTS addresses. */ +#define set_ots_addr XMSS_INNER_NAMESPACE(set_ots_addr) +void set_ots_addr(uint32_t addr[8], uint32_t ots); + +#define set_chain_addr XMSS_INNER_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr XMSS_INNER_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +/* This function is used for L-tree addresses. */ +#define set_ltree_addr XMSS_INNER_NAMESPACE(set_ltree_addr) +void set_ltree_addr(uint32_t addr[8], uint32_t ltree); + +/* These functions are used for hash tree addresses. */ +#define set_tree_height XMSS_INNER_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index XMSS_INNER_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig_stfl/xmss/external/namespace.h b/src/sig_stfl/xmss/external/namespace.h new file mode 100644 index 0000000000..3fe67527d2 --- /dev/null +++ b/src/sig_stfl/xmss/external/namespace.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_NAMESPACE_H +#define XMSS_NAMESPACE_H + +#define XMSS__(prefix, funcname) prefix##_##funcname +#define XMSS_(prefix, funcname) XMSS__(prefix, funcname) +#define __XMSS(funcname, postfix) funcname##_##postfix +#define _XMSS(funcname, postfix) __XMSS(funcname, postfix) + +#define XMSS_PARAMS _XMSS(oqs_sig_stfl, XMSS_PARAMS_NAMESPACE) +#define XMSS_PARAMS_INNER _XMSS(_XMSS(oqs_sig_stfl, XMSS_PARAMS_NAMESPACE), inner) +#define XMSS_PARAMS_INNER_CORE _XMSS(_XMSS(oqs_sig_stfl, XMSS_PARAMS_NAMESPACE), inner) + +#define XMSS_PARAMS_INNER_CORE_HASH(funcname) XMSS_(XMSS_PARAMS_INNER_CORE, funcname) + +#define XMSS_NAMESPACE(funcname) XMSS_(XMSS_PARAMS, funcname) +#define XMSS_INNER_NAMESPACE(funcname) XMSS_(XMSS_PARAMS_INNER, funcname) + +#endif diff --git a/src/sig_stfl/xmss/external/params.c b/src/sig_stfl/xmss/external/params.c new file mode 100644 index 0000000000..2a91a964df --- /dev/null +++ b/src/sig_stfl/xmss/external/params.c @@ -0,0 +1,754 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include + +#include "params.h" +#include "xmss_core.h" + +int xmss_str_to_oid(uint32_t *oid, const char *s) +{ + if (!strcmp(s, "XMSS-SHA2_10_256")) { + *oid = 0x00000001; + } + else if (!strcmp(s, "XMSS-SHA2_16_256")) { + *oid = 0x00000002; + } + else if (!strcmp(s, "XMSS-SHA2_20_256")) { + *oid = 0x00000003; + } + else if (!strcmp(s, "XMSS-SHA2_10_512")) { + *oid = 0x00000004; + } + else if (!strcmp(s, "XMSS-SHA2_16_512")) { + *oid = 0x00000005; + } + else if (!strcmp(s, "XMSS-SHA2_20_512")) { + *oid = 0x00000006; + } + else if (!strcmp(s, "XMSS-SHAKE_10_256")) { + *oid = 0x00000007; + } + else if (!strcmp(s, "XMSS-SHAKE_16_256")) { + *oid = 0x00000008; + } + else if (!strcmp(s, "XMSS-SHAKE_20_256")) { + *oid = 0x00000009; + } + else if (!strcmp(s, "XMSS-SHAKE_10_512")) { + *oid = 0x0000000a; + } + else if (!strcmp(s, "XMSS-SHAKE_16_512")) { + *oid = 0x0000000b; + } + else if (!strcmp(s, "XMSS-SHAKE_20_512")) { + *oid = 0x0000000c; + } + else if (!strcmp(s, "XMSS-SHA2_10_192")) { + *oid = 0x0000000d; + } + else if (!strcmp(s, "XMSS-SHA2_16_192")) { + *oid = 0x0000000e; + } + else if (!strcmp(s, "XMSS-SHA2_20_192")) { + *oid = 0x0000000f; + } + else if (!strcmp(s, "XMSS-SHAKE256_10_256")) { + *oid = 0x00000010; + } + else if (!strcmp(s, "XMSS-SHAKE256_16_256")) { + *oid = 0x00000011; + } + else if (!strcmp(s, "XMSS-SHAKE256_20_256")) { + *oid = 0x00000012; + } + else if (!strcmp(s, "XMSS-SHAKE256_10_192")) { + *oid = 0x00000013; + } + else if (!strcmp(s, "XMSS-SHAKE256_16_192")) { + *oid = 0x00000014; + } + else if (!strcmp(s, "XMSS-SHAKE256_20_192")) { + *oid = 0x00000015; + } + else { + return -1; + } + return 0; +} + +int xmssmt_str_to_oid(uint32_t *oid, const char *s) +{ + if (!strcmp(s, "XMSSMT-SHA2_20/2_256")) { + *oid = 0x00000001; + } + else if (!strcmp(s, "XMSSMT-SHA2_20/4_256")) { + *oid = 0x00000002; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/2_256")) { + *oid = 0x00000003; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/4_256")) { + *oid = 0x00000004; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/8_256")) { + *oid = 0x00000005; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/3_256")) { + *oid = 0x00000006; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/6_256")) { + *oid = 0x00000007; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/12_256")) { + *oid = 0x00000008; + } + else if (!strcmp(s, "XMSSMT-SHA2_20/2_512")) { + *oid = 0x00000009; + } + else if (!strcmp(s, "XMSSMT-SHA2_20/4_512")) { + *oid = 0x0000000a; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/2_512")) { + *oid = 0x0000000b; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/4_512")) { + *oid = 0x0000000c; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/8_512")) { + *oid = 0x0000000d; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/3_512")) { + *oid = 0x0000000e; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/6_512")) { + *oid = 0x0000000f; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/12_512")) { + *oid = 0x00000010; + } + else if (!strcmp(s, "XMSSMT-SHAKE_20/2_256")) { + *oid = 0x00000011; + } + else if (!strcmp(s, "XMSSMT-SHAKE_20/4_256")) { + *oid = 0x00000012; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/2_256")) { + *oid = 0x00000013; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/4_256")) { + *oid = 0x00000014; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/8_256")) { + *oid = 0x00000015; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/3_256")) { + *oid = 0x00000016; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/6_256")) { + *oid = 0x00000017; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/12_256")) { + *oid = 0x00000018; + } + else if (!strcmp(s, "XMSSMT-SHAKE_20/2_512")) { + *oid = 0x00000019; + } + else if (!strcmp(s, "XMSSMT-SHAKE_20/4_512")) { + *oid = 0x0000001a; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/2_512")) { + *oid = 0x0000001b; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/4_512")) { + *oid = 0x0000001c; + } + else if (!strcmp(s, "XMSSMT-SHAKE_40/8_512")) { + *oid = 0x0000001d; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/3_512")) { + *oid = 0x0000001e; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/6_512")) { + *oid = 0x0000001f; + } + else if (!strcmp(s, "XMSSMT-SHAKE_60/12_512")) { + *oid = 0x00000020; + } + else if (!strcmp(s, "XMSSMT-SHA2_20/2_192")) { + *oid = 0x00000021; + } + else if (!strcmp(s, "XMSSMT-SHA2_20/4_192")) { + *oid = 0x00000022; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/2_192")) { + *oid = 0x00000023; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/4_192")) { + *oid = 0x00000024; + } + else if (!strcmp(s, "XMSSMT-SHA2_40/8_192")) { + *oid = 0x00000025; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/3_192")) { + *oid = 0x00000026; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/6_192")) { + *oid = 0x00000027; + } + else if (!strcmp(s, "XMSSMT-SHA2_60/12_192")) { + *oid = 0x00000028; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_20/2_256")) { + *oid = 0x00000029; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_20/4_256")) { + *oid = 0x0000002a; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/2_256")) { + *oid = 0x0000002b; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/4_256")) { + *oid = 0x0000002c; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/8_256")) { + *oid = 0x0000002d; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/3_256")) { + *oid = 0x0000002e; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/6_256")) { + *oid = 0x0000002f; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/12_256")) { + *oid = 0x00000030; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_20/2_192")) { + *oid = 0x00000031; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_20/4_192")) { + *oid = 0x00000032; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/2_192")) { + *oid = 0x00000033; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/4_192")) { + *oid = 0x00000034; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_40/8_192")) { + *oid = 0x00000035; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/3_192")) { + *oid = 0x00000036; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/6_192")) { + *oid = 0x00000037; + } + else if (!strcmp(s, "XMSSMT-SHAKE256_60/12_192")) { + *oid = 0x00000038; + } + else { + return -1; + } + return 0; +} + +int xmss_parse_oid(xmss_params *params, const uint32_t oid) +{ + switch (oid) { + case 0x00000001: + case 0x00000002: + case 0x00000003: + case 0x00000004: + case 0x00000005: + case 0x00000006: + + case 0x0000000d: + case 0x0000000e: + case 0x0000000f: + params->func = XMSS_SHA2; + break; + + case 0x00000007: + case 0x00000008: + case 0x00000009: + params->func = XMSS_SHAKE128; + break; + + case 0x0000000a: + case 0x0000000b: + case 0x0000000c: + + case 0x00000010: + case 0x00000011: + case 0x00000012: + case 0x00000013: + case 0x00000014: + case 0x00000015: + params->func = XMSS_SHAKE256; + break; + + default: + return -1; + } + switch (oid) { + case 0x0000000d: + case 0x0000000e: + case 0x0000000f: + + case 0x00000013: + case 0x00000014: + case 0x00000015: + params->n = 24; + params->padding_len = 4; + break; + + case 0x00000001: + case 0x00000002: + case 0x00000003: + + case 0x00000007: + case 0x00000008: + case 0x00000009: + + case 0x00000010: + case 0x00000011: + case 0x00000012: + params->n = 32; + params->padding_len = 32; + break; + + case 0x00000004: + case 0x00000005: + case 0x00000006: + + case 0x0000000a: + case 0x0000000b: + case 0x0000000c: + params->n = 64; + params->padding_len = 64; + break; + + default: + return -1; + } + switch (oid) { + case 0x00000001: + case 0x00000004: + case 0x00000007: + case 0x0000000a: + case 0x0000000d: + case 0x00000010: + case 0x00000013: + params->full_height = 10; + break; + + case 0x00000002: + case 0x00000005: + case 0x00000008: + case 0x0000000b: + case 0x0000000e: + case 0x00000011: + case 0x00000014: + params->full_height = 16; + break; + + case 0x00000003: + case 0x00000006: + case 0x00000009: + case 0x0000000c: + case 0x0000000f: + case 0x00000012: + case 0x00000015: + params->full_height = 20; + + break; + default: + return -1; + } + + params->d = 1; + params->wots_w = 16; + + // TODO (from upstream) figure out sensible and legal values for this based on the above + params->bds_k = 0; + + return xmss_xmssmt_initialize_params(params); +} + +int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) +{ + switch (oid) { + case 0x00000001: + case 0x00000002: + case 0x00000003: + case 0x00000004: + case 0x00000005: + case 0x00000006: + case 0x00000007: + case 0x00000008: + case 0x00000009: + case 0x0000000a: + case 0x0000000b: + case 0x0000000c: + case 0x0000000d: + case 0x0000000e: + case 0x0000000f: + case 0x00000010: + + case 0x00000021: + case 0x00000022: + case 0x00000023: + case 0x00000024: + case 0x00000025: + case 0x00000026: + case 0x00000027: + case 0x00000028: + params->func = XMSS_SHA2; + break; + + case 0x00000011: + case 0x00000012: + case 0x00000013: + case 0x00000014: + case 0x00000015: + case 0x00000016: + case 0x00000017: + case 0x00000018: + params->func = XMSS_SHAKE128; + break; + + case 0x00000019: + case 0x0000001a: + case 0x0000001b: + case 0x0000001c: + case 0x0000001e: + case 0x0000001d: + case 0x0000001f: + case 0x00000020: + + case 0x00000029: + case 0x0000002a: + case 0x0000002b: + case 0x0000002c: + case 0x0000002d: + case 0x0000002e: + case 0x0000002f: + case 0x00000030: + case 0x00000031: + case 0x00000032: + case 0x00000033: + case 0x00000034: + case 0x00000035: + case 0x00000036: + case 0x00000037: + case 0x00000038: + params->func = XMSS_SHAKE256; + break; + + default: + return -1; + } + switch (oid) { + case 0x00000021: + case 0x00000022: + case 0x00000023: + case 0x00000024: + case 0x00000025: + case 0x00000026: + case 0x00000027: + case 0x00000028: + + case 0x00000031: + case 0x00000032: + case 0x00000033: + case 0x00000034: + case 0x00000035: + case 0x00000036: + case 0x00000037: + case 0x00000038: + params->n = 24; + params->padding_len = 4; + break; + + case 0x00000001: + case 0x00000002: + case 0x00000003: + case 0x00000004: + case 0x00000005: + case 0x00000006: + case 0x00000007: + case 0x00000008: + + case 0x00000011: + case 0x00000012: + case 0x00000013: + case 0x00000014: + case 0x00000015: + case 0x00000016: + case 0x00000017: + case 0x00000018: + + case 0x00000029: + case 0x0000002a: + case 0x0000002b: + case 0x0000002c: + case 0x0000002d: + case 0x0000002e: + case 0x0000002f: + case 0x00000030: + params->n = 32; + params->padding_len = 32; + break; + + case 0x00000009: + case 0x0000000a: + case 0x0000000b: + case 0x0000000c: + case 0x0000000d: + case 0x0000000e: + case 0x0000000f: + case 0x00000010: + + case 0x00000019: + case 0x0000001a: + case 0x0000001b: + case 0x0000001c: + case 0x0000001d: + case 0x0000001e: + case 0x0000001f: + case 0x00000020: + params->n = 64; + params->padding_len = 64; + break; + + default: + return -1; + } + switch (oid) { + case 0x00000001: + case 0x00000002: + + case 0x00000009: + case 0x0000000a: + + case 0x00000011: + case 0x00000012: + + case 0x00000019: + case 0x0000001a: + + case 0x00000021: + case 0x00000022: + + case 0x00000029: + case 0x0000002a: + + case 0x00000031: + case 0x00000032: + params->full_height = 20; + break; + + case 0x00000003: + case 0x00000004: + case 0x00000005: + + case 0x0000000b: + case 0x0000000c: + case 0x0000000d: + + case 0x00000013: + case 0x00000014: + case 0x00000015: + + case 0x0000001b: + case 0x0000001c: + case 0x0000001d: + + case 0x00000023: + case 0x00000024: + case 0x00000025: + + case 0x0000002b: + case 0x0000002c: + case 0x0000002d: + + case 0x00000033: + case 0x00000034: + case 0x00000035: + params->full_height = 40; + break; + + case 0x00000006: + case 0x00000007: + case 0x00000008: + + case 0x0000000e: + case 0x0000000f: + case 0x00000010: + + case 0x00000016: + case 0x00000017: + case 0x00000018: + + case 0x0000001e: + case 0x0000001f: + case 0x00000020: + + case 0x00000026: + case 0x00000027: + case 0x00000028: + + case 0x0000002e: + case 0x0000002f: + case 0x00000030: + + case 0x00000036: + case 0x00000037: + case 0x00000038: + params->full_height = 60; + break; + + default: + return -1; + } + switch (oid) { + case 0x00000001: + case 0x00000003: + case 0x00000009: + case 0x0000000b: + case 0x00000011: + case 0x00000013: + case 0x00000019: + case 0x0000001b: + case 0x00000021: + case 0x00000023: + case 0x00000029: + case 0x0000002b: + case 0x00000031: + case 0x00000033: + params->d = 2; + break; + + case 0x00000002: + case 0x00000004: + case 0x0000000a: + case 0x0000000c: + case 0x00000012: + case 0x00000014: + case 0x0000001a: + case 0x0000001c: + case 0x00000022: + case 0x00000024: + case 0x0000002a: + case 0x0000002c: + case 0x00000032: + case 0x00000034: + params->d = 4; + break; + + case 0x00000005: + case 0x0000000d: + case 0x00000015: + case 0x0000001d: + case 0x00000025: + case 0x0000002d: + case 0x00000035: + params->d = 8; + break; + + case 0x00000006: + case 0x0000000e: + case 0x00000016: + case 0x0000001e: + case 0x00000026: + case 0x0000002e: + case 0x00000036: + params->d = 3; + break; + + case 0x00000007: + case 0x0000000f: + case 0x00000017: + case 0x0000001f: + case 0x00000027: + case 0x0000002f: + case 0x00000037: + params->d = 6; + break; + + case 0x00000008: + case 0x00000010: + case 0x00000018: + case 0x00000020: + case 0x00000028: + case 0x00000030: + case 0x00000038: + params->d = 12; + break; + + default: + return -1; + } + + params->wots_w = 16; + + // TODO (from upstream) figure out sensible and legal values for this based on the above + params->bds_k = 0; + + return xmss_xmssmt_initialize_params(params); +} + +/** + * Given a params struct where the following properties have been initialized; + * - full_height; the height of the complete (hyper)tree + * - n; the number of bytes of hash function output + * - d; the number of layers (d > 1 implies XMSSMT) + * - func; one of {XMSS_SHA2, XMSS_SHAKE128, XMSS_SHAKE256} + * - wots_w; the Winternitz parameter + * - optionally, bds_k; the BDS traversal trade-off parameter, + * this function initializes the remainder of the params structure. + */ +int xmss_xmssmt_initialize_params(xmss_params *params) +{ + params->tree_height = params->full_height / params->d; + if (params->wots_w == 4) { + params->wots_log_w = 2; + params->wots_len1 = 8 * params->n / params->wots_log_w; + /* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ + params->wots_len2 = 5; + } + else if (params->wots_w == 16) { + params->wots_log_w = 4; + params->wots_len1 = 8 * params->n / params->wots_log_w; + /* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ + params->wots_len2 = 3; + } + else if (params->wots_w == 256) { + params->wots_log_w = 8; + params->wots_len1 = 8 * params->n / params->wots_log_w; + /* len_2 = floor(log(len_1 * (w - 1)) / log(w)) + 1 */ + params->wots_len2 = 2; + } + else { + return -1; + } + params->wots_len = params->wots_len1 + params->wots_len2; + params->wots_sig_bytes = params->wots_len * params->n; + + if (params->d == 1) { // Assume this is XMSS, not XMSS^MT + /* In XMSS, always use fixed 4 bytes for index_bytes */ + params->index_bytes = 4; + } + else { + /* In XMSS^MT, round index_bytes up to nearest byte. */ + params->index_bytes = (params->full_height + 7) / 8; + } + params->sig_bytes = (params->index_bytes + params->n + + params->d * params->wots_sig_bytes + + params->full_height * params->n); + + params->pk_bytes = 2 * params->n; + params->sk_bytes = xmss_xmssmt_core_sk_bytes(params); + + return 0; +} diff --git a/src/sig_stfl/xmss/external/params.h b/src/sig_stfl/xmss/external/params.h new file mode 100644 index 0000000000..e9a5faaa2b --- /dev/null +++ b/src/sig_stfl/xmss/external/params.h @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_PARAMS_H +#define XMSS_PARAMS_H + +#include +#include "namespace.h" + +/* These are merely internal identifiers for the supported hash functions. */ +#define XMSS_SHA2 0 +#define XMSS_SHAKE128 1 +#define XMSS_SHAKE256 2 + +/* This is a result of the OID definitions in the draft; needed for parsing. */ +#define XMSS_OID_LEN 4 + +/* This structure will be populated when calling xmss[mt]_parse_oid. */ +typedef struct { + unsigned int func; + unsigned int n; + unsigned int padding_len; + unsigned int wots_w; + unsigned int wots_log_w; + unsigned int wots_len1; + unsigned int wots_len2; + unsigned int wots_len; + unsigned int wots_sig_bytes; + unsigned int full_height; + unsigned int tree_height; + unsigned int d; + unsigned int index_bytes; + unsigned int sig_bytes; + unsigned int pk_bytes; + unsigned long long sk_bytes; + unsigned int bds_k; +} xmss_params; + +/** + * Accepts strings such as "XMSS-SHA2_10_256" + * and outputs OIDs such as 0x01000001. + * Returns -1 when the parameter set is not found, 0 otherwise + */ +#define xmss_str_to_oid XMSS_NAMESPACE(xmss_str_to_oid) +int xmss_str_to_oid(uint32_t *oid, const char *s); + +/** + * Accepts takes strings such as "XMSSMT-SHA2_20/2_256" + * and outputs OIDs such as 0x01000001. + * Returns -1 when the parameter set is not found, 0 otherwise + */ +#define xmssmt_str_to_oid XMSS_NAMESPACE(xmssmt_str_to_oid) +int xmssmt_str_to_oid(uint32_t *oid, const char *s); + +/** + * Accepts OIDs such as 0x01000001, and configures params accordingly. + * Returns -1 when the OID is not found, 0 otherwise. + */ +#define xmss_parse_oid XMSS_NAMESPACE(xmss_parse_oid) +int xmss_parse_oid(xmss_params *params, const uint32_t oid); + +/** + * Accepts OIDs such as 0x01000001, and configures params accordingly. + * Returns -1 when the OID is not found, 0 otherwise. + */ +#define xmssmt_parse_oid XMSS_NAMESPACE(xmssmt_parse_oid) +int xmssmt_parse_oid(xmss_params *params, const uint32_t oid); + + +/* Given a params struct where the following properties have been initialized; + - full_height; the height of the complete (hyper)tree + - n; the number of bytes of hash function output + - d; the number of layers (d > 1 implies XMSSMT) + - func; one of {XMSS_SHA2, XMSS_SHAKE128, XMSS_SHAKE256} + - wots_w; the Winternitz parameter + - optionally, bds_k; the BDS traversal trade-off parameter, + this function initializes the remainder of the params structure. */ +#define xmss_xmssmt_initialize_params XMSS_NAMESPACE(xmss_xmssmt_initialize_params) +int xmss_xmssmt_initialize_params(xmss_params *params); + +#endif diff --git a/src/sig_stfl/xmss/external/utils.c b/src/sig_stfl/xmss/external/utils.c new file mode 100644 index 0000000000..f03ef93d40 --- /dev/null +++ b/src/sig_stfl/xmss/external/utils.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include "utils.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) +{ + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) +{ + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8*(inlen - 1 - i)); + } + return retval; +} diff --git a/src/sig_stfl/xmss/external/utils.h b/src/sig_stfl/xmss/external/utils.h new file mode 100644 index 0000000000..e3c1d2853d --- /dev/null +++ b/src/sig_stfl/xmss/external/utils.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_UTILS_H +#define XMSS_UTILS_H + +#include "namespace.h" +#include +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes XMSS_INNER_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull XMSS_INNER_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +#endif diff --git a/src/sig_stfl/xmss/external/wots.c b/src/sig_stfl/xmss/external/wots.c new file mode 100644 index 0000000000..0d5b57fd57 --- /dev/null +++ b/src/sig_stfl/xmss/external/wots.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include + +#include "utils.h" +#include "hash.h" +#include "wots.h" +#include "hash_address.h" +#include "params.h" + +/** + * Helper method for pseudorandom key generation. + * Expands an n-byte array into a len*n byte array using the `prf_keygen` function. + */ +static void expand_seed(const xmss_params *params, + unsigned char *outseeds, const unsigned char *inseed, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buf) +{ + unsigned int i; + unsigned char *prf_buf = buf + params->n + 32; + + set_hash_addr(addr, 0); + set_key_and_mask(addr, 0); + memcpy(buf, pub_seed, params->n); + for (i = 0; i < params->wots_len; i++) { + set_chain_addr(addr, i); + addr_to_bytes(buf + params->n, addr); + prf_keygen(params, outseeds + i*params->n, buf, inseed, prf_buf); + } +} + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(const xmss_params *params, + unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *thash_buf) +{ + unsigned int i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, params->n); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start+steps) && i < params->wots_w; i++) { + set_hash_addr(addr, i); + thash_f(params, out, out, pub_seed, addr, thash_buf); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(const xmss_params *params, + unsigned int *output, const unsigned int out_len, const unsigned char *input) +{ + unsigned int in = 0; + unsigned int out = 0; + unsigned char total; + unsigned int bits = 0; + unsigned int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= params->wots_log_w; + output[out] = (total >> bits) & (params->wots_w - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(const xmss_params *params, + unsigned int *csum_base_w, const unsigned int *msg_base_w) +{ + int csum = 0; + unsigned int csum_bytes_length = (params->wots_len2 * params->wots_log_w + 7) / 8; + unsigned char *csum_bytes = malloc(csum_bytes_length); + if (csum_bytes == NULL) { + return; + } + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < params->wots_len1; i++) { + csum += params->wots_w - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8)); + ull_to_bytes(csum_bytes, csum_bytes_length, csum); + base_w(params, csum_base_w, params->wots_len2, csum_bytes); + + OQS_MEM_insecure_free(csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +static void chain_lengths(const xmss_params *params, + unsigned int *lengths, const unsigned char *msg) +{ + base_w(params, lengths, params->wots_len1, msg); + wots_checksum(params, lengths + params->wots_len1, lengths); +} + +/** + * WOTS key generation. Takes a 32 byte seed for the private key, expands it to + * a full WOTS private key and computes the corresponding public key. + * It requires the seed pub_seed (used to generate bitmasks and hash keys) + * and the address of this WOTS key pair. + * + * Writes the computed public key to 'pk'. + */ +void wots_pkgen(const xmss_params *params, + unsigned char *pk, const unsigned char *seed, + const unsigned char *pub_seed, uint32_t addr[8]) +{ + unsigned int i; + const size_t buf_size = 2 * params->padding_len + 4 * params->n + 64; + unsigned char *buf = malloc(buf_size); + if (buf == NULL) { + return; + } + + /* The WOTS+ private key is derived from the seed. */ + expand_seed(params, pk, seed, pub_seed, addr, buf); + + for (i = 0; i < params->wots_len; i++) { + set_chain_addr(addr, i); + gen_chain(params, pk + i*params->n, pk + i*params->n, + 0, params->wots_w - 1, pub_seed, addr, buf); + } + + OQS_MEM_secure_free(buf, buf_size); +} + +/** + * Takes a n-byte message and the 32-byte seed for the private key to compute a + * signature that is placed at 'sig'. + */ +void wots_sign(const xmss_params *params, + unsigned char *sig, const unsigned char *msg, + const unsigned char *seed, const unsigned char *pub_seed, + uint32_t addr[8]) +{ + const size_t buf_size = 2 * params->padding_len + 4 * params->n + 64; + unsigned int *lengths = calloc(params->wots_len, sizeof(unsigned int)); + unsigned char *buf = malloc(buf_size); + unsigned int i; + if (lengths == NULL || buf == NULL) { + return; + } + + chain_lengths(params, lengths, msg); + + /* The WOTS+ private key is derived from the seed. */ + expand_seed(params, sig, seed, pub_seed, addr, buf); + + for (i = 0; i < params->wots_len; i++) { + set_chain_addr(addr, i); + gen_chain(params, sig + i*params->n, sig + i*params->n, + 0, lengths[i], pub_seed, addr, buf); + } + + OQS_MEM_insecure_free(lengths); + OQS_MEM_secure_free(buf, buf_size); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const unsigned char *pub_seed, uint32_t addr[8]) +{ + unsigned int *lengths = calloc(params->wots_len, sizeof(unsigned int )); + const size_t thash_buf_len = 2 * params->padding_len + 4 * params->n + 32; + unsigned char *thash_buf = malloc(thash_buf_len); + unsigned int i; + if (lengths == NULL || thash_buf == NULL) { + return; + } + + chain_lengths(params, lengths, msg); + + for (i = 0; i < params->wots_len; i++) { + set_chain_addr(addr, i); + gen_chain(params, pk + i*params->n, sig + i*params->n, + lengths[i], params->wots_w - 1 - lengths[i], pub_seed, addr, thash_buf); + } + + OQS_MEM_insecure_free(lengths); + OQS_MEM_insecure_free(thash_buf); +} diff --git a/src/sig_stfl/xmss/external/wots.h b/src/sig_stfl/xmss/external/wots.h new file mode 100644 index 0000000000..8f8756ede3 --- /dev/null +++ b/src/sig_stfl/xmss/external/wots.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_WOTS_H +#define XMSS_WOTS_H + +#include +#include "params.h" + +/** + * WOTS key generation. Takes a 32 byte seed for the private key, expands it to + * a full WOTS private key and computes the corresponding public key. + * It requires the seed pub_seed (used to generate bitmasks and hash keys) + * and the address of this WOTS key pair. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pkgen XMSS_INNER_NAMESPACE(wots_pkgen) +void wots_pkgen(const xmss_params *params, + unsigned char *pk, const unsigned char *seed, + const unsigned char *pub_seed, uint32_t addr[8]); + +/** + * Takes a n-byte message and the 32-byte seed for the private key to compute a + * signature that is placed at 'sig'. + */ +#define wots_sign XMSS_INNER_NAMESPACE(wots_sign) +void wots_sign(const xmss_params *params, + unsigned char *sig, const unsigned char *msg, + const unsigned char *seed, const unsigned char *pub_seed, + uint32_t addr[8]); + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig XMSS_INNER_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const unsigned char *pub_seed, uint32_t addr[8]); + +#endif diff --git a/src/sig_stfl/xmss/external/xmss.c b/src/sig_stfl/xmss/external/xmss.c new file mode 100644 index 0000000000..6a224a8d3e --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include + +#include "params.h" +#include "xmss_core.h" +#include "utils.h" +#include "xmss.h" + + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +/* This file provides wrapper functions that take keys that include OIDs to +identify the parameter set to be used. After setting the parameters accordingly +it falls back to the regular XMSS core functions. */ + +/** + * The function generates a public-private key pair for the XMSS signature scheme using the specified + * OID. + * + * @param pk Pointer to the public key buffer where the generated public key will be stored. + * @param sk sk is a pointer to an unsigned char array that will hold the secret key generated by the + * XMSS key pair generation function. The secret key is used for signing messages and should be kept + * confidential. + * @param oid The `oid` parameter is an identifier for the XMSS variant to be used. It is used to + * determine the parameters for the XMSS algorithm, such as the tree height and the number of signature + * iterations. The `oid` value is typically encoded as a 32-bit integer + * + * @return an integer value. If the function executes successfully, it will return 0. If there is an + * error, it will return -1. + */ +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +int xmss_keypair(XMSS_UNUSED_ATT unsigned char *pk, XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT const uint32_t oid) +{ + return -1; +} +#else +int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) +{ + xmss_params params; + unsigned int i; + + if (xmss_parse_oid(¶ms, oid)) { + return -1; + } + for (i = 0; i < XMSS_OID_LEN; i++) { + pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; + /* For an implementation that uses runtime parameters, it is crucial + that the OID is part of the secret key as well; + i.e. not just for interoperability, but also for internal use. */ + sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; + } + return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); +} +#endif + +/** + * This function parses the XMSS OID from a secret key, uses it to determine the XMSS parameters, and + * then calls the core signing function with those parameters. + * + * @param sk The secret key used for signing the message. + * @param sm A pointer to the buffer where the signed message will be stored. + * @param smlen A pointer to a 64-bit unsigned integer that will be used to store the length of the + * signed message (sm) after signing. The length is in bytes. + * @param m The message to be signed, represented as an array of unsigned characters. + * @param mlen The length of the message to be signed, in bytes. + * + * @return an integer value. If the function executes successfully, it will return 0. If there is an + * error, it will return -1. + */ +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +int xmss_sign(XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT unsigned char *sm, XMSS_UNUSED_ATT unsigned long long *smlen, + XMSS_UNUSED_ATT const unsigned char *m, XMSS_UNUSED_ATT unsigned long long mlen) +{ + return -1; +} +#else +int xmss_sign(unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + if (xmss_parse_oid(¶ms, oid)) { + return -1; + } + return xmss_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); +} +#endif + +/** + * The function xmss_sign_open verifies a signature and retrieves the original message using the XMSS + * signature scheme. + * + * @param m Pointer to the buffer where the message will be stored after verification. + * @param mlen A pointer to a 64-bit unsigned integer that will be used to store the length of the + * message that is recovered during the signature verification process. + * @param sm The signature to be verified. It is a byte array of length smlen. + * @param smlen smlen is the length of the signature in bytes. + * @param pk pk is a pointer to the public key used for verifying the signature. + * + * @return The function `xmss_sign_open` returns an integer value. If the function is successful, it + * returns 0. If there is an error, it returns -1. + */ +int xmss_sign_open(const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8); + } + if (xmss_parse_oid(¶ms, oid)) { + return -1; + } + return xmss_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN); +} + +/** + * The function calculates the remaining number of signatures that can be generated using a given XMSS + * private key. + * + * @param remain a pointer to a uint64_t variable that will store the number of remaining signatures + * that can be generated with the given secret key. + * @param sk The `sk` parameter is a pointer to an array of unsigned characters representing the secret + * key used in the XMSS signature scheme. + * + * @return This function returns an integer value. If the function executes successfully, it returns 0. + * If there is an error, it returns -1. + */ +int xmss_remaining_signatures(unsigned long long *remain, const unsigned char *sk) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + unsigned long long idx, max; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + + if (xmss_parse_oid(¶ms, oid)) { + *remain = 0; + return -1; + } + + idx = bytes_to_ull(sk + XMSS_OID_LEN, params.index_bytes); + max = ((1ULL << params.full_height) - 1); + + *remain = max - idx; + + return 0; +} + +/** + * The function calculates the maximum number of signatures that can be generated for a given XMSS private key. + * + * @param max a pointer to an unsigned long long variable that will store the maximum number of + * signatures that can be generated with the given XMSS private key. + * @param sk The secret key used for XMSS signature scheme. It is a pointer to an array of unsigned + * characters. + * + * @return an integer value. If the XMSS OID cannot be parsed, it returns -1. Otherwise, it sets the + * value of the variable pointed to by the "max" parameter to the maximum number of signatures that can + * be generated with the given XMSS private key and returns 0. + */ +int xmss_total_signatures(unsigned long long *max, const unsigned char *sk) +{ + xmss_params params; + uint32_t oid = 0; + + for (unsigned i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + + if (xmss_parse_oid(¶ms, oid)) { + *max = 0; + return -1; + } + + *max = ((1ULL << params.full_height) - 1); + + return 0; +} + +int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) +{ + xmss_params params; + unsigned int i; + + if (xmssmt_parse_oid(¶ms, oid)) { + return -1; + } + for (i = 0; i < XMSS_OID_LEN; i++) { + pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; + sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; + } + return xmssmt_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); +} + +int xmssmt_sign(unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + if (xmssmt_parse_oid(¶ms, oid)) { + return -1; + } + return xmssmt_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); +} + +int xmssmt_sign_open(const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8); + } + if (xmssmt_parse_oid(¶ms, oid)) { + return -1; + } + return xmssmt_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN); +} + + +/** + * The function calculates the remaining number of signatures that can be generated using a given + * XMSSMT private key. + * + * @param remain a pointer to an unsigned long long variable that will store the number of remaining + * signatures that can be generated using the given secret key. + * @param sk The `sk` parameter is a pointer to an array of unsigned characters representing the secret + * key used in the XMSSMT signature scheme. + * + * @return This function returns an integer value. If the function executes successfully, it returns 0. + * If there is an error, it returns -1. + */ +int xmssmt_remaining_signatures(unsigned long long *remain, const unsigned char *sk) +{ + xmss_params params; + uint32_t oid = 0; + unsigned int i; + unsigned long long idx, max; + + for (i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + + if (xmssmt_parse_oid(¶ms, oid)) { + *remain = 0; + return -1; + } + + idx = bytes_to_ull(sk + XMSS_OID_LEN, params.index_bytes); + max = ((1ULL << params.full_height) - 1); + + *remain = max - idx; + + return 0; +} + +/** + * The function calculates the maximum number of signatures that can be generated for a given XMSSMT private key. + * + * @param max a pointer to an unsigned long long variable that will store the maximum number of + * signatures that can be generated with the given secret key. + * @param sk The `sk` parameter is a pointer to an array of unsigned characters representing the secret + * key used in the XMSS signature scheme. + * + * @return an integer value. If the XMSS OID cannot be parsed, it returns -1. Otherwise, it returns 0. + */ +int xmssmt_total_signatures(unsigned long long *max, const unsigned char *sk) +{ + xmss_params params; + uint32_t oid = 0; + + for (unsigned i = 0; i < XMSS_OID_LEN; i++) { + oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8); + } + + if (xmssmt_parse_oid(¶ms, oid)) { + *max = 0; + return -1; + } + + *max = ((1ULL << params.full_height) - 1); + + return 0; +} diff --git a/src/sig_stfl/xmss/external/xmss.h b/src/sig_stfl/xmss/external/xmss.h new file mode 100644 index 0000000000..566b809b9e --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss.h @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_H +#define XMSS_H + +#include +#include "namespace.h" + +/** + * Generates a XMSS key pair for a given parameter set. + * Format sk: [OID || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [OID || root || PUB_SEED] + */ +#define xmss_keypair XMSS_NAMESPACE(xmss_keypair) +int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid); + +/** + * Signs a message using an XMSS secret key. + * Returns + * 1. an array containing the signature followed by the message AND + * 2. an updated secret key! + */ +#define xmss_sign XMSS_NAMESPACE(xmss_sign) +int xmss_sign(unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen); + +/** + * Verifies a given message signature pair using a given public key. + * + * Note: m and mlen are pure outputs which carry the message in case + * verification succeeds. The (input) message is assumed to be contained in sm + * which has the form [signature || message]. + */ +#define xmss_sign_open XMSS_NAMESPACE(xmss_sign_open) +int xmss_sign_open(const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +/* + * Write number of remaining signature to `remain` variable given `sk` + */ +#define xmss_remaining_signatures XMSS_NAMESPACE(xmss_remaining_signatures) +int xmss_remaining_signatures(unsigned long long *remain, const unsigned char *sk); + +/* + * Write number of maximum signature to `max` variable given `sk` + */ +#define xmss_total_signatures XMSS_NAMESPACE(xmss_total_signatures) +int xmss_total_signatures(unsigned long long *max, const unsigned char *sk); + +/* + * Generates a XMSSMT key pair for a given parameter set. + * Format sk: [OID || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [OID || root || PUB_SEED] + */ +#define xmssmt_keypair XMSS_NAMESPACE(xmssmt_keypair) +int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid); + +/** + * Signs a message using an XMSSMT secret key. + * Returns + * 1. an array containing the signature followed by the message AND + * 2. an updated secret key! + */ +#define xmssmt_sign XMSS_NAMESPACE(xmssmt_sign) +int xmssmt_sign(unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen); + +/** + * Verifies a given message signature pair using a given public key. + * + * Note: m and mlen are pure outputs which carry the message in case + * verification succeeds. The (input) message is assumed to be contained in sm + * which has the form [signature || message]. + */ +#define xmssmt_sign_open XMSS_NAMESPACE(xmssmt_sign_open) +int xmssmt_sign_open(const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +/* + * Write number of remaining signature to `remain` variable given `sk` + */ +#define xmssmt_remaining_signatures XMSS_NAMESPACE(xmssmt_remaining_signatures) +int xmssmt_remaining_signatures(unsigned long long *remain, const unsigned char *sk); + +/* + * Write number of maximum signature to `max` variable given `sk` + */ +#define xmssmt_total_signatures XMSS_NAMESPACE(xmssmt_total_signatures) +int xmssmt_total_signatures(unsigned long long *max, const unsigned char *sk); + +#endif diff --git a/src/sig_stfl/xmss/external/xmss_commons.c b/src/sig_stfl/xmss/external/xmss_commons.c new file mode 100644 index 0000000000..3d7e469a4d --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss_commons.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include +#include + +#include "hash.h" +#include "hash_address.h" +#include "params.h" +#include "wots.h" +#include "utils.h" +#include "xmss_commons.h" + +/** + * Computes a leaf node from a WOTS public key using an L-tree. + * Note that this destroys the used WOTS public key. + */ +static void l_tree(const xmss_params *params, + unsigned char *leaf, unsigned char *wots_pk, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *thash_buf) +{ + unsigned int l = params->wots_len; + unsigned int parent_nodes; + uint32_t i; + uint32_t height = 0; + + set_tree_height(addr, height); + + while (l > 1) { + parent_nodes = l >> 1; + for (i = 0; i < parent_nodes; i++) { + set_tree_index(addr, i); + /* Hashes the nodes at (i*2)*params->n and (i*2)*params->n + 1 */ + thash_h(params, wots_pk + i*params->n, + wots_pk + (i*2)*params->n, pub_seed, addr, thash_buf); + } + /* If the row contained an odd number of nodes, the last node was not + hashed. Instead, we pull it up to the next layer. */ + if (l & 1) { + memcpy(wots_pk + (l >> 1)*params->n, + wots_pk + (l - 1)*params->n, params->n); + l = (l >> 1) + 1; + } + else { + l = l >> 1; + } + height++; + set_tree_height(addr, height); + } + memcpy(leaf, wots_pk, params->n); +} + +/** + * Computes a root node given a leaf and an auth path + */ +static void compute_root(const xmss_params *params, unsigned char *root, + const unsigned char *leaf, unsigned long leafidx, + const unsigned char *auth_path, + const unsigned char *pub_seed, uint32_t addr[8], + unsigned char *buffer, + unsigned char *thash_buf) +{ + uint32_t i; + + /* If leafidx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leafidx & 1) { + memcpy(buffer + params->n, leaf, params->n); + memcpy(buffer, auth_path, params->n); + } + else { + memcpy(buffer, leaf, params->n); + memcpy(buffer + params->n, auth_path, params->n); + } + auth_path += params->n; + + for (i = 0; i < params->tree_height - 1; i++) { + set_tree_height(addr, i); + leafidx >>= 1; + set_tree_index(addr, leafidx); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leafidx & 1) { + thash_h(params, buffer + params->n, buffer, pub_seed, addr, thash_buf); + memcpy(buffer, auth_path, params->n); + } + else { + thash_h(params, buffer, buffer, pub_seed, addr, thash_buf); + memcpy(buffer + params->n, auth_path, params->n); + } + auth_path += params->n; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + set_tree_height(addr, params->tree_height - 1); + leafidx >>= 1; + set_tree_index(addr, leafidx); + thash_h(params, root, buffer, pub_seed, addr, thash_buf); + +} + + +/** + * Computes the leaf at a given address. First generates the WOTS key pair, + * then computes leaf using l_tree. As this happens position independent, we + * only require that addr encodes the right ltree-address. + */ +void gen_leaf_wots(const xmss_params *params, unsigned char *leaf, + const unsigned char *sk_seed, const unsigned char *pub_seed, + uint32_t ltree_addr[8], uint32_t ots_addr[8]) +{ + unsigned char *pk = malloc(params->wots_sig_bytes + 2 * params->padding_len + 6 * params->n + 32); + if (pk == NULL) { + return; + } + unsigned char *thash_buf = pk + params->wots_sig_bytes; + + wots_pkgen(params, pk, sk_seed, pub_seed, ots_addr); + + l_tree(params, leaf, pk, pub_seed, ltree_addr, thash_buf); + + OQS_MEM_insecure_free(pk); +} + + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +int xmss_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + /* XMSS signatures are fundamentally an instance of XMSSMT signatures. + For d=1, as is the case with XMSS, some of the calls in the XMSSMT + routine become vacuous (i.e. the loop only iterates once, and address + management can be simplified a bit).*/ + return xmssmt_core_sign_open(params, m, mlen, sm, smlen, pk); +} + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +int xmssmt_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + const unsigned char *pub_root = pk; + const unsigned char *pub_seed = pk + params->n; + + unsigned char *tmp = malloc(params->wots_sig_bytes + params->n + params->n + + + 2 *params->n + 2 * params->padding_len + 6 * params->n + 32); + if (tmp == NULL) { + return -1; + } + unsigned char *wots_pk = tmp; + unsigned char *leaf = tmp + params->wots_sig_bytes; + unsigned char *root = leaf + params->n; + unsigned char *compute_root_buf = root + params->n; + unsigned char *thash_buf = compute_root_buf + 2*params->n; + + unsigned long long prefix_length = params->padding_len + 3*params->n; + unsigned long long m_with_prefix_len = mlen + prefix_length; + unsigned char *m_with_prefix = NULL; + unsigned char *mhash = root; + unsigned long long idx = 0; + unsigned int i, ret; + uint32_t idx_leaf; + + uint32_t ots_addr[8] = {0}; + uint32_t ltree_addr[8] = {0}; + uint32_t node_addr[8] = {0}; + + set_type(ots_addr, XMSS_ADDR_TYPE_OTS); + set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE); + set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE); + + // Unused since smlen is a constant + (void) smlen; + + if ((m_with_prefix_len == 0) || (m_with_prefix = malloc(m_with_prefix_len)) == NULL){ + ret = -1; + goto fail; + } + + /* Convert the index bytes from the signature to an integer. */ + idx = bytes_to_ull(sm, params->index_bytes); + + /* Put the message at the m_with_prefix buffer, so that we can + * prepend the required other inputs for the hash function. */ + memcpy(m_with_prefix, sm + params->sig_bytes - prefix_length, (size_t)prefix_length); + memcpy(m_with_prefix + prefix_length, m, (size_t)mlen); + + /* Compute the message hash. */ + hash_message(params, mhash, sm + params->index_bytes, pk, idx, + m_with_prefix, + mlen); + sm += params->index_bytes + params->n; + + /* For each subtree.. */ + for (i = 0; i < params->d; i++) { + idx_leaf = (idx & ((1 << params->tree_height)-1)); + idx = idx >> params->tree_height; + + set_layer_addr(ots_addr, i); + set_layer_addr(ltree_addr, i); + set_layer_addr(node_addr, i); + + set_tree_addr(ltree_addr, idx); + set_tree_addr(ots_addr, idx); + set_tree_addr(node_addr, idx); + + /* The WOTS public key is only correct if the signature was correct. */ + set_ots_addr(ots_addr, idx_leaf); + /* Initially, root = mhash, but on subsequent iterations it is the root + of the subtree below the currently processed subtree. */ + wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr); + sm += params->wots_sig_bytes; + + /* Compute the leaf node using the WOTS public key. */ + set_ltree_addr(ltree_addr, idx_leaf); + l_tree(params, leaf, wots_pk, pub_seed, ltree_addr, thash_buf); + + /* Compute the root node of this subtree. */ + compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr, compute_root_buf, thash_buf); + sm += params->tree_height*params->n; + } + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, params->n)) { + /* If not, return fail */ + ret = -1; + goto fail; + } + ret = 0; +fail: + OQS_MEM_insecure_free(tmp); + OQS_MEM_insecure_free(m_with_prefix); + return ret; + +} diff --git a/src/sig_stfl/xmss/external/xmss_commons.h b/src/sig_stfl/xmss/external/xmss_commons.h new file mode 100644 index 0000000000..958fd3ffa3 --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss_commons.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_COMMONS_H +#define XMSS_COMMONS_H + +#include +#include "params.h" + +/** + * Computes the leaf at a given address. First generates the WOTS key pair, + * then computes leaf using l_tree. As this happens position independent, we + * only require that addr encodes the right ltree-address. + */ +#define gen_leaf_wots XMSS_INNER_NAMESPACE(gen_leaf_wots) +void gen_leaf_wots(const xmss_params *params, unsigned char *leaf, + const unsigned char *sk_seed, const unsigned char *pub_seed, + uint32_t ltree_addr[8], uint32_t ots_addr[8]); + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +#define xmss_core_sign_open XMSS_INNER_NAMESPACE(xmss_core_sign_open) +int xmss_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +#define xmssmt_core_sign_open XMSS_INNER_NAMESPACE(xmssmt_core_sign_open) +int xmssmt_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); +#endif diff --git a/src/sig_stfl/xmss/external/xmss_core.h b/src/sig_stfl/xmss/external/xmss_core.h new file mode 100644 index 0000000000..54cccc25e4 --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss_core.h @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#ifndef XMSS_CORE_H +#define XMSS_CORE_H + +#include "params.h" + +/** + * Given a set of parameters, this function returns the size of the secret key. + * This is implementation specific, as varying choices in tree traversal will + * result in varying requirements for state storage. + * + * This function handles both XMSS and XMSSMT parameter sets. + */ +#define xmss_xmssmt_core_sk_bytes XMSS_INNER_NAMESPACE(xmss_xmssmt_core_sk_bytes) +unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params); + +/* + * Generates a XMSS key pair for a given parameter set. + * Format sk: [(32bit) index || SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED], omitting algorithm OID. + */ +#define xmss_core_keypair XMSS_INNER_NAMESPACE(xmss_core_keypair) +int xmss_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk); + +/** + * Signs a message. Returns an array containing the signature followed by the + * message and an updated secret key. + */ +#define xmss_core_sign XMSS_INNER_NAMESPACE(xmss_core_sign) +int xmss_core_sign(const xmss_params *params, + unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen); + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +#define xmss_core_sign_open XMSS_INNER_NAMESPACE(xmss_core_sign_open) +int xmss_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +/* + * Generates a XMSSMT key pair for a given parameter set. + * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] omitting algorithm OID. + */ +#define xmssmt_core_keypair XMSS_INNER_NAMESPACE(xmssmt_core_keypair) +int xmssmt_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk); + +/* + * Derives a XMSSMT key pair for a given parameter set. + * Seed must be 3*n long. + * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || root || PUB_SEED] + * Format pk: [root || PUB_SEED] omitting algorithm OID. + */ +#define xmssmt_core_seed_keypair XMSS_INNER_NAMESPACE(xmssmt_core_seed_keypair) +int xmssmt_core_seed_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk, + unsigned char *seed); + +/** + * Signs a message. Returns an array containing the signature followed by the + * message and an updated secret key. + */ +#define xmssmt_core_sign XMSS_INNER_NAMESPACE(xmssmt_core_sign) +int xmssmt_core_sign(const xmss_params *params, + unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen); + +/** + * Verifies a given message signature pair under a given public key. + * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED] + */ +#define xmssmt_core_sign_open XMSS_INNER_NAMESPACE(xmssmt_core_sign_open) +int xmssmt_core_sign_open(const xmss_params *params, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk); + +#endif diff --git a/src/sig_stfl/xmss/external/xmss_core_fast.c b/src/sig_stfl/xmss/external/xmss_core_fast.c new file mode 100644 index 0000000000..9ad19e3908 --- /dev/null +++ b/src/sig_stfl/xmss/external/xmss_core_fast.c @@ -0,0 +1,1113 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include +#include +#include + +#include "hash.h" +#include "hash_address.h" +#include "params.h" +#include "wots.h" +#include "utils.h" +#include "xmss_commons.h" +#include "xmss_core.h" + +typedef struct{ + unsigned char h; + unsigned long long next_idx; + unsigned char stackusage; + unsigned char completed; + unsigned char *node; +} treehash_inst; + +typedef struct { + unsigned char *stack; + unsigned int stackoffset; + unsigned char *stacklevels; + unsigned char *auth; + unsigned char *keep; + treehash_inst *treehash; + unsigned char *retain; + unsigned long long next_leaf; +} bds_state; + +/* These serialization functions provide a transition between the current + way of storing the state in an exposed struct, and storing it as part of the + byte array that is the secret key. + They will probably be refactored in a non-backwards-compatible way, soon. */ + +static void xmssmt_serialize_state(const xmss_params *params, + unsigned char *sk, bds_state *states) +{ + unsigned int i, j; + + /* Skip past the 'regular' sk */ + sk += params->index_bytes + 4*params->n; + + for (i = 0; i < 2*params->d - 1; i++) { + sk += (params->tree_height + 1) * params->n; /* stack */ + + ull_to_bytes(sk, 4, states[i].stackoffset); + sk += 4; + + sk += params->tree_height + 1; /* stacklevels */ + sk += params->tree_height * params->n; /* auth */ + sk += (params->tree_height >> 1) * params->n; /* keep */ + + for (j = 0; j < params->tree_height - params->bds_k; j++) { + ull_to_bytes(sk, 1, states[i].treehash[j].h); + sk += 1; + + ull_to_bytes(sk, 4, states[i].treehash[j].next_idx); + sk += 4; + + ull_to_bytes(sk, 1, states[i].treehash[j].stackusage); + sk += 1; + + ull_to_bytes(sk, 1, states[i].treehash[j].completed); + sk += 1; + + sk += params->n; /* node */ + } + + /* retain */ + sk += ((1 << params->bds_k) - params->bds_k - 1) * params->n; + + ull_to_bytes(sk, 4, states[i].next_leaf); + sk += 4; + } +} + +static void xmssmt_deserialize_state(const xmss_params *params, + bds_state *states, + unsigned char **wots_sigs, + unsigned char *sk) +{ + unsigned int i, j; + + /* Skip past the 'regular' sk */ + sk += params->index_bytes + 4*params->n; + + // TODO (from upstream) These data sizes follow from the (former) test xmss_core_fast.c + // TODO (from upstream) They should be reconsidered / motivated more explicitly + + for (i = 0; i < 2*params->d - 1; i++) { + states[i].stack = sk; + sk += (params->tree_height + 1) * params->n; + + states[i].stackoffset = (unsigned int)bytes_to_ull(sk, 4); + sk += 4; + + states[i].stacklevels = sk; + sk += params->tree_height + 1; + + states[i].auth = sk; + sk += params->tree_height * params->n; + + states[i].keep = sk; + sk += (params->tree_height >> 1) * params->n; + + for (j = 0; j < params->tree_height - params->bds_k; j++) { + states[i].treehash[j].h = (unsigned char)bytes_to_ull(sk, 1); + sk += 1; + + states[i].treehash[j].next_idx = (unsigned long long)bytes_to_ull(sk, 4); + sk += 4; + + states[i].treehash[j].stackusage = (unsigned char)bytes_to_ull(sk, 1); + sk += 1; + + states[i].treehash[j].completed = (unsigned char)bytes_to_ull(sk, 1); + sk += 1; + + states[i].treehash[j].node = sk; + sk += params->n; + } + + states[i].retain = sk; + sk += ((1 << params->bds_k) - params->bds_k - 1) * params->n; + + states[i].next_leaf = (unsigned long long)bytes_to_ull(sk, 4); + sk += 4; + } + + if (params->d > 1) { + *wots_sigs = sk; + } +} + +static void xmss_serialize_state(const xmss_params *params, + unsigned char *sk, bds_state *state) +{ + xmssmt_serialize_state(params, sk, state); +} + +static void xmss_deserialize_state(const xmss_params *params, + bds_state *state, unsigned char *sk) +{ + xmssmt_deserialize_state(params, state, NULL, sk); +} + +static void memswap(void *a, void *b, void *t, unsigned long long len) +{ + memcpy(t, a, (size_t)len); + memcpy(a, b, (size_t)len); + memcpy(b, t, (size_t)len); +} + +/** + * Swaps the content of two bds_state objects, swapping actual memory rather + * than pointers. + * As we're mapping memory chunks in the secret key to bds state objects, + * it is now necessary to make swaps 'real swaps'. This could be done in the + * serialization function as well, but that causes more overhead + */ +// TODO (from upstream) this should not be necessary if we keep better track of the states +static void deep_state_swap(const xmss_params *params, + bds_state *a, bds_state *b) +{ + if (a->stack == NULL || b->stack == NULL) { + return; + } + // TODO (from upstream) this is extremely ugly and should be refactored + // TODO (from upstream) right now, this ensures that both 'stack' and 'retain' fit + const size_t t_size = ((params->tree_height + 1) > ((1 << params->bds_k) - params->bds_k - 1) + ? (params->tree_height + 1) + : ((1 << params->bds_k) - params->bds_k - 1)) + * params->n; + unsigned char *t = malloc(t_size); + if (t == NULL) { + return; + } + unsigned int i; + + memswap(a->stack, b->stack, t, (params->tree_height + 1) * params->n); + memswap(&a->stackoffset, &b->stackoffset, t, sizeof(a->stackoffset)); + memswap(a->stacklevels, b->stacklevels, t, params->tree_height + 1); + memswap(a->auth, b->auth, t, params->tree_height * params->n); + memswap(a->keep, b->keep, t, (params->tree_height >> 1) * params->n); + + for (i = 0; i < params->tree_height - params->bds_k; i++) { + memswap(&a->treehash[i].h, &b->treehash[i].h, t, sizeof(a->treehash[i].h)); + memswap(&a->treehash[i].next_idx, &b->treehash[i].next_idx, t, sizeof(a->treehash[i].next_idx)); + memswap(&a->treehash[i].stackusage, &b->treehash[i].stackusage, t, sizeof(a->treehash[i].stackusage)); + memswap(&a->treehash[i].completed, &b->treehash[i].completed, t, sizeof(a->treehash[i].completed)); + memswap(a->treehash[i].node, b->treehash[i].node, t, params->n); + } + + memswap(a->retain, b->retain, t, ((1 << params->bds_k) - params->bds_k - 1) * params->n); + memswap(&a->next_leaf, &b->next_leaf, t, sizeof(a->next_leaf)); + + OQS_MEM_secure_free(t, t_size); +} + +static int treehash_minheight_on_stack(const xmss_params *params, + bds_state *state, + const treehash_inst *treehash) +{ + unsigned int r = params->tree_height, i; + + for (i = 0; i < treehash->stackusage; i++) { + if (state->stacklevels[state->stackoffset - i - 1] < r) { + r = state->stacklevels[state->stackoffset - i - 1]; + } + } + return r; +} + +/** + * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash. + * Currently only used for key generation. + * + */ +static void treehash_init(const xmss_params *params, + unsigned char *node, int height, int index, + bds_state *state, const unsigned char *sk_seed, + const unsigned char *pub_seed, const uint32_t addr[8]) +{ + // use three different addresses because at this point we use all three formats in parallel + uint32_t ots_addr[8] = {0}; + uint32_t ltree_addr[8] = {0}; + uint32_t node_addr[8] = {0}; + // only copy layer and tree address parts + copy_subtree_addr(ots_addr, addr); + // type = ots + set_type(ots_addr, 0); + copy_subtree_addr(ltree_addr, addr); + set_type(ltree_addr, 1); + copy_subtree_addr(node_addr, addr); + set_type(node_addr, 2); + + /* The subtree has at most 2^20 leafs, so uint32_t suffices. */ + uint32_t idx = index; + uint32_t lastnode = index +(1<padding_len + 6 * params->n + 32; + const size_t stack_size = ((height+1)*params->n)* sizeof(unsigned char); + unsigned char *stack = calloc((height+1)*params->n, sizeof(unsigned char)); + unsigned int *stacklevels = malloc((height + 1)*sizeof(unsigned int)); + unsigned char *thash_buf = malloc(thash_buf_size); + + if (stack == NULL || stacklevels == NULL || thash_buf == NULL) { + return; + } + + unsigned int stackoffset=0; + unsigned int nodeh; + + for (i = 0; i < params->tree_height-params->bds_k; i++) { + state->treehash[i].h = i; + state->treehash[i].completed = 1; + state->treehash[i].stackusage = 0; + } + + i = 0; + for (; idx < lastnode; idx++) { + set_ltree_addr(ltree_addr, idx); + set_ots_addr(ots_addr, idx); + gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr); + stacklevels[stackoffset] = 0; + stackoffset++; + if (params->tree_height - params->bds_k > 0 && i == 3) { + memcpy(state->treehash[0].node, stack+stackoffset*params->n, params->n); + } + while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { + nodeh = stacklevels[stackoffset-1]; + if (i >> nodeh == 1) { + memcpy(state->auth + nodeh*params->n, stack+(stackoffset-1)*params->n, params->n); + } + else { + if (nodeh < params->tree_height - params->bds_k && i >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*params->n, params->n); + } + else if (nodeh >= params->tree_height - params->bds_k) { + memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((i >> nodeh) - 3) >> 1)) * params->n, stack+(stackoffset-1)*params->n, params->n); + } + } + set_tree_height(node_addr, stacklevels[stackoffset-1]); + set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); + thash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr, thash_buf); + stacklevels[stackoffset-2]++; + stackoffset--; + } + i++; + } + + memcpy(node, stack, params->n); + + OQS_MEM_insecure_free(stacklevels); + OQS_MEM_secure_free(stack, stack_size); + OQS_MEM_secure_free(thash_buf, thash_buf_size); +} + +static void treehash_update(const xmss_params *params, + treehash_inst *treehash, bds_state *state, + const unsigned char *sk_seed, + const unsigned char *pub_seed, + const uint32_t addr[8]) +{ + uint32_t ots_addr[8] = {0}; + uint32_t ltree_addr[8] = {0}; + uint32_t node_addr[8] = {0}; + // only copy layer and tree address parts + copy_subtree_addr(ots_addr, addr); + // type = ots + set_type(ots_addr, 0); + copy_subtree_addr(ltree_addr, addr); + set_type(ltree_addr, 1); + copy_subtree_addr(node_addr, addr); + set_type(node_addr, 2); + + set_ltree_addr(ltree_addr, treehash->next_idx); + set_ots_addr(ots_addr, treehash->next_idx); + + const size_t buf_size = 2 * params->n + 2 * params->padding_len + 6 * params->n + 32; + unsigned char *buf = malloc(buf_size); + if (buf == NULL) { + return; + } + unsigned char *nodebuffer = buf; + unsigned char *thash_buf = buf + 2 * params->n; + + unsigned int nodeheight = 0; + gen_leaf_wots(params, nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr); + while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { + memcpy(nodebuffer + params->n, nodebuffer, params->n); + memcpy(nodebuffer, state->stack + (state->stackoffset-1)*params->n, params->n); + set_tree_height(node_addr, nodeheight); + set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1))); + thash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr, thash_buf); + nodeheight++; + treehash->stackusage--; + state->stackoffset--; + } + if (nodeheight == treehash->h) { // this also implies stackusage == 0 + memcpy(treehash->node, nodebuffer, params->n); + treehash->completed = 1; + } + else { + memcpy(state->stack + state->stackoffset*params->n, nodebuffer, params->n); + treehash->stackusage++; + state->stacklevels[state->stackoffset] = nodeheight; + state->stackoffset++; + treehash->next_idx++; + } + + OQS_MEM_secure_free(buf, buf_size); +} + +/** + * Performs treehash updates on the instance that needs it the most. + * Returns the updated number of available updates. + **/ +static char bds_treehash_update(const xmss_params *params, + bds_state *state, unsigned int updates, + const unsigned char *sk_seed, + unsigned char *pub_seed, + const uint32_t addr[8]) +{ + uint32_t i, j; + unsigned int level, l_min, low; + unsigned int used = 0; + + for (j = 0; j < updates; j++) { + l_min = params->tree_height; + level = params->tree_height - params->bds_k; + for (i = 0; i < params->tree_height - params->bds_k; i++) { + if (state->treehash[i].completed) { + low = params->tree_height; + } + else if (state->treehash[i].stackusage == 0) { + low = i; + } + else { + low = treehash_minheight_on_stack(params, state, &(state->treehash[i])); + } + if (low < l_min) { + level = i; + l_min = low; + } + } + if (level == params->tree_height - params->bds_k) { + break; + } + treehash_update(params, &(state->treehash[level]), state, sk_seed, pub_seed, addr); + used++; + } + return updates - used; +} + +/** + * Updates the state (typically NEXT_i) by adding a leaf and updating the stack + * Returns -1 if all leaf nodes have already been processed + **/ +static char bds_state_update(const xmss_params *params, + bds_state *state, const unsigned char *sk_seed, + const unsigned char *pub_seed, + const uint32_t addr[8]) +{ + if (state == NULL || state->stacklevels == NULL) { + return -1; + } + + unsigned int nodeh; + int idx = state->next_leaf; + if (idx == 1 << params->tree_height) { + return -1; + } + + uint32_t ltree_addr[8] = {0}; + uint32_t node_addr[8] = {0}; + uint32_t ots_addr[8] = {0}; + const size_t thash_buf_size = 2 * params->padding_len + 6 * params->n + 32; + unsigned char *thash_buf = malloc(thash_buf_size); + if (thash_buf == NULL) + { + return -1; + } + + // only copy layer and tree address parts + copy_subtree_addr(ots_addr, addr); + // type = ots + set_type(ots_addr, 0); + copy_subtree_addr(ltree_addr, addr); + set_type(ltree_addr, 1); + copy_subtree_addr(node_addr, addr); + set_type(node_addr, 2); + + set_ots_addr(ots_addr, idx); + set_ltree_addr(ltree_addr, idx); + + gen_leaf_wots(params, state->stack+state->stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr); + + state->stacklevels[state->stackoffset] = 0; + state->stackoffset++; + if (params->tree_height - params->bds_k > 0 && idx == 3) { + memcpy(state->treehash[0].node, state->stack+state->stackoffset*params->n, params->n); + } + while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) { + nodeh = state->stacklevels[state->stackoffset-1]; + if (idx >> nodeh == 1) { + memcpy(state->auth + nodeh*params->n, state->stack+(state->stackoffset-1)*params->n, params->n); + } + else { + if (nodeh < params->tree_height - params->bds_k && idx >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*params->n, params->n); + } + else if (nodeh >= params->tree_height - params->bds_k) { + memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((idx >> nodeh) - 3) >> 1)) * params->n, state->stack+(state->stackoffset-1)*params->n, params->n); + } + } + set_tree_height(node_addr, state->stacklevels[state->stackoffset-1]); + set_tree_index(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); + thash_h(params, state->stack+(state->stackoffset-2)*params->n, state->stack+(state->stackoffset-2)*params->n, pub_seed, node_addr, thash_buf); + + state->stacklevels[state->stackoffset-2]++; + state->stackoffset--; + } + state->next_leaf++; + + OQS_MEM_secure_free(thash_buf, thash_buf_size); + return 0; +} + +/** + * Returns the auth path for node leaf_idx and computes the auth path for the + * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo + * in "Post Quantum Cryptography", Springer 2009. + */ +static void bds_round(const xmss_params *params, + bds_state *state, const unsigned long leaf_idx, + const unsigned char *sk_seed, + const unsigned char *pub_seed, uint32_t addr[8]) +{ + unsigned int i; + unsigned int tau = params->tree_height; + unsigned int startidx; + unsigned int offset, rowidx; + const size_t buf_size = 2 * params->n + 2 * params->padding_len + 6 * params->n + 32; + unsigned char *buf = malloc(buf_size); + if (buf == NULL) { + return; + } + unsigned char *thash_buf = buf + 2 * params->n; + + uint32_t ots_addr[8] = {0}; + uint32_t ltree_addr[8] = {0}; + uint32_t node_addr[8] = {0}; + + // only copy layer and tree address parts + copy_subtree_addr(ots_addr, addr); + // type = ots + set_type(ots_addr, 0); + copy_subtree_addr(ltree_addr, addr); + set_type(ltree_addr, 1); + copy_subtree_addr(node_addr, addr); + set_type(node_addr, 2); + + for (i = 0; i < params->tree_height; i++) { + if (! ((leaf_idx >> i) & 1)) { + tau = i; + break; + } + } + + if (tau > 0) { + memcpy(buf, state->auth + (tau-1) * params->n, params->n); + // we need to do this before refreshing state->keep to prevent overwriting + memcpy(buf + params->n, state->keep + ((tau-1) >> 1) * params->n, params->n); + } + if (!((leaf_idx >> (tau + 1)) & 1) && (tau < params->tree_height - 1)) { + memcpy(state->keep + (tau >> 1)*params->n, state->auth + tau*params->n, params->n); + } + if (tau == 0) { + set_ltree_addr(ltree_addr, leaf_idx); + set_ots_addr(ots_addr, leaf_idx); + gen_leaf_wots(params, state->auth, sk_seed, pub_seed, ltree_addr, ots_addr); + } + else { + set_tree_height(node_addr, (tau-1)); + set_tree_index(node_addr, leaf_idx >> tau); + thash_h(params, state->auth + tau * params->n, buf, pub_seed, node_addr, thash_buf); + for (i = 0; i < tau; i++) { + if (i < params->tree_height - params->bds_k) { + memcpy(state->auth + i * params->n, state->treehash[i].node, params->n); + } + else { + offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height; + rowidx = ((leaf_idx >> i) - 1) >> 1; + memcpy(state->auth + i * params->n, state->retain + (offset + rowidx) * params->n, params->n); + } + } + + for (i = 0; i < ((tau < params->tree_height - params->bds_k) ? tau : (params->tree_height - params->bds_k)); i++) { + startidx = leaf_idx + 1 + 3 * (1 << i); + if (startidx < 1U << params->tree_height) { + state->treehash[i].h = i; + state->treehash[i].next_idx = startidx; + state->treehash[i].completed = 0; + state->treehash[i].stackusage = 0; + } + } + } + + OQS_MEM_secure_free(buf, buf_size); +} + +/** + * Given a set of parameters, this function returns the size of the secret key. + * This is implementation specific, as varying choices in tree traversal will + * result in varying requirements for state storage. + * + * This function handles both XMSS and XMSSMT parameter sets. + */ +unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) +{ + return params->index_bytes + 4 * params->n + + (2 * params->d - 1) * ( + (params->tree_height + 1) * params->n + + 4 + + params->tree_height + 1 + + params->tree_height * params->n + + (params->tree_height >> 1) * params->n + + (params->tree_height - params->bds_k) * (7 + params->n) + + ((1 << params->bds_k) - params->bds_k - 1) * params->n + + 4 + ) + + (params->d - 1) * params->wots_sig_bytes; +} + +/* + * Generates a XMSS key pair for a given parameter set. + * Format sk: [(32bit) idx || SK_SEED || SK_PRF || root || PUB_SEED] + * Format pk: [root || PUB_SEED] omitting algo oid. + */ +int xmss_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk) +{ + uint32_t addr[8] = {0}; + + // TODO (from upstream) refactor BDS state not to need separate treehash instances + bds_state state; + const size_t treehash_size = (params->tree_height - params->bds_k)*sizeof(treehash_inst); + treehash_inst *treehash = calloc(params->tree_height - params->bds_k, sizeof(treehash_inst)); + if (treehash == NULL) { + return -1; + } + state.treehash = treehash; + + xmss_deserialize_state(params, &state, sk); + + state.stackoffset = 0; + state.next_leaf = 0; + + // Set idx = 0 + sk[0] = 0; + sk[1] = 0; + sk[2] = 0; + sk[3] = 0; + // Init SK_SEED (n byte) and SK_PRF (n byte) + OQS_randombytes(sk + params->index_bytes, 2*params->n); + + // Init PUB_SEED (n byte) + OQS_randombytes(sk + params->index_bytes + 3*params->n, params->n); + // Copy PUB_SEED to public key + memcpy(pk + params->n, sk + params->index_bytes + 3*params->n, params->n); + + // Compute root + treehash_init(params, pk, params->tree_height, 0, &state, sk + params->index_bytes, sk + params->index_bytes + 3*params->n, addr); + // copy root to sk + memcpy(sk + params->index_bytes + 2*params->n, pk, params->n); + + /* Write the BDS state into sk. */ + xmss_serialize_state(params, sk, &state); + + OQS_MEM_secure_free(treehash, treehash_size); + + return 0; +} + +/** + * Signs a message. + * Returns + * 1. an array containing the signature followed by the message AND + * 2. an updated secret key! + * + */ +int xmss_core_sign(const xmss_params *params, + unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen) +{ + if (params->full_height > 60) { + // Unsupport Tree height + return -2; + } + + const unsigned char *pub_root = sk + params->index_bytes + 2*params->n; + int ret; + + uint16_t i = 0; + + // TODO (from upstream) refactor BDS state not to need separate treehash instances + bds_state state; + const size_t treehash_size = (params->tree_height - params->bds_k) * sizeof(treehash_inst); + const size_t tmp_size = 5 * params->n + params->padding_len + params->n + 32; + treehash_inst *treehash = calloc(params->tree_height - params->bds_k, sizeof(treehash_inst)); + unsigned char *tmp = malloc(tmp_size); + if (treehash == NULL || tmp == NULL) { + return -1; + } + + state.treehash = treehash; + /* Load the BDS state from sk. */ + xmss_deserialize_state(params, &state, sk); + + // Extract SK + unsigned long long idx = ((unsigned long long)sk[0] << 24) | ((unsigned long long)sk[1] << 16) | ((unsigned long long)sk[2] << 8) | sk[3]; + + /* Check if we can still sign with this sk. + * If not, return -2 + * + * If this is the last possible signature (because the max index value + * is reached), production implementations should delete the secret key + * to prevent accidental further use. + * + * For the case of total tree height of 64 we do not use the last signature + * to be on the safe side (there is no index value left to indicate that the + * key is finished, hence external handling would be necessary) + */ + if (idx >= ((1ULL << params->full_height) - 1)) { + // Delete secret key here. We only do this in memory, production code + // has to make sure that this happens on disk. + memset(sk, 0xFF, params->index_bytes); + memset(sk + params->index_bytes, 0, (size_t)(params->sk_bytes - params->index_bytes)); + if (idx > ((1ULL << params->full_height) - 1)) { + ret = -2; // We already used all one-time keys + goto cleanup; + } + } + + unsigned char *sk_seed = tmp; + unsigned char *sk_prf = sk_seed + params->n; + unsigned char *pub_seed = sk_prf + params->n; + + memcpy(sk_seed, sk + params->index_bytes, params->n); + memcpy(sk_prf, sk + params->index_bytes + params->n, params->n); + memcpy(pub_seed, sk + params->index_bytes + 3*params->n, params->n); + + // index as 32 bytes string + unsigned char idx_bytes_32[32]; + ull_to_bytes(idx_bytes_32, 32, idx); + + // Update SK + sk[0] = ((idx + 1) >> 24) & 255; + sk[1] = ((idx + 1) >> 16) & 255; + sk[2] = ((idx + 1) >> 8) & 255; + sk[3] = (idx + 1) & 255; + // Secret key for this non-forward-secure version is now updated. + // A production implementation should consider using a file handle instead, + // and write the updated secret key at this point! + + // Init working params + unsigned char *R = pub_seed + params->n; + unsigned char *msg_h = R + params->n; + unsigned char *prf_buf = msg_h + params->n; + uint32_t ots_addr[8] = {0}; + + // --------------------------------- + // Message Hashing + // --------------------------------- + + // Message Hash: + // First compute pseudorandom value + prf(params, R, idx_bytes_32, sk_prf, prf_buf); + + /* Already put the message in the right place, to make it easier to prepend + * things when computing the hash over the message. */ + unsigned long long prefix_length = params->padding_len + 3*params->n; + unsigned char *m_with_prefix = malloc((size_t)(mlen + prefix_length)); + if (m_with_prefix == NULL) { + ret = -1; + goto cleanup; + } + memcpy(m_with_prefix, sm + params->sig_bytes - prefix_length, (size_t)prefix_length); + memcpy(m_with_prefix + prefix_length, m, (size_t)mlen); + + /* Compute the message hash. */ + hash_message(params, msg_h, R, pub_root, idx, + m_with_prefix, + mlen); + + // Start collecting signature + *smlen = 0; + + // Copy index to signature + sm[0] = (idx >> 24) & 255; + sm[1] = (idx >> 16) & 255; + sm[2] = (idx >> 8) & 255; + sm[3] = idx & 255; + + sm += 4; + *smlen += 4; + + // Copy R to signature + for (i = 0; i < params->n; i++) { + sm[i] = R[i]; + } + + sm += params->n; + *smlen += params->n; + + // ---------------------------------- + // Now we start to "really sign" + // ---------------------------------- + + // Prepare Address + set_type(ots_addr, 0); + set_ots_addr(ots_addr, (uint32_t) idx); + + // Compute WOTS signature + wots_sign(params, sm, msg_h, sk_seed, pub_seed, ots_addr); + + sm += params->wots_sig_bytes; + *smlen += params->wots_sig_bytes; + + // the auth path was already computed during the previous round + memcpy(sm, state.auth, params->tree_height*params->n); + + if (idx < (1ULL << params->tree_height) - 1) { + bds_round(params, &state, (const unsigned long)idx, sk_seed, pub_seed, ots_addr); + bds_treehash_update(params, &state, (params->tree_height - params->bds_k) >> 1, sk_seed, pub_seed, ots_addr); + } + + *smlen += params->tree_height*params->n; + + /* Write the updated BDS state back into sk. */ + xmss_serialize_state(params, sk, &state); + + ret = 0; + + OQS_MEM_insecure_free(m_with_prefix); + +cleanup: + OQS_MEM_secure_free(tmp, tmp_size); + OQS_MEM_secure_free(treehash, treehash_size); + + return ret; +} + +/* + * Generates a XMSSMT key pair for a given parameter set. + * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || root || PUB_SEED] + * Format pk: [root || PUB_SEED] omitting algo oid. + */ +int xmssmt_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk) +{ + uint32_t addr[8] = {0}; + unsigned int i; + unsigned char *wots_sigs; + + // TODO (from upstream) refactor BDS state not to need separate treehash instances + const size_t states_size = (2*params->d - 1)* sizeof(bds_state); + const size_t treehash_size = ((2*params->d - 1) * (params->tree_height - params->bds_k))* sizeof(treehash_inst); + bds_state *states = calloc(2*params->d - 1, sizeof(bds_state)); + treehash_inst *treehash = calloc((2*params->d - 1) * (params->tree_height - params->bds_k), sizeof(treehash_inst)); + if (states == NULL || treehash == NULL) { + return -1; + } + for (i = 0; i < 2*params->d - 1; i++) { + states[i].treehash = treehash + i * (params->tree_height - params->bds_k); + } + + xmssmt_deserialize_state(params, states, &wots_sigs, sk); + + for (i = 0; i < 2 * params->d - 1; i++) { + states[i].stackoffset = 0; + states[i].next_leaf = 0; + } + + // Set idx = 0 + for (i = 0; i < params->index_bytes; i++) { + sk[i] = 0; + } + // Init SK_SEED (params->n byte) and SK_PRF (params->n byte) + OQS_randombytes(sk+params->index_bytes, 2*params->n); + + // Init PUB_SEED (params->n byte) + OQS_randombytes(sk+params->index_bytes + 3*params->n, params->n); + // Copy PUB_SEED to public key + memcpy(pk+params->n, sk+params->index_bytes+3*params->n, params->n); + + // Start with the bottom-most layer + set_layer_addr(addr, 0); + // Set up state and compute wots signatures for all but topmost tree root + for (i = 0; i < params->d - 1; i++) { + // Compute seed for OTS key pair + treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_bytes, pk+params->n, addr); + set_layer_addr(addr, (i+1)); + wots_sign(params, wots_sigs + i*params->wots_sig_bytes, pk, sk + params->index_bytes, pk+params->n, addr); + } + // Address now points to the single tree on layer d-1 + treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_bytes, pk+params->n, addr); + memcpy(sk + params->index_bytes + 2*params->n, pk, params->n); + + xmssmt_serialize_state(params, sk, states); + + OQS_MEM_secure_free(treehash, treehash_size); + OQS_MEM_secure_free(states, states_size); + + return 0; +} + +/** + * Signs a message. + * Returns + * 1. an array containing the signature followed by the message AND + * 2. an updated secret key! + * + */ +int xmssmt_core_sign(const xmss_params *params, + unsigned char *sk, + unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen) +{ + if (params == NULL || params->full_height > 60) { + // Unsupport parameter + return -1; + } + + const unsigned char *pub_root = sk + params->index_bytes + 2*params->n; + + uint64_t idx_tree; + uint32_t idx_leaf; + unsigned int i, j; + int needswap_upto = -1; + unsigned int updates; + + // TODO (from upstream) refactor BDS state not to need separate treehash instances + const size_t states_size = (2*params->d - 1)* sizeof(bds_state); + const size_t treehash_size = (2*params->d - 1) * (params->tree_height - params->bds_k) * sizeof(treehash_inst); + const size_t tmp_size = 5 * params->n + + params->padding_len + params->n + 32; + bds_state *states = calloc(2*params->d - 1, sizeof(bds_state)); + treehash_inst *treehash = calloc((2*params->d - 1) * (params->tree_height - params->bds_k), sizeof(treehash_inst)); + unsigned char *tmp = malloc(5 * params->n + + params->padding_len + params->n + 32); + if (states == NULL || treehash == NULL || tmp == NULL) { + return -1; + } + unsigned char *sk_seed = tmp; + unsigned char *sk_prf = sk_seed + params->n; + unsigned char *pub_seed = sk_prf + params->n; + // Init working params + unsigned char *R = pub_seed + params->n; + unsigned char *msg_h = R + params->n; + unsigned char *prf_buf = msg_h + params->n; + uint32_t addr[8] = {0}; + uint32_t ots_addr[8] = {0}; + unsigned char idx_bytes_32[32]; + + unsigned char *wots_sigs = NULL; + unsigned long long prefix_length = params->padding_len + 3*params->n; + unsigned long long m_with_prefix_len = mlen + prefix_length; + unsigned char *m_with_prefix = NULL; + int ret = 0; + + for (i = 0; i < 2*params->d - 1; i++) { + states[i].stack = NULL; + states[i].stackoffset = 0; + states[i].stacklevels = NULL; + states[i].auth = NULL; + states[i].keep = NULL; + states[i].treehash = treehash + i * (params->tree_height - params->bds_k); + states[i].retain = NULL; + states[i].next_leaf = 0; + } + + if ((m_with_prefix_len == 0) || (m_with_prefix = malloc(m_with_prefix_len)) == NULL) { + ret = -1; + goto cleanup; + } + + xmssmt_deserialize_state(params, states, &wots_sigs, sk); + + // Extract SK + unsigned long long idx = 0; + for (i = 0; i < params->index_bytes; i++) { + idx |= ((unsigned long long)sk[i]) << 8*(params->index_bytes - 1 - i); + } + + /* Check if we can still sign with this sk. + * If not, return -2 + * + * If this is the last possible signature (because the max index value + * is reached), production implementations should delete the secret key + * to prevent accidental further use. + * + * For the case of total tree height of 64 we do not use the last signature + * to be on the safe side (there is no index value left to indicate that the + * key is finished, hence external handling would be necessary) + */ + if (idx >= ((1ULL << params->full_height) - 1)) { + // Delete secret key here. We only do this in memory, production code + // has to make sure that this happens on disk. + memset(sk, 0xFF, params->index_bytes); + memset(sk + params->index_bytes, 0, (size_t)(params->sk_bytes - params->index_bytes)); + if (idx > ((1ULL << params->full_height) - 1)) { + // We already used all one-time keys + ret = -2; + goto cleanup; + } + } + + memcpy(sk_seed, sk+params->index_bytes, (size_t)params->n); + memcpy(sk_prf, sk+params->index_bytes+params->n, (size_t)params->n); + memcpy(pub_seed, sk+params->index_bytes+3*params->n, (size_t)params->n); + + // Update SK + for (i = 0; i < params->index_bytes; i++) { + sk[i] = ((idx + 1) >> 8*(params->index_bytes - 1 - i)) & 255; + } + // Secret key for this non-forward-secure version is now updated. + // A production implementation should consider using a file handle instead, + // and write the updated secret key at this point! + + // --------------------------------- + // Message Hashing + // --------------------------------- + + // Message Hash: + // First compute pseudorandom value + ull_to_bytes(idx_bytes_32, 32, idx); + prf(params, R, idx_bytes_32, sk_prf, prf_buf); + + /* Already put the message in the right place, to make it easier to prepend + * things when computing the hash over the message. */ + memcpy(m_with_prefix, sm + params->sig_bytes - prefix_length, prefix_length); + memcpy(m_with_prefix + prefix_length, m, mlen); + + /* Compute the message hash. */ + hash_message(params, msg_h, R, pub_root, idx, + m_with_prefix, + mlen); + + // Start collecting signature + *smlen = 0; + + // Copy index to signature + for (i = 0; i < params->index_bytes; i++) { + sm[i] = (idx >> 8*(params->index_bytes - 1 - i)) & 255; + } + + sm += params->index_bytes; + *smlen += params->index_bytes; + + // Copy R to signature + for (i = 0; i < params->n; i++) { + sm[i] = R[i]; + } + + sm += params->n; + *smlen += params->n; + + // ---------------------------------- + // Now we start to "really sign" + // ---------------------------------- + + // Handle lowest layer separately as it is slightly different... + + // Prepare Address + set_type(ots_addr, 0); + idx_tree = idx >> params->tree_height; + idx_leaf = (idx & ((1 << params->tree_height)-1)); + set_layer_addr(ots_addr, 0); + set_tree_addr(ots_addr, idx_tree); + set_ots_addr(ots_addr, idx_leaf); + + // Compute WOTS signature + wots_sign(params, sm, msg_h, sk_seed, pub_seed, ots_addr); + + sm += params->wots_sig_bytes; + *smlen += params->wots_sig_bytes; + + memcpy(sm, states[0].auth, params->tree_height*params->n); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; + + // prepare signature of remaining layers + for (i = 1; i < params->d; i++) { + // put WOTS signature in place + memcpy(sm, wots_sigs + (i-1)*params->wots_sig_bytes, params->wots_sig_bytes); + + sm += params->wots_sig_bytes; + *smlen += params->wots_sig_bytes; + + // put AUTH nodes in place + if (states[i].auth == NULL) { + ret = -1; + goto cleanup; + } + memcpy(sm, states[i].auth, params->tree_height*params->n); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; + } + + updates = (params->tree_height - params->bds_k) >> 1; + + set_tree_addr(addr, (idx_tree + 1)); + // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists + if ((1 + idx_tree) * (1ULL << params->tree_height) + idx_leaf < (1ULL << (unsigned long long) params->full_height)) { + bds_state_update(params, &states[params->d], sk_seed, pub_seed, addr); + } + + for (i = 0; i < params->d; i++) { + // check if we're not at the end of a tree + if (! (((idx + 1) & ((1ULL << ((i+1)*params->tree_height)) - 1)) == 0)) { + idx_leaf = (uint32_t)((idx >> (params->tree_height * i)) & ((1 << params->tree_height)-1)); + idx_tree = (idx >> (params->tree_height * (i+1))); + set_layer_addr(addr, i); + set_tree_addr(addr, (uint32_t)idx_tree); + if (i == (unsigned int) (needswap_upto + 1)) { + bds_round(params, &states[i], idx_leaf, sk_seed, pub_seed, addr); + } + updates = bds_treehash_update(params, &states[i], updates, sk_seed, pub_seed, addr); + set_tree_addr(addr, (idx_tree + 1)); + // if a NEXT-tree exists for this level; + if ((1 + idx_tree) * (1ULL << params->tree_height) + idx_leaf < (1ULL << (params->full_height - params->tree_height * i))) { + if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << params->full_height)) { + bds_state_update(params, &states[params->d + i], sk_seed, pub_seed, addr); + updates--; + } + } + } + else if (idx < (1ULL << params->full_height) - 1) { + deep_state_swap(params, &states[params->d + i], &states[i]); + + set_layer_addr(ots_addr, (uint32_t)(i+1)); + set_tree_addr(ots_addr, ((idx + 1) >> ((i+2) * params->tree_height))); + set_ots_addr(ots_addr, (((idx >> ((i+1) * params->tree_height)) + 1) & ((1ULL << params->tree_height)-1))); + + wots_sign(params, wots_sigs + i*params->wots_sig_bytes, states[i].stack, sk_seed, pub_seed, ots_addr); + + states[params->d + i].stackoffset = 0; + states[params->d + i].next_leaf = 0; + + updates--; // WOTS-signing counts as one update + needswap_upto = (int)i; + for (j = 0; j < params->tree_height-params->bds_k; j++) { + states[i].treehash[j].completed = 1; + } + } + } + + xmssmt_serialize_state(params, sk, states); + +cleanup: + OQS_MEM_secure_free(treehash, treehash_size); + OQS_MEM_secure_free(states, states_size); + OQS_MEM_secure_free(tmp, tmp_size); + OQS_MEM_insecure_free(m_with_prefix); + + return ret; +} diff --git a/src/sig_stfl/xmss/sig_stfl_xmss.h b/src/sig_stfl/xmss/sig_stfl_xmss.h new file mode 100644 index 0000000000..a6d0aad55b --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss.h @@ -0,0 +1,590 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#ifndef OQS_SIG_STFL_XMSS_H +#define OQS_SIG_STFL_XMSS_H + +#include +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +#define XMSS_OID_LEN 4 + +/* + * | Algorithms | oid | sk (b) | pk (b) | sig (b) | n | + * |-------------------------------|------|--------|--------|---------|----| + * | XMSS-SHA2_10_256 | 0x01 | 1373 | 64 | 2500 | 32 | + * | XMSS-SHA2_16_256 | 0x02 | 2093 | 64 | 2692 | 32 | + * | XMSS-SHA2_20_256 | 0x03 | 2573 | 64 | 2820 | 32 | + * + * | XMSS-SHAKE_10_256 | 0x07 | 1373 | 64 | 2500 | 32 | + * | XMSS-SHAKE_16_256 | 0x08 | 2093 | 64 | 2692 | 32 | + * | XMSS-SHAKE_20_256 | 0x09 | 2573 | 64 | 2820 | 32 | + * + * | XMSS-SHA2_10_512 | 0x04 | 2653 | 128 | 9092 | 64 | + * | XMSS-SHA2_16_512 | 0x05 | 4045 | 128 | 9476 | 64 | + * | XMSS-SHA2_20_512 | 0x06 | 4973 | 128 | 9732 | 64 | + * + * | XMSS-SHAKE_10_512 | 0x0a | 2653 | 128 | 9092 | 64 | + * | XMSS-SHAKE_16_512 | 0x0b | 4045 | 128 | 9476 | 64 | + * | XMSS-SHAKE_20_512 | 0x0c | 4973 | 128 | 9732 | 64 | + * + * | XMSSMT-SHA2_20/2_256 | 0x01 | 5998 | 64 | 4963 | 32 | + * | XMSSMT-SHA2_20/4_256 | 0x02 | 10938 | 64 | 9251 | 32 | + * | XMSSMT-SHA2_40/2_256 | 0x03 | 9600 | 64 | 5605 | 32 | + * | XMSSMT-SHA2_40/4_256 | 0x04 | 15252 | 64 | 9893 | 32 | + * | XMSSMT-SHA2_40/8_256 | 0x05 | 24516 | 64 | 18469 | 32 | + * | XMSSMT-SHA2_60/3_256 | 0x06 | 16629 | 64 | 8392 | 32 | + * | XMSSMT-SHA2_60/6_256 | 0x07 | 24507 | 64 | 14824 | 32 | + * | XMSSMT-SHA2_60/12_256 | 0x08 | 38095 | 64 | 27688 | 32 | + * + * | XMSSMT-SHAKE_20/2_256 | 0x11 | 5998 | 64 | 4963 | 32 | + * | XMSSMT-SHAKE_20/4_256 | 0x12 | 10938 | 64 | 9251 | 32 | + * | XMSSMT-SHAKE_40/2_256 | 0x13 | 9600 | 64 | 5605 | 32 | + * | XMSSMT-SHAKE_40/4_256 | 0x14 | 15252 | 64 | 9893 | 32 | + * | XMSSMT-SHAKE_40/8_256 | 0x15 | 24516 | 64 | 18469 | 32 | + * | XMSSMT-SHAKE_60/3_256 | 0x16 | 16629 | 64 | 8392 | 32 | + * | XMSSMT-SHAKE_60/6_256 | 0x17 | 24507 | 64 | 14824 | 32 | + * | XMSSMT-SHAKE_60/12_256 | 0x18 | 38095 | 64 | 27688 | 32 | + */ + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h10 + +#define OQS_SIG_STFL_alg_xmss_sha256_h10_oid 0x01 +#define OQS_SIG_STFL_alg_xmss_sha256_h10_length_sk (1373 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h10_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h10_length_signature 2500 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha256_h10_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA256_H10_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h10_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h10_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h10_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h10_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h10_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h16 + +#define OQS_SIG_STFL_alg_xmss_sha256_h16_oid 0x02 +#define OQS_SIG_STFL_alg_xmss_sha256_h16_length_sk (2093 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h16_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h16_length_signature 2692 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha256_h16_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA256_H16_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h16_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h16_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h16_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h16_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h16_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h20 + +#define OQS_SIG_STFL_alg_xmss_sha256_h20_oid 0x03 +#define OQS_SIG_STFL_alg_xmss_sha256_h20_length_sk (2573 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h20_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha256_h20_length_signature 2820 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha256_h20_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA256_H20_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h20_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h20_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h20_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h20_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha256_h20_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h10 + +#define OQS_SIG_STFL_alg_xmss_shake128_h10_oid 0x07 +#define OQS_SIG_STFL_alg_xmss_shake128_h10_length_sk (1373 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h10_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h10_length_signature 2500 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake128_h10_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE128_H10_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h10_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h10_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h10_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h10_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h10_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h16 + +#define OQS_SIG_STFL_alg_xmss_shake128_h16_oid 0x08 +#define OQS_SIG_STFL_alg_xmss_shake128_h16_length_sk (2093 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h16_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h16_length_signature 2692 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake128_h16_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE128_H16_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h16_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h16_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h16_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h16_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h16_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h20 + +#define OQS_SIG_STFL_alg_xmss_shake128_h20_oid 0x09 +#define OQS_SIG_STFL_alg_xmss_shake128_h20_length_sk (2573 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h20_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake128_h20_length_signature 2820 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake128_h20_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE128_H20_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h20_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h20_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h20_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h20_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake128_h20_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h10 + +#define OQS_SIG_STFL_alg_xmss_sha512_h10_oid 0x04 +#define OQS_SIG_STFL_alg_xmss_sha512_h10_length_sk (2653 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h10_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h10_length_signature 9092 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha512_h10_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA512_H10_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h10_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h10_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h10_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h10_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h10_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h16 + +#define OQS_SIG_STFL_alg_xmss_sha512_h16_oid 0x05 +#define OQS_SIG_STFL_alg_xmss_sha512_h16_length_sk (4045 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h16_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h16_length_signature 9476 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha512_h16_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA512_H16_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h16_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h16_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h16_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h16_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h16_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h20 + +#define OQS_SIG_STFL_alg_xmss_sha512_h20_oid 0x06 +#define OQS_SIG_STFL_alg_xmss_sha512_h20_length_sk (4973 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h20_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_sha512_h20_length_signature 9732 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_sha512_h20_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHA512_H20_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h20_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h20_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h20_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h20_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sha512_h20_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h10 + +#define OQS_SIG_STFL_alg_xmss_shake256_h10_oid 0x0a +#define OQS_SIG_STFL_alg_xmss_shake256_h10_length_sk (2653 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h10_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h10_length_signature 9092 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake256_h10_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE256_H10_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h10_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h10_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h10_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h10_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h10_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h16 + +#define OQS_SIG_STFL_alg_xmss_shake256_h16_oid 0x0b +#define OQS_SIG_STFL_alg_xmss_shake256_h16_length_sk (4045 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h16_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h16_length_signature 9476 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake256_h16_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE256_H16_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h16_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h16_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h16_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h16_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h16_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h20 + +#define OQS_SIG_STFL_alg_xmss_shake256_h20_oid 0x0c +#define OQS_SIG_STFL_alg_xmss_shake256_h20_length_sk (4973 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h20_length_pk (128 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmss_shake256_h20_length_signature 9732 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss_shake256_h20_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_SHAKE256_H20_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h20_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h20_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h20_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h20_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_shake256_h20_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_2 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_oid 0x01 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_length_sk (5998 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_length_signature 4963 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H20_2_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_2_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h20_4 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_oid 0x02 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_length_sk (10938 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_length_signature 9251 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H20_4_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h20_4_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_oid 0x03 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_length_sk (9600 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_length_signature 5605 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H40_2_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_2_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_4 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_oid 0x04 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_length_sk (15252 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_length_signature 9893 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H40_4_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_4_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_8 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_oid 0x05 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_length_sk (24516 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_length_signature 18469 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H40_8_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h40_8_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_oid 0x06 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_length_sk (16629 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_length_signature 8392 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H60_3_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_3_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_6 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_oid 0x07 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_length_sk (24507 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_length_signature 14824 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H60_6_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_6_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_12 + +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_oid 0x08 +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_length_sk (38095 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_length_signature 27688 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHA256_H60_12_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sha256_h60_12_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_2 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_oid 0x11 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_length_sk (5998 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_length_signature 4963 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H20_2_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_2_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h20_4 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_oid 0x12 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_length_sk (10938 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_length_signature 9251 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H20_4_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h20_4_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_oid 0x13 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_length_sk (9600 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_length_signature 5605 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_2_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_2_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_4 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_oid 0x14 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_length_sk (15252 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_length_signature 9893 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_4_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_4_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_8 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_oid 0x15 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_length_sk (24516 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_length_signature 18469 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H40_8_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h40_8_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_oid 0x16 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_length_sk (16629 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_length_signature 8392 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_3_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_3_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_oid 0x17 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_length_sk (24507 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_length_signature 14824 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_6_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_6_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 + +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_oid 0x18 +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_length_sk (38095 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_length_pk (64 + XMSS_OID_LEN) +#define OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_length_signature 27688 + +OQS_API OQS_SIG_STFL *OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_new(void); +OQS_API OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSSMT_SHAKE128_H60_12_new(void); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_keypair(uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_shake128_h60_12_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#endif + +#define __alg_xmss_XMSS(funcname, postfix) funcname##_##postfix +#define _alg_xmss_XMSS(funcname, postfix) __alg_xmss_XMSS(funcname, postfix) +#define OQS_SIG_STFL_alg_xmss_NAMESPACE(funcname) _alg_xmss_XMSS(funcname, XMSS_PARAMS_NAMESPACE) + +/* + * Generic XMSS APIs + */ +#define OQS_SIG_STFL_alg_xmss_sign OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmss_sign) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key); + +#define OQS_SIG_STFL_alg_xmss_verify OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmss_verify) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key); + +#define OQS_SIG_STFL_alg_xmss_sigs_remaining OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmss_sigs_remaining) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#define OQS_SIG_STFL_alg_xmss_sigs_total OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmss_sigs_total) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +/* + * Generic XMSS^MT APIs + */ +#define OQS_SIG_STFL_alg_xmssmt_sign OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmssmt_sign) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key); + +#define OQS_SIG_STFL_alg_xmssmt_verify OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmssmt_verify) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key); + +#define OQS_SIG_STFL_alg_xmssmt_sigs_remaining OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmssmt_sigs_remaining) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +#define OQS_SIG_STFL_alg_xmssmt_sigs_total OQS_SIG_STFL_alg_xmss_NAMESPACE(OQS_SIG_STFL_alg_xmssmt_sigs_total) +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key); + +/* + * Secret key functions + */ +/* Generic XMSS SECRET_KEY object initialization */ +OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_new(size_t length_secret_key); + +/* Serialize XMSS secret key data into a byte string, and return an allocated buffer. Users must deallocate the buffer. */ +OQS_STATUS OQS_SECRET_KEY_XMSS_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk); + +/* Only for internal use. Similar to OQS_SECRET_KEY_XMSS_serialize_key, this function does not acquire and release a lock. */ +OQS_STATUS OQS_SECRET_KEY_XMSS_inner_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk); + +/* Deserialize XMSS byte string into an XMSS secret key data */ +OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, void *context); + +/* Store Secret Key Function, ideally written to secure device */ +void OQS_SECRET_KEY_XMSS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context); + +/* Free Secret key object */ +void OQS_SECRET_KEY_XMSS_free(OQS_SIG_STFL_SECRET_KEY *sk); + +/* Lock the key if possible */ +OQS_STATUS OQS_SECRET_KEY_XMSS_acquire_lock(const OQS_SIG_STFL_SECRET_KEY *sk); + +/* Unlock the key if possible */ +OQS_STATUS OQS_SECRET_KEY_XMSS_release_lock(const OQS_SIG_STFL_SECRET_KEY *sk); + +#endif /* OQS_SIG_STFL_XMSS_H */ diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_functions.c b/src/sig_stfl/xmss/sig_stfl_xmss_functions.c new file mode 100644 index 0000000000..3b205e8f90 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_functions.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 +#include +#include + +#include +#include "sig_stfl_xmss.h" + +#include "external/xmss.h" + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +/* -------------- XMSS -------------- */ +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(XMSS_UNUSED_ATT uint8_t *signature, XMSS_UNUSED_ATT size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, + XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + + OQS_STATUS status = OQS_SUCCESS; + uint8_t *sk_key_buf_ptr = NULL; + unsigned long long sig_length = 0; + size_t sk_key_buf_len = 0; + + if (signature == NULL || signature_len == NULL || message == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + /* Don't even attempt signing without a way to safe the updated private key */ + if (secret_key->secure_store_scrt_key == NULL) { + return OQS_ERROR; + } + + /* Lock secret to ensure OTS use */ + if (OQS_SECRET_KEY_XMSS_acquire_lock(secret_key) != OQS_SUCCESS) { + return OQS_ERROR; + } + + if (xmss_sign(secret_key->secret_key_data, signature, &sig_length, message, message_len)) { + status = OQS_ERROR; + goto err; + } + *signature_len = (size_t)sig_length; + /* + * serialize and securely store the updated private key + * regardless, delete signature and the serialized key other wise + */ + + status = OQS_SECRET_KEY_XMSS_inner_serialize_key(&sk_key_buf_ptr, &sk_key_buf_len, secret_key); + if (status != OQS_SUCCESS) { + goto err; + } + + // Store updated private key securely + status = secret_key->secure_store_scrt_key(sk_key_buf_ptr, sk_key_buf_len, secret_key->context); + OQS_MEM_secure_free(sk_key_buf_ptr, sk_key_buf_len); + +err: + /* Unlock the key if possible */ + if (OQS_SECRET_KEY_XMSS_release_lock(secret_key) != OQS_SUCCESS) { + return OQS_ERROR; + } + + return status; +} +#endif + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key) { + + if (message == NULL || signature == NULL || public_key == NULL) { + return OQS_ERROR; + } + + if (xmss_sign_open(message, (unsigned long long)message_len, signature, (unsigned long long)signature_len, public_key)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + if (remain == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + if (xmss_remaining_signatures(remain, secret_key->secret_key_data)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + if (total == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + if (xmss_total_signatures(total, secret_key->secret_key_data)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c b/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c new file mode 100644 index 0000000000..6903135cb0 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include +#include +#include +#include "sig_stfl_xmss.h" + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +extern inline OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS_new(size_t length_secret_key) { + + // Initialize the secret key in the heap with adequate memory + OQS_SIG_STFL_SECRET_KEY *sk = malloc(sizeof(OQS_SIG_STFL_SECRET_KEY)); + if (sk == NULL) { + return NULL; + } + memset(sk, 0, sizeof(OQS_SIG_STFL_SECRET_KEY)); + + sk->length_secret_key = length_secret_key; + + // Secret serialize/deserialize function + sk->serialize_key = OQS_SECRET_KEY_XMSS_serialize_key; + sk->deserialize_key = OQS_SECRET_KEY_XMSS_deserialize_key; + + // Initialize the key with length_secret_key amount of bytes. + sk->secret_key_data = (uint8_t *)malloc(sk->length_secret_key * sizeof(uint8_t)); + + if (sk->secret_key_data == NULL) { + OQS_MEM_insecure_free(sk); + return NULL; + } + + memset(sk->secret_key_data, 0, sk->length_secret_key); + + // Set application specific context + sk->context = NULL; + + // Mutual exclusion struct + sk->mutex = NULL; + + // Set Secret Key locking function + sk->lock_key = NULL; + + // Set Secret Key unlocking / releasing function + sk->unlock_key = NULL; + + // Set Secret Key saving function + sk->secure_store_scrt_key = NULL; + + // Set Secret Key store callback function + sk->set_scrt_key_store_cb = OQS_SECRET_KEY_XMSS_set_store_cb; + + // Set Secret Key free function + sk->free_key = OQS_SECRET_KEY_XMSS_free; + + return sk; +} + +/* Serialize XMSS secret key data into a byte string, return an allocated buffer. Users have to unallocated the buffer. */ +OQS_STATUS OQS_SECRET_KEY_XMSS_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL || sk_len == NULL || sk_buf_ptr == NULL) { + return OQS_ERROR; + } + + /* Lock the key if possible */ + if (OQS_SECRET_KEY_XMSS_acquire_lock(sk) != OQS_SUCCESS) { + return OQS_ERROR; + } + + uint8_t *sk_buf = malloc(sk->length_secret_key * sizeof(uint8_t)); + if (sk_buf == NULL) { + return OQS_ERROR; + } + + // Simply copy byte string of secret_key_data + memcpy(sk_buf, sk->secret_key_data, sk->length_secret_key); + + *sk_buf_ptr = sk_buf; + *sk_len = sk->length_secret_key; + + /* Unlock the key if possible */ + if (OQS_SECRET_KEY_XMSS_release_lock(sk) != OQS_SUCCESS) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +/* Only for internal use. Similar to OQS_SECRET_KEY_XMSS_serialize_key, but this function does not aquire and release lock. */ +OQS_STATUS OQS_SECRET_KEY_XMSS_inner_serialize_key(uint8_t **sk_buf_ptr, size_t *sk_len, const OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL || sk_len == NULL || sk_buf_ptr == NULL) { + return OQS_ERROR; + } + + uint8_t *sk_buf = malloc(sk->length_secret_key * sizeof(uint8_t)); + if (sk_buf == NULL) { + return OQS_ERROR; + } + + // Simply copy byte string of secret_key_data + memcpy(sk_buf, sk->secret_key_data, sk->length_secret_key); + + *sk_buf_ptr = sk_buf; + *sk_len = sk->length_secret_key; + + return OQS_SUCCESS; +} + +/* Deserialize XMSS byte string into an XMSS secret key data. */ +OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const uint8_t *sk_buf, const size_t sk_len, XMSS_UNUSED_ATT void *context) { +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + return OQS_ERROR; +#endif + + if (sk == NULL || sk_buf == NULL || (sk_len != sk->length_secret_key)) { + return OQS_ERROR; + } + + memcpy(sk->secret_key_data, sk_buf, sk->length_secret_key); + sk->context = context; + + return OQS_SUCCESS; +} + +void OQS_SECRET_KEY_XMSS_set_store_cb(OQS_SIG_STFL_SECRET_KEY *sk, secure_store_sk store_cb, void *context) { + if (sk == NULL || store_cb == NULL) { + return; + } + sk->secure_store_scrt_key = store_cb; + sk->context = context; +} + +void OQS_SECRET_KEY_XMSS_free(OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return; + } + + OQS_MEM_secure_free(sk->secret_key_data, sk->length_secret_key); + sk->secret_key_data = NULL; +} + +OQS_STATUS OQS_SECRET_KEY_XMSS_acquire_lock(const OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + + /* Lock the key if possible, otherwise return OQS_ERROR because the lock_key, unlock_key and mutex are not defined.*/ + if ((sk->lock_key != NULL) && (sk->mutex != NULL) && (sk->unlock_key != NULL)) { + if (sk->lock_key(sk->mutex) != OQS_SUCCESS) { + return OQS_ERROR; + } + } + + return OQS_SUCCESS; +} + +OQS_STATUS OQS_SECRET_KEY_XMSS_release_lock(const OQS_SIG_STFL_SECRET_KEY *sk) { + if (sk == NULL) { + return OQS_ERROR; + } + + /* Unlock the key if possible, otherwise return OQS_ERROR because the lock_key, unlock_key and mutex are not defined. */ + if ((sk->unlock_key != NULL) && (sk->mutex != NULL) && (sk->lock_key != NULL)) { + if (sk->unlock_key(sk->mutex) != OQS_SUCCESS) { + return OQS_ERROR; + } + } + + return OQS_SUCCESS; +} diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h10.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h10.c new file mode 100644 index 0000000000..7e4a5e50c2 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h10.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_10_256 ======================== // + +XMSS_ALG(, _sha256_h10, _SHA256_H10) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h16.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h16.c new file mode 100644 index 0000000000..bcd4cd56de --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h16.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_16_256 ======================== // + +XMSS_ALG(, _sha256_h16, _SHA256_H16) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h20.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h20.c new file mode 100644 index 0000000000..80392100cd --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha256_h20.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_16_256 ======================== // + +XMSS_ALG(, _sha256_h20, _SHA256_H20) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h10.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h10.c new file mode 100644 index 0000000000..1a4fe53c41 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h10.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_10_512 ======================== // + +XMSS_ALG(, _sha512_h10, _SHA512_H10) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h16.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h16.c new file mode 100644 index 0000000000..2e8f87c026 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h16.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_16_512 ======================== // + +XMSS_ALG(, _sha512_h16, _SHA512_H16) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h20.c b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h20.c new file mode 100644 index 0000000000..bc3827e3de --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_sha512_h20.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHA2_20_512 ======================== // + +XMSS_ALG(, _sha512_h20, _SHA512_H20) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h10.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h10.c new file mode 100644 index 0000000000..85fde8add4 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h10.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_10_256 ======================== // + +XMSS_ALG(, _shake128_h10, _SHAKE128_H10) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h16.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h16.c new file mode 100644 index 0000000000..8b48276f45 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h16.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_10_256 ======================== // + +XMSS_ALG(, _shake128_h16, _SHAKE128_H16) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h20.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h20.c new file mode 100644 index 0000000000..30d34b9633 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake128_h20.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_10_256 ======================== // + +XMSS_ALG(, _shake128_h20, _SHAKE128_H20) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h10.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h10.c new file mode 100644 index 0000000000..dde4f1d400 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h10.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_10_512 ======================== // + +XMSS_ALG(, _shake256_h10, _SHAKE256_H10) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h16.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h16.c new file mode 100644 index 0000000000..1a41d0f172 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h16.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_16_512 ======================== // + +XMSS_ALG(, _shake256_h16, _SHAKE256_H16) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h20.c b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h20.c new file mode 100644 index 0000000000..321876fb97 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_shake256_h20.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSS-SHAKE_20_512 ======================== // + +XMSS_ALG(, _shake256_h20, _SHAKE256_H20) diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_xmssmt.c b/src/sig_stfl/xmss/sig_stfl_xmss_xmssmt.c new file mode 100644 index 0000000000..ed25233be1 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmss_xmssmt.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include +#include + +#include +#include "sig_stfl_xmss.h" + +#include "external/xmss.h" + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +// macro to en/disable OQS_SIG_STFL-only structs used only in sig&gen case: +#ifdef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +#define XMSS_SIGGEN(xmss_v, XMSS_V) \ + sig->oid = OQS_SIG_STFL_alg_xmss##xmss_v##_oid; \ + sig->sigs_remaining = OQS_SIG_STFL_alg_xmss##xmss_v##_sigs_remaining;\ + sig->sigs_total = OQS_SIG_STFL_alg_xmss##xmss_v##_sigs_total;\ + sig->keypair = OQS_SIG_STFL_alg_xmss##xmss_v##_keypair;\ + sig->sign = OQS_SIG_STFL_alg_xmss##xmss_v##_sign; +#else +#define XMSS_SIGGEN(xmss_v, XMSS_V) +#endif + +// generator for all alg-specific functions: +#define XMSS_ALG(mt, xmss_v, XMSS_V) \ +OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss##xmss_v##_new(void) { \ +\ + OQS_SIG_STFL *sig = (OQS_SIG_STFL *)malloc(sizeof(OQS_SIG_STFL)); \ + if (sig == NULL) { \ + return NULL; \ + } \ + memset(sig, 0, sizeof(OQS_SIG_STFL)); \ +\ + XMSS_SIGGEN(xmss_v, XMSS_V) \ + sig->method_name = OQS_SIG_STFL_alg_xmss##xmss_v; \ + sig->alg_version = "https://datatracker.ietf.org/doc/html/rfc8391"; \ + sig->euf_cma = true; \ +\ + sig->length_public_key = OQS_SIG_STFL_alg_xmss##xmss_v##_length_pk; \ + sig->length_secret_key = OQS_SIG_STFL_alg_xmss##xmss_v##_length_sk; \ + sig->length_signature = OQS_SIG_STFL_alg_xmss##xmss_v##_length_signature; \ +\ + sig->verify = OQS_SIG_STFL_alg_xmss##xmss_v##_verify;\ +\ + return sig;\ +} \ +\ +OQS_SIG_STFL_SECRET_KEY *OQS_SECRET_KEY_XMSS##XMSS_V##_new(void) {\ + return OQS_SECRET_KEY_XMSS_new(OQS_SIG_STFL_alg_xmss##xmss_v##_length_sk);\ +}\ +\ +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss##xmss_v##_keypair(XMSS_UNUSED_ATT uint8_t *public_key, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) {\ +\ + if (public_key == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) {\ + return OQS_ERROR;\ + }\ +\ + if (xmss##mt##_keypair(public_key, secret_key->secret_key_data, OQS_SIG_STFL_alg_xmss##xmss_v##_oid)) {\ + return OQS_ERROR;\ + }\ +\ + return OQS_SUCCESS;\ +}\ +\ +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss##xmss_v##_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) {\ + return OQS_SIG_STFL_alg_xmss##mt##_sign(signature, signature_len, message, message_len, secret_key);\ +}\ +\ +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss##xmss_v##_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {\ + return OQS_SIG_STFL_alg_xmss##mt##_verify(message, message_len, signature, signature_len, public_key);\ +}\ +\ +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss##xmss_v##_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key) {\ + return OQS_SIG_STFL_alg_xmss##mt##_sigs_remaining(remain, secret_key);\ +}\ +\ +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss##xmss_v##_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key) {\ + return OQS_SIG_STFL_alg_xmss##mt##_sigs_total(total, secret_key);\ +} diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c new file mode 100644 index 0000000000..0a0664291a --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include +#include + +#include +#include "sig_stfl_xmss.h" + +#include "external/xmss.h" + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + +/* -------------- XMSSMT -------------- */ +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(XMSS_UNUSED_ATT uint8_t *signature, XMSS_UNUSED_ATT size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, + XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + + OQS_STATUS status = OQS_SUCCESS; + uint8_t *sk_key_buf_ptr = NULL; + unsigned long long sig_length = 0; + size_t sk_key_buf_len = 0; + + if (signature == NULL || signature_len == NULL || message == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + /* Don't even attempt signing without a way to safe the updated private key */ + if (secret_key->secure_store_scrt_key == NULL) { + return OQS_ERROR; + } + + /* Lock secret to ensure OTS use */ + if (OQS_SECRET_KEY_XMSS_acquire_lock(secret_key) != OQS_SUCCESS) { + return OQS_ERROR; + } + + if (xmssmt_sign(secret_key->secret_key_data, signature, &sig_length, message, message_len)) { + status = OQS_ERROR; + goto err; + } + *signature_len = (size_t)sig_length; + /* + * serialize and securely store the updated private key + * regardless, delete signature and the serialized key other wise + */ + + status = OQS_SECRET_KEY_XMSS_inner_serialize_key(&sk_key_buf_ptr, &sk_key_buf_len, secret_key); + if (status != OQS_SUCCESS) { + goto err; + } + + // Store updated private key securely + status = secret_key->secure_store_scrt_key(sk_key_buf_ptr, sk_key_buf_len, secret_key->context); + OQS_MEM_secure_free(sk_key_buf_ptr, sk_key_buf_len); + +err: + /* Unlock the key if possible */ + if (OQS_SECRET_KEY_XMSS_release_lock(secret_key) != OQS_SUCCESS) { + return OQS_ERROR; + } + + return status; +} +#endif + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key) { + + if (message == NULL || signature == NULL || public_key == NULL) { + return OQS_ERROR; + } + + if (xmssmt_sign_open(message, (unsigned long long)message_len, signature, (unsigned long long)signature_len, public_key)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sigs_remaining(unsigned long long *remain, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + if (remain == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + if (xmssmt_remaining_signatures(remain, secret_key->secret_key_data)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} + +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sigs_total(unsigned long long *total, const OQS_SIG_STFL_SECRET_KEY *secret_key) { + if (total == NULL || secret_key == NULL || secret_key->secret_key_data == NULL) { + return OQS_ERROR; + } + + if (xmssmt_total_signatures(total, secret_key->secret_key_data)) { + return OQS_ERROR; + } + + return OQS_SUCCESS; +} diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_2.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_2.c new file mode 100644 index 0000000000..1ce98d95ff --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_2.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_20/2_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h20_2, MT_SHA256_H20_2) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_4.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_4.c new file mode 100644 index 0000000000..c914958bb1 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h20_4.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_20/4_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h20_4, MT_SHA256_H20_4) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_2.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_2.c new file mode 100644 index 0000000000..187292a29e --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_2.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_40/2_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h40_2, MT_SHA256_H40_2) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_4.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_4.c new file mode 100644 index 0000000000..db6ac22a05 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_4.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_40/4_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h40_4, MT_SHA256_H40_4) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_8.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_8.c new file mode 100644 index 0000000000..293810cc19 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h40_8.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_40/8_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h40_8, MT_SHA256_H40_8) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_12.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_12.c new file mode 100644 index 0000000000..eb80bd0f91 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_12.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_60/12_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h60_12, MT_SHA256_H60_12) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_3.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_3.c new file mode 100644 index 0000000000..05a4cef584 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_3.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_60/3_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h60_3, MT_SHA256_H60_3) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_6.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_6.c new file mode 100644 index 0000000000..b0a552ca26 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_sha256_h60_6.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHA2_60/6_256 ======================== // + +XMSS_ALG(mt, mt_sha256_h60_6, MT_SHA256_H60_6) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_2.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_2.c new file mode 100644 index 0000000000..682859a90c --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_2.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_20/2_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h20_2, MT_SHAKE128_H20_2) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_4.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_4.c new file mode 100644 index 0000000000..9325b6b81d --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h20_4.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_20/4_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h20_4, MT_SHAKE128_H20_4) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_2.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_2.c new file mode 100644 index 0000000000..9ef0fccb47 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_2.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_40/2_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h40_2, MT_SHAKE128_H40_2) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_4.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_4.c new file mode 100644 index 0000000000..2568826e85 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_4.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_40/4_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h40_4, MT_SHAKE128_H40_4) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_8.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_8.c new file mode 100644 index 0000000000..9605ef940c --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h40_8.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_40/8_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h40_8, MT_SHAKE128_H40_8) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_12.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_12.c new file mode 100644 index 0000000000..db71c1ca4f --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_12.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_60/12_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h60_12, MT_SHAKE128_H60_12) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_3.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_3.c new file mode 100644 index 0000000000..60dfeaf572 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_3.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_60/3_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h60_3, MT_SHAKE128_H60_3) diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_6.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_6.c new file mode 100644 index 0000000000..e658846d57 --- /dev/null +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_shake128_h60_6.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (Apache-2.0 OR MIT) AND CC0-1.0 + +#include "sig_stfl_xmss_xmssmt.c" + +// ======================== XMSSMT-SHAKE_60/6_256 ======================== // + +XMSS_ALG(mt, mt_shake128_h60_6, MT_SHAKE128_H60_6) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3468dfc550..eb297a8047 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -88,6 +88,10 @@ set(KEM_TESTS example_kem kat_kem test_kem test_kem_mem speed_kem vectors_kem) add_executable(example_sig example_sig.c) target_link_libraries(example_sig PRIVATE ${TEST_DEPS}) +# Stateful SIG API tests +add_executable(example_sig_stfl example_sig_stfl.c) +target_link_libraries(example_sig_stfl PRIVATE ${TEST_DEPS}) + add_executable(kat_sig kat_sig.c test_helpers.c) target_link_libraries(kat_sig PRIVATE ${TEST_DEPS}) if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS) @@ -99,6 +103,17 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS) endif() endif() +add_executable(kat_sig_stfl kat_sig_stfl.c test_helpers.c) +target_link_libraries(kat_sig_stfl PRIVATE ${TEST_DEPS}) +if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS) + # workaround for Windows .dll + if(CMAKE_CROSSCOMPILING) + target_link_options(kat_sig_stfl PRIVATE -Wl,--allow-multiple-definition) + else() + target_link_options(kat_sig_stfl PRIVATE "/FORCE:MULTIPLE") + endif() +endif() + add_executable(test_sig test_sig.c) target_link_libraries(test_sig PRIVATE ${TEST_DEPS}) @@ -110,6 +125,16 @@ target_link_libraries(speed_sig PRIVATE ${TEST_DEPS}) set(SIG_TESTS example_sig kat_sig test_sig test_sig_mem speed_sig vectors_sig) +# SIG_STFL API tests +add_executable(test_sig_stfl test_sig_stfl.c) +if((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_C_COMPILER_ID STREQUAL "GNU")) + target_link_libraries(test_sig_stfl PRIVATE ${TEST_DEPS} Threads::Threads) +else () + target_link_libraries(test_sig_stfl PRIVATE ${TEST_DEPS}) +endif() + +set(SIG_STFL_TESTS kat_sig_stfl test_sig_stfl) + add_executable(dump_alg_info dump_alg_info.c) target_link_libraries(dump_alg_info PRIVATE ${TEST_DEPS}) @@ -150,5 +175,5 @@ add_custom_target( # skip long KAT tests COMMAND ${CMAKE_COMMAND} -E env OQS_BUILD_DIR=${CMAKE_BINARY_DIR} ${PYTHON3_EXEC} -m pytest --verbose --numprocesses=auto --ignore=scripts/copy_from_upstream/repos --ignore=tests/test_kat_all.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS oqs dump_alg_info ${KEM_TESTS} ${SIG_TESTS} ${UNIX_TESTS} + DEPENDS oqs dump_alg_info ${KEM_TESTS} ${SIG_TESTS} ${SIG_STFL_TESTS} ${UNIX_TESTS} USES_TERMINAL) diff --git a/tests/KATs/sig_stfl/kats.json b/tests/KATs/sig_stfl/kats.json new file mode 100644 index 0000000000..21d0c11252 --- /dev/null +++ b/tests/KATs/sig_stfl/kats.json @@ -0,0 +1,48 @@ +{ + "XMSS-SHA2_10_256": "7acc06cc456a087456f937d07c7acae2ffeee517cf71b1693adc916f638df388", + "XMSS-SHA2_16_256": "b20ee19984d6a47529c8e2c127e43e619090a7dff0f2dfdc750d96b6d2453275", + "XMSS-SHA2_20_256": "0632c1e3049918a208676d9d39a97b81f3296665205ad342ed0f0042c7ad848c", + "XMSS-SHAKE_10_256": "f5175c88db4f0ffca54998e0e46cc15d02b5f193063cc349926e493fbe8c39f4", + "XMSS-SHAKE_16_256": "519f61b7c839cf29b4a67b8fa9bfa64a37b360cb98232363a7768a5004ac8a37", + "XMSS-SHAKE_20_256": "0b1e25ce1c89709624a3a668a4ac75ae053f1306b5f461b9424ca3ae6a153057", + "XMSS-SHA2_10_512": "854cb9aede50a359703934010d08db846a3a8c4b9b984471cba74ef07d620bc5", + "XMSS-SHA2_16_512": "772613c5d30da675b87a4f3f932ac71c7dc3ebf8803a9bc12936e6683c3f60d1", + "XMSS-SHA2_20_512": "7ae409257aaf6756ac9a804aec3df8ab98916e026f6ffa2a78da3bbc97dd48b7", + "XMSS-SHAKE_10_512": "8142c58d407dab3f39f1142e253fff535c572d5adcb4fd21b51a62eef33453d8", + "XMSS-SHAKE_16_512": "29150754aad6d8150e86f58224f72521d76d5bfba43d5f54791c1d5def27a205", + "XMSS-SHAKE_20_512": "fbe74ab00eb150f63b9da9ddd325b667e55a65bb994434ccf2c7b670e7e22406", + "XMSSMT-SHA2_20/2_256": "9f117294999c886ac6b69d6f32c3fc152599343add210f4464aee5d1ca0ec34d", + "XMSSMT-SHA2_20/4_256": "0c990e8ff8189140e8539b11ae3f85040544fc7d549f8db17d83392569647de9", + "XMSSMT-SHA2_40/2_256": "91605c4b67afb4e17d57ed076e10d3c4287264deea4a46092e374199c041d489", + "XMSSMT-SHA2_40/4_256": "78e16d2935701cda17ecf493f5ed292827c20f0bf34c1c63c25c94f028ee62c9", + "XMSSMT-SHA2_40/8_256": "f0feef94797276e832634a3b55020a8791dbe14d400e3c076d4f8ecd53892dac", + "XMSSMT-SHA2_60/12_256": "7bdbc5498d33dffcb32675df8578d8ef590f0f06cbac6685342a131cc34bc720", + "XMSSMT-SHA2_60/3_256": "62ee9b8b9a46ed95a2e4fb3d18552fe2e87f91e530b0fb82c5edb1242c0e0258", + "XMSSMT-SHA2_60/6_256": "5ab099ea120729e8b4fbbd074bc7b60396c009a69725eeefefa9d89274b2ba83", + "XMSSMT-SHAKE_20/2_256": "75d79d1a8a0cc714a97acc956f12040808c9382b37e3fb2d389e5ad29a1f3b53", + "XMSSMT-SHAKE_20/4_256": "391f4d0b64d1a24f53fcc642bd679f4b6f9230abd1c4641f30e6c7d7dee451f9", + "XMSSMT-SHAKE_40/2_256": "f2601cb4acc1422852ff3dd933ed84f3ce4dcb0218db6f43793bb146e6b75a10", + "XMSSMT-SHAKE_40/4_256": "eb578e8b7d7dad45e99a177abe482fbd087c9281767b1a3bdd660c2d5e04712d", + "XMSSMT-SHAKE_40/8_256": "1597d62ea8aebbebaf364141d1443a804fe3f6d0705165a55794096a4a3b1c71", + "XMSSMT-SHAKE_60/3_256": "7ca90f7c64b21d844975ef39c48405dc61922f6fd0be8cbb88b2a18a54bc754d", + "XMSSMT-SHAKE_60/6_256": "c11ca5be510f88c9c8188cb98da65e7d4b2be1cd7efc5a9769348c4fa2b33b24", + "XMSSMT-SHAKE_60/12_256": "79b6690809f1317fbc2466590e4fccc8a7f706b05abcb277ad1018565096ad88", + "LMS_SHA256_H5_W1": "26273b16351d40b7a7bf73db200c4494cba890624235d214bca9368e60cd1c02", + "LMS_SHA256_H5_W2": "a4877dbf9f06a08469afaee13cf25ef98e20064d2be0009888c68698995aca7d", + "LMS_SHA256_H5_W4": "e13ceda1f66c90cad1a15087f26bb025378f7fbb69ecfc138ac365a9bf3fb6a5", + "LMS_SHA256_H5_W8": "175f2b5b8a6e8a5faa82bdeb2779a88cc977ad7cca46d815b0d02c6dd672396d", + "LMS_SHA256_H10_W1": "b52bb3ff8fab21d69eb0933f5eeffac1380f87c1c8154983cfe4f3f27fcfb1e9", + "LMS_SHA256_H10_W2": "a1a2709362ac8aeb956d0d88cd4a42ce2fc8df9a69979270299b9471f61c3dbd", + "LMS_SHA256_H10_W4": "707e4ff1adb835f6e79453caca0c787c156a2ee270b1657a42ebbe6eb7424494", + "LMS_SHA256_H10_W8": "799e7bdf00fc0839519e6847b7df40763b89949e1d1b99bd5b9f669387bf0fbc", + "LMS_SHA256_H15_W1": "af9d334c2d306bb1f5409f45c4669799c952593cb23e1ecd5acce37900bf598b", + "LMS_SHA256_H15_W2": "0c6455312cd68eb9023ed4e74474c000210d67d042038a62dbe322a3f4c43c2b", + "LMS_SHA256_H15_W4": "9e2a4d4b52212ecfbb0a1df877aaef0406e373bcec54597df81bd1d300c2eaba", + "LMS_SHA256_H15_W8": "ea0f3dcdcf73a2b990b86707c480fc698f9325537672928064c9b40348ce1cca", + "LMS_SHA256_H20_W1": "5670ee0668ccb704e15c9f6e42f4a017f4b8cf8aa34c311ca905b1b538a2352f", + "LMS_SHA256_H20_W2": "53e844066e5dda43713261704c6d07b785373dccc37293b2cbe2ba1b7b961382", + "LMS_SHA256_H20_W4": "55a9c196d69acdff73b2e95f9d0bb97b9edd260bd93f53b5ce4f50c26d6575a4", + "LMS_SHA256_H20_W8": "2594c05e1ae86a029ff42a74d2b3ab4d0adf01729f4fbfe81269037ac029c184", + "LMS_SHA256_H5_W8_H5_W8": "a20ce5f27d9962865463223a138a7507f30690ec7268e802eb6ba2f04c6bd99e", + "LMS_SHA256_H10_W4_H5_W8": "f51cd27e5a35f63586796a39f00d6729f5148fb6d454e61737fbdeebbde3aed8" +} diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W1.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W1.rsp new file mode 100644 index 0000000000..13e87a9215 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W1.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000001c044f6230d8e90854489e823101a65fd2f0ef7ee9c0d49fcf5a354076f3aee868880df42fe232b55bde5016e05e454850883a80d3570cf9ecd0c960b9701fa0617c2e0b4a730c7e1fe228ac702e0f68c0ea9b3985e0704db86f1bf0305addfd7b7db7617bc50db44b28dec65d4727393a6362cbaac5d368ed18e0f4b06d77088d97fe31a2276fc39885891915bd7a738aa81c360177de403ec91338f2c3d6097c7afbf153370a416161c03a4977ae1eed6ad61eea2d0dcd081d2533499c213cef6585a0210e8f806a064f739e1d3e630ecd4e422fa3967895ddda5621b176e1e4b3f20c11f875e45d7ea0f765875376cece2acd7ade36c52f3511aeb23624fa0b3a4bb554cf8abfe8adf0e5129a821fe71b0420ed90ef0c670e68ee81897a3665aa40bdc6e86614b91e042854b71fb1372db99872bdfd7979e8552a2633e8d123150f06c6ec2316aae6bf64ac2a2db5349b7d08a7b9a97152193747a69081fd3b57cd666cd28555e531bb870483a0144cc13075dafae36993b1aa3fb7ddc6dbf095a7c2142ecfcab40830a293ea6303b5666518692f468bdf82c0e802624621c5cbad8056aebf836506ecbd4992ced3e8c8e5ba2633591f3b0ab3f0fd61ee396a7fea0f0661d8271d56796a48cc88bb555c74c2b500d512622149b13a49550597cf1b17e140cfb3738ec36a386f1d9aa92caf1e75e7c9c819419a69e1711e4fd461dd1e00059e8172f0c5f8550c0a95b1eaf9f2796df7bbd8d0e08ab1a240a6049678f481a0097e3fd05359c78dd6fa3d9d53bba7fa3083f041820561703c5a5f071f3b3d33024657840d72156daa207a8c6308af5bf0b50e476292d95d6786092622c109d9fd388dd8f9f2bdfc31a95bedf6deead4760a6e76b363932246c8437294566da6f372dd61b1a0d957f7393c7b3dc43d26c4b413380d1a3e9fcb70c8c2028932b913fdd0e81b360b76b27662cc1e8119db1d00e35999196918fdc1763aca80c861bf8563cff7f62fd5c4713a5a44e9f6fe9ca3855183e1aaa120d72d27bac94aaf7f2216c9b1287c05e60da13799ebc3f8fd2ed9cd873707d0f093a1a57e169d88dbee305c7e08cbefa8bcf2e643dda0f464b7450e57cab132101e0da4612941c50f809c2a592e6c15f791cfa91d4dee9aacd064a4e1a147a52ad353710f15db8159e283ae8399620b58401373fc093d91303a9bda436a23390023897bf3747c55a103c18a4f40dea1029b2ae1c6404d0387a7c5c7f1202ba8cd49c451d9bcabd23489ab3a5e82cef30712c95d02bb804ab01993c9e765474cfc9cdf9b7b68d6e6228f1481e73ca03138ff76d92d37dcb5ba9047b9ca8cddc7427b1d01f33114a2262df1ce69711920fe7ac428b2a92f0df08f3059be97e404b34d1ad3c04a837d76b3ad7966335568247f386bd5fa9de5cbafe53000ee3559eb6c06a3a3c85fa8ecd68e2ab30cc02db71aa9cfaaeae95dde704b353945198f75874dc746b3c169bf2edd15cb24f7414a070643b882a39720804e8f845dcfcd4254fb717d0748a9c9186eeae81b8066533b1dfed213886fb579e660bb2b9660b6878b02b514bc9ae3026a161b23bd3f1e0ad57bad5a4861e8930c20731e6dba31a6de742820384611cd2ff2e392a37402ff7016ee68d2ea04e00f7eed62a5c1fff05c2e32326b37f19ab7b36b57f43ac4ed784ade45dc2a7b69c5b93fadf362920e23bc000b2700c8b3fa81f43149d2a1300638af7c780813c11bc9eec1cfb3e719a02eec19c0205581d371f2d4892e1725f286ea62fb92bcf002b4ff2cd03c4ce8de4bba8cab2b3d060ec504f51de9858e4ebd87700192d06062fc19b75709215d080e04f2d1bf1330336c70d21d996f5597c971e6a91aaef92fb712908d1dd6338be54fe6b433752e92f4d841844f63bb42fe25eba83978664ceb75229b9406acca437b627b262b4f73d2e6221695f8f8e23cfde9c4933b6d22705536eb66f9a6bb8892c5fd47b014bfd81bdba6bd53e2cc5c8e4af2a275735fb974d675ec1abf6a4b46ccbd7eb9853252055143d054dc22114fd12a74ea3672952f6796dbfee528e744ae8808fb94f44aa289465805bac2446e1e2652bef7a411d12f8f28bece67c3d71723aa4c345e91077230e93eefcd19933b2ad7ce6f2a4e716b22201509a797531856920a3ad3d0b256eef648414b1ce56193994035de4f755927324300b0187571683905acae0ed98a6c9cc5487aeb006a4e8b20077ec6749ed8e8d6c1ba74746f47580d6fd834ff19076a1a53d4f627d83c8eeb54383071eecd277531a1f17b078a57875464d069f7de6ba87ebed03b6133b70807989aa1d887e875a0dd6caa1fb7577ac7db6196040473c5116c19ad0f78add6041d3790b8b124fb87d3290e14ed4437a040b557f6a57bbe35df9ab0b593998ea6002a7d33ea0053bf07ac82842d8bccf0f8f6366e0a496e4470825c00d5f88c4726f4e6bffe39aaa127d868b71ede4fa178501888a985241ead8d21145d0e78200ffab22b38708220a6313b507e3282dd575f070868790efaf886dfb4d18144488fb992d8e8e9983151310ddcac4a6a10af0708a10b9e74f46c972a852d1352538849d53f23887bff6ad1d56cec8ee77097b50184f27efd6ff5643bd8f9a7438bfb00937a13a6a65ea4cf70c2287a80c2de433878a504433fd2244c59d8f65e907a15ffefe7b7ba487e1d39749aa3503dcddf071c6e904d98b070c2c226da31fc17c649dc494263009abdbcd2bfce0c96d2e53ab169cee718c4809b3e1f49d43d60369b79af9c0dac15799576c58163b513db329729fd391a4ee5adc3df2f6cffd927187c2714f2f0ef52796550d71c93982e1406b37221cdde3da3675638f5c9ea2c4fab3ffc03519616a09138be036a33ab7f3b025608b3cbc263d44729a02d3af7f7aa587ad2661067cb88d3aac03f3efb3f3eb7da876ed42a7b8292406a965bc3da2fe2f5d815183e291b0a667e442ff907127e48a6e7aa70ce6b893720eb4fe104935fbda3ce1ddc4f0c2cc8ba6ab0e66d1850ecb32ed50f3767763593e8223304ff768ced4e03816526b6d3958477fe2ff57f77a2a1c80745a3737883196aa7aeb090655626a3d3682c9aab46fa0090cb09c398dc14be9a16a52281df2a875a2e7690923a8d63be691e6c519ae41cc550c8618af002ad5b826badc763762046e4ebcc474b3618b56fe2deed72425252390c20fda469d4ea19ba8746aaf06b10e7dc822c0ef872ec1b85e39c3b2944d1680964c11f5eee844bb6b9d97952e29b946c9c71fa0f7c94dbb6cac5b701d03690b5ffa669089118af04e42e5a12ab0b7199bcdfa41933a7de4de50239ab0f82ba223fea923c2ac4bb37534aeeb0abe8883cb458a8388fb94e0e1c7cae58689d297d8ef2bfb356993f761754ac1ffa5670b69a43e61362a3e71f99d0f1d95ab0789d8a831efa30a388d3b3f191237026a541f556b44d67d131c29a9329634bdf7deef48ddfb1636b9094ddee01261e135c7fc782faccf9489de8ca1b2790af3d8b77ab92a9dd992139a6fc0f369e2031bb9df07ad67bbb7ed9366f214ff9efb115c9510b219afbc7decf1de3c0e471adf5897189745dabd7525c760bc49739f1a45ef64f126de0dde44e95a44801a617191e960b72a6a3d362e84b7f8c0a852fae3191a8be19e4fdef968586b20dc51b78029722d7f44eeac63e50a3e19f9b49e2a47495d708e59091e78f57e4e17cb8cd37971aa83ead384da8fab871aa3a90a506fb7ef2cf316b626bf0e34a4f6718af6df12dc38ea7b382cc5bb5fe15ee5c5fa54a54824e31faaed6ced9364cd7e0692d76979d95b0ca7c1e912c9a6a6e882e2df0e143562b17e33c81a5d7e5c0a44cced6bc961d11fe6d7a7ceae323f8e136842982ee764f9b7622dcc43639bbbd55207165aa6525415af15813260e9b7735fc68ebcc7cd8346cd8fb661aec511e5a17d11892a5c8cf84d3cacc9971edf88f979be7f891aff54de818486d03f51581e10e12bbb8ac43587d0b0e87aa0c1302346ae31aaacb290968a56b88b7e06c99591b5e096f638f540d6627a0ec9c0be8a71426c7581baac231b8cbbbd8b1d4a8e6332782aba68c61c274fd39b2c04fed27ff8c6afffdc285f652fcc3e4f81fe2667f04f0aaa043162ab7fc0fa2e5dace3ee139bd7a2a7c4137b786e8e631d39313ffe4d6359be064b97f87a43ea52b59830a791399b60e567e3ab072ccbc85ee731cb0e3eec8eb588dd38b9128b948f9faafd1afbcd1c22808746306085763bb36cdac3ebf03c78c73522e7f9b048450afcf26aa4e6ba5c0b9d67a4f23a1737206e5a455fccaf939616dffb2a37bc4f0f8b07d50b6f165013fb8b19b7fdbe5fc963bf4ca5eed1cac12dc25f0bdbd7dfd155d92d7a67f5996684558c2391f7491e01777c8b870de45587195883ef84879185646833b305ff883b67700a2bdbad3cecc2c72c29f31afe69ea90d62b07d77985c6b66c98536abee2fb469beca6231a7b18e9e2f15d2b5cb1413ac0cac4306fab163abbc7825882f4469c819eb34e090980a7855289858967d68bce082629d1a284e128bc05d8aa3b20d3bc1cae265a279cdcabd582b3fb52afbd72f57402289946f9abe07b2e4a6e4be45996d7555eaa95c9964254f8a97f0d4f8dec47b451ad63b79b463c6ba27e81775edf8eda9d6109ee75534c7eca0bf0922cfa1764cae631535daa56d9db9af3ff7ca7294b6c8b94c416970bb5465dac9b437810ed393724d8f4b9aee0dfdb76c80634c512182ca3a61041f3a9ebd9b0ed13fe80ec347c60efffdf259f39c87cb87a107ae7b66f847fb30d62ac3fb3c4e364cce8a2d1c1b68da478e3cb18966510e3133f47be63f2247d95acef4959506ed21c4ee3a4dc2a6775feb0c317d6c96c58975901fd22a3cff32618b01d027ec5548ee82e7c6cad1401ec0de200d4ffa816a5c54ac344173a22145883c657d6b10bdcc522e9ddeb13d8c7cec932ef28dff74703f4a74fc75f75290227d11efd2909721b3f70a01db8b5a87c9e0bc63b30b2de13de8c0e25a91b6bd047148060f03783e6626252c8b278217d10df42db3b0fd1f7313270c141fadd1217972f3f78ee16607d3bb726dbe289355e1e277338bc60feedcff08f900d289db8a1e1670cae7a5ad5e4fd30aa367fc74854ba9dfb4084aec45bfdeba68ae85e9bf938b55b2db19d7d8b6f875bb2c74c2613edc3394d0e5bf3e71d01c2ee71d983083867efa32cae1c5cefa3089ea96500fe21f19920c8e182034fd3c009f9e48b6e49f6e691743c4066b478f73853f04485df6f3dfed6f307820c293ea8a7adf48a14e081b228136a74a51d59c14edd09decbe2903c4da0436e54b83626b678e75e91ac2e75e4180d6e1807110ba68576e59f80115926a352e8bc2d69e99b12f79537bf1264408fea3f0b6851d82557228291a39cbbe590f66b530fb022a7a3322b6a507fdb48f128c465ab1f98fee8ea442d957d14e3d060eed76cfa6f0d1cd1de93ec216bd5fcd9889afb0ca02c9ffc52fb92d76675dd30a4d2c2f937b7dad5044731a269b80c73f52db035474b6bb7f2124f50793a85818c0a1778ccae570002c695dc47641791eb89d7aab7370644fa9ec2f69c5349570cb0bfc9af395ec61589313121ae1a111028e0797845902fef6f2c2caf061d56674543b455acbf078378af10083adb7b29f9c347605c5d39287a5c94d6d512be0bb131ce06df64f2a5bf6e072b8d374afcc7a1eddfdb1d4ff98f0e2e015867e623f124a821d38c553ff4b899ea2e99fdba5b88ad921eb3c9a5bf42bd534972dac661eca5deb47c47bfe4af8bcf042d9f111613b11cace3332438cf10ad67b0e8c12faa1e60b460057cb36a719bef0fe9fd6dd672b30ccd61ae5d559e83b62bcae72db42da2b95217a7249fa8bc6878b9fc7f59c2988a27e1706bc84b47600ea42a45c3830752f00e33fa3318b2cdab84d44c9b7156bac88247dfaa5b3b7734aef4e12ffe77fcf399ef3916725ccd1214647339bee28b78c7bdd490ae7e8aa68e50f610ce12687e0c2faf91a2a84492067e17a7878a70d08f1f66c14aa556a2b9898273d4b7fbe5166baa52e9fee4daf24c9bdca63d543da430cb15318b5aadb721153dc6f3756c2f26d22780026e0e340246a5892787d6caf45dc3417d27c093d974edc3de8eaa34ae760081076389a050fd3b78f2e2c8c75250443f526361999f23d1a803c72246142e0203cba42c9fa4791623f7ffdb0fc9ae339ae92bcc66fda3e7d343ac701422dcdf4c89a2f2044d44093d225addaae2c3848a9e55c1643abb64e1222a33edfe62d44a3c146b48ff57c54408be6ccf605c5f4d97a1a4932d5bbdcebed5c6f8edcc35415c3be2cbd09166c03b5796417938ec7102943a9174ef3c377db5eba123b79830bf9aa9d6ba7094dd691400c1849fd987dfb94da5bc76537bd38504f7625d53f7adc60517e0b6420ab8d407293c1aaacafb9a73ce02436648c1343a24210a26fed2f6c73afada4d38da06231bbb8b7ccc1a9c045bba93f46abca2b691a0fbba1223274a9ce0e3221e4c606934ecbcfd5b1e6ff4bdb6c1fe1cdbc1b1a9fd3a4588a685ca786ab503767ba620d878f84d7b5338f0d9b6b07043453f53505e9d7e26f85ad8001aabdf661e92c06a8fac95590527aaffaa9502e689dceceee7322e63bbdd6dedf6c022c4d2fbe4cb68cab932a213a7dbb78e1c3d2dd8b147244faf11333f857311d3fc060816bd08b9bced8fd5c44ca9b4ec37355762caae31c0d3ed6b54ea06b46f6bec414e8ce70cf5e5ee2ba4d6e61aa7bf61d8fdc790d3f7e8d83df50000c9a3b627b5a79a974bc49ca887d5c81c4908d8a7b483f1cc8984bedcc346096ad8114722d23fedd319dcc95d3cda9f8a4af2d888751bbbd7138ab8d2d7dbc3a1505ac7675a7abd99c46f1d33a1b5e743be3cf002e7116eccd515cce11a46e198fd532bc0efb696fe871371c422486f5b0469a82869333a57df8a917b15f91960411743166c93ccd551bc48a779812a66550f4c4e395747ae09d35b28c466e5e61dc9f30ac2124a745bd3607b74021064bca34fe7fc99b5993ca0c35f8c7c751d35de70c25b2ca1e8e72e91841b9d9d436e115791ceb4a8e5ebf8bc232dfd3703975f0e5f50de5bc684232fff7a3a9da09cdb17c719e004d3354d90356bbe97624df21295cb372ad491b92d5b3487ccc27d4b65f0452a944d1f1e46a95c2d2195162f7fc76de43524104b6493dce02a8158a07504b37edab79c6cdfd4c849ff31d1b62e62516e7b306a8de7edf39ca6065cedced468e04a99585acc782bfa5e82372eaf284e5af5e9e5711d1188afeb3f5f4daaaeda0f018a6f69bb0eb5b9e759b846884889122a3cb2619788a7abcaa15a9a6296924cdb9e83df9761c0fbdc993a5d93a01f46d165d6bc9ba409ba6f16e4948849e9f03b3e14404df153f3fe4f10bc67bfd188897f0adef44428508733f11f49f10497e78f6070917d5b93c425ea628ac5c9fcce0f782132d74cb0347d90b3aabe395be584f497023984fccebc79d6634390080042567c4828ec7176ba8da4e05aa15d0e3c68f07caf5e373b8187c33de7387adb464d5e90378aaa5223d1360961f315c53c8cf6313c9fd48645f21c3fa7c3c1a685b93de4453bc09fc3b0ebdf6d52cc521818f1ba0c2e88fcb07a1a3f4e8cd33b9f0eb6fa811100169c6d4cbfb068bb22c618edb5c3d2cae01810151ebc960254284477ee68cf13c2e96f7aa5fb2666019d8abba36cfe9687658c378003e4e0d43d3771a850274d63d05686277ba10fe9fc134530f671344f77d5b9195fabaf5559399896222aecfe8d8bc4b1013429716ac93e676cb4a6326a0a7be15e917627ef9bfdef640579adc8e7aadd16f5c3352806ba9d380c65f927e1bab8fa0c1077490875890bf814256147ad951c5fe2d07f895946aae7ee5a24374255455d5aabf6104be3e3f4a4b36dc466a68486f1ae586e4db46da74dd3e195207c0f1fe34066871e9d7b28513d6b31f4f17a4a8a7a2e81b93c9c760c2a93ef24fc1d0321b64dd65845d1acf2d4dcc2fc3917935c59334d0e3268af83ccd350162d8e8930f04dd31c26bf2ba9d17168ba0f77451771bdcce1ab6205f2a8cf4df2f583a2ff43a049baf2beddd7d82e3239f8cbcfd50538656ffac80253e419a25b93bc931de0a24c9a37444a56a62d00ceb02664ab597719082f78ad463bf6d999f8c2e3cd0340dd1a5fa44c78196af816230ba3559c1c3bedae23a913b3d5b65a77e2a8bc6b39ef371cb82500e0124cc8179d26f8d9b21d82b1b81b323f42ff02584d16b020ff0319cd886a2b2492b4ed1c27b3f5b51ff759650bbb17643a18cdcd9f56b5e3e40c6762e20b147e55d56ee9773743db41a296fcc40b326d3e17062ebcc9720171cd8872001a9e5ee6135d1b9cd16e538ff8ba2a2d8ec3f931cd971b4757f4c92f840b0d985fac936ae6ab492b09ceb63ac80b13d5d9c5fc4508dc0cedb5bca1e2398dbb90c371696d93ec80a8cf2b6b9e5ee1a73b031da2709b4a6987af3bdf44fe2800502d10622884c562540d20c2c823eb92677d3accda6408b9ac3167adf889472c93405ffc37e2acfd8e2495725eef98b1b2c066af0e11a287e0313e63f79262e22921265614dac795912ac60ce6b626d5c2ad79420f136a9db58d2536d3525ebe30a00a88e81a787700ed2a077f6b4c1b6019115283c1d8a3a27dd4349fe0e77cb4b864c680dcc96410e00f5c1a09e6aace2ed201a8a0140c3156bd9d3ef2b08312cd22f04c2c7d08d7a298b7819d5f3a30877ad88b35aa5efd00cd7b5f01f0a5b491a6a1c7032fd19ce2e8a6e04693bd7d9481ccd22b57a0b8c749d975ecfc07e9c5205ecf4fa993ba866f5ae6eb45ad4518e3c94644fa5911141acc37ac2bf123ca70e627e604656c3615d38971e571019793e535a9ddc756dace6e1ba5a5d0135b7347d85d29adf6cbf17c6177346e4904353d5c8b44b2a0dedf4a039a9d945370697deeae5a850db0e8be9a003ad36ed3fb675ef5f6e386da850d3223549b1b6305159bcef54b3ddc39ada9d74d97ba4e7cd78d326c39eb9a9d5caaec9ac7ab7cd30181a9410a98b15a69c168c78b9b03d723f57b8be73b3698f7fceb5ccd92cb495a547ff2706805d97819a6f43d3423917f877dae750ebde6f81fe200b59c6dbc8565ccc5c96c55125e851783f3b60502df961e971fba37fbc592c05222bc1185763a5864479471ee97f05b1a953af6faca1f7669cda1f1bd7a4ca35d286cf1c699e4f74177f1a9feb71708c0404fcab769fe49fc0ec8ec2a8e310b69913f07ee69ece421379e0acd2381c7bdf9d877d847419181a9f27500b1750ee6f714beec530ce962829bdb9f1d1d6ff5ed7e28533abc4d3f31ca467627e34a89bfad4a50ce5b7c7409432c31319d98a0f986d4992a7709a949349b2caca79eb0fbb6c481f6e4b2cbf4eb89581694814ec968514915e92be777900564f99efb85d872bcf740cdd8f90b4c983f8677e43fd30f622ca502680f9f85e707c74f94e18e3fd9fa935f662004dd4af3d7e8cadc5bdd119806e2f630fea565dabdd51907035c8c8c4e5d94e37fe5efdab61ce8e459f5dea5a8582e3104741db18933907ca05c3fc93688fd75f60b4464a46a44356e78e8dcc8704eebc2c8c12b89ae7f3d64a9028cfb9b6284833695f565f8d6db30a2e597683c17e0529f653d6d90f290489cdd84b1b5f01a130c85b6ccdeb3ef3ff7ef8d8a8c2627aabab2b43e6cc957eb8165d6debcccb225f4d8d49ded27d1b5f9afbacc317fc289b951c22f390b91746c06d11e4c133318e24a62067873ca1147ac0f7b8b572ff4287fabd48d587f976d2b5eae6eef4d2acb924281891fc95304d5f99b3d0adfb3badf173b7ed56b3dc85fef93f917dfa4a45ce34ea61661e772e480c5bab1c09a07e3d4f5713f47f4a97f476a8188413479e6c0320db6b9a7ea2a05e130bb79eaf350b60d1d8936b29835d5fa873f70ed264dbfdc8172706ce713d7b52815bc458ca41f114b0897ee65dd59351db4fc4a069b344a1b95c53df6763f0e498958cbd3499c26fd8856cdfce17e8f8ced0f50a9afd62bbc2b1955bdc2c25b0a806f69e237cc2609182ce2d0916fe200027e038cb6d8e704b34ae7eb5b6408b42bed2f0ff03e3fd0e42b510cf1b0f9ff73c57120edf67f8742d75f5d7b8576049ce9ea5bb2cd8f3ad06e57b3155ef85f7539102c94bcc6fdd0a9faca161315c77906c5dcd6e0278498ceb2807fee87a6cfd387dea4605ff778449a000dfb7d79cfc194bb70e3e9f0a9c63faceeceebd47faff72f42493a18ede63f2cd06fd217d5772479d362055e27837157c047c5ef0a77bf5884ea78c9c618b571ac7dc2c24a81eab1a5d0c027ad5e1f9944d8200160c1a37ea44524fee0dadeca457cd259ac8766732acb7608ded63195a125221fb3d90b16f19cfef20953632dee7af848c75276e95ea9d34449e17465c91f2dc289c724d5179b7d2f83008d994e911a5d739c989dbf63d05dcefbb5a851045ae969787c167c8098bf14e473cd13848ce7ca4e16a440e0ec3dfae770d15201a41cf90b87d0e87ae78c0176b274a3b2c3fd9cb12e7eb4765dda7ed7eea3639b0cd11c862d7e2c65c1c6b0d1606595e9359bd6f94e20b12cdcb039cca934ee01f7f957c343cec9547592b180f6720cf2454b8fc526522c8c3071445d6ca95b47289862021855d9a2b38dd9d39a8fd633db4761a17969f941db403a7c0e260f0c8de4a1e45751aff151e33612dbefaad6809217023844e12f6a8b90be585c948c12a571b30ff0a69aa5bdb4c3c9b5018b77c57980c07dfbcf7667ebd7030406d3110d5406718b8e95d5d035a86dcf2c78fe575ac316d7c44407aa6c68087008433eada0e7bbf670b718830db42f668d203519d294ceb910edd4abeadc3af44cee24e0cbe6c436f3a523e60d0627129e9ea4ce01c5c45e0377c1655e8ed4b8f79ae0b8bef8a914f6326a0477d9f17e59ea6096d6a5ba75d64a94e68c8ce11e8f28eb80d07efac85c64a6c3c493516c7d929859307b33dda16c271cb21f4400f3156337ba02143f38f677b89b7907342fc16cc14bcf00ac312e0a0f9af6e0be926f345f556693d730e667f7f25098277efa691ef155fd65b8289c1e92d67dadb608902cbd4b567198cc776168a2c7543e58041a3f09989994a7aff610f9b35fe7aae6a8d43b676778dd7a8dc97475ace615e09e101de1a8f5f95ba082f296715aebb3d4ccd5f8d000ff8e3dd452a79f4b9ba75b7ec71545bad1c2ac91898d4564db141e42290a37390e0f4058274ffaed8ecba88a976761d716096babf3909bd37b873f1cd98cfbc3fed8978928c69211365519d30dc68598addf3f5ea2d0de53c4650d9b183834bd89b2fd55e1ae9ec2123e0fb66b8abb36b6ba62da3cc205f24edd14d68d355133de0aa26dae7c5d7b8b60bdbe4b6daa43aeeeeef410234d6b179557a39186022394615629430f783c8fc1efcfb23df92267cb81bdd20bce73f2e825d31c52d99d27b77a4cfe821d5f9b4d77c403e0640b0d53e04bba350228aac6a36fc7ec513cae4b832fb7de3b1938fc9aa35efe1df21ac41905fa9141cbe5719c3c3b73bc5b3d1a49d4c7e8e8f31f653634d8494b18c439e1f65751ecef9d95911370ec9c6ee74f632990aeb6ae3d04a429308177b6a7703b471a5335e2d356534c92768cf92e168e07d971a7abf08ab722622215982c97eccdf381f95c490f3596fd03c8465cdba4f9512767855dcc5a082f947e8f308f584d0971469fdf742dbdde2dbe79e97420f9f61076fc0dab44902f324f644ab22dac6374cc20f01e787da093ac0025e737fb2fd795cdd4f1da73018da1b992fab997189ea359c2cefa0465963c6505d0830ccc13c010295a61f69875e13dbf596a5e4320a648f07a9ef5d29c92babdf2757ebac1113dd761b2f5fa1fae5365aaea3ca3d0c3ae1de09f78ba8ece95e200000006a3761dc5d71c1cd0c210c04f7d6a2e64411150e168d7a5e83d532feee580087a78cd5fc4e68e3c9a2b34f4f5bf46a6773102f940d108e236c1830219c1ef88b8fd4846cc3f5f980b5aec0fc2a29d4408ad375735ce8803c9fad7b38c9e98dfe1dfeea1a3e57316f52addc5b501d133bcd1ca2e6a855f1705b6e946b2ee206446e1d400c943f425fc82ebaa069233b625195ab5bfbf9692d9607200c7442e33afc6cba48d00dfae2198d3c8a9d13f8b87774e41640ab9d7c2c66b778eb122e9b5298c717b3b4c58a2748ed811aa75154724454d8672a7cf49c0f9521993031e7cdb863bae7bfdd3d4d91ce8f61ffed3f8951b810594152fee76a4dd1c998f52b071f56a1e40a0b2963fb7ecf2a71952249fd9dd8ff29029d30a381dc6e1818224b2234904a8e50aa4e9df193b12c9d8a6f32b6c43c233889597e57abab57dcfaf + +pk = 00000001000000060000000116dc020cfd4abfd4d0423565aba4d66f585c5f38861af8c7c2626cc33b043c12db72c2210f1578c00a1e6d087eb37c8e + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W2.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W2.rsp new file mode 100644 index 0000000000..8bfba122e1 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W2.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000002fbe373f21f0131199ae1967db9e8c8e5e91b55b41c1a30b1074b4aae40788dcb1fe11bc5b99ce8c08bb612b75649e5e7966836669e5b4fafad1766c736e99d66c47d7cdfdb318def37933fecbdd392174e6bf3d476122609c175052b0b03e8ea63aa156096b3b23472ba6f1252285802ad7272a4174c69b255cc64583b543e13668beb8581ca27a10023757560b6f5273a56d5c2dd4adf9ede64a7eab5cdc189a64d91bd7ca4e2d3ea559981ad535e2425911b9d8ab94cb81416326d851aa8d81ddae453fc4cb231a58cf405c0ddeb06f5c67e611a411add275d9567d3f625cfa26384586c435609da22f62ee8f14af17ef86c10f72d2e15fc00d6563e113ff96347e550bda84502167c62a9520d7c7bceb772866f422e8410d62418f7508e2192f7cf28d6192e93bae26533bec0139ebf6869464ed0f62a2b5d10bcbfc78923747fac8f0102dce0f60252b1160406849180a70befa6f56d11daf1ea4a02d4f85e3e653c7eb3b6db7a705d499e51ed477c305d92ccec35198f2bec53133c147ecd694689a5b636f935c0fa08407298328207df0f38a3ebf7dde9985cb71a1129442e03eb414881d63be98361c244a4cc92cad855521da2345eb24b52963f55aa7c7fb13b11b06d6acf8c2108a9090e35e75b10b177351f196002198c7b3e7126df03d1e625aba220bcef06c885a041ef5f33340d2104509595140b64b8f0222474141d0371995fd6461764e87f3d94f6e1a7bf06e350cfa5982de3bcb4c2eee90e884be8c78bf1ecd60d466fb01a33431536dc9106e989f9af03517c78e89f855727c8590567e91193ec3e646f3f7bc99dd55cb889c4751e9209198b55f27e82a14d55bb62324bb1e65a4ec65244c90b755d729bc13cd81f15aace49b1de09ad58f052258db141a8051990edf33c38cab95978dea6b507191251f09f22c9c53300883928c5ad361039751088eadea38ba65b9abff4ca94ec4f5cf5e64189bf9630c7019a48701288a9d01ad1cadba3a6df888e3bbd91d28685f02aac6fe1ce4fd79ddc577dd08b3b3909877694f1482bf0e1011a5953a035f6c78d94d5f18260108205badeb37e6f6bed44f3a7c8fb72e7258c9c23c4ed8463959463f60e2cb71dbb51d0c78be4f817fbc6f1c0287af42b9c889081da7c4ad849dd1ef36b41561322585aa7c12b0affecdb282298b2e3f1dba120a450919631ec0542e1d4923351818be85ddb0d9af8a86b40750ddd65308bed9fd789c6bb127f5e0dd7e5b7954be351411c16985e651e9117bf620e57761ee1e08bd79ff50ecb09a7b9b8e27802c991930472712a6475367bbf60de34e586ad178093245f47dfd068600267945783c61d3afcb030ba3a10d349daec3bd62832260561b621e9638f9123948880bc448e4503822afb4765aa8829a4a41501abe11bacb790793e2baf52306be0fda5f2ad39ccf950ea5101c99fd3f360f6c9310ddf112109106c33ec95a56bf18e6675e365eb50913b08e5e0ed6a8a4eb51e62f2999b50c4e7f933d325bea4e27c629c91fc41cdd0831a9d1173ad4dfeda232668acd172595c9a22164db2e21b15119b45742615cfab51ae7ae500d0617f8a47e3cd38e7e216a3307ad7f6bd675b44db9fff1c6dc7334558a122708045d03dd082fcac0ff210181435bd77d5b3da9a95eec42721c264823bbf73cb747c00101e654f7308e00d35ec90af819cd83e1695dca689625daf70a46b0f1a6849b75020216f5cdfd7638eca97e798a11efcae371b79779d96b68b3bee2da785b1b7be96202428de97877e08b38b634453aedf262d063d057e2a088bf52da274ea8a85085492724e99bb939cb2f2ae8e32aeb6e457f5e25a0f32844518d1333497f015a95e77066748731b92ea75855eb4a091279f775292045e6759259b31411d301ea0b3aeb797e9057bf66ea26ecf3f2c5fdfba8e59bb571eb27870251c830dbbde7992c5900a638034c4fddc2f32c10d680043ae528046f0f9418b19a423ec2b1ef1c9cf2f8823897a25582e4874244560797ab6883b47f31df1929b37938d81d71934fb2a3642587428dc3b050aac515b5c0d5b51e671f4ba3ab4f1f4e50cb854e0a8df162672c61d009a1ce84536eaf81644f790f582072bdc68902c1e100bcd21a4d349b24d860b9ac73b0ffd83af5c371a2d7c164912a9a7e397ca69704cbf831b07d702520628869f89549e641331ca8137f5ba478f08f3323807313fe5ae54898a2dd0f9c8a76fdb9920e5a9077bb9b4a0825889244c59e9cfd81cb1c219ef6649cfb0ca0ae7548f11e109ad2ef4f1083f23c6fa57fdbfdf4fa6544f7422eae4c8d0c3b6dc9d3566eff5568698fb4f65155a17b6ee202c4478dccfc3563ad3736856f750860c38ef414eb57bf007423f67d47f4a2b72372089e1c906b0cb3f495ce37180049a7b1839cfbb4e1c943e54cc026829322fda4a13d7cacc2466e1b3a74c6095fac5c37393616621e8885182c992ebc040cdb2d3cd17dff9d7f761a793c8a7272adb4a6f3b6a945a6476590f3f0c5291b7d367e896824d51e0c9a8cac943ab86a4dad31b13299e5c05375b4a69e1cd1a5c1f0db8221cc1e64a7f2d940a1c3ab2884b121ed8a02f379cafb47ecd0d07df41df903486f88b1564be398a3694817e6d00b6a9d704259bcf368c36b612ff131b136f620af09bf9757cddc741d04a48fecf8944f848f8f84d16f8475d726538e600b9666904fe8154e641fc79377455dfeeec84297e5220a0c8bae196e1b4f7afa7c513dac1c27d9e55d5cd942737685134ad28156e295c89e8377fc2eefb1b6f78002e9207fe4e6b490e03621e15cd8db3379d78bee769fa505f0939ae07e24e0a29612acc2f2b5fc9c7797b111096b1120ebf2e9e44bec5f7fd9bfb20e8d39aa922d0c781c2c79ecdb3cd97c5476d7d22648c718b088e24ad01759dbd5e38d81cbf5007649807e737509b8f89da5f9ad3471d136b50685504e1a2b8b9167d91020a4c8648dbfe1af14074e9ef4ccb66e34304d41f35b1fc9672dc4430fbaa1c654643bd7fc5012df2ac7818dbb0b739986ea1a8360e710a69a2b3acaf683c62320b1c5184a6ed97af06413244bc73a0dcaa3a023bf8ef4048083df122d4f8616ffb648116fb959f044277c9ff7ccc634d1d64955fc9dea925e2c87a1c5244b47e06f3a7350b7269f37adc5b4b6d13fc8bcde6c0b1a895077780074a66563ac9871976167c3b8cb588a2c3646d22605d74b429b39ed28f90c358e37d05ebc8ea55012e14e3140ef33037169baa700df3a26b81b65276058c0c7da75d555ae9930edae33610dc005e12b5ca33b4fc0bdd827b6732ef531c5fd12974a0d6346a05fce10e5bfd39501ab27752a7f1d93e8c1ad30df412a654096d5ddf91ca7cde9fdb93a4c594eebd12438c0a9caba13a7f054bab27d0d3710bffb80fc9d27da1c80cc1adc1f1f74d39f1b87c55b4b8401fee6f03be85cadaa9f0599db12371abbec87f401c4247199b2448165fc309e8f03530cfa94a929f61cd90caa6a715f75e9f8f8eeb3c889f4368bc2d04bea1babe2d6681c85a7c3767e11da601e346a63363694aa5c9bbae69b33246d383d17a964bc3cd92a9e866158d8ece3359c119ad05a6bae1b76797a20381683bfa209acd00c8e9395eda6c309368d7e11e8b1bcb8197b0e5ab033dc76044a22a96a15b1b5d329d692b67a6365aeb6f41c0628a436f5aacdf400aad71f1ba89aee43c442d17c172bf7fae4f26d755152fad7e4b9a3c76ed365d6e6c3852584cdf7ffd3784d5473f75e126d5678dff50f0b3add401019d00c3d843bb7dbff67c6a80ef95a257dc46dd80a900b731b768c88e1550a4705a07a9acad0dee22ea92ef4fbccad11d805ce0b74d42f009e0e1db5808f230488d7ca36f9f41648a69ec6e9f82bff6fccf1a029c1b4133c8eede4cea8faec69ec3368acfeac3f503b0b8b39d8cfb4ba0cb558a9dfcb26bfa88071585f06d51c45f5dc69a898a422cfc93a28bfbb351c8bfd820d2af034d6b8873701396fe37d80691fbef22c81d2b59e2528900401fd52c92a01168bbfb0f38accf304432fdee1059aa76071635abbe552a297915a6b0e32617f945fc2a17c00312e771ba75b92471309d0868ee4be35feb6122cf644e3625e0f2b45622e096d23303c50d26dbc75134658bbd2cbcec849a969a6e32da2198dd6bbebd859dbd9559b5263b68a6236acaf67c1a24ffcf0396f7d6cb0a67f7d147f6636b111ffeacc86a5200c8fee40d03f2ab4cffb3ab8d0347621b1c812afba8b50099c06d3f39222708218c4481b1b03dc2afd0f528aabc5bd917d2da2c6f9be60b84c07e86c84cc2cb54041254013f60523948aa48ff6936d19f6658b6ebb043df00a3f67e1f5769145d5b2c9fbfcfad4718f2555dae7345ec3460a2d006410619c0ababf3af5fd24ae0c6f0a6afba83b467ebcad8f4bf975d12cd5fd3c4aa81eafdf65b7cbeb0a40c23e2a9646b459369681b9390436096b0363d96bb941669e247d541e6bfd082614bb880c922e56afb2e061b5836852530ed2d56fabfe3cd88d035561574215999a1a309dd8696a63452f44c73c17675316137ca4eb59638f83c5e751642164e7b3e8d6cb6b55e2da2bb413d16c5bb46ba7bb887bd42ef2c7e7172d744f96ee8a6e42caf7e1a608aa353ad9bf541820c1bb37895ff2b7a3bf60b261c28c36ce1f08a979b51c2ebabd3870c1ecc05256344c21f72367f0d10eacdd169d074dc48418c7e996ec9bee750dbed649202a2c6f30cdec8eab58c4b42aca7cf52e4e3c49674f8e64512dc429156830438794a3f3d787926d1c1e1c321becc09ef7958b2af3a3be4dfcdfb1fbf725e7d3712a875e2fd665a2077a60c2dfc818d9dd11a31d4f237c21d65f07f16c894401df1cac95f5f8086156e39bf7cb2e9a5bb17c775d6b76dcff9ecfb81f511041ac6bdc97719842333ee30c11484b4045f0111d56f40c913686c812bd7700896d77996ee2caea8b5429d8b4bb469b516ea65aea4675e4a8a15017a56da3242e11322fe9ed0112fd521af63aeed89769c51b2db665776a75e8e6049c548fa59c83b59df8fbb3e1042b56debe1639d66750fc2ccb8ab379fea3ec1730ac865d8f93df792f2f6eeb1ab52660942457a83077cf1cde57150806b12fcdb2491afd1f9350579cb8c094dff941b0b72867b4b7abe3e522930460cb4459401bd9183d504b19cc23b8d0b25ba8253568a8991cdfd0502c964c8ca9b76da74e2fc343afd1c1d2ac0ebd9e5f582b527de90b2ef53435a4ab5106f6fc724e3eaa7c24cc2de651e784221e0a698f22a1cb64362c3ced006a7031ec875ea4ecde9e901d6f094db57e53b617876ef3f5eca499dd6a43cd0da463a1c74d89e071d9ed265fcf3cd691f4de004d82ccfa54889c9885d1de8a5f0cd1adaac04cfd586963760c36e59882b5619707a31220c7ef13ba47fb5c4efd887e6aa417f4bbabe089a385f1115e1189976854b53e4d6a45db155689ef525287b5f853bb71d065243e696441564980f94b2d33d8976993904e9f5ab06d6807def08e6a37a6c554aca37698225d8eb0345899e1a6d06ae26c6e50c791338097081eb58ee2b019f295a482272f24047d429fee6e8b783498db27684d5d591a66a63f3ca4f9649b73abd1bc4ec55b928ede769e54f08aa8160a1ad68b41a12ab7d7585088c61db423d41e1693edefa536606722aece9f8552e7ec0ed4dcd2b322794d808acf0911490ba37db7dbe9a1bb6c0a93db328d71457acc4ea6585a1323b613265b50b13a5ed68376cea8cfbdd4d44ceba37edf4941d3e8dec0d1acb6b93ff3fb965710c36b8d7417bf0cc32519c1f0dae8320914faccbadf2f572dba4027e3746a685c8ddffd7f3667f7495223378f0c73aca0db3999f51ab4e46f8e3c27b033de2475d73e758f1409ac8be14a788f552bf3116ecd76948e8cecd03ed9f057064387939f471c03ad1769b63d300ca960c7130a279c92d1a1aac12d9d021f045fdbcc91bd81b1dd970311d9427121b8f2bdfae35bc08b31cae8f95e92c000000069001b4ba886086ca8ae0e5b1d7b99491d7a5f93012a9a8fe4b8b38f49bd6ef107a0679dffea4a8993d4eb8dbc65ddf29f7df08ef81aa69c396230d5372a659391db0a224dffcc1a3b11b8cd29a29542687ed6f23741cde1d38d4620024ed4c6d3ba55af8762dcd8b31774c61a2eb5ddf60e0d06cb3557d13b44b675409306e639b41850b005ad91ace703d12e2532881289e340274ec561b21efce4b68e8f5bcc3b6a261cce940316dce317f0facb914822afb9050378c9f9f35f95991e1266f9d95d9680464bd717ed6dd0b54a06e39a57813ff9dde406d418f2cc925a7c2f1ad134818ed84d0475bbf35d761fc3ed4905a08779d52002835bc5702b54df36957a49173b48261407ee35c3c8eadb59a407b38d9c83c0dc2e959c89d380998486fa5a2cf960ea54f743ef0e3c1851b0297e1bb2e0292ee3b47956d598fe202cf + +pk = 000000010000000600000002f669d58a91971ac07f6a5944eb3559d47589156c855b69b744ce85da0ff511a6a353f52748de5549c1c7c6cd4236564d + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4.rsp new file mode 100644 index 0000000000..a11e9ec00d --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000100000003584a33ceb2d50a9af04409357774dbaf8b8ea517370e62c4dc06882c1407baca174157ebbde27d8e255d5c522c78617f3cfa03b811e32593ca965f771f8d88fb3059a272c3b9af8e445b37650f3616b9a06d2a79e74e847dceddcb6f854fbae8e6790d241e5e496a66244ae738bca8482630b5369e2c45e27c7ed919fa298c1d5ca5efdde0a12b258a584c9f44799b5c40f3889b1e8f3c274a355e24c088bcdb5288a47bf40a4677062662f4feef135493ea4498640c8efca349dbedbf5525af5425a8aabbfb671de5f71072eb07867e15c383a06f39ca2a09ae0d53c4db18370011d4ab6842a35c3bab93e642bee89310ac457e68869f4289f9e93ba553e39892b2969578ca5a02ae8a0272f1b2d6c8a022dac6a397d84bd2ea56136ea45aaccc1122aca34bd4ba6a7a06b2cfede81ce193ff878368f9f2181b8116185558cee1cac048f61109ae5c7b3973241919d9974f8b44dde66f1a8b2830abebf3ba1a115f4563453fe20f7ac023f6a02544d24b38e661a25a68ccb44c287f28d3fb0769048eee6d8f41046423d77e56344f7d5771f8ebacda4a4b5069f0c4746a74e77aa8b5615257b2dbac9863937e6d9c905217341a825c0460dce7a13845db6449d1e1f86d42731df8eb6f4381d71dff4defc11fa5d6bc9a0309a47e298dcf55e559c750f3c5d0fc1a1fedc8c8c0248a7babf6390fbcf70ad7b51259b336a2a39e1306968abb7f39a94a36374910ffa96a436a225436f7753eb7a28198750c3b5deffa1092eeec7857244b4a4d13d1eec3adf0efcce3ea75507f376a6c7effcd9e904ef2bd7b3c8c092066d46955c7ca38ed79ca8a7ffb1617d1619026c8fcb3cdc23c7403cc3f90e3c3d88123b20d40e8763c0aeccaadf79c41a69667cdbdfb73b33642f1d1e3b021cf2400e6252526d3fe62edc9d022e88ef111b6b5b668d2b20e23baccd9746668fb63f3916630506d0b696d850dcc60eec42504398f4d25e2eb6f36a417bd71c20c780f1a5075f86e953302ef0b7a6a9b909857d0ee6fd4c1ade224cf667067d9df328433b19e136bed536e364f82ac05705439967560c8606cd1c26b7146b82e825a233dca703ce03ab7df5c5345b5285be16d542a47a1fb4af74e786cbfd01c0456b8f86fd0e685137617224ff627b5f3dfbb75c9258484d9347ad6282e170c2657f5721e24d5643a4705d6f9aa335294278421da783d44ac38cfc7676740a399f9002ecac9a78b41c70c3188298dca26452b72a8d582d167c3c965d5f5c8c8f57022f417b0941f7828721951978d568a3d2ee0b7a843e5c697b0c7fc0975f0f09fd18856a16fc63db04e0f3ce3a357e4d3208546460814c270629d7810e452454927f29666a919fc8fb104f3c9c1fd38c19c6574d4dddb5c18683a8973cd061faf5f5c18b66734bf8c08766612897d0d9025e380c6317d88791d0861484e51f205c14e0bd83d2d61c394df3645eb0d66c80ded707429fe5e1fa77f3c3389ac59b353ca657e6aa88dcf6498479e76bbba01e75e9d992e6d3181eccd53e122c0c3ed428d809eef91934ee657364151bf711f0c922b6490fa2a9ea9ef02a9fad3a655cd305a2ccff01f60b9ca0b3e8381cd83960c08c066a30a9f46585e7ba143da7700216cb5234406301beb66a0cecd7d8122429992f8eab74cebaa1e7c8ce4d54587056bdad8636c46326e484c63b5aef8b6560e289acc20b953e8bac254da2f22751d83845be6132c6595cbf91b0d2ff7402fd789c92249af031afc1076bc99b9e9cd6e42a1a2dcf8baa42a0c34dc343508e70bb0760e5f9d8ec6390995bbca810dff3a0474c59cf9fafd9d09bf190bbafe003c7576960a6dcfa0226f874a084b4a50d6a680f88f1f3f352c71eb26df521e5ac9c2c6cc410c51ecbfcd090d7c09541810c80cafa5710c849ed324ee734a8ec0610a1a0ccda429f86b28ca0d0cfdc7d29ec03ea1b97021dbb00a7837d5ec8f6e6ae198ae31c9b4365aec42e83e92e879fb641915ca129324176444171873a75b3df1322cc74796b5e6cac0f950d92c322a8a3c6c0a824f8f92ae30aa110c8a415687ce6dae5135b4121b67fe4e5bff65fda4e0cde3372a0937488d22211c92192eebb9c0b38770356fc65533a86efb75a759fcb02c62aff2f61d3af079ce09d6b01ec9d6fd3fa6f5e2f60273f4b9c3de7bed546311557c197dd2c5398853a5b768db5d45b64d2860137c1c1e9bf3bbaf8f44cda1ba1c88798bf91c962195a11d1d43b937801243ad3483d951ce3c250de463aa136273c9fb9404ea92a204ad15a161852182d271e6dccce0c1385eb8a192d063b0a018cfa36d8357d89f1257aef5be8be3f26051dcd238e4977324204029f2d70a4dd2a9e9cdef1831c7163276bcfff2f2530f29dff5dac9a7026f3ebf9ee0449465a61db572b18434dcbd30fb0843ed81560473f8529191b25abb086d5ee06022b10a64b3a1ff18aeeccf277c4b33c9ecf4097bd5097e6bd0a30ad4d52cf5db089d15f4627a44e0689781a6c6a8ce08d744123f6364b1e7428aea701b20985f2ef76cdb3023297c894c7f14892a3e891f396a3edc2507892034a142556e78deba31ee286f0e2752eea28a0322789fecdeec35306d87105ca2c19f977597bdce1de1f8cc1f00c45ab2ecc7dd6f2d8e8e7f625be39a2348e77688819ed541d2c12ed74688d201fa307d958ebc4b8ce08a6b0e9a3116b89a038807e587bceb9cc98cb91d69f884c67e88e30c7c8d72b208dca96f6af60a73c4444d5e7f5b472fd2ca3b36cfa2b4bcb767acea4d8085b080e57f76ccc0dce2c2943b6c806ce20c88300bed34a383e5bbcdfad496910b9198bd43364da92d1fec89b90b53ba54ac634d5ac1f7faf0385358b6b0b5f5d06e31df6d3b17eb9181cfa131897dacbde42ae3c66010b978ea391944db2b52e52e47ff7312b1600e569b46859bfb6af8c4402ccaa3632eb293ced20d61552c75f0068b5a0a7d71f276367f0061f01e7fe71985ecd70fea79d406217f42260791f554b1a1b943e5312ee65251ac228d78c90f517949f6460dd3664f09b092f483d6ef2c00000006ecf1ce60192137cb466675f2310292d462477d811c672cb1890ffff4979ded0aa791c87c602307be68e7e3ed69e59b7c22458d9d49f353679f1f89cba91cd886900b1eb3666e5f0e78dec37a110c5cf09c1571f66e5862d48f6f4dc01812fb600ab2b3ddb1c5585cb2127e4a5e5faf00636beeeafb3b18f2481de5a4dbb9182e93a5cad39c43bab87f66eefd1428d0a426e0ee8c41fab4baf40bb982b9b5f1ce9eb65ad914744b45a4f00c11dc8fb012844cde05816d91fd387be9a2087c3758634e4ae3658a035e9b9e2d50a98ecb21489779c538aac7fde32b293e4f809494a800bb16c5ad2e8d4f22d61fadd2cf82bcc9ac210bada1a203f90f67b115cca1f9c109cc955776335779e6d9153a9880c91c9af9eac9e88b7a5e5bceb3bba9ec9432fe015b672ce4c04cc49ec42b865038b7166de32c1f745c27ee919bc25d0a + +pk = 0000000100000006000000031fc1a45b518c620d9ecff3b054dc2104f35f80dffa2515819e569eaf3594081dd7029a581ae1e818b181368d1cabd76e + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4_H5_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4_H5_W8.rsp new file mode 100644 index 0000000000..638351718d --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W4_H5_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520656e756d65726174696f6e20696e2074686520436f6e737469747574696f6e2c206f66206365727461696e207269676874732c207368616c6c206e6f7420626520636f6e73747275656420746f2064656e79206f7220646973706172616765206f74686572732072657461696e6564206279207468652070656f706c652e0a + +sm = 0000000100000003000000033d46bee8660f8f215d3f96408a7a64cf1c4da02b63a55f62c666ef5707a914ce0674e8cb7a55f0c48d484f31f3aa4af9719a74f22cf823b94431d01c926e2a76bb71226d279700ec81c9e95fb11a0d10d065279a5796e265ae17737c44eb8c594508e126a9a7870bf4360820bdeb9a01d9693779e416828e75bddd7d8c70d50a0ac8ba39810909d445f44cb5bb58de737e60cb4345302786ef2c6b14af212ca19edeaa3bfcfe8baa6621ce88480df2371dd37add732c9de4ea2ce0dffa53c92649a18d39a50788f4652987f226a1d48168205df6ae7c58e049a25d4907edc1aa90da8aa5e5f7671773e941d8055360215c6b60dd35463cf2240a9c06d694e9cb54e7b1e1bf494d0d1a28c0d31acc75161f4f485dfd3cb9578e836ec2dc722f37ed30872e07f2b8bd0374eb57d22c614e09150f6c0d8774a39a6e168211035dc52988ab46eaca9ec597fb18b4936e66ef2f0df26e8d1e34da28cbb3af752313720c7b345434f72d65314328bbb030d0f0f6d5e47b28ea91008fb11b05017705a8be3b2adb83c60a54f9d1d1b2f476f9e393eb5695203d2ba6ad815e6a111ea293dcc21033f9453d49c8e5a6387f588b1ea4f706217c151e05f55a6eb7997be09d56a326a32f9cba1fbe1c07bb49fa04cecf9df1a1b815483c75d7a27cc88ad1b1238e5ea986b53e087045723ce16187eda22e33b2c70709e53251025abde8939645fc8c0693e97763928f00b2e3c75af3942d8ddaee81b59a6f1f67efda0ef81d11873b59137f67800b35e81b01563d187c4a1575a1acb92d087b517a8833383f05d357ef4678de0c57ff9f1b2da61dfde5d88318bcdde4d9061cc75c2de3cd4740dd7739ca3ef66f1930026f47d9ebaa713b07176f76f953e1c2e7f8f271a6ca375dbfb83d719b1635a7d8a13891957944b1c29bb101913e166e11bd5f34186fa6c0a555c9026b256a6860f4866bd6d0b5bf90627086c6149133f8282ce6c9b3622442443d5eca959d6c14ca8389d12c4068b503e4e3c39b635bea245d9d05a2558f249c9661c0427d2e489ca5b5dde220a90333f4862aec793223c781997da98266c12c50ea28b2c438e7a379eb106eca0c7fd6006e9bf612f3ea0a454ba3bdb76e8027992e60de01e9094fddeb3349883914fb17a9621ab929d970d101e45f8278c14b032bcab02bd15692d21b6c5c204abbf077d465553bd6eda645e6c3065d33b10d518a61e15ed0f092c32226281a29c8a0f50cde0a8c66236e29c2f310a375cebda1dc6bb9a1a01dae6c7aba8ebedc6371a7d52aacb955f83bd6e4f84d2949dcc198fb77c7e5cdf6040b0f84faf82808bf985577f0a2acf2ec7ed7c0b0ae8a270e951743ff23e0b2dd12e9c3c828fb5598a22461af94d568f29240ba2820c4591f71c088f96e095dd98beae456579ebbba36f6d9ca2613d1c26eee4d8c73217ac5962b5f3147b492e8831597fd89b64aa7fde82e1974d2f6779504dc21435eb3109350756b9fdabe1c6f368081bd40b27ebcb9819a75d7df8bb07bb05db1bab705a4b7e37125186339464ad8faaa4f052cc1272919fde3e025bb64aa8e0eb1fcbfcc25acb5f718ce4f7c2182fb393a1814b0e942490e52d3bca817b2b26e90d4c9b0cc38608a6cef5eb153af0858acc867c9922aed43bb67d7b33acc519313d28d41a5c6fe6cf3595dd5ee63f0a4c4065a083590b275788bee7ad875a7f88dd73720708c6c6c0ecf1f43bbaadae6f208557fdc07bd4ed91f88ce4c0de842761c70c186bfdafafc444834bd3418be4253a71eaf41d718753ad07754ca3effd5960b0336981795721426803599ed5b2b7516920efcbe32ada4bcf6c73bd29e3fa152d9adeca36020fdeeee1b739521d3ea8c0da497003df1513897b0f54794a873670b8d93bcca2ae47e64424b7423e1f078d9554bb5232cc6de8aae9b83fa5b9510beb39ccf4b4e1d9c0f19d5e17f58e5b8705d9a6837a7d9bf99cd13387af256a8491671f1f2f22af253bcff54b673199bdb7d05d81064ef05f80f0153d0be7919684b23da8d42ff3effdb7ca0985033f389181f47659138003d712b5ec0a614d31cc7487f52de8664916af79c98456b2c94a8038083db55391e3475862250274a1de2584fec975fb09536792cfbfcf6192856cc76eb5b13dc4709e2f7301ddff26ec1b23de2d188c999166c74e1e14bbc15f457cf4e471ae13dcbdd9c50f4d646fc6278e8fe7eb6cb5c94100fa870187380b777ed19d7868fd8ca7ceb7fa7d5cc861c5bdac98e7495eb0a2ceec1924ae979f44c5390ebedddc65d6ec11287d978b8df064219bc5679f7d7b264a76ff272b2ac9f2f7cfc9fdcfb6a51428240027afd9d52a79b647c90c2709e060ed70f87299dd798d68f4fadd3da6c51d839f851f98f67840b964ebe73f8cec41572538ec6bc131034ca2894eb736b3bda93d9f5f6fa6f6c0f03ce43362b8414940355fb54d3dfdd03633ae108f3de3ebc85a3ff51efeea3bc2cf27e1658f1789ee612c83d0f5fd56f7cd071930e2946beeecaa04dccea9f97786001475e0294bc2852f62eb5d39bb9fbeef75916efe44a662ecae37ede27e9d6eadfdeb8f8b2b2dbccbf96fa6dbaf7321fb0e701f4d429c2f4dcd153a2742574126e5eaccc77686acf6e3ee48f423766e0fc466810a905ff5453ec99897b56bc55dd49b991142f65043f2d744eeb935ba7f4ef23cf80cc5a8a335d3619d781e7454826df720eec82e06034c44699b5f0c44a8787752e057fa3419b5bb0e25d30981e41cb1361322dba8f69931cf42fad3f3bce6ded5b8bfc3d20a2148861b2afc14562ddd27f12897abf0685288dcc5c4982f826026846a24bf77e383c7aacab1ab692b29ed8c018a65f3dc2b87ff619a633c41b4fadb1c78725c1f8f922f6009787b1964247df0136b1bc614ab575c59a16d089917bd4a8b6f04d95c581279a139be09fcf6e98a470a0bceca191fce476f9370021cbc05518a7efd35d89d8577c990a5e19961ba16203c959c91829ba7497cffcbb4b294546454fa5388a23a22e805a5ca35f956598848bda678615fec28afd5da61a00000006b326493313053ced3876db9d237148181b7173bc7d042cefb4dbe94d2e58cd21a769db4657a103279ba8ef3a629ca84ee836172a9c50e51f45581741cf8083150b491cb4ecbbabec128e7c81a46e62a67b57640a0a78be1cbf7dd9d419a10cd8686d16621a80816bfdb5bdc56211d72ca70b81f1117d129529a7570cf79cf52a7028a48538ecdd3b38d3d5d62d26246595c4fb73a525a5ed2c30524ebb1d8cc82e0c19bc4977c6898ff95fd3d310b0bae71696cef93c6a552456bf96e9d075e383bb7543c675842bafbfc7cdb88483b3276c29d4f0a341c2d406e40d4653b7e4d045851acf6a0a0ea9c710b805cced4635ee8c107362f0fc8d80c14d0ac49c516703d26d14752f34c1c0d2c4247581c18c2cf4de48e9ce949be7c888e9caebe4a415e291fd107d21dc1f084b1158208249f28f4f7c7e931ba7b3bd0d824a45700000000500000004215f83b7ccb9acbcd08db97b0d04dc2ba1cd035833e0e90059603f26e07ad2aad152338e7a5e5984bcd5f7bb4eba40b700000004000000040eb1ed54a2460d512388cad533138d240534e97b1e82d33bd927d201dfc24ebb11b3649023696f85150b189e50c00e98850ac343a77b3638319c347d7310269d3b7714fa406b8c35b021d54d4fdada7b9ce5d4ba5b06719e72aaf58c5aae7aca057aa0e2e74e7dcfd17a0823429db62965b7d563c57b4cec942cc865e29c1dad83cac8b4d61aacc457f336e6a10b66323f5887bf3523dfcadee158503bfaa89dc6bf59daa82afd2b5ebb2a9ca6572a6067cee7c327e9039b3b6ea6a1edc7fdc3df927aade10c1c9f2d5ff446450d2a3998d0f9f6202b5e07c3f97d2458c69d3c8190643978d7a7f4d64e97e3f1c4a08a7c5bc03fd55682c017e2907eab07e5bb2f190143475a6043d5e6d5263471f4eecf6e2575fbc6ff37edfa249d6cda1a09f797fd5a3cd53a066700f45863f04b6c8a58cfd341241e002d0d2c0217472bf18b636ae547c1771368d9f317835c9b0ef430b3df4034f6af00d0da44f4af7800bc7a5cf8a5abdb12dc718b559b74cab9090e33cc58a955300981c420c4da8ffd67df540890a062fe40dba8b2c1c548ced22473219c534911d48ccaabfb71bc71862f4a24ebd376d288fd4e6fb06ed8705787c5fedc813cd2697e5b1aac1ced45767b14ce88409eaebb601a93559aae893e143d1c395bc326da821d79a9ed41dcfbe549147f71c092f4f3ac522b5cc57290706650487bae9bb5671ecc9ccc2ce51ead87ac01985268521222fb9057df7ed41810b5ef0d4f7cc67368c90f573b1ac2ce956c365ed38e893ce7b2fae15d3685a3df2fa3d4cc098fa57dd60d2c9754a8ade980ad0f93f6787075c3f680a2ba1936a8c61d1af52ab7e21f416be09d2a8d64c3d3d8582968c2839902229f85aee297e717c094c8df4a23bb5db658dd377bf0f4ff3ffd8fba5e383a48574802ed545bbe7a6b4753533353d73706067640135a7ce517279cd683039747d218647c86e097b0daa2872d54b8f3e5085987629547b830d8118161b65079fe7bc59a99e9c3c7380e3e70b7138fe5d9be2551502b698d09ae193972f27d40f38dea264a0126e637d74ae4c92a6249fa103436d3eb0d4029ac712bfc7a5eacbdd7518d6d4fe903a5ae65527cd65bb0d4e9925ca24fd7214dc617c150544e423f450c99ce51ac8005d33acd74f1bed3b17b7266a4a3bb86da7eba80b101e15cb79de9a207852cf91249ef480619ff2af8cabca83125d1faa94cbb0a03a906f683b3f47a97c871fd513e510a7a25f283b196075778496152a91c2bf9da76ebe089f4654877f2d586ae7149c406e663eadeb2b5c7e82429b9e8cb4834c83464f079995332e4b3c8f5a72bb4b8c6f74b0d45dc6c1f79952c0b7420df525e37c15377b5f0984319c3993921e5ccd97e097592064530d33de3afad5733cbe7703c5296263f77342efbf5a04755b0b3c997c4328463e84caa2de3ffdcd297baaaacd7ae646e44b5c0f16044df38fabd296a47b3a838a913982fb2e370c078edb042c84db34ce36b46ccb76460a690cc86c302457dd1cde197ec8075e82b393d542075134e2a17ee70a5e187075d03ae3c853cff60729ba4000000054de1f6965bdabc676c5a4dc7c35f97f82cb0e31c68d04f1dad96314ff09e6b3de96aeee300d1f68bf1bca9fc58e4032336cd819aaf578744e50d1357a0e4286704d341aa0a337b19fe4bc43c2e79964d4f351089f2e0e41c7c43ae0d49e7f404b0f75be80ea3af098c9752420a8ac0ea2bbb1f4eeba05238aef0d8ce63f0c6e5e4041d95398a6f7f3e0ee97cc1591849d4ed236338b147abde9f51ef9fd4e1c1 + +pk = 000000020000000600000003d08fabd4a2091ff0a8cb4ed834e7453432a58885cd9ba0431235466bff9651c6c92124404d45fa53cf161c28f1ad5a8e + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W8.rsp new file mode 100644 index 0000000000..912d84328d --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H10_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000004e8005f5e66764d13c1a66c4b0919b51b818e23767f813cd64ce8f961e189ad2287a30c45cb69478d54db906e55516483dc65862e24ef059bafa11845aba072ee4302a1e4c22243cd893f12b053529942bf1d3c97de2c317a317c9d2fe5dd7e3cdab428bcb8935db5f3efbd2757261b50431c9ef1cf49256a37355bbc2931ff7478acce22a47dcf7c0662d7b21a8727b0d1ae54473d2c761cdfddefcf10f050821345b78d6a1fb6399a0233d8cb0062792bd3e944951a9d1bc85922fd5bad206242800aa6070d1968d1738f2837039f1d8023543302c075ae3b7e490b4e49b1c2f52f7604f94d455d49c08695f4536d027374838fb11e1c32de758434c1b95aff54b3a949c2249eade7486bbd5a600060d1d925da6cf66ec882558813bc3c35c7b461b013f847c3fcde510affdbb548f0cb16d4151341ecbf521090d6d94062d4c06316a0c932a260cc3a93fe75a6e56e642238902fe1d064b43390e71c95ab901dffaa506aa89fb5e4620fd9b71718a8e4516b791c0ca899addd197172f26fecfb6905ef031679b85fc32b98bebf54c172d294d749e041d4b8e11dcca56c70a181c55d1fac4acc936efa857eca994ef6b4bdbea24881ca38607babb2bfa9635d824119d87c78aa919b9ed71d4708f044222f5c80590638981ed8b46a099c5162982665ed2c1bbe1a6f1a91ebb2c07dd5d577713bac16964eb5bbc763b7600c08a13e02bfa253caac622d038961fac0d45f3e3ffa998d13f80f78f454ec7593bcf47214584f4f32dd02350a0175f646c7a80685f2d5d2bfa3ec8f09bf45869d077a6fd43b777c95bf8f848445709acaac75e82fb479a578a16ae5724084b3bab6d8bb5006d246545dabe8a27bc7419f2cbb71beaf7d30d2213d053e3d75d3e785d7d76347b45f0ae31e1d4138da2836b401424213e08863e87760d3cee7caee7e5c9d576ddd3cd0a827960c2697751b855fdfbb1ae63a87317fcabcbe251a305340172bbf0d907ca57d4d01fc10abdd4d7191fcd9400cac13ab3c949f2ff0b1559cf6336f2cac59b97c45faa702b1212b341490bb0905b0598b8d76d95cec3ee6fc37d4096b625c84c2ce3a4bfd1e541661eb57bd4ca0a5d1a55578d0018bf0183cc2684fe61d8376ed35fc6c9715e03d20c3c103f29f8eb4d19bfbfe71a81cd587ec0a2302789bdc9b6741fa811e0b7dd4e66abf7287fa282d039f9c98cba1e46594ba3d2fd2b994794c7afc627f3dbb29900f42aeb0d7aad125634fc281e9c37047a1c7aa7cf9d78c3100e3d1395df86e785970f3e107bf12ffcf7ee3fa8c1169192c61dd9f3bebdc08d4290e36e8b135d6596b70c91c281b766b0ff8ecc82d2355f33d1077d7f0a5bfd05e19210b78408175b1e7c9330a8f4ab4ceeee202b3667694277169bd0403db497b57d9974a3c1ee438a0339908736e1f97ccb1ea3f324682f0786e218c59751f8231ab20d9bf2648e06e32018f3822d66a2d180fe5203484401e5471b925cf05aa64f287571b0645d05c438f61c14660c316dce2d8aaf22a64430f69d7c3bb14721ce16569863b7e65dbb6192b581751a903fa2de500000006979941fe2a0034185d9aeb8f6eb51ef6767f2e0218f9f1a20c604fb41592503e1efd6c941c7e3056ad0b47b3afc6954a6354791967c9274a43f835fc370099fe0d26a4850bd75228166c06d23d16cb07326be16f454269d1648fa58b6ce4738a8fb926d2a61b5aa66c4a3d4417b0ab7ba7fec2f7bcc1d1d179b7d7a90bc316975c81d903b29345a3ccb9309534aeeb6647dc5662a5a64e9b2c622bd394339b9963ac9e6c3479a5d6180400620115b6b09af77ad82c7a39e278ced784702d1ca621705827bce972d17fe501ad892d4de6f94e748cc7ebaf600ef73037d41a4719cb7a96ef86d89b0eb0e7da8668c85e52407b2b14c232ae6df56bed6d1ab6d7e5bd2448f15e0acdb7792f62cdc3e7ff1db99db034524e0e2b77749ef0b624dc6e2937e289954069c33fe4d0328672caceb377112bbdaa844bdef5bfdedc1950aa + +pk = 000000010000000600000004d1436ef5c39f769b4c9b61659c603f4a29be7b4a06700654e65fcce588dab0b2478e6b0bfb4e74880afac2a1a2d2fb66 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W1.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W1.rsp new file mode 100644 index 0000000000..3d78978c41 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W1.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 0000000000000000000000017d1442b03e3d2c279b85ed284445fa421587601ebc1015f9b49ea82e29ae7fa09c61209ca5af037ba2779cd5e9ae813a491892562b8f737a6334445e63c739bd3ee3725b06f7b9a26316a6997f143db039f38134e35669d9dddf12e75dbcfc9cd0641d9281215a820882047fec3d52854c3285eb61b25c9b5db59d0fb4f38acf5a3bb2a14fa03e2e03a4df7570cdd167cbdddfa44973bcd3ebcf3501aa80a748b70fac5ae3735bbf1a8937d6b8621d837cf7c5edb65ffd08e830cd17bd6753cdc98df5a09fbbed909e812c50f80f71315e2ec337ea1ccd0f203c9932e889056e19144c0b17144bdcd0c50bb51e8f39ef8ba2d787fcf9536e55e59be8b5b5f55f15cb186678c41210466eb6843957f69f85fc0e1e789ac26c2a0744b076c971bd364cb121c87e2e08491734e51f9be2a3698373473761bdf54529fc40e2cfa865442f320e3045ca046ad2646f6a2e2e91f054a9c4ad449bdf7a35ac9b29e6b8385d342b49c15fb0077aa4a41c0d67dbbff3329c7f3a32f183b47affb5292af90082c6446999b1316c46f79716ff2c4a5a8d510977af1e86bae7cd578f43f4e8a85d8ab33541431499cfbbe66473f1d7653a3882ead0dae56f7e010fd17987361d5c48a2835f25ec9c70b7671dc53c950c27e4ebcce2b6d5b8332792afdf1a4ae1501af44799f9337edaf1933ad5b679b8291be1589190ace128670e5b3bc230925b78ae34a175c5d1dd7856812011da166d5d8ffaf33f60bf82223fa88bc25696fc21033c7ef5c47f6b0ae0ef47e2119b58882a379ff38b89cd6895cf84770abc68bdaf5309bb070a194f29f3aef69ad6731a741710951fbed65e82d259a73efd6cef99d642695651e1b0ca4dcbe39ae8fdb6ec4b1c44d9386125cac42335da4ca99610d0924473da7d1a85dd527999d363062bba6c919272cc529062120705fe39b11cf43003c851056cb858649da4a0b8eb53c056467163de4d3da8bfd370879c834f78553ad0921d5dde65855d47380121316e8e774adc1576ad529be5c7e465b77dc36e2b28cd88ea44574a8998e477911073fe4ead79e6ca304783ee4817cf1442d311ff17d949ad643f2abc4d71ee5332a62ce8be26623304e68ce1743acb9a25eac59d5ec657673278c28252a3dac364a232730eac4c0d03ea39ac7e954f1b551d8dfd5d429f944a357148f9ab5e74d05d4e2e3dc96c1f5d086e2e313e4ff986cae049445589de4be46e2360e311ddf0592f1c74224aecbf2dbfc72e8c9111fde1f64b7028702e8653f2f6a7823629e174b01c44bc33907709fd0e3673c5d087d730017ef2e61544ebe71ef69d23e0292afe1a7ebb41326cf530d1076b3cc863426d204c8e8b548640e62e1bb236a5d22f61bd1c769d70bace9e813f4ad7fcfa90167fe4c4c78648512185496e942331f0bf35f6bed5be20f9f7d77ca900871055eb9e84fd6c95e7e7bc72c0a92fac0c788841329921423e152c95efadbf31721a36194370bcb0d77738f3b1a4963056d220bc399276e7a0fdd3a1953bde9e2983fc2b045a5c6d5cec1bd6d8251184b93c7bbe06f2606a913f602bb7e2aa42264b25d8eb7d4aa9ec8bb6e90841e52e93b005539d3aa42e953c00a89289fbb75baecd04ba4fc13cb0e17989257cedaae0e52aaff6b06db21d4ab5fd45db385a1e978b91fe6c4aa9473ff6687a80b1f96bfb822f1314a2e097804602c81a1655b71ed74efbe23696e51310edf39b58091d791fd62d17432392e79cfc0c70b9da67f621bcc7fa93b9ee56d340450022f2b3ce5f01f3325c4a7851d7e64646241b394a65486829a794b82593d0579bf4a2203e673fcdc87411de87e157a1fabd7b137da30d632953460d76d48f461180c86cf77392265193906453ec36401340770fcd33a4a278d5c82059a089eb45fa784f5f5dca852f6cbf0ddfad9b8210d472be700e66efb8dc4fa66233a524daf2631be8e39f25119f6388c3d03ff75980d390c99392777ee8dbcc29ed93e9481dc4901d4d26ca5abbbc45a066b5318736967083f3abd97aa8ececf19822b22b3372a76095d5581c7e7a852438f937837cb7a9812234e93af88c465b201aedce324c2af3d7f75adad90e01b67e3e3fae8d8ea18b45506c00cb130312e3805ec4c38e4bc5264f4cee3ec1d1450752b4fb6c6466e3281527385c41e134945b80ba041a8b903a8e08124c9a3fe29bd9722cbd20f1f5f9a0b9cc67a118a504c89d4eceb7bdc87195930b1fa2c29c31abee9a0877f64dc02290871f204629b88a857bf2dc01ff1eeb80af9f44fe70d6f441edf54f72e8d96b0dcecdf7f2961aed57eadf36e40da8142f082cb118534fa7294cea8d741c8450075957f094eb170b6508cb504ee685dcc890d591f460a89c0c3cc08c4010d748c1b7bf32dabe1116dc0781bfded8d98c1c579d4b4f522c273f20255300e7e0b39123a1ba87f9dd4c8a6d435f6d6b4ad1c9580c7aaf5d0c5b4b4ecc1c201fb3fae9b76d14a6f64c1cdb101688909a4207176eeeeeaaa3f2abef9202d051b8042866b09db501adc7f6dd6ce283451f2b247ce89b1c177caf840865ab5cdb619928e92ac4a315eca917a52ab0af747c45c9d4f3977b96b84bf5b46e323ca4a0031ce21fb80021148b84218a420a9430bd23fca1bed37e84cec725b87d7b8e2a7a47d3d016cc434965ae6f6d106f46c8c4565fc467d8dfd24aed77db85834995f9f21c38f405c16d3212220415b3d0b5f97729ed438254a7aad03c8c555364b80885fe75f003b1cac833a4fa1cc3ec7af43e328e5498499836b830b310e46ddaa447c6e8db7d3eb0ee5523ccb52d05d84a4a51288bf73edaaac052fcf5130083937cac1d09e98a70f6f2610789476a30f8b9206448b448c36dd6874f9e5418ad11b7d790276140287f849b441409d2c7bb7b037bd15b5d52fc0190a02562734ac0349d5482b494c05321f0c484e5adc20d9b9d175491dbb05e7220996710d641449207d8d408e3bf4e5dab294381d72766a31038e02d08b007e30f21b79c655ca313a7fe1b893763f2b923dcaa23658d5cad13cd7818e3fab3ef2752b638bb6b5162578a74aa388628ff35e487d7754c4b7b18414973914fe4f075c63e81a7ffd474febf313edf64eff44d542afc40d5d90b7618b6577108523528d1d603535511f890e426da5cdc150d4c50b047a7159d48b7abfffe824cb176a8a6e5cf613bcce956a012b83b7d2b916f0b2db5d2e68b8255b6b3dd930fd8cd8eebc3fc0665865835dc0db816ef635275ec5f463b8edb99bec830746ec86bcf87cfc7cf3d6ce98528181d9f4c75bfdae6981e539ee06b97d48e1807eb4cbca3847debc05ca002b2f726018475de66e9ffc92adc1280774faf20162f9270fc6179ebca7ef612fef2dd253d637f51cf8c76fd1c831e4449091ff3aee820e8a545bfcf9a7c16d080c73aee97384618f24793cd6c37293c2c23d13ad0d7d03c38992215be779e73b6cb979908b2290d051297cc2591b5d7894da71f6c2dc255c9f01eb548c05b5fc5cfb4f9bdb6c007a03b173ec25970fe6b841754bbc529ca32486654556eb20a311f94983c77e118642d5de4d6eb2f4fc95f8b37c90a9825c56a2295e5dd166c9d0a1e3f94023738ae46fd4c99ba60c06d8d42cac8568e7547500a12d02c64a2d73bf075caa8218cab2ae30b0d2d45cc7c69fc44d21dc2cf17453eca38048e58f18980bb5c4c608f1e8f4c264f0683ae0229b8283c93a48eb1182857474a484f473b69aab94ab76ec62f9de834012c91f237d0fec778996482e04c58858bca4dc60573ab69628bb6b73e0fc51bdb3fdc684ebd00006210cce6ab04914001661c8d5b36260a0645053431ca8c29494efceafb20019ab9351225a20a513a8b2321f2c5a6e3c54424b4e9485e504701146812c051cd42fa482ac1c00ee2b227b978d7b0465114636cf1bc04c39840efdd33d033ff4067e850126acaa8b60005f61d69ad38613d3446bcb5e421371104c584711512f65d9131dc08a39291b910482438c6d459353d12d0d7ce4a06c3ac24facf80cf6d1b89b743467140a7d05a36b2eb970d38d914970b65eb6b6dec1b52f1e973b99d4a170bf31ca7908f4a4fb3cb62bc64aaf557b9e4c1511b0daed60f88bdf7aaa4f9b9a849758a6237467144b2aa2b0f24b16590bc151340235133827024fa8cb4e291fac6daa96e18afd121e076c12617d64a34139b1470fe7f7defe9653a6e416fec220656bbd1cf83adca819b7b415085bb746af4b0ff3ce65b5f8252f30ab100b46bff20c047ef76079e0061ac365a2a54d1020928c31d778e19676512d4bc359630b165534b7b6b50197d5146979336f33e9289a120dee4450a0a60394eb2e32a4b2a770a40f81fc98a02865833044f79ed73174118b2b201ce0c4d1a8a0ad9b44cbab004001c5d69734302f0d845cbefe6afa47342bf7924d8e8d231e7cb0e2e1af58938ee32bb08610864384c022f415876746454f427c0fd485d51707ef3227e0628076a14c0580dbd09fb05aab40bb307f290502b03b7d25d4c6259311255998c43be15f25c9f5a340a3cf1d2a6fe722689db45e283529a3c1237b9ecc84d76952a86c7461a73c7bb26aacffcf0a33f9cb21ad93e42e23c25090d7272c4721e48d73c752350a243a0d568b3d6da99ad1a5e31f1946ef130ebebfccaef41a28edcfb0bc3c7f76ac279d92979608f735ab4d5606ff04b21d67f4e44e3e152d871b3eb329612e8881a9e91e4ae037d7da1515397e8a99446ca0efdb889345db20c627b4b583e7d609c0bff453f7df98d3bda21c70187a14f8502699b4d55aa71b569a3f66b04c4b1791d830faec2fc9ab29c33b64165c9ac08377c475c2877e473b3d89018f734c1497bb7143b8e6386f474801403372f8acc43a7188c4fd67eafeb1f0637b9842dfccfb74468199bd90cb52fba0b556b8c32a5ef2ce65cbfdcc0bad3102861415405636a43c75f54b2844325cf7544a22d5c56f2d98c9fe6155c984ce23439440366a21a8ea24ce6846a7bfe40459039c0d7c1f3112a9d5ca8548f8f20d884086e907f9385a15493ebefbd509e7aa19691029741dbdabc15da65fb42f2816c633fbc1d5b42488466795a902ea4ccdfe4d70a50b6bb594f614e111f57527496a1901bb290c3c59f21aef0c68a877732de2774fd3823e2271ef0083bb35530158e9378fc050f0fe5df440a2e63fcab3e6b58a5ef185946f2f9fc780b329dff4fa5b29be55c1868812b71bebb26588c08b97878b7118412caf4ffe183efea366b626391a67f6d0ea2e00e28be4ecc261b397bd76cb9da3c99be84cf7ba4938622c3e7eb3965de2e1ae07e4e811811cdba640c9cc13c6fda6340df33e87ae23ae8edba372fd154b63e3851360380bda2b4856428f14f99d008357e45cef52b500cd84e6e07607d8b058fc2765ca7be87c3595d1455a05e984aac50f432145cdad0a98f2776b70c63ec6137754361d778a413fa657d0ca945682a179420c5ecec5d11d4088979bcf2a823c14fb3548108cc520560ed0e6842fe1a49268bcd69bc20e31136126f80084afc99444ff0b35824d3699c143a91eaf3e97ac4c01ea5c983c10cb910c0301d6ff257956789705be6445c56b260ce10dc8d8f165ce4619a8c56051a7fc4d62be54dffd06c3f95817c144282f33fbb7ecdf495dd44f2a4590137d3bf89b729ecd102e43e72b6f71a059baab8c54ade2d90f61a2dfa819443ccac6d3473a9fb6532820a3168e2a7870a07dc077fe3bffad4c9cd53dfa02a345b19115d89236fc843993c6a336d19bf666d67fb50b54e7001237137ea8c1ab4d35e9f330d322687e5b7653fbb72f14cebfa405dcb978eced6f313c3c6b2ed02892cf051ab489154a18ad86f59aa9e5af5c42b0cd85cd41d2e0294f5aa3989437535e4e362bcd92f6d7a74977590f1086e877ad1e291895a9913f24a44a5ee056b9e1624734c09d8ee02ec4da4a0327e5c3ec3d8441c1da8532214006b316ff404cda80d6595507676404ba8f3bab7a8b7459ec54e0acaa9b98263041d1e81b70bb48b24839cfc1737ff4116168f51dc5c9f84c91a3bbb4f7190da7271659f98286f11650a28c8bf8847810f7d286f3d28c5b86f2869e1d532e77f62ed0c24d4ee3c722038821736acfad959f763fc0b8d348f724d0a0a95371a6c4752f120eaddb080d73ca064751dcc3364fe950643a1f242be28d9b8a55a1a3d6bbb87b04eec17569011f19ae74ba249a12327d7f008442289d1c4324bc2f14d86283e195e76b47a9b599cad0a8ef23a952f85eb0610dc4a3cc2f77297c2a446ea43ea7839a0771c6b88b131ab2e2f2b39d031f39bad2c7336874db3f0b3b78274410321c61990498b16c68c1ca17e3f25c3ab283abb2938cc4e383dcb81432058abd8c7a298d0c892f482d77187fd25174b12b1194a50b29d90e7da3ec2388f75f85777bd2cbf224bf65ade3057561a0b37c6ff1c0ee59703fb7bff8ad9c58cd6d643b9a8da7116318c3cf737001af6a343104cfbacfff57fc82dcaadd13fd1ad6a8dff9506e1c3dff33832291e9174e8afd4c447164796d8daad8735922ec139a3bbc0721ed51e1ba85c5c9fb5cb0f4b23707cf32f7af4e61cd53775c4cd346dd09b8fa075adb9c311f3c4ecd79e9fa6bd3002651ea513765f847ce08ce5a0256501dde7804e320b1fa6528b88afa3f5094d326325d02ccddcf56a9be83afa5df7b69d83842e714f3cf18518f4145df769f7ae73856708aa90770496eb3e969e1f21aafbec05af7368e1bc31a668170a368bad96244a7cd42ac576f4d4b53324133fb0cfc849972781eabc2dc6d5361f9b5cfacd6d7f3a2cc69e1bcd6ca6515ac5d704ec53fa68f8422e7437a1df7db7fee7b0277b6ea71bb5c9c9f4f310faff9a0ccd118c0a463313ce4b0b9d61f72f48bd1ee8991f0e1120ece2255ca63e3a10750eec286b0d50ed7774206d0c268c9f5b29618547bf2bbaff0eccce72883b21dcad1b5bf47ab5a943da9823211684517ebf71745a2a0e627f15c8ebdfa104883b60693d4c3938dd6d6e5e170dcbafd9f15dbca23a4aef76c260d7f6394de91badda5ebc56e2fc19f7d5c663012a3be507a2f0648c31131128f6c0889fd65b323cb3d9a5d45a9e5a363dad6e450625bd5b227c37326789eb214725be108660cb30fa0de03637764156e72e1e545135698a561ff16d40ab264c2aab89494dd43afdd8ada1373e0c9dc703b2dd3af759d58fca6da57bea537ff54c8bfb7e8bf90d22fd7653b2695219136294bdcd68fce4fb19f53ee98bc6a677aca85bb74cf9a653996258bdf00b9f2d174163b330ecd55c86706e7d18983785e8bac6e2b3f96be025aa892bb4e02623d95f981d30d60f8583fb6f14bbfccafde70886d032c491df8e5d07dfced834e01a64b83fbf744a4c1c40afc38d6557f9258ab9fa49f52db50e3b261d367663f49bda16ef5e6c73635312b507132a1178cc8aa8b4befbcf1c595f966a36491ac23deb941e63b20f2d17d9e575043eeb3a2804cb6b509e731a54b718234c226c8efa217323924a0e09d73eabfc89399a49947e93c3d3ac6f65309fd70c09192d315dab37d2815077f684aaa9eaef4ce77b6d0653bc4d8bd77b0c5bd10174aeb5ad0dd7aa7af7fb79c8af3aff371f0a4c625e584a0b9c75c10187b009a6cf1bf7d92a44fa489aa1ffe90e00c1a5ee0a3ad9256c77be81f8adaa14311ea934bdbd9e1cdd0c31d9f7ed8004aa5343d28416e9e888a46be875bb8110d03b048a7de74b868b124b59a9f38d6f6164c263ad8d0fdc3728ae3aa7d103945faf106aa62db4401c3394ecde71b3e966aa4100efe8c2a233d97ddb3a376e0c5fcc2ea88fd35e8db7e391d9e5d6aba6d06137b725b7fe7d961773ffba819fb498185fc64399f7a45369cbd1138a67f2c8c8cf4aa112aae89e125b74adbf76b3e02bd1ae10670c57e3e87bcc2250682f34f7f41dcfc8a140b176a0e7254d8cbb9357e1daa642dfb72130649d1b9c680d7103ef60aa2cda3b661ccd41b310e6bb24f51531ee0ddf4255b50276199c01fa2b36b0b139b6fc245232371ca7239721a4d7ac080dc7dacfc12144f8e5186e7bbf89d4959351161be25407cf903290c1fbff1c52accb445e5aaeae4b49d35a3c4e4f2b6ce02947da170848a2e337c6f3cce5a3a32a3162b84b3e76e2b43be5600beeac09d2450f14dd7000d157f073b41ade05fec31e148dafe7a603cf9702e7b066418925c2182126d41a252c9f989f3d09483c5d036dabd5c00f0533a3691f834c88631f40b51d69356ff8310ca646ac1cb343866e6a721e118fa2ba83e18a00f0dbcc748feb16896908c4bb0607c02e235ff3d2376a8544f06322d27d88ea777e4bfa1473c855b9d42143cc7195eb796c5e5d1608aeab8806974c314b22e08eff7ce9547041c4fbd33858d5c2b6b56da4d64079745c02354ed18966a27548517aa255cdfc3e4cc7447e246d867eff4fb828a8d66e44c321bdc78bd34f6519a4d03a14b54727e6619e47a0d328b817ecfb44b7696de948aa382a0b9ef40201191aea8771aad83a7a854351942c7f1275667d0d55306a1484edea1f0c496ec3f73eb5c512a30de2fd3fb75bb9d438e328f18746309eacaba3e022a37d9e6a7ecd52565951609934bf206c9e3b547b56cbfdbaa1fb20c2cec67010180edaddf35613fbaab373895c3c0ed63ebdcb381a731690a96a2f3f7374dbfa74692bcf046c7dc093963f985501a8d3163e8deffc88b8af1492becb0246bae65cfc6270ac59b7cf6f89a75e2553427560343dd30da6e9cf9d286c7366f7612d33e123c759da9c77d86710463a6a4b940bbffa67834d471fe6fa1dd0d6a6eea669cea7dc2bfe265456e37e91caecb427900e3fe81e2ab3d89619b8887fdf07a1cfdf724a6ad7d3b64cdf6af69769f8baf3d6ec9b4cdd28dc255825d85a4e675b091cdd38074d81170e12820f2b87eb6bb9c28a6a810e867631930cb02283c3d7addcd7024a25199f1601f2afae5c41593c92d670ba4baaaaec69c472070205568dc084a2d11cf1d862c4ef31066031809990ba8abe27ad644559b2368c5495fb24bce089c6d84c539402a3a6da60477b032f4655b3f9750633f10527a1b9c08815bcef973d1c60e1c077b06dc0456288ff4cee7482215e2cd131875d19a46e88618a263e6fdd09ebdba9288ce359efbe18cb994eb5a532a52d6af1159fa0779be5faaa86f312c972516d4e752aedd501219f11f2f1ed0e646432bbf1220008007550b2ac59332728726f0e78774e16e085224c56da67b2da89a66c21233e14ebac292bc710a4e3420f821bbe79f3ecd76e6f27bea09604d7b9762b45147773742e7a98219708316e0d211a7829f179c038241f8289173a99c319702381f20aa96232da4d072dee8b587a1f1392939c9c0d2cdd0b2fd734b43cf5b742d5a11384503bbdfcccbb33c43795192e1f2e4c1309d4de9671d4e90a460159defc8f3d6fd7aee2ee2c07800d43d5a1a57c0d8a8f29ea1706bbb9d1c69cdbae5c27ddaed71b5483be5905037904ee19d2f126ee252dd7b769005b45428fc82447134b8c0a49759374ee62a1780b8797beef9e50acaee70c4cbda59eb615692f1c5f0de4e5b5f7468cfe5cebecf2d4fb33dc95b10627df81584dba001fcfdb1bdfed8b11022277f859fdb2bbe2083c124d15a260cf2160fdb8718258c0b10080a99e6e40f59b07f504b8cd526157f371c503e9e67c52ffcda238c3042d80d30f897a0ad481ac6771cf2556b07ccdcdcfe85c292e6b59c201889984758604e918b07270e38a182de814fc756763b10ab59cf832556c1813823ea2a276accae7b7e9e18a4cbcfcecb32f4745afa48305869fccd3d21a3c5d31105d64cc985cd9dd2d3fcefa6d6b397154dc219392dd7527ff4b0a3d62c3005bd770cbd00b4e15f6b85508e14c687ba63a167782a8392703f2f16010e1ef120e936efadc099a0e9e904e662f51f7f46951215773fc0eda8ae1f0f9411c799280cc2d2827e226ee1a7f7e225999aa49d47401b44a74dac13f16fcbe6709445addbd2005f390084d52e4a0c86d8a713ca5febf4f58ac66720f2f6d8382884a3c416b6e4c2f66ae865ac28f2a31d9ccf3bd7bfcad84d80116ce3c217b9f4ddb00db4dd8835b5ea1ed439c258ad054c8621d8842d95060e368be065f7b5c7f701f50d09c5d1c1c9ec085226894bb708bfc705fd7d63554c0a47742b0daf29de184b1bc96f7272449289054d6e8d35a27895b6f23ef2361ffc8a5ea338381bf39c63b4337c0779389f34e4ba8acc79fdffceddebc7999ec83d058e5f335f0962533aa8aed74d09dc2e21769e624b116ecefe4612f4c2552864e648b8c9f541469925d7f6601d778872515f675a446e908eadc235c9bcc6f84feea5e8b2ec7d437af884ccb619632959dd2ea272f38fc3c9ecd11d14857a499f8f98a358b5096b4f8565c3a72bca57dcce68f168c6bf092fe27a80084e5f803162f58ad7a0a5cb86e3ce57d2f5d4c3cbdfdb6d239e4d3ba25053127e2a5a668b7f955169135921ddb43839fe464dd2efb8a8c9fd93d62edcd0e2a949b69f398b0fe2f84b6e5aab4672a19d7454c9fbf9732da4252a1dd759a2d91aff5bbbd8a49b007087ac2c7663ce2f6801cb5668621c466fb273ed2584dcb3a7fd352156d4a9581ad007b1b5d072e8c2ff7ef003faad178c0fb2fe847c2991fbe952d59287e50d049b9745185ec9a64bb3bb9f9590fd890b3dfa2a415077322d308c84b3dbe1beea254cb583c87c88b22fd5e6e3ae819266cb777649519e839c52cf458a2ee5a1a4b2142baac0ebff7ff55e6fee2e362932ec9e58c5f106faebfe5079950a0d24ae615a8dd60e6611a9fd13bdc0b6de2f3e4b7cf355959e2803a430776d211aa97fa7f759ac4f8aa0bce11d9bab5ff2299bbc093a33d40054ca49f364e2afdb98b94ce7acb2f13e11dcfc7c9e16887df27f09c16dad202975d1683851d5bc410c1e1ddbc802f7493ea504076970f4b4c6d22ee0f1619e851238c3d056a6400ec0d27a9a20f41d238a2ee396bba4783fdadb71c266d110367bd9c64eb72dbd5a609f2ba414fb7f8f67b2b4da3339c43193df2c3d0942d3c3b30db2ab59b14a3fd30878a48c95ec161cccd572ea241ee4adc190b89560133475f5b99ac247b56c2488a8132c2f024472b45691223fdb9a46aeefb0df73e6ba3685dc2d19c909383d108fba300fdcb4a46cb8268cf6f19939c2cf789d009549d187d9b895e12034db35fd3a17e862795e50484dc071164bf2415eac1b0177e5677f20778ec4ed2cef56773b2f0227d355ed61804210ea7a136d6a0593b484c5ccfe733faf8244e5761225732a2aa1f6ad2f6a5263a4822a624ab308e590183af5663cf82f7043565edc1870c53f4d173189fd0e146925574e8e04b63d56d1eb9c3c67df7bd165ba2e089a7069a0678254cad9d15057c367de62b8e839128bb428dcbc3591443a5bb5afd147e1baae525cff0a7cda95587cedd15b67699b1378744b8143a0a112c5c467cfe26821a616107f9548e9418fb7e96cbaff23654cf029fe172a38fd830022ef2c05a8972593f6740fca55d68b924bda7ff73712f02288f195cfa6d9dcb66e5be19474aa7a584a282858fdb6341436140d7d11ec428e01d16cbf7a638dfbe9e18da8763fe2ec4f5987bcfce15e988a411da4b6e54f373f63fc6512a839a4840a37bcd845c4305e3723980647b038a7d298b67d94219b31a84ec3d4df4bb81aaa07a8a358736412bd5b761789dcff2d182a3ffd22ae05845af001f7f028fb3f46e461e4533db88b9fa11cfd12dd2d34ea11bc8c74b1843e8f28a5b845a8bb3c7277fd1c49ba1dd17acd340b1f63086fb9329c774c54c036798d5b5184de7097a71a4484bebb858a11428491669d4b41b652fb5848c8725938743aa03bff8d1bd5576155d77979cbe76fd5aa75875f395fbdb5d03af750dcbcf1afa0ffee9c7cfb1722b533c87f84a57b53b000000074390c608ff3cce57b78d6e566cfea91c5194e61fa3b921d8bf843acfcc90a14707eeb6d1583937420c247cff52d53f4400e90287ebb3ff64e2dd5b4455b39e56b4765ae3b1dac860e281ece98ddc4209d4e31c1ef61c01a8fe8027911f131d120b391b97b20915840e0e5cb9d727eed75623fa38673e6cb3a094e508d9a9983bde1bc386ee4d584347f341ea70358d9f35b1f64fbe08c8edfc4e4e1d79a44d2af06bc484d5a19d448adda5d1a5af9b7fbd5f9599c5e05a0f576cc3568cabf31541b650611d2793675d3edf1140b65f310f98be6af7618bb8735d7043d73df3409d37749582429085738936562f603720fa713f2df9e95fa47cf35f9b3bfa82618dd955d746010aab36d9d6e826e39eef5d682b87281b2ec40a1f03d9d1139361e15c12276ab4f1ef62e944538751e2a585118eb91581a2291d500075b7ad514cc840cd07a77accf69cb3b3ff7dd8d1c6eae293d702373647a8e215e7c386dbb9698ddbd84792d57c041ec08ae5b1e034f4bd6dda80c35d968397ee84afd6f533c90813a67f525faa2f5ff5bfda87c936fdbcc443b1f4e1ec87258484fbd36d3a708bdf805c5b8b287b352241df3f5ead4eb730276d5d7915cf5c6a8fcb357ae35b124439a5ae68d9425b3d476ec7de45d79e31a5732af9712d5844a7cc26889d + +pk = 000000010000000700000001ae5630e18184f7991499298f672208ddbc2277f012b38faec33bcdd80ef1b5f3577e649214e41db2724dfd194e3258d2 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W2.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W2.rsp new file mode 100644 index 0000000000..5ec6a5b991 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W2.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000002f08b5ed856f80451558c031cbeda91f6d5f610e6980ee56751444e2aa676356757ad620d1fd857d154c6c42ea5f4e169b4d9e71c8cc801cc32f9f5c675c6ed6b65ddfb0d0b3058e195d1abaf2db1c182a814453ff0bca5f67a5b7990aac2be11264c00cbe443510f9e7dc92b874fb03ba51f6841569f84c7be828662be715f3805e80ad07144ba1f74bcbdeacb4f487a04b4dfb873568eeea19da257507086c23e0e1c757ff97e4a3fddbf56caafde716eb678ccb9e70b097955d01a7354c32bb762af1aa18bba060580a9aa515507008ab99f0180f76d9d1548a85cb0c567129dfa7bcd632be21b545f0aaad3832ceab7dde6117f4f5cc65fe6e5d63b110badfee7d3233ac43d55717e721e5de68dcf99a13463823de42f488ac70d88fb04b50e2e4b8f9c3cfc57330ca0b84d33b8ec0842fabd160088e62dc64770aa3ee02e8840a7698183fb484c897fc7de9efd597347924921544fbb545ba4bb3ad3f95a05fa55e21a827f78d44d8ea96dde96a6d9bdce75491fd2e9c7edb3a0c155576cd083fdbf706d6c54ca1abed0e9ef069438779cf2fb20318b47db116c1fee2972617306a6bceb64bb910c11baacd8fcc0a63596d328dcab0f41bcdd1f5d4b17f3ec2a8b2726d2071d9257adf8fbfc52c620ca411c1a3d9afa3c224745f8601e28ef0e3351ca8593f119079b3ec16ae4009f78299eac494e5b4a4ed920dab2e2e9912856d586ff7d037f49f25dc5bcef30d0755f4949312cfc9a3673cbd4f636cf81350f5adc050c323ab9633bad880690cbc13f7cf0dd93922ea92688ef1fba968b903725c6ea09170f4d26bacd62132856b6972665b466f6688e37a6e8a8c938a72e1fccad2bc8c1fa7a246e1361ae543892f23c3637ddd20b3d8a3b0aeb68ccb5edff07be9e9169d93c6e4c0e5dd7adbb3384eb679b4b8c14c23e3679a6ff721678be639d3684375e9a01f14d29f310c8460fea41de9dc5289a784080c090d23da1ff5aad37caf80a920c82962f966f0a8f00cf4972752b44c4bf2af44e18cd373a6b5afc281055a71dc9d39d65233f1c397dcf8ffc0a32a07905f2007798979ef0123d65eb1033eb98be9481286b233875ca0e0e6a7734956c6120733ef49ffcadac9986e902a24aa00a5facebe20c8a90e899ef14cc4fb536cb2fd272849f448bdc30943fa027b697177dcd9dcb135c78d4e000230ba274754d5dc7591b0b818e8b2ec5eeb216e02415ffaddd6e10e42a2cb55c122bbe2dd7c19a70bb33b52e1450db1d49a30c1dda1673015cd7944b35efeda84a821134085193f70030a1e375fe43e89fe5e84a14283f78ab2a5985403b45f8da9ee082a1c773acc7c8b0faffdd433c840f5519a1945c622642548dfe4128a01bc15ddb3a4defdcc9fdeac62c27f8ea27e939966471ceb011e0a116b43b100050cb6c2d74c71156e48ad869c18b54d08196101f845ca21c89b647543fc38e05ce47fa3c21c3fd65401747ec0076fd74ba27e1c2d70db3c05bb1c08e2a392a8d548f428dcb572c7cfa49e709ef62305ac06ee9e705bb5c5c440ad92f8d72313dd0d35d244613b6df9a325e6b7670ed0838af40bd48bf42c239ba12408adbcfb492b9d2fc0eb523dfb419bf9eaebca4fa4305e622088a4482ca4735e14c0d8bb26305882c254e87f60d5039a1857b0d6d2a9dcbad8a10c802ab9a9ec8a6f5caf05a4dcfea0bff82b6830201978c145611a3eb060d08fb70e6d9a6eb85c6f779c7b50bf2c38f9631003a1d8c5943d24a987eddd3a9a27c694c6def4b3cb938515239a3e35452acefc29165e8c5cb3d8e8b5da9423debd3ce1ccce82d1279af8253c21e8dbf743fb80d8cb1f51d3d9afab06da2d11d99ebf26f69e93bf726d9d33a8f06ca228602692a7ba44ef95990ed181ca9acc62954f8a1af3b873b2a07faf575f387b3a3fdbd9ce68afcb2094f39713d2cdd430c85e534af140adf30d99167597d2b05ef7d7fb4a636bb8c94c4892484a00b987cb203ef3b038fd6034850015a0f3ee971896b9c76df5ff2d724ba2c5eaccf86f19e83bcf968774106d7fb42614cfcb5c1da672d5ca1bb41877bb3835ef3ad680f3c14ed7fb0e2839bde1a8d70ec318b1005ff0385f8cca6febb52294f4caa3b284349466d3fb2c65ba2df6fccbeed18187b24a65801304d1e09b56befbc5fa3ff1ef44d73e0f3e1dfb9b86f85f2f3a99c2541808071d20b9248e100e7813fe18d553b63ce520e3e60612aea4f076e65f53d23f122a9bf435eadf13e5053d8b509ca895844b7b36c284e6be757407d202c447355174634cee9c90a1c0c2d29628d9ac6e9c4996d6924f9f6b99adff788cb99e3a4ff46e257db3a9ce2b25e71dd783d59ac36f28d48e0d6271a1ddf1b4c5deaf1e97421031bf6d8e86579ffc1eef966e502b695878bfb514cb4524b28ce202d38e7d4545f14b4f4709f7b23de5a0b5695e9e1ccbd16bf8fc89b960da883667d256b08428f8b5874630213007a24d23c086e3b171ac61ea4a042f8129b22c1adc85de8d68f534116493980c28054f8a4887b7fb8d53bf0149927c5504956284f4105500c9b8170d2ec6746030ca343ad1224c836b4538fa9bedf2d2ee97ff85d6ea7290a1aa3df9e47550947c35a3b7c74e0969e6a3999deeaed57c9ce705fbf859f700a197f73ccceb5399a028c781aa42a4216500ac3a1592d7c3f58474986b0ae7f2685c6ede892b6098cbd6c9743fd974dc39d45d732f392617dabb33e12df59d4252bed5d19f36b77b67d45d56b9ffc26219fd9988646649742ee364f483aaccc9ef8c7aa16e19cf045a46dffb27863cbe8637403638826fcc79e79929f49dc315fe802301072b5fc9b26a91664e6b69ca897f4c5ff753e3be247a0adc3fe5e3d779f0da3c7f4be1340b6c38f596afafefd951760f4f25611f689aba3319dfe54044a1d6cc4aa9d6e3f1c21c35c6bc1dfeabff882eaa624fed9f50bac1fca9d53378629c1da9013c21750c820a860dd5a97ed04b3aaa771ed8135bb4ccb9bd3815fa925e464db27b96d4582c105c8a1f471dd5fd0c512a3e5f596856e3ca297e7b78bf654d078cdd2a46eea45ae7febd39f127351f2beeffa29d967417935dd98467d0f1766dadeac80f999d517902dc869fe13dbf186d7e871141e5e04f68a238140933a1e5b215666eb1c7499f28dbe2b3407f3bd2ce6a7088718768a6d71a24d3fa16e62d7d57e2643274029b5f87dd5e04d887012bab0eecab3c9b5f3391c713ed718e30b968d65e342f0b4a61baa381fc9c3d2aa398706a2ff9e6a7c5fb964cba0a1d58fcd6a133008245ad9788482e153effd601ac217568ff7a35675b0af3623df1ecb784f2e7b690a059870654057950a49cf7f037915baf02886badd23fcb2e61274482e7ba856d7203c620f81be9d22f24557c11126c79cbb45026e21c43638d059144c6a2dc7c161d87963b3185641d97bc8e2ffc9bf11e78d27b2bd62b1fd13f872c454d7354b92613436cce8a1333b59ef75409581c76fbfb76b2dfb157aa6a0fd85ef1cb38006c9ca2676b83ac624932175bd04f72b8ecca8b23a86bf440c9a8f9b874ad1508d515d18b5f097c7e182b63787d1acc78defed914cbd33ad0d07ffd9cfa73eaa956297281fe3e0310902b2dfa8fbbf21ac1ff387b1d8fb202a3be3b157bbd113c4db44e86329bc86080ee38593773f614ea7b7841583340fce41b7345607d84e877f8b715f5575fb57201572bf775c960cb17f976504a00a98b0057b664ecce394e3d117d62bf9b653b76ed6fb4e2436a22deb7f72b399154d151f85a224862c6bbe564c3ffae36a6732e528f84b15fd617e383663c3ee28cd442bd7ed4c38228fea64e543d684f6e613982bf8a9934e4f81db467ee1b5da2b8a2231eb5c2dac2795a478bfd91beeba8f3c731381c98593a4699a520437659a8dc297c561cfc66986e886b0f2a79899324af9029466f6593bf4dc5191f3ac0e2d0b7d6afa2764942987bcea3c0404de1942f0e058f5b1457a7713d987e408d54ac05bbc5322181fc30934d3fe516f1678f91ba1733b4b31fa1c968ab5bbc6567a436ad88b328b31194e7f3274ea9e14dfb2af9fd137dcf6bcb31ae8723d3d2b035cf062e614ddff037f3e636fba860ca70540dbb704fcf1886bd5453b028e7d50020973aef05155215b044ca7eff50cc74f1cb2cb6dd447f43d42ce8d3c69295aaac5433e72deea922afb0853b27bf5347d205eb121eefadd31fc337c4e67ecc1df4e36c125b77fe5dea89104a52a58b36e76a57cc5a5f61fbdd7ea04e7bfb0895a790724e9ea93eafe01d20d2f3a4db460fbd9728c0e954984851a48c3806fde2930b98274109201c57fe8d0ccffa2cceb7d7f1bac2264235676df2253d65de551b6112f0a617f9b16d64953c646b84137185e63018cbfd28643d4dc96c782a8ca43809426bb905a7d872fecfad0814fafdc0f6079aa80e1b7236e33f3ca28ac02fc32d4fc4e751fc053b5b31b38b76068dd443fbb9b37ac9ee779da0d90bd9b4fc80f1cb71675c243ad4f2c2f03e9cc58263da9bf5aed282b1ab905474bf3a37225f7bf7952c930b7135479f9fffdd2cf85f2c3d5664f696bd32832db043f6b39ff627448042f7248253ef8b9e3d577f824c5100230a35a3581eed96308693407fdfa960266f8e338a70e2a8206886467bdb5d7ef7e6695eb0145e52a370727cdc55f437469c56a52a69a667cac0f057caea787700c5ef454600574dc27784d9b6d4b91296d776752d12d0ba6b5569f79121bb1bcd3a11535c5badc7daa72362a23099aaa10d2e45c081423afa48d28203d18d16529610965e28af87ae97a73b7d5ae048dcd9f352381ac26b96ca3269da6dbf88e96c795650904e479b72b7dd6b9bf46ea10d24d88213a002d0655918cd9217d02750d396a44c653a71e2d9125a133542a5462756b0cfcd1e1d9e7be3b919a65042e69e3d3e293f1fc34974eb6a148700c7f74c5497351be1ded9060f95a103b5f1243db2acc218b30fe27697f5fa3bc7a43fe28174bf916e985750f3647b53479f1ebe74806322b64659ee49d3a754f5b1c22fd39f8b6f36aab9512b4371323a3d939b97aedd726303d91f804731ed921f70dab7c2475af8cdcd54bcb6747faf7e7b6a1aa579cedabf8447358d23aec2cc4b75a547e0b59de77984b33bf04557210150718f53f94dac4e80eff9e20c61bc457dcbfffb69c61d5df812ac70ed8600a2d8d9081e46c34ad9ce6a0f1aef9b25277b8600e3dc9a001ab305f732f5d01a1cd9096ae813c53731490e5af8018ea3a15618e365e12861340e7ca7f8afe683be65a508d8f8ca5dc701c2708ec1c2d70a80362a217cccbaec9bf6e1a201d70025701759121a5bced89d618a1fdd8b9456f23d7b3c105395f9397fb80ad8ca754c132f7d0e9f95ae2f956b18e313520da33dccf03e3ca0b37cc6a4034aa7d50489054970da47fc22f385a4ce208613fb347f74f02c0e17eaf381797362acbf78294609c343eb3035e42fe71ce86b9e0dad4f1777f29457e7ada88d3c0c3f8be6d59076bc2fcd9c52debe5fdfcc280b567bb7622c2012eed6cfefa3533d9a2606aef17ae20d9869f02f83606c93778529e20d2252ff239c4252b7944ed439f443c1b1394a1c1df5b386bf5f9a3a839d7b1f30aa6d04ae2f1348bc926c65c55880918a4ea278c141afc3229eb756e8f16402ad40ec7d30c8ee56317d6ff3023b58e468cbe0404decc7e2f548d41f4669c5ee79da45a3d30cfa9466ca9bc34474d1b3a3beede79ed5c177b2bb48edff3a8c3c71284a3bd1c29eef2bd1defb2d40c1c70f5fc02ff899dcd3e7c73d88602e7ff66b25b71537437eb0e349c4d62a306c97131f0cd5affde1e9938d86602df061f6837bd542d68600324f9f8120ee567c9ffc87fd0a9507b1034789055b932528d618959ae2c43778051824c117d884b3315a3c0fabe2ae16284ea6ac01712006d222f9874d7871777255b46cfb44b72b3048f1a43f7e9d72ae996ae791d2f17ad97c26ef23692126df47840f7219e414e4994ac281328000000071f0adb73b4cd33823d14c463983567475f253c2723200371379ddd88255aaa21bd9434e4366d569655f38c8f6f2d25c66fdf7450ae9aaac284e91d433870308864e3f2568c460cfe515027b525228a27f154ca0161e0c3571ad85e38b2b5e622871da013c0ce035df5cb59508775198d3b69dc52a7cbb459d10ca900172c9c46a44efaee553817d7fdc7f7f1e3f2f6714d101c8555756b1d5b8d13342d7fffe8f1a37aaa0cffb53ef5cd6c83bb78b450a026edfa8e34d18fc68743dceaba69ebc6b26d18d63a9b80f6dfcf9293b7cad5523e0b215539cfd6dd858471d7fd725e030265518140575ab772b858152f41844ef97e54b685e81745c47e9b7f0b9d375e65a2214ffb0fa163b8df334d1495b44b8232ce3dd8c5e2a760cd92eb59c80080c841d0150fed836cd7ac390ee1b17ff670869b98dc3ec29c5f42c4381a3866764e0754fb5f4b73050993e1445fccad4d346a2dc6b61476cf0cc8658b3ff406bb1ed89df047dcd49f2583911ca3a7c4bf17fe0dbf5ba32440f253f12f9f791b9bb80d413204c41b4e9689cd72b5b8bf73272fc005c6a9f230997310d49dddd68df985bba18ce58c1dc63d5c62c8f150b29e077892d148e1c6ebf342277990b51c26762bd0da452a6c88bc50de214cb59918583839641b67df417828fc2b9f08 + +pk = 000000010000000700000002e8de95cb58a8b0aa8ad47f68af1c98524fd0f190b5205f40ed55507653ae7fda835c910eea1f29d7716330c27dc4f835 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W4.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W4.rsp new file mode 100644 index 0000000000..a3ba862944 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W4.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000003b15d44eb5dec79430945738b499d2beebb5302eafc1318028103aab6469c2cc9f7701919bad01498c915de8d56a9e221413bc8191bbb0a6e538298c49f46213ec9b6f27b26d85c13541b2dca4fde3fcb5c6cd830ba044c8e6478011c13a10e79d5ab11157d952166ca5e5cf7f36c675af016a4476d97b79bed46cc06d261e82ee8eceae9031cdf85e0afabb71aee45054e90534ea22e32987f6bdad1d82e5753c3d49b70a2da50e715598dc45e37ce67404f50d6f068ea9f053f89a25f3167b778f670834a4247dbf2f3463772f1af1fe98def960bad75531503874a8ba1679b0eaacfa0532017d7f12587180a0cadd20abd54e206f9482ff3d24be9efb41e6fe749facd7312927a81857f0810d14610528c4ea6b3fe3e8efb75f3c100ace31d91b273790534851f0ba37977178b38df4319405c8ad6c9a657c536836c6362f41fe67884198d8ec5366bc788c43b8f7c1689c47d4f3d1c33727937fcab453fccb7dfd4f1932caad1ad5ac45d51e4c4fec014ea796b3b9e70781a541e9bebdb309ebde3a30918b63d6d076c4ca22387e0b7a17a42e300ec1f9b750511d989c443edf89d9f24bcfe96767aca712ee08583a70fc80b6d7b7f3d7883c02491bcc02e37e267d9f14ac003fe002a669a8ff5ffb37e55a8c002bc1ed3743745119eb0ec227ff38eec5956f1a36390fa086f98ab4d9200e7c17a48ecd8f8b5bf38341ecbf8a5a0f5f3fe4b2a0f813df19df6277b014126d1c0d42e093d1bbc4e2cbae00422a78c1e70b2203ea18591b22d2015f8d4d000fa484e879d44ceb86e7ef89e11f3ea786f3b6d204e4ba13466bad37b1cfb4cdbe0f7bf26623d787681441e6a64d3d783bdeae7fceb6fad18c8b011c2f14b3660951a8cf87b75d292489dc87cfdfed0610cbc7b727b780400b8ddf7a1c5d5fc265a7f0d2356a7e39862dca4ceb0b07efbea59bfa5c8d27ca1c04857b5c033322dfa8bb5f0aad504c246f17d97e306c55cf17f0724d5201ef283f8e0191ddb9b5ffb5f2e86586a1ec2243dfe17b61e6c5b48204717a3de944a26082b396d016a3f689fec52354321d08722f2141e53063305f988a720a91cd326bd7ec72071ea45e314ad505c66a85ac4478fa2fbb7abfe83e890779f607de7bef9b852e1b72ca511cb49b5495884f04a6c6252dae87ad6154f0934c44ffd9f9b7e78ff32163f414fb1ae01d703b53afd5400178ebdfefaaff149de556b474d507cc4f83a2b6bc8d8aba86d55f32dd6c59f90376480d195ccb157201150438b93432b26cb6a437be4bc84b5239b89bc477ce4ad981c7c6ff38cee53091aa3489a095e72b582ccfcfe783554b3dedb32af18f136cbe0c83ace70cc09164debd2b67fc5aa9a9320024dec45a74be1793e3850062849860596cdc36b9ea154cada6ea752049b391082ba0107e4658e6efd741fc5899fb5ddb7549cae174fb9e08d0b42d75f15b1743d06f107045ec931f8ffcc67fe70779cfb6c3e3f58fa230c951cc6278571796cd0f83249ec93f7ba62868782e431c177a691fdf617e9af2221feab9ee09684365d0a8a5e1948de7a01b6e390d18651f26655d994c1363efb93e6dc196b64e65b8ce1150b7d020b280760e0354d561d08228611e2fe9f483ab574f93cbd709fb3b4b07af72d27f3960f6c6579ecc02ceaae745a3939112e883e9dca7856d5803dd5b21f889c145d3c54b2a5fc117c341e2109b935cde6c7959ef33e3c2a9aaf32cbe003c14aff7f36cabdf25f37467e7fcc58155eb0a354313057f30898370ecdc5b75eb2a74388197adfb36439ecf97a7f9302a2f4d7be079abb824db22f7e962136df36dad41cd5816f4e8deb434b59b4f308818a12963dcc0168f20a15017f941f129dbced6e41fadd87f91655655b7001170188fe9545fa93424f939464c7af32a5f282d999e5f93523ac2090041cb087f6be7e8cf2aeb95e05afba361e973c4a69eca8bf7c1f22bd98e94dd71e604561ccd316f6579a82c75b58f731282f658ed2de278ec4c627bd7e89b4f7c4a8ea68a48cf8744be232981218ca4ed83db5dce7719b3237236632e9679516271015ec8db512d517f03e038910cdac47ab895d8a8a17dc43fdb7c27273cb830372edc94e9188fc8eb0b95bbd6f10ea1d593a7aaccf302b6ceea1f6f3b71d7d4bff16abefdc5c065922e1eb3527af393186b963b15b3a5c0c7626e68b69de1df88dd9d5430d8919548b1dd21fc65f4e602b6a0e1fed96e931ad8953b30f84eaf86b630a104d5f296afd9196c865134e9f93ccafd17abcb2b2fad3d7c379cd4b7f2382b30af940474665eef0e0817e322cbaed4ff5607e7970a8b5292313a9594e5ad6878cfb8cd74e9c498dcc63510e7c28d931ff70253c602ab5cd2d600580ff642f68aabf7a3643f1c7af8a41e65310311ea43c75e95f8370ba5a6ac3cb0065d599d79e4d44f0591135a87245eaa7866f49046e764facfaddff76c5759fb7e58c215dd446f8a81ff4b8e48154e6840c38cd961b9b9dfcd55fd605880bdb8816d877fe1a53237b7a3e056f60476ef3ae607725eab95cf03290fda825d9db7ae0262ecfda3370e5799ea77dce227ed43316cbaca2bf61217151d703ad6801add7891d374353de6bedbf63c69bf33eff12c937df5300f52bfe07f7dc12f197e7aa071a76e0d2e3eba64f99737a8fc0f413b143c8a068e64fd7c0767094b46945ccb76ca3591c0f7cf02caf00254eec04585a8b9e38d3125283c3932fa6ea02999cde821a534272b267df5be0aa822a18edbd174bba9262d0f43a6870b2a5e95e8e673a00b7de8a0acaa0f38d78523564b7dd045c151e5c072f6e8d4b179eb36d7775d3f55523331527c1af2b623b4c894da1847a3bf9ace1eff733eb1dd0a04c09d8b378e9abbd00ffdb9d9bc8d73fd4977b8271240d1ddcda20bf41e2402e2f3085dd9ccd4ac881455a22d46cf9637ab93fcb3e4bdea1facb4f10fcbcd96fa21ec295837c56148dcad04c34a15db5aa2a9b0b4098493682e9d536acce9150cdbcfa62015c43473d58e5fb1f30adb8905b90a4426c81abdb345696f21da4bd210000000775500fe3a11d75bbd8a575414493dd05e9089d78918012e60f09610f1d957fc6724bc66eb0f0ecaaf9d040e31cd61531b5b950991637d97ec4aebbdd68efef4fa42b984809bf91e21b1b767d8550f0ed2d957fc61db16b5bcb2965436e5e15b76bc299f66f30d459eca6642eba5b5068cbdb38aa87def567852f1adce0d08175390ad6b1e9db4eaf8a07c11fdc7e68bbeb66afa3916aca2b7e9366cea55c60d643ddae869ef53e95a5e24866168c106f6ed019c0b120417c64b479bd973077c1543ca6242a05abc1d48e778eaaa3b3bd5e45bc9d569f372189309aa91a927ab31f67daf8b45a5947db1149a9ff29a4972ea03b0b238bde23599b4068f4075f02bce308631ad3b4a00babb5fef7a03a6a335a543e10e360824272d7d17b9f169f1a9d39e941c61da753842870f3d058192ba9b808376e08a5879c077ee8fca7228f96cbb6d694d6bc10be0cf5b718389378115e38943a57716e5d98041c4a6b93f40e2a781728d98d9965784f7404dc2fc7b63e3c8af12992afe5322284fed577a9e9c866a590332436b08fb783891cf1cc7c7b4753d24e23feb7046f90aa3bb9ec1e30ed1dfcc1f22e78ee63e648ed3bf949bc04e47f410a3441d614b912a8e7aa21ffbb15fa2f3261cddac3758c6f5a54fecf3153d7e168c0aeed75c91cbef8 + +pk = 000000010000000700000003a61d708a980acafcb08bf59ee41d84fbac8fb29c8713a2d9ca6f42c2df089c931619b265671140e35027c6428e2cc18a + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W8.rsp new file mode 100644 index 0000000000..06c629fe73 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H15_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 0000000000000000000000047af430445b89d9b8c82509c6d6e14559a7e26488764d076cb6428ec25a95afb01d0fa6b245bcd544909ca29bf1787ea02eb45ad125a5aff76f43fcf8d58c8c92559e4a1f99339a26f66a75296eaef6d9c087606dd3df5987808521b95905e0a6c7119faa2e57df8e1ec02be9d1ce346f32d465eb404e928080dbbbc6f9994bdf9ef72a44948a0f69794401fedab887ba9a8dcf117650c5cb45b239d08b9247dcde09b238a5cfa5fc26aa00f2060e7eda5bd7d5ce5b6037475185b0b2561d8851626b2beebe8f12b1efb24bdb9a86b657893ccbadbee0d04efb421fa494aa1dc926a3666a959313d08358dce4d7ce16b23e36cad0c26e56e2d5b32afa744ed53310fceea855092a45fcd7058568cbe4508d511b8bab52cd30a75d3c97cd1a42e7cc2f16a6242e8e10fb498606556d6e65e2f7d55294560856f706cddaaea7f3d495d4d0c6b655cba91b211b7d79dd9e4cb4e8c44f187ee7de6312c39a99c34590a8f50141c31be1efd6083a8aaf36f5da7eca4f66fdff1d984e764b720bdc830ee4f6c7406c2b0cf0889a00ed51d435f0b31c7b9a10eb8484c64d3d24cac953d38b11c02047d919da39782db070571a9a10658eac751c19eca9df0b0a0f68916ae4830f56d28eec5f18341542bbf2c8652b44ac354326a9b2a854f6326ae920f4f201f5f71a1c698ce69e9964fe7aca73f9080c420fffc8fa3838194ce479c87e6ed5619eab0bd317b84485755a2390ab4b8220d74b73d14087ea334c14f61bb06da084eaa77aa99f13b62758e6a83f9665999b0f86f92c854a1e44b45e5cb5209193025d78bc7e5fd8300c91740b444ae3cd3880bf22927f777d2833eae0d4792b917fae8dda163cf4be2928e8c881d0fbab323a4925657335a5964f2cf295de1d4c1817be9a78e89712accb11e4b02bb02ef55e42832f94b293c732e1164e1254c6597053620fd88b78d884106d98c88f87756656ab1fab40175542c4f716340d485441e9af121860e971eb8c2b26d8f5d262d09376e04c8cbfd79f5c45261cfb6c290563b4ea0b62c6464d40d1ef036a2cbc3e8e9e227c91798fc2018c393ad54a6709a8b13caa03e2c0c8cace8253baef126a4e2900ec69bd79e2a99faf088795b894b09f002e8c33ac189346003372543b186e145f322630883a283b9c31d8f0679b9fddf0b3a551c451bce5f9d6e47cd113894d723accf6ff6a28e37452884244456f55cc89514dc24585b458725595890c809a6e034e69135ce605bba18d813a3f68f0a91595b3c301e955a283620e88425d3ce747e68d081dcaca159d269adfdd8901920916ac8dc652fd2b019d86342d1b92e3e8dacae938fc14bc775021a8faac81f5722446c8e9715e23ce5c68a114ad1611a6e146dc80488d4f359537de3b44bd3f1b7ea74d045f6846931bfcf1747e089c75a5ffd2b7cc7adf693a282966d414ce7715fae6064938f7db7006bbd98c70b661f2b82bfe5dc4d30a9d7763e4be9bfefbc63bb7c5d4c8da6c9adf6a9e1f20025bef2564fa87886feed6789d555ebee11bc812660b5e5b4b54c196eea96f693324ff20646e1e4dba9400000007f656672dea662ec5bcc26a23487368222eade00324f8f5f72c9111c474af6995e54f45a1ea3ede6d95a73d863b1491982f23f2ecada075a63512600c7661590ea4097241a052c5bcad87ba7858e9d5458a9a7627c06ffb3a7351aa34e7654ea893deced8e5736374ad7a3efae2331d3f4ccfa90ba46871258a920ad200f575b755e977555f8480b3b59e1e5aca7300654b78a56befe6cbc8f7194ef7b451e09644d4220ddb8c52ddb9029d220bc3794a26581e2e1dab769184b502f32141242b0f73f608ecea7f3915e7e4730a99dca80a672cd4ee902b64e15ab4292e265431012040373192b3579d916b8cb20f746c512c065eed493dc15d7af1a7836caa481a3a0369373debf8061bc276f8fe6cdf6062c607457bb08653baad184ce8dc6262114e566eb3e6917a12977028a252d27b4d20f88a0157dd5bcda24fb14d9b55a4663782d6ba567f424acfcdaa1ef74e3b4467f42f78cb1a75e5df72d2f3f1f8b027252d2598fa3cfe6cb30db132eee876479f7de10a3988bf5f9f828bb34cd497307f92d16d14ea5041dcb7223099850a79f6411dd01eae4d04a5a029c6c32f728f778728492ff47cd2867a830a0c68db065021b163470ec315ac84d0f1086b841651ed5101170aa822dc63cd76d198a44d50ca755cc39d0cc421b9923ff4e2 + +pk = 000000010000000700000004ee75d92a6e0f472dfff23ae76e330d6175dc24edee5b25641c195c2c60ddbfd9382942405a37f4bb4b3bac9806603507 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W1.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W1.rsp new file mode 100644 index 0000000000..94f25d3247 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W1.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000001c0228b6816e9c280638c69e725851f996df55bfaa61141788b213464e517bcfae1e2e52bccdd49fb616c682c3feff0257c25f758fb41e031b0de1999c68856c95de7f94489ff58f275cc6ae9084c0224c65f015b6a370965e4a16953f311b2cb2020f5d7fd649c2535d47409f7144817fcb8e3cc6e4faea1a4e49fe32af89087f7c992578df860af90f4e1357c3be9d05fc5b2dcd23840e708847d65433412df9f238afa72c6a7561b917f3e3313e44628daaed4663206a63a39d8e5eb2306857bb29f7667394937e7a9a7a1b3ab5e231046efb97028f0ac6bab86e2637c46bf164bcfe7d8613d9aeac631a3af401f562b7e6b24473e7c22d7030d27bed9ca721119e1b0ea2b195fe3f9b2abbb0ff03cd3fd666ce0d1cb94ade5a8b189be3bd888a21f41e5f9ade9ec1c377d047553185aad657609bd4356936c60ae1eb29ad56ff4de54b79a9027ab406e9ce8f4b5aae8fc4ee3a401950df35b3376394869abfa8276328de1e2b4d17e8d3ffa1ccdfe80c808514401def95d73c87c9af8e301b03ee17ed3a6d3a6a82664ba846600b9b2482a009cd1aaa1dfc319ee98e98619c91785a6f404508748205992e12f115a0f35640598241a5c320151d3d7568385d79cd8e7fecfa570538ad82fb1a5aed8fb13310f1791b9b885d638c182f148b9a035cd4774f303828a534c33590d6aa4cac1a8f51717694662f0995912ff63856179479c35e93fdcc079c3a7ee4ad220417be72d2634d2768103b5c1c9c7af1cf957cc89720fdd004da77a1e2fe9cff04aedc64b13f5a509b8810167aa2014a4036a89f5b4e03f72348882adf6b9aade977b6a61b0cfa0a789812c4086b7c1d0ad78fb0ceb59e246e06caae90011cdda63af047d4eeca24d631f72cb83cdf52d41814101af0d0c6261b034a9a5588945f046616f35049093ea66ca788cf7cefa41de218915ef934ce4c2c883a1f44682bc450fe8e78c5616e4598443611de11394d463744e3896f9de8c63af0e6caa11f4c9f1668f31e43fc7b78803b089f05314f781cb9c60f29f65f03fedc199f0f953d8f120b189977d028160b15b0607898722709cba176df3441894959dde46c52cf78987bf102b1ca44290efd51ad37fe969b2177e24983c4bd7569723c4c13ddef10222fe9277346e67db8ea3c7eb11e598044d514faf74f34c25e3ea6891c0a1ba4b91f1f0ae79d5a36174c342bc58e5dbe8840b4aea026c4353445b1068b29dc6d42632c2742606615b3c94116694e5051ceb193c6d10446f3529e513c2ac81e3e69e56db86dd17672eea3e6a4bd35dd8be87919a853694b65f439003e4631ee6a2ecf1e783bca8e87c5fd232ebb068fbef64ed41eb2e0c1f6ee536c23010574a23d5265bafbe40e6cac639469432d926caf4b3c3f9e04a4cc232b595777353f00ab2efac0a3d1175c1eeb9d9b160f7af3d2859e17efbf7dd5a3a9de48e27533728161ecd5880e6ac0865b4e1f2a5c517c449e7f336546655ad546d51d77b98f65290b003a89fd7f187f72daabb36010898709f85b959600f8f92323788fbba6e4d8c10c352f13dab5f1ad2dc5bfb3753b4b7f22207a8a591f1e291c02ae53b3c5d593238686907792ffb6118d162f8e8a884b8bf091f5a788250231aa5660f87ade9aaf7e1e87dc2fffaea7afcf584e6fba8cc8674b405921d32722f34002a0ef915e0c313c36b1e3ee600155ccbb0c09536256d83662896c4dde681747289dec9c9bada62312df7e69f6140b036a45801405163a7aafce19c642ff9bbdd807189fbbe5c4cd7490cf291010d4d3e7ff0713c611a3427a28782456c09faf1c40f76157a39adf0b805ea40070b08403821e416444f904e12d243cd2d92f026dc6cb4b9bdb6227ffd4e97ed1de4f7c23e1670a51710b60478ccadca849aba66871020d799f3a5ea4087fa0246ddaad1d4e7e6355076bd59a1c02822aaf12d1fb63a5648cbe597d839c142cb14b0f1998ef266a35ba5eec1f26e7f6587425cb3ffc0be475d56446a45bcfc45b781c1a8c32c98eecf271242a0c69ae67f01e6ec4df033b574ab143782ce393de71bcc0db84bb72c0319cf089f8707c3926eb0202ce01f08c548f579269e9f32254a6d2f8a83ae6ace7d80ca4aca63e08ad5169997c05b6a809f243f5c1e3dbd9d5fe0dcd3cf77cb17578f09a731d2a3891c8a4496ee62f87d93afbc9ba68039403234cb1e552133a88ae9c644c6d8504becbc5f457072cf07ba6a02cf49b22592d1963e01359326e476da37a439fe9c52c001519de2e4228e34c10e99f897749156769512ccb6efff3dea10fada8e1d49924f3c4b0e9f8360f0fc9c680e721f292d2744370674b1780eedc8e7e106024c5ed240dca97b0bc91de1d4e39a3921866785fec13e325ee3042b09e40b804b195eca06b488e53f0ce7dfec718004a5a3f2256b6044e8635cf8642949ea9550c9ed9ddecedca7bf886fff103c674ba334aed47c3734e7c0c8cb50f4fb197502886ec02017c18dd94d5df6e404e6312bad153abc8ac5d8c860f3b6d35c8ca1837ff40a35d55b210ee7ff6e9e9efc5617398727cca27768abeb372a19a79db130a5aa7e17dd53805d8c9b5ecf3b33bcabd89ca491c8b0dca65c218f03006c29ab6e145b7f4ce12df7575712a93ae7ab746ecac67358fda8b96b43bb144d15f15206636cc6d5404eb14bbfaafbb9c967a5849b1472a1829dc41e9277ffe2a1252d3346be797fdd6be25a203006fbeb5d4c44e2ac95e9066838d199f2c5fce7d6ed825851b6ba51d319eb50d7379edcf054d1620ac4d9c74f0a9c3339f69627ff961be41a603423fd5b23c8fd42120ff6ef745d72a8b82528edd42e0ab00a1bef3440bd671312a4c134f5d1e25314043c48296910cc4084dafdb0b392526b68d79c7a3cebc01300243e5de21a317e53f09e4b65872d769c19b1aa72768b3298496d5ab64bfc993c4ad21a25f5864d53d8ebd1d7cfaaa7ac12fa517af42c4e1d874ca356bb4d40a55a3276fe42ff468bd45618342baf4bdabff943b76a9822104207987d9278fde73e031e848183e11a85580aa99538ba1f69fe18f7a36e38caa69982bf62c67991c37632fa6522352776fec155f55e134b64e6b688a3b0734634a99b545aec48641ffc243ca9e6d83b203f6bd529010b99790779f5463c7ae521324cfb004d2df83881552215168efb59ec495d425f5d51f6c25eb4a4eb066f45fb754e7e1d869981d4ccb46b54554ff41f3a7228c07bd8ac2b4cc7f21a7b59007eab643581e89340910dc1e966c93e2b16f6b42d6638a95ccb1456225c4e1f16e9b81c6ad1c681a7dba004f60f312b15a34958b00198e19b351760ef7f54137096af6ee388cd3431e184f3fec8527fe3a9dffbe70f4bdf688ac845699c652f6c70c588d4ca1599e8274a15843d77f82b34c6f85571b565d485017b35e05da22b8428278e97dd2ea96ae4961ffe02dded0f1026af739484eb97a259c7a95c367e5408d527ed08f7e1d485ab7b6e806a6687c7bb4bcdb5ee6815fe38e83ba6380905902bf2a19f26e3811168544b68476dd6402a2ca14f625b0150ca18fce52444a93ed0004cd60f013e68f5d01335eccf3be61ac5cff0b67f876db0368a779f98d81d0f451bc353cbbe57d6d54dc450582f47c3fc626eadefb971f6b570ab943d02ccb016e90ac926ba73afb1d4c03f55b355143aa9356ac9821c53e2b6552369c5607b05cc2ecbf3a522cf2c442cf1341c42e06517f7191a7195f2e80f93d78b4e6ec0d65ccaf946b2e95d1e58e19d4601b85a8630a5d44cef2439eaa4437a99e743d5fcefe8f204fe3a02d080b1146423d08cbaa1eb46ca0ee414db14e9aa81028ab1ad4f760089c84e83ab5bf786ac9d8343de08a7f419b2f27bdec69c4dd36c905880b13c90edec09a4dc10cdcf7e045a7700c538837895383bfad6fa0f3820cc147dfcb0c649ad62cf79f97447b2e8001f68e0c59639f2c5e5ccdc7c8c8028cc528cd979a55eb3ae4aa9716ae9b8629574c37bfd9790f6027bc7e3053aa580e5af824199d14bd0c0f00dfcab665bd255c6eb367e6072b4eafbb68e1310eabb0be06493a542bd394c106a52741030e20d25ac1956485e4967fb8d5cd21a4e9165273beb2853d8c85de85a68771e87f57232eb2e600cd912a41da7c56ea0ebedf12db3b160e456f584ea870f13f973d7ceb8069a96dea7fb355d3ea077ef5949ff71a8f33b1e2d2b71d7f6b671da32ca60fd100e1261319bcc54eff8e9602ba4a5e5df945203b3112764baefd20154e662f8e0738ce867e4e8c13ecde81750981ab29c366a9709df04f5e3a425801125ece6029637d0dc7a15a180eaa22bd6105b6a774e306111ccbb4631316965aa61b9b51821c0d1bf77ab7f8227f60b9209e418fc90263536b5f616bfa23285a4054a9302aec6073d4eedd896415a4a6afb20b406e51914ed1f04fe83fed971e977c89cd01beb90e449ed1270e61a1dbd13e2b111d232e337d5d0813f1a89950db909b3bc3991cc65c54ad51c07197f3a6887a2d6c3343c7e708d3723037e1a3dcb5c921500224100aa6aef3d877993632cd3cf53702844d22249336cd3bbbf3a75b14958fe79850476ff9a142787484b134cf2689f48b3f3ae9f847f6f3682604fb7b58577093f39e65a2f9bbc4cb041194e62e9909b2104ff2d9520b541780c60cfdbc039758fd3e822648e0aa0de4507834a790a57b7dd3651b337e7757768547d92b9f3a41441f29dccc3d32321e445a3466604a0fd9779202918a172005bfff0e3d3604335de16185023dae0e5b06ee6dd24d5232149b5a2c36619479dc5d24f56a014e73431fa5562f8b4952d132ca77328b94c121fd63dfb071a881a349ddf00689b35066822e35d79203eb8544cca9f46dc860d6931b41e9cfdd0d68befa32ed018a4e40e989d22eaa9cc2b6bdd076a698e555e0ad7eb8d18b559e3bc1f6325a416c4f20c45e91f3537839889255c24498abfdfc62e31a58bb3c4adac6fc06c02ea797181d25a471788606d0b6cfc86ce9c3b648041be48238a76e48d21bc01c6089499d0ad702ee3a8db82c0b07e17801db880477bf51b9b5c5fa042aabc45322c5f2b480f291d77cba252b1b807e317851382bb4b9fbdc818baf23a84bb3e68daca17d0679b3310c70d261a541681d8ae3868aa4c82b35c7f7d341aaba00e23c39721692b4fe9f4b370ed737ba1a1425f1cc7966d06497ab9fc3454d51251c582d2f58ede07cc6ee4f5afed06014a1565b4db5c3291e05ef6724cd426cfcc351abb31791bf23fd02f9d0a94adfce6a5ffd0649dd731b716b650a81aacfbbc0f321e423df0399197f0117987726bbc5066befdf298a2626cdbc9bdfbc8fb4ca1019e10ae713e553689cfd262b0785f89c387223d414083456b14bac872b9d10d244585ae64c247bd49f89bf931b716439d6b62f25934f8115c5bb171878f9f7d8c2cc313ad461be60698074adf388ced446609d8ec6df763711d7c0a6b84f39a1df7b7b91dba55b2836a471c6f4b1fc71c63f2c7a902664931af1d533c28642fe6e1e7213f896b96445a66c02a2d18cab936298e49c7475cad39727ed018ec06abcd7f127899d6eb3c04fae1ecb4d898e31587cbca97c5ccaf072aa3b6687ec73049a838d39fc0eb23c9fb4e7f3cb9bc8ff59035948ba51e1b6227616e07ec238bf73e62778ade666ebaaf9ca1fc8f75061a274f05a81b453a82919626a5b4806bc90fa9e67759c393b2dd01e4355256f675726d0b427efaf9249d8a65597d84ca5202a2b25099750c5caecd998b6cc4f096663f2a22408a3c30a01a1a55576dfea2248ce9fe192d14d2c7847f331ffc55facc83ae63de3f06ed4da61a680f5398ef17de35f839c00561430d6d5f954045fe73cf4e4d5b5f7a6da31bebc22e7efdc09d2365e16fdf4005657132986a8b00a3e42803a0e7c5536b1e676969d710f1edae0bb10886410939aff6cfe873103c170178b3767c82c7bd517c2a4c9ef780b407c4d793bd37cd30841bd4bf92cad75c92d42b523f274ba5a5e70d73a7fcf4fac4096cc33f5c1fd414d98592f1dda66038dd43e279c4cfe53a7491151e534fcf9a0dffe6d8ab9816b71909d31172133a8688e7f6c686ba9cac6c3b5c3b97349c6d1d35159e065f8eec03ea00dc13b8a3aca6a214e0dd84784d8ca3bd7ba82f3e8b72fe9e795eddb1e40b892d22e678b821bfca547e39cac1d0ec79f41cfc838e12246a0d4afd25310cd8978511fd1350fb537985f8492dba75192395364f6139b1e6920ba5f798e4f856e4f43f1befd17efffe5e53e31c7ff03cc78dce7b262e939b8bc37a8c364272806d3c726c0b30db4d3604bf5511771b4c14cd17a15afa7a25c85427d3aed70b1f54dd6227ab2d134a5118decf9dd63f31f20f19c82bef4dcade144de5caa366ee7fd56d77850e6f49a302f4f3e4daea513985c2c6a56b9ef68b1150da5445fc7ed014f2630193640b0c54cf30e6db14c229639650e90131d8c2074551d9bffeeff5005293add6166581651bae5db6d0ece72d6393cc3216128b5161598e170093245a1e068b5b3b0e87991eb06622fc52796c79970ff7b813b952ebea86373377a7decb8de35fee87e00d7ae758165f2b244ec85aa96eceae5e37021958afbb50e81a9553b6358003f042936d15536ecb57d15846413cbedbc124c01777f0973954c7d93af230716526eba5bd84f0e35050c74b075023759b71074bc09a77dc1f9715cbd8858bd64068b376fca1b28e12f9644d314a31ba2a54f0a9119a04bd3ac40beff7d79d110a9861b5362b157dd5364fe9b778ba940aa1bfbfd88e9eca65b6f9cb6ae2823a056897b6fcfa402490801e3dcdca784bde34ca6e02ad1e3c33a2a21e8d4990d52ebb363119c30de6c6e882bdeabcec6b3e9fe55b5c2acbcd1ee39c4800d33266723b7fbfe3b2714d6f5de746fef266d692f0748906caedda4e7366dc8e515bfbe033044ef6694731f1fdac5f732498469033fb0e89e6a6003ba11eb2e75d131542c4ea9ce728282db5dd20254d9814e91dc8efeb3f11467c9410134a7d8f10201c6d6a6dd76909524a24138da4afade14c662ccd901f076c92321e2c55375900668eaca39aed979f25ecc0f646d5ecf7d276369b9c400c64abb86a086f8a7fbc87c9862ddbfa8e752c125927d52ddcb177488ea6dd486c9f4cff3979cd2a7ce422a1ab0cc5f50d9b04ec03c3aaad923c97dba8702fa573f66c3cfe48dd162b329ef8176f254292dd48197b67bfa3c2d4762d1bbad6b713b5da53425d2fc2ae192a5936692927c4d8b4528a6cadf4db389aa541c5dd217709b5be86d8d680bb408d7bfc3b4b6d74d66a07e7ae19aa4f4ab4977980741f026d79543460856e14c0be10fc7cdc8fb757b4d52072942693ade204e245f6cb7689a8a2ed626d73efea6d52c5f1fb8ee532ad72b069bfada33221785796186303a90620a809c07c051701b7b77882b00e243461bec75f00b82a009f91d26a602157f9199889c54be8e4cfb88488ce52e8ecec906d658228954699a533016e61e6dc2baf01373591945bf42fda64287cda318628e5b1d50f23cc7ddeabb49137d915621d47e8d8674ea4d28d66ca97d92b5a8766701fbe0e456c3c96cb981ad8fefbf7e2bec0e0c6e8416b6b16b92093dbfa70b1f22e5134b437870ebce5105c919ae78bbe11cfbc9f67b9b3a3f32bb7c4b377aa7240d7cb57986a69a7b09af890df89aa302b02dfb1c1890bb12ce2867548c1f82759e48809163b4dbef99b25a0530a379e4a6e9c34323aac76d6d0e2402d9fb5913f69b5a22bf963dd213009b2816f0f9aa40d1a53dcf55bcd4335cb3e4946eb692a997857d3fee5ccd3477f2c10eb7350940394ade01f1a0d4d91be111413b2e3439881a1b79f65b9293b743c9dcd4b125ba5a832b4a40bb0ba3db4f386272c7c197a0e61c33ae0faabe1e77f7be21be7a7c76545d0072d3ec5de25dfba72fea931b527e2753b0dface81fda30a6a2aa7a82508cd0f26c6b2618fe5f79ff649dcfd5c7aae489061d848f49fe3c3c8ba76cd140fa02a83db417fc6c5dbdfbf34b841318f86c7d3a7ffef5d3bb10d33aab4c6b37919bcef9c8b799f9c4ea1d26017a391bdf6b45d5eb1a9996b6236b8ab3296efa5e70b6a13e4fc22b9c0e6b51ffd13c079f05dc91168dd9c745452a57c16b68a138212946f1f70b4ed0334e6001c23bb8304ad95191870f5ee2b25e16c20250446f4c6aac9032f467705beb550c5493abbb9a84d245c4c80f5c6be3f40d8a3067c10a4f647e63ccc8047b1c48a904b2eb4c78755df457d5e09a12236e09097692dc0f5b87c9738fde4a863ff925380b62c5545b326403cf0d0f00a417a4f0e59a1d637833ba1d763427a5df1f291b94890b115cad736b387f106776c5c68258587960663d5bb985b1d13e35bab772046d79d6eecb8bb0417bf1faf6f76ada12f0c9a9a3a1ba15a376d0475a3a4bbe33fd1bee878a112bf7281bdc5b60b126e2e6c1c8ccc8731d0bb924099af1ea3b555fefa367bc9854f804363925c1c497011bc2b47bf938d48220e0e8a916b075cb52b24e4233d688c33eee9b6c00eb6f1c4f78d2dc8d59f759746891a05cd990016a7b9aae3392b23ad4568a0f727f9f73de9bcf66574b381e470d757eee50c9e0a208804da1ce8fb5fc2633723595c89dea8ab17b19f3489b1cc43c4be2d9762fe7f3233ab35bf82a91a097dce2957cb3ed7d2417fd5164919b8f3a9e9ba064a194c1b69d999e9334cd6715a5ff1d5f653d2389e1f10f9c2841bdbb5d1241489dafba462b0aee76eac30dea6f20625bcf7958245009e839c325774023e8da431c3863fda3667836678be1c2297c2e41d2620109299dcb1d5b1dc2e5b4c45dbcba88cccdb33b962f5fcf19f54b6a41349f2e6725be606bc89aef7ff6a8e19d01459e007658d5d9a1576b22edefcbfa1d3a58fd654f17d9737108db5851f7bc3712414df1490ef7956ef109138214bc1f167522949c33b7138a9df39cabcba58701be56a2f9faf9b00c1d8c20fcc3e5188580a4cc3b1c175e2ef9ccff2fc1feaf3fced006502e732102d4f466e3c67b2deb7de46d02b098bf633306f08b78726c420f8d2a879f9ef7fe28fd09b4933a21e51b9264caffaf819f90dfe7f8b08698429833628bbde882f6efb266858ac67c297eb3c7dcd4a129f40714dfde897b996846c578c3515fb5f1a6047bddab51f6c3bb65bb4a7dd8176795a23309a3c79755138db59c4d102446114146b209103586d007292e8ff01eeae492283470fb8ce36a9862b476107e96c66f4422afdfdc1d9a9c5bd43fb29d20ab2b883d02713e7732dd58c729fe46b006718b69b264c13dc4096797a846e2c9e5fd4db0237801d9fed1ea104f46f978c6b040f627ba5cdd9e175d158bda4540eb9b775c17feeb5e2b43776ef351b649209ebc8d7e24caced0b68f6c83492405732c36538a706343f562c2a773d9045f6d809257f5a622772a104ab91b9819feb06a9c7c7689b046dfb6531bc46ca59af211eab34fc3a5abb0e97107178e33bbb9a5a763288a0eef707d6a450d399175f3df009efb17a10dfa99c96cbf5220546d280c43ee2bfab372e33fc7963bc9ba34fb9f249af84e10052e2a1fb3938f47fd464c6bc23b484ee240046841062b66141e9f791e5f4b7296abfd557947dd40c19404b03edf37e3574b2daaff918848f8e6e42fe167968a15c422dfc357d25825dae7d85921fe6235b64b2287df01686e469f11908eca1c79b0c0bf7dd852d959a89e33d83ecc227303eb6cb96d01e42aac20700f5b6772fbd03d838787c8124da272dbaf483ca6f74292a2b94c412a3fbeed8b027d4b49dd4eefc3c552bbcba74dd849622eb2c97340335dae7c58867e7f5b6f53a5baa4b5b27828916d74e1ef4a5cb0b571a52122c442fbffb76be605470c08cbbd06db2c829500bad3942b366108e2669a803ab88463702591ac552d6b20ff3ed8ae44c8d72bae401a2e4891ba6f68fa9ebc5e1c9ca0dea44a605da9a8977a5ef9453cc9a07b022726c8c87072fff9b5589a223f0c74707ec7e963e0487883a535d811cd8329fca2c8b536bb404761da5eecd4c6cfc8d4feab27340c29ae44b15114fcaf02a6bc8271383e697a1c8680b21ce4e22a961572da213dca40db8bfe68469afeb109ce524a0b906799dbaf4bc98cb41d5ce14e38320a9a3289f37e15dcab9dd07767b43447c6c04c65004ab47b4a03e652287325d313cf8ae129a40ff473bb472719feb37255707599d8b5b0e52d5ef56e0f4858c15fd7cd53aca5a36e77c3523e4c4f8028541770058b5d446091e6e67f6054fc11bc0b67ff07c2e8b3eee1953c70cf379a4344d1ff0277d0c3cddc749b6d92217d0eeea38c669d27ed521028e342daff82a5efb66b74c4fc65ff31c517236f9294b91ab8d08525ceb6f4f7a2ff6f812d75218337a5ce550131fb4bcf00a600f2e3e5c09709f6c801cb93af2da05601dcc73e47b6e46cfb011562132567a6c91362bf9db2710bcfbad097e81a3e35e3c53efcfed080760d93b3e0dffa96c4b16cf72ddc0d62ca91a4116a69536a22afeffcb7b1dbd79757f340fe7ff7e721044153e4e5f353a259d8e1546a98b7da7a039332c4118e0196a31c03077adb6b764fe9b34eb31b35f983248556fb5744d40e090a955759709df56a1e469431a510351f74c30a638c82b37b5555746ca1eb4176b1ac8ea8d6fa8f9cf5441d670d3e0347976be0d524b2b04c6657978c5eac4f14bd7520434e7082cb17edf5df97810497fd1ac5992824c8c52be2dc2ff130f3de8788a6a2aaa843a040592e268cac01a1f9bccfe30d7906af9ddef9c35435b1f18446c6a1221f88c904150694cfb01764ffb020e3a76efbf9cc178264b4ac5fb532594278e67daaa06e5f968f177a4a546a4d424dd4092d1635e9220c60d608dbfd55baadc6864a519ef31641bccc870a5bbc8430c779911b171e1e445f25f2bf79f14eda57235e2bf857d301ede525c8b5927b05f9a745e4ebcfe85c0a69af2a6639cda72c75fb1080c24cf602b16f7ac7c39f5c62900b5a7c3e3c864d6ab7d0acf6c03c16c75db3fd9064b67de88ebbd335b051ada9c5fd1c96d907c58adfc3a9e18d7e5e5ed50ac942d140d418c3697731a505e53923ca12caf0b9323d12df0f2bfd4b1f1d6f1534e55b6d0dbb94f3e74b710f6bf1cdfff0cbd6af49de716d89da6b136c88d8ea2ae82f908ff679aaa2c294dbdf5ee5ac73d0abf22a040238314eac35aedfebd49cc52f6f54c9ebe8299627ec1058cd82b99a0cb269852ddc8d9c520bfef9a339322be240fdc58d8b7eb2fd38206729255e2d5174e3acc3c88e144d039f25b6da38255a587d16be6929c9cfc2ddd08a6bd41a6a3e54bc3571a1ab1b2e2797fbfe4e3d469383de2cc4de2e0e6bfae99d97a936e1d354c92f93be90131397f35384f2889db4e949709a00e5703d80361c88321233e2eee03fdff19d012967351fd7610d0b0b38f21116ebc46abc56d7181e7dcbbb10de6479981ad536d9d9b8a817511f949b4322c20f0b40600bef17fc572653a1a14787a2042bf1453bfc0d9aa878ee7e1e5842be2d51803740e203d3530791b0ff6578904f90f094d06d9077d6488995cb37f075779b3c3425f3bb8fdd2be06ef877a730faf45d4af78e1c5b537f089ddfa9b19d17ec8a3051a1165f77029f2b03634723b24f7dd4cadb229f59c6a5fe15e1d07c582909d460f34ffa275838b0bc5dea8bfd0b95ea75ddb1732179120877064a2b91deca0163b96059a66467262e0544344681f547dfb6ea22828a8e18def5527ef4603f3641954da0d7554a58aac51b4898505413f84e2d0a387d86781370642ceb069a9451f35590fe6cc5edb02df40a11fb494c0c5e9c6d9690f699e1486ea14e053b6f2fea5b44bfe1488ed8ccf51614780880d22cca18494983f8012669a829d565a5652bbe2132d1954815c038e9a34abedc940aa10e3088a659300000008c8f1e9392a53c8ce2ea53d83626ee04031d76b225f2defb2dc8e3d78893e9a6613e02d1d2a36e2d9a8bed878ed678d74890868b489e5d9d1304036211350bb64ed0c11784af90af64dbf003dc210e2976fbaf867a9a2cfcdcabac0e9c4ae2a48e086855d5b3d6b28639f43a483bb27d17e883a1150b9ae2fdf1be6a31059182847f5d1e4c099750b3c7f3c2dd28d85ef383124d035129b83bfa588a507ce81514671f67958d1647240fb164997ca028b0630d6468898803d914c64376b22d1cb957c7b0d872930fb4a1820ce0a9928dc8896dad09e8f7266c4567426a909e1c54e39cb9cbf3a4fb612681e5e263e3350dad995fac91f22730d7d57bdedc09f1521b807f4e51f306b9c7af27c55db874f9b95a7c816b954d169ee4982963c0c7f3459510e311bad9381889f3b0a8b61172cfb8f5e787b8a956fcb9717aade60376547e8cf44e0e8d6e661078f63d5708ce36800ac3579d6dbfeeaa70c95e2a92b2e59e8ad96a2535054bb72cd58882fdafa350cf342d73e0e39a449e97849c61d3367cf7bdd18b0e7632f7d00a12ebc44c449f5941bd4f5751f429c578173dde171efdffc750a4bcc9cbe1e038a8b613a77c22ed876333e69b8e39742d11da0fdc014058741156912771c9b6687f6f1d37b2265b49ce914950fda134a5e90f7ad4677b0b5f75536837cdb8871383065333f6b7417487a99179280b413a7636917fac9b0300fbeab9d50243ab02cd3c45432fdffb348abc206e83b3bd85da6f8280c488909e487df8fbb592bfd1850ff2b06d1e520d4b460b5815d1dda2ae095f694881f6a8b49f2284d50c2a4d035331d1e9bdf5d3e7bbc4839aba234453462ad4b8b00b463419fac10612f07dbf2e6d036cdc4fca84f089055ad4c734ec411e4 + +pk = 000000010000000800000001f8142f2273c3495dc1e4bced0300a27839572bc36123d71f3bc6b847841ba4c377bd240deb05ec3ed15ee30f7fca56d3 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W2.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W2.rsp new file mode 100644 index 0000000000..1ddbe2f50d --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W2.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 00000000000000000000000270cbc93eaef8347f7c263187859d5aa45969e78fd83aa3da69ea10802942af0cb7d0a433a5b0e39993a0200f7da84e434d0111941b43ea8819da913e0a955d7dd4c05fd2f719ebc987363dbac1f0db8bec4daf210f9aca23e68e5419ba0a0683c96965703529950ec0b563dc7616e7ad0feb9c9098c41ac82352f8f23b49f9c063fee47599a88d2580f3618f95b221998ece2324d10f5c9aca92d0b9b065d29051e41cf8242a5a6ce2562d28e3e8fa29823fb6ed5df3da56195bb01f5fdd7c62a07a3234e280cfb7e855890d7cc6423b1214155683b6a30f7a85dc2eecd4ccdf230899c31e819559786b81b1f7ab30e8a288b971eaa3c483ea0a13e5447fa0c0de47efba3e67e5759608702b094980b13d9a53852c8de6991101310fbaaba8c7b74ded0d53f47005dcf6dcdfe1d154e13308543bcee4e5f91197d9ceb9ffc763016b2a683f5b180990c126dbed2ab5d45c391a152bc7f3fefd088f76777dd6f24b12f3b9283d7108ce1b1d1ca1fa540f7100b62bce0cbfccd71f64f34d540a1d35056887ac069b4f07bde01f07eb2d2603884e396735e91aec35c93bef29fd5201db70e047e938e3ffa307dde005b7803f0699bcff5c0f9b56da1f13f77b6a239c7dca93be5ca1b5eff0534da3a6d22dcbfa312a95769c9b6894a32b5308f559a51e0eb6287d6ba51820b1b2c57fb75b9c073830735a173f3449356d11f4090b6f67c471200430a7a1c6d05158397c413be214ca194880484eef3d8e6072dab6a3e649194979b90e39e1cf243958b614a401ec578b1b6a2c0542a91b06021491c7524d9648dc9d4ff4e8590a2c1cbed9c8be58b29576625488f0caefaffef05f9b47fd9ca320d5338ae59391b24b981c492614861ed5a05c3dc23731d363b5d0a4efa8cee7f6b809ba89d6c3bcce1ef5b23b47dbec62d76cc30e7402b93954aa3ce710413a45b810274fb7a7ce5044fd4afb87706616997ad853c5bb0a2bc202e4b1f252cd2e5ae72742906bc36c2a8d129718678535b0bc9ffb269e1e74d5f2a37931d49add7bf397f4d62013fc7cd0e5af68d3df77eb74128119ca903f6ac8222d0492c1ec7f11f4220eaa3f1164b7322951ac2983397b11de0fe0b915a236b70f317c28e9ec458956cc7d62157f7fc7ad179cee31a6e0c07d09d99f65a8d2b1bf84a9b55d085f84aa94086d80f4045c11a67f8df1646df47735ad026b6db5ff769fb946caeb02829e3e11aeb0ed3e1a16be21cafdc66fb5d3bb8b133830209db4ad5b2c2e9935af16618001a714a098472d291f9dcb8949254a7529d654fb4460c14c88e55b966540ec4b22a19513665f02f00d560f586d08242a63a0f192832cf897e4a1587569de114ae85ce9263ab308a3a8fa2a62a0de24efed2193953c53c69d710e340acde7c1851dbe371954a59da03543f854a84f7aae5a3d50e2be068d0584199bdd81047d7adbc975d021202f97032217a3e4dc8398245b2c0b203845565c4f025df5eaa6347608a09462c81a134e32d5a0ef7cb4c464f8ce2ad0aa5cdb0d26a86ccae4bb1960b71eaf7075a402addbff18d3da51390f28f088fc3b0e8b625cf2bd082177ca20d7421fc38b44bdf73eaba440fb272850ed0461d544022807e79a45de86accbc3695d23d118a43439afe3e4f116bb306deee09ff7206e85352aa70b5cc8eba70f259b22c90d3084722ee4fabc67c92808140d1892439691f9a0afe9c5f3a2dedaf6ab211c5b29ef0e4fa9825ce11568549823d0ebbd36a4ca2d88f9344b2d20f7112f836768ad31ffe694419dbb35ce1a304944ea05ddfbb33f118290313a9847031e6f8a2b51ec3379b66fc4573ed1b2f6091d24156b44220d5fabe5b7389d7f8777a51c74fcb314c8a9dced4ddb0a551628647bf1d1a0ed665abe77dde46976e101cd7802b803035175ea7d4b57c1511f258b1878d4329d7530a9db0014d35d3b03339947a529ec16da327f61bb22994a50f1e274217c606f55dd959893cce0f0c471e535c2376437c72192dd783ea73cd7aed94a3120bfd0f315d61891a716fe67dcf44c5a50d8f82dd4edbd21c0fd5fc3e4a9ae32ee3cf138a2b9646eca7ba7fb5b1814a0162ecdcfd4b93d8d4d3316dd99db0df390050423b100edd5dc4f478fb930bb9e1ce7e85b62794e99b5f46ba96b9b734397777f1274998ec77817d704abbc6195283165b961d730e55c2c44306a6753bc42bfaf25939d22b3a4ac307c16ca28e260ec83615b934eba5a17a58bfd1be8cb4e336a68613b56ea8fceaade54afc2f87b2658a7b3a8e0c9e9bc76a8a012f2e15ab6ca59c9df0463fe2bbc594bd756f2516bacd04a423d219b22cd88144c0a4e4bca914a5c4e575a049dea608411afcaeae51f680743610b5d6d05d8fba39e5126ca1f0aa3a0bf7283b46099cd4f9337f354ac730f020ccaf0e33644807d72898b726ebdb20eb5078288800b3204dc58679b4658106fbe45b9324fe1da13239189e7aa068bbafaf36f6bfedcb6846464939ff03d0eea29f1464b90502bd4325d49c643ad5a4d51e7892dcc00d0f7d43e57511d2556424adebac0e2a0d6a053d0aba09bd7351638a05555c6fb7f91a5262ec8a326bf0b7b4392e06e479a87662b7b3b2bc5066e689aa2917509a07f74983714731e785104b81e9c5ccc734f3e47c0980001e1befca30e4a447ab317c7b139cb88f3e4c1819600713b4a45d3c292d2982a46be517dc3029a739e65dd107bdcdca86a6962f8fa7e5de507e4352938942ab99b19fbd95fadbfdad169807be9f8d9c9dc1c1ac4a530965a6abac63baec409b6d834ada0fcc58be2d3ec519d649b13502a98705535b5f841f4011bebd87237b2ade344a2dc63142e5390fb620e24b1f9504ca78fee0d2432e186e9efb7dbc3aeec617e3af88492492f6a70ff4bc2006e0ffa9020fdb386dc30a576f3a06b46cb43f8d5b4d6e2f691b7a7c471ec7c6f5c047595a8c5acd8d6194bf5fa500e362697266ccf0ab2621983013dd2984e8d7ef562a77cef437c1d68b22a522eb887fc39874d3579a262baad48a69a54f5523180d46da0a5c30ac87d79fed8a3bb1392cec27eec881192c63fd62f3624145a69ef54ff95979037c0bc9dfb70cce5b73ae6da2db0411d140c244d148532f02eebe97f4b5259dab9c01bd84bd9660d854a3bb7cb613725ce9e8224b14c1dd2325e8f44d30929700f0c95af1ba875336dea67471f650fc77922f3c8c49be00669506dc94a968c1f6ae58f5f2e61fad22760eadaf1bc70fc78fc82221ed6d6dd029563713daf4cc64f978fbceeed2d31113399922c48fa071297e44659484b2ccb98e0ad94735dfcd5b4acf7a80953b41b6c0d9c865cec6c5decb3669eeb8611b24b806ba7578074cce2299eab8fca8254841188fb9f06d0326009f13694552c34e9e54d79550362fe49ba7761385d3a4d092b77e20ba3bf1d1413c2fe0ffb29693b60f97643efd05a8a9e5165e13a9caed226a3a14ea37c7c54c37eb0197da7aca429da04a62cf4832702937d447c1a32fdbf3bab57727ad87bd8352f6ee1ed94b0808aa9de1feb8ed3325c53e1a440674dc7ee3ba523645a605d484a3909f83ab6651eabb5a5196ee9e9e1350af9370325d11a4f9c6a4cff9821435a7fb6be95dfcd6ec25294ba847cebead8d3cae3c388d58c04adcf545db68b983061962d2865bc9217f4c3b4890e02ecbe4300c55672c3f31ab3ab86175908914f852570d84dcacd03beba7eb379727dea0e117a5e6b33f760bd219e1cefa584a96931c873d21db1b529960d631dddbcfb799775d411f2c81f83368844557405e4da95a849eaa73da7b1f433a117ced5880abaf8f3b37e36e245ada21af768a4598572d729dda11aa62eb4af07cf1b467b954cbbe7fa1b0d0d92e1ca25e169189a144a9aebf1e1d13278fcb0ab4023c7b086acb5aa8aa3a948c189564a7ba8e3d4409fdb2f4610e9d16c44e4fcdc06d1a66dc96c645698bcaf4a1d2da65c5bbfa47d05f6e5234154f53c38db9af4828c6310e6d72469b746443bae8c5c37374b1626b842c46399508839e6b1b208e47e749ce6722e0dc966783944ecd8ae9bc4f959a704252b05caa70d4076de26f1648badacab530ad2920b5627fe558c9cbbdc4d583900ea33afdb995444adb283ef80979ef6dbfca07fb39b965a4c6aee65250d43460acad5547dbc62693993e9d28c91b0267d9df93e1cf375b0807b1f61d538c1ec089532f873c3dfb723300b8d3c2ce9189208bff8b0776a61625e639486503b3bb850a950ddb940c6161f67f904c482b423f5e63f5f9fa5de88204b2eff2d719a880bec7c882765918b33393f4bd3222010ebc37fd1b7c0c674ef850653b22f205d2a9005ba6bf5d9a33ca3fe0d6eab3e19d3bf4eb28ec5c55e7e9ea7c4e1b036deb668fa4a352b5f9ff0ab8f42ab110dc006b6c75249e3fd2f089b10423d592e8959cf275f2fba0f6dda4838526b81320e49bad5dbdce9541beee5e70377e03b54eab41fa04d65a2141d763f3bc3d2dacfe013b36940979d82070e4f3c5e6fdcdf4af93939f9af71224d3a3283dd21634a2062f98f4c5522ae34aacf773a5611fdad906e30598f51e27c052411e6ce1c7a755fde2dd530251c1f4de1164ab285658bb5a674951767e5bab6eefbed65de00ba4a5d88a2d30234215e73035f2a84d4468d827d3dff51aab1bc7e85e974b36268d139a0b9ceccf8e91c3301ac1fc31843b0edbf62f31306dc2e4c5104bcd6b7243d6578cec97f8c60e922a45e9f1a4ba06b20a0f2c49f8e7a3638ba6f6618c3f56d3425eaa8f14f76bcd6f7212a141aab63a3af49da3dd81f16b247ad36aeb7f4deb928c7804d1be0cd1721c0e0451dbf1449a52f82a0adb64e8f350117bf1204820c99d1046a8967034730cd3fce7302916a945b5bb6f373e713465130fa3ae1a233f0a412b890a47fa6c75d960894064bdc92cc570344eeda7176a238972a24e0297d7176d6f37e5878355cc151e9f8be423b3ca74be8b46cbdef22aa205c40d03e1d75380a32db764ec8feda089134ca7ae016c92d63565af09b66dd235c0d9148303b5924d44b8b854943093497224c350b112c7a786b4e085a9d7109ac33dc89a6c4d5bd9c9df514c69cae7cf226fca6de7eccf075521f1c929e3416f0ec19a93089d6888b2647415d8cba864ae643ea11402e0f685d1f047dcd43ff8d42e19430c6859aa812c477111e96521f427db2cd8c99c47d1d5c1de91f54219881bfc6e4cea3b4a844fc6180ca622dfcce3dfbaf4c775e3b27b2aaa021dcb99a7e6bb48bc14f969794d08656f7650091a6c15ed9880170328421bb4735205bc20267669fa89ea2301f508c81bc47104d320ea8d754d55f08d88ddff81edd342b7430a54c3406bbf843712137f13f78a1a951d6f4e4277ec4e9c66434f4ff0bcd4095a9ce744d969f7d73336847abf76dcd1023f2e5d92580ea275dc25df9a98165ba863ac31908d3466b03386e5abceab01b64dadac6237e1fab22c59e887ed71716c58e5ca8e88f1fd9f1cbdca0822c9dfb0101ee45fc64744f5a8f3e2c12abe7057e20121eb0141ec4f82a9a917242d4556a59348001243e8df4d272c1d455d05b4e792f8f522f8e5bedc5999bd0f0b79561e85617feba1af0875ae7fdd4f3f9761d279b34b9bc378c1c8d2df99aab19829201a3fa2f13b2d5516a8a3e8104021244fad1f5c13b6ce010b47410542fa9229bb4f7505806419f14764691b42ebc0ba569d3eda081a1f9ba3a6dc9bbedf66f85738eb574fadc183d5c6ac554bde82915193744fd332728779ae0f9ccdb6f9d43fed0b3bba36ab60027f8c29c035b2b50b01768183a288de3caef3e5087660bd1d10eceb17f0daeeb8778f234a57491fa439e646871ebabbb008886105d3ed601b5dca431167c03ee66b5622c9a28e9b415c4d03be006b0f7733a57380ba346c50c8370180eaa179339275c7147afd3884f029af75689ab5a1a7ef98ebf1aeb9fa612f5cacc1530eab1cf4de29cedbf12a1b21cfec2aaa453ef302066f05bc3ab318e23d9654cb86a00000008fbacba04e2608ce5de88939ed3cc5f92631b7a435f695253dbf8e35f0e92dc089d295724a3753e2a821aa454712d3739dcdbad73af25d7e4ac14cce109ee1510d75628951cbed855c82448eed4846e440f7cc824f0960f9eb6452fa955225b2ca657acc7cde4fa0b5057d407b37335492fb69444d00b89eca2d042bd0f839a7de3f0d236ce0fc52bd2ee6e7a10ee1018f47e3f3b8e7fea48886ae18144e5395f16528b67f3d3393ef6390d85c857fc497da24331e8ad8d11ccea2bb1fb7dbcbeda700058268bb61db029ba43f1602c90890222d07c6475102520466dadf30a1955898bab32c91f557534de0c7954b3f4effea63d64d16d2ab75532b1b8010c717106219f38b04fbe7c083e1f764ee72063154cb0042661f48c385eb9d5b0e3f20e002f0757655039feeb3add3517fd32b40833e81466a61d1270297f03ed65906667e0b19f862b37e2d02d98cb563aebadb65e967a26fec2d873b467f16c142b5c4301a935aa25a2011d7c2660b6cabb9940a681d1718944337472a9fed2f24f62009e568d3d7f6dbf2869e8e16b13dd36eddaaa4a7d198d1458351bed134d69c60bf516dfd21783a5025260fae43097e57f2054739763fa9dde8f4f088764facbb54b3547717f8c43fca90ee96b53a6af1fdd143e69031da0d2f76b2b0c6a356f5c15c1c8189c1fe397ece30ab2ab9d68509a234fe2a93f200436275164e0d4ece03dfaa8a3f0fd476f44f52f34990b938a86c07b93950c98d041f3fc68fbd4cca7026e213febc5cbea40f01ceb4e8c6be31f1741c3f708125b19ef3a2df2194e8eeb7d443c19b0731e44c05316f86f0b573378f7cbb30e8766598cf472175425d874b3967453dda75c4f795d8342bde0fd7bb97525a65ce0d7bcff9cb86182 + +pk = 0000000100000008000000027298009a2dad468224314c20395b436b6cd9955b10abbc17538e96f1cd6d55ee948288bf22a0602760b00231a8d71ba0 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W4.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W4.rsp new file mode 100644 index 0000000000..50424b9e17 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W4.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 0000000000000000000000037c43ee18a5df8fbfd9e917f1c48edfdf3bba8def38735c8467489c1392881b827fa292e35aa39f67ca2a2ceb9301d7a592458d8bb115f78241ae487783e50926c43c04ae72ef85993a9a2d8db2139ae7cc95eb1d1cc04840713e0e867f0aa3644179e4411498d0f50c3e149c8849e03979ab92e726ffc2e3be442cbd4d1c9eb8605678e51e613417f33479ea18e3ac3e864c8219554629568da7f5b8ba9d4f3dfdd7f63b4fcaf606467d1f5b326e20c36e45c9f251c08b0116bcb01e3e5cbaa1d5e154ac2ce0e11ec42e81e105244a020773ed094262ee3d609d668b2948a0682e96ec77532d85e899d5f7e07e48b99b7416f27f05408e8704d36251bb5df5568c53df8c3aa7a0b14a7e311f0cb63752610127d73ac0b80733144c93d6de013fdfda6ff4693fbd19e6c7ecead046f1e2c937875f74f1428e3f1f54996b3b47fde49a07b34298b678d0753b9e363ac9e8a777148cf816ecffb458d829a440d983ab9b0d435bf8d98ae71a81a37b7d10f5e001fd0c6a3ff033530f0eb1f155fe96e21637dfc82c9e802070b1c4e008998206e9c04cf3a38f89108b275b5afed4d58b9c34cf4b7d94df20ae5a516e7da4557d53750ead4f760ba82a8e7e217c048acd6ba2ba877825522cdb72e152b31993cfc0fc1df21934cdb80fa088011c62e127b3799a498860108e5f4f8cd6e9fbaeab60b7ea46e84942e354e4065391a6c7039125eaab29dc08cc5bb695ee950bf37cd1d3d83030ba994f280b00d22d48269f05c56ffc54e43c45311bc6dbfb4b53a1df6ee4920a370c894c17fe90e521175bb5ed8bf39987d343e59fafe785e9389daef38de6e863035a3fb630cc2755b58f0d4952cdaa83040c84775faf0314a7d84008ff79239b7f77e3627afd2e868aaf5a73cb3d92f697eb4b880557cfa589fdde3feac0336c7814cd0bb962d96ab5a9a3737cc465e605ccdaf5162c21de0feebd23b6cf9cb0fccce7a1645a66341b7314df7cbf24ac1256ae53d5ac9952de184c1b026b9b2f227591694939f95d1480243488e5a26ed84a628dce33aa884460c0cc3535b73be0dbf4b01608866ac032c19fc1ddf288ee7e2b955c1fc80c1761cd6ce0ed9d6fa3a66723c1f4bfc67b5c2b36269035661a8f10d20dbee8712322d93f6d70c329b5ca914ccc91373f2b809686a5a68ed5bce241112ff1274350219cd10208c51f1b1ba415b61a1bab437e6a75d422f635584a83633ccac0040215df734c6d5e654874f8059a26893183a3d1357e01f2f5522351f945957a0d14c263d5da7602b2168c786c66bc419eb941c1b029ac4ae53b89fecfadfb58ee1aaea9e71287152c180952de7f553599aed4adaf6a6741fd358f2ae0968c027a1f5f175acd951303059cea84a98b70b7ca986709bc2ea405159ac9d50665f25eaba56e0ce2fbc5439df6e5cd08d10d4167030fdbade6eafac433d37eebffc185c9333411d3abe34f5254f1451191c7541352f7daafca626b26716663fb25726e77aee9c1c6ea2de33c1f28c2b6d15cb7addca5bc422d6b06c0e4db832b9ab0f08da4530218d082116a1a0ff9f4563992302b2ba889d04c1375bc15fda2510aa034963121af0cb9be12a68c99d76390c126f6fd7df89f8a38982e7edff991e8d9318a9429dfdab46a54aa9a04018b634079d23a511350e4b0162e628605ad852f0e589730d0f8e09222716bdae6151aed4a62dc3d50e417e9a8817fac017ddb0da99ce08723bf420b6a70d25abcb2914c3997361b5be31e485b4c621ae493729c7f9efb00e5e445f4828629d61d532459f08654531b4bd5da5867745b58a9e608a753e568c931afa3909da2a5dbede3ac7cd52cbf954e9fa26f510476cdaca57fb014b4d9f46cbf4d2450e2c5ad020d189e5d32eb49aec0782de2556403f51ed8ce5f519c2cbd451233f1adb9702918dfad4031ff5604376384a200fd64bc0bd80371cfb896dc56f379b8f3c964d2e57998bf67fc2fe12c88d23ed3bbb267e0b54d1603f833a5588a0458a04521b86d90a56c7e9ed3a8beff5f13a49517a79f270d245fb24fc3dafb1ce0f01f6f15b8e230291d5f6d6f394572a49f9f85d1847b990cb2060b09dcdbff555eaf9961fd5acfbacc64556b77139c177438b8e7a86112c60293eb1c583afbc17de5261eca46b76de8160d5068764c194fcb6a9243396ac5a7a6db9602b3421f8f4f425495d91d5da88eb9aa3036b5749a670d0fc8b40af82515f296057210751d49269d6e86e7cede47534b7b307b39c6ab21fecc37048f4c911112f38ae2cb01a5fe9a2379d37bdb4986a0e40c2db67f529cd3903d41a9157224224661414a9092f906e6fc7b6d60a68d311159107d22d2a15d757f0b4aee8d1a453676f26ba90ba8862b9ae5ea403e6ebee935407d468bd84107c8913592539adc3c65609f859f57770f72d202a903a63ee0778a321e402e036fdcfe4b62d78a67e3330b71efadf9bf2678fb024c75d9ec9591f2c58c08e6543b5fb5427177cda74ac3c0c641308c0562938e30455799bc555f9c0cbbbf12b9b1b7ad907ddf838c86634d3ae4f3b9f9d5d4dea929c75c5af465d17fa96fe88233fa8996cdff1e1cbe21cd5ee75fb3ffbee0f0f15817923588737a6b1647324b9cad29c33414b5f87c7db0b0280bc27dab78b4c8cf137752169d65fa5b9d374fceece83acbfca612847a147a66642d2b25bc19c4e7e86118efef57ef08eba9fd9bd36854f96ae47ec1b7ba8d4e53f97553386d1a117fd6d11eead3d10e58cda7258ab8d530c47d33321247690dddaa770c9dd6b5295e164e2a0b9b815dedbb9654517be6691b3dfc739c9d470cfee8ea2117ab7a2c2876a21e3513911486e00649f98aaf9ef1a32b63000dea1ecfecb9d433b51333781262053f1096c884fbcbb3187b09489fe1da7ef9d3eb14ec1cd91fa1e09bdc2a6f05ba95bbcc583a86fc73daeb18ffaa7802e671e0641331813bded68bfc6f284cf44ed3cf810caa5e6103208bd4c56ea670269e04f96a5627ce77b364b50b21b38eeebbaabed9b311bdf49f46310be5d19aba8b76b5ff276f90a784850000000863db9401ef22c5a1bc3ef9a0894c875e66109f097575f50f8feb4e2c18ef1b3804d41ae1c38fb1dc4d3306ab4cdc3a0912ea0d70983212a10c7fd15f9eabe503251cd8e12103dbb3d5520a22bb4f758ace010741d5eca7d2fb972e70abc782243b7639d486656e9c0bef7a89c6e64ecc0bdfee8af27e24349e9cbf37ea13c9533fac0b57d5ad9ed89b7af20991dd140b9c23a01f53eb3f1e649d8b2d6d941948ae30c64cdec7cf05e17ef2b74d24445ff0c108a240168aa5694336f1ebc3f9577ecf4aba3fe7494eed663a8fc01b85498206a6e87a435e30a3bfa64558126e79e440369683bba29269d86d8c08150286a1ff69fc0a4eec0067e88542a2dc03fbef3d11681fa55c18d9ce1ed722755012df301ad7082256925a5fd0b50d675913a929f7cb289ef8abfc5514815a88397a1be657ac0f5a3a343e18d56a8264d0d52596c561a22a72d18a7d6551b001af0ffc60576f54829d36515e4b9a5c4069306d2c3511f176d2d74c092c7e261d9fe4b8ef9b1d2f1dea9663795afbc7058c147f1fcb977f80f98fda75a7c8821fa226af50fe8d02b9f8b9a9ab58d6f498544e4c8414938f106891bbf87d215e42a3b3dd82462c9ee5007edbe45379f89bde29d86b485af81942fc8a71123b51971ecbb49ebce70a85298ef1eef2226ded1b68a16f525be1f074364084b9aa50a2f215e9824727ecdfb536c3e2f8254b2e37aa81bdd106ed7669e5085774e49ebeb7683554c867c6aa891d6f02ba298fb5bd75e2af2163e211cf09873ce061f20badfd14743a9088c2fcf756c37ebb41d3a437857a85abafd33d57765e8619429abeef65b6a532f5b2a8ed9892316f3ed951eb32a10f51edd95d7a5a0e5eda591a481d081e124831d297cbc44c233522ea9f26 + +pk = 000000010000000800000003bf90b647b42dad7ba89ff319a8b70dc30f41f24161c1b6d1935257ae4b0bfa5ce168fddedee56ad0931604f868f9d5b2 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W8.rsp new file mode 100644 index 0000000000..de889b92b8 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H20_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000004c77901fbdf3723a0e739e33dad60d6438b3a33adfc72c33f3e1a3e13791a362aa3a1cf96aefb864bcab9cf5714de25794d8d59428eb4585ba22ccb719b12dd7301bb456156130d9c8d34e1624025b402dca6c4d2d5462ef59c5842a9aa242c72cdf29daa26527f5f529c01af89066ed129477f2796f7a2bbf91233f4bd3a9f658e995fcf6221a40547c442f3f5dad46aecff3a4b061bd72c2bd725af87940805954d9b9cef4395fe8e914c736cff67cb8f481c5e9842ddfb95a4c7f9f1310c3bdf951acc06337ca482b677992f207e11fc3520c923d69fcf8b863bf113531e0266246adbd818300bce8ab72b081d453f109bb298e72bd499614f9e609a12bd1e7171187b65e70e9f175b7f03eec038f2faeea0a6c13058264f3b21ef4cfd27c3502eccaf94c68060a468353f1e3c111226bf3baae1af78d783c91c32a344ea5b1e3875f1571cf381e4a142f154c749a572ee587395b1bc49df8c979623dd8b4b09bf1622d7bd1846bf5f65d7be5f28f69a40eb9cb0f25cb30b1090205f85b067870d2abebc20f7bb67a35afe9eb9e1c8f9d90d32b18728b313e055c22671682ae85de2277aebfa94380bbc7ca11c090430cc519695f3af0c5667a3595bf565e7b1114e069d9343132d36adc42043cf0ff1d075f82147d4f8baa9e38e68ba8aa9170c855f3c6e3be4840dc92f65cb5f2e1e24730bbf6d4f73349c3d85e4507b8c4f39bc8b07eeee8f2fff240b07858d391a9e24d34d7f219bad1688546106ecdc177589ea3cda62c02b3c862d7ec1e995e6555beb0d2fecb6d6d86c232dc76f063fb90b1bb4f20116bafdd7436825a53fcd26d1544e71a1feeb0b154ea298948c3ba9ba0adeacdd46860c6d28da3630b36acc8913ecfbc1288417513b8988d977613b93fe7c5c883a4df6096ca35875f24b4e2f7c6c5cf715aa9428069b365e1a121323556113a0ed9a2b8c1cbb944eba56e4917ae1dd6dca34dbb4098a52651af8a8b32a0416b85a9ec8c3e305268c518f713edb977fd6b17cac7fe85d574003bc5133b590d117e5b471a0abe73f96a069b0162bafd492a01900cb3c9bf6ffa6c30f11e9d1ce0eb5385187990f54387a1f66be91b8e9cc09acc5cf0545da67470ffbe95b856f90335573b14cb487787a1440166a4b5249c8108b7d7e07f340f2a30f986cbc2b1e3055cf425dde138deb3fb12a9bb2cfae7020b2503ff50840ad2f026282bb9725e82e310cb2c32a1fc1e7291817f7539055d8b61335643d2a6754033df4326da389ed5f83a6a1c88125975548fb213a2fd7287d98e8d815f42524e10ad9117cdbf88464a8354a96e6c1127167f7cf00088440501d660e670bf98e174cbb5bef986899bd2ed23f0051d1d776e6f4eaf6a8b4c973f12fc85b218c17d346dc8e8f820f71716219165fecc90ac1101a58d0325a586e9a2fed1a2ca2a96b86c94892551712aa032e2a474315ef6e0aeabb2d92356a65e55ccdd371f79a5e6f59e902667731512f1faf7bbbc3ed307927323b1a51f52268d696be32066cdb859662fdb69f8e2a718462537a612987377552f3e34919ff9e044ebfef0f000000088688c398c528e063a27c2654d8ef6fcf86cccf6111384367569f78e0c5544ac0c32f502398b9fb43c94ce6b0c2fdff387ca058d8b3d70edf444567347c32180e5f579935bee605d8d59580c7092b374ce27758f3fabbdc1210c52e7cdea694281ba308427afff30f71588a9280f7ebc56fe9b80c84ea65867cbe443ce760d0dfa3c7889846873ca76dcf464c7ac41ce082605d115f02ac350289557bf7afa58157cbed69a0dee6991af022ce6cd54867c1a05e71949fef85c941fca240e0cb67ea053725b7fa8de0ef248b9203f3de202fad5415112aa621ffaa5504fe4d20929b4f761d9b8621a63726e079b36c2e04bff0782374e2cb103c54842768c164ee77668753efebca2f6f075f47002f7dfb3689e27f1096236cd904645108e7ee25a0f6f3a24ca2db67b53a13a5e9c39601d526b5bf1658c9e9ce2b80f0a6eda7ddeb8811c6458dcea902dad8c1e0da485459d01a9349bebc7e03c7da4366fd53ed29b30c7bb9d28d758c5574f7347cc02e1becabc07964ef20bb27950f4352c92382eba52126a33d4fbe947a1a70dcc622115e4a1e61d283cb7e21a26d43f5ef2317acba85a2aafd6fcdc6fd902bf7821de2b21f252d73efb0f632e46097ed8b9d7c859175c8b4c54d7509ed221131702fef73ca28d9f25f7e1e915be840ff3e56b8d09323f93da0a6a041b5fe66a1910707f5a06c805efe8cbbbcef36a20680cfbbc4d793bf7ba9be868e290e4fe99c1f44eff6f1444775ce1f2c2bf2479b38db8029024f7cca496cc0c1d4013f96a1791e73b72d4220d649d7333761aad155a45e23e00b83bf3c80848c4c3bef451b33102338b11e4fa27c0e63800f1fb10c72029c3034e04d606bed563c0a001f5ad8c718d4056acce6076a1a652b28699928 + +pk = 0000000100000008000000042fd1d7b686c84cbe1eaaf415f6095268787d809d3b8d9cd021a0967b3972c847cfdc0935346b1ce9f3f6e21a2fcde0cd + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W1.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W1.rsp new file mode 100644 index 0000000000..340436bf29 --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W1.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000001a5b1fcba390b752269e52f24ac609acf4e5f1cd5c45f46b26f6177ff23e3502f959bb3e4a9995e7337dda0dcfaf464974ca49ebf852abca2643fc8670b9428dea973c569cf1b6efb10b7aec60643882bbb57b84111901de9df43ff8b84941b85aae106b431995a6cbf103758a727cb4234cbf8b6e3f659aaa7d72286174708859e0e153c5101dac9615e1b9a43426433ff250df739bb9bc3e8e19723199f93564690801de8699bfbc5c966286a1d58936a50d2346635e4da1047576f1e97f97056975d2ff57baf59d88ba3459050f049b3a74c6fb82e7a8cc70c121ce1c633afc86093af3426c5bb2096dae2f40d68024928c28aa3b371d204194d22616413bf304548fb1c93821e16aa0005ec8d14cdf300de7a841b925731319c19b413594e3b2db5e74a913e70a1cb89b0bce8175c8856b1e221d5a07bd2d3a2d106f9acabef321cc2ef36e5ec9e60240956d5b9533f45e11bace27017bcf6d74eab81e3a55e10025e954b510b1b7909956f6d0b2188bc62dc05251114b8e878dba723f8cb9aedcb5c1bc2fc47b3f1663070a23ad908adb9abaffa2fb3c4fa3b8ef5305d979852e1306f3b88bf826ea086e9d6229de20cac880aaa32a0426fe9e0e5e283d055a298d3749721235ffaffb1561bbec3321d96c68140371ef7a20cce5987a9a37e9a3dddd45707e181a855df4bd29a22e63995c92b22db1919c7c1882d8e91c6764506dfbab529319e49dfe6c32a9dccafdcb387a05704938a20c786a9d413bcab3dd020ab8f8bd5a8b6821902c028e19b3ef75726dd5c6f546f25a820976f3d6c6d30ef4d42b06a0133d8ae43b97e639863f50310e822c568e4ee523f354feda584bf549294140674e5756c248afa342eb60b9e0873a1db661b1184371f752ad23026cef236855d3e707eef88b5f7b72f607c1a47db31cfb51bc346f20526f4f5b696ba7171a65d94e536a361863b67287b040860ea3ed4d25af0051581e135ff422243e4346896eb58ad50517b3b63df6d104176b02bdb5e2a6e8af0ef52ac4284c35b2561212a2d1b0b9f16d0f08378ba0368f0e5cd031cd898d21d0d7df5c81241861623896903b1115a0a61e4aed71abafcb609344eaf227af41a0ae4c3017c8dc7f8dc99aa679fe0605a800d6443bc27f18f4de198f93c4553836cede5f24de328319ec49bd203e322e4c1b57c2504e087b042824e11dbc6ea13207cffe3b0fa1fb595052e80cdfa8fe7ecf4be060b8d049bf52da0bf09a24b5297c2d7720ba7f9cf8264cf1397a5550a39206dd98bc5488cb7f5429f6327f643d3eb49c31cb66e281bfb7488777dc0ef8c18f9670e29c1f03d08cf405c263dbba87f5fcd1f1d365abe7dcdb087449618d3f0ad10b3b663757f8a496f24d857a61ad952984e13e181c31a7c39440f37ef23ca77e1a95264fc784cc53a779ae92cd3833967a8a7bd8baa57cf98be69d67f0d540592fbac6990d1b11b01facc7c570d267480f94ef5bdcbe6558c70b5e23d4fe14625e45439784601d0cad002b2f541f65880d286cc279f0ffbb0bac3a1bda18f3f8dcb3210300c843ebcc349cd59f48eb8763d901575158c77f6b1494ad63b2118f78461e773383a0ea685008d1bcca28f6dfebb445d2e82a90ea8f4856d1a3343bd00cfc8a73c0d496dba865a7b0c232f0a79bb0be78263ecab7d273db90219abde2deaed1e82c1ef3efe5d0a2fc826a396fb4121abca045898814c8b63bf70f584cbd75481eac9dbe9b13f5e50c95871bfb5facf07deb4873c2d8ad81b3a212195de3110be065dc1694a84fee5b4bc80b143a81e6055e3bd26fd4b487c7c27b73079449fe59393ca2ee06d51bd9902f5bff9c5bd6d0793a2ab21333009cd9efa6f64fb67f97d5775110be4356c20600188458faa739ca149796f5a598b05f46da225b969a297947b75185d0e9c8c32221414ac4ea886209b8e4dcaee07af50bc1a995fff0d5b0ae01a6a36c540f65642ed3be1d1b6808df18f575df9c01e1d2150e1ab268355d3fee33eeb7fd6dfac9adb0d9c99aada56e299e9e13a4c37e4c902738bc92b684d5ebde5284944a95cbbf2f5119040e3f8471b6d572f108415034f574f13dc417686a3a92306f0ff22bc9e253c5f04b9a96b9105c397da197ee587bacf961c71d8787cacc05d12bd14f8ec2eca4d8b11de8810d7d31cd0c172dfda21f732eb6a53088d11db3aa4b9080eda3230e2b55bb339b4aedc9624c32d5e6eed1110bb61373fa10d98255ecd9c073f374ddd197c4b9c208771d963e93beeb263c7be992ad8bb9930725303c9e5b8b2eb40fe7266e3c1f26f6150da42668021c9bb2ef8f91c76a1726efd58244f0aabac9d958f320fccab4e4f32898be68a83dbfc15f1dddf63fef8b3ce05d8f8d1765ed7b2d3aa6a8941c94600c4e177d3f0a0d606dc2a55b4c46be43dab0380fc96784b5dd0ed9dcb590083682aa3a7e6b32c90612be44d1082e3738cf5ca4ef581497c3ce6d7eed774561c86177901cd67cb7fdce4ccd81586a5a3d0587d8099fa7678a43f095eead13c98976481ed4040529ce29145436157b0228241634faa5a43c0d0185ed9f2e07eec3ee3aa95a62b127e45ea2902f97d024ff810968fdae1c1fc6c851b51b8829dd1280d2cc3b6029f0097326d34f3c350d6501a05d7a333323d23839931e947f5a7df7274098025a0041e4d5e719a0ad3480b3a16c76486d119a1a4ba0542fce25777e0cbaa44936b540c5ff91c013351e0ccc93d3413f9b145c551c2c4d302f000f2c5b3c3dfe5642ffb9e5e5978c323eea9ee7e012dac29f62af9d57f0b5dc106ba751900604c76573eedce79c4c06c8c055daec35e2534ef7c2eb6aad9c9c4cba215ae520cd87752ed32a4dd3916ce38c302a13c3e1dc613e754480bece4994b28e900a9be004a0aab63eddc3e06fd05bd744fc43f76487407b6999d9fa65d15550a1cce8478e55860f614a2f13d0667e98763788802a95c2fadab792928d397dd8e2e3a2691c88681574e1169642e9a1d637bd3ee8e0494629692ec9b1d0560df3374c53b33ef8a1c13c105daeb538b7fd65de27e2223255e3dedb08bcb8d3d18447a61948731d30a9358c3aa61169bf679ff24aaf7d0ed19a82add52a6ad496baf24934c3d991274d70380c8a9fe2a520272106e2d67d5a136b9588c0dad681d7b11fbce6d835caaad3dd9179c594be9e4c58a9d294b85353974fdecc6075f7dfe1ffd1cbfbba7b6f0d99f1f9b3eb3cd22f0a75e4ee9361025890de6556c2b450748dde7c200092a0a52ad85ea5e1d9c6eedd274c05e55cf42624a3a2477ac162061803eb176ba5747559b1460008b9f55eb5a3c55a575342addb5fcf0be3334aac1e0ed0f22c457a2c1f4b1dc0afc8485905ff537360060b895681acc58cd5f23eb587edd60b2e33c2aa77b1b07bd4090a3f8ea627dd1351fc68aeddc50d51bf5323ef3055f6a16bf2a6d1d97f124ffa7c27faac2a0e765a75f363faf715b0452e2719cf3e13b2b10d890a7c66aa3202760ba41874d14ca98709005166f7bf5f93de9054f31ab4d9eaf5c97e2db07c9b6376eeed1048dfb6c26242e5de8a46bd308b37edc9a9acd3a4beb04b084ec9e1325aa02ad58af47f264cdbe5fb49d4d79cefb6badb8e2afb4c2ee7db16606f0166be7b2acc848dcf51ae6603d72ac4c1be1b8e4cd54de4a2fccb53a42b83e8750c825b4e1b0052a5faf2f5bdd4581a557834c6571cae4e05d47e71efa27b792ce9596d2605fa89306942699d126f842746190a36c5605d5b83cc9fbf3133ae752ba0a4c42b474d30e6fd9127b306854f92d0f0e29c8a734c468e0837b073bd622319c05b00db874b63c2e6cc152bd0fd7e5107f168c897d80efc7d943f3bfb2a64a108d84506c2895d1a0cc6206ac92f9d274757e91defc3612b2c6868937fc02d45b0441cddc7969fa0dbf0df711a35b6c43ebf8b12a3ae77b941367175fa8795241002cfb3262cd4bc9857e1fc6420c9f7deff319bcad70047cc9a24dd13b19ee95a96df562d36c5eb010f45b0e0fe353f95fab81a722dffbaeeaecf1e169e8ed774048b34f9f35df7757438e57f157f83507382ad7bc169c50186cfea182a6e402cec92b4915f8447ba1b96a6e2fb16634241efb103f1de9184a62e3c32ac1fc4e3c5c7142d9895ebd5b80954cd141856dd2242a42d760712a895aa52c74c52a0c0544ea85ced655e74725944f87b9c1522806e0a6c9b8dd7a1f0f92ba06c9fb002de559cf637fc139abd90d0a836360be6fa4c0bb8eb6b797d4e64af3d4316e402c59e432f25d54220c50b04ba0f6a6e4b7f349090d5eaf205800cd6feb6f5459554f03cd8e3557f6132889f3d33b91a8a56190d9b552bfe99b0b3b3f260948ddb14e106a22b96ada2e7459adad648117dbc0c4944bf46db8d557fb3a1a997d963debf89e542f43e6695140eeef90f93b06a378b2f4466eceae8ba6d81e5019ebd2baa6d28a11a8824fb17fb808b612e36225d7c1ac798dc49faba3210f40fb230f9ba0d24549ba5eacfd9f8a470b83cedcc895347d50bee5fb5d4602d0294a5d73332b03d2800ed5eb21c6f7288e01a917da98e6c9214372d9139fa2bcf82912df4c6e9b4537f3ca9a57fbc55f20483b99acbba555f9ef4c6e6bc943e24919215854b902fb2e5497b22e6aaf0f5b0d4f3cb338f94c24ca9d53f87b98ecf391e27df19ce311598ccdb09f5581111d77c1caf8aa8d163a485c74db922355924ed67db075c2bc0dd29b4efb130e7869aaed5f20ba740cf5ad4f47c64c93fcc9e964bb0aabea679d4e17150658a3d97da9be89ade5ee42d52c36379d5bc2520b344bb269b0cad9e2e0087de976e121cf0f0975ed9051ff8fc0c7eca3341399f14b8e62fe5e0cbd3f15b8f3a18b10473a1b253d645815b0205841a9c4d7c493d4eeb4e982a4b5ea723d29c8ec06083dbd252846f119aebc07fc9d568b2eda28db5ad905123dad39d02c012186d854e561443b0fb73b139d632f2a102e33b52ab2b94c3993aa8d8713b141379c62193d3464a96529c75676fce6451482875c33a4d699bdafab582b543399764102820ef92837d3bce37938b6ffa46bc7a0ba4ad3cc8e7e196b12df2ef03748b8bbe1541613c693d4a02e54cff8b72438fc9cd36706422e327b5f60ecc0e7285c2cb3ae37a818fd9310da196ea7bc87ce42f358570032a1ff791a471fea3f5dededff0439d98ea5e49958e3521c646bba4f1494c9734b05f2758b81b8cc590cecf09ede5d69d29a388cfb04dd0d20d2b0e4bf6616aeccd45df4682ba6a93acb83f33d17ed8740bb26f6676519d29a96827af74882140a88603c0bc1cd98f0466f8a9952de5c9f8e58869a2783d4e35778fa2407522005c5666f70273d55f8901a5459c2e2c53f484ee811516a5a235b5575787acd073a944b29d5ee4f8a3f9936e0dde8570c357a990c49c05eeef2dd604c8ead74541d7593dea66125d19d2c65da11bcb7aeee7fbb35ecdd7f7a17520f46e17ad0c3e68bfde0d459d8aa9da2ef6cc2ca2c90c9349501312778adaf1948624ce0250e1254b443a11a0a1f5532a0576123d2bdac0be59e9111bf7dfae21859ca219760dc4f6dc5ad73782138084a48abee1a8d2476d44fc22aea93b99f3e4b94da17282cd2bb8f624a92ecc5d24f5c0096434e4a6ca1ce474ea3abe8d658cbf3ec5a9c9ab563bc68043c55d92267cd9dfc5bb086a0dc9b800849c675d5179e60bb6f38385118ec7b2aca937d54e8ea99bc9736fe94e614f2e584f203892ac14cd2ed24067680ec94d0c1d8dfb9cd0cbedea7efd865c32fa1e2e6c8f0f7e86dbca875dc0d0e83f1edb9ff190f463fd57b89ccac14b9142d513e6c60ce226cbac592a3aa47b4b062844b6aaf3976acb6714f9d4080dde568c29de2d710816693a31e2f0e4fe61608395f67c0b4f0000fc4d3eb46bac57251d99188969116864fe0593bc60f3e5f7c9f9ad0964194b37b897431acc14effaaeff4802753093027caaf6ad88e20cdf6ceeaceaf681a2edc951e4b6e4d49239797c54d87e591ac324a5718fb62338074330b1febd106ee389b727346b581e4b0ac8a7c40d7b56574ed506fca456838abf7ed3f789e55de37051c07ac02b610f0a8d656add1fe9104b0243a29ca46093f6292e0ae152e4976e7c5c8eb6c18e04cfeb11a3163a14cbaee778e0967936fcf76ddbbadbe93794a98ed8befffd0d182b3a96a8a0217ff1be9fe8377e93a2c5f4d75f83df93eaa3e2d55574851dc3e0d096685a3b3c575d6c703a41807888ee4222461e1753ebf1862e39f29a5bb321bcf111a0dbe748fe337e301ee9ffd1b7de24b90f815bbcff5ab6d1d730f4795446a5c5655fa4e99554fc9e461d9d88c26492b28d94c7bb32e5f99ca567705536b7c3530f3bd4c0db0eb984d15a110417247caadce1afd28cfa5cf9f7998459ae4461637aa5db978db1bb15187bd7606276d720be8a4a421f0b4fe049c0decf60c5cfaf3afecefc431ed8498ced36c88b20f417e4ff5a5b871df26e7918ddd44edfd04caff5870e0591cad7d085102dba0a880fc0b456535211cfba89a5b45fcc58d6d996a32e39488821b7834ca4ed81e4fa77b37a9fde7f4309531fae3988e0fe2c2c5cd390acb4232480b20896bb5a136b66b95c2728474d91acde95dc61b86f18d719f183aa1b47aaea4f9d7ab9ca0099f3496c79b203edc277b76a00e99d287aff8ee2cccf5da4725643f97f0aa6c9658c4a2deef1c5e09278080e035343632e3212f72d82e09d672463a3471af578c7da9aef1c727238626c8c76aac5544626fdab7fb15b620865db86cdbf3718c076dad60779186f13f334a0546ba457e5b33b96c575aadd2455139b911c3e69a14dcfd8c85ac63f1f9159c2825cd8ec8ce9c7eca54c3dbc8c37128867508e0b410030444cc0d6acc1e9ffdcf3288889710dbd95524333be72257d2dc79af0eefc4d0961ac720640af06e1d15f5da49664ab3eb1ba68c5767794e9a79f595f70626365a47f4e53d31229158270ff4b9a3ba2611a4a53fb739c87c7e4f9ef88b6d5ed6eed8d11d345756c867e37e342b48170236f9fdb11c4aa49d534daec9cba8bbf1b0a7fee6c1673175ac2677c4cf1604a8adc2c6d37df26f102ecb2b9f9b7a493767f81eea07fb60e319a5d2c5c239994952e56974900798cc2335de0790dcf706e18a563942aa04f32d869a97f9a6a30904a71164ede9a33f75e5d47b94e49ab6931092e982fc2635b83ed8e085cdaabe697bc26ef3611f894c97dd410ddd45d41f5144360c1a96b332a583f47e75ad4afb74ac27ae97bc0a1f05a1a780d0a0041f9416a1c5631562c34e0859d5e973400c9d5acfaed302364f11e65c47448bae7271dbc36c00c494614218f04585fff089d0914b3840939817972bf6740b7e6e53be78ba98d50aa469a965f0e8fd33857f5aa2ab731a7ca7a8eb4f000443eb6e436057debed8441c8dce197de6e9e32c646fda78feebcd0fb5d0ea4471f5dacda99f20e89657a6af993a5320979ab45b807b9f756197850d419b5c816662519ebae7fbd17c3893e753cc8eec9d7fc3910b8ee0277b78ae08eaa4dce23a64139dd9800a173e047d447664ff81f5689b164590af784e6e4859993683b747602a816d49b34405487ff12ceff7fe7ac0990ba49130295177d1678f783867ddb593e55fb3f49dbd7d7092078296852fa9c9f02d1d399250fae993c1eb51d32df789e75590657d25ae633ec882c896829f861375a8139b824775b8bbeafe72ce20a7b55a8d187cca8a8554b4a8c314c8c4d8cbe8124a7ff4d63a0ae11ad6806e9cbdc4b8c2c824579960b7c49a4b6bb3cbe18b28c9e64909ce50fd5d9d1744a44e016b0433b66ebb5eaeff9fac286d71d80f04c8e78b898b818cab7dbd2b701045d2cdcee907e3171408318fe0a4a5f86fda1fce6398b78854598e287bc0594402fa56773ad8cf53b839c84bdce861a20efa67aa3ea38ed601687f9a9050818b3aee87e22355e62bc5978979c98df3a7418e468d7ff33b15114e838db3b39b0f5e6bc83a774b84210a2642b9c56c8691e2796f7d0bd72c72035ba327ff33f220380d6a39cc1a0322e8c2bb5a843f6411652f4792f7c15f4c0d4cf87c484a89fe45eead455cd2dbc792a2c840e3be5278feb93a988c6426ff56529b0185520443f2c21aa5f6dc4c03f96d6d30d778fb9dcd685ee6e3ca5eeb0c05d300806dfd7ac94fda5118e115d2df3f8bb8bdf3e198a06d5e876b202d391ebe92a633fcfe2f8315d6ebb2c27a9cb7de232ee7cb12069ace3f58fac8a7ad8c628ce28a757151b9b690fe70ca8fbec03c0212c91e96a1efed549d46e379edc255b66e097acc473662d079c393f00177c80c0528240eb19e74378526eabab965d5e2f433191d0fb7eb3e3bb8c1ae32c8ed2ceb8ddbda24f8f06a8e64a2cf1fde2c1044a7f6d55d5cddbc8208a39f08f9d712aa40aa1d8223e3a42d866d8bb8925fe37291285d4aa71b83dc4072bdaaaf9f02fe833310014c050808a24e70830b6d0014fe3750dfe78515bf135bdd47af71258ecaf59cbb3dc147f55cc13274e8c959bc594a8394b690dcc1d98f564058f2ecf0097beada116507d9062394eb45164dcbec53137ca226043809bc44b9477137c99e79d483a523e60d29e35134cca5f589b5b1f1d5e49c971fc2e5ff224b53e0f19745d39c93f212447ef0fd0fa70856c1fcf86dec2c4583ec2943566353fdcc139ad4b87e4b4942f87f74f353bac1c9097818dc6796feaf1829bfadaa7dd07cf6b2ec95c0acd49f26a03616caf2a8ec2b1d44d8891b6846965cf0d7e6b08012c4d2b98ef86ad9c30380d023ee096fc749b94712ead24e2fa2e78600b3ad4ff5bf3451604c9a9c44513a1c18c665da883a5adfa8ac42d445c6572e30bf63324b94052342c671c1702e9ccd0da5abd1c77017414832ef16f636015a653268507f0e8fd186b83e4aeec1da71280b31393ce0f5a776cd8ac1d221ecae60617fcc3a36c53839043df0d5d94391f96c567b9659e94415f7c229518ff2f675eec0c97090146355e02f67ff5c42ed2b29dfc541b3e6fefed4d124031706b319a36999afb787740af4cdaa1da253bc3cd2e463d603b059dff4b5c6310a876b0260fa40d65300ca194bb590d599391a7e049e76b10e62b21b5ce6a83b4e92682b25dc6ec68f7ecf1e69d8e1db07d3837d45df27452cf4d6c26903450b352718f4d3ed7adad608c377c1f53e6414a3282d43f78b348c496d8603e762b909fcaefbc8193cf277041082cb9dd36b8810ff8221d956de5e0ced5635bfd261bc4c32de67fe1648f2b5d1e01784a288df133c2f8a803718bea3160b207f9b11c5dfa9981dbedf7fbdecaf5117b65760708045f8fc1e54d54f53c37995a367e3a578c876086c96bda438c9a8daad35ce5e8def882bfdf0a0d65cda63a7a9e3ea7fc91a45dd02ca9614263e6ac1f62d28c70922b81fcd98a5a966ea56beadf4ecd25aa5a2edc6f8a92ded720d8e062077db026fb845b08bbbfc9da7f6ac48eac5118b654cea44262e53db291d0cf4b7d4925e7115372aaf4164bb86d1fc5e52690984c74b055b384a91405ef626e79532917f8e26c63a4e8882372bd6c27eb747a2a3d1c17845b7ed826d2984947e8a299d718cc274e6c1bd530f14853656220b508c0dfe96e4cee284a60d183fea3b5c8d39eb0615e067633376acd5852fd447781aa5a288a5ae2347152a1830d72c5ce1f267157166cc33fc0ac5150b00db8f030ea63e51e1ca1cc1fbdef61fda793f29394d3a8053f04bfb2f182aa9060273b76a129e232687f2d42d00a3b9dc67c28c10d1c561c428aaf2e21bb290d66f7d73add81ff98cedd69f34875c84f30d4eb48dc3b882be8965db6c23b246cefa9c94c36c52c4979b464bb4592e422b121bc84f904acc48a04870d42e6894a12eb78b849b6ad26c4d637b8f870b25360542e143563efbb2adf39e8001c1b958ab1a04ec186a1c5748fab6d3bbbdd15bfd36300bb986044caded761067f841a31a4e95ffe9caccc1fbf0d51b83945a29ff1daa8d2d57630c7976e9ee730c5b2441330513e5fd21b234a5e9b65e36b256c3939d1de2730fc4c2a273d702e13dd3f8584d47ed692a730c82f5ccfaa8acf077b722ba2fdaa5c246b2209e897da9972c4a54b7a49e3a14eaa592a2ddcc9e70a8a7a8121a1ceb33d22dd0ffcfb7cfd76688b1ffdf6ee63abd623d30854266cb534fcd420a578437282a37a1deb3ab51f63c4c600f011be09f4ab3840caad041f87a033cb958cd4fa0307c8e33ae224fc85d8d332051324d2fb277874e1e17998ad1338843bc0160c31fcaf90c4fe87df89a48f14882f797e54c9a62702c8750d5051b631810ff0c01a05867c02346adcfe2c446db28c0d07e5dec99dbb508bfa0838d914ba1bf69b79c9b5eaaf46db732b57f315cedb1a050059c2e94a1b337bf7c64fd07df43ca7933827b6dc9fde538b53c3e8b8f579db106a743deaf31592b4697222f6b64d19210bd832207002690366c68291e641fb7c9f0877601de2d1590290ec3bfd8bb2e433f3c94416890e5bbff624c8e256d636994b5a3d1813e4334eb8f4f221333b1772dd15d280554c188fdd75063581362107d59d470dea5f3616be025b41ae8d00130f3b3357d6e7d5d9571cd6b801982fbdbc12b2f29aab5b9b7085a223629767c97e0f21d1040ada264f0c6a6e4cbe9690d2dfa58a52dbeba0db545a8a023adfc720923cd1b616bd0f60e7e3a9c3d08cd070faae9e7fbf5d7b8bfe0fd8c3212367db7fdfc9b635e986cf138900acf395188292be5dc88e6bd158eb637d8473ce8e750e49a4cabb6635d31da466a3b253192f633bd7125210d1fbd266c6c3d93701f888152ee1645481177d9981fe4b404f977004f6771c92049755d9d629eab760421137ddb63b778157924930bd5d239c2ae90fb5fdb8c8015a788cc45dc61a207ed4605d28a7cbd00caa8b97cd3b62a0e2278a76ea2b3d5bd41a774f659e196130fd4539ae8ff20fecc5b24a20bbd39ed7cdd08348116446ddaae9acdc320de58f63397b29c77199fc60f42f31ea467522ed446f4596b9917e27135bb7b73d1c5851aec57f763568d86b1f1340ff6acab7a45bb9c746a7f2a2f3faae60e4a598d37f45088d9d1250599fb0fbf68e45d2cfb28eb02215879ff74cec3b38f3741f64f03611ff7fc17b1c49c02ccfea56f2dbd13185c8d77f42a943ff5ee2fabe4e616d722ccf66314e8da191b67cd16c04aa94d19eae82c40d0c3f2e13ead51245e9fa9447380c597ea4bf26e90ed235e59ac2f783c681d21fe057b79e4bb3899fa72182892431c3c66dd3207b178d0d3a973123da3b69bbb2e73da6bb8d71a86fd501cd58ad5c72cf56e9c26387ec3271306cae768e920dd88eae06049d360015dc9719a0b91132bc0f55a005320fde40505bf18912817346ada67f36424907d7b6d950958bec05944a9b55bc93908a3cf1a9ae8d709ac366def39d29657c959d6a72b2cd1c57277d3b8340fcb9bb9745a0f003278ac104346eb655e60591b0e341d57828343b3fb6b8ba2ae24153cbdac528861fa30bd9b54c7d1035ddb4b280fce1a8a069d9224753cc449decb3148c111ea658601b59165f6374b010dbd343703e4a6cc5c8efba4ac7f420511b9150d13af80184bd1f371b64bc15e289268faef39b5eb7825dcda6326897dbdd9c6f37a3d5653b6613a37af51e5b74d27ae8b344baf8f47347227f201af58403ad59f68aeed8c9e3e1662a2bf2d0bb567fa22814cbe36b533ec64cb055122962d8725cf132aefda54f8ee290a51e53922e39abbf1df0439acedaec5031ecae048cbbe4a291044911f5b7097f98891f08ab729086e6fc4f9142dba686732db6f2b3044e4fa327284a1845fece6f59ef2ecca89b8d5000b2b1b21cfc690b557a54c6f1514d85fbccf269e8eeae79c4c2fa9d33965f46934324a1cc97c648cba1d5f6befe5dd06b45538689f146e28543b41c5c9b2de6000000005a83e68d4f50adec31a352dde617fa8ff70e9028362d2f20a9b1e9ba99a4ef0e0a8d6edbf3799ce086584ec56e2c3d9f8819e40bd62d4fe38e0295f2761f8e55d4da91ea2d2130a4b5b88ec92108b8b02b2967b1c68e4c467c8e3b65880f1dfc3b4fa3c1883401b6bd771d0147874f16d3635ec192c5990486ab3604f9b754229c837a959aa1847e50c6e05332d252e8f8b92e3db1d8b43a71a61c01e485ba1c7 + +pk = 000000010000000500000001b36459ada3fda491d658ab3eb3746402365eff2d5dc9a06584f35229d860137b855cf7759157d382db8a687384089567 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W2.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W2.rsp new file mode 100644 index 0000000000..436baba31e --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W2.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000002150417e62d167e4676733e92d1394e814545ed6b9b5bcdb5abfe12ef0d5e14f418017877e0ae217554001f178e1fbb78c6517a7b91a4768e2133c5c0ffc3541c1c957502a004405cb29dc9f86b37da393939e10c6050fc178853f99a31f96dee2893a203398e3cb632d761c2552e0f181eb568ce5984b89658da394dd4138df820dc6974ab9baae3253756c4c90e329464b5663e5b4cd00ec4efd4e3d4224b2fd0d0c6e0241fa222e9ca3057d903c958a9e3bba381d3b3e91406f34f368be3f40f09a4d7ae479944113e69709ea4a8eb3a0dc3c02b49822f35deaa94bf1d98335bb0a10966eaa9fc19167d9d07956f1e2cb1eeaa6ce5ef1d1860824911d8d151aa133eaa0974823d9b0ebc6218b5f1d3d39560832c303c99fa3a73f4a5c983cf80937cc18788a162e025515213225f357dcd2e2d8a9411fd4abb915892461db7d02e15c4b7f774837ca87d764d2f07e8c437465c53152691e39c65e7c6649e83ddb3568e2e31c661c649ba174f9829351817456b4e527ef6e2db153033becc31af7ffb1ec040d7f4f6ccfad654a34d7041a854cddcb8ab905356d37e4332f5632aef346eae7a49d6d3f465d3a918a532e4efe3f458bc3c2a17200e18e71bd05730f44d1d3b9490fec0e4a52d532bc987c7f29b0c4d1a1375b302a48476645f6f9d938ed7c4b9d874b496488439a299e9108be95b2c695e5049e739a9a3d14684d88b064884ea5438f2e009c0126509541457c87a3f06af3c75da61373ecda9a693b980113b22c34ba15c95696388c2e66d90b2fbb800a97a1b96b31a954e411229bbd86cac0fe668990a9c15c6181f847f2a1db288e995257b2c525e049609ee143555eb36649e119c0f427c998ffb45592ea6faffeff2a9e498428b09b6f1d3fc3a0c8b62a749c51b279be712be38f7b323455b50ac4e325703cf564025e2aa1e5876dd56a7be2ccb920dd22e475be7db8b3ff442711e9d0f3b392eda27da8a34cae12cd4f99fa17d8364d5a2a1303e996621b649a6d7105343b0a5af6dd65f2b1f13d8f36545eb65b99b8b6db5f022bc702e8bd2a1ddbc99b64a291affd1e2adcf8a01e9dd9c117e80e32f874beea046b56b44ee8cc2240d03de68c90d9f4d67e5f3aea949cf6f47d5356a6232e979329c10422193f206c74cbe2d06d290d40fb0ffcf2bafbca374a7c327006cb1b21608af282955d3259a4f4b845ac2d9b386be83e96eeda3a84a64810ae3c81b709fef15078424298917b2697d2bdd3e7f4d365b9a84bbab07c0be4d0929be663a06345d1a67360141c03c3f37891f09c24776177e34a9093fa62005187511268fb2fa80740cb751f5e9fd0d74b0f61b643d139f8ccd040c9a9a32cc740b825a2e6a5beb28a8915fbbb1bcd41c9694fcc72ed570b1e96cafaedde8adf8d5028f80eead64f9407e57ff5465da3e5e341e587cbf091f2f5bab89e95666a3fb7158718afcf685df10ea4a22ae7fe55c8f70d5d5a5973f3dde9c80f2a9eb13d58ca3485268f6e380464892f4c3c3598c81fc3d77d1ce0d3d9f50c78be78b88f6a9e17d6ec4ad9e6a86edbd5a4e5e17219fde097f422498c171ec1d0f6dbb6a2a49d34a66ae854e2650fa4a6c2833af5106472e7c787ef2da06f28f84f0f1197c7b4c4cff6ab3ceaac5ee819809ef20ee9b535252c23117da43e31ce778abfd84bf647875573217cc79c088f91ab07adc4c930a4819b936a98834ba2f9b034996d26bff2cc901317536b5481431656c083780d774b686ac5b0abd7ae2e05981c39726e6efb4ea2507b20e85cffecac815d6d9f84fa86240e6ded4dcaa67a2e2f944ac6d38f986b7268f2c240d8f5eafc0b2b67dfc11992e305e64264e19e021fd29b72dea8be8c315e3aa5f02c49fb9e77a34c48c58a28c4340ffaa7fb5b5d0c8a4aa4abd7bbf3955a0b71cbff160c5dd9a6a4ddefdf00367f414dad1c7ec0f77c1a777ec1c726a1049a2c4bc01554b95665496584cb13b28dafd7c668baa7d0c1e425e5c8cef9f75f21819a5708db01e5a5918df096424abcea2d758d4a8c5fbd96e10ba91bef727bcc47930bd45bc7d6851b21c7daf94c016e8cd10498f18ea44c6474d865a8841800dd19fe3d57611660c3729b5c2a2f1d1765a1237db7b97bcb6af56f79f275677bfee3c37fb1a0d7c2b453feea1f7adc60892a95a7e00421b4fa320ea25119fbd6af73d9049c8e109e2b1b683f5bf83933d63bd552f65fbfb806f346db3592e244acc0878c450962956f4e47bb0bced88d1ee0d18f93acdaf6bff6e6d9b451db35755c1bbb547dc4e098012823874546757f5aa94cd0bd294709da538e8c8675e96d47269451bb63d35b6f027d68aa0871b23114553e883463512890d489286886a93227ad5ba80c53f0bb4d383f15f607091a3ddf07cb199a7d8abee54097371c8ae59b354a8f86765288dc635e4f5a3f1bed2f0998f0562755035f39a4fb0f69618ebdbc3427f1fec8d1040aef11da99c0d3f0864615b1283fb2f9e66b957cf666ae08b2e11fc9153dd32b5fc43736758f65d896d253dbe16d7b16db56130851b7a0935d92d33fa75affb9d509ee73c40c9b61359ff814267e962d4aa80f6fb0ddb76dd4cbaf49fe65ad51b406a2f33bbf698a6dde309a7d7ce95f7c68ee5bccd1631f1443f0b1e823af31b2245095afdf073708fa9afa0c3b1c4606d5428cfbe3799003437b74b136b1d0d2f80848a1e5ab14fe7e9ffe02a09e21bd5d9c4eb0607bb5549f0399c2336cbc76a6e55c7f80fc0ee968c696beaa803fb020438a9ca6c89ef1e8823801e91c1cd7cbacf09c79f128f22f29c9d49355ecfe470b8df5edf9a47bdc781a3ff0ae8e5596e13bc06c610bab6121f85d54ef764e6a82a290a4ac3db0f76820d986ffeb5f19460db6246b59aa659afe6753093998876cb961b07fac8b0c0896d0931bc5843c4f545263a950523b7ad8520654564e27d0661f1cbe60812ad232b458ca36c6439750ed12df2f5d89b12f584e0023a2b8fa39c2a13da2b7497a968189f183f65bb37c5999fd6187f9979f39ec459271d67676ae157271b24ac7b3d3876840c48296096ee2730e14adb8af5ae11666d02e441f83c859aad9657c1216a9c8116d660abfb5e061f2face2f11088e661ab2046b969e72c3d23c6410c951ad210572e3cbddba77c5fb81c7594e60e1a4784d3d606b254a49f05521a0289dd14687cf8efb78a2eef2211e6021aa14f2a3d2a5a0d5013282591239e7df7991e3f44442b544e14ae382181f0790d4901b30f659f0cf9b3080a113d2bf869e44149667438b194bca40f1ce542ef7021222e0d6b7bcf40b8631e9a23b87dc1b97cd6eea407d3f7149e250c70a021b3614b5f68c065eccba5ac481fc4435f2da541a1e368d69259bc179338e641b9b14e77abe6762ae8db9a980061c85f49aa161aa92851f6f1e6a38152edac3f121326e517215cfab5746db3e026ffa2b5b4ea41d297bc4bf91f1d07c866b21425e022f0081c7284fa81c0b6b43bea2ce4d61b910aaa539b5485b79f0f766bc704eba870b33855a589ddf7525cbc07c828cf51e687f6d804e4d43535820171d38a67a8025486f0594872c996768b56177a916b13bdf622ea4d05ac608bd1f9220420733fabcbee129a4e89b243bfb4cb7cafebdbd37b1b505014ac3b9419bb51e274f8aa81f82725693341424df75c08ff6acdf622fea4988d0925ffb33466489331b00dc3432d19dddf30fd64194d4523dd3cafef94bacaf6c72b68665d1731edc8c2e9933d9302c61d576160c3c98a9fa393aa60a843238acc975f5af75532b5088a06299dfe395bf4ffdd4ba2c96ca3c7536c6986d34bdf61e01004e537748f427a7cff650918ec3c0916cdc7ba3037d078c1f96d1d77ec7560d1fa3a55443a8b2876c882a7ae2ddfeb611af3806be2f02e39a82e734728348bd90394b732da8798ea1552925e36a8ae92697bca66ec1cc4f6c2d0d60348f81f74ddae919516cb53455e4642f0782acd678e0f2daf973f866ff0f5576517038ffc52301bc53624eee8cacd1d9fdc4c74bf2afd75bd3d0c7a8010ab8d082e6edba64106cff64b5a9ac166f02b906b9b84539361a68703e43c74439306382964d3f2245a1cb9699b9aafe48922dcfec3515cf9d737d72888562b4830e5a80594ea437556ca1c7921629438c620a439196d194a862dba078524bbfd801d2cb33cd500957b84719352baae64d8163ff85cf8236c509ba495633d4972ba8094d1e293b07f7693bc939ffcf4e3979c1f077e48b6a7b2666360759b82adffc811635b860062fe55d70b1397d6dbebe2f73e722fcb90af4d98a55d4043edea799954e8950e7f6744a1e3a98b2fd48f2ff685208c8ad85becaac5ae51e187e75beaf6589773d23367379a6b46082761f247d79341d9498d210a206424d07bb88fe5018a302f4bbdb2d0ceafd4b25603fce716eddbd18ba669fd0a18c93112082b2941924ba80c5a50efaf1f391e6e0d7d6e27cc991c29f4065d75be997762e4032b62bba80be85d4c8ec05ebf54354ebed5c32ffc47caf0e7c703c38559f125521ba736225d9284e33fbab9d32ad54e3ddce4a79a6a0adb2fcd15c57281a9f150a38d8fc96a27c751a888daa65c4461b54efaf2dd2e0d3b5a6ac12027e3b9721f6bb1a32239824faf8574574845a4d649820b1a003cbe2b3e6466f47062356432d3280edc53b1c4fffc63de4fac290e4525c151ce05314c8a8b0c744acd5768936f93a7421eea8e69522ad6d188f71f4b285a535d84ca72c965bc4e40f03b09703d534b6de536b2da8bb36704ee930f1252fbaab91d5974a9d89e1411c5662d65328334a3982c31d4d0588000204acb1f5fc359302d931d8844dbf24201483041dde064ac06dc020768f40039ab61e8a4b893a1a782a49632e38d5a70120aa4ae391d69c9fe11aff5c3f4fc55153ecf9bab047e130e4585e5de2fb875ae4841d21abc580a945e4738674ee2423a237e9f03edd0bf5e395760d5ffffa1645846019fac8a58ca6741a221ea52c0c3020ca6590a7633388da3daed3ea8425ad3671f235420b00ccdaa006a0cee192855a6d8f6cc17794c4bb1da3c6d1b3b2269572bc2f9d93ba886fe30cdcdd2f105536472a580d0e9ccbaf9d2bd091cd33a2243c816da0fd4a3e8f1c01657dc236ea26cb83e05f1c6c184d9c0391535307cb945f80f9329800b39dcbb10e1ba5d13185a3050772d694429e17426136db817cffe563a77703666f1dc827d81790bcc4e9ceba15c34a28c420b6cc7df34cea563d48e9fd20a208497e0cb5a02eb25c3f67095f3f3a63d62d06ad7953ebfddbfddbb613c676394ed866622ba3323d6b1ae1b1324aa41e99170ee1e66560fa78b74051fb172f9b82e53a02be5859ca2d59a133551b7f1cfde0ec524b4fb4aefa69df632a385db308044922dce6258d71b36b14cb481e82928fafc56111ebd5969a3588ecab557b8c15654cbd559f0792b6caed5413d750867d00ef53aa597949fdb837c468c41bdeb081aae58040a50172cbf3d075a9263f4ad7da16062e80e5fe39da2e05366b79a148ae181c465aae82ecec18e98f696649bca24931a702c338f25bb2d135b95bddea4f9f92a2f925f31ee784f195d29eb4003a5b9a21cda79c6a35a579a470bdfa05ce3ed9c2a693ec92ac559691cdf22e5b074c479f58ef2395781369738f7de2c13de64090dc6575920c28a2c5164c8266e9dee906ef55c69c73fc932a64549470fcfe4da13bda91672870957d0cc002998510826d6452f7b400d09c47925eb3e4bb8f53bbd3f657d2afcd7eecc992966bb1ea7774ed15d22d931dacd5bd45993151ce89e173548d0d9324ef74be4c0cb89a1d824f1eb164821249116274a536b1b760846a4f6d1426f946d338ef04f06494a8ad0e3a59fc2269cbd411b0106e8b1245dcc3814ccf330790dd352e68a675736119d839155378f573524f5071487329e2b30405d2b0f07ad82cf2a7a3514821356f126349668f35350f3f3b71045bf60f1f608da2ebb1b067f0e9b673a1e6bf221eee8aaaae8000000051c142d7004cafdc21431a71b81e6ddc44a8ab75a3a2c8fa3a9a8cc4a781d9079063f7a97bf683473a44e5ec3877cb60d400f6a6d8a3e4fdcb02f51160f6d828ea4358ff1f2fdeb78042387d9cf0452ad8653f511d53435401a55c32b0c03a76b0edfec3b1fcb0b864da0ef3663930feab4e318cb7c271ac7b0ee8f7fa2c67838b293d94a7bddb92e05b5810f88ac6eea3182bbe37704a0190fd4658e268be368 + +pk = 000000010000000500000002ad412ccdb2962114e64225d1add892b4adf8f6b43057169755d96b6ebc59eaa37904fb719e358e6759f598593ea69f7f + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W4.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W4.rsp new file mode 100644 index 0000000000..222fdfcdab --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W4.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000003aeb14a03f55d830d64ab4981809d932f48f8371887e4b52188d67e9e77d296b7699c4267b07320535a32b9fda668fe4d64e126e1190851de8400a1eb29b6251778dbf3fb6e6c2d4ed9cd306501ff53e4b3e2e6338d8107537ba3bfd14ce795cf8f939e9ea6add97df60ae591800014cac041bb38857d29a479ece3289240b926b02e7079af6ce0bd239fd9c9c55880c7c68d527abc9210cba38903c561130e1cf88e75ac230a1ba6591edf39142739e8cd16d5c744d49c6dc9318927b3f6a2f44139131b5a29635a80e5e4ebde27570727e9fcd9aa18c7e45293f67c0a179a7a159574908c1a43de083e69aead0dfe6ae356367da1de7bc4007b45483f3863b045a047ccad8a88c16ebf45aa2e76a40a5806225bfefcfce1687602b204efd87385308a2a4d4e0378714ce5bd12341b1a71e8d155b2cb2e08616d5280c418d355987cffad11b65e2032371a211269943baa66907285e4968fb4bfb271230809365dbcb8fece0e66a6c23ae94a4a91ad6cebea8c2ed848ac76fd43935db8382731ad2188f556519b87efad901b656f8c5b533a772cdb1f59b2afadf46ea3cacb9eff1eff51ef73cb414da18f188880a67d6a2dc70c4aafda7d2d65ccb3e870033c3ccd2e16116b4f685ee45194cb8ff4415768a22ae5189ebd2f5d2a0bb796890b85a01979536d5ca3ea77994cfd530bf95a039a7ce635a6db922baa997a6c26ef45e12018b58cd2cbc7b3b3d0d2938b28ae7d0779369e0f8889c36ad3a20e6cac70268428eb43fc660d6a2a293762aef9df55e5873304141ec87a96ce4d6a7e20fe69d66a70e872c4f037f32b5317f51a602196c8e443ed0cf80bc2b7104b2b5211cffd650cba2de1777268b1e015556e55f3e4400e61abcff383541594947f4ca2394ad26c43d3301264d05cae9a38d4c70b7b6edf50368f2e30842bd619387961c258abf34181b0e662af0db9ddd8e444116e28d1959c4e56f5e32322d51b772f6f994e971c49869ced203936f76731787fa6e8d13dfc533103ca0c3cea5d8c27d8b3b05f9ac81b30b9ec947cf39299972214b6e058f3fcf58ed982efb02bd1cdb6199264183c82853ae04cac67f6d2baa37f725dc77f08534273e8cf070e9383d8f4ebdc44bb2f4a48a8aa9ad9b8c6ccd1a718fd9ad8716aece437630a5294ae83898d44392444bd7d26fa0705fc37f384b9b09b94ef0ffab639b9d01758d286a8ae14c933e746459c64dc31d609716e928469e38b36e563ef68e3644a7200a262b1688fd8e4363b57d42a64d0866e19501ec91d83707067fd37e1a3b42453e75afa9739e73030180ad38b687230b6bc8ba02ec2bc300a87828a1de3a8cab63fb26d30099f960dd82b7cc65923b0dc380d3513cf0c74e671e50ba668b8b0497919e260cd8c2755de8ae3455ab3dc3c378a789b8c84dd6ee8641a4feb06ac3d8dd80093e744ca7f44e1a3bd0e1d05870841e13a6744530cf89b887085cf8031c1c713d9167d9e1ad5d5e7c5d6ecce0830863f846d423dd76a91be60aff65a72f16e71173609a46f3bbd33f46d8d1928fe620a646bba75325dda0e8dbf1f95ca9bc02e891889e6b3009cbc944b9aab65fa30cce224ec1856abf23556ac570f43396c61cab7f458d5ff1fe7f83c0764e78fa0f9f9d75fa9e0c518379a3ca746205fe03751231ba269e19b579b90b1da30d8b6315ed7a4e54ae88fbcdb15a8fbf24fee6d9f7b95dceb99d330b449f05a53974118989ca9ac1bcdddad5a43b882db01cd27d72236c0d060b2b6120ecd7053820a5cfa84dc672fc2c310067cffd3f5a8c3bca13077fc1d44e99c111d4f95cd68d74bf827849277ccd7245166950beb19f33297a00838ca21b896073878f2b509bedc6d6ae8295dbe1a059cf3ebcf40e7790e0530dcb66159a8c0e0fdde36f1b6374e42eb331b92bfa9061c6f480bb64e73c539eda7ef879730904d5843ea1c5616798adbe21d6c5fc4efebb60c45ccb30b7b1fbe673e754717ac71f5ca272dfffd2aca2eb8cb885c8a8395800f70c90271aba676239abb86c0708301bbf643028e55b9dfcbd338f2e22f5cee5c4d0fa163488a06fab8f15337dc219292f53325f98a4ce0f3f931b2961483d165a97e19d9d1408a156c7d35eab47fa5edf71dcf862e68a37787a1203c35383047398b3f305e1d4fe19d8dddbeb07990c507e8d80b6992c5c996c14b7cd31f65006585dd6bdc7fe43a893e96e06daecbcde583759f8138b3461341ec115ff29f1ed2eb72ff45d29e674dbc27165c9c2ba212455264936a9b8615ec5fd6cc26390dc45e1bfdb9815c8026ab9744af6eedfef8d2b2e73adcc50c52593ae3750dbc880c19dd627f215a49b044f87f866098c14e2716a055819ed0314ce687193cddc15773a220c1204b81dbf11087019ef723f0e14131f638cce5224bc1c73626a2811fec0becf91b6e39674c16c31407289222bb02eeca5ccb6a195c8c594d5ec984ac7fa1cc266f40dc4c6ca0724a94da0e1c8ac89ae52ab5c35ab2dfab88d9899336b19b099a71d0564f31ecfce6c582446a37e4acd62c62902afe83d01b977d61b31e4d03efeef17e381891c5e96a1043da0421eafacb98358ec2e98986762add3036aa1a1dd9f3235dd9a6f991e935d44337a265755aec34e819175e140b51079662ab5905073e588c785647444c4a3484c7f5643056b49e4fd0927cbfdab1b4c3101484c20a673b5322fafba8525d8c76f05e2cf522f1bd9955b86ebff690c02bbe96f73247396f50829f12ab26d21f082af26fb68cf7c4edd47602955a72eb29fe18a22131a8ec9b33936e816da6ecbc78b83e7656796dd756eb408a462df7830a67371d088b4e3aa15d4f56412cc1147338ca3fbd759ec61c2069d58ef9e84fd436eadaf2f8a955bf86c1d336830e9e8e8ae5374827cd801f0fd92dfe10043e8e1776c6ecd0cb7b9e0bfb6e326e8eb0224203575ec16007008dd284836dc7b4425fd39048d3cd2df1ef4fe18d6499abcd55d38d44c70852557ce09c3e3f45234cfa94f417600886b9b8a946a24ddeb19726c8b0a0b1a41be57b203c310f558daa000000050233c68da9d372a5a75790fd99589f6cb07f2c9cf97325a28c59bac5ec87e8eac10877a29091357b9b12611d2ad4b6ebb92f2a92cd0efd4a80eba5fec0eb6f95d1d9ddfe0b6e9eadb2420921ab517eba102bb8fa0402cf463d7b7d3122e161a5b18959390a8a38d08706f1ee4c2a7cdbbf95a642133e504791cb5516e1ccf2915cdc752a2a6cc023632112bf44115a1d97fce39359885b203307721151e4574c + +pk = 0000000100000005000000034cadc1a52afbdd1adb775d499fa9defb5f95bfa52fa746594f3311b8fb9c837b15412323da079146956b63e0a30c423c + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8.rsp new file mode 100644 index 0000000000..709a37263d --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e2e0a0a + +sm = 000000000000000000000004c15445cdb0955e650d038fe369128bb41dec49c85cd58208337d27a63c4c4c613fa669e360606b31f1bcbcef9540a8babe0fb27755ca9e444cc7e3b2de51f4f63b9fad23b7a334003a45ce9919f223efa24d1e24ccd6b7d46f645834ae72cdd32484d1db569f8ed1b784ee2aaca9645e3fb7b0c68c1c8d22812b6903176e4475f307e0fad497f2134462d94f51c63e1e29defaad7bdaf03e49da1ea7086c064b3e536c01c4cc435d5be073cea199da5e6d1c3fd3a9f6d5b32f5ae2d974f07dfef21994f9e33999dfc0d3074aa8bf41c73d1b2f106ec5624badbb6521a3d21bb59fa5c28e8f02788975290248ad126ccec0639da4b0eb2e1a09be522dbadac2fdf2643c4cf2f905a55e7181542ce391f9ec6e3023fb3f015a52358be92385d6fb2c5ea84ed630622c872fcfcfab61e90b94b0307b31fab6df36c43c3d8907ff7842573d998b4e66f629d37681700c8f8d0c4da8ff8ab6e20348e817ba9e818de076ebd99d0b8ce672c12459b5955dd714b40a93210050bf54c8bbaf22840c2d007cd1f40a000cc55c745cfd3316205731818b93cfb51045369a4ee88cbce94b77544e64861d62dd10e711795d6fe3d4ad1517ead72967403c1a6a308bf834d224da53c2f89528c480bf294ca41e9018f129c0ba6316ea18fdd6e9d80e0593333c668432cf8a9505659fb63fe309b5ef348bef9e19fbecc33af91790b1c4531a85cad51af236ce5efdcbd77212fc0b642dcb91f7719e49a38ddd5afad688ed9ce5fb48d98f5e2c08f06d743d92b005e4d013e4474703f8c8f5b085f4f479896191f8fc9e9d6fd8b9c529ce2a7e8d1fcf614078366943deb263455843a31d16be42aa8551185315c705e90afaf25a06e93a7c7ea6696cf6f3cb496c674e3366e1fd6c1280a83900d5e62de9757e3383feb324728b32a496b97f6356f30ab160611ea04abc38b21cc7553901599ea4c590f9a4082e6341a9c323ea5dbf0f93180ef5bec182694c44e3360cc4ba3be21aed6958da7a6d8a75bbd84e24b40d88a2cd477e319933ad193b3072a987915edd7404e67d67759b31bfca09c6863e3230ff1e8731d1d8611bcdf31d5c5e272f674eff68b25933555feb2356b7639b7147961e3d8405e42f01bd6710bf64e896658d3532a78f67dd99d047060e107e084141ab06ba38124224861d6ff5e356bb43f90ca37b7b119ee2a06665b1c9f5d913853cc27f20b539727957ff17c07de0b9754d49f3ea1ea6da022112015e82a477e719aebb35e4c7e680dce407e3919832143ae3898ee14cf91ceb150341ebf5f767d2e1581c41751b8ddee365491e69d4c3c9ac548d60b8105b6b6afef80be691f1a766c59ad94ddee2ac824e26a3341b4409050486fbc94a1d95488446fd58595465204a0b7baeb3654c85ad124a6a42d6bb134e2bb9231a9f073afdfdb9fc6f114a99d08a685587475567cc68df54376fd13acab6b83b06628715e5ebc69938154c9e7c14c7cae80f78ccd41a8d07f2a65c09f5be027cd8fae674059b48d9d720250fc35160dfbcf520f89cce57af12415ea14996e85c6eaecef30319642839d4ce000000052c26f6dbb703f8711854e896635d51cec418c2c01df5fa5067c3a3ec08b30d042f4a08bb5dd156f17039c6eb9cbea8cdfbf46e64c6e345edc8aff2dcc7ad2ad911f2fca9853978b696cab99a0d633873e5f36f7e3faae37e24f8a27451604e9aca4a6d3549035e7a4e4527fead4920e658bd66d06509eda1841f843720016117ef0a66c52e26a12b719480cdb6055127a1601bb7110772341f1202e54ac90824 + +pk = 00000001000000050000000467bf07c0d0e24981d1b189ccad1efab150d6409b74d36699f982f537969d785c7bc406d1803ccca5905e8e9c0aca1113 + diff --git a/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8_H5_W8.rsp b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8_H5_W8.rsp new file mode 100644 index 0000000000..57f2155e3e --- /dev/null +++ b/tests/KATs/sig_stfl/lms/LMS_SHA256_H5_W8_H5_W8.rsp @@ -0,0 +1,6 @@ +msg = 54686520706f77657273206e6f742064656c65676174656420746f2074686520556e69746564205374617465732062792074686520436f6e737469747574696f6e2c206e6f722070726f6869626974656420627920697420746f20746865205374617465732c2061726520726573657276656420746f207468652053746174657320726573706563746976656c792c206f7220746f207468652070656f706c652e0a + +sm = 000000010000000500000004d32b56671d7eb98833c49b433c272586bc4a1c8a8970528ffa04b966f9426eb9965a25bfd37f196b9073f3d4a232feb69128ec45146f86292f9dff9610a7bf95a64c7f60f6261a62043f86c70324b7707f5b4a8a6e19c114c7be866d488778a0e05fd5c6509a6e61d559cf1a77a970de927d60c70d3de31a7fa0100994e162a2582e8ff1b10cd99d4e8e413ef469559f7d7ed12c838342f9b9c96b83a4943d1681d84b15357ff48ca579f19f5e71f18466f2bbef4bf660c2518eb20de2f66e3b14784269d7d876f5d35d3fbfc7039a462c716bb9f6891a7f41ad133e9e1f6d9560b960e7777c52f060492f2d7c660e1471e07e72655562035abc9a701b473ecbc3943c6b9c4f2405a3cb8bf8a691ca51d3f6ad2f428bab6f3a30f55dd9625563f0a75ee390e385e3ae0b906961ecf41ae073a0590c2eb6204f44831c26dd768c35b167b28ce8dc988a3748255230cef99ebf14e730632f27414489808afab1d1e783ed04516de012498682212b07810579b250365941bcc98142da13609e9768aaf65de7620dabec29eb82a17fde35af15ad238c73f81bdb8dec2fc0e7f932701099762b37f43c4a3c20010a3d72e2f606be108d310e639f09ce7286800d9ef8a1a40281cc5a7ea98d2adc7c7400c2fe5a101552df4e3cccfd0cbf2ddf5dc6779cbbc68fee0c3efe4ec22b83a2caa3e48e0809a0a750b73ccdcf3c79e6580c154f8a58f7f24335eec5c5eb5e0cf01dcf4439424095fceb077f66ded5bec73b27c5b9f64a2a9af2f07c05e99e5cf80f00252e39db32f6c19674f190c9fbc506d826857713afd2ca6bb85cd8c107347552f30575a5417816ab4db3f603f2df56fbc413e7d0acd8bdd81352b2471fc1bc4f1ef296fea1220403466b1afe78b94f7ecf7cc62fb92be14f18c2192384ebceaf8801afdf947f698ce9c6ceb696ed70e9e87b0144417e8d7baf25eb5f70f09f016fc925b4db048ab8d8cb2a661ce3b57ada67571f5dd546fc22cb1f97e0ebd1a65926b1234fd04f171cf469c76b884cf3115cce6f792cc84e36da58960c5f1d760f32c12faef477e94c92eb75625b6a371efc72d60ca5e908b3a7dd69fef0249150e3eebdfed39cbdc3ce9704882a2072c75e13527b7a581a556168783dc1e97545e31865ddc46b3c957835da252bb7328d3ee2062445dfb85ef8c35f8e1f3371af34023cef626e0af1e0bc017351aae2ab8f5c612ead0b729a1d059d02bfe18efa971b7300e882360a93b025ff97e9e0eec0f3f3f13039a17f88b0cf808f488431606cb13f9241f40f44e537d302c64a4f1f4ab949b9feefadcb71ab50ef27d6d6ca8510f150c85fb525bf25703df7209b6066f09c37280d59128d2f0f637c7d7d7fad4ed1c1ea04e628d221e3d8db77b7c878c9411cafc5071a34a00f4cf07738912753dfce48f07576f0d4f94f42c6d76f7ce973e9367095ba7e9a3649b7f461d9f9ac1332a4d1044c96aefee67676401b64457c54d65fef6500c59cdfb69af7b6dddfcb0f086278dd8ad0686078dfb0f3f79cd893d314168648499898fbc0ced5f95b74e8ff14d735cdea968bee7400000005d8b8112f9200a5e50c4a262165bd342cd800b8496810bc716277435ac376728d129ac6eda839a6f357b5a04387c5ce97382a78f2a4372917eefcbf93f63bb59112f5dbe400bd49e4501e859f885bf0736e90a509b30a26bfac8c17b5991c157eb5971115aa39efd8d564a6b90282c3168af2d30ef89d51bf14654510a12b8a144cca1848cf7da59cc2b3d9d0692dd2a20ba3863480e25b1b85ee860c62bf51360000000500000004d2f14ff6346af964569f7d6cb880a1b66c5004917da6eafe4d9ef6c6407b3db0e5485b122d9ebe15cda93cfec582d7ab0000000a000000040703c491e7558b35011ece3592eaa5da4d918786771233e8353bc4f62323185c95cae05b899e35dffd717054706209988ebfdf6e37960bb5c38d7657e8bffeef9bc042da4b4525650485c66d0ce19b317587c6ba4bffcc428e25d08931e72dfb6a120c5612344258b85efdb7db1db9e1865a73caf96557eb39ed3e3f426933ac9eeddb03a1d2374af7bf77185577456237f9de2d60113c23f846df26fa942008a698994c0827d90e86d43e0df7f4bfcdb09b86a373b98288b7094ad81a0185ac100e4f2c5fc38c003c1ab6fea479eb2f5ebe48f584d7159b8ada03586e65ad9c969f6aecbfe44cf356888a7b15a3ff074f771760b26f9c04884ee1faa329fbf4e61af23aee7fa5d4d9a5dfcf43c4c26ce8aea2ce8a2990d7ba7b57108b47dabfbeadb2b25b3cacc1ac0cef346cbb90fb044beee4fac2603a442bdf7e507243b7319c9944b1586e899d431c7f91bcccc8690dbf59b28386b2315f3d36ef2eaa3cf30b2b51f48b71b003dfb08249484201043f65f5a3ef6bbd61ddfee81aca9ce60081262a00000480dcbc9a3da6fbef5c1c0a55e48a0e729f9184fcb1407c31529db268f6fe50032a363c9801306837fafabdf957fd97eafc80dbd165e435d0e2dfd836a28b354023924b6fb7e48bc0b3ed95eea64c2d402f4d734c8dc26f3ac591825daef01eae3c38e3328d00a77dc657034f287ccb0f0e1c9a7cbdc828f627205e4737b84b58376551d44c12c3c215c812a0970789c83de51d6ad787271963327f0a5fbb6b5907dec02c9a90934af5a1c63b72c82653605d1dcce51596b3c2b45696689f2eb382007497557692caac4d57b5de9f5569bc2ad0137fd47fb47e664fcb6db4971f5b3e07aceda9ac130e9f38182de994cff192ec0e82fd6d4cb7f3fe00812589b7a7ce515440456433016b84a59bec6619a1c6c0b37dd1450ed4f2d8b584410ceda8025f5d2d8dd0d2176fc1cf2cc06fa8c82bed4d944e71339ece780fd025bd41ec34ebff9d4270a3224e019fcb444474d482fd2dbe75efb20389cc10cd600abb54c47ede93e08c114edb04117d714dc1d525e11bed8756192f929d15462b939ff3f52f2252da2ed64d8fae88818b1efa2c7b08c8794fb1b214aa233db3162833141ea4383f1a6f120be1db82ce3630b3429114463157a64e91234d475e2f79cbf05e4db6a9407d72c6bff7d1198b5c4d6aad2831db61274993715a0182c7dc8089e32c8531deed4f7431c07c02195eba2ef91efb5613c37af7ae0c066babc69369700e1dd26eddc0d216c781d56e4ce47e3303fa73007ff7b949ef23be2aa4dbf25206fe45c20dd888395b2526391a724996a44156beac808212858792bf8e74cba49dee5e8812e019da87454bff9e847ed83db07af313743082f880a278f682c2bd0ad6887cb59f652e155987d61bbf6a88d36ee93b6072e6656d9ccbaae3d655852e38deb3a2dcf8058dc9fb6f2ab3d3b3539eb77b248a661091d05eb6e2f297774fe6053598457cc61908318de4b826f0fc86d4bb117d33e865aa805009cc2918d9c2f840c4da43a703ad9f5b5806163d7161696b5a0adc00000005d5c0d1bebb06048ed6fe2ef2c6cef305b3ed633941ebc8b3bec9738754cddd60e1920ada52f43d055b5031cee6192520d6a5115514851ce7fd448d4a39fae2ab2335b525f484e9b40d6a4a969394843bdcf6d14c48e8015e08ab92662c05c6e9f90b65a7a6201689999f32bfd368e5e3ec9cb70ac7b8399003f175c40885081a09ab3034911fe125631051df0408b3946b0bde790911e8978ba07dd56c73e7ee + +pk = 00000002000000050000000461a5d57d37f5e46bfb7520806b07a1b850650e3b31fe4a773ea29a07f09cf2ea30e579f0df58ef8e298da0434cb2b878 + diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_256.rsp new file mode 100644 index 0000000000..e48c4fed28 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_256.rsp @@ -0,0 +1,12 @@ +pk = 00000001B901B8D9332FE458EB6DE87AF74655D0B5AD936A66FDB6AC9D1B8CF25BB6DB8404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000100000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94AB901B8D9332FE458EB6DE87AF74655D0B5AD936A66FDB6AC9D1B8CF25BB6DB8404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD09000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2500 +sm = 00000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA7010C534B0D4C6FFDF4DBFE00E72405EFE83BBCF19AA2030A8CB163808482B6376FF8CE01FB8090F4842896A1EA5E9282F35CACD245A4B9DE9FE84E9315851D68A72B3ECB9F440937C8BA4AC3F0429246CBC2777E8B92D84F4BA49FAB89465FCB0FC8017E582746F531B4697925154A22E2D6A0F1B81913438000C295153D7ADCA8F852C50D360F65F887479E9631A2CA30FE3AD92E7BF648643835F4F8CC081A6C951B83B77608A08C021821DA61962CFCC8E97D75441921D39C5AD537543EFBAF0345DC70826E6E950929570C72E51619600C58D932A72657B19AF163E0B8F7AAF2949A5EB26C517909E0E663E36753491182975206009107509DFFC898D308B903E84A8B29718BF7125397AFF5467D53CF8F36EB945B6B98D48E81C0174A0E03541D24369CF8EDDA4288FFA615D16FBC7355CFC0966BA9256E5B8A44DA95760DFB61301B10FD3E82436E267DB089773E43B984297D1E0D395DCC77FCFECCEFEBD4B80B3F241872EA251DA466CA6C5324346F4B5E6886654A86592641A8C32AC554261B2D9130462C976B039E593F873AD1712820FF3E723FE57F137751AB3CA8B5B20D28D1B9384DF1D710AC39FAF699989418B7856C2034C695A693ECC336EB472DE5049C743089529695B028F2F72BE0893E59169E9A2376C64BC5CCAC5482E5A6E9C88D710A3FF8F23C206B09D314BF50568228B1BACF1CE330D529BD3793D7C7CD9EC770C111D9681D6F1B97D908CBBD436444853FEB47F234D31F5E92B9E0465D67AC0FE48859126BEFA7F7D121A67C2C2970B37B8081B4E73C5A21A41F60160A61FAFBD48649A3D2032C1679A67F348E3E25275FCD9AF650937FEB0A30F25878CEED7D6CA693518B5A2F5418135EA9316EFFDECDB1DFFC9EE3A62EFF0E66F3D05BD9D5F8679B536BB6D39792B28DF2481A6EECB9BEE40B11A10D39A90EA1AAC47BF956FBFE9B0427B599B9BC024F326515E71615419423FEC3F19F621D49B6EED59F129A6B1411B7B1AFCF073095D57B03F25A16F946ED716BF705F567A151BE85B8E8195CC2F070BFD482702182B8A4A43ED942F6BD3CBF9DE7E8AEB17C41E1C009C94FF4A2050E3731088B75474B38DC52BADF53C7DCD3FB98D023649FC4799CE060ADDACEC7CD4E656074E631C1CB8AEF88EFEE0817C2E3D79E287F4510E48DFB7E23CB49D6FCA39A1E0F471F16A8BB65AF02150D059036D00386DD287BEA4D52FB263B57AE5ADD901CADE838B1D7347D9E47EAF6456148C6C4E44B0FA3DFCF5C9CEC2D80AD509A65AEF0E3E663B7F31BCA437311BA799D4C2ACC138F85D73CB40792FF03F8F20427D951444990CA3976A71368A7DC1455E880722F06F02163BC712E852A914F22E5675EB9B1C6C8B7FD20A8880AD2EEF97982C065C937BD3639357E4C7450CBDA0B51CCA8E3E078DC760FD99EBF646B82369576539B2BD5B2C866ED5AE94423A5CE18C685352398D01C983F080D7BEB8A9243AAA9AC1DDCC1B058B92BEAD301E8F3B8F5EF71EEE7966302B44D2E26D2A02393713E5D4D3FEF42196FAA368274C78C2932D22840ECA6018CE7D16B19A0727CB1966EB28B57D137C5264CC2E627F24A3BAD50EA4F75C7BD8998709C01ED5ACFFF0891934E94DA2CACCA212FB48BE3F9EAA310547E73C388D881F36AE21EFEDD23744F6B07C5D6D2776C191ED41E607316F61BBEF7A20E1A03150AE833D18952AE35188FBFDFA55C12A388836717BB2BDD97E89121C56C3B53E8198242315C9E438512E0C8354A3E599CB7217AE688647A72985606BBD0720F6FA5C5B6F70E88234EE54C6DB0A41106C866564650829FE4B232635B06B18240C9F86369C75B2F7D237211A380C43F95D362E0680D9EA2CA47E1DC8C49703E22650B765F847AD86BE25A3B7630D640A0097632DF13F600E8A025DD9A1FC67B0EB09C1CA9FA3923896927DEE1E3CC0C81F4B82E43B89CACC69C9B8ADCA1670F7D4E50DB7BCD94C2115E75F2BFD2336DA5A304D0F3455927360BF5040E95D1454106F2A8A7CD27D5510E7B5BE7B5B9EDEFDC3D4249D655C51F4C1DBA0F359BE4769AB66EDBC802824E9AB866E8EEAA2FEB1CC855F0A745AAC84A610DF0238112C6519F8E7346C45331A6036F84D5B6250F4B5BC0A2A6A31DAF9C60EB13C20CC649A18E27A6C98B82F08E21706A8BDF338CC69C1679D25ECFF733A721211C1F6DD28091AAA9C93B047EFCD2C8A55F2DA65E616F07DCC0F44081D4E359C1688A00F062EC925D24432862B547BB70F2AF126A3DABA5C918B224DE444B8733E6FA601B3D349307E94583D0EC976AEDA2B90972324B3ACE8C7B79A67723AEA037E12DA9EFA9CA9668A4F5FDADFB9EEE13398921F5023E354A6894825431DBA7317E6A6F69F0E77294BCD02D7616E75AC31EC528FC070B8C34027C4E9CD0672903412FCA6B723650D56AF562069312FC7EF1891A77E1A3F29D810C205EE212E75863F3B8B1ED216DF888ADD07AFF45F1B5C01196329311414797CD5F67FFC54AAD04C803FF7E83C2E8BA224CE83695BB7916AC42B1861F5CB527FDBCD82DBFA31C5ACF981D8414203837504263C96A0015841FBCC721F96D50A86D6E096AB54AF9980F06CEE6341C78D6583F6BAE8081B3C44B0F10FB7300874B5011FF0F97C52F975A31355884C2F12B6FFEE20E8371D38183C9D04977BFA037C9BD4DD7F7CE203FD7FAD3852B3C2AE9D078ADEC70DB1A7140EF1114EBB03E8DE03237E0A27FF510015AC76FCEFE4EBD4C3A1B6C67DB2A82FE2B1BF18723DB0F29FE4AD47B2EEF22AC3C6661CFA7DA7476D23B470FA2E0441B6473EBD291791F09B4ADA70A5286EB05167BD59BFD8C46427413D60692382EFB7882F60DC53AAAFDF2014CA7D27F8FA93C187A8371B41796557AE739912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70D3DB184EABED83E30C11C9BC62F3340923A0082B987EC45CC7BD1DB4B2B15E8AD3EAD74E96D8C20D85617BBEDC0BDAF8ED48B7EE8D7C42990028EC0669AFC0861C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A +remain = 1022 +max = 1023 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_512.rsp new file mode 100644 index 0000000000..4c5d3081f7 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_10_512.rsp @@ -0,0 +1,12 @@ +pk = 00000004E219A0AAB2C8F4054939A56A419E39D2B91371C6A2A485B21D749DC399E0E58275A69ED6A400A7C1EA5A7B4EEFF0DB2A7E742C062A847DDBA24680388DDDBFC14D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000400000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957CE219A0AAB2C8F4054939A56A419E39D2B91371C6A2A485B21D749DC399E0E58275A69ED6A400A7C1EA5A7B4EEFF0DB2A7E742C062A847DDBA24680388DDDBFC14D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B589FD94AB5C37762EFFA44AC2093812248300D072E964594FDE1E5EBC7987B59EC36D4C0C120E76872FB77366F2C5B18B86B9139DF28EF7D44E32FECC4C804F010000000000016B410B4BEEFE73CB8F4D4C3ABB7DF62F132C01D90F410AE51281E0C5172FC3762D01221D015C100F93020CD106AB5DC052522C419A0FD67AD1A5EE9D5FD62E180200000000000121D1E9B1C034C0E95BEA3582EBC57F8383D0F6D1DA068D3ADB5B2B6237AADEE9A89B9F772A990889B143707CDEFCD05608317F599099BCDD2EDCA4B7CF410EB403000000000001C23E183353CD7FB42309F34D450892A84D2E250627D82E72E4A582BFCA8BAD10D4F5A2CBC313BC02333F65E8FC8BAB87A19EDD304EC7F7F85AC8078CFA3ABEE7040000000000011E2BAE00E2D34A2B2CF6745FBEF9D552837C3DC63720847E7DE3094B58785B6043AC7DA8CCBB7CB127C7B0C7A974607349D30D61CD7F08BBE092A3F9C7BD0FBC05000000000001657D3C7D66C12770C0BB75D4F5214C4B194F841F23B240ED784A12295B734A173AE89D8EDD857516ABFACE192FED90D2CBF6254B4DF0CD8C0D3F7CE520B0FAA5060000000000014567D4BD416073A25CDF242C18DBEA42908A4D6F0F15266EFF60569D4C458758BFEC8027BDB07730ED08E3A23D0540D8B90A140E06A28CBB64891316084D93FF070000000000017B8C7C4EBC5F897F112AAAD0FE18AB8CE4360565BAECD1075FED846955A14048C88B6B5C1A065F92AF55BFCBB10C7C46B114C80E9A36CC3BE6A245F466351B7D080000000000011F81CA34F234A41958ACAC3BE7C53450FCCB7E4D785F18C94981FC721F4CFB851AB0550BEE14A4DDC57D2A9EA06065395660BF32D43B71FCE388DC6F33795910090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9092 +sm = 000000006686539E267711CC53D8B185DE1BEA3A8484A81CDD6B6B0E46CD6568189E74C033347FA34BA7448CD4D56964F49F730BDE52ED29F39B1CAE52DBEDC90A0941564695221F5431496845B1E75D26B6B857E2611A6451456AE84936147AFFC7C7B2D2C1E333FACC759EBED3AEFBCB300486A32BB292A7F5331B29C4CA9D53EA76525BF71D5A3E48FC845FBFC5425860C9A12823F207A63C137A2F354B763989905F589D19E88325E04DAB387A43728A4F541C50FD01DCC2A7D84C6F18B6E97EBAB3CC292356AED4291FD4B69C3D557CC1FCD2964C9CC149D630EA9C2E77275C448894615FBD360F62B0E244B1C000F1975FA615DD6A6DD56929E69F80F1086F533631B97B3061C60CB3CCFAAA690EC0F4D9C3A99567C975C87A589881F548C5F1BD93EC0217C975EB40B2A715F44E2A70068D27B8EB36A6BEFF81E312438EEE5813EF919C7FDFE95C078BE095A07A41E468AC98C8AA215C6C976DC94AA462B2DD38EB434E35A03CB016FA3DC81C1D8E91E41FC43F71CA3BFFF5B5ED792DDF10BF542E2E0161113497B31AE7D795C0B9DFFB62E809F587779B6FD7B1DDCB38EF48A449BE87FFF3D39854CB01E9F97B36ADDD4B2D8C4562C45AE61E527AD277EFAFAA5E69FD57EEAC4828EE99DBE12234E48A253102FA3FE6298ED6FB7572BA4FCE73F55E90CBD9F6F0D111DAE055BE32913F0275722C5EF30C2A1E10D6D6A783C2AA2838C5A6192CB37077B5A1AD2074C2A24F21854C91973F186FCEEBB536B6EF677311DDDDABCC839947F681ED60691910FE67C017A449B91D4F2BB342A9CC5DBD62C2EAD8B2DE02150CD5B0D3327B7D2BEED3415167D54F73AE24BAB4BF906C1A056A1392B078CB74664CAE461FAACAF60FD0C6A7925CEDC5FE1DA590D0C52CA558F6750C7A75A8F66C221421F154A3A0DB9542AB5555890176CE1345DB286997894FC57EB5C2C3EBA0A4C6E8C9D7C637C56B034057C364C66F3EEC2C6DBAC1080BE9C26B16610D007F303C4B9B7A329D17000CFF3853EA3F9D56A5315BEB2313265CE888B790F4F6E16E53F6A75DD689FC246F6E9675748F56FC883F850EBF452AB50D70A21F6ACA9CBE83C7452B8A05EEC284B49CB92A4FFD1ABC8FFA72CD41273B4D0A0E91DBB3B321F507274EC896231A24B3CA654405654E449EC9F0ABF7FE8182F7098A6DFDD2889BDBECE91F5E86CEBE4CEBF8EF098C05A5895040E89A2D24730373D42A05DFC4E9DEFFDEC1BE8EB34AD922C94F80075F0BC540B1587AA961E1B668789484624BB34E0F1D2C6E163EE3DAD3E9D8A608F267D2BF7CD4CA356915B3792EC7B2956CB5335E1630ABC7EA438C7131FBA2BF91E4E7E0E54D3DE82934C2A711F4DAEF7D4EA9062E659449D207EE702945ACBA58A9DE4B8E9514A130561352A04B1923DA060D90B0EB3C654C540507F745F0F24065FFB8D76C0C5B326DA7C300F3E2BDC6DBB570C85850C88E0996753DB70B1C9201593B3A8E6ABC9D581604EA41D9C7109959DB8E8882265C7F8D12F24702F9BDB9BB4AF388C55C02FB49B4FAEFB98A25886B558D4C3492048BA4DABB55680D5F5BAFC70BC02492283183BEA8127ECDCE84EBF441C8AEB01082D07CFA9DA4C9034C8F4A509FAACED436450317A7DB7DAA434D927BEBD2AAF917B2E6D434511237E31A7B04E7F3E6C5FA38087E274E5B6BDB334F9D9F6ADE18AA9065FF72F09CDAE4B3BE7FB1CA862C78B0B8A9B8031297629CE35DAD8281075CD7D250557ECC3581AC93F62001020264F8E93FBA0FC322245747EC7076288748AC8D13F18AC5A3AF4884FAE075042FB85CF3C0DD3449575E0066021BE65428A2976BDE033407039D548D9EB6DA7D02B2CD6556B12362140950B80E378D44E4B1AF627BF715B7F36083F6B899B4D09FD639E47CB04541E6A306894AD18BFDE42AFD2BDBF2B61A78E98DB066BE125999FD687A324F16E0452119E9B7085799DB594891A9D631EB4A955B5B0F4F4773C19006EB10BA46D8445640074FECBB51649B6FE90BC1C63503018A37400CD476CB166A6A2782EE1680495B2E11F5EC5BFFA5FF196C739CFDDF7430331E71CC5686366E753DCE01F186ECF2AA9CC1BF911670165C06319EECA4D406145735FBAB797A794C3C58E998827A076E23DDCF473ABAA62E2C5BDDC6DDF55DA550BFFC23BC4895F223F904064AFFD5D5E61A7B64E29E3FAE23CD6FD9619795A1314587D124F3FCAF3569206484848932025D8F638102A4F25644DC1F62F13AA1262C5C55679AFE8E1F7BF340ADAEFD97221D46FBB8702B2BB5EBA511066C8E9F159F52431ADAFEDABB476DFB8E836F153B08F3BD4643B9FCA0A954DCAEB7194661EE8EEB97781695D64EFFE2301189B28BD7C2F9E64C32E263C99C6BD804AEDB9127A60EC8489973F99C782D062679F3F604ECDF2460383BC369DE103D0736DF1A0868D6037F68F091E0C741442DF88E14E8EA615F5E8646A68EE301E551849F580EA63BCEF034B847C47B373602465E6FBAECB948374A3D64410717B19A240DB023B16B6BB0B7BCF1D63987106F171B53DEFCA63A7E0652FEAD5584FD17F54F50AF85E1D87FFE5CA116AE1664CC9AD25B327362D9857CCF6169BCFF97A95B1583B8E20B7BFA4814BF5D82F00F07961107B6063E8CCD453E1A622A7BDE9C4C6B97BA3A41057AF2D7098CD4E829C34A80AE24846D8BC92BD7489B854831DC7A4956D010988AC9B2135917188810FE4D94FEFDC59F6954EA289C444813ADEDA9CB435B6C470C0037C21024FF67B7B7031E87D8F8774CD6BC926318982544BD6FE38C09893B929C9F8B7487D51614D1FBCCEDA56C1794C943A36E54225B729D63855471F2AA9A514D567F61B9E9B4AD4A327E6B113CAF5C0A22D26F74A507B0EC1A67965F0978C608B70E7F6D1646E7F89D2E70EEE62852C69618ED8AA136DB1E75D4A687A62443A82802EB270F1C91E97074F3A12C63FDF3BABEF882F934B4BD0C2468C66B1C6E37F8CDA8FFCCFE109FB291FF10163AAD73721CDB57A5E2CE8CC41467CBB125E3B525185F8ECB34C4F4675220CD92836BE2E420F24BE023F22594B5E3F5AF06CE056C8EDFC67B49808AA9643FB1160DB9D455C38071F49555D3FE9A7890DCA5E2047BF23E904D07641140BE0142DC90069A86D98A280D45A88C7E54B6B0660656A5C40018C9AA955F5CA9F10A10005C735C90F5B2941043AC88271B241AF7EF66218B4B74E41579BF64C812F9502DBAD602FC7894000F3ED41946FB81DBA9DCCD666125E9A4A5AA7DA1B8E5B8347E1964D36F6D0ACCAFC14DD8B5DF301A3768F5EC7924982E1B57D37D019914A01EA0B7B1652EBA5C15A6843CE712C34A1AA8842DCC9FA570A6883857EB260BDF01EFDD4F233551D18F89B585993A92A3DE64CA9A0EEB74A7D91DB9E0FF5FE1E035C97EB8CBBC796E22302FACDFF89231FA3F77E72EE189894071B376D0113BAC1EA0911D3A5E24D638CF8BF0C8B92B0A321B7E4557CF465B88102F98645EA37E58DC6664DFAF870E024A4D9E84C8B913EB467D8252BBC8F86818EB2F9D03EC70B4342CEA881278C516382DC79E27B4EBA9879AF2DFEA6CB914AA98593C52CC7857A877371F871CEC175AA5E72285023F1A59BB072D9B2912D974A26B4B57A6B772F9CD7334A3A66DA86DCED932119C5D57106FFDC51D4B7E10B6E94C343A90C9C15D078E9D5A66BA252695CB27377607E0968C93D529E02EA881A2AD58DB81863B0FAE8B45252AA6F742E04D310D82FE58B7E6BF2D0BF8A7D714F7352BFBFC3EFBE050F75E60222CD694496EBA04C85B7DA12A33ECF4325A392ABD40458D087DBC638BC65270E6E7E5719F14AC7721541610F2724EFA0473CC320023013DF549C8DBBD5F5691450E04C26202F5666F5130154012204FBD584E84D821EBA36CD2FCDCAE1C4BBE8BE5C9AB1983526743838548D107810E014FED68387355106C3B39A9539F2C24D318DD5F1B0715E853E168C809BCE684671411C783A766B7307675CA4D04B0DD86442B1744ED1B8EE018F83D9D68B4FCAECC66FDEE75EAC379E19D0DBED5C3473089EF153433ED2B5587C22C3299898850F7A872BCD7A064A7F8211AEB8175668B1402E79729AFE8F4EBB2F147DEABD1E0234E5056F5D1DA522752639E200C12C166D5A442071F190DEE7670941E2F0C59C05F1F1EE8C6449EC731082CF56CE8DFC8DBABC019420CEB0975CC90E59F165B156FDDE09152FA049386C57EBC64DBF0ED92181C6605B0EC442B5CC242DA32C1716B2FCAB0F64F6C94E7E8053CFFA1B5329D7DB924DF329BD3AAC38A29DBEE3454E1FE3D79A6EA6877DE61518DB7D79BE808BF2D6D12AE400E94866A8E27D2F4FC70D9CB443F8DCA23113E32C1497EB0E61AA22594817739E8F954A39CDE8B6B1A543CBD65286E2DDCBD0F5FA3A6A28B28036210ACABD9EEDF4B006B94DF3631B68A824824162C1A3A1E3288924B834F21568605AD9543CF93919467A90E61C49F5EF5EC30DF4FFA1EF2C8CF59A7EFA1446238D9E23C3B5A42809BEC365038F526DC24D81AC1DCEAA429678B3A019C12A772B3AB24DF707A1E9D83FEFAC76668A9E234FDFE197101FA2F74EE80C9F0CB50CE2EA40A19D618EB82699E032B417810765366BB2DCCC2B41081699F01563DF24D65E6FE0142E9AFBEC6366C1C027864ED04D3C3F1EABCD974A2C842C640E46024FCBC33B5C94494AE26FD0CCDE2A62DCB2C63D22AE6F0CC2D107C78B1C4B0E54CBE78573B38785A0CF94839C6DDB6218C234CD351F3813E119DC05765C450DAFD64BEB915E7BC6D09FF6B756949615CFEB5518F19A7FFD3C36078FD18CF782D5FBFA41AA86ABF35E16079E71886A63077763203439B75DFE4E5CE50F97EFC93030C80ADA63754D8096271224D1EB627E3FDE3F54E2D566535C5D33F2485E686D4B56B0C674BC5D6EB60C81488344A32BFB02FF5A309FC45088769B98930C32B2A9F269EB83E3AA3E0CB0FAFEACC1EE2BB5366C6787E89D46155687639CC5B02EC4681977761B43191E5402CBFFA0573D63041029C7D14F33BB2BA687208F18A91AA8E22AAD4E86CE927DEEE97256EC3CA81B71738B4BCCF072234047F5B32E44D030FEF18D9509CFEF94B447ABA3CF4878DCF9C0FBDE9DD7738D91D5AE94D1583504292E5495945E3CB6B202674261F4D1911468E9C95B6BAA96FDE0EBE07EEB47C5BF9ADCFE3A276F79C84CFE48D3A5A9A2BFB656C8A9A87B76A602508018DFEC14EA398A05022C87D8FC0969EC627F4FFAEB1F8242D31B82CBBB11B4959307B3D5DD0376F3E7AA40FAD8E2FF8DBF5D0AC1C9F90405B943879D5633041A05942A6BF60B89DD7ED5BC14F1C1658C4CF226DFED57C8AC5C825BF5409BDC051F8C83506164836662C94CCB33EB665E90735DA8132850BC22BCEAA581A42D97E45884C03CBDA6113587454CEFB86EB828BE506E20FFD3A4BD3F0BEEE7239FB57CB8EFFE15B421A049D5A654EDFB06F17EF56BEB8B7E9F0FF2FFE632AC59DEF87DFD32129479284462B108D604B665EFEC0D25ACC19CFD6EB6356E7CE960EE78553A56D622D3B2838F49510940221E87EA2B308F4DA54915B3D61C95500A3073A2E4B9B34DF59C8111CFC5F6E03B86E339C806CC0A4128A7E47F6340737C8A3004A2626E544CAEAEBAED62EA3C45801ED8711715D6B0A85A4C005CC39629D894C1C590BEA60BF5AB5B02A9B76728A6E7F72F7C746265D51FA1771ED9D2FFA4184D4EE985BB95235DED9FC782DBACB8AE478797CA856EE48A24941059B4CABAE9D48E1C4AB18F419EA94224485ED860D056AE7D5D0D00E9AC97470A30D805CC2176895F3F80F1D8EB9F914C6F86C6E870EDD24F0AB9D0D1BC03B4A6CFE770CAFC641B4BE6222CABB3BF68DA88AE2822BC27255ECB02085C7E19C4BAFDBE27C05FEA7B8E3AEF255164A84697D9C7E4E540C01F6FFD4E7566922FED1EB49DFB029E350CAB96EEAA30567500EE1C5C04FFE0F2564098798446351894219168368642ABA593001A47584DF43742D652659CCC1F1BA0FE7C21797859AD752423033EC5871F5A1703D0504E20B458677C4C4740D9181951412512D0C0B5A32AB9C33BA1C9AD9CCC303021ADAC2091500382D42149A0AE666ED8CB8DA412E52D2FBA633AE5525EA0FE81DF7FFD071C39EA7AD445C01F9B0847226C84973B024F3A69AA22D64F477E130DCA563037B7CDE81B11498EBA5850B5C31E2873EC2A4423741EB539B66580DA833E487A3ECDD6EE957143534C156407EBACD74408888066EFBBD69441277EC843C45B39B3E0B6E2F936D2F8EF15F45075982618BA5F983806E7919BD4D59582282C16AF1221980B5510A38DBA62A587F6D80F4080ECF7819B5EC949B2856FD2AF0DE295274718D859D64FFB280C63546D27C98873505F49D23DA88DF5E3052769C28FDCD40E0FF72893DA4244E492FC2EC940D407344A1A4EDAC677EFDAA1582772990C3DCD904B3104569F93989FC13FEF43F344AF7C75621FC14C448FB778D681F506671E5D03D24016424B2BF10CBDD9495E7352F040A48F46FB33690DE20A30C0ACCCED872430F7A277B4278BC83939E90B07B4B548E4D541491EB8B997C17825EAF3DAAE1F5E308099617F30955E3EE32AB8B029A6D72EA42A2FCF33077620AD4FC58CF7DDE2BE8D6A62B9466291BC7286096F14E8BD2D11C73AF7D92D2CD31DF9C18307AF432E933635CA06153A8DC47870BF5FE0183AA8AF5687D01A8DEC21957E57EA27DD4BA80ADFB48B2ADE869BD76D11BB4FAC2A74984397FC8D65E641A8A0DEE95CDE25AAA04EA13D3007A031F80AB9AFC73BB27C60F256407715DA96071C8197A8663CDE5DC9990FB29A1EC9AAEE667BE58C4EF1017534D07C1CF9028754AADC687D760D6410AA1FE5E2A6A4C35CA7EF3BB3E5B4DEF14FFD7903AE3570175C4C75E65C09DDB262724AEB97ED9735CDE139B74ACA9A5D7B1463D6BDD900E73E8D1AA1AE534AEDC0B0ADC0634D6AA682AAA4C8FC2EBFB97E98478FD918AD4B24B4CAA246D328187047E8958756BB05E80E4CAFAC794BA6824CFB30EB09EC7786BA7CBDC468A7ABD66F6D7D62570D7B2CE612D4A781663D2FB9C5BA533F6931FDF374D77681CDBB92B2E0ACE313023857010DB8E401FB36365BCC03E91E78F4959A0BA59348BE988805AC9585172CB1AC5749644900832A67D493F54E0D898E7606276073226B5FA8036437067D193C744C0115F5C71E345A48F96A4A7B10E58D79B9A0EA10C545DA202CDA1B4AF08A968B218E5C43AB295740FA5D36D9B611932B9E0682A1EE6D5DBE228FE90E9C7E169748261E1C566EC82308884DB143C3A8F199B814F706CE6F7C612B26EC1A01ACD713CF758C1682D15262280F0CE056A2FE81D6A4965B6E66CC8CB01C7193C9AB5B17159724D0917AE84C28BA3525DBA96691397BD9238483AA3DDA24C3334AE22EC9A47FE426B3B08640E6B6347CA91AA4384D1B27B323C8C9B363A162D27BBAFB8EF81CDC90B309DE38FAD663F00C0343A8D8FDBFE6F3455BD288987C3443AF79DE32D86735339B9828478BF5887471663B2D20CDB0C92D87F27833CF08D628DC834210CD7A9C852B58C14B894E24C21B380A1E44937B6E831CF0DB2BF88799A2532A3383C755EACF3970ABA6EFAE0D5825B7DF122F6A7B536CCEFFD000C2E61A519412B6C60966D4ADD9DE24F94F771348E043EBD2A25599CD72233B9744EA63F6C94424A4AFDC10B30EB857E423C4B19D41CEF442432E433A6AF71629EDB05E7809FC011FE3DF16FC6A56B83AF09EC0169A6D17B318C27BB074DFDF0C4D817679551F0080E7A8D1D9101B63FDDDDB2D1CDE21770CCE0A0EA5ED402AFE65311A48249D2A49D44C10B7CFDAC28583C67CB6430DF02EE9F84E430C88522CF1016242CD0677EB43F077842B5267A638C551AEA6931D182D2D3C631598B247FF93964C59B0EABB99C4C9941E641B0023B8AA5F3F93C17FD684B3F18996E30FBB8D3D7798C37BACE0F096F04BF1CC4446549B49931107D2F86C66638AFBCCB22CE50D7390CD38311EF7A9D50734A7021D872B87E8B60AAD96B0F12748F7BF4EF8C9BFB515A5B017191E9079956DDEFF3CF016DAE35C99D3FBB755BB3A79E69EA78F4576B9E05F35DD7CBCBFF369822B9322BA2B05337A17930AF87975EF0CD380B920CA86B6C4B7C4238A59F6F03E8AD55EF1E6AE8FB04663D7327FAFF924E6EE53476C449AB25A236C98523A7067A93EA0C54EE9468B9F79DE251D99A95C1AC1D7C78B56FDC43369418DE381B78CC9C9E478E64D904391F368A188444E80F3C001BDC93459ABFAC1E229C7905DB266ACE93C2AC4614AC777663E448EF8DB336AF6A937CA13E325A2043BA5514C3AF9CCBFFEF3FF635658808CCC58E2FD1CA58802FFC72E386E777328A79D163298E1DD66603E0396DE534A4AD7D3A19C117E7873777EC8735A910E4177B0442D9294C4EAE3246E87B95F437335AD6930D4D1D6547065756BEC9EF32188FCD42043BE04249D920335B6E34D944AEF7C542F18333280557DE060C94CC2F93079741811FBA2930F038CD4941BEB47984CF3DB2F3E721AC15B1AC979CD933EBE8EE073D129888C9B871C87303889897A8B9FAE58999AE9574C53F3C024F9E1587DF95A820B3886A4DE641EEA0C2A17DC347CB16ED3D4BA5BDF45EED7222F6714DDB16F4343AB65FE27E27A47D18D82CF8003332F59DF37976DDB719AB48035169C6AF53DD2EDFAFD2512CE3B73D53859455B456D756CBDBC3EA9E1E869EE96002CAA7EB6ADD8D9C0201AC3E88332A531D509A861A95BF04F0EC5867AE4CDC1B5B0A056DA596BDA426545829EB5C2773AE19951D346A9C62DD6EF1C031A4D659FEE60472619BC1DEF82F9183B7D776F5FE30F625CB1F41054C522E4B983013203D7F55294B79C878B069A9A86E195CE477B71B53EC98B482F5072F9B442C32316CE3E6CCE64D0AB79197D439D4169FD36BA3A30A9F150821821B395695B7179D8937B264A6AE4506A9599F73998967C824F444CEEBBFE3CB587412FE39C3F5F88CCA164CD050EDF18CEE52BF1FDC4B33A2A347E82720B49707737278348DCB509A488823BD2907C60F0465CD2710DD0041B53BE0D1EEDEE5C6F39A02226BDC3FA56409AA98990C1D6E62C324797D910C79AC06DF3D956CF6788EEF1F70B267348C0E5C88645059E631E17EBED5D365A0C16BFABD6FB9DB2BF9FC078C7DF6187EF616E236D4DDC816332D10DFAD1601979D4CD14EF177FDC5D93DDCE075E0CF0081E5EE900E00B5B58820BF0FA5BCE0FD9CA38C6E2CDC456376DC2326E99DACD54592756C2A5F651131C084ED369C94654F44669E1A950F16FEB85EA106F752BFFE23AC4B089F37A07D3DF7CED35602F57DA407F9D60DA3B2D110005D0C27927967B61A3D3B16F4F0AF9EA887D9CC9FD812132E60254F1B3AD778202696F7084388AFB30AF25D61DE9B7CD3D53044524A832BE78D058A68B17BDC981D4773C5FDE404362A368272CDF08070EB738D7AEF2B8B5519BD005BA5140E230C2AE07A24C4FC0B22579FF144DAD576466D6CF76C2CF3C663F5E8E1F423C2F516954B1888096333826079EC2743C737824220E68221A15AC03DBABD6B73BBD6565D9B3B2FAD2D107ADA8759030253C4B7EE6721FE96850B07E962322F6D47BE10711FDCEF278DA39B6588EB45FEA241875C0BAD85FEBF38FAE94358BBC673D57138D1B09437F963C20A764DC35D73FD7CA0CE1B44F28E4FD2731FDB75B9E3001E63A4623811141747F410903ABF5A914DBC9D60ED5C3E59443D569DD33181B33869F1E00ADB57C61FF5F74E5F3F8C0AB974F7D5E9AED105E35DC112F50FF03461C19E2E456FFA22C3DA25491396837FE35064CD5AC5F8BC453E0E86736CDBCD997913BA652B281B814278F7772ADC3081EFAEDF51946AE741AE63D3863CBDDF78A900AE829F97F63B4155EAF0B245843A5962C62707A5B57157747BB6D20054DC9A49D0AC4D1E5EDAD0FE3303055B8667D773DDB4DF9B72F6FE2E2FA58C2E7A4C3D6C9053AC3C4B7E4E80A54AF105F88AFB441106E38D3143B7AF5B70447D1F96AE8FBC7CA4D7FF9764252125C2739963273D2E139640DE66F878AC3793DAECE33FB1D05338FDFAC98E051D2613FD4A4817ED459FA7B05CCD6C90A6110AD8A01AD594EFB2FC2DAC88AD30737A55C475149505C341E9D77B3562DB46347DFFD2A9DB8A68124026D9E9D9A9997AF40D70D3A922DF54D52845B387DD8C2E4623CD85659FA7F25ED157C79337C99BD9173FEEC9D14B0C8D18881BE0BD2D639A7D2F3BC5628F9574E923D74489CA281CCAB138B54F75870855923206B9E8BCFB6B41F46B7953E3BDA5A8E8A233865593A41F393C05594FEF6AAD0D21D6969BACD767AF83E2C05A524E0C5B2EFC01609C5F7AFDF6A2CD90BDD871475B703544AE98A4DDF412084B0A8CAA4321007D12DA982338FB3311238E26C35F2D5C7EED3E4BD6F5F932C42E0A790B17BC5C974BE06113B70D9B34D7BEF5B5D37662A698F8AFD529A703EF92686C27018828D114A1DA99492698BF66F2A801E8C97BE82786B458429DBF7FC1D90390B438E6B91D021FE8DCE180BD28F5204F373CF45BBA390AB9E3977FAC6AA1B680C49832F7FB649EAEB80058FCBD1E4E67B7F4A065E7D80CFD90146B2D0BFEF64ED0AC34E4FB1AC2F1CDD51D1A3A10F99AFA145CF94E374929C139BB64D5B143C1FDAF309B15BA0A57686F2BECF7FF886CBAB80A3886D94B2C99BA026E1963C6CDA0E50D4242A4F78D4C93C171F47A8457FCD3BFDA4CFABD771E41015EF13D6479E6FAA1EE63BA568E7DFFCC7DDD98EBFF25C16C53DDD3122E1F33C3A18C6D4081076324D50EEC28549F3EFF9007726BD7CAA24004C778BDA91B88DE6175CA3A9D26C0074F3ECBD8A5E980B41CD46E571E1A462596816A711E816DAA1F373FBEBC98461A05E47E3C082FE88DC300C95AB4112CDA18BB7956FD530E68CD8C916457ED0CE6734CF72560A8B675C0AC8AEE7DF585994E5FCCE96917E2E034E07D6EF7114C74BE2F799EB98D1BC78725FDF26AB22CB9FB25FDDF7F8A7B122827564563E400EFC7FFE34602E577EE0427892BE8D5EC42BB4764C4CDC0C779FC057F7CF8411CD966F45ADEE37853B3C988DD739FFB5126C760323D83AE1AA97D979D9DB3080033208B5DA3CDF7D98445D336949B28BBB27C282F9B0779FF04AF813E5DD203E0EB21C32D9CF2B825F150E853D4906C960CB624EF33820290DBAE1EBE78E60888DAA2D72B865EA952BD21DD234513019551BE865506BEC1513A187682186BD5C482ADCF0AADEEB83D05601CD570CF0E406E94F557A3F8DE99EE903CFBBDBF2C50B3A33FD6BE722804D2D64FB91D6EBDF5BD762D78C86D1AC2976A85CCFEE7CB3CA718E706C41AC8BB41BFC2888AF84E7E3A6088087D669098AF90EA6D92E9BBBB37EC26C1C9A705B11C71A442D32ED65BE2D79FA73C2F99690A21A627891F2BE7FCF340477AFE57A6FA2E827D05FDB3A4AF6A49388FC062D7F24FFBAF8AF61503124D79EF179D32CB6F717B854F11B401908C700B8E4A38337C3E76C33525A93525845C614F39C5B7310BD07A88D7FA99558DB3292B3B5036F85A046FA38B040544ABE58C8DDE9F86362D03557FBECDE436683C5BBCD58A497AC07F7E7F3B62B2AA8BBABE4250F4C418DDA374DE6988F843B7F71517B385A9A1CF02931A0D9DADFB417722E17910530EF488309474E6D9DDFF56A5DDFFA3859354FE34B93FFBFB0E7B1822C832230DB644CEBBD319B2D8C4E2F689642852B34F2B1253BB58EE9B7C62B757E6382CEBE47BF5CD1D26F0ABDFB5AE5356F0944F82BC00B52BA61EB5C603B7BB0EE768D763B8ACABA90516914D5C73FFE5908E753F498EC7E28BC3ECFB69D8EDD76D313140FE218F3AD55BA76F3CB73E331BB762B7F7F92F75C2CDBAAA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859 +remain = 1022 +max = 1023 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_256.rsp new file mode 100644 index 0000000000..8cd3c93b7c --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_256.rsp @@ -0,0 +1,12 @@ +pk = 000000025E84310CC01CAAD0B2B1E010C15F6691FF24977EF626465F5CAC2B015342A52404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000200000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A5E84310CC01CAAD0B2B1E010C15F6691FF24977EF626465F5CAC2B015342A52404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD09000000000001D5DA3370DA40FE4B2AA8D93A4C52E009ED16134083746A63365266ED868E33160A0000000000010EB7A75A56A1497F0FC1FE5B3F6B396014CC9357B7FE8A6D2BA1B553EE3518610B0000000000011B23B9B57C09E7B440346ACFAAB7028D8821AF52CA85D5CEEE66FA4E95B45CA40C0000000000016AC8FE7754C3CBB4F71F8514603EAE30A764437F404409A1283CFF4B7159C0F80D000000000001CC6FF52DE53BEBD4E1D3DD11D0BE5FFEB977CA63FF2ED1099705AD3D5BEB1AE90E0000000000019B6C3951BCA1748DC7B89630F962DEB3937A4F8D15BF5634741113C38D2699F10F000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2692 +sm = 00000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA70104A82ECC99EF0F9172F36D2B461A6515DC13666B7F1D917746E7086F99C8F1A63E1C7E5A339AC394788015AB12B3532C7ED27D1BCE2B1F25ADC96165F6104861C3DCC2B150E1DD088C95AED7DBA928946BCC8351DAF6136F7335FA45EE8F4651CB9A6E98D556765100FECE8CCAE704D7AE90AEABE735C2FF46DC9FB302D2A1F4C33F371ACC4FA552FE83C254761E140E990474A10D5D2119D90AC9C2736BA2992026D11473619FC9D1857C50BD2ECB693FE0DD9C15EEAA100015D58F2D8F936E154B5C932078BABD1E9A3E3D7B876174311282D3C02D8463E268FB1542D967EEDD01DA7D0ECA0E3257F84C2813FD01B211B495B9191A48E3CFC34E056844855BD1EF463F5D1F9E9A8C7FBACBD29E2726EC1AFA11522536678005155E1CCC5562A8C0D1AE450EA842EE72F236381AEF42F2445DD5B9CB2A791B1D95240D10FE14A3343E73C5FE2CC524A7FD21FA547675C86F6C8D4EADEB1AE29060EF687EF65344A45A5F1033DA0B50A5529AC43435DC3A8BBBC986F1ACC1AD60CC13F9BB26A1F99DF207BA4E2C7B1A4A0BD8B5B9529F705C1C323AD93B7F67D735958A454CC7D6927CB165E25F6C4811F8D486A34DAC2C8A920D506682D747BD6496258BB4011164FB8F12A3E984085401E73A96C5A0B7A661F6D9288910CCF1C1101E0BBB68646191DCEFF06EAE14F3762FA5C231D3D57770F230802C2188D108FE326778A10980AFDFCCD50CB32C844771C1B5DF2054A7F9D19FA28F461E81EDE49B2D780FB3FCF424A28FB9B2E88CD08E4D4BCC31E1BD06481E817980FA8A40E74D0CECA78B87452100271944681A77667368E04F077001DD9B1454DA4614F631A83335A8C5B1F83087C603CA6D731A4AE32346FFBF5BBBE7FFCD206304CA468789748789EA6620D7C8AAA5D10EA029C3EAF78675E35C29A598CB5624FF0ABCE0548CD6C9DAE3CE9BFE4665EE57358DBEC0D157880889597F245FA042D00FFB56066AC873718FB1BD12E0428923AEF51F55928C8DA0D632382E3325E4CC5C6A3EBC4776C9F6520EF2C6960F0129A707F90315AC1AB035A7BA0D293A6400C30D363DF000F53D309FCB4CD455AF4290FE44F8FB76B6C32ABF15BAEEF44136CCD739D96CC95B0DC0EC8186125075F21570A6440A5967CFB83836BBE0FA463C0B6692A9C6D673038D17D343EF79BA50ACE3835F6216C3943470012081600FD81FE5B31B604E946A2328C40E977558DBDECCB8D643E07A573A9CB5DB4518877320FBB4998BFDC59FEDF2EFBDAEA4058725054A1317CA755D3BDD4780AF57F3B76649B3675DD9DD95A16F5CBDFCE00CADC229C2DD7B4E32D6EF82B346C5900BD03164C1896A4640F8B79FD7241614D2FED6D1E2E5795827F146C2158BE0A39E9556BCE1B08B774531FBFED5012C3F1DDB0C27A8503A43AD652AEBCF8E6F904EB09F30AAFF35952227395C3151F2927727015BE31E6A03C994E8011B555AA21C792E806511407B653D1CFBBD97D1D4CC87BEC5E436487DD454363E2E87AF3C2AD4590B98E9597885A533623BDDDA308151FD4902D8BE5EA43CEC046E62DE367D9C21F581AC2EF46EAF0F0E10438D4895C49FDD3049A23E32561BCEAF00F0C192BB9B2426CBDE0CC3E6186C3228990D0C0703BCB923061D0256CA76F9A75429F35CF416D6A93FE80E8C771DE016EB671CCD86B9B221CAF0C521F58D8BDDD226514234C6D44554A5943C782FFE265FEB6309F643277F09495ADB42B4C362E1EBD6790AEEB0C5329F797809B1A99E617BF85395C38D7B367F2C2AB5E26A156437E7248DF2E9F2F6170493DDD3FD0A0CFEFE8577D87D69AA8E668F66279BE02DEC2D05BBA330A504C68A7E81709454395DB2C55345262308C2443E6D245675277291C8E6718B222332047A841B2EF96801D464F6EA1053BF96F6E69F495D45535AC3FD4411C27FF7DEE1A7BE429B3D9A386E40B99329DE24163911705BC3137F0C728AB5848532999315D7DD980036E8107AC3A68691D840FD37C6950FED7E43C79CED8DB06685476979EB357AEFCBB1CE969D9C37505FF2EE6B27F8FCED566180664EAA36D867E2C702C6716A8EC826FAAD00204EE915AC2241D72BD22B8C46387703E5005F5A2FBACA6F84D5B6250F4B5BC0A2A6A31DAF9C60EB13C20CC649A18E27A6C98B82F08E21775133C937E715F8EB13518C059EDF4585E7446408D2AED56F1AF125187E172DA47D9A150ABAFCBBB6BD37E68B51E1E3B76A88186784096804E0CA23134BDB161B70F2AF126A3DABA5C918B224DE444B8733E6FA601B3D349307E94583D0EC97649EDFF2BD44402B649537B4A3AB06D71227E40BE5A484B47D7364A839A4730A09D12310A297840646C5828AAC63A9C3D416A375BFD3CE0D4A35C24762B458CD70B23AD28725612F5FB98FF740AFB457915740084644120ADD17B445078AAF541C08E140C4F0E8E005322F8AB6BAB5DF2FEF6DC1EEF9555B3FDA2C9354130A171A704637AD2E628163EE49D33FFA1530ED03F0A3E771B74CCF546BEF58EF21DD1522538D7ABA7F4A83155F8567A89BB7E052994F9E491025A37F3229BA80485F66F0BFEB7D77B5227DB43AC1360C86DFEDA86872B28FA47CE1C78A4DA2508F2144D5F353F6EAB57CC363587735255342964CCE7ABFB619A8072054867C554D4474EC48C059D2384AE7E36865F8DDF0CDF3C1B34C9783169B23CEAD96903024CE5D0B798AF6C9717BBC5DEE4C9150E8B271E12B53D2DC24D62BB1B522696BA13C595EED0091E7B3E7B5E50DB3DAD2516992EF120B950C8A22C5D1DC1959D8A6DE0E31E568B1B105DF9711B589CCEE0BF0A8A4597AFB9D07663D1FA4FE307488CDC692382EFB7882F60DC53AAAFDF2014CA7D27F8FA93C187A8371B41796557AE738D2AE42D887D10EDBCABE6AAF951E0A070D881879332064C99F8527A5EFF252439DDC6270CBF5906FC144DE1CBB74B260E8615FDB2903BBACC7A30DA76937CC982BBF293AF6DE61315DE00A8D15148487FFC0BA96489AB359231EF31202AF53CC22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B583 +remain = 65534 +max = 65535 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_512.rsp new file mode 100644 index 0000000000..062a0f68cb --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_16_512.rsp @@ -0,0 +1,12 @@ +pk = 000000058AA2D66ED8FC46C0EC0504C56F35B897EEE56E6E022C0020BA1B38E675296297D99CA20060E4954AD137D640B279CD2903DE768E1FBF6A412EA45B5A33EC55D54D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000500000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957C8AA2D66ED8FC46C0EC0504C56F35B897EEE56E6E022C0020BA1B38E675296297D99CA20060E4954AD137D640B279CD2903DE768E1FBF6A412EA45B5A33EC55D54D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859EBE1763192D55AC1F413982692F909485720BD4F9B15A9EA968A63EE3F4A698AC73B58112D644CC2E1EFE05CAB29911A95C103284C83290F67B83587BBE7556294C5225374477D7ECAF9AB5EC9460765E6A40DC75A84EC417263C50D22FE5583FF9626977B8826C06E160772D6B0506861A86633446A807183935350D91EEB5D37414CF3BA477AE353761B74E05BB6DC167E86FD20D1EBDCF5C7F6AE3C16116BF9CBB6B67BB564009B597CC2CA1B16B7B3B484C6B172A817AC71985522092AEC980B2FF393DEAB2A375CA8C894A68CFE3DDCF7CC0D468B43C6531A58723A8BB14E201B277155AE268D6A3D15933778611288CF4B0BF3A33C30C1A77AB39A8E6770125995651FA889FAB2B28C87DD556DD7260ACB83D691E2B9DA5880BCFBC2EB079B0D42F673A8064710EE9CAE5913E37500A2BF7FD4B6BB409F511117323CEF7EB39EF1BCD8096E4EE0F5605D58361BB74E6656935E7B075F389DC49BE4973B7C6EDB05DD051E120406EBE62FE8A1DB88A91CDF152BFD790E3AD2308C12B755000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B589FD94AB5C37762EFFA44AC2093812248300D072E964594FDE1E5EBC7987B59EC36D4C0C120E76872FB77366F2C5B18B86B9139DF28EF7D44E32FECC4C804F010000000000016B410B4BEEFE73CB8F4D4C3ABB7DF62F132C01D90F410AE51281E0C5172FC3762D01221D015C100F93020CD106AB5DC052522C419A0FD67AD1A5EE9D5FD62E180200000000000121D1E9B1C034C0E95BEA3582EBC57F8383D0F6D1DA068D3ADB5B2B6237AADEE9A89B9F772A990889B143707CDEFCD05608317F599099BCDD2EDCA4B7CF410EB403000000000001C23E183353CD7FB42309F34D450892A84D2E250627D82E72E4A582BFCA8BAD10D4F5A2CBC313BC02333F65E8FC8BAB87A19EDD304EC7F7F85AC8078CFA3ABEE7040000000000011E2BAE00E2D34A2B2CF6745FBEF9D552837C3DC63720847E7DE3094B58785B6043AC7DA8CCBB7CB127C7B0C7A974607349D30D61CD7F08BBE092A3F9C7BD0FBC05000000000001657D3C7D66C12770C0BB75D4F5214C4B194F841F23B240ED784A12295B734A173AE89D8EDD857516ABFACE192FED90D2CBF6254B4DF0CD8C0D3F7CE520B0FAA5060000000000014567D4BD416073A25CDF242C18DBEA42908A4D6F0F15266EFF60569D4C458758BFEC8027BDB07730ED08E3A23D0540D8B90A140E06A28CBB64891316084D93FF070000000000017B8C7C4EBC5F897F112AAAD0FE18AB8CE4360565BAECD1075FED846955A14048C88B6B5C1A065F92AF55BFCBB10C7C46B114C80E9A36CC3BE6A245F466351B7D080000000000011F81CA34F234A41958ACAC3BE7C53450FCCB7E4D785F18C94981FC721F4CFB851AB0550BEE14A4DDC57D2A9EA06065395660BF32D43B71FCE388DC6F3379591009000000000001FE9BB64389A416997D68A9C5451FF9E3E78396632F38598E5345173954CBFEC8673FBB2AF02559E05CD20C58416401806095E8E1C2857DDAB16D1EE0F3E190DA0A000000000001614A2C14DF18FC44145D5BF5D800B784E33E3A9CFF914651EC186AFED8DD7B7BE9DF850F296C864358A76F3746114A0E8C77DC4275625349967A30017CB236F00B000000000001F9DB099C3387CCED2252727351924A10457131B3BFFB25244647716F38397BB534828F09AE38D601A810D11DDD56B5EE1DA23E2FE2DD430E40465C7D6B2E0F9D0C00000000000105E33C911412FBDBB9E20A3ADC0B7252641A464D05EA7033F487C212AE41F3183BE15D981076DAB6BE2E3FD38B92902A67949DD0DA273D580B0F486C5A66B3E80D000000000001E66DB2720E5C55537B360D0F774F1CC73246C4145690C3EAB8367194A83269B7AB01804478CADEC9A748FA6B2BBF7F33D13C61CCC88F19A0BF16908E0B0BD12C0E0000000000015F9CF8DB14A3F181CEC637BA72FBE950458F42346F664729CFBBEEE0A492EB07BDD134095EB0CAB4FA91B361999C9BE0959B55087B34DB128EE3FD6C02D7E4FA0F0000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9476 +sm = 000000006686539E267711CC53D8B185DE1BEA3A8484A81CDD6B6B0E46CD6568189E74C033347FA34BA7448CD4D56964F49F730BDE52ED29F39B1CAE52DBEDC90A0941562F22013107A0B9A812D3763286B6DEABDD26B7D975D267CA8D98F7A4EF9158E8CD7254464071BC8456847AAF9C54BAF4164E50E45D0417F3E9C05E9C1FE81AAB153A5F0C71B1159C1481EACB9BDB9EB4DED57C56BF48661F4775A35225DE9D2EE101EF5B13D4DC507EFBA53E65FB539793ED8C45E5FE4763F0CAC9A29C5E6685571D9AA4D3365B9B1014A1927E25870871F9C8C0EA530BA455B0B2360C24B1839019549E1862D3AB46C728804F06859D2E974B49FA858282D752079D80E0420A9C94EF9DB7050E9D83A8AB5B37763812080A80FE3514AEA7C767AD2C637E7DD267A27B2ECBCCCA482C11CBB111846DC6EFDF105181DA3453CC3342CCDE25FFB2890779D5F57790F1339B680C95ED5FEA0B4E0DD7B8071149CD9432E9F2DC0D451735247973EAF1F284C8E0E4E09FB49A659505338C62CA09DB6A820D9AE34C95418FC6F5B22273C55A5A4523C7ADDAE31CF57D12C4F7A8472A5F3292A2AAE44AC57E22D3F2BA2104EF47CA54788A1D754230DA125501428804B85AF0D296A8301278114033F8B9FD1BBF20FED474C486FDD6598A5480E3F3C46A5D432930C1DCB43711B63341E31CFDC262F53BB4E355678AD71FBEBA8D6887D67E7CE3ED994B961B8EEC3659BDC3251EE7E92BEA91B17A8302ECE53EFB4571729FAD476EC91E2AEA3EAD3C30730D3F9D454B44C843B9E1859F8E420119B153F83BBDDA898961B77BF6D0845BC513419C529B3CC2EB61CD813633419E80C461B9F46187ABFF24D359CD067C1792B41D2A7001CD548F8E6BB1BAFFCACF72D29D5675356238BBC2F0A0AE53850FE21ABA0B9912570EF03454D3548411E9C2E2DF47FA81A08336CB05044958E94D96006B6B80346FD722EFDBE4509BC4C27C779EA9CE3FA6D4540A5A30852BAC3D98E69F92319B4CE434112B9E046E80AC8C98AF74C0F75C80E0E55FE0F54F8D1BFFA66BA2FCB3B39BF957F6C35F00BE5735481503B311BCB51F8085303054C88CE780A72CD3A41FF87C89FC0C0D19B5F14555B99B813EA0046FA9D421287C14472602EB5836875B43EAF674E37D971DC563A89399440960BC748B244AAF9D8744E1408EC8E0818371808AC6F10CEE8A4CD6FC25B5F616B4152BDEB86B4AB037E4E1BF59F6AFFD7EC15A55375111D8F8F2FCF710941DD0CB532FAE810F87613AF8B853FA559F4B7F61024A9D73E531BAE8FEAE72AF55A282EFE6108AD2DB94FEC5E3D9C6E052B9B67F5AF7C4469E00A21A91BED53DB2541037D72C1AB3EC8C8933E6D65A458A8A5A57744583949653BF9E771695B7C8D30EB9A1B57D15BAA3F89D28315138BFAA88DDD261EB3AB17EB6F3C4A85065934000B2F7915B326DA7C300F3E2BDC6DBB570C85850C88E0996753DB70B1C9201593B3A8E6ABC9D581604EA41D9C7109959DB8E8882265C7F8D12F24702F9BDB9BB4AF388C54A0AD6AB6B60641551B31D77CD08E99048ED64D16659D9B65BB8ACB3895948EC2B7CF30870B25E4381E550CED893B3BA2713FDC8F14C58EBA6F2CDB2FE3B2BB0310A51F954624BFE8A8139E9E37D329FDE86A56B1E3DA98EF9C3A6F654AF4E2E89E8BBD2271ADC9129C21AF4CFA132B4196FFECF5700C963268928C92BCF513CFC081409A6714C353C36A5540E163F57AA0A57FE68E2AFA78F331AB752173F3921B49E17CA30FE44412A904930D1BF967E9BD4BEE04538B02EA3058D0BE461FF6641F3A5E2B393972AA0943DA5DC0DE745567F22B02F60798D647A71A59A141E675EAC27961F95BCD87FF5C196F08766ADDA7F43E73EFA570E51C89D0A596D861A2B1731FBEA4D5D953E9E699721BAA76F564C39EFA91B1DC10F78BD396643AC730C45519FA0247B58ED7A0A4FA11342EC4789348C4FB12CCA3608E22B7EE96173C19006EB10BA46D8445640074FECBB51649B6FE90BC1C63503018A37400CD476CB166A6A2782EE1680495B2E11F5EC5BFFA5FF196C739CFDDF7430331E71CC7383F41DE05AB125B74D8F25C445B975C4BAE944F94E73A60D62C87EA33D60AA7F55DD3CBA1947848AECF5F01A9F253201356E02722D0531128893FD2ECB735D9BD46B778D1D00C245F38301F71B90D96C1359753921556A9AF55478B971B0FE8D8B284964A625D4322E90BE82C9067445E5469EFBFC33FA904261072CC196842470BA810566F2D5B553E7291CBA9A4FF8CCBAA223BC0D0E8044FF34795ADC85ACD048FCF710D31641074EF233CCA6611603F87BBCC47E20A9348CC567C7E23FF84C766A49B7BAE6A59F59AF957721AFF84E83539B8C683149A5787CFC4C05EE82C46340E64C486217CCC83C57C2C9226EED64EAFFA9923877514B46AA08FCB446DB1D731C742B8A17C6A652751C94387DDEF68C679D1ED0845026C68DA6B7F3E36CFE1B02898DF0EBD98FE88EBC2F3F569CAF8F11C2D66027B4C4A1440324843622C2E7D450E98C437BC5E66F02D3524F0FDA9FFC063C7DC91B56A48C2943D7D04B674EF6494105BD5F4BF79D4179031580E5FE9974E5EDB124493EBB0EA947119C50C4EEBE1A7E9EF3CF77C2AEB05E55FB902A867A353A635AF798F74BA88B9A8996964BFA72DC73DE5290966FDEFFC94EA8E767F9C977BC27E50290F3E0D9423F3BCCE545D594CF0B4ED7BA966F0BCDEA0172EF7CA8AE732BD24AAB99BAEF03CF970D3877DBC1F7D9F82FF63F316D7547463129BBF08604F7F21DDEDF5A3758EC8DFBF104738CF062F712D64B6F653484DCB6D8601C5FEF58EFA234BDBA6FB052F5254BFA7B7212FF8D6D03A03AA502F797E100790A3499185CC8BDD5BDEB0978C608B70E7F6D1646E7F89D2E70EEE62852C69618ED8AA136DB1E75D4A687A62443A82802EB270F1C91E97074F3A12C63FDF3BABEF882F934B4BD0C2468C6A036DDC3493F2311294F01D09CE5AA36E5A7AA830672F45EB2894A80E5C1937BAEF259EBF97F61780A84F31DF608E126ABE26038708017FD2588656AA416D24B89D52D80739EFD42A8FBCCE76C155BACF1B514C8B8C3F7276424A52CFB8444E548DB752EA947DF2CC1DAF29490FE79A42FF2D845E7A491ED6861ED64AA868A162C70ABD4C04B0C8B1BA523AD0B6E8E0EA210166D6213B94CE1275CAA2108DEA7BBAE6017963FBF7D5F7801685EF6750F6BED988D0C1FEF24FB9B75FF7C95A8B6A9DCCD666125E9A4A5AA7DA1B8E5B8347E1964D36F6D0ACCAFC14DD8B5DF301A3768F5EC7924982E1B57D37D019914A01EA0B7B1652EBA5C15A6843CE712C34ADDEDE75F42A117A14B1A9D9EC75594333A3BCC41D95099F30B7293AC6A76B535FC09AF856FA8BCBD2CF72770D48120A3FBA021BA64D685D58072257FF93A7331243A8A7C3D6507BFCC58E7F76D28FFA3EE36BDDCF6E389E9DFCDF813315D720773AC005EF78E77F093FA5E6FF281E647B4BD982AC33591B40BB2F2E2A37BDA9CFFBF08B0A1954FEC592FCC0A5C15D07ADAE82739FF85CEF18025B93C6AF3ED72D63590D8FBB6B7CC0EF87DD769819DD5A6E60630EEECD4BF4296F27D4F5058E20CB33E5B172442509EE7BCD817CA7C67F263D4F3BF41ECC6851986D74E49C1AD0D2C97008EBC070E122F1B19DF8DA264BA46BBE734F9B08A154167755B2A3089EAE043E9D1A4ECE5F5D1C0C080963C1DA98AF78A665FE477338F3F0B36FA7E2AC73992F509EE47C11FDDA16BD612DDD81FB9427C5DA2587154264BAAA4654441B46400F0481AEBE3B8A744B973169CE5A06C78071821E8E644CD5B66573991C6C0390B2B553534DB4D0748FB63DA09112D58D75525D6F73C94BD93CE121BE678FFC625D9241222CC785131D42D8B36BC5825654BAD71E7896CCA575E3A66F948EFDD54BCB2E574B39E456045BF1D8CF7327100917AD670336BBDEEEC25277E6DED2BA4B77D91CEBCBD247B5B91CA02888E208498DFA03EFE10C25B94C8F5BA3BFA5CEE079E1AA8A07F109B4701706A3F96BB3C049382417EE0E08605EF08B06D62AA092592D816631AC7394250971E2E56218B0320FCCFF0CBC0B670237D1D1479AB655780CD7E41D2D1582FFCDE1528CAB79AB734DCE747E58483C4BEC989818E91AB33D5E8BD6E080B8EF7437B9D5C7ECEE65EE24E6B3940E4EF18CF7D5A9B217A9A2C058A900BE7129B628E81E009F3758ECB3D278E456432D5B6A3EB800E10BFF7DCD958501CB055F8A20F5579DA1421F43F593B7F2F8BBCB6D90805AA9A9CC5E2456F530BF522FE5FEF9E38295AA45D6CD8BEAC16D5152B9505DB546924DC43644753A7A151C5711E00D534A288D662FA4EE5C6DE546C203D4C37192AEC06F52A9A1AF4DCF6A86A32D78F214823D1F0EB76B297C1C7B3DA933AE8D6405E3486C1284310237BBEF96CE1620D8BEF7C4035D1E01CB1A67AA4E613EE471CD9ECD14DACFF64C986CBAE45D3C39C1E2C36EF9DABFAC020014AD281DF4673F2F4072047F9C881CA03DBE28908646872A48667042EBC119D9D162C5343778C99858950287015D6128C884E4F335E65D7FF03B6FC7D954E7413B5619888474992800304D1C9CDBEABBC7466200AE6075DC257698C454A5C2DB560AD172FFA64E38BA5A8382129B23BD52432D10A2977683DA4A91546AE242CFBB5AF9B24978C4AFC3F2CA44543DA40D27EA7CE154844F48EC6C90684587F0EE3BA0654F8530D2A47182F6EBBC44B5585BF16653D6C81866C6C02813FB92E9E4B6D39D1F022AE14FC2B55ECD93DAC6595BE2F372A1516D1A4E6131E72AAA49019B359E4035C864F829EDF26EE08A45E9C252D6F76AC45DC63EABBFC641E80AF149DBE1E53F1EF85B66D3B813C2BD444D6E0DCB5C59E2978BFF9F4A60CB9C6AE0A9ACEFBCECED54ED592EEA9C9B0F9BCC9356A3D1EB7271329EBDC30BC8F8EA72969B03FC5AD6042DA3DB87C36C00A7F0CE9F28305E2BC72972239C61C973522DA519EE286B388A0C6AF3FDC3A09BED2D38CDFFA16AF6A517F6B73621B136C2C2D8E67FF6314D2DB42C6A3FFB19C74C0637BC530A56F8DF71FE105DE525BA2B24071A2CAFFBB0D37F8F5C3EFB5B34FADBCBB9DD2C092A0BE9B4BB0AD03ADACC8D06CAF6A980C8B66DB154F07BF689C3E9306A6CB6694AC8588CFB5F42105214FB51C576EE777608A051D9FD3850B22CFC2EF1F4C3A8D659AE6F43E74A335A14459F7ECB60CAB8A90294D51571BBEC69283E957B055A29B5BD7616510E8D782B7C25327FFB042E9B00F8793BC7268C0B92411ABFC2830042AAC561786D93178C6DF6051E5B520E8BEEDB629509B0B3581BA16D27A84EA94D05A8DD3F9CE73EB75027CF29D3AAA5FBA10F88CCA732D15352AA09E04E0BFFF2CFA60A41207D7C9D07B7E3BB1D39D93C4127454CEFB86EB828BE506E20FFD3A4BD3F0BEEE7239FB57CB8EFFE15B421A049D5A654EDFB06F17EF56BEB8B7E9F0FF2FFE632AC59DEF87DFD32129479284462B826A56E7F957C82037D1D753EF996155A8E13D8E4213BBCCE88B3713A079FD4CD25E611D857F347639367B25D9771969FBC13BA2161D64970695977BE8EC125927FECB9DC34EF4097CCB154B41C3098637CFFDEE46DACDD83A51DDF20CD4F2DC12582C937BCA1F33E311E40F7A35A98A14917AC8BC2934F2F3E68410C893E2B02A9B76728A6E7F72F7C746265D51FA1771ED9D2FFA4184D4EE985BB95235DED9FC782DBACB8AE478797CA856EE48A24941059B4CABAE9D48E1C4AB18F419EA945395F3B2530ADA8996D2C6A77D18D7E374E994BFDE761C04FE235DD6CF3AAF57E1FB12CD0585A74E02147E3D4814634EA9D82C5A746E8BD611C05EA798DA659D03F5B5F6D77BB8ED9CD99CDA42B176351633FA4C06BDEADF1867B2DA7D68D5BD5F915EE4988A16C8472450A47EB217310E79327FDB829A5B2DC0878026BEE398EF0E4CC70CD96BA57463A5B596FAD237E47C4923DB8E3EE9ABC263733FDBC34D05B3C0A133681AD5F50D817BF674486B8E3C3CED4654D4D93E2B8BFF92AC9FB6DEFBC1982DA0F50CB14F72301A25E3855602A6E8BF915509E4005AC69D7BBDA193AAE56A95B72774D3177A0988007CE34C97B4F1DBEEB95EA966E51A9FA7EB78AF76F7CA88C869459A5837D3F05821C7C5BEEB0508738AACA46D0A2FF361E47538429FF845488A14653D34B4AF836DCC39E1DFE62EF9700D7F6D01C3C5EBD31C87B03605C0A6903C8AF70AEDE6BBA5238426E92A7BC99C68B2601F25EFA92A72BB89C4BC86297EC8E67FF2B3E6BE96D11CD7C500F380C1E3EB68F7EEC1C16195ACB77CE9FD9E7E2D48ABF0FCCD27B1A058CD74E969DDE90D004128ED790B2E40F78BCDD3F630E4C01424EBC58F5C020A92BC81D6887DEB065B6252294B5B7F458BEACEE6B6B8313E23653C80C4C532CD2E515931E6452EE883F6B124642F9657328FCCBF300DC2567E2118B7BF394143C6D1FDF380F92EE15C07BEF9C18A4054EBCE1ED59AAE8318725EBDD388948BEB3BAB282228C743B3B0A62AA7B64C70141BB187C77852C4DF2B90387E4E3670E2AF35E3D969E7A516D2FFF28C7C0799396E5A7FBF936293C3633ACBD50BEE1BB396E04D228D6BCB5F1CE8FEC6E54069593FA0DD244B61D017DEA5007F2ACEEA73C208E7129912849B398D318DE57405AE4D82CE8793AAD854DB0755CF659AA3A0EE83EF6AF166D81383A3CE1D5C0917074517C9C68002E584C47FA0B6188BC5C9263933222D7E106499F98B42B39973A65CF611CF5C9DE267487DBD9E19529A4C02321EAC4794A43070D8CD97E7732EF97E53621D203A5FBE0ED3D3C5DB794083784744FBC4E66D7114559BD343A53A582CAE18A8451122F93BBE34429E7B2284F1274AD7933F26ECB2A81C8D5DC60BCB98C9BDFD7D6170585D4813E93DCFC6133EC18794ECD9BAEBEC7DD31D80BCE151B61CE42DF11EFD55AE81A115D073F7414119EEBFA05E73D43A2D8FCF1CEC1D7FD9F0D3A1AAC4E5945A1D8400340D7E8B3F1701DD57CBD4261AF00736BC25499356F02E5BA7D0F19475F7397269186697D33A9BF4699F1EB385E08059712615E3C1F6A03C0BF8959A78E3960F7F2C51C6F0530B217879721431260492C1B3B7F9D074DC62E722798C9804AA83EE2779C73715AB5B78F8639D8D30F9D54671023D8331EDFE4718C78D79980A446F533F8556B16BCE1A1C09C607C2626525052986F3818BABD08ECFA78D7C11FA71519AA2DBE8A3B34EE82AF05ED10D089F7DB006F6D92AF90FD0962F8EBCFAD63D5BF41D3A51AD570789ABB8EC53B37C3904D7C914B83FFA8206C968814F82EB25DB9893FD427DC0A9A584270E306BBDB4EB6853EE37462F4EF562AB2A26B6B520A18D52489C566EDDC1BB61574D20E2A17B55D142A77E3DE415BB98C6E39622DB30F3EE02C62E405A5DA0DE9B07FE58A72B61B60011C752C01FCC1245DC3049691A145558AF755BDED22872431B0FFFBB7C2A09F61885053A19EE8589E76CF218A1CEE5710D962EAEC8F9C463936AEA8E4168407CB8AEE787A2C5FC3DA3B9D7F2C6985D1D812537AA348E2403E5C0A2451854B4619F634EDC83A193EF6A48921EC9BB4DBA821C890659E2ACF30ABAA37D70483F3B808A8F64F477E078AED9F6A87D2BC23D2AB079251AC645B75BC1500351F100F771348E043EBD2A25599CD72233B9744EA63F6C94424A4AFDC10B30EB857E423C4B19D41CEF442432E433A6AF71629EDB05E7809FC011FE3DF16FC6A56B83AF2E13E895AFC2502186964EB95D68FA0B39D11F78DF7D4C5D0B65DE97B352BBF256F41DE84DE4E399ABF4614713974D0364349E2C465C422BC09C779166D104BFAB82AFAAD2001C6AB97AA598DD9F8D9F17CF2AE19802E3DCC3542A04FD158A8A4961E7333AF64127F6A08B378688DDA8B3BF53EB0DAC1146B18DBC3FD1718E3E7E07821A83F6AF9534809168DE9C3D4EEE7283D4B012B18D119051D0A942C19B79236E427FE1027A46E0F1FDE1A68F45E36D4299E8DBFC690BB470457A854B8A86F9A235E8257F66A1DB0A704A39A78652E5928A95FB4C1889DAD77CCD4BDF90A6D330D0E6067C3B319BE5EFE2D4DD1B562413394A983DF3B4F989F74D0B3EC7D8A11865F3AC62F9D84932886D24FE3BF135E66D7F0A27D00EC010F88E0951A2B67F0BE92BAEE3687DCEF1AB008CE6A289560E90D41BE20C1E9E83C07D04F073938EC45416626FB219C7CE32DD9ACDEE512CD1E2A64B48B2846D97D3F57355BC68A8BB28336BCE8C1C33267BAF2EBA5CF9623FC4EAA61AC506148214DA6AAC02C8CE3441C8564260F3374E4461799C5FFB6A67CF34F7C1CACA39591D0ED86F6B1B5BA45ABBF6A4488E669B281B5058F92C89023FB0C482E0B245052B45A63519CB6F30486343C8BDA9F47651344F15C876AB8CB40FD8E694C24CE5318773D6BB148A67F9EF7722A9F4E1833CEFCE62C4ACC89622AFF50CAB1101906402B2F91BA0C4EF9BB59FE5F49C65B2F993F999C212ACC148CF04AAD8D5910DEF892441A3F91D5289D0F2F5166506E6EC068F2042E69746BF2C20F0463BC40F0A4DF6AFB6577666E4B60E5DBAB251340BDE082420A0BEBA2D3BEED60D17EC30C7DE6304359ADDA83E9E86A9A5DFAFC8AD72256209A8C6E34DD0907BD6BABD698F7748A908534FB2A986BA65B1DEF141CB0BFFE420545A293BD648836D22C4B072EB60FE3C1E4524540495B5D3BE99E170CFE6C3CA4C3B72252A0D4127A3BCB1DB74818BD259F0293F161FCB8CDF54D957F7AFF6118452CAA20F38DF881FE306C2E918BBCF4D6E4776658BC27FBA1C88DFD1FDD80D72A4FEEFEC07F78F76FAF76A3B9803C6FB8BD0CB2588D1766F4A930D9DCFDA7E1639FA0ED56E5D7742F6F55CE9432C57685DB5B7199BDC12756C9BEA29E22A6F6FA3B5F8BA2B301FB3D9E129014B757F21155079B3FF1C5478BFD9E8123B9565F9AFCE4C0E75C7C4E19AFD397F2FD5F9CC2A3FBC7447AF54E6BA8051A0CF5F35DDE7E4FA4238909B202C9134D36CD7F5AD05EF5D671854F39030784B7531B757E8F9F4F710A4E714E2A97AEAADD6FE9A1DEE57626BB2A360383D014FDC273C11A18DC52A59D7D0E7C756D6D48F1394E25A5CE5025222471AAE0AB79A9667DE5CA3D97D11E2A8455A77ED842744C5CB5E3E810B543ABE67063F04E6BA5388C61B8D6FFF48971E7D16F1D519DF56279CE71768AA7EEA14B23A420FFF3761968279CEB896460ECBECBE5785E33AE248E1B309CA20B7F7E70AEEA065888A2C20088D0C686F7F566811FA6D4B0747786D5EA1F91AAF7901F6185EDB3E0F21C611C8E084BF7594C3AB0837429DE9ADAECD98EE324708DC1CDB1EF927F13463472253D413863F7E89DEE36AA8CB604CCA4ED03030551A1E448EEEA671C8FE8C7A9A88C3BC7E8F0F06FC9202FA988E04521FDB25ABC209D0A134B0D2A84032F503B1B0FC206077349A35AF71349AEC444427E398BB33F4DD668A709DC6704CBB40CC126683080FD9EBE5822333B72D71B4BC4E15F7A17634A5E414932DF52EE6EAAB1E2CF2119C0F4D11E8D38907F7B3307E655DB30087AA2901A4CC6EE4D15F72CDE62F429E2825F5B7C70572D98DA4ED88F56CC1DDEE36D09BCA15FE29ADD81EC74CD0F9DFC2AAD2CF50D71454AB4E04F3A8763E3EBD3F31FD22656A0A846925DBAFD0DDD107D9A86AB28D8E7F8D127CA642BCE5D010562B3F2D5F47014DAD1A88DAEDC54C3547560EFF5E764A20966B860273D35A686FEF539575B8898C3ED6984E0BBAA6FD5E8BA596CE548EB72CE5F7A7E53022CBF8BEA53EADC6EA1F4D4EAFDA59807B939E02E8417342CCDF07D00DA329B3FFFFEF94B61BDA2495816C551AAFFF946D2E3C0B6721584620FC264CC0293316411AB56EB337F613326C456F2D59318D45CE4C11B42A08F2644940EE91DB6B709E07DFF670EFFB7D6B5F74089B44DA284571AE0AB361E233A76A099DCDBE955CBBEF8CCE129A3CA380E8C45D3879C65DCFCCC928F0E4233B8B6BEB60C5EA34D691BFCBCE45E469510F3FE1C5A37C93AAB390B352790849E7B17A36B420E9C8AEA845EB671A2C9649264425B9F2A953114FA75B2161D9EC058132C4FBCE3587A24BD8C2671E2B8A1D29727C283A43B88D270FBD9A7978D9FE6EC869F4D9340321B6A283891010F801AB780927F7688B5FB73728CCF39291329C6B97A445587C0A1B1AF2EC8CD86CA83A912B6AC359F9B569988CDBBC22F5591F81FD1F97C205BADC0E62C390E8426C35AC602ADB498EFC1E8A589134349F2D901ABC7637793E2DBDB6A84803A6A5516ABF3BD2C4076BD44F7E8927D29F5D618DE1B5CCEC5A16C57D4DBF5741EAAC41008312B14000E27035FACF21B175075FDB9B0CAE9904FA41AE4F19320A1981B1D4D092F62F84D404AB8688D0A614D18AE93FEA9C5211B9BA81C573C4452A405771D7A88EAC32F7AD29EA64622EA20C9D9239D4A064651BFEBD64F9938961CFB26E832053F17FF9D6DD2F0F463E2BE1BB92BFACE323B15DD68927C4365A08798728B1326E43CD8496D30207B0527AD68E02CC16E56B8BCCD23DF0D7C5E3047220BF7ADDA607F4EC540F47A1FB0FF28883070E2CCA49A42D364646D826D34131B971378C26081B861AAE59EBB9B714FBBEC97F5A3E0622D02BF5704FFC48AF154DD5A952CF43830C8C9931F2F0DA2DE2F94140717D3C9B427889D2FC2394710F501E41FA5DDCC509391FA97784687A115574E60F723B9CC83A68280BE41B5014F02A3486C6F5F249C430C1E1DACF9A03C410174A386F6275CEA5E101D53E7025971E7226693DE2CD39395EFC763A9E52103F00E7F0CCF2C7EA45AB213D3F37608335403E6551D2D896621EA9678C68EC2395E86DD2011EF70915CD9D10AB88C52AF27FD0067630F7AE9BD0504951C9316504373B2A60F155EB1E49119480746B79B4D4A67A5BF39912C69411737D16BF3CF8BEB29CCCEE94D309979F2B757A07C440FA9F53BC9056ECBF6FECE40CC20AD9DFFB3CC0E16B0E4D7BB9389D610A965E9A351F03F7B2F35E141E1A67E75F1DE81A1C941A41D6605D0EA8F1D9D47E93D2F65ADF67D96EAFEA77342095E82BCCC81606908AA41404CC36B0F58FD0943ADA9571259C253236973C1BFA8F82A519276089219706E5092CD4A940EADDBA5FFCF52D699F30CF5CB4B1B6392D9C33D00CF632333A06EA1ABCDB2473F65835BE2D3E703DAB2E469CB78A0095561589EA0B114A6BEAC3B1EDEF9764E2A4159194E0D5968FBAD672332FFA3E6E3A82FCD08E8F7443230F2AF4104C3D8537E1FBC1057691037DE846EBB6426354B80BC635C61BF2B9411569BF5E339AE82276D400EC319A2E575A39CE1A662EC3581E428D4E74D285EC5E283FFDABEEC19A1130AF54691E5479D4BFDE9E5DDF4D1AED4A8BF69411F9F6720542BBEAB7870B8E1BE43361BE2C017AAD2C10915686E506E872523E088B80E0CB5AFCF340477AFE57A6FA2E827D05FDB3A4AF6A49388FC062D7F24FFBAF8AF61503124D79EF179D32CB6F717B854F11B401908C700B8E4A38337C3E76C33525A9356C31A70691496A56A0AC6338ADACA88AB590597E016D913CD21A91D07AFCCBFBC32C6BE8B19121EE42FF926B8F55106D15B7B6301E6B0E456EAB19366F057C9FAA8BBABE4250F4C418DDA374DE6988F843B7F71517B385A9A1CF02931A0D9DADFB417722E17910530EF488309474E6D9DDFF56A5DDFFA3859354FE34B93FFBFB1CD2F2E1B4C72CE4A762DEC2EA1B0CCEDD01D81B69DBB663DEEA0CCC04E0CA9017162A72F288BECBEDA8D2FE3B2C31859C3C4B7E06ACE1543A1A8277C08BA6E0A5EBB08E14CFB334FEB3AE84F99538DB994FFB3DDCFA5B7DE509FA096233A13EDFA21C59A49C3B33420E148701403C7FFA694CF5C5B45BBE6CE596E60414A6EDAA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859EBE1763192D55AC1F413982692F909485720BD4F9B15A9EA968A63EE3F4A698AC73B58112D644CC2E1EFE05CAB29911A95C103284C83290F67B83587BBE7556294C5225374477D7ECAF9AB5EC9460765E6A40DC75A84EC417263C50D22FE5583FF9626977B8826C06E160772D6B0506861A86633446A807183935350D91EEB5D37414CF3BA477AE353761B74E05BB6DC167E86FD20D1EBDCF5C7F6AE3C16116BF9CBB6B67BB564009B597CC2CA1B16B7B3B484C6B172A817AC71985522092AEC980B2FF393DEAB2A375CA8C894A68CFE3DDCF7CC0D468B43C6531A58723A8BB14E201B277155AE268D6A3D15933778611288CF4B0BF3A33C30C1A77AB39A8E6770125995651FA889FAB2B28C87DD556DD7260ACB83D691E2B9DA5880BCFBC2EB079B0D42F673A8064710EE9CAE5913E37500A2BF7FD4B6BB409F511117323CEF7EB39EF1BCD8096E4EE0F5605D58361BB74E6656935E7B075F389DC49BE4973B7C6EDB05DD051E120406EBE62FE8A1DB88A91CDF152BFD790E3AD2308C12B755 +remain = 65534 +max = 65535 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_256.rsp new file mode 100644 index 0000000000..778c2c0169 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_256.rsp @@ -0,0 +1,12 @@ +pk = 00000003A7FBDCA19FC30ADB13F35C92F71086094413263CD71A0570C9C2F250CBC2842704562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000300000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94AA7FBDCA19FC30ADB13F35C92F71086094413263CD71A0570C9C2F250CBC2842704562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD09000000000001D5DA3370DA40FE4B2AA8D93A4C52E009ED16134083746A63365266ED868E33160A0000000000010EB7A75A56A1497F0FC1FE5B3F6B396014CC9357B7FE8A6D2BA1B553EE3518610B0000000000011B23B9B57C09E7B440346ACFAAB7028D8821AF52CA85D5CEEE66FA4E95B45CA40C0000000000016AC8FE7754C3CBB4F71F8514603EAE30A764437F404409A1283CFF4B7159C0F80D000000000001CC6FF52DE53BEBD4E1D3DD11D0BE5FFEB977CA63FF2ED1099705AD3D5BEB1AE90E0000000000019B6C3951BCA1748DC7B89630F962DEB3937A4F8D15BF5634741113C38D2699F10F000000000001F21F01A1F02A9D105C71E89A189791BDA7CFB7BC89003D2EEB2AC6E7DBC26814100000000000019CD3ED9E3D49C10FE36B3813045F452DD0B3CEB702EA9FD3DE2289FEA46C9E41110000000000010CD4EC639F5FA5159D505EFD1215E62E35B38AC9A8B36077EB263B10F5BB4B741200000000000111A178357024706621EF264E4A66422A6F5B9F4C24A35579CB17DC686277D05913000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2820 +sm = 00000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA7010C534B0D4C6FFDF4DBFE00E72405EFE83BBCF19AA2030A8CB163808482B6376FFD2CB50DDA1EDFD708F002ABF07D0001C3357A70F6511884C4185790EECECCC578715C21A26FC1E7A951C54A30ABCDB7EC71AAD92F2662BC900F9E9A93054CF39B9A6E98D556765100FECE8CCAE704D7AE90AEABE735C2FF46DC9FB302D2A1F4C3C0901B0B16F96846F8196BA6E2E8BA4375B3F5FE010A02661EE3374C1B28A76A4A8879EF91C329714FFDF118CF5669BF7BD65CBDB738CF6A8636F20F399855E5BA4B0955661EA3FC882D9D64954405502E2BEF7D3063D36F993460D2557C7977DACE2D6D7D9A77DEB151610372F7DA0C73F7B2A737064A6C62DD0CF4B69F1CE4D9BAE3589B525734E92F3F8D4D2AD9091B6C82F7C0189D3780AD854BCF3CD62ECA5F998274C2E153FFF3CEB473D81B551AB5F85CA351B4BC225D7942733BC8DA6EEF78B8184B2E355CC338055DD2A26DD02B1A0740CD15F6CBA4EF429254DBCE0CC4F4B00DBFFBA622360B091DD6AA817423484ADF53F5D8A30E3D4164F539899DF207BA4E2C7B1A4A0BD8B5B9529F705C1C323AD93B7F67D735958A454CC7D4290DEE03A74DB1B3A62D2EC10EA3C3EF2DB3375893598133F36B5B8F2AD5929164FB8F12A3E984085401E73A96C5A0B7A661F6D9288910CCF1C1101E0BBB686FC03DC302429EA2768093BA3B43C542F272E93D15A190426830A92526E5251912FE8153DDA93C92A1195701DAB2D2A22C9F380DD4984645384692FF8721D549A4CC74ADF8A5C2BD5DE48F6A923D8FD37E36377639AD73D1C7AE721D0152DE0E73844FC867FC8C029E657271B738EFCC1A39C2A64EC5DCA96D89BAD4C407D4F0CB226B913ACD451E7C65BAFC90021E665C24A2EA208A16D92E9C27BC18B9D59B7FAA8FD4A12AD43A403062FC7003ECC756E3E26F8B1BA47801DAA46173063E37823CFA4B1481DF4C88093941CB014F54D73B5058ADD52B6A0638C8F3341DC13235F18FFADE0EA5601EE831BD587A8EDB72F96744AF8B08AFF190BA55D0B25D47F33F84F17D6C15B50AF1684C8F4044CA7BA2CC196C7F3CC9AC2603194A9A536347F33972E57BD89F4E3AB7977CD3220C0D5E54911F17007973BAEB9C8B3DBB95D1483FB4C281E8137940969814A5B6FE7D1057E1DCFB7AB61415E94AA4338F0635813AC5FC9767CAB6C9B71F63D372BA40AF511C7259875386539636DD45512165EB3E72F1046CBFF94254043D879CA0B64F7BD7AEC79F5F87C11DE3DE80756E9FA3DFCF5C9CEC2D80AD509A65AEF0E3E663B7F31BCA437311BA799D4C2ACC13818BDA90266F7A362B61CFDDE0523BEB8866B829512E9B625A90898DCA3DBA0BAD32BB3F2B1687014B418E277BEF2F73A6CFC6016578227EA1A56E5F7655C68B27E3B486B3D2D5EDAD5390DA570BEC6613D901E5D75A913978DF9002D8AF64A9B4E6BDB7388057A17624FC600F3031D016E61D17E3E6A9B2771E2CC466B2A17C425E4F21F65131B4005AF392C685BEAB2FF1E5E4E886E1454DB240AFA0319449B4F3DACFC2FAFF74844BF8128A3B77237211ED11362BA8A6F87C6D103A23A7D6628B57D137C5264CC2E627F24A3BAD50EA4F75C7BD8998709C01ED5ACFFF08919C609F8F74BF5303C281E4D8D1488EFB7FCBCF8AEC5C4B26330A6CF6E4D798C1FA4FC6DDFE7FBFCD3C4CCC352F28FFFB9301C08B0731F472F6CFDED99EFFBDCFF23AD4839258197D6706C3551375B3F7359C6A8403C9BA07CDAA348C82E896416D74BEB3BDC53DC8CBD2A281340B78F7635419636A3C38E9D5515CF8A035A439D322FAC7F9853AD29B44EAFA7AA9A4ED2471B0BC91B4E1FDB7E6A80056C0F264CD1E0837F2ECDB1EC864CF6565D6F9ECA34C9B961B278867E8ED627C1CA3F0E05A841B2EF96801D464F6EA1053BF96F6E69F495D45535AC3FD4411C27FF7DEE1A7BE429B3D9A386E40B99329DE24163911705BC3137F0C728AB5848532999315D616AE1EE474D3F1C1DD7BC7F282E6DA92731914758830B8AF74345719259AC8366C65C61697E08F06B61AAFB4C247C6FC8412F815114AC9C3D9172C1B5CF22867D870CE2534C0C2A163DD971EFB7226AF5B9BE4351DE6AAA45F27F9B2CB0831FB8C51B0C6412F36BA064FEA5ED935CD8FC498C92D651E2C9BB0A294D35E87BE8B94C03E5893DFAD17EB8A15E5B131E62A0924331F3888CD95D68D0541171EFE3389CBEC636344A6AB01468843A94F56FA7FC1806448C09DA99219B5B3FF5EEEC1397B66DA61A963FEAFD805408782D911B79206BE9A53D04EB1ADDF69988D97437FAFA9FE1D707144A2290523A7D25AC1BB6206AB824556519D2B909E4D04DE8D8D35A0398398CFD1A6A4D5B8B9BAC3A42A27B05E91DC07C8AE10BB4636D08A9D08F444A61A465254F464EBBA190A6B09EF04567EA727CF57713F381DDD9FA8D431BD19121BCE533E07068AB0500B15488F2F60DC3C2BFE4CBDBD849C873D2036743E7CBED5BFC1F8511489AED9E0CCC0FAD5D9F1805544D2A20F56AAD3E0058522538D7ABA7F4A83155F8567A89BB7E052994F9E491025A37F3229BA80485F6823B9A3781C1CC42488414DD491B2F80FD91E049E56AFB0D3823E66A6A3FCB1660641E4368990B3D05CFA937C51BE7692B36F007281321B5F317242030B2007DEFBA495E0499587494A9B6E4974C37F5C006A34FF102A23985FA9F660326DA39E41C65227E6F51D5EC56D93D19E1D3279F668A13A2B3599139B265111473D5F8F0B23E656D7E2729177C18213323818435F2951FAF7288F66F9B7B6ABBFC9617B0191CC9DA4EDE34F511E0849E7C27115FA6EB6C43172DC2FD4CB1AF4C27A4A6874419356CEE67CFA51989ECB77328F87F18629E63A6732C5BEBAB4DB4BEA3E19912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70D982818E4AA66E926983B45F64AA0172AEB48B28DD4994F24311F28B2577791EF712689DF5DE30ED5313C773311EC605B8E44C297ED4AAC95D3B1DAA8631F7786C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF9 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_512.rsp new file mode 100644 index 0000000000..ffa415e6a1 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHA2_20_512.rsp @@ -0,0 +1,12 @@ +pk = 000000065711A97061C93B4FF7199D48104CC42415C4634EBA3647D8E51BB1ECB7D4C455418BDE977F20460E48826E531A7A59E7DA8746D7AD5D80CD059D8007C2E890304D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000600000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957C5711A97061C93B4FF7199D48104CC42415C4634EBA3647D8E51BB1ECB7D4C455418BDE977F20460E48826E531A7A59E7DA8746D7AD5D80CD059D8007C2E890304D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859EBE1763192D55AC1F413982692F909485720BD4F9B15A9EA968A63EE3F4A698AC73B58112D644CC2E1EFE05CAB29911A95C103284C83290F67B83587BBE7556294C5225374477D7ECAF9AB5EC9460765E6A40DC75A84EC417263C50D22FE5583FF9626977B8826C06E160772D6B0506861A86633446A807183935350D91EEB5D37414CF3BA477AE353761B74E05BB6DC167E86FD20D1EBDCF5C7F6AE3C16116BF9CBB6B67BB564009B597CC2CA1B16B7B3B484C6B172A817AC71985522092AEC980B2FF393DEAB2A375CA8C894A68CFE3DDCF7CC0D468B43C6531A58723A8BB14E201B277155AE268D6A3D15933778611288CF4B0BF3A33C30C1A77AB39A8E6770125995651FA889FAB2B28C87DD556DD7260ACB83D691E2B9DA5880BCFBC2EB079B0D42F673A8064710EE9CAE5913E37500A2BF7FD4B6BB409F511117323CEF7EB39EF1BCD8096E4EE0F5605D58361BB74E6656935E7B075F389DC49BE4973B7C6EDB05DD051E120406EBE62FE8A1DB88A91CDF152BFD790E3AD2308C12B75581541C17666CCCA89933F0BAFD5A0D93CB983D087BF3D1D8F388D22F6B09BC3418FB7AAB26A5754CED0B1F20E1DC38A0426E818B22F34C296DD19DBEE2F1E048C65EA766F8B9EAF074792D83B2C35D363CCCBC4516C9F0FDAD4B07A3DC3C44A9D27368A57F7C52E75500763BAF2CE58C0B9520E1CF94B584D0D9223312ED434D305314718BBBF41BD80668F2D6ECD82327BBEE9FD960898BC7227727341B863F9664701B3F77A1E01155063FF685D613EA39DBD04F12F9E72C840A286A1DB44E63C1CB55527BF3238DBDEB31328477B9089683B1F07A3A0034660ED39487C43D1DB76757D3F0A1D0B52C26E6713D66CE20A818A113D19E5A312C5127507A3C410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B589FD94AB5C37762EFFA44AC2093812248300D072E964594FDE1E5EBC7987B59EC36D4C0C120E76872FB77366F2C5B18B86B9139DF28EF7D44E32FECC4C804F010000000000016B410B4BEEFE73CB8F4D4C3ABB7DF62F132C01D90F410AE51281E0C5172FC3762D01221D015C100F93020CD106AB5DC052522C419A0FD67AD1A5EE9D5FD62E180200000000000121D1E9B1C034C0E95BEA3582EBC57F8383D0F6D1DA068D3ADB5B2B6237AADEE9A89B9F772A990889B143707CDEFCD05608317F599099BCDD2EDCA4B7CF410EB403000000000001C23E183353CD7FB42309F34D450892A84D2E250627D82E72E4A582BFCA8BAD10D4F5A2CBC313BC02333F65E8FC8BAB87A19EDD304EC7F7F85AC8078CFA3ABEE7040000000000011E2BAE00E2D34A2B2CF6745FBEF9D552837C3DC63720847E7DE3094B58785B6043AC7DA8CCBB7CB127C7B0C7A974607349D30D61CD7F08BBE092A3F9C7BD0FBC05000000000001657D3C7D66C12770C0BB75D4F5214C4B194F841F23B240ED784A12295B734A173AE89D8EDD857516ABFACE192FED90D2CBF6254B4DF0CD8C0D3F7CE520B0FAA5060000000000014567D4BD416073A25CDF242C18DBEA42908A4D6F0F15266EFF60569D4C458758BFEC8027BDB07730ED08E3A23D0540D8B90A140E06A28CBB64891316084D93FF070000000000017B8C7C4EBC5F897F112AAAD0FE18AB8CE4360565BAECD1075FED846955A14048C88B6B5C1A065F92AF55BFCBB10C7C46B114C80E9A36CC3BE6A245F466351B7D080000000000011F81CA34F234A41958ACAC3BE7C53450FCCB7E4D785F18C94981FC721F4CFB851AB0550BEE14A4DDC57D2A9EA06065395660BF32D43B71FCE388DC6F3379591009000000000001FE9BB64389A416997D68A9C5451FF9E3E78396632F38598E5345173954CBFEC8673FBB2AF02559E05CD20C58416401806095E8E1C2857DDAB16D1EE0F3E190DA0A000000000001614A2C14DF18FC44145D5BF5D800B784E33E3A9CFF914651EC186AFED8DD7B7BE9DF850F296C864358A76F3746114A0E8C77DC4275625349967A30017CB236F00B000000000001F9DB099C3387CCED2252727351924A10457131B3BFFB25244647716F38397BB534828F09AE38D601A810D11DDD56B5EE1DA23E2FE2DD430E40465C7D6B2E0F9D0C00000000000105E33C911412FBDBB9E20A3ADC0B7252641A464D05EA7033F487C212AE41F3183BE15D981076DAB6BE2E3FD38B92902A67949DD0DA273D580B0F486C5A66B3E80D000000000001E66DB2720E5C55537B360D0F774F1CC73246C4145690C3EAB8367194A83269B7AB01804478CADEC9A748FA6B2BBF7F33D13C61CCC88F19A0BF16908E0B0BD12C0E0000000000015F9CF8DB14A3F181CEC637BA72FBE950458F42346F664729CFBBEEE0A492EB07BDD134095EB0CAB4FA91B361999C9BE0959B55087B34DB128EE3FD6C02D7E4FA0F000000000001045B70F509F59A21D1A0FD0A9F8005C66F7556733966737A4C549A1C0AD12610A16CCE4745E8352426D85C4E0AF11B546CA400B2996B322C29C2A698955FD3F910000000000001D2D4342E8FBEE48D2E8AA9E243D9DCB48B35AA0EE43D40CE90B89731870E68C17200FA64C7A187130A45439DCFE40F0458C394F8C491F2041C1BDEABD782BD2B110000000000010212C4441F454AFA1C1AC6665B123A752D82426D32EDF0E05020D303C645B0A0BB63DD21C34037AAB34EE80578496AEFEC17A3FAFC11CE84578D979D73201B0712000000000001CB1D49A4FBAC9CE0FBC7E45ED2DE9B6B0A55CC9753404E56FF1FF2AD8EB2BF64224ADDC0CFED6A8C93CE346D9A653F16C3560C18A078D30146DBFA378874F62D130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9732 +sm = 000000006686539E267711CC53D8B185DE1BEA3A8484A81CDD6B6B0E46CD6568189E74C033347FA34BA7448CD4D56964F49F730BDE52ED29F39B1CAE52DBEDC90A09415613AFB9FFA4CA8FF0A1C2FE2CCDC30559D5B553C328CB7D274CF36CE9104C96584BAA8EB576112AC8ED1BC3C20B09B7985E5CA1956DD1C3DCDC22628B1F901162153A5F0C71B1159C1481EACB9BDB9EB4DED57C56BF48661F4775A35225DE9D2EE101EF5B13D4DC507EFBA53E65FB539793ED8C45E5FE4763F0CAC9A29C5E66851528A4BFD1D6DBA65C7F404041CC51F47969695388CBBC506DDA3E940F9137B1E47347870006F3FF7DD32743538EECE9616E083B98BF9BC4A12CABD07B8755D2FF35D87FA3535E4A71CC53671EBECE3F0873B101013D42484FBB91435D6F763FD9817383F1FC1DDB9D7C26D23BC278FF71B1B195699353E0645FE1366E41F5786254F1A42BCF162BEADC23571504F690F39AD1EAE858CE58DA432C62AB78CB8641B1C66EF57F7EF37F89B44838292B438697FE9BA3AC1E689C59771D7AEFBDC6E5902C14AE10F94B511BF3F258EE81D8086942B14FDFC7CFF87C4570E508E7CA7B80723F5A301E7D5B757FF97878807C0432A1B22A76696C5DE9AA94F4A1AA8F5E69FD57EEAC4828EE99DBE12234E48A253102FA3FE6298ED6FB7572BA4FCE73F55E90CBD9F6F0D111DAE055BE32913F0275722C5EF30C2A1E10D6D6A783C2AACE4B819F5F9B5940B6C56D2F81C7B3BDF64EF04C81DF8C57242836691287201D11D4986E783547912E7F6A1DF5013A440DF63C1DF428F8810E0D530E691AC07820BDC33A1971F5708A3E7A5035049DD4944B8295F801582C73A9CB00CC39D1E6081038A0F2B3ECB5C6AE9C4B13997320557FDE870FAF844F8A0D4BC43DC21A71E38F14ADCBA7F3E9288F3E2612D22B8D5249E91C3F01A1F977032B7463DFF8EF72327AAED145F179E94886D5FB90ACB9004C1411158CE2F663C14C9C6DC9EC143F048F00B7F0F0979098489058E3D6AF2BE145603B827EB8B76F310D28461B13C6958BDD6EA91274779E59A5CBB750BDD51C002E808093FEBBF4CFE94EC5A51685303054C88CE780A72CD3A41FF87C89FC0C0D19B5F14555B99B813EA0046FA9D421287C14472602EB5836875B43EAF674E37D971DC563A89399440960BC748B916D898728772B9F5878191B66D626705194D259D9E1F68BEEC1B9B8895C4245571D88C52268928B51529E0099A2D8E7D49A9F766E903238F35011D0FD47A1E81039EB665108E4C6C7B4C62058F09E406FA3474A1741AF851FAF7B23AC344D791E0C14C685CA29478975828AB1516842998ED710FE128F48FB5FB3A63C08155E232D0100CF0D50ECB21D9049F34764D8724DC4E45B70E456820666848D0303384E8461D36EA162296ED6EEDE9BD81379F7329347521E4E40DF1D7BC30E0A8E41C26531333ABA5FFF195127D0DB72CD0AF27CBABF5D058CBA7DACA16C469BE9040312B01372C0EFF86F9731D10414F293702EA83D0AFB09741471A25543A8D091793D9AB64F89827A659E3B3D515E1A7DFF6D9A1CB220D1D2351B6C724383C4B20F9131D1886FC3CAAE8A853FD29ECBB19780181ABD830CBBACFD53C98661883CC31887868910F3406E821BD391C401B02112D41C31535D4D767D7AE42DD72CE68D8857D66B1CDB42D3E89EB6BB9BEB9834B5391850743E2FB46C8AC0BE0F98E5FC081409A6714C353C36A5540E163F57AA0A57FE68E2AFA78F331AB752173F3921B49E17CA30FE44412A904930D1BF967E9BD4BEE04538B02EA3058D0BE461FFC2AEA9B91AADF42AA65DA4C547EAEA680F4E5E5E6D1956AE8081CAFF8BBDEC475447D7BD9A9E8078BE92CDAD1AE866B55B593FCDCBA9AD2CF989F833D15550971A2B1731FBEA4D5D953E9E699721BAA76F564C39EFA91B1DC10F78BD396643AC730C45519FA0247B58ED7A0A4FA11342EC4789348C4FB12CCA3608E22B7EE961E6C7461E30DB4CBC9BBA8A29D722B9AA021D162ECBCDC90AAE91438D78CA253CA4A1394CAAB5F60D363BF00BF738FE348117CD26DA9452E1E4DE630074D61C1489E5DB6070417D44FE30D08926DED0EDA454D7514A29BFD8754A4399E440DBEE6B78C0F4F6D0D6A8D1F51C7E0F7D506EE906FBEF6E6ED4D2E1DD0AE58D55698A6E6B717326F2E997BE7A0CB55BD4E3DD913EC26911B595BD6331590DA242751DBA012FEC296B5DDB01F9779F939512211DBDEFA51795892B669773CDCBBCBAB4969FCA853F3030D30935A08BB3FA4CBBD318889E9F2AEBD3E8DD9428522FF3734E77B3EF92D382809BB455BED3E95E520AA3E54B7B6F5776453E7F9F6D821DCAD970FD27D1583CE527F20E0237654130E185E50CF4D62A3034FF82F32FC67E60BA74E2E6AEE1C547F81A0C38FC23EC9B8F60FB49D998448BCF6A43A995B44BD169B93D688E52DD7B964A5022A1F3117C0D0A61EE2C1A3793262BF105EA52544456FCA11B4F0177AD2BB56F4A7A5EDF483D6C04DC69E9EF95E313B526BD2CA11FCD81149033684A733DCD232E2A280492770F6B264923F975B7DC8C8A5774EB2CE5EEECF7835FC6860E7AEB14EDC3E1CB2700B6160DEDE5DCA58855A70B308E98C5B2542A5CA6A7AF4E94C0A58E0C3CF905AAEC65CF04897BE10A426A359BAD9BC70B5B9401AB423C9159EBD60965674BE8A2B3A8B0DD37547B80E62840F75E4DE979B936E321E02F42EF615C780498C801DD99F0B361E0080313C3576FB79C88749DD8533886B110FCCFF387D0883035C0241C7F568D9666082D66FDE31DD16B8A1938CAE11FE763128D2C973574FA48C24E1C90A37CF221D830A9D1712DCD3ECA38D6EDA822EC3EA2FCD4ADE875CCB990076EBF4F224A82AD779C97E3B593DAD7CFD440D1008F122F0E4BB6A201E7E86258E90E5B2F212A2B348B9E1AF78622BE875D2293505CE6693D26BFBF0445B63D0BC1C25B24593B2B978E711C3EFF6B5688618CDC5EB5BB11A18D6488FC0C70F7B1DBDF325A4539216FDEB8E392B8C1034BA9B603EF6ED6473C8A53665C9D1A1E80B96EC50C9D5A20BA05EF423806458F7F9B9FFB0C407A2861DDD3AB3DCD110A34BBA2977C9630543A13A226CD2F66AFE92228D79D91AC8A8E64AE8481E63A3C0C2A97757C8ABDE5D993691ADB3C308698A6B2869C1012D60F6D82CC77243095B8EE6C3F38155C5CDB3C314B8A1F16553BA0F3AA85FD8611851C57E1AF1E0684F05883F772654825F16F8D27ABA3AD42EE7BA3369033B20A0BAC878286671A43373D0532B4FE562902FF31BAF65A90413A0234250A9C24358F1E8A18845E2B8BCEA3FCB2935D39C7B81551EA055339EB2BA7CFA2064CBE3911FA3216ED6842BC4656448871D9B70F73C74D347A6A78CDA23A0CEC7164B5CD5A176617435A1EBAF7A98E36CCA820B50F6A0FE07F09F4BE1C8E86C5C583B001A3BE7CEAA41994109A967D84FEE131B5ABBB38D730D79BB77A49376EA5A105C711CFBC0F7FE145BC3D2067C050A13AA92D7F0F1B312C8FCE42E4DE45706FA2481375188D3F10659514E97D5A5E1A54024CCC8F19654DA2B7E5CF571C13F525E39C117CB0E7C4DC5CD27B44263DDEADC59DDAE0EFC10BFFD525B0750E992D7EE6B47FF94D0C6B5ADE35DC9CC23A1B8D464DC765173947A8347AB27C679B5CE60B743AECCD58BBA4BDF44657EC8832E02188FDBF2B6D9D3B18ED3C27E503AA3BF2517DCAF9D6F937F34FA3C6BEB756C7DFD1BA21FD55F87C399349651BADE09B047F53932D36CAB6D9BCB2D991A3224602B857FAF27CDFC3B46400F0481AEBE3B8A744B973169CE5A06C78071821E8E644CD5B66573991C6C0390B2B553534DB4D0748FB63DA09112D58D75525D6F73C94BD93CE121BE6789102B7A65B60A4EACD5C6680A6195A3038EF74263D961B1A24FAD476D6697E4881E0F7B70AA830E2AD8B52954C3574A46D50AC6EBC5E14BA1FB2C986007CEF0068C809BCE684671411C783A766B7307675CA4D04B0DD86442B1744ED1B8EE018F83D9D68B4FCAECC66FDEE75EAC379E19D0DBED5C3473089EF153433ED2B558785E0413821C2D80E4EE91C2DBE5CE074B6FC405433A00EADDFBE023E8A4C4C221B36DABF183FAE588D0333871DF98F13D6C6ABFC73783BB250875C432335D094AFCD4375BC6337DEAD712E837050FB0C9ADFE917B176BED05D90333CC981DDB972D03A1235787233D8342DEFC761A8942302E07303C19CF338856596F0E7B57869F823161FA631F2424B8C32E2A05F45763DAADB4D6502FC794B617D6A6591FD7778BCBBE2AAE927812F0361953A835E716192A3C77C4FE7062D2210042D190514CAA2C62958ED7CF63321963DD1F310F0237C988B2CF0201223930C55CC0E4BC917410D50F6751E80684FE22F1B64C46F54197427616762D8E11E0B644A20A18CFD68FC2BC4F12E00D0945696909464CA8256486CC7FEA84603F8C612A7B0EB6FBCB1FFD250D3E0B78DC6B3CB5AB69D60C2E8EE5ED147A571322C4FF0B72EA8E0AF97B46A366AFAF27FAD33998C8B7C12083969AB0743EEBC91AFC80DC24534B3620EE07E0F2B062ABC74CD98DAE3CA6875E2F72D74D4B3DBA97A2B93D3D855598C89F13BE30E960F8D7EFD077C1CB5E7D89A19EFBECCA33657C639CF92F8EFB0312DC8A2E69620F4030885B002E6F48686DC28455A44B2453A89779EC8CC42641A1E8FB65D371C2C71AB4B54631F2F6F7B7C99E37B623D1BC55BD54576817B80D864BE46D2A2E802DAF1B0148D77F9CE21A3881C23DF956737D29FAE6E052D9AC14C5F6957B801552F2749A6FDEE111A2C5484610EFE230126A005D2BD1D759BB213F974B243797EE9A20713513FE4A32883C0D1D319FBDDE35C498700B0E8096271224D1EB627E3FDE3F54E2D566535C5D33F2485E686D4B56B0C674BC5D6EB60C81488344A32BFB02FF5A309FC45088769B98930C32B2A9F269EB83E3AA316C1A5DA65BFC5C28E26DD1CF6617F5D543319DE20054BE65EBF5E4A3C1A8E39498C519DBBEBE2974AE52CB322CA7647F07F615743B1FB9F8CB2354FF4A19406D59AC8615CE015A50ABB6F308B229FFE6D5FAFB71CC6F745131BA7A449B3476C7FE7B49EAE4CBD3230C2BA977BC68E6C13BB0035F79F364E480FB36B2BC032A2E3CB6B202674261F4D1911468E9C95B6BAA96FDE0EBE07EEB47C5BF9ADCFE3A276F79C84CFE48D3A5A9A2BFB656C8A9A87B76A602508018DFEC14EA398A05022011B056386BB8FB9F62AE55D7110889D53098A6E17DCB74EB2AB09AEB036A236473A939D5C3E3C42E7C54DAD4EBF48627C2A12BA56F6A9653B7BBB68A591C6B28F8E64681C3F925B21EC850B49EFAE3CC6FFF5CC5BB741FC4F76614D9746FFF59973214609723BE5D81F250291EC4340AB735D957B6315A88A54A1E34901740EE82FCD7B181F03708C1136DD681D1E75012CA308F1827001625E7E2DA5E183EF8D5EC42C6C158D567E8CD1C700CF8C77836D9C1FBBC57A1C24CE4DCDE060E084F27A6B6EA7CC0456807FDC54031FCB8B8829D749366D1603A5DEBE435B76AB7A47DC8F9DFBC4C594F668B17E2B91AA264B024165BABD302B3D5084A723DDD30192BCDE345F2C5016C2F9DA6407B5559728C4B00AD4A45803A84F74E8DDF421FA6D838B9097AEDB9E3AAA05841A22CB4FA5FA9CF5A69B9D592AA7FF2D9ED3B86B2F9F517480DE548575F0AF25B1A567E38891A9444E997942D12FBA7B901D1A8A66967EC85D539327194092B2EDC62631C56634C1FEAEEA62CD2F32310D41DED0D89B0CE73C6E973DAF6ED7306E2C06FF48D5F4AF9255F0A4E4378539EBFE6B40A987E4F2BB93BB3E2D4A5967C918D63FF56BD89FE3C91ED40F4969D351DAC55C03F5B5F6D77BB8ED9CD99CDA42B176351633FA4C06BDEADF1867B2DA7D68D5BD5F915EE4988A16C8472450A47EB217310E79327FDB829A5B2DC0878026BEE3989D15481FDD1527A6D9100A3711FE95DE06C769E78557653CC4F713FFC3F5E7FE129C80C30860EF8D5D7453E6AE14576AC95F1A18D6D116E4AA170E023653B391D7D13CB1463C6E6D861D3D35FCBB8218EE5B5ED0455E20FC7F87BF1A268DD767AE2B17E2AD3552D6A61722F7FB75D69168C09E62172A500C0B93377634E642D4F640330DE54AB18893DDE617236D9182534900361C2DCDA629BCF6FF71F8BA270DC68AA4A984A72F2A36CD3C63BD36662115B9AEB160DCE73AAA32A112761BB3378DA1DD28F6C4A5C39836BD0E4ED8A0091537190D10F84165906321759025675F7C19164B148F4C86ED0563E116F62ECDC327160DFB11BDBC39364268F96DB0221980B5510A38DBA62A587F6D80F4080ECF7819B5EC949B2856FD2AF0DE295274718D859D64FFB280C63546D27C98873505F49D23DA88DF5E3052769C28FDCD7AAB51122FF764AF782FF548DBB5E2FA136BC20167D03193146DD5711C0063C868376E114F8528159267E167FD17286319B743D488CD77F374B8A2FA29FE4C5E71E5D03D24016424B2BF10CBDD9495E7352F040A48F46FB33690DE20A30C0ACCCED872430F7A277B4278BC83939E90B07B4B548E4D541491EB8B997C17825EAFD7DA17D01DF34EA9AEF82FFB981BB743985F0FCD454D651421DCC7ADE9649559401CF7D7E8812642C1ABB88EE592A23D253F8CFB7B3F1001AB8A68DE52FAA65A44D75418DB889DE8D701580E2C7A9E96E5D00D7DFB65577EDE71019B3D2FBD83D275BD4E3AED01D19D40338F720CCEF2676243E67B125DDA3460A96FA4E19ADACD506BFBE751CD3F3E039473367EFBE4C6F88BA0A749DD9A6EB07C40CCF69D3560F08C7EA7AE2ADE605332EDE497369E08D04ECF303A30025C2973BADE39E4A5C391DE0619C2785A646956A908271FB7F9201515F8952B287E61509B3939CC97971D4DB0F146A2B6CEC952FE8E215BB4A4C4505ECECBFAB113AA354C3445CC9BB61CE42DF11EFD55AE81A115D073F7414119EEBFA05E73D43A2D8FCF1CEC1D7FD9F0D3A1AAC4E5945A1D8400340D7E8B3F1701DD57CBD4261AF00736BC254993A9A7516C849967BF35BCEBAD46ACD20EB2C4DBA97718DD21A269EB831E429CF863474CB5276EFEE181EB1AF88E6C1AB7B26C6205A8178F006AA0029F7E2D835D4959A0BA59348BE988805AC9585172CB1AC5749644900832A67D493F54E0D898E7606276073226B5FA8036437067D193C744C0115F5C71E345A48F96A4A7B10E58D79B9A0EA10C545DA202CDA1B4AF08A968B218E5C43AB295740FA5D36D9B611932B9E0682A1EE6D5DBE228FE90E9C7E169748261E1C566EC82308884DB143C3B5C73674360B0302F946C4B9D42654B52C36DC38235179AF6149A395787727F630E454C76CAB55DC551D0A84A679223D10C8EF900328582CDC82416A30F344F42A77E3DE415BB98C6E39622DB30F3EE02C62E405A5DA0DE9B07FE58A72B61B60011C752C01FCC1245DC3049691A145558AF755BDED22872431B0FFFBB7C2A0994B3D48AC1EAFF5EAB329675498C77ED7B9520EE3588A35A48319B7AE6566F002BEBF7B39BA6A194FFB695D092A26E35CC52A2106A391178F000C931B080577CF88BF1498BDFD153C8CD13C4431966F9F4AB5A2046D5D6BC3E1758C9CFAF8DA5AC283A1AEEEA5D9B3DA041653047A088F4D1AF809549AEA457D02FD4DEC195454F12E6386D28E54A26A4F0D180DC2C86D7E892E82E29DD66E252EE56EF1F0F9E5957642BABE1DFBCAE474EED94D756CB59DA77C4848F75A96C16C5F5FA4F162DF12295985B731655D9728699598D2DFAB4E66D9A4B2A8F8B6A20FA28A8B50F256FC68626BC83637BC9604E518DD6386CD4E2593D63AAA722269475FC42F22787FB75FF59280A452633564FD89CB9BAF7C03A59EB278D7E02B382FBE98F1326CA6CE1DF7A91C6A4791BEC4EE328A9DE2C83B771A939F7069C5E2A39AFB6F39AFF4AE266C4AAE3D59D99BA1E9242A33EC319CA09C58F278CFB8B394DD6336E16F2452E155263728BEC16B81117A4CF98935F50767374587E4B7C82606AFD0CC4D2589A6A725D4DEB5EAB7F385E02099801D4C35FC384D5DB22E9C1E42361C7D10E82FB6919E74D58671F5F80EF98A29C800051DC8733A31E7D0F7B5199B93BA4E8B86543C9BF6472DCF27DEF21D432FA95263F5415E91766A1A01350C69519E728F1EA767941BEE87370EE8CBB8FAD0361E45CDE8412F04754DF98B94BDF12E42B6870169358AF2B12A0C99DDACDB7BA6F6E5EE0D8D81425E363B1947ADA640ED116E397E51955ADC8943E5435DD39E109EFECD67D7857B9A90D5344ED690E74CB0E074D499381374345BE36FC21208808AD9AA817023BB0515305083295E88501AA64A55EED1CE2D9BF856B6E3F8B7246F796F81628E623FA38F935EB2ED6194A40AB1FB08C82F794CFE63D7B448D9A6AE1183DF1DAAAAE8F4C4B14AFD727E5267714E7C731446F9912A567AFF9CBCDADD513B09D6C10D8F509EC9E42CFCCD6723B66AE50E8343085BD970267BB98C3553BB0C94F12169E87485123493623FC4845CE4D048E0709CCB3186107127DF0B2344DBA35635DEF2C2667808BC835D534C17FA77403DBD6549A9BB1C209C98CCD745E552786A268CC3E9D1BD62A980E1627F030BEF0FFE7947419AA8F702EEE5FF8CCAE5DACFCDC8ECC89670BF8E6A0563AB65FE27E27A47D18D82CF8003332F59DF37976DDB719AB48035169C6AF53DD2EDFAFD2512CE3B73D53859455B456D756CBDBC3EA9E1E869EE96002CAA7EB6A7CA6B786652E3D4F796BD25A912E159DB9EB8DBA66FFD815C61406CE01E494D29B96CDC5E4D44D98F13BC42BB696FFC90BEAE60F325B178500898B2561AF414B06C1603DF1D485686A419C4BA076AF518BA6A9F1FA808C75800BBB85CB28124A46364495B8617AA0D089B1BF88C681E73E9A692178DCBFECECBBB429323ABF29CC39AE714620F2A44C766360D51A25271F419FFDE94B390CC7018DE603418EEBFC3A0F88277FB9001CB9217DB8E44175CCC3AB8F118BC90B870BC4D07E656F74984AAD630DC431888301214C77E5468B0377D87B80D9959FE15BCB075BA4B99C7E6B265CDC537223BBE9C17A5A67B4B02ED243AD935FA8C76CC9E287052AB1473FE17BC4BFF23788C3FDFA8FF286D1EDD9EA3DD9518AF14E4D44DF1521732D0025E70A8AF60C121E236047EBDC5A26B287CB844DB787FA5C7ABE6A06038C1B17F40B75335772ED71766511C2A23CB2A1D82313BCF0D5B852207248219D195CE87C6F4E0A9D7E1B35D7475BC5B0FB5F4ACE00838CEC43F4AE4A5B6C4C3AD49D6E83244265626747EE6ADAB13649E7FCFD9D572D0939B348FA5ADB0B2F9F2B90F0080F6A60473ED136BC0FB14DB1DAE2AD08EF52E2919EA92D6AAABD880EB0FB3700D6F53B7F0F01117AC44533815B47041EBCF2DB565C908AB57DE7F980B5A1C53B627D423395C168A4201FEE645CC4AF4455AFDBD4B234160B7040E51834BCE48272CDF08070EB738D7AEF2B8B5519BD005BA5140E230C2AE07A24C4FC0B22579FF144DAD576466D6CF76C2CF3C663F5E8E1F423C2F516954B18880963338260BF4DA12E7928CD6FB411F972C86929192624854B7BFE2115FDEFAFB79ED3C084E7969DBE364FF5E57D699B5B112B4DD357A120665841C35C3B9A53773A341BA942FF09979C2E9C9C01F6131784168814A10871B63F3BF9677DEFA6F559CD700DFC65B95F6592C0AE664FB9520FF7CEF970453BE1B2A86FA6DE1A445BEA10BEA53F01345D227D25F2C8C5271FB0446B8CD5B9505FC5528A96F05FE8601AA06BBA137F9CC5251550A1BA82FD6F8409102F9510878DB871D537C67788E5D4DEF101154318C52142BCE9C779696A70D710FC247E7C8BFF58B36ABDAE37EBFB1AE8D5A5E2BF466632ABD26A05EA4BCB0A5D93B3AA47AB700AD3942938B4BB272F55B6C36B46CE3C4C39AE24B775C8D4CF174B5B30057FEB10318B0FD88B576B3408B22B49224D6E438AC84FA0A6F34D0AFC0B75A9102CD5FFA0ADFA1ADFA11422C450ED66C55C3FD4D062F978EF277E5204F434FDCFD5B6AB953DEA57C7461A62F631BC72928B16CB3E906E166C0C1ADBE398D0186C6376090092C1F12ABA0452FAB0FDAB00962023CA033195870C5AC2800B0CAD8BEF1CCFB55137D3C5D3EEEA247FE6391BA4FAB13D7A55BD3EE5F92B8C79A6E9AB6C24F5BF992964D69C1DC6578D8E09EF9FB298FAD5BFCDB62BC2665F2ABFE6DDAA0A1BC5D8351AC1E7B83F7BE92AAFBA85D519B9F6196A4D3778E25A9AFBB2D0780F416F3B90E68BF08727B9956CAB6CAEBAAA12C2CD0D6A481EE770AD66ED443DFDFF76137A5EE278857AEB240E44068898CC4083FB758D173017EF9A6A58A21DF0E11ADEC122926F68B292DDC91A9F8DA849946B52E50D682ED08666B90EAB23BAF484DDCA47F051EDE5E1FC1C67A4421B40598075B764BB78BEA5824AE7C71364AFA6A73D9EAB7792671614749FB76FBD9585F333003BD5C18BE3B6BD291237C7E315E463E225D5DBE624D2665A5A81AED53432BA48EF2327F375212019F174AA2412DAE46F7E1BB4C2E002CC480522332ADA06504F1A8331EEB21718BD62A41DC79AACED15EB077F664851BB4823454F3FD0E1747556539FF3AE95EFC2CEFD22CEB477A7B475B5EE1C200F0425E774D702126A7DF653128B09A0677D4E2732E2F8D4AC9CB50C26CFAC734B17D210E994DF9E54F70946F0133B56B520A1E184CF9FA3CFD6E930729A8653A899DAE11EE1820ADA86DB0785079EB8B1726A0339E8D3153F989249A00E2BBDBA4C1A887D41ECF34FD5A7C217BF70B47A733B5DCECC55865DBCE89C4DBD665365674327F4197D6EA82E2BBAEC16EECEC6C193921499A3E5223332E9AEC043EE5180ADD4083EBA0C605A3A47E717E1DDAE6FDA44A762E7E676BF231AFE77C234D1C73B6F9B690C08FB67B34920E5115D8524D900923025F033880359B0FFB842647E589216BEDDD1BDAF5E76E73E1C2D80EA2FE7846490793EBF8108BBE66E70D534E5C49D8F1D06DEA168F39062E92CB996EF6BFF72D6AEF92FA97FE18C8ECB177277CF35B5D021DE16DAC6B4844DAEF9B2AD79ECDA0E95A6FCFCE4370F4C3706EA64C7DF8070D1513C499ABF8CC4881FEF756053DED9329AC96A534AE5E50F9B0F3844A96C5F6CEE9DEF4BA1B29608051FA384B3912F8602CA72BE17BBC5CAE71B6189F9E6F54506CF27EC4398E0312503071DFD5D5186571B24A980DC95A24ECC889E478712BBDDFE6059F0146B2E0C3D38BFDABB019D304395C9A38913E6443D4A1BC47F8B9FAF7438A1E6C21A1E6CDED75C75D3A285AF1468AD83870F16C6C95AB3585EF0B888469887358270EC3E39D75F6540E77BA2EC7C63F9435F4D91A718E706C41AC8BB41BFC2888AF84E7E3A6088087D669098AF90EA6D92E9BBBB37EC26C1C9A705B11C71A442D32ED65BE2D79FA73C2F99690A21A627891F2BE73403F0F7919CB63F96A2BAD0CF275511DE2A3AEE1C28E83386C2814911CD0BBD61608EF9D562B1F251DF188D2E40803E3A6863D6C00D67D8869165EEB55D977A6C31A70691496A56A0AC6338ADACA88AB590597E016D913CD21A91D07AFCCBFBC32C6BE8B19121EE42FF926B8F55106D15B7B6301E6B0E456EAB19366F057C9FAA8BBABE4250F4C418DDA374DE6988F843B7F71517B385A9A1CF02931A0D9DADFB417722E17910530EF488309474E6D9DDFF56A5DDFFA3859354FE34B93FFBFB2986795C3F5D858E00B8CD6D5C30330BD1A0283CD34F28ED1B4F4832AF142579299FA4CB3DF35540F247D9FF92B7E9A53BB8F72211627E71646A7545424C4A9D7A37A1D8F98574C14907FD23DA45F811CB5AABE618B3E1FED837A80106779773040FCC9D37EE5715DD26CFD151BBCC7BF045B8672EAB87EFC08A36ECBC52FC5BAA7662A4DC4B05165A87B8D0064114CD7836FBF0E8816843C48A8FCADBB6A7FB88801F98928A5E5B90C63DEC0EA0FA3395D402190BCAD7718FF534030A15444CF7658E15BFE22A447F3E23F7CD3B21642364F858C75968120262406989789AA6381C6C7535C2EF461B882A555A1BB43239564EBA5E7450722069495EAF1D3A396C45CA714A94B1C38E13E94E14249A8CBAEEDD0EB6A1F867221D94D164CF5D47DB5C759708AE19D193AC01ED5DD678BBEC27E908CE04E5F45B13648FEBCF66AD7181BE682028A9F3C137E962B292AE5A1D8A661085461D378100FFBD3737C4FB6B436A85B851F5F823A0BFA2F981E2C0379C626F2F813B3CA1708CD9D844A8044A917DB24EAD379D5A34E90E3546AC2D9121365D162CAF65B3DEEF566ECCDB449B1CB773057B21BE4F54E6036E1923FC486AAA69AF01CE1E29A3C89F78DF91A71F1145A92FB5C12BBB2D4E43210A60286263F56951307B13956F7BC1EFDEF3C8194B815692D4B71BB74DEC510CB396F1D903FB30BF8FA8D845915B74A537CEC2F5BD6CACC6E0896A10B7FDAA6D1412CF1B29A2669A3BFBED70CC9A6D3F8E782C5AF72DC54E3D1EA0F88BF2BE93E0EB4479DA07ECDC18885ED58D555F8BE63A483C6E20A875928081C31DC62E49E550D608A6EE22480FEBEC0A3DB64056A63C772DD0C14B1D2A8EDFC0D3A799B008B5D7C63D42D1848C06F43A974DBDB5334F237E6C21481E12170947B7CF9EA5E81D7400F79936FB292C1E1910F016AE190BC1514559E027FBD2C85DDB78A3230443DF8D1F35FCDC73FB189353361C7A4C819D3FFFA3CE11E6237664C8FBD8D0AF7AEC9C2C47D0DF15B588773520C10E0285F00299584CC25D5BD18DDE6DACD091C1CCB8318F830C6051D181AA29F3863B0859EBE1763192D55AC1F413982692F909485720BD4F9B15A9EA968A63EE3F4A698AC73B58112D644CC2E1EFE05CAB29911A95C103284C83290F67B83587BBE7556294C5225374477D7ECAF9AB5EC9460765E6A40DC75A84EC417263C50D22FE5583FF9626977B8826C06E160772D6B0506861A86633446A807183935350D91EEB5D37414CF3BA477AE353761B74E05BB6DC167E86FD20D1EBDCF5C7F6AE3C16116BF9CBB6B67BB564009B597CC2CA1B16B7B3B484C6B172A817AC71985522092AEC980B2FF393DEAB2A375CA8C894A68CFE3DDCF7CC0D468B43C6531A58723A8BB14E201B277155AE268D6A3D15933778611288CF4B0BF3A33C30C1A77AB39A8E6770125995651FA889FAB2B28C87DD556DD7260ACB83D691E2B9DA5880BCFBC2EB079B0D42F673A8064710EE9CAE5913E37500A2BF7FD4B6BB409F511117323CEF7EB39EF1BCD8096E4EE0F5605D58361BB74E6656935E7B075F389DC49BE4973B7C6EDB05DD051E120406EBE62FE8A1DB88A91CDF152BFD790E3AD2308C12B75581541C17666CCCA89933F0BAFD5A0D93CB983D087BF3D1D8F388D22F6B09BC3418FB7AAB26A5754CED0B1F20E1DC38A0426E818B22F34C296DD19DBEE2F1E048C65EA766F8B9EAF074792D83B2C35D363CCCBC4516C9F0FDAD4B07A3DC3C44A9D27368A57F7C52E75500763BAF2CE58C0B9520E1CF94B584D0D9223312ED434D305314718BBBF41BD80668F2D6ECD82327BBEE9FD960898BC7227727341B863F9664701B3F77A1E01155063FF685D613EA39DBD04F12F9E72C840A286A1DB44E63C1CB55527BF3238DBDEB31328477B9089683B1F07A3A0034660ED39487C43D1DB76757D3F0A1D0B52C26E6713D66CE20A818A113D19E5A312C5127507A3C41 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_256.rsp new file mode 100644 index 0000000000..1c1436e12d --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_256.rsp @@ -0,0 +1,12 @@ +pk = 000000077B563C8B187847A60569B3A0CD3049A5DF6CA3EA3B446D75F99F8D37B940AA9604562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000700000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A7B563C8B187847A60569B3A0CD3049A5DF6CA3EA3B446D75F99F8D37B940AA9604562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D93309000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2500 +sm = 000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E651324F8D245291EFF735334671EFFD85F3A823D972D2D49DF408A2AE09590B24CB219D4BA4FD030544953AE56AB3CC426D1E89F8567A33D4ED495164A01434E617E01CF73FA1022A8E19ECD580802F2A359A6BE287236C711249E8CFD26E81E0D962E4E6007A684AF87B096B9034966949F56D02660E2B7279214CEB93E62073BCA7A334E8928210CE101C948DE9105A5FE3B87AB9741B4B4185D7EE42AFA3055430682E22AC918051D97466B12D2FC559413DEFAAFC677C8351565ACC58D481259F0F41EE4C3DA4365AE4ED4094E4B7406AB6963FA3883037750A6ACBD864F56826811C4DD77FD89B17FB35E2EA7C907A056063335AE03884B54E791EFC5B68DCFFA47AB17563DEFAC3A51C0C7E96367FD2A5BDB6420DB2F8E1FA8A1E04E02B5033836AC23BCDF359C659C13E9237867828AF0F173B3F932629847BAA0FF1658833035CF78699FC249FF331272A068D55590E7451D2F1C118B8DFE554FEC7D2B2E0B494B145F9033007E7EFF53151299DA3E5C48DD1F35C37DE0D832D55AED0433B04149A965F5EF8A804F0E6EA4239ABF28A694648719C1A4A315A4EE054B04CAE408D5436A081A948E75B7EF5914E0DD9A9D01018918CBF37A224824D0B936F9E659D7C7663EB4B63FABA90515F2700301544682570E6B3EF16C59082F949173C93ADEC1E111F387845B826C3523FC184B5F1D1D830191C88D1F9F3C3A81337495F73F2B992EDD1E9D930F098492BDF4DE0C16A604D71CA275176A5C2148B151E1961C11F7D8CCCE4F08E9BADDA88E17BF2DB02A6D1E1D2827021DB46592168223ED5CE3170858485437C132229DB3823CF7D727E8DDC6B6BF00983947D02DA1D6A0C82EF62F0B0A9F1FBC427D200F636E66DE934401583B67DB03BB8492A21BE921E1C2CC0ECBA29139E304A0BDF7123670D3FF614F1F0E22C7C8E161E91E90EBDABC3BDA8347463B052E4E97DBA22481C772462763AA738E424431E22FC0B8441A43735869308C228166FE2041FE782E25EC9ED80EC9994EA098FDB0782856925994C9E8FDF09EC353677934D465C348E01FEC000C30ADC8B85F0C19844A4E6B4D0E8F6B2040D9CCF85DA7C9522BD571EFF09D5B1561225886FFCD6B788E6A6267ACECD693E42C90E4730F2EBCF73204F7DBE114540F4AD0C2CAAC6D0565C6DCE9F7F1C5542DD0F7016BD1C976AC68FC2C45E702D9D428999F9041C8CD89B70FA2A90286D7A5F6EB267C45893AB7A9C0E9F75889E64F9A24ACF8963268ACA48B903DA92B5D86FA1C5E8DA5C12CD2C030F11A8F670E028AC1E3925B5D70E7EF6E258B5B1C7F64D767098FA20C976F74949B4BD4792A13DE3CDBAB345B43C1900F6F63F45D02F6A576D8E6234AF7631821A82C758CB0FE7A920EB689186D83BC6D34D4FA579D07F899DE605C6B6C53BB3EB5DBDDA07747CD49164C54A9BF8A9F6A9548A58E119830C4A1C28BDAFB0F94E7539D5F73E2043018B8FCEB218AD24D0B5AF139DE4BF0968A70B206EDA0FF3324096BDCB13A3DA1C550639C0606527E494572744D779FACB63A81CBFD2C18FDDF4883B35F19FAF86B48D5CD2DD9177065D7380AFB479A59205262C98995C8EC3B26E648E01252E75EE3278581B71C84A6F9F49B0EDFFDCE1DBC2AE84F1FD849E3E1D049EDA6A5EEFC0E5EFB68199B40274DBE381ABC0C1BB6336975F1CB08EA7A875241CB911B9853025F7CF48F75D4FA0ECC39C94887E71903538BE9408E8DD1AF757ABC63097ED308C7F0EDF784DBDCE94CF1B52C96E524E7179C8ACBBCFCAB586CE6CDAC4FD71787904D4D19A3C95963CC8A0B0F4073965CD5FEBC875F971ECD647F269A6365491CFB0E6F0908347A384EFBE009EE5ACD512C88DC34BB54340BC9B1C0CCA389E8BDE6AF14B3DC4672459266931B482AAAC2ACBB4542B22D3D25E2E279700167CD7AF03866E60B41CDBCDFFF1216F45CE0741C53B57059C2F55F8D2529C6B0E760FA3BB04A38153913A2A372B5CEC76D57348A81842EC2A2BA6D8D23C976F3CB9F3D349A8448C04962D6B064AB2B8D48AD48F1B221B7BBD9612FBD83C101B7047D793FBD30262FDB21DA3610060FCCE410A86D46779A61C7122F5BA45A814E46224EB6D5969EB9FEE6EDCEEED25B698E4E83CA574A8AC2896FBE20E91DE3BC759FB39137FE7C26A9201D40914CB387223C9F8937FE6F5503D7C207C9330CEF1A170F355484FB1A3BEEE3253FB58D7B532C7885549593BF2984B3D6FCC2E70105FC34A1CD9A85B5D7EEB3A3EB4F07F2E7E0E649042A947B4F9D9A5149F0D57913A7EFE5265E853091C4EB95FCB9EEC69656DBF47ACD54F0045644E95BC75168F17C797F9E54C42DA5ED4E72F3CBDC54D20135C64F39492E2F2F577EB888047FF44CC2528BDCF0F387DC53F045523D40423CD4BA0626CF907312F5314FD59BF41A47F18186B517A59C7B9BD07FFF6433631AC5C062DDFE499E0C22DC5E3A10AB8D8D0C5D9A098331052A74A72C2599419F61A78459B45C7976E43E96BDC2EBA3AE45FFFC8766D70CAB36512C02951240FD5ACE420AB2C8CA931E1113F541C8439AADB13BBD01D08553C645E1E8AD6AC0BDFC48F9179909E135B6055FA9CBA44BA072D2A538BE604D931A5E3273F4F5BEC1CAB03D56A297B5EB5AF99C83F60C70873CB17A1ABB1665B6D7DAB0DB36359457BE473FBD9078313419BD89B3B947A46C2FED48F0CBF057F179016B6DA9B9ABFCC164E97B4E56278799D669385C5F0EE1BC47C9DF611F3C69CD4BA07AECE7C31D5EFA0A3D8FFC137CAE208E806DCABE99584F7EE28086E4A338CE9B8073DAE5D30A9571B807D43788E72A7A499DA5589B7C5BF91173A9A93A386048112071548CF0A71C9991DBB3A11D93483E3716D9A8BAAF62BC5BB58B991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA6E323ED6E8A520C761F371CF760445A3E865E4B2524DEC48F47386A1E6CE5561FCD200F736E4CCC848CF9D69404EE753B6CA35671A40AA2B667270FF670DCE5AF0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD +remain = 1022 +max = 1023 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_512.rsp new file mode 100644 index 0000000000..2dbce6b683 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_10_512.rsp @@ -0,0 +1,12 @@ +pk = 0000000A28C42CBBFDE2F32EC67C1630DF460F62D15643A6B5FD3A53D78B5A0011F6621D645A874D43300F9F334AB1D6DB08EEE382C34931E9EBEDF37ADAA8A57A37AA404D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000A00000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957C28C42CBBFDE2F32EC67C1630DF460F62D15643A6B5FD3A53D78B5A0011F6621D645A874D43300F9F334AB1D6DB08EEE382C34931E9EBEDF37ADAA8A57A37AA404D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016A30B3920D43D47945F47566B618719C38844032986568606F2DCFBD7104EEAC5436CCD86E9677E05985FA63C1B6D3E642D0F145B3FF637B96F2AFBEADED75F30100000000000197C186BD25DEEE5DC2CE5B760508549B1EFB2F3E0A34047232BDCCA39B144EAE820DB1F2D3C3159D012D7CAD7AAB1C44E15F53F4B1166E23DB8AA23ADA9E23AE02000000000001C5A2B2230C54CCBDFB5F42AD8805628B6B3D4723AB84E514035694195F2FB7E716F21EE8845170F30D1BEF79ED4468F2A45A72853F2D8F601973595098010E1D03000000000001C9E730A265A6F2DDC4B0F420CEC9C7AC976ADE4FDD5CEA3B6D5445AA2562772F76635C514BC81DA00E36681EDFEAFEBF29B1C3078AFEBAE3956D74AAF351E35904000000000001B661B82380E38D5CC77679867BB8FC1C94E77006AD05DE9576A7BD210641D25D011A056637775E72395B7643018E0BA023747219D875DBA848A58E0F9D7FD2DA050000000000019F3A31924919E8711F88BC45477356D330ACF65BDA612F6AC681F64C24FD70A6AF08B3FBB6136E4AF05B38A9205ACA4A2773D100FF79057CE6EF6C3F82AA9DEA06000000000001EDF9A31569FF07104E7B2FDF78D2CFC2FB28903D720F4D2ED95AB35DEB5EE579384ABCDC10CCE008B5BF753154B78207E452D4AF2B5646C42B89EBDDFA02570107000000000001BA911C4438781B45414444B18E3EEB1F0E57D33FB8F1BFB5DF1DC85D88A29371496D214B1042FADF9F17DFAC6215231DECB7D4ED1ADE6272BA7933403D3BADA608000000000001D85DF2FBED8348BA8E34D08202B5F944A00F91F1CC1F50C50D2460DFF1CFF490D84B84A1FDCA7A5E1760FF2E3A392D3F4ABB78116DDA6CAD29E694F9A4691E3B090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9092 +sm = 00000000BAA7550F0E617123968A7F276A4E50664475EB64F4E5DC6805ACFE998B45C1E0EF24208EC4F8C326F4E4D4B36902314578DB3668398F8D67F573F98468AC125AF0437077A8CDD3F05F6FB65D3C9AA15540627956048C55BEF5EEDD31FF57A3B38C0C8B079A22FA8C4F910E43F1C71E52AA4F621B8D4E9EDAD6BED5AA7B55D96F5377E4D1C90EDCF0E9101E4EADEB45DF369CCE46AE87D9FB350FD6F71FD8A4A9CC7169BC7BE08AF160D9C4FF4E17133E98C694EF995B78898ED467ACB68D301AFBC96E96EA6B4C8B756FD955337C4C558D78FDF7853E9519930416E4CCC396C092F2480C530BFCBA340E102AA1FA9501B6C985C9C00FD8711A216850F91A5267A97E57A963C3BB42C86E365E37A258BAD6901D1F1AEC279CE2F14E9E3CA316DE8DA0B086DB8102A746FC5C3EA9C99BAA79F74F7463F047DD6878FEA751585B40EEED6A775CCF99DA0882EA094FE37B03BF42D843B2E58EDD709D0B7157952189D6E05DCF84D7A98E006FEB4A4746BBFD556FA25DC5CE32026F4D42CAEE72DCEFCD6E085205B104F30EBBCE03D9379CE23E884EDCB5844D875098A851A999B3C01EBD13F4EE2C95ABE76E4658ADE75DE9E73F3F531DBFDF366773B69A422916B9E3B033E015454FA5A31DC03124ED69C91FA12B18C028EB56FF8025D46272390E2CC84274FFFBC61E60055D6BEBB1D24D0482C00A7240A1FA86C3B28CA8B25848B109CA18B5ED836ADE7C00DAA6B65C5109ACA7CED72AFF32B9DC99D1542F41C2726028EBC437EE5C8E3EE2326E46546C36C8F1E3B85A946A7790C59D4547DC156441C09982CB02EA2B28D887A0345D2B62A5C2CECCC3C4083C35E47DBC096D2327AE64DC84C822D511650FFA8155619193E70B2B285E98516A5815550C699FFB11384225CA719CB1AFA38992E7315CEB3BD02ECCB6BE6A1FF8D0FC74B2BAEFC196D6D1D839F16BE25EF9C595BFF82613857E6C9DD1707ECA4BFA3790367CAD1D28A49ABF2281522FE1D9319DC6A73EA986345B69D82027777002B40EC9BB896570BE4B1E74DE3016325C72C876A9D93C834C936DF976F78F33D9407D4A5CE48D5A318F39B968154700FBD33EE81C800C09B7521098E565766EC58FD6F4DDC0E0D11BBC4AE0F8C7CA5B75C3D9A3A11429120BB71A44DCA86DCAE5D9C67C1A1189587D6753B7A60679E76A6BF91AEC1A1EB2FF181DC1BB11DD597E55F3CD9D90811B3F6FDCB01B351BA04F56B749C356AFB5656B4329036B44C961EA89F3E47F5A33EBBE7E3EA6140147518E42867D2B820117E6F7BC5D685623B4557D03BF5FEE5914FA7B01D34E14B398AB4152CE9A622851DD8C4009EBB1002B88C5AD6B75B35EDB4043AFC721310C9B3B69E30EC11597B14862B8A3AB7240FFCD4444592207371036AD8A221773700BCB0A643D295C56BAC055CA672FB8F9BB7C93A62A46646A59D1A8ED7268DE772A86C557C5CCE6C59C5449069A2DABFBBBBDF7F84C221BE0973847615C4A5C770264B54F110D2FB213FD8D93C19418666CEF1FA23097234B4DFB4F8CBC84610E6D1E65C654046AD37AF98F29EBBCC67B2A3D68BFA0F1541DC569F3B755BAD59BE5A6BA5AA01E674EE71E759A8CFBA7A139D5809B3EC21C25AF2F153E8FBF4D0051B455429C81B226A21F3F4DBF46E08143B20DE9CBF9D6DB13D5C0F51C9707565ABDF0666923B99E8D488D8F35FA68D02AADBF7515566B4A2E1F80A509BCB19556DCC4DC4849A33A16D12DF9C3C686FAEE401EDFD7625AB1EA6E122CAC4755FBCB1BEDD4627A60AF9396C950F9A72FDC7337066C140AF7F26A36F27D1840E4A93FA77DE018E1B1DE1F08319F6AC6FBC4146A9663E83B2427AD4920BC3AE2AA7077EB1D2A110201928A68FBF341E11BADB18CDF00B6C24FBDCCA114E870EE6272A5F186263C7E5AEA1EFE28ED7ABFFF79B369BEBC70A98F62C8F8734BB6D068FB2051CDF4DED516260F1EF5CE952529DDA4DB8EA91AEBBBD8BDE4AA50A2CF7CD1A6DD8C0314794CD5C5FCE66734368FE141CA7D4781445B16C2D11CE41AF9AAFAB28E5A8E067FA8224D487C792EA08E406A6AD7DEDA72DCDE3AACB4ED3F7E987C750A437E4315F7CEC44A5C6556FE705C289F2BAFB0B99F61E05E7D4D88448E69C9CD8D6EAC8A2E4FBFE862F98C78AA5B242E936F2711D3E733903E6AEB012E0E27F6A7C82627D8B8E82F371418B5810ABEE5ABC94F8D082C7F3301AA3C2C4E794BBFB5AF1144292876D83BE465B4BD50E677D7A0E2E58C02525AF4213BEA0FEB8749FC24D827E7EC6071C77BDA458414AA7A7C8DBDC876734BA2FD13137B55097D940F04B04A39AD0AB325A77A358A7E574C2D64E0AC794E13ABD793C43A7F561EDA57110C63D5914AF56EB4009FC4ED230171BBB7E8732A79E3E417C235DEFC0E67E2A233B8438EA0127F6B69605E557E7DAA8F63FB3D4BDEB9DB92A0AA5014C6D7DE78C198D4AAC70C407D913C414EE858795A40D73321EC677E002A0ED64E28831C61D124CC7BDDF561D3486155286432CBCBA1024CA40204016C95DCC76639423EC073F74D448D0319EC5EDFC78EA4BB3E54322124816F87C95C17497536F10E88BA7805B566A4CFD1650525D00278AC57DAA1840D81128754DFF3E18F558F0A1A64511A02E9B48996E0EA33A994D4B6BE0D16FEB008FCA38129221A016BA24D49EC85117D771C55B145A17607676C2879740ED02395C8494C515BD27A92CCDB65479EB8A2F2D8FE303AAE2050BE07CE0FDF0DBF8C14D193676960FF278BB421D184DEA70E3ABCB6655A05347FE032DDD578F14DA40F036A8A5CADDDE1DC293925F7851643CDC02BB7A12DDFFD20A50B50904E566893F127A01089FFDADA35B6ACA4EB4D175D4645F9478C6A8DBF03AAE51AD153CC4EA6A6AD03D60915D838545A168F8191E2AD373EC5003A969FD87908B2ACDA7D1E65944A9D6A125AF9BDF078209BDDAF31634204F077F372AAB28C37E81E125484288DF6799EB714B8CA9E137BF722E2B4C5399991AC63336E7EE9E787E0F14438834BB9E5159700AA990A68730B289513DDE3FA5C824356674C3D1C08207376582695CAA359E3E888891A7B84294A2E6E99D311FBEC1F596B69080C0FEE7831E72C15FD534954B8590D68CD8A28FD20AE0CA8AE24CF2C955A09FBEDD94C5EC08CA801FAE3AF107B13352A0AE0E2E3E11BE3BF96C0D07F7FAEF067F7507F892456B3D3EC4B58873F6C83554175954E8A4FD2989F769F0E0D0ABE1926474CDEAA1E573D10FDBDAA4E588E5FE59822834B0B629825213DD022085ADCAD4A28F447CCB257E1D969B66E6F403F8509C6B94725ADCADE52ED635DC9B9E1A42B11052D69F4B131B660CD0917974902870FDE186BDF628B61856C9CBE1D04D2E80A91500E9CD68095E711F125EFE9E32D2AE1C91B1A0136C0F5422C83421D97470CA298B6C9FE37A5148F5B224496653A2B36423AAB5837AF52A131B2CB89E875FBB99D2E032D1389074FB37311A15EC81464BED81B4AC47047E462734B5FD2D192D539A4BBD39DC8524EABA99BB69925AF7E2E2B3FD9B520FD1806F90533FFDE3784390214ACBA48E89657BD5246A6B5F626C45574837A8E1691A539F978FCAE23E29D31ACBCAD633961BC741153B77BD76B3A3D1D5D302C18F9DC589039EF815C57B27C925ADD9C52E5F3A6FC226766B3E165522B344F4ED2E9071854AAF991F02D2B1AA83F111A02B017E9033A48144C34E89D9EF73B1E598969870E1A41DA9F6A610616544CD5B981255A9542295A082CDD3A66CC07FB9F2D1BB4B7B8F64E129F69EEC185C218D299B827F1814C9D5D54280FB9110198029B95C565AAE7D6295616275FA799F71C790283D7B8AF5CE60416B584FED823A46EE48289F37B55EF27DC4E507AB04A907467A17C6959045595F260C9FC1D7A02B3F364E033CB1ECD9650441EBD6B50F0E44BBA7321D33BC39D9FCA19D3A0C0A4671EA68C09057FD6705A61EF6F924958881AFAFC13DAA5B3AE9876352F6DB0ED78AA7E1EB8A5C56B9D3FE6A808741B28200C381C08BA0890530633FDF515AB52544ECCB70B1530EB2B2E39AF49264BB4864436375AE62B8F9F8E675A70AF44252999A011BAECF423E511A8B6FA5E7FB0C467476520694B36AE5C0D475D3F526CB3668CF76973985D2536EFC73711740BD5C05FD3E3521002E2EDC65EDA06B81A5AACBB7EA5C3569BFFE89DCB32A3B3CF3F53061308AB5BD1AE1C9F4C999BA765ECFDC379A2E4FABE8E6D7514684A99E198A53B778E0BCD70AAE29AA52BD4F8EDAFF89D60E846EA0305DDC8D368314248917C2F0C5AD6B107374A674100776DFDF6D44BC179C305EE7C79E16AF07AAC4BF858FD677916EA65213B1987680E3507E6C976683CB9FBBE0A223F7B2AE55E9CBB1B1AE83D8971500AE7AEE000660C989F6A3979F74D75CD1621B0D5A8751189C380579671CEA39D0BDBA4F1A975E0956077D8599C60AAE9192963B563FD8C509B2B3423FCD52F974B89C109403AE80DB6D82E5FDB28D3D6B62850D6E4EA7B71B982632C4B9067A21D3F24DC18087A335325EC49F747003438F8F088EB80861F6C1D9446EA350450C52438EF91E4A61B41BD6E74D8516DE54F6C0F2572FAAFA731ED95A6BC399ACEF17419A263F692AAF04136E62B36BB271F3D949667BB84823B00A8E5B8700FC1795378146EDBBF022F938AB6663BC1367FB1F937BF6085115218C5A3CBE7D732D8D62D2BCF54B116B7763B4ADDB6144CCF34A8768C1AACF13E1894D84082CD242E3D0ED236EB8A7ED4E35C8E72D9CEE34F89963577D0D0CA9BE8985C339B429417D816EAA396CFCE3C1A40898FC6A3DE5736891F81FE5BFF5A7EC9DA88F5123CE5126BE7F0D705CD2BBBA5B97B0EED10272D0A7496D81EC612D585F21BC5C3237794CB9E83506BA93D96FBCB62AD010ECC406D3AFFE514AB8607A1F8D9454061D760D417E210B89015C1DBD1C090BFFC39BA761EEA223D93774E7AB86F2B03B4B2A25BBF56B413E734A0870100C4F0F05B429FFC0F93BC98C45EEEB806A6444ACD5C61E8E241E93C47F73F244D38A0EAB2EE9C1F296981261F179F9AEDAB136B73950F2BD1F6A033C7F33B7E5BD902C5E9183588065D20F6C8DC3648B35641F3A33A81A430161483838FB206EAA89841888B93AA8FF8F5A3BDB35737997120E2EE9FF2409B006020641B51D8D8DF939B04103D63C099B73F2D2878246D1802AF9CE44723AB19C87FC23CBF7BF89650441837B72A1C216F7D12F687F955DEEAC751232B3745DEC50BD3E4C2575C1D13FCAABE57539AAB71694D548A9CB6C8EE765C95FA453F1630A014456FE25639FCC61CDFFCA8C41032617561AD3425C82F360320C1A63E0EC239915E2881B58C183BA66DE53330BF665C885ED53E52F316A445F35C143B80D22A999E5BEB6482EA903A3F1F76AA262A20793A9A1B2727BE1131B53AB699D0AC5B2982B9A24C590F92DA2A257B1AC570ADBF5E396D41ACCDCEC44048E7CF77A8A480360099DAEA1185A2A21C80DAA70B0139F3C3A18577D31D5A52C2B1121C25DD7C41E3735DBA3BCD4C0C94D296EAA93B096EC9918D5FFD60F23132D5B11687FEC66CA0442D6846FDA79C9A7D7D3EEC831E6B8EFF7BE7CE522821071971F4AEA58E062F8B69E00F8FCE860F995CABF7AA719EA893FD2BA50CE72ADEC147FF6D7A10633D197C52688945D36A69F80A1D1D5E1066517672B946B67D427887B77BE803C685B3CC17EFC2AB1EA4AA80052BC78F84D928F4098220CF7CF5A8B69C66AEE3744236091974DD9FCFC1EA3EE0F14BAD1868F165EC932E710CDA329D67A630C39D9EF46881E12A79E1115C35B78E47961F52AD6BD39BDC807FB7D57350207C32F439906E32702BCEEB64864B3B658D246C6933ABBA99AE14405177558C1396DDFAF20BF4B96BE166C47201204A10106E7A62E06261A5414268B4F75FFD5075675FE9CCA38593136EF843C39DBB514EC0BA5002A91EE6F375BF4910D8F818EDC39D119E650CBAF6DA563D563CA33B457C8E40B4F04349CF401B772FFF6D4EEB5621ABC1A857779B78623A2AC2AE038291C187F88352734DAEACC2D0D16F3AA45B06972CBFAC4730EDC26F8E9E093F58A35D2E97427360E5EDFF75C14D404524782DC542CB28EAF9F7E1CA0808627D7EE7C7CE279B81DB543EA575876E8A194F4B9177ED6F1B9FD89A3039A361F413AC1CF454DCF91BF014F7F401BB303F534AC8D9D54B9A6D38202B03E9A5C5412A17E210F19D433D935C2392308FFACD85FD5DFC13C5FA608FCFCD7635094833DED7AA22C0CAC4C525127B0057FDC2685EB9336930CDCFC69F1376B2DAD0A98D52CDE7E83F54016FDE66BD371C13026FC975454361626EF5A6E668028E1ED42E2F8C9C8A29864B42C665B6A44040EB470562E8B1A40731B0859CD19BDD6E82E90C73A6EE21ACB55B3A08714743FCEB566A44743E3CC39272568EC083A7CE4D7868EB12195300B224918B50C198399622704421CDBCAD2861E8E3D6C87AED11B2005990E7FE9E34C8251C777CAF4F613D91443D75C50B8C8164803BACBB4397247B943FB01F6C94C547DC9000ABDBBF9E182280E2334E9D630DAA178DF4F78D4FB0531F9C27F9CC28E269204F0AFC394516B58EB97838820FF609951952C5896C8BFFF81C4002893DE238EAB3708663A3B0284EA1ED9A04F5980F1750BBBB9010AA1E4A3DB0C96F1A71E8249B87A2E28B381341C57074491B8475204F2F67529DB15F0E54C6696139D55672BABD4D3B2FCF38EB0023E8543DDEEBF7FD8C2A609751F612DF37566BB0EA5F1DAE8A94DE5D94D39F2901AE84CB772FB59C958088F9B3BC446DB14262F9C71B963D82BC687ACFF2EBD69352F158D09FD12D232B70D61A4C61FEC224B3A47A2D18DEACB31C142BC81CB18A2ECE744A28843DF157BEDC7798FE1B4194D0EC0AA71829CA1034D0EBBD1FC49D41B19326AE664724DF88218ECD0CD6BE7410D0CF47F755B31D5E36B57E2E9294CDBF701888521B9E8169596DDF8D4A0671CBFD4BE464D6DE62BEF45BBAC3B6B1C21D873B851338771B667D727A936743B93943CD47092B0132C4CD09E7AF8F276B84F42855CCB3D56361072F23DCBCF57A490AD90C3AC8A2FB0253A65AD4835B97F3EE70C71EE481B26D947879507285F47A200294D1D58C5360E01ED774EB93613D94231C7BDA56983A055BFF871EC5C29CA34AA651FDCEF8D66F72AFF4B5BDBD0BAD54AE41C37997CFD725A9989B4992DB9F8EC6B94392D30B67220F20647A8939C61863BB34BB8177C106E32DA64EC6C3834E6C446C75258FA1CF17E0B727896A64F1A65083DC2CCD471C65977D5382F3B8F8862878CC120F6BD9CB29EFFC42BA91B9BF085ADA4B437840DDBDC8442A6FD660F9C92AB617D43FBDDFE0621A217F508AB4406D6A03B64895A5C654198FA0AAD218AAB250DE80A85295CA6944D32910ECBF9B47E5F2BF35CED98707E4F433F1958B6AB9C902C1F4BB2B67F972F29C18CD215BD3875C501039C1B677142D31F0A8C07CA1000E963FA4693EC5E7EAA929861E0D431997A536182D624D8426B74DDF841B513CBD2AC8A17397E9F591A5ED5DBAE478D6082075892CA9331219DC353F2C3563CA6745741C7A2F0C334E219AE1C0D1164DC4A81AACFFADB400846688F2982A568414F20220A01FF0780E5AD1C7E8D2E3C7B1FEEC8F7C67C9A85C3628136AC05A576F6091972AEBA9DC184CBCCD35BC61671C6B729E3F2965E7C119131864953DA34A8BB9DABF2B82EECE7455BEC8BD509BB82074DBC766F7CE25E1813444A3CD05C1A4FE28D32651B43DEF2D2511E7E64C5C7AA51BEA1133ABA11005D0DE317322A3E2095E5194B748467133FFA8CCE0CAFCFA8080A3280A231C090C7F5EA61A97E001C59E65E1483215FD96468F1E99350D24373B32136C201CDB18A81EAC0942CF8619FB636B755B4650A55489FB705E7432809E2393180D3BDFDA4E22F4286C0B5CEFBBCB9D9992DDAB4BF662E3037B6D4EB741BF66F0E82E90A6A65C71239A6C939EFA9E0B1B5F1E7FE6A4BBED7FCB163980C866740949CB298A2A0FDA5007F8659FBC18CD236F14DC5B71EDDA3C88F7C68A0833EB7325422A512573F775B87698FE54BDF14607979A04D2579CA552C22EB53AE43D21DB17E3F4618E9070F43F3E58FB206D1CBDCC8DFF1963C1F403CF207E4E9A315F0185B5CDDA7BD84D3E377439538427A5FDAD1E9FCDD5EFAE6A438299FC47AE0C5D622451447242E287BFB0D0584537C45649FBBDC8C24724EEAFE2E03A475F6DFAE4873BB35C11F85707EA90D16D5A90FFA59085F2C3EBBEABD468C69C5D4BE845D45ADE69C9A8D725CAEB9DA4FA48884B5B3570E5DA3BC102865EE9ED58E8EC07672817A72F009C9BD007BC4158C9B137E117BCE2F0255ADAA6A394E0E1DDC57DC3BD38761EE5DE81165F964F6AD48873ABB279F1A236B7A022D565089304ED57C2424213530704A052FE4BAE2E2B501DAC5E7CA411AE2124D3D9F1ECD8F2EF653554CE8B2CA9504518C21EEF67CE9A0142CCBDFDC782FD34C529A65C552311A89781307BECFF507788B97837E6715CDC96820AC849112CCC2DBE7C99C89F5A0D111E23C19BC9115EC8096B469E69324F8FFA428B81D7FCD0D38489820F83EF8DA083B401E75DE57FB7E7A88F4BA52E7B45140AA8F1A97A51C112B5DF3A562F0AFFFD87BF2BA9079EF8A5CE2D5AF0A510EF21FCAEFFF192DB398947D9CF71A2E80E3CB7C5F8E83FC0BCAA59939C5F29DE2411E5D9245FAA641556A5B15DB99A0F9A86715A28F5BCA9F58AFAA1DD0974CB899565DE9A33BFFB8F0E2C118121B8726B87EE872165241B74B2DD0F961CD47D24D81D2A8B0CE4BED4C9D1F22D88FB8311B4704034D73EC20BD63EAE3E6657B8787AC1E1CC4403A1CBDF168E151ED3D30FFAF78A1C6D1B0948F535B472FA7FBD5C7C4DD78F815CC0EACC685431AACC3DEA9A7A75D95CDBE650F6428A81BF0D21AFFF6989F64633E50FF3DA779C7A3E2157C13DB06A3B09C4F7B4947C3ACD8F816312080E7749371A621B39FDBA5F227E86C98F95FC4F0397AB5EA3D2FF66B3958D195CF9EF2F8B4D34096037CFD856EDBE0D65CFEC3F3DCC014A7E91E39AB99F4D5CF00DB910562E3F17827064826E641B0BCB2A147A0D12EA4B93A8EB85AC079400486B2F4EF1BCF288ED73EFFF3F10493AEE8AA69CC37F55CC18E0C3E1F9E9914D268B7E8101428DBDCD1F9992E4C52AC91F7C8C946CD795A7DDB6B794726950E72581306D5FF772A10F4D63276B65A26DA6198CE3C3511AE3407B7B077F978524D778C9FA6D39D27032539C10BAA82B4D9EF44248ABDB4DA1817C20C1A7AAB51F0EE40E2B1DBCE8537CC9820E3272141E23B5160C7741B39783A557F5EE9B28DD0395262473C8C5FA6BADDE0F079C39609B611C7CC402BFA755096396DB229EFEDD326681DDA81EA4DB6C7BFC873F0673900E9DF2CBC053C7CD90C86F39D3C3CC60DE7A0DF08E2CAF9436DCF06107270CCFD32618AAAA84AD18721E69F9A40D4A02114664697ADD364AF0372739CE483EF0424EF250A9D8B1868F7AF515151C7A82F57FBFFA415618720D9F6B74D26620D7DBEF6FB5BD65D21D3E23692EE7692B1AAB7144DD5BF9DC0D29F735447D11516A068B7E5E88D0CDA94894B3DF62E90B20741BA266A0CF5AF40A6B651376B3BEA1982B9A1D1FAD34E81268E178557B9D0099EA569BEE5CC37EE87DA8FB8E194AD9262017636DD3280447C7D47B4CEA5C29308EBDAB0DE6F71BE71ECB562CB68153E8657D18D826C846F51F7FF9AF0A0EE144FFDEAE4B8B4B86744ED8568131FEC11580FCD130FEF66B0F3B80FED72570CF8D05B5D0A0F04FBDADF278423E80A645F3A5950BA42CE8F5CA1AF452F8E17310609F673E8B194C45A6028856BA19525A1AF21DDF66DBB42867169293631C8ECE4248F6859608B792169A785D5B0AFA42BF20B127D0CBF3E6DBF9CA7F4339D46C0FA311E0B6D7AE4FAD7C7B7E95142670525AE1FDD8312AC7E4FA311DEB7DA2C86898E138A6A85DCA01D3907B257D870977DCCA7566BFFA75368E0EF1A5ABB4A37C1C7F479D4CDF7DA4E4F15306C250B844794A700467D10478C70ED7576CC7A47A5214E87EF2064DE4E8CCC1C79A77999B9430E01F0A96CB4596BC71157F5691AAE0CAB95A34F556364B81252BA1ED74D9623823BC1DFF2C15B803253B4BB945567148AEFD159ED587A7543A38498FAC6B9F4FA387F208FD346363E8F024B875765E509EB158959EE37CCACAB20699D2E3B93DF596C0E7858DD2769AA752D7A04DDFBE8B663368BB16BB5E5FDCA2A07BF19D6BB64D98117E7D2D3DFB0F52C5FDC84FD477FCD77CCDA54E394B4C33F3AD535474B32F4695C94B79C5412DBA1C5266DBC0F3BF3CD6053BE1F45BD6248FB43F64D2E85B2F7182BBADDCAF27C3113E3A028473065AA28421B7DD2A48D5443A13B8828909E77DE44090C2F8E173524AE3B80553479C5B6229EF0617C9D7A7E977F6308FCB273726B911CE4C32BB7862CB97B4AE20BF738E02A1CAFD80A16A60D7A34D1BF415B90C6DEAFCB3484C5E667908797D4F4AA2610ADEB56C653C8F185A7CAF56EBEF48A2848BD6171D22001FC68AC2FA840ABA5C431246FDC23BAAF6D0DF066E79526FE433EE580C1FE39DBE388E052E07284CEAAD3677383BD09D051B1805D54E5303637B33579ED70AC197F40096622FF037F212425585DADDB7463B98BA1778DF41BB35AC25CF70C28FBC38D8375F51558047B13C4ED023310CDF766B8CB1DAA02B1B636713D63BD1DC219C3BC6D503C849BE11768D1223BFCDC8334441B8F9B12B320C3FEFD135FF8570AD9A7CD41A94A840BB2BA24D5DB235EBCADC26AB29897D6FE8FD2610CFECDDE4B192191A68E65BC9220F2FEFE3A81ABB0B339B4E67616325900F15D2A08F5372598A78879243EFC57FB452D6546312B64B140014BE557F111C383E6A230577E71C0D393A5FF4A64FF24DACA82EBCAEE30D15A09B23B5A8D2D7969C7A722D759C2BCE5B4840EDCF138CB7DF66ABEAB6CB261C1C4BD58215ACD30F123BBA9B9341AB4D3EB73FD5D03AC61BA9AC088A2E54CFF758756BE0EEE2567F68BD7C1F82D320FFA0F6A70574060C855BC5AF805E6393DD72F96108C960F40FCA7FB3DFC2D6D0BFE282E47F5C5337E6E45D4D2E16B84FF3E5CEF4C234FCD100613EBC8E64B88972F76C910D3F670620DF511138B38CB2DFDF52E9C149BF2C735E55BA7E78D059B90686E457B060B430D210920EE1381B7A5D391439E8647983867DC109AB65EC8A1FC72F106B90E4AB58C4E94B1A3D1879C14D276612764132E3A83F5FEC46445A2FA4FAAD22DB92AC778226EBD0768EEF419B9B0E640CD728401106B5034EF589527DD3C723DD9BB9BF84D8B807BF5E44D9861CBD0FBE01CB67614FC637E59AEBDDDFFB2C942AF3B12025D0DB6A87C8FD2B11E097154B8926AA3C474269949F0D7527ECF258510170DD37B36E9859CB0817921D58308AEB63F82BBEFB3539949CAF754B9C49FC538016E6187F33B9E6FF1377B1B442E7C90381A15714866F555145414DF827213D9BA1379D345ABF1E5B42A9865270956B1193B1623D4086A9C9362D7AB9268829ED2E08431B6B86A49D4AE71483E00A4B881E6BEF7F3E2A88F012B3C06A7332E900E0791DB4730D1F9C8B2210824ED920BCA37246A51653BE1221C9FF9DB1FBF9C602FDD52D0092B1BAE8FBE7716635678161F1AD15FC55B651150FF4743FBC00C55EB5DDDDE5576F21B4AFEFB9DE8069DFE7B917653E4D180F6CE483BC229D37FC72424C4BE81F59B0193D2598C75AD9B818E84985DEDB445C4DABFAE5C9912748B32290F33C5169F54089F39630FF701B4EBD727B630EDA9752AD3601DF69693AEDE984E84B80D72FD9BD347545A27CEACF2B2C81DF266D320EDE2AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B9 +remain = 1022 +max = 1023 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_256.rsp new file mode 100644 index 0000000000..c63503507e --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_256.rsp @@ -0,0 +1,12 @@ +pk = 000000088B4832442313757CA73F5832B981BBB6B72FFD8A75EADB03605950D69CDC5FBA04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000800000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A8B4832442313757CA73F5832B981BBB6B72FFD8A75EADB03605950D69CDC5FBA04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D9330900000000000121C29A3D4E6C5DAA979424FCA26B0EBE6D3FEA8F078FA9A98B0F55503C2541CE0A0000000000015EB6FB8267689B81BC8E2C8950E5F59F4B43194AB167C4A60EC9BCDA7572E5980B000000000001F02838F27F104405AA4D9E111D3A0B1849F6725926BA5B3A6412DEF900E7259A0C000000000001BA1EE79A04487C5639BA096A60E3E17F7A0E9C0238FA049EA7AFF52FAF5890980D000000000001B63504B794C356EB44A98DE32960830E6B275526432F232A7729ADA72571E8D90E0000000000014DA82230B909123D34E30FE0722BDD93EB6D56243518275547CBA7C473744E6F0F000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2692 +sm = 000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6FE5428C1B38A2155B8EF1FB9DE8440D993A1F197229DF83843A1615CACF924D481D1478868BB902124AF51010672C7478B1AA93977097EE47375B6A5BD3ADCDB13077F648B8C7435CE755907418C55379857F06E2F7A61A232B67C86AC1352B9854E31EDDBFAFFD3992A2FF8D8B758452896E7B2D56A89B09055C2684A6FBCD2868149F65E73EF30210B36E03DCD6257185F671F78904B3F11EC67EAF994D1B9810B03806BA5E0F9C9F764CF3EFC1772C1624A7C8D63A6295339488C2FDD9CBC4D52F94BD09075E359134DCC1745B0B9A12095AC493DBCA32FAB2980588C131B31246F16CC261A56C9F1903B0B4498B849B4598E5F8C73A6A1521F7D75628427F95374C29BB0585B22A7421D7A01B07092AF4E6C0D03F0445A64110B93F814194F4EE29447A8424917FD3EBBE24F5128280697659EBE4569087D96AD8F0AC7B67D272DEFC429B7BE6E9F76ED4A60B42FF5F0CF9EC09791851E1E7D263EF374CFBBA724670050F31569813630709AB6A4E35D66684AB154CF647FD64DA3B2E5530B4ECA5ABD9666549F8079173D267642D94F9660C76FF6D5378E015B792B13BB773CEEF4C7B3AD10BC12FDEA7DCC1891BCBDC9CD83ABD7DE6012ED3F07F1CE676F9E659D7C7663EB4B63FABA90515F2700301544682570E6B3EF16C59082F949F388D9FDC43455CABDCD4AD51E010674F23D753CB00A62685205FAD8CB4BE5D5174BC2039A9D72F3887749FF061BAB898B75511280A6E9134C3379B1609BADF260A2F78C4C9863965A97BF5DA405B992E011375D9834FD1AA73799E97F4F701E1453388E6A2E01080743D9A836F20FC93663C7E4591849A616ACE98011E52BFD3C156F233100992998ABCDFE26F36A0A4191998EBFE07E2B4D7D9787DFB44F858B43CCAA440867C0C6B6C74E32368C7884B8860E5AD1B518F322EE72CEC31F5253891BCA1195D4B5CD305ACB28479FB1BE4550E16F85D9285EF98B1F325D755F2D43E285EFDDA4F0842A1727C2EAA123789C359DF0C696349055E452E7F27CC668814754D5F91CBC9BB551E5663948A692D12D054D90840580C1D66423931FC5A4E6B4D0E8F6B2040D9CCF85DA7C9522BD571EFF09D5B1561225886FFCD6B788B60A2740339A04956DC654E108016C69006BDE4C2BEBB3A3DE40FA45F5DD19D0E3F2D9487FC2287870964D9F328563E36677622B3E074A980DAB585FF96FD09B95A6065CB8246841079ABE344B55A1F2D367FB3CF72F1391462C45BCAA89EF4D623FDA3904F18B7739B10C9EAC71DCDBA418DF1E5DA13E1BA5A122000BD71E0C2060ECF72407AFDEF3BA54EC75F425B4AB32F564854AD5C39A2A1D9D06FBD74DA44B83F449072FE1E7F6A82B308A253FA60B722B0B949204E5931BCED17F2B1C5EF51D9A6F477F108EFC9DCC7F139617993D5362ED390A73955749EF1FF0825D95C689192BB35FCFF90B87519113376A44AE4BA207EE9AF82719AA72ABF543ED04221A9176561983CE0FEAE6C491381F6E112192272AD8C82CE4037BD968C1F4E7B693C41F717FEC260DC06486D04822DCD3BA1CEB89F12DFFE3534B51B107E73383B4DF8B367F2E123BC873626A8EF6142C485C932E27BFE6024722F5825CA4C84A6F9F49B0EDFFDCE1DBC2AE84F1FD849E3E1D049EDA6A5EEFC0E5EFB68199A9913158FD2FD0A1EB0C039623FA42CFCF6A0AE68C6B65B60D79C9987EBDDB191E271CD9632AA1EEDD35A437D3405B89CEED11D4871C6C1F9A9C33B15AC647845C27F1B5233F2C78E908DC396F097744D841C8BF1BD732255BC62E601A9E50DABEE504FAFD020889BD3E0335DF683D946334C147F31FEC61975DC21582CCD00E77AE099812A621537438D6AF2F1A64E98F801173C97B9EF4923BE9B179A94D20D64CDB799F04FA406789F34D5A04CE3FEA635DE803FA73EBE3439BA0238086F39970601DEBD0E7DEFA07933EAD357C796B76DB6E6F557222BBC9AE2F4840F608E59075A190F8A156CA92CC81F4F69369EF086D61EE895B7F12C300DA076E09BD43CBCAD6F5857BAAE18071F291C3D742C9FF3FC54A51D1CB8061D5A0ED4358E8AB70079EFEAEB3947276F612A4376555002FA7AC9B7EC9778FC3B4A6EE1025D4C73A8CABF27E1CC7B33448B947CD339BDFFC9F377952D6249911F099F535E6FFD1BECF740CC96822076C1C173E32EB8A2A1D282D8BFEB277B9BAD5906F6C8ECDFF4C980A4F708C8D83847A125F12D726A803911B7669FB587EDDAA13FAA92D1745DAE5494E4DBE639AA2B03412ED97FE1C1EFC391CBE070881822B2626AA473C605E9D16D8A4A44644D551C332240FC9CE25D8A9484A9F0A65B6DF11CE50A984285D2B583BC4ABD4A26907E5613CDD84BBC4B8A6FE153F5D50CDC700FA96C40B8F33F4F73F6260DAAB08BF5A02A2F664E62BC3BFAA6A4800EEE8423D93ADB908B28E1F1DAD9CCF410A1A717F2FAFAAD47C60AA96B100947EB6EDEBAA92FBE4C0AD2407EB3D645DB8FA4EEC242E907FFA8E6D5771F18739E44FF6E70221FA212F5755BD9574163E60412DC2DCC34F449167D76C769FC5D9D4AEA104824F0872C46D1E4C35F337D007F2EB9B832EFD426982739F74A14BEE901570011D4FB7F43B5069C64556087A248D8C09CFA5E34600B3BD6194649DCB093B3DF86DEEB4FB42EF65CB5CC3C3FDC89852BD57F34D20B9EB617AF516E372BBC4154AA94744BF2835AD2E71334279B019756795B96FBE4D57FFFBBD3D6E4E5786234FDC6E5768AF9329225E1BCB7F680B66729BEAAB9C5AC5A2120C8D427E349F364F595BC1D72874466844FCD43252D480576898E9037633A8424577B3DCFFA3AECFE14317B60F84E450247EEFBD497F4F79FBFD48BD99EA0CAB725A1A4F1CB10B461FA0AE6F5FB991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA6B7E3BC14749E7C7FA2F28480EFC0784B9C5FEEE217946EF2D55F5FD2902B6E080431350D4BB60DFB6DC98FF57CE274ECF76AB7C2E9A87D99EF54D9B8A5B4481F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C +remain = 65534 +max = 65535 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_512.rsp new file mode 100644 index 0000000000..4385540527 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_16_512.rsp @@ -0,0 +1,12 @@ +pk = 0000000BE63E1958AFF9CEC5CC26706D9B33FE461CF17B8FCF54E1B7394AA3E0B51BDCC89B4D854731B25D63C27019AF9AD43E63969A575E7C181079BC1207320A6658BC4D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000B00000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957CE63E1958AFF9CEC5CC26706D9B33FE461CF17B8FCF54E1B7394AA3E0B51BDCC89B4D854731B25D63C27019AF9AD43E63969A575E7C181079BC1207320A6658BC4D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B98A138DD28D76BF35B6B9BD3AA30CEE5641266AA5B6E3476CBE1CCB18839B063A655FF7831A6B655D5DCF74C93369FC562827A2E93B53A295E86E9BF8879371A9E0A176587912D1CF344CDEA03DE86B587548FD05D775686D36B8A3B5AC77165B6226682EA37B935C9FE0E02A8FF9951E2467626865C6369A8DA0916AFBFC03DCFD599163BEE9F73F99E34A3F8356E5F193E76C4648053269A659E080A7014A3EA4D7D9766FDB36CC8919294E88D722D9996FA0EFAE5FC3DDA45C14636AE77342A5654D12731B64E40255DBB777CD68D73B7CBB3D8D1013CADE109F474DEE5565B1852F646002BDFCE39C736116E56EB8EC6F75A46F2A19ECE8F0CAD24152DFA63F89AE0C375E32AE637BFD43A1D3B027930461A8CAE0809D65E9B81DE9BA9D0D498262EF57887D6B892F149030F734B44BD9DE9A4C8E97772A50E7404020A9D64D6785059250DC03745A68353456A7229B21F0DF6AFF33894919136D210915581A525208E3FC16F1AC5BAD3908D4D7D7155929F32C5B790F625CF89B8AD926220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016A30B3920D43D47945F47566B618719C38844032986568606F2DCFBD7104EEAC5436CCD86E9677E05985FA63C1B6D3E642D0F145B3FF637B96F2AFBEADED75F30100000000000197C186BD25DEEE5DC2CE5B760508549B1EFB2F3E0A34047232BDCCA39B144EAE820DB1F2D3C3159D012D7CAD7AAB1C44E15F53F4B1166E23DB8AA23ADA9E23AE02000000000001C5A2B2230C54CCBDFB5F42AD8805628B6B3D4723AB84E514035694195F2FB7E716F21EE8845170F30D1BEF79ED4468F2A45A72853F2D8F601973595098010E1D03000000000001C9E730A265A6F2DDC4B0F420CEC9C7AC976ADE4FDD5CEA3B6D5445AA2562772F76635C514BC81DA00E36681EDFEAFEBF29B1C3078AFEBAE3956D74AAF351E35904000000000001B661B82380E38D5CC77679867BB8FC1C94E77006AD05DE9576A7BD210641D25D011A056637775E72395B7643018E0BA023747219D875DBA848A58E0F9D7FD2DA050000000000019F3A31924919E8711F88BC45477356D330ACF65BDA612F6AC681F64C24FD70A6AF08B3FBB6136E4AF05B38A9205ACA4A2773D100FF79057CE6EF6C3F82AA9DEA06000000000001EDF9A31569FF07104E7B2FDF78D2CFC2FB28903D720F4D2ED95AB35DEB5EE579384ABCDC10CCE008B5BF753154B78207E452D4AF2B5646C42B89EBDDFA02570107000000000001BA911C4438781B45414444B18E3EEB1F0E57D33FB8F1BFB5DF1DC85D88A29371496D214B1042FADF9F17DFAC6215231DECB7D4ED1ADE6272BA7933403D3BADA608000000000001D85DF2FBED8348BA8E34D08202B5F944A00F91F1CC1F50C50D2460DFF1CFF490D84B84A1FDCA7A5E1760FF2E3A392D3F4ABB78116DDA6CAD29E694F9A4691E3B090000000000017C1668200DA615F45702477762DDACC68BCBDB862EDB8F34569EE898D80B4DFB1AA4251E3C3D1692C8C50DA2BD543C84A807DA4027BBEB6EA8A4093D5E560E110A0000000000011171AA4B7778E156AC8674A7522E4E47C54E7ABB917E693DD788D8782675BFF5E0108D4853BA609E9E9C0FD4FB0B8908D8D36F3CAB806CEEF40B173B740540330B000000000001AB4927F65EF9D6DDC2CF1B044B306445ABDD4629C4D63AE6278E049C96933D81862327AEC4B7D2C31B6C7509C6E45D2945E0121A0DB90076FD84AA9C5AA53DD50C000000000001F73CC84242314EBAD62F95C79805461C1902C40FD822F19F69C029997DFBEB840EE33A9905894B1290A75ABD10F4EE3BD6E75DC6CDCF69A7FA48735C08EF85E00D00000000000125A7E166681FE462663B71CEDAAF483C1D8097F57EE39EDCE104F6B10BD85AB43EA3C766F25F76C0AAD896BBBE825A8FA45AEF3C0483571EFA6FC24E973AFE4E0E0000000000013DB4DA57E43C4A075E6A8B417B395066BFB8C7291C42A04F1095A5F410002B3AE64DDC3633B2E27A4C28475C56FCBA6F0A6D5B730FF6320C89B39E55ECB22A730F0000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9476 +sm = 00000000BAA7550F0E617123968A7F276A4E50664475EB64F4E5DC6805ACFE998B45C1E0EF24208EC4F8C326F4E4D4B36902314578DB3668398F8D67F573F98468AC125AE12C99BC1AC30AC1C70E9F5512DCBB72A03F07AEDD114A5E2C73E994252AC7D8344377E0BD8DD7E5D8AA7C37A8350D10E78049E98C5354C298A2A97A05F1375AEF91919DF3C700D64569F90D0E42EA543393D5ECFC90F5E1ED1173810AF83E1E12445F5FB5590B3A00414C47D7419D2AA0DBE2E4003083B6294CABB043E099B1433B6322DC7AA17FF2A5B756F87FCED9FF415A70E5FFFC2794C974DB85E4737016041B8B817D20B986C1842F55C85CB40C06E274D6F22ADE5C49DCB27457A297A97E57A963C3BB42C86E365E37A258BAD6901D1F1AEC279CE2F14E9E3CA316DE8DA0B086DB8102A746FC5C3EA9C99BAA79F74F7463F047DD6878FEA751585B40004D9E5223780147183D48AE736A5EDB2D61D8301ABD2FAC1B1E60B5BD2133C25AE6158E1109CF1C3F9038E6ABAEF95BC0B8EB39BA412B4EBADED88EF612BCB5CD6E085205B104F30EBBCE03D9379CE23E884EDCB5844D875098A851A999B3C01EBD13F4EE2C95ABE76E4658ADE75DE9E73F3F531DBFDF366773B69A422916B946DCB72853EC436A574838038C65B859D520972AB0EF69714DA03A840EB9FA46B8AD366C3A3034C316001AB869808374ABF5C57D943809C2C11640C14DC9F550DCC7F5FE407E623B98262DE9618F71F36CB240F66418705405E0BA2D452296B522F1366C4DCBD16CCFC896B8DE3BE331CCCD48B291CDE4F1894B9B0AE51DF7D4FE0BCD0F86D8126430A4DEB5EEFE5AB35EB0679EE5F029BD0CA4F6E364F6F6B97D3BEF756880D8FD1F7E1978FEDE67E9068F4F52795C4258F0C001CE40F4C1B54BA7A2526D11D62E30D1D938D7B9475439E5A5A2E4FEF606A1E7FC210B415CD123A82B08539A2F9B9DC79ED7F7D75412DD6317D699A57214951587078E9F8FABB27BB02FD87E871FE65C3F2ADEFFA5C5BB430ECAC0694B88A5883710B97FCF72A39252148B1D304DDDBD9ABFC29054FF1AB375722D8C6705FD87A83E4BBE2EE1EFF9734EA129DD30BF7F62DFBFF2E7A511258E268F69A1D1656A2475AFE819AD0A624691C920445BF7C2658D34FC8AAB137C3C13ACC855A6CD66FD2BA32DBD7F5E16FAF47C8976C8569E330985CC808D67C4161399D64EA943B248C6849C3A91C0E38612AB2ADE4683B62E2F8A2418E54F8B1599331924FDDC3668DB783B4B422696A03800C9045010122E24B346B99C4A92514E0DEEE6CBB755E78EAAAE02B9F0B54AB3AC33799225B661D3F5729080FF9508EF12F2FBFE791D5819F0C283D9D4666B93C966147218BF5DBDA389086110544606F5BF6F120EA288696AB7564EBD704846D2D9DEAABB77EEC66ABE1502762C6DF1353DC29B95ADE5D05853F1C53E1F32519CCE7655A5531EFE89DC0747356D39CE8D2A52A35D7F82AF5AFC88DA85478AD66495150DBA318B7FAEC3D2EB99DA48EC9F9B5ABE09CE782A9C8FC854B53E2E5B514CA9C6623519C42514127D8D57C080EC7BA0A159BE9CD5C4D099CDA476E93A8D785AF6A303A3AA3B77FF313964E1B9E095E5634EDDA4D5BC8CA2C4333ECB93E60EA6AB7D3BE7CAAB2678F65B44991FB909802DFB0026520B1025A3435DA746BF4AC8D2CD5CC07DA809E5C388FF156FC159892D645CBC9B37B5E25BCA92AE0084379A77A4D2BEF0BCEF989E0317B0D82BAF54486B0792C312F8923C0B85E5FD4D5B8F86D9E99A12AE166F7E518713707BED5E140EF7C35277D8F0CF563CE49C71ED38C5C15D5514340457527590B9005E3C02DC8360E12DC702CE9622A16594AD89F0BB57F81BD71B0292F235EE0F52F8D5BC8317173675DFA09ABF4A19D71C21BFFBEF9B058C36B18F359ECC1A378E118EA577EAE122E71DE995CAD6048380E5A2A24F943F2468128A94AEF1CDEDEE86630F9D46155896408BF90C0FBE204D7EAA49B6F0E117BBC58E3CA42AAE72BAA21EFEF8B3C248F9C085A1B39D2733D451865BD9D23CE32519057EB3E345BEE6B5766591157B9EA7F57626EE4F9A94352646EEC8C35E41DA59ADA25FC38F5B35E520858A8E490B20FCBCAA8A487B90395CAC25B1562D77FB982C9DBEFCE6FE507841EC30E547B0C6D6E717E125450016F77CDEAEB8E6CE1E2AD4E6C5FE29C788FC473BB6A1A9EAA4CE83791D0B7A3426A2B86E5C328820E839F87FD2428F7C4A5F43477C48877F8FA0322107D10B532044720D001F62BBD5581247F6399DDCBC01CFFBD12C9D312720BC16A8BFFF3D7CB1E83D96547050B25B2881681427B16752B1F58F3EB5B8B4CF8AF877AD3E6B4EFA12DAA71D2FB9534CE5F4A6684B24956647386385D57A9944F3CA15E326CCF70F8403C62E07149558EE2FE2F5D7F015C88A93E712E3151E316B9BC4A8A031502F073DAA1F1AFCB970AB6874ECF40A3383E2BB3196BA7320A08AA644538AB234E8D299940E65093F353F0A78C01D93F58D5E70FD464E07A1B6C7E9DAD2985C8C5F9FFB489D692E482CB83F95A226F2C351763D0B1AC1EA2BAF9907F117FF3C5CA5303BDA839A3293A171B77E9F68414C5D4FDFE24129B59D15F154B984B79709EEEA084A07809697EC9CC748C2363508461D7A1F1D6DD1887FF96A2BA275E110740210E9507324C0E4DB1A0CBF541C9EBC2580D9FFB18AA03A1A1DB485552218B5F1D05A1C862AC7D0439C8F12EDAA7E7ABF2903E653691AB5A0C26C6B30BF0053E0629BA2FBEB8BC6A5A6C2315ECD6BF9F755D40DF5929F6CA05B4DB3F595E191FDECE614AA0408DB903B338EE8F2458A32CEDABDB8CC31C55220EB7EDECE225A0E0BA8DA3A4CC35408FBC8277E5F6B4BC0713B96A52EC914D4AB4100449B159127DA510E6C94C4BA751A4CCEE6AAAF7688D1AF7B8EE10B187FCF5E172FD997DF85F02771CA9C5432BEDA41F922D3DD9FC498425CBC698F32CF3C5DAB50279B204CA067735B54D33BD0F96280A1486F8AE9E692E9BD39C687796024CDB0EDACE00A83A5708EB72BCECC6A51A4D266B6C0902067DEABA6C0E4927A0BA4561A82635A058571FC30921F054D27574005C4D91C17ED8FD68F88DD71D763818AFBAAF0D6BCA51E2825730CD6516E6A9EF5C99D133A82F2D9F240AEA8AC5293C89C4228FBD398BFF0996E3AE3DCFB7A1D4BA0A3200827EA6573D349F8CC2771032A128D7A61E772C20955A3299E56D9E5B0F746555BB8C0DE252C19188DC3731747F2BEEDDF5E92BFBE630CE1A618E4E7BEAA674BEE4380456301B5D0578ADACAD2B685BDCCD8BB20A0EA0D330F284E5AA318FECFE8893138D179FCF67DA80DB5A5B0A1D83C205106555F9ABB6DC02309A8310654B736B879C5806D86994DB3F3B2076CAA13A7BD6291B0A5F18DB24A542E6CA65EA69141F5EC8726336236EA04305C638B19C6D97759361B2E9F1EF455A997BD4E48C7ACF00E1945A919C77B6DCBAFBB3C3A1ECF0178EC042C940B1D449D803A955092A32B0AD6DF0D6B22D9B6884BA21451F8430738F1D32139E4B450CED6BF244F0D6442C6D1245FB2024904325D1744CFB92DE691B5632C00AB1A333CE0CA6AAC2D056CE3AB2FF552E5AB8E4EB626E988ABF6F27010F010822710F38B85DA10A0115FB8D76D3DB3E79F27F8A5E472ABE15B46773E77511A9AB78CE4076087F5E46AA21F953E06E11AFA9D912D93EB716F9FEC1C913CD0B2B69643FA4D0BE4D354C34234F65A1358D9FF6EB3B686FC1CAFAE14EF43AF20A498356FED501E1267F3B9C1D061109288F43CE00F4E188CFA2B68CBE8395768515C48BA515A46F4E48F669786AB3D250F3AAB360214309179BBD7E6E4F36EDB424524E2E28A7C2BC00683997FEC38DA95CAECBF5020C5CBD4ED3C041D403DE200C93C0AC004E471BE71BB3EC729B853CD8FED9F22241FBA4517EA291BA9841EAF8453597BC7625E4CC78C9F9DA52147C1DA50F8E7DC3421F3F3393412D535A505BCB84BF9928F9A8F6BCB87DCF80FAC84D9A80D57879EB74D6FADBDF060F6B61A7F08CE7F274D7C365D36ADEA9DA7642CE3E9B55E7FC0F72237C02556F514DB779EAC2C89993A623F55F668A0E01079E50CF885AE8CCE63F335A33763687E2EC2A61E6DC571268B4A405D32BF54DE503BD86431B262C14E2D0B482D1D8C0516EFB1E4BC7C59A3233597BF10FCE6176F0E5F93853CA71A15EE903F51F01275C307059EBCDDB41662896327EF0CC02108DE4E66C4D3B5B1BC1C4FACB24CE6613D9DAEFB55A6B5D6C6DD925C5DEE1E43079435E6C3EC704743E7640E4C8F5FF2CB29AB5C223A1FCE9F2D4CDFCA8C9535338004AF28386A3EEC6581CE06F0B5ACF3B7CC4D11693D840746377A1781473F4DB2AFC1E71939664DCFC76715EE777832C29BE4CC0B10864EEC338196F4F38FFB2E70AD32A3C15D9082C9DC5795CD2B3C38957E03AD9261BF7B836F8BF1E50ADA19F026983B0902A37FA2DB926B1AF6C9B737356322ED3069010190286939CE20B380D450D6E4EA7B71B982632C4B9067A21D3F24DC18087A335325EC49F747003438F8F088EB80861F6C1D9446EA350450C52438EF91E4A61B41BD6E74D8516DE54F6CC50665BC5C9D9183F3195A7117BBA583A2EEFF10B57B778B7E95DA6BF8D18E2A1391112235EC64E7701AF5C73231EE6664305C79FC59BBD67D774C80D33B9CFB2EC5DD98842BC41BC3888DEAB4D33E74D3AE046E4F2B2E17F6037C4595AF6E463BC5E9F7C95CD26997F7AE62A388049D0CE33A8E9760EA94D8BC65A8002731547678F88CCE64974147E67E81052008549E3D90BC5E61C5B95AAACBCE61A75FCB4056FCCC93D91203AF60A730587960AFA8AA6F95E50E961EEF2F0A7506A685D8E975CC89BC67B777C530CB62430FF11C6508F338174719DEDA9A648D13AA86CED5936AB7026DBAB13D49DBAA5E575569BB67C0F5DE83A0452B567E8B7CE3C65F59FD12B442BBE6FB5D458F2A1A821DE40AD517559A24A8E323696F6F6DB7D8B16C5EC58E3A77530E4C29293A9DDC08F4A6D0E200D248E2C132E18C72B689F3C4D183866333B2A6CD983B4B47205E436B696D885088A5D5643ABD08F121FFB92A69470BDE73F9DDEDADCEB572A5BC2C2987493D5A832DB8417A3BE817601E11EAD608415358DB7DF5ADF61EA9864171437E0A9318BC9805C322797EE85FC7943577C831BC24072FD1F8E29241C240CC80215017D3FAB209F004983542258302E2618F67B99189CBF90FE1D3CA7A6B991E138D798ECA742954D56A43598C0D4B9D53B143A2FFAC61C96F5BA13BC6B2D81687D212DBA423675391A849225AB53DB48721F083FE5AA727A727CD1F0FABB2DE7C2744106CFFCA3E687F596DB59FC5886291AE4EBADE51171B0BBA5FAD9391938524A148BE1C9F5592B29C7C486B841975641B0F63C4FD5B60E4EE27FFF53700C77F52AE131E606BD22B79E1CB48969F4E94E48509AEDD1835044C391DA0D16C71C79317CB425A158F86AFF9C0C4F310554EE1775D1063E6AC1DF9EEC2F9855D6F9CA5D5717ABC6A03E3827911B025EE757DC6CBC8F0A521628274356F814FBE77BB65DD2BA6F24B8F68682089B0B4CCF4AB93787DDCB748F5D04F734C1F541B317C408DB77F9B6F3B41DAFA3C40C3C423A3A05B4D123ADB4A08B394FA626F5D80DB0F3E63906E32C51F6E79CAC4360DCB620AE869956C87CF448B0B012188077D179A6F21899B15F77ADA6D24062D14F8B2DC33E809F9916E4EDB68B3DC09E0FECDA436E314F6C1B9E75912DE2D553C04A63C904721FCE036C8D30E27ED04EE5AFF1DE11E9F7DC225F1852D1D66722A766CE5C26ACCC6FC379BBC0CFB966C521F50BAD8375FF6C48EE75502AD81039E7031386B91FEDABD23613AECFA6298D961EDB5D7EF31EF45398B454036593520790E422C9320569CA969D2B8228F13931AB7087849CB7743269965E1CA46CF655DA1917C3AE60BA1531580528D602EA592C9AB888ED4F5C9C0501AB6D229E3D7449650F6195B2094C91D771B7B2D237AAF3D3F1EB0A9B213CE39A9DE996B39C23A59BBCAA636FE5162D840F90C6AA6E28A0EB3629ABF902FDB60D8A6E20B1A9E5F41F858B2E35BE9BEEEF93F74CFEC0D60E6988F3CD8302F95618B11D3E55F66DA8A6A7544E92CF1F507B628D36D57360E31274AEBF3F77205FEA5CC9BF057BE026B7CFE95893F9D0583FFB15896D4FD9C485AB70D06D67C6D0CBC604BFAB9331F8F36375725D97D74ECBC95047221D0E09649C1C89D14DA15BB86CE74CDB0DFEFA89CF07C8C09AC7B78F5F8DAA070D6D3C6AA30272EC6EB5CDD6025166FAE7CDA5351A457FEAC61E5DCF917F264F61C944D6AB7791FF89B0039481572CD7C5D49098966F87801D4313C16D644DB8612DB934A7DD68BB172F5413ECA078E09E956AE5FF1AA1E70FCF82874644FE072AACDBF5001347E5DFE68B7623D21D93B10D2F658D98535E4F015C53A1292BE6357D295F65D285B0CCF9245A47E7331FD7B308AE3B0FE33F4909CFDB64F4F6A26D882B6772EED60FFC985C2F61FD3078FD2F59366D78B33C3973E40B63322D75C816F6643B34E75D00EC4D68954BC2F28A0033A541661509EB337AD0E47BC30BCC6491FAD1F664385ECB53AA091C209AE870A910083DFE4EA5EF73059803D256B4399E63E4B71D608B3FE571868760964D7C2809851E0378FDC63BF620F1363C25C30CD1B7EA77F281D50340602F9224AD5FCB34AED819909BD05868B218E233A24770D332950AF29E8B0DE35163882C0343E2AA8FF50324FC773EDE5C94319531EA89732DF779E23262FB9064A8A359E814642D1B99A36CB122AE6E0BEAAB3500F4F0D65BBF745CA24C7685DD84496DE72CE33027E8018104D3E3B8A3A35C2AFC4A602E8FA9C42BB0FBA7A426EFA9890C2AE4384C39BCDD612214254E8FE43C02754CBE3A2E2687165F0886FCB36E669EEBC3FF86F52EDF7ED16F6246816968ECB720055842C58627C7BD81D6DB051C00B993D0743B99776CE4A793654E36AD40DE4FBDBCC74F023121CADBD2C1D0C5B8EAB4A3BC583BC97B6F4E5D3F4B825A5B88025BADE3B2C04FECADBAA18DF3138E24BC55E48104F9908C9BAA96371C622F7702D6010F59894730D819697CC3EA8C3158D5AECBE6CA7AAB7FC1CB51E410831D81AF12F49E36965011EDD9110AB4936E70335BCA7142FD96BF7C7684D2C6F9371FB39B560E3DB53E2CF4AF28288E4693A45C457CFEE2DE2BBD1AE5DB1C65EE01DC660CB27746E98646478B27F1F5A6AB571E4568FDB14EE3BA815E895944798CD1EA08331F3FE931B48898FDAB48174659493B0D39956CB4828F888DF0C1E6E10BAF50D4301FC5FB92B5D1FE0D7B5491F6C750A8FB384827807273AB2E3EC3125F4C07994A12AF71C3F1D8B0BDCECB2598E602586B54B5775B292B06A407E4DBD04BE47DB9BD008421F0F70B177E71E3980B4CF2EBF6154B6306D99136E2C8B4AF2FF3604837B455A07D2732597846CA0C2AA9366D3598BD34204046428004686B881FB5F52A0BC6C244DC453B6AF4128E1972539ED0E98FDB952E756C09FEEFAD1AA03BBA471D8A0FC2F08D572AB0C5C8EE5FCCB6C40E35CAB030DD5361A86B0E30E20756D65DC4F9D5FDEC968C9ED481DB2D3EBADEE1E6741B2184CF68ADA3B04E2A92C190F01E8F43CB7FC5D6C2A7339FD09C8B8FF9135E3DDE85BA80E54F5EB2FF32851F35CB057793E912E93147ED00FFA486BE23653AA83DA8A5BC14CDC7319DAA10995F2063BD4457618802D7B8644E6F61E655B39871CC328CC62F1AA0701A36EC9FEE032B1595B0D8F3517FF85DC09678CDD9ABB313841B10CE8AA11A6DD6AEFA6CC3D876F90783173C141D0234318D679E03B07BECCD9C90D23A93A05B2281B63AB124B1DC13EB95AED53C4367973203DB6833A84B228ADD3EBA92D952795B5E6E095056C687B031CFEF4C8A9AF779E1B2ED16163C5D575E2070D7345609DF9C1DEFD133543C76A72FF590E70362F5A73C45597BA94F70A6742AFB3216201D08505147446DEB4A140958DD88504A979B25B2A23366C81CBD06DFF74E7A93B60896876B7B6276044A6C8FAA20D657C852F594EC1CAB2B148A6AB9C84F2267641FBB28BA4F867BE2B26BDCB93F558E2626065B39431EAADDCAE761FD53CAEC6FB5DF898A2C95A7D44CD5EF84E3EB1D83CAF2E5A63A02DB8098BEF89B61E971ECA06E07821BDBDEC22A8086B82F120D149F41074FC2620270462C6D23A09EC22F4BDFCB0C5C04BCC82FF67816A4C203D80B7AC18BB30710235F1B0A02DF94FCBBACC7A1CFB719D048DA86556ABD468C69C5D4BE845D45ADE69C9A8D725CAEB9DA4FA48884B5B3570E5DA3BC102865EE9ED58E8EC07672817A72F009C9BD007BC4158C9B137E117BCE2F0255A1CFEBC2BFD8C36EB534A1B2D9CD8C8F87905375BD8B802322779248174E5F15041EA7F546F1B0D042A53A93A253DB083D7F81FEFC70DD5BF1DA47596F77BBC6459D4A79DBAA24C05B2EC968DAB2D3D21A430B98989DB43169B3EE9640178D66B3A80694647202246DF5D090CF3F3222EB4A3817760F193E38417E9DF5065D379FF6481580DAEC9956337BA21B066210588A6F80653171297D3B3F516784A02A6DCD7DD23C9340F0C13A86C7B25F84E1893D166D47F134A082C2B2EE4DF7E1D6E6EC747CCA360DA11122815F448356BD4B9B6DE4F5AD60AA47C9C7DE640B428494673ACACD8FFAAA3D6E36D657425D8F1A60C31EE940BAF7BCDED624CDC0E4DAC6A9A1F8951B1A87CB4849CB5D37AFFE410B3D00E014D8425B4D74C3A76497B6A5F1C08A9FBBB3FA4D67B1D8DBC76306EDD94D6226ADC0A202849C65D7E1AE11C1E4D21E02F3C939F17FD1E066EC50C0C81265CE0C7733836AA43EEF5A888EF0A557C964BC1CB08701FD91CE0A166D1E2D8415CDF34647D3B67434EE76B89B6BDE6368D909747004212CD632D44A4280E0C92645C44C3EAF0C01B4FF14A52CC1710058A99FA7C8CB46E06588BA723CC3FE2BFDA8DF36A7582E3F54E128D1BA5E8BBEED00464387B3280A80E9AA5724E44ECCBE883CF15B07E593660AA01E853F18BF5A511D6640386AD0867475E85766E0220AF8158FA8E494347AA140009EEBC3D423A059747C621A148B107DEC26289F9F92CBC66BA9CF0CF883E53BD62F899163FE38C74FD9AF0874493DCCE34428608C4A14CE76BB1A7600CB5D60CE0AA5454AC1A62F02F393DA1E5EA3186D510D15AE626406717C81BCC494DDA9430E2C24DA506184136CD2CD06E4626822F04E56EFB5B93FD89195B4D6D7E0835E339957E2F2F6E66F65BBB512ED0DDB2B36C5C7FB039EBAD72FE891E6AA459442EAF99929BEF947199C08EAA89A719F8052BCD3EB273EB11F1EA1914133E6545A4D6B9A1D259ED760F90C5CF56FF6E3946E008A752163AD517A3C443DF600A8E5D83D32ABE887022437B08EA6CA008A2FE72B0E7E6A22903873879656CA49391B2968E7B6029EC15B1C737DEFF674BB3340BD24D435808B781BDECB2CAF2EACA15D01856F389E7E0BA887471F85607FFB4444A16CF5FC9740CFFB0F91D3CCDC6C27E9CE96F01271341A7236502141B41DDA4EA016970395026A77B5F068F62D4432FC0CA6B377E6C634ECFD43AFB4A01DD7AD33FE82DB3FBA3924B1A48ABF1E4FCFE9CDC0F8BD4595EEB4CCF0EADEC874E2822536177FA3AE9B4570DC928A7175068AB4EB8B44F5D85A98C6D62C7DC519788142BC08915A5C25B8AF7D57AE1535320EAF9DA27806E77CBCD36102D24A29486FFDB5B3F21F88E9914BC2C9524F9010B72217CD3E524290AE85841407C5529E4AEB4C9A9121CB89E28E2FED2EEBB3EB10AA0F04FBDADF278423E80A645F3A5950BA42CE8F5CA1AF452F8E17310609F673E8B194C45A6028856BA19525A1AF21DDF66DBB42867169293631C8ECE4248F685DDDD67C5F8132F2BE3400D02571629FFF8DCD4EB8E3455370EA9672DD8C9DCFA6D125B4DA10DE0C166920E025E423DD0509E46D86876A69B2F09D11CDCAD6F4328A2B59AFF5C51CEEE28AE7023E726120A24346BC27FFA4188AF834FFBCDBAE46CA3A56911854FF595CBE35BB2D25F9A49EFAD39AE131B60DB8825496709967B4844914AE127276F74E593B36D00D934EB3B59D791D9F509B9D00BC245DF26E76DA86218E33FD2DF4019EED80A7B35D239F09C07F99000A6D0AFDE4FF6E88E596578BBA2E9CF89D070D1FD3B220E7A040EAA2D365AA75616C844C1ACD07FB19F3B7DCEA8859289B01609A3C0D7A6B790776FC7E9A606EAA2E424C2BB7C5A1E9636BC5485AF0FF25D6324E13DD067C3F88AC0F509A3D90CFDB259CE19B3FE27C6951BA56150D2293B7A5C64E8F564C0BDA74FDB4B60D9A66585F053F0BED5AC7BBD50557FA874640AF8F2EEDE4199813DC53BEE2CF3D4EEA1FF20F99E459568F899BA40448EA614964FC2844B13A83234502A4962830E2FC0AB04AD714B6FE95FFBEBE2550373E8AAFC2E192B9EC1B1BF441C56B6A1ABCC562C51258D46D63F585874E319EC6C777B6EFA137E564B38600DDA185A20727B6431825575F1731DB56560041763020F5950375ACD5DF0630E6308DDEEB474C65E36EEA086E76FE316ABAC8DC6C9C9298E22307DDA9A4170DDB6027DA5FCC4C5BC3D924D4403BE7472EB5FD9DCFEB0B74B2C59F37263E622FEAA18EE65F29A6B04F19D19397B83E24EAAAC4DC4B89E1F8E8FE22DBAD71DBBA2B1E3E3B9883C023516F4070A2EF4D60C79986459920B5402C455B856092DD9834AE32E3F6B3B4419B93EFCF288D50A0272E7E657AA76D91BA47032F7276B98E7DB9C1C676C40C3D2ECB76A243141606300D18AAD44AFCD29E626BD50EF268E83EBFEE1254039E00DCFC1C9EF04D5D1C4B68FB6DC3AB906082296F3C5ED29907A28F3CD5AB4EDFE18FD93E145F8A22FA69243EFC57FB452D6546312B64B140014BE557F111C383E6A230577E71C0D393A5FF4A64FF24DACA82EBCAEE30D15A09B23B5A8D2D7969C7A722D759C2BCE5B48B8906C6F67AABC72FA964752A7D92474A8A5EF85B50AF508F6FE268F3AB7EADEC9210CCBB4005D44ABAFE1653F5B529503F5CFAFA171DC71A6B5E714D6DE20E1ACE60FCCA0CBE39808144826CF71D57F66EB4CD9C84362FD3024AE7C94C905EB0575070E29D59B8EFABF17B2B69FE4C376232D718644512C19B10B57C137168545A00EE2B08C511ECC71007AC5587A1107BC3A186C0BA320D0CD19121906C8BD489B683B846998F33199457B4BD9B35FB9F5539746E37C00D02AEC01EE7F689CF130231ADE5CF12620C5F3CDA95C65532FB0421DE60E0974045B9FF51F6B33FFB9E57FA4F33C1E9285C5B231D3F896902592A0FE2F750C782A72A11FC421FE34E30C2A3D25E11D8942F94A2880FA2F79ADD49E81156DCAA92701B6C69C85546B09603AA65EF5FBF3CED9DC6352F3FE826DC7CB4A4A27B69FFEB1435645D5AF065727A4D6D1196D4F220DA715702F8BAD68D2F53CF02DBBB753DF045F5612B4EA3E5E64402F384C274407B43804B0AC429BB9F41B422734B95E4663D62B22A694F51D409BB9B70881732B7ABACC1333B74384F706AE7F8EA87DED4F94678BD8D61AFCF0F7DBC46E1CF96571182EBAB284DDC5649215CE1AEC155756794BAA2B3AC06A7332E900E0791DB4730D1F9C8B2210824ED920BCA37246A51653BE1221C9FF9DB1FBF9C602FDD52D0092B1BAE8FBE7716635678161F1AD15FC55B651150FF4743FBC00C55EB5DDDDE5576F21B4AFEFB9DE8069DFE7B917653E4D180F6CE483BC229D37FC72424C4BE81F59B0193D2598C75AD9B818E84985DEDB445C4DABE5956646227A2354289FBABE2CF6EA9877DC08630651D69B78AFFA04446720B55738BF80B08BDBCE28A935B020DE50DCE55E56566C607D9B8901BA171CE5D8752AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B98A138DD28D76BF35B6B9BD3AA30CEE5641266AA5B6E3476CBE1CCB18839B063A655FF7831A6B655D5DCF74C93369FC562827A2E93B53A295E86E9BF8879371A9E0A176587912D1CF344CDEA03DE86B587548FD05D775686D36B8A3B5AC77165B6226682EA37B935C9FE0E02A8FF9951E2467626865C6369A8DA0916AFBFC03DCFD599163BEE9F73F99E34A3F8356E5F193E76C4648053269A659E080A7014A3EA4D7D9766FDB36CC8919294E88D722D9996FA0EFAE5FC3DDA45C14636AE77342A5654D12731B64E40255DBB777CD68D73B7CBB3D8D1013CADE109F474DEE5565B1852F646002BDFCE39C736116E56EB8EC6F75A46F2A19ECE8F0CAD24152DFA63F89AE0C375E32AE637BFD43A1D3B027930461A8CAE0809D65E9B81DE9BA9D0D498262EF57887D6B892F149030F734B44BD9DE9A4C8E97772A50E7404020A9D64D6785059250DC03745A68353456A7229B21F0DF6AFF33894919136D210915581A525208E3FC16F1AC5BAD3908D4D7D7155929F32C5B790F625CF89B8AD92622 +remain = 65534 +max = 65535 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_256.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_256.rsp new file mode 100644 index 0000000000..ff52ff9d9a --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_256.rsp @@ -0,0 +1,12 @@ +pk = 000000091EA51EAA13ABDB2B1A37732B47125C74B4F2D624F9145E295C560DF4FFD6AEB404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 0000000900000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A1EA51EAA13ABDB2B1A37732B47125C74B4F2D624F9145E295C560DF4FFD6AEB404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D9330900000000000121C29A3D4E6C5DAA979424FCA26B0EBE6D3FEA8F078FA9A98B0F55503C2541CE0A0000000000015EB6FB8267689B81BC8E2C8950E5F59F4B43194AB167C4A60EC9BCDA7572E5980B000000000001F02838F27F104405AA4D9E111D3A0B1849F6725926BA5B3A6412DEF900E7259A0C000000000001BA1EE79A04487C5639BA096A60E3E17F7A0E9C0238FA049EA7AFF52FAF5890980D000000000001B63504B794C356EB44A98DE32960830E6B275526432F232A7729ADA72571E8D90E0000000000014DA82230B909123D34E30FE0722BDD93EB6D56243518275547CBA7C473744E6F0F0000000000017AD15652FFFF1B8B9E752AD4A07EA737B8D79DE25D7F194E19ACF003E62C48F610000000000001D6819E585CEA52B14299092F01E66E9A6E7AFC9613A69B89ADE061890A230145110000000000017FB1A159FFBC19461AD72D4E385722A08E9A942BDBC3CF8352CAECD938737D89120000000000017B2C7FC20B3305327D2F0FC3C4854B0053D00E56EE4E005E43CBE807A619BEA813000000000001000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 2820 +sm = 000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6429AAFF05B285E06B6EDBBA11503F92E15E17C582FDE9CCF8FB0E5BDB90FCABDB107005759C1AD991FBACA5F12BE25CCF5A487CDCB35D2FA0415A48AED18AECFE49E32AF457F664D605D54CF42246B21C1B822727BF0869E79C2479B3CF7EF92B2D92D18C1A9520CC21A0A17908D121E1EA426738CFE364AB99172E83544AD0FEC48EF86066353B471BDF03374C02568B2ACA5D9787A3547B32EAD02723B86085852D62225D7554249CC1FE71B8CA3B01240808B769DC4154DB886DB5C1EF5B5CD1E9A5781AF0B8028EC1D1E1E82D6AD6AA45A6D07B244962F9CC5A5A14674087C37F5C128471A780F7E20C5F04EE713489718EA13D2DD776EC37B91AEC089A1CB652A4CA27DF77D2B59BDD5DB0D4657882E1C3D50D022B673C7E4C1DC6AA9D0961BA4254B0FBC7E8A37B1D610C74A511E52A8A50F4943217493F7EA4C92CF25FC55C8986FBEA375F95A3E2EEA5595322FC1079823D49731A6713DD270B3AD1DFA54D60EC4408C15DA7FC4B5BEC5120F1966279A400F0AF374CF6ACD439AB0307168092C3A8F03F4024169DBE782051501D6CFD53F3344F583668D2F25276D0F93B0896752FCAE3699AF03C2E8C8725BE6073251317D1EEFB497336A32C511CA3D91BA9C3CF4528D139148FFFBE43536D085EF62CA9EDD4A56A4127C96366A690A32F4705C98818ACAC9A62F3421985687FC5107199B035FFCFFF5103D7B169AAFA3F7873198C245BEA6FB442A5EA0710814787B60EF727174C29BA2DE46E283BDECDC6DB095544CECE9268232729556E6339B9B8A2F22FEEA16F32E6FBA5577B4CA665BE58EE459BDEA5C1765D63045C230ACB40DEE76D8FFD25275D33730D608B41AD8FCF6149DC8C5602305056A1E00EFD26E79C204239C69DEC416E8AAA98B43CCAA440867C0C6B6C74E32368C7884B8860E5AD1B518F322EE72CEC31F52CB0B5D16C7813F05F9578CECC287D621864B54E54836F3315642DAF8E0F3A61C68EFB4FCE7D560363BC9F3A5A0086D87169AAB81B9736674E598CB301F84E7F03D94EC6741B481B978440F93D3B0A5426121B516C7A4D5DDF078995BD22D0970A4E6B4D0E8F6B2040D9CCF85DA7C9522BD571EFF09D5B1561225886FFCD6B7884FFEACF7644B9DF10F6FF9F1408EB28E5F212BFB503C2F8FC7981663C50B7739E3F2D9487FC2287870964D9F328563E36677622B3E074A980DAB585FF96FD09B7A843E4B2BA51E42D964AF28BDFA113E2853EE1051EF044C34EE020DBC7172C1A1C5F71AF0F2B8A6A8F9C2E4C8BBEA834A94F34114CEE3ED19E514449946DAEF69516854BC502BB54F46086F5FA4EDAD92893384F67C4D1C11E826B5F1E910DDA7ADFB66C00FA7BEC717F2419E026C3492CE4DE1B568A4DBC25C6C592641852AD2D562A9CEF92CDA1EE295DAD0074EA1C01DC90A6831D3499FA6DC8D6B5D737C95C689192BB35FCFF90B87519113376A44AE4BA207EE9AF82719AA72ABF543ED8EC30C89BEF5ADF1723437F91863B0B6CBD2373F9638D74D6EF309D1B787311CA839339BB9AB60CB5B1F922D6C430FDF84A3A8A81B7FC0282C404FAD61A9AEC0E974476860D49A2BA734DC223B46D2C25797CC55E16A37D56B5021A9413F7F65DE41A840258A1A492267B8EA54C51DCCC1A4572023546321CE81E7F51B4DB3836B1E2CC30E6E7DC45BFDA37C100EB88E44069492CECC82E9E4EC8C7C2C9F85B0BB6B57713F156B0F0B1F2D50589DEF2CDB05E5790D34CECE7C22212AE889BAD4A39F127D0F88709DF1FA2D58AB09D249014EAD040C0934787438A1A5C7C9520F36D18AFC8DAB6866EA201DB358B45AA0CDCA0959B4F0BF7ADDCDB0CF61ECC7FBCEDD43D7F85EB9C9B771CB8EEA797E79F369BCE45087374A20BDC6FEB45871AF744BD1C6D91F72509602FDCA13C0F43D8C9C0EC8141AC267D940537B86335E609D558CB2D1DA9EE891F338DFF31CD3748B61CDE572EC77997A2BCD420E58ECBDAAFD9BDBA4BD815108B240DEA39524C501079A2815C04018C444AAC8AEC51B9207412600285537487F1C65E5E53B472D0836698B80E10F1F06EA466C78F7065088E07801C44DC68A93ECA841BFA02881FA3003878D8EC6E3CA1CC6590607558CE59C93E72BCDE6D87961B3185CA3ECD7D6A913D9F86EDB5017F5A1F28FBFF054D1BECF740CC96822076C1C173E32EB8A2A1D282D8BFEB277B9BAD5906F6C8ECDA3BEEE3253FB58D7B532C7885549593BF2984B3D6FCC2E70105FC34A1CD9A85B9B2A48FA806BB1FE35675ECD1BA10FD998068C0797A6874B02F3759F9DCD3B771041F74F76D99E4FF70A47B904C80118090DA4220AC717C36C588FD89EFC473084AB49FC4849D497AAEC8FA2A8C8DB244001F4348AE47425932E61A64C79846C4214ED25F04D7E07E38C51FF1B1B3BCF0D8D38B31CD3B8A69210C1C3E5A92FB8CD5BB3A57E03D5D9672A86589501558211537988D9B6FD2B248B4C6B39CAD3A41052A74A72C2599419F61A78459B45C7976E43E96BDC2EBA3AE45FFFC8766D70EF340F6C1BE587DFAED8EA010542245C17684A9944E53BB33C776507D940D6990B152898366FC0906F835ED4B9FE9A776EC249F3B7A73C8ADD42D2B17B5893634E68CEE35D6BFFC32B9C588DE07ADEC32475AE5AF1F29EDC5E4EBB848C5DF4EEFB01A405403F4ADDD2097729FDE708EB369DB19FAFC35528A11EFF706445E69FC3F47DDF27092C44B520438B711428B717CF2D19F31D996047E852CC36403C86BD4C2485B886668646E164CD67132C6D187490F3B18BD3A339FD5FB07DFA9F1F74466844FCD43252D480576898E9037633A8424577B3DCFFA3AECFE14317B60F573A7CB1C938876CA58C9DEE64B7EDCB6BACA85C9E20AFAD6B68054B862DDFCEB991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA6E323ED6E8A520C761F371CF760445A3E865E4B2524DEC48F47386A1E6CE55611B40AFF393D6177502756D15DB5232BCD58ABDB633EFEA7390FF8BEA443BFB32F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_512.rsp b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_512.rsp new file mode 100644 index 0000000000..35c2aeb6a0 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSS-SHAKE_20_512.rsp @@ -0,0 +1,12 @@ +pk = 0000000C2A857867C4C12EC4296D971A38A242B9DAB9C173678C2BC776A662A1619B1B0149358B252995E4B17AD6593C1ABE2AEFE1D2A0E4FA52E24E73AFB0A4B61A3D544D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE +sk = 0000000C00000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A4E3B7DCC104A05BB089D338BF55C72CAB375389A94BB920BD5D6DC9E7F2EC6FDE028B6F5724BB039F3652AD98DF8CE6C97013210B84BBE81388C3D141D61957C2A857867C4C12EC4296D971A38A242B9DAB9C173678C2BC776A662A1619B1B0149358B252995E4B17AD6593C1ABE2AEFE1D2A0E4FA52E24E73AFB0A4B61A3D544D3FB22591039B76774FDAF41CDB22A8B5C5A20F3BE5F9058E466D2A013C60E39DBA2EEB33B69D3A87F593F3D02EF134760D5BE6BD693833524E2A5B4AEA21BE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B98A138DD28D76BF35B6B9BD3AA30CEE5641266AA5B6E3476CBE1CCB18839B063A655FF7831A6B655D5DCF74C93369FC562827A2E93B53A295E86E9BF8879371A9E0A176587912D1CF344CDEA03DE86B587548FD05D775686D36B8A3B5AC77165B6226682EA37B935C9FE0E02A8FF9951E2467626865C6369A8DA0916AFBFC03DCFD599163BEE9F73F99E34A3F8356E5F193E76C4648053269A659E080A7014A3EA4D7D9766FDB36CC8919294E88D722D9996FA0EFAE5FC3DDA45C14636AE77342A5654D12731B64E40255DBB777CD68D73B7CBB3D8D1013CADE109F474DEE5565B1852F646002BDFCE39C736116E56EB8EC6F75A46F2A19ECE8F0CAD24152DFA63F89AE0C375E32AE637BFD43A1D3B027930461A8CAE0809D65E9B81DE9BA9D0D498262EF57887D6B892F149030F734B44BD9DE9A4C8E97772A50E7404020A9D64D6785059250DC03745A68353456A7229B21F0DF6AFF33894919136D210915581A525208E3FC16F1AC5BAD3908D4D7D7155929F32C5B790F625CF89B8AD92622A0B155ACC09CA4CDC24518B84CCF0C924388B77DDD51F3FEE646A774CE41367F983402ED44E85B679908928FF5F7522BF9199CA1A41A6B42C6CCE575A6343E512475A3CC90B7D0A456141E1C3ED6ACAA15C6241328BA1936A6F78E0D6BEE97827CE1E329F2CC6B58E311847B4195B396C8AEFCC5D9A8F08EE282B26B4CEE8B79043589828F854650D73A433E0B879E11C577ECCFC08AB67DD9FAC9C3E5128060C2F2695DCAE7520EF6C12DB22F74F2F261ABE6F9FC6244489B96ED9222803F635DAD7FBB43AF6C2913FF809E208C97D9379BF5BC7E4276CEE51C6509A6D13D4EEC779A04A07B3D80569AF1A325ACF378A219999B8F91DD48AFF90105FFF878F400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016A30B3920D43D47945F47566B618719C38844032986568606F2DCFBD7104EEAC5436CCD86E9677E05985FA63C1B6D3E642D0F145B3FF637B96F2AFBEADED75F30100000000000197C186BD25DEEE5DC2CE5B760508549B1EFB2F3E0A34047232BDCCA39B144EAE820DB1F2D3C3159D012D7CAD7AAB1C44E15F53F4B1166E23DB8AA23ADA9E23AE02000000000001C5A2B2230C54CCBDFB5F42AD8805628B6B3D4723AB84E514035694195F2FB7E716F21EE8845170F30D1BEF79ED4468F2A45A72853F2D8F601973595098010E1D03000000000001C9E730A265A6F2DDC4B0F420CEC9C7AC976ADE4FDD5CEA3B6D5445AA2562772F76635C514BC81DA00E36681EDFEAFEBF29B1C3078AFEBAE3956D74AAF351E35904000000000001B661B82380E38D5CC77679867BB8FC1C94E77006AD05DE9576A7BD210641D25D011A056637775E72395B7643018E0BA023747219D875DBA848A58E0F9D7FD2DA050000000000019F3A31924919E8711F88BC45477356D330ACF65BDA612F6AC681F64C24FD70A6AF08B3FBB6136E4AF05B38A9205ACA4A2773D100FF79057CE6EF6C3F82AA9DEA06000000000001EDF9A31569FF07104E7B2FDF78D2CFC2FB28903D720F4D2ED95AB35DEB5EE579384ABCDC10CCE008B5BF753154B78207E452D4AF2B5646C42B89EBDDFA02570107000000000001BA911C4438781B45414444B18E3EEB1F0E57D33FB8F1BFB5DF1DC85D88A29371496D214B1042FADF9F17DFAC6215231DECB7D4ED1ADE6272BA7933403D3BADA608000000000001D85DF2FBED8348BA8E34D08202B5F944A00F91F1CC1F50C50D2460DFF1CFF490D84B84A1FDCA7A5E1760FF2E3A392D3F4ABB78116DDA6CAD29E694F9A4691E3B090000000000017C1668200DA615F45702477762DDACC68BCBDB862EDB8F34569EE898D80B4DFB1AA4251E3C3D1692C8C50DA2BD543C84A807DA4027BBEB6EA8A4093D5E560E110A0000000000011171AA4B7778E156AC8674A7522E4E47C54E7ABB917E693DD788D8782675BFF5E0108D4853BA609E9E9C0FD4FB0B8908D8D36F3CAB806CEEF40B173B740540330B000000000001AB4927F65EF9D6DDC2CF1B044B306445ABDD4629C4D63AE6278E049C96933D81862327AEC4B7D2C31B6C7509C6E45D2945E0121A0DB90076FD84AA9C5AA53DD50C000000000001F73CC84242314EBAD62F95C79805461C1902C40FD822F19F69C029997DFBEB840EE33A9905894B1290A75ABD10F4EE3BD6E75DC6CDCF69A7FA48735C08EF85E00D00000000000125A7E166681FE462663B71CEDAAF483C1D8097F57EE39EDCE104F6B10BD85AB43EA3C766F25F76C0AAD896BBBE825A8FA45AEF3C0483571EFA6FC24E973AFE4E0E0000000000013DB4DA57E43C4A075E6A8B417B395066BFB8C7291C42A04F1095A5F410002B3AE64DDC3633B2E27A4C28475C56FCBA6F0A6D5B730FF6320C89B39E55ECB22A730F0000000000017B5CF3181D29B993558C7A0E3AFD4320F7B7D1EEFDCD2FB0A3468643C74BEA9FAA355404C1E87E21758F95A9550DFC35D65FE4CF5B7023C963E54A680F9B06E210000000000001C9E3EF53D631E6DFDC8C3AFA9A9587423B4B2EB4A98CD686B3C50BFB5C9C99D7D24DB39B7D9A2E75B23666B0B7B5FAAECB29A98E1A814408EBF10A7B75C110C9110000000000012A5B873804EAFF769CEBCCB642FB8FA833D7F189AD87DFE06243AA869FC10A204159BF0E0A8C197D275F7F5402AC39337575938407F162E20FDDEBFB39D018AD12000000000001982FC2AE47D7278B0DCDD6CAFDDFC61B07E892F823F5569457913E9E6B46D137BE1E39EE028AB4DADBF1343208EB64F9ED562CD46BC8AC4F3C3F71B4C6738404130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9732 +sm = 00000000BAA7550F0E617123968A7F276A4E50664475EB64F4E5DC6805ACFE998B45C1E0EF24208EC4F8C326F4E4D4B36902314578DB3668398F8D67F573F98468AC125A48D7968F80492509E1DADA7B6A244DB720657882BB29EE8EB5B2909CA2E050ABBF43CE3BDDFEA41964793A0E69CA85B0886938A7261F46A7DDD3AE5B2480894D524551F101A16B171E57FAED681E13356AE6949546E9B60D753BBC664F564BCF0FCCE0ED541FC5E2C3DCCF3CC35453A3AFB3250D9D21A5BBF905BA7A717F8383456EFEE4743ED451D4452861D9F91A7AF09714028A201BC2724A2F72037FB25AFC45938D425A5E3736A9DB00958A4B4207BAB54956B772C52A52AFEA8F831D9686CC4FAE8749A070DC047DB8BDB3008FBA6051528245CD1B3DB51AD261601361060C7C25138B342A815AF4EA2B32C3CF6F0765B9ACE46BCF7C20067A6F4BDC15FE2CC72B09A6F66E468EB6A056FEA2C17638BB4A642D95B9FDE18620C35DACC1D5A2CBA71FBA4C29D539F57F54A59056C422CAEF6C6F889073ABABFD9CD5F8907E6C3F60F38A328B2F2D51A03C900F4E38E81BC8E787C64F3185F2DFE129E70F8443AA8747B57914EBD06B80147A2CBC463C564D048FA7A3B2241F1850FA405BC98B7A42EDBCC38EB1B46F14C3E07DBAB10B4BB0DC090214FD105BF5A488D9131D2DE5C7FDB78CA17B03F899C3DD77E3C132D4512A6BC6658CC2ABDC229A207D3F993ADA9A1E6899BE1F550F6477A2CD9652E8298EA0ABFD3BE2D6FB92C913A4BD09BCCFA92A14293ECD9C7A7DE6BBFF45EEB4B204C66FEDE1D75C64FDE7647D580E99DF34AB555CDC3A3D5E325830FA5FD722D09F2F0DB129EB5BD82C9427587FBDF6B28E52D11307C468E9D1AC46793889EE6349B75A90D1834C05B5E914E225A5E7AD158AB48F11CF733F612485319E88FC57F9EE728E5264EADFEF56FCA94E7166C148548ECD1485A9A126B8339A457881CFAE65F87533765219D657592D28A49ABF2281522FE1D9319DC6A73EA986345B69D82027777002B40EC9BB896570BE4B1E74DE3016325C72C876A9D93C834C936DF976F78F33D9407D4A5CE48DB5879D08AF016B67FB0DCD68E12FB0770CE148944F4F4218C5BBACB24A8327E029AEBB399607EA3981BC7ECCE1978FB7C226F94ABFDA6D836F6B9A9C34B8648C29F71D9A442F0027B461AAD8E6C12E70782D89DC3371B3DC225E9AA57AD4E785AEE6D5C21DDD122CCD3B13438476E450DE59729B2A1A71A6A463AF30B4E62E7F33EBBE7E3EA6140147518E42867D2B820117E6F7BC5D685623B4557D03BF5FEE5914FA7B01D34E14B398AB4152CE9A622851DD8C4009EBB1002B88C5AD6B75B332B06E65FFBFFEC017F20C84C6670237479738DD67B0D49BC66A859051B65C42BBDC0CC4C91A15FFF9A8CB89266E4B177FA4F9A735B4B64A939C0F4FAF31B5C38A174F671F86DD21D6461D4E0B71F85F58E0F1D6C366C27254FAB70A4E7381790F81DC2BA72A96DD9738B5B8571AD2983874BEC370BBA303413922FE613DFDFCAF3E6201A69D246B10067AA141C6AFB35F79E7B8C8089145F07735986C77AF22E6C832C26AFD931648477E434B3FA47BE828F89B2FB1ACB5E1EBE621BEA0EBF225AF2F153E8FBF4D0051B455429C81B226A21F3F4DBF46E08143B20DE9CBF9D6DB13D5C0F51C9707565ABDF0666923B99E8D488D8F35FA68D02AADBF7515566B354D17A95F5787424EDC05E4739B1145265A2F7137C3D44CFEE8528520B8A98A547DAF2D8FC30E325CBA9DAE98682FC48AC544A2C7C8E4425744D7917C4B9A275238F06715D8BE40F2AE5ABE5C5594A080CC8302F91AB8B44CA0A445EE129B9A1F0D4CAFD3CD742DAA99327B2D2927E399FE9FF50D12BD3713C3A0D1843D953DAE68A90CE2435930A5A8CA8A852D12082C138BA64D31225E3901A2203EF75A1A33B64380D3C6A8A0D8C8D150097C707B4D2C6971CC79EEB8D57DF801401165627905F18017C394EB5953CC4976A022484803434DECEB76EF259C17BA424570C3DE4871A60564EEFD8BA801550ED0C8CDE89D7EEC693F01A8CD3E9E8089DB3116515E53D6747DB93DAEDC2ED26B37A1D32277EE3642C48DA63E8922672469DE0C2302DB2FBB9C5A84D55BCFE4541505370EB4984AF724A52FDCBE9ED53A634E4B9201DE89D486A5CD10CBA000F0032A954FBD69AE65C2EA4851C1C0EBD1A5AAE6C88546A21CCA42CFB70CA4CD8BAD566721249AC8D536AE892CA4E856D3042CAE77C9A15FCADA3FEC9E4A8AE7C6D63AAE1F06982258A0170F9008ED55498373EBDFD242BF018DD5810663FCFEEA83A9625135E9971F2E4943283A53D0A24B5994527BE2B7BD4EF8CF2CD51BAD59B01A2752BA68ACB92173059A0ED6E7435657963D9D048877B430DBE6DA6D99A4B2339955E4A62B7879B1AE0AB62B4718C40D0CF11000E959F9A99B95F650C75216DF446D8781EE8409FBF3D9CCCC795791621962BF96E063BFB23D9E781F4F21663871110172C46A04606DF46F57CF382D3465F1146A054C7E221B439DA76A2203491782FEE368E90BA6045CC4E0EF9CE63C69284BCBDFBDFB41FF1450FEF4BB22EDD14A0DF06A69F042C193C7823BCCB97797B50576960E352E73FF2E8F722F7A687CF296C8856863BD5F69D009D8198812F383CCC1AF142DD76D44578A50AEDFF30CB85A61333A7D58BDAEBF575A486A754F7AC60D88660EB148F3FB8BC31B6B057023013CE84EFD806FDCE46D0C2B359FEA6E4C77E358BA93FB2B71B47B0FD6EE17A4267797FBB9F11B1192941FC13992B67099757A124009EEA46A89579F361F19ED02D6F3A17F58DDF52AC0881F3D0B41B89603234CFED7DF3F4E20C1ACBD505B9EAF7A742BDA1DAC0732C1F37CF98C98A216DB63D6A6B79AA2FD02BF1F1688FA20558BF4C3F2E7CE7B054CD73495C2945105FE7A80DA396F953D456CFED09DAF45F511B1C2908A12B55EA575B23B9B104D58150D334FD0E79D4C911A845E38A7B30A586D2C0A1B72122FF85A09177630655235DCE989256B7064DC8018DCCE8DDBC1B824A71C9B3F920682CD8D522529AA613124A9DC598DACAA16A538159213D12B341AD1BF372A4E95C571826A6E7E81E87E691449B73E10D2924719190C26D394C42F015F4B581E4C32319F02D3428E611C44A86FB7DEED726826421BF21A9638C10A5E2F921B616BC9448229A71C30627C398C4257406F9ECE7BEC2E9F7B2AE1F7047E80746B156E0DA9F4D22D50731747F2BEEDDF5E92BFBE630CE1A618E4E7BEAA674BEE4380456301B5D0578ADACAD2B685BDCCD8BB20A0EA0D330F284E5AA318FECFE8893138D179FCF67DA8CED69059EE410D7B12BBA676297F731A568D53BE999E31F5F76B924C710B8C72545012CE23973E52D4FB9A7F9B934EDC2B6E27A7AD412F52D3840E70BC8A4F0DE5ED7A890D5705BC40B0732AEF50CAA5563E15310B5EB6E70167B693185124F828E88FDC6E147591CF31F0524F981832ADD6CC9D75DC323077D810A9AFB623C41245249AB508B6E84B9FDE68B70BBA0EBD51AD50B2798B2B0A3FF30BF17FD109D5B66C9D1741C3D1FAE1E33FA503AD68526AED523A0F59AD785FB6764E3E4F26AB8E4EB626E988ABF6F27010F010822710F38B85DA10A0115FB8D76D3DB3E79F27F8A5E472ABE15B46773E77511A9AB78CE4076087F5E46AA21F953E06E11AFA08EB04C98C285F1D54B29F4BA70F95758BF633C778F8A674B94AEBB68A470C68BB07CCE6E83BCC2AC6FCA5789D0AD80FEE6983E5AD6C0D877E1B378DE56C225B5E04B7CA6D668DE404B150A615F3AA81CF775C8A7087BB390BD6468E13D3C01F480ACC4E92CBE0AFFC10CA5A83BD8F800AF3C908CD95DCE85E42C6976B645F27F94BF40BC9F175B15F85E4BF965528BC226D1C56937DA29EAA5C6E37D2A73686D4287A2006FAD01878C9F18A519084C0B0E7F92907713A01060F545798F2D6DE67B1750C52289BC5A9EFC8D71617C6FC30AC2FEA0A3FCA3C689A6D7E0FF05BCC0777B60E1227D97CFE10042E03A16D18AA235D78E3991407DD87CF8E9E265A5E39AF49264BB4864436375AE62B8F9F8E675A70AF44252999A011BAECF423E511A8B6FA5E7FB0C467476520694B36AE5C0D475D3F526CB3668CF76973985D25367D037C379A06D142F39D41B86BE8897CD327A765BF6490DD33E809315C4DD225D109D978B972FC62AC0BE6EB86B2B5F49198E8E1D60BE1852F2CFF34CFCDCDDC207622E9A69BE9F363D5AEB8161D28B32116DF586770E65ACD5D0FC2A8C8969F666705D3FAFF3D16848ADF972E99AD4D8BEF1CDA5040FCB87897BCFA8CFC0160E16AF07AAC4BF858FD677916EA65213B1987680E3507E6C976683CB9FBBE0A223F7B2AE55E9CBB1B1AE83D8971500AE7AEE000660C989F6A3979F74D75CD1621ED0AC65FFB20CCB56830970F137D0014E7F334E957714A35AF3CF85935C7636D90604AA3F5D1AE5651F59456DDADD77340B873479C47A41C8480DC2D57EF6948521A23E73F677C3E78830BA27218421C098795D3DA41103F744C8A0A5A6FE6960F26C0F90C31E51A893FAA00C6B6EFD76BFA5E224E9CE76AD683B41C18711E1BC50665BC5C9D9183F3195A7117BBA583A2EEFF10B57B778B7E95DA6BF8D18E2A1391112235EC64E7701AF5C73231EE6664305C79FC59BBD67D774C80D33B9CFBDA295C483A7E063493FB8C96F915FD887E5ECCF96652AD374BBA9689BC8DF98B70B672943C21F5FD0D52D44811D76ECB7A16FA0A9DFA37D4759DAF65D69B2D84C0429F3A922A23734B95BB35D0C52E3C123214315BB9BD108C9350DE588FA5002E6A3536A4909B3924A3E7F8674D4F74C09380FA35982123E584F970820802F0E4B7561A54715D3D0A37850E879605AA0BC7546544827A8EACCB0772DFC330FF0356D34AEC0C3BF1BCEEB5B4BE7FCD9E21919F1EADC23C414ACF0599B0C9963DD2455A237B4C7AE8950D17829F5030BEE7B01D5DFB552678F0A36E9E1DBE1F0E4767B2C1820DC77C436BCC6DBA2A0707D7D8D8C9F3E754E717AF878A48FC83A89C1F296981261F179F9AEDAB136B73950F2BD1F6A033C7F33B7E5BD902C5E9183588065D20F6C8DC3648B35641F3A33A81A430161483838FB206EAA89841888B8DD0A9468616B40464A5ADF80E28A5E33E1D2CFEFAEE6A7A4C59E975913F1BDFF49B40479D4903CD92108EAE54CD4B7247FCAA5FCAFBA7E32A4C4DA1805362DFB72A1C216F7D12F687F955DEEAC751232B3745DEC50BD3E4C2575C1D13FCAABE57539AAB71694D548A9CB6C8EE765C95FA453F1630A014456FE25639FCC61CDFFBAE0A154EB7DAE4928F40B0AB881CF4D0E8A1D0725733500815124F1705DA0FDA52F7E3B270EB81FDB86B1C5AAB117032906CA96FF73661E2C707D64D27E45D9979B4DE41D64FC42DD7F8FFD0227E9421BE8D47131204A416E3B6A78BA749E5F0EA8E9902360DAF05ECD83A5D494E1E4D8D42A41621E263ECF9F6D6E01FB83A0F5CBD435C9D9B367AFB579BC0393118DF8FC3DB793A2C0D504CF5A484D346BEA86571177C4E9ECF80B77498D64305EC9B287CECDA7FDD9CBD1A3CDC3EB3EAAEF6F7236BAE6FEABC4E17F8E8173066E2AA77CB6B435A5E81F04E866262495E2682BF7E1CAC4986E7E63D6C350DF4BD4338288716B8E50E3A2DEE49BDE27FFCB8627A97941FBC5BF74E7B2811E81E3D51AAFD54C4512EDEE3069A58C5CCC95F059DEB17257D6B16F30C34D6998ECD12CCC24EDE44E2A6113DDA9D3D9B298D58E61F663070364EC4A1CED4B70676E87706D4F4281761B900D8E10B8EA9B42A1364EFD4EDB44231097FCFFF21AD515B93BCE77F9D26C3432593976AA386F0A48B70BC659FDAD0399914A577A401D24C88B971C60DEF61D30F36EA9040F301734941742B66E4D4E9C883DF71D6EE901A135E0E110FCEB8A24A609EA226DF949704925DA1917C3AE60BA1531580528D602EA592C9AB888ED4F5C9C0501AB6D229E3D7449650F6195B2094C91D771B7B2D237AAF3D3F1EB0A9B213CE39A9DE996B39C2BCB4B909383CEB2A32F361B71D6CEC12FB0ADF2EF59277E4DA927AA08D2B2354D2451E74B2425019A6FE8D29672B103F92AB1377DE4DABF8B9A03A33FC6D641604644A9E153AB0BA4DF62F4F3AC71B34BFD2ABA44C1EBDF9B1176A2139D5E8DB791C9AC2638B80F2B312731C8E9F0E01CF4FD6B1BFA84DB2A02ED6E4AB4653A167D3F65AA04A0FCF7C87FADFAD06D7A146063735C4E7BF2E981B71302E1575CF6D15AAD2C9F327C5A65712D112511376988387A3D62F90D878E3E7C8874FB439CB059979E86C18AA096BC495F516B01627B50A77009A9101E925716334B9BBA939456E42F829EE45B902EDC68E4768E5A2EB06670F2F69B2118619168D82B3418C8AE26444E3E43034A88DDEED8464B6DF093A48545712B8D86D3DB7EBCC586E589174EBBF66743E972D342EE1FB62BAE073961B6CC3264D2C6D09932AF46841964D924AC5C317BD2F4643AF98DEEB154AD6E1D6505F98AD460F35597A262EEC900BF6B0A1EE36F31D54FA32BAB6FC6C3CA6501792168FD1A936FB732231B1DE5E443EE0B5CF8CD64E7B2EE04FEFEF8A517C40FF0F78F87247C8CBE209B000C36D44DD313B226B09522D087B73C04AE187774DC21A1FA0EBD77B4DA23D067461296CD4D0FBC79B36396A3B7640212C4DC10CDFAA8643FFDFBE5B1A1D23A3D8A56AD621FEE0BEA5AA24EF6BF0612367CEB4DFCF152018C7DECB6689A94708AA9C151498DE7009EFA79D220DF6781107BF7B50FA7DEE57BDEC2100B92A493B57FE6233D87129D1602645BA18F2207A3406F7704D24C6CCB0BFFC9CB6122E73512E3CBBE36936032559E18272F127ED2313B77FE6321FE6063F8581BE30DCFE3E689E4098EEF571C08F7A38F99F2CB3FCC4BA0FBF52A07E47CE5928AAC17F69C83C0754D22DA22CD4077D9A8E8D7782E897B2F1F192845B9A334C6714AE2FEFF4B308ECF6922BD982D862CE33B170F17A1E8FA9328C63A70537BED3B893048CD8D7BD5F8447B037D153051CECD070240EB03033D416C4B765E3B47D4B2AC61FF18703D8317D400D0DE8A2B94A9D5A851E1834BD29EDDC78470C325AB8ACA665B2333712B846CFB7F65720AE12D74731181BA5A63396C1B1F5C3E00544F6B7559ADEC52DC827DEFD24C8F44CE7627CEF0759E2CC4271F7F2FB1B06FE3DFF6E78C1711CAC99350E7D5E71B811DE6DC8D845960E9E35631803E3683B85C82E861442A9F582D1565C104FB333B3EA2D86F87373BB9D0E22DD3D36CB5A6CDE4EA6105AA1B84FE4B49DBA80F67CAD6DA4535B56529EB354ADD5C31DEE3BA77D4382938734ECFC58C016085320DB34F7287F38BD74C73762603B2BE31ACF4FC6A87112E4BB69834287E01AF41CA41D26AA4F74DE75F9840439BEDDE6804AC022BE7D9104956F66E458EBC1C98B6DE4CB004DECC068398286F5F26CBF0414852AA46F9ED6B73D157274F9D62A909D4D4975923208738DBA0D55B64FD54B5EC4A1691A4C335BA8E87A5517FB4547035C995B76B7B8BAB6B990063B5C5D8A4B482E0C8625E0E1967CDF3467380F69B9628B864CAD2FA430D40180708493E9BCEA465A49B0A705DE89CBC3AA934D8336F33C86A308F229FEBDEF3DAE69416FD9A977DD92753D6801DB3D3D72CB55D60F047D1DACE7A7CD19B2B2F5BFE6E8CFE888855EB60E61D4D6346F5CB03EA0BC74119803FFA0AB111BE22B4A98318C7F503EC9F585C7891B598FA07F260D25D5F4B5E3BF38330CDAF77658BB4669E6FD54F4AA798E6B7CFFE772D6D53D2D8DA94BADE6112FCA7B093174E3AE87E0A66B20AB61E208D9A6DED593453148E4A9DA7E88B3744CEE26D19344347313172EAB5D962DF2BB9F01E6D620BB9672C468B6A4D422FCCCC1C30886C4AE37027E5D50F219CB67CE662394745B28598FB6C8E08428D00D7190D09625F02EF93EEF410FEF7546B621CF9E332E6F428D83EB15C665DB735F860727983396E43C448909A92419DC369577859DB56501B6371A250892E8BE86FB19F251307BB7F5EAA9354E73B0F2A45E316933747BB153D0700887F3FF4B76735C8309BF4868A3087C02A91F53D8EE4FCDD389C18028ABF0A74D19594A2C5B7637FC8009E7D5EC2E4C2DC1E133866C5D896E3BAA033265E8E243F95F952DC451A307A0114B4165868E04A59837708ED0248D04D7DDD886115FE37498DD905AE9FA6613689297A2D892672F0EA422F4C376107B5F07B1B033EE4E43B578D06A5429422768C6A27CCEDB58435A9D04C59ACEE99AABD468C69C5D4BE845D45ADE69C9A8D725CAEB9DA4FA48884B5B3570E5DA3BC102865EE9ED58E8EC07672817A72F009C9BD007BC4158C9B137E117BCE2F0255ACEA158E95FF35B2366BEEE9DD02F9E3909ABAD9BD170F8564E6F182655A46A54B927465A61222E88762C981C512E1D70EC65F5F7A7ECE82F760250BE2E6E65515AF363D99A7A2AF47A553CAD49732BBC49E97D2D5AB3248F79586DE72CB48FBA20A0F737D387A10094788A7F916B2355ECEF0BEF38AAD9C67DE08CF31A2F6288CC2DBE7C99C89F5A0D111E23C19BC9115EC8096B469E69324F8FFA428B81D7FCD0D38489820F83EF8DA083B401E75DE57FB7E7A88F4BA52E7B45140AA8F1A97ABE03F4E9C9852B58B450CD01FA92F0666B3F7FD89BECFDED69D3D70A789858143B8F521B2056EC817CEC2A0E61DC5E9D769ACC5A8D62893D32D3A7AD89C406BE462C460ABC57996D5759EAD97AFD5D382240679C3F2DB42A7CBBFD12AA735961BA74F1DC0235248F64E2E8F424276D0D66A54A5AE6286F489FFC3C52D4BEF770482358B4F679BD838E184C509497E99D91496193C5838A6F9A0C69853C2E645ABA8E0F0E59640642EB0069F2EB959A4C57DFE1D3FD7A64BB660906520A4ED133F1B0CF864780EC1E211B2B2451CD4F9D04D6060EEFED3B0E09DD4BD8D7639C35AAA4F2290EEB5464935509FE16C377C0161DD0AB95B3CF96A874C709802272763F0E283FEA8E53554E6354DB7E5F1C4D5EE09E1F6194C8CA78406278F5F41C47306DA5A81BDBC8F8466F32822EF7F585A5626A1FFF904F0C5F86930F9F5728232E3F17827064826E641B0BCB2A147A0D12EA4B93A8EB85AC079400486B2F4EF1BCF288ED73EFFF3F10493AEE8AA69CC37F55CC18E0C3E1F9E9914D268B7E810120DD18FF54527BE73929E57D787F167E48AC4D7887CCD78E4C4C8295939276EAD69FFD48143702864706D7217B1C5A83D233C0611077873C3392B6D209ACAAAB0713F38B758C2250950CDB8F1CDD9219C9EDFB0BF70A997EC0E7145BCA47800FFD7B09B94BFB24BD16B1F0AC0C7E6E4B6607E7BA1D11146EAD9B81378F4E0511CDAF8183CA4532A421AA2893B59A385B2C6C849078C3CE7F21C81B4215305C71DF7A9AF97D79FFE8EA57B1A147EC4BDE9F0B7A18797BFB7F48E641D043F9FD65A2F1A8B3CFD1CB637649CBE52E413F960CE2716CE25344EB7C67881263862BAE76344B5C11679FEF3CC8D06AAD204ECF9D82C785CCA36E8CE64D592B6FE14BCD941B204BD944D775AF18235F12478D3A6D195DA8034543DDF772388F1F39E994A99D78E83B45A3F72BE242BBF0B047B65AD5B957CC19C245CCC04607BEB897BF7E5C9E6A5BDDAE4684E52D065904DC71C2420EB4E8C28AC5DFA77EA3DBC314D547A2BCA9D8EA7A95E3452FFFBCEDE40BD7C73AD778525626A832B097B5F46ADAAEEF9C02B55D82B592817799FF2D350122654E686683C2BF15AF65893CC327B740F4036E0E7CCCCE6A60287777AA16E6858B1EA90D7F1BC3061C733F25DADFD612B72EBD990CDBD767665D4EAD421C4AE17815AC7AE5E959736FA4DD505E90CFCB188774C18880D264E71E1D043112C00C65E127582538CE792AF5B909015547F7BF244D66EF008BDC434CEE3AAEE28F5A7D6865B3ED85D08ADEBC9BB7A0150C8BA780ED98503FFFC4FA99CFC7CF0F3905355077761BC69BEAE276BDC22133256D2373E64DB496C9FA01809000EEB661D4098278B4A7BB06D3CD53F9CFE0D8A44E4560B0E3DD1EB1F36A57C00B8A0C49F5384BDE2F10A945E41AA4CB95C1D28E7EF2064DE4E8CCC1C79A77999B9430E01F0A96CB4596BC71157F5691AAE0CAB95A34F556364B81252BA1ED74D9623823BC1DFF2C15B803253B4BB945567148AE7662C135511008E1D291A603B4886202E9E9843ADAC01ED8BE39EF346B8AAE1A5B7FCDB5A9412235012273797811C7324255CF7B7EC4E1158B16DCB13D499A817743AF3B1F397EE3E060DF378FF06C6D9A8A0D5F4CD38F81A015E0754B3D8EBDE9E53E52A889E3E87012EE48669939D49E54D9E1B2159841E2C7D1572F52D4A4AD7D950B009967F7FEB07ECB4C861FCF6B037BC999E353F1B7C65AA3B0FD06D5CE6627C14DE5B489DE4485A1D73DD057235F1A68021A2A6A69DD0EB196131F05593178EA151B216B920F671F358E64A4DAB6977125DE0A7459B7E783C849B8FD4DF8158B3EBD370AD97030AC84824672B5EF5088E3EEDC909261D3AC83D617F29CF825EE12519A07CFF5F95F626A6484446B343EA6E02AD2ED9382293373B347177765B5316AD91F916C5D12DBFF4483337C7D819E02681A0B2672D14F1285E507284CEAAD3677383BD09D051B1805D54E5303637B33579ED70AC197F40096622FF037F212425585DADDB7463B98BA1778DF41BB35AC25CF70C28FBC38D8375F5E096E90D04A5C7A6CAB3AC340B286A730CDBD291DE9F88C472C09D494DFAC4463ACF0378F3C12D982CDBE556DFA2B61DCC65F49C453CEAA5131B2AAD1544DA7DB46C5553160EEC3A96D509E2BB0C80FC6D141EA7B730F019F0BD7ACE57470A9061047F19BAB4E8E88DAEE4A4F703BCF24CD75CC0930B02BC0CF69B640ED66FA9B99719330DE9DB8838CEC4CE696DF786A636BC0FE9714482A72491DC1DB0E7F3048FF370309AF7C2F3859DB9CC42C0A742419BB35384C0BD03F80FE006370A853983B376E904E29632FC9C56396E1E434FAC69358F814FBD1B85AC8640A6F64C90B79E1D08A03602880535556290E3A74AB0481C87A219173E3C4B47D3C3ED5328DCF97C1FC490788157F0A2CFA9BC1A920A972A21AF6A0DBEAB0577D7C39E96D66A1E1EB566A10F3DDACA296EC1B893002AC989F48CB64E2CA0239FC08302917406AE4E1F9CEF6A7DC96B5CCE0725F7EF4EB60814B4694F872D8FC56096FFC033340E794E9093FC9CC32C8A7E666A4775E2DED466473F2AA0C88331ED3D97630048ADBB3E1A652445E3AB583737CBDC1513939ECD3BD151419584B373428142C6E392BDD288C8E4D9B176AE5ED5222715C3A991933B8A497C57C5942232D34624AFB8777D190C621E71A3E55B650FD8860ECD34EC57659A17A3AD94A035EFD9161EB42DD9785531B2203F67D87AADC0A886602AD1A26BBDEDCEECAD38B844326F5C60764AF5085EF0E02E26E223907347A6773A1C9273C289168736D79C8F8515F15E62428307174C1AFBF16FB2B016861B05FEB38213833CE77990C78FAFEF51D409BB9B70881732B7ABACC1333B74384F706AE7F8EA87DED4F94678BD8D61AFCF0F7DBC46E1CF96571182EBAB284DDC5649215CE1AEC155756794BAA2B3AC06A7332E900E0791DB4730D1F9C8B2210824ED920BCA37246A51653BE1221C9FF9DB1FBF9C602FDD52D0092B1BAE8FBE7716635678161F1AD15FC55B651150FAB011DD61BCE11599B5AEA7C13DF99C13894897E44034E068549AA6DB284686CB1D3AA3BD00FD06ECACF21B3541991DE3F7362C01F95FFA9D826D41ACC2038BBBF859BB7A27A6F7525FBD906D0C6016A2A6FD9BB914832D6BB46D0CBAF2EC2900729E050028D722F67D59A1D811A5DE513BF9AB4174304172DCC0521FDB0091E2AFCF3BD5578FC5A469B5EE30687A6686B9CF04E9AA88815B89EE6F2D170BF84B0BF845A75B2C303B3968643511D4AB568552F4FF6C0243725F291341AAF654E72DD805C798FCD5214B14616E7AC9F3A4EA6C211B319FC9009536A1772156E62E666788121874F472FA5CAB32BA174FD0B2218F50A3BE7BDF448263F84CE6184306BDB40D6AC6EEEB7A009144D47CFE5121C5F44044D10B0776B575F883AA5CD63B5A577409851707816E4CBFBB13B047D3902D0C7916E4C9598BDADB732E82166F10149695106C8A9F3C0D2CF4349B59CC5A66177FC51A7B1098F6D30FFD8A5D016AD38097C062E0DA6BA3EB4C8FF851503B97E7A276E026DC8D92C68F979D53F9157695FC63A97A9F58D8F92140217D196A9778CD52A9074348743BCCD068B5DF2D5B76943651822D37F217E71EA6763CED121444AA3570A5880DCF44CE21FF035E8EA8107430E6116C10485E4DC7792D04A9B9717932D621B572F42221F1BAC60D3B65D93007913BB100E8658968B0CA77C533F20B9396BE2A7DB9B233028465E54648E3329BA2820ACF6CF00D46BA0CFD045C20C6BA992AEE34F57E9C84ACA1E95C45E9EC6D0BF500A7F7E6626D5777DC6AEDB370A4B1EB82BF4CD0F63DED9A4CCA567FCACDA440EC29CC67A926059152AD7BDB3F3EB06813BFDD8314C365E490C41C6FD4A6173A13F4C4A4E517037315D0EF14428275919CC61AD393BE23333F7D8A93C59DF7FBD4DFA8235AFE88803BDD881CB8E591A721E917CE44103EE38CD499655B666AC3536A1DE850F3FCA9C393454D9BD6F0C75B11822FF23EB22DBA69B08D3F4E92B8ECFE9BE9432A8B445A5BEE8757C7C53DD96FB2058A5370EFC4368FD6B5FC124FA0B9366074719377A0C533415161E29C71D5AA85356B98A138DD28D76BF35B6B9BD3AA30CEE5641266AA5B6E3476CBE1CCB18839B063A655FF7831A6B655D5DCF74C93369FC562827A2E93B53A295E86E9BF8879371A9E0A176587912D1CF344CDEA03DE86B587548FD05D775686D36B8A3B5AC77165B6226682EA37B935C9FE0E02A8FF9951E2467626865C6369A8DA0916AFBFC03DCFD599163BEE9F73F99E34A3F8356E5F193E76C4648053269A659E080A7014A3EA4D7D9766FDB36CC8919294E88D722D9996FA0EFAE5FC3DDA45C14636AE77342A5654D12731B64E40255DBB777CD68D73B7CBB3D8D1013CADE109F474DEE5565B1852F646002BDFCE39C736116E56EB8EC6F75A46F2A19ECE8F0CAD24152DFA63F89AE0C375E32AE637BFD43A1D3B027930461A8CAE0809D65E9B81DE9BA9D0D498262EF57887D6B892F149030F734B44BD9DE9A4C8E97772A50E7404020A9D64D6785059250DC03745A68353456A7229B21F0DF6AFF33894919136D210915581A525208E3FC16F1AC5BAD3908D4D7D7155929F32C5B790F625CF89B8AD92622A0B155ACC09CA4CDC24518B84CCF0C924388B77DDD51F3FEE646A774CE41367F983402ED44E85B679908928FF5F7522BF9199CA1A41A6B42C6CCE575A6343E512475A3CC90B7D0A456141E1C3ED6ACAA15C6241328BA1936A6F78E0D6BEE97827CE1E329F2CC6B58E311847B4195B396C8AEFCC5D9A8F08EE282B26B4CEE8B79043589828F854650D73A433E0B879E11C577ECCFC08AB67DD9FAC9C3E5128060C2F2695DCAE7520EF6C12DB22F74F2F261ABE6F9FC6244489B96ED9222803F635DAD7FBB43AF6C2913FF809E208C97D9379BF5BC7E4276CEE51C6509A6D13D4EEC779A04A07B3D80569AF1A325ACF378A219999B8F91DD48AFF90105FFF878F4 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-2_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-2_256.rsp new file mode 100644 index 0000000000..a07767dc99 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-2_256.rsp @@ -0,0 +1,12 @@ +pk = 00000001049D5FE86EA348F4C6D28583AA3F9F86C36156FD23AAE68BD09B104163E2E2EB04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 00000001000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A049D5FE86EA348F4C6D28583AA3F9F86C36156FD23AAE68BD09B104163E2E2EB04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD0900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E7040000000000017D93C20AE191054626B3138F02E186A4607EDEF6E32DD3B2D788325E88FB01E90500000000000159008B71F97B67D9710ACBCAD0DCEB434823D0DDE4E8526701AF9ADE23FBCDC406000000000001410E6F39D12638391198E1827F643E6547AD7438BE85774B713D8FF3D8CB682507000000000001030C34B96241353C81CD7DDEA97ED6CBED8C9F9FB86DB60A6B78E39A253C001B08000000000001B07CBF5330F3B30963D6B0A4AC7AC4DD77585E4EB8A08B62B9AF1FBF42B76FE509000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 4963 +sm = 000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA701095690ED3CAA8519B752CDFBACE3666EDC260EE5325F9EA849CF9DFE6CDAD655BFAEEE83253874CD01D7C5D07C53050812648A4891B86ED9B949459337CE4E48A389B5FA7E67C06E689894EBA9EF2B30A6E85FAE21DB5E8D5F6499CF1C5A59A6D7A8D490A5464AF68854E65606D09C887C8A95A511E76865A1B432139E0C164EEAEDB66976EB9610DA9403923B229A8A81AD64A8292003BCC9A8FBD97284FB83F255CA9569583D0B40DC8A5942B9284515CCD9497D7AC749BEFAB0032A08D412C0291B9F93EA852A8937854ABE02DA2E505DE98BE606DF1ECF315300F6145C26529510438E87AB06D786CF52C18D7F9C95D7B82F4F0E1AEB59E4221D40C67EB13EF80BB3601C44E35C901ABEE1EE25BFAAB80639021377FDA25672D97ED4126B888B571BCF4A34CE363BF227A5830ACB4844CB17A942625686FEB09DBDA47AF7568C4ED2AD3DC8191BE8F775AB35E37528F5B94BE4DDFF4E56600E488856881A622BB8619A78752AB810E1EF1E95A04A10597D7B674C38102590FA8BB21B909B3E05A4453E58D0D1EFC4EE285C0B3EB81F2DB7E57C22946C3ED1D4155D0A6041072FB2968834D281510FE4DCCE2D85ED825C3F2C646CB718C5C742C8E7694C288548F3B542B812369DE5C5B650683CCAA23D4B8BBEB833B694BE7EAB094F39BD8D4E6FC2CFF5A94DF26DA0C0170FD8713CFC44391EB96DA0957FD5066FD83C6A49E07417E807C087062711DCC7BBFA4B0D54077AD8DB142A191E6BA6BB2518374F77E9F7FB8C2790CBA9844A7FC11D1E6C38E1E9EA573E0A80CE46DB790375D915D3C1F311F819D63F288CAAC1F49DCEFCF8F9B30E025FB946B8A8520860ED5D425878CEED7D6CA693518B5A2F5418135EA9316EFFDECDB1DFFC9EE3A62EFF0E6647A2D39C98B01A8BA4A8B9FDFF89292303C02C3AEEC2EEDB69DB6CAB0F45463BA7A25D6C3E4B7D39A28A65A5628A93556FA9F54E273B583F9A197BFF4731E04237D992BAB4119585A36F7584D2B25A2263A428A218CF009BF9EB533839059E362FDFAC5E8EE98639254EB106410A8BEE8214C66A7BB81C99C989737A7EC3EDB303EDD88D20A7D32FE8E2735A21A0055B3473BA260666DC3A9CD83E3AE3B6FF7D7D8D5964AF6A4DDD928553D5D44D3A6ED501CED954E06F89F82D334C458125844219EE3DB69A83DDED1030CBEA57D3D2EFE8AE168D83856DA3FBADB0102D52C5EB3E72F1046CBFF94254043D879CA0B64F7BD7AEC79F5F87C11DE3DE80756E92F7BDF93266EA7D5A17B974C518C7024DE642D12B495063AC5363EF6C532E0D9C96AA96BFC9E1D6A851663336861DA97A10FFC00A4D5A8E4F1CA04A8C91FAB90CEA2895370C57B8BD4DAEBA7B426B8E8B3968A6ECA166D917889AEBDB335E3B8115DAFADB4F258D8BBED23B21C65486E46D8BCA833B6967A09FC7DA038DE146403C9AF2D41510FE1D89C15CE442C7FCE52DD7AEF5B65923DD8CE7C031E671882B33206242916D836656273E7BCF440A020F6BD2212AFED89DB1DF7C77FEDA1143CC52238532A9293D465022828337D62D54CD964879D20BD79F2F5C8042F16A9C2FB2E1A7013828FF9CFA9903E4C46D7F0A4409133EA2AF9207A68E5DF1EBB203398C519742B581D604C13E10DFEDBCAD3EB1F66133D21F83B2C15BA70E2084E20169B68E73B20457198BA678C4496B02F7124E0474EE3BB9B7107646385F85E396D5B6413A9FF0BC969B011DC3639F1798CE4EDACACC625459A25639F6F2C5C15DB24488CAC196FD09E1A5AA1ADF13D6A4316B27BABDF3ADD912C5D1A25114B322FAC7F9853AD29B44EAFA7AA9A4ED2471B0BC91B4E1FDB7E6A80056C0F264C07EA4901DD4FF16E8E94B742AB1BA0D9B7C12674D959DF58DA15C7E22363C8AE8B2D2003632CBB912A4F788E97B9BB1C7EED5532B3026F7B8574061C607F615F7BE429B3D9A386E40B99329DE24163911705BC3137F0C728AB5848532999315D2BFD2336DA5A304D0F3455927360BF5040E95D1454106F2A8A7CD27D5510E7B54E165DB2CBF8027EE9B5CF5EBCC9DD06A5C319E2B9611BE946B6020CE4D9DD7329B336BF3E1A68CE17D1FB3485EC4AE8A823AD73C293A8AD9C8A45B2313792CEC3A649FB0DB6EE6F511B9B48E3DA2B198695DF9ACDD096ED9BE58CB5A6DFE702D4F9CEF844F63D60F6E671DF4C58FA9737EF38E41D273D28CB5091AFD0A9857C87AD54963C2B8344F1B0B7D04CF60AF2F462FC9E118D52827FEA10BB9FFE8A0669C43C7F0FD2B44AFC59F5F1E04E13D3FAEC42EF2E5CE5C39BB7E9A671F6FC6AE6BF9D49BB099E99E115FB80548BDCA3276CA7DD2F3200DA1FC5724E17D63321E7518484F9CBC19EAA901C9B4359152FCD7C0E51C82C962FF3F9A68B4F8B30440B23AD28725612F5FB98FF740AFB457915740084644120ADD17B445078AAF541DDAAE3B630834D387AA4B42958AAFD178D333B9E1D92DDDDC028609DD1C65C57A704637AD2E628163EE49D33FFA1530ED03F0A3E771B74CCF546BEF58EF21DD186BD74BB36D42E7D9D5F94DD718412DD7417024BA0156A865CBF27A461847E450F0DD03D0B6940BF0A7A3D0DCF04FFA9F744E8EDE879679E9B2B30DF30EC5C8C9AB598E42C39CE458F83C500EFAE48C4B8B2B688A9AE8C84C68CCA9D73C640BF005BBEC6C139005A872F0D032278DDCFEE8E636303308F418F73E3FCB7B63464D0B798AF6C9717BBC5DEE4C9150E8B271E12B53D2DC24D62BB1B522696BA13C5F73022D8B7CF740D798573335CAA3B04CEE0BDCADCC2DFD20E920A0B83391E2CFA2E0441B6473EBD291791F09B4ADA70A5286EB05167BD59BFD8C46427413D6079846BE00FC21D586D7F2C2AF4FEF5A3F2E0AD8F4D487B9B6BF50ACE604177339912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70D676B893C9B7BEF24DF70145E4CE1DD2B660884C82FB0EE47D1473FDD0B8C4414011CBE8E48BFCBC428382A66B103B905C0CAB36A7511B1BD6E23F4C69073CBE6C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A14BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F7 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-4_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-4_256.rsp new file mode 100644 index 0000000000..4bbff39fe9 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_20-4_256.rsp @@ -0,0 +1,12 @@ +pk = 00000002CFA7F813F78C9797C0F6AD44C84059350BE2D1EE249919C6E1F305D3C0E7024404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 00000002000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94ACFA7F813F78C9797C0F6AD44C84059350BE2D1EE249919C6E1F305D3C0E7024404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E704000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF54961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019C1A7BFD8300283215BA57DB5CDD95EDCBD04E1C41419317BC2069C2AAAE22130100000000000143ED646E32FC21554D8DAD350C5732270CC220F7E264ECB5B7A8E8A4586D0CD002000000000001762D040EECA13E137753604D099809D946063368BFE1C7CF0E6549FCA746F7C6030000000000015FB7406F1B25A2B4A6A1666269772EB08D6FE78D8A8395C56AD80FE6924DF082040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA7285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909D + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9251 +sm = 000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA7010591AF601BF50208B6C5968D4F692F07279A9C6AA2E66590F7D2E54DCFB47261CD2CB50DDA1EDFD708F002ABF07D0001C3357A70F6511884C4185790EECECCC57389B5FA7E67C06E689894EBA9EF2B30A6E85FAE21DB5E8D5F6499CF1C5A59A6DE8D17E2B400CB70FB0A864A239D1985E799F31F1ABDA096C57123F06B2260714AEDB66976EB9610DA9403923B229A8A81AD64A8292003BCC9A8FBD97284FB83F96A944CC1878D4FBA0A59E308F18BB3A90F9704B0342262BB5FC542743D246CDC9AB35B9AE477B083CA1810094CA5FB540A37E570282E48E4CEB5FC19A7FA82B29E510FD11DA67C0C0D3B6448B88B96E0834210FDDA112F57C7B4FA60EC32332EF80BB3601C44E35C901ABEE1EE25BFAAB80639021377FDA25672D97ED4126B8D5943C4AFC991D3AD0413BE1E84DA3156547C13C9BA17DFF08C34E5B226D7389E9E8D58659CAA4ED33A02C4FD0D3315C22ED07A04A4D89DD74EB188F9E0FF02F0B87F56AFDE4094CB079CD0DF2CB4106DEA80FDEA7967AC53FC349C83C144DCA2D75F2338FEDB00B906C9EC104C5E837EDA2180E53BCF4279D3487DA42B1605BC7329B6C264A9B24F73BD95BC8890AF4C36695EC8E2C29B32F4CEF4E02DBA54908D2003A825CBFF22E3F6A582C3944C6CE0F79099F574A57715E751395D7428173F09C28EFF19BBC4B99C5ED3075C013067DDA903F8D8067153887B056A1BEADCDC912C2D8FF1E15C4F4B6AA4FC3A25CD8150DCB968F8910F6D22AFA80331596967C92BD4979E062D2D38663ABC59D3CBFED0FC6D94A1F157100389EB4322BF05345F497F595F49DEC594407A3E14B55229FC1F72F4926A530EB5F018889C61F4E34D56CFBFE507E95A9E3D86591149D0E5DB6DD9A9A83A811D103580A40F3EAFAA8FD4A12AD43A403062FC7003ECC756E3E26F8B1BA47801DAA46173063E3788684AC3B47FBEA813CEFA4754D02086281392EADE94F003AD0EF78DA65C89BAA29BA00E66D42A900F85130532F5303C7BE837860BC82BC2CF7CDF0ECEA9429324A966984DC99442F4ABA490765F650C46FB2FF9CEA7A8549C511820CB2C81C1119E23CF21A5FADFDB79C0C60627E58576F274261515F1D9F4ADBBC5F6E4DB507F51EAD30CDFD170155A675ABB01E2C06C2E04365A619CC6294601207BA2CCCC2C1B049484D6D933B4EA4A53B85BA8826BB108E2C952F3242AF6AFADA16D637C5A2328C40E977558DBDECCB8D643E07A573A9CB5DB4518877320FBB4998BFDC592B0C80FEDEE27F500EE81F76D642DA862FB4DC7DDE2B33A88A1C5AC5EBD3E3E887B7E0BCDD9121C2855C87CCC9078FFD868D7F0BCAB9C6072DC52A6153A0DC12803AD91DBE0FE7081209F6371361D5124161843DA7EC990EB54FD15CB869367DD46439B14A2742EE6EBFF2C55CCA5FBB9C29C633E4C347BBE6E4C95A0F0F9BCE5B2498F110E32A3127A635B6DFE2413D522BD462E99E87FB994697278830F86200B9471B5BB0CBC8D62AA1AD1A74AC26884557924123193F3F7540906676F61AC572A5E6BBC3E395E57FAA869661A2E4E12409A5E93DC41D80304AA2C5460A3C233D422BE3274839110264F30E81818E6E3C7E9BE404E7FC7F65B63D626E1E2E34E94DA2CACCA212FB48BE3F9EAA310547E73C388D881F36AE21EFEDD23744F620169B68E73B20457198BA678C4496B02F7124E0474EE3BB9B7107646385F85E396D5B6413A9FF0BC969B011DC3639F1798CE4EDACACC625459A25639F6F2C5CC0C8F560E82F0063AA2E8E30BE04FA85AEF5C9611EF09217024036C5BAADA004AD711158BFAEEB39C98014D0C1A172699F3C6D33C5D9DC9BE93C7F3A5780F02A0D255B78E7882973749CE5859469B762FAA1148C77AADD965812EBEE90117C4CA841B2EF96801D464F6EA1053BF96F6E69F495D45535AC3FD4411C27FF7DEE1AEE1E3CC0C81F4B82E43B89CACC69C9B8ADCA1670F7D4E50DB7BCD94C2115E75F382819029917785C50C6293EF5A4461875F80FECE5C7F7BFD56D8B45D8D59D19FA3E07904DA1B884619C6E3FF0826E79AE517976FC153C3398CB2DC279B1E90BBFE9E700412A7D23BDCA95940640182B3D6373522124BEA741629250B1BEC7BB67CF87021CB7E256C70F86B56C1B9C8E222683513965F6CB1CAEB8A6E90054B7B720A94A981790243729EDAD9D6BE0866AFCAF7BA6E3B7ABF0CA31CFC74DD2C1E852D3991702738A85EC058C598740343B21D7817D3CB805E07860B3EFEBB2B2B70F2AF126A3DABA5C918B224DE444B8733E6FA601B3D349307E94583D0EC976AEDA2B90972324B3ACE8C7B79A67723AEA037E12DA9EFA9CA9668A4F5FDADFB92C273480A18885B0DC4B717D93BCDD352B3DE4A2A90F04B239520B8C1149BF0D4EC078D85E41744750FDA0D2767044797A4C3BDB3307C68D3782370C2FC6F67129BE58F68365C622E70B4DFF55E2C1B9F1759BBABCA9629C31DE06948FC51E605F1B5C01196329311414797CD5F67FFC54AAD04C803FF7E83C2E8BA224CE8369A9FBD8420530F63CD1638B988724A1E11888CB9A2B11411C221BA02F0ADCF54F6F0BFEB7D77B5227DB43AC1360C86DFEDA86872B28FA47CE1C78A4DA2508F21483C440334815B9506D25B8D970FD578FC5AAF4B225892F9EC8E55F185005E630CF90BFF0245E82E1D31C75E2D8542DB6E613BA52A0831D06796D3F4D752CA7F4D280B6021BE71887616028A0B0ECB4193524480B917CD352870C0C33591E887DF0B23E656D7E2729177C18213323818435F2951FAF7288F66F9B7B6ABBFC9617B0191CC9DA4EDE34F511E0849E7C27115FA6EB6C43172DC2FD4CB1AF4C27A4A6CFA68635EAFBE197FA2785E5C4BC21108FBB7FF7D8B47C356EE380B7A1DD9F2F9912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70DCA617FE06B50B30FDC6C79E168F5C8BD57CBA8E2CC34CCD54E6665ED65E0F64F8970AA0F4B350BBE7F49626406F6F1828F6C57A1CF9FFD94051500D66388DC4FC22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC9D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D00C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA2F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549617285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909DC96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A3 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-2_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-2_256.rsp new file mode 100644 index 0000000000..9b66f0f23c --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-2_256.rsp @@ -0,0 +1,12 @@ +pk = 000000030D4B3BE22EE30889C2EA6A12AD6FCC92452E1B92832A599FB4CE52C86E8C429504562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000030000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A0D4B3BE22EE30889C2EA6A12AD6FCC92452E1B92832A599FB4CE52C86E8C429504562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD09000000000001D5DA3370DA40FE4B2AA8D93A4C52E009ED16134083746A63365266ED868E33160A0000000000010EB7A75A56A1497F0FC1FE5B3F6B396014CC9357B7FE8A6D2BA1B553EE3518610B0000000000011B23B9B57C09E7B440346ACFAAB7028D8821AF52CA85D5CEEE66FA4E95B45CA40C0000000000016AC8FE7754C3CBB4F71F8514603EAE30A764437F404409A1283CFF4B7159C0F80D000000000001CC6FF52DE53BEBD4E1D3DD11D0BE5FFEB977CA63FF2ED1099705AD3D5BEB1AE90E0000000000019B6C3951BCA1748DC7B89630F962DEB3937A4F8D15BF5634741113C38D2699F10F000000000001F21F01A1F02A9D105C71E89A189791BDA7CFB7BC89003D2EEB2AC6E7DBC26814100000000000019CD3ED9E3D49C10FE36B3813045F452DD0B3CEB702EA9FD3DE2289FEA46C9E41110000000000010CD4EC639F5FA5159D505EFD1215E62E35B38AC9A8B36077EB263B10F5BB4B741200000000000111A178357024706621EF264E4A66422A6F5B9F4C24A35579CB17DC686277D0591300000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F7F8F9EAAA74A5C910DD60B2FA5179B3FC341BEDAB53B1E957F40AFFE59FD454EE839D34EE92ED029C1B5853A46CC8B48B58DC4F74EBE2164B7F867B17ACD180761BBD5017870DCC53B0ADDCBB8DD1A6F5D014B1A789493C53C3D7B304F6237F836AA9372B0CD7007588A7EE166C1F8BC1C7826CA9D6E2D73B1B217E238FFB65DA1671204B7137B3C91D19ED0DAA12A98AB71C239C6F0E6B29D3F61DE3F71688560646DCBB9846A8F28BD1E7606E2C93CC0CBAC8A85BB578671BB01347E7B2BA757AA92131B2693D7F9501E87FC7C1BBEE1B8BF15E28DAF9B74487ED12BE8A4075FDE22DA018C0531776136F0FAB5ABF372E160CF51685CD0B8FEC7D63D39F4A7EE635051E54EEBEC7E8C4A408EBE848B7255685201592E3730C4DCCC6E7DE956B4FF296E76D0052EC6C037ACACA6E6474CB17AB271FFCA98A688D224C3A25425F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E7040000000000017D93C20AE191054626B3138F02E186A4607EDEF6E32DD3B2D788325E88FB01E90500000000000159008B71F97B67D9710ACBCAD0DCEB434823D0DDE4E8526701AF9ADE23FBCDC406000000000001410E6F39D12638391198E1827F643E6547AD7438BE85774B713D8FF3D8CB682507000000000001030C34B96241353C81CD7DDEA97ED6CBED8C9F9FB86DB60A6B78E39A253C001B08000000000001B07CBF5330F3B30963D6B0A4AC7AC4DD77585E4EB8A08B62B9AF1FBF42B76FE509000000000001D62A2ECDA2D153580BB57CB3FC1EDFFE89B6C06DE234962509FDD49A5A2438EC0A0000000000013792F4A440FAC20AF31472E40F1E79BD1E1C5DADC93FCA0319589FC55A542CBF0B000000000001FC454756AAA4BF5A8163937BA2E80D39CEF46D765C11FD66664120A83A61838E0C0000000000015DD4A3768F248125F414048EBD3F6AA793AAE4CA471DEDF5A9890841DF6DD56B0D000000000001CF0D1BF19096E3DE0950E9EB4C435D0C6B3DB4604FEBB60342D5B7C30528D4730E0000000000016ADD9B858AD6562C3B812B026D9BCE050D5A40ED6D936B1034C036AA490CFF910F000000000001925FBBBD85D4CB4AA7F5D18D703449AEABB18A5D32CEF076C16B7131DCFC08D8100000000000018DBF8B67F11FF96E3229EF8CBDD85719101DC3D8E6F636CEC6D19E63ADF5679011000000000001AE3D1E12FA31B287D509FBE36C261650C199242799057289B96E8D67301B473312000000000001AB1B5ABFFCFA0D28692F1FE23A1C1C3C31133714D112C66E05A09912A1CE32C213000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000087DFB8B692D4548E69E8F52A40B52D87261DAAEA3F734803A146D4622D4C8B17E1D98A7B04CF346B99E512072176F7A8811405EF38E007181DA3563CABBC577F41D6B8EEE36B0D67FF4AA525185A5821F2ACE2DD7F0607828ACF8AB08FE940D7FD268225449F5D20ABF61D2C7DB585A8513AEF60841E1BFD4AD3C47D3A00F68F71DCD9236D7E0FBC428C7095CA12D8D10B2E69C9FB6C976F4831246C9C0E2686091FB040E21C594960A1F6734A0B84BAAACE4EEC7FD1FABCA7F71373620EF656309B93B9D768970B0A03B9E07FA9C888A01D85B0B92F6550534E528BFF6289CC398003AC6A91CF86329B6BEB13854C20A8A75DCBE7A470B216C334CFE6AC120B8AA42EF5A9BC9FD224967218F17A334DB9364F966DA366BE08CA2D1C6DBAD769ED1537C3F5528CA849841BA495B78D07901481631E624DC0656F7F5D0B4820B6FC2269E404ABD245B49EB4FE7FB119E88663C8B8E75EC63C9C5A8EE478313B3B058DF1ACA81F65DB0F2E3E411A30158178585699BE52B6C11A2DC966753D7485AFBC75AB6EB6D0443DAD871D0BF43128A057593EBD325466AFCA3EA492311A31788F75372B5321217937AB4FF23D37D3A01E3578E758A2087941120E801C12F26FCC55D089C712C0A05E67122E28351745998168D1760B16D105D854BF2EFF369971D100CF448D3D00C2C34D5F6037A07522DE2EBE014E1E60D7A535B4CAC42EB69F7856E7A259627F4492A0CDA142D743D7BB90F78EDCC15B1EDF8DE7D0D4366367E581254AF959768265DAC9175E18F133DFFEF628CF769EE7E9BD0E07259AFD067AD441ABF81FA7726FEB1140C3146BB510185AF098DB53040DB97F1EF894CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318E413A87250637B5C4A4BF18A2D661BB2458CA7C7F9E320228FFFEE614E88838DE28767053DAF289E9BB8073D60114D20309CD17A6EBA5FF2FC47B49402DA3600DBC4323559761781818334D1C0CAF34FAB5A940C83D6A363433E390C3B589E1B6D09A2F4276547FB279D1F0E2D1ED91A3AFC953F9E7942BEFCF2AA66B19AE877A6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291D560067063A6EBCB1EABAF7FC12F66BD94F1BAD021254D0CE1F1F850B081262A446E84188C3A9A3CB89A80BC9E8F597EA247A39A6F59BE2D76CCDD6C96DDEB9EB0A272D02C5327DF20934FF8C0E26C71F6736FBD5B85A56F15E41F03DF2713DA70DEC489B962A1F7E119465FC8D72AD1DA559EE0F25FF661AD2F62C6BF172C4B7B0891FF05D0C985FBDCC4DEF2DFC3A73AEA39EAE9010A080DD47BC1268BBC1B5282DA83C62A9FE25CBC62E611951A411B03FA8832E227D761A35F4FB902E54083FD05142177B5D2987BE26FC4F9C5D13FFA21E7488F19245FD19D9FE2DA32608B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE5BCC31B508B8177B41775B459DB06F4AACB419F24EA979AA24C996554DEC91EBCB16E9E1B754DCD221E02231F10FBAABF79E362A514D54670DE7493B7CD7B66BAEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBB0A1E0563E934CB60493FD19327C71D824F361B1133A15E47857567979B5F8288D5FABC9D1D47402577CFAB60BF840EEF0D9173D47757BAF197EE10941704811690592F587BC7F532446BA10B875CB7994CA2613A25F65D16A6735E9CC0C4238036F68FFC1A893DDE19859CCE3F5ABA348F769D122DE567889C14924B243B1379AE65238446E7294F293F0DF1751C166CCF58B4F76A4A7A6178A136E3F72D120FCCFDD47311A340A0734C7DC77664B6D7BD87EA93215C69CA59F0DAD8E258637B49DF9864B84B76089E4F50B6C2BC496835D701C6F106B2B96CDA03A7F118AB5AC2F7073E7596BAE489C83FE68A8DB1E9A5427A31E8A6DC4E2962E5571FF061908EBBED929D64B2505C1C491CA277C2917E0A964218059309167716F47FF2699FEE7248ABFC6723085934D706ADBA0BE046CE3156EE682A5E0ED51534CFEBFE9B7118577F6D3157F31E8D849071E31A734BCC1DABDEF02B7D817FBFFF2CF120ACAF9BE403C35D92B960CDABB7242115FFBC4208977E19BFFBF250DE7C71814EC7206CB8F2E1D523E293E557D49801FA6D9E5AE279D396F91021690DF5EA153B3020CA3E08D8C53DC9DCD731315CB24C9394C6DEA84543806DF231011B086BE37A57CA2B888A74FBE7379EA346ADB56D932BA4B7B857A7918116B70987865FEAB8A42792F788F8CE13F75670B36029660F68A7E27FA23EBD2CC06C7CE9A51FC7B92220D44C4E9C7900E1FFD77D08D35B34B201EC5DCE6348FF7AA08F0DE5A4AE7C664F8E70D3531E181B4B5F7D74E8B6FCA7AE776AC73C4620B77C1C2397B987C241CC139C6407FEBF5B912A407695EE8AB6612C8C3D610D6E11E107E43AA6C638FF86104557546FD5CA0098C44C4EFEF0825DD5E8B33E5311238A32672242BD19ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDC05256E7B9EC23FA6F460956174696C9283AF19A615B7FD209C25EEA0587D15765808D7814EA792B7C31F469AA7004FB9A78EA5E59459C6E3F75E9E4DE961B5FABE5149967C9F97B1BC5DBF8E297DB4B25FC55241FDC189E9488FE06F71E9D1D4E19D50E7A3B81FCFA4799B127AA0D8C12FAF48811D52E4EA08D965813E20A7CB532F3EBEA5CB60601DDBFB1CD19FCE3F0A9CD1E452D1BCDDD215B91160F6EF5892280D847E32600F50E5DBB0DA83A650FD17E4A58EC02BC05DE23CD3B2C04172708C15A96A3D43A212FFD4401EEC87861C35351A0BE9D7D4D6AC5D60DA8AB5E1BBC7D943F4439AEBD7A6B022C8EFEB712BE5EAB7A1802CDD2FB9D93FA6E4383586E517A4D79D9FD2F6BBFEF8C65F1F3111067670E6A059A1308948697F5650C + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 5605 +sm = 0000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA7010591AF601BF50208B6C5968D4F692F07279A9C6AA2E66590F7D2E54DCFB47261C040A14FD137EE498C24B0DC750905F56FED22A393C31815CAF6ECFA1D3BC458E3DCC2B150E1DD088C95AED7DBA928946BCC8351DAF6136F7335FA45EE8F4651C6B0A4897AB5ED84C95BF9D9D78816FE9E92F843558029A08EF7015764C3D1AF1852C50D360F65F887479E9631A2CA30FE3AD92E7BF648643835F4F8CC081A6C9255CA9569583D0B40DC8A5942B9284515CCD9497D7AC749BEFAB0032A08D412C7E9C14ABF9DB094E3BC134A7340CCC65AF466D98443007DC0D228B92614C4AEA2949A5EB26C517909E0E663E36753491182975206009107509DFFC898D308B903E84A8B29718BF7125397AFF5467D53CF8F36EB945B6B98D48E81C0174A0E035CD71994D48CEDA477BF92043B7E7C743DFD9E32948D29632C6C47355A5701C0EA6EEF78B8184B2E355CC338055DD2A26DD02B1A0740CD15F6CBA4EF429254DBC42B4E4CAF8C6A654DC35E975B5D6F725102362943C6BE446FE298B8F60D4F7945F48FA30DE2E92AD9D0EAC1F4B2F6B8DBA9D1F8CCB77367706BBBF6A04658E8B5B20D28D1B9384DF1D710AC39FAF699989418B7856C2034C695A693ECC336EB44A408370993A75DB92E04D2AE87E9B68A9B3ED860AE3B2FE35CF590BBD5C8FDB578DDD5CC10FD6A277CB7F7E3FE7D4A0BE921B1618FEA9ACD67A0A6403A4CF19503DD53FB1B3AF7ACFE24C28A700632DD3934A56129B66BA60E6BE40B7EC27DAE98F99E31983B4C2DF95885EAFD770642683F7BE36EBD50B76020DA763EC0CDFED7CF9BAE790E7EC9573A0DE43636BBED92A210DFE814B95600B775240CF7337D124B757C9441C0D52C3585DD7B4EF2379A73DDA87B41CE87DDCD392A4B6FD9942A9A24E79B7D98A56EF751FD1AAB89A95F99301932337C4E7820B84B1DE9CA28684AC3B47FBEA813CEFA4754D02086281392EADE94F003AD0EF78DA65C89BAA18FB1BD12E0428923AEF51F55928C8DA0D632382E3325E4CC5C6A3EBC4776C9F6520EF2C6960F0129A707F90315AC1AB035A7BA0D293A6400C30D363DF000F536BC9BE5B558AF33A21292D74831447DC10BDCE1DDE460F168D09CE0EBC1866581CDAABB3A1CF1B2F23B1B131831F0AA6A9B9812A422573EC10548371DA356F10510E48DFB7E23CB49D6FCA39A1E0F471F16A8BB65AF02150D059036D00386DD2921D5E8459ACCA633C5B50F7C6A36062BE168AF6246317A8B052CD7F15A96EDC0BCA137C5F65137C2F61DC5E02708B286B4A416EB49929D86E713FB912E44B87F85D73CB40792FF03F8F20427D951444990CA3976A71368A7DC1455E880722F0300029FD0D41FB427D0515FF9AA3344F5F3E4811431191A1AC406B7A16DA1063115DAFADB4F258D8BBED23B21C65486E46D8BCA833B6967A09FC7DA038DE1464689E09376BF39F4C562ECB1A68E02D5D91318EC0C91D38E8E480B8A0E65F45252585CE1A0C20AF62AA5A28C4FBF5D15AA7B0A71F964FF58031123CD5A9986D9F89CC18F2B6664B4D83235357E327821B297F813F86DCCDB13E3B5903FAD26CFB2298461DDE724EDA70528C54B09AB368C492937993E3093A695AF1F950B14A1D348B12C3C63D8F8EADB9A26B8FFD6DFE7453EC8B6FAF4B9F5D6F74F6CDB81B5420169B68E73B20457198BA678C4496B02F7124E0474EE3BB9B7107646385F85EFBFDFA55C12A388836717BB2BDD97E89121C56C3B53E8198242315C9E438512ED74BEB3BDC53DC8CBD2A281340B78F7635419636A3C38E9D5515CF8A035A439DA3D8CAABF1F06E36E322294F3AE10918203801BE05F8E4EB9A2663EF7894829F1A380C43F95D362E0680D9EA2CA47E1DC8C49703E22650B765F847AD86BE25A31377FD516E97B6AF21BDAACCDC8D36619B7D89C62EAB646A95A90E0EB467A75C97C1014D748D6338397737A54B2CD2CF860C14CBE1AAC697CC39DDE00C3037102F1EAAC7944E4E7E754B78F741D7B3858E4BF33C370C36B8A7560D6445B6D2F64E165DB2CBF8027EE9B5CF5EBCC9DD06A5C319E2B9611BE946B6020CE4D9DD736E8EEAA2FEB1CC855F0A745AAC84A610DF0238112C6519F8E7346C45331A6036D84CE48A25C1D687C6AB85A7863A51EE463CD2CC2686DF144AEC6049484E3FC1A1646DDEF29122F153C5B5197A2AA78E9DEBDF712F92C42BEDB4BF1AF46B1A2F47D9A150ABAFCBBB6BD37E68B51E1E3B76A88186784096804E0CA23134BDB161FC9578D9E5B309675B6C05FC8264D3591B80770D4DDFAD2AC53E7A93D8A8469837FAFA9FE1D707144A2290523A7D25AC1BB6206AB824556519D2B909E4D04DE82C273480A18885B0DC4B717D93BCDD352B3DE4A2A90F04B239520B8C1149BF0D4EC078D85E41744750FDA0D2767044797A4C3BDB3307C68D3782370C2FC6F6712FC7EF1891A77E1A3F29D810C205EE212E75863F3B8B1ED216DF888ADD07AFF47738AE40641E2FEFB1097D7048C618D4A0B99C75276B6F41EAFB4FA57B0925FB775013C6C36C81EB0FB69F86B4514EA931FF7E4C4179DFDC31A92EE8F618321A2F4DC28CF39967D04766E592F7D01995F16BA6C9D1FBA22CE251F5F0FA554D59D75BD46109FC202692A3FE21B7739AA9C39BD1B24AB82C59373CC06D3F92D48BEFBA495E0499587494A9B6E4974C37F5C006A34FF102A23985FA9F660326DA393AC26CB1FAC5A29BA262D95C83C292FF3D75F4DA803F4C139AF1778793988AB25608A8216E5C8E91E1E89EFEA60DC1306CFBC26529D23619E354A7F1332E790C6730FBF34A79269B4FD988E4712D927E6487995B4A33B3DB9292AF35F278442B99E10440F06BC626856A2015DD832F087A72864D390131A760B46BFE305E3B4E9912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70DD4CD344ED3ADDBE4C748D918BF1846595ED36485972F668C65B6365638B4D41B7AA1071D740ABE2895647F286260874BBE8C609165131481CD81E4C6D98293F1C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF987DFB8B692D4548E69E8F52A40B52D87261DAAEA3F734803A146D4622D4C8B17E1D98A7B04CF346B99E512072176F7A8811405EF38E007181DA3563CABBC577F41D6B8EEE36B0D67FF4AA525185A5821F2ACE2DD7F0607828ACF8AB08FE940D7FD268225449F5D20ABF61D2C7DB585A8513AEF60841E1BFD4AD3C47D3A00F68F71DCD9236D7E0FBC428C7095CA12D8D10B2E69C9FB6C976F4831246C9C0E2686091FB040E21C594960A1F6734A0B84BAAACE4EEC7FD1FABCA7F71373620EF656309B93B9D768970B0A03B9E07FA9C888A01D85B0B92F6550534E528BFF6289CC398003AC6A91CF86329B6BEB13854C20A8A75DCBE7A470B216C334CFE6AC120B8AA42EF5A9BC9FD224967218F17A334DB9364F966DA366BE08CA2D1C6DBAD769ED1537C3F5528CA849841BA495B78D07901481631E624DC0656F7F5D0B4820B6FC2269E404ABD245B49EB4FE7FB119E88663C8B8E75EC63C9C5A8EE478313B3B058DF1ACA81F65DB0F2E3E411A30158178585699BE52B6C11A2DC966753D7485AFBC75AB6EB6D0443DAD871D0BF43128A057593EBD325466AFCA3EA492311A31788F75372B5321217937AB4FF23D37D3A01E3578E758A2087941120E801C12F26FCC55D089C712C0A05E67122E28351745998168D1760B16D105D854BF2EFF369971D100CF448D3D00C2C34D5F6037A07522DE2EBE014E1E60D7A535B4CAC42EB69F7856E7A259627F4492A0CDA142D743D7BB90F78EDCC15B1EDF8DE7D0D4366367E581254AF959768265DAC9175E18F133DFFEF628CF769EE7E9BD0E07259AFD067AD441ABF81FA7726FEB1140C3146BB510185AF098DB53040DB97F1EF894CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318E413A87250637B5C4A4BF18A2D661BB2458CA7C7F9E320228FFFEE614E88838DE28767053DAF289E9BB8073D60114D20309CD17A6EBA5FF2FC47B49402DA3600DBC4323559761781818334D1C0CAF34FAB5A940C83D6A363433E390C3B589E1B6D09A2F4276547FB279D1F0E2D1ED91A3AFC953F9E7942BEFCF2AA66B19AE877A6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291D560067063A6EBCB1EABAF7FC12F66BD94F1BAD021254D0CE1F1F850B081262A446E84188C3A9A3CB89A80BC9E8F597EA247A39A6F59BE2D76CCDD6C96DDEB9EB0A272D02C5327DF20934FF8C0E26C71F6736FBD5B85A56F15E41F03DF2713DA70DEC489B962A1F7E119465FC8D72AD1DA559EE0F25FF661AD2F62C6BF172C4B7B0891FF05D0C985FBDCC4DEF2DFC3A73AEA39EAE9010A080DD47BC1268BBC1B5282DA83C62A9FE25CBC62E611951A411B03FA8832E227D761A35F4FB902E54083FD05142177B5D2987BE26FC4F9C5D13FFA21E7488F19245FD19D9FE2DA32608B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE5BCC31B508B8177B41775B459DB06F4AACB419F24EA979AA24C996554DEC91EBCB16E9E1B754DCD221E02231F10FBAABF79E362A514D54670DE7493B7CD7B66BAEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBB0A1E0563E934CB60493FD19327C71D824F361B1133A15E47857567979B5F8288D5FABC9D1D47402577CFAB60BF840EEF0D9173D47757BAF197EE10941704811690592F587BC7F532446BA10B875CB7994CA2613A25F65D16A6735E9CC0C4238036F68FFC1A893DDE19859CCE3F5ABA348F769D122DE567889C14924B243B1379AE65238446E7294F293F0DF1751C166CCF58B4F76A4A7A6178A136E3F72D120FCCFDD47311A340A0734C7DC77664B6D7BD87EA93215C69CA59F0DAD8E258637B49DF9864B84B76089E4F50B6C2BC496835D701C6F106B2B96CDA03A7F118AB5AC2F7073E7596BAE489C83FE68A8DB1E9A5427A31E8A6DC4E2962E5571FF061908EBBED929D64B2505C1C491CA277C2917E0A964218059309167716F47FF2699FEE7248ABFC6723085934D706ADBA0BE046CE3156EE682A5E0ED51534CFEBFE9B7118577F6D3157F31E8D849071E31A734BCC1DABDEF02B7D817FBFFF2CF120ACAF9BE403C35D92B960CDABB7242115FFBC4208977E19BFFBF250DE7C71814EC7206CB8F2E1D523E293E557D49801FA6D9E5AE279D396F91021690DF5EA153B3020CA3E08D8C53DC9DCD731315CB24C9394C6DEA84543806DF231011B086BE37A57CA2B888A74FBE7379EA346ADB56D932BA4B7B857A7918116B70987865FEAB8A42792F788F8CE13F75670B36029660F68A7E27FA23EBD2CC06C7CE9A51FC7B92220D44C4E9C7900E1FFD77D08D35B34B201EC5DCE6348FF7AA08F0DE5A4AE7C664F8E70D3531E181B4B5F7D74E8B6FCA7AE776AC73C4620B77C1C2397B987C241CC139C6407FEBF5B912A407695EE8AB6612C8C3D610D6E11E107E43AA6C638FF86104557546FD5CA0098C44C4EFEF0825DD5E8B33E5311238A32672242BD19ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDC05256E7B9EC23FA6F460956174696C9283AF19A615B7FD209C25EEA0587D15765808D7814EA792B7C31F469AA7004FB9A78EA5E59459C6E3F75E9E4DE961B5FABE5149967C9F97B1BC5DBF8E297DB4B25FC55241FDC189E9488FE06F71E9D1D4E19D50E7A3B81FCFA4799B127AA0D8C12FAF48811D52E4EA08D965813E20A7CB532F3EBEA5CB60601DDBFB1CD19FCE3F0A9CD1E452D1BCDDD215B91160F6EF5892280D847E32600F50E5DBB0DA83A650FD17E4A58EC02BC05DE23CD3B2C04172708C15A96A3D43A212FFD4401EEC87861C35351A0BE9D7D4D6AC5D60DA8AB5E1BBC7D943F4439AEBD7A6B022C8EFEB712BE5EAB7A1802CDD2FB9D93FA6E4383586E517A4D79D9FD2F6BBFEF8C65F1F3111067670E6A059A1308948697F5650C000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F7F8F9EAAA74A5C910DD60B2FA5179B3FC341BEDAB53B1E957F40AFFE59FD454EE839D34EE92ED029C1B5853A46CC8B48B58DC4F74EBE2164B7F867B17ACD180761BBD5017870DCC53B0ADDCBB8DD1A6F5D014B1A789493C53C3D7B304F6237F836AA9372B0CD7007588A7EE166C1F8BC1C7826CA9D6E2D73B1B217E238FFB65DA1671204B7137B3C91D19ED0DAA12A98AB71C239C6F0E6B29D3F61DE3F71688560646DCBB9846A8F28BD1E7606E2C93CC0CBAC8A85BB578671BB01347E7B2BA757AA92131B2693D7F9501E87FC7C1BBEE1B8BF15E28DAF9B74487ED12BE8A4075FDE22DA018C0531776136F0FAB5ABF372E160CF51685CD0B8FEC7D63D39F4A7EE635051E54EEBEC7E8C4A408EBE848B7255685201592E3730C4DCCC6E7DE956B4FF296E76D0052EC6C037ACACA6E6474CB17AB271FFCA98A688D224C3A25425F +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-4_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-4_256.rsp new file mode 100644 index 0000000000..d17a127d5f --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-4_256.rsp @@ -0,0 +1,12 @@ +pk = 0000000463FD804E9E56657035D9C1FC5A291B8586E41D1E5E5560AA76B30C26198181A604562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000040000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A63FD804E9E56657035D9C1FC5A291B8586E41D1E5E5560AA76B30C26198181A604562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD0900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E7040000000000017D93C20AE191054626B3138F02E186A4607EDEF6E32DD3B2D788325E88FB01E90500000000000159008B71F97B67D9710ACBCAD0DCEB434823D0DDE4E8526701AF9ADE23FBCDC406000000000001410E6F39D12638391198E1827F643E6547AD7438BE85774B713D8FF3D8CB682507000000000001030C34B96241353C81CD7DDEA97ED6CBED8C9F9FB86DB60A6B78E39A253C001B08000000000001B07CBF5330F3B30963D6B0A4AC7AC4DD77585E4EB8A08B62B9AF1FBF42B76FE509000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F04000000000001F37353B4AAC3DE6FA6FA583102CC2F35D6CC95325A07AB88D9B0304EF6F8103305000000000001E087F84EB8A6A13A9581B22CDEEF8942E186FE62896C636D0503675B28692B72060000000000015FDAFB6EEAA60CDFFD2E2D1C034AF7306D60B106F145206FADB857BA565C66FA07000000000001CA463E7885C94740495E419265530662D2D8B0CF6C9E7C290FA86E8E136261DD08000000000001761CA5CF20BB11D4515629D8BEC9D72E02E0D3392C20084723610CE22260DF920900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A3928351163E04D8BA817C168A0CE68CAA6FA744E7E30A2670B2BB88F27810C887E48E90EFAD40F9735B5767F60EC515C146D56EA534C970E04BDD10302D85A2317C478BD195FC93499C051F5AF61A6C5CECB89A1D67BF5BE2CA7EFBDCC20B884597EB2BB0799DB9B86E2EB8FD93389AB91A391F2D68A057FDE361AC97A87F4406F40A7EE2E7709E46DCD756617DCB0DBBF43E6BD4851F3D834BB53CB150D2FB7B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019C1A7BFD8300283215BA57DB5CDD95EDCBD04E1C41419317BC2069C2AAAE22130100000000000143ED646E32FC21554D8DAD350C5732270CC220F7E264ECB5B7A8E8A4586D0CD002000000000001762D040EECA13E137753604D099809D946063368BFE1C7CF0E6549FCA746F7C6030000000000015FB7406F1B25A2B4A6A1666269772EB08D6FE78D8A8395C56AD80FE6924DF08204000000000001207155BDC49069839D60C0C74C9F57C739D2F36E6AAD0F698CA840A48FB11EFE050000000000012B5052F4510570C5839D41287DA3BD24DE8CBD40BA9E159E783C5812A28606A7060000000000015C07001390BCC398A47CF40395338496D66003B5E0C1DD7187A5D605984F79ED07000000000001285C8B2D9B398B8A212B3CE0FA820CE44048C2105C067AB9FE6FA70B1E712C33080000000000016F81A741E38029A214AF0CDE4C75E79A618C7B4942F7819A53CBF8EAA263EE490900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F1C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB62334F4B56AA20F9BB57C09EBF41BADB20D36485AD613C790428C382B437866A681635BB509C97D4AA12387C320F6CEFD1838459F0DABA3DA54684B83E3ED10C07B8CE62549A876A13D86D8F3D001504D939500462E64C94B6EEAEDDB8856D13AB345659CB16C8B977B6670208B70920BA34E31E6A10EC724CC6FB3C299ABE890047E1F6B3D5A69BF731EFE803088FC8D3B9E69DF3102AABBEBE90C3EE20DD829BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB714212BBF4237C6D69B1D61531257FAFB41BCD74462C292880AA396FDB392A42C4AAD9B5492EE4F2A076CEA42927C22BF7CA54FCA135A0FF512CAFDA620DA75DF70C37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B755D1BA8476CF0553AA3B5049EB57DF8F00AC5DAC2C1DEF316793E5DDAF9F352894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779A89119240A8E28D1D44AE57D7D3252B69192353D745AE1C066DB60F6C6E82F35854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F04615F48FC178E8CD389A2DEA13C83E2534271AE7DB54D7C89B8714666381C388D37BEC8102F8497D8A820C70C47254582C5C27D3D97A6ECE379315D5520BA346E8F5B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E07949F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DB9D6E9AB3A0926402DD8095AAFB46217FC41A2E0D7C5960C1FC814E461B1F1F219CBD0A97D50180BB017229AC9F884896F357900724A3A7A8E4D479CF6A093FC30778F755C63CF618073C40F6042FB2143DECEE8DC32CE9D3E0064EE378F78B8F945A05629C118D60A6AB5DE2DA55A06B7325FCCEE42C01A5C408F0291E3610C44684BE1F66D3FB8F6BE43EDAD2EA87FAD50C993CC447DCAF79AB19DD406B20974363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D024DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA1678158142C023B3C238A93F3D1CB8E48EF84C168E27E6645DC6DC6689E89CA0A74D07087B760743BB526662636725B7FB700BBC0B3A73793C291EBBBCD4970B27370C2E85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B780BF58A5656928CC6684D80B728FA0C1570B8268DFD57EC9168CF7D39997BC8458A5D4126FEB278B26769C4F55EE77EBCD778D00F836BFA6EB13307BA2D7417B0812FDA4CEEDA359BF73865982622728D7EA8BAE1620A63483DAC957E4F8E082588E12FFC57A2871119AED0B43DE4ED1EDC4AD6434A485C64D9FAFBFC7F01A8793E5649BF33A7186BDBDBA5DFEEBCC16F2CCB67E355774B8C32B932119DA7158A4D131F560491BB42B47C9EF1594FF6F09BF29E972502A7D62A2240FBBBE55C3D82050B374EB42E433CDBABC163A95A6492A7F7DA6824B5A20527C9D0933B97C753932ED9ED277E40CCB8C4A042FD5B88E9C5D569A48F512ABA1DE68C821BD20C1A995235727654ED6E59B063EBA5F4046E7D047B886A22A7D7C5BE009F3E14629FFB78F8555B7376AA2B7B4B360F0D3C295ABC2590CE1AA36943A46379C1085D66FFE0DCF3C37C89BBF1C7D76B6D62D5D2D265EAC52164E4799C52D9A7E67836B66532608870BCF43815BA0633B82CF8E92FDD0A4DF829039370202BBD93541D4D398C42900F96D70AB85AEE46D4AE2CDB5BC61B0E57DE8AF9BC4A366730CC4A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349E9A943B50EA190BF7E28B4406FC4B14E77203739F8DF7D168EC43FE06D0645ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC40509461C2CEE814F7E26684AB01D51A1385EA51162E9CE43172A1564809B328A45AA68BC14BF38692467DE23B8908FB07BA05C90DD44A372477233DEEC84BF89287B1F8E1FED4F275FAD98265AA76F0D798266081567140ADAF2A9C64F41E053D1F329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB03F8A842A1FF048CFCF92A8D77409DE43CA455C5ED59F89358559BE214EE1B531915180697A948C945A9924FD6864D9CFF00E1D47F38B54092E4CFF1F92A65CCABF206A7D71F25A66969E37EA7D52EFD74B80E93CD7A048F71EDDE1EAF82A24F20145528EC96BF1857E0F1D8F19812EAB34E07D4262D195D1BB4D20FF3E226C2468B90E951C8212023248340ED5B7E4EDF3C6AF6A6FEE63F8DE613EC6F1526E3F6A9327A17C2279BEF50B6CCF1569A86FA56DC4B8866C365DC5D16B9BA888234D6860885B2A420401C0E3F8A971BE2CCF46FB27EB58D6C8EDE207B703FB7EBFEAC77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981C93D4B2B08DD6DD375D4C84791CE66913FD4E3D6B01287F258E8EB01A223CD222F81B1412BAD3DF60D89E29F4FCED352A1DC0D52A296D6D8145BB66BCC936BAC362F309AE4520552C369E4BBE918F20C4AEDF8F037EC9AE0A3BE8BA1BA0CBD40949CEB55F41C8728AA639789BD51539F1AFA46F71106F428C9FC659F34F6BAA879DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA79EB4AB02F6134488DF1220F8FA56D2C14630DA6F79094DFEE7180D218C621A32C153D6E5AA82C318BCBEC16FD901CB860793B8B3E9E357D0F008EA80BADACA56795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1DE1A2B10D241ECAD1523291D88D5D0EFE1D5CA4DE89F22AB2605BB5AF0CC6564C0FEBBCAAE5A19E133CA77B6C4AFE98FA12CFEB1A87D38463C35DE33D5B7D2E08C3DAED2A32A25502AA2B4E2F2A330F06294E202466F0701D4B361C71DB74253ECA3148CC5E1119591830C19DE38FEF1A5F9302B766F68E4E6616611EA940522EE92E6625C8783357799CB4B9F6A56A84976EDB84939B94A676D4657DBD04F7D754A901CEE47AFF04327CF6E0193DD3EF8CD61ECAB28CE8CDE2A56ED422C47BBD5E4B1C005EFD6C982E1601461DFE8EFF46797FCA8B79156473C7A964515B4A0B4373513F5DE44B5088663F1B9D235681C2A0F31675B7BD215F95D42216FC76E5C93A2C8929163064A58FCAB39F6A8700820BBC9EB62588C0377C15BD74E5B7E4F11559E54EAA502404D245774A51F17A9CA804C570941434AE4464CA23D8CB2D042633395BB951DF71EFCE0FEB7AA66CB0EBC83321C73AAB08C45F89D8DD625753795B7BDABB1CC042A4EA7BEEBA6AD585ABE6849B63C9630142B7191742C772BEDBDA162F8B4101824D6F16D189D65446852A08B37F359617ED6B0F2DC1A5648983AFC78D3D4009BFBB088F85D85B551DFCB0C99B46C65130CF3A25EEA02FAD2159409FEA41A7F3BF71F020CE618D82E4A2D5DD005E1E8839EF6B43D864647D89502AC44A7517F0D0E9E06BF9F55BE677F11F7A4689D51E5DC4892181C32AB56A831AD8E8691C9DC7C8D59FB0098C7581BF682298C353CAE2242C7BDE5F5933B48E88624CFC605A87E401D4B01FCE73BCC86D9FDDE138A185AB4B79B2394FC0718A30D5B8FAB24C2A67DF7C57690E380B21B9BD08674E49328286D6CD82FD782FF7BABEE169FCEF38BD5DC8ED8ACB324A374F426B0D835A5A947627DD5D026DACB3669212EAE997EFA073A3800694A8470BA89780C06F034BD1ACA26229A7C13345B4514B3C48A810C8A017062BA454688349B3244A3022F86EBD132636D566A899C38D183C149E8C9EE50F7F254409A4FA45ABB9B74750B0FFE552845BD460BDB3FFBF6259FA6D048B59198B4FD2B135A9DD870881D24109F95CB1B0857B395683A40C358ADFBED50D70A8FA540F6006D2493B59AE4BEECC8BE3E70396BF298B2F49B468B64DDAF12FD0C594DC243A782FB8862B2B73BF1F59FF1B812DCE96AD72D73D928EDD5D6D384CF214C7EBBE25676FE612556461D465BD1D1C8AE96BD8F349371553AD9E9B80623B49D5C8C38489415ACE7DB17DEA495DB1CE9B68AE228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023C8C898A4A7D16063A2F7FB6F6C00EBEBADE4B5A79A9814803CDA526D542E0C4C44DAFAE06659E810969F48EAB6EB002F7938B62157E85E1BF258D2B81ABD9195EB828938D84BCD92C9793BDA17DCD6ECB92068BEA49626C4595EE621E192309156F9B0127FA44454075F7C73A94992400B22CAB60A056EED2E04045E74494017E601F044245A2B64B83EA8BFEF2A02A32029224D3C9F5DAE64E4A3298688C1E4205FD9038743CEF33B08CD9366560AB57EEE937008332B6A4224476A759B07D04DEB016DDB8EDF3665BA71053A894F98DBEBA95EFEE3F46AFB944601CC71C39315012B024E672E7CEBA843F35C6F435983AAB0F14BDB63B2D130A91AF9F72CDFD73EA39DC02AD3074F0E4B3780E81732B550B298998169B1640D80FD56474FF655A233E3ED6C48E5D94A4C6D31ECBB5257DC07F29D5A4C98177DE0A4DE1BE24D2CA3CEF4DD2A3FFBD818E75023732E1F1D3F9051AF6E8047081FE588E2492E5EB4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F933819140A786527AEFC7A872908B98E8356286485E2ADA68D8733129C32FE7E0D0B7AB63E890DE8AEC5DB2D52F88D328E1DB56FF586DC2026817A277844C18228D01C4A792C6D27D72D4E36AC852098685807B31A411B62DF550CE9C5080F1BA5CEB1634B8EE7CBBDA91DA660CECF740A502064AF7781F544A2A9F6527CB431A33A905262210B977C09374F03C360642BB200F00F13EFCAB19685DBAAAD7EFBD4D42A8B428342F44A61D9D58808B9E7620ACE2D4FA47D16FA98950485E67EA182414D9C7B78C51CAA4960A79B1BEF4B6BB5CBA79515042433C7505B5038C4DD0CC8805CB9C1AA93B2BF96402909E229C46A5C2C7CB18F0B7747642714BF204D42A8AF263AA6C8F1DED9414FD0E6586D7B680D4BF1CB6CB6DD90D63511150A76C2C40384A4F156E827A22D0D207611E84477254E492397A85643BE2EFA36371F9DF6119813B2CA7F31D099B0715927919FFABE384400D3AA0869AF2E95B525D9A1453679B1624C4F2718AF080BE493D1DF583843CB08C5FAC4587627805AF278A009530F8545958E7C04ECD445240A70C6D0450DE5A3F3CBE710E610D8EEEA17F97381119B8A53A62EF7F4B0D8F84BDC86BCA2245664DA120E7E36945038F7973099B1ED88113E6594EC0CBE05B5CF5ECEFD58D48FFE4C16E0F941FCFFFDE6D3E584584EC8A03AEDB6126EF5F479E4FE8C97BA01A4980F78D12717DF17BC4E9040B105B2D74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7566DC65863A7E07D0D8774305019C67D504E7FC4DF77A8821AECBFB762EF377DFDE75F24A9DEF9CA7997E8F4AF3B4E60071F11DBA6303A964B7F9C3FD443C766346B4B1E50EA1D79357CA76ACE991F4760184016A12C2368F7D4E6BAF0C8EFCF4A869F3973B41564F52D762BECBC7FA49B40D6FCA22052287E1B10DD8FA257423F984FF4CA38BD49F322C84CA37874056055B3A0C51060360F05BE3E1DA6E1829B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F3171151E6F5442468D000FA46F17DC7437B058242696056ACAAC06AF22742452798DA226D91074DEFCAC6C3D770DC54CF7ECE9ADFEDB3B421ABCD9DF305D412A71FC77801FAEA989C03A0D633C4B06766491F4C0DC67FF8DEB16AFC8BC7E3D41601BF7B964B91A8638DDB7CC08B68691D5D501B5D3D72915442F0D1B9EA4DE4A + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9893 +sm = 0000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA70104A82ECC99EF0F9172F36D2B461A6515DC13666B7F1D917746E7086F99C8F1A63D2CB50DDA1EDFD708F002ABF07D0001C3357A70F6511884C4185790EECECCC578715C21A26FC1E7A951C54A30ABCDB7EC71AAD92F2662BC900F9E9A93054CF398017E582746F531B4697925154A22E2D6A0F1B81913438000C295153D7ADCA8FB21C6552D41F5F3865791CF993DD00FE3A036175178B6407E88A3F76605B5EAA51B83B77608A08C021821DA61962CFCC8E97D75441921D39C5AD537543EFBAF05BA4B0955661EA3FC882D9D64954405502E2BEF7D3063D36F993460D2557C79729E510FD11DA67C0C0D3B6448B88B96E0834210FDDA112F57C7B4FA60EC323321A23B8EE4F3EC419BA999054325BEB9B8BFCA6A2BBDF11FF7F8A170E9C5481D78F113C56F2E3BB35FE284CE8EAEC342D0D110591B00EBA3DBCD0FB7B965F199AA6EEF78B8184B2E355CC338055DD2A26DD02B1A0740CD15F6CBA4EF429254DBCD060C040187ECA41B2E544463458CAEEF75CA6EF08474060A8A1A356F1BA92EA6CE2FDA531076DF2E6296DD460D39973BF771E938FC21B05C01C27ECAEEF1B29C7329B6C264A9B24F73BD95BC8890AF4C36695EC8E2C29B32F4CEF4E02DBA54963C09D5F56674AB6CBB75352E7D87BFE1D85372318F051B955CA3661F1797D3C46191DCEFF06EAE14F3762FA5C231D3D57770F230802C2188D108FE326778A109E07417E807C087062711DCC7BBFA4B0D54077AD8DB142A191E6BA6BB251837447D20C4427ECD55AF940037B6D3485F6D6C7B3CDF5A5C19C958655A51A34BA73B87452100271944681A77667368E04F077001DD9B1454DA4614F631A83335A8C8953DDF5F0562A9D378DF36D061DCBEAAC8613034756516EBF622F21096E20646F3D05BD9D5F8679B536BB6D39792B28DF2481A6EECB9BEE40B11A10D39A90EABA7A25D6C3E4B7D39A28A65A5628A93556FA9F54E273B583F9A197BFF4731E04E7725CD11443807BC4EECBC46D46EC3D79A9C0C755A65AB867B1BA4B07FC1C2F151BE85B8E8195CC2F070BFD482702182B8A4A43ED942F6BD3CBF9DE7E8AEB17BE6840E11EDD8EEB095E890AF71214311C2811E2E07C1EBBEA8EFB786EB321559FFEB8219555DB545D7DA6FB9A32B0A8F38A664FABAC2918C2C79A154F293CA8B7BC5ED49FD2BA5A1CA39BFFC9118DF8EBF732962924BC11BB190413E9BA0C7EA2328C40E977558DBDECCB8D643E07A573A9CB5DB4518877320FBB4998BFDC59FA3DFCF5C9CEC2D80AD509A65AEF0E3E663B7F31BCA437311BA799D4C2ACC1386FB466CD5FEBEE9FBC50D64DB78AB57238911EF50154835A6F32A63B7723BC668B79FD7241614D2FED6D1E2E5795827F146C2158BE0A39E9556BCE1B08B774530628FD7AD334BD17A52436209CB5E0CB08299AC5D618A73889380D9D4AF03D7E689E09376BF39F4C562ECB1A68E02D5D91318EC0C91D38E8E480B8A0E65F4525BB4B34F69DE75E4BBA54CE08465263BCD35B6C89003D738D145B03E200113735C572A5E6BBC3E395E57FAA869661A2E4E12409A5E93DC41D80304AA2C5460A3C55F9CA097AA6C3B65C5CD659AAE22F412427C2918AD8C309342C8369BB454C50B3A6F2E555E150F9C05581F09882E165B19FF0F393EBC3AC3C842D4DDD647F96B48E4353B554747AC62ADD7FE15D0C5CBE5A0CEA51D5E9339C72AE9F93FAD05EC782FFE265FEB6309F643277F09495ADB42B4C362E1EBD6790AEEB0C5329F797D0A9FC8BFE30C11D7093D7B9A82A4E2A7A62A65FA32300FD0750E3B6D38CE5763DDD3FD0A0CFEFE8577D87D69AA8E668F66279BE02DEC2D05BBA330A504C68A789B198A28F6AD355B74455297DDA5CBC8B88DEA9B7AB7D59E2C78363EC25A2601906247CBEFF8540483C95BA2BDD8E11CBE540D0B6958770D798891C01C696A3ADE5F5BA26D69ED191B3B47599B1CF4E28004F8C1DA229C20EE36147369CE8C9EB4272CF4BB9282993823EE7F187D67EB5B220C01EB64244F80B74F3A82B819BE69444398FBE437D944C74C4A366503580CC17367118F5FA8F818D7903BD4C0C9E8CEE39FB9496CCB77190F052B8DC58C76C5ECE6F0FB81A47088D8AA2085533BA507C80E3BEA5C0A43536117479EF4EFAF26DEBE8B536B932C8726E54D309445E44D90F65A4EC5BA93065A2A731CD107EBEFA54AADA64C3014C9A6A25066075A718AFA60C9411C80143C846F4E65173BFA7B8E0E02F10ECE9CBAD48DA9E0916B70F2AF126A3DABA5C918B224DE444B8733E6FA601B3D349307E94583D0EC976E6BF9D49BB099E99E115FB80548BDCA3276CA7DD2F3200DA1FC5724E17D6332169D5C20AA99EDA34414373F438014E66E104843EFEB4D8C735C73A32E68E00D0F22790BDF69AB447551B814FDB4BC3FEE56516113672C869715AB940097C9F18D612C657CB314841775DF71EC753FD66B70DF8C75C96468E20AE8126BF8BF62D20F53E003B1D12EB97F7B0B9A2A8B101C3C30C8FB78B8BE3267E1F3149A49AF062737735846EF0C8EF26765413ED32BA0C4D0359151681DB165A82B25B9C5D7F839CE80CEA428581B6CE720C459D6D2961C5A7FA8256FEC4951B69C04FD5383B74580BC603BF35A74329BF88F2621953FAFF5398064AE5E95A44336EC46CE73B986BB677DE38EDB99E61FCED7CFB2FFE50FC26E59109A2F3A365893F037E2C27DFFB2756E97349C738E49615B3CFC7A7AECFFAE45EE75E4B94D35E5F625EEEA50CAF3D4773504CDF16EBFED64F678FB18F012193B1DCC67B722A5D175DF541B89B2327AA33BB2F01AA3598D08D6246E5D4CBBB73C8008D6EC423B27CEC92CC88AB2ABA8C222B35CAB84737275612307A060F36E3012E9AEA3B69196711BF0BC48D2AE42D887D10EDBCABE6AAF951E0A070D881879332064C99F8527A5EFF25241013CC40576F20A6467A647F7E679E6C7D146BA3071C18496307D2DB4CE99FD37AA1071D740ABE2895647F286260874BBE8C609165131481CD81E4C6D98293F1C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A14BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F71C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB62334F4B56AA20F9BB57C09EBF41BADB20D36485AD613C790428C382B437866A681635BB509C97D4AA12387C320F6CEFD1838459F0DABA3DA54684B83E3ED10C07B8CE62549A876A13D86D8F3D001504D939500462E64C94B6EEAEDDB8856D13AB345659CB16C8B977B6670208B70920BA34E31E6A10EC724CC6FB3C299ABE890047E1F6B3D5A69BF731EFE803088FC8D3B9E69DF3102AABBEBE90C3EE20DD829BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB714212BBF4237C6D69B1D61531257FAFB41BCD74462C292880AA396FDB392A42C4AAD9B5492EE4F2A076CEA42927C22BF7CA54FCA135A0FF512CAFDA620DA75DF70C37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B755D1BA8476CF0553AA3B5049EB57DF8F00AC5DAC2C1DEF316793E5DDAF9F352894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779A89119240A8E28D1D44AE57D7D3252B69192353D745AE1C066DB60F6C6E82F35854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F04615F48FC178E8CD389A2DEA13C83E2534271AE7DB54D7C89B8714666381C388D37BEC8102F8497D8A820C70C47254582C5C27D3D97A6ECE379315D5520BA346E8F5B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E07949F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DB9D6E9AB3A0926402DD8095AAFB46217FC41A2E0D7C5960C1FC814E461B1F1F219CBD0A97D50180BB017229AC9F884896F357900724A3A7A8E4D479CF6A093FC30778F755C63CF618073C40F6042FB2143DECEE8DC32CE9D3E0064EE378F78B8F945A05629C118D60A6AB5DE2DA55A06B7325FCCEE42C01A5C408F0291E3610C44684BE1F66D3FB8F6BE43EDAD2EA87FAD50C993CC447DCAF79AB19DD406B20974363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D024DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA1678158142C023B3C238A93F3D1CB8E48EF84C168E27E6645DC6DC6689E89CA0A74D07087B760743BB526662636725B7FB700BBC0B3A73793C291EBBBCD4970B27370C2E85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B780BF58A5656928CC6684D80B728FA0C1570B8268DFD57EC9168CF7D39997BC8458A5D4126FEB278B26769C4F55EE77EBCD778D00F836BFA6EB13307BA2D7417B0812FDA4CEEDA359BF73865982622728D7EA8BAE1620A63483DAC957E4F8E082588E12FFC57A2871119AED0B43DE4ED1EDC4AD6434A485C64D9FAFBFC7F01A8793E5649BF33A7186BDBDBA5DFEEBCC16F2CCB67E355774B8C32B932119DA7158A4D131F560491BB42B47C9EF1594FF6F09BF29E972502A7D62A2240FBBBE55C3D82050B374EB42E433CDBABC163A95A6492A7F7DA6824B5A20527C9D0933B97C753932ED9ED277E40CCB8C4A042FD5B88E9C5D569A48F512ABA1DE68C821BD20C1A995235727654ED6E59B063EBA5F4046E7D047B886A22A7D7C5BE009F3E14629FFB78F8555B7376AA2B7B4B360F0D3C295ABC2590CE1AA36943A46379C1085D66FFE0DCF3C37C89BBF1C7D76B6D62D5D2D265EAC52164E4799C52D9A7E67836B66532608870BCF43815BA0633B82CF8E92FDD0A4DF829039370202BBD93541D4D398C42900F96D70AB85AEE46D4AE2CDB5BC61B0E57DE8AF9BC4A366730CC4A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349E9A943B50EA190BF7E28B4406FC4B14E77203739F8DF7D168EC43FE06D0645ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC40509461C2CEE814F7E26684AB01D51A1385EA51162E9CE43172A1564809B328A45AA68BC14BF38692467DE23B8908FB07BA05C90DD44A372477233DEEC84BF89287B1F8E1FED4F275FAD98265AA76F0D798266081567140ADAF2A9C64F41E053D1F329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB03F8A842A1FF048CFCF92A8D77409DE43CA455C5ED59F89358559BE214EE1B531915180697A948C945A9924FD6864D9CFF00E1D47F38B54092E4CFF1F92A65CCABF206A7D71F25A66969E37EA7D52EFD74B80E93CD7A048F71EDDE1EAF82A24F20145528EC96BF1857E0F1D8F19812EAB34E07D4262D195D1BB4D20FF3E226C2468B90E951C8212023248340ED5B7E4EDF3C6AF6A6FEE63F8DE613EC6F1526E3F6A9327A17C2279BEF50B6CCF1569A86FA56DC4B8866C365DC5D16B9BA888234D6860885B2A420401C0E3F8A971BE2CCF46FB27EB58D6C8EDE207B703FB7EBFEAC77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981C93D4B2B08DD6DD375D4C84791CE66913FD4E3D6B01287F258E8EB01A223CD222F81B1412BAD3DF60D89E29F4FCED352A1DC0D52A296D6D8145BB66BCC936BAC362F309AE4520552C369E4BBE918F20C4AEDF8F037EC9AE0A3BE8BA1BA0CBD40949CEB55F41C8728AA639789BD51539F1AFA46F71106F428C9FC659F34F6BAA879DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA79EB4AB02F6134488DF1220F8FA56D2C14630DA6F79094DFEE7180D218C621A32C153D6E5AA82C318BCBEC16FD901CB860793B8B3E9E357D0F008EA80BADACA56795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1DE1A2B10D241ECAD1523291D88D5D0EFE1D5CA4DE89F22AB2605BB5AF0CC6564C2F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A0FEBBCAAE5A19E133CA77B6C4AFE98FA12CFEB1A87D38463C35DE33D5B7D2E08C3DAED2A32A25502AA2B4E2F2A330F06294E202466F0701D4B361C71DB74253ECA3148CC5E1119591830C19DE38FEF1A5F9302B766F68E4E6616611EA940522EE92E6625C8783357799CB4B9F6A56A84976EDB84939B94A676D4657DBD04F7D754A901CEE47AFF04327CF6E0193DD3EF8CD61ECAB28CE8CDE2A56ED422C47BBD5E4B1C005EFD6C982E1601461DFE8EFF46797FCA8B79156473C7A964515B4A0B4373513F5DE44B5088663F1B9D235681C2A0F31675B7BD215F95D42216FC76E5C93A2C8929163064A58FCAB39F6A8700820BBC9EB62588C0377C15BD74E5B7E4F11559E54EAA502404D245774A51F17A9CA804C570941434AE4464CA23D8CB2D042633395BB951DF71EFCE0FEB7AA66CB0EBC83321C73AAB08C45F89D8DD625753795B7BDABB1CC042A4EA7BEEBA6AD585ABE6849B63C9630142B7191742C772BEDBDA162F8B4101824D6F16D189D65446852A08B37F359617ED6B0F2DC1A5648983AFC78D3D4009BFBB088F85D85B551DFCB0C99B46C65130CF3A25EEA02FAD2159409FEA41A7F3BF71F020CE618D82E4A2D5DD005E1E8839EF6B43D864647D89502AC44A7517F0D0E9E06BF9F55BE677F11F7A4689D51E5DC4892181C32AB56A831AD8E8691C9DC7C8D59FB0098C7581BF682298C353CAE2242C7BDE5F5933B48E88624CFC605A87E401D4B01FCE73BCC86D9FDDE138A185AB4B79B2394FC0718A30D5B8FAB24C2A67DF7C57690E380B21B9BD08674E49328286D6CD82FD782FF7BABEE169FCEF38BD5DC8ED8ACB324A374F426B0D835A5A947627DD5D026DACB3669212EAE997EFA073A3800694A8470BA89780C06F034BD1ACA26229A7C13345B4514B3C48A810C8A017062BA454688349B3244A3022F86EBD132636D566A899C38D183C149E8C9EE50F7F254409A4FA45ABB9B74750B0FFE552845BD460BDB3FFBF6259FA6D048B59198B4FD2B135A9DD870881D24109F95CB1B0857B395683A40C358ADFBED50D70A8FA540F6006D2493B59AE4BEECC8BE3E70396BF298B2F49B468B64DDAF12FD0C594DC243A782FB8862B2B73BF1F59FF1B812DCE96AD72D73D928EDD5D6D384CF214C7EBBE25676FE612556461D465BD1D1C8AE96BD8F349371553AD9E9B80623B49D5C8C38489415ACE7DB17DEA495DB1CE9B68AE228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023C8C898A4A7D16063A2F7FB6F6C00EBEBADE4B5A79A9814803CDA526D542E0C4C44DAFAE06659E810969F48EAB6EB002F7938B62157E85E1BF258D2B81ABD9195EB828938D84BCD92C9793BDA17DCD6ECB92068BEA49626C4595EE621E192309156F9B0127FA44454075F7C73A94992400B22CAB60A056EED2E04045E74494017E601F044245A2B64B83EA8BFEF2A02A32029224D3C9F5DAE64E4A3298688C1E4205FD9038743CEF33B08CD9366560AB57EEE937008332B6A4224476A759B07D04DEB016DDB8EDF3665BA71053A894F98DBEBA95EFEE3F46AFB944601CC71C39315012B024E672E7CEBA843F35C6F435983AAB0F14BDB63B2D130A91AF9F72CDFD73EA39DC02AD3074F0E4B3780E81732B550B298998169B1640D80FD56474FF655A233E3ED6C48E5D94A4C6D31ECBB5257DC07F29D5A4C98177DE0A4DE1BE24D2CA3CEF4DD2A3FFBD818E75023732E1F1D3F9051AF6E8047081FE588E2492E5EB4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F933819140A786527AEFC7A872908B98E8356286485E2ADA68D8733129C32FE7E0D0B7AB63E890DE8AEC5DB2D52F88D328E1DB56FF586DC2026817A277844C18228D01C4A792C6D27D72D4E36AC852098685807B31A411B62DF550CE9C5080F1BA5CEB1634B8EE7CBBDA91DA660CECF740A502064AF7781F544A2A9F6527CB431A33A905262210B977C09374F03C360642BB200F00F13EFCAB19685DBAAAD7EFBD4D42A8B428342F44A61D9D58808B9E7620ACE2D4FA47D16FA98950485E67EA182414D9C7B78C51CAA4960A79B1BEF4B6BB5CBA79515042433C7505B5038C4DD0CC8805CB9C1AA93B2BF96402909E229C46A5C2C7CB18F0B7747642714BF204D42A8AF263AA6C8F1DED9414FD0E6586D7B680D4BF1CB6CB6DD90D63511150A76C2C40384A4F156E827A22D0D207611E84477254E492397A85643BE2EFA36371F9DF6119813B2CA7F31D099B0715927919FFABE384400D3AA0869AF2E95B525D9A1453679B1624C4F2718AF080BE493D1DF583843CB08C5FAC4587627805AF278A009530F8545958E7C04ECD445240A70C6D0450DE5A3F3CBE710E610D8EEEA17F97381119B8A53A62EF7F4B0D8F84BDC86BCA2245664DA120E7E36945038F7973099B1ED88113E6594EC0CBE05B5CF5ECEFD58D48FFE4C16E0F941FCFFFDE6D3E584584EC8A03AEDB6126EF5F479E4FE8C97BA01A4980F78D12717DF17BC4E9040B105B2D74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7566DC65863A7E07D0D8774305019C67D504E7FC4DF77A8821AECBFB762EF377DFDE75F24A9DEF9CA7997E8F4AF3B4E60071F11DBA6303A964B7F9C3FD443C766346B4B1E50EA1D79357CA76ACE991F4760184016A12C2368F7D4E6BAF0C8EFCF4A869F3973B41564F52D762BECBC7FA49B40D6FCA22052287E1B10DD8FA257423F984FF4CA38BD49F322C84CA37874056055B3A0C51060360F05BE3E1DA6E1829B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F3171151E6F5442468D000FA46F17DC7437B058242696056ACAAC06AF22742452798DA226D91074DEFCAC6C3D770DC54CF7ECE9ADFEDB3B421ABCD9DF305D412A71FC77801FAEA989C03A0D633C4B06766491F4C0DC67FF8DEB16AFC8BC7E3D41601BF7B964B91A8638DDB7CC08B68691D5D501B5D3D72915442F0D1B9EA4DE4AC96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A3928351163E04D8BA817C168A0CE68CAA6FA744E7E30A2670B2BB88F27810C887E48E90EFAD40F9735B5767F60EC515C146D56EA534C970E04BDD10302D85A2317C478BD195FC93499C051F5AF61A6C5CECB89A1D67BF5BE2CA7EFBDCC20B884597EB2BB0799DB9B86E2EB8FD93389AB91A391F2D68A057FDE361AC97A87F4406F40A7EE2E7709E46DCD756617DCB0DBBF43E6BD4851F3D834BB53CB150D2FB7B +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-8_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-8_256.rsp new file mode 100644 index 0000000000..fac5a0f156 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_40-8_256.rsp @@ -0,0 +1,12 @@ +pk = 00000005AF6E11950B411D09B02C47AA513FC66675E96AA47C3B284279F9543FA23A226804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000050000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94AAF6E11950B411D09B02C47AA513FC66675E96AA47C3B284279F9543FA23A226804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E704000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF54961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019C1A7BFD8300283215BA57DB5CDD95EDCBD04E1C41419317BC2069C2AAAE22130100000000000143ED646E32FC21554D8DAD350C5732270CC220F7E264ECB5B7A8E8A4586D0CD002000000000001762D040EECA13E137753604D099809D946063368BFE1C7CF0E6549FCA746F7C6030000000000015FB7406F1B25A2B4A6A1666269772EB08D6FE78D8A8395C56AD80FE6924DF082040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017F7DF0085A4DAADCB03AB4E8241B0E6DC05E727E817C3B6FA27F05AE1FA2DE1601000000000001BCF2F650C31EFD6F2F09775A3B4F87BBB33AD0D51537DAF37E0D1C1AE8BE8DC00200000000000174F4FE7914F390776AF328164E738CA8EB0751EF9E535BB1B0E80B05762E683C03000000000001241535B940156367A4ABD922871FB10B37235B67CA38CD8B2B02AA8064C5CAC60400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186A69EB284CFC56C72C2C83351D5CCDBEC831992175BC2D2D91B3F9378E0DE9E010000000000010A318F954C197DF2DF39A85C4B322E7EB1B16B0B4EB8C8A492F4F3B904C47E7602000000000001A9204F8E84112663772797AF87ED34C559ED4D6D37E634EFACE6A18C700CD53A03000000000001D2E20083FA11E157A2E5B72C9A986D3F47348E54C1935F48A86F7A9D78B2BE600400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A6442DC6DD49889C3DA3AAF0FB310C3AD990480EF12059DD23AE881D5A72603F50C7C61626AB2E0BF9C8C198CB0F637EF72954E04DF5956355147B5073EEF3848CE65EBA73E67955A1CFF187CCA758372FB67823E230B05EAA9982488E8D22F6DA1415A731BD0A2B036F858FE16FB4349149B507D9DF770B9F3D3B45ED752EE888F40FEE65C4F3EC6897906303A19863DD968C666AC1980F26D8B574D5A16C95000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100132C90901F97161C5614019A534B035942B26ADCEF40AB97BE258B03C87585010000000000012BB35E6F2C4AE0A3430CE207629C011B30E4C6F5D6BDFF2AB750EA0C69BE95C1020000000000019CAFA71D2E43D02FBB0C55294A6CD0AF3AF0816F6E6D1F4022AEFD413DBE8C1E03000000000001943191FF197E71722D961AF04F9570BBEC438A6D22058F1018F6C61F3CED67E50400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000290F4FE6675D4A1FBE8A93A91C6B09B1456828554CD0CDA039569E2C08430C3481E2970BA760DA29C31944AF18085694530E8A952B54516062CD9528A95D0772323B4B8E02C7DCBD71FFD2236E772268E25F6D4C622F07F5D437275B2FEBECE7605967771BFA2007FECA33154FB46A3B788E9E7702F38BCDF175EFE4611B61147D89195BE90840FB1E365A76840BD9B40C21949F2D41205A491C019B7F49139C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012A13FF51186CBFE9467BCAB51417E5129671EFD5D0D686D09E2C5BB683FD45450100000000000184D0629348E528473585F873A1929F01BB41F19090B770D155E497E4AFF30A990200000000000163EB4A114558605E9DDBDA75D10B78F28322197D1DF7FB4214438DA12328F8F203000000000001B86361D142F7F14ADAF4EC3E307CA82B6106FBDE3777E656781187D3558E3E1F04000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA7285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909D5F79B7F944D0041C0130B7F59B0ADCCAD97670C92355CCC8F0FE34612A088BFAAB33542EBE8F3283AD67A79EECC3E7B7C5D4CCC29B6083AEDF7AABBFAC8281B7D7711DED8D4CA70C383C5042272379356BB80EC0A9BB8E4F1C73F2D2DE1676BF5AF43AF87AA2B2C4A6826DCDE46E599B2F31E9EA87A816EC5D8163952A7384603C8FEC20F58E1AAC52188E42774382077A35700EA5EA2FBD04135593A7E40ABA137FE400EB63BAC7F417252EF6AF6EA8FA9CB3BABE7718FAC4A756702AD64BF1F912E6ED44DC6D424CD15D3E45BC9F86ABF7CB2924D7B4E8AAF67D69401F5609B17D251140842D7A94FE5D911BF2FD37418208B716D2DC66320743B79E64CDAC6F2257AD34D112E22F977AE6034068C0E0F089FECA11DE03396BFBD365B1A788B2C550ACBED3643C1E4F13618F904B40031CA9E73F9B13293DC92102B33FBC16C9CDA02E511D49394D5DEFB95770E5CC750801623042B7113D385E8BE8FEDA1D7F9105D545B18AE98870B1326494F9BC31B33EC24CCA7CB8E53F9AF1A7E099B0D9A40CCF40B085C0D406B5F1DD7DCA794345FF98F272F7D9A11C30CC5448D2D311502B7F0F81437B52EB11CC5FF11C1FD62B9A34E2E102C5C59D14A3326702F6B6862383B5BA1041A59B2F4E009161857FEAAE3F0C4006926444BE77169E9963DF262BBACFC643F032414200B26840295326BA1983CF450DDABD0DEAF05B3AEE35CC029B1E67729517B6555FDC996782FE0CB275645E739BA0BC75A08869998C082BF6680E2DED0D643F06EED3947CB24E4D240CDAB6B07EB71762DB159BD8E8FEBFF190763906FAEE1D307115E7D6697AF3DB2192D37468806FD49ABAFFD157647B652B339A8912CAA3730EDB23593BE64CE9A50A1622D43538926E5B05D878029C5AE57DB40072EBB7889423A948257F9E8684E5B4F10C09A22AC506B5105246ADE89409D3AA78C4A88181FD562EB714E9402F8C4AB2129E73FD77BB64F3F6752E5AEEBC4DACC209D01A274E39A84857736671BD0604C153703CEC940CB0D79CC433D157EC5004ABA2F359B80DA9FC04267584B2897B594C494883185E613283B939DEBE0F324B3CB9F45A6FBF11AB1CF2704C5F83BE3B8CE1C38663757828909CA4AC49ACC134F533F5DAF470EC30D2E8FBC66C9B6C58CBD2ACBFBFA2842E78DEA2DCB820CCCBFB17454EFDB2B1D706B93B0254B3209CFFECDA9F52CFDC1CF312EAE3035C1A3D75D8764F693350C2301864EE1A3797F6574AE38F66B40F82904FFE6CBB34655B99959759EDB652F6A3BDC1D0F24E8EBE1761B43E876A6A7AA29E8B1158F1D150E25A742B5FBC7161234A85B35803FABBC0AEA40821E9990D48BA7EF7E1A50178ABB3CDBEE228B40C8B02C98C5E8B70CFF650E570988E64E6F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257302026A4B5934CC6A417A99706CF783722DC2663F469896FF8EB4CC741D531F3C32B41F0BC6DCD4A32786747BE120B33718A94639FB4D754E0508B0315990F31555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE94149EB3F4A4F9779A1AEFE60FA343AC04323795C9D33DE8AF95219B8711B1168A107EF83062F033203511E5663EFA0C45ACF54432C9D4EFB5678332B5E164092612E42C61560D9EEC768594F4E0E6AF10AC7B3DCD22D229AFA8C022EB00AFA626C63E8E96B72DF979586867B42B8FEDE446A0F6807F1F1C775595FB5DEAA3BE2A45570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41FACBF13EE45A1F97C20748CDC3B4068D993D944D5A165FB858FDF4FBF88632FB826103B1276C7791C64195106635996700A71E299889131E533F7F060C7F96E7C54F02D2A32835106FEBE6D40CD4D56B57ED26A7431731B04A78CB5A4884F0CACDF007DA6E1C4195B2B59A53F31C48EF9FC33CC7F6BD147032A1B6313C7EEC43B1E46164BEBFEF16FADDB1A176FBFBE34DDA7C88AC9C1EEFD4F33B7960D847872B8B433AD5D1293EA480E6FA097BB9AE29A7C0270A062EF9BADDD796FD8EBB1502606E9262357EFCBCC9B7343ACBD03CFAE6907BE46BCD32C4C4C4722C8D3A9EBC76EE4CDCE71B049D688C42104B94A1F7FE6F945BDD02E3DCE0C345C047AB31E7E8051ADDD3DBCBD33699AD660C1CE3E25D203C4EA56368B19C77D498E67CFE083ECD3D36BDCDF29A148224623E0D70D060EC964B329186162C1567F7E7B5B6921CAC8894E88BD8BD6FBA1E8EC4081D35931ECA2BE1E72E32D7C986956EE9CFB07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42E63C0C23B6C61D15F2C9FFEE5663E3CC74F7400D0645219751B70C916C03C0C67159F71BC0B3BFA0956F026B91F8C2419D671D3E00D7F633DBD2DBE88126DEEFC7733C2C926D1D8B0C8BFB1077A700BBF3892F0C4F3E30DF78BCE0A340A8F98EBA5BD384684D1E0081C1237440B3A6F117178C0DE4F19D05D4241240924D9EAF9CA45E3D4231AC903C8EE5298A3445F01961D6D3786E36D24875E6DF3EB1D6C1BE5EEA0E060D3E0EED1DB2D4E795D35A0DABE4A745764F05A858291993541AE149CECC5147FEF0F3A96B42F38963B9B29466FD66AD46CADA8F10E2D53BFC3B823CFED410147B5FD315FAA62ED06429D6D3FE6E5778A64B5C9BB06A8CF5561EB7A8B15838AA226DDFCFD4C31805D53A6EB7D2DB861451027CF84218C39078756B2911021C3EAFC2E82ABF792C5012CFCA3AAFB0A277A9C9E1E515CBC4439D95B2A54510318F5D6EBF97C8DE2AE0D4FF669493AA354C25460D3C15B1A57AC53D7E6C07CA407AB1EEC4A366A637AD4081F0343433C555DE72B71ABCD8ED3C043532A61125CC3CA06CAA634E5F75B750BF262756A57E3FD235FA9EF00CDD9553D37968DD680EBD5935FBDFE43A82E9DD39F96FD483AAB7F2D0517F23727E8F4DACBF1442D207EFD647078CA9CDF7800804012D4EC23BA14C99666610A22DA87523E4E5E41A6698E5235743A9B9E1C4795F38AE20CBE5C3A2111ABA307C3BA6E03F092E96AC6EF297548A3F144ECF7F643EF19024B2E98B51173450ED06ED68EFFA06EFD60721E73C9C6993F14C00E3E4BE441791C648110F699AB5089D7CD092AAD82AE007C0C3C8659506D5F2817E75EAE8B803734822A2526861036E35C3689EDCBA348A7A2E4BE2F1E291F63473988AFFE650C1BC49CDEA3875DF4E6B541727B5AA6F04C9C1E4D06BC5CC744D1B955958E2578C6176AFD7E3262CCBC0F6FA21596BDC36349BF9329BCBA08FFF934E31DC1FEDB7D7F6B459BB1A0165043B902D600C447792A618B77C1671E5793473DED54FB3322180F198873E306E1F8BD17BE04FCD3CF4D6A9201B9B804BBC772B742097663C42F0FEE3766B3B205F14A39D6ABA56963D03DCDF538ECFB8A7AE64DA3C116BFC09506BACF5E8B5754B220F7CF70C5AA4492AB72D20CF8F4966A114833B057662EC63B9570D9B2DCEAC86590569934F91A61A03E18835E31ADBC2EED3BE0BC148FF004675C9555C901B280BFB56FF8A1C079E1F290C67FD1B7E53A6C27A5C649ECA9EEF836621F9E708EB84B6F5C529ED2F07BF0A6160154F41F323DFF8A498177FD09D22DB15A273F787529852D898A6DF0FDBEBEFBA3F3B602B1E67352224860125216AD6D68CA891606E179FB415DE4B95484CA6907319438F69337316203F06AB1488A471924545C81A470D78E2EA29AAF89E94920AC4B0E7F2FE01092BC8CF3839480A02C0E8DAC1E864C9BFF5CBF46C0FC7B6A01FF0DBBCF96E3585496C392C6496D06C44765878B26B6DFF2C2FEC20F26A9A2706838A2048E579C65F3BDDEFC58C89D8830FB8C75FAF96788998DD200D48189C3B59B41501BD310420DB96F7CC5B61A2EAF88B498ACD890F7DF623A35479472694CDDA58C000D9BC04FD903E4AB88A2E757700FF3F460F075F9876DB3F76F17003E01DC96A92543DCDFCD7EFC86A5C0DF387A50ABB69953D6DC19A699CD225941F82438A8EB7889B212F65ECA7399F89CA0D9B9915E827D2E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC876E4C5BF248F94C2ADB3D6C9F23C3E70D1F611A2041C7759317B8EC1696B2632CA10CEFA498D7571D016E102DAC10051DAD086BEC58AD5DDFD7988C5F433DE87C314E3930FFF937A6E0C81787F04B77F893287AB63125CAB8B7460F119D03BF3076A98FF029EA5022201DD54C854711B8BE718EE678544B51AB13B7ED0262C8180C2F36CBAB64D862D38AD7D8172AD8BA3380706D52048826CAC611B07468967CA4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F238380083A064421DC7CE13EC2F715580924D9B6EFBDBB0D45AD8952F602BDED6455C0BC2734CB135B79966464546A261D0A551DEB43E5AE111CD02D0F2F2E996454DE17B471C6103D851CCE2E1FEDBB828C7F4EE66053A57831C708C377FDC6FDF037F400A09E9A610350BE6C013239D7F1C42758CA84B428EB06C6A6A3E05F10FED769CEE2D8EDC3EEA29204605005468B0366B2E957A7A55FBCC7842598F55021E58DBEEF44C5313226E6E56A2D3837F2A098C94BEC791737F355E6CE5643C954C4719C6C1C939B7716A29191CF0530BC2E78CD028D526EC286FCF02B18A077C86BC54F078A19A529F6EAF69D5562D4B31E4CE3B953A24655429BDBAEB5378C13E5B404A138B2B5473A415EA236245B0541B6D92F384D4CE63680ED5A6C035FFFC663C893C8F51C5DEC6F90D33573A05CBAED63B69079EE77DBDD21AD7A778B37EA5E0543BBDCD47497F355B1B2D8AD93DF4BB96A5E85A2344192B782D54C4C8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D947DFA8260661FC9326B9E76214D36B22172C026EC12E04ADE3C62D4E957AAAAE686D350793BC6E9C862D968C0E56B3160B5C70520E9AC7767AD2BD8D1D6DC951A23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831EC44071AC6184AACBFA0A2326D7EF097650C1D4D1E58134408C11E839A0DBA17CAC9DE3B437E697663AC136380D0690DA4A52070A2DC552275BA09C01B601D55E97AD7DE83A32B962D0A9053C1533600FEFD1171C638A50922B9962C195551F81FE80BE28342A13ED0B25FF8986E0E9C39F3C2F29B9F40AADF8CF61E879A7FC863B32F02C5B5BE16F0E2CF00F30E312820E84D09BDF073E0B16B1F32C73F0E6031DCB3221DDC48670D0F2DF9A8065BD027C30DCF9F12782C812753F109615828997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8B28262B6C82510AC69F4785752AE1F619E3D334170A4ADB4DAF3138AE90AAF8D82573E7AD25A16243E16650219C47F4CEBE6915B433B0ED0354EE62FABFD3E118AC777A63316637DA755A99AF97DFE9857B2F58A83ED70041EDBC49997EC93C03A7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE458A65E6B9BB209359F7FA47B95EBB79C83F329ECF88C7541446868CEF363218841F55D346A2B714DD48C711555BB25B1CCEFA6199A0E7646646B667634E486116C0AAD7E977C091A5EA356778C299EFFB7DBD3232C4B73B54C796BD1E33284CC8E4354C772DF1CCF762F615715FAA903D1551A67965FED6C7E1ED7BABB9325AC30F92305FC284724C59079B11D1A0E32F4665AD8390B34968D1885C9EB8BC5DDF63D7858E042CF7C66FF5E36365F1C7156C79CCDF596EFA551E203456E5BB22C2D9B742F490824B1D5EE482F335393E34E69C7820A639858C6EFFC2E8377876E461788FD2736A2D1BAAA432B008850BBB44FA193DC54757D8C75760638A12DFB614580A882EBD945716D7A3D3D29396D4A0D267B07B035EC001CF29C87E23D8446E21D604BCAB110869FFA98C32E35A9B6C878360FD7BF8D564B09384D5C52E0C9BE0F45E814C954FBA214F3D3089AC4D01ACBCDB25B9331558FE1D29E67628E13BFC928F7A9A88D13E0759B77674C3F2795CDFE0C6617022F9C6A87B60C4B5A69E8D1706749FB0B4E086C94B5BFC16CC3B34FF3B7EC227A5CC646E9A003E5D897871067191AD1F8A8C33A0E567F4DF2D91D00FEA00B152183D202BD72DC0694F16ADFDD6E44A248D80FC6609E601CB91EE691C4535CD80BECFF9F23F32BAB5F106234A8867CAC0B5269CA2BC588E48AF922B5917BB6813E9D1005F35CCBFDFD419404B59A84497BCAD743384461F24267C497A932411B690BF405A7ADCA63858F439B123201F41AAAAA4D0A478101EDC6AD214E025B5DB6D24021464C53FB376503B6CAF4E4D4974E072F8C88A7C61957239581B589ED8D1753844ED928642CF96E5ACCA32E69B52CFA3AF54B9FF793E7553CBE16C4F9DD6114D1357E539C238AAA4434C5E540AB31FA584B82AFBF419DC51D6B08FEBE34B7991EBF2A82FF8E94990BFD02764F7D1DC049A635A08B7BFDB46A521170B6B8BD940883CD4505224D9DF930E33C5827E303083CAC4F846D9CB9A6E3FF57E755C7CCA541DF51819C5A52BDFDF005217000967A2776F51217813B2FFC509EE35F8AED6481BBFF5D5E61732BA17C90FBBCE1FC29E8DE849C146642845F982A2F766DFC0A703B5BB612E4C2B8CC426BB56196D714FC6F1BCAA0F19F32CBC06C3DD1406B591D2B0CD0E834D003CE56313B66C224594354866598118C87C1A86F7D247593846100395EE6303E54D130F91FDF81D0DFD021C274AA9567B9F9A500F35507519BCC25535407E419B52FA4D9ECD3D53F467B6295505DE979CBF6C7BC909812265ED65B30269FA1500264347FBCF1CB34AC5A405F208E73DD503D0D0E15FA474802F273C76C3D3DF98070BF3151D5D338DB368DA0D2280BD821880265763EAB2076766540EB9A51EAE647B96CA4326C82626DBCFCA1B3FF6DBA63DD64AEEA6741FA49E358E97D8F60C7F1A56248E8CE18933CD6F850E667134F69176DFBE2A4FC259994ADE12676F63D483FE16F7658F1003C1561B8D46FEA0888D2C82A4254AEB9E4104B9FBC973CF836BCAB5E263240ED9D87E9C434DC66E8F4A7B73EAEB30BB745F4094A4B82EC96CF99219F557ADEFA605DDE957CAD9D5343558A9A0904575A7A954948DC927E71786394DF40E9328C9B4382CF4FD8423B97088BB07CB4B257E5AC7B817088C3A6912441992153D374D477EA4EFD21C9F706D3619634AF7DB364F5FE73D12FF9623B665980B98E83991215E188462A57C4B3F653E11B4B1E16522CD421105A1FE67AD0F58F3D4AD34A8BDDEC13454EFD5FAC6146012476391769D4AAD22B1A0BD1CE9599600EEDD95DD265C4640CB064F92C22B0C45C64FC411375852E596F268EB415B03DA88ABF9A089EDCC5F06ABBD96E1BA461D4DFB3772938CCBE093AF922F5CE290295EBA2289660868ED4B6AE38B28B1ABAA06B66BB97A5396218691B13D099ACB89D6754517372564CAB054763190677139C9E2F0BA2FB19D0471E49BF6A0DFF2F951A414ED5D0F17C729891F4EF658F19FEB6D31F0BD8EC15DC9F9CC1FD73BBD7A6CA326AB06F55078D4F2F90CF185849567E8C78F2773938A916FDA23279FC3A9D62CE3C3AAD309264EA076635487EDE98CE79ED297D1BA99D96C84EB712CCE028298C8BAF5B5CB3EFB2EB8996EFFF6F7682D6EAFE498B886FFDC157AE3995D8493BC6B51541BE6862B41B5A35AC420D4D120957AC00B6E488AFA394C5C3F99DEDB4BC4AD4127082E44F22194654D3FEF9CFF3AFA66A764864D8344939255F4BD77942D6B2063FA9C0F82DD3B8D9ABF5C633B6CACB152AC09B9DF3BD12770444F99843FD913E2C815368910DECDB46DC4E13EF2E89AC3FC7D13749B88197F633BB6044E1EA0FF4CE060C7F426D01D0CE94833304CDEE3C857FC7258DB654F49E7C949C4D4B2DDD689DEA7E0C526E694B5EF77F8DBCC199F73D833C54C6C389C9C63A9E203FDF4389D83A4DF4AD86D7B36D3847C8DA829E04E31BD81791E403D6098AE9DA476D75B357A74FBE2F0C42FADDA27AC72B653FD87A8D1D72E72E2BAF5D852D1FD6DE10D5A6A600C795F65A4A59A00E2C503DA0BAD2344CD62FFFAF6761831AB2CA4055C18294DB1CCAF2BC6A13DB522CA1BFBA9DFCB930E4D6C32EC24DB5A8D5C15398CF2202878D240BEE11756559F26355C059A81765FD0D993FA64887D5CB6EDE1B379B2B8B5D5430F3D7A6ECB8259220DA7C9106CACBA69CF6444192275A2C6EDC588234E8D24985A0770607FE1C4AE8CC7559B3687522EBF7D3CEF0E19B229509D2A247E8650C3676B3B272340EB71C69064FD3CE931406569E7AC1603E49A13BEA93B2892704378ACB4796CEA77687C98E8AAEC3501143271E504408CA5D7ED271C45A1A7637CFABEA8EDFCB11DFF3F8324C8C2C7D9C73A26B8B1C05B6F18013E03928FFFBBB5068FCF4B29FBC21A5819EF85B91B19A5098883EF40D91B7E287749A578E7743680786FCA565BC4D19AAC06BF70C283E7649992BD6BC0305A0A093B75DCFAECD7E049E16F274AA9B017CAF3F5068FECB55C6FA6ED97F64E17CF1CDDDAEDB45036C6B2227A0AD5181AD7389B72C8967B8176E18CAA3506BECFCDFFF15B598C47D10E11E65D9AE8AF9AFC8B189562D98BBB02EE55D0A5C41EEFFD3D6E8EE69878B3A003DE7A52A98978892E51219387C24BAA7A773944F530816FB27BCDCA933370CB340781A70DB5724C597F72F7A34DC05B732FEB79A18171281AB7A94DFCDFC2C96DD00784F2E67D7E56D0F146F1585EAA1448BE1CCAFC6F334CAB07A27E524BEB95E19D426689B900176A70B21E32278F27EA3BAEE623F92B14696CFB1EABA0D90EDC414FAAB03AC0572B4B8836F071A375849BCF46E83A05979A4111167CE5C43F6FF48F386E3E8F92FCA1655E3ADF4C2123DA2C5551E252E9BFD93276B5B2BDADBC8F23C0406875614ABDE72C520002AFE6F55BF1D19ADB7F26D4F71842FC66335FF670C60583CE65DF747AA6DB218471551478BF36140DCC5C6B9AECD22944CD2B781A240C914D2BC4B37877709794CA33ABA878615050637B0A0B3F04DE2FCF37A2442A242E6C97398CF483260BE8A092F998EEA5FB5519EB25BB10B9350AC7F6948CE13DC282ADFD3A251C07E32A25A8A93276A563755B3164C0A9510260425ACDC093CBDBC6C8C5D0FEC94A6DDB415C80D45BF9A6D8DCDA606E3204EEF6AA291AAC9AF7122810A77E0E1160A461AED63687B3C137EC40897B972493F33636B2CFF07747A394747C0887C0402CC4F50E78F70785E5DA4C6084BFD7AE379F0AADBA0CBADF8C70C34FA7A6B0C14F32D52FE8AC726F750DDDA95C741131C7F692CAF7A3A80173479690A3CC0A93D1823BA1AFD5634A9D14E17E7858221497CE6934D7630E73D615127209FA239A190EB60B4D49770A1122DE7ED76708CB660EC4E52900D130C9A4638448CBFB16B1943D7C007D521F945D00D42CD0AE51FA89D5BBB9DC68360C2551D3A0E08CB0025B061057FEA0855305C0F6496903EC94DDF067E722AE07D06AD5AC67A1B5A9D1D036F4D157220087AB098F2C6A911F710332AC3AF782A6747B8E079F12A768B9372BAA222EF43084F65A46EFBDC5D8BE794084FEDD23BB2BE82A7FD1C5FCCCA0E10FFF7CD47FE805A43F82E73773670C4F43571767DB9F9A59A16B1C6DFF3AEB739FDFDCEE27D8699BC080B9D5973F30BD546DAC6DE594F91E5C2F0DF432099D949C5FD0E9ED66BA4FD37F77CBBA8D511A0D712DD62859D6E3C0177A264EDC37393FA86D8BB241B13A2023CECC4A8A57242DA1C7BB796DB4B50197F8E7DE6FD645C6B9099D6F76701B0A36CF2DBC1C9E2F56AC8CB222D37682E19D33A1728916687BE117E14BC7D137CE28948A0997FD9B25545316DC91AF2780D34EB5D9A262B327FE0E57AF30D9299C1CDD7FF92E3CF8C70A9CBA640A71425B164DE8D2D0D78A19853125F684FB1E94D7D02473BF12C6537595311354BAB832C69593F4195132C6552176CD781A04D4293BB9E329B78AE8929A249AAC01C5C81DC46DF707C914E08A642BF4B0277302BBFE3950EAB036CEABBDDED57D2AB2DAC00B61474150F0F641A571573A79C7CEFE5B1E08C2A0D7C144D69764BBAAA9DA45E8C1CE02AD4BDA14E86E6F4509823913D553117C25BA7727244D0A5F4106962D2441C4D3813A780757E169AB7DA6FAE572D7CB919DF7BA028ADD524236473F8CEC4509FA954310D970F13B8F57505F248413F93CCEB0D2A8B81A3B6B812422E630863D5F37142EC8B03444B7509B92C2C46E8B7DB79679EE93FFC1DF1B807E29773C0B9A280334CD97CFFA2AEAACDA2A662F8767A323DA9D48CBCD419ACB2EF27A01A26F7F2968B572B679155717F7AE7CF17987EEBF9B088B153D06F88F683CD8A53B1D69CA429BC5D17DFF465377F6895611C319A8C8BC23438BED492817703D83BDBB93CD491EA8C39122ACD809BA158D5951E0B78FA5409E63E7CC69B5B6BC9BC56349CAFB05B71BD8C8ACC90F929F58037617118351CC1E0E0B3CC4040BCAB505CA4AA36C06277B4D550922DC424A005854FEA6EBE6C833980D3F7D49F38F595E3B156B89809B65E62B57E0C79947B2EC463027DE21FECA9FBEE0CD5B8EC64BB776FC95D93232C53A5A5D8F5954AD65E6BA6A3677C62497C3F4DD408AB08F2B05E00F865CAC6983159D2E4EB54EC0B89384F890E6033F71C5C888A9EF25C2E5563F4B79CF7F80E221C59FCC0CBA7A56ACA182D6A22A77AFBDD2209D5BBE8400605B918912E1F8268EEA13534E86FE8B6588ACF64A1322DFBA8990E280AD5A2E185DC29AE3AB7AEDEBDFF8932A21ECB57071D2C6207740AB48DA0286EBABE44AB1566D845A6B231073076634B6493FF5F4669CE06BB0BEB477C3BF2F9173ED7A36C22EB347036E7358BB62192E4E7BF5B9515C6A433D21E47F56C886AF92422741D1CA07EEB3A67A027283E78A27B64C89AC0EDF6D3CA5AAB03AB2437B7813BC5E349434386F00F0C0D592256BB28E68D0ADD1F23F001F2F0DC867BE42CFB316FCC3AB7F2ADE8F262E2F2A817435D72D2B9F181E285F7D58C2E9D0ADCA7E67933CEE6F908BBF182523A0367EC978CAC6373140022E3B851EBAE9D7086C4191C0BB856FBA1C5785F57A555985D0060A4BD79FC0FBD7798CE46C543B3D26C62BF07B7FFC0C5CB00729D2F9DC75A8A308AD312EFDB71DCF069034FB4F970969B749BD6F487F5E77627FFA00F64DBCF819A4F8EC0681AC3816282EC1717DA96444B3EC00B32B8C07E806988EEE0B8CEAF0CEED4F400F27F1D79267AA4BA333E61B84E6F10222FDEAF05D3561F5796CD819C879A07E780BAE63E780C05F024F2880EBCAEA6C1C8258D94B753BEED298829CF221BEEFF249643A4915D5C0E8AEAD2C85ED170790074EEC22327260470E99DD940227A671D56A9204224861E56624244241513ED4AC7117ABD09523C29C4F23E0C41900011215540597EC1BF8516CD28C228D03F8C7A65E4FFE575C6F5FB1F833B04F3DD1FE2DA3F983FC8A6BEE8CD7FDCFBB4436D8E8F09D466CA0129B4080F5C4D2A078B1CA2BAB5B306B26B4F75F49335E128D5E27B6FE1D96B9B863268E813A092C5176087562125530D23E8F6D61D99ABF133B032021530A5FBD7CAA65063B17304B76498D90B0F3E6541534667952F6B31A74394000AA731CD42D2CAB1EF3AD7AADBAEC7541D04E60B843FD337D7D08B9991452889376EB57FFC5D2D454B35DE0BE42E0B04E5C21D950E809C5D499AC04DE0E4FF912237DD83AF0FFC5CB8E520493400C91235F9D49BB30724098295713F70ACB57194F53B656D4B3E5879E2E28734370A052FE51C8139021ADD0DFC6D3D8491AE9C7C8E3AEF6A5C1E119D65923212BFDC35792BB5E3109BC36003C17100DF5302C7FE73ADA012B36AFA5452CFE356C38E63C59E80C1F3FAA1735150F1F3CE87E7008281D125FE7627B3D6C8DB3A2101DD6D650656EE5B8E0E8F0CA1DBEE12303499B6CECE8AC80111C504804F9ABF9C616D22DF34FBDAF27 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 18469 +sm = 0000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA701095690ED3CAA8519B752CDFBACE3666EDC260EE5325F9EA849CF9DFE6CDAD655B850B4D00B825B12E384E4CE8F666B543D8C8BECD261A578DDE551E6CF90A36003E412EE569DA19D006D0826FB3293AC847724330EA49515D4E5B4DC3E46EF7486B0A4897AB5ED84C95BF9D9D78816FE9E92F843558029A08EF7015764C3D1AF1852C50D360F65F887479E9631A2CA30FE3AD92E7BF648643835F4F8CC081A6C9C439720087F16209AD7D3DAD7FBDFDFED8B6E91E5FD0D118B85F3616E510B8229CA2443C7CB3E2CB8A4496225E251B20EF7BF07A1A37D00A59DBFCC0BCFF40DF1E71AE21A2F47E739C7AED529E7EED5825FDA6446E40F6C889E249C813F2656995B25FB9169A3460E4AC08509F6C41627AFB5261A8E5ED535C7D0FB4869E1FBB9F9B5545373C3A86DDFDB1D863609DA537E44270132411E8A373729B4D37C277197E5E72AEDA323C10FB7CB3E7F169199EB86F5018CBAAC09E9B322FF53B461C6197F55B8A2C849396C4B19633627442973CA4FE54442355306C2207D6A632117E6AA6D434BAB8FD8B67091BE465C3BFB21CA9D16D794635422DEF832911110F5B20D28D1B9384DF1D710AC39FAF699989418B7856C2034C695A693ECC336EB44751F234CE3EB9DA99AFEA939C270AB221C09C99C1538BBA65D88E13DEE3D82EDDB9994161F2F83D2829B47A2886BFC4FAC9CCBF78EBBA2A40C9F2F0946579887C7CD9EC770C111D9681D6F1B97D908CBBD436444853FEB47F234D31F5E92B9EF436C0E8C75BF71D78A7F90EF443748CAB197234EA10CF3209320CCF8ABA1BA0E3A789C1A3A7E2EF2DD79D3C48A562D4599D4C204E3A393724FC11749CD28AF44E34D56CFBFE507E95A9E3D86591149D0E5DB6DD9A9A83A811D103580A40F3EAAC60C3D0D40B8744BD2A8C97E20821F46750D130024AAE8D968515F6314D8F25B7E267BC7716B6F64367028A87D330880BF8CB7FC94AD8DF4CCCD6D6C5C24AB9E7725CD11443807BC4EECBC46D46EC3D79A9C0C755A65AB867B1BA4B07FC1C2F62FDFAC5E8EE98639254EB106410A8BEE8214C66A7BB81C99C989737A7EC3EDB49D00B96789B4DC9018224DD7B1CCF3FC893A10C06EEAA776CF0013263513CF0F51EAD30CDFD170155A675ABB01E2C06C2E04365A619CC6294601207BA2CCCC24D08B9D0A5A3F6009F660E9B15456060AC696B025F2A874623DBF0B61F73C56A921D5E8459ACCA633C5B50F7C6A36062BE168AF6246317A8B052CD7F15A96EDCFA580D8FB229B0797A6B4C45DCA773108A4A0893546B4F42192E0B146B33581687B7E0BCDD9121C2855C87CCC9078FFD868D7F0BCAB9C6072DC52A6153A0DC127C0D7AE9E6AC7062BF0E32260C11266C4AEB1815B9D80CC2C7F5898A39D5C1CD10002B3D710DC236EC8D68027C56FA74F71482643230330B6FDF0306DA1A39805F56FAA5EB1B2038CF5FDC70F204F0F1D4982B7DBE1BFAEBFA628CA56052B581C1DDCC1B058B92BEAD301E8F3B8F5EF71EEE7966302B44D2E26D2A02393713E50E97A5E1309649D4E93719A883E1C7EAB902CDDA5AFE46434431417A67D20C0555F9CA097AA6C3B65C5CD659AAE22F412427C2918AD8C309342C8369BB454C503398C519742B581D604C13E10DFEDBCAD3EB1F66133D21F83B2C15BA70E2084E0E96D865CC4D6A606FBF4DE92C66BBFB686C56D23150B560DF6C4A899A3CAAD123DCEE5A1D81F1E20ABD1DEA550546C1D13ACB5AAEA1E6F2304541F641343DDEE6E0A066BC266687463E93C5A235862776216A7294A9B18BEAFDFF95A17AB7CB4E7FAB3B1D2265743AA9CEDE4423AA9D5E65EE25DA90FBAE188B81FEB612D3597B7615487DE8858DB8A45448140CF4A9D2152E12279DC7A6AE1DE1239BF9B1AC54D212926B7F2F17985DB1943D5ED8EC711A88DC5AF85CE6CC47237014255691B2B5807FEB4B1F2FA5FD7108614F0111A2006FC13859790AC63FB3A98442D30D2F1EAAC7944E4E7E754B78F741D7B3858E4BF33C370C36B8A7560D6445B6D2F6186530FE32C466597E512DC0924A135CAE452048EED75B482355223F2A9DAF3FCF987E323EB63EB61FB83F76123FD8CBE6155DD251E20F090991CD6489A6F433B8C51B0C6412F36BA064FEA5ED935CD8FC498C92D651E2C9BB0A294D35E87BE85E44D90F65A4EC5BA93065A2A731CD107EBEFA54AADA64C3014C9A6A2506607547D9A150ABAFCBBB6BD37E68B51E1E3B76A88186784096804E0CA23134BDB1616C6C6171F79A60A5759406D13E1DE37665471E194598FBC67D2713E4C767B295AEDA2B90972324B3ACE8C7B79A67723AEA037E12DA9EFA9CA9668A4F5FDADFB9E4278B48367B4C50FD7C42161E491BC40C35FE359EEE17A1333375545BAD7576FEB7542B22B51702D73D0253907F7AC6D32AFD378410070FBAB10D31A4B2BC818AE5DE2ED5D631B575F59F445A94E79190E6640E42F2A3DCAAC94A1C6E3D522BA874184C8A8D15DDA84BB247C2A2E48B5FC81BB64A1CE95161CE2661F6CF8ED45BB7916AC42B1861F5CB527FDBCD82DBFA31C5ACF981D8414203837504263C96BA3C6B4565D4163160F135D27A95E1105E4327276D2BC3688C76EAEA804631DF081B3C44B0F10FB7300874B5011FF0F97C52F975A31355884C2F12B6FFEE20E8371D38183C9D04977BFA037C9BD4DD7F7CE203FD7FAD3852B3C2AE9D078ADEC7886E0D5DCB57ADD979B87904537D98A9179696CAEFD7FE3EF62AD44C8FCBE817976035CED8547228BBDEF5341D9C876901B08FAD036AC277A918FD8D8CFF38F7E9447636C3FD64C2AAB9F44C2FC2E4B27A6D4D7CDCB4295F43E2B4B04C931AB8987079555572152AB8ABF9DE2FC4ECC91A00B7E36D11F49EC02620148D3147EB8D2AE42D887D10EDBCABE6AAF951E0A070D881879332064C99F8527A5EFF25241E773D96CAB3EC602D83261F07793CCE2DBF7A28EF9B5792412414567DBA9372712689DF5DE30ED5313C773311EC605B8E44C297ED4AAC95D3B1DAA8631F7786C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC9D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D00C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA2F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549617285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909DC96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A35F79B7F944D0041C0130B7F59B0ADCCAD97670C92355CCC8F0FE34612A088BFAAB33542EBE8F3283AD67A79EECC3E7B7C5D4CCC29B6083AEDF7AABBFAC8281B7D7711DED8D4CA70C383C5042272379356BB80EC0A9BB8E4F1C73F2D2DE1676BF5AF43AF87AA2B2C4A6826DCDE46E599B2F31E9EA87A816EC5D8163952A7384603C8FEC20F58E1AAC52188E42774382077A35700EA5EA2FBD04135593A7E40ABA137FE400EB63BAC7F417252EF6AF6EA8FA9CB3BABE7718FAC4A756702AD64BF1F912E6ED44DC6D424CD15D3E45BC9F86ABF7CB2924D7B4E8AAF67D69401F5609B17D251140842D7A94FE5D911BF2FD37418208B716D2DC66320743B79E64CDAC6F2257AD34D112E22F977AE6034068C0E0F089FECA11DE03396BFBD365B1A788B2C550ACBED3643C1E4F13618F904B40031CA9E73F9B13293DC92102B33FBC16C9CDA02E511D49394D5DEFB95770E5CC750801623042B7113D385E8BE8FEDA1D7F9105D545B18AE98870B1326494F9BC31B33EC24CCA7CB8E53F9AF1A7E099B0D9A40CCF40B085C0D406B5F1DD7DCA794345FF98F272F7D9A11C30CC5448D2D311502B7F0F81437B52EB11CC5FF11C1FD62B9A34E2E102C5C59D14A3326702F6B6862383B5BA1041A59B2F4E009161857FEAAE3F0C4006926444BE77169E9963DF262BBACFC643F032414200B26840295326BA1983CF450DDABD0DEAF05B3AEE35CC029B1E67729517B6555FDC996782FE0CB275645E739BA0BC75A08869998C082BF6680E2DED0D643F06EED3947CB24E4D240CDAB6B07EB71762DB159BD8E8FEBFF190763906FAEE1D307115E7D6697AF3DB2192D37468806FD49ABAFFD157647B652B339A8912CAA3730EDB23593BE64CE9A50A1622D43538926E5B05D878029C5AE57DB40072EBB7889423A948257F9E8684E5B4F10C09A22AC506B5105246ADE89409D3AA78C4A88181FD562EB714E9402F8C4AB2129E73FD77BB64F3F6752E5AEEBC4DACC209D01A274E39A84857736671BD0604C153703CEC940CB0D79CC433D157EC5004ABA2F359B80DA9FC04267584B2897B594C494883185E613283B939DEBE0F324B3CB9F45A6FBF11AB1CF2704C5F83BE3B8CE1C38663757828909CA4AC49ACC134F533F5DAF470EC30D2E8FBC66C9B6C58CBD2ACBFBFA2842E78DEA2DCB820CCCBFB17454EFDB2B1D706B93B0254B3209CFFECDA9F52CFDC1CF312EAE3035C1A3D75D8764F693350C2301864EE1A3797F6574AE38F66B40F82904FFE6CBB34655B99959759EDB652F6A3BDC1D0F24E8EBE1761B43E876A6A7AA29E8B1158F1D150E25A742B5FBC7161234A85B35803FABBC0AEA40821E9990D48BA7EF7E1A50178ABB3CDBEE228B40C8B02C98C5E8B70CFF650E570988E64E6F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257302026A4B5934CC6A417A99706CF783722DC2663F469896FF8EB4CC741D531F3C32B41F0BC6DCD4A32786747BE120B33718A94639FB4D754E0508B0315990F31555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE94149EB3F4A4F9779A1AEFE60FA343AC04323795C9D33DE8AF95219B8711B1168A107EF83062F033203511E5663EFA0C45ACF54432C9D4EFB5678332B5E164092612E42C61560D9EEC768594F4E0E6AF10AC7B3DCD22D229AFA8C022EB00AFA626C63E8E96B72DF979586867B42B8FEDE446A0F6807F1F1C775595FB5DEAA3BE2A45570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41FACBF13EE45A1F97C20748CDC3B4068D993D944D5A165FB858FDF4FBF88632FB826103B1276C7791C64195106635996700A71E299889131E533F7F060C7F96E7C54F02D2A32835106FEBE6D40CD4D56B57ED26A7431731B04A78CB5A4884F0CACDF007DA6E1C4195B2B59A53F31C48EF9FC33CC7F6BD147032A1B6313C7EEC43B1E46164BEBFEF16FADDB1A176FBFBE34DDA7C88AC9C1EEFD4F33B7960D847872B8B433AD5D1293EA480E6FA097BB9AE29A7C0270A062EF9BADDD796FD8EBB1502606E9262357EFCBCC9B7343ACBD03CFAE6907BE46BCD32C4C4C4722C8D3A9EBC76EE4CDCE71B049D688C42104B94A1F7FE6F945BDD02E3DCE0C345C047AB31E7E8051ADDD3DBCBD33699AD660C1CE3E25D203C4EA56368B19C77D498E67CFE083ECD3D36BDCDF29A148224623E0D70D060EC964B329186162C1567F7E7B5B6921CAC8894E88BD8BD6FBA1E8EC4081D35931ECA2BE1E72E32D7C986956EE9CFB07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42E63C0C23B6C61D15F2C9FFEE5663E3CC74F7400D0645219751B70C916C03C0C67159F71BC0B3BFA0956F026B91F8C2419D671D3E00D7F633DBD2DBE88126DEEFC7733C2C926D1D8B0C8BFB1077A700BBF3892F0C4F3E30DF78BCE0A340A8F98EBA5BD384684D1E0081C1237440B3A6F117178C0DE4F19D05D4241240924D9EAF9CA45E3D4231AC903C8EE5298A3445F01961D6D3786E36D24875E6DF3EB1D6C1BE5EEA0E060D3E0EED1DB2D4E795D35A0DABE4A745764F05A858291993541AE149CECC5147FEF0F3A96B42F38963B9B29466FD66AD46CADA8F10E2D53BFC3B823CFED410147B5FD315FAA62ED06429D6D3FE6E5778A64B5C9BB06A8CF5561EB7A8B15838AA226DDFCFD4C31805D53A6EB7D2DB861451027CF84218C39078756B2911021C3EAFC2E82ABF792C5012CFCA3AAFB0A277A9C9E1E515CBC4439D95B2A54510318F5D6EBF97C8DE2AE0D4FF669493AA354C25460D3C15B1A57AC53D7E6C07CA407AB1EEC4A366A637AD4081F0343433C555DE72B71ABCD8ED3C043532A61125CC3CA06CAA634E5F75B750BF262756A57E3FD235FA9EF00CDD9553D37968DD680EBD5935FBDFE43A82E9DD39F96FD483AAB7F2D0517F23727E8F4DACBF144E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A76442D207EFD647078CA9CDF7800804012D4EC23BA14C99666610A22DA87523E4E5E41A6698E5235743A9B9E1C4795F38AE20CBE5C3A2111ABA307C3BA6E03F092E96AC6EF297548A3F144ECF7F643EF19024B2E98B51173450ED06ED68EFFA06EFD60721E73C9C6993F14C00E3E4BE441791C648110F699AB5089D7CD092AAD82AE007C0C3C8659506D5F2817E75EAE8B803734822A2526861036E35C3689EDCBA348A7A2E4BE2F1E291F63473988AFFE650C1BC49CDEA3875DF4E6B541727B5AA6F04C9C1E4D06BC5CC744D1B955958E2578C6176AFD7E3262CCBC0F6FA21596BDC36349BF9329BCBA08FFF934E31DC1FEDB7D7F6B459BB1A0165043B902D600C447792A618B77C1671E5793473DED54FB3322180F198873E306E1F8BD17BE04FCD3CF4D6A9201B9B804BBC772B742097663C42F0FEE3766B3B205F14A39D6ABA56963D03DCDF538ECFB8A7AE64DA3C116BFC09506BACF5E8B5754B220F7CF70C5AA4492AB72D20CF8F4966A114833B057662EC63B9570D9B2DCEAC86590569934F91A61A03E18835E31ADBC2EED3BE0BC148FF004675C9555C901B280BFB56FF8A1C079E1F290C67FD1B7E53A6C27A5C649ECA9EEF836621F9E708EB84B6F5C529ED2F07BF0A6160154F41F323DFF8A498177FD09D22DB15A273F787529852D898A6DF0FDBEBEFBA3F3B602B1E67352224860125216AD6D68CA891606E179FB415DE4B95484CA6907319438F69337316203F06AB1488A471924545C81A470D78E2EA29AAF89E94920AC4B0E7F2FE01092BC8CF3839480A02C0E8DAC1E864C9BFF5CBF46C0FC7B6A01FF0DBBCF96E3585496C392C6496D06C44765878B26B6DFF2C2FEC20F26A9A2706838A2048E579C65F3BDDEFC58C89D8830FB8C75FAF96788998DD200D48189C3B59B41501BD310420DB96F7CC5B61A2EAF88B498ACD890F7DF623A35479472694CDDA58C000D9BC04FD903E4AB88A2E757700FF3F460F075F9876DB3F76F17003E01DC96A92543DCDFCD7EFC86A5C0DF387A50ABB69953D6DC19A699CD225941F82438A8EB7889B212F65ECA7399F89CA0D9B9915E827D2E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC876E4C5BF248F94C2ADB3D6C9F23C3E70D1F611A2041C7759317B8EC1696B2632CA10CEFA498D7571D016E102DAC10051DAD086BEC58AD5DDFD7988C5F433DE87C314E3930FFF937A6E0C81787F04B77F893287AB63125CAB8B7460F119D03BF3076A98FF029EA5022201DD54C854711B8BE718EE678544B51AB13B7ED0262C8180C2F36CBAB64D862D38AD7D8172AD8BA3380706D52048826CAC611B07468967CA4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F238380083A064421DC7CE13EC2F715580924D9B6EFBDBB0D45AD8952F602BDED6455C0BC2734CB135B79966464546A261D0A551DEB43E5AE111CD02D0F2F2E996454DE17B471C6103D851CCE2E1FEDBB828C7F4EE66053A57831C708C377FDC6FDF037F400A09E9A610350BE6C013239D7F1C42758CA84B428EB06C6A6A3E05F10FED769CEE2D8EDC3EEA29204605005468B0366B2E957A7A55FBCC7842598F55021E58DBEEF44C5313226E6E56A2D3837F2A098C94BEC791737F355E6CE5643C954C4719C6C1C939B7716A29191CF0530BC2E78CD028D526EC286FCF02B18A077C86BC54F078A19A529F6EAF69D5562D4B31E4CE3B953A24655429BDBAEB5378C13E5B404A138B2B5473A415EA236245B0541B6D92F384D4CE63680ED5A6C035FFFC663C893C8F51C5DEC6F90D33573A05CBAED63B69079EE77DBDD21AD7A778B37EA5E0543BBDCD47497F355B1B2D8AD93DF4BB96A5E85A2344192B782D54C4C8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D947DFA8260661FC9326B9E76214D36B22172C026EC12E04ADE3C62D4E957AAAAE686D350793BC6E9C862D968C0E56B3160B5C70520E9AC7767AD2BD8D1D6DC951A23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831EC44071AC6184AACBFA0A2326D7EF097650C1D4D1E58134408C11E839A0DBA17CAC9DE3B437E697663AC136380D0690DA4A52070A2DC552275BA09C01B601D55E97AD7DE83A32B962D0A9053C1533600FEFD1171C638A50922B9962C195551F81FE80BE28342A13ED0B25FF8986E0E9C39F3C2F29B9F40AADF8CF61E879A7FC863B32F02C5B5BE16F0E2CF00F30E312820E84D09BDF073E0B16B1F32C73F0E6031DCB3221DDC48670D0F2DF9A8065BD027C30DCF9F12782C812753F109615828997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8B28262B6C82510AC69F4785752AE1F619E3D334170A4ADB4DAF3138AE90AAF8D82573E7AD25A16243E16650219C47F4CEBE6915B433B0ED0354EE62FABFD3E118AC777A63316637DA755A99AF97DFE9857B2F58A83ED70041EDBC49997EC93C03A7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE458A65E6B9BB209359F7FA47B95EBB79C83F329ECF88C7541446868CEF363218841F55D346A2B714DD48C711555BB25B1CCEFA6199A0E7646646B667634E486116C0AAD7E977C091A5EA356778C299EFFB7DBD3232C4B73B54C796BD1E33284CC8E4354C772DF1CCF762F615715FAA903D1551A67965FED6C7E1ED7BABB9325AC30F92305FC284724C59079B11D1A0E32F4665AD8390B34968D1885C9EB8BC5DDF63D7858E042CF7C66FF5E36365F1C7156C79CCDF596EFA551E203456E5BB22C2D9B742F490824B1D5EE482F335393E34E69C7820A639858C6EFFC2E8377876E461788FD2736A2D1BAAA432B008850BBB44FA193DC54757D8C75760638A12DFB614580A882EBD945716D7A3D3D29396D4A0D267B07B035EC001CF29C87E23D8446E21D604BCAB110869FFA98C32E35A9B6C878360FD7BF8D564B09384D5C52ED4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A20C9BE0F45E814C954FBA214F3D3089AC4D01ACBCDB25B9331558FE1D29E67628E13BFC928F7A9A88D13E0759B77674C3F2795CDFE0C6617022F9C6A87B60C4B5A69E8D1706749FB0B4E086C94B5BFC16CC3B34FF3B7EC227A5CC646E9A003E5D897871067191AD1F8A8C33A0E567F4DF2D91D00FEA00B152183D202BD72DC0694F16ADFDD6E44A248D80FC6609E601CB91EE691C4535CD80BECFF9F23F32BAB5F106234A8867CAC0B5269CA2BC588E48AF922B5917BB6813E9D1005F35CCBFDFD419404B59A84497BCAD743384461F24267C497A932411B690BF405A7ADCA63858F439B123201F41AAAAA4D0A478101EDC6AD214E025B5DB6D24021464C53FB376503B6CAF4E4D4974E072F8C88A7C61957239581B589ED8D1753844ED928642CF96E5ACCA32E69B52CFA3AF54B9FF793E7553CBE16C4F9DD6114D1357E539C238AAA4434C5E540AB31FA584B82AFBF419DC51D6B08FEBE34B7991EBF2A82FF8E94990BFD02764F7D1DC049A635A08B7BFDB46A521170B6B8BD940883CD4505224D9DF930E33C5827E303083CAC4F846D9CB9A6E3FF57E755C7CCA541DF51819C5A52BDFDF005217000967A2776F51217813B2FFC509EE35F8AED6481BBFF5D5E61732BA17C90FBBCE1FC29E8DE849C146642845F982A2F766DFC0A703B5BB612E4C2B8CC426BB56196D714FC6F1BCAA0F19F32CBC06C3DD1406B591D2B0CD0E834D003CE56313B66C224594354866598118C87C1A86F7D247593846100395EE6303E54D130F91FDF81D0DFD021C274AA9567B9F9A500F35507519BCC25535407E419B52FA4D9ECD3D53F467B6295505DE979CBF6C7BC909812265ED65B30269FA1500264347FBCF1CB34AC5A405F208E73DD503D0D0E15FA474802F273C76C3D3DF98070BF3151D5D338DB368DA0D2280BD821880265763EAB2076766540EB9A51EAE647B96CA4326C82626DBCFCA1B3FF6DBA63DD64AEEA6741FA49E358E97D8F60C7F1A56248E8CE18933CD6F850E667134F69176DFBE2A4FC259994ADE12676F63D483FE16F7658F1003C1561B8D46FEA0888D2C82A4254AEB9E4104B9FBC973CF836BCAB5E263240ED9D87E9C434DC66E8F4A7B73EAEB30BB745F4094A4B82EC96CF99219F557ADEFA605DDE957CAD9D5343558A9A0904575A7A954948DC927E71786394DF40E9328C9B4382CF4FD8423B97088BB07CB4B257E5AC7B817088C3A6912441992153D374D477EA4EFD21C9F706D3619634AF7DB364F5FE73D12FF9623B665980B98E83991215E188462A57C4B3F653E11B4B1E16522CD421105A1FE67AD0F58F3D4AD34A8BDDEC13454EFD5FAC6146012476391769D4AAD22B1A0BD1CE9599600EEDD95DD265C4640CB064F92C22B0C45C64FC411375852E596F268EB415B03DA88ABF9A089EDCC5F06ABBD96E1BA461D4DFB3772938CCBE093AF922F5CE290295EBA2289660868ED4B6AE38B28B1ABAA06B66BB97A5396218691B13D099ACB89D6754517372564CAB054763190677139C9E2F0BA2FB19D0471E49BF6A0DFF2F951A414ED5D0F17C729891F4EF658F19FEB6D31F0BD8EC15DC9F9CC1FD73BBD7A6CA326AB06F55078D4F2F90CF185849567E8C78F2773938A916FDA23279FC3A9D62CE3C3AAD309264EA076635487EDE98CE79ED297D1BA99D96C84EB712CCE028298C8BAF5B5CB3EFB2EB8996EFFF6F7682D6EAFE498B886FFDC157AE3995D8493BC6B51541BE6862B41B5A35AC420D4D120957AC00B6E488AFA394C5C3F99DEDB4BC4AD4127082E44F22194654D3FEF9CFF3AFA66A764864D8344939255F4BD77942D6B2063FA9C0F82DD3B8D9ABF5C633B6CACB152AC09B9DF3BD12770444F99843FD913E2C815368910DECDB46DC4E13EF2E89AC3FC7D13749B88197F633BB6044E1EA0FF4CE060C7F426D01D0CE94833304CDEE3C857FC7258DB654F49E7C949C4D4B2DDD689DEA7E0C526E694B5EF77F8DBCC199F73D833C54C6C389C9C63A9E203FDF4389D83A4DF4AD86D7B36D3847C8DA829E04E31BD81791E403D6098AE9DA476D75B357A74FBE2F0C42FADDA27AC72B653FD87A8D1D72E72E2BAF5D852D1FD6DE10D5A6A600C795F65A4A59A00E2C503DA0BAD2344CD62FFFAF6761831AB2CA4055C18294DB1CCAF2BC6A13DB522CA1BFBA9DFCB930E4D6C32EC24DB5A8D5C15398CF2202878D240BEE11756559F26355C059A81765FD0D993FA64887D5CB6EDE1B379B2B8B5D5430F3D7A6ECB8259220DA7C9106CACBA69CF6444192275A2C6EDC588234E8D24985A0770607FE1C4AE8CC7559B3687522EBF7D3CEF0E19B229509D2A247E8650C3676B3B272340EB71C69064FD3CE931406569E7AC1603E49A13BEA93B2892704378ACB4796CEA77687C98E8AAEC3501143271E504408CA5D7ED271C45A1A7637CFABEA8EDFCB11DFF3F8324C8C2C7D9C73A26B8B1C05B6F18013E03928FFFBBB5068FCF4B29FBC21A5819EF85B91B19A5098883EF40D91B7E287749A578E7743680786FCA565BC4D19AAC06BF70C283E7649992BD6BC0305A0A093B75DCFAECD7E049E16F274AA9B017CAF3F5068FECB55C6FA6ED97F64E17CF1CDDDAEDB45036C6B2227A0AD5181AD7389B72C8967B8176E18CAA3506BECFCDFFF15B598C47D10E11E65D9AE8AF9AFC8B189562D98BBB02EE55D0A5C41EEFFD3D6E8EE69878B3A003DE7A52A98978892E51219387C24BAA7A773944F530816FB27BCDCA933370CB340781A70DB5724C597F72F7A34DC05B732FEB79A18171281AB7A94DFCDFC2C96DD00784F2E67D7E56D0F146F1585EAA1448BE1CCAFC6F334CAB07A27E524BEB95E19D426689B900176A70B21E32278F27EA3BAEE623F92B14696CFB1EABA0D90EDC414FAAB03AC0572B4B8836F071A375849BCF46E83A05979A4111167CE5C43F6FF48F386E3E8F92FCA1655E3ADF4C2123DA2C5551E252E9BFD93276B5B2BDADBC8F23C0406875614ABDE72C520002AFE6F55BF1D19ADB7F26D4F71842FC66335FF670C60583CE65DFA6442DC6DD49889C3DA3AAF0FB310C3AD990480EF12059DD23AE881D5A72603F50C7C61626AB2E0BF9C8C198CB0F637EF72954E04DF5956355147B5073EEF3848CE65EBA73E67955A1CFF187CCA758372FB67823E230B05EAA9982488E8D22F6DA1415A731BD0A2B036F858FE16FB4349149B507D9DF770B9F3D3B45ED752EE888F40FEE65C4F3EC6897906303A19863DD968C666AC1980F26D8B574D5A16C95747AA6DB218471551478BF36140DCC5C6B9AECD22944CD2B781A240C914D2BC4B37877709794CA33ABA878615050637B0A0B3F04DE2FCF37A2442A242E6C97398CF483260BE8A092F998EEA5FB5519EB25BB10B9350AC7F6948CE13DC282ADFD3A251C07E32A25A8A93276A563755B3164C0A9510260425ACDC093CBDBC6C8C5D0FEC94A6DDB415C80D45BF9A6D8DCDA606E3204EEF6AA291AAC9AF7122810A77E0E1160A461AED63687B3C137EC40897B972493F33636B2CFF07747A394747C0887C0402CC4F50E78F70785E5DA4C6084BFD7AE379F0AADBA0CBADF8C70C34FA7A6B0C14F32D52FE8AC726F750DDDA95C741131C7F692CAF7A3A80173479690A3CC0A93D1823BA1AFD5634A9D14E17E7858221497CE6934D7630E73D615127209FA239A190EB60B4D49770A1122DE7ED76708CB660EC4E52900D130C9A4638448CBFB16B1943D7C007D521F945D00D42CD0AE51FA89D5BBB9DC68360C2551D3A0E08CB0025B061057FEA0855305C0F6496903EC94DDF067E722AE07D06AD5AC67A1B5A9D1D036F4D157220087AB098F2C6A911F710332AC3AF782A6747B8E079F12A768B9372BAA222EF43084F65A46EFBDC5D8BE794084FEDD23BB2BE82A7FD1C5FCCCA0E10FFF7CD47FE805A43F82E73773670C4F43571767DB9F9A59A16B1C6DFF3AEB739FDFDCEE27D8699BC080B9D5973F30BD546DAC6DE594F91E5C2F0DF432099D949C5FD0E9ED66BA4FD37F77CBBA8D511A0D712DD62859D6E3C0177A264EDC37393FA86D8BB241B13A2023CECC4A8A57242DA1C7BB796DB4B50197F8E7DE6FD645C6B9099D6F76701B0A36CF2DBC1C9E2F56AC8CB222D37682E19D33A1728916687BE117E14BC7D137CE28948A0997FD9B25545316DC91AF2780D34EB5D9A262B327FE0E57AF30D9299C1CDD7FF92E3CF8C70A9CBA640A71425B164DE8D2D0D78A19853125F684FB1E94D7D02473BF12C6537595311354BAB832C69593F4195132C6552176CD781A04D4293BB9E329B78AE8929A249AAC01C5C81DC46DF707C914E08A642BF4B0277302BBFE3950EAB036CEABBDDED57D2AB2DAC00B61474150F0F641A571573A79C7CEFE5B1E08C2A0D7C144D69764BBAAA9DA45E8C1CE02AD4BDA14E86E6F4509823913D553117C25BA7727244D0A5F4106962D2441C4D3813A780757E169AB7DA6FAE572D7CB919DF7BA028ADD524236473F8CEC4509FA954310D970F13B8F57505F248413F93CCEB0D2A8B81A3B6B812422E630863D5F37142EC8B03444B7509B92C2C46E8B7DB79679EE93FFC1DF1B807E29773C0B9A280334CD97CFFA2AEAACDA2A662F8767A323DA9D48CBCD419ACB2EF27A01A26F7F2968B572B679155717F7AE7CF17987EEBF9B088B153D06F88F683CD8A53B1D69CA429BC5D17DFF465377F6895611C319A8C8BC23438BED492817703D83BDBB93CD491EA8C39122ACD809BA158D5951E0B78FA5409E63E7CC69B5B6BC9BC56349CAFB05B71BD8C8ACC90F929F58037617118351CC1E0E0B3CC4040BCAB505CA4AA36C06277B4D550922DC424A005854FEA6EBE6C833980D3F7D49F38F595E3B156B89809B65E62B57E0C79947B2EC463027DE21FECA9FBEE0CD5B8EC64BB776FC95D93232C53A5A5D8F5954AD65E6BA6A3677C62497C3F4DD408AB08F2B05E00F865CAC6983159D2E4EB54EC0B89384F890E6033F71C5C888A9EF25C2E5563F4B79CF7F80E221C59FCC0CBA7A56ACA182D6A22A77AFBDD2209D5BBE8400605B918912E1F8268EEA13534E86FE8B6588ACF64A1322DFBA8990E280AD5A2E185DC29AE3AB7AEDEBDFF8932A21ECB57071D2C6207740AB48DA0286EBABE44AB1566D845A6B231073076634B6493FF5F4669CE06BB0BEB477C3BF2F9173ED7A36C22EB347036E7358BB62192E4E7BF5B9515C6A433D21E47F56C886AF92422741D1CA07EEB3A67A027283E78A27B64C89AC0EDF6D3CA5AAB03AB2437B7813BC5E349434386F00F0C0D592256BB28E68D0ADD1F23F001F2F0DC867BE42CFB316FCC3AB7F2ADE8F262E2F2A817435D72D2B9F181E285F7D58C2E9D0ADCA7E67933CEE6F908BBF182523A0367EC978CAC6373140022E3B851EBAE9D7086C4191C0BB856FBA1C5785F57A555985D0060A4BD79FC0FBD7798CE46C543B3D26C62BF07B7FFC0C5CB00729D2F9DC75A8A308AD312EFDB71DCF069034FB4F970969B749BD6F487F5E77627FFA00F64DBCF819A4F8EC0681AC3816282EC1717DA96444B3EC00B32B8C07E806988EEE0B8CEAF0CEED4F400F27F1D79267AA4BA333E61B84E6F10222FDEAF05D3561F5796CD819C879A07E780BAE63E780C05F024F2880EBCAEA6C1C8258D94B753BEED298829CF221BEEFF249643A4915D5C0E8AEAD2C85ED170790074EEC22327260470E99DD940227A671D56A9204224861E56624244241513ED4AC7117ABD09523C29C4F23E0C41900011215540597EC1BF8516CD28C228D03F8C7A65E4FFE575C6F5FB1F833B04F3DD1FE2DA3F983FC8A6BEE8CD7FDCFBB4436D8E8F09D466CA0129B4080F5C4D2A078B1CA2BAB5B306B26B4F75F49335E128D5E27B6FE1D96B9B863268E813A092C5176087562125530D23E8F6D61D99ABF133B032021530A5FBD7CAA65063B17304B76498D90B0F3E6541534667952F6B31A74394000AA731CD42D2CAB1EF3AD7AADBAEC7541D04E60B843FD337D7D08B9991452889376EB57FFC5D2D454B35DE0BE42E0B04E5C21D950E809C5D499AC04DE0E4FF912237DD83AF0FFC5CB8E520493400C91235F9D49BB30724098295713F70ACB57194F53B656D4B3E5879E2E28734370A052FE51C8139021ADD0DFC6D3D8491AE9C7C8E3AEF6A5C1E119D65923212BFDC35792BB5E3109BC36003C17100DF5302C7FE73ADA012B36AFA5452CFE356C38E63C59E80C1F3FAA1735150F1F3CE87E7008281D125FE7627B3D6C8DB3A2101DD6D650656EE5B8E0E8F0CA1DBEE12303499B6CECE8AC80111C504804F9ABF9C616D22DF34FBDAF27290F4FE6675D4A1FBE8A93A91C6B09B1456828554CD0CDA039569E2C08430C3481E2970BA760DA29C31944AF18085694530E8A952B54516062CD9528A95D0772323B4B8E02C7DCBD71FFD2236E772268E25F6D4C622F07F5D437275B2FEBECE7605967771BFA2007FECA33154FB46A3B788E9E7702F38BCDF175EFE4611B61147D89195BE90840FB1E365A76840BD9B40C21949F2D41205A491C019B7F49139C +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-12_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-12_256.rsp new file mode 100644 index 0000000000..a99617b857 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-12_256.rsp @@ -0,0 +1,12 @@ +pk = 000000089C3469640CD3578A98E9F9471F596649E45D969754FFE37395B79731156A1E2204562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000080000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A9C3469640CD3578A98E9F9471F596649E45D969754FFE37395B79731156A1E2204562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E704000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF54961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019C1A7BFD8300283215BA57DB5CDD95EDCBD04E1C41419317BC2069C2AAAE22130100000000000143ED646E32FC21554D8DAD350C5732270CC220F7E264ECB5B7A8E8A4586D0CD002000000000001762D040EECA13E137753604D099809D946063368BFE1C7CF0E6549FCA746F7C6030000000000015FB7406F1B25A2B4A6A1666269772EB08D6FE78D8A8395C56AD80FE6924DF082040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017F7DF0085A4DAADCB03AB4E8241B0E6DC05E727E817C3B6FA27F05AE1FA2DE1601000000000001BCF2F650C31EFD6F2F09775A3B4F87BBB33AD0D51537DAF37E0D1C1AE8BE8DC00200000000000174F4FE7914F390776AF328164E738CA8EB0751EF9E535BB1B0E80B05762E683C03000000000001241535B940156367A4ABD922871FB10B37235B67CA38CD8B2B02AA8064C5CAC60400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186A69EB284CFC56C72C2C83351D5CCDBEC831992175BC2D2D91B3F9378E0DE9E010000000000010A318F954C197DF2DF39A85C4B322E7EB1B16B0B4EB8C8A492F4F3B904C47E7602000000000001A9204F8E84112663772797AF87ED34C559ED4D6D37E634EFACE6A18C700CD53A03000000000001D2E20083FA11E157A2E5B72C9A986D3F47348E54C1935F48A86F7A9D78B2BE600400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A6442DC6DD49889C3DA3AAF0FB310C3AD990480EF12059DD23AE881D5A72603F50C7C61626AB2E0BF9C8C198CB0F637EF72954E04DF5956355147B5073EEF3848CE65EBA73E67955A1CFF187CCA758372FB67823E230B05EAA9982488E8D22F6DA1415A731BD0A2B036F858FE16FB4349149B507D9DF770B9F3D3B45ED752EE888F40FEE65C4F3EC6897906303A19863DD968C666AC1980F26D8B574D5A16C95000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100132C90901F97161C5614019A534B035942B26ADCEF40AB97BE258B03C87585010000000000012BB35E6F2C4AE0A3430CE207629C011B30E4C6F5D6BDFF2AB750EA0C69BE95C1020000000000019CAFA71D2E43D02FBB0C55294A6CD0AF3AF0816F6E6D1F4022AEFD413DBE8C1E03000000000001943191FF197E71722D961AF04F9570BBEC438A6D22058F1018F6C61F3CED67E50400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000290F4FE6675D4A1FBE8A93A91C6B09B1456828554CD0CDA039569E2C08430C3481E2970BA760DA29C31944AF18085694530E8A952B54516062CD9528A95D0772323B4B8E02C7DCBD71FFD2236E772268E25F6D4C622F07F5D437275B2FEBECE7605967771BFA2007FECA33154FB46A3B788E9E7702F38BCDF175EFE4611B61147D89195BE90840FB1E365A76840BD9B40C21949F2D41205A491C019B7F49139C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012A13FF51186CBFE9467BCAB51417E5129671EFD5D0D686D09E2C5BB683FD45450100000000000184D0629348E528473585F873A1929F01BB41F19090B770D155E497E4AFF30A990200000000000163EB4A114558605E9DDBDA75D10B78F28322197D1DF7FB4214438DA12328F8F203000000000001B86361D142F7F14ADAF4EC3E307CA82B6106FBDE3777E656781187D3558E3E1F04000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008AAD20F59A5E2539D3EA32A9A717691D72C2FF90173D53FDF598E4BC0790180A6CD182CDC6CA0B5FE69AD663506A6A43EF780D1F2B7E05E904271A587E0619EAB04598E3574C7F271892C3F482D2817BF74FABF9B63E43E74348386C624CD0A73AFF1C917D1DBB8D08BF504299C0DE3E5736BC9E3FAC872BFEBC1E5DDF68D69EB0572AF7243E531157C9EA81ED640B87BC14A959FBCC7658CB5BDF6E87F4E6770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E203D0691CEA545CC43DCFBE161452022A98B0EE265DD051C66D4D40CB142EC70100000000000198AD7048E8F4A1AC6FE162435B004552EAD82ED6463EC081779E26B35577C7A202000000000001BEB756F3DA637E592811BCF2D4051971434CDDBA76FAD2E9BA59F8BDD7AD523903000000000001F5264362A5684064AAD87ED555D342E88F3DD3AD0D4CD54CDABCB2A33B347A5C0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CB4A42F0E5A9ACBBA9A6E6568753C7B8E4AEAB9B1DCE5052A2971003750085CB05B68E6E9E126AD5BE084FECDF62C8AEDC63A920DA15D1A3B4C5CAD650A2DB43D93EDAD2E498B0ABA4071B75F8DDE617299C990E6979D860461342EF7D52E632ED2C78AE41EB9ED9ECBDB9CEC925EF47CF57E413BD7A4B9A71E6236CAA1AAFFF8A8066E50E19D3CEA70F910537B76B350CC194B2804C1458A428BDEF11FD82470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C59C0BECDDC4FC283AEFB2854FC4736C46F380627C810301EA77C23239780A100100000000000157A6050CCF22BE4B46B275064B9A7EA36848C9FACF2ADFC708F950326444E35C0200000000000179C1F7FF0B18868E800C6EBCB4BD4C88CF17A157A22A079435B5D8AF520D290203000000000001DD30F4FDD599D12004F8B06EB85EBE61659BD7CE19E28309A1F5D103154FE4260400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DA74B87E0ADF3119B9A2AD38D7679D60DF92CB86566B14AA71186C40C338B3A396579902434ED860428BBEF6BBA18121004411641C50A92EC832174AD38A679F5A49946EF241A8FA1D26974F9E465B1DB8C6F88D84B62A1507CAD3AF350DBAC43276A87D94FA1C7A9E8488B5E3A2EB66605C69AE4C2D7A551163F85877A81D5B0F988F48A6B2D06C9CB879DA0068CC2B3DBC36C5BD714E30A5021AB48AA57F830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DF4DA42AF634CA5BD15D0E372A2AC3B003D11DD9BFAE0B70E6E492E9661278CE0100000000000123BA7FBE99564830BF93790201B8BD29A47D288046D9E19DD1011CB8CD8470E502000000000001427455E428922B66D2C1F37EEA0B540B002E8989FE01F762D0523B5E22BC74D403000000000001CE06EA2927B35D814BA88A8222E3070EDA3149DA0FBB30A0B7EB1206B74E4487040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020468B089D5CAB0CD8F29FD284ED47E7546D39B4D6124B431B7190FE5D5489DF4C39914BFC951CCE080444FDB4D4BFDDDEBF80A22412911D5CB7DF5CCF5434E2E9C7094FF22B5924EB967324E73090832FB75FAB896104DABED028C4D096234B96BEFDEC7E669F850CD731ED2782B60512E2F83B3E063719F2A0F984C9EAB52C8BB7672F4A7E75231855BE3B541BE8BDF4638136802A83225ECB0020B956B6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E7143B6E483C8094DFD75A5579E15E27298991073099C5103C6F44E17604725001000000000001C261BA3B2D08ABFCAB9362CCD93DC25527163262B29AD7AA14725737393423E902000000000001E990075F7BD30339EBF3E3034821B5794A5D5031F2842DDCEBBEAB049F3B5F41030000000000019415C6FC5645D2BCB5D37DE763D8A3038A00E8A5547CE9A4719C5DE467C12CBE0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA7285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909D5F79B7F944D0041C0130B7F59B0ADCCAD97670C92355CCC8F0FE34612A088BFAAB33542EBE8F3283AD67A79EECC3E7B7C5D4CCC29B6083AEDF7AABBFAC8281B7D7711DED8D4CA70C383C5042272379356BB80EC0A9BB8E4F1C73F2D2DE1676BF5AF43AF87AA2B2C4A6826DCDE46E599B2F31E9EA87A816EC5D8163952A7384603C8FEC20F58E1AAC52188E42774382077A35700EA5EA2FBD04135593A7E40ABA137FE400EB63BAC7F417252EF6AF6EA8FA9CB3BABE7718FAC4A756702AD64BF1F912E6ED44DC6D424CD15D3E45BC9F86ABF7CB2924D7B4E8AAF67D69401F5609B17D251140842D7A94FE5D911BF2FD37418208B716D2DC66320743B79E64CDAC6F2257AD34D112E22F977AE6034068C0E0F089FECA11DE03396BFBD365B1A788B2C550ACBED3643C1E4F13618F904B40031CA9E73F9B13293DC92102B33FBC16C9CDA02E511D49394D5DEFB95770E5CC750801623042B7113D385E8BE8FEDA1D7F9105D545B18AE98870B1326494F9BC31B33EC24CCA7CB8E53F9AF1A7E099B0D9A40CCF40B085C0D406B5F1DD7DCA794345FF98F272F7D9A11C30CC5448D2D311502B7F0F81437B52EB11CC5FF11C1FD62B9A34E2E102C5C59D14A3326702F6B6862383B5BA1041A59B2F4E009161857FEAAE3F0C4006926444BE77169E9963DF262BBACFC643F032414200B26840295326BA1983CF450DDABD0DEAF05B3AEE35CC029B1E67729517B6555FDC996782FE0CB275645E739BA0BC75A08869998C082BF6680E2DED0D643F06EED3947CB24E4D240CDAB6B07EB71762DB159BD8E8FEBFF190763906FAEE1D307115E7D6697AF3DB2192D37468806FD49ABAFFD157647B652B339A8912CAA3730EDB23593BE64CE9A50A1622D43538926E5B05D878029C5AE57DB40072EBB7889423A948257F9E8684E5B4F10C09A22AC506B5105246ADE89409D3AA78C4A88181FD562EB714E9402F8C4AB2129E73FD77BB64F3F6752E5AEEBC4DACC209D01A274E39A84857736671BD0604C153703CEC940CB0D79CC433D157EC5004ABA2F359B80DA9FC04267584B2897B594C494883185E613283B939DEBE0F324B3CB9F45A6FBF11AB1CF2704C5F83BE3B8CE1C38663757828909CA4AC49ACC134F533F5DAF470EC30D2E8FBC66C9B6C58CBD2ACBFBFA2842E78DEA2DCB820CCCBFB17454EFDB2B1D706B93B0254B3209CFFECDA9F52CFDC1CF312EAE3035C1A3D75D8764F693350C2301864EE1A3797F6574AE38F66B40F82904FFE6CBB34655B99959759EDB652F6A3BDC1D0F24E8EBE1761B43E876A6A7AA29E8B1158F1D150E25A742B5FBC7161234A85B35803FABBC0AEA40821E9990D48BA7EF7E1A50178ABB3CDBEE228B40C8B02C98C5E8B70CFF650E570988E64E6F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257302026A4B5934CC6A417A99706CF783722DC2663F469896FF8EB4CC741D531F3C32B41F0BC6DCD4A32786747BE120B33718A94639FB4D754E0508B0315990F31555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE94149EB3F4A4F9779A1AEFE60FA343AC04323795C9D33DE8AF95219B8711B1168A107EF83062F033203511E5663EFA0C45ACF54432C9D4EFB5678332B5E164092612E42C61560D9EEC768594F4E0E6AF10AC7B3DCD22D229AFA8C022EB00AFA626C63E8E96B72DF979586867B42B8FEDE446A0F6807F1F1C775595FB5DEAA3BE2A45570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41FACBF13EE45A1F97C20748CDC3B4068D993D944D5A165FB858FDF4FBF88632FB826103B1276C7791C64195106635996700A71E299889131E533F7F060C7F96E7C54F02D2A32835106FEBE6D40CD4D56B57ED26A7431731B04A78CB5A4884F0CACDF007DA6E1C4195B2B59A53F31C48EF9FC33CC7F6BD147032A1B6313C7EEC43B1E46164BEBFEF16FADDB1A176FBFBE34DDA7C88AC9C1EEFD4F33B7960D847872B8B433AD5D1293EA480E6FA097BB9AE29A7C0270A062EF9BADDD796FD8EBB1502606E9262357EFCBCC9B7343ACBD03CFAE6907BE46BCD32C4C4C4722C8D3A9EBC76EE4CDCE71B049D688C42104B94A1F7FE6F945BDD02E3DCE0C345C047AB31E7E8051ADDD3DBCBD33699AD660C1CE3E25D203C4EA56368B19C77D498E67CFE083ECD3D36BDCDF29A148224623E0D70D060EC964B329186162C1567F7E7B5B6921CAC8894E88BD8BD6FBA1E8EC4081D35931ECA2BE1E72E32D7C986956EE9CFB07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42E63C0C23B6C61D15F2C9FFEE5663E3CC74F7400D0645219751B70C916C03C0C67159F71BC0B3BFA0956F026B91F8C2419D671D3E00D7F633DBD2DBE88126DEEFC7733C2C926D1D8B0C8BFB1077A700BBF3892F0C4F3E30DF78BCE0A340A8F98EBA5BD384684D1E0081C1237440B3A6F117178C0DE4F19D05D4241240924D9EAF9CA45E3D4231AC903C8EE5298A3445F01961D6D3786E36D24875E6DF3EB1D6C1BE5EEA0E060D3E0EED1DB2D4E795D35A0DABE4A745764F05A858291993541AE149CECC5147FEF0F3A96B42F38963B9B29466FD66AD46CADA8F10E2D53BFC3B823CFED410147B5FD315FAA62ED06429D6D3FE6E5778A64B5C9BB06A8CF5561EB7A8B15838AA226DDFCFD4C31805D53A6EB7D2DB861451027CF84218C39078756B2911021C3EAFC2E82ABF792C5012CFCA3AAFB0A277A9C9E1E515CBC4439D95B2A54510318F5D6EBF97C8DE2AE0D4FF669493AA354C25460D3C15B1A57AC53D7E6C07CA407AB1EEC4A366A637AD4081F0343433C555DE72B71ABCD8ED3C043532A61125CC3CA06CAA634E5F75B750BF262756A57E3FD235FA9EF00CDD9553D37968DD680EBD5935FBDFE43A82E9DD39F96FD483AAB7F2D0517F23727E8F4DACBF1442D207EFD647078CA9CDF7800804012D4EC23BA14C99666610A22DA87523E4E5E41A6698E5235743A9B9E1C4795F38AE20CBE5C3A2111ABA307C3BA6E03F092E96AC6EF297548A3F144ECF7F643EF19024B2E98B51173450ED06ED68EFFA06EFD60721E73C9C6993F14C00E3E4BE441791C648110F699AB5089D7CD092AAD82AE007C0C3C8659506D5F2817E75EAE8B803734822A2526861036E35C3689EDCBA348A7A2E4BE2F1E291F63473988AFFE650C1BC49CDEA3875DF4E6B541727B5AA6F04C9C1E4D06BC5CC744D1B955958E2578C6176AFD7E3262CCBC0F6FA21596BDC36349BF9329BCBA08FFF934E31DC1FEDB7D7F6B459BB1A0165043B902D600C447792A618B77C1671E5793473DED54FB3322180F198873E306E1F8BD17BE04FCD3CF4D6A9201B9B804BBC772B742097663C42F0FEE3766B3B205F14A39D6ABA56963D03DCDF538ECFB8A7AE64DA3C116BFC09506BACF5E8B5754B220F7CF70C5AA4492AB72D20CF8F4966A114833B057662EC63B9570D9B2DCEAC86590569934F91A61A03E18835E31ADBC2EED3BE0BC148FF004675C9555C901B280BFB56FF8A1C079E1F290C67FD1B7E53A6C27A5C649ECA9EEF836621F9E708EB84B6F5C529ED2F07BF0A6160154F41F323DFF8A498177FD09D22DB15A273F787529852D898A6DF0FDBEBEFBA3F3B602B1E67352224860125216AD6D68CA891606E179FB415DE4B95484CA6907319438F69337316203F06AB1488A471924545C81A470D78E2EA29AAF89E94920AC4B0E7F2FE01092BC8CF3839480A02C0E8DAC1E864C9BFF5CBF46C0FC7B6A01FF0DBBCF96E3585496C392C6496D06C44765878B26B6DFF2C2FEC20F26A9A2706838A2048E579C65F3BDDEFC58C89D8830FB8C75FAF96788998DD200D48189C3B59B41501BD310420DB96F7CC5B61A2EAF88B498ACD890F7DF623A35479472694CDDA58C000D9BC04FD903E4AB88A2E757700FF3F460F075F9876DB3F76F17003E01DC96A92543DCDFCD7EFC86A5C0DF387A50ABB69953D6DC19A699CD225941F82438A8EB7889B212F65ECA7399F89CA0D9B9915E827D2E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC876E4C5BF248F94C2ADB3D6C9F23C3E70D1F611A2041C7759317B8EC1696B2632CA10CEFA498D7571D016E102DAC10051DAD086BEC58AD5DDFD7988C5F433DE87C314E3930FFF937A6E0C81787F04B77F893287AB63125CAB8B7460F119D03BF3076A98FF029EA5022201DD54C854711B8BE718EE678544B51AB13B7ED0262C8180C2F36CBAB64D862D38AD7D8172AD8BA3380706D52048826CAC611B07468967CA4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F238380083A064421DC7CE13EC2F715580924D9B6EFBDBB0D45AD8952F602BDED6455C0BC2734CB135B79966464546A261D0A551DEB43E5AE111CD02D0F2F2E996454DE17B471C6103D851CCE2E1FEDBB828C7F4EE66053A57831C708C377FDC6FDF037F400A09E9A610350BE6C013239D7F1C42758CA84B428EB06C6A6A3E05F10FED769CEE2D8EDC3EEA29204605005468B0366B2E957A7A55FBCC7842598F55021E58DBEEF44C5313226E6E56A2D3837F2A098C94BEC791737F355E6CE5643C954C4719C6C1C939B7716A29191CF0530BC2E78CD028D526EC286FCF02B18A077C86BC54F078A19A529F6EAF69D5562D4B31E4CE3B953A24655429BDBAEB5378C13E5B404A138B2B5473A415EA236245B0541B6D92F384D4CE63680ED5A6C035FFFC663C893C8F51C5DEC6F90D33573A05CBAED63B69079EE77DBDD21AD7A778B37EA5E0543BBDCD47497F355B1B2D8AD93DF4BB96A5E85A2344192B782D54C4C8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D947DFA8260661FC9326B9E76214D36B22172C026EC12E04ADE3C62D4E957AAAAE686D350793BC6E9C862D968C0E56B3160B5C70520E9AC7767AD2BD8D1D6DC951A23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831EC44071AC6184AACBFA0A2326D7EF097650C1D4D1E58134408C11E839A0DBA17CAC9DE3B437E697663AC136380D0690DA4A52070A2DC552275BA09C01B601D55E97AD7DE83A32B962D0A9053C1533600FEFD1171C638A50922B9962C195551F81FE80BE28342A13ED0B25FF8986E0E9C39F3C2F29B9F40AADF8CF61E879A7FC863B32F02C5B5BE16F0E2CF00F30E312820E84D09BDF073E0B16B1F32C73F0E6031DCB3221DDC48670D0F2DF9A8065BD027C30DCF9F12782C812753F109615828997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8B28262B6C82510AC69F4785752AE1F619E3D334170A4ADB4DAF3138AE90AAF8D82573E7AD25A16243E16650219C47F4CEBE6915B433B0ED0354EE62FABFD3E118AC777A63316637DA755A99AF97DFE9857B2F58A83ED70041EDBC49997EC93C03A7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE458A65E6B9BB209359F7FA47B95EBB79C83F329ECF88C7541446868CEF363218841F55D346A2B714DD48C711555BB25B1CCEFA6199A0E7646646B667634E486116C0AAD7E977C091A5EA356778C299EFFB7DBD3232C4B73B54C796BD1E33284CC8E4354C772DF1CCF762F615715FAA903D1551A67965FED6C7E1ED7BABB9325AC30F92305FC284724C59079B11D1A0E32F4665AD8390B34968D1885C9EB8BC5DDF63D7858E042CF7C66FF5E36365F1C7156C79CCDF596EFA551E203456E5BB22C2D9B742F490824B1D5EE482F335393E34E69C7820A639858C6EFFC2E8377876E461788FD2736A2D1BAAA432B008850BBB44FA193DC54757D8C75760638A12DFB614580A882EBD945716D7A3D3D29396D4A0D267B07B035EC001CF29C87E23D8446E21D604BCAB110869FFA98C32E35A9B6C878360FD7BF8D564B09384D5C52E0C9BE0F45E814C954FBA214F3D3089AC4D01ACBCDB25B9331558FE1D29E67628E13BFC928F7A9A88D13E0759B77674C3F2795CDFE0C6617022F9C6A87B60C4B5A69E8D1706749FB0B4E086C94B5BFC16CC3B34FF3B7EC227A5CC646E9A003E5D897871067191AD1F8A8C33A0E567F4DF2D91D00FEA00B152183D202BD72DC0694F16ADFDD6E44A248D80FC6609E601CB91EE691C4535CD80BECFF9F23F32BAB5F106234A8867CAC0B5269CA2BC588E48AF922B5917BB6813E9D1005F35CCBFDFD419404B59A84497BCAD743384461F24267C497A932411B690BF405A7ADCA63858F439B123201F41AAAAA4D0A478101EDC6AD214E025B5DB6D24021464C53FB376503B6CAF4E4D4974E072F8C88A7C61957239581B589ED8D1753844ED928642CF96E5ACCA32E69B52CFA3AF54B9FF793E7553CBE16C4F9DD6114D1357E539C238AAA4434C5E540AB31FA584B82AFBF419DC51D6B08FEBE34B7991EBF2A82FF8E94990BFD02764F7D1DC049A635A08B7BFDB46A521170B6B8BD940883CD4505224D9DF930E33C5827E303083CAC4F846D9CB9A6E3FF57E755C7CCA541DF51819C5A52BDFDF005217000967A2776F51217813B2FFC509EE35F8AED6481BBFF5D5E61732BA17C90FBBCE1FC29E8DE849C146642845F982A2F766DFC0A703B5BB612E4C2B8CC426BB56196D714FC6F1BCAA0F19F32CBC06C3DD1406B591D2B0CD0E834D003CE56313B66C224594354866598118C87C1A86F7D247593846100395EE6303E54D130F91FDF81D0DFD021C274AA9567B9F9A500F35507519BCC25535407E419B52FA4D9ECD3D53F467B6295505DE979CBF6C7BC909812265ED65B30269FA1500264347FBCF1CB34AC5A405F208E73DD503D0D0E15FA474802F273C76C3D3DF98070BF3151D5D338DB368DA0D2280BD821880265763EAB2076766540EB9A51EAE647B96CA4326C82626DBCFCA1B3FF6DBA63DD64AEEA6741FA49E358E97D8F60C7F1A56248E8CE18933CD6F850E667134F69176DFBE2A4FC259994ADE12676F63D483FE16F7658F1003C1561B8D46FEA0888D2C82A4254AEB9E4104B9FBC973CF836BCAB5E263240ED9D87E9C434DC66E8F4A7B73EAEB30BB745F4094A4B82EC96CF99219F557ADEFA605DDE957CAD9D5343558A9A0904575A7A954948DC927E71786394DF40E9328C9B4382CF4FD8423B97088BB07CB4B257E5AC7B817088C3A6912441992153D374D477EA4EFD21C9F706D3619634AF7DB364F5FE73D12FF9623B665980B98E83991215E188462A57C4B3F653E11B4B1E16522CD421105A1FE67AD0F58F3D4AD34A8BDDEC13454EFD5FAC6146012476391769D4AAD22B1A0BD1CE9599600EEDD95DD265C4640CB064F92C22B0C45C64FC411375852E596F268EB415B03DA88ABF9A089EDCC5F06ABBD96E1BA461D4DFB3772938CCBE093AF922F5CE290295EBA2289660868ED4B6AE38B28B1ABAA06B66BB97A5396218691B13D099ACB89D6754517372564CAB054763190677139C9E2F0BA2FB19D0471E49BF6A0DFF2F951A414ED5D0F17C729891F4EF658F19FEB6D31F0BD8EC15DC9F9CC1FD73BBD7A6CA326AB06F55078D4F2F90CF185849567E8C78F2773938A916FDA23279FC3A9D62CE3C3AAD309264EA076635487EDE98CE79ED297D1BA99D96C84EB712CCE028298C8BAF5B5CB3EFB2EB8996EFFF6F7682D6EAFE498B886FFDC157AE3995D8493BC6B51541BE6862B41B5A35AC420D4D120957AC00B6E488AFA394C5C3F99DEDB4BC4AD4127082E44F22194654D3FEF9CFF3AFA66A764864D8344939255F4BD77942D6B2063FA9C0F82DD3B8D9ABF5C633B6CACB152AC09B9DF3BD12770444F99843FD913E2C815368910DECDB46DC4E13EF2E89AC3FC7D13749B88197F633BB6044E1EA0FF4CE060C7F426D01D0CE94833304CDEE3C857FC7258DB654F49E7C949C4D4B2DDD689DEA7E0C526E694B5EF77F8DBCC199F73D833C54C6C389C9C63A9E203FDF4389D83A4DF4AD86D7B36D3847C8DA829E04E31BD81791E403D6098AE9DA476D75B357A74FBE2F0C42FADDA27AC72B653FD87A8D1D72E72E2BAF5D852D1FD6DE10D5A6A600C795F65A4A59A00E2C503DA0BAD2344CD62FFFAF6761831AB2CA4055C18294DB1CCAF2BC6A13DB522CA1BFBA9DFCB930E4D6C32EC24DB5A8D5C15398CF2202878D240BEE11756559F26355C059A81765FD0D993FA64887D5CB6EDE1B379B2B8B5D5430F3D7A6ECB8259220DA7C9106CACBA69CF6444192275A2C6EDC588234E8D24985A0770607FE1C4AE8CC7559B3687522EBF7D3CEF0E19B229509D2A247E8650C3676B3B272340EB71C69064FD3CE931406569E7AC1603E49A13BEA93B2892704378ACB4796CEA77687C98E8AAEC3501143271E504408CA5D7ED271C45A1A7637CFABEA8EDFCB11DFF3F8324C8C2C7D9C73A26B8B1C05B6F18013E03928FFFBBB5068FCF4B29FBC21A5819EF85B91B19A5098883EF40D91B7E287749A578E7743680786FCA565BC4D19AAC06BF70C283E7649992BD6BC0305A0A093B75DCFAECD7E049E16F274AA9B017CAF3F5068FECB55C6FA6ED97F64E17CF1CDDDAEDB45036C6B2227A0AD5181AD7389B72C8967B8176E18CAA3506BECFCDFFF15B598C47D10E11E65D9AE8AF9AFC8B189562D98BBB02EE55D0A5C41EEFFD3D6E8EE69878B3A003DE7A52A98978892E51219387C24BAA7A773944F530816FB27BCDCA933370CB340781A70DB5724C597F72F7A34DC05B732FEB79A18171281AB7A94DFCDFC2C96DD00784F2E67D7E56D0F146F1585EAA1448BE1CCAFC6F334CAB07A27E524BEB95E19D426689B900176A70B21E32278F27EA3BAEE623F92B14696CFB1EABA0D90EDC414FAAB03AC0572B4B8836F071A375849BCF46E83A05979A4111167CE5C43F6FF48F386E3E8F92FCA1655E3ADF4C2123DA2C5551E252E9BFD93276B5B2BDADBC8F23C0406875614ABDE72C520002AFE6F55BF1D19ADB7F26D4F71842FC66335FF670C60583CE65DF747AA6DB218471551478BF36140DCC5C6B9AECD22944CD2B781A240C914D2BC4B37877709794CA33ABA878615050637B0A0B3F04DE2FCF37A2442A242E6C97398CF483260BE8A092F998EEA5FB5519EB25BB10B9350AC7F6948CE13DC282ADFD3A251C07E32A25A8A93276A563755B3164C0A9510260425ACDC093CBDBC6C8C5D0FEC94A6DDB415C80D45BF9A6D8DCDA606E3204EEF6AA291AAC9AF7122810A77E0E1160A461AED63687B3C137EC40897B972493F33636B2CFF07747A394747C0887C0402CC4F50E78F70785E5DA4C6084BFD7AE379F0AADBA0CBADF8C70C34FA7A6B0C14F32D52FE8AC726F750DDDA95C741131C7F692CAF7A3A80173479690A3CC0A93D1823BA1AFD5634A9D14E17E7858221497CE6934D7630E73D615127209FA239A190EB60B4D49770A1122DE7ED76708CB660EC4E52900D130C9A4638448CBFB16B1943D7C007D521F945D00D42CD0AE51FA89D5BBB9DC68360C2551D3A0E08CB0025B061057FEA0855305C0F6496903EC94DDF067E722AE07D06AD5AC67A1B5A9D1D036F4D157220087AB098F2C6A911F710332AC3AF782A6747B8E079F12A768B9372BAA222EF43084F65A46EFBDC5D8BE794084FEDD23BB2BE82A7FD1C5FCCCA0E10FFF7CD47FE805A43F82E73773670C4F43571767DB9F9A59A16B1C6DFF3AEB739FDFDCEE27D8699BC080B9D5973F30BD546DAC6DE594F91E5C2F0DF432099D949C5FD0E9ED66BA4FD37F77CBBA8D511A0D712DD62859D6E3C0177A264EDC37393FA86D8BB241B13A2023CECC4A8A57242DA1C7BB796DB4B50197F8E7DE6FD645C6B9099D6F76701B0A36CF2DBC1C9E2F56AC8CB222D37682E19D33A1728916687BE117E14BC7D137CE28948A0997FD9B25545316DC91AF2780D34EB5D9A262B327FE0E57AF30D9299C1CDD7FF92E3CF8C70A9CBA640A71425B164DE8D2D0D78A19853125F684FB1E94D7D02473BF12C6537595311354BAB832C69593F4195132C6552176CD781A04D4293BB9E329B78AE8929A249AAC01C5C81DC46DF707C914E08A642BF4B0277302BBFE3950EAB036CEABBDDED57D2AB2DAC00B61474150F0F641A571573A79C7CEFE5B1E08C2A0D7C144D69764BBAAA9DA45E8C1CE02AD4BDA14E86E6F4509823913D553117C25BA7727244D0A5F4106962D2441C4D3813A780757E169AB7DA6FAE572D7CB919DF7BA028ADD524236473F8CEC4509FA954310D970F13B8F57505F248413F93CCEB0D2A8B81A3B6B812422E630863D5F37142EC8B03444B7509B92C2C46E8B7DB79679EE93FFC1DF1B807E29773C0B9A280334CD97CFFA2AEAACDA2A662F8767A323DA9D48CBCD419ACB2EF27A01A26F7F2968B572B679155717F7AE7CF17987EEBF9B088B153D06F88F683CD8A53B1D69CA429BC5D17DFF465377F6895611C319A8C8BC23438BED492817703D83BDBB93CD491EA8C39122ACD809BA158D5951E0B78FA5409E63E7CC69B5B6BC9BC56349CAFB05B71BD8C8ACC90F929F58037617118351CC1E0E0B3CC4040BCAB505CA4AA36C06277B4D550922DC424A005854FEA6EBE6C833980D3F7D49F38F595E3B156B89809B65E62B57E0C79947B2EC463027DE21FECA9FBEE0CD5B8EC64BB776FC95D93232C53A5A5D8F5954AD65E6BA6A3677C62497C3F4DD408AB08F2B05E00F865CAC6983159D2E4EB54EC0B89384F890E6033F71C5C888A9EF25C2E5563F4B79CF7F80E221C59FCC0CBA7A56ACA182D6A22A77AFBDD2209D5BBE8400605B918912E1F8268EEA13534E86FE8B6588ACF64A1322DFBA8990E280AD5A2E185DC29AE3AB7AEDEBDFF8932A21ECB57071D2C6207740AB48DA0286EBABE44AB1566D845A6B231073076634B6493FF5F4669CE06BB0BEB477C3BF2F9173ED7A36C22EB347036E7358BB62192E4E7BF5B9515C6A433D21E47F56C886AF92422741D1CA07EEB3A67A027283E78A27B64C89AC0EDF6D3CA5AAB03AB2437B7813BC5E349434386F00F0C0D592256BB28E68D0ADD1F23F001F2F0DC867BE42CFB316FCC3AB7F2ADE8F262E2F2A817435D72D2B9F181E285F7D58C2E9D0ADCA7E67933CEE6F908BBF182523A0367EC978CAC6373140022E3B851EBAE9D7086C4191C0BB856FBA1C5785F57A555985D0060A4BD79FC0FBD7798CE46C543B3D26C62BF07B7FFC0C5CB00729D2F9DC75A8A308AD312EFDB71DCF069034FB4F970969B749BD6F487F5E77627FFA00F64DBCF819A4F8EC0681AC3816282EC1717DA96444B3EC00B32B8C07E806988EEE0B8CEAF0CEED4F400F27F1D79267AA4BA333E61B84E6F10222FDEAF05D3561F5796CD819C879A07E780BAE63E780C05F024F2880EBCAEA6C1C8258D94B753BEED298829CF221BEEFF249643A4915D5C0E8AEAD2C85ED170790074EEC22327260470E99DD940227A671D56A9204224861E56624244241513ED4AC7117ABD09523C29C4F23E0C41900011215540597EC1BF8516CD28C228D03F8C7A65E4FFE575C6F5FB1F833B04F3DD1FE2DA3F983FC8A6BEE8CD7FDCFBB4436D8E8F09D466CA0129B4080F5C4D2A078B1CA2BAB5B306B26B4F75F49335E128D5E27B6FE1D96B9B863268E813A092C5176087562125530D23E8F6D61D99ABF133B032021530A5FBD7CAA65063B17304B76498D90B0F3E6541534667952F6B31A74394000AA731CD42D2CAB1EF3AD7AADBAEC7541D04E60B843FD337D7D08B9991452889376EB57FFC5D2D454B35DE0BE42E0B04E5C21D950E809C5D499AC04DE0E4FF912237DD83AF0FFC5CB8E520493400C91235F9D49BB30724098295713F70ACB57194F53B656D4B3E5879E2E28734370A052FE51C8139021ADD0DFC6D3D8491AE9C7C8E3AEF6A5C1E119D65923212BFDC35792BB5E3109BC36003C17100DF5302C7FE73ADA012B36AFA5452CFE356C38E63C59E80C1F3FAA1735150F1F3CE87E7008281D125FE7627B3D6C8DB3A2101DD6D650656EE5B8E0E8F0CA1DBEE12303499B6CECE8AC80111C504804F9ABF9C616D22DF34FBDAF27C46002B5B7260F47253C1A5AC8745639F0E1833808F7CA27BD437569D38D2C4AFCC5293E6C221D9872EEA5B33A43C5217438DFADAAD8F243DDD779FBCF4E95C6E4CA4E11125F9FFA93A4F04D385175435E391A7DD4C026ACF110F0B0CCDEECB8DC1ED8C24AAC7B3499C0DFE478F292B8B46DBD70451F459D0C5487C973DB0D19E196A66DC3D611D3BE4DDE59128AA6229BA0CDD9077B20F9E03145EEA04CD0B2FBB5EF90D327C1030B15DC8B5CD259EBFBF04A5EC67C741F6D38180F9B0F1FFB97CA1D0C0C5C6C791CC92908B44374BE315D4545F5F7C10DEB4E94B676D47D08C4A0C7466803F767C8A42BB0B74B6E85E11C6BB5C7EC3A8D543C703095F2077FE89A6CD8F450DDAD4007C1EFF0E0CCE2ED78F8CBA8FA0724D395C8B7714EB2CD2BB4CCFF497F09661F28A04B7AE27C8324FB4840336EB48BDFAA240A39BE662A93F5B12682E80964A14E32F9513051FCACDFB4AF64D835A1BDC643D421C9C667F7EFF4E56A7988FB757281563991D1C6B5B0C97E1C38B9185D049B4A95124E6248DCE7073EE9544DBD370AEFD8291D1016D0995320B2675D300A28C061555D9F29925CB9BD253D214E1D4FF9141467FA3449674A71A800985A0656EA2EE415366F474DA24B9C899F26B072E7244E7CB2E76890A89D42E6B9B0AECBB5180D6EB2D34954D4098D10A36511465340E3245A716C3D37A619D0E36E129A92C205579A7AB47A6284C06E7984C714DA51CD825033C241C11CAA0F2A930DBA13A28BBEADE973C6E8A838A62E04B1A5AEC0C72A4A2B73EE9925DCFDEC7C65CCD3D4EB65621EB7C90BAC3D36D8BC3427E0DEB8F253E221605ACCD5F6DD73A50FE09215DAE82AAB23DF4B86910EC72E3EE515A746FFE7CF903077F4D13B59226DF6D94A528F57E13D741DF28C45A072A41C01CBE1EF6587D9664CDF4B8A3E2215F667E2970A841EE78F7E14CB1839199163AA591EE9A2B5AC639623254BA87A216FAA462C5F9F8A74E97C24FCBB3D53152ACDCAC8A32D5A18C890004471F9A43AFEB325C767807C66EEECA54A594567AD7D4E9135DFD212A01536B32D590B9F662C17AB9784D8603C618375383BE8FA258651259EFEC97CFC616C218E4BF54A8D84E4DB080BF25650D8F522CBC33DA5BAD3144C134547AE090930BADD38EE0EA02733B057F0CEC2AE05FAF9E494813DDC49DFBE8557E80650120EB1C9003A5F57D330888C56802199C89EBA3DC085ED5DE5C0E469686850AAA7C9DBFDB47C563AA9660B079A7E23187A2E8C57AEF291FA99B0EFFE67A6D43233D7F84A9E385403DC49997BCCC69F0CB3C6F707ADD2FE0CFCBA5410DF3735306F9D2029872992C772EC24635DA6C73628A1F5789ED2E5D91CB41F2C8DCDFE641A1361AB283A0BE8446A5CA187983E34434191C64DA727D6088F90430F1482FBD5B7493E15D3FFEE375680BDBCC812B93CE10FD51BA3A712C3130DE63A77A79DFAE2C946AB370F8700999B0EE37A1B06484CC4D3859A4308DF702D40590C5C14BF8CE6D6D2872A060190B14FA78592DE2D8B0766DDD09276BDBFE487FA6621A5E1108D01787969EB8043B236F8189D2FE9E60E95EC52E69D156E20B435C5DF5A98F25E829EF3C15464D1883277A5EA42AEDC83FEAC327FDD2EE1D9A0331F06DA74BADD8A9F80432CAB5CA1A81FFC79A1F23E604112DEF22E9854468592BD2291664517CB91C80035F1A8DC97A5C8A0501CBBA6F47213D8FE0C556842324BCA2ED74EEFE8F6CC896DD4794478C07BADDD3AF65E580664BF0609BBC243280C3641C9A5803E856525410755770BDA536F0C722612AEE5CB643DE530DDD0F7E68A8EA1FF9D1F08751BF99CB8ADE48089343C253794EF22037AC8EA20A28A22242EDB9F9A682F23D5E51E05CF68DEDC4E4BBF593DAEB24E2CC69A08F35106558D22DEFA9A696B6014DDD99FF8BC35E8DF6C2FE76F162F81682294A1D9444B9632F63144C0909890A934450E27DEB72E943076414576575834941A21152A535BF404B71F18CB4851C70FF3E167E65071236844BE4785D1AA773D641207323BEDAA64571D2EFEE19A59933F3EF8E7AF86C5C9C795E88322185CA8CEAD78CE097951B57CFFC98D9B4BC920AA3E67F502CA5C4A9DA541608647C8D7C6B8CF46C573F1C1EB086D416B2E20CE3B9F1F2C3193F9D3EED04E9AAE230EDADAF0ED5A297640AC642AB70494A6006DBE0F242DC002CEA1CA8C9578ABAFD7709B58C579E2A7C2DAEE05242D8F1A26F0B96442D65227084668FE64EBC1F31DC6D7EC5C0ED61307B70452A8B5B846B5CF3AA859F0B0ECABD6082429EC6C5C9F757BAA27F52693004B19D35A675CA00FD42ACEAE5AE07C6286F48AC02AE2E43BCA4DDB0982A40B411A23990864378836BEE832ACAF1A4BABFA6C3483A9CAA663ACE89844197AF9496D43FEB39053C4A03F04FD4E1DDCF130DC450C3AA99F85B34E54E4B7F372F8C6AFF5A17385B637169C396C230CBDC45B7452354F797446F75956ECE0CE4620EF515A6EDB2CBA3C01573E293A17A22A5C33EB367A8A9E331927DFC1697BEA0E9F6EC1303D6E63179A7ECF68B5865C5B12D79AB95B5E419C45EA2A117F233E6AB777BF3041268F9AF8F0337A989C1A24686B127A0AB21486A023E85C511351C7C5982B01484868342098EE2FEFFCF1339CA74F569E89F32EFDB11DCFD33EA1245ADC75BFBEA4D1CC707F7D52229A286A1BD4D4E69BCA878C62A8FFFCD096A741F8BE4B17E069899EC20C66C23DBB9571116C105814BF5CDBD71AFF209F55EA526D91858332457A486DCE7F4A5C46EB3FC8673D6CB46E2DE3098F22AE17745AB0BFD6A4E57CFE6D7317875912BE641651D98E70C940F7FE1BF9882AE12A52B76BA21255AA0CCF272F8215FDB211A506AFE5AAC69D951DD8449A5527DD2617DDA35CB1FCFDFAF6322DE113D48678405CA1E68B6DB9F005DD80FD447E045D6A5D3DC719EDB0223F14F92370E5DE7B22FD0189F6C7CA5FDAC1DFAC8C3525DA00707665040820A763DDB5406DF41C23BEBBE6011FACFEF3932CF353D6721124F8E8F2998DC06D262729071FD56F1FA76524815E4552548FD48EB6695B81C07A716E2D4BEB22348B4FD554A0A2ED702E6E2A51C1B621C6D6DF7C675D0169DE88A85F0E45BFC398D5FB2BEA9958DB9F05A82B5CC3CAD980B25415409DB4C0EA1B15F249A4ECE2CC71449C9219411CC81AF35468A8D4320B36328298CBEA852800113F9DC6A6E727B340FD8516277E3540A9950E5A8E64F0050AF7F9707389874BE4A616DDBD017CC0216DAF1D270EEF9605B26A588A285736B3574E6AA3B6F197DFD451FCC03F2B4F1788C1F4EC59BAC79BCEBA3253E8DB04357AACBB468E9C8A714366CA216EA44A764DE67989D504A8F721098CD0AB285456D21AD99BD11DA30A83054BA40BE695EF6C298E22F8D7269E995C5397DB95B5A56AF5D9BAAFEF08166AEFDE6612FB700BD797B26F6DAA7DA1A3ED773ADDFF19C592AE7C3FB87268406DB5B9BFD98D4C8CA02A18ECBAAF3FF88F7DB93E06A445BEA851E75CA4B8011F3A2E3F57286D691667E3C2DC11419B7DA22B5AED705CAF0B8EDC70F438D57D4D549D41F07955EC3E339042D11F17792EB71D8C3B9C464B54B35BE2D45A3E07EDCA62F86CCC96C6968C567730E3845D4C8B8D6675606C6994DFE5569260BD2943AA189AF3A3EFC8F63FEA89B71F2191A7BAB25BDDB5A02FABF7224243FE5C6CAAD0F7CC66A6C6FD9754F700E4DA2548843949C7F02CAD107FDCAB04204637D6714789155D2C61AD3930D6F8586EF5DB5515F673A8AEEEC8C9590598B16CBF84032545AD5C1BDFD11A92093B0B0B48DD98EA963E208A43E5857A0722C3A641E60C7C398D15084D8C4B35F4A3146E77AB439985209AD99296A12BAEE3C3F3E994E76387D15C2FAEBFF7B44BBCA08A9937E74F9CC01613A5A2745C3F3E0473373EB1E6B4E29188477CA96845A7B24C232F8FB9E405C715E3E8DB593B14FDBAB225165BF0B0612BE50214598D943BE032FE5D5D9A33C23BF8EA48A5FF6BFB80316B5314A9D73C07D8022D3431CDED66AE8326EF049B2DCA5E63C6354666D1656A46BD5C8B430A157A43FAB904BE87F7773F5683949A416510B361ED60D700387A5E1AF0DDBBE08017270673ECEA9FE1F59A4859E7C097B806B79019C7056E6B1B8C2B43D41F78389A1422EDD4FF13239F36C54673118333E1DCDEC960A524F3D9E3E4BA1DD9B62917E8820249A397DA3DFC9417652F02EC8995851FBBB668330EC8EF6F89F77928F54628F6E3AAF55940E6F73720533FC39AC2CAB0C8495FE09563D4A0B22C628DAA66D06855CC24E85F9BA30046A79BE4EFD1B9DCC6E098DF8EA4055B19871F55F71A07138F7ECE919D3F6EC059DE0A7A363C0E63A16FD8A9944150D65F56D4A0D1CE83CF4DFA3B79A87A3CA9D003CB578B0A862E8A8309A9F8617CD5D7D1634766ABA5CF5181B2DEFD4CAD9A1F8F2148FB137CE27EC8E62771F46E7A8AD1B370474B1BFF0A634408D56E33EBA8C4F4BA282D716E03FE0799D012C1B9D3F1EE3D223E3D30F3020C0E026604FF5BA9CA8F25CB0C6D1C7835F66BD1FECCB77B911C259394E8D6582ED0B83A44776DCCFD677E7CA0352569B227DAE57777BF15464A8C91A01547BF754178888EEE0274A0EAB6503A50905C3D04CBF80E39F5EDA193CBB574D9141AA553186CBF7934E9AD2A2FA730599D2910DC1CFC2AA8DAD926C58385BEE6F37203F94E5DF5688B9FE0DE1F67956CF2D7872A9A256382165A8572BDF85F083A94A94E4C08ED85FB17F2BFDDFCD4DCFC86CF4E608A6CE1E6615DD4EE79BEA7BEAB94B696F8EC236133067FA6417895B911914FC39971AABD1C5ADF8A1B46B34647599252EDB50610E4403CF05AEA437D1B23FC22BA4AFDC836FA167791D3703FE28BF015C7BA755FEE0FD33211AEA356FFCC38720D04F325DCBF5415037A0EACF799165D590D36F036E0778963F1B9B059A479E0E6A8BBF826B0D55399B8CFFFCAD4CCF859B7C226AAF04BBCF49260F242FE7665B72AE5B1AEBE3AD1C4FDE360C56F2A9F719E8B5A4679D3700F8483C54FC2CF99AF9814FBCCDF46A85A5359359040473A71AED3199AC0283983D8595ED6169FBEBCC92BF9CCC7A687B173193BBB636DC889ED448C942FD52BB8EE81BA817C800285CDBF370502BEE6273611ADC1EEB4EBF9A625AE0EFFA97DE9D0E5DE3BC4CE8B8CB1E07E79578BBB65984464F724E34FDD3E2B37D65886782874AEE3C700754D7EA76555F6A37BE99C25D3F7924B9F5C15D6D36E6F709AE41775902710A12E5568115101E6ECB68CEFC6C1E3EAFAD850677F925293937A7CBF1B545E56E20AF68ECB04595F8104D942BB3961B39997A8401107E938F74D6DA03821E8FC12D25B83958E720E544BC10D4DAF73F34BD23E19E52E2A3D675558BA09A6B9BF36EC3EB3EDA9E0F4CCA329BD2FE20482B7C424CD1A765DB6CDC7A5C3A0635A7F48F9FCAFF2245B13B6A91BB666DC0B131E4754C2D2C1E623122E73ED103B87DC55CB62A152DE41ECA29FF4DE07A3E3F85398A14FDF1FDB85C1A6202C0C5564C3F66796B7FB9D9481861271901B8281991A9F6F66DB8DD2ACA5B9E5FDF4197D61815E423A4C1DD61233E06C3499034CBD2490FB22660A966D4D7882FDE18CC041294B9758A5544F3A697CA7BCDAC81EF742221F56EEF86CC2999CE0C55503533CF7AC81EAE88AE83A835103E91F3AE125F46B3C7ED05B40737AE62DD89B82D90C22BBF36BD4C169A9D9D8FFE33E2E80D503FF0DC214D37EA4B81D9ED2704515C6E5B7CB57AEBB3A912109B8897E271B756C77D8B7C975E3F4697FCF8C1DD1CBBFD52C9F1BBD22E7DB82335E5A6FB849F5531AA9841B92FF1CBE5A34F4E9D5C41565145E2C69AB65196FEAB627BED94F77407F7A180F1AFC4E9D03988507831848F23AFD2CBAAA6422389D64C1667CCF290724D58E28B2B74D70771682F70492AFDB247A3C118572BA5DBAB9BB2E4ADA05E0D78C79F0A2F97AD053E87B43C8755A7B2C217340C81D5BAC243B9DC51236BB7977C2F84D6E765C579058C996960C0A548BD6BFF0959720C43E6AF1A94BEDBEB922A8B4A02E451E88D4FC8A29B92D66AC1F6BE6802B5CD979480264C1AACA5D6578F44BBE06230CE75105859584EA29D16C20ED4128A0EA85F4CA9A3EBDAD29D0B661D56784E0EC2F04EC2DA448FE96A3B9EAC31A9E53A2925701C52CDF1B19447F23C4BCD507909F3035D1F6BB9BB2074239D339492C6863337869B2855EE7CCDBCC6D4FD9131576DBD7B0B475C51970D3740D8F232724BF53C09325303CCC41645694D6A9F7A43A93464507BCA194F2E1C8159821D1DC950A3CB5E9D1FD829222E52ECB1AA5BE3FFB693766886FE328B33CF44ED3FECFA0D2EE91EC515A59B419D903524112CF788ECEBB117241C61FFB84E266905B4EADF0606D1F070C1FB0BAD9EE87EDABBAC32AFDEB276E3C63E1CF73C55FC76ECD8A275FC17BE731FD1983956B1454E5611192EE16996A744DBBDC88BB1E309425A23FD480477997C6A27B780396D4CE034063BD1684CDF49B42ED5D23FE2C36A8CFB0BCC4F8F3D029C5F233C9D28ECCB8EAD8ABBDDAC297371916B0F0025151DE512FBE03163D09E73776F09C5EB535A2C81CE454EFD21E27A51E8E746E018FD19B89B74923CB2C6136061B6F94ECF88BE57540FB784ED209BDF98BEFA822205B6EB9BA7C43DBF10E82A000DCEFB30E1B46ED4753F45F568368AF289D9B257609B81392354313ED12A0782ED0DA12049D4C3633639CE970D733B213C8D40A29BE5BF69EAE20F568BFC3E6755A423E22D68963FC2C85979FAA14F895FAE3A46ED30FF96D3ACE7B8A16B8527607915A8DFD7BC9ACB0B27E06A8F22E2FF223DF6826348E96F2D1F74995F0CE064B45B4944053E3FBAB1AB2336AB869C53B3CF65E3FED0C5B41B9B7860EF3427219FB2F47AECFEBBE00DA51FC22CD074FDD84990C1B70ABA87FE2FD5EEAA5A7E6D1B88CCF9AF31D6363DB8BF9728077B7D07B254CD768EB3E107C729BE3D2AD1146237B9FB53B4F9BFC4296099E94D35CD1B358123B1D28D78D010098ED1CADA99F82F5A0747DBF6D342922274658FBE819DB904D59977046F5636318DDE0CC440AC3C0474712B8FA488CA585DD81A7DE27EFE65EAB1BFA52A8CD16FBE2F56A131C86C7DD1F713BE0F5A6D0938891049CB452DCDD744665682C0E1F68EF9ACD4DE6776618492E822E5030D018443802B916A25A62DF68B95F847AD787C0848D2609487993893EA08733CFF496BE0FB34B21DD51F10A071C44837B9676A6F7343D5A2445F4B75314FAEF07E3E40EFEF20A32F8CDF8F82A1BDDBC7F96DCB3640F298C34D5DC72F7F262C8C8559066A4F0BBEC31B2AEC81F2BF690D4ABBDC56B7839666A5BE71743B38812645904BD1D1A9388FC18BD9EE7DD0C4DF20AF8AD4B50886867F0EE7B6C9ACAE5EE58ED2190D2C2637765F4D2784BC8DB292A12F297D2E905D1432DF48FA6F0EC3DB1612AF65B6BDC2B58EBADBF411C323CA09AE4B56ABBDA4452A2018FA5687720FF761AF1295968023628AED87B51716FF33AA80E4E931FBEABF76227337499829A6D79C7C6DACDAEF490CF021210DFFD0C27FAAA7F09BD37C5BC07B55A2E621C9AA9BE12598EA98AACBBAE1981C51F76C5D4E48693EAFC22BE0891F74BE3A115CD68FFBE55188A043D013B741044E59B3165C5A62BCEE94543B637E8E0808D64C228123E402CC047C45D9F63CB3E6F5CDE58F0199666F39280641623F48CB1EE9E76DBE6DE0986C71A3C91C8A82D51252D473A42CF4223B6045A73D9AA9F061BAA949660B1BA38BA3F4B9A2FAC838D2A386601DCFCD6F361DCFFF555FC9348735C1844E957DCFE0C7DDEA5EE03822A3A5E17D07419AACCA1E59E4E3B726D68E2EFE10394160B897C2CAA9A6AE2D7F9ABF852E7042B3B276941D5453909C2E9D80E0858769266731B99A4599B172A6CC20D7DC1F8478BBC5EC2EC8E387F88A63144DA10E09F17765C15694945C8496386AD0B83F7589DA9BA60888572B16ADF404D223FDE1B4D55E5D8B5D3CE2F5A492BF3B17748DA28B43216700BDB1352907E1AB5438AB1EE224749862D36524ED24C724940B38866C531CACDFFE38755A65375579021316511987CA6EF0B03F6E2D82A6B7D4CD8E310EF5FEA12B7D84A0CEADBAE39FAA04460E04FB2C4B1E759243B11A138063BA9C96242FAFA15FCE06ED9580E29B00F44F3E74A437C9D7541C5E4BDADD92D0179E86F84FA3DBAA8F1CEA1B4A329E56B0595C90B8670F63E942D42A47B30805D770D86F6412CC87AE063DCFCA9C353FDC3E8068E3E5A8E4C3D3B8E48E245B7728D6997FEBBE412C01406D869715AB2FE5432AB89577EFFA2C6FFA435FBA59958FCE9DCB9A3E9A748555AF0CB64D7F0D85ED5FB0AEFB361A411406AF6A34610CA9D280C5AD4ABC8F1B5CC4221FB6323930D8F0F2C7F1E79220144627D49B5D442FAE09A2033E1AEB858CE38A54D7FED0328A06F7075E206FE3434E00F09992C81F902742A2A0688AFFFBE257FDA551C2F0089C72F8B75FAD8787A4DEF71F6B39C2EF08E88A8BB0EDED81B001B29F8BFE1ECC36489135B3672C016052FBB824F4B3077E024794C3D1C1C11EB1C31D78A5F314A8CD10A228280C72E9D697598335D2EB05E256997FEB9977BE8A5F1472E5A7F361FF6520F58ACCB812C16FED197F4A967CDFAEE8DE32C65D6A8E176E776D80EB8069ACAB5DFDB3822EF8057E4222E2AA0A5E90D196DBB334EDAEF375D80D6220B069F0625CDF43727085BB9DD60DF31DBF16FDD02A1D3FD0932C4BC23586592F20C7A411225D44385E8CE6B17C43BB4FA6BC914218D88DD7815963120F630D178B34032FE24EE8C2D5F256D7005FD2FA005DF391923FFDD6B1A02DDE26D301AA91DF609967EFE772EEEA6D271F41F2623DD1096E8656DD44EF4AD4565CC8A6DB0FF5168C9552F9A08F84E91B335F3D18248B6F54F84121E17EF6BD48663A2EC9EAB0D20EF4BD6E27907F5D568F33659B2DCD64A10C82C82BCBDFF5296972DFD8369027198108E537D4F0F151D9E52D24360D38172FF8C77C03BFD97F904B50105E63FFAB45BCF5BD6D576C86115E90669BBA2CA946CBF8052D08C3C8F77333196822D3DD10B9955C4D1449F7E4EFC0AF27696929637533689D59BF3B03AE55C835A2AB28022A6738CC5F3FE43BB12DFB8BF1E0137A3CA5ACD5B0493ED71E9B575AFB0D25F8049731C85F50BE87DEBB3CD180077184EEFCC3233072E0A27A9918C0BB6B24E656559D2119391FDF74FA03BF6D982D156E54BCAB37A3F8C7367BA95DE2CB392E6B085E4AB974BADD8A55A4765F42C878E987782A59B9EC7419729869687DA4035147846B227E285AF50DDED91E9333B9EA118AF549280ADFCA75AD6C23B456CF7B222EDA5899E834BDBE2240C534B2ADFEF524AF4906BC66132EBEBCA911CFF0210B634767C0C163B94B169C178F0C7B40C641894A105F375758ED7BA6A1A2B6478F9E97A5D3ABE5F0097F6440F325793571FF212C4C53A38301C3E4D076878270DBFC080448E4BA5F048CCE407F963D2ED434A2AD17385557AEA88525E30E0C3A9D6228B72ED2761315A2EF649E8B483E231B9A21BFBF2F8F07BA5BF89C00E11C239F0C409C769419C748C506D878DF7D0E4F44DBF4900076FE304017BD3D6C87B4C20D92AE90729FC985BE4D9ED63C7FFA978957167E2197452392BD82CF4709A8DCF816C49C6588CECA3D0C1360BCA17F1F152DC439CCC3F153D2DE9771802841FC90943528B2D6FBDD00E88D091B11AF84CC4ED4F1E032180371037A94886F301ED534D63E1B92722954585CD167CAB7145AAC3FA46A692B8A3229D83FF6C34B64C92507F7433140480018374D78FF90BDBAA09354EC34B5AA399C5F2934EFF7131D6668371001A96168A0A8EBF49E6306D7AE4C624372677031109549F426108CA25085C2A40C808B405899C0CE905DAAF47B17617A99849605A619A03A104275AB9DEE9FF17AB747527B28539DDA5BBDD4341BE7B8613562A13CD37C3AE160B616D61C4E9D16ED85AACF2354D61A1506143BBAC9BD6958EF542C3641CEE7DB6A54A4D7251E653EB25E05B4C345FE6D06478E6FD39F73AEE17CDE073BCC7C19D4F239B84E5FD50CF04D928B7486ACF519C68904B838F1268F12C05FB40698585979C59C70AB2124BF99FB97E3CDA3441FDA18AF55DB4E5C39D3D75DE1F6E44950021288572D2F040253FABC31224798CE55E2BCB3BD976A8DCDD7C77A9797265187CD35777453C81286DB5FF66C6B9878619B45EE5BC62FB267615EB970B812A2B19A85B77F12B18D322DBFFE7FF462702C6ACBA478C0596972918F3054C7654A888879412FCE7232F084BC2818AEEC294E52980F854389367943F8C9D77B3050A71A475978C841CB373D37A3960B25BC7A257760C51133CDE7E50B78CF561F1EAB9E9A84B322DCB040FC246239F54DA7D7ADA41FB6026246E81D82E5E7C00487354C4525A8C2FA070963AA0FCE163AF71F5B522C64740D9DE5FD465E328C3F992BD53C2A66F44CD89AB53C19ED320CD6B1C3060A9DB6C3812818ECCDC7B02B9A854D07799F980566B8054045F656EF1989D6120A50395EB1EFDBEA3ED45ABDE671F2ADD8542A87B3727D3391E6125D1D950E0B15A595E23707F2FB9E7C597EBB3C571DD1A5E062A12BF9918DD7CFB06B80B71EE05283EBDA7A6CFE119079C10C55EF683F27CC9D06E85D26900F33188D39D2128B200E648ED30843460DFAEE006423B4D18F37D7AA70CD4209073C6EA812A67DA603A863BAD29A79C993C442BE5968A0DF0B7D26D56ACBD0AFB3ACAE7D42FD1400304AEF11E4D6B5AECD5CB77CC2C6E9FFF03CEBAC5DC54724FDCD47BD4A1D6EC45C6B5A0EFDBD97DCA8BAA7B6CE0F6323FFB6C0099A6414B5CE20A2F0109FC35EB142565EDDEF76754BA999672BCAD22B9849EAED945A7F112F46D9BDDBDE882A4E78DA96D38057DECA09C4BF232C0B89EC9743C6244CA2BFBF52A3285D758250EC4633063E0716962CDE9CD88E346E3579ED9D1F085909BA632EEFBD86536B205359A933F9FD148058D265FFF73902C85455339C92D178C6D26AEECA94375B0A4B7F293E101FF375E263B2561F971D7419983CF733C3BF50D77C4D33CAB9116E8F189A48C00C04AB7CAA471C360C696EEE43DFF6E33DC931ADB4E69806670F365FB97814E9367BE22919DBDE5016CE0F44E0465FBA667E751FCAF2DCDA33E5FC488BF1DD7748897D8C520E4A46FFA8F2A539453328E8C2BA6EAC0ADC1F1188F8D57EF7A28F44F7699CBE83D0E8F2E6AD098B921D1B770C1056BAD3B2B2B7D383E56C935400D84A50431FA94C88A53545656B62BDB67EB7B3E76E0E3BE35B99C529809F59C9FE65F0B19789F758B01C6BAB1A30A8A3FBB28B4EA3E14EC104B9046B70C228503D8E29291818F873DF242A3225C9DC7E1F2C27FFAD83C89C70D03ED21AA0C616137A2C2750A24B30EBBA9875A3074D922076F7D24ECA129549B33016182DE68A235C18AA78A9D27E6732684DAC97320984E441B9F65A5F5230C957B398454E2BA1ADE900CE36CD1A320F81E21FDD36A449A036BFE7410876E0880015BDD895D29AF0F0A9AEF2596BB022CEB44B5DDA25F5BF3EC0EE3AF476E28D5F60F1C8D104003BE1109792D3966DCE207109EF665552ECC29E3C0A887D0811BA980CA96EFDA9B823E1EB1F0E760F0BBB0DC9C8D2919402ACBE08F0E1522838ADAAC6B45CB71611ED85238D2E17907588715D328015A225B713F01300FA5AEF960DA36D4120722ECCBD6886DC08E57A0F68466769636712A361724FB2FBB4AC9775287BFAD7134D577C31170A8A9C39FD5F1557AFCC167B11DA412436F79946BE332F148A72351279E2E1E32522AA8C0731F2F312B893D4F24A35BF2C42279DB8872E70E987CA680DECFB29425A5C51709216A5F69C00166B9C971E9E02B52731AC8DA8988A8A7878CD368085244678777C7C1DC7B0C6340C71FAD6BE4EDB0ADD161D5F701B56E98CEC853AF23B3695AF8CA7493BCB3B405B2A3A5F247FED50EF3F0E5679C2AFA4C2F613AB73CCACDB655A97E00AD5F7F13 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 27688 +sm = 0000000000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA70108E5D31084F6F9D247281E725410F388DC94BF47D8D65423953F7BD8B175D8050E7A09B0DC1E96F31870177ABDD7AB42345B9BF49CA7689F703557EECD4C9FF327EA11B8824D0E94B4E1403A982CD894D9A0E85436647AA74A97735EF614234C47A8D490A5464AF68854E65606D09C887C8A95A511E76865A1B432139E0C164EE80E6C6D99D6EA3C828A660B7FF33E894955E19F46E5831EB21C675466E458406E786CDC1C6D52560A46A26FCF335479AB9678525B94DCCAFDB7A9B6959E00CBDA47DBBDEF5D6D974CCCC04C88FCDC86B9C3DED226919419949E1EC94EF5B162F13C44767ECF866B44F6B8947CFB4608F5F72F394BFB430C1D9513D81B13B05B495B25FB9169A3460E4AC08509F6C41627AFB5261A8E5ED535C7D0FB4869E1FBBECA5F998274C2E153FFF3CEB473D81B551AB5F85CA351B4BC225D7942733BC8DC1F0B2FFBFB477F46826ED037A6E7378BFCDD20578442F9E92BD6B03C8077EA3E89B174D5C4892BFC0417F1640D61FE20E88DB05BB1ABFD542EE6C14ABF5D244746A457DB0CB019795E480CCE9C457DE66257271565E72D03BAD5A02D8311B494290DEE03A74DB1B3A62D2EC10EA3C3EF2DB3375893598133F36B5B8F2AD592972DE5049C743089529695B028F2F72BE0893E59169E9A2376C64BC5CCAC5482E13DECC3723604111446FA56B31CB301051AEDB4E1533567612ABB95A8099FF158ED0D5C695A662B0EA2B85270674FCD635917F4F10D577CCEBEB8877FED67DCDEAC83360CF8C638B6D57B943C63DA7BAF63F99ABBAD2C9B47977BB7A57BEB9410160A61FAFBD48649A3D2032C1679A67F348E3E25275FCD9AF650937FEB0A30F8953DDF5F0562A9D378DF36D061DCBEAAC8613034756516EBF622F21096E206442A9A24E79B7D98A56EF751FD1AAB89A95F99301932337C4E7820B84B1DE9CA2BA7A25D6C3E4B7D39A28A65A5628A93556FA9F54E273B583F9A197BFF4731E0429BA00E66D42A900F85130532F5303C7BE837860BC82BC2CF7CDF0ECEA942932151BE85B8E8195CC2F070BFD482702182B8A4A43ED942F6BD3CBF9DE7E8AEB17EC786BFE2AFD21BCB353A1F77030A18BAE47C0D2B9F396BD8E5FF560328AEDB20C718E8427DC76AEED4A3F38D853470B7271A968B537E0F60E1979BC257B0A6AD433C67673DF7EAC9BE29415E55FFB6629F621AA5970B4F58A93F52564E58BCC84F2453E034B68E21C492FAAD68E2E6795244F4D34028C14B65C23E9F23D5C2BA27F67484ADFCD6EFF8E13E7C1BFE7EE5879654357E6A6B98DB099093D34E793C96AA96BFC9E1D6A851663336861DA97A10FFC00A4D5A8E4F1CA04A8C91FAB90346DA60FC80299F79BA6F8FEDB4E1F705DE37AB2A10761A89127B9757D0F10001923A14E18828A59272060C3C7F7B4F17BB4D470B214ED52B31626F1ED62F1D003C9AF2D41510FE1D89C15CE442C7FCE52DD7AEF5B65923DD8CE7C031E6718825D1BDD7C324F7587D4412000A3EAF78333B65C00A8540790414E83288FF8D9C9F2E5B8879D61077A83925E92D1C3106A85A7815F9CC0A00D536475C5C63263C26CF37929B5F2D4827B72B8B27B64DC91EBAB724047EF3EE1D4304B98D74984EC5E78F5662510C632A8A493910BD6DCE3B1EF3FFBE4583513F2B8D6667ECB86448E01139D394D40C1C23243D2CE8EB2D6334EFA975B68A57940B01E7AE65A38E77903B47056A97A9DF915AB3C3887E2C77DA350F5F8C4EED477B97F822CE86F520C8354A3E599CB7217AE688647A72985606BBD0720F6FA5C5B6F70E88234EE54AD711158BFAEEB39C98014D0C1A172699F3C6D33C5D9DC9BE93C7F3A5780F02AE964D131157AA78711B1A1FE5FAC4D087B5ED235135112034CEE15D792A362D046199906ACBD18807371EE76F04E4DEA69A68B75074CFCEEE3B13ED977BFDF0DADE5F5BA26D69ED191B3B47599B1CF4E28004F8C1DA229C20EE36147369CE8C9949F7E5CE56323077490807321869B9D7DC329B0144EE11C2608142C9A29446242BA70019E737774335AC1C50A0CD6E13B06E3499CDE6E9DEA640B89DBC09B7D867FD5AB1546E60AAA06344D4610348BA58D8269AE23C87A3B0A08D3B8DEBF66198403A17E0C98C14AC4A5FD5DD6D543BD9888A96C54644ECAD9B108AA9F04474BE804FFC6B0D772DD5757BEDF361C340C9CA3D9449895E9AFAD2BF923436FC420E668D3FD58E175278BC30BB57C0880833CAB3C77F12E98C3550A8ABD94869EB5B3BFF85B945AAE0B740C2A1AB94861181379BAA1ABB3B04E3716F43BE1FCCF919998375C849D7658B8FB77DEA0A72A17F5CA24C878412709283F7FFF77EAB385CAD8DD6D937172EC79F4AA07698FF6A6E4C559893DC05EA367C2A717CE120A7E2CB455011B3E98F8CB3799F0B0600E74AC1214454C9F6D1DBAD9EABF89C0608AE5DE2ED5D631B575F59F445A94E79190E6640E42F2A3DCAAC94A1C6E3D522B9682AF0F8FFE84461F7BACEF360D279EDD9537AD2838851E97C564BD2AEA949AA9FBD8420530F63CD1638B988724A1E11888CB9A2B11411C221BA02F0ADCF54F6F0BFEB7D77B5227DB43AC1360C86DFEDA86872B28FA47CE1C78A4DA2508F214D75BD46109FC202692A3FE21B7739AA9C39BD1B24AB82C59373CC06D3F92D48B005BBEC6C139005A872F0D032278DDCFEE8E636303308F418F73E3FCB7B63464E41C65227E6F51D5EC56D93D19E1D3279F668A13A2B3599139B265111473D5F8F73022D8B7CF740D798573335CAA3B04CEE0BDCADCC2DFD20E920A0B83391E2CFA2E0441B6473EBD291791F09B4ADA70A5286EB05167BD59BFD8C46427413D609827DE664819C8CF4522000CFEDEA88B1CD2818254337A24515536513833D8DB9912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70DBB81517936455A05C964F54489323E7A18431AC4CDA3E320A38C51634DAE5EEE35A116A3A2C931019499E44907A8AAC00D621FE3639FE1C31F4316EE530D4009C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC9D550F851D023315BE35A69C83D099341F6BA69B6A40E224DC554A3489D33729C9EC8196BD665514030C26AAEF80CD6E1BB9EC739BAA2B8E4A63EE691AD2BFBABDDEE2B13CFFEEAB7C25273CAD45409B5270678CB1535AB800679906CE77189DCFE05BBF92FB5E31F184CECF3C427437958F695917E343ACF46DA2B9D988CFE316313FA9FAAD49EDB72B007A7F3D6FC55A88E6BA784FEBE9737803AF05B4801CE0C723C0D15CD8E7CA8E237D4A1C0BB1413D369FC3F21F69205D428069EABE626B971A2B5698ED05BAE54218300BE8C4BC9A52EE5FB296BAF2A9AA42F3C865DCC1DDA69969F085C91D3CC5934567476EB70461B942059AC0F83BA10DFE783F5FB405F159563419B3F5699179D6F33AD05E840EC9227C592E361A49E31D99445437D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB3844833CA9CC7907865878A01BCAE7DB72BA4F7701F20523E0E98B27AF08AA747B57DB1DAAA1B616DE469C7FC83CAA1DA1D6BA6F0C2B0F7F2CB7A4F58FBF7FFEC292AAA7FC3B87E797DCA067ED7672BA9B4CBC27FE9AAEEA63C8569A567129990E1E12A8D23039A877F7FA3EA9B9359A842A19E33CDBF284AF95FAE2A2DDEB80030A8245A7E51131D27EAE94B6C38A8C4818CA7EAE0A1C0841E7AACDDF68A4C4491EF97D5F3F6AD8CC47D2489DF1FF96B7DD444D31DD2FFFDC69C9ED7F750526B3CD81EDEEE2CBBFC0BCEBE875DBB644B3828795D2B81DFE37E0E4E68F9A798E09588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE596674368D1D405B742EE812FB88947D9F5DE52083777E54C2F0A1F605027BCA5A12BDBF9CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318ECCE515F732608A96D4E557ACCA60F144A212276CD52FAC0F12C39F7F45565346B6EE409558FF37D5C50280099C9D75B688C7D873EA7D07EC6C9305AB367ABC2FEAFF9200CAD14D71DE9E1F1DFFC4F15FD0908C6687F585D9721AA773BDECA4C7DBDA2D8275C59A2E90EE07ED6734A09566174D695356166041C646F18180DFC5ACCBA61F1672213C3CA6933A5ED65898AEB4BAF534751900D2CF25A7A94C273533B8694EEFB366F4B3E6D4DBE7FF5FC70EF5341217906FCEC863502598936A4A0D7DD4267B1C0C6E8175CFB3B9B6BA86CF3094D4677BD57712235CA8395A6914063B4E2849AFA406B7EC6E3AE39B343EE39348D2D29A0C2319BB34655A53E1A816CD5FBAD3A3796FEF2C7B67BE4507438E5AEB603B1A0796293A274A3F3D63C7C1F14297987085EC271F06E8DC986CE41DDA37ADBB39613E6790644A669594AF10B5D7C2DCDA7190B03F77E69D79A143E9B7D8B42E18E56D1D191DE05D58DC29F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA4C86ADE353F4AA57DE2220D13EAC9BC8FE02D625EBE3BF2761493F180F968DE438B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE8D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB07425116F11D430A927D45FBAC134C59EA8E5907C35A59E0CF2FA548F9AA27A3530AEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBE6FFF1A2A91E8DD23131A7840BF7CDEA3E18E706A324AB688A5866B82EC18082D89DB83F78DB30D5CE6EF134BBCE7628AC017E6D6974B1D82E4227235AEC9862899B7A4E0E8B10A8AD0B19A54DE7ECA861D6AFA1D91C9CAC7B8D6AE536C458E176AE68697912D7EC853D514AD4EDE982FA89400CE895D3241E5610D0AFB17AEFE51FBB41E2DE044A00D84BE759242476BC0099DFE159F0CAF2187BB311DF2342A59C003778A56907F086C8DC9309D8E41703779C8E1141070708E02B9F987ACF3214A8E442B76121374DD243643D64283D01279A49154760E3567E46ACE89898BCD67842223D5B8CAB03DC13930BE7210FAB7FB2318BDCD92B642F6BF178BC30B4F959F5D8BE15F67C5AC4A4C81F1E3E707AADF0B4CD02982ED4E4E52A81EA2FCB60ACB5817849D53C2FFFBF7906E290BF76E505071913AE0361FDFCA4B279897C9DECF546FB0366D65C9F81A9B51402F3694F0B5DC600B7E4F084383B643AABC755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E6C007F614D3C0A2E45486C2E457C2E6636BC1AFB76B2A7FA351FD88399098C64E379F99B64A3340473DD46C11564937DB9A28C4DE3745308433153B2BC6D5E0D515C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFF0116375D404211C3D3302D17DDD0390712E06CA05FB4BB2AF749D3439A5B30D3E9FF4731822AE6607BD96108BD229A4BDA5ACF50F7185BD1C0F56CC56D69C008077082C0869F237A6F19D73ADCF9844686E3C5583E7D8FFDA636E70E989B1742ACA4DCE98101BBAEDA8E852555033A46F8DF4E3DCA1B9A09E9F938E0C1E468C52F7DC695389C21D0F425B4DB554FD5BE1FDC2765B997FAB1F94D864DE1B4C8FB1323A8D90DC0CD7FA7363AB70728FDBF33C2325FF97C59ADC84C104E730C85CFBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272D144DEFA2E32DCBE8CF7843CBDB9A67EAD7892ABCE9B25A6B91AF0B893846ADDDB6C26354D4D8B77B14FC2FA2D8D589237C4BAF80344C306439619E5A4DDD4630B558BC9B3581AB842BC8B630F232BD18D4BB10FFA1DD3805B18635F6A9A22CE0D470FAA2AB813662EF63C784628138499A1A3648CC877300401E61DA9A379FDB3FC6DD985CA26EE8093A24879BEF107C4D6A38017BE3AA5CCE124259C42519C6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156771072191C21BC3190193111CD3BD0604EC5427C6D70B1BF21DB6E59ED636342BC417CD9F69B804EDB6359C9F8E347AD253370E065D500CAC64BFABE3E420E39000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D00C27D20CB93DA243BB3270F1EF2DE68AFB80842E8BE7C1FD48BF0F5622530CE84C1D30BC69EE1164CC602F2522FA39158D4D0D30ABE4FDE43213ABD6E4D65E62FBEC9AA1D485599FB7ADF5C2C97B90C82A1DCCD2C44ED66CCE79EFCEDCAD0CA1366FA51DD03DAC9BFC60B79719033B32247DDA9195233329F5AA36627FCEC5E42F078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DF657C03A3914FD3BF1E82EF96AD7EA46373B0A4DD0F5655F22F754DCD35ADA89358DDAF6AFF78EEEF21010DBC6556C2C3A018E4DA1D612CC3EF237BC2B1E9E600D923E2CE04FA27CE8EE63B969F6079FF8551B8C06018E99D84669C059AE08081E3A1C7ABC19272D7FA3F2704CCF6E491AF93C7CBD4660410389D86BBA47BD5A0E996F788FB9CE600AD76485D265628019B57FC69631D5266E8E46913ED9142FEFAD87E26DE53ECDF43B352EAC14BF6DA899058228C9414E7323430F9357D6244E7165F5CA2FF2DC9899AA6D8C2B8DDE8E2C5FB7C6E02BF74F578823CFA2355F2FCA1F776C6A87943344A5E53BFA39559EF98C397423C75EB318EA9B5F375C17E7B46A8D592651E7D50E70233224592389C1EBD1EB66678AC42C2862A2C660BACD03BA4064EA38D34A7D44B32DB9E75ABC6B5025B504DEC60512A80F78876C54D36324C7143FEA85ECB9E66800E8F4004061EA7607EAB964DE3F9A273D2C7A4CECC1B4270ECFF87A254A139DEA1E0F0B0F6366C02A0A790D46EAC94866A82DD8349F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DEA67846512E96901F78E601EE427F8B1A7986FB8832D091D575C277CB202E87602D670CE131CC6023A9E83AF41486A04D62616C1E912D4EAECD5DC815BAC1C0DBDB347F6B5DF06B0F58441FAB98B9511AC0423ACFA43E0422A62AE32A48E935C6288BD0D2314C6A739A7779BFE24DD7E2D66E9C4A4111E22481688EA39F256224531ED241A9D35D395F340421F2D8F5C05B873052D2128CEDF4ABE49E609176674363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D02AB14858954A117C6B6F2CDF4823BEEF1904FFB4D841B30537D57C577968CDF18EC8631C536AF09B54D5887FC0EB11A70E86B72EF315FD722FB680EF03A3487434215A0EEA412C0D78DB2EFE20061576237453927710860F0A49DE0ED0C42FDE2A5903D635B19D4F2001EE353D7B5210E1C01F50251ED6E753635A972EC8C1914E36522B1B41BA51E9F3F1CE83BB5F526FBEC31C21983736E42EB7880B9B27EF6CAE0618E57F881193714D3E8B38C9E9056378DD79E78422BD7C4CD57D230EF44B38F6A107ABC77B8D5A953D3A3969FBB7DAB145C4F4615FAF8F2172AA2BDEB35C4A0494100CB9CE188DA4318EA5B617EBACE910A32F0A280C82AF82121720569232D71AD065E45268B36F92DDA13673529F24E6B83A865F3E266635D9655C8000C06478530294DE092640DFB324E09DB3B87497C94502BD46092D72DAEDFA93A0353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB51691B3F0ACA92B02FE916D2AEB98BD9E23313F49A0F44394883A432523EB5B34B690EF9C16B4D60572EF2D791F2BF403255A28D9BC3352B02687AD9200D34C05259FE0C93B75455218E031D59A65D4F571CD7F8B130A0CA1363BAF2D9895A8E8925ED20ADBE8FE96C34A6A13B9318AC8A23A7EA320B83B7175FB54868DAFA9E233B0F4B18CF6FC7D85F7A2B28CEEC561222C5051572B092F2FB269ABF1CC7826675F09949FC443EF723AB476E9E5D670C5F05E46DAE93837AA0F65A4E83AE2C71DD02CAB1038086531F93E163AD65BD962ACB9497C0F268876B5AD3CBBFC4C24EB2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADB0A78B6C1C4ACB8B4C97EA8C4CC3F3778CBF761AA653D9531216588A46701366E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC4050CBFA6FEF6B9FE785A59511CCCE21EC5AE3F429A07B4626A4F0C555A15B42C26A5F353E7A479A700595689D5734C39D61177AAB2943775ADAC879B4ED7B8ED826CB43881D2C1B5734F64A5490A4F77ED4DCB9775B258C18182B42C560E6CEE89A329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB041A19053D3003420EC262BF0F45F1C7CF6E55BA9001E4BE097329CA460D335BA899503CAE0D617BB7FFF0AD37076C91B1659BD448C05C49D9360462B4BC601536844FF2C635BB654EC5749FBCEF3288E41B8A7835B645E0BB501FF805EA4B39785C203BE03F0B105D17E513D50B7738E78EC18AFAB3FE134FD551E754CAA189DC4FA2308B6EED1B8CE87EBCE212E15E72C9516B778C1F62819131E2EFA7AF63BCF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0A2979199F43F2F59FB2C62E8AF2EABAFE9B89B71E75AF029BEC77A6A56F86EF6A4A7212A7458986D2DAC9E00CF68EDB81CA05A297B522D3CB2E0AC3146E4638995B683EC201C67C911C83E6BA3567D31565DF914783F41077E2C31B06640446A6D403F9D46BB9D00B3C436FE1FFDA80AD0AC466AF0417D18D5E7DFEDD7D68987BA55F545F3B89A38908BCCA1DACE0B89FFB49FBA3A67EE7384DEE68FD05721483030ED53913A6CFA059DDB451C780877E919BB86DDCA9E18814123CCC822A8F30D0AB4602815D2279398ADEDE00B23AF4EE605A771AC616CAFFCD3AB12991023A6BE6BCEAFB1672ADA631C6CC29827088627EF9380FFF46FC479E2B586432B58F95A824C0D5F08704C2B596A7BD0A36A52BFD8C14D999F92E676C83EA62DE54C3ED7ABF290BF17C48DD69F949668E11D957299DB6920D740252A9AFB65179FDD62B69D2A1A339CEF805FD258D83FD2F406841565AEF5E42ED7687D9D466E6A4E513E072A9EF6181016DAD988F7C2305A77740F196465CE30A35BF3D098781DBA2F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549617285753A9438517AA7159A9C806A19CE8B8BA5F9C99250358404671F36214E8A7B5A04767FF8C094A3CD74751835BD896FAEFD1747DDFBBE79F48148D56BF585CB0CBBF34300CBFAB9DB32469814F107EF7822151D158CAD68F01418F88B181B092970DACAE4D5DEA7AE39965D1929CBAB7685E758206D309CADC07687274657F6EEF56A657D3FED4D34C7FF6C9CC5F344F0EF4F0E752F83E06B8A23DA0D65A2C10C2D675CB3A214F5D363C35E6E10A1323579803E4268F7D868F4716BF849B3C3D8EDA94476BE7322891C36D6DF146075F11AD02434D2216351CC26600662BE0D38E1DFEF9A832B9F066718FCB2134115F33717B57936CCD2DFA3A95C1D4C4C98BD09D64EC04912C06C7C6A2FFDCA2801628D873EE6D0D43EB67FF0AC93A7666C9ACBB9400593C00316E05F0F5706ABD923D85DE72A0D1CA9F0774F5180B65AA578B95BD20C1FCC322A5B23995ACC9DC97CE3043B1A723AA2815314637B7667DE02ED0FA0924C0791CA09FA028633CCC594429D6E7429930C7F01EB6A134952E89B8CCEC743A23C63CDD9E161B5A2D1F1E0D005F16727A3B0E8B90C20656B850A4F8B5D400B65E91E45AA25A880B76BE09F226DDD4F0E0AEA00259E19634EBAD387CCAB556997A153D1C1B87AA62E5B613A5E02C65E7EE7DDE2E19D965D27B42AF8542066549A6FEFF3E10A93B349EACB843759F5E4EECA76CF82277BD55C57FAD09BE938ABB47720E49CED626AC860446B290C7FE9BC83DB0C7FDCBD5CA2B8FF6C52B2CF2556040B3792BA99DD43EDF1FD4CBE38970D235E8BEE40DDCD2708E432008992D3F9DCD73AD594171092909019E9BBE7A5D4A21EADF82C5C22D877F422EBC64734717C93A027E9EA7EDADFFBB8A04B465E2F1BDDA54BA30963A41978562C27EE91E8ADD7A95B97A1F9F5C0494C3E44AC5422759F971200B1927F5C37B003499B213C1CEF1823847ED4A308D7D98FD5E42115D49B1FD42C7405B55437E1C8C0226884DD801CD89163AEE8D74105F621EF2CE222B13ABBD14078943CE054E3D68F7E8D763948CA83876F0AB7CA5123ABA8C5F68679FCD116D03391F2A53F637D26EC486FF6363F0C297E1A672EB717107ED9540C2AAD46038F8D4C2B5D1D918AF6BFBA7DE46E6628B2C217672257EB98F585A4E4CDD87729BA5ED16719F869FA1495302E8BD043F92ECF8799DAB7B9C501DC956EE3E55FF30E6D565E228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023E10A68B5275694C30FA7BE9BE2392EE6B18651980A01348A97C4BF091DE3501B30B528092599313ADC93C8407FB07E740F784E80461A23A1DCCD78BE8A72EE2AD69CC6E63F385963275DF49AF300E5D468285CA4457F090504D42056F571A8D453903B85D7E63F893431A5A1C8A66A8E4C999F0592D75717940E296C8275952C4A8DC6E97B3D5602408DF3644E8A1338C856296C37B1BA8445883CAFB408EFB9A545AB53CD632C40659DC607F4937A4F364F7E3B47A907BD30D8558C76A8EA9EB357177B8B2639477433604EB74F9C2E3528215459533C1A989FEF107944FC8A402E29495F72F2C210135FD836028B9E21E76C6F13096DBD2BE9721DD2C35504D648C474907FFB896B014CB022942F308C3263CFF227D4444763A483658E728EE6B7954C48E3FCAB1246CED1B1E2EA9CC4D5475BD4FA43FFEF56AB2A2D779E9D206E3E657A2244108BCF55C7F4F97666457CF5F796105ABC773C541173B9E338B4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F9338191406A4C257E6B7C058565272FB78A54A46007F5550234FE9B7952A82581C08AA6A1EA68E497D663F82C5D20E9D1134816EEA319EEAC8E431A0D82B6D62F7B93D121D8382F0EB3DDBB9FCD43901C8AF1AA019A7160B76B72D4E8CA1228E5E9DFD49E24F3154F4A914987FD0264ADA4C8D6FF9EBB91C59C03CBD484E9EE72F1A98C3F97B9F2479FFB79DFAFBC33C8ED249286369F003C471C8B64A9B1546B1F31BFDD0ACA06AAB3EFB61E49CDF5506AF8A4693A7591498D9D7F8B28A72A10EC60F806A9955D7EB41D2654EE5B37C284F41CFF3F591C227E3FD0CD524379DCB384ACF486CE7B1E658CC743293DCF546BE85382FC40CFDFDFA407A9EA33AC46468E060524BF06C9CC109A726CEAF0811D0F857C08A3D4AEA67CCC0B17B2C38C53DA9F860C99E3AA769EE27CB7C9229207ACAEFE6C62D3ECFCA201DDFAAEEE1EC7BFD40086AA922961198B53C94BCFA97EEC1DC0FB8FF1D9448B6770DE4F5703CAE179FB51CEAF935F666F398B74BDE9FC87B01AFB6EE8B47490453198F9B38AA2259D2194E9EBC42E1C57994921413D6327018B91538CCB0B90E965564171D133CCD9E7F65E851971FB71F2C47B4592C2A52A4101D2EE7A69DCAB3852A56C4DBC9295D2EEC5BAD1B8A13B7EDE84768C0AF5FF0B0253B44038C236412ADCEC91508A76BD8D16E6D6BD5CBB3179B34DB8902863056CC65A4DD40B6A1929F28DFAE1CEC64A74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7E8104E8D9DB129F0AEFF48177BE4EB60236851F6D0DF3EAF508CA7F97E4D5814F71ACBCF00471EF263D3B5CD58ADEEF11E3465C704D90101A5FCC1C8CAC25387B7D6B83C7CBEF04E05BBA1766C5C5D804642609AF84AF3FA7E4572393761664021A632DA048F2A10C2A349E2E1C260C1C3CA6184BEF6045F43D9C767E2328B9AF5E48EFE8298DF69599C49CFE153BF59010741DEE011FFFBFB4EFC5AA4B5DE409B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F83369497B16CBA6B3104624902242C468F89E89322D299123ECDD8ECC98FD5C53D99FDFBBADB056D1034CA39CBBFF29300769BFF634A38678FE7BF929676A43CD0FC3161391877F0623D9B59DF30E28F5B47C0445F83B36F0AA67F6A2DB8C0C3D3F45738A4DE393D8675E286F4530AC810D244C621963923BEB20810EE32909DC96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A35F79B7F944D0041C0130B7F59B0ADCCAD97670C92355CCC8F0FE34612A088BFAAB33542EBE8F3283AD67A79EECC3E7B7C5D4CCC29B6083AEDF7AABBFAC8281B7D7711DED8D4CA70C383C5042272379356BB80EC0A9BB8E4F1C73F2D2DE1676BF5AF43AF87AA2B2C4A6826DCDE46E599B2F31E9EA87A816EC5D8163952A7384603C8FEC20F58E1AAC52188E42774382077A35700EA5EA2FBD04135593A7E40ABA137FE400EB63BAC7F417252EF6AF6EA8FA9CB3BABE7718FAC4A756702AD64BF1F912E6ED44DC6D424CD15D3E45BC9F86ABF7CB2924D7B4E8AAF67D69401F5609B17D251140842D7A94FE5D911BF2FD37418208B716D2DC66320743B79E64CDAC6F2257AD34D112E22F977AE6034068C0E0F089FECA11DE03396BFBD365B1A788B2C550ACBED3643C1E4F13618F904B40031CA9E73F9B13293DC92102B33FBC16C9CDA02E511D49394D5DEFB95770E5CC750801623042B7113D385E8BE8FEDA1D7F9105D545B18AE98870B1326494F9BC31B33EC24CCA7CB8E53F9AF1A7E099B0D9A40CCF40B085C0D406B5F1DD7DCA794345FF98F272F7D9A11C30CC5448D2D311502B7F0F81437B52EB11CC5FF11C1FD62B9A34E2E102C5C59D14A3326702F6B6862383B5BA1041A59B2F4E009161857FEAAE3F0C4006926444BE77169E9963DF262BBACFC643F032414200B26840295326BA1983CF450DDABD0DEAF05B3AEE35CC029B1E67729517B6555FDC996782FE0CB275645E739BA0BC75A08869998C082BF6680E2DED0D643F06EED3947CB24E4D240CDAB6B07EB71762DB159BD8E8FEBFF190763906FAEE1D307115E7D6697AF3DB2192D37468806FD49ABAFFD157647B652B339A8912CAA3730EDB23593BE64CE9A50A1622D43538926E5B05D878029C5AE57DB40072EBB7889423A948257F9E8684E5B4F10C09A22AC506B5105246ADE89409D3AA78C4A88181FD562EB714E9402F8C4AB2129E73FD77BB64F3F6752E5AEEBC4DACC209D01A274E39A84857736671BD0604C153703CEC940CB0D79CC433D157EC5004ABA2F359B80DA9FC04267584B2897B594C494883185E613283B939DEBE0F324B3CB9F45A6FBF11AB1CF2704C5F83BE3B8CE1C38663757828909CA4AC49ACC134F533F5DAF470EC30D2E8FBC66C9B6C58CBD2ACBFBFA2842E78DEA2DCB820CCCBFB17454EFDB2B1D706B93B0254B3209CFFECDA9F52CFDC1CF312EAE3035C1A3D75D8764F693350C2301864EE1A3797F6574AE38F66B40F82904FFE6CBB34655B99959759EDB652F6A3BDC1D0F24E8EBE1761B43E876A6A7AA29E8B1158F1D150E25A742B5FBC7161234A85B35803FABBC0AEA40821E9990D48BA7EF7E1A50178ABB3CDBEE228B40C8B02C98C5E8B70CFF650E570988E64E6F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257302026A4B5934CC6A417A99706CF783722DC2663F469896FF8EB4CC741D531F3C32B41F0BC6DCD4A32786747BE120B33718A94639FB4D754E0508B0315990F31555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE94149EB3F4A4F9779A1AEFE60FA343AC04323795C9D33DE8AF95219B8711B1168A107EF83062F033203511E5663EFA0C45ACF54432C9D4EFB5678332B5E164092612E42C61560D9EEC768594F4E0E6AF10AC7B3DCD22D229AFA8C022EB00AFA626C63E8E96B72DF979586867B42B8FEDE446A0F6807F1F1C775595FB5DEAA3BE2A45570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41FACBF13EE45A1F97C20748CDC3B4068D993D944D5A165FB858FDF4FBF88632FB826103B1276C7791C64195106635996700A71E299889131E533F7F060C7F96E7C54F02D2A32835106FEBE6D40CD4D56B57ED26A7431731B04A78CB5A4884F0CACDF007DA6E1C4195B2B59A53F31C48EF9FC33CC7F6BD147032A1B6313C7EEC43B1E46164BEBFEF16FADDB1A176FBFBE34DDA7C88AC9C1EEFD4F33B7960D847872B8B433AD5D1293EA480E6FA097BB9AE29A7C0270A062EF9BADDD796FD8EBB1502606E9262357EFCBCC9B7343ACBD03CFAE6907BE46BCD32C4C4C4722C8D3A9EBC76EE4CDCE71B049D688C42104B94A1F7FE6F945BDD02E3DCE0C345C047AB31E7E8051ADDD3DBCBD33699AD660C1CE3E25D203C4EA56368B19C77D498E67CFE083ECD3D36BDCDF29A148224623E0D70D060EC964B329186162C1567F7E7B5B6921CAC8894E88BD8BD6FBA1E8EC4081D35931ECA2BE1E72E32D7C986956EE9CFB07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42E63C0C23B6C61D15F2C9FFEE5663E3CC74F7400D0645219751B70C916C03C0C67159F71BC0B3BFA0956F026B91F8C2419D671D3E00D7F633DBD2DBE88126DEEFC7733C2C926D1D8B0C8BFB1077A700BBF3892F0C4F3E30DF78BCE0A340A8F98EBA5BD384684D1E0081C1237440B3A6F117178C0DE4F19D05D4241240924D9EAF9CA45E3D4231AC903C8EE5298A3445F01961D6D3786E36D24875E6DF3EB1D6C1BE5EEA0E060D3E0EED1DB2D4E795D35A0DABE4A745764F05A858291993541AE149CECC5147FEF0F3A96B42F38963B9B29466FD66AD46CADA8F10E2D53BFC3B823CFED410147B5FD315FAA62ED06429D6D3FE6E5778A64B5C9BB06A8CF5561EB7A8B15838AA226DDFCFD4C31805D53A6EB7D2DB861451027CF84218C39078756B2911021C3EAFC2E82ABF792C5012CFCA3AAFB0A277A9C9E1E515CBC4439D95B2A54510318F5D6EBF97C8DE2AE0D4FF669493AA354C25460D3C15B1A57AC53D7E6C07CA407AB1EEC4A366A637AD4081F0343433C555DE72B71ABCD8ED3C043532A61125CC3CA06CAA634E5F75B750BF262756A57E3FD235FA9EF00CDD9553D37968DD680EBD5935FBDFE43A82E9DD39F96FD483AAB7F2D0517F23727E8F4DACBF144E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A76442D207EFD647078CA9CDF7800804012D4EC23BA14C99666610A22DA87523E4E5E41A6698E5235743A9B9E1C4795F38AE20CBE5C3A2111ABA307C3BA6E03F092E96AC6EF297548A3F144ECF7F643EF19024B2E98B51173450ED06ED68EFFA06EFD60721E73C9C6993F14C00E3E4BE441791C648110F699AB5089D7CD092AAD82AE007C0C3C8659506D5F2817E75EAE8B803734822A2526861036E35C3689EDCBA348A7A2E4BE2F1E291F63473988AFFE650C1BC49CDEA3875DF4E6B541727B5AA6F04C9C1E4D06BC5CC744D1B955958E2578C6176AFD7E3262CCBC0F6FA21596BDC36349BF9329BCBA08FFF934E31DC1FEDB7D7F6B459BB1A0165043B902D600C447792A618B77C1671E5793473DED54FB3322180F198873E306E1F8BD17BE04FCD3CF4D6A9201B9B804BBC772B742097663C42F0FEE3766B3B205F14A39D6ABA56963D03DCDF538ECFB8A7AE64DA3C116BFC09506BACF5E8B5754B220F7CF70C5AA4492AB72D20CF8F4966A114833B057662EC63B9570D9B2DCEAC86590569934F91A61A03E18835E31ADBC2EED3BE0BC148FF004675C9555C901B280BFB56FF8A1C079E1F290C67FD1B7E53A6C27A5C649ECA9EEF836621F9E708EB84B6F5C529ED2F07BF0A6160154F41F323DFF8A498177FD09D22DB15A273F787529852D898A6DF0FDBEBEFBA3F3B602B1E67352224860125216AD6D68CA891606E179FB415DE4B95484CA6907319438F69337316203F06AB1488A471924545C81A470D78E2EA29AAF89E94920AC4B0E7F2FE01092BC8CF3839480A02C0E8DAC1E864C9BFF5CBF46C0FC7B6A01FF0DBBCF96E3585496C392C6496D06C44765878B26B6DFF2C2FEC20F26A9A2706838A2048E579C65F3BDDEFC58C89D8830FB8C75FAF96788998DD200D48189C3B59B41501BD310420DB96F7CC5B61A2EAF88B498ACD890F7DF623A35479472694CDDA58C000D9BC04FD903E4AB88A2E757700FF3F460F075F9876DB3F76F17003E01DC96A92543DCDFCD7EFC86A5C0DF387A50ABB69953D6DC19A699CD225941F82438A8EB7889B212F65ECA7399F89CA0D9B9915E827D2E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC876E4C5BF248F94C2ADB3D6C9F23C3E70D1F611A2041C7759317B8EC1696B2632CA10CEFA498D7571D016E102DAC10051DAD086BEC58AD5DDFD7988C5F433DE87C314E3930FFF937A6E0C81787F04B77F893287AB63125CAB8B7460F119D03BF3076A98FF029EA5022201DD54C854711B8BE718EE678544B51AB13B7ED0262C8180C2F36CBAB64D862D38AD7D8172AD8BA3380706D52048826CAC611B07468967CA4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F238380083A064421DC7CE13EC2F715580924D9B6EFBDBB0D45AD8952F602BDED6455C0BC2734CB135B79966464546A261D0A551DEB43E5AE111CD02D0F2F2E996454DE17B471C6103D851CCE2E1FEDBB828C7F4EE66053A57831C708C377FDC6FDF037F400A09E9A610350BE6C013239D7F1C42758CA84B428EB06C6A6A3E05F10FED769CEE2D8EDC3EEA29204605005468B0366B2E957A7A55FBCC7842598F55021E58DBEEF44C5313226E6E56A2D3837F2A098C94BEC791737F355E6CE5643C954C4719C6C1C939B7716A29191CF0530BC2E78CD028D526EC286FCF02B18A077C86BC54F078A19A529F6EAF69D5562D4B31E4CE3B953A24655429BDBAEB5378C13E5B404A138B2B5473A415EA236245B0541B6D92F384D4CE63680ED5A6C035FFFC663C893C8F51C5DEC6F90D33573A05CBAED63B69079EE77DBDD21AD7A778B37EA5E0543BBDCD47497F355B1B2D8AD93DF4BB96A5E85A2344192B782D54C4C8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D947DFA8260661FC9326B9E76214D36B22172C026EC12E04ADE3C62D4E957AAAAE686D350793BC6E9C862D968C0E56B3160B5C70520E9AC7767AD2BD8D1D6DC951A23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831EC44071AC6184AACBFA0A2326D7EF097650C1D4D1E58134408C11E839A0DBA17CAC9DE3B437E697663AC136380D0690DA4A52070A2DC552275BA09C01B601D55E97AD7DE83A32B962D0A9053C1533600FEFD1171C638A50922B9962C195551F81FE80BE28342A13ED0B25FF8986E0E9C39F3C2F29B9F40AADF8CF61E879A7FC863B32F02C5B5BE16F0E2CF00F30E312820E84D09BDF073E0B16B1F32C73F0E6031DCB3221DDC48670D0F2DF9A8065BD027C30DCF9F12782C812753F109615828997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8B28262B6C82510AC69F4785752AE1F619E3D334170A4ADB4DAF3138AE90AAF8D82573E7AD25A16243E16650219C47F4CEBE6915B433B0ED0354EE62FABFD3E118AC777A63316637DA755A99AF97DFE9857B2F58A83ED70041EDBC49997EC93C03A7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE458A65E6B9BB209359F7FA47B95EBB79C83F329ECF88C7541446868CEF363218841F55D346A2B714DD48C711555BB25B1CCEFA6199A0E7646646B667634E486116C0AAD7E977C091A5EA356778C299EFFB7DBD3232C4B73B54C796BD1E33284CC8E4354C772DF1CCF762F615715FAA903D1551A67965FED6C7E1ED7BABB9325AC30F92305FC284724C59079B11D1A0E32F4665AD8390B34968D1885C9EB8BC5DDF63D7858E042CF7C66FF5E36365F1C7156C79CCDF596EFA551E203456E5BB22C2D9B742F490824B1D5EE482F335393E34E69C7820A639858C6EFFC2E8377876E461788FD2736A2D1BAAA432B008850BBB44FA193DC54757D8C75760638A12DFB614580A882EBD945716D7A3D3D29396D4A0D267B07B035EC001CF29C87E23D8446E21D604BCAB110869FFA98C32E35A9B6C878360FD7BF8D564B09384D5C52ED4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A20C9BE0F45E814C954FBA214F3D3089AC4D01ACBCDB25B9331558FE1D29E67628E13BFC928F7A9A88D13E0759B77674C3F2795CDFE0C6617022F9C6A87B60C4B5A69E8D1706749FB0B4E086C94B5BFC16CC3B34FF3B7EC227A5CC646E9A003E5D897871067191AD1F8A8C33A0E567F4DF2D91D00FEA00B152183D202BD72DC0694F16ADFDD6E44A248D80FC6609E601CB91EE691C4535CD80BECFF9F23F32BAB5F106234A8867CAC0B5269CA2BC588E48AF922B5917BB6813E9D1005F35CCBFDFD419404B59A84497BCAD743384461F24267C497A932411B690BF405A7ADCA63858F439B123201F41AAAAA4D0A478101EDC6AD214E025B5DB6D24021464C53FB376503B6CAF4E4D4974E072F8C88A7C61957239581B589ED8D1753844ED928642CF96E5ACCA32E69B52CFA3AF54B9FF793E7553CBE16C4F9DD6114D1357E539C238AAA4434C5E540AB31FA584B82AFBF419DC51D6B08FEBE34B7991EBF2A82FF8E94990BFD02764F7D1DC049A635A08B7BFDB46A521170B6B8BD940883CD4505224D9DF930E33C5827E303083CAC4F846D9CB9A6E3FF57E755C7CCA541DF51819C5A52BDFDF005217000967A2776F51217813B2FFC509EE35F8AED6481BBFF5D5E61732BA17C90FBBCE1FC29E8DE849C146642845F982A2F766DFC0A703B5BB612E4C2B8CC426BB56196D714FC6F1BCAA0F19F32CBC06C3DD1406B591D2B0CD0E834D003CE56313B66C224594354866598118C87C1A86F7D247593846100395EE6303E54D130F91FDF81D0DFD021C274AA9567B9F9A500F35507519BCC25535407E419B52FA4D9ECD3D53F467B6295505DE979CBF6C7BC909812265ED65B30269FA1500264347FBCF1CB34AC5A405F208E73DD503D0D0E15FA474802F273C76C3D3DF98070BF3151D5D338DB368DA0D2280BD821880265763EAB2076766540EB9A51EAE647B96CA4326C82626DBCFCA1B3FF6DBA63DD64AEEA6741FA49E358E97D8F60C7F1A56248E8CE18933CD6F850E667134F69176DFBE2A4FC259994ADE12676F63D483FE16F7658F1003C1561B8D46FEA0888D2C82A4254AEB9E4104B9FBC973CF836BCAB5E263240ED9D87E9C434DC66E8F4A7B73EAEB30BB745F4094A4B82EC96CF99219F557ADEFA605DDE957CAD9D5343558A9A0904575A7A954948DC927E71786394DF40E9328C9B4382CF4FD8423B97088BB07CB4B257E5AC7B817088C3A6912441992153D374D477EA4EFD21C9F706D3619634AF7DB364F5FE73D12FF9623B665980B98E83991215E188462A57C4B3F653E11B4B1E16522CD421105A1FE67AD0F58F3D4AD34A8BDDEC13454EFD5FAC6146012476391769D4AAD22B1A0BD1CE9599600EEDD95DD265C4640CB064F92C22B0C45C64FC411375852E596F268EB415B03DA88ABF9A089EDCC5F06ABBD96E1BA461D4DFB3772938CCBE093AF922F5CE290295EBA2289660868ED4B6AE38B28B1ABAA06B66BB97A5396218691B13D099ACB89D6754517372564CAB054763190677139C9E2F0BA2FB19D0471E49BF6A0DFF2F951A414ED5D0F17C729891F4EF658F19FEB6D31F0BD8EC15DC9F9CC1FD73BBD7A6CA326AB06F55078D4F2F90CF185849567E8C78F2773938A916FDA23279FC3A9D62CE3C3AAD309264EA076635487EDE98CE79ED297D1BA99D96C84EB712CCE028298C8BAF5B5CB3EFB2EB8996EFFF6F7682D6EAFE498B886FFDC157AE3995D8493BC6B51541BE6862B41B5A35AC420D4D120957AC00B6E488AFA394C5C3F99DEDB4BC4AD4127082E44F22194654D3FEF9CFF3AFA66A764864D8344939255F4BD77942D6B2063FA9C0F82DD3B8D9ABF5C633B6CACB152AC09B9DF3BD12770444F99843FD913E2C815368910DECDB46DC4E13EF2E89AC3FC7D13749B88197F633BB6044E1EA0FF4CE060C7F426D01D0CE94833304CDEE3C857FC7258DB654F49E7C949C4D4B2DDD689DEA7E0C526E694B5EF77F8DBCC199F73D833C54C6C389C9C63A9E203FDF4389D83A4DF4AD86D7B36D3847C8DA829E04E31BD81791E403D6098AE9DA476D75B357A74FBE2F0C42FADDA27AC72B653FD87A8D1D72E72E2BAF5D852D1FD6DE10D5A6A600C795F65A4A59A00E2C503DA0BAD2344CD62FFFAF6761831AB2CA4055C18294DB1CCAF2BC6A13DB522CA1BFBA9DFCB930E4D6C32EC24DB5A8D5C15398CF2202878D240BEE11756559F26355C059A81765FD0D993FA64887D5CB6EDE1B379B2B8B5D5430F3D7A6ECB8259220DA7C9106CACBA69CF6444192275A2C6EDC588234E8D24985A0770607FE1C4AE8CC7559B3687522EBF7D3CEF0E19B229509D2A247E8650C3676B3B272340EB71C69064FD3CE931406569E7AC1603E49A13BEA93B2892704378ACB4796CEA77687C98E8AAEC3501143271E504408CA5D7ED271C45A1A7637CFABEA8EDFCB11DFF3F8324C8C2C7D9C73A26B8B1C05B6F18013E03928FFFBBB5068FCF4B29FBC21A5819EF85B91B19A5098883EF40D91B7E287749A578E7743680786FCA565BC4D19AAC06BF70C283E7649992BD6BC0305A0A093B75DCFAECD7E049E16F274AA9B017CAF3F5068FECB55C6FA6ED97F64E17CF1CDDDAEDB45036C6B2227A0AD5181AD7389B72C8967B8176E18CAA3506BECFCDFFF15B598C47D10E11E65D9AE8AF9AFC8B189562D98BBB02EE55D0A5C41EEFFD3D6E8EE69878B3A003DE7A52A98978892E51219387C24BAA7A773944F530816FB27BCDCA933370CB340781A70DB5724C597F72F7A34DC05B732FEB79A18171281AB7A94DFCDFC2C96DD00784F2E67D7E56D0F146F1585EAA1448BE1CCAFC6F334CAB07A27E524BEB95E19D426689B900176A70B21E32278F27EA3BAEE623F92B14696CFB1EABA0D90EDC414FAAB03AC0572B4B8836F071A375849BCF46E83A05979A4111167CE5C43F6FF48F386E3E8F92FCA1655E3ADF4C2123DA2C5551E252E9BFD93276B5B2BDADBC8F23C0406875614ABDE72C520002AFE6F55BF1D19ADB7F26D4F71842FC66335FF670C60583CE65DFA6442DC6DD49889C3DA3AAF0FB310C3AD990480EF12059DD23AE881D5A72603F50C7C61626AB2E0BF9C8C198CB0F637EF72954E04DF5956355147B5073EEF3848CE65EBA73E67955A1CFF187CCA758372FB67823E230B05EAA9982488E8D22F6DA1415A731BD0A2B036F858FE16FB4349149B507D9DF770B9F3D3B45ED752EE888F40FEE65C4F3EC6897906303A19863DD968C666AC1980F26D8B574D5A16C95747AA6DB218471551478BF36140DCC5C6B9AECD22944CD2B781A240C914D2BC4B37877709794CA33ABA878615050637B0A0B3F04DE2FCF37A2442A242E6C97398CF483260BE8A092F998EEA5FB5519EB25BB10B9350AC7F6948CE13DC282ADFD3A251C07E32A25A8A93276A563755B3164C0A9510260425ACDC093CBDBC6C8C5D0FEC94A6DDB415C80D45BF9A6D8DCDA606E3204EEF6AA291AAC9AF7122810A77E0E1160A461AED63687B3C137EC40897B972493F33636B2CFF07747A394747C0887C0402CC4F50E78F70785E5DA4C6084BFD7AE379F0AADBA0CBADF8C70C34FA7A6B0C14F32D52FE8AC726F750DDDA95C741131C7F692CAF7A3A80173479690A3CC0A93D1823BA1AFD5634A9D14E17E7858221497CE6934D7630E73D615127209FA239A190EB60B4D49770A1122DE7ED76708CB660EC4E52900D130C9A4638448CBFB16B1943D7C007D521F945D00D42CD0AE51FA89D5BBB9DC68360C2551D3A0E08CB0025B061057FEA0855305C0F6496903EC94DDF067E722AE07D06AD5AC67A1B5A9D1D036F4D157220087AB098F2C6A911F710332AC3AF782A6747B8E079F12A768B9372BAA222EF43084F65A46EFBDC5D8BE794084FEDD23BB2BE82A7FD1C5FCCCA0E10FFF7CD47FE805A43F82E73773670C4F43571767DB9F9A59A16B1C6DFF3AEB739FDFDCEE27D8699BC080B9D5973F30BD546DAC6DE594F91E5C2F0DF432099D949C5FD0E9ED66BA4FD37F77CBBA8D511A0D712DD62859D6E3C0177A264EDC37393FA86D8BB241B13A2023CECC4A8A57242DA1C7BB796DB4B50197F8E7DE6FD645C6B9099D6F76701B0A36CF2DBC1C9E2F56AC8CB222D37682E19D33A1728916687BE117E14BC7D137CE28948A0997FD9B25545316DC91AF2780D34EB5D9A262B327FE0E57AF30D9299C1CDD7FF92E3CF8C70A9CBA640A71425B164DE8D2D0D78A19853125F684FB1E94D7D02473BF12C6537595311354BAB832C69593F4195132C6552176CD781A04D4293BB9E329B78AE8929A249AAC01C5C81DC46DF707C914E08A642BF4B0277302BBFE3950EAB036CEABBDDED57D2AB2DAC00B61474150F0F641A571573A79C7CEFE5B1E08C2A0D7C144D69764BBAAA9DA45E8C1CE02AD4BDA14E86E6F4509823913D553117C25BA7727244D0A5F4106962D2441C4D3813A780757E169AB7DA6FAE572D7CB919DF7BA028ADD524236473F8CEC4509FA954310D970F13B8F57505F248413F93CCEB0D2A8B81A3B6B812422E630863D5F37142EC8B03444B7509B92C2C46E8B7DB79679EE93FFC1DF1B807E29773C0B9A280334CD97CFFA2AEAACDA2A662F8767A323DA9D48CBCD419ACB2EF27A01A26F7F2968B572B679155717F7AE7CF17987EEBF9B088B153D06F88F683CD8A53B1D69CA429BC5D17DFF465377F6895611C319A8C8BC23438BED492817703D83BDBB93CD491EA8C39122ACD809BA158D5951E0B78FA5409E63E7CC69B5B6BC9BC56349CAFB05B71BD8C8ACC90F929F58037617118351CC1E0E0B3CC4040BCAB505CA4AA36C06277B4D550922DC424A005854FEA6EBE6C833980D3F7D49F38F595E3B156B89809B65E62B57E0C79947B2EC463027DE21FECA9FBEE0CD5B8EC64BB776FC95D93232C53A5A5D8F5954AD65E6BA6A3677C62497C3F4DD408AB08F2B05E00F865CAC6983159D2E4EB54EC0B89384F890E6033F71C5C888A9EF25C2E5563F4B79CF7F80E221C59FCC0CBA7A56ACA182D6A22A77AFBDD2209D5BBE8400605B918912E1F8268EEA13534E86FE8B6588ACF64A1322DFBA8990E280AD5A2E185DC29AE3AB7AEDEBDFF8932A21ECB57071D2C6207740AB48DA0286EBABE44AB1566D845A6B231073076634B6493FF5F4669CE06BB0BEB477C3BF2F9173ED7A36C22EB347036E7358BB62192E4E7BF5B9515C6A433D21E47F56C886AF92422741D1CA07EEB3A67A027283E78A27B64C89AC0EDF6D3CA5AAB03AB2437B7813BC5E349434386F00F0C0D592256BB28E68D0ADD1F23F001F2F0DC867BE42CFB316FCC3AB7F2ADE8F262E2F2A817435D72D2B9F181E285F7D58C2E9D0ADCA7E67933CEE6F908BBF182523A0367EC978CAC6373140022E3B851EBAE9D7086C4191C0BB856FBA1C5785F57A555985D0060A4BD79FC0FBD7798CE46C543B3D26C62BF07B7FFC0C5CB00729D2F9DC75A8A308AD312EFDB71DCF069034FB4F970969B749BD6F487F5E77627FFA00F64DBCF819A4F8EC0681AC3816282EC1717DA96444B3EC00B32B8C07E806988EEE0B8CEAF0CEED4F400F27F1D79267AA4BA333E61B84E6F10222FDEAF05D3561F5796CD819C879A07E780BAE63E780C05F024F2880EBCAEA6C1C8258D94B753BEED298829CF221BEEFF249643A4915D5C0E8AEAD2C85ED170790074EEC22327260470E99DD940227A671D56A9204224861E56624244241513ED4AC7117ABD09523C29C4F23E0C41900011215540597EC1BF8516CD28C228D03F8C7A65E4FFE575C6F5FB1F833B04F3DD1FE2DA3F983FC8A6BEE8CD7FDCFBB4436D8E8F09D466CA0129B4080F5C4D2A078B1CA2BAB5B306B26B4F75F49335E128D5E27B6FE1D96B9B863268E813A092C5176087562125530D23E8F6D61D99ABF133B032021530A5FBD7CAA65063B17304B76498D90B0F3E6541534667952F6B31A74394000AA731CD42D2CAB1EF3AD7AADBAEC7541D04E60B843FD337D7D08B9991452889376EB57FFC5D2D454B35DE0BE42E0B04E5C21D950E809C5D499AC04DE0E4FF912237DD83AF0FFC5CB8E520493400C91235F9D49BB30724098295713F70ACB57194F53B656D4B3E5879E2E28734370A052FE51C8139021ADD0DFC6D3D8491AE9C7C8E3AEF6A5C1E119D65923212BFDC35792BB5E3109BC36003C17100DF5302C7FE73ADA012B36AFA5452CFE356C38E63C59E80C1F3FAA1735150F1F3CE87E7008281D125FE7627B3D6C8DB3A2101DD6D650656EE5B8E0E8F0CA1DBEE12303499B6CECE8AC80111C504804F9ABF9C616D22DF34FBDAF27290F4FE6675D4A1FBE8A93A91C6B09B1456828554CD0CDA039569E2C08430C3481E2970BA760DA29C31944AF18085694530E8A952B54516062CD9528A95D0772323B4B8E02C7DCBD71FFD2236E772268E25F6D4C622F07F5D437275B2FEBECE7605967771BFA2007FECA33154FB46A3B788E9E7702F38BCDF175EFE4611B61147D89195BE90840FB1E365A76840BD9B40C21949F2D41205A491C019B7F49139CC46002B5B7260F47253C1A5AC8745639F0E1833808F7CA27BD437569D38D2C4AFCC5293E6C221D9872EEA5B33A43C5217438DFADAAD8F243DDD779FBCF4E95C6E4CA4E11125F9FFA93A4F04D385175435E391A7DD4C026ACF110F0B0CCDEECB8DC1ED8C24AAC7B3499C0DFE478F292B8B46DBD70451F459D0C5487C973DB0D19E196A66DC3D611D3BE4DDE59128AA6229BA0CDD9077B20F9E03145EEA04CD0B2FBB5EF90D327C1030B15DC8B5CD259EBFBF04A5EC67C741F6D38180F9B0F1FFB97CA1D0C0C5C6C791CC92908B44374BE315D4545F5F7C10DEB4E94B676D47D08C4A0C7466803F767C8A42BB0B74B6E85E11C6BB5C7EC3A8D543C703095F2077FE89A6CD8F450DDAD4007C1EFF0E0CCE2ED78F8CBA8FA0724D395C8B7714EB2CD2BB4CCFF497F09661F28A04B7AE27C8324FB4840336EB48BDFAA240A39BE662A93F5B12682E80964A14E32F9513051FCACDFB4AF64D835A1BDC643D421C9C667F7EFF4E56A7988FB757281563991D1C6B5B0C97E1C38B9185D049B4A95124E6248DCE7073EE9544DBD370AEFD8291D1016D0995320B2675D300A28C061555D9F29925CB9BD253D214E1D4FF9141467FA3449674A71A800985A0656EA2EE415366F474DA24B9C899F26B072E7244E7CB2E76890A89D42E6B9B0AECBB5180D6EB2D34954D4098D10A36511465340E3245A716C3D37A619D0E36E129A92C205579A7AB47A6284C06E7984C714DA51CD825033C241C11CAA0F2A930DBA13A28BBEADE973C6E8A838A62E04B1A5AEC0C72A4A2B73EE9925DCFDEC7C65CCD3D4EB65621EB7C90BAC3D36D8BC3427E0DEB8F253E221605ACCD5F6DD73A50FE09215DAE82AAB23DF4B86910EC72E3EE515A746FFE7CF903077F4D13B59226DF6D94A528F57E13D741DF28C45A072A41C01CBE1EF6587D9664CDF4B8A3E2215F667E2970A841EE78F7E14CB1839199163AA591EE9A2B5AC639623254BA87A216FAA462C5F9F8A74E97C24FCBB3D53152ACDCAC8A32D5A18C890004471F9A43AFEB325C767807C66EEECA54A594567AD7D4E9135DFD212A01536B32D590B9F662C17AB9784D8603C618375383BE8FA258651259EFEC97CFC616C218E4BF54A8D84E4DB080BF25650D8F522CBC33DA5BAD3144C134547AE090930BADD38EE0EA02733B057F0CEC2AE05FAF9E494813DDC49DFBE8557E80650120EB1C9003A5F57D330888C56802199C89EBA3DC085ED5DE5C0E469686850AAA7C9DBFDB47C563AA9660B079A7E23187A2E8C57AEF291FA99B0EFFE67A6D43233D7F84A9E385403DC49997BCCC69F0CB3C6F707ADD2FE0CFCBA5410DF3735306F9D2029872992C772EC24635DA6C73628A1F5789ED2E5D91CB41F2C8DCDFE641A1361AB283A0BE8446A5CA187983E34434191C64DA727D6088F90430F1482FBD5B7493E15D3FFEE375680BDBCC812B93CE10FD51BA3A712C3130DE63A77A79DFAE2C946AB370F8700999B0EE37A1B06484CC4D3859A4308DF702D40590C5C14BF8CE6D6D2872A060190B14FA78592DE2D8B0766DDD09276BDBFE487FA6621A5E1108D01787969EB8043B236F8189D2FE9E60E95EC52E69D156E20B435C5DF5A98F25E829EF3C15464D1883277A5EA42AEDC83FEAC327FDD2EE1D9A0331F06DA74BADD8A9F80432CAB5CA1A81FFC79A1F23E604112DEF22E9854468592BD2291664517CB91C80035F1A8DC97A5C8A0501CBBA6F47213D8FE0C556842324BCA2ED74EEFE8F6CC896DD4794478C07BADDD3AF65E580664BF0609BBC243280C3641C9A5803E856525410755770BDA536F0C722612AEE5CB643DE530DDD0F7E68A8EA1FF9D1F08751BF99CB8ADE48089343C253794EF22037AC8EA20A28A22242EDB9F9A682F23D5E51E05CF68DEDC4E4BBF593DAEB24E2CC69A08F35106558D22DEFA9A696B6014DDD99FF8BC35E8DF6C2FE76F162F81682294A1D9444B9632F63144C0909890A934450E27DEB72E943076414576575834941A21152A535BF404B71F18CB4851C70FF3E167E65071236844BE4785D1AA773D641207323BEDAA64571D2EFEE19A59933F3EF8E7AF86C5C9C795E88322185CA8CEAD78CE097951B57CFFC98D9B4BC920AA3E67F502CA5C4A9DA541608647C8D7C6B8CF46C573F1C1EB086D416B2E20CE3B9F1F2C3193F9D3EED04E9AAE230EDADAF0ED5A297640AC642AB70494A6006DBE0F242DC002CEA1CA8C9578ABAFD7709B58C579E2A7C2DAEE05242D8F1A26F0B96442D65227084668FE64EBC1F31DC6D7EC5C0ED61307B70452A8B5B846B5CF3AA859F0B0ECABD6082429EC6C5C9F757BAA27F52693004B19D35A675CA00FD42ACEAE5AE07C6286F48AC02AE2E43BCA4DDB0982A40B411A23990864378836BEE832ACAF1A4BABFA6C3483A9CAA663ACE89844197AF9496D43FEB39053C4A03F04FD4E1DDCF130DC450C3AA99F85B34E54E4B7F372F8C6AFF5A17385B637169C396C230CBDC45B7452354F797446F75956ECE0CE4620EF515A6EDB2CBA3C01573E293A17A22A5C33EB367A8A9E331927DFC1697BEA0E9F6EC1303D6E63179A7ECF68B5865C5B12D79AB95B5E419C45EA2A117F233E6AB777BF3041268F9AF8F0337A989C1A24686B127A0AB21486A023E85C511351C7C5982B01484868342098EE2FEFFCF1339CA74F569E89F32EFDB11DCFD33EA1245ADC75BFBEA4D1CC707F7D52229A286A1BD4D4E69BCA878C62A8FFFCD096A741F8BE4B17E069899EC20C66C23DBB9571116C105814BF5CDBD71AFF209F55EA526D91858332457A486DCE7F4A5C46EB3FC8673D6CB46E2DE3098F22AE17745AB0BFD6A4E57CFE6D7317875912BE641651D98E70C940F7FE1BF9882AE12A52B76BA21255AA0CCF272F8215FDB211A506AFE5AAC69D951DD8449A5527DD2617DDA35CB1FCFDFAF6322DE113D48678405CA1E68B6DB9F005DD80FD447E045D6A5D3DC719EDB0223F14F92370E5DE7B22FD0189F6C7CA5FDAC1DFAC8C3525DA00707665040820A763DDB5406DF41C23BEBBE68AAD20F59A5E2539D3EA32A9A717691D72C2FF90173D53FDF598E4BC0790180A6CD182CDC6CA0B5FE69AD663506A6A43EF780D1F2B7E05E904271A587E0619EAB04598E3574C7F271892C3F482D2817BF74FABF9B63E43E74348386C624CD0A73AFF1C917D1DBB8D08BF504299C0DE3E5736BC9E3FAC872BFEBC1E5DDF68D69EB0572AF7243E531157C9EA81ED640B87BC14A959FBCC7658CB5BDF6E87F4E677011FACFEF3932CF353D6721124F8E8F2998DC06D262729071FD56F1FA76524815E4552548FD48EB6695B81C07A716E2D4BEB22348B4FD554A0A2ED702E6E2A51C1B621C6D6DF7C675D0169DE88A85F0E45BFC398D5FB2BEA9958DB9F05A82B5CC3CAD980B25415409DB4C0EA1B15F249A4ECE2CC71449C9219411CC81AF35468A8D4320B36328298CBEA852800113F9DC6A6E727B340FD8516277E3540A9950E5A8E64F0050AF7F9707389874BE4A616DDBD017CC0216DAF1D270EEF9605B26A588A285736B3574E6AA3B6F197DFD451FCC03F2B4F1788C1F4EC59BAC79BCEBA3253E8DB04357AACBB468E9C8A714366CA216EA44A764DE67989D504A8F721098CD0AB285456D21AD99BD11DA30A83054BA40BE695EF6C298E22F8D7269E995C5397DB95B5A56AF5D9BAAFEF08166AEFDE6612FB700BD797B26F6DAA7DA1A3ED773ADDFF19C592AE7C3FB87268406DB5B9BFD98D4C8CA02A18ECBAAF3FF88F7DB93E06A445BEA851E75CA4B8011F3A2E3F57286D691667E3C2DC11419B7DA22B5AED705CAF0B8EDC70F438D57D4D549D41F07955EC3E339042D11F17792EB71D8C3B9C464B54B35BE2D45A3E07EDCA62F86CCC96C6968C567730E3845D4C8B8D6675606C6994DFE5569260BD2943AA189AF3A3EFC8F63FEA89B71F2191A7BAB25BDDB5A02FABF7224243FE5C6CAAD0F7CC66A6C6FD9754F700E4DA2548843949C7F02CAD107FDCAB04204637D6714789155D2C61AD3930D6F8586EF5DB5515F673A8AEEEC8C9590598B16CBF84032545AD5C1BDFD11A92093B0B0B48DD98EA963E208A43E5857A0722C3A641E60C7C398D15084D8C4B35F4A3146E77AB439985209AD99296A12BAEE3C3F3E994E76387D15C2FAEBFF7B44BBCA08A9937E74F9CC01613A5A2745C3F3E0473373EB1E6B4E29188477CA96845A7B24C232F8FB9E405C715E3E8DB593B14FDBAB225165BF0B0612BE50214598D943BE032FE5D5D9A33C23BF8EA48A5FF6BFB80316B5314A9D73C07D8022D3431CDED66AE8326EF049B2DCA5E63C6354666D1656A46BD5C8B430A157A43FAB904BE87F7773F5683949A416510B361ED60D700387A5E1AF0DDBBE08017270673ECEA9FE1F59A4859E7C097B806B79019C7056E6B1B8C2B43D41F78389A1422EDD4FF13239F36C54673118333E1DCDEC960A524F3D9E3E4BA1DD9B62917E8820249A397DA3DFC9417652F02EC8995851FBBB668330EC8EF6F89F77928F54628F6E3AAF55940E6F73720533FC39AC2CAB0C8495FE09563D4A0B22C628DAA66D06855CC24E85F9BA30046A79BE4EFD1B9DCC6E098DF8EA4055B19871F55F71A07138F7ECE919D3F6EC059DE0A7A363C0E63A16FD8A9944150D65F56D4A0D1CE83CF4DFA3B79A87A3CA9D003CB578B0A862E8A8309A9F8617CD5D7D1634766ABA5CF5181B2DEFD4CAD9A1F8F2148FB137CE27EC8E62771F46E7A8AD1B370474B1BFF0A634408D56E33EBA8C4F4BA282D716E03FE0799D012C1B9D3F1EE3D223E3D30F3020C0E026604FF5BA9CA8F25CB0C6D1C7835F66BD1FECCB77B911C259394E8D6582ED0B83A44776DCCFD677E7CA0352569B227DAE57777BF15464A8C91A01547BF754178888EEE0274A0EAB6503A50905C3D04CBF80E39F5EDA193CBB574D9141AA553186CBF7934E9AD2A2FA730599D2910DC1CFC2AA8DAD926C58385BEE6F37203F94E5DF5688B9FE0DE1F67956CF2D7872A9A256382165A8572BDF85F083A94A94E4C08ED85FB17F2BFDDFCD4DCFC86CF4E608A6CE1E6615DD4EE79BEA7BEAB94B696F8EC236133067FA6417895B911914FC39971AABD1C5ADF8A1B46B34647599252EDB50610E4403CF05AEA437D1B23FC22BA4AFDC836FA167791D3703FE28BF015C7BA755FEE0FD33211AEA356FFCC38720D04F325DCBF5415037A0EACF799165D590D36F036E0778963F1B9B059A479E0E6A8BBF826B0D55399B8CFFFCAD4CCF859B7C226AAF04BBCF49260F242FE7665B72AE5B1AEBE3AD1C4FDE360C56F2A9F719E8B5A4679D3700F8483C54FC2CF99AF9814FBCCDF46A85A5359359040473A71AED3199AC0283983D8595ED6169FBEBCC92BF9CCC7A687B173193BBB636DC889ED448C942FD52BB8EE81BA817C800285CDBF370502BEE6273611ADC1EEB4EBF9A625AE0EFFA97DE9D0E5DE3BC4CE8B8CB1E07E79578BBB65984464F724E34FDD3E2B37D65886782874AEE3C700754D7EA76555F6A37BE99C25D3F7924B9F5C15D6D36E6F709AE41775902710A12E5568115101E6ECB68CEFC6C1E3EAFAD850677F925293937A7CBF1B545E56E20AF68ECB04595F8104D942BB3961B39997A8401107E938F74D6DA03821E8FC12D25B83958E720E544BC10D4DAF73F34BD23E19E52E2A3D675558BA09A6B9BF36EC3EB3EDA9E0F4CCA329BD2FE20482B7C424CD1A765DB6CDC7A5C3A0635A7F48F9FCAFF2245B13B6A91BB666DC0B131E4754C2D2C1E623122E73ED103B87DC55CB62A152DE41ECA29FF4DE07A3E3F85398A14FDF1FDB85C1A6202C0C5564C3F66796B7FB9D9481861271901B8281991A9F6F66DB8DD2ACA5B9E5FDF4197D61815E423A4C1DD61233E06C3499034CBD2490FB22660A966D4D7882FDE18CC041294B9758A5544F3A697CA7BCDAC81EF742221F56EEF86CC2999CE0C55503533CF7AC81EAE88AE83A835103E91F3AE125F46B3C7ED05B40737AE62DD89B82D90C22BBF36BD4C169A9D9D8FFE33E2E80D503FF0DC214D37EA4B81D9ED2704515C6E5B7CB57AEBB3A912109B8897E271B756C77D8B7C975E3F4697FCF8C1DD1CBBFD52C9F1BBD22E7DB82335E5A6FB849F5531AA9841B92FF1CBE5A34F4E9D5C41565145E2C69AB65196FEAB627BED94F77407F7A180F1AFC4E9D03988507831848F23AFD2CBAAA6422389D64C1667CCF290724D58E28B2B74D70771682F70492AFDB247A3C118572BA5DBAB9BB2E4ADA05E0D78C79F0A2F97AD053E87B43C8755A7B2C217340C81D5BAC243B9DC51236BB7977C2F84D6E76CB4A42F0E5A9ACBBA9A6E6568753C7B8E4AEAB9B1DCE5052A2971003750085CB05B68E6E9E126AD5BE084FECDF62C8AEDC63A920DA15D1A3B4C5CAD650A2DB43D93EDAD2E498B0ABA4071B75F8DDE617299C990E6979D860461342EF7D52E632ED2C78AE41EB9ED9ECBDB9CEC925EF47CF57E413BD7A4B9A71E6236CAA1AAFFF8A8066E50E19D3CEA70F910537B76B350CC194B2804C1458A428BDEF11FD82475C579058C996960C0A548BD6BFF0959720C43E6AF1A94BEDBEB922A8B4A02E451E88D4FC8A29B92D66AC1F6BE6802B5CD979480264C1AACA5D6578F44BBE06230CE75105859584EA29D16C20ED4128A0EA85F4CA9A3EBDAD29D0B661D56784E0EC2F04EC2DA448FE96A3B9EAC31A9E53A2925701C52CDF1B19447F23C4BCD507909F3035D1F6BB9BB2074239D339492C6863337869B2855EE7CCDBCC6D4FD9131576DBD7B0B475C51970D3740D8F232724BF53C09325303CCC41645694D6A9F7A43A93464507BCA194F2E1C8159821D1DC950A3CB5E9D1FD829222E52ECB1AA5BE3FFB693766886FE328B33CF44ED3FECFA0D2EE91EC515A59B419D903524112CF788ECEBB117241C61FFB84E266905B4EADF0606D1F070C1FB0BAD9EE87EDABBAC32AFDEB276E3C63E1CF73C55FC76ECD8A275FC17BE731FD1983956B1454E5611192EE16996A744DBBDC88BB1E309425A23FD480477997C6A27B780396D4CE034063BD1684CDF49B42ED5D23FE2C36A8CFB0BCC4F8F3D029C5F233C9D28ECCB8EAD8ABBDDAC297371916B0F0025151DE512FBE03163D09E73776F09C5EB535A2C81CE454EFD21E27A51E8E746E018FD19B89B74923CB2C6136061B6F94ECF88BE57540FB784ED209BDF98BEFA822205B6EB9BA7C43DBF10E82A000DCEFB30E1B46ED4753F45F568368AF289D9B257609B81392354313ED12A0782ED0DA12049D4C3633639CE970D733B213C8D40A29BE5BF69EAE20F568BFC3E6755A423E22D68963FC2C85979FAA14F895FAE3A46ED30FF96D3ACE7B8A16B8527607915A8DFD7BC9ACB0B27E06A8F22E2FF223DF6826348E96F2D1F74995F0CE064B45B4944053E3FBAB1AB2336AB869C53B3CF65E3FED0C5B41B9B7860EF3427219FB2F47AECFEBBE00DA51FC22CD074FDD84990C1B70ABA87FE2FD5EEAA5A7E6D1B88CCF9AF31D6363DB8BF9728077B7D07B254CD768EB3E107C729BE3D2AD1146237B9FB53B4F9BFC4296099E94D35CD1B358123B1D28D78D010098ED1CADA99F82F5A0747DBF6D342922274658FBE819DB904D59977046F5636318DDE0CC440AC3C0474712B8FA488CA585DD81A7DE27EFE65EAB1BFA52A8CD16FBE2F56A131C86C7DD1F713BE0F5A6D0938891049CB452DCDD744665682C0E1F68EF9ACD4DE6776618492E822E5030D018443802B916A25A62DF68B95F847AD787C0848D2609487993893EA08733CFF496BE0FB34B21DD51F10A071C44837B9676A6F7343D5A2445F4B75314FAEF07E3E40EFEF20A32F8CDF8F82A1BDDBC7F96DCB3640F298C34D5DC72F7F262C8C8559066A4F0BBEC31B2AEC81F2BF690D4ABBDC56B7839666A5BE71743B38812645904BD1D1A9388FC18BD9EE7DD0C4DF20AF8AD4B50886867F0EE7B6C9ACAE5EE58ED2190D2C2637765F4D2784BC8DB292A12F297D2E905D1432DF48FA6F0EC3DB1612AF65B6BDC2B58EBADBF411C323CA09AE4B56ABBDA4452A2018FA5687720FF761AF1295968023628AED87B51716FF33AA80E4E931FBEABF76227337499829A6D79C7C6DACDAEF490CF021210DFFD0C27FAAA7F09BD37C5BC07B55A2E621C9AA9BE12598EA98AACBBAE1981C51F76C5D4E48693EAFC22BE0891F74BE3A115CD68FFBE55188A043D013B741044E59B3165C5A62BCEE94543B637E8E0808D64C228123E402CC047C45D9F63CB3E6F5CDE58F0199666F39280641623F48CB1EE9E76DBE6DE0986C71A3C91C8A82D51252D473A42CF4223B6045A73D9AA9F061BAA949660B1BA38BA3F4B9A2FAC838D2A386601DCFCD6F361DCFFF555FC9348735C1844E957DCFE0C7DDEA5EE03822A3A5E17D07419AACCA1E59E4E3B726D68E2EFE10394160B897C2CAA9A6AE2D7F9ABF852E7042B3B276941D5453909C2E9D80E0858769266731B99A4599B172A6CC20D7DC1F8478BBC5EC2EC8E387F88A63144DA10E09F17765C15694945C8496386AD0B83F7589DA9BA60888572B16ADF404D223FDE1B4D55E5D8B5D3CE2F5A492BF3B17748DA28B43216700BDB1352907E1AB5438AB1EE224749862D36524ED24C724940B38866C531CACDFFE38755A65375579021316511987CA6EF0B03F6E2D82A6B7D4CD8E310EF5FEA12B7D84A0CEADBAE39FAA04460E04FB2C4B1E759243B11A138063BA9C96242FAFA15FCE06ED9580E29B00F44F3E74A437C9D7541C5E4BDADD92D0179E86F84FA3DBAA8F1CEA1B4A329E56B0595C90B8670F63E942D42A47B30805D770D86F6412CC87AE063DCFCA9C353FDC3E8068E3E5A8E4C3D3B8E48E245B7728D6997FEBBE412C01406D869715AB2FE5432AB89577EFFA2C6FFA435FBA59958FCE9DCB9A3E9A748555AF0CB64D7F0D85ED5FB0AEFB361A411406AF6A34610CA9D280C5AD4ABC8F1B5CC4221FB6323930D8F0F2C7F1E79220144627D49B5D442FAE09A2033E1AEB858CE38A54D7FED0328A06F7075E206FE3434E00F09992C81F902742A2A0688AFFFBE257FDA551C2F0089C72F8B75FAD8787A4DEF71F6B39C2EF08E88A8BB0EDED81B001B29F8BFE1ECC36489135B3672C016052FBB824F4B3077E024794C3D1C1C11EB1C31D78A5F314A8CD10A228280C72E9D697598335D2EB05E256997FEB9977BE8A5F1472E5A7F361FF6520F58ACCB812C16FED197F4A967CDFAEE8DE32C65D6A8E176E776D80EB8069ACAB5DFDB3822EF8057E4222E2AA0A5E90D196DBB334EDAEF375D80D6220B069F0625CDF43727085BB9DD60DF31DBF16FDD02A1D3FD0932C4BC23586592F20C7A411225D44385E8CE6B17C43BB4FA6BC914218D88DD7815963120F630D178B34032FE24EE8C2D5F256D7005FD2FA005DF391923FFDD6B1A02DDE26D301AA91DF609967EFE772EEEA6D271F41F2623DD1096E8656DD44EF4AD4565CC8A6DB0FF5168C9552F9A08F84E91B335F3D18248B6F54F84121E17EF6BD48663A2EC9EAB0D20EF4BD6E27907F5D568F33659B2DCD64A10C82C82BCBDFF5296972DFD8369027198108E537D4F0F151D9E52D24360D381DA74B87E0ADF3119B9A2AD38D7679D60DF92CB86566B14AA71186C40C338B3A396579902434ED860428BBEF6BBA18121004411641C50A92EC832174AD38A679F5A49946EF241A8FA1D26974F9E465B1DB8C6F88D84B62A1507CAD3AF350DBAC43276A87D94FA1C7A9E8488B5E3A2EB66605C69AE4C2D7A551163F85877A81D5B0F988F48A6B2D06C9CB879DA0068CC2B3DBC36C5BD714E30A5021AB48AA57F8372FF8C77C03BFD97F904B50105E63FFAB45BCF5BD6D576C86115E90669BBA2CA946CBF8052D08C3C8F77333196822D3DD10B9955C4D1449F7E4EFC0AF27696929637533689D59BF3B03AE55C835A2AB28022A6738CC5F3FE43BB12DFB8BF1E0137A3CA5ACD5B0493ED71E9B575AFB0D25F8049731C85F50BE87DEBB3CD180077184EEFCC3233072E0A27A9918C0BB6B24E656559D2119391FDF74FA03BF6D982D156E54BCAB37A3F8C7367BA95DE2CB392E6B085E4AB974BADD8A55A4765F42C878E987782A59B9EC7419729869687DA4035147846B227E285AF50DDED91E9333B9EA118AF549280ADFCA75AD6C23B456CF7B222EDA5899E834BDBE2240C534B2ADFEF524AF4906BC66132EBEBCA911CFF0210B634767C0C163B94B169C178F0C7B40C641894A105F375758ED7BA6A1A2B6478F9E97A5D3ABE5F0097F6440F325793571FF212C4C53A38301C3E4D076878270DBFC080448E4BA5F048CCE407F963D2ED434A2AD17385557AEA88525E30E0C3A9D6228B72ED2761315A2EF649E8B483E231B9A21BFBF2F8F07BA5BF89C00E11C239F0C409C769419C748C506D878DF7D0E4F44DBF4900076FE304017BD3D6C87B4C20D92AE90729FC985BE4D9ED63C7FFA978957167E2197452392BD82CF4709A8DCF816C49C6588CECA3D0C1360BCA17F1F152DC439CCC3F153D2DE9771802841FC90943528B2D6FBDD00E88D091B11AF84CC4ED4F1E032180371037A94886F301ED534D63E1B92722954585CD167CAB7145AAC3FA46A692B8A3229D83FF6C34B64C92507F7433140480018374D78FF90BDBAA09354EC34B5AA399C5F2934EFF7131D6668371001A96168A0A8EBF49E6306D7AE4C624372677031109549F426108CA25085C2A40C808B405899C0CE905DAAF47B17617A99849605A619A03A104275AB9DEE9FF17AB747527B28539DDA5BBDD4341BE7B8613562A13CD37C3AE160B616D61C4E9D16ED85AACF2354D61A1506143BBAC9BD6958EF542C3641CEE7DB6A54A4D7251E653EB25E05B4C345FE6D06478E6FD39F73AEE17CDE073BCC7C19D4F239B84E5FD50CF04D928B7486ACF519C68904B838F1268F12C05FB40698585979C59C70AB2124BF99FB97E3CDA3441FDA18AF55DB4E5C39D3D75DE1F6E44950021288572D2F040253FABC31224798CE55E2BCB3BD976A8DCDD7C77A9797265187CD35777453C81286DB5FF66C6B9878619B45EE5BC62FB267615EB970B812A2B19A85B77F12B18D322DBFFE7FF462702C6ACBA478C0596972918F3054C7654A888879412FCE7232F084BC2818AEEC294E52980F854389367943F8C9D77B3050A71A475978C841CB373D37A3960B25BC7A257760C51133CDE7E50B78CF561F1EAB9E9A84B322DCB040FC246239F54DA7D7ADA41FB6026246E81D82E5E7C00487354C4525A8C2FA070963AA0FCE163AF71F5B522C64740D9DE5FD465E328C3F992BD53C2A66F44CD89AB53C19ED320CD6B1C3060A9DB6C3812818ECCDC7B02B9A854D07799F980566B8054045F656EF1989D6120A50395EB1EFDBEA3ED45ABDE671F2ADD8542A87B3727D3391E6125D1D950E0B15A595E23707F2FB9E7C597EBB3C571DD1A5E062A12BF9918DD7CFB06B80B71EE05283EBDA7A6CFE119079C10C55EF683F27CC9D06E85D26900F33188D39D2128B200E648ED30843460DFAEE006423B4D18F37D7AA70CD4209073C6EA812A67DA603A863BAD29A79C993C442BE5968A0DF0B7D26D56ACBD0AFB3ACAE7D42FD1400304AEF11E4D6B5AECD5CB77CC2C6E9FFF03CEBAC5DC54724FDCD47BD4A1D6EC45C6B5A0EFDBD97DCA8BAA7B6CE0F6323FFB6C0099A6414B5CE20A2F0109FC35EB142565EDDEF76754BA999672BCAD22B9849EAED945A7F112F46D9BDDBDE882A4E78DA96D38057DECA09C4BF232C0B89EC9743C6244CA2BFBF52A3285D758250EC4633063E0716962CDE9CD88E346E3579ED9D1F085909BA632EEFBD86536B205359A933F9FD148058D265FFF73902C85455339C92D178C6D26AEECA94375B0A4B7F293E101FF375E263B2561F971D7419983CF733C3BF50D77C4D33CAB9116E8F189A48C00C04AB7CAA471C360C696EEE43DFF6E33DC931ADB4E69806670F365FB97814E9367BE22919DBDE5016CE0F44E0465FBA667E751FCAF2DCDA33E5FC488BF1DD7748897D8C520E4A46FFA8F2A539453328E8C2BA6EAC0ADC1F1188F8D57EF7A28F44F7699CBE83D0E8F2E6AD098B921D1B770C1056BAD3B2B2B7D383E56C935400D84A50431FA94C88A53545656B62BDB67EB7B3E76E0E3BE35B99C529809F59C9FE65F0B19789F758B01C6BAB1A30A8A3FBB28B4EA3E14EC104B9046B70C228503D8E29291818F873DF242A3225C9DC7E1F2C27FFAD83C89C70D03ED21AA0C616137A2C2750A24B30EBBA9875A3074D922076F7D24ECA129549B33016182DE68A235C18AA78A9D27E6732684DAC97320984E441B9F65A5F5230C957B398454E2BA1ADE900CE36CD1A320F81E21FDD36A449A036BFE7410876E0880015BDD895D29AF0F0A9AEF2596BB022CEB44B5DDA25F5BF3EC0EE3AF476E28D5F60F1C8D104003BE1109792D3966DCE207109EF665552ECC29E3C0A887D0811BA980CA96EFDA9B823E1EB1F0E760F0BBB0DC9C8D2919402ACBE08F0E1522838ADAAC6B45CB71611ED85238D2E17907588715D328015A225B713F01300FA5AEF960DA36D4120722ECCBD6886DC08E57A0F68466769636712A361724FB2FBB4AC9775287BFAD7134D577C31170A8A9C39FD5F1557AFCC167B11DA412436F79946BE332F148A72351279E2E1E32522AA8C0731F2F312B893D4F24A35BF2C42279DB8872E70E987CA680DECFB29425A5C51709216A5F69C00166B9C971E9E02B52731AC8DA8988A8A7878CD368085244678777C7C1DC7B0C6340C71FAD6BE4EDB0ADD161D5F701B56E98CEC853AF23B3695AF8CA7493BCB3B405B2A3A5F247FED50EF3F0E5679C2AFA4C2F613AB73CCACDB655A97E00AD5F7F1320468B089D5CAB0CD8F29FD284ED47E7546D39B4D6124B431B7190FE5D5489DF4C39914BFC951CCE080444FDB4D4BFDDDEBF80A22412911D5CB7DF5CCF5434E2E9C7094FF22B5924EB967324E73090832FB75FAB896104DABED028C4D096234B96BEFDEC7E669F850CD731ED2782B60512E2F83B3E063719F2A0F984C9EAB52C8BB7672F4A7E75231855BE3B541BE8BDF4638136802A83225ECB0020B956B690 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-3_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-3_256.rsp new file mode 100644 index 0000000000..86915f5431 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-3_256.rsp @@ -0,0 +1,12 @@ +pk = 000000065FC7351ADB3E5E78B0A1EA06ED988995BFD8960B36F604AC8F03600F0F15E05004562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000060000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A5FC7351ADB3E5E78B0A1EA06ED988995BFD8960B36F604AC8F03600F0F15E05004562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD09000000000001D5DA3370DA40FE4B2AA8D93A4C52E009ED16134083746A63365266ED868E33160A0000000000010EB7A75A56A1497F0FC1FE5B3F6B396014CC9357B7FE8A6D2BA1B553EE3518610B0000000000011B23B9B57C09E7B440346ACFAAB7028D8821AF52CA85D5CEEE66FA4E95B45CA40C0000000000016AC8FE7754C3CBB4F71F8514603EAE30A764437F404409A1283CFF4B7159C0F80D000000000001CC6FF52DE53BEBD4E1D3DD11D0BE5FFEB977CA63FF2ED1099705AD3D5BEB1AE90E0000000000019B6C3951BCA1748DC7B89630F962DEB3937A4F8D15BF5634741113C38D2699F10F000000000001F21F01A1F02A9D105C71E89A189791BDA7CFB7BC89003D2EEB2AC6E7DBC26814100000000000019CD3ED9E3D49C10FE36B3813045F452DD0B3CEB702EA9FD3DE2289FEA46C9E41110000000000010CD4EC639F5FA5159D505EFD1215E62E35B38AC9A8B36077EB263B10F5BB4B741200000000000111A178357024706621EF264E4A66422A6F5B9F4C24A35579CB17DC686277D0591300000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F7F8F9EAAA74A5C910DD60B2FA5179B3FC341BEDAB53B1E957F40AFFE59FD454EE839D34EE92ED029C1B5853A46CC8B48B58DC4F74EBE2164B7F867B17ACD180761BBD5017870DCC53B0ADDCBB8DD1A6F5D014B1A789493C53C3D7B304F6237F836AA9372B0CD7007588A7EE166C1F8BC1C7826CA9D6E2D73B1B217E238FFB65DA1671204B7137B3C91D19ED0DAA12A98AB71C239C6F0E6B29D3F61DE3F71688560646DCBB9846A8F28BD1E7606E2C93CC0CBAC8A85BB578671BB01347E7B2BA757AA92131B2693D7F9501E87FC7C1BBEE1B8BF15E28DAF9B74487ED12BE8A4075FDE22DA018C0531776136F0FAB5ABF372E160CF51685CD0B8FEC7D63D39F4A7EE635051E54EEBEC7E8C4A408EBE848B7255685201592E3730C4DCCC6E7DE956B4FF296E76D0052EC6C037ACACA6E6474CB17AB271FFCA98A688D224C3A25425F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E7040000000000017D93C20AE191054626B3138F02E186A4607EDEF6E32DD3B2D788325E88FB01E90500000000000159008B71F97B67D9710ACBCAD0DCEB434823D0DDE4E8526701AF9ADE23FBCDC406000000000001410E6F39D12638391198E1827F643E6547AD7438BE85774B713D8FF3D8CB682507000000000001030C34B96241353C81CD7DDEA97ED6CBED8C9F9FB86DB60A6B78E39A253C001B08000000000001B07CBF5330F3B30963D6B0A4AC7AC4DD77585E4EB8A08B62B9AF1FBF42B76FE509000000000001D62A2ECDA2D153580BB57CB3FC1EDFFE89B6C06DE234962509FDD49A5A2438EC0A0000000000013792F4A440FAC20AF31472E40F1E79BD1E1C5DADC93FCA0319589FC55A542CBF0B000000000001FC454756AAA4BF5A8163937BA2E80D39CEF46D765C11FD66664120A83A61838E0C0000000000015DD4A3768F248125F414048EBD3F6AA793AAE4CA471DEDF5A9890841DF6DD56B0D000000000001CF0D1BF19096E3DE0950E9EB4C435D0C6B3DB4604FEBB60342D5B7C30528D4730E0000000000016ADD9B858AD6562C3B812B026D9BCE050D5A40ED6D936B1034C036AA490CFF910F000000000001925FBBBD85D4CB4AA7F5D18D703449AEABB18A5D32CEF076C16B7131DCFC08D8100000000000018DBF8B67F11FF96E3229EF8CBDD85719101DC3D8E6F636CEC6D19E63ADF5679011000000000001AE3D1E12FA31B287D509FBE36C261650C199242799057289B96E8D67301B473312000000000001AB1B5ABFFCFA0D28692F1FE23A1C1C3C31133714D112C66E05A09912A1CE32C213000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A02E88916DC8ED98AFD66F79E221DEFBEE75A5F18AE06DE81B8FCB94F06AF90A6E36B516E95723A80EA6651490B492765305BACF3DD8EBE02F583A32BD1537CDB034B4DF991724F7B078E55124D36BED20F8846C7FACE620FC7ED376EBE80E7B7122931848C35D74251572804688C127A1AEDAD1003741525A657B5C2901A753E0D14EF5F9A0D5782597165DFA12CD98F310CB2C667C34350C4C5F8E3C31C295C79F9561C0CF3DCCAA0E146799F097185974B77D76EBD9C40646648BCBDD85F00BD7BE65EB0B86C45236BB3EF4FBEDF9063AB38DEACA2ABC25C316C62A8FC0AAB8804D54A84CA6602AC2415383AF59495ED3FB5238B5CAD3D30ED637A6F2D1AA90447647D9B1231825578EE75493A63DAFD2985E8363295A0F24F454C3D59464527CB63F05213AB34DF7B134BB172E3FCFF116BC5BBFBE3EBA5B09E652A4C023400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F04000000000001F37353B4AAC3DE6FA6FA583102CC2F35D6CC95325A07AB88D9B0304EF6F8103305000000000001E087F84EB8A6A13A9581B22CDEEF8942E186FE62896C636D0503675B28692B72060000000000015FDAFB6EEAA60CDFFD2E2D1C034AF7306D60B106F145206FADB857BA565C66FA07000000000001CA463E7885C94740495E419265530662D2D8B0CF6C9E7C290FA86E8E136261DD08000000000001761CA5CF20BB11D4515629D8BEC9D72E02E0D3392C20084723610CE22260DF9209000000000001DAE3E662F52740958363C199EF0CB5F0828BA7D720A1C22E48024697A752BBE40A000000000001641A9FF6624F56629B9AC0BCA35CEEF5426CD40B73E5E6E976CD805B626351340B000000000001970701CEDDB32F91B1653BA5C933B6F57C7F1FF99BC31B459A16CD76024DACF00C000000000001BD84277343BEE7E83CAD70FDEFF5A5DFDD0F9A3AA1FF342DE85C27889AA6D5730D000000000001AD8BF136C3B7CEA71632789EE3D7E8FB2C3AA2548574A403838DDC313CCE97F20E000000000001B4135A97848AFDC9B96FBEDE4501CCBF1B855C542A7165D3EB5E3F0F2303ECB90F000000000001AC2898B9C17C21ED20A550122441FC4ED08A7D669CA1F3D8768DDAD0E2F6BD3310000000000001FF86FB42353270642E15587334A17E39AA7DC9CFBB4C829CB4B16510DAA83F6E11000000000001EBF5F05C9D7C61C2A99BAF7478A73E89B5CF10CD25174F1EE5FD61DA26DE7EEE12000000000001F9F5610037B38150D3AA10BA9EA0592CA0A21714CE0926F3D8D8BADEC020AB55130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000087DFB8B692D4548E69E8F52A40B52D87261DAAEA3F734803A146D4622D4C8B17E1D98A7B04CF346B99E512072176F7A8811405EF38E007181DA3563CABBC577F41D6B8EEE36B0D67FF4AA525185A5821F2ACE2DD7F0607828ACF8AB08FE940D7FD268225449F5D20ABF61D2C7DB585A8513AEF60841E1BFD4AD3C47D3A00F68F71DCD9236D7E0FBC428C7095CA12D8D10B2E69C9FB6C976F4831246C9C0E2686091FB040E21C594960A1F6734A0B84BAAACE4EEC7FD1FABCA7F71373620EF656309B93B9D768970B0A03B9E07FA9C888A01D85B0B92F6550534E528BFF6289CC398003AC6A91CF86329B6BEB13854C20A8A75DCBE7A470B216C334CFE6AC120B8AA42EF5A9BC9FD224967218F17A334DB9364F966DA366BE08CA2D1C6DBAD769ED1537C3F5528CA849841BA495B78D07901481631E624DC0656F7F5D0B4820B6FC2269E404ABD245B49EB4FE7FB119E88663C8B8E75EC63C9C5A8EE478313B3B058DF1ACA81F65DB0F2E3E411A30158178585699BE52B6C11A2DC966753D7485AFBC75AB6EB6D0443DAD871D0BF43128A057593EBD325466AFCA3EA492311A31788F75372B5321217937AB4FF23D37D3A01E3578E758A2087941120E801C12F26FCC55D089C712C0A05E67122E28351745998168D1760B16D105D854BF2EFF369971D100CF448D3D00C2C34D5F6037A07522DE2EBE014E1E60D7A535B4CAC42EB69F7856E7A259627F4492A0CDA142D743D7BB90F78EDCC15B1EDF8DE7D0D4366367E581254AF959768265DAC9175E18F133DFFEF628CF769EE7E9BD0E07259AFD067AD441ABF81FA7726FEB1140C3146BB510185AF098DB53040DB97F1EF894CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318E413A87250637B5C4A4BF18A2D661BB2458CA7C7F9E320228FFFEE614E88838DE28767053DAF289E9BB8073D60114D20309CD17A6EBA5FF2FC47B49402DA3600DBC4323559761781818334D1C0CAF34FAB5A940C83D6A363433E390C3B589E1B6D09A2F4276547FB279D1F0E2D1ED91A3AFC953F9E7942BEFCF2AA66B19AE877A6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291D560067063A6EBCB1EABAF7FC12F66BD94F1BAD021254D0CE1F1F850B081262A446E84188C3A9A3CB89A80BC9E8F597EA247A39A6F59BE2D76CCDD6C96DDEB9EB0A272D02C5327DF20934FF8C0E26C71F6736FBD5B85A56F15E41F03DF2713DA70DEC489B962A1F7E119465FC8D72AD1DA559EE0F25FF661AD2F62C6BF172C4B7B0891FF05D0C985FBDCC4DEF2DFC3A73AEA39EAE9010A080DD47BC1268BBC1B5282DA83C62A9FE25CBC62E611951A411B03FA8832E227D761A35F4FB902E54083FD05142177B5D2987BE26FC4F9C5D13FFA21E7488F19245FD19D9FE2DA32608B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE5BCC31B508B8177B41775B459DB06F4AACB419F24EA979AA24C996554DEC91EBCB16E9E1B754DCD221E02231F10FBAABF79E362A514D54670DE7493B7CD7B66BAEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBB0A1E0563E934CB60493FD19327C71D824F361B1133A15E47857567979B5F8288D5FABC9D1D47402577CFAB60BF840EEF0D9173D47757BAF197EE10941704811690592F587BC7F532446BA10B875CB7994CA2613A25F65D16A6735E9CC0C4238036F68FFC1A893DDE19859CCE3F5ABA348F769D122DE567889C14924B243B1379AE65238446E7294F293F0DF1751C166CCF58B4F76A4A7A6178A136E3F72D120FCCFDD47311A340A0734C7DC77664B6D7BD87EA93215C69CA59F0DAD8E258637B49DF9864B84B76089E4F50B6C2BC496835D701C6F106B2B96CDA03A7F118AB5AC2F7073E7596BAE489C83FE68A8DB1E9A5427A31E8A6DC4E2962E5571FF061908EBBED929D64B2505C1C491CA277C2917E0A964218059309167716F47FF2699FEE7248ABFC6723085934D706ADBA0BE046CE3156EE682A5E0ED51534CFEBFE9B7118577F6D3157F31E8D849071E31A734BCC1DABDEF02B7D817FBFFF2CF120ACAF9BE403C35D92B960CDABB7242115FFBC4208977E19BFFBF250DE7C71814EC7206CB8F2E1D523E293E557D49801FA6D9E5AE279D396F91021690DF5EA153B3020CA3E08D8C53DC9DCD731315CB24C9394C6DEA84543806DF231011B086BE37A57CA2B888A74FBE7379EA346ADB56D932BA4B7B857A7918116B70987865FEAB8A42792F788F8CE13F75670B36029660F68A7E27FA23EBD2CC06C7CE9A51FC7B92220D44C4E9C7900E1FFD77D08D35B34B201EC5DCE6348FF7AA08F0DE5A4AE7C664F8E70D3531E181B4B5F7D74E8B6FCA7AE776AC73C4620B77C1C2397B987C241CC139C6407FEBF5B912A407695EE8AB6612C8C3D610D6E11E107E43AA6C638FF86104557546FD5CA0098C44C4EFEF0825DD5E8B33E5311238A32672242BD19ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDC05256E7B9EC23FA6F460956174696C9283AF19A615B7FD209C25EEA0587D15765808D7814EA792B7C31F469AA7004FB9A78EA5E59459C6E3F75E9E4DE961B5FABE5149967C9F97B1BC5DBF8E297DB4B25FC55241FDC189E9488FE06F71E9D1D4E19D50E7A3B81FCFA4799B127AA0D8C12FAF48811D52E4EA08D965813E20A7CB532F3EBEA5CB60601DDBFB1CD19FCE3F0A9CD1E452D1BCDDD215B91160F6EF5892280D847E32600F50E5DBB0DA83A650FD17E4A58EC02BC05DE23CD3B2C04172708C15A96A3D43A212FFD4401EEC87861C35351A0BE9D7D4D6AC5D60DA8AB5E1BBC7D943F4439AEBD7A6B022C8EFEB712BE5EAB7A1802CDD2FB9D93FA6E4383586E517A4D79D9FD2F6BBFEF8C65F1F3111067670E6A059A1308948697F5650C1C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB483F7999C92CE3962C6527BCA9BCD8AA4BC4358E39DE5D52EAAB2FCDB3D23E5FDB643B9967374A140DC0813D252B1730B592100644AADEF3DD4BA506B4D4B95F3F95D2984783B7EFE70888FEDC2F8BA40338F5727171F1D799BD2E214D18AFDEF078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DFB179E6FE98B1C807944E610D3A1516646509316FB8E95E16D0E368B0E95370989BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB71410EB0ED1462BD35E503C47AC3DC9E9915C28E375719CCDC8F265898EFFB5A5B0212D18F96E473E185736ABF8B9C7DB9E75681B0CF51697CD4C44B0BE03C799CFC37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B578E146EE63A9FC66C147592E35C3E7785F3883D458746E1FA6E05C928CEB6E4894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779C2092E817BB119F33C436D107F97EE21363AA6D16A8D7C3735F4C9995180C4B5854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F046151EEC6F1BC5A7CEE799165259DEA61A25806F16B82C0FCBD046ECC5597A92C4FA14B6BACA60BCC65AF37A12AA67AD84239FF680AED031EE172D1EC34231230960B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E079FB5833EE071F22593511FEC1620797AD8A38BEC92A5C958A47CC030CEADB4E60CA548C946BD7B2D663B5A34F11E335ABADDE0126BB632F87518103815FB41C3B30C1162EBD9A23A40A2B1E47C1E8530C4E308BAA4EA544F5416D3C2B19B8D75B87396123DD962FCD143732645E3CBCC799D52A889ACC0397AC81405174220EDCDE3CE13663FCF49CD05018BCD4C8E085D8B055BD4A38386222164FEC91589493238047F1CFA07E7C2D8D34775BB61DAC79F301F0942127C6787CFD093620687E9A5C8E0B7146153759272866DD82A69A178D3BBB3AD2AE177DE91B44A0C0CE6C4DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA167815801985FB7A952CBE74331B6EF9F545A8D958BA7120898C02DAA3F7CC187C81DDF09B5E9F281CEC29A0F012F8EB726DFD7B193833CDA2B0CBEA378E6FB25C84C8CE85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B6C933E397A7153D950BD58C62E8233D1D1C276157386488A275508CEEEC7E9896F8B15726ECF4CF837328D80E8E1A4382B9029C26CD3D9205C66E8007EB5C07E51DFD1E90C612FADD09B2985D352FF0F423F45A9E35E4ECAB14E1FA851A060286A131ABDBC53DB24CAAABD058E356751BD847919A68991CDF865BC959F4F5106E21201360A7FD64CE70D102E0615086133262296E48308D05AB0310AEF2C07E169164ABD3DCB8B023145BDD480F927AF80D87E7A088568195585CE2D8BB484F70353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB517B9738E423B8A779C6AE71E3FA4D2396FAA0B00703FF9EB574FABF0A1EB8AE1E59CF6F87D1172094C9FC02F027A8383C25C1CB186D5F2CFBAFB208ECA37B1E5267527F8F29F91C0FA10CA75AC7FBBB397021A44DE7DFBE23D639DD1954190897EF00D981A0E12335FA7DD99C20C3DF0A8E35CE108180046AFDD4EBE56B2DDFC3872F128BCB4D131C339BFD52DC1694BE3CC63C390206DA62F597F54E69954C495DD683A25503F8E37F3CB9AD436FCCC3966D34430A5751D9EFCA4948E7A038D54A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349B2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64AA18B2C2162F8EBFCE0CECBB57C2516C1933D72FCE029413FFD07B9CD3B8A005C4DF20CFB4542C1B5EE33991EC20CDCA0348935CD698012F9D195DFA690C160FF58054B603119C0C986DBB69C2AD7FB64BA7EABBE0DA6E538B6DCE1097982BEF1676F2E1F6F82CE729BC38EC4CF9E04BBC1AB178040E055B421ED4EE8DA8CE1049037A1C8050AC7981609799BC7923C0BD995B0EA79E9567D192564AA11A88BC6459146968D0D70849C4C8FF6B7BE1E7EDF8DE8D2C3F12F5E6A86EDD30D0141F520FEC5E0695E7A806415B1140A5B29D4B8794A38ED6D2DC039574259ECF15E79FDE234C8C6614F347F9B07F8E5EDFF0B931CD68C5A5D711D4A69DD1193F67F56B66ADFA32C26E4D251D169ED47F769B061B9E9973AA5EEE68F8AB555277D164739D365D93D507B05707E400C7365EFCEA4282D3079F4504FC88CE9131AA9D8ECF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0F4D12EA7A891284AA94DC0A55154C7F4B33C6A0D905ADF95AEC20253E8477272C77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981D6EECAFE8534E2538E22B627D3974100CD9F2633782F4799F7CF1D8A4454AED2C61452924632D0A4B78D9C88CC1E9DAA6A02FC37D49A4423B4FC5C52A82BAFEEA48D41FD835314AC901A6BEE00D5910C4A6F5BA8F375B8B2E0F9E9633BA894D16926C76D88E3256A3337829BF81245CF173801D3F964D96BB23EDD9772B1623D79DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA9076B979D66AD9FCD914D0098092FC24DA2D956E1ADD473F5D5E97B81CBF9F42A45DD6CE06682BEB5B740C0872BCD90D6468129848CE45B8C70F176035CB05236795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1D21C64D6EB1AE468490B50A06C706D32CF44A483219FB45E14C654CD2ED13E0F3 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 8392 +sm = 0000000000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA7010591AF601BF50208B6C5968D4F692F07279A9C6AA2E66590F7D2E54DCFB47261C040A14FD137EE498C24B0DC750905F56FED22A393C31815CAF6ECFA1D3BC458E8715C21A26FC1E7A951C54A30ABCDB7EC71AAD92F2662BC900F9E9A93054CF39ADF736B5C6988A42FAAAB94F7911C85A9B081A35349FACE8BC499CA287720E65AF6BD9DE79A988F24DF6B71B22E8E50F3DFD73CBEA35CBA762C7D846E79CE6D29562D5B58D74A5EBEC8F6AD3D6D8CDED91F9FA51CDA414D653852E50C13C0CF35BA4B0955661EA3FC882D9D64954405502E2BEF7D3063D36F993460D2557C79729E510FD11DA67C0C0D3B6448B88B96E0834210FDDA112F57C7B4FA60EC32332EF80BB3601C44E35C901ABEE1EE25BFAAB80639021377FDA25672D97ED4126B888B571BCF4A34CE363BF227A5830ACB4844CB17A942625686FEB09DBDA47AF755D050E219A6031573126971470E90C947BC06E3F76A8E7354D2A87114187F9CF92824C5D9F9938FD4E861397294A51035B91B14D9786762BB11AC06C6FD0C6285F48FA30DE2E92AD9D0EAC1F4B2F6B8DBA9D1F8CCB77367706BBBF6A04658E8BD775633D41470CCFEA9283AC792FB671F6E1BCDBCCA7600910D3127BCCAA772AEC184137C31D2F41DD1FB349EC1AC61FED09B068DD382CDE422B65FD5FA8E17247B0A3B8D1F115CE27C50B8BC81665A65D97C2991F5078F1A33ECB61CD11AA7F503DD53FB1B3AF7ACFE24C28A700632DD3934A56129B66BA60E6BE40B7EC27DA47D20C4427ECD55AF940037B6D3485F6D6C7B3CDF5A5C19C958655A51A34BA738D8CDAD826645020A0BC02F5F6F3B6BFD28319B84B5A9F3FD9D99DA363E0267D5B1F83087C603CA6D731A4AE32346FFBF5BBBE7FFCD206304CA468789748789EE3798D4CDD773DCB6E36B719EB4B6B164287FF5C6D837A25CD01DBC826399C54E3242BC1BA4078FE683767FF48114262E30C2D1B55C983DAFACADCD92552039F9209DECF6F1CD358590E9C0DE9CF1A5AE165FDB700A9B4B14C959CA89001BBE933F84F17D6C15B50AF1684C8F4044CA7BA2CC196C7F3CC9AC2603194A9A536347975AA3A6B8929A3E4EDC681AA1A0FC410C54CF1CF561C6741E245B269AE605C8460D5D3C427E39CD5AC141104D0FB6A3D09F71BD5D57EDAB310998EF776BA3E124B590A373920DB5A24CCD39D66562EF2909F19046FBFC0BA04D2CF7A9CA47D87BEA4D52FB263B57AE5ADD901CADE838B1D7347D9E47EAF6456148C6C4E44B0B3AF44E84EBA5997051F779812941DBDEC0309FE593B55963647CCC0954E8D57F85D73CB40792FF03F8F20427D951444990CA3976A71368A7DC1455E880722F0300029FD0D41FB427D0515FF9AA3344F5F3E4811431191A1AC406B7A16DA106310002B3D710DC236EC8D68027C56FA74F71482643230330B6FDF0306DA1A3980689E09376BF39F4C562ECB1A68E02D5D91318EC0C91D38E8E480B8A0E65F452500B9471B5BB0CBC8D62AA1AD1A74AC26884557924123193F3F7540906676F61AF2E5B8879D61077A83925E92D1C3106A85A7815F9CC0A00D536475C5C63263C255F9CA097AA6C3B65C5CD659AAE22F412427C2918AD8C309342C8369BB454C508B82F2761B1AC648469993DC8770D77AEC80AD8A05129D20EBF2AB9CF7D5739A4F0B796FA3E18D0B3C862254D2D1EF0C1141EF2A665FCBBEDA2BD28B70BD0C4123DCEE5A1D81F1E20ABD1DEA550546C1D13ACB5AAEA1E6F2304541F641343DDE809B1A99E617BF85395C38D7B367F2C2AB5E26A156437E7248DF2E9F2F617049A7ECAFE220784990CE695E1C32EAE4F10BC988CFC2B56742FA299C57394432DA7B7615487DE8858DB8A45448140CF4A9D2152E12279DC7A6AE1DE1239BF9B1ACA841B2EF96801D464F6EA1053BF96F6E69F495D45535AC3FD4411C27FF7DEE1ADC490D79B073A0D4A04A903D84921A5FA52859B9DED1F1EE674256F2A57DD5E6616AE1EE474D3F1C1DD7BC7F282E6DA92731914758830B8AF74345719259AC8398F56A7F9663EC9CE82C2C0864DCDDA13DC99CFC527C2F42F86DAE54811B29589E8CEE39FB9496CCB77190F052B8DC58C76C5ECE6F0FB81A47088D8AA2085533F7D6427AE4A09570D48AAB9446FB0A49A36AD6003420C9B64A27FA2DEEA97D1D4BE804FFC6B0D772DD5757BEDF361C340C9CA3D9449895E9AFAD2BF923436FC4EDD59550F149304B3F9D24448FEDC4593A0F94EDBBFEFA223EC3FEFE59A34E94B985DA3E652070EDD15A60D47A6C319D1CCB7129E77F28A9E6536AC00261E6BEF5AC25DCE824C508AA0403E063A8562FC21A25FF7F99D4C518A32A99D3E41C8DE7518484F9CBC19EAA901C9B4359152FCD7C0E51C82C962FF3F9A68B4F8B30440B23AD28725612F5FB98FF740AFB457915740084644120ADD17B445078AAF54123FDF28F3A9CA137DE547F35FBACBC8F23207A7A3E6BF9CD001E18BC590C757E05144C3D05918E358FFAECC0B51B2F0B06E3869667B1DBBAAAC4AB4167776CCC2FAD197BC60BC76BA35F1FF80A96013054323266E972FD51C1610F8C04E01E16266C271B3B10695A6321BBB5DFF292DE959CBF408916903F8E0C9CFD2A2744016E934D66314506B7B791F5F9071C60545022564D64D7DDC92EF9D6362A0CA8F7FF48AE9B71A3A14738A7AD925653951A1DEDBD16EEC484417E92496276CB73AEAB964842CCA5A527EB0787680648B9932927D7EB2627B3D73D254C1904139D8A2C764F72CC114E249FBADEB2B0F590830E8EEE33ACF36AAFB08E1A83C9FF28E6D6D623EE44A0B86713015BA15D74BA7431EB5BA91C739028B83133C5AB36CCF899E10440F06BC626856A2015DD832F087A72864D390131A760B46BFE305E3B4E9912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70D8A18A427BE88BF379EDAB2E45A1AE5F3199C5D6C0BDF55A8CD1EDEC7EAF92F0D011CBE8E48BFCBC428382A66B103B905C0CAB36A7511B1BD6E23F4C69073CBE6C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1ABCC7BF5184638350478FE05829DCD0C5190BF84804D293190C08140A600415D691DBB652DE950481258ABD45E76B9668FEEB94EB6605DF5900501BDACB58F4CE0F6B0120CAB51933633EF98DE5471774EA6BA1642AFB0DF6C7041A8C05555A5F1D0212EC753E23A7CF68CE52417C9D7CA5F9C180D04C6B64F70CB860D2903E843B956807A682500805ED38DE3DB09B05C5E31C4E78C72F83F1446F69441E4D9D9168B4F97EE394586A683D38B9FC72FBD5D92D976C70A407E0B1E25F3046B5832CE029A1A95FFCBD5C8B157282F7364E680C60B252C49483FCA03529693B074E0D2B1F6DFD6463B974DE6829A616F20C839B0D2B8BE5405623B5B722EF22F7A3BB78E91315F715D9DCDB0C8639CB8A90685BEE7969671789047083CACF24FBC4B601B1B23B2E79E42176B2438CB405BDF46369F4DE5F411B2ACD32BEE3065DF987DFB8B692D4548E69E8F52A40B52D87261DAAEA3F734803A146D4622D4C8B17E1D98A7B04CF346B99E512072176F7A8811405EF38E007181DA3563CABBC577F41D6B8EEE36B0D67FF4AA525185A5821F2ACE2DD7F0607828ACF8AB08FE940D7FD268225449F5D20ABF61D2C7DB585A8513AEF60841E1BFD4AD3C47D3A00F68F71DCD9236D7E0FBC428C7095CA12D8D10B2E69C9FB6C976F4831246C9C0E2686091FB040E21C594960A1F6734A0B84BAAACE4EEC7FD1FABCA7F71373620EF656309B93B9D768970B0A03B9E07FA9C888A01D85B0B92F6550534E528BFF6289CC398003AC6A91CF86329B6BEB13854C20A8A75DCBE7A470B216C334CFE6AC120B8AA42EF5A9BC9FD224967218F17A334DB9364F966DA366BE08CA2D1C6DBAD769ED1537C3F5528CA849841BA495B78D07901481631E624DC0656F7F5D0B4820B6FC2269E404ABD245B49EB4FE7FB119E88663C8B8E75EC63C9C5A8EE478313B3B058DF1ACA81F65DB0F2E3E411A30158178585699BE52B6C11A2DC966753D7485AFBC75AB6EB6D0443DAD871D0BF43128A057593EBD325466AFCA3EA492311A31788F75372B5321217937AB4FF23D37D3A01E3578E758A2087941120E801C12F26FCC55D089C712C0A05E67122E28351745998168D1760B16D105D854BF2EFF369971D100CF448D3D00C2C34D5F6037A07522DE2EBE014E1E60D7A535B4CAC42EB69F7856E7A259627F4492A0CDA142D743D7BB90F78EDCC15B1EDF8DE7D0D4366367E581254AF959768265DAC9175E18F133DFFEF628CF769EE7E9BD0E07259AFD067AD441ABF81FA7726FEB1140C3146BB510185AF098DB53040DB97F1EF894CDF900B1632F65393977D69F5FD1FDEF8E6A2101281D4997C7E4F821A421318E413A87250637B5C4A4BF18A2D661BB2458CA7C7F9E320228FFFEE614E88838DE28767053DAF289E9BB8073D60114D20309CD17A6EBA5FF2FC47B49402DA3600DBC4323559761781818334D1C0CAF34FAB5A940C83D6A363433E390C3B589E1B6D09A2F4276547FB279D1F0E2D1ED91A3AFC953F9E7942BEFCF2AA66B19AE877A6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291D560067063A6EBCB1EABAF7FC12F66BD94F1BAD021254D0CE1F1F850B081262A446E84188C3A9A3CB89A80BC9E8F597EA247A39A6F59BE2D76CCDD6C96DDEB9EB0A272D02C5327DF20934FF8C0E26C71F6736FBD5B85A56F15E41F03DF2713DA70DEC489B962A1F7E119465FC8D72AD1DA559EE0F25FF661AD2F62C6BF172C4B7B0891FF05D0C985FBDCC4DEF2DFC3A73AEA39EAE9010A080DD47BC1268BBC1B5282DA83C62A9FE25CBC62E611951A411B03FA8832E227D761A35F4FB902E54083FD05142177B5D2987BE26FC4F9C5D13FFA21E7488F19245FD19D9FE2DA32608B34833D55E1761FBEDC88E644D7CA5F8D33E86EE25C65C2A6DA4F57D2B580FE5BCC31B508B8177B41775B459DB06F4AACB419F24EA979AA24C996554DEC91EBCB16E9E1B754DCD221E02231F10FBAABF79E362A514D54670DE7493B7CD7B66BAEEC1D3E5B7DF7AA1564E1D8294F454E439B7F102074AA586FF5931827B7F7FBB0A1E0563E934CB60493FD19327C71D824F361B1133A15E47857567979B5F8288D5FABC9D1D47402577CFAB60BF840EEF0D9173D47757BAF197EE10941704811690592F587BC7F532446BA10B875CB7994CA2613A25F65D16A6735E9CC0C4238036F68FFC1A893DDE19859CCE3F5ABA348F769D122DE567889C14924B243B1379AE65238446E7294F293F0DF1751C166CCF58B4F76A4A7A6178A136E3F72D120FCCFDD47311A340A0734C7DC77664B6D7BD87EA93215C69CA59F0DAD8E258637B49DF9864B84B76089E4F50B6C2BC496835D701C6F106B2B96CDA03A7F118AB5AC2F7073E7596BAE489C83FE68A8DB1E9A5427A31E8A6DC4E2962E5571FF061908EBBED929D64B2505C1C491CA277C2917E0A964218059309167716F47FF2699FEE7248ABFC6723085934D706ADBA0BE046CE3156EE682A5E0ED51534CFEBFE9B7118577F6D3157F31E8D849071E31A734BCC1DABDEF02B7D817FBFFF2CF120ACAF9BE403C35D92B960CDABB7242115FFBC4208977E19BFFBF250DE7C71814EC7206CB8F2E1D523E293E557D49801FA6D9E5AE279D396F91021690DF5EA153B3020CA3E08D8C53DC9DCD731315CB24C9394C6DEA84543806DF231011B086BE37A57CA2B888A74FBE7379EA346ADB56D932BA4B7B857A7918116B70987865FEAB8A42792F788F8CE13F75670B36029660F68A7E27FA23EBD2CC06C7CE9A51FC7B92220D44C4E9C7900E1FFD77D08D35B34B201EC5DCE6348FF7AA08F0DE5A4AE7C664F8E70D3531E181B4B5F7D74E8B6FCA7AE776AC73C4620B77C1C2397B987C241CC139C6407FEBF5B912A407695EE8AB6612C8C3D610D6E11E107E43AA6C638FF86104557546FD5CA0098C44C4EFEF0825DD5E8B33E5311238A32672242BD19ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDC05256E7B9EC23FA6F460956174696C9283AF19A615B7FD209C25EEA0587D15765808D7814EA792B7C31F469AA7004FB9A78EA5E59459C6E3F75E9E4DE961B5FABE5149967C9F97B1BC5DBF8E297DB4B25FC55241FDC189E9488FE06F71E9D1D4E19D50E7A3B81FCFA4799B127AA0D8C12FAF48811D52E4EA08D965813E20A7CB532F3EBEA5CB60601DDBFB1CD19FCE3F0A9CD1E452D1BCDDD215B91160F6EF5892280D847E32600F50E5DBB0DA83A650FD17E4A58EC02BC05DE23CD3B2C04172708C15A96A3D43A212FFD4401EEC87861C35351A0BE9D7D4D6AC5D60DA8AB5E1BBC7D943F4439AEBD7A6B022C8EFEB712BE5EAB7A1802CDD2FB9D93FA6E4383586E517A4D79D9FD2F6BBFEF8C65F1F3111067670E6A059A1308948697F5650C000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F7F8F9EAAA74A5C910DD60B2FA5179B3FC341BEDAB53B1E957F40AFFE59FD454EE839D34EE92ED029C1B5853A46CC8B48B58DC4F74EBE2164B7F867B17ACD180761BBD5017870DCC53B0ADDCBB8DD1A6F5D014B1A789493C53C3D7B304F6237F836AA9372B0CD7007588A7EE166C1F8BC1C7826CA9D6E2D73B1B217E238FFB65DA1671204B7137B3C91D19ED0DAA12A98AB71C239C6F0E6B29D3F61DE3F71688560646DCBB9846A8F28BD1E7606E2C93CC0CBAC8A85BB578671BB01347E7B2BA757AA92131B2693D7F9501E87FC7C1BBEE1B8BF15E28DAF9B74487ED12BE8A4075FDE22DA018C0531776136F0FAB5ABF372E160CF51685CD0B8FEC7D63D39F4A7EE635051E54EEBEC7E8C4A408EBE848B7255685201592E3730C4DCCC6E7DE956B4FF296E76D0052EC6C037ACACA6E6474CB17AB271FFCA98A688D224C3A25425F1C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB483F7999C92CE3962C6527BCA9BCD8AA4BC4358E39DE5D52EAAB2FCDB3D23E5FDB643B9967374A140DC0813D252B1730B592100644AADEF3DD4BA506B4D4B95F3F95D2984783B7EFE70888FEDC2F8BA40338F5727171F1D799BD2E214D18AFDEF078A9E3A5823FD097F6860AF7B8E224D3C5222A049D22E7B73CE6D9300530DFB179E6FE98B1C807944E610D3A1516646509316FB8E95E16D0E368B0E95370989BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB71410EB0ED1462BD35E503C47AC3DC9E9915C28E375719CCDC8F265898EFFB5A5B0212D18F96E473E185736ABF8B9C7DB9E75681B0CF51697CD4C44B0BE03C799CFC37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B578E146EE63A9FC66C147592E35C3E7785F3883D458746E1FA6E05C928CEB6E4894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779C2092E817BB119F33C436D107F97EE21363AA6D16A8D7C3735F4C9995180C4B5854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F046151EEC6F1BC5A7CEE799165259DEA61A25806F16B82C0FCBD046ECC5597A92C4FA14B6BACA60BCC65AF37A12AA67AD84239FF680AED031EE172D1EC34231230960B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E079FB5833EE071F22593511FEC1620797AD8A38BEC92A5C958A47CC030CEADB4E60CA548C946BD7B2D663B5A34F11E335ABADDE0126BB632F87518103815FB41C3B30C1162EBD9A23A40A2B1E47C1E8530C4E308BAA4EA544F5416D3C2B19B8D75B87396123DD962FCD143732645E3CBCC799D52A889ACC0397AC81405174220EDCDE3CE13663FCF49CD05018BCD4C8E085D8B055BD4A38386222164FEC91589493238047F1CFA07E7C2D8D34775BB61DAC79F301F0942127C6787CFD093620687E9A5C8E0B7146153759272866DD82A69A178D3BBB3AD2AE177DE91B44A0C0CE6C4DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA167815801985FB7A952CBE74331B6EF9F545A8D958BA7120898C02DAA3F7CC187C81DDF09B5E9F281CEC29A0F012F8EB726DFD7B193833CDA2B0CBEA378E6FB25C84C8CE85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B6C933E397A7153D950BD58C62E8233D1D1C276157386488A275508CEEEC7E9896F8B15726ECF4CF837328D80E8E1A4382B9029C26CD3D9205C66E8007EB5C07E51DFD1E90C612FADD09B2985D352FF0F423F45A9E35E4ECAB14E1FA851A060286A131ABDBC53DB24CAAABD058E356751BD847919A68991CDF865BC959F4F5106E21201360A7FD64CE70D102E0615086133262296E48308D05AB0310AEF2C07E169164ABD3DCB8B023145BDD480F927AF80D87E7A088568195585CE2D8BB484F70353661988C85A63C489C30724588FE31CBDB00FDC94A011F2D2A269B872CB517B9738E423B8A779C6AE71E3FA4D2396FAA0B00703FF9EB574FABF0A1EB8AE1E59CF6F87D1172094C9FC02F027A8383C25C1CB186D5F2CFBAFB208ECA37B1E5267527F8F29F91C0FA10CA75AC7FBBB397021A44DE7DFBE23D639DD1954190897EF00D981A0E12335FA7DD99C20C3DF0A8E35CE108180046AFDD4EBE56B2DDFC3872F128BCB4D131C339BFD52DC1694BE3CC63C390206DA62F597F54E69954C495DD683A25503F8E37F3CB9AD436FCCC3966D34430A5751D9EFCA4948E7A038D54A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349B2A98243675E5887CE67C324C1894250CEE560A971E8C32D69205DB2D932E9ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64AA18B2C2162F8EBFCE0CECBB57C2516C1933D72FCE029413FFD07B9CD3B8A005C4DF20CFB4542C1B5EE33991EC20CDCA0348935CD698012F9D195DFA690C160FF58054B603119C0C986DBB69C2AD7FB64BA7EABBE0DA6E538B6DCE1097982BEF1676F2E1F6F82CE729BC38EC4CF9E04BBC1AB178040E055B421ED4EE8DA8CE1049037A1C8050AC7981609799BC7923C0BD995B0EA79E9567D192564AA11A88BC6459146968D0D70849C4C8FF6B7BE1E7EDF8DE8D2C3F12F5E6A86EDD30D0141F520FEC5E0695E7A806415B1140A5B29D4B8794A38ED6D2DC039574259ECF15E79FDE234C8C6614F347F9B07F8E5EDFF0B931CD68C5A5D711D4A69DD1193F67F56B66ADFA32C26E4D251D169ED47F769B061B9E9973AA5EEE68F8AB555277D164739D365D93D507B05707E400C7365EFCEA4282D3079F4504FC88CE9131AA9D8ECF0EA404D9BDD7F4AC2E61DCB5286BC8B66483D5459E273EAAEE8E77A5EC02A0F4D12EA7A891284AA94DC0A55154C7F4B33C6A0D905ADF95AEC20253E8477272C77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981D6EECAFE8534E2538E22B627D3974100CD9F2633782F4799F7CF1D8A4454AED2C61452924632D0A4B78D9C88CC1E9DAA6A02FC37D49A4423B4FC5C52A82BAFEEA48D41FD835314AC901A6BEE00D5910C4A6F5BA8F375B8B2E0F9E9633BA894D16926C76D88E3256A3337829BF81245CF173801D3F964D96BB23EDD9772B1623D79DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA9076B979D66AD9FCD914D0098092FC24DA2D956E1ADD473F5D5E97B81CBF9F42A45DD6CE06682BEB5B740C0872BCD90D6468129848CE45B8C70F176035CB05236795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1D21C64D6EB1AE468490B50A06C706D32CF44A483219FB45E14C654CD2ED13E0F32F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A02E88916DC8ED98AFD66F79E221DEFBEE75A5F18AE06DE81B8FCB94F06AF90A6E36B516E95723A80EA6651490B492765305BACF3DD8EBE02F583A32BD1537CDB034B4DF991724F7B078E55124D36BED20F8846C7FACE620FC7ED376EBE80E7B7122931848C35D74251572804688C127A1AEDAD1003741525A657B5C2901A753E0D14EF5F9A0D5782597165DFA12CD98F310CB2C667C34350C4C5F8E3C31C295C79F9561C0CF3DCCAA0E146799F097185974B77D76EBD9C40646648BCBDD85F00BD7BE65EB0B86C45236BB3EF4FBEDF9063AB38DEACA2ABC25C316C62A8FC0AAB8804D54A84CA6602AC2415383AF59495ED3FB5238B5CAD3D30ED637A6F2D1AA90447647D9B1231825578EE75493A63DAFD2985E8363295A0F24F454C3D59464527CB63F05213AB34DF7B134BB172E3FCFF116BC5BBFBE3EBA5B09E652A4C0234 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-6_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-6_256.rsp new file mode 100644 index 0000000000..f775441ed4 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHA2_60-6_256.rsp @@ -0,0 +1,12 @@ +pk = 000000076948691BBB3D39575B96EB00BBE25665738D3B70378EC25AB76CD8D200F9BFDB04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000070000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A6948691BBB3D39575B96EB00BBE25665738D3B70378EC25AB76CD8D200F9BFDB04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001BABEE5DDEAD48C384DD12B603E7DC662BECD05787E659B7A4F42C219604631E9010000000000014FAF3A985C827CC08F0D3F4B0931AAA529DEA84CAF9C6EE9906E2A940BA1E327020000000000010F8E4B4F87A6782C5EEC46137A8A8C6E86E11F46C241FCFD839218BB0305105203000000000001D49255A7D48890564ACBEE0BD3619157B47C374DEEC424D7430636AD855D145C040000000000018788654A63F4B5743A54543D6EC5B5DF61BB9756223D195F0C9455B82BB8AB4A0500000000000175130597769A70C420AD21016DF456DBC65C8DCFF50B371F703C779010DB61E006000000000001A4BEAA773590472545884EA0AFDC81800943A8BC91B4FFC76E5ECDC6B878866B07000000000001E4760EF548991A02F056AD9A34AFEEBE6BF1568F273258BAA58FD72DD9D5E7E90800000000000170A8D3850B38CC15CF6F3D5774DA66E93CD09EA69E3B90B6B5E24A0794C523CD0900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001679E9E3F9DCC784BF6B061A699870789E78B2AEE2C1D9F082DD7FD241A53647F010000000000013A62723E901C4C50A6D05799DAE9C4F804BD9F01AA226EDC129C77E962D909B502000000000001F1F2182334ED10684EF22D59127FD103A216EF4CB169A4615C1013B2D00D143A03000000000001916D09F583779651E6B192ADEB350B07714F00E125E51013C6A4F41EAB50C2E7040000000000017D93C20AE191054626B3138F02E186A4607EDEF6E32DD3B2D788325E88FB01E90500000000000159008B71F97B67D9710ACBCAD0DCEB434823D0DDE4E8526701AF9ADE23FBCDC406000000000001410E6F39D12638391198E1827F643E6547AD7438BE85774B713D8FF3D8CB682507000000000001030C34B96241353C81CD7DDEA97ED6CBED8C9F9FB86DB60A6B78E39A253C001B08000000000001B07CBF5330F3B30963D6B0A4AC7AC4DD77585E4EB8A08B62B9AF1FBF42B76FE509000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000113CD47F2466A56323209409FD7FCF7485A71CD8CE96D61298A20473D9ACBF99C010000000000019AB3950B30D3E7877159B364A25B214B41B8AA32E293E2DDD44AEB7DFC560A82020000000000019C359D104347B69607EB28A02E6924C24BD2A26DE4CFFF3FF98E48688E291E58030000000000011EC9B78F3B1189A5482238BCF700922D642E45D07E7EA10833E31A4CBC3CA08F04000000000001F37353B4AAC3DE6FA6FA583102CC2F35D6CC95325A07AB88D9B0304EF6F8103305000000000001E087F84EB8A6A13A9581B22CDEEF8942E186FE62896C636D0503675B28692B72060000000000015FDAFB6EEAA60CDFFD2E2D1C034AF7306D60B106F145206FADB857BA565C66FA07000000000001CA463E7885C94740495E419265530662D2D8B0CF6C9E7C290FA86E8E136261DD08000000000001761CA5CF20BB11D4515629D8BEC9D72E02E0D3392C20084723610CE22260DF920900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A3928351163E04D8BA817C168A0CE68CAA6FA744E7E30A2670B2BB88F27810C887E48E90EFAD40F9735B5767F60EC515C146D56EA534C970E04BDD10302D85A2317C478BD195FC93499C051F5AF61A6C5CECB89A1D67BF5BE2CA7EFBDCC20B884597EB2BB0799DB9B86E2EB8FD93389AB91A391F2D68A057FDE361AC97A87F4406F40A7EE2E7709E46DCD756617DCB0DBBF43E6BD4851F3D834BB53CB150D2FB7B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019C1A7BFD8300283215BA57DB5CDD95EDCBD04E1C41419317BC2069C2AAAE22130100000000000143ED646E32FC21554D8DAD350C5732270CC220F7E264ECB5B7A8E8A4586D0CD002000000000001762D040EECA13E137753604D099809D946063368BFE1C7CF0E6549FCA746F7C6030000000000015FB7406F1B25A2B4A6A1666269772EB08D6FE78D8A8395C56AD80FE6924DF08204000000000001207155BDC49069839D60C0C74C9F57C739D2F36E6AAD0F698CA840A48FB11EFE050000000000012B5052F4510570C5839D41287DA3BD24DE8CBD40BA9E159E783C5812A28606A7060000000000015C07001390BCC398A47CF40395338496D66003B5E0C1DD7187A5D605984F79ED07000000000001285C8B2D9B398B8A212B3CE0FA820CE44048C2105C067AB9FE6FA70B1E712C33080000000000016F81A741E38029A214AF0CDE4C75E79A618C7B4942F7819A53CBF8EAA263EE49090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A768B07A9912E72515AC62BACB31DC0EBECCAA1360330949EAD48841D91C61B13E2EA79C1891C9290FEE2F779EA4EC57692960A91913AE591D6550BC59CFCC5EA68483E4066EBBF11C2D9647E7B5ECE7845996AAF856A1BC1458EA7C88E73B1C19FCE34B68DC2BB0EB2CEFD4506D674C92A2BE87429BC026542F6F8F48CB088F945D76C07477009F8F9D2B41552CD688E00D2A977C67003989D0A2FA7688B410C6C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017F7DF0085A4DAADCB03AB4E8241B0E6DC05E727E817C3B6FA27F05AE1FA2DE1601000000000001BCF2F650C31EFD6F2F09775A3B4F87BBB33AD0D51537DAF37E0D1C1AE8BE8DC00200000000000174F4FE7914F390776AF328164E738CA8EB0751EF9E535BB1B0E80B05762E683C03000000000001241535B940156367A4ABD922871FB10B37235B67CA38CD8B2B02AA8064C5CAC60400000000000158C4427DF89BCC228982E6BB71C9037890E11D302D9C0378108AFA067D58D55E05000000000001384D1A0B27013C6337247C54AA3DCCD045A950C606E556515E5055243CCE916E060000000000012318CF2B5CDD3ED1DAD6013254844671FBED69801D2017AB776CD63FA76F14E907000000000001179C26EF68F54F7CF842BAAA6E1D70CD828DECD748E792E5689C2BC065D3FE2D080000000000011085411CB66EC413039B45DC41D9098C2EE6981718081DE0A120AC81043DF7AA0900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A23B38A0E6201B3A52E5BD893BEF169D6E665829DCC297E9BF3DDE2974EF56B848D62499354AC81D756C3CEA6F0E5EED1E0E58EA69F3843B09E11F3BBF8898F1724E4BE566D1AC9AB166CA7D5CDC3BAC80652CC469E048BEDFF5444254926930835827E5FAF2CB16AF0E0CB13A3653AE4EE9C49D838F84D3464EC035DC31E025F30A12EA7630A6A630A351E06620774E7CD342027BB9AABFE167CBBA7D526F0767000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186A69EB284CFC56C72C2C83351D5CCDBEC831992175BC2D2D91B3F9378E0DE9E010000000000010A318F954C197DF2DF39A85C4B322E7EB1B16B0B4EB8C8A492F4F3B904C47E7602000000000001A9204F8E84112663772797AF87ED34C559ED4D6D37E634EFACE6A18C700CD53A03000000000001D2E20083FA11E157A2E5B72C9A986D3F47348E54C1935F48A86F7A9D78B2BE600400000000000142D78126E30680B5A226E280A30E4A2F47AF1C173AE745B1A3BF3A129452BB9F05000000000001C63B321575E217F363A1936335817B6BE75E1776DE1123AD6737CC50F99C7876060000000000011CE036EA27D47B8F7AD9F59C21D3402E6026F55694410ACA06A2972ED23F24DB07000000000001B12F5BB6C6A34E4011BC807F2A09656EBFBDCFF75F962C93B647842AD5F390A008000000000001BA14498E89CD4B4DEB6E14FCB1E51605AB6B7899F804195839EF2E0BA9FE3759090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F1C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB62334F4B56AA20F9BB57C09EBF41BADB20D36485AD613C790428C382B437866A681635BB509C97D4AA12387C320F6CEFD1838459F0DABA3DA54684B83E3ED10C07B8CE62549A876A13D86D8F3D001504D939500462E64C94B6EEAEDDB8856D13AB345659CB16C8B977B6670208B70920BA34E31E6A10EC724CC6FB3C299ABE890047E1F6B3D5A69BF731EFE803088FC8D3B9E69DF3102AABBEBE90C3EE20DD829BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB714212BBF4237C6D69B1D61531257FAFB41BCD74462C292880AA396FDB392A42C4AAD9B5492EE4F2A076CEA42927C22BF7CA54FCA135A0FF512CAFDA620DA75DF70C37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B755D1BA8476CF0553AA3B5049EB57DF8F00AC5DAC2C1DEF316793E5DDAF9F352894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779A89119240A8E28D1D44AE57D7D3252B69192353D745AE1C066DB60F6C6E82F35854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F04615F48FC178E8CD389A2DEA13C83E2534271AE7DB54D7C89B8714666381C388D37BEC8102F8497D8A820C70C47254582C5C27D3D97A6ECE379315D5520BA346E8F5B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E07949F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DB9D6E9AB3A0926402DD8095AAFB46217FC41A2E0D7C5960C1FC814E461B1F1F219CBD0A97D50180BB017229AC9F884896F357900724A3A7A8E4D479CF6A093FC30778F755C63CF618073C40F6042FB2143DECEE8DC32CE9D3E0064EE378F78B8F945A05629C118D60A6AB5DE2DA55A06B7325FCCEE42C01A5C408F0291E3610C44684BE1F66D3FB8F6BE43EDAD2EA87FAD50C993CC447DCAF79AB19DD406B20974363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D024DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA1678158142C023B3C238A93F3D1CB8E48EF84C168E27E6645DC6DC6689E89CA0A74D07087B760743BB526662636725B7FB700BBC0B3A73793C291EBBBCD4970B27370C2E85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B780BF58A5656928CC6684D80B728FA0C1570B8268DFD57EC9168CF7D39997BC8458A5D4126FEB278B26769C4F55EE77EBCD778D00F836BFA6EB13307BA2D7417B0812FDA4CEEDA359BF73865982622728D7EA8BAE1620A63483DAC957E4F8E082588E12FFC57A2871119AED0B43DE4ED1EDC4AD6434A485C64D9FAFBFC7F01A8793E5649BF33A7186BDBDBA5DFEEBCC16F2CCB67E355774B8C32B932119DA7158A4D131F560491BB42B47C9EF1594FF6F09BF29E972502A7D62A2240FBBBE55C3D82050B374EB42E433CDBABC163A95A6492A7F7DA6824B5A20527C9D0933B97C753932ED9ED277E40CCB8C4A042FD5B88E9C5D569A48F512ABA1DE68C821BD20C1A995235727654ED6E59B063EBA5F4046E7D047B886A22A7D7C5BE009F3E14629FFB78F8555B7376AA2B7B4B360F0D3C295ABC2590CE1AA36943A46379C1085D66FFE0DCF3C37C89BBF1C7D76B6D62D5D2D265EAC52164E4799C52D9A7E67836B66532608870BCF43815BA0633B82CF8E92FDD0A4DF829039370202BBD93541D4D398C42900F96D70AB85AEE46D4AE2CDB5BC61B0E57DE8AF9BC4A366730CC4A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349E9A943B50EA190BF7E28B4406FC4B14E77203739F8DF7D168EC43FE06D0645ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC40509461C2CEE814F7E26684AB01D51A1385EA51162E9CE43172A1564809B328A45AA68BC14BF38692467DE23B8908FB07BA05C90DD44A372477233DEEC84BF89287B1F8E1FED4F275FAD98265AA76F0D798266081567140ADAF2A9C64F41E053D1F329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB03F8A842A1FF048CFCF92A8D77409DE43CA455C5ED59F89358559BE214EE1B531915180697A948C945A9924FD6864D9CFF00E1D47F38B54092E4CFF1F92A65CCABF206A7D71F25A66969E37EA7D52EFD74B80E93CD7A048F71EDDE1EAF82A24F20145528EC96BF1857E0F1D8F19812EAB34E07D4262D195D1BB4D20FF3E226C2468B90E951C8212023248340ED5B7E4EDF3C6AF6A6FEE63F8DE613EC6F1526E3F6A9327A17C2279BEF50B6CCF1569A86FA56DC4B8866C365DC5D16B9BA888234D6860885B2A420401C0E3F8A971BE2CCF46FB27EB58D6C8EDE207B703FB7EBFEAC77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981C93D4B2B08DD6DD375D4C84791CE66913FD4E3D6B01287F258E8EB01A223CD222F81B1412BAD3DF60D89E29F4FCED352A1DC0D52A296D6D8145BB66BCC936BAC362F309AE4520552C369E4BBE918F20C4AEDF8F037EC9AE0A3BE8BA1BA0CBD40949CEB55F41C8728AA639789BD51539F1AFA46F71106F428C9FC659F34F6BAA879DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA79EB4AB02F6134488DF1220F8FA56D2C14630DA6F79094DFEE7180D218C621A32C153D6E5AA82C318BCBEC16FD901CB860793B8B3E9E357D0F008EA80BADACA56795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1DE1A2B10D241ECAD1523291D88D5D0EFE1D5CA4DE89F22AB2605BB5AF0CC6564C0FEBBCAAE5A19E133CA77B6C4AFE98FA12CFEB1A87D38463C35DE33D5B7D2E08C3DAED2A32A25502AA2B4E2F2A330F06294E202466F0701D4B361C71DB74253ECA3148CC5E1119591830C19DE38FEF1A5F9302B766F68E4E6616611EA940522EE92E6625C8783357799CB4B9F6A56A84976EDB84939B94A676D4657DBD04F7D754A901CEE47AFF04327CF6E0193DD3EF8CD61ECAB28CE8CDE2A56ED422C47BBD5E4B1C005EFD6C982E1601461DFE8EFF46797FCA8B79156473C7A964515B4A0B4373513F5DE44B5088663F1B9D235681C2A0F31675B7BD215F95D42216FC76E5C93A2C8929163064A58FCAB39F6A8700820BBC9EB62588C0377C15BD74E5B7E4F11559E54EAA502404D245774A51F17A9CA804C570941434AE4464CA23D8CB2D042633395BB951DF71EFCE0FEB7AA66CB0EBC83321C73AAB08C45F89D8DD625753795B7BDABB1CC042A4EA7BEEBA6AD585ABE6849B63C9630142B7191742C772BEDBDA162F8B4101824D6F16D189D65446852A08B37F359617ED6B0F2DC1A5648983AFC78D3D4009BFBB088F85D85B551DFCB0C99B46C65130CF3A25EEA02FAD2159409FEA41A7F3BF71F020CE618D82E4A2D5DD005E1E8839EF6B43D864647D89502AC44A7517F0D0E9E06BF9F55BE677F11F7A4689D51E5DC4892181C32AB56A831AD8E8691C9DC7C8D59FB0098C7581BF682298C353CAE2242C7BDE5F5933B48E88624CFC605A87E401D4B01FCE73BCC86D9FDDE138A185AB4B79B2394FC0718A30D5B8FAB24C2A67DF7C57690E380B21B9BD08674E49328286D6CD82FD782FF7BABEE169FCEF38BD5DC8ED8ACB324A374F426B0D835A5A947627DD5D026DACB3669212EAE997EFA073A3800694A8470BA89780C06F034BD1ACA26229A7C13345B4514B3C48A810C8A017062BA454688349B3244A3022F86EBD132636D566A899C38D183C149E8C9EE50F7F254409A4FA45ABB9B74750B0FFE552845BD460BDB3FFBF6259FA6D048B59198B4FD2B135A9DD870881D24109F95CB1B0857B395683A40C358ADFBED50D70A8FA540F6006D2493B59AE4BEECC8BE3E70396BF298B2F49B468B64DDAF12FD0C594DC243A782FB8862B2B73BF1F59FF1B812DCE96AD72D73D928EDD5D6D384CF214C7EBBE25676FE612556461D465BD1D1C8AE96BD8F349371553AD9E9B80623B49D5C8C38489415ACE7DB17DEA495DB1CE9B68AE228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023C8C898A4A7D16063A2F7FB6F6C00EBEBADE4B5A79A9814803CDA526D542E0C4C44DAFAE06659E810969F48EAB6EB002F7938B62157E85E1BF258D2B81ABD9195EB828938D84BCD92C9793BDA17DCD6ECB92068BEA49626C4595EE621E192309156F9B0127FA44454075F7C73A94992400B22CAB60A056EED2E04045E74494017E601F044245A2B64B83EA8BFEF2A02A32029224D3C9F5DAE64E4A3298688C1E4205FD9038743CEF33B08CD9366560AB57EEE937008332B6A4224476A759B07D04DEB016DDB8EDF3665BA71053A894F98DBEBA95EFEE3F46AFB944601CC71C39315012B024E672E7CEBA843F35C6F435983AAB0F14BDB63B2D130A91AF9F72CDFD73EA39DC02AD3074F0E4B3780E81732B550B298998169B1640D80FD56474FF655A233E3ED6C48E5D94A4C6D31ECBB5257DC07F29D5A4C98177DE0A4DE1BE24D2CA3CEF4DD2A3FFBD818E75023732E1F1D3F9051AF6E8047081FE588E2492E5EB4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F933819140A786527AEFC7A872908B98E8356286485E2ADA68D8733129C32FE7E0D0B7AB63E890DE8AEC5DB2D52F88D328E1DB56FF586DC2026817A277844C18228D01C4A792C6D27D72D4E36AC852098685807B31A411B62DF550CE9C5080F1BA5CEB1634B8EE7CBBDA91DA660CECF740A502064AF7781F544A2A9F6527CB431A33A905262210B977C09374F03C360642BB200F00F13EFCAB19685DBAAAD7EFBD4D42A8B428342F44A61D9D58808B9E7620ACE2D4FA47D16FA98950485E67EA182414D9C7B78C51CAA4960A79B1BEF4B6BB5CBA79515042433C7505B5038C4DD0CC8805CB9C1AA93B2BF96402909E229C46A5C2C7CB18F0B7747642714BF204D42A8AF263AA6C8F1DED9414FD0E6586D7B680D4BF1CB6CB6DD90D63511150A76C2C40384A4F156E827A22D0D207611E84477254E492397A85643BE2EFA36371F9DF6119813B2CA7F31D099B0715927919FFABE384400D3AA0869AF2E95B525D9A1453679B1624C4F2718AF080BE493D1DF583843CB08C5FAC4587627805AF278A009530F8545958E7C04ECD445240A70C6D0450DE5A3F3CBE710E610D8EEEA17F97381119B8A53A62EF7F4B0D8F84BDC86BCA2245664DA120E7E36945038F7973099B1ED88113E6594EC0CBE05B5CF5ECEFD58D48FFE4C16E0F941FCFFFDE6D3E584584EC8A03AEDB6126EF5F479E4FE8C97BA01A4980F78D12717DF17BC4E9040B105B2D74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7566DC65863A7E07D0D8774305019C67D504E7FC4DF77A8821AECBFB762EF377DFDE75F24A9DEF9CA7997E8F4AF3B4E60071F11DBA6303A964B7F9C3FD443C766346B4B1E50EA1D79357CA76ACE991F4760184016A12C2368F7D4E6BAF0C8EFCF4A869F3973B41564F52D762BECBC7FA49B40D6FCA22052287E1B10DD8FA257423F984FF4CA38BD49F322C84CA37874056055B3A0C51060360F05BE3E1DA6E1829B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F3171151E6F5442468D000FA46F17DC7437B058242696056ACAAC06AF22742452798DA226D91074DEFCAC6C3D770DC54CF7ECE9ADFEDB3B421ABCD9DF305D412A71FC77801FAEA989C03A0D633C4B06766491F4C0DC67FF8DEB16AFC8BC7E3D41601BF7B964B91A8638DDB7CC08B68691D5D501B5D3D72915442F0D1B9EA4DE4A84F8D037672EA110B3F93C3AC7EDCC5B5211DCC6BF4685C2D711AF156B82961C5369170E2E76ACF126B3036492BA13A920E126E7CA29791835CFCE00B3EF7AE43ABA16123C386FC3AA80F7F55F094F1664D67FCB5B990A1B93AC8D9FD02595A6005B8CE100F00F9818D7C2313416A65FC916B102A019EB2C7DE91A346F6E3CBF7CD85D2E8FEBC968AE7CF4E6A64400C45C7F71CC17BDFCD337C726028AD4F1956D8AF94345E2FF8F1C9E57AEA206DEEC8A93010DE204CF6F3D9CDE952FB8E4955EE2708B8B19C5788865CACE48EAEAB016AEFCF9FCE16621401B9B14F01BAD76AB32105CFD3C5A3EC7E7CEDD9A64C0B2AF82072F95D2762333ADC34CCAD8B93DE773FDED0AF8569A4ED1032A10D522056894A78C45B0C1FADC66A29CBBA8AF0600B416497EA782E66C42A4B1B518B7DA3DFA17E2EC7BF70208F1911CADADF3173E26A9285466819AFA7E43CDA3E79C3379ADB9F88A8C460AECDEBCFED326E15F01E303A0BB62615B2A2CB097B045DEF6AB46F799A70EA5F4C54B215A0BA6BC2BDFE5846A65D620BCEBD2607DBFC74BCEFC9712B8AAE5BC6C179B2971829F9EA1EF896FE1F6EED7D4A3B6D04A0B96848599BBD3A5A4AE6431AF6921A26726EA8B5651B74CD5C5723D8610CCC9E9220532D22E4BEB538A7E7EA50B7FE7D21E4F7EDA1A6E232C8DA603BD8A40DD5A9E87778D5EE4E2711C229E5F66F7C19CC263A38A184B437846BA2945CFCED1C270FFCB2C9C03D8EBE37F9E2199FD4084E94A02F74C3C2E3D577470B3F3F4B0B7CDA7671722B1E900A49096AF21F74E327D4B9204FC3D7E3AD6DE2A5037A2FED9BDB1100870156824C3E2B736F55E200F84EF5C0B6D39FF0A929F20749413DB40418EA6A764BBAEA67EF31C107F7F23A1193BCD26297EA37CA92CF90973BCC7BC548C62EF44BD5FBAE7CA281C5447895061540CEC586CBAB07CC6835253C332BE03CD64CAF6CFBA2C5768AAEE682614AEDAE4CA6BF839963D13970AB2D37BBD203FC8F5197A62C183B76BCBA09E5E47D686ED98A652A176A90284D0034391003C5BF6E9C6A091108A3107E128BF3465BBB72CD50C374A343C714E7AE5599915411D31CCEDC7ACA1734B5F23783839CD46D0786814D52037477FFD7600129FE5AD39C8601C30088977D58C83B2D0B5B6AC14579F5C52BE795726F126ADBD2742BE107CEF59ACC94B78DC7A51AB01B4A3B212F10768D35C3CA5CE6D4EFC33995ACD07AFDA29782EB4D86447F622B2592F7D18E835D5F922FC7FCFCA5F12251B5A3DFAD7ED2B6C9F3C6B734F34991C30C700EE325CD9752D68D4DB9B5DD98F91348C1DFF570DD106D0CB457C4108580FB341BD44DA99F4AD058B064AE955B584627DCA083785EBC199607782B5B096DDCF3A0EC0C5F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257331504D6571E35C7E2953D0B1EDBC4B1C48F21012DBDC773107FF4B459FCD253425217787310AE7D8F74F77E60A4511B8B23A6A1714BDDCEA8694F2A8508991C555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE9414F26D70F154CE91D99105D5E34340D34764482934F3F3145436CD3AA2DDCCEBA06D0439C960E7D16BB68113560CABB3611F2CBC43D79915CFF16CF0BB72EDFD858830AF8C790F7F1C18409C4C48601F24454BC986B12540B74EBE53F5F3AAED84C8DD523702B0492BC34B98F2AF02C856882F37D1234C04B42060DFDA8FE106CF570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41F4C820CD5553B0132BDA47AE8C0A85874D1FF5D23AE2158B85206E9F95CBD6DE6F2092A31D700E8E86ED0009F9780B1D349E01944FD5FC58A95CCC7502C6B1385AB36D24C663C8316F2F453E88A98EA61D721FBD4B018F43B84DD5B5C83316488AF78ABBD005C15399B7F94F6AB6F5239B10CF44B82FA774ECCBB5CB932A51B1C5202F112198FF20A160DA0DD130510C4540AF4C9ECB078C38AFE183911E2116F130DAA83432E3B05F76DAFA8C9285CB7237B57407F2C4999D4ACBAA916D2887D2ABD50590B5F761D3995A3D484A632696156ED00346555A19AD569E80F2DC6FEF929F3AB753AC9F451D991D1F9C614CB562F9AD1B984E94BF00204B8E0411D9AD0D374A9752B6989CB7AD969B047E60F5D371FE4FC3D17B4DDE42878C758FF19EE3FA205FFA1E5A3ED709AF71DF3527F26F712462C0AB5815A447EF29BD1887D7CB8FF44C2752A9E1BC890A80A5444E8384BED9EFCD06F26C467FAFBB01B97EA07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42EAF0545CD82BF62FC699298C98D9B9947D436D234DF8333E144C207D0DE124707A1A3262CBDF544C5C6FE70F2137EDF11BC8A3E2E7B6C35909DAC8C160CCBF3FF25275B7F97E5E0D56349A1AB617E944BBADEFDBBA8BD06B26468C961756F0E1506F5D2C5C332CB7D18155B3964343C682A5721C97BD5F6D675D44FBB9B5C9AE58A02BB327AD51C927CED9F3E27C8DCFA2EA7F4F20867DE29279B5DA09E70B6B6ED9C2C21502D185DAAE79A792F5D79C8814375643B4E69440EB7AED63285EE40ADB2A43111BB8E45D109B955B309FBDA17862D551F72C2EB06BABCFE4BCF46468789347AEA8FD0CF3E2938521DADC71D0EEE1F435B38023B69022FDF00B3D1AA0A456DCB917056F934240BD6C899E8E0D36E4F1C8135F74FFB493B7591BF9C2DD47E2C2B64A5CB0D34A0DDF8486DC9CDCF85E8D5FB8327A486076AC1AFB63681A253CC57B65DB36619DBDA966569822860B30D9DD55BE869766BB1986D254A1C486E6990EB6CC4D22E829230CC0B5CD80B6E0C3E4465CBF7AC3480BF67E671B31E38F24800A61B0C98589FC4D98BC896C27D4A9F8EAD8CA7D567AF1796A82C64F3A9876B921B4F9F009EC821DAC29B54AF75F0F5F59BA04AE753A786D0FDA22130A1036FC1AE46A86DA837812C7FD4539985A05346319FD809739255705BB1BBE7791F520D43F33F06493E50423C6418BF781834310AD40B92E396722B1C67EC08FB5FA918351C89574D5A47D31D7F6D25A30712BF53AE5410B587B9CDC0D652F993ABCADD6442E5F52229C5011D36980BB01D0053433DC64E02F535EB87F04F2FDFAD3A4378477E4A0BE652FC73E3604285CC0721796206461EC07608C4A8C0C913924525EC5DCF185891F1740E56E4E88E3C957D028D5BEBC5DC6AA9CFD3B6A94CA9B281DEB7FD816C7DD27AE5FECACB499A764C58CEF0EA4A18999B80D89D2074754894613FF9A019639CB6E1A31B91F6389894454B884F1F76BF3A20984E908C60BF36D3CCF439D9B200C3C97E076A75B5209C363FB23DF3FE4A8A792CC9FD93527667603AE461FCE62593DD7DAF62D1D78060E4AB4DC2424BCA29A0C96ED4978987C8D4F2791F61AFFD6300415F0E4DE0764AA88C672EBB55D765FD9382875CF67B176C8BC422F613D22605BFC24C2D69DA0E7CB76AF9378DD04C21E76BD30E9F923D724F6F3633928EAE801001F869B7BCCF9EF79B6FF8E8A741EFF812B31E140A7C798D8738D272068FE9A5468EA0CF60D339DD3D56A73D3BADF14504FF3FC2816A0BB816806B5CEE3164998712B9460C4227117261169E1B4C20AD79049980017BB1CACAE8EDFE29252C782485A5BAF0599796BB5004FBB2101CF98470B60E8140B828E7DDF8D3B561AA5A147739DC01970DEBFF008D85ACED07EA28D10E594E60A3569C6A13D9619FC2F76D279143D829383549772E09F3E275840913B08E0FD33C24CD38760D585FBAD94FF3B0355D247B1A5D8F22E67E34803F1D454D979BD9576F36F816005BE186FB6D58BDC8FA63935D7E4CB00A0F6752E1121241A67095E77A3231034C7D14649276638DFB1DBAF56AE7BBF54C64B817E10B6EB7E974208B16C658FBF3480BA6C86F5BDCFFD2F830801C95F5D9677EA593BA221A9E7D2F09E1E19FF70AA4A73E2FCB455583F3E21618A50CAA4B53EAF90F0AD1A47BB59B77EA66DE84A10E6D5FCB7A9CA221BA0DC44452E7074206ADE1C1B02E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC8718EDA1408151C9F4C1FF4046A444CD0F8F10C82BF697013DA572E3EC04726E89BC96ED083C2387EF5DC80AC9D74144D0AD906BDCD4608974D57F515101973291804C5180C348EFD6C91AAF5433A6BFACACD657BB7C579A195C6EFEDBEF3E6746FAACF6AED5975115AF77843A5497EBBF4F254D13D82321B29A6EE275AD3389B828D1FA19FFFFE79123A579B45B78D3F0A5AF0EF44A19F07513426CBFFA519F93A4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F2310C2A4EFFE0851C1260C26F2ECB491BD2EFCC41F06EABF26B48E9E61FC3C550F6CCAB762B0FAB75DFF6353F814E55E98A3AAD5C82CF9A891AAAC5112D38C6687E30610AC3379222517D90CDF1AB77E96B16E4EBCA8B0E8719205FF3D308550E3BA58A9CCE5FC6BF05A4DBECFECEBF1F4B7722C6AAC9FBEC2EED1C90466147C022C4B2150D6DE9B76BE278F43197479C5D0CCBBF0CBEB22C31308982105A95A5841AA37DA3BF81F8F7602C9E68C059A36BD0DD395EBDE7616091E3753AA1397A0251EC887FB27A166DCA318DA3EDFF3E29320AFABB616813DC83D4641F3664407C3DABDACA9F5EC3FF32B6538624C2F10415019168777C2BF58D51E619C872F1FBCDC8363C69AF421E6B6C046B8EACB1233A634F492189D114FC3B17B3A6FAC0CB04BE2FB6CED8D3DBF570B66D7EA390C11D2FFE35A8F675CCA65026CD83809D8C60480A25536A9DFBAE0D1229F2D563FBA86229F6B7F7CE9A9C12E6CF024402A8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D9B6462E6A24D508013457E7D4E3D7030DEE74216B3EB93C676CDB9F5E6754A10A635950D60C9916D00565C50A33EA1BBFEBF02BB60483B6DEDF0481C054710FDEA23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831FE4090EE8C8E87DC459B1CE8480E64B78A5F15EB30FF165CC9F5F261B42E5EBF469A2319A405E8CBADD241C475A5AC949BF372A41B060353FA3EB8C79B969874223CC14B6E5B3EEFE72C0CB8C8E1B114AB6B7A435B786D8A8FCC935C8BAA5BAC879B50D8180B65FD0DE78CA05D750591F479FB953FD55BB00F1D50EB99AFE348B00A63DE9E79B12C5C32F257C97CA0CF00153C8C3D8AF3988200052059CF3C841296651EC607D910D661EAA1078FA7EEB6738A8484224A29CD0463649275D117997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8BE1B269448FE8A4DF87DC1EED33FA1EAB13DCADDFD7F2BB0FFB042FDC6EA8C00A6379B640CA2855112F86F6FA5B2A622079AEA2EFB9D9063AC89D7F94AE3CD7551F3FF99B5A3C41D3770C44E9555969B97D719A3C5590B3D8A1F65995AB57BE3FA7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE97680458FFE5A18DD2D3CBF178E91629F050DBA86E31E5A42548E1582E271B399A6DC512CA068153BE53E78A5A6F83C8C39FA6F92626B000E8066A1BEAF2C21975B2FC29959C3AA239CDD2A4B47A55E0EC54495769A9293F33F23FE19A886DE5AAB35F3BC80C9CDD0FAD599DB6359B84F396E9DD06848EC5844B44AE00478C8C1FD5E964031EE21158F6FA1784A07A09E6173412180C5A0354B11480F780C1E3CC436BCF5D3FC2B5E094C1A45AE192369966B103D700B955D0FDC49733525BE13D82164C5A2996F0FF900DC890ADDE848305ED6D225460FB75CDC1453C513EDAB63E576CE7CDFA755055AC07036627843E640E20767EC35B45C69A28151210BC3F93EBB880C6419D545316029814C22D2872E8B0B4B4ADED8E44D0035CF687BAF0C593C2B947CEC9770E19E28B62537B3C463F582084CDAD9A704D8E4CCE851D + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 14824 +sm = 0000000000000000404DFF9B9F3931FE6158FFF355A8EE715C9BC6A87FE6627928F3CA1055FA70108B307B55E90F36943261B10F4D92A0F4AA0696D42E7766CB9EAA67647A56DEC2E7A09B0DC1E96F31870177ABDD7AB42345B9BF49CA7689F703557EECD4C9FF32076C999FFA0461054EA4A1E863A1FAB50E5FE03A9EA847E4A5B476A41885B53EB9A6E98D556765100FECE8CCAE704D7AE90AEABE735C2FF46DC9FB302D2A1F4CB21C6552D41F5F3865791CF993DD00FE3A036175178B6407E88A3F76605B5EAA96A944CC1878D4FBA0A59E308F18BB3A90F9704B0342262BB5FC542743D246CD503A2438B438344D55FAE0A0CBF3F6061F2AB5685E9C3210FC441B3DA673E3F029510438E87AB06D786CF52C18D7F9C95D7B82F4F0E1AEB59E4221D40C67EB131A23B8EE4F3EC419BA999054325BEB9B8BFCA6A2BBDF11FF7F8A170E9C5481D7CD71994D48CEDA477BF92043B7E7C743DFD9E32948D29632C6C47355A5701C0E3343E73C5FE2CC524A7FD21FA547675C86F6C8D4EADEB1AE29060EF687EF65344A45A5F1033DA0B50A5529AC43435DC3A8BBBC986F1ACC1AD60CC13F9BB26A1F7E6AA6D434BAB8FD8B67091BE465C3BFB21CA9D16D794635422DEF832911110F75CC152316E26583F4E3E9852B62D535029CF5E0F17381282F84B1D658B96F6047C813C1B4F4A16C6E7FE523D3397CD89A5A92D85813703EBC6F3FE6EE26DC55D4E6FC2CFF5A94DF26DA0C0170FD8713CFC44391EB96DA0957FD5066FD83C6A49B866653FAE1FE64ACAE482337978125F0DF84D9A85A5E932E940C2661A898DB130F0F2573F50D1FEBE92DC828BCBA9F7C01D56F6DB226890D911DDF82BD5D4240B66EBFAAE4552283904FC706E9B7683884AC5B893F4F81D2E14A0E4AC57BF98703DB7F13859B5137BCBA8FF977ED7AAD69BCBCF9F2CA845D008CBA0EB29D9C8155D3924964150439144860C1E5B6864506FE3EEC30FAA801B458516E35DDB4BA7A25D6C3E4B7D39A28A65A5628A93556FA9F54E273B583F9A197BFF4731E043ECFF72D42580294D9D3C8CF910D424C636850E61AC0CCF2AB7866EFF4913D36690C765230DCB89993C60885CB1850754DF50C48538A5EBA8AAB821F9B04C0A1EC786BFE2AFD21BCB353A1F77030A18BAE47C0D2B9F396BD8E5FF560328AEDB237F2717BD16C62163FA242D09159E03AAD5590CB151143CA16E6DB3F4C4BA5C64D08B9D0A5A3F6009F660E9B15456060AC696B025F2A874623DBF0B61F73C56AFFEB1227FD01AA4AE0CD5A4FA29EBCD6C0997EC7E973C3F98C4674370EF456F0FA3DFCF5C9CEC2D80AD509A65AEF0E3E663B7F31BCA437311BA799D4C2ACC138D97F323B19BB892BB18C8C530250B082F14BFB41EA7A1BEC5FEA64404E3C55617C0D7AE9E6AC7062BF0E32260C11266C4AEB1815B9D80CC2C7F5898A39D5C1CD115DAFADB4F258D8BBED23B21C65486E46D8BCA833B6967A09FC7DA038DE1464A993EBDD656682B6DF928AC9BC8079B08F9AE5E4921BA288D8234209C7E68091460A20EAA7AE055D8D71770CE9CCBE116CF81917E004306693A483A49459114295DF86CD25D3F8A716C4752F1276385906C5B141C267EE5C065802EEF3FC35AA6CF37929B5F2D4827B72B8B27B64DC91EBAB724047EF3EE1D4304B98D74984EC1CF561C5011B41F749403684937CF80B0A47392C9A1C0098C189DA2E070FAE819C907F1ABD8F0040B4BC30B0A5B8A1894B7140F8A41ED377CA4A4B94A19B762BC2205D49227CD8D9C500CFC32F70A4CF8D7188D73C377F57A9435B8BD01C875E0C8354A3E599CB7217AE688647A72985606BBD0720F6FA5C5B6F70E88234EE545A5A5DA495171254A7C4EEDBFF6C527D58C8B2010B0BD8AD0437D24E58D5DEA089B198A28F6AD355B74455297DDA5CBC8B88DEA9B7AB7D59E2C78363EC25A2602B45DE7A3F9E3C01FC51BC5D6A0E15B7B8B52A545154A2598B038C74F5873360386424FEC7650D8CC97CDD7D3E00F4C890614D359CD60FA0498E97F4AC282AA6EB56F968F9814E62F40C71033B32261344CD2269D7DCD62F7A9C9C14089C5F4966C65C61697E08F06B61AAFB4C247C6FC8412F815114AC9C3D9172C1B5CF2286CF987E323EB63EB61FB83F76123FD8CBE6155DD251E20F090991CD6489A6F4330D8D0BFD1C49F9B69A3D6A4325EA85EC2D7332D47FEB73B98F82EE9738E07F40119820C5F429E298EA348A200EB48C74CE2F0CD36756498B06C90F299FD52AF06FC80E0DD67566CD3E2651F4852A85CAE74D7D5F16E4AD53DA41D3932175FCB840A64ADC463ADADD53CE215AA2F0C4DEC4E0BB2155F874D7B60F46F671A8EAF31FC446ACA59071CC077F86F8C4723A9E227EB5E9091A504B641B459D38EB852295F33EB9706B28E8EE393710D80077306E5E83B1F23B621473F83F97BCAFB61F7E2CB455011B3E98F8CB3799F0B0600E74AC1214454C9F6D1DBAD9EABF89C060B05A54F710BB049155BD727BD117E934CADEAF3C118DD6C1CE927AA84675735E695731DDA77CCBE59CA2DEC2881046C519251731B60AA43EEE29D3F0FE2B0EAC2FAD197BC60BC76BA35F1FF80A96013054323266E972FD51C1610F8C04E01E16839CE80CEA428581B6CE720C459D6D2961C5A7FA8256FEC4951B69C04FD5383BA3FB66C2A40D85B41EE3F215A96F35898045E1DA96127C205C124C1C805814C3EFBA495E0499587494A9B6E4974C37F5C006A34FF102A23985FA9F660326DA3979A43BEB2A0C7CE97F1A180C300FEE0228AC673E5AF3D65BC5F01A722E03876D5608A8216E5C8E91E1E89EFEA60DC1306CFBC26529D23619E354A7F1332E790CD59271BECE083922C4E18B01560F9BD9C0AB1C891529371D295C1A524637A804FB84DF86BF95F7B65F3B54022725BCA40A65474F2ABBC9BF737F20BD12CFF5619912E5991C713532E81FA57F9BA562E1D3026D2D2D7373D99871BC62768AD70D8A18A427BE88BF379EDAB2E45A1AE5F3199C5D6C0BDF55A8CD1EDEC7EAF92F0DB2F3B18A2035973F56757DC09EC3CB32FCA024C6A0045077D4FC0AC0F6A26A1CC22F2E9109F9BB35426BDDB4A69EB8F45CD5B226F92E8026F1E62DE1DE435A4FC0CAEDA91C38A88F0037BDB296CD7B07FF040B1E08F02711E946B307A5A38487F53070985B8E28BE6CCE809F34100F0CA780996CD38E91BA7773BB632D0BE7978F3AF3A92B961BD3A8759590726D6C1811F9E0BCA87377334E7C1F12FE37401CA0200823938C816ED98981521470F7F2CCDD69D85E7530EBF39E3A592B1C09BC6C352C3FDB108FB26E7ACD3D5A4FC0442962E2C09651AC0D026E370F1EE1A8219C4833D70793D6E581FD25B0E95FAB1EDA67232C2FA12C4E379A6627E75AD408C1D2526005F2567CED8608E88CF53064FCDC58007198ADFA860F9FED1DF80EFACC768A0A063E1AFEE6DF1BE3483105B1C45EB50BF7863B4278422CEBA9001EA00299AC0415BF28A9C49CC2E92FC15565B547538A027886C6EB0D83B71138CE1A14BCBE4FA64052B0853EDE00CD41BF95B66DA2A519216FA1A0A8BA5F10B4EAFD8BE62C40DA2A76DFD8A5EE8EF42A8B808C55A533FC488A2B33A935A635E24F3E0C717E2320FF575ADDB18C567B1333DECB0855E069D5759C48FE6D8C6A9D217BFCB7A9D40735A3151382E3456CC4BEDF6C7EC94F186FCB6BF9398FEC934714E8E231402FC7BD5153981C7C789B26208DDD77E4796F70D6A72B7B9C5EC75E4E3CD122F72621E92B1AC515A33B12B1801B2C3E461AF788661815E6BAD2E6472116B89B941A0E68A232089C6F831229BE2EB0CD244BE4FED78C8371D2DC614445C76907F4A3EDF18722BF0998FD03209C31C348CC79A2AD06ABB1B3CC549E73B206A05345EC801A1C5C42D794BA1A35747493D76CA8567B62F0C2151923D8D9CD2F37D77E70EF7E12A80A3DC73CE284F2BAAE3816C351BAF037F5FBDF29A970BB385C19D6AC3BDECA5BE59F322A17FBAFF466E945FBB943BFE35854802837FEFEA3937069240712886742E890428C0C21BC057E82D5BB961095A5A18DE149CD19F79E9DC3CF0FEB5149F856C5A7BB82B6AFD4B5310993D9E4E1D33B4CC601265906186B98CAB4AF1570CFDC928C0A221A3BBFFE8E566D580A689AB51BB69826FA60135F60C1A1EA97CCCC9AE96CC93B66942370BCF910D916CBB7F87A0BF5EF46DFEBB050637754B0E40509441E19465B238EA45270D7BF5E0610A89B4A47AA821D9A3BA58127DDCEE4E7204C38E0EEDDFF72B07FA5AD8EB1FA89554D940C2C88EF588F62EA602BA30FA9ECF3462711612B3E1AC0CDC4C11C85ABB04AE5966743689380FD336A081B8C7F753B889BD73F10345B8C4988A7A4C865250E3707A8424B606059E3ACEA75F2F732058477097D5BF8F5A2DF82E4AF0EE9C4BB251A5657C15808B7EF26806E2F3D61137B44C9DF4196A9208065ED1C70F9DCE3C75AFD719F14D79818812360E4709E521E78B983F99B31863039069D3F86FFAAF318853EB4A1AFFC5E598ACB6B15198E016C779BB7D77C54971E4566C2071EDFC0D19B41827913C5F7EE5D8A9411AB2706F3C9DD8E2CF4AF497765A647C1AA42E3645485AD6598A776E2A46C9609C73AADC67A7477172D9F497556348B5CC055D8A6A0A752E5B9A508BCDC346BD1AD8643FA19EB36D922A018690D37D0E437857A78C47291B3530D6094FDEDB782E1C927C11235EE632F6C3FA150DE1BC1125FEB330079EDB0733B58F1CDD3D20904F85DE31C06FE375E7D1E20F4C79484C5431A026EF8F5C8AC47E7FEA2A80E17256ED956484E9004BD99AD8ECD0D1EE5790A83CF9A14827C3B5D5C25AA18255F5D512917BC1FA868AF35ED3540BF0C10CABB267F612C26AE27DEDB5665A4DE3913AA2631C034C1BD22E5A721194BE6D1E4337D1CF488E9F438BF7F77A856295E0D55A3AF7F55BEF0D7643D85B8892A69304AB1FECE1EA498B7DA996B2692EB8C3D1D8BC9BECCFECC8EC67EE3A87DF5B0B9C7C887DCB0CBA7F5E1372399F3A4F4CC7DF247752994CE0D024D2C6E620EDD0B8CD30891FAF58D6603D01C8308F95620A16B4B993AEC83DC9E71A16C2D22B89E7CF8290DB074AA6092A1F23DCD01D8B8C70674D55670C07A6D0655CF37D0516E6E1102865F0C53C5AF80A45B09B078337D61AFBD12DA2820AE45CC4B213C00576FF3D5FC21D0DB8D877757226F81078653EB4C90C0D2C7D304A6E0C4265DC3C1DB343202664008385964C6C56FA11532D7CF41E93F92EF28F3DE2CA1D5817AF2114A97BDA7F6504EBB2A6EE6BF4753274BE064D3CE467673717AD7350DE4E83A1BA27306F11DF36A2E30572E3FEF2EF6B2518419395DA9B7D4B191C88F3A863A477A2D226E5BCC04E39AAF1AA042A7B115CA26BE8DA52A162FDCEC6E511B1497FFB8B8AD23D3C429F71236DCAF9DE275D7B1D2DBE83822FF7D8C9BC7BA3AB5CB517228AFE2E30C53E64C44D02CF9CB51CE371827CDBDF798B1723B418EC7CDF66CF09F444A06DDB94355F529337D6A3178D754D68BE658934FEABD4F4874B11E739F0EE4E95D2D23B41F037B9668C9F74D2B3D31027861779FF8516A29246D766D2A61A02CD5B8E338B9630E8E0ED5BDACB017A6D3B89C8A1108E525BAD96E203E7A0C0B7F2148274FD20F9B53601F2B38DF303D7F8785D06260485D7507782E11855EA62F44C755E11DC4E5E06CA263A2E6D229726B08A66962C1AAFE0B85A896D3A21AB0E695CCF3818C69AE16DC71782D99440EC9AF4A9C33FFBC728C9C62C47E0D37CEA661064246A8B2BBA14ABF5767F33E490AEAD721929515F091663B4437BDC34F5B15C7816B7C5CC8035F4FDDB37C9A09712BA1A8E1FB4E0D8B37F0BEABA9D1ACFFBD90B13035960ABEF4E3CFF91B9871E49B16A6F0FF86445C441921D2E698117109D810C864F024F62F8D25C263CADA33916763373D76EC8955ED113F71C40834E79A1BD5E21CC2373598C66168492FFCD083D2A8E7E480F76274C048719AFF98C5E2774BB1039646BD25A240875655A77023B7F884F5852DCD9C5DA173DACEF7F01F6527CB7F5375FEC1FD2D5C90A46D3D0501715B2D4CF51166226D8F35DB7A9ABE320E88F04F460F239DC2C0B65987ADB734C1F9068B89F56E3ABB3B35C1EDBF72E5CE393330FF905F02DA9C591FAC66CBAF1FF1DABB3B199AC4A764EB5272AC230107F230E29845C2E2283763A5832809AF2428C304C07CB21A96D7B7CDADF857F54C91A22B8AE6E4EDC0DEE01FA60697269BB1299F9FD7D3699D4D865A25BF0F31F93DAE1D51C42FE755219BC2A4B2505487483A1B81BFA86BF6A99642C51AC3DC78D5E42FEA4ADCC51C0501A8FD543217134694262E0FF5957CE719766EB0CB34CA2E541992CC2619C65822A763FE6572E3B33C4C8C216B4A62A13BE7FE6FEA1DA8EC1D45CE65C4DFD09532FDAF74F99152DDBF0AAA53806F2C4EB3A156D49ED44C7713B7A50EEEBC575166A1B6CC3AEC2CA98398971F648242C35E8EAA21257BFAC587485D48AC54BC306344EDEBBF2A42B7E37B6086B1D9F54255742F000794155E7245F6CAE1088C20619158F78F7B9554B43C2872DC68AAB415F3065688612EC88D83577278C8A7B64334993F80BE7EDCBF5CEF5B00A2FC5B0CA04564DB35EE027BFB28DA1A7EEE4E72E366A22F6B50780F70355DA825FC2101BF7A057E5D26BF4216269A4C807F6B2055367D88910FBC65533CD0EDE915232B023D039AE21A53217DCF8398A5B70C3F2F1820F5CE459DFBFE7C3C9387F93D488D001F20B039229A704FF0193076F164C378E0AD63A1F11BD3332FAD6A4A6F39302C69607400E8A4B9D9EC1682E88656CF619DE7BA7384B1FD26850B80702BEE5893A4AB526F983AE3F8AD933B2D60CAF51BAAA828B87F55357DDC75A69F41F46493810EB69B9289F0954C9B9AA0A9C4B5B739BB75617C38ECBFE977BE182BE7EEBA3DE73A9F25E491756D4AE3BA047A9542BF62A8AEF9BA9025AAFECBA1F25590F71C9BBD708D6DB1AB7F44BC2473A4897D83DAEA510BADD3ECC8C9F2E4F889D5AB62334F4B56AA20F9BB57C09EBF41BADB20D36485AD613C790428C382B437866A681635BB509C97D4AA12387C320F6CEFD1838459F0DABA3DA54684B83E3ED10C07B8CE62549A876A13D86D8F3D001504D939500462E64C94B6EEAEDDB8856D13AB345659CB16C8B977B6670208B70920BA34E31E6A10EC724CC6FB3C299ABE890047E1F6B3D5A69BF731EFE803088FC8D3B9E69DF3102AABBEBE90C3EE20DD829BC1C46E6764AA8C8E2396E4FD1A65A171D9EEDB2B04843DD2845B5E5F5BB714212BBF4237C6D69B1D61531257FAFB41BCD74462C292880AA396FDB392A42C4AAD9B5492EE4F2A076CEA42927C22BF7CA54FCA135A0FF512CAFDA620DA75DF70C37EDADD455AB3C8EB0F334679EF94E6ED2E8BFACF20DECAC68B3AFF3979869B755D1BA8476CF0553AA3B5049EB57DF8F00AC5DAC2C1DEF316793E5DDAF9F352894CB9E2B7C860E4D2BD42D0053B2BC8C7F3C11FC0DAF6DECA58CA37526095779A89119240A8E28D1D44AE57D7D3252B69192353D745AE1C066DB60F6C6E82F35854FE73C1C961A0E178F047DE9EC62C589C2D7E30929DEA6CE37C4042F04615F48FC178E8CD389A2DEA13C83E2534271AE7DB54D7C89B8714666381C388D37BEC8102F8497D8A820C70C47254582C5C27D3D97A6ECE379315D5520BA346E8F5B5F7887F9E3E44FE4C156E7472EE8D9C327587A0704A8035E519B1C4A9D2E07949F7B23EC43C839B4B963BC694E34AD8F363615405D3297F051BA1B16CB53D4DB9D6E9AB3A0926402DD8095AAFB46217FC41A2E0D7C5960C1FC814E461B1F1F219CBD0A97D50180BB017229AC9F884896F357900724A3A7A8E4D479CF6A093FC30778F755C63CF618073C40F6042FB2143DECEE8DC32CE9D3E0064EE378F78B8F945A05629C118D60A6AB5DE2DA55A06B7325FCCEE42C01A5C408F0291E3610C44684BE1F66D3FB8F6BE43EDAD2EA87FAD50C993CC447DCAF79AB19DD406B20974363E31FB88FC21F83DD7C34DF85ADECFFF23FD036F17F0AA81FCF008CA4D024DAFD78B7F2D3B3C54AE60062DDCEEC2BF3A579A53E27A72402BED5DA1678158142C023B3C238A93F3D1CB8E48EF84C168E27E6645DC6DC6689E89CA0A74D07087B760743BB526662636725B7FB700BBC0B3A73793C291EBBBCD4970B27370C2E85E7BAC610B75AE5CFA9DD39290DA4DADF4F61BEFE0F87959174D2BC28BD76B780BF58A5656928CC6684D80B728FA0C1570B8268DFD57EC9168CF7D39997BC8458A5D4126FEB278B26769C4F55EE77EBCD778D00F836BFA6EB13307BA2D7417B0812FDA4CEEDA359BF73865982622728D7EA8BAE1620A63483DAC957E4F8E082588E12FFC57A2871119AED0B43DE4ED1EDC4AD6434A485C64D9FAFBFC7F01A8793E5649BF33A7186BDBDBA5DFEEBCC16F2CCB67E355774B8C32B932119DA7158A4D131F560491BB42B47C9EF1594FF6F09BF29E972502A7D62A2240FBBBE55C3D82050B374EB42E433CDBABC163A95A6492A7F7DA6824B5A20527C9D0933B97C753932ED9ED277E40CCB8C4A042FD5B88E9C5D569A48F512ABA1DE68C821BD20C1A995235727654ED6E59B063EBA5F4046E7D047B886A22A7D7C5BE009F3E14629FFB78F8555B7376AA2B7B4B360F0D3C295ABC2590CE1AA36943A46379C1085D66FFE0DCF3C37C89BBF1C7D76B6D62D5D2D265EAC52164E4799C52D9A7E67836B66532608870BCF43815BA0633B82CF8E92FDD0A4DF829039370202BBD93541D4D398C42900F96D70AB85AEE46D4AE2CDB5BC61B0E57DE8AF9BC4A366730CC4A8443203C374F1F58A2203BACAA6A0C93783B0BFD8E85A869ECA37AE0FA0349E9A943B50EA190BF7E28B4406FC4B14E77203739F8DF7D168EC43FE06D0645ADBFBC26542CD0335EE21852C8CAE8DBE734028D2F6BF457CB086172F176456A64E0186ABE46D179477CD209BDB5EE46DF3D36DBA69F5453C9AEB1E1DF4FAC40509461C2CEE814F7E26684AB01D51A1385EA51162E9CE43172A1564809B328A45AA68BC14BF38692467DE23B8908FB07BA05C90DD44A372477233DEEC84BF89287B1F8E1FED4F275FAD98265AA76F0D798266081567140ADAF2A9C64F41E053D1F329EF62E543C4E18C1587F6203711CFA12253211CE4521AE01F2273FBA71CFB03F8A842A1FF048CFCF92A8D77409DE43CA455C5ED59F89358559BE214EE1B531915180697A948C945A9924FD6864D9CFF00E1D47F38B54092E4CFF1F92A65CCABF206A7D71F25A66969E37EA7D52EFD74B80E93CD7A048F71EDDE1EAF82A24F20145528EC96BF1857E0F1D8F19812EAB34E07D4262D195D1BB4D20FF3E226C2468B90E951C8212023248340ED5B7E4EDF3C6AF6A6FEE63F8DE613EC6F1526E3F6A9327A17C2279BEF50B6CCF1569A86FA56DC4B8866C365DC5D16B9BA888234D6860885B2A420401C0E3F8A971BE2CCF46FB27EB58D6C8EDE207B703FB7EBFEAC77465237E1EE73B675C37F656EBABF91BA91A79FC679C5566A637F6417B8981C93D4B2B08DD6DD375D4C84791CE66913FD4E3D6B01287F258E8EB01A223CD222F81B1412BAD3DF60D89E29F4FCED352A1DC0D52A296D6D8145BB66BCC936BAC362F309AE4520552C369E4BBE918F20C4AEDF8F037EC9AE0A3BE8BA1BA0CBD40949CEB55F41C8728AA639789BD51539F1AFA46F71106F428C9FC659F34F6BAA879DADCECAAFA80505AC2E0ECBBDBA3679A483BC7B92A54BDEAADFA7F386BA0AA79EB4AB02F6134488DF1220F8FA56D2C14630DA6F79094DFEE7180D218C621A32C153D6E5AA82C318BCBEC16FD901CB860793B8B3E9E357D0F008EA80BADACA56795A369F5E6F910F706986E7F66A84B100C265BB5339972BBDF6B770B694B8D2DD8323E86A90E83EE039AE031A331E6D7B99E75FDE0E8E42AF855F52C925F1DE1A2B10D241ECAD1523291D88D5D0EFE1D5CA4DE89F22AB2605BB5AF0CC6564C2F0EF9A0EB57779C157657D9A1BCCF0DE21B60DCA9EA29FB5D6D36C7973FE0D8FB8CFFB812B2C3080BF0F0DDCD99BF9832A3161F14FEB8863777E8EE65B8F88B2262991CEA2227E360DE1F384A9E4C722302C42F9ED9CE1ECB1225BC3180B4CA27552F940E6D3AC102CB0EDF13951506103BF790CA9923937C7AD9661B13617CADDD3F1D81944A87AEC9AC06202EC18EF736DC325C55E21D33A313DACEF549619B2CE208EEF551E81A9AE87029B4302D012853622BB3BCD47FBB055E048923FF9ACD043DD40211F720396E02E71DB06FCE4E8D757DC264B4F5AC3089FE49361710B3FEBAE56D82E67A6C29504D6B061DB48FFCD3AB91E7B6B870AF8042312735EA06532FA075BA5DCCF6C9E92AF59BAD50EF0A3797C335F50FC43DF22481EC203C13BEEEB42DC753BE45EC74C10D40CFB3D55B68602D288855C63FCE824A2F4A0FEBBCAAE5A19E133CA77B6C4AFE98FA12CFEB1A87D38463C35DE33D5B7D2E08C3DAED2A32A25502AA2B4E2F2A330F06294E202466F0701D4B361C71DB74253ECA3148CC5E1119591830C19DE38FEF1A5F9302B766F68E4E6616611EA940522EE92E6625C8783357799CB4B9F6A56A84976EDB84939B94A676D4657DBD04F7D754A901CEE47AFF04327CF6E0193DD3EF8CD61ECAB28CE8CDE2A56ED422C47BBD5E4B1C005EFD6C982E1601461DFE8EFF46797FCA8B79156473C7A964515B4A0B4373513F5DE44B5088663F1B9D235681C2A0F31675B7BD215F95D42216FC76E5C93A2C8929163064A58FCAB39F6A8700820BBC9EB62588C0377C15BD74E5B7E4F11559E54EAA502404D245774A51F17A9CA804C570941434AE4464CA23D8CB2D042633395BB951DF71EFCE0FEB7AA66CB0EBC83321C73AAB08C45F89D8DD625753795B7BDABB1CC042A4EA7BEEBA6AD585ABE6849B63C9630142B7191742C772BEDBDA162F8B4101824D6F16D189D65446852A08B37F359617ED6B0F2DC1A5648983AFC78D3D4009BFBB088F85D85B551DFCB0C99B46C65130CF3A25EEA02FAD2159409FEA41A7F3BF71F020CE618D82E4A2D5DD005E1E8839EF6B43D864647D89502AC44A7517F0D0E9E06BF9F55BE677F11F7A4689D51E5DC4892181C32AB56A831AD8E8691C9DC7C8D59FB0098C7581BF682298C353CAE2242C7BDE5F5933B48E88624CFC605A87E401D4B01FCE73BCC86D9FDDE138A185AB4B79B2394FC0718A30D5B8FAB24C2A67DF7C57690E380B21B9BD08674E49328286D6CD82FD782FF7BABEE169FCEF38BD5DC8ED8ACB324A374F426B0D835A5A947627DD5D026DACB3669212EAE997EFA073A3800694A8470BA89780C06F034BD1ACA26229A7C13345B4514B3C48A810C8A017062BA454688349B3244A3022F86EBD132636D566A899C38D183C149E8C9EE50F7F254409A4FA45ABB9B74750B0FFE552845BD460BDB3FFBF6259FA6D048B59198B4FD2B135A9DD870881D24109F95CB1B0857B395683A40C358ADFBED50D70A8FA540F6006D2493B59AE4BEECC8BE3E70396BF298B2F49B468B64DDAF12FD0C594DC243A782FB8862B2B73BF1F59FF1B812DCE96AD72D73D928EDD5D6D384CF214C7EBBE25676FE612556461D465BD1D1C8AE96BD8F349371553AD9E9B80623B49D5C8C38489415ACE7DB17DEA495DB1CE9B68AE228CDA2CED81BA796890764881DCF4C9907BF8477F939F43C8AA173CD3044023C8C898A4A7D16063A2F7FB6F6C00EBEBADE4B5A79A9814803CDA526D542E0C4C44DAFAE06659E810969F48EAB6EB002F7938B62157E85E1BF258D2B81ABD9195EB828938D84BCD92C9793BDA17DCD6ECB92068BEA49626C4595EE621E192309156F9B0127FA44454075F7C73A94992400B22CAB60A056EED2E04045E74494017E601F044245A2B64B83EA8BFEF2A02A32029224D3C9F5DAE64E4A3298688C1E4205FD9038743CEF33B08CD9366560AB57EEE937008332B6A4224476A759B07D04DEB016DDB8EDF3665BA71053A894F98DBEBA95EFEE3F46AFB944601CC71C39315012B024E672E7CEBA843F35C6F435983AAB0F14BDB63B2D130A91AF9F72CDFD73EA39DC02AD3074F0E4B3780E81732B550B298998169B1640D80FD56474FF655A233E3ED6C48E5D94A4C6D31ECBB5257DC07F29D5A4C98177DE0A4DE1BE24D2CA3CEF4DD2A3FFBD818E75023732E1F1D3F9051AF6E8047081FE588E2492E5EB4273A8BC3E031CA33BC4DE4FE367B0BBE3530C88C0DDD7F55A358F933819140A786527AEFC7A872908B98E8356286485E2ADA68D8733129C32FE7E0D0B7AB63E890DE8AEC5DB2D52F88D328E1DB56FF586DC2026817A277844C18228D01C4A792C6D27D72D4E36AC852098685807B31A411B62DF550CE9C5080F1BA5CEB1634B8EE7CBBDA91DA660CECF740A502064AF7781F544A2A9F6527CB431A33A905262210B977C09374F03C360642BB200F00F13EFCAB19685DBAAAD7EFBD4D42A8B428342F44A61D9D58808B9E7620ACE2D4FA47D16FA98950485E67EA182414D9C7B78C51CAA4960A79B1BEF4B6BB5CBA79515042433C7505B5038C4DD0CC8805CB9C1AA93B2BF96402909E229C46A5C2C7CB18F0B7747642714BF204D42A8AF263AA6C8F1DED9414FD0E6586D7B680D4BF1CB6CB6DD90D63511150A76C2C40384A4F156E827A22D0D207611E84477254E492397A85643BE2EFA36371F9DF6119813B2CA7F31D099B0715927919FFABE384400D3AA0869AF2E95B525D9A1453679B1624C4F2718AF080BE493D1DF583843CB08C5FAC4587627805AF278A009530F8545958E7C04ECD445240A70C6D0450DE5A3F3CBE710E610D8EEEA17F97381119B8A53A62EF7F4B0D8F84BDC86BCA2245664DA120E7E36945038F7973099B1ED88113E6594EC0CBE05B5CF5ECEFD58D48FFE4C16E0F941FCFFFDE6D3E584584EC8A03AEDB6126EF5F479E4FE8C97BA01A4980F78D12717DF17BC4E9040B105B2D74DB5A8DE17226344C0D3769F1DF6B6B9C494783121EB3F42B8686D7FEF027D7566DC65863A7E07D0D8774305019C67D504E7FC4DF77A8821AECBFB762EF377DFDE75F24A9DEF9CA7997E8F4AF3B4E60071F11DBA6303A964B7F9C3FD443C766346B4B1E50EA1D79357CA76ACE991F4760184016A12C2368F7D4E6BAF0C8EFCF4A869F3973B41564F52D762BECBC7FA49B40D6FCA22052287E1B10DD8FA257423F984FF4CA38BD49F322C84CA37874056055B3A0C51060360F05BE3E1DA6E1829B2AD90DA73CF2B0FFF812ED813AFE0934EFADC2CB387678B5A2D6C0E640388F3171151E6F5442468D000FA46F17DC7437B058242696056ACAAC06AF22742452798DA226D91074DEFCAC6C3D770DC54CF7ECE9ADFEDB3B421ABCD9DF305D412A71FC77801FAEA989C03A0D633C4B06766491F4C0DC67FF8DEB16AFC8BC7E3D41601BF7B964B91A8638DDB7CC08B68691D5D501B5D3D72915442F0D1B9EA4DE4AC96C6E10238113B17AE11147C1BF46D1D0E16BF333B1A12BA3D2C34F69CE34186FADFEEB02418D227AB09DD8F5B50664B97BC1ECB70C28C79FDC3B16FCE85D63D1A59107BB62594C2FD67438D6448FDC8005FB3BD2BE1E7CBBB35FC5F1E6B1284641E1B520AFC98F158BFEE2D20A6B03541AB11A19B0D02D9F628C4A00C25A03457C2A17D3B1E11A8AAFB4BC26ECFB423BEAE0F68EE89AB2C7FEDEA2FCAC00A3928351163E04D8BA817C168A0CE68CAA6FA744E7E30A2670B2BB88F27810C887E48E90EFAD40F9735B5767F60EC515C146D56EA534C970E04BDD10302D85A2317C478BD195FC93499C051F5AF61A6C5CECB89A1D67BF5BE2CA7EFBDCC20B884597EB2BB0799DB9B86E2EB8FD93389AB91A391F2D68A057FDE361AC97A87F4406F40A7EE2E7709E46DCD756617DCB0DBBF43E6BD4851F3D834BB53CB150D2FB7B84F8D037672EA110B3F93C3AC7EDCC5B5211DCC6BF4685C2D711AF156B82961C5369170E2E76ACF126B3036492BA13A920E126E7CA29791835CFCE00B3EF7AE43ABA16123C386FC3AA80F7F55F094F1664D67FCB5B990A1B93AC8D9FD02595A6005B8CE100F00F9818D7C2313416A65FC916B102A019EB2C7DE91A346F6E3CBF7CD85D2E8FEBC968AE7CF4E6A64400C45C7F71CC17BDFCD337C726028AD4F1956D8AF94345E2FF8F1C9E57AEA206DEEC8A93010DE204CF6F3D9CDE952FB8E4955EE2708B8B19C5788865CACE48EAEAB016AEFCF9FCE16621401B9B14F01BAD76AB32105CFD3C5A3EC7E7CEDD9A64C0B2AF82072F95D2762333ADC34CCAD8B93DE773FDED0AF8569A4ED1032A10D522056894A78C45B0C1FADC66A29CBBA8AF0600B416497EA782E66C42A4B1B518B7DA3DFA17E2EC7BF70208F1911CADADF3173E26A9285466819AFA7E43CDA3E79C3379ADB9F88A8C460AECDEBCFED326E15F01E303A0BB62615B2A2CB097B045DEF6AB46F799A70EA5F4C54B215A0BA6BC2BDFE5846A65D620BCEBD2607DBFC74BCEFC9712B8AAE5BC6C179B2971829F9EA1EF896FE1F6EED7D4A3B6D04A0B96848599BBD3A5A4AE6431AF6921A26726EA8B5651B74CD5C5723D8610CCC9E9220532D22E4BEB538A7E7EA50B7FE7D21E4F7EDA1A6E232C8DA603BD8A40DD5A9E87778D5EE4E2711C229E5F66F7C19CC263A38A184B437846BA2945CFCED1C270FFCB2C9C03D8EBE37F9E2199FD4084E94A02F74C3C2E3D577470B3F3F4B0B7CDA7671722B1E900A49096AF21F74E327D4B9204FC3D7E3AD6DE2A5037A2FED9BDB1100870156824C3E2B736F55E200F84EF5C0B6D39FF0A929F20749413DB40418EA6A764BBAEA67EF31C107F7F23A1193BCD26297EA37CA92CF90973BCC7BC548C62EF44BD5FBAE7CA281C5447895061540CEC586CBAB07CC6835253C332BE03CD64CAF6CFBA2C5768AAEE682614AEDAE4CA6BF839963D13970AB2D37BBD203FC8F5197A62C183B76BCBA09E5E47D686ED98A652A176A90284D0034391003C5BF6E9C6A091108A3107E128BF3465BBB72CD50C374A343C714E7AE5599915411D31CCEDC7ACA1734B5F23783839CD46D0786814D52037477FFD7600129FE5AD39C8601C30088977D58C83B2D0B5B6AC14579F5C52BE795726F126ADBD2742BE107CEF59ACC94B78DC7A51AB01B4A3B212F10768D35C3CA5CE6D4EFC33995ACD07AFDA29782EB4D86447F622B2592F7D18E835D5F922FC7FCFCA5F12251B5A3DFAD7ED2B6C9F3C6B734F34991C30C700EE325CD9752D68D4DB9B5DD98F91348C1DFF570DD106D0CB457C4108580FB341BD44DA99F4AD058B064AE955B584627DCA083785EBC199607782B5B096DDCF3A0EC0C5F4FB69DD11814016F8AFC30F853DCF0B793E150C3B796CDE2B1B43B3E346E257331504D6571E35C7E2953D0B1EDBC4B1C48F21012DBDC773107FF4B459FCD253425217787310AE7D8F74F77E60A4511B8B23A6A1714BDDCEA8694F2A8508991C555D6C1DE281244E229377BB4FDB9CBB38AE483A3569F735AC438C492DFE9414F26D70F154CE91D99105D5E34340D34764482934F3F3145436CD3AA2DDCCEBA06D0439C960E7D16BB68113560CABB3611F2CBC43D79915CFF16CF0BB72EDFD858830AF8C790F7F1C18409C4C48601F24454BC986B12540B74EBE53F5F3AAED84C8DD523702B0492BC34B98F2AF02C856882F37D1234C04B42060DFDA8FE106CF570235BF1169F163501B400DB5A48D7FF08851543CA92A0E8448F98BE619F41F4C820CD5553B0132BDA47AE8C0A85874D1FF5D23AE2158B85206E9F95CBD6DE6F2092A31D700E8E86ED0009F9780B1D349E01944FD5FC58A95CCC7502C6B1385AB36D24C663C8316F2F453E88A98EA61D721FBD4B018F43B84DD5B5C83316488AF78ABBD005C15399B7F94F6AB6F5239B10CF44B82FA774ECCBB5CB932A51B1C5202F112198FF20A160DA0DD130510C4540AF4C9ECB078C38AFE183911E2116F130DAA83432E3B05F76DAFA8C9285CB7237B57407F2C4999D4ACBAA916D2887D2ABD50590B5F761D3995A3D484A632696156ED00346555A19AD569E80F2DC6FEF929F3AB753AC9F451D991D1F9C614CB562F9AD1B984E94BF00204B8E0411D9AD0D374A9752B6989CB7AD969B047E60F5D371FE4FC3D17B4DDE42878C758FF19EE3FA205FFA1E5A3ED709AF71DF3527F26F712462C0AB5815A447EF29BD1887D7CB8FF44C2752A9E1BC890A80A5444E8384BED9EFCD06F26C467FAFBB01B97EA07CE0B5091605780D9770A00252C92C4DEDD4D8B942E14C90DFC5BD612D85CE24C5CEFDB3EA964FFF256B20A4DC2C0EFD50DA4BAB56BC846B09DE27F341EE42EAF0545CD82BF62FC699298C98D9B9947D436D234DF8333E144C207D0DE124707A1A3262CBDF544C5C6FE70F2137EDF11BC8A3E2E7B6C35909DAC8C160CCBF3FF25275B7F97E5E0D56349A1AB617E944BBADEFDBBA8BD06B26468C961756F0E1506F5D2C5C332CB7D18155B3964343C682A5721C97BD5F6D675D44FBB9B5C9AE58A02BB327AD51C927CED9F3E27C8DCFA2EA7F4F20867DE29279B5DA09E70B6B6ED9C2C21502D185DAAE79A792F5D79C8814375643B4E69440EB7AED63285EE40ADB2A43111BB8E45D109B955B309FBDA17862D551F72C2EB06BABCFE4BCF46468789347AEA8FD0CF3E2938521DADC71D0EEE1F435B38023B69022FDF00B3D1AA0A456DCB917056F934240BD6C899E8E0D36E4F1C8135F74FFB493B7591BF9C2DD47E2C2B64A5CB0D34A0DDF8486DC9CDCF85E8D5FB8327A486076AC1AFB63681A253CC57B65DB36619DBDA966569822860B30D9DD55BE869766BB1986D254A1C486E6990EB6CC4D22E829230CC0B5CD80B6E0C3E4465CBF7AC3480BF67E671B31E38F24800A61B0C98589FC4D98BC896C27D4A9F8EAD8CA7D567AF1796A82C64F3A9876B921B4F9F009EC821DAC29B54AF75F0F5F59BA04AE753A786D0FDA22144E3C9C3413B4497ABA623AFE3257572D979FD7234C04292B8EC507187752446AD11D10DE925035D368AF83D202AF6979123C7F3B7FCB8D83812728A890B5C09B482529FFC0737FB59C35B552AD7C5820E27332D2E44F2A31ED972E2E5C834FCC652204BB401557D6FEC656BD9F63B9226056E2D025988ED1312A2A767D418F1342BE489B463AA4BE823D471648D9893364758DACBAA63BED8B3D8D4DE1E4A768B07A9912E72515AC62BACB31DC0EBECCAA1360330949EAD48841D91C61B13E2EA79C1891C9290FEE2F779EA4EC57692960A91913AE591D6550BC59CFCC5EA68483E4066EBBF11C2D9647E7B5ECE7845996AAF856A1BC1458EA7C88E73B1C19FCE34B68DC2BB0EB2CEFD4506D674C92A2BE87429BC026542F6F8F48CB088F945D76C07477009F8F9D2B41552CD688E00D2A977C67003989D0A2FA7688B410C6C30A1036FC1AE46A86DA837812C7FD4539985A05346319FD809739255705BB1BBE7791F520D43F33F06493E50423C6418BF781834310AD40B92E396722B1C67EC08FB5FA918351C89574D5A47D31D7F6D25A30712BF53AE5410B587B9CDC0D652F993ABCADD6442E5F52229C5011D36980BB01D0053433DC64E02F535EB87F04F2FDFAD3A4378477E4A0BE652FC73E3604285CC0721796206461EC07608C4A8C0C913924525EC5DCF185891F1740E56E4E88E3C957D028D5BEBC5DC6AA9CFD3B6A94CA9B281DEB7FD816C7DD27AE5FECACB499A764C58CEF0EA4A18999B80D89D2074754894613FF9A019639CB6E1A31B91F6389894454B884F1F76BF3A20984E908C60BF36D3CCF439D9B200C3C97E076A75B5209C363FB23DF3FE4A8A792CC9FD93527667603AE461FCE62593DD7DAF62D1D78060E4AB4DC2424BCA29A0C96ED4978987C8D4F2791F61AFFD6300415F0E4DE0764AA88C672EBB55D765FD9382875CF67B176C8BC422F613D22605BFC24C2D69DA0E7CB76AF9378DD04C21E76BD30E9F923D724F6F3633928EAE801001F869B7BCCF9EF79B6FF8E8A741EFF812B31E140A7C798D8738D272068FE9A5468EA0CF60D339DD3D56A73D3BADF14504FF3FC2816A0BB816806B5CEE3164998712B9460C4227117261169E1B4C20AD79049980017BB1CACAE8EDFE29252C782485A5BAF0599796BB5004FBB2101CF98470B60E8140B828E7DDF8D3B561AA5A147739DC01970DEBFF008D85ACED07EA28D10E594E60A3569C6A13D9619FC2F76D279143D829383549772E09F3E275840913B08E0FD33C24CD38760D585FBAD94FF3B0355D247B1A5D8F22E67E34803F1D454D979BD9576F36F816005BE186FB6D58BDC8FA63935D7E4CB00A0F6752E1121241A67095E77A3231034C7D14649276638DFB1DBAF56AE7BBF54C64B817E10B6EB7E974208B16C658FBF3480BA6C86F5BDCFFD2F830801C95F5D9677EA593BA221A9E7D2F09E1E19FF70AA4A73E2FCB455583F3E21618A50CAA4B53EAF90F0AD1A47BB59B77EA66DE84A10E6D5FCB7A9CA221BA0DC44452E7074206ADE1C1B02E520B6D481C27D4CD833EE7D985B20FA5BF7A21E4DFCAD092628EC0A6E2DC8718EDA1408151C9F4C1FF4046A444CD0F8F10C82BF697013DA572E3EC04726E89BC96ED083C2387EF5DC80AC9D74144D0AD906BDCD4608974D57F515101973291804C5180C348EFD6C91AAF5433A6BFACACD657BB7C579A195C6EFEDBEF3E6746FAACF6AED5975115AF77843A5497EBBF4F254D13D82321B29A6EE275AD3389B828D1FA19FFFFE79123A579B45B78D3F0A5AF0EF44A19F07513426CBFFA519F93A4A4DB52628A2FD56DD3A323382E5DB171811EA861E2D46537D0A4E545C65F2310C2A4EFFE0851C1260C26F2ECB491BD2EFCC41F06EABF26B48E9E61FC3C550F6CCAB762B0FAB75DFF6353F814E55E98A3AAD5C82CF9A891AAAC5112D38C6687E30610AC3379222517D90CDF1AB77E96B16E4EBCA8B0E8719205FF3D308550E3BA58A9CCE5FC6BF05A4DBECFECEBF1F4B7722C6AAC9FBEC2EED1C90466147C022C4B2150D6DE9B76BE278F43197479C5D0CCBBF0CBEB22C31308982105A95A5841AA37DA3BF81F8F7602C9E68C059A36BD0DD395EBDE7616091E3753AA1397A0251EC887FB27A166DCA318DA3EDFF3E29320AFABB616813DC83D4641F3664407C3DABDACA9F5EC3FF32B6538624C2F10415019168777C2BF58D51E619C872F1FBCDC8363C69AF421E6B6C046B8EACB1233A634F492189D114FC3B17B3A6FAC0CB04BE2FB6CED8D3DBF570B66D7EA390C11D2FFE35A8F675CCA65026CD83809D8C60480A25536A9DFBAE0D1229F2D563FBA86229F6B7F7CE9A9C12E6CF024402A8DF251BD5F72EC415621FCE91148DB266EE1BDA0885827E96E8A9AD9C50F43D9B6462E6A24D508013457E7D4E3D7030DEE74216B3EB93C676CDB9F5E6754A10A635950D60C9916D00565C50A33EA1BBFEBF02BB60483B6DEDF0481C054710FDEA23BE9FAF9DBFF407E7766C84CCC3F281C6383079DC3188FBE8F9675D0A26831FE4090EE8C8E87DC459B1CE8480E64B78A5F15EB30FF165CC9F5F261B42E5EBF469A2319A405E8CBADD241C475A5AC949BF372A41B060353FA3EB8C79B969874223CC14B6E5B3EEFE72C0CB8C8E1B114AB6B7A435B786D8A8FCC935C8BAA5BAC879B50D8180B65FD0DE78CA05D750591F479FB953FD55BB00F1D50EB99AFE348B00A63DE9E79B12C5C32F257C97CA0CF00153C8C3D8AF3988200052059CF3C841296651EC607D910D661EAA1078FA7EEB6738A8484224A29CD0463649275D117997768C75660D469691278A111D50A72CEE9600124E3850507C0B963E9121C8BE1B269448FE8A4DF87DC1EED33FA1EAB13DCADDFD7F2BB0FFB042FDC6EA8C00A6379B640CA2855112F86F6FA5B2A622079AEA2EFB9D9063AC89D7F94AE3CD7551F3FF99B5A3C41D3770C44E9555969B97D719A3C5590B3D8A1F65995AB57BE3FA7D55524CCFFF8018EE1A587AAB9FB5D3E33FE7BAF2642CF9421540C134F9BDE97680458FFE5A18DD2D3CBF178E91629F050DBA86E31E5A42548E1582E271B399A6DC512CA068153BE53E78A5A6F83C8C39FA6F92626B000E8066A1BEAF2C21975B2FC29959C3AA239CDD2A4B47A55E0EC54495769A9293F33F23FE19A886DE5AAB35F3BC80C9CDD0FAD599DB6359B84F396E9DD06848EC5844B44AE00478C8C1FD5E964031EE21158F6FA1784A07A09E6173412180C5A0354B11480F780C1E3CC436BCF5D3FC2B5E094C1A45AE192369966B103D700B955D0FDC49733525BE13D82164C5A2996F0FF900DC890ADDE848305ED6D225460FB75CDC1453C513EDAB63E576CE7CDFA755055AC07036627843E640E20767EC35B45C69A28151210BC3F93EBB880C6419D545316029814C22D2872E8B0B4B4ADED8E44D0035CF687BAF0C593C2B947CEC9770E19E28B62537B3C463F582084CDAD9A704D8E4CCE851DD4FF586D6CC300F09F878FF5FDD7E7BFD0AC3AA2AEC0C223DE23D190C6F67AFF7C00001F7DE39C907235BF8D5EC16A34AD2D2E6DDC419F5B24EACE1A17BEF5CC52AAA05F04D5AA8BB018210354282E98DABB918100165E7D962A6F396F22753B1FB928AE3576A91CE62216E9E6214ABFF91FCA2E6E77611AD13F70CC87E67A1E6D886120CD2C2404E0312A57635D1C2524C97EC0BDD9DE011D158F8FCA7AD1A23B38A0E6201B3A52E5BD893BEF169D6E665829DCC297E9BF3DDE2974EF56B848D62499354AC81D756C3CEA6F0E5EED1E0E58EA69F3843B09E11F3BBF8898F1724E4BE566D1AC9AB166CA7D5CDC3BAC80652CC469E048BEDFF5444254926930835827E5FAF2CB16AF0E0CB13A3653AE4EE9C49D838F84D3464EC035DC31E025F30A12EA7630A6A630A351E06620774E7CD342027BB9AABFE167CBBA7D526F0767 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-2_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-2_256.rsp new file mode 100644 index 0000000000..8693856dba --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-2_256.rsp @@ -0,0 +1,12 @@ +pk = 00000011CC3CD3FEFBB5188AE538CEAFC0E64816F394C351FE22AA134A3EC20A6A25FB5004562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 00000011000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94ACC3CD3FEFBB5188AE538CEAFC0E64816F394C351FE22AA134A3EC20A6A25FB5004562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D933090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000018F224E19E61C8A7076585BF7780AD32D73D04D66A52F0B4CB6D35D9496906BFB05000000000001C0F7248E24BEA5635FD0F3F3411F1A20316CD29E2BDE6DCCBDEF8AFD463CADB306000000000001BFE2E0B4F4BD9B2B955C3CE73D4D0E703C44BE5168224D99756D865D86689E1607000000000001EB5D1F16948BBDEB3335E0F93C3DAC5C3FF7DCB33B16BB28D3826194192729F80800000000000194BC268989E8C957203F60EFD29089692A7FA0980912BCCB1FF3D6921B9805610900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 4963 +sm = 0000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6429AAFF05B285E06B6EDBBA11503F92E15E17C582FDE9CCF8FB0E5BDB90FCABD06FA41D595338274EF14442E5C967BA01C008D19237429ED719B99E0BA91D580C514F5DB69A428FCE3592C4928A1461E736B86804529D3AB6535C3DEB873B45873A5037153C910492CB49EACC2B24931700DDB0962B1AE245FEFB4345D58F90F62CA12C27CA2E25F5C1799AFC3C56C20D8763361A7AA8757AE5C1A90FA05D6625430682E22AC918051D97466B12D2FC559413DEFAAFC677C8351565ACC58D481ECE4C96410219AA2370A23C6E92E5322E0CD81840622A3C20D7243711074E19131246F16CC261A56C9F1903B0B4498B849B4598E5F8C73A6A1521F7D75628427099DB406303D3634EBA7F9EF84D42F8B59753B8C55B71DBC82E06F6D674B979C1F2E6BEAA7180B7DD54525F52523DE6F98A205A6866C5B7489000B5CE17FF49A645C1A7763F5BA271F9023A89DBFF7189CDFDDA48F112B14E7907795A7C92AA678727144332A7276950BC3A0548E270CBD4FC31004AF248BEA3BF61558946A2D26131D7D51C3221D6C24A9EA4C05827290AA1A66C9011153C120FC8F974620A2988266C9B2D49652CB8CDEC30866F81F41B8F6EB6C6F5DDAE07C5E405A42EC21383BEFDB77CEF1664E01F11EBA2513A4C3EC82362321C163730079A59933D9CB173C93ADEC1E111F387845B826C3523FC184B5F1D1D830191C88D1F9F3C3A81309BA06825E1A32451CA92D7B58785E22C755B2083EEEEBEB7071E62A3AC45C09151E1961C11F7D8CCCE4F08E9BADDA88E17BF2DB02A6D1E1D2827021DB4659211453388E6A2E01080743D9A836F20FC93663C7E4591849A616ACE98011E52BFDDA1D6A0C82EF62F0B0A9F1FBC427D200F636E66DE934401583B67DB03BB8492A8952B7DC0473151EC0D9571297FA6AB0793D3EBB4AD559E0E367DE90BD20B96ED7AD6F608976654F01E1DF2A5B7B7A54D448714D6E1BE40CC6C76564A8CFB5ED8D0859AC3B6541B286B5794C4B2AE7B4BB4C91ECF560E085C6626C9388E031F5CE2B09BCACBD1E67B946FA5CB736B2A641A0C5E8D152EBD752F4CA60C49827FD6EDAF3A6A71C48FA89786E1A76FE326B90AF058B1627040851A517242451CFC3194FD5C959E05BCA2B9B93B4A8EC90C078AD381B57075B5B4C83F0C17A67F8DF5901B4968C46EAA98D824B6A9FB2CA5E583E3AF6718C42B47420838BDFA070DD8350D320C2439D92BA252BC89405731261FFC9F2B5EF3AAC944770321193DA5EB16924C3108FDEDF07D7940CA3C8E46A5E76F5A358E7927976D16BF55B9E54965F8CC13A89E775AB6123C3A1D8301FBA857F30B65D1961FCCDF1C0A1E5410920E84B4C8BFE12E3B1B84721F6CFDB26FD8D39AB82756BC29725DE0B632F556C167705588C5D03A64E33DB87F0432B67C1AB69143592EAB3A832AD7375AE3397DDE149ED361E30C807C308875164B475E46CC14E278D7C129F0D909E2C06D5CDA851D6534AE73B220CA73A13917887367D055D38A65273890D1FB7A3AD50A7BEC306BEC9F246D6025499B69389AADF76741B4665031E74E1C836028D815ECFFEC3E974476860D49A2BA734DC223B46D2C25797CC55E16A37D56B5021A9413F7F651B894ED06E313F1B4BBA00F7D5DF43AB472D66CFE6CE3B96B4F37F3D7535603510353CFCE64882BE681C9C8046A403EC89BF47A3A4561226B84815C3661606210EC8AD191BF0B1D8C6D027A7C176BCE1CA7CBBA0C336D80411D9A61A5E4D093F5C27F1B5233F2C78E908DC396F097744D841C8BF1BD732255BC62E601A9E50DA36D18AFC8DAB6866EA201DB358B45AA0CDCA0959B4F0BF7ADDCDB0CF61ECC7FB075EFB21E937AD32E4FF503475CE0374E064460B5A0B4F955395D59C474CD9BD3250C92F063C641BE91C5D3820B9D2C39466B24BAFBF05001BBC0BC63E00D7EAB41CDBCDFFF1216F45CE0741C53B57059C2F55F8D2529C6B0E760FA3BB04A38130B3326F0BC0E59869282E6E6870A1435DE8D83D9174F2314B6D007A6FCF177661AAB80D756D36813FA06D86075306817D37856F1F60BC2DD52342AAAA26CA611EAB00BBEC675FF7EBC347B2B3078CFC8E827E04A3AAA3E5A2F06DE077D32C6D51A6AFBD1EF6E49CE8FD350DE872090DE73F0C124AE014920F104EC5BC7EA0FC49DBFDB3EB4E0FFC5AE893D46E0A98343B1C7D25EC74B9EF16BF54D211C3928852873CD0EA39D3A2527B72BF325B02D5A8AD1B50320FD2513D89D1A164F5F8E770B329BEDA67EC4F75441467D2D45A3F4BCD6051BC851CBFCCF7F1644C8462127BB68067FFC32F23B443864EC5104D7AD3A1B68FC59FF2C9775D4A9C1D0F25F084AB49FC4849D497AAEC8FA2A8C8DB244001F4348AE47425932E61A64C79846C4DD33F99680081AC5F25B0B3FD815ADC0DCF5AB104931F58860E77B4C620A8E18A68B3F068CA77CA14D60E815745802DBAA1E6650A2D337A8B8FC33217467F61AB87909D9D5B21508BBD0D5D3876F754FE9285CA3208CA501606F0EB6B7FA6720D9809A6799A6E7B2DDB84AC602BF3CF936E171E16F5B4EE3BB6F1F8D70A121E129ABDA16B2871303DA6FCEBED15C3340C072584C7F306AE44D7037C8EE5ED6935D675F308939045FB0522E5560262A425BA5D23AB0A7E3A26DD7930E88CC025293E48E8B72BFCD134B8C3613753A9AEA514B79BEB1828D08E928B94EFC93952D401D4FC5E97CD40B375D0F6302502B3BB83098A6BFA378373FB0042E15783729329225E1BCB7F680B66729BEAAB9C5AC5A2120C8D427E349F364F595BC1D72866A1A60777897D0636344B4A3A6D4B891BC5E066A422AD6CB0514D1E9D708885573A7CB1C938876CA58C9DEE64B7EDCB6BACA85C9E20AFAD6B68054B862DDFCEB991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA1E51FDD737CB5103920F8B27DDFC3FBF47480793A68EBB780A1BAC9141D609EE1B40AFF393D6177502756D15DB5232BCD58ABDB633EFEA7390FF8BEA443BFB32F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD5894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-4_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-4_256.rsp new file mode 100644 index 0000000000..07fb5d5c3f --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_20-4_256.rsp @@ -0,0 +1,12 @@ +pk = 0000001253040139BB0C869F0B49F12B2ACB6B6E78731BF48B976D5668CF38EA836868E404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 00000012000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A53040139BB0C869F0B49F12B2ACB6B6E78731BF48B976D5668CF38EA836868E404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA24010400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE5900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011420B60C54314ED8291B4F251FF32674EE6A3C3609140380F6B20865B7AE643401000000000001DA6EC89DAF2B01E86C06ABE8043C9A6EA0562A18C49B4A9497D347FAF8EB910002000000000001A0A42481338E08706BAC35F7B5F5D93432D40144F47A0F6790DF4B68525ED740030000000000014A9507DA8B4941DFD3D5E9A02EA050B97F9887A65D93FD8723FDC30C7E2AA4E0040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB332A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFE + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9251 +sm = 0000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6FE5428C1B38A2155B8EF1FB9DE8440D993A1F197229DF83843A1615CACF924D4F7C034A07E8D99E7F548B998DBE686E6F146747163419D911CDF36891B5CE67FCE30A4EE54EC1D1BDA34E8F5BE6FC86445C4E732ED6A2F3717BCFDBF1EC5952AC6DFFEB95D5F828ACA606136DCA17F08C38DE5AEBF9CAC54646BF3B7809882E94D6C58C88F8FD5C2C018CB53B7BBDA343D9B0F76F9057BA0C56DE12931A55620810B03806BA5E0F9C9F764CF3EFC1772C1624A7C8D63A6295339488C2FDD9CBC4069AC1646996731948816530C43C82CC1346A5614222B29B4C635AAA4542F11023B3A0B4EE1A22D367CD4E000A7067C2C7DD162FA09E777CA9DFD3B331ED20810EEBCCE92C9FE28855527751A9567241135557CD840556FD141538AD228677F0EEBBE54BB463D23A3C7E6E71E1CC6DF3104CCEFC7124BE31C854ABF06071BBAFC55C8986FBEA375F95A3E2EEA5595322FC1079823D49731A6713DD270B3AD1DBBA724670050F31569813630709AB6A4E35D66684AB154CF647FD64DA3B2E5533BA26B80AF62D1328351A6E0045A82BFCEB153B0F6B8FD5AE3B2056006C5EAA15E87B7916E5FDE15BB2E41FF1A75C926AC7E64C93FE1451CD75F3AEDD49B1132383BEFDB77CEF1664E01F11EBA2513A4C3EC82362321C163730079A59933D9CB63937ABDAFC11529A49EA5BC69A0EE1C86D3E5FA6367170D2D5D45A4BF164D4DE3B8F7196A03D3E74AB3BDE2DE84D00D112D489E6133A0FCAE2ACC8DC59062CB45E8ACEEF3FACEC55B716E1D4FA8B926D7A96200B00AABB668752FDB0A7ADBC136279390A03AAA2D41CE2F40EA4005F1EA2A87D61354A932E70E8677BC0D6E67DA1D6A0C82EF62F0B0A9F1FBC427D200F636E66DE934401583B67DB03BB8492A8952B7DC0473151EC0D9571297FA6AB0793D3EBB4AD559E0E367DE90BD20B96E53891BCA1195D4B5CD305ACB28479FB1BE4550E16F85D9285EF98B1F325D755FB51E1749ABCEB67C4DBF13794C49CBA8259AECF2C8843C57521BA6AEE603516ACFF629B995D28350AB8417C87F07E31C622EDD406BAAFE489FB5443F93C9583EB8C510AE49205FB361487B47B63F0EE9CBBC9BF3983A75A1080CBC7FDCC58AD8490221F8F42CBE5DD49461942A233D7D9A4F4F121C14C1A48F90F4F39D6A32E8ED8C312FF9C43E4C1198E0B3EC0044EF37FF9A9EDAA4F4CCECD98E910022A8793A61C5997051349524161204FDCA085DB451FB0C3E67FCADE5E78EC0A356B2BDCA48B903DA92B5D86FA1C5E8DA5C12CD2C030F11A8F670E028AC1E3925B5D70EA2F7D8C162BA7F7F4601025685E59E261826B1D9E9A9AC5B4AA1DD947CDAE896AADECCE2E41880CD5D368ECA94F5AB91D24AE62880ED25ACBEE0AB61E9DE6E3CC31FCAB40497A4F5FE4F15BBFB53599D08806AC825A4E67B5B6352F1DD87241B5728E4A8CA6264070A7F1F09CD093CAD71FE3263B0E60C73F5F8641AFAF0767642B074B80978D810360C6461ED3EDF9472658F910B055DE3DA84C0F9D864887B06BEC9F246D6025499B69389AADF76741B4665031E74E1C836028D815ECFFEC31E016610038E514FD8C40543D51044F15914C46629E4AAFBB375263475D8CDFBBC16608AE86EF265A6F96C3DD8ED50EE43654691CEDD9D56D1953EE8E79FAB98B00C125CB7AB7263C045BC9C084DBE1082F5BF4185FCA92A8A86B02824FFB27908B08D008E6847395C57EC721BCA98DC0B83462956092D8420C6D8FE788AE977EBE07F8E35BF47CF0139F21D472E866AC90A0F9934D889720BDBB0B6758FE460E433065DA58947840B243B5C1D7DBB77B3F5647E6B1E5E431D7377E97A5BCF0F075EFB21E937AD32E4FF503475CE0374E064460B5A0B4F955395D59C474CD9BDC172757C4E8C43F87A05741B0454DA49A357EBDDBDE8BD4D5EEF757E273F78CA03D759940F88FAF5EB05BE1B90273FA0BC0048267B43376CDD718399A354E3B39AD1AAC43D9C2B70E451C8735865EAE9FE002A29CCF21E110FDC8143F7F6F6F561AAB80D756D36813FA06D86075306817D37856F1F60BC2DD52342AAAA26CA613E00A9115D57C1E17A0EE160B6594FA15A508BCCC75D4AB1A92550FC7D3EA97C95CA005C1A19AABB3CBDBA66D69363BC654DD41E108155EE7876EE35D0131231DC0C5363795788CEFC6210B502DB88C434099C46316476FB3FB07E701E29075AA3BEEE3253FB58D7B532C7885549593BF2984B3D6FCC2E70105FC34A1CD9A85B9B2A48FA806BB1FE35675ECD1BA10FD998068C0797A6874B02F3759F9DCD3B7702F687B52B7C266357544355534B01A42AD2C4D72F8BD9BDDBF19E907B4AAB42AFB9C50EA8B1C2D24086613B04E95C864564B0F144ADA774B34B26CD69629D0D2BCE8E0D611E1C6993589B529400771332F16F123352198A4D6872CF63F4401A69480FCD587D115B1D7951C75225493628CB4963EEF967CF17C509540AD2B76528A6512C270D08F57DE18F0604DF6A7F0FC6EA83D446EB3C281357147AFE5FB70D9809A6799A6E7B2DDB84AC602BF3CF936E171E16F5B4EE3BB6F1F8D70A121E2073DDE647EAB354AA4B41CA00B804C86C1F0E43E5B0121F340AD5B2AEE00092D931A5E3273F4F5BEC1CAB03D56A297B5EB5AF99C83F60C70873CB17A1ABB1668103E96C8FD9B5A2AA8B31BD9AC07C2EBFF610B224102C28626D812CA223F77817F11254DBE77FA55F77CE54550ACC8F6C4F725C5DB72F56BC4BB1AD86DBCF26C1D2120A35AA49657324A01423524C5A5311FD6D80ECA89B78221AF91A751637FD590293CDCAAD1BFB5BBD6473F1D3D600B9A921145B691088A88BCA7D1038BA83A7FCA224EC74713DA1B07688D053980AEF766325769F8AB513B03F813F5530B991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EAD16E1125A10C75C47056683C86956E741DA2772431C6436CF7B385DCE6509239E2CB3E61134E6B4CF5811150F4276945BA08D0779468902DB915F36620A54536F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D265894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB96557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB3357F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B82A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFED92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE59 +remain = 1048574 +max = 1048575 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-2_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-2_256.rsp new file mode 100644 index 0000000000..5fba789ede --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-2_256.rsp @@ -0,0 +1,12 @@ +pk = 000000139671F9E99FB4EC6B22DCD31B932FA6A76204CF58477B1B054F10C47913D088D804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000130000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A9671F9E99FB4EC6B22DCD31B932FA6A76204CF58477B1B054F10C47913D088D804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D9330900000000000121C29A3D4E6C5DAA979424FCA26B0EBE6D3FEA8F078FA9A98B0F55503C2541CE0A0000000000015EB6FB8267689B81BC8E2C8950E5F59F4B43194AB167C4A60EC9BCDA7572E5980B000000000001F02838F27F104405AA4D9E111D3A0B1849F6725926BA5B3A6412DEF900E7259A0C000000000001BA1EE79A04487C5639BA096A60E3E17F7A0E9C0238FA049EA7AFF52FAF5890980D000000000001B63504B794C356EB44A98DE32960830E6B275526432F232A7729ADA72571E8D90E0000000000014DA82230B909123D34E30FE0722BDD93EB6D56243518275547CBA7C473744E6F0F0000000000017AD15652FFFF1B8B9E752AD4A07EA737B8D79DE25D7F194E19ACF003E62C48F610000000000001D6819E585CEA52B14299092F01E66E9A6E7AFC9613A69B89ADE061890A230145110000000000017FB1A159FFBC19461AD72D4E385722A08E9A942BDBC3CF8352CAECD938737D89120000000000017B2C7FC20B3305327D2F0FC3C4854B0053D00E56EE4E005E43CBE807A619BEA8130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A86CB037675575D46C48D89A7B644810666979BFDDE595E1A2362B9961A71D9F75A4A72ABF56BBE2C07844E774123A5DEED0116677B286BB3F8BCAF92D501A5FF375487D2694B089FAF47D8632DA9E213A9C914689D9FD8B0DA5320F6A89787E198248FA523B9B2E910FE55F6127ABFE1FF1EDFBAFF132A06AB9FF0F2E368AEFC6AFAAE9F61068AEEFCAF427D37CD93FC0B0D226CDCF6A7C1F007BE2E59568970AB644D475E62D7B8E7E5F7BBCEA4D007BDDAAFCF6B84E09BCBC5553F516E2E5DFFFEB66C9F5EF34559251705C736FF66A96AD2CA2C40A368602DF65045808D87B7E24CE23C67906BF64C90CF0E0F8621537D08A09290E431737F9C493DBADF98C9E250E094C6F0F7E850F5EF65E71967F69159ADD14974C1AF501C74F01D1C36AEBE604A32DC02B676BBD7CE4BC3967FA8899F3B1F654E7F3E425ADB5ACF59B6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000018F224E19E61C8A7076585BF7780AD32D73D04D66A52F0B4CB6D35D9496906BFB05000000000001C0F7248E24BEA5635FD0F3F3411F1A20316CD29E2BDE6DCCBDEF8AFD463CADB306000000000001BFE2E0B4F4BD9B2B955C3CE73D4D0E703C44BE5168224D99756D865D86689E1607000000000001EB5D1F16948BBDEB3335E0F93C3DAC5C3FF7DCB33B16BB28D3826194192729F80800000000000194BC268989E8C957203F60EFD29089692A7FA0980912BCCB1FF3D6921B9805610900000000000182B44F3F72EC96002984E059C46042E3085A35BBBA6A0CA79700D29DB34DF2FA0A000000000001174A1DED5F222EB3573B2A6CC27870F2FAB30A64FFB9601B5B8167314CD3C4AC0B000000000001CEC1E018C94D354F99802059603298AAB121FB0D1CE89A6C90B945D90A6233560C00000000000184D0355AC86A5E83CCA4300AD4EF13DCF7D6185ADD1B29F22FF24B446B6A184C0D000000000001EF0BF8DB8426844A322EACD3C79500078561868864057744206E70294F1B4FBF0E000000000001EA649E4FFD3B7A864E5C9177F8B14D91BE4CFDB050B6EBC86571996AFC1AF62C0F000000000001F80F14346EB4A8387798C08955A0CAF061B367B1F969D28F833140663D9A4B24100000000000010990AE38170C318A1CB81B1C8C6D980077F153C1C0403EC9645459C3C222225011000000000001DDF5AD2829966C243C523B4B91800973741F27929353122DFD2F0F9DE717F31D12000000000001254C2BE70DF73E405F76FFAA6BF442F41018C0C2D3823AC64CC175A601ECE527130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000665137D5D47667E1CA8F1B70A9029441013DB1E00D4FB39DE01E275ADE1AF6E6483B18C34D78AD814C71F370A0AF1E681C1041FFFACF9685BABB03923BDB41701F927F3316ED4DA8420A373F5471BE4A7215CFE5683EF16855C748D8FBD21DD9A6C36EBDA9BC5497F5C0C93DDBD40A717DCE151B87E8D5CCEFE5E8A0A66B3F92739B24915DA4B87BC7E555AE0554A8FC1D2514A7979DCC78E92D79C6908005648F90E5E4AB32CBDE27EF1BDE91C49C5184A3CE134D7AD33A1AC03F4A09CC245DAB6033C99636D9F6E9A723429F5EDFE118C045EDA721EB21387225EE2764A00D99625EB4FDDDAE398DBB4D8CD926310601CB34D38B7BA4BF60C66925B2E66B838C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A3692F3176BEC212C8CDDA63B223901AFF8E3CA0612978B7D97E8F2E1C000B0D2FB992BE80BE6906A967BE9949853BED6333CB070A1384B5A26ADF28D3BC5ED2236C6699909AC8EF3CE18997A672EFA2087DC9C0C38BB416613F206E136D3135C4E39F98C7C1F50DBBD69337069248EC64C3E5C6EE0EB7618396BFBC2BA26667426721DC84D3A53129AF465CAB586A54924BD35CA4BB250865AE0EFE67BDF060D8F947141B55502BD264BE2F24B40DA59C45FA59620F207E10FE94013B6A9F94182CFDA5694E19B1ADA22B18F183D7DF0A51AE2876A5D6B79D911B0B8A0D3EA283DDE8F0FC0DA1D77498ADC4DE901F89F11DE2753E8EF674622BF03110CB519AE4F6CD0ADC41A43D1929CBE5047D9B09FE60D9075C85CEAE9C825EA53585D180FB610BBA83BBA2E590AC5257DF858E7F11B8298C848F2F79D78C37F00474AEF9B5E9AEDBA4C81ABA062F24531171F8137F7FCF50FE09A38F60404B03CD1BAA934D6DB5CFCB1DC552BF873C6AA9B5FE76FAE92D4C3674E20DCA7BBF430C865F6E5FB5D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF710D288F760D8E6A64D9E2E53F680C21D30AC1439A4A90469D0C6271AB6EFBB90A4F4DBFF7D5F3875C6507DB321D81C3510D7E7F48B297881DB6FA0AFCE41645FC93A37FF04FCBA7FC19B9089BEABCF9BDF44E2C4614A73FEC80C1234162B41BDF1313F6E13AE2C48A6C4CABEF5EDE59AD461384DEFAF1935E23F5CAB3829A81E2DFFBBCF2FFB141D975EABF78FB4BD484F75E08318C08B2104A468E670786397EEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA360AB78FD9219EA890695CE44CC785A3A4DD39CB8F3C82FA5C6A3167055CF3309EB06EB90826159619E65C5E29D46D35E61C961AEC002F87B44A2B7D5C0E2111D17268FC3B147434264112A2E95AADA6ED860C50359372609ADB174741CC3AAAAD1FB50A42A560BB18D12C228F10D2776DED26752930890259A5C0F64C7D30C49383F92F1EAC6B1E8D6BA05423368AD3A8BD145D397389720E80F6EE11965E467D4D5864E164E51437277F698BEDA846AEB66DA3DEF39CA3288D30C001D3B0BCA113AFE8AD333A08D801A9E4C52DF0DDD4C63D8DF7EA938014336BDCDFA10E960DDDB4B5471263D096A49E3C83A188C46AD4EA8D2AEAAD3B1BA78CF6F116D0818BD2F38DB39D74D340546233ABC52278B381B7DEDC3A3B5DAADC8A4E7519AC9F3572A35C016CC7A8E0FABC029801012DD7454D7475E5D8B492A119AC583F4043D25CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438D81219D292421651600D48C2BD291766ABA14ADDC9186764DD212446D27C3738D2F606A9654BB310288F37CF0ECD5D38590E4D887D9D5C523527007F6501ACBE7CF36803727022D98CB15BCC0A88A509DF3B9A84E99B41843283FF2E10FBDA3C14CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D446D278BBC90D6A56B71D6DA6FCA49F332776F402F58D180482B2EBA5132D8ED67144DA06AAF952EF5B9BEBBF0CC8101E93F3BE05E58EB75D55B3CE72B9C8A07725C61C24C34DEB9A7349E51256EECB7DB61510D8BF55798B060EEDF9F9551AA615F1661F544B0779B2974A54BE8BBA388D6D7FB8E2C0956DCB23F834025CAE4BF26B798CBD5938A517C4C3B8FD3B8FE920558256C391433854481944BE487AFBD226853E385D942014B393488D554FBC143B44F7E9F348FB79920D4AB758CAEC55ED8CD388DCE4B4381D5C3A9FF36ACF9948993CF2B2E03030646852CB4193585AC6C56947193F96292D813FCF3671D46B9DF2D99D43E0AB4F1994B81235A50D5D977FA3560CA3D46CF60945C8D3E1103B6B1D13CCFAE43741BE65EAFFB9DCAB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832D381248D668B0A5ADC623F2529B02CCE42442E86382E03BA3FAF21F86FDE1C633C9A17426EF1F4923824A1E394BBAF5058C00950968357FEA01AFA8303DAA21BAE4617293B3B19A50C88C8F7D8A677A3314640452734E7FE4BA483C8AF87356E6822D943C23705352F458ED80B8375DA6F1F0DD7688CBC6101727F2AE7FE500C98A185F29DC71EE3506F8425B8D7EA94BE228679F42ACED5C9162D6A0E9AF148E5903C0ACC117C2BAAF1EC4A73A0BF73CDC646D1559EB1FA607044B5C7CA60FBDD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C6F2AE696330DD7C816130134AC101764D6B4FAFA1E71A404CEBA3406E1996391AC35A28F18E05DA188AA8FB52712696C986C25F70A31DA73957B238FAE89EE0BE4F77ED34ADFF62BB5C0838F9B645F6851BCA9241ACBCD3038BC40F40F076D1CCD8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CEC2A8424E383ACE82322B3629ADA77D454B677A60A2932B49F844A9389E73FCCB + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 5605 +sm = 00000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6DAC51184D2E4216B689657E98DE08E43946559C194B79D61BCAD87EED916B16CBBCC675AA586D085AAAE1C4C330ECCD5175C5DA952B32829871E231AB5DF21664BA023C2BCC5E6A8E23448E84431B33CBB812A458DD44EC9C2C10E7570B2657F30354434A7E3B1BF99467D1067CFB19264ACF52D2524511F0FB34AB02BF1266B66A0D5672F44DBB9632CE082C47A1191092030F878A87D3007016131038259D301FD9F8C8FC0CF2C5961F669207E6BBEE6F8BAD3B1AE3DF6E88C679BCD425CC1ECE4C96410219AA2370A23C6E92E5322E0CD81840622A3C20D7243711074E1914424E503C694D3360129ECDBE6ADA3F8D0FEF9BD08B3638B1B2076462013954855C6DD4C888FD4C8BDEF806EB73B632B3C27697F2410935EBD0B4EB7D4FE85D9961BA4254B0FBC7E8A37B1D610C74A511E52A8A50F4943217493F7EA4C92CF2591CF5AF0075C2B16BA82F2072C9419430FF672963FA85340B43818E9643DDC3CBBA724670050F31569813630709AB6A4E35D66684AB154CF647FD64DA3B2E5533B01944B68487B3A43C12094B7F4BDCE13FB2C882BE4EDF31F6CEAE8B8C9B0BE50BDFA63BE7C492FCD5E2A1A1334546D3937FB47D9673832B4E4015C43D199CD23FD99DA24210D8F5A4EE00D85FC2AE1F439009A21CADBEE4A699D5886ADB1A91DB87C1BEFDA40A6BAAF785B98971D733B5237497B86E89CCEFF4047BB0EE4AF2C0CCE36561758781EB57877CDA69BA5118EBF885452A682B2F650FB9C650884151E1961C11F7D8CCCE4F08E9BADDA88E17BF2DB02A6D1E1D2827021DB4659219A53F4F2C4C3512C48663CDF1EC31B6DDD6E35924EAA021247103348AEE988E84DF07EFD4A4BBDD190878F81047F477A4FF9B89DBA8ACA2B5058528061CC13CC21BE921E1C2CC0ECBA29139E304A0BDF7123670D3FF614F1F0E22C7C8E161E91167DE9D2380AB6D5B0807DE6032472D838B3F681E7ACBC75D71426F33ED97C79F1AB866C0EC37A66D86CED0DCAA7DAD8A4E71E08A856A7E8809F918430DD063868814754D5F91CBC9BB551E5663948A692D12D054D90840580C1D66423931FC56EDAF3A6A71C48FA89786E1A76FE326B90AF058B1627040851A517242451CFC337B7DEA5192657F498A96A2D405C7AAFD57EE39F6BE2C82A53FB2B744F8A003B689A394B8F61F7536B86985B684DA6C8C1C2B167481C309D1A85FCC85D1516138C86D028F556465D987D2F811892889E529E9ADA83956DC4741F939445B2711AA890B29BA3E9FC52C4881A9A34400B4B94126E07955BB03129FBDB971A00A45684921527E0431A3AB6B216B29F71296C1244DD9AD2D6D1A87E5CA6320CAA8EB347CE4D9F8AC77A5B3E43929F5F4847B4410A434B372FD317392AA7800C5E54946220CE06C2089E7CAA8F993A0A7C75FF2AC9137B272AB3CD4E320F03DD9B8E8EBF53B4A4B3E0A2AE1C07B14CDAB8F2BD7876E4D4FB45C950531E2ADCB7A4C41AB0ECFBD596F875E032C49705595F70A6A7B37A07484B5B173F9C611156BF564727E494572744D779FACB63A81CBFD2C18FDDF4883B35F19FAF86B48D5CD2DD91B565F6F3F7774A9CE75488FBA6FF0205FD45334A09906A3774718DDF36BB668C690438A5CC2F8313F8D8B35002CA267F3FAE2ACAED9FD4AC11F8388FF7CA27C3546763398E70BA97BF84F3DE6EE6C9C674772ABCC1D8FF097688E3BF3AAA181156E4FF135A1496F57BF70B4A953C9ECBB173E540EB285C140A6ED4CB5396B6958B799FAA589F3560CA7827B256A3001D465F3FA74BC5F397B5234A3D94DF962411DC97DBE8A6C554F9542FB6902B2D7E51B3D4B94559088F825C10A800FE6A1A8F56AFFFD51EA286DBB923E624FC7648B59CB8C78EFF8BED0E9B0DFE3E17CB1CF59658C0D73D1E63F8FAF0FBE8A8C2040111959D5A670BCC211CCAE5F5F687C59D558CB2D1DA9EE891F338DFF31CD3748B61CDE572EC77997A2BCD420E58ECBDAAFD9BDBA4BD815108B240DEA39524C501079A2815C04018C444AAC8AEC51B9271EC59D2C2647CC924B55E236369BA5C9F100EADE87928D10820D2C7B24CD9F76C8051F01577D24C318FEBC2762DEE56090A69FA567D0C5C78126420F1A05ADA26E940B72E6A1F9E107E8E42A9DC82FF74987C9C874B5C1714AD51AEACA48C79B0A6AD85F5CD06E4B59918DDA9C1EA1356480AB1D7254B2AAEEFBDC3AE61F995820C8D25218B7AB81957686E1BB2C02A72AD3B067589E7E454232E6D4AED6D531D31F29F7E297056681AEBDF65EDED3D6AF07161B5701231D7BF81A5ED366BFB24B287E1511840B5D4A91ED9317892FBF9E9684291E2A3D7F86C1B50F20EA98B41430AAC502011A616D454CA4673C0C3B3E188AFFAC0ADE22C470D99F216F912236252B0F1C3FAF39F5559E3D0172EAD6CDCF9300933A0B2C8CAE0C69503B978ED984A7657A5D9C1D1AB5F6ED5AB23FA6CC4941C8CE4B8C60E709C7AB5C4FC7D0D4679F9D78F4276DF36A375CB2C50BAD8BC2C807EFA5BC82B013E7126D008BAFA34C4701D464A9F05DCD14482A95871046B385D87F0CE6BE103A45B7E8F10E410548842655E088F270E443633B1A4515EEF5ACDA58551D97321492D14B0DE243A40813210D712442091D9A5624F353739618540511E6B51C9C5CB2798594AB428A87041F739E13504103A1A8324392800C0F640D6A7D75DCE2D69607864529B6A37750619565E885A3FEFBEA701E877A4095F1B519757A8543A598BBEB843CBAF01F3882AAD3C86F85E3256CDBE4209FE15ABAF88058FA199B21918C064B40EDAEA01CE9C99BAC79F55E0CCB1C03AF2EF2C56D45E06D33F9D3ABBC6CB4BE09793A386048112071548CF0A71C9991DBB3A11D93483E3716D9A8BAAF62BC5BB58E24D982E067547936FBB57F2C25218A230EFB1A665F3D948CDEAA9F8659900F10C43437C01BF081D2664641DB6FD5B0CBE2004A96DD26D999937817B3A8DFF742DDC33FADFE21A034F29F62E5EF6C502CEC5014A10A68A2DCD1998C74D620E84F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC665137D5D47667E1CA8F1B70A9029441013DB1E00D4FB39DE01E275ADE1AF6E6483B18C34D78AD814C71F370A0AF1E681C1041FFFACF9685BABB03923BDB41701F927F3316ED4DA8420A373F5471BE4A7215CFE5683EF16855C748D8FBD21DD9A6C36EBDA9BC5497F5C0C93DDBD40A717DCE151B87E8D5CCEFE5E8A0A66B3F92739B24915DA4B87BC7E555AE0554A8FC1D2514A7979DCC78E92D79C6908005648F90E5E4AB32CBDE27EF1BDE91C49C5184A3CE134D7AD33A1AC03F4A09CC245DAB6033C99636D9F6E9A723429F5EDFE118C045EDA721EB21387225EE2764A00D99625EB4FDDDAE398DBB4D8CD926310601CB34D38B7BA4BF60C66925B2E66B838C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A3692F3176BEC212C8CDDA63B223901AFF8E3CA0612978B7D97E8F2E1C000B0D2FB992BE80BE6906A967BE9949853BED6333CB070A1384B5A26ADF28D3BC5ED2236C6699909AC8EF3CE18997A672EFA2087DC9C0C38BB416613F206E136D3135C4E39F98C7C1F50DBBD69337069248EC64C3E5C6EE0EB7618396BFBC2BA26667426721DC84D3A53129AF465CAB586A54924BD35CA4BB250865AE0EFE67BDF060D8F947141B55502BD264BE2F24B40DA59C45FA59620F207E10FE94013B6A9F94182CFDA5694E19B1ADA22B18F183D7DF0A51AE2876A5D6B79D911B0B8A0D3EA283DDE8F0FC0DA1D77498ADC4DE901F89F11DE2753E8EF674622BF03110CB519AE4F6CD0ADC41A43D1929CBE5047D9B09FE60D9075C85CEAE9C825EA53585D180FB610BBA83BBA2E590AC5257DF858E7F11B8298C848F2F79D78C37F00474AEF9B5E9AEDBA4C81ABA062F24531171F8137F7FCF50FE09A38F60404B03CD1BAA934D6DB5CFCB1DC552BF873C6AA9B5FE76FAE92D4C3674E20DCA7BBF430C865F6E5FB5D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF710D288F760D8E6A64D9E2E53F680C21D30AC1439A4A90469D0C6271AB6EFBB90A4F4DBFF7D5F3875C6507DB321D81C3510D7E7F48B297881DB6FA0AFCE41645FC93A37FF04FCBA7FC19B9089BEABCF9BDF44E2C4614A73FEC80C1234162B41BDF1313F6E13AE2C48A6C4CABEF5EDE59AD461384DEFAF1935E23F5CAB3829A81E2DFFBBCF2FFB141D975EABF78FB4BD484F75E08318C08B2104A468E670786397EEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA360AB78FD9219EA890695CE44CC785A3A4DD39CB8F3C82FA5C6A3167055CF3309EB06EB90826159619E65C5E29D46D35E61C961AEC002F87B44A2B7D5C0E2111D17268FC3B147434264112A2E95AADA6ED860C50359372609ADB174741CC3AAAAD1FB50A42A560BB18D12C228F10D2776DED26752930890259A5C0F64C7D30C49383F92F1EAC6B1E8D6BA05423368AD3A8BD145D397389720E80F6EE11965E467D4D5864E164E51437277F698BEDA846AEB66DA3DEF39CA3288D30C001D3B0BCA113AFE8AD333A08D801A9E4C52DF0DDD4C63D8DF7EA938014336BDCDFA10E960DDDB4B5471263D096A49E3C83A188C46AD4EA8D2AEAAD3B1BA78CF6F116D0818BD2F38DB39D74D340546233ABC52278B381B7DEDC3A3B5DAADC8A4E7519AC9F3572A35C016CC7A8E0FABC029801012DD7454D7475E5D8B492A119AC583F4043D25CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438D81219D292421651600D48C2BD291766ABA14ADDC9186764DD212446D27C3738D2F606A9654BB310288F37CF0ECD5D38590E4D887D9D5C523527007F6501ACBE7CF36803727022D98CB15BCC0A88A509DF3B9A84E99B41843283FF2E10FBDA3C14CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D446D278BBC90D6A56B71D6DA6FCA49F332776F402F58D180482B2EBA5132D8ED67144DA06AAF952EF5B9BEBBF0CC8101E93F3BE05E58EB75D55B3CE72B9C8A07725C61C24C34DEB9A7349E51256EECB7DB61510D8BF55798B060EEDF9F9551AA615F1661F544B0779B2974A54BE8BBA388D6D7FB8E2C0956DCB23F834025CAE4BF26B798CBD5938A517C4C3B8FD3B8FE920558256C391433854481944BE487AFBD226853E385D942014B393488D554FBC143B44F7E9F348FB79920D4AB758CAEC55ED8CD388DCE4B4381D5C3A9FF36ACF9948993CF2B2E03030646852CB4193585AC6C56947193F96292D813FCF3671D46B9DF2D99D43E0AB4F1994B81235A50D5D977FA3560CA3D46CF60945C8D3E1103B6B1D13CCFAE43741BE65EAFFB9DCAB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832D381248D668B0A5ADC623F2529B02CCE42442E86382E03BA3FAF21F86FDE1C633C9A17426EF1F4923824A1E394BBAF5058C00950968357FEA01AFA8303DAA21BAE4617293B3B19A50C88C8F7D8A677A3314640452734E7FE4BA483C8AF87356E6822D943C23705352F458ED80B8375DA6F1F0DD7688CBC6101727F2AE7FE500C98A185F29DC71EE3506F8425B8D7EA94BE228679F42ACED5C9162D6A0E9AF148E5903C0ACC117C2BAAF1EC4A73A0BF73CDC646D1559EB1FA607044B5C7CA60FBDD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C6F2AE696330DD7C816130134AC101764D6B4FAFA1E71A404CEBA3406E1996391AC35A28F18E05DA188AA8FB52712696C986C25F70A31DA73957B238FAE89EE0BE4F77ED34ADFF62BB5C0838F9B645F6851BCA9241ACBCD3038BC40F40F076D1CCD8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CEC2A8424E383ACE82322B3629ADA77D454B677A60A2932B49F844A9389E73FCCB22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A86CB037675575D46C48D89A7B644810666979BFDDE595E1A2362B9961A71D9F75A4A72ABF56BBE2C07844E774123A5DEED0116677B286BB3F8BCAF92D501A5FF375487D2694B089FAF47D8632DA9E213A9C914689D9FD8B0DA5320F6A89787E198248FA523B9B2E910FE55F6127ABFE1FF1EDFBAFF132A06AB9FF0F2E368AEFC6AFAAE9F61068AEEFCAF427D37CD93FC0B0D226CDCF6A7C1F007BE2E59568970AB644D475E62D7B8E7E5F7BBCEA4D007BDDAAFCF6B84E09BCBC5553F516E2E5DFFFEB66C9F5EF34559251705C736FF66A96AD2CA2C40A368602DF65045808D87B7E24CE23C67906BF64C90CF0E0F8621537D08A09290E431737F9C493DBADF98C9E250E094C6F0F7E850F5EF65E71967F69159ADD14974C1AF501C74F01D1C36AEBE604A32DC02B676BBD7CE4BC3967FA8899F3B1F654E7F3E425ADB5ACF59B6 +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-4_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-4_256.rsp new file mode 100644 index 0000000000..38e4a7a962 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-4_256.rsp @@ -0,0 +1,12 @@ +pk = 00000014A855A0EF256ED6B3F83CB4938E1BCAB172AA13D2FF813E233B4C2E3DB18D27D804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000140000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94AA855A0EF256ED6B3F83CB4938E1BCAB172AA13D2FF813E233B4C2E3DB18D27D804562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D933090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000018F224E19E61C8A7076585BF7780AD32D73D04D66A52F0B4CB6D35D9496906BFB05000000000001C0F7248E24BEA5635FD0F3F3411F1A20316CD29E2BDE6DCCBDEF8AFD463CADB306000000000001BFE2E0B4F4BD9B2B955C3CE73D4D0E703C44BE5168224D99756D865D86689E1607000000000001EB5D1F16948BBDEB3335E0F93C3DAC5C3FF7DCB33B16BB28D3826194192729F80800000000000194BC268989E8C957203F60EFD29089692A7FA0980912BCCB1FF3D6921B980561090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA240104000000000001806EBD8412403D61AFCBD000376F11695F17BD253F82340C13342F750D09B2D205000000000001207581737977FDD59550FE1E0E62692061E1E37C554529C52E427434D2BC50AD060000000000012C3C45D74BE1C78902947B902756864EFD771DAF34009F91281FBAD0636A74EE070000000000014DC0E1A0DD7194009DC2FC5355C4D62179DA0010E19737654D7DC0E4C9761DFD0800000000000112F03C455D30919DCE22D2F8A0D4B5491A8188A32F17059A6AF994ADE911EF750900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE59F8968E30E844A031BC745FED8550EE78B1266A91694B967E66785403F9FDE097DBFF047A171318C43FB2472127512463FA79877B475C7F810D28AE0BA7C5966102673F9F55653D9E546E378D2BB17CD35FAD2F50C5372DF7871B1F1DE78A72FC84F2AD1BACFB45712FB13E3773B3565B021D30A31602528EF16FE6D83795A1A8620E06BE25AAB07A8F3F1EE979687840B7C863D0D8A547A5F7197FB72024DA7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011420B60C54314ED8291B4F251FF32674EE6A3C3609140380F6B20865B7AE643401000000000001DA6EC89DAF2B01E86C06ABE8043C9A6EA0562A18C49B4A9497D347FAF8EB910002000000000001A0A42481338E08706BAC35F7B5F5D93432D40144F47A0F6790DF4B68525ED740030000000000014A9507DA8B4941DFD3D5E9A02EA050B97F9887A65D93FD8723FDC30C7E2AA4E004000000000001BDEA75F9BF80695B677BD7E643AAB0D6DEE791B64A29E66D796C51176B9F718C050000000000014F174AE6AE0AD2D1C856FD802C756287A8496B907E56C4BE48E85864F71DE7160600000000000131702A4AC2D7BD2722AD083379A254918CF9EE0656A5DAD6B07C11A74BBEC85207000000000001C2F54B401EC9CFC51F249ED76CF09A24665D8603D3747E67778075CC7817C4D708000000000001A1D56697DB12706AEF7EF31B1584DFB73FC269AEDE8C438FE9B6FE17C7A65986090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD6E7D8241F8BAB4D68DE3288296539D0DDF68497D7634A964B76E82AF13767129B7FE5BF4C85685F9C1649B8A52FCBAA9B2AF0C0C2BE1904DEB98ADA34507734E7937BE5E686F6DDD4E57D5EEF9FDC2164D60CD06AB5C9D11B840625837703C3CEB44B6542B684CFC5EB9B3297D946E7F698FD75C5A824EEA9328EDBA65225623ECF3B1F560C0D9DD03CA404DDEB74F901FA06FF4D2B0972C31F94450036B01DDD94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB0AC0CF31A27014816177F79DBE703195F44C47205EC4A5CBE62146B5246AFD86660BB52A30FCC16AC9D773E97F581C7518D007FE0489C09FDFA334F49313FAC2B579C7AF47F9946A85247DC902ACD5E0B22949F45945DDD51DF6AB0FBC225603D7377F93D29F2DF9500194E614F93DEFECBCA3AFB03D22F8FD7661D9D41D62D3F34476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC5986DAAF87F5A9E602BA73B7392923FDC5B81A6BAE67BDABA7F7D2E9410D160455BE2CC6A833BA1B0F8FE54852A576BCECECF9BDAEF1C9B426B3DBCA32353CEF2D782F9FF8C8DB114C65E259BD077E800BBF0AF92AE1083501FBCB6D736C848AFA2C836F2E20EAC0336B58D10000EE1E6FE4AF2C87B2DB73F0F695508E653A3755D0CF17516575A25E8960FFDB7B1A00FBED460A8BC7EDC370A52E214885B7DD496596F52B1697C11D5127906C27EEA91E5D3E948E752D54EDC1A8284B9330F1BAF79C2B31C41136602FB4D1A7418EE586E7386677F90D185CF9D61FD7178055651AAB6AFAF6B955469C05B619297155F922B97B7FD28FDA0C0FF3BF34081177EC83DC0433EFB8A1417D60691D76E15384DADDFE66566032B722D99F959653F5C68D4FACDEB4DB5F9CA52CAB9D78109D66D75ECA67FE82A790ADABA4C8F8EDC5663FE77361E78A43189D2B89D1F26535B1E860C9F18E7A3BC6892A68C68AF96C1F4730192CE3BF69D4E7048912FFAA309913C054E041306B4B0079D606F9EF3E08020379FC3A11CE22436F7C8BE6C5F5EE2C1C1778320456C18A68F306AD1B55954389F635A502169454E7C432BADF0A68F529903CA29C2B836DFF01B67CB745A77A9E7813A52B92C810B51BC3E71D7AAA9A9F31EE4542965AA0F6F9907D1595A31E720D4A7098FB2D72F01F8B83BF3A93D05157307E2B595F0609BF2C8B94EF6A5D60E53F20C1559A9476CD2391127B12D77357269359C424A769021D139860DCA4136B718B65880234089C1138705945AB76C815ECB06C01C73C60312FE6DE218F09C1607F528CEDD2898E077008FF6E47C4FB6B2C103BA92C399A24CC38B373B3D7F00D63E6A42412F710C62528106482F703ABC7CD198A24723A6BE730E6DC971D468EA20D76800F938E651FAFD425643ECCDE70BB4DC1D6FE4E9B3D3624C330E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD6847C7DCD156F805A9A513F17CFB60F16925F4C587744E4AD35C7127757AAD37B73E5277D6614F0C315BB9E3BE48F654AD2D343B3967FCCF5387EE8297F2F74214B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FED8B073D52EB9D1847445D2064669D9E03116C2D999F3274876F37552E2D8A04E4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AF91188FC2BBA388067FA443275DF1C06B23BEBEB418CCF1A7CA0E4BAD57780AD7D5528BD18362F273F0D97C081E502F32EFE1508B343268F1D2EB3F12914313283E40F4EC9F02AA17AA8A310FF50DF2712F49896FE31BA07A188488E45EB59D6BD6B858D527BBC0892580637EE631FDE8EAC14EDEB1E73EC75C8C241294EA628DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF47606C4D632B57BF57812D2B2CB85C631F239710C05C7743C2F4515F6C64CBBC8109E7FFA421A5A637256FFE7F44413BBDE5787EB92060591282ED69794E9D64356A585D5E293E705EFC493596D08F3E68CA984532F71A20D81C4BE0CA989A19C2FC268CACE37F8F2D5B481F2A4F387043A4715FE805C6FE2D4AB89DEBE10CAFD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D34B022FF9C01B7ABAB66A08EA5A0983E6E85954C92A6D3B2AB9D45BA49B21D45A3468B53440BB45283D3251613D162A9CE508A5766740BC16F13842C2F89F2396E3363A1934E3AF2E7221957FDBC5F2BAA72B6E62BAEB9E6D33B248A5102714178A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573D2974687D3B63D655D412B1DC0D3084791DC9CF5BC4A42D6D3787A187D4765E5C65894BA159FCFEE27FB3B36A54A9FA312C81EA09C6762770B9649872A738FA0111D745A1F9A0BC53FA819D6E7220FB07293058C8EE51270F86D956780BB52984745B68DA948F7F936345F770F38661F35198D5BED466C3E1C7A23DD56D543CFC93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B7871339ACAC858B546C9139F4B917CDA356F04B779BBF803351C1B452BD9EDD0E2DA226A5F930C3C97F43D4633BF11B8BCEBF646B8608685E36F0ECDE7C7FB5F977E4D61038C745DE151D832D47C979224CADCFDB0C82650055F1519B94680A840FA14B55B2190C71AC1F7A7AEED989BE8C8AC61149A0C809449B677AC353867D0185EB15322792A3A7E328FEE3DF2230E4B70551FD7F9BD57BBEAF02E40124C58F019EEB66602B9EA10094839EFA9070F5C2DA3AAB6CDE6EB58246A59AFFA0352106F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C013843CFEF1EDA266283A5CE4A6ACD7597519FBD097E9E460D9B071D34EDC61672D14E6D9D4F9A033B5B473A1B13476C3C447E884455A5D168DA793F9E2F09612A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B2BD0A2D4978F82258687586F9E6EE6AA21877D8A2C7AE37332573C420DB9C8754CC20EB937A8B94056D96EF571162B0106AEBFC344B5F28D52B8CD02F6168F45B321639DDDFBB333C5B872E80370F408EFFB5CC7394767F8CEC0CDCD7C9189E1B24FD29C7FBA4B14F30B8F5996155855C08A749B6AAED58C55271223A53D1E8714549EEA65B9A9245D9F5AD2EEBAE82637B9E3C78A24B5262873759CAE9AF9054C3230F88509E71CAE2238AA2DA1C25F0DCBFDE9BCC7B234BF1EA6697DD4E8B020B099CD92492855F1B528BA0B359BDEC1E77245432B7B1B2A5A7B969947A2FCFEAB2E94762E2F3F524E88E6FEFC4DBECED7EA550E6BCEDFF229E69D9C7C7803FACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E9847ED6D3A7874015F0AE87EE37FB6C478F7330A07D4C59E314847065E2F1F5F7F6DAE557F85B03FE6BB31B28A40263B64218FAD4572BC5FF2FD4E3F8F9A8894795658466BFB5DAFFCD99A69D532713CE072D81A42045933CDD30DD257F6C9848577D9F8B09B5D7BF71CF202AC4CF296E05C6A7ADF77D8FC670B88DAD02DE5A80D4168F7F72A7252B0E421F9734012AC8A8188677647D35ED6199EB300A6B71111D7CC77F04AF5E559A0D34CE1E1490576716A861E79902678C1241CB6F614176147ED88C82A99CCF2BBF62AE65572300CD4FB12DED4B6B0901D5F6BD02F036BF66B095215AAA76BAA4A07E2C0CAD2B2D76BEB56956C26ACDC11FDEFE9D42C6A698C09F0ECAC502F2F7E00233329DCA9595A191DF6C87B728E8F9B59105B9074992A62F2DFB38852C7F4BA5BF782395E906AF48136AB2DEAB4BBE7F0F79867696DDAA4176F14C9DC7A301B0DACA30332F73CA3356A62A4832A12DCCC3D696505F59E73148ED6401A34F6986428CB1CF18FD61DF1455A042455FBD97A76A404E65CD0BF41E26465281A0BA11EAA39CB48B99F2354BF5407629727B52DBA14B29C65083AE8B8891AECA5500BD15DE9E66E7D5C0104891C17A108B79D8D96D35F12170E2C930F8F16068AE3CA8511016203A1A4726CFEC7B6AAC959B67F3FF1E4AAEAD667487299703D38472B5085FC55B9BB775574AAA118BC81076CD53A4AA7E927482B1D617C09C6C24DEB07DD41C2C42B6A0BE168493CA5A40266AF5B992B9B2C65CFA82A2EFC515948A5FC521A7F49DC4BBAD296BB6FD4AA6FE1B7A7726229C03DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D973867CC37DAFE8FC39332DFD321B1ACA45587EB6D4727F5AFEC4178CDD8AF03FA0629DA84844B5131CC2AA07E2FBB8F80D3320AF5C1734031AEB68DB8B6C7358F775E8538C260FE6A79DDAE2BC7D40222B2942A2D8ADD3F295A135B5FBBA319FA3636F56D1BC8CBFA175EA61C1F53980664282E56291B4ECE5B5FF33C2141F04A3FF83EFC062CF6C635497FD03D6E56E405C43C4A31DDE872C4E277AA190D1D8350A298F16BE75BE305891F9D1084146199960A881C34318CFCF1366E82A487CEE95D5EC9F9756FFFC9DF3A1058E367160B321753C937D587130F9AAC766C19F033CCB2D886AB532683F50D360D10DF559AA16DA2C0E3203337B46EA1FCC1407675C5057052EDEFFF36BB2A6331522DC5CBC871C52CC35E95DF677771084A6E3E10A56111E6B9F7DAEB1FAA11B9CE5EA450A7D75F2B7266193CEA51A9532D8A32A2D4C275ECE75C3A59C3F02E3F9F40968642D6387F752C801A761F121A3EEF4F6B0AB83B7E815E5BB9D67EF85BF9DBF72E5E6DAEF4A6F7519130BD4F826A82D23332BC291A3D320CBFBE4BF1A143B78FAF7C1BF61F30801BCF715A05F2F7429F0D1A3B9F90D191754FE3D761A77CEA46082D3D2CA5BF26EF05257DBC8B72D156920EBCB1E064FBEC3CA43AF31CB2A53B246BA02E3F8AD4E07DE794CC1D8E3814DE61807A116F768CFFB159D16CB7214EAF1F52452B768380F4E16E2BCC10E82A027148477F2C717844DBB1677D6F2559AACA58E4759D40C7D62610399D6EDBC6DD4DA7904D2C53E4D9E07928FE181D503C5D45D6DE07E767025D9B0386F8C123C38CAEF00BE2223E8B1F46370B1D20FF0DBF78CB6A016D0F72F07820238885D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3A1E6EADFE7066FC6A5781AF310597B333977E34D01483A860E7D986357107DADB4F5D040550E524D9D1AA456CAED45FB5F6475160AB01C8AEC46EEA735384E4FBF205BB117F68C03F6D301E5C469033B05360DA23CF49DA36E050D627B2067B30983B2B426DCE0B78C0500BD15B3D2572537DC9B5F0BC0E1A12F533F58B2E21102318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3F5C33BF53D2A951EA7BE7FE2D487362EEC1DCB93920B266C5AD39FFA0FC6D4B335B1355A6D8AD3CFE51E9F69C8961A82831BD27F727C9030A816E817783DF89B519D6EC14C9CD88B73FD6152250E229BC6CD8C952777CC5D670051B18F5AFC99860FF7387C5880564703541C2883BC93C5C0EEFA57AF9E9D9D04EAB3BA87782807C37D299789C60C63CC2E86B5610ECA54D3949E17070B1978781F705E32042AFF28FA979979A511C5D14ADD08AFF7DDAE858415D7B0CBA138BF6D1C72C99A9564FE6CB5C9ED554B98D21CB796FC053CAFB4B3E8214F44643C99D9C92EA847A1B6DF3BC21FBF810F9D04B26771BC6DBAD0BDE30265D402E62EEE8ADC84CE8AF0FECBE8F68D13501515B8C28F68AD45D9D1A454904DE944A90C7500049FB74979AE952EBDCBA09DE543283CCA44D3F00EABF99DD714B8FDE3755D30105AC8CBC4569789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411935E2773E3B03C5E4959D9A2F7D55B05B8574768DF40B5EBF76FCAA69F463E0FAFC9F02B01C7B89C1AFB661B43AED07A9D54A6669DCD9022A4EA628CA69577EB1 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 9893 +sm = 00000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6AD447A5EA848807453245A18CC01A94E648515E259B4B02F4CB014A3064FACFB443FDD5FBE6890778BF1BFC187A67A07BF1296F0847C5F3CCA1A7FB1FD9023E9BCEFD889D3361070C554580F55CDC11D8572F0E0F241E24FF7A7AC9E3BFD197FB2D92D18C1A9520CC21A0A17908D121E1EA426738CFE364AB99172E83544AD0F868149F65E73EF30210B36E03DCD6257185F671F78904B3F11EC67EAF994D1B9D8E83842D91853C8E1A4E123A8BAA85CDC3BEF892DB683E3CFB4D60DF60CF4704069AC1646996731948816530C43C82CC1346A5614222B29B4C635AAA4542F11023B3A0B4EE1A22D367CD4E000A7067C2C7DD162FA09E777CA9DFD3B331ED208390BEAF62B72F91B502F69B6340B31F9D76A961DED774B471ADE78E037785CB71F2E6BEAA7180B7DD54525F52523DE6F98A205A6866C5B7489000B5CE17FF49A0F7DFD04029531B2B11444442249E7EC5E3AFC17C625C1518D4572F25A430957FA54D60EC4408C15DA7FC4B5BEC5120F1966279A400F0AF374CF6ACD439AB030AAC07D59B03A06086E043466BACB5E4DDAB7AC7F43409219F27561CA6168DD1793B0896752FCAE3699AF03C2E8C8725BE6073251317D1EEFB497336A32C511CA0B7C50EC84D8C0000D09632545965D732E921D01DAE77512180C12B01A2791BDA2E9D5A6B8D5DDBCDC0663306EF3064C548CE33CD8A644884C48ABCD720EFA3535EA50DC699D5233C7C07E22FA98EACB905820F49CB77A44374C0219D53B7570F655867F45720C67D422D5D284328E5439C2BE923E7F9C5307F30E5091A88A028D854EC9C6EDCA171B4E22C3510AE398B72498DDEC9A789612017CA366B164BE9E9FF5B29C0119111C7E194CC862333007578AC87C0A31254C758E96819FF2058952B7DC0473151EC0D9571297FA6AB0793D3EBB4AD559E0E367DE90BD20B96EC20ED1097E1670E2B93FA14EB1BA35D7B2C047E6BE110205B80B6F169695CDD43E5CAA8BC694B50F502DA1EE6CF34B148C124CB9F9A7C126FDAFAD4A5D7C10EC37376BAE08A0C313E5AE477A8DC6E0B54DD81E44E4E892F50EAB30D7978402C58B18890976C506E91D31F7FB3BC77EB0B08B99B12FF9572A673DEF5D64C16A1550E16E7027880D8853F1174E4B6A6E58BDD3277BC2B3E956FABCFA1633528BBD412D3E2F6C95AF02600C32B350543F091577CC486749C1ADD068F99DB36D8C4C59E35F94A4492867F7A94B9CBA5348F7071C5732563F8C1C008AD8C1767EC2D2ED2F3461E08EAD719760B6F43A811C31C2FFA680BE036C0982E60FBF9CF3FA705C58F3B2270A78E69A252FE4837E7E94DAD4842E9028DD986E5AAD6A8F16F9F138220F5672F8BEF56252D8E93E693A43FFC9AE96ED514D7405F080AC39BE1BC1F7BB117AB555E88AA0B934AF842719315E9C4CAC0FA685487177D3873EF1ADE626432E99402AF7ABD96CF8885DE3905BC9A2E4E755BE83AAD7C9280D0658507C51D6534AE73B220CA73A13917887367D055D38A65273890D1FB7A3AD50A7BEC3E7B693C41F717FEC260DC06486D04822DCD3BA1CEB89F12DFFE3534B51B107E75A3D5A0CB2436E8C9D8D85EA68ED5A5122F037785AEBAF31CA3BD4D001D8E9151B894ED06E313F1B4BBA00F7D5DF43AB472D66CFE6CE3B96B4F37F3D75356035546763398E70BA97BF84F3DE6EE6C9C674772ABCC1D8FF097688E3BF3AAA1811A2328704DFA7347CE5F938B3B4668994AD8A581E922DC72B14208BDB9671D73960B0747CFB99B09D25B1C0EBDDD5CE383A703FBE27C8A497B3C97FE7DF05CC6F36D18AFC8DAB6866EA201DB358B45AA0CDCA0959B4F0BF7ADDCDB0CF61ECC7FB7936AC13C35553CAB1747877424EC9FF34B7BF34172C1F65EF2D3F43DA07CF42D391577D3C7C28A0DE98276CDF9601CD0D4A8E79B7D27DFB2A31D57B86874B4E03D759940F88FAF5EB05BE1B90273FA0BC0048267B43376CDD718399A354E3B3AAFD9BDBA4BD815108B240DEA39524C501079A2815C04018C444AAC8AEC51B9243CBCAD6F5857BAAE18071F291C3D742C9FF3FC54A51D1CB8061D5A0ED4358E8AE0266816DEB0F3BA03299C533D554AFF476259527D312F3E6EB7E28290475F9E59C93E72BCDE6D87961B3185CA3ECD7D6A913D9F86EDB5017F5A1F28FBFF054D4058752C43C58B7599D697EE97FD109A46E627EBE3943B5044A18F1E08EC23E83B4146A39DB9ACA7CEEB0A93C4B5F1E625978CCA15C8C357DEF852277E400DC2D1BB52A35052545FA899B73D5DA8D6340B3C2794D4A24A4FD388C8581C384407EA9429D048B67D56B413B9002434DEFA4F2F025658778DFCF9BF148E70A2A70A185EB62720EDF55A36BA9C9359C49DD6ECED5E8CBCBFA03FE06416AF5AF976B8F33F4F73F6260DAAB08BF5A02A2F664E62BC3BFAA6A4800EEE8423D93ADB90859C7B9BD07FFF6433631AC5C062DDFE499E0C22DC5E3A10AB8D8D0C5D9A09833E106F1B8092E6A32B663C6EDC54366B5DFC4D1757DBDAE9F8E33B05A669DD692EF340F6C1BE587DFAED8EA010542245C17684A9944E53BB33C776507D940D699553C645E1E8AD6AC0BDFC48F9179909E135B6055FA9CBA44BA072D2A538BE604F88CAF5C2928BEF611C41113AD14CD4D92B45C3B9C0B8F339C7219E8982B9AC9C8063AEBC9FBF1978C1559D174EF9C55A74C7208114F94F2ECE9214B02D50834D401D4FC5E97CD40B375D0F6302502B3BB83098A6BFA378373FB0042E1578372BD4C2485B886668646E164CD67132C6D187490F3B18BD3A339FD5FB07DFA9F1F642E179872A32FEA44803F1728BD9EF3C177C047615E19B84BD6F8F61D368B32F78D2943AA14FCCB8D7551E69F02BCE1F438830583A0012B5A2B2A6AA8453208B991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EAF5C7A2FE46CF8DC6C729F18BDB361405C6D336725999A4CC76C94B5668A471861B40AFF393D6177502756D15DB5232BCD58ABDB633EFEA7390FF8BEA443BFB32F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD5894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A6E7D8241F8BAB4D68DE3288296539D0DDF68497D7634A964B76E82AF13767129B7FE5BF4C85685F9C1649B8A52FCBAA9B2AF0C0C2BE1904DEB98ADA34507734E7937BE5E686F6DDD4E57D5EEF9FDC2164D60CD06AB5C9D11B840625837703C3CEB44B6542B684CFC5EB9B3297D946E7F698FD75C5A824EEA9328EDBA65225623ECF3B1F560C0D9DD03CA404DDEB74F901FA06FF4D2B0972C31F94450036B01DDD94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB0AC0CF31A27014816177F79DBE703195F44C47205EC4A5CBE62146B5246AFD86660BB52A30FCC16AC9D773E97F581C7518D007FE0489C09FDFA334F49313FAC2B579C7AF47F9946A85247DC902ACD5E0B22949F45945DDD51DF6AB0FBC225603D7377F93D29F2DF9500194E614F93DEFECBCA3AFB03D22F8FD7661D9D41D62D3F34476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC5986DAAF87F5A9E602BA73B7392923FDC5B81A6BAE67BDABA7F7D2E9410D160455BE2CC6A833BA1B0F8FE54852A576BCECECF9BDAEF1C9B426B3DBCA32353CEF2D782F9FF8C8DB114C65E259BD077E800BBF0AF92AE1083501FBCB6D736C848AFA2C836F2E20EAC0336B58D10000EE1E6FE4AF2C87B2DB73F0F695508E653A3755D0CF17516575A25E8960FFDB7B1A00FBED460A8BC7EDC370A52E214885B7DD496596F52B1697C11D5127906C27EEA91E5D3E948E752D54EDC1A8284B9330F1BAF79C2B31C41136602FB4D1A7418EE586E7386677F90D185CF9D61FD7178055651AAB6AFAF6B955469C05B619297155F922B97B7FD28FDA0C0FF3BF34081177EC83DC0433EFB8A1417D60691D76E15384DADDFE66566032B722D99F959653F5C68D4FACDEB4DB5F9CA52CAB9D78109D66D75ECA67FE82A790ADABA4C8F8EDC5663FE77361E78A43189D2B89D1F26535B1E860C9F18E7A3BC6892A68C68AF96C1F4730192CE3BF69D4E7048912FFAA309913C054E041306B4B0079D606F9EF3E08020379FC3A11CE22436F7C8BE6C5F5EE2C1C1778320456C18A68F306AD1B55954389F635A502169454E7C432BADF0A68F529903CA29C2B836DFF01B67CB745A77A9E7813A52B92C810B51BC3E71D7AAA9A9F31EE4542965AA0F6F9907D1595A31E720D4A7098FB2D72F01F8B83BF3A93D05157307E2B595F0609BF2C8B94EF6A5D60E53F20C1559A9476CD2391127B12D77357269359C424A769021D139860DCA4136B718B65880234089C1138705945AB76C815ECB06C01C73C60312FE6DE218F09C1607F528CEDD2898E077008FF6E47C4FB6B2C103BA92C399A24CC38B373B3D7F00D63E6A42412F710C62528106482F703ABC7CD198A24723A6BE730E6DC971D468EA20D76800F938E651FAFD425643ECCDE70BB4DC1D6FE4E9B3D3624C330E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD6847C7DCD156F805A9A513F17CFB60F16925F4C587744E4AD35C7127757AAD37B73E5277D6614F0C315BB9E3BE48F654AD2D343B3967FCCF5387EE8297F2F74214B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FED8B073D52EB9D1847445D2064669D9E03116C2D999F3274876F37552E2D8A04E4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AF91188FC2BBA388067FA443275DF1C06B23BEBEB418CCF1A7CA0E4BAD57780AD7D5528BD18362F273F0D97C081E502F32EFE1508B343268F1D2EB3F12914313283E40F4EC9F02AA17AA8A310FF50DF2712F49896FE31BA07A188488E45EB59D6BD6B858D527BBC0892580637EE631FDE8EAC14EDEB1E73EC75C8C241294EA628DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF47606C4D632B57BF57812D2B2CB85C631F239710C05C7743C2F4515F6C64CBBC8109E7FFA421A5A637256FFE7F44413BBDE5787EB92060591282ED69794E9D64356A585D5E293E705EFC493596D08F3E68CA984532F71A20D81C4BE0CA989A19C2FC268CACE37F8F2D5B481F2A4F387043A4715FE805C6FE2D4AB89DEBE10CAFD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D34B022FF9C01B7ABAB66A08EA5A0983E6E85954C92A6D3B2AB9D45BA49B21D45A3468B53440BB45283D3251613D162A9CE508A5766740BC16F13842C2F89F2396E3363A1934E3AF2E7221957FDBC5F2BAA72B6E62BAEB9E6D33B248A5102714178A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573D2974687D3B63D655D412B1DC0D3084791DC9CF5BC4A42D6D3787A187D4765E5C65894BA159FCFEE27FB3B36A54A9FA312C81EA09C6762770B9649872A738FA0111D745A1F9A0BC53FA819D6E7220FB07293058C8EE51270F86D956780BB52984745B68DA948F7F936345F770F38661F35198D5BED466C3E1C7A23DD56D543CFC93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B7871339ACAC858B546C9139F4B917CDA356F04B779BBF803351C1B452BD9EDD0E2DA226A5F930C3C97F43D4633BF11B8BCEBF646B8608685E36F0ECDE7C7FB5F977E4D61038C745DE151D832D47C979224CADCFDB0C82650055F1519B94680A840FA14B55B2190C71AC1F7A7AEED989BE8C8AC61149A0C809449B677AC353867D0185EB15322792A3A7E328FEE3DF2230E4B70551FD7F9BD57BBEAF02E40124C58F019EEB66602B9EA10094839EFA9070F5C2DA3AAB6CDE6EB58246A59AFFA0352106F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C013843CFEF1EDA266283A5CE4A6ACD7597519FBD097E9E460D9B071D34EDC61672D14E6D9D4F9A033B5B473A1B13476C3C447E884455A5D168DA793F9E2F096157F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA02A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B2BD0A2D4978F82258687586F9E6EE6AA21877D8A2C7AE37332573C420DB9C8754CC20EB937A8B94056D96EF571162B0106AEBFC344B5F28D52B8CD02F6168F45B321639DDDFBB333C5B872E80370F408EFFB5CC7394767F8CEC0CDCD7C9189E1B24FD29C7FBA4B14F30B8F5996155855C08A749B6AAED58C55271223A53D1E8714549EEA65B9A9245D9F5AD2EEBAE82637B9E3C78A24B5262873759CAE9AF9054C3230F88509E71CAE2238AA2DA1C25F0DCBFDE9BCC7B234BF1EA6697DD4E8B020B099CD92492855F1B528BA0B359BDEC1E77245432B7B1B2A5A7B969947A2FCFEAB2E94762E2F3F524E88E6FEFC4DBECED7EA550E6BCEDFF229E69D9C7C7803FACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E9847ED6D3A7874015F0AE87EE37FB6C478F7330A07D4C59E314847065E2F1F5F7F6DAE557F85B03FE6BB31B28A40263B64218FAD4572BC5FF2FD4E3F8F9A8894795658466BFB5DAFFCD99A69D532713CE072D81A42045933CDD30DD257F6C9848577D9F8B09B5D7BF71CF202AC4CF296E05C6A7ADF77D8FC670B88DAD02DE5A80D4168F7F72A7252B0E421F9734012AC8A8188677647D35ED6199EB300A6B71111D7CC77F04AF5E559A0D34CE1E1490576716A861E79902678C1241CB6F614176147ED88C82A99CCF2BBF62AE65572300CD4FB12DED4B6B0901D5F6BD02F036BF66B095215AAA76BAA4A07E2C0CAD2B2D76BEB56956C26ACDC11FDEFE9D42C6A698C09F0ECAC502F2F7E00233329DCA9595A191DF6C87B728E8F9B59105B9074992A62F2DFB38852C7F4BA5BF782395E906AF48136AB2DEAB4BBE7F0F79867696DDAA4176F14C9DC7A301B0DACA30332F73CA3356A62A4832A12DCCC3D696505F59E73148ED6401A34F6986428CB1CF18FD61DF1455A042455FBD97A76A404E65CD0BF41E26465281A0BA11EAA39CB48B99F2354BF5407629727B52DBA14B29C65083AE8B8891AECA5500BD15DE9E66E7D5C0104891C17A108B79D8D96D35F12170E2C930F8F16068AE3CA8511016203A1A4726CFEC7B6AAC959B67F3FF1E4AAEAD667487299703D38472B5085FC55B9BB775574AAA118BC81076CD53A4AA7E927482B1D617C09C6C24DEB07DD41C2C42B6A0BE168493CA5A40266AF5B992B9B2C65CFA82A2EFC515948A5FC521A7F49DC4BBAD296BB6FD4AA6FE1B7A7726229C03DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D973867CC37DAFE8FC39332DFD321B1ACA45587EB6D4727F5AFEC4178CDD8AF03FA0629DA84844B5131CC2AA07E2FBB8F80D3320AF5C1734031AEB68DB8B6C7358F775E8538C260FE6A79DDAE2BC7D40222B2942A2D8ADD3F295A135B5FBBA319FA3636F56D1BC8CBFA175EA61C1F53980664282E56291B4ECE5B5FF33C2141F04A3FF83EFC062CF6C635497FD03D6E56E405C43C4A31DDE872C4E277AA190D1D8350A298F16BE75BE305891F9D1084146199960A881C34318CFCF1366E82A487CEE95D5EC9F9756FFFC9DF3A1058E367160B321753C937D587130F9AAC766C19F033CCB2D886AB532683F50D360D10DF559AA16DA2C0E3203337B46EA1FCC1407675C5057052EDEFFF36BB2A6331522DC5CBC871C52CC35E95DF677771084A6E3E10A56111E6B9F7DAEB1FAA11B9CE5EA450A7D75F2B7266193CEA51A9532D8A32A2D4C275ECE75C3A59C3F02E3F9F40968642D6387F752C801A761F121A3EEF4F6B0AB83B7E815E5BB9D67EF85BF9DBF72E5E6DAEF4A6F7519130BD4F826A82D23332BC291A3D320CBFBE4BF1A143B78FAF7C1BF61F30801BCF715A05F2F7429F0D1A3B9F90D191754FE3D761A77CEA46082D3D2CA5BF26EF05257DBC8B72D156920EBCB1E064FBEC3CA43AF31CB2A53B246BA02E3F8AD4E07DE794CC1D8E3814DE61807A116F768CFFB159D16CB7214EAF1F52452B768380F4E16E2BCC10E82A027148477F2C717844DBB1677D6F2559AACA58E4759D40C7D62610399D6EDBC6DD4DA7904D2C53E4D9E07928FE181D503C5D45D6DE07E767025D9B0386F8C123C38CAEF00BE2223E8B1F46370B1D20FF0DBF78CB6A016D0F72F07820238885D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3A1E6EADFE7066FC6A5781AF310597B333977E34D01483A860E7D986357107DADB4F5D040550E524D9D1AA456CAED45FB5F6475160AB01C8AEC46EEA735384E4FBF205BB117F68C03F6D301E5C469033B05360DA23CF49DA36E050D627B2067B30983B2B426DCE0B78C0500BD15B3D2572537DC9B5F0BC0E1A12F533F58B2E21102318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3F5C33BF53D2A951EA7BE7FE2D487362EEC1DCB93920B266C5AD39FFA0FC6D4B335B1355A6D8AD3CFE51E9F69C8961A82831BD27F727C9030A816E817783DF89B519D6EC14C9CD88B73FD6152250E229BC6CD8C952777CC5D670051B18F5AFC99860FF7387C5880564703541C2883BC93C5C0EEFA57AF9E9D9D04EAB3BA87782807C37D299789C60C63CC2E86B5610ECA54D3949E17070B1978781F705E32042AFF28FA979979A511C5D14ADD08AFF7DDAE858415D7B0CBA138BF6D1C72C99A9564FE6CB5C9ED554B98D21CB796FC053CAFB4B3E8214F44643C99D9C92EA847A1B6DF3BC21FBF810F9D04B26771BC6DBAD0BDE30265D402E62EEE8ADC84CE8AF0FECBE8F68D13501515B8C28F68AD45D9D1A454904DE944A90C7500049FB74979AE952EBDCBA09DE543283CCA44D3F00EABF99DD714B8FDE3755D30105AC8CBC4569789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411935E2773E3B03C5E4959D9A2F7D55B05B8574768DF40B5EBF76FCAA69F463E0FAFC9F02B01C7B89C1AFB661B43AED07A9D54A6669DCD9022A4EA628CA69577EB1D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE59F8968E30E844A031BC745FED8550EE78B1266A91694B967E66785403F9FDE097DBFF047A171318C43FB2472127512463FA79877B475C7F810D28AE0BA7C5966102673F9F55653D9E546E378D2BB17CD35FAD2F50C5372DF7871B1F1DE78A72FC84F2AD1BACFB45712FB13E3773B3565B021D30A31602528EF16FE6D83795A1A8620E06BE25AAB07A8F3F1EE979687840B7C863D0D8A547A5F7197FB72024DA7F +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-8_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-8_256.rsp new file mode 100644 index 0000000000..405000a405 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_40-8_256.rsp @@ -0,0 +1,12 @@ +pk = 000000150C866CCF8B4C8031FC149A5B5C6C504B1DE97B1C9B8F84B9CE8BCF536E3BC15404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000150000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A0C866CCF8B4C8031FC149A5B5C6C504B1DE97B1C9B8F84B9CE8BCF536E3BC15404562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA24010400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE5900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011420B60C54314ED8291B4F251FF32674EE6A3C3609140380F6B20865B7AE643401000000000001DA6EC89DAF2B01E86C06ABE8043C9A6EA0562A18C49B4A9497D347FAF8EB910002000000000001A0A42481338E08706BAC35F7B5F5D93432D40144F47A0F6790DF4B68525ED740030000000000014A9507DA8B4941DFD3D5E9A02EA050B97F9887A65D93FD8723FDC30C7E2AA4E00400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018BB8E296C7509BC115ABB151E123D4E0343D51087A3A7321FD6406381792A7DA01000000000001166966BACD855719FD325B6CB7EEE8DEC0ABA7479BEEC9A71F451BD9EC1886B002000000000001E480EE1888B362F2F00B536DC0FB57F3AA94097DD543F05D299341633DEFE5FB03000000000001522E3D23E82223C8085779A58B7ECF45EB835F4B8FF5294923C95EEC4FCA5034040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001D10E76AEEA90CDFF9F15085B0834F5C0339E4C86D2CB52C234F6B18B472E8A020100000000000195C0CD14484D08075EDA691EE42CD999A552CA1A62318D9765CADAB553C1C5B90200000000000157A8A577120F2AD134FBF0E0E061E38A768CF935F4D2AA9A541C7A3D033A991503000000000001A467DDA3824B40F0D0D861A12328735CB8C23D1726982BE71F4CF68EEB4925500400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B07C872596E0E48193D8B6513232AE14EC985E19B27E231B2EDA344957695939677A09ECB8C65C93C63C6B08FE5DA691AD51D463012565EAE07805134DE6FD09BA7B3659089DB2B16DAB68A89406E67D63B3F0BC70C271C7D0295293CF5E174FE0609D593810EFAD6CD648BDF6D3253E64DCD6D2FA70FCDCEAF24B7C96A3E3E4B078E1668E5F6CB9A598FA202F0AE1DAD0AFC54BB46BEE1105C69C535390CD63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000151D5FD68390EB99D8038558DDDF270C7B6F86FB6880610C1958EC697B28F07030100000000000110E17383D0E375BD799216DC0666186C133435744D4C0B5160341DE623FB326A02000000000001446011ADFF0A4CDC66D4AD0938159A880A250A728A209F32F3AFA46A2FE4644303000000000001656C05D7A6E564380A829747834E40FABF67FCA7B2388E9EA19CB553E670F39D0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1CBC0EAD4BFBAD01E0651103DD17A534A2CCD00CA53C713F3045B2389B81651E8E2C2B6629D127505EAE2ABD26F2086E9D6BD48CA6FC3BF98F99604F221DC203BCE9D61B756A89BB0B418249889529F7E8F070F35D35E572EFA012DABB16A98D0AC8A99E596A91468A1AAC939629FE780A45D8406B60D04C8E2B31EB7E28294FB2595F4E7071CD906FDFEC3EC3CBB02B03E38AF71EBE9EBCAE3DFC9A37E6B540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FC2D9E83F622B942A7AB522F9BBA979A17180C4905EC5D9373BA8CFB20522714010000000000016319A9C8C78226547F3DCA6A70375F911BE4AE9028FDCCA6D161C5E3698EF41C02000000000001B15AA0B323C0B86CC6F8D84E17A54A6198649F962EADC06CE71C2D0FCE0F3F57030000000000016849136962E7C523775EF2B7BFA1967E4C45FD1B5FA9927D5068CB7045F945F804000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB332A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFE8186E4905539B32F01DF3F0FA65E08B09F4F16719DAE9A987DAC3A28B2B9E001FAAAD0F03810E525D26529CBA1829D42796B65515D55BCD2315DDDB342591BE8E217286002741AD99A1565D106690A5D6277539266747D8632686C5C9061D5119998BAF8B6C09E61D13B2D91426AB98DDECE3EBC2CCA03A8B6591E2A1712FE71F847F486D6E177932521D9196CF0F637314E2329A86F733D95CAA0C2F7F08FA45A993F52B44077712B70116CA4A7DB6587E24BFEB70AFBF3A6F1A33F469D98278A6603810F6664B9BDF27388FA8C69CDD4127B39AD97A6E2432E3C2B6E0087EEBCCC54DA43837F112E61409D225BF5E5222DC107D698C0E571EE8D532C99C6CA353C02F2BC7233F1636D14FAE126DD4433CCBB5DA1C5BD079804FC920E7A7906C9579B18D7B78824CB39614E28A2091D1194C26DFBE86462EE24FA1FE24ACA85F912404458AE8DDCC5B03A0E0402BB689ECE763D0825A8D566713A013923627115705098D63351D22772A01D57BD39566F1EF058044281C3275AAB8C44F905DEA89F9D1ACD8FC3C5E9F2DF429637D635359D0A3D91D765C71E5DA37C2BCF29F1EA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23DDCEBD1114559AAA8C6621F7A7AD11AD19D6312097C99841A84C35772FF6ACF5E1028BD5885C73C78A719FE0D63D52E9F55509B7AEB252865C6720285208786A2439382CD03CA0BFA2FF1A45B734943CA586AAD35DDCFB075538B0850551967EE7D7E1261DEDE7016BAC7E1B447BED75C565A09D3F173B5F9DF4CBD86780F35E9D7D62E54A2FEFFA0FCFC5CBAB99D2F5EF5784EC92C6A9C8DF06FD4491E197B153B084BB9A5F629E4E7923220EA7981AEDC10CCBE387725C16BCD5A4CFFB3566525CB00B5295DEFA64574065D1173DAC40340878BDAED7D71811FF8EB1B55C9E3C8BB8BEB2D011A9D6DBA1522C969314EA2A7FF20000EEFAC8F760CD24975B2CD9D37FFF352B4B13CEC723C68A595E301D02E0FD881D3286582D5472DB230F77C644E02E4FD2118592D323D93CD22E55EDAEC15693758CA10E3F215E6814BC13E2DACC05A226ACAF6DACA3B9EE91B0CD0740A5B50E6E10013407A7AC9A58F2C2D41A8CC0BD39BEB52BB643AA89A1194312A69D6245A1844A03D0EE0BD92C46B5D8EA77927C48D23107C3D498427E8DCEAEAA36E368A58EABA0E06B97532BD8D2B17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A59CAF17D13F6E01699B1ED376095D3F6850ED50053CB56D83A15DF12887CC06E7B45D143CF738881A322557FBAA2381B355638DEC332B690F7A2C91AD96C5102819AC027304301756A1B970378FC0C627135DB8D5F6B0B75316DCF93F0955E37193575DD0C14961D776379DAC58F5FC1150785BBBA92D1009E1B49D7E3362CFA468D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E528FC4BAE4FCB020F4ED5EF4F2A71B9D225F7B7E6655E60877D7B7F3DCFFD8C4C77A3A3B36073A69EEE8B35F49BFA43AEC19ADE9CC7DFBB1F6A7AAFC69B3210DD8B9D2D54268336896CC79F76B441391662909A9261AE1A5D75C4F9C360AB0C19A94F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB11EC281F61A34DC4C3FA81C4C11ABA995BD4EBF44373AB98B000C9F53E39A9E09607A88AAC7AE6A1AB1E735E1D0F8F8D34253718687CFE01212B0B818030EC3F1C8F79574580A44C571456C431C52BA9DD336B1A5F8753263FFBBF6005A7AC41B11814D8CCE8CA7C6B68C4F9A56845611FD6D46C35562176A9E14B357EE8DF2B3F76950986449C0AD69B0BFEF0641CFFEE6CA5112F71E1978592018BE903F66F340EDDDF09089FB1DA7C60F76B3D92527D470E11455137D94A80082FC1AB8DFA33F518E348D50068DC6BFA59015590904AE41CAE8E6A05F2A1296D97077A04DABEC3E27E25173C60F955161EA514178875427F4018AE8CE74578E79E80310F069A611AE281EA56517083EE94B5B37A1493E614AE495D28CC5D8E5A6EA4119FF599BC8DAC4167880FB7EC2FF09007E874ACBF9CAF516CBD6E305EA8492B3FEAF23BC6571A5B800489E07BDB1F2C800BAF3E7D35B4EC997B21A3C29960A9FAA177344E6F9B9C59489A67E782B630D9CB44FB0F82922839403A85C7AD53A9F32D163A64DC226EAA21E0994B218DB931E50BC31C0E1B5651CF2098EB00153DC510E086B1FEB74661932A95116E04BF13E9E302A4CD3783C572CF52249F5FDA51AEE054682E7D3E9BE99FA215853668F015F5F788BC6DE4261C7E53A2FB9B46FAAF6C821BC64ECE7AB00F059A65EA3EA9AC7C64971F504F26D97B48817B3DF9DC46B3C106C041D1A136B4731AA2922B97DEB83A3AD798A719BAA1CC2ADDE4A34D5EA63188A0CFBD3407F3930647C3993848154841EEEAEBCDC2149D942FB644A671D50A1B51ED937765C0C2AAB1B35FC6E4E6DE85E82B4D87727BF30085AD56A27A796F53CB4D3609F07BD7645F7B32EC8B72E51592714D78514941E217E6A8A393F91A907BBEBF9804CAF5925756BB3EB09D32E125469D4413DA437C8BB4CFF2F9C23C6ABA4B90395F55E94E0113E372FDFB37E7801F0AF52AACA367BF4BF90C58D093771AF0991244B91BE5C251F9380444AA86C221D06D0BC12BD1C2DB949E7DB4A5DF1EFA0A4BD339B8F1B937F2AF48072CF8F69E47BC2E20286D2524A59F271852286AF9B8BB57C5FED3E3010743E81629BD1C366D9350DC9329BC839F7B8AD5B7E570C85EF644413F0A6974DA2CE7FD7194C30A43780D5146942339CE2B186698B8CFA564998F0DA458E36F2B66CEDA779C9E9957D987676AD23A507730959ECC0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2A75998AF280055E9105EF6A91BFDF40FC5FD0E6E97EDF27F96872351DD3E8C28F46AAC52365CF914A32E5C21626BE9E13BF80A1E7E616022639DB2A5ED92A119EFF891AF7D33883382B554819C5CBBA093B55E335D550DACD6AFF9DF70A2A92C1BA88F210224F8F1DFF0B420B6C2F673497B86A156F5F1C675D301F55D69E5D275BD43C850F39D321DBC76B0F153EF703DEF0FE7480D5C83EB1535F0FF92A37EB637DC3AB8D7C7965C8517131F5273B10A2B5E64C16C85791D41854E43BD503F0E52180E9C29499C45CE64BD97C0BA486377BFBE1C6EA2A84AE249C8AE40CF3E86989F0379B9D02694DA77F9E73560E0F38AFD05744E0A30FEC0D8DFF8A1CA3A0EC629144E96B590FD5F75D92F40E0FC0A1127486133218B844D932E038CD1B04DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BCA926D661B145AF5B8090D1A4E51D9CBF8818A4EBFC8FF1BD6CF2C76B914B8A7BEE0EB33F37ECA54E2DA3CBC29F1720DBF0A024C969D4B1E36326FB6F63C9195608C68A3D7C87AC394210D0F4CB7D858A88168FCC25B79E29197E2EA3B3D4A862B70A1D7F3251C75F02D476926DD863B778059B83198414E0672AA1F27898C8A6F035D26AA117F838EC83D453A0D5C49AA350B288F1FBCE59D86C8CCC99F14A221AA18A9F300DA266DCF084910890994ABCBD8185D28BAE4CCA4BD68D4D5790FEFBD7A6D56B8C78974F9A8675E6C410F6D5F7F6D254F1C7885F48F0391E1BEEAEC7437553D480FBA79F55DD5B19C596DC2089BCF9980959958F7FB7E6DB0358093379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E6B09F3A309D255D0B7A8B8430F7E9544A881EEB694C7282E20EA3E1ADEA50564B935D528C0372397F26B1497DFA3D0F117F7A6797C1626D1AACEC708302CB0C0E406BEF60B7F6578623EA59A005B804C009A38E0A615F1FEDABBCDA5269C9C48E148A143562E1A372C0DB9D8F249FB5A7ABE5928B4BBB17DBD747A57D9438774BAE2550A5B205FEA96912A2FFE3FBEF1D6DF372A31B1084F0715829C141B845551C086DCF8FB9BEFB43B417AF3426BAF6007DC2EFC3B4999D2A658B5A19CC61FCB3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E608E25F1C4FAED708E98E1D88193FF5DE2D33B178BCD345DAAA3ADEB8B1B6D7C3E9C2468F943A4AF0596B0AA480A159BB882857360DD34CEB848F5CF3481A660F70E49916F9A952B001E60F11A31CEFB39D3F49BF76159FF3E8B3570BBF5D759F5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7E5C5C61EC2EC722ACD680BA597A47ED44E937AA64C0E3523F1EA891BF01E2B92D54EE9A3684A122D33ACD2A6D14133A8DC35EBE37F49D59BB4BB5F24940C18E0B4B5F1349AB813E994AC43DD0420A52527147C9A0F4729F8BCFF0941B934253B98628403937D1E2DEA8BD23A2EDE0A7BCF3A2D66FFC7049C8D2D3D52B4F9479F6652462AC2D18DEBBA361721EF71168CC59501174444B5A2E58AF71E8DFC4E9F836156C1C844EE12FCA65ED97F8189FF34B8EED18C26508B5ABD7DC94DBFD37F18A514F66BEA2AB8F02DFBEF4D54850B589898EBBE0E68E9F864D4468C96BAA0BDF1C074AAF51CD47B20784CDD20DCFC3444802DF292D0B21D32A93F2DCF3154860EE0F469CF0E8BCB4BB474C2C0F6E2F97EE8C155EF5B270FAD06AEB3336087B314915E7CC95153698BC2E486441D1484052BBD641183C9F5495CE45B270E5D085F4DF45707C7615CC89197B2646196A2F382EFBB8436E3B0A09CB2384FA6D3D7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC776AA5DCD1D7D1F191AB56003FCCA1F90F9488AC0C010A6FBCF7CCC51AFC15BA2F9E678B9B2D2B44DE9B7C841C386126135E1871324C9C7D3648DCB8213473E4D006FBDD976D2854DBC257DC1C21E0199C10AA0FADFBFAEE03693930F970285460EAC6BCCDB873F2AE73A173F17CF6C07C26B3FEDC0E81E8EA4FF7D68CAACE34340EF1990F3BF44E23BF65CAC9F65B50E4AB2ED67F01DE310314B56B351691609FD835399C51AD9B35E4118BF3B26AD5DAA9A0609CE6A24C8D2A1244709F770A655DF9E80C0C7441917C8329446EB8FB371C506EADD1DFBF6646E0790637395A2C1429C60252D485BD99EB641F0FBCA951DF3698F69DA2B8E751BB02BA592AEA7DD21E7B961499C0238B93F6AC1FC73DD562C80D39493800D0A0A594F26D16FE54EE71B5AA5CCD70B5F1ABC79687AA87DD986F10FDE0002EF9D964E80940FFC39C5F2FDFB81C190A83B0AAB7BB176476712EDE00F6F97973B9FC6061EB404C24993B85BD7BDB4582903BE253ECC3C10C0B65232F5F681953B179E19D4246B0799477359E0496BE7925D46065E4AC4B5EACFA466A8DB0A62F1D1AD326063C89539BBD517FC53ED562D98D20D8A7CE4FC1404B3BCEC7D500F4573EF14C99BCD70F290E6F4206E9BF9E4052A8DF39BF57BAC1969CB4D85E43FEFC1907449AAD6475CD2A7B9F962C315ED6DCFE913A2FAE5E1A695C5BCBC0568797F5154AAC68A30E0EBB8D2F73E6975440421D001AE2076AD1C65F3ACA6C05144A65D535C89243D6F099CD26C54760517EDB1CE98AB4F9E0B6E3A06B3765D62E7812C38B23D6A92ADC6CAF95A256FB750DBAFAA6D3E937BCA9314331C3EC2BFB571E0D54D3A98D5D28522326681F2B91E5BCF4ED462CC90B4CC27225742E5C2286AD1FFADD8418B9B3FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B5705C3BC66A1916D1424D631E588FCFA838C2BF8BFE2CA2F5F6648E79942E3DA4B064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C479F17E1A29D5B6F18387D15E7AB024AAD60E6D68869726EC117084D8E0C42A3A18FEE5FE427610B9311F4173A555CC3D534439D074BB8153F99EF5C62288F9CD393B0C257FDF1AFA64BB68F3DCE632BF81FDFCFBFF93A4CF99D8D50805B18EDAFD09D086D586BF8A5D6A2026084C7DBDDE343F74C964ED3011E29C8683300EFBD9E93C68EE571CD156D8FE815579D8E5AEDB483103BED689A4CEB7EA73CB8E19A6994A01838E173EFE68E816CA53CE578B87754CB34961D83A611466478E9325529D6D15C156B2E2E06E1F624139D230DD3A32A90AD2C7097F43119E10A2E788F15795548B5470728DDDB77CFD86A6C3C6669B9A2217BC37B15B8EA558D2B9E99EEB37E105700A324FD17A5A00803F41C5317FC2445C7216FE28DD0F15BEF50566BFED945796D4F3DBB97D53204D5BD64478A75484912749D9407C09D01CCDC391BEC54A4D43C9157D0A871195C731EB746F61A3F82D6F1A9807C2BD3B275553AA6CDAAE509A3A350DA3F119521A3DF789E011E59EE8138C17EDFA2AEA5C15841D25DF2E3A1FBEE40A3CD98C275AE4FCAD2708F31D7354E4059D43FC5625858721409E990F1DAE7D7FF6B3084897B817D88A99C149497599957A667750E1CF446F5D24409E3CD2AE7F13197FA6705BFAE8C1BF36AA626D524EC10CC50F77B359D718734797BA0154CBC3CCCD88030C97386483EFFACEBA41E5061B95BEF6324AC98FD576AA2A8D264D05596B20200496C54C58146883B62C9051E5F52224294C996EA6B44F84EE277D029766D66AEA021467747DB5CE0597E5D91D92903B74DEF2A7100BFF8201F70D009B0963454C25351D8D43AF77A3E70C95BA5FF34747F55049243C06C036984C5C303378D475F841749BCB2DDE91A25C105501EEF479F2B6C68A60EB8F1A308E74EDEEF93E1E34A50CB272AC278ED9263C0DAE162B7C1FD035421A2CDA9774ADAF21B292C252B94398DF63894C88C4B5529FC5AA5A18E788D74EB6126C7FDEBE4D650E2871B25F37DB9EA8AB64FD4806121F4509D4FF190439B7A8690A81275D9C03CF2B51832B32DE2967485BF84E915F7BCA7647E09863CA48B37131815DF9E5F5A88535186C40F177A06B657B4437728EFA50AA22C45E49026053B3C2A3C554F1B2613EBE50F27CEBD3BB03C8CA17B22EE76C4200A0E85A70B6DFF7F511FA2265BB7D858556213C48436D573F120D4222BB1A5C924B2EF1605B4A1ED717EFAF63AE53B070D7C62B2F8CFDFFBD18DECB0C405E7575C6AD8CAEF4789D6164039F963F807C3B978CEFE718A83A68378F9156BF52F6A3F76E411CFFD88448BFB452ECC10CE99AE5F5E303EB099B89765A377868B0B2B3A0D631264AEE47BDA8FF3A92483D27CC269B16390B3ACCE3350DAA649AB53B9C1CFF2872B6C1F9BA67D9D22C6FBE01424A7DC815F968C77BE937563456A273992579C8E6AD585A0B3D38AAE13ED13B81D58599A43E86C4B4AE7825B358C6FB94BAD7F552544790377714DFAC7F17B9B6B3BAF2E5D6E87AE0D0769A39A5580D5347C78067D7D7C375A91B066A61E124E754549CF27779D43109D8E167423F13D05093CD1D31B7E6B76A89C6BA817D852775ACA8B385138C6CC73639FDA3AB6FDC5F84CD46DA221B2D437A51B54D43D98E6D77E31B07FF420AA12FD6FA8892C4220AFE432664F946E738DFF89EEBBFC16CB168CE1721738B4A1174265AEB27FF3808A80D3BFB6CB893D1B6B33DC27239E96108C6D0D20C912BC1EBBE7E245056220BE957E7B9D49EEE6C4D341AD73932D304798F0A0F04F31D8F70DB5E06E3ED2DA627D47E0AF1C2E14E56054A87AC9810B617A52D0DB5145FE4C2BF6D0D4AFB0F9314FE15167A5AD0FBA0C1454FBAB0705FB6BBFE5F7E39824E59DA24CC67B3AAD9491E7A40906487BF895E90F63CFE6D7C0984F1D2747676B82D09DFCCD2A8F6DD158C917DB81FDBE6213FE43780DDE17ADB969B3D64CD6BA6EF1F9ECC7D6F6207280078B10DBEBAD7581A2E8C2F83E4AAE8A26F8D1DF0F8CB45C690615EA304E5CE30D2A96C55696C6B1D82D274E9D5765C3E5D2D7D05EC6A202BFD0211B534B7C9FC684C7A72C2D619E9DEC4175477792BB930EB5888FB37198A6E1DCEEE6651038F5C0A15DEDCE6D1833CDA5CE4EE61CC144E7C5202FE532E0B274F2CE4E90D91F2BAF7808D0656D5A106EE157491277F92A36239D1CA7D26150C118F9ABCEDD5470A2A0069AC1BA97ED1CA9885FDF2B6750157AA5B72DB5E7C1140E1FDF78DC7FA04773F4570F4544281C2E9627E5F59CA9740A38B452C9F3A930956187079B4EE4C91B3E3D9F0F502F8558A092630BBA965FD8900E738FD1498FAC10E6AFDF58F32DC0824B405C0E1D962CB213D4D834D7D26199B9172CCA1A36D7A76DA603FE07CE0EB070AFD90E7A30D937A32D26419A002A32AD9043B1735AD3D0696AEDA5F47046F8A3134B8D45C090C0A54C70AE992A0916A49AE7F3006165FBC71CBA5F0611FA5140FC304CF49DF3081CEB754E9E87E4FB637D7E701D930EE23B6E7A739274EC3AEB90736D91745A92DCDC5FAEF42918E63079E07316C2F9E59D8B79062F1D816C536E8323F501A20A11D6FAA241A5CB4A04F8384206C1D4BA5BD2DC0DF41A69CCD6390270FF0451211B36B489AC95476493D812ADE03FD8EA165053401587F7A18C2F3FBF4960C82B30E9C7C30EA830FE7D052DB5A191C0F8DB73833839F0D7AE822027E19C3A899EDBB02AD49EA87E1A2D55EA6B010BD984FC6C5B12289B41264F9F2F23B8761F262598692F57DE1277F48B3EBD06762F791DAC23F5A5846795B4C4806EE0909163CF27111BE948EE0CB673F0B744707BE8189B059F6D33E52AC33BEC99DB223FD42F64BE1C3E8D505592A78D5F7D3E465A5E34C1FC7D7ADD80752A83CA5CFBDD7AE15AFFE7BC0A4BF3722EEC05E54482A88287D9850672C2DCDE120E0C7AF377659E5A3313D0FEAD9B350A80F0A5A4A480346AF02414FAD52E5108B911B7A4B877215E400B3FCD4E8786E962704A50EC2B2D2D7256777111EA6646AE8A57C84B56C30D704C4B914EBFCA60FC07CEE5DB943630C0A2BE448CFD70112A56A74AFEDC4CB48BD579FEE9039DF705869A1623B1596F77D7420B59F32801106F6AD8A16DB40B1ACD82415BBEADE36585C3BB47F37BFA7162C255542E8284D8EF8CFF88DB68A47249DCD14C1D2E8E5C44E258E9BA867902ADCD588A5A382A60A580458C8C59BD5F182742CA1BD6A52F35FAC26893D74C3D74429401712918098CCC493BD226EA8A9F8C7700123924131913453EF8069237ABCC4B851B0A868015162AB8B7B63B3110906B267DCCE5659F4FCA5298C4073BAAF392C5649B429D5E378557D5CA03C9A52B6208936AE2CFF83D7E28A3274398CB3586BEE9694A14396FA1D67BFA90524574B7DCF0E8C7B86C86A69FC0C2263B437016842743E7E1743802C4542DAC8E6A23D03A158BEE47F010F71E5D9A7063E26FE8C40B208160936B5CD4D13ACD22F928352902BF25A8C8D294B493907F6794A4DCC0E7CE621FE45CC6E5F33199D798FC6E833F9EA4EA54FF6A465EACF2EAC6864D3CD0057429D789466CC60CD853B829679FCC639446CB0657C15B869BFDF27AFB572303E17FF826F8C4EE2C747AE330858830F70879FC8FD6F8D7CA2BA986E5D4DA1B613DF88CE09212B99BA77FB3E3AF7AEFD4FACB02B3E3172AD43BA87A4433CE38E45C1DA3ACE463315CF5A87B14CF4745D5282B17B613A033A9FBF52A40D8265B49A49DFFFC6C71377C20F4B3EB43FE7D89D829477619A7E5B2F7CC9FD0299C838419661773087C7BB3573568DB256F94E57423B1AC21C0662B60F526AF49629B7A8F7E833F858E5C7423437ED22E6E704EA66B26E79878EDCE376E8BB682EF83EB4B9600015217C1219224381665C140C78374B80F47511C48B5238937464F3B0A5612D2F1FDCC91B74CD861CE655CBCF22B68F657EB7D8806DDDB03B4F08E52089938121B0F6B3ECDD2D23003C889FD2F9A4F6D3D4358976641511DDF513181B1C86DE10522AC021B6A301249FB9E6DB19DF42C5BA6D53F1FBF9A7A2249C516513522F8702636F688145B52B1FB6172CA96F59B9F845760677D91996B38371DAAC111D6BC59BF28F19B4E00B5E312191087255D008FEE158A8E1619CC0674E12DCAB593EAF6C99C9CBE9C700B498697A725E2F30EA74365F3CD3318AA1D0D7C07DCA4F2F6C3AC8EFF0501F8F65A07363621059517EF1BA27310ED930A1A1B0D4DA322D5FD13EF522D21A3A7D623FC499AB8648C1AA0CE2EF94316B2965A246AD7C8869E9C489AF1FD2DA40E3D688531CF77F083F281E012ECF83C4ADC97B5AE47CC38FDB41C7ECBF402AD42716821AE404A1D224363958B9E71DD4B3E77A16FC80598A3065E8E00F36F2DF940F4E99902A1D62D73470FB4923D3A46EF07E65D02963E1B5308121675F1C1973C656549030DCE1BAE145C7712A4879E2F3E219B72B673243BD71442B699F3A4E366C7B88C1266330282D0D9357FBCEC2F95AE54D87A50C8581597B0C24C2F77763B326A55EE924C4A492307610526A864CCDDF6FFC64321D570589BBC5F9CFBCDD95D0C7AD62DEC853875BA2F3C5E3FC20CFF99FF86539F37EDC56643EF7D70D0025B395061B83A100E1BE1D6096D007DC42082D4E793CCFB79CC5A06242518998D835B32B7E579AA14806AEB8A4F19E554FD72D2899617541C6B86B63AC60BD7B6185A7A86BC7702CCB91069ADA68EB4F117E239BB7A9581A56CAD59A618449EE02E2089CE3A1B97B22AE34BBB421F2194B00B80F1841480577415436FCC20FD60731E6E28138A320C9237FF656A5366890E492A318EFDAB7F22CDF81AE5CE56539034A8790E942E58118A8F141B2FC6E4559A04B9EF8827BB7C11D5A4CDAC22E42660082AEE184078053860369D354552F1CB9D798F3FDF657648A7D5BE4F41E6141FBD80732B6D3AB57C0F60D38848FD33F7E468BF7600E16F25B9552688D3AAE33DA731DFA536059D24AAD21AE940CF31E18A40508DD1623FC89EC11BE4B852EEEFD56C002C1388DCD5C54E0524BB681A25E076CFFF94EA7B5E0A0B7DA1DED8DBE3F9770536FFD43BB48C9E55E33554E5C0411BB823FE16AE3CFE51DFC9177764955DB39B08C627F74A7B9A16DCDCAAB1CC31E37B0D3B90ABA2F1EC00FD2EF6E4FF3A15358C551BACB93EF59361567E0834E72383F4EA2E8F76F000EE38B179F7F0F9A3351C5BFF81B49E8A5119C6CB5CFCF49A6875B3A99CF14E6CBABAC0F4F38FC97CBADE13BB807CEADF726AD565D65334539E879575702D58462BB2A7C7F322A16F3F1C4FE116CEDBA6094EB4712D774B8207189B700C8B84FC7D0DB49B02F7AF17A6270BD75AA54F8A79E4A1A6D588FEDF94C0829EC1496988507C8C5BB87A70DFC3FF6C7F985ED38CF6C23E04FFC8001C2958B5E0920B284A4A3A55023D13D4FB99D392A0F61281E6DE6AD1F907788504F80477B8C21454E4FF16236E42DF95C85E20DEC39B2920ED49AA540BF504E74627B678097B4EC800A37698C32118BFF564BDE9BE0E4B16A3D91A9A83FBE991DD88E7341BA96976F7694323E523B76DFE3C52F28188C8D64DFB1341EAFC98C9A28CE446C4983AC52A1C38F9CC5D8CAAABA4E8BF9B7E45E3521567A46AE5166642E89F8503F892F522A447B2FCB1BCE2EF4EC86E22F48FA99555DC193F080D3F0096A47BE3C2597FE83A27E8132D28EB55AE87B36C93F31A9E371BEF51E405037DBED6CC4916E5A855116586F7C34F33B3EE626DF600644EC881246E32B5716E9580A1733ABCB22346C4414E5FF2C085E2CBFB45BC77168F4164B7CECC874DA5594F6E8D0B7B6B36EDEEDA1342672A4D6925CA2864B93BC7F63994F8449929C3206E086738FADF14B1872973A6093B5916E565DC3B354FC544A44202598AC2326C5EB9F305C448CF68323DE4C5BD28472B340E43DEDCA0DC290CAA47238A7A26713869C6B4237D40EE2743BFCE74E5CADFC183B14075FC8088943F3B2E93FD3A96ACA364B9292413B2B67B43C855A898F877683FFA238C05E6F789ACCCC40C434FFFA494F2710C3DFA213DA7B56D5A4C273603ECE648F3E9D6E + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 18469 +sm = 00000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E651324F8D245291EFF735334671EFFD85F3A823D972D2D49DF408A2AE09590B2477731B03EA3F8D0196A27D1C42405953F3CAD196E2AF5F897CB89A61F544FAD4AAC5D5560820714B57DEE68B1FC7BC9320D4E9ED476C79C8257B34570798C59A944B9F2B22F2D9419B5B5DB6301DDEA449F184552E9EF0F4B80893CE0D38184D0F8F2424E5B39E783D8CF5D3E40F8B822A5CB770E7C793EF70EC55F2DB527489D8E83842D91853C8E1A4E123A8BAA85CDC3BEF892DB683E3CFB4D60DF60CF4705644534E0F86ADE3417BE364CACDF76C0C906F64BD58A7B363C52870995A9DDE6826811C4DD77FD89B17FB35E2EA7C907A056063335AE03884B54E791EFC5B6855C6DD4C888FD4C8BDEF806EB73B632B3C27697F2410935EBD0B4EB7D4FE85D94F4EE29447A8424917FD3EBBE24F5128280697659EBE4569087D96AD8F0AC7B632EEDC65E0D807DEF82C028FF4DD9B179B761A6BBA1DD80F395A524036A7D50A786294AF71A1CC7783E789CA5E8DE21B1E3F771C5E9A256A2D0D12F911285E9F3BA26B80AF62D1328351A6E0045A82BFCEB153B0F6B8FD5AE3B2056006C5EAA1773CEEF4C7B3AD10BC12FDEA7DCC1891BCBDC9CD83ABD7DE6012ED3F07F1CE670B7C50EC84D8C0000D09632545965D732E921D01DAE77512180C12B01A2791BD0A32F4705C98818ACAC9A62F3421985687FC5107199B035FFCFFF5103D7B169AD346BCCD523B98475B92F9EE6DD954A6534913AD07DB45E620589AAE5F70A7B20F37D62442F711363C3AFF1F571B2A6471E08DB2CECF405676A1B73B7D768543B818B7E31A574796497C2AD22C79CDFF65DE6D4E12F165710A69D1474BC7FB5E34D64263543B02918CDFA271F53EB8B07A9859107D88153FD989ECAEF350E5F8572280261A6EBB9AE8A0D3777BE70BBA24CD737407541AEFF0EEA79C1FC0E73F167DE9D2380AB6D5B0807DE6032472D838B3F681E7ACBC75D71426F33ED97C7968EFB4FCE7D560363BC9F3A5A0086D87169AAB81B9736674E598CB301F84E7F0DBAE6B747B79B8F437746C713E1FBFA24DA920A4F3F3E92E914C271E3EA483D6BD7A4880B86A916605F059916F9D115C41A1BFE270D0C39D3C48B44ED9056712E0DA6F355D31666557247B6BB8AB41EA0201599F1EB9441E4B23284B8BE53B6BBBACF025A2BF597FCAE269E8B86FE4755B4692E0179281ACF62EBE8CD644B11159E35F94A4492867F7A94B9CBA5348F7071C5732563F8C1C008AD8C1767EC2D2A1C5F71AF0F2B8A6A8F9C2E4C8BBEA834A94F34114CEE3ED19E514449946DAEF5C58F3B2270A78E69A252FE4837E7E94DAD4842E9028DD986E5AAD6A8F16F9F138220F5672F8BEF56252D8E93E693A43FFC9AE96ED514D7405F080AC39BE1BC1E7052026B1FB0D65335FB7CBDE8E0EAAA2E29F28846C562EB741204CA105FACEE149ED361E30C807C308875164B475E46CC14E278D7C129F0D909E2C06D5CDA83303D57841E55DBA04C02702E226161DE69093472D07A2408DD87057A1E25D363CCF0B32025BF24DCBF54A0F54D62D6CFC870BBBCBFFFD1AF85A1EEE4532928FF130814E363AA0FD5ABB68BE0BC2CE6D0EB362BE0C106A017196F1295969EDB23739D139D5E629140BE6778F0C912343373F637A516E029047FCCECD7C99A59681772B981C48A3005D5F95D4EFCD6B17FA570122F2A68AC1E9EB11934578DD965D4FA0ECC39C94887E71903538BE9408E8DD1AF757ABC63097ED308C7F0EDF78E138ABA2002AE12DD317205ABE4FA332FDDFB4AAE669A71A0A6A402D3E8DB7E409A5FBEA41C86474057F5D46ACF35032AC331BC0F33FF002D23A7ED791C642D202019E62520710B50C76A82229A1075E52F918DB230C481D0350A33EA0E6C8A2C4672459266931B482AAAC2ACBB4542B22D3D25E2E279700167CD7AF03866E60CAA9A880DE5055A80E48A4EDC261C705EBECE13DF4F9AE7D8E33016A83B6A05DEEC44A0F6C123B8CF162E2814638BE4E22E8C65A8E9B2C6593EF39B915A86C7D43CBCAD6F5857BAAE18071F291C3D742C9FF3FC54A51D1CB8061D5A0ED4358E82CF93CA9750450352C4326F2B9B20F3D091528FD46A0ED40077C79EA0B12E70EC73A8CABF27E1CC7B33448B947CD339BDFFC9F377952D6249911F099F535E6FFB0A6AD85F5CD06E4B59918DDA9C1EA1356480AB1D7254B2AAEEFBDC3AE61F99552873CD0EA39D3A2527B72BF325B02D5A8AD1B50320FD2513D89D1A164F5F8E7C034CBD4718AE2C9C6D2839C144C47418636455CA4B9E674B3296AEDBD92C793091C4EB95FCB9EEC69656DBF47ACD54F0045644E95BC75168F17C797F9E54C420F05C6E45A5DA109F6A0EFB313ACBA155CB69F94F21439FAA4821B43A1CAC7172BCE8E0D611E1C6993589B529400771332F16F123352198A4D6872CF63F4401ACB9B5299A74E06FA83EA57797B29DC131C00B7E475927AA0970648E69CEE30ECF7D7D4162727D1A252794C85BE791A4DA538EF8B855182EAB0A724E0E68601A10D9809A6799A6E7B2DDB84AC602BF3CF936E171E16F5B4EE3BB6F1F8D70A121E76910CCDD79F252D4FA6DB1D4FA2AFF6D1F4A0246688F24B24114E97C1B758F96C485A679499AC15C89843802B844E9E5A280057C9A5DCE4D75B14DCB8CF4475E4619DE0734946BF920F58EA7C967CD268E287E9D1F8DCE855F5FCFBFEC88A8D7ECDED07030F6A3CF16B95CA2CA5635B17418D411C233930DB488CA4F7E287B255DA30A254D0B3C2EF633F5E04CDB10A20311D2846AB24749D78FAB6EC47F89E66A1A60777897D0636344B4A3A6D4B891BC5E066A422AD6CB0514D1E9D70888593A386048112071548CF0A71C9991DBB3A11D93483E3716D9A8BAAF62BC5BB58B991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA6E323ED6E8A520C761F371CF760445A3E865E4B2524DEC48F47386A1E6CE55612DDC33FADFE21A034F29F62E5EF6C502CEC5014A10A68A2DCD1998C74D620E84F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D265894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB96557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB3357F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B82A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFED92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE598186E4905539B32F01DF3F0FA65E08B09F4F16719DAE9A987DAC3A28B2B9E001FAAAD0F03810E525D26529CBA1829D42796B65515D55BCD2315DDDB342591BE8E217286002741AD99A1565D106690A5D6277539266747D8632686C5C9061D5119998BAF8B6C09E61D13B2D91426AB98DDECE3EBC2CCA03A8B6591E2A1712FE71F847F486D6E177932521D9196CF0F637314E2329A86F733D95CAA0C2F7F08FA45A993F52B44077712B70116CA4A7DB6587E24BFEB70AFBF3A6F1A33F469D98278A6603810F6664B9BDF27388FA8C69CDD4127B39AD97A6E2432E3C2B6E0087EEBCCC54DA43837F112E61409D225BF5E5222DC107D698C0E571EE8D532C99C6CA353C02F2BC7233F1636D14FAE126DD4433CCBB5DA1C5BD079804FC920E7A7906C9579B18D7B78824CB39614E28A2091D1194C26DFBE86462EE24FA1FE24ACA85F912404458AE8DDCC5B03A0E0402BB689ECE763D0825A8D566713A013923627115705098D63351D22772A01D57BD39566F1EF058044281C3275AAB8C44F905DEA89F9D1ACD8FC3C5E9F2DF429637D635359D0A3D91D765C71E5DA37C2BCF29F1EA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23DDCEBD1114559AAA8C6621F7A7AD11AD19D6312097C99841A84C35772FF6ACF5E1028BD5885C73C78A719FE0D63D52E9F55509B7AEB252865C6720285208786A2439382CD03CA0BFA2FF1A45B734943CA586AAD35DDCFB075538B0850551967EE7D7E1261DEDE7016BAC7E1B447BED75C565A09D3F173B5F9DF4CBD86780F35E9D7D62E54A2FEFFA0FCFC5CBAB99D2F5EF5784EC92C6A9C8DF06FD4491E197B153B084BB9A5F629E4E7923220EA7981AEDC10CCBE387725C16BCD5A4CFFB3566525CB00B5295DEFA64574065D1173DAC40340878BDAED7D71811FF8EB1B55C9E3C8BB8BEB2D011A9D6DBA1522C969314EA2A7FF20000EEFAC8F760CD24975B2CD9D37FFF352B4B13CEC723C68A595E301D02E0FD881D3286582D5472DB230F77C644E02E4FD2118592D323D93CD22E55EDAEC15693758CA10E3F215E6814BC13E2DACC05A226ACAF6DACA3B9EE91B0CD0740A5B50E6E10013407A7AC9A58F2C2D41A8CC0BD39BEB52BB643AA89A1194312A69D6245A1844A03D0EE0BD92C46B5D8EA77927C48D23107C3D498427E8DCEAEAA36E368A58EABA0E06B97532BD8D2B17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A59CAF17D13F6E01699B1ED376095D3F6850ED50053CB56D83A15DF12887CC06E7B45D143CF738881A322557FBAA2381B355638DEC332B690F7A2C91AD96C5102819AC027304301756A1B970378FC0C627135DB8D5F6B0B75316DCF93F0955E37193575DD0C14961D776379DAC58F5FC1150785BBBA92D1009E1B49D7E3362CFA468D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E528FC4BAE4FCB020F4ED5EF4F2A71B9D225F7B7E6655E60877D7B7F3DCFFD8C4C77A3A3B36073A69EEE8B35F49BFA43AEC19ADE9CC7DFBB1F6A7AAFC69B3210DD8B9D2D54268336896CC79F76B441391662909A9261AE1A5D75C4F9C360AB0C19A94F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB11EC281F61A34DC4C3FA81C4C11ABA995BD4EBF44373AB98B000C9F53E39A9E09607A88AAC7AE6A1AB1E735E1D0F8F8D34253718687CFE01212B0B818030EC3F1C8F79574580A44C571456C431C52BA9DD336B1A5F8753263FFBBF6005A7AC41B11814D8CCE8CA7C6B68C4F9A56845611FD6D46C35562176A9E14B357EE8DF2B3F76950986449C0AD69B0BFEF0641CFFEE6CA5112F71E1978592018BE903F66F340EDDDF09089FB1DA7C60F76B3D92527D470E11455137D94A80082FC1AB8DFA33F518E348D50068DC6BFA59015590904AE41CAE8E6A05F2A1296D97077A04DABEC3E27E25173C60F955161EA514178875427F4018AE8CE74578E79E80310F069A611AE281EA56517083EE94B5B37A1493E614AE495D28CC5D8E5A6EA4119FF599BC8DAC4167880FB7EC2FF09007E874ACBF9CAF516CBD6E305EA8492B3FEAF23BC6571A5B800489E07BDB1F2C800BAF3E7D35B4EC997B21A3C29960A9FAA177344E6F9B9C59489A67E782B630D9CB44FB0F82922839403A85C7AD53A9F32D163A64DC226EAA21E0994B218DB931E50BC31C0E1B5651CF2098EB00153DC510E086B1FEB74661932A95116E04BF13E9E302A4CD3783C572CF52249F5FDA51AEE054682E7D3E9BE99FA215853668F015F5F788BC6DE4261C7E53A2FB9B46FAAF6C821BC64ECE7AB00F059A65EA3EA9AC7C64971F504F26D97B48817B3DF9DC46B3C106C041D1A136B4731AA2922B97DEB83A3AD798A719BAA1CC2ADDE4A34D5EA63188A0CFBD3407F3930647C3993848154841EEEAEBCDC2149D942FB644A671D50A1B51ED937765C0C2AAB1B35FC6E4E6DE85E82B4D87727BF30085AD56A27A796F53CB4D3609F07BD7645F7B32EC8B72E51592714D78514941E217E6A8A393F91A907BBEBF9804CAF5925756BB3EB09D32E125469D4413DA437C8BB4CFF2F9C23C6ABA4B90395F55E94E0113E372FDFB37E7801F0AF52AACA367BF4BF90C58D093771AF0991244B91BE5C251F9380444AA86C221D06D0BC12BD1C2DB949E7DB4A5DF1EFA0A4BD339B8F1B937F2AF48072CF8F69E47BC2E20286D2524A59F271852286AF9B8BB57C5FED3E3010743E81629BD1C366D9350DC9329BC839F7B8AD5B7E570C85EF644413F0A6974DA2CE7FD7194C30A43780D5146942339CE2B186698B8CFA564998F0DA458E36F2B66CEDA779C9E9957D987676AD23A507730959ECC0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2A75998AF280055E9105EF6A91BFDF40FC5FD0E6E97EDF27F96872351DD3E8C28F46AAC52365CF914A32E5C21626BE9E13BF80A1E7E616022639DB2A5ED92A119164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F4EFF891AF7D33883382B554819C5CBBA093B55E335D550DACD6AFF9DF70A2A92C1BA88F210224F8F1DFF0B420B6C2F673497B86A156F5F1C675D301F55D69E5D275BD43C850F39D321DBC76B0F153EF703DEF0FE7480D5C83EB1535F0FF92A37EB637DC3AB8D7C7965C8517131F5273B10A2B5E64C16C85791D41854E43BD503F0E52180E9C29499C45CE64BD97C0BA486377BFBE1C6EA2A84AE249C8AE40CF3E86989F0379B9D02694DA77F9E73560E0F38AFD05744E0A30FEC0D8DFF8A1CA3A0EC629144E96B590FD5F75D92F40E0FC0A1127486133218B844D932E038CD1B04DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BCA926D661B145AF5B8090D1A4E51D9CBF8818A4EBFC8FF1BD6CF2C76B914B8A7BEE0EB33F37ECA54E2DA3CBC29F1720DBF0A024C969D4B1E36326FB6F63C9195608C68A3D7C87AC394210D0F4CB7D858A88168FCC25B79E29197E2EA3B3D4A862B70A1D7F3251C75F02D476926DD863B778059B83198414E0672AA1F27898C8A6F035D26AA117F838EC83D453A0D5C49AA350B288F1FBCE59D86C8CCC99F14A221AA18A9F300DA266DCF084910890994ABCBD8185D28BAE4CCA4BD68D4D5790FEFBD7A6D56B8C78974F9A8675E6C410F6D5F7F6D254F1C7885F48F0391E1BEEAEC7437553D480FBA79F55DD5B19C596DC2089BCF9980959958F7FB7E6DB0358093379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E6B09F3A309D255D0B7A8B8430F7E9544A881EEB694C7282E20EA3E1ADEA50564B935D528C0372397F26B1497DFA3D0F117F7A6797C1626D1AACEC708302CB0C0E406BEF60B7F6578623EA59A005B804C009A38E0A615F1FEDABBCDA5269C9C48E148A143562E1A372C0DB9D8F249FB5A7ABE5928B4BBB17DBD747A57D9438774BAE2550A5B205FEA96912A2FFE3FBEF1D6DF372A31B1084F0715829C141B845551C086DCF8FB9BEFB43B417AF3426BAF6007DC2EFC3B4999D2A658B5A19CC61FCB3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E608E25F1C4FAED708E98E1D88193FF5DE2D33B178BCD345DAAA3ADEB8B1B6D7C3E9C2468F943A4AF0596B0AA480A159BB882857360DD34CEB848F5CF3481A660F70E49916F9A952B001E60F11A31CEFB39D3F49BF76159FF3E8B3570BBF5D759F5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7E5C5C61EC2EC722ACD680BA597A47ED44E937AA64C0E3523F1EA891BF01E2B92D54EE9A3684A122D33ACD2A6D14133A8DC35EBE37F49D59BB4BB5F24940C18E0B4B5F1349AB813E994AC43DD0420A52527147C9A0F4729F8BCFF0941B934253B98628403937D1E2DEA8BD23A2EDE0A7BCF3A2D66FFC7049C8D2D3D52B4F9479F6652462AC2D18DEBBA361721EF71168CC59501174444B5A2E58AF71E8DFC4E9F836156C1C844EE12FCA65ED97F8189FF34B8EED18C26508B5ABD7DC94DBFD37F18A514F66BEA2AB8F02DFBEF4D54850B589898EBBE0E68E9F864D4468C96BAA0BDF1C074AAF51CD47B20784CDD20DCFC3444802DF292D0B21D32A93F2DCF3154860EE0F469CF0E8BCB4BB474C2C0F6E2F97EE8C155EF5B270FAD06AEB3336087B314915E7CC95153698BC2E486441D1484052BBD641183C9F5495CE45B270E5D085F4DF45707C7615CC89197B2646196A2F382EFBB8436E3B0A09CB2384FA6D3D7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC776AA5DCD1D7D1F191AB56003FCCA1F90F9488AC0C010A6FBCF7CCC51AFC15BA2F9E678B9B2D2B44DE9B7C841C386126135E1871324C9C7D3648DCB8213473E4D006FBDD976D2854DBC257DC1C21E0199C10AA0FADFBFAEE03693930F970285460EAC6BCCDB873F2AE73A173F17CF6C07C26B3FEDC0E81E8EA4FF7D68CAACE34340EF1990F3BF44E23BF65CAC9F65B50E4AB2ED67F01DE310314B56B351691609FD835399C51AD9B35E4118BF3B26AD5DAA9A0609CE6A24C8D2A1244709F770A655DF9E80C0C7441917C8329446EB8FB371C506EADD1DFBF6646E0790637395A2C1429C60252D485BD99EB641F0FBCA951DF3698F69DA2B8E751BB02BA592AEA7DD21E7B961499C0238B93F6AC1FC73DD562C80D39493800D0A0A594F26D16FE54EE71B5AA5CCD70B5F1ABC79687AA87DD986F10FDE0002EF9D964E80940FFC39C5F2FDFB81C190A83B0AAB7BB176476712EDE00F6F97973B9FC6061EB404C24993B85BD7BDB4582903BE253ECC3C10C0B65232F5F681953B179E19D4246B0799477359E0496BE7925D46065E4AC4B5EACFA466A8DB0A62F1D1AD326063C89539BBD517FC53ED562D98D20D8A7CE4FC1404B3BCEC7D500F4573EF14C99BCD70F290E6F4206E9BF9E4052A8DF39BF57BAC1969CB4D85E43FEFC1907449AAD6475CD2A7B9F962C315ED6DCFE913A2FAE5E1A695C5BCBC0568797F5154AAC68A30E0EBB8D2F73E6975440421D001AE2076AD1C65F3ACA6C05144A65D535C89243D6F099CD26C54760517EDB1CE98AB4F9E0B6E3A06B3765D62E7812C38B23D6A92ADC6CAF95A256FB750DBAFAA6D3E937BCA9314331C3EC2BFB571E0D54D3A98D5D28522326681F2B91E5BCF4ED462CC90B4CC27225742E5C2286AD1FFADD8418B9B3FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B5705C3BC66A1916D1424D631E588FCFA838C2BF8BFE2CA2F5F6648E79942E3DA4B064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C479F17E1A29D5B6F18387D15E7AB024AAD60E6D68869726EC117084D8E0C42A3A96F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B18FEE5FE427610B9311F4173A555CC3D534439D074BB8153F99EF5C62288F9CD393B0C257FDF1AFA64BB68F3DCE632BF81FDFCFBFF93A4CF99D8D50805B18EDAFD09D086D586BF8A5D6A2026084C7DBDDE343F74C964ED3011E29C8683300EFBD9E93C68EE571CD156D8FE815579D8E5AEDB483103BED689A4CEB7EA73CB8E19A6994A01838E173EFE68E816CA53CE578B87754CB34961D83A611466478E9325529D6D15C156B2E2E06E1F624139D230DD3A32A90AD2C7097F43119E10A2E788F15795548B5470728DDDB77CFD86A6C3C6669B9A2217BC37B15B8EA558D2B9E99EEB37E105700A324FD17A5A00803F41C5317FC2445C7216FE28DD0F15BEF50566BFED945796D4F3DBB97D53204D5BD64478A75484912749D9407C09D01CCDC391BEC54A4D43C9157D0A871195C731EB746F61A3F82D6F1A9807C2BD3B275553AA6CDAAE509A3A350DA3F119521A3DF789E011E59EE8138C17EDFA2AEA5C15841D25DF2E3A1FBEE40A3CD98C275AE4FCAD2708F31D7354E4059D43FC5625858721409E990F1DAE7D7FF6B3084897B817D88A99C149497599957A667750E1CF446F5D24409E3CD2AE7F13197FA6705BFAE8C1BF36AA626D524EC10CC50F77B359D718734797BA0154CBC3CCCD88030C97386483EFFACEBA41E5061B95BEF6324AC98FD576AA2A8D264D05596B20200496C54C58146883B62C9051E5F52224294C996EA6B44F84EE277D029766D66AEA021467747DB5CE0597E5D91D92903B74DEF2A7100BFF8201F70D009B0963454C25351D8D43AF77A3E70C95BA5FF34747F55049243C06C036984C5C303378D475F841749BCB2DDE91A25C105501EEF479F2B6C68A60EB8F1A308E74EDEEF93E1E34A50CB272AC278ED9263C0DAE162B7C1FD035421A2CDA9774ADAF21B292C252B94398DF63894C88C4B5529FC5AA5A18E788D74EB6126C7FDEBE4D650E2871B25F37DB9EA8AB64FD4806121F4509D4FF190439B7A8690A81275D9C03CF2B51832B32DE2967485BF84E915F7BCA7647E09863CA48B37131815DF9E5F5A88535186C40F177A06B657B4437728EFA50AA22C45E49026053B3C2A3C554F1B2613EBE50F27CEBD3BB03C8CA17B22EE76C4200A0E85A70B6DFF7F511FA2265BB7D858556213C48436D573F120D4222BB1A5C924B2EF1605B4A1ED717EFAF63AE53B070D7C62B2F8CFDFFBD18DECB0C405E7575C6AD8CAEF4789D6164039F963F807C3B978CEFE718A83A68378F9156BF52F6A3F76E411CFFD88448BFB452ECC10CE99AE5F5E303EB099B89765A377868B0B2B3A0D631264AEE47BDA8FF3A92483D27CC269B16390B3ACCE3350DAA649AB53B9C1CFF2872B6C1F9BA67D9D22C6FBE01424A7DC815F968C77BE937563456A273992579C8E6AD585A0B3D38AAE13ED13B81D58599A43E86C4B4AE7825B358C6FB94BAD7F552544790377714DFAC7F17B9B6B3BAF2E5D6E87AE0D0769A39A5580D5347C78067D7D7C375A91B066A61E124E754549CF27779D43109D8E167423F13D05093CD1D31B7E6B76A89C6BA817D852775ACA8B385138C6CC73639FDA3AB6FDC5F84CD46DA221B2D437A51B54D43D98E6D77E31B07FF420AA12FD6FA8892C4220AFE432664F946E738DFF89EEBBFC16CB168CE1721738B4A1174265AEB27FF3808A80D3BFB6CB893D1B6B33DC27239E96108C6D0D20C912BC1EBBE7E245056220BE957E7B9D49EEE6C4D341AD73932D304798F0A0F04F31D8F70DB5E06E3ED2DA627D47E0AF1C2E14E56054A87AC9810B617A52D0DB5145FE4C2BF6D0D4AFB0F9314FE15167A5AD0FBA0C1454FBAB0705FB6BBFE5F7E39824E59DA24CC67B3AAD9491E7A40906487BF895E90F63CFE6D7C0984F1D2747676B82D09DFCCD2A8F6DD158C917DB81FDBE6213FE43780DDE17ADB969B3D64CD6BA6EF1F9ECC7D6F6207280078B10DBEBAD7581A2E8C2F83E4AAE8A26F8D1DF0F8CB45C690615EA304E5CE30D2A96C55696C6B1D82D274E9D5765C3E5D2D7D05EC6A202BFD0211B534B7C9FC684C7A72C2D619E9DEC4175477792BB930EB5888FB37198A6E1DCEEE6651038F5C0A15DEDCE6D1833CDA5CE4EE61CC144E7C5202FE532E0B274F2CE4E90D91F2BAF7808D0656D5A106EE157491277F92A36239D1CA7D26150C118F9ABCEDD5470A2A0069AC1BA97ED1CA9885FDF2B6750157AA5B72DB5E7C1140E1FDF78DC7FA04773F4570F4544281C2E9627E5F59CA9740A38B452C9F3A930956187079B4EE4C91B3E3D9F0F502F8558A092630BBA965FD8900E738FD1498FAC10E6AFDF58F32DC0824B405C0E1D962CB213D4D834D7D26199B9172CCA1A36D7A76DA603FE07CE0EB070AFD90E7A30D937A32D26419A002A32AD9043B1735AD3D0696AEDA5F47046F8A3134B8D45C090C0A54C70AE992A0916A49AE7F3006165FBC71CBA5F0611FA5140FC304CF49DF3081CEB754E9E87E4FB637D7E701D930EE23B6E7A739274EC3AEB90736D91745A92DCDC5FAEF42918E63079E07316C2F9E59D8B79062F1D816C536E8323F501A20A11D6FAA241A5CB4A04F8384206C1D4BA5BD2DC0DF41A69CCD6390270FF0451211B36B489AC95476493D812ADE03FD8EA165053401587F7A18C2F3FBF4960C82B30E9C7C30EA830FE7D052DB5A191C0F8DB73833839F0D7AE822027E19C3A899EDBB02AD49EA87E1A2D55EA6B010BD984FC6C5B12289B41264F9F2F23B8761F262598692F57DE1277F48B3EBD06762F791DAC23F5A5846795B4C4806EE0909163CF27111BE948EE0CB673F0B744707BE8189B059F6D33E52AC33BEC99DB223FD42F64BE1C3E8D505592A78D5F7D3E465A5E34C1FC7D7ADD80752A83CA5CFBDD7AE15AFFE7BC0A4BF3722EEC05E54482A88287D9850672C2DCDE120E0C7AF377659E5A3313D0FEAD9B350A80F0A5A4A480346AF02414FAD52E5108B911B7A4B877215E400B3FCD4E8786E962704A50EC2B2D2D7256777111EA6646AE8A57C84B56C30D704C4B914EBFCA60FC07CEE5DB943630CB07C872596E0E48193D8B6513232AE14EC985E19B27E231B2EDA344957695939677A09ECB8C65C93C63C6B08FE5DA691AD51D463012565EAE07805134DE6FD09BA7B3659089DB2B16DAB68A89406E67D63B3F0BC70C271C7D0295293CF5E174FE0609D593810EFAD6CD648BDF6D3253E64DCD6D2FA70FCDCEAF24B7C96A3E3E4B078E1668E5F6CB9A598FA202F0AE1DAD0AFC54BB46BEE1105C69C535390CD630A2BE448CFD70112A56A74AFEDC4CB48BD579FEE9039DF705869A1623B1596F77D7420B59F32801106F6AD8A16DB40B1ACD82415BBEADE36585C3BB47F37BFA7162C255542E8284D8EF8CFF88DB68A47249DCD14C1D2E8E5C44E258E9BA867902ADCD588A5A382A60A580458C8C59BD5F182742CA1BD6A52F35FAC26893D74C3D74429401712918098CCC493BD226EA8A9F8C7700123924131913453EF8069237ABCC4B851B0A868015162AB8B7B63B3110906B267DCCE5659F4FCA5298C4073BAAF392C5649B429D5E378557D5CA03C9A52B6208936AE2CFF83D7E28A3274398CB3586BEE9694A14396FA1D67BFA90524574B7DCF0E8C7B86C86A69FC0C2263B437016842743E7E1743802C4542DAC8E6A23D03A158BEE47F010F71E5D9A7063E26FE8C40B208160936B5CD4D13ACD22F928352902BF25A8C8D294B493907F6794A4DCC0E7CE621FE45CC6E5F33199D798FC6E833F9EA4EA54FF6A465EACF2EAC6864D3CD0057429D789466CC60CD853B829679FCC639446CB0657C15B869BFDF27AFB572303E17FF826F8C4EE2C747AE330858830F70879FC8FD6F8D7CA2BA986E5D4DA1B613DF88CE09212B99BA77FB3E3AF7AEFD4FACB02B3E3172AD43BA87A4433CE38E45C1DA3ACE463315CF5A87B14CF4745D5282B17B613A033A9FBF52A40D8265B49A49DFFFC6C71377C20F4B3EB43FE7D89D829477619A7E5B2F7CC9FD0299C838419661773087C7BB3573568DB256F94E57423B1AC21C0662B60F526AF49629B7A8F7E833F858E5C7423437ED22E6E704EA66B26E79878EDCE376E8BB682EF83EB4B9600015217C1219224381665C140C78374B80F47511C48B5238937464F3B0A5612D2F1FDCC91B74CD861CE655CBCF22B68F657EB7D8806DDDB03B4F08E52089938121B0F6B3ECDD2D23003C889FD2F9A4F6D3D4358976641511DDF513181B1C86DE10522AC021B6A301249FB9E6DB19DF42C5BA6D53F1FBF9A7A2249C516513522F8702636F688145B52B1FB6172CA96F59B9F845760677D91996B38371DAAC111D6BC59BF28F19B4E00B5E312191087255D008FEE158A8E1619CC0674E12DCAB593EAF6C99C9CBE9C700B498697A725E2F30EA74365F3CD3318AA1D0D7C07DCA4F2F6C3AC8EFF0501F8F65A07363621059517EF1BA27310ED930A1A1B0D4DA322D5FD13EF522D21A3A7D623FC499AB8648C1AA0CE2EF94316B2965A246AD7C8869E9C489AF1FD2DA40E3D688531CF77F083F281E012ECF83C4ADC97B5AE47CC38FDB41C7ECBF402AD42716821AE404A1D224363958B9E71DD4B3E77A16FC80598A3065E8E00F36F2DF940F4E99902A1D62D73470FB4923D3A46EF07E65D02963E1B5308121675F1C1973C656549030DCE1BAE145C7712A4879E2F3E219B72B673243BD71442B699F3A4E366C7B88C1266330282D0D9357FBCEC2F95AE54D87A50C8581597B0C24C2F77763B326A55EE924C4A492307610526A864CCDDF6FFC64321D570589BBC5F9CFBCDD95D0C7AD62DEC853875BA2F3C5E3FC20CFF99FF86539F37EDC56643EF7D70D0025B395061B83A100E1BE1D6096D007DC42082D4E793CCFB79CC5A06242518998D835B32B7E579AA14806AEB8A4F19E554FD72D2899617541C6B86B63AC60BD7B6185A7A86BC7702CCB91069ADA68EB4F117E239BB7A9581A56CAD59A618449EE02E2089CE3A1B97B22AE34BBB421F2194B00B80F1841480577415436FCC20FD60731E6E28138A320C9237FF656A5366890E492A318EFDAB7F22CDF81AE5CE56539034A8790E942E58118A8F141B2FC6E4559A04B9EF8827BB7C11D5A4CDAC22E42660082AEE184078053860369D354552F1CB9D798F3FDF657648A7D5BE4F41E6141FBD80732B6D3AB57C0F60D38848FD33F7E468BF7600E16F25B9552688D3AAE33DA731DFA536059D24AAD21AE940CF31E18A40508DD1623FC89EC11BE4B852EEEFD56C002C1388DCD5C54E0524BB681A25E076CFFF94EA7B5E0A0B7DA1DED8DBE3F9770536FFD43BB48C9E55E33554E5C0411BB823FE16AE3CFE51DFC9177764955DB39B08C627F74A7B9A16DCDCAAB1CC31E37B0D3B90ABA2F1EC00FD2EF6E4FF3A15358C551BACB93EF59361567E0834E72383F4EA2E8F76F000EE38B179F7F0F9A3351C5BFF81B49E8A5119C6CB5CFCF49A6875B3A99CF14E6CBABAC0F4F38FC97CBADE13BB807CEADF726AD565D65334539E879575702D58462BB2A7C7F322A16F3F1C4FE116CEDBA6094EB4712D774B8207189B700C8B84FC7D0DB49B02F7AF17A6270BD75AA54F8A79E4A1A6D588FEDF94C0829EC1496988507C8C5BB87A70DFC3FF6C7F985ED38CF6C23E04FFC8001C2958B5E0920B284A4A3A55023D13D4FB99D392A0F61281E6DE6AD1F907788504F80477B8C21454E4FF16236E42DF95C85E20DEC39B2920ED49AA540BF504E74627B678097B4EC800A37698C32118BFF564BDE9BE0E4B16A3D91A9A83FBE991DD88E7341BA96976F7694323E523B76DFE3C52F28188C8D64DFB1341EAFC98C9A28CE446C4983AC52A1C38F9CC5D8CAAABA4E8BF9B7E45E3521567A46AE5166642E89F8503F892F522A447B2FCB1BCE2EF4EC86E22F48FA99555DC193F080D3F0096A47BE3C2597FE83A27E8132D28EB55AE87B36C93F31A9E371BEF51E405037DBED6CC4916E5A855116586F7C34F33B3EE626DF600644EC881246E32B5716E9580A1733ABCB22346C4414E5FF2C085E2CBFB45BC77168F4164B7CECC874DA5594F6E8D0B7B6B36EDEEDA1342672A4D6925CA2864B93BC7F63994F8449929C3206E086738FADF14B1872973A6093B5916E565DC3B354FC544A44202598AC2326C5EB9F305C448CF68323DE4C5BD28472B340E43DEDCA0DC290CAA47238A7A26713869C6B4237D40EE2743BFCE74E5CADFC183B14075FC8088943F3B2E93FD3A96ACA364B9292413B2B67B43C855A898F877683FFA238C05E6F789ACCCC40C434FFFA494F2710C3DFA213DA7B56D5A4C273603ECE648F3E9D6EF1CBC0EAD4BFBAD01E0651103DD17A534A2CCD00CA53C713F3045B2389B81651E8E2C2B6629D127505EAE2ABD26F2086E9D6BD48CA6FC3BF98F99604F221DC203BCE9D61B756A89BB0B418249889529F7E8F070F35D35E572EFA012DABB16A98D0AC8A99E596A91468A1AAC939629FE780A45D8406B60D04C8E2B31EB7E28294FB2595F4E7071CD906FDFEC3EC3CBB02B03E38AF71EBE9EBCAE3DFC9A37E6B54 +remain = 1099511627774 +max = 1099511627775 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-12_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-12_256.rsp new file mode 100644 index 0000000000..678fdccf6a --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-12_256.rsp @@ -0,0 +1,12 @@ +pk = 000000187C9DBD8C9B8EA4E9F5B0D99E80ACDC712F597F327BFE800419A478530242532C04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000180000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A7C9DBD8C9B8EA4E9F5B0D99E80ACDC712F597F327BFE800419A478530242532C04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA24010400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE5900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011420B60C54314ED8291B4F251FF32674EE6A3C3609140380F6B20865B7AE643401000000000001DA6EC89DAF2B01E86C06ABE8043C9A6EA0562A18C49B4A9497D347FAF8EB910002000000000001A0A42481338E08706BAC35F7B5F5D93432D40144F47A0F6790DF4B68525ED740030000000000014A9507DA8B4941DFD3D5E9A02EA050B97F9887A65D93FD8723FDC30C7E2AA4E00400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018BB8E296C7509BC115ABB151E123D4E0343D51087A3A7321FD6406381792A7DA01000000000001166966BACD855719FD325B6CB7EEE8DEC0ABA7479BEEC9A71F451BD9EC1886B002000000000001E480EE1888B362F2F00B536DC0FB57F3AA94097DD543F05D299341633DEFE5FB03000000000001522E3D23E82223C8085779A58B7ECF45EB835F4B8FF5294923C95EEC4FCA5034040000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001D10E76AEEA90CDFF9F15085B0834F5C0339E4C86D2CB52C234F6B18B472E8A020100000000000195C0CD14484D08075EDA691EE42CD999A552CA1A62318D9765CADAB553C1C5B90200000000000157A8A577120F2AD134FBF0E0E061E38A768CF935F4D2AA9A541C7A3D033A991503000000000001A467DDA3824B40F0D0D861A12328735CB8C23D1726982BE71F4CF68EEB4925500400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B07C872596E0E48193D8B6513232AE14EC985E19B27E231B2EDA344957695939677A09ECB8C65C93C63C6B08FE5DA691AD51D463012565EAE07805134DE6FD09BA7B3659089DB2B16DAB68A89406E67D63B3F0BC70C271C7D0295293CF5E174FE0609D593810EFAD6CD648BDF6D3253E64DCD6D2FA70FCDCEAF24B7C96A3E3E4B078E1668E5F6CB9A598FA202F0AE1DAD0AFC54BB46BEE1105C69C535390CD63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000151D5FD68390EB99D8038558DDDF270C7B6F86FB6880610C1958EC697B28F07030100000000000110E17383D0E375BD799216DC0666186C133435744D4C0B5160341DE623FB326A02000000000001446011ADFF0A4CDC66D4AD0938159A880A250A728A209F32F3AFA46A2FE4644303000000000001656C05D7A6E564380A829747834E40FABF67FCA7B2388E9EA19CB553E670F39D0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1CBC0EAD4BFBAD01E0651103DD17A534A2CCD00CA53C713F3045B2389B81651E8E2C2B6629D127505EAE2ABD26F2086E9D6BD48CA6FC3BF98F99604F221DC203BCE9D61B756A89BB0B418249889529F7E8F070F35D35E572EFA012DABB16A98D0AC8A99E596A91468A1AAC939629FE780A45D8406B60D04C8E2B31EB7E28294FB2595F4E7071CD906FDFEC3EC3CBB02B03E38AF71EBE9EBCAE3DFC9A37E6B540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FC2D9E83F622B942A7AB522F9BBA979A17180C4905EC5D9373BA8CFB20522714010000000000016319A9C8C78226547F3DCA6A70375F911BE4AE9028FDCCA6D161C5E3698EF41C02000000000001B15AA0B323C0B86CC6F8D84E17A54A6198649F962EADC06CE71C2D0FCE0F3F57030000000000016849136962E7C523775EF2B7BFA1967E4C45FD1B5FA9927D5068CB7045F945F80400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B76671FE88C84A4357C76C316723D855FCC4372ADE20F8746B501EB76E62E66AE390961FD58752D4914C7CA53CD0B83E168C40777F8F136502A84B6C1A338D450ACFE885E77790E4EA399EA859A3F37A5FCB8AD3679063566F14B36FABB97B125F4BAB4B60EE9B26EAB4BA86E1C81E61C1A4103D9BB2D17389A93D792C203B005A361C41D2C620CDA46919CD9F7D30E547F62CFCF3BAFC540F5E6D9CC212792A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C9A1D016CBD15EAD633BACDD80FA9B396D41EB60B5C6C42A9376572A15B7630801000000000001340AE4E9FBEFBB05FAE40AC69DD5D9882AEC64ACEB5B791C23B5E38F7E0D8C86020000000000017BF4F1D53369BD8AE978EE67ACE5844E4677C930973856D35464FFB7DD2E380A030000000000010A5A6E217E8ABD673B1F169D13255F2B1EF225A6B17B4E8FDB3638EEE425A0FC04000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002FE6945E6FAB674CFDEE3C8446481D1144C9AD9F8CA0DC87D99E2FE038A09F0E9741814E09511540CEAE2C0E950551E10B4BED309E2F6E7CE10500BD8B00C5BE0B5D88B01A1AF25ADD068421C0F98CF345A597427D043CB53ED18DB764F4288B2B88AD917C4F0788488D1C56B7579C7695983135EF479D902A4360389A206CCD9652672552F9726782AAE9A57D0C64034E7F124FF75B1B55AF309F0E9B4597E20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001407FB5EC75AC3694AE740341B13D2FFBC2F6AE7343A54E37F6C6F2EEAB258CAB010000000000016C508B22C241B8C08D163FE5B1977B860137F0FA390970C779F27757D5462FA8020000000000012AF02BB715D65D2C0C4F7658BA084A5F34ABFE8EC98BB4A4C7729B0B1D5727F50300000000000163E339A7757812D58B835953C2F8542B9ECA45C566C6D40776D1E0F54E4BF3750400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D896E231EE5DE2FF695736AA9B93B48C13D6D0F9E4EBB68A1088B311D3E1696610E7DBA6023AD3BB4122BDC83FA28938AA6023D1BA84752D897BAC75911F9928A4585F3C071FD858EC3721BE2A9F5FFCD260A7A5413BA2F7BE17E59830A7DE2299D83F779D0C780EFCA74D6D71015D7F21F54DF0A5231A5577BC161BFEB7F6B2A41B5B9A3661FCCA56ABDCFE63F3B49CCEF00938CC038FD084477C91123FA1490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FF52E922221EAEF117F25F4BA35F0DF3BFD2E83DC3CE0F32221B397B0F58D3D301000000000001456A0108B1CB197506370C82469217CD46DA5260518EBE060F5041541526F0B20200000000000139283287215239886CF223FC451D7DA8F28DD9DF4A17E46E24B0A3CEF86ADB3003000000000001C1BA8932F5114BBF3321498FBAFE23E699D71BE06B2EA0CC423F79688CB3DCE60400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DF8DCC3B3A8B6659B70F64725133A9FD36DE92C29A485C582BB80B5C6609CC4C7D274BB7FAAF35EC4D80F5362F198D5B837132D84273B57B21103639CA52F910FDBD585155A2BD052051BC9E8E43C7AA006A41FE7864BBFBA510253161545DC3E660490763A929FD7A5FB32773FF52FDEA9FE7D35C141D13ABFEFA7A164D484F75B78484DACBE33271095DB0A74F25E78B1C0514641F50D62A173D20DF1B38600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F29DF8D7B37FF45EFF2C758310D7A14228AF285986BD41E283E3197DB9A7F530010000000000016BF475A4431CFA7C1CF0BAEB757C97E64B03D109D598E620FF8641E5CD50710B02000000000001A870C6026E859248B7866BC1A623CDEC1A9E807C402550E33676E949C2B6DC8803000000000001D19E407B03C9F6EEA492ADDCB9DDE699227C8DC630DBD5134D93EC762844274F0400000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB332A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFE8186E4905539B32F01DF3F0FA65E08B09F4F16719DAE9A987DAC3A28B2B9E001FAAAD0F03810E525D26529CBA1829D42796B65515D55BCD2315DDDB342591BE8E217286002741AD99A1565D106690A5D6277539266747D8632686C5C9061D5119998BAF8B6C09E61D13B2D91426AB98DDECE3EBC2CCA03A8B6591E2A1712FE71F847F486D6E177932521D9196CF0F637314E2329A86F733D95CAA0C2F7F08FA45A993F52B44077712B70116CA4A7DB6587E24BFEB70AFBF3A6F1A33F469D98278A6603810F6664B9BDF27388FA8C69CDD4127B39AD97A6E2432E3C2B6E0087EEBCCC54DA43837F112E61409D225BF5E5222DC107D698C0E571EE8D532C99C6CA353C02F2BC7233F1636D14FAE126DD4433CCBB5DA1C5BD079804FC920E7A7906C9579B18D7B78824CB39614E28A2091D1194C26DFBE86462EE24FA1FE24ACA85F912404458AE8DDCC5B03A0E0402BB689ECE763D0825A8D566713A013923627115705098D63351D22772A01D57BD39566F1EF058044281C3275AAB8C44F905DEA89F9D1ACD8FC3C5E9F2DF429637D635359D0A3D91D765C71E5DA37C2BCF29F1EA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23DDCEBD1114559AAA8C6621F7A7AD11AD19D6312097C99841A84C35772FF6ACF5E1028BD5885C73C78A719FE0D63D52E9F55509B7AEB252865C6720285208786A2439382CD03CA0BFA2FF1A45B734943CA586AAD35DDCFB075538B0850551967EE7D7E1261DEDE7016BAC7E1B447BED75C565A09D3F173B5F9DF4CBD86780F35E9D7D62E54A2FEFFA0FCFC5CBAB99D2F5EF5784EC92C6A9C8DF06FD4491E197B153B084BB9A5F629E4E7923220EA7981AEDC10CCBE387725C16BCD5A4CFFB3566525CB00B5295DEFA64574065D1173DAC40340878BDAED7D71811FF8EB1B55C9E3C8BB8BEB2D011A9D6DBA1522C969314EA2A7FF20000EEFAC8F760CD24975B2CD9D37FFF352B4B13CEC723C68A595E301D02E0FD881D3286582D5472DB230F77C644E02E4FD2118592D323D93CD22E55EDAEC15693758CA10E3F215E6814BC13E2DACC05A226ACAF6DACA3B9EE91B0CD0740A5B50E6E10013407A7AC9A58F2C2D41A8CC0BD39BEB52BB643AA89A1194312A69D6245A1844A03D0EE0BD92C46B5D8EA77927C48D23107C3D498427E8DCEAEAA36E368A58EABA0E06B97532BD8D2B17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A59CAF17D13F6E01699B1ED376095D3F6850ED50053CB56D83A15DF12887CC06E7B45D143CF738881A322557FBAA2381B355638DEC332B690F7A2C91AD96C5102819AC027304301756A1B970378FC0C627135DB8D5F6B0B75316DCF93F0955E37193575DD0C14961D776379DAC58F5FC1150785BBBA92D1009E1B49D7E3362CFA468D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E528FC4BAE4FCB020F4ED5EF4F2A71B9D225F7B7E6655E60877D7B7F3DCFFD8C4C77A3A3B36073A69EEE8B35F49BFA43AEC19ADE9CC7DFBB1F6A7AAFC69B3210DD8B9D2D54268336896CC79F76B441391662909A9261AE1A5D75C4F9C360AB0C19A94F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB11EC281F61A34DC4C3FA81C4C11ABA995BD4EBF44373AB98B000C9F53E39A9E09607A88AAC7AE6A1AB1E735E1D0F8F8D34253718687CFE01212B0B818030EC3F1C8F79574580A44C571456C431C52BA9DD336B1A5F8753263FFBBF6005A7AC41B11814D8CCE8CA7C6B68C4F9A56845611FD6D46C35562176A9E14B357EE8DF2B3F76950986449C0AD69B0BFEF0641CFFEE6CA5112F71E1978592018BE903F66F340EDDDF09089FB1DA7C60F76B3D92527D470E11455137D94A80082FC1AB8DFA33F518E348D50068DC6BFA59015590904AE41CAE8E6A05F2A1296D97077A04DABEC3E27E25173C60F955161EA514178875427F4018AE8CE74578E79E80310F069A611AE281EA56517083EE94B5B37A1493E614AE495D28CC5D8E5A6EA4119FF599BC8DAC4167880FB7EC2FF09007E874ACBF9CAF516CBD6E305EA8492B3FEAF23BC6571A5B800489E07BDB1F2C800BAF3E7D35B4EC997B21A3C29960A9FAA177344E6F9B9C59489A67E782B630D9CB44FB0F82922839403A85C7AD53A9F32D163A64DC226EAA21E0994B218DB931E50BC31C0E1B5651CF2098EB00153DC510E086B1FEB74661932A95116E04BF13E9E302A4CD3783C572CF52249F5FDA51AEE054682E7D3E9BE99FA215853668F015F5F788BC6DE4261C7E53A2FB9B46FAAF6C821BC64ECE7AB00F059A65EA3EA9AC7C64971F504F26D97B48817B3DF9DC46B3C106C041D1A136B4731AA2922B97DEB83A3AD798A719BAA1CC2ADDE4A34D5EA63188A0CFBD3407F3930647C3993848154841EEEAEBCDC2149D942FB644A671D50A1B51ED937765C0C2AAB1B35FC6E4E6DE85E82B4D87727BF30085AD56A27A796F53CB4D3609F07BD7645F7B32EC8B72E51592714D78514941E217E6A8A393F91A907BBEBF9804CAF5925756BB3EB09D32E125469D4413DA437C8BB4CFF2F9C23C6ABA4B90395F55E94E0113E372FDFB37E7801F0AF52AACA367BF4BF90C58D093771AF0991244B91BE5C251F9380444AA86C221D06D0BC12BD1C2DB949E7DB4A5DF1EFA0A4BD339B8F1B937F2AF48072CF8F69E47BC2E20286D2524A59F271852286AF9B8BB57C5FED3E3010743E81629BD1C366D9350DC9329BC839F7B8AD5B7E570C85EF644413F0A6974DA2CE7FD7194C30A43780D5146942339CE2B186698B8CFA564998F0DA458E36F2B66CEDA779C9E9957D987676AD23A507730959ECC0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2A75998AF280055E9105EF6A91BFDF40FC5FD0E6E97EDF27F96872351DD3E8C28F46AAC52365CF914A32E5C21626BE9E13BF80A1E7E616022639DB2A5ED92A119EFF891AF7D33883382B554819C5CBBA093B55E335D550DACD6AFF9DF70A2A92C1BA88F210224F8F1DFF0B420B6C2F673497B86A156F5F1C675D301F55D69E5D275BD43C850F39D321DBC76B0F153EF703DEF0FE7480D5C83EB1535F0FF92A37EB637DC3AB8D7C7965C8517131F5273B10A2B5E64C16C85791D41854E43BD503F0E52180E9C29499C45CE64BD97C0BA486377BFBE1C6EA2A84AE249C8AE40CF3E86989F0379B9D02694DA77F9E73560E0F38AFD05744E0A30FEC0D8DFF8A1CA3A0EC629144E96B590FD5F75D92F40E0FC0A1127486133218B844D932E038CD1B04DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BCA926D661B145AF5B8090D1A4E51D9CBF8818A4EBFC8FF1BD6CF2C76B914B8A7BEE0EB33F37ECA54E2DA3CBC29F1720DBF0A024C969D4B1E36326FB6F63C9195608C68A3D7C87AC394210D0F4CB7D858A88168FCC25B79E29197E2EA3B3D4A862B70A1D7F3251C75F02D476926DD863B778059B83198414E0672AA1F27898C8A6F035D26AA117F838EC83D453A0D5C49AA350B288F1FBCE59D86C8CCC99F14A221AA18A9F300DA266DCF084910890994ABCBD8185D28BAE4CCA4BD68D4D5790FEFBD7A6D56B8C78974F9A8675E6C410F6D5F7F6D254F1C7885F48F0391E1BEEAEC7437553D480FBA79F55DD5B19C596DC2089BCF9980959958F7FB7E6DB0358093379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E6B09F3A309D255D0B7A8B8430F7E9544A881EEB694C7282E20EA3E1ADEA50564B935D528C0372397F26B1497DFA3D0F117F7A6797C1626D1AACEC708302CB0C0E406BEF60B7F6578623EA59A005B804C009A38E0A615F1FEDABBCDA5269C9C48E148A143562E1A372C0DB9D8F249FB5A7ABE5928B4BBB17DBD747A57D9438774BAE2550A5B205FEA96912A2FFE3FBEF1D6DF372A31B1084F0715829C141B845551C086DCF8FB9BEFB43B417AF3426BAF6007DC2EFC3B4999D2A658B5A19CC61FCB3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E608E25F1C4FAED708E98E1D88193FF5DE2D33B178BCD345DAAA3ADEB8B1B6D7C3E9C2468F943A4AF0596B0AA480A159BB882857360DD34CEB848F5CF3481A660F70E49916F9A952B001E60F11A31CEFB39D3F49BF76159FF3E8B3570BBF5D759F5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7E5C5C61EC2EC722ACD680BA597A47ED44E937AA64C0E3523F1EA891BF01E2B92D54EE9A3684A122D33ACD2A6D14133A8DC35EBE37F49D59BB4BB5F24940C18E0B4B5F1349AB813E994AC43DD0420A52527147C9A0F4729F8BCFF0941B934253B98628403937D1E2DEA8BD23A2EDE0A7BCF3A2D66FFC7049C8D2D3D52B4F9479F6652462AC2D18DEBBA361721EF71168CC59501174444B5A2E58AF71E8DFC4E9F836156C1C844EE12FCA65ED97F8189FF34B8EED18C26508B5ABD7DC94DBFD37F18A514F66BEA2AB8F02DFBEF4D54850B589898EBBE0E68E9F864D4468C96BAA0BDF1C074AAF51CD47B20784CDD20DCFC3444802DF292D0B21D32A93F2DCF3154860EE0F469CF0E8BCB4BB474C2C0F6E2F97EE8C155EF5B270FAD06AEB3336087B314915E7CC95153698BC2E486441D1484052BBD641183C9F5495CE45B270E5D085F4DF45707C7615CC89197B2646196A2F382EFBB8436E3B0A09CB2384FA6D3D7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC776AA5DCD1D7D1F191AB56003FCCA1F90F9488AC0C010A6FBCF7CCC51AFC15BA2F9E678B9B2D2B44DE9B7C841C386126135E1871324C9C7D3648DCB8213473E4D006FBDD976D2854DBC257DC1C21E0199C10AA0FADFBFAEE03693930F970285460EAC6BCCDB873F2AE73A173F17CF6C07C26B3FEDC0E81E8EA4FF7D68CAACE34340EF1990F3BF44E23BF65CAC9F65B50E4AB2ED67F01DE310314B56B351691609FD835399C51AD9B35E4118BF3B26AD5DAA9A0609CE6A24C8D2A1244709F770A655DF9E80C0C7441917C8329446EB8FB371C506EADD1DFBF6646E0790637395A2C1429C60252D485BD99EB641F0FBCA951DF3698F69DA2B8E751BB02BA592AEA7DD21E7B961499C0238B93F6AC1FC73DD562C80D39493800D0A0A594F26D16FE54EE71B5AA5CCD70B5F1ABC79687AA87DD986F10FDE0002EF9D964E80940FFC39C5F2FDFB81C190A83B0AAB7BB176476712EDE00F6F97973B9FC6061EB404C24993B85BD7BDB4582903BE253ECC3C10C0B65232F5F681953B179E19D4246B0799477359E0496BE7925D46065E4AC4B5EACFA466A8DB0A62F1D1AD326063C89539BBD517FC53ED562D98D20D8A7CE4FC1404B3BCEC7D500F4573EF14C99BCD70F290E6F4206E9BF9E4052A8DF39BF57BAC1969CB4D85E43FEFC1907449AAD6475CD2A7B9F962C315ED6DCFE913A2FAE5E1A695C5BCBC0568797F5154AAC68A30E0EBB8D2F73E6975440421D001AE2076AD1C65F3ACA6C05144A65D535C89243D6F099CD26C54760517EDB1CE98AB4F9E0B6E3A06B3765D62E7812C38B23D6A92ADC6CAF95A256FB750DBAFAA6D3E937BCA9314331C3EC2BFB571E0D54D3A98D5D28522326681F2B91E5BCF4ED462CC90B4CC27225742E5C2286AD1FFADD8418B9B3FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B5705C3BC66A1916D1424D631E588FCFA838C2BF8BFE2CA2F5F6648E79942E3DA4B064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C479F17E1A29D5B6F18387D15E7AB024AAD60E6D68869726EC117084D8E0C42A3A18FEE5FE427610B9311F4173A555CC3D534439D074BB8153F99EF5C62288F9CD393B0C257FDF1AFA64BB68F3DCE632BF81FDFCFBFF93A4CF99D8D50805B18EDAFD09D086D586BF8A5D6A2026084C7DBDDE343F74C964ED3011E29C8683300EFBD9E93C68EE571CD156D8FE815579D8E5AEDB483103BED689A4CEB7EA73CB8E19A6994A01838E173EFE68E816CA53CE578B87754CB34961D83A611466478E9325529D6D15C156B2E2E06E1F624139D230DD3A32A90AD2C7097F43119E10A2E788F15795548B5470728DDDB77CFD86A6C3C6669B9A2217BC37B15B8EA558D2B9E99EEB37E105700A324FD17A5A00803F41C5317FC2445C7216FE28DD0F15BEF50566BFED945796D4F3DBB97D53204D5BD64478A75484912749D9407C09D01CCDC391BEC54A4D43C9157D0A871195C731EB746F61A3F82D6F1A9807C2BD3B275553AA6CDAAE509A3A350DA3F119521A3DF789E011E59EE8138C17EDFA2AEA5C15841D25DF2E3A1FBEE40A3CD98C275AE4FCAD2708F31D7354E4059D43FC5625858721409E990F1DAE7D7FF6B3084897B817D88A99C149497599957A667750E1CF446F5D24409E3CD2AE7F13197FA6705BFAE8C1BF36AA626D524EC10CC50F77B359D718734797BA0154CBC3CCCD88030C97386483EFFACEBA41E5061B95BEF6324AC98FD576AA2A8D264D05596B20200496C54C58146883B62C9051E5F52224294C996EA6B44F84EE277D029766D66AEA021467747DB5CE0597E5D91D92903B74DEF2A7100BFF8201F70D009B0963454C25351D8D43AF77A3E70C95BA5FF34747F55049243C06C036984C5C303378D475F841749BCB2DDE91A25C105501EEF479F2B6C68A60EB8F1A308E74EDEEF93E1E34A50CB272AC278ED9263C0DAE162B7C1FD035421A2CDA9774ADAF21B292C252B94398DF63894C88C4B5529FC5AA5A18E788D74EB6126C7FDEBE4D650E2871B25F37DB9EA8AB64FD4806121F4509D4FF190439B7A8690A81275D9C03CF2B51832B32DE2967485BF84E915F7BCA7647E09863CA48B37131815DF9E5F5A88535186C40F177A06B657B4437728EFA50AA22C45E49026053B3C2A3C554F1B2613EBE50F27CEBD3BB03C8CA17B22EE76C4200A0E85A70B6DFF7F511FA2265BB7D858556213C48436D573F120D4222BB1A5C924B2EF1605B4A1ED717EFAF63AE53B070D7C62B2F8CFDFFBD18DECB0C405E7575C6AD8CAEF4789D6164039F963F807C3B978CEFE718A83A68378F9156BF52F6A3F76E411CFFD88448BFB452ECC10CE99AE5F5E303EB099B89765A377868B0B2B3A0D631264AEE47BDA8FF3A92483D27CC269B16390B3ACCE3350DAA649AB53B9C1CFF2872B6C1F9BA67D9D22C6FBE01424A7DC815F968C77BE937563456A273992579C8E6AD585A0B3D38AAE13ED13B81D58599A43E86C4B4AE7825B358C6FB94BAD7F552544790377714DFAC7F17B9B6B3BAF2E5D6E87AE0D0769A39A5580D5347C78067D7D7C375A91B066A61E124E754549CF27779D43109D8E167423F13D05093CD1D31B7E6B76A89C6BA817D852775ACA8B385138C6CC73639FDA3AB6FDC5F84CD46DA221B2D437A51B54D43D98E6D77E31B07FF420AA12FD6FA8892C4220AFE432664F946E738DFF89EEBBFC16CB168CE1721738B4A1174265AEB27FF3808A80D3BFB6CB893D1B6B33DC27239E96108C6D0D20C912BC1EBBE7E245056220BE957E7B9D49EEE6C4D341AD73932D304798F0A0F04F31D8F70DB5E06E3ED2DA627D47E0AF1C2E14E56054A87AC9810B617A52D0DB5145FE4C2BF6D0D4AFB0F9314FE15167A5AD0FBA0C1454FBAB0705FB6BBFE5F7E39824E59DA24CC67B3AAD9491E7A40906487BF895E90F63CFE6D7C0984F1D2747676B82D09DFCCD2A8F6DD158C917DB81FDBE6213FE43780DDE17ADB969B3D64CD6BA6EF1F9ECC7D6F6207280078B10DBEBAD7581A2E8C2F83E4AAE8A26F8D1DF0F8CB45C690615EA304E5CE30D2A96C55696C6B1D82D274E9D5765C3E5D2D7D05EC6A202BFD0211B534B7C9FC684C7A72C2D619E9DEC4175477792BB930EB5888FB37198A6E1DCEEE6651038F5C0A15DEDCE6D1833CDA5CE4EE61CC144E7C5202FE532E0B274F2CE4E90D91F2BAF7808D0656D5A106EE157491277F92A36239D1CA7D26150C118F9ABCEDD5470A2A0069AC1BA97ED1CA9885FDF2B6750157AA5B72DB5E7C1140E1FDF78DC7FA04773F4570F4544281C2E9627E5F59CA9740A38B452C9F3A930956187079B4EE4C91B3E3D9F0F502F8558A092630BBA965FD8900E738FD1498FAC10E6AFDF58F32DC0824B405C0E1D962CB213D4D834D7D26199B9172CCA1A36D7A76DA603FE07CE0EB070AFD90E7A30D937A32D26419A002A32AD9043B1735AD3D0696AEDA5F47046F8A3134B8D45C090C0A54C70AE992A0916A49AE7F3006165FBC71CBA5F0611FA5140FC304CF49DF3081CEB754E9E87E4FB637D7E701D930EE23B6E7A739274EC3AEB90736D91745A92DCDC5FAEF42918E63079E07316C2F9E59D8B79062F1D816C536E8323F501A20A11D6FAA241A5CB4A04F8384206C1D4BA5BD2DC0DF41A69CCD6390270FF0451211B36B489AC95476493D812ADE03FD8EA165053401587F7A18C2F3FBF4960C82B30E9C7C30EA830FE7D052DB5A191C0F8DB73833839F0D7AE822027E19C3A899EDBB02AD49EA87E1A2D55EA6B010BD984FC6C5B12289B41264F9F2F23B8761F262598692F57DE1277F48B3EBD06762F791DAC23F5A5846795B4C4806EE0909163CF27111BE948EE0CB673F0B744707BE8189B059F6D33E52AC33BEC99DB223FD42F64BE1C3E8D505592A78D5F7D3E465A5E34C1FC7D7ADD80752A83CA5CFBDD7AE15AFFE7BC0A4BF3722EEC05E54482A88287D9850672C2DCDE120E0C7AF377659E5A3313D0FEAD9B350A80F0A5A4A480346AF02414FAD52E5108B911B7A4B877215E400B3FCD4E8786E962704A50EC2B2D2D7256777111EA6646AE8A57C84B56C30D704C4B914EBFCA60FC07CEE5DB943630C0A2BE448CFD70112A56A74AFEDC4CB48BD579FEE9039DF705869A1623B1596F77D7420B59F32801106F6AD8A16DB40B1ACD82415BBEADE36585C3BB47F37BFA7162C255542E8284D8EF8CFF88DB68A47249DCD14C1D2E8E5C44E258E9BA867902ADCD588A5A382A60A580458C8C59BD5F182742CA1BD6A52F35FAC26893D74C3D74429401712918098CCC493BD226EA8A9F8C7700123924131913453EF8069237ABCC4B851B0A868015162AB8B7B63B3110906B267DCCE5659F4FCA5298C4073BAAF392C5649B429D5E378557D5CA03C9A52B6208936AE2CFF83D7E28A3274398CB3586BEE9694A14396FA1D67BFA90524574B7DCF0E8C7B86C86A69FC0C2263B437016842743E7E1743802C4542DAC8E6A23D03A158BEE47F010F71E5D9A7063E26FE8C40B208160936B5CD4D13ACD22F928352902BF25A8C8D294B493907F6794A4DCC0E7CE621FE45CC6E5F33199D798FC6E833F9EA4EA54FF6A465EACF2EAC6864D3CD0057429D789466CC60CD853B829679FCC639446CB0657C15B869BFDF27AFB572303E17FF826F8C4EE2C747AE330858830F70879FC8FD6F8D7CA2BA986E5D4DA1B613DF88CE09212B99BA77FB3E3AF7AEFD4FACB02B3E3172AD43BA87A4433CE38E45C1DA3ACE463315CF5A87B14CF4745D5282B17B613A033A9FBF52A40D8265B49A49DFFFC6C71377C20F4B3EB43FE7D89D829477619A7E5B2F7CC9FD0299C838419661773087C7BB3573568DB256F94E57423B1AC21C0662B60F526AF49629B7A8F7E833F858E5C7423437ED22E6E704EA66B26E79878EDCE376E8BB682EF83EB4B9600015217C1219224381665C140C78374B80F47511C48B5238937464F3B0A5612D2F1FDCC91B74CD861CE655CBCF22B68F657EB7D8806DDDB03B4F08E52089938121B0F6B3ECDD2D23003C889FD2F9A4F6D3D4358976641511DDF513181B1C86DE10522AC021B6A301249FB9E6DB19DF42C5BA6D53F1FBF9A7A2249C516513522F8702636F688145B52B1FB6172CA96F59B9F845760677D91996B38371DAAC111D6BC59BF28F19B4E00B5E312191087255D008FEE158A8E1619CC0674E12DCAB593EAF6C99C9CBE9C700B498697A725E2F30EA74365F3CD3318AA1D0D7C07DCA4F2F6C3AC8EFF0501F8F65A07363621059517EF1BA27310ED930A1A1B0D4DA322D5FD13EF522D21A3A7D623FC499AB8648C1AA0CE2EF94316B2965A246AD7C8869E9C489AF1FD2DA40E3D688531CF77F083F281E012ECF83C4ADC97B5AE47CC38FDB41C7ECBF402AD42716821AE404A1D224363958B9E71DD4B3E77A16FC80598A3065E8E00F36F2DF940F4E99902A1D62D73470FB4923D3A46EF07E65D02963E1B5308121675F1C1973C656549030DCE1BAE145C7712A4879E2F3E219B72B673243BD71442B699F3A4E366C7B88C1266330282D0D9357FBCEC2F95AE54D87A50C8581597B0C24C2F77763B326A55EE924C4A492307610526A864CCDDF6FFC64321D570589BBC5F9CFBCDD95D0C7AD62DEC853875BA2F3C5E3FC20CFF99FF86539F37EDC56643EF7D70D0025B395061B83A100E1BE1D6096D007DC42082D4E793CCFB79CC5A06242518998D835B32B7E579AA14806AEB8A4F19E554FD72D2899617541C6B86B63AC60BD7B6185A7A86BC7702CCB91069ADA68EB4F117E239BB7A9581A56CAD59A618449EE02E2089CE3A1B97B22AE34BBB421F2194B00B80F1841480577415436FCC20FD60731E6E28138A320C9237FF656A5366890E492A318EFDAB7F22CDF81AE5CE56539034A8790E942E58118A8F141B2FC6E4559A04B9EF8827BB7C11D5A4CDAC22E42660082AEE184078053860369D354552F1CB9D798F3FDF657648A7D5BE4F41E6141FBD80732B6D3AB57C0F60D38848FD33F7E468BF7600E16F25B9552688D3AAE33DA731DFA536059D24AAD21AE940CF31E18A40508DD1623FC89EC11BE4B852EEEFD56C002C1388DCD5C54E0524BB681A25E076CFFF94EA7B5E0A0B7DA1DED8DBE3F9770536FFD43BB48C9E55E33554E5C0411BB823FE16AE3CFE51DFC9177764955DB39B08C627F74A7B9A16DCDCAAB1CC31E37B0D3B90ABA2F1EC00FD2EF6E4FF3A15358C551BACB93EF59361567E0834E72383F4EA2E8F76F000EE38B179F7F0F9A3351C5BFF81B49E8A5119C6CB5CFCF49A6875B3A99CF14E6CBABAC0F4F38FC97CBADE13BB807CEADF726AD565D65334539E879575702D58462BB2A7C7F322A16F3F1C4FE116CEDBA6094EB4712D774B8207189B700C8B84FC7D0DB49B02F7AF17A6270BD75AA54F8A79E4A1A6D588FEDF94C0829EC1496988507C8C5BB87A70DFC3FF6C7F985ED38CF6C23E04FFC8001C2958B5E0920B284A4A3A55023D13D4FB99D392A0F61281E6DE6AD1F907788504F80477B8C21454E4FF16236E42DF95C85E20DEC39B2920ED49AA540BF504E74627B678097B4EC800A37698C32118BFF564BDE9BE0E4B16A3D91A9A83FBE991DD88E7341BA96976F7694323E523B76DFE3C52F28188C8D64DFB1341EAFC98C9A28CE446C4983AC52A1C38F9CC5D8CAAABA4E8BF9B7E45E3521567A46AE5166642E89F8503F892F522A447B2FCB1BCE2EF4EC86E22F48FA99555DC193F080D3F0096A47BE3C2597FE83A27E8132D28EB55AE87B36C93F31A9E371BEF51E405037DBED6CC4916E5A855116586F7C34F33B3EE626DF600644EC881246E32B5716E9580A1733ABCB22346C4414E5FF2C085E2CBFB45BC77168F4164B7CECC874DA5594F6E8D0B7B6B36EDEEDA1342672A4D6925CA2864B93BC7F63994F8449929C3206E086738FADF14B1872973A6093B5916E565DC3B354FC544A44202598AC2326C5EB9F305C448CF68323DE4C5BD28472B340E43DEDCA0DC290CAA47238A7A26713869C6B4237D40EE2743BFCE74E5CADFC183B14075FC8088943F3B2E93FD3A96ACA364B9292413B2B67B43C855A898F877683FFA238C05E6F789ACCCC40C434FFFA494F2710C3DFA213DA7B56D5A4C273603ECE648F3E9D6E5DDC034C1B684A22B4C43569169D30694DA2D259C846541CD1FC1D4F3553DDDEB5650C0207248DED91C549B76BE830383E8E158E188D78CD90E7B03AB56FEAB895A3B82C1709F9FDE140EF89B847CF556D8D40BA06511E6B003080C2A9FA8E9B43888C41965DA5B6B2225206AA998AD1BB76E38DAA65F1759EBE6F4E301AB3B59D217FCD6C08C626143FE4B176E51D1B66839600593F01E40F7DEF55A9405B5F3E816E59039E3528A724CF0116508D784866E2FC9864778D5BD5F25DBF3C8023DB6AE937B028A471165990FED36BD793D165DA1A4A836FCC7B9039CE4375344659432BEB0820FFE1CE1DDF984FDAD61284FB7BF551CFFA91FDD3237950DBB9523C478C56AC1D0B5E7DC0BD88548A1946CB98BE05BAC55BFB535391558FA57EFAD67AAA9456D0F9AF82567AE1FBF375F69ED9B30324350C6FB4FAE7FEA4E7BF7012F515076835FA348D9ED6207D9A21A471AE1D5E036801694BCBF5268776EFBC9020F5101055D97EE9EB04C5CBFB4D9132855E2B0DB7C4F4C26B97A7B8DB1C2433BC12085E0E624896179924685837CF20258DD9D5F698BF4D1E5203F6CFFAACE82379CA26B15603786CE45AC18C296B05919A834CA0EBA4855F63CEE3BCA8FA2AD24C07D3B7B9F73ECFECABD9306C647F575D7ACC30ECD72329D51B7AAAFB919C0511DA596C23A520D9705BB6C5A4969346C30AF6D53D5A9032E04D1F960B87E0BE110FC1468A4E657BD55A832476E82A839B9B44199B12D51D3642F50774A9490BA404470C54A9249E772BCBB344597CCC73FA0919C4C67971C5195449D812F7A6979279C23B020C6801DCE5472B66B4457F56B7B0CE5C9AADB0955180917A72E93B10F4EDE8691ACA70109399FE9ECAEE4FDE5B687836315E7F16FABDD3FDBC2004D9ED41008D0AC77CE46DB9E402C14C08DE7C0AF9EBC927D40DA2D7C7DF9CDFB5DDAE39743E9A15C53A7999B3B35FD329FE1002975F668A2307221020F884388C0649E8A6EA76027BC254C948426CA44628071076E4E5C77C7F155AB517C5026032052792533A29E6FE7CE81A20C68786F9315C73A430429E2F2BDA55C4E3C09FA73081E19166F7F0359FA6B078F1B4EB95103698F9DF7610E30B3E801AF5BEC6D262A2B8F1D1EB0D00FA8B041F6AB95888643EE9B00F3E925455A0ADB35267FFA9E8354BC69AC46E67106979EE5B75705D80550D7173CC407A4201127FCCA7A162F00796F46DEB7CBB36311A900248FEA298EFF33A3D645E28FD183B230841F4D848A1FB51A7319D5C1474A05694C06741CD15B251FF33E95F18DC944DA035532E1F27C654C302FE8BFC7D8CB5541008B01AE4D5E7C2A09E4E5D5C5B314B67DE4A03BEF268203ACF15A4F9A148E4072710AD9C94F78A55784558C32F3A2E513E84E9B1299FBE18E607FF547B1619AAD1D63A1C761DEC8A262CBF89714EFFA189ECAFA723C81D00ADC10B09B4F678A6710BB3C64569F731E7F1BA28371905460C7E1C877F398422C48D8232DD5204089DEC49108CBA8DD493418DB492BBA225FE73C1CAA7D91D6638A2662F114A40CAC9D1D6AA16E67E0DD281EFAC4D883A25ADE30D9CD44FB2E2D24054CAB5C527301CA96B020EB0ECBDC803B9C1FF07BC50CF6921CBBBC757A2EBA28D307F9B67C752443A9859A35E14B25EF675243ACCC36641991D00E03234079C0B53E8AC99033B52967861C85D548D25DF927EC74C8AAFA5F78884B5443D8F43591451494BC12F7CA33BC42C629EF0AC93F11B942F4C8250C4A4411A6B14774EE772BC485E2C676746083A0DE3EC7D0894281E09686D13A7E628A4EEC1DEA1F847698086CCEB661AA10F54755E8E7553502F5F0431D91DD4D66B963B213D615A0DCECF5CA6195EC9610B92C3FBE750E3912180D33E3F04B29842F61CD1454CB4D0302F2BE905BE49F82F470380492429A349CE86B0EAA2E305326985321D35B1AAED5FD3324D12EE14CB3FA5BB739696228F645A1E9A9063DFCE147C2065BE5E2E7741B20B29A037974174FD42F0796CA07764153278AF8707320DD6A820EF2A72EB981A82EACE9FF55179554DFFB3F8E1796973E86BAB1C22848968823EF74DA3977108CBA1FD67EBA4170539D24F12087F5954E6FC086D915A2037E7BFCE97A394F987EA1D6FB7DAE67765939991E7F2163C33DD20950E0F00A4EF163CA7A903C0AAE22A6516C172D54A73D4EB181DEC2B1BD62671562D60192F32844EC777DB3EB698A8575787EE699402A80F6E2AD283A6EF387C23A4102463C14E2EBC5A0FACCDCBF0E359263792DAE6DCF0E2EC202ADFFA1480357A3B722DBCFBFEB8D341FB67CE96AE936A36D42113F298E3125289FD8617DC69536B2E52BC81E903A7E72CDF15A0FE289C51C35F5A04237B797D1E3E71E09FEEFEEEBA7F14A9BEE50D4ABA48BB2F39B0E6702AADC8A93BBBF9496A15C7F35AF67415973BB58626E9315042019E1D35F768D377035870264A1806AE7A142ED4FC9A3EB4A9F54185E990889BA19EA36961EAFD483802AE4AA6E7FB34B1F7A6AE378C229FE154FCC476AAB6C23C524877DA7BD994F8859B7B9DE9F841EA055A56469962133E231EFE161886085944D70F07819D4896F6E63F5A20F4EDA06DD45EBCAFEF5D5B384E7F0B2DD10809D9B84885385C12C5345DBE856A4E2513277E576581BFBC6D73F085314E0AF1D2A3364532D4EBEF4F8F960201DC635731765B4FEFB8D13C18626D5D4A955B1FAF6E5D65B87CEFA18B021B72187365C45D6FAB5B2A4AE7060C5479124B5F5CD2E6D6496E52BDECB9900686BC6DBC0848C8E71FC9D7740405ED290C5AAA70A3126A4040C5966DFFFA6CA4D20BDE82441C973D7E639F774C806964B00221ADFD7C60836F032E794DC6B814B9E36EAAF0AC330407ACA11305731003502A578C9DD2556400086DE1A137176E752AD2A0BA318FC09DC51977725ADEC2F5CC4D71BB2AAA373DA9EB4A01F5E7DA252F75FE7B94A3F80E9EAD1863D1A478E5E6D63702D7730843AD460B0522D28F9EE1F5E6AC01DBE3CDF91F291202C4FEDA136CA6899184C53A94B2A2B2F027760875ADAD89484F21305226C8AB81BAF359B9A9399C4E71E343043B41FB814656E62A49F75D72F8B70EDD2B3AFE68C0449920ACE28BC7B4117CAD1B78A0ABC4069B742CB4781B10664BE256B345925FC0E56EC16437374426D7330716AE3F4FAAD02FD5B5F7C01CE23E9304914C8305B39309B9A7AC172E0C8FA63812A11F4A4EB5338CBFC2287AA1490D8166BD1866CE08654BDE8069D65EDCED448117EEE3B3C69549CFEE04B802B06567FB33D41BA1FE380CAD9B3D3F732A6D065F84B401C78DA3684BAF9A559A548807ECD23CD0B75EB36AA7350E23756FBC96BDF49334FBF1ABE26E165804C5627A08B11AB1DE840350BBF7FE153011BB1BE7489EB5A211FC23BA240F5ED74AA2C3E84443939F4728AD938391C6C1CC808BF9EE734E81711868D986A1616E3CD56F1A61E1B339A057688C74A3FFA6BFF6EF62022D21CD6D7729746463A520065B66CCDBDD296771F9B5C002491191EAA0A72609EEDAB634DD69D328665D6109E9DE6284018DBD25F77234C556A474968445D85011E09E31A17FEE95798508E7762221BAEC3D6A4956DF1262A3B13B967154E369B26A70C16838260C63979DC56A02BB1E3953DEE601E69F5467F7CE20C1DC799902C391D27635BADFCD73242DB995F7B6CBC331BE00FF871DF5DB0F2A497B9B06DEE8C77ABAB0B27F2AA4FE1383668A8C3DBBDB9FC21F053171ED76E797F08043204E2FDFF63760C15373A120A95F9989194AD1D5126B4C224F0722AEB2327AFC908A6635BE840BE589401F1E97858FBF94B2295930A490117755D298A5D3E417ABBE3EAAFC8585E76C08CF7B563B2DED16B40538FA4267CDD3B3455783035CBF9258B5503F4F072D7FBF60DCACA6DA5AE3482A3CBAB760F774720BA86DCDB03E38B75F27D6DE9C06BE33B8B68983DDCF453802BEF21332B1F221BF653F58331116E31F8939F51D8FC63531DD0BADB161C8ADAB525E6DFA1F8C84C6A2AA557330DF4DAC68DFDB1D29344869792FC6E4AFA247A3DF68EC505CC8770F7B4805F2A8AF534629BC61C92A1B1C02D55656D7A19115C48616F6C813248C20901FBEF34EC0DE8C429174040458C3B431A62D2C57CE4BA13CA80063DE7BD6668384FF7CB02629C967538617C4F58E4CE1B2E26F09DC7F51E9C3548D9A99016438D9F98E2C7FE468BB5E4CDE479EC24936BE7CF353E185385BC82E7ED9A11C3193C00B923587E98DCD268AC6035FCDF802B733497FF41CEDE795BE3434A5BEB065297A701A24EAA026A4A95B5DA980020C77714A463521794DE232AE1A538FFFEBDAB46C8A6A660A338F932184DBFFC9ECE13B8A8D5808FF2ABB614C39444AE701828BDDDB7B91446894E323C9270763AB3DF7D0A4028EA99EB3823D64625AFF2E01E381ADCB40F1B7B833296CA35F17EFF716232FCA154ADC289A1C9ED14AC0E527E8243BC3540357EB5ADBA8800921611B48A81EC2482CAC88FD4693256F4755700FA47DE0807D29C71264F848D907F9C5FFBFE2581503A591C0ED2711EC0EEB80AD335F0E6435DB9AD543E6A1F881C52F867F51E5280CAAE4BF63BB222DD7AFFC0B1C5C63DCFB19E3F17AB415BADAF3A8396F15C20AD2B5A6C8603CA70742FED3128D6F9C52F3A8CC7B8473643FE4C54FE696885AEC9C1A02CBA04C5C81A4844E927DDF668ABE9A083B84FCFC15D2C747BEC2526CA293E8363F1B495CDA2573DE1BE95D2F5882C89CCF61998EEA4CF5002C3674807C9800D652AAE2A0210DD9C206B5D351C5320DAA89A79D025A365396BBAB9EF785BD4485B5D59E9A10559F3C6F7D541119DEFA26CEEBF7ADF3A0CCB0F1EF2ED7367F2EC87B335994041923C1924798925EF572912EB5C3A344B0F9724632BE4011EBAB92F9423514B19DCABA93A4A7C8F51C0EBEFBD86E50DC6820DD61C166A52DCEC9BEB5230ED209E9BC839F6F16C7F0BDCAD1BB429C8FB4403AE3A72304F178FACFEA00DA6ABA89ADFF21CAD65BD1ACDFF2F8F5AE0D89C25FBA430BC54F8B4C79A159E22750395CBF2A8296C49A74D1AAF4AF55E6A52445044C948F43E9E49CB730267A2AC636AFA84F96F935E8BC021A68CA506272C4332EA472F5A8DEBD98A002CC8E4332B542194C34BE4F493572C563AB7C44E93BCE4AE67DFFD6FED96C3F3CE2470AFB2DD4A0FF01AD6FD485649B1F262CF8C86E51D41686A9E71CDA534E02ABA6C832E92E3B664F5205509B774211D8634843245D3553D8912EAB493A8825DE21810ED60C61C3C51E702207308509BA05E78E6DFA755EB4660944FBDC0DC8AC53DAD237DB0C9531FEC555425F4B1198A2C97F75C588E490ED7806FE0EEC48450D1EFFF90512343BCF48BAF528E30F3AC1A3BF72EBC51D872CB8990435B35189DEC662F45F327CB14DFA069624F20DA2346B2C556C9AD4F692A739829F4B967054AC1222F351E7B81454AA5D594304361BA49810FD0C6DC469BC9137AFFF98D0AE0CC13BACA774394A1575CF01339CEB8085DC985DCEA36BADDE80E50FB8BE1F6165A5B6976391A6468815FC70C6A5976109930414FCBCB070F469446F0B71DA220F64D800695A0CCFAAE22E876BB0B283C3DBCE83638D571102E894F9DA43C9B4C359063DDA0B86FC9C7D45DA126C7F06E2C9ED770B17E57E860B03C64AC7E9FDD8ED8CE95E2DBC2F51122FA2B6730151B144CB6C82E3FBA42C55A5405AC1E023840771F8EED666662AF35431A463BB569839A4871AA21C4817A0144A79720F530F32A682743B9C01AEDB95FED48C38C9793F59C2098E60779293D0F8E20284C2267F03C085303AE010171256C4787EE88FEAB7B31E269142887D2CCC30B8737772DED1A9F671556BFE43A7C381D764B6318A82DD7FFFD190222B5A33F79232EFB1E767E6764A9FEFAA5165B7645FD10D7E30C735EBB49038D582E2DCA81BC47EFE21514B20795DDFE04F114C7AFB4F91881B8C03FD368F3AC30437269B521FFDB8DE0D978CA78D28C716086F58B2767A2323D46172274BAB8DB92814987D9AE26BC0140361E4528877C2C66668F2F7A127F63F5A43C2964894036C46F90A673040FB198DC50D9866BB956364FDE3B9BB6F2E9274D4A6E05AB919609FA3DA339C75A542083E1D6CFC6AE7D40C1EBE4D9AD9358AD16D392E78C086A682FC2CA00E386764073A121157F98A15C7FADFB9525D581A7DE84DF9B0293BC1B7961BEA4A894FC598CD76D6BE49CA389D3C6D06A4E79CB682BFD8D2246D1BBDE5E9754AD3B3F5F6A8DDAB708CAFF40909EA4DF53753D1DDE1C8C959F939DE10DE4CB937C21111973B890AEC27B06C8DADFCEADA3A211FAADE3411FD5F376CD1752B91019C3D9AB949209A344D24C5F4432B6354AE4B2631811990F49E16DF01DB78577132348B7D5A4157E60D7DF14798C8B606A6240AE45D6F1448314AB98AFD0D703266671192FDBCCA33B67A469D1F600F51C4A75BAADA71838D74272B41DBEF720DF137D57F208C195144527958F7EF69D6AE9631E899DF15B8EB560E372A5618FE7319296204A68C97DE9BCAB00296957F7A1955C8EEF4484EF2617E73E5783F8A3DD61BCB40A2F2C560CD6C8EFA96A9C58B73E0D654A5C016E6C776BA3D9D13D78CD7C5B640BEAEDAC87B16D12DE8BF4BBDF77F04A917D70046C285D6CDD3AF7284C2DDB5AA9016DA50207D2C28F52CC0B924D2515271BD986DCE5659D337FD9F2D939E192E310BF0D3A00CE794F0DB51D912630E4F35A04D94E7D9A2DB86FECFE8D799AAD2059D7410D1F2FA0DDBFAA343946A16CBE0D334C8DF591C890B3EB764E29AFB3077EE99525EF898C7B3D460CDB6B8B6F42D1A62813AA0F5179B95AA5291E36345059CE4066F9A2E8AA9411A70FA0D9E51BE77C21A5D7150411086CA188254437C9F5857927E6551D4D551A930D2FF7C8FBC0E5D9C03F584AECB8EB5565279F63AC74A1E9DB16EA8A0F4B6D0845372BB842A2B08A96F1D9A16BEA070CA72101CABEE6A2B17D5E33FE91C134D0DC7CF8A2F019937101D7C02EE727A56587E440AF7D82D036D5A124C1268BD6E32D73F896A9EEAE3B67517889E2EE99BDF8960A857B4D494BAFFD01E098B1C7F95B4A8A205644212A171EC485DD2CAE014962F15B1557ECFA9205DAEC5C5DB83D9B5642C817CBD6CA12E5B56650990FE46842C425FFE5C0C18D4669CEF27800A7A7FD3F34944B63BBE4EB0A41FBD6D0FCA12CFA457C72B122EE5CFD43429E9FBE78A38FDFEDF58724519E0550EEAB0481485453FB22FCA1C0A4FB3993B48166CB0B7F88A1609FBD833A866728747DF88B798DCB7BAFF64458567EF3419C9A659EC81B8329920496E82FAC7634BB7936AA6A467FD8971C061908A0F63F52E847E9D7667FF8C7995F457C4E0DEA5E9E8ECB60E8EE3BBE3CF55321A6E2E33C6FFE922AB56E6C494445451A1A0A9F144A0FA330AFDB58D3BD0A1D0166D6CA7AF21B86F0CE184F0BE6F1CF84609AA79E8D59D5BDFD7BC69A997E3D8B51B4C9F95165D9A451DE1342A736053BD21D538F9B1A43C9CA3621526D031344B51D5DEAF78F85BDB8BAB5CF11D6AD7B1F99DD4E90CC6B4B2F524ABB33B50BDE01D046AC09CEEDDE4D32225EAC2FF4D5E6E1B4D391C3A9D20D542214D03DC25462B60E8F5D80EC469FAAB57E4AA15BA50F94AD559DB5FD02FD5E334D5988C82EFA9B94E0A347757B81ADDF735753119350C0F3E8F3657BE5F58D4EB1E51583560B0775CDADE003C320FA6650D69674B3224318E8F51A17B4F3C9A5F9B3D9C1C3F6AC472D56EB9CCFA6FF592E8397BB30F558F12E290EA0333A6A0ED58A2EB1BA457FFE88888B610C9015A7DB11850D49011898A40E01C98A129DA9BDA8C64827879842D3966619A0388ABD88CA787005B7B69FE56066A0AAB8BD9D28ACE6AADC728E3EB30E16E4ED6C0F93670891CCCF18CE0CC7822E9CEB6D9E6B2B4F0F2DCA5382887A81F7CE2AEB122F0B7429C0E0D5BB32E53DAC5094481A2385D9F65B2FD2922F84D03AEDC4CA79C4F81F0A73386FFA7E5FE5B41D1571C426D88B18861FFC16311D61DF54F123A65DDCC2A6A5380F396C5B532A657BB0A97CCCE2F7D8C46096D0883CB16EAA8C57087678D9AE57D502E9C693DD899435DFC44F274B5F7F67A09F9C62AE0C08DC225B65983E3FBBC014000B51E3AC1B6290F135DE1FD32C6B6C049314DD7546E10A1EFA5A5A715D197B27408FC04AD61ED93A1FA08A764D2932060EF61ACDBEBCA8D6A16BB146FF0F6720BE6716292D2351B3F396B25015701B1827A8805204678ADF18AC38DDE4E2B27C6B1514BD197248FA9E88655E7DD20EDF4C9060653CE3C49D3B722514C421D0DAAB0CE802C7DE6A85C247B9DAF3EE936FE2823E13632FA91B9217B749DECECC7B4CC5A30168E0661CC142B8C62D5D056FEFA683EA4B06C74AAFA0170685D3F60E68CB0CE4F343B5F2900FA928557312A390F6744D47DB83D2B1917EB736B68383A90A14011A3C5EF48C7779E5BB6413824DFFB0B584420FCA86F7B798C33F790535EE0090E7CF6A0BBC0FDCA5D8A157748B4FE5B1CC64D9F1FEC367AC4D967712B7193F05058A35D7D286686AB611F1C4807B8F6B95BC021BCACD7EE59156710476C0BC628C387C1ED619BFF0FB68593502CAEC6996845C28489039AAD9BF5F0BD92776804ADBCE3BCBFE5F9F4FAA49DB29E53F6D047427A874AAE9B37A2FF7E753B7C712BAB4B128D88420CB0B8AB746491FBD4EBB70CE6AB653DCBE5A175E92D94DDACFB6F13094DC4205EAC3F85AC3EDED83C86DDEE0A9EF785DD42BEFD4299B5F044EF271571E5DB7D5349E47F14CEB297866621578F976DDD07F01698F8312117532CA2F68F57420F77CB85A8E0F1408ADAFB96D6BA04A0E6269B9F5D9121959617885F4F75E052D09DCC32C91F56A3E86832F6764038B61CF1DF5E6D588CB1028FACC7F99AE4082E5A604A5BAAA180845045993EACC930B64AEE680A9ADAFFE21A271721A3771EE60B12B85987CF25265D0ACF2C6FB55E762E877ED8E44266941C47F410A5698102D7E263F8530FB0EE9A26E0E5603A189CCEEAF7141CAA1467A523948869C47F4E2905E7B48A468FE615643E66BBDC55356E395381FC0C747ADF495233356FAEA046F2C18F2DCA0A7CE744C110D0E0B2DD861BB5080570DB0A2674C5F177E902E171C6A96BADB979A5DB94CA8F73BD8AE70B43C3F8E2B618097D2C796F7F92DC56092A6B0D863A04E2F4645C4817E42AFA9CDFBACF1597341DA1BCDF29F38B37B8BB135A937EC8D16BFDF3B5E1CB4C335FCCDF7F71522E7BF2004EEF77F9B73B5B69216C4EFA4DBDC170132F2E0B897A8D5DF9866CA80F54342B024ADF78B550DEAD9E1642483205723024A15DC37AAC36EA593E152A6F7F8AD2A985AABBE3F1171E738FAF2594370A0C330CCE5D06E23EB942EBCB8F68FA465FB98F8FF1604A4AC4A286629AD3AD552032A49FA27774734B8C8F0DB2DD6A28C2D4DCF2E07BF1969AC4A9F218939EC685DAD80D848A8F6E803DF90A4BD133EE88F1013942FB74E19333B4AE530EE5E7752EDB8603D0D9D962A9CDB3D2188A610CE5C6D71D6A508446BE79DAF26B866DB6EEF1ACF5A995C9EFA9B33256A9582DBB4773BBAC9DEEAC03175BC18D283E76A8815EDF736F4C3217E810807BECE4442A002B71F87F6BDED77E5780FADC3AADB2FC146788D4E7F6EFCAF95213CF7F954C210754A3E79164E2373306C87F9814A07F155BE50F9EC2968F5E9D1A620240DAD2FCBD7521D8A875F8C50E6F86DEFB1BBC6ED7E8A9E434BAD73AC655B507A7F306A1554E73683BC5626D9EBA5C68CA9017AF81F74DB79CB2C594ECE50A73C8AA927554A30444D147DB937D5664D480D85FD560225E6DF2CCC33FF2C4EFC13A9E1116A373EB9CE1A064D10DF412A0C989FDCFCE6453AF69131D21DBC2B0D2EA5690DD4C76ACE68101E8C62487E06B303B41538A6FA71F264156E58E3BB29726E527F8C2E0E8285A9600FECE97E8FEC1C23F3FAFC6BD9D87067888B619328E25178198ED8CF2EA8D064A7B4B3B23FCC20734472B21D1E953024A3EF48B6379D632663607D22B81D3733E5E0A91F2A923BCBD91869BC51392625D0AB03676E6F2493327BC2F3E22C372BD1B6F9B33979FBB4F0EAA539E0510348F54C08C8F15AD4164AE7C8AF54F1C350AB9199BCBDDB54F4A346345F8F3D2418CEC1ACAC26E0AA592417D341A561BBD234FD5592E98308464AC5075B12EC1CBBDCF6D755C1B7214DAD0D68B2E031001216D0F0E8C458ED8446C81C6A689E776128C8327153E8908A38DB062520C4674773AFAEEE925B3C147F2573BAF628B90451CD169A7CE7CD110E54FF4AADDF92D0BFA853BFA03DC7C4E56A0A9807F3D17461E018C0CFB45968788D8242B3F6BC497052C272A1D1F9AD87DF0AE450BC9CFD342C10B6D1B644607C7CE3A26E8502C3C511B4958AC2064F9341036687A2F60C1415484D044B9C1B311EC5DFC5CE73D419FA7F2FDA6A69DEE46B8B53304FFB8C6B54C28524C3F85AE319DD339EEA6EC82DB6F0E71A52ED1032A01E00E9197843D5D6CC394CD826938E3791CAB36CD64C1B96B9139B761FA05B7CE05B548AD6AF898EACC9F41EEC6F4913B0493C22354CF3FD33D7CDB1A77823945EEFF0FF14FE286D8C6C94D681870457EA2B17EB50F15F3A4FCC15D3FEE02C1755B1311C8AD40A953FEB72429989F20465C0614826D863F0F2B8B6F79506D1F4696049B87DEE0DD4F9572EC64E7DFA4E2762012D5D7501399407BBD1377A99D38BE5523D286BFE047F15A35470262B8AEF766EC1F1044BE8E8091E28337F2E6AC3CE60230CEBA94D7263F17631E7BD5AC570E4F8E9DB1295C47523F55AC69BCB6E700C96275D622DAAD8FA5EB8AC2D8596C66D9A36921AC8876DD857DF0CCCD9E995B42B9B4A35E2173167FFAD52C3EDF245E1F309A39463EE1AACB6CE436ADEEEADD3F23CB7A046AC04B1975643D26D8947B99BA98C8115AEFBFC68AE16161045F4AFB151FCB9A8B99B48DA52A16DA615960743BFC8D37DB87BC5267432EB1F3B2B7CD6BDCE900D18C7DEBEA76E74FFAE48AFB2B2F0D93BD7550EED69704645586760AB0D7A4E1EFEAD9E32C11FA3D2941403A4928F52608E56DA5841B23F9ECD188588D1E06595C8096BD8BFEC4C8026D733E6958366140C45E074A1FDDBE5E660287157668246664C17701CA69FA30AC21E2C66EB6FC2133ECBFDA9053013002A2985376E8C64E3DF2E5A1ED150A2A77DA3E48749C2FEDA06F1E4F2E13344348FCF64587B3DD571FEDEF9435C00D6B9905EC78C3CF2E2275B1CE57CD54281CD7B2653618793966DCBD52213C1DE648E00866BFF9879685D91367FEE3A0C860C40BEE995D1F83E3DD8A18826B2BB1394A3DC5ACC8D32ABD88AC3883736F1A87F1207ADC1DC24314AFA573CEC977E9CB9A872F42228CD3A3A1F2CDE0F5B48AAB9F8E57AA4DB21CD76CD4F6818DBFA5A6EEA2045FC4A5FC94232700411BBEBF3CFA3A1EA79DBD80B06A1756910DFDA987316433548788243EE97A2CA95E48FE04EC9B94409088D1A174F0C72EB9CD40C68F01185090D53C8314CD4A1E3EA7ADE58B834634D9684A9B7597FFD0F94C63E4ABCE55F0DBDF098BB25E91DC34E12B87FE7990E7F42AE93D3786BBB04EF4557645971CBE15361C9CA0334F7BC24060E7719B302BD30B03DF4F6FE0E4704171622F698F49A12A2F275B54F189D3CCBCC985E3484D6CF116B48838B7285FF2BA096B1D5922F3CE587E8E01E2D52D810E8F4A043E8E52961423CB4D5598DB0956D5571701CFAD3D7D82F6880C5DACC062B38B132B860E67D872C6C13B3A058DFB5EB2514D20349A672D4CBEA53A0992E4DB48DF060ECDEB36AE029F911F2D09C56C26659A3AB6B062FB87DAB85703921BEE6AB6753189ED1E66A6D114E98B09413F8D07C8056F393431A3CEDB33E90B8C599D41D1E62E95F4BFF1B95D16F29DA210E290E623331E35D0C751D82C935CD554F17D936A690435447DA2C31DFF0CA9A5FC732E9A9F2045AE04594F36DAE29EB90ADE939D701491E2F5EF7B3425161EBA828083733742B7D9CD69C6C51E9A574C2130C92C + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 27688 +sm = 00000000000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6936812CC6477E4A34C890D220F2C0ADF50811BF03F0A198DD1EFCE9B1BD475ADB107005759C1AD991FBACA5F12BE25CCF5A487CDCB35D2FA0415A48AED18AECF13077F648B8C7435CE755907418C55379857F06E2F7A61A232B67C86AC1352B9C6DFFEB95D5F828ACA606136DCA17F08C38DE5AEBF9CAC54646BF3B7809882E94D6C58C88F8FD5C2C018CB53B7BBDA343D9B0F76F9057BA0C56DE12931A556205430682E22AC918051D97466B12D2FC559413DEFAAFC677C8351565ACC58D4813CDA3DE3DAA746040AF1B2C23D07DE37701C19D709600831D7D504B9EE5726175C867B0E080333CE315D72777219B6350D39E366D591FE3ED9EE9EF63A3291ED55C6DD4C888FD4C8BDEF806EB73B632B3C27697F2410935EBD0B4EB7D4FE85D9C2BDAB9A5E9A5FDF318AAE6D462D982DA995A71471994CC82E5A293A2228BD645083110E6EA40E37B74D165AB9F394E7E8C66143A319C832923A83D13133CC09F74706B5F89A6A5C36351181638BB36F11309C672B7B4D234CD7E4537489406FAAC07D59B03A06086E043466BACB5E4DDAB7AC7F43409219F27561CA6168DD17988266C9B2D49652CB8CDEC30866F81F41B8F6EB6C6F5DDAE07C5E405A42EC217E50AA87CD6E7083FB9309F7536D7CEEB80FE10ED59DE83E6CBCF832280B1CE403B410AF91DED3E66AA5A849B0E9006B97005A133E7BE66BC295473961DF6C5935EA50DC699D5233C7C07E22FA98EACB905820F49CB77A44374C0219D53B7570BDECDC6DB095544CECE9268232729556E6339B9B8A2F22FEEA16F32E6FBA55778D3E7D9E51D6E5B2E8BCAF0DC0AC338EE1AC30758672A27DC09A9BE38957BAAE5F97ECD8B86028FF8FEE10503ECAD7AA2C80431D97F2F60C7E0AF24FE782584921BE921E1C2CC0ECBA29139E304A0BDF7123670D3FF614F1F0E22C7C8E161E91A68117C321B617B039B9E959026ABAA73BDB8BCB6E852AC7E661E2C316BB3BD479B46A3C3D7F58A693491E85A75DC3F8DD5BC0124C3C811236F16D02FC5A46E77215A1A303D5064C11C7DDEE11810F33E05292A78CDD6F8A34709B56414A4CB3247AA9757EF13771EA5BB3CAEE6D93AFA18665B2B6621EDD3C961C151179A97B4CC73FDA4B0851CE702E085953B9D195E13981E55CCDBA1620CB5DA2D599570A30BD9FC3023FD9559D895E07980FC00563233B57946EC04F8FC996E63DFD602DC132C6C621E713C34F333AE17767867E6E866D96C29B3DD48C7DC7C519070C9059B394DE8D15BFECE1FCE1884860BE12411A625BAD6A8CD7A99C157C62AC36B3A2F7D8C162BA7F7F4601025685E59E261826B1D9E9A9AC5B4AA1DD947CDAE896AE82981B2430CF17DF5F99AEC8A7B6D51DA7367CAA8BEA46AAEE4571D657D290FEA3545B757A7FA09AAB8ED0C941B5F91EA0A89DFE54737A37267760AFD2CC84A9F6A9548A58E119830C4A1C28BDAFB0F94E7539D5F73E2043018B8FCEB218AD24D0B5AF139DE4BF0968A70B206EDA0FF3324096BDCB13A3DA1C550639C0606508C1FA5D4D8C57C4450C792469FC166C18EF0134760323FF8BEF4E9E16C1C48BB565F6F3F7774A9CE75488FBA6FF0205FD45334A09906A3774718DDF36BB668C0E6EA958198FD4DBFA834119583E248955DAD739F078DD240FB8B5A3642BF5506B1E2CC30E6E7DC45BFDA37C100EB88E44069492CECC82E9E4EC8C7C2C9F85B00EC8AD191BF0B1D8C6D027A7C176BCE1CA7CBBA0C336D80411D9A61A5E4D093FE138ABA2002AE12DD317205ABE4FA332FDDFB4AAE669A71A0A6A402D3E8DB7E401A3F8FD69EC9C4AD644FC10F73E8D4EAA8D202E38A3609D1034E9A9460341D702019E62520710B50C76A82229A1075E52F918DB230C481D0350A33EA0E6C8A2D8670C1C475BCEFC9106350D0DFCCD2D1E46187432CB18B46F12AE9BABA851D30304EE94F6647F707A3583CDB82837D280DC501FE49B9D27AE13D5796BC047F5482AD8837D9292111D56E88AC70930176D14EE75E771DAF91316664D9F6F84B4509B13FB00DF87ED2BFDEA30928486A9363A6559C08A4ED761F5FC89A488B81BAAFA27919CE38E7D5550819CBD0F02A02420FC3F10D62E2E1436804B7F12E6B451A6AFBD1EF6E49CE8FD350DE872090DE73F0C124AE014920F104EC5BC7EA0FCEBE08F20F05310687E973E17F1B39B9436F1C1BD5CB39C7641828A7CE9326E53AFF9DD828FC436A9C04183ECC25BFC1E19A6B2C5CB182239761D25ABCF71FE3C2D1BB52A35052545FA899B73D5DA8D6340B3C2794D4A24A4FD388C8581C384407EA9429D048B67D56B413B9002434DEFA4F2F025658778DFCF9BF148E70A2A7084AB49FC4849D497AAEC8FA2A8C8DB244001F4348AE47425932E61A64C79846C2BCE8E0D611E1C6993589B529400771332F16F123352198A4D6872CF63F4401ADA24D8BAA8DD8A433AE2F58F188C064465DF6ADF6E57E982A8D5234D0F19650FF52D3F474B9AFB3DDB2C7606402D32BDFD91415832B3C3D22FF68DFF183D81F0811A8EC2C94C40AB226519C8D324F3069F4ADC08211A716C181B1D47ADFB07120B152898366FC0906F835ED4B9FE9A776EC249F3B7A73C8ADD42D2B17B5893635D1C1F7665FC12087A0DB4851503264508C31852B8741903D43BE0EFD469F89F28A87041F739E13504103A1A8324392800C0F640D6A7D75DCE2D69607864529BFC4219BC6D76EEEF5E7B592DBE80AB3D19CC9500A8ACF148F75009E4EEF81EDA55DA30A254D0B3C2EF633F5E04CDB10A20311D2846AB24749D78FAB6EC47F89E4A338CE9B8073DAE5D30A9571B807D43788E72A7A499DA5589B7C5BF91173A9A573A7CB1C938876CA58C9DEE64B7EDCB6BACA85C9E20AFAD6B68054B862DDFCEB991456CDDF24C6BFC89FB8A8757F940DF8DE473602610F33F655872E11109EA6B7E3BC14749E7C7FA2F28480EFC0784B9C5FEEE217946EF2D55F5FD2902B6E01B40AFF393D6177502756D15DB5232BCD58ABDB633EFEA7390FF8BEA443BFB32F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D265894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB939E6518A5122E37D4C257B0A0FD60CE0BA3BD55C9CBF369DD315A3C0609933D25DA403DF7E69FEB7EEE64DC3C13DC83217C2834B42876862CD48E99E69564B336506B85FDB493CF8FA87A7FE48DFE6778DDE8E8DD066FAA745C121480B5BF9D5F301B358D18FCCCBD24069E71836981F168FC49E6A4F27B00F6259B183B62CEAE0BF4AC0F53FCEBEB9052C0B48EB0666F361C5DA674B20B06AE2EA8783C2DD7EA74D98AC98C55748A368DF5B433C39538365EAE8DAE5E032A2008768FEB01F65D001AAC437781F742F536EFE2B3AE59EA12A6DC7F2712BA2D9D1C253D29B419A765985ACDB42BCCE5D64F6AF8368A5D122BB16B525A80C8BC5355A53917CC82262254378CFFDF1C7D6355F114E4FC013A5E4DD9AB373A0EFDC470854E20330BC00960ECBE882098D6D0D429A7AD19D3E5D4B78AC5E568C722A21877DA617190CB43123FB04333FAE5846953E33407080D04DF1417E740E7E7A14B0E3CA7D5B693F9615E1F7D417B9004F28D5002325B851C31F5EB31E1DAA80E6CFF22F11221E5180BB050888B6564A381E54401AF9409FE12A818B69BA34E1916092A0EBA24457EF994A1B0028649C9803045EC93CF416373F6A568856B771C3BB076AC265045ACE8E9BE3C3074D8806BEAA3B8B21F7E37F50B16221E14FE5503C615A13738CCDE39E2395E292119959CF686532CC3C9F9129E62ECFB43A091B06FD48ABE8C2CBE2D9691C8907881991CAB9D0D9CC7B2699F2261E5D799D26A7C8A4AEC40789B34CF5FE7BC8D24D6F0BBA7A5870E37F4D9B2605BB56ED9BAEB780CC74097DD8AA8741A97E22EC7B7434F81DE9D83CB9816A33C5A79D718C76A3442FE50C68FE1CE7AF728F2177F88E5168D4668518897AB050B57FF42AAC731E484B440D0D7B254383C74BE41C2AAEC02A8D8C7020355C4A1FAFAF4BBF56C74D78949D087259FE8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B179B32F9F94BBD8371B973B19E60C3CE2206A2061C7BCF159BC3A50163924774BB13C708A573472DA73B4C78DB30FEF310EA3643BC75D9155762D5B87809E2A727AC0428B746801D693074ED5245F29B8FF9FB782F2E57BDD89DD700EDBF12E8311946CAD9BCC98E3B1D581E678BEB1D0A6EFE15CF4052A1AECD328B2C4A8D5DDEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA36145D1653D108813E42654CB5350FFDB33BD2FDF4E416C6C0A61784E2327F42B2DA2AF040822C291D63645B0AC2377D0DE3FDBD99FF9CD9AAAE2B978C4DBEA95E330E90EAB0C4C34E88855C7C62C40B231AA1A9EB409D18CAA1C612A98F1B7BC25B18E3A89CAF96AA4BDF12F865EE7DB20273D7CA11970219BE997DD0EDE7A8ADFECFF1D90984694EF152346402207BD7D9166DC1B09F3C3520D109824442B8AB08869B0A4850BE3227E746998925CECCB422C4C05047D890E291B4E5478967A42BEEE34BA2765D86D183C71FB6A3CD86EAF457756FC000FAFDB24AF3C968E547A5223821BABF91B31B3F970D9F7C1FBFD16CC63D14243DB22CDBC266BFA4DE4B15D23B17D34C674649A695E80F84F6FEBAC0255BB155BD8B8D46FF7AFC532117E26985D99B0E23345F9A0247D834697804C6644501CA7D2726DA563C7F02371B5CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438DC67DF57A5B11025EDDC8915C57C8C72F6D6E71978496E206201184593506E39582DD2C803CE9204D2AC833C35BC683E0BD3CAD30BBCBF584AD38DAD30C9A400DE22F0CD6199FA6C622941E79F8C5C500389E9FBDEB8E1C926443B6FB0313DA9AABB163F5319C0164C1E58864827E38C18B7ECF6FB44274CCCB84B10F1A1BD76C8740F479777BDD7C557DBEFA9415B7FD50CA659E304EF4FA22680980D0FCEFC75E36231F740F38E9B4AC55BD8307F8AD9FE45B046B7BFF0F1B9FD5EEB82D474DC311A8418BB27CFE324426CD3311D65513B0A4D58515B94B8EE5ACC6815D6D1246527188E7B6C579CE42B28E1F273887FAFAA96D44FE6830E96081ED562FF4A08416DE4213A89CD666E2814FA290A5B1FA5AD6DB86B9E4DA85486E11BB36382C13607F50EDC83909F47A7D089CFEAF4680A6F2F10A2D9D9A679AE82D2DB387C5B7BCA11161E49E01C28D0FB7FEFE1C9A4BEDE994DEA4087F3B74906EA8E49153ABA49BE0F35C0572E9CE0C68B2267884C4BC4AD32BF28CE64DC7C825BDB2D8561C69161E075F48A40220159BFF1C4158187D4DE23C85979304DD4DBB98BAA57DBE6B7C55C271B134D61906F6ADBA4639BCAD3C1A70DA04A9409A4A35FEF1BC103D4F17BAFEC37C3F108B31327E0FB227E0E2C5B5410726ECC93B56D4D153572C2DB4EB4757F5B2232C475EB9802FEFB53EAC7BE6A090AAE98027AE13D2B338442FE6EF2DCF141C4D1AF00C7B3E973467FADDF6F1950ACF2BE908FED354EDFB147D6AC4B0740F87DE06E768293CC83AC995760FE0015CAC682036CCABA9C86B9B06924369E35688F7255F5D5422AB808D023B150D62D9A7DE4F7A5D28689EB038E9EF9D3366C3D777AB6D1C33878327018CC51EEDE65BB5FEEFDB1442B9006C76B10B6CE9EE1B6E43306DBB0D9030E3A191DA24634A80063F6A5269E77543525E11BCF02DF82E5921E3225EC97FC5F9174E0225E8C5D08B4C093EA28A19D03E908426578661E107E5E2C5371D79C31F11468112A6050703BB8FD9ACDEEF8D0BC31E82FB4F7DD0DFE8AE0216582E6C86FCBC1E7B3FFDD921F220702D827F145D79D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CE8D216DC6F19C3AC0A1017837C31D76ACDBD48F018A1CB14E98848B66A59F09AE22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB96557964888EBFCAD45C491A2A3C44B7085FCA7C983EA4AA22F62B99109F6E425CDFF5D87105EDC065810CA3E055F62FB80F5CAFEC57F7CB47A95B14A215714FB345FC73E57C1574E38657755CE991FCEEDC5ED84824E0E4AFD43205E126A3402910DCE16C59C8840FC7FC5ED9FE6379F9A388601D57B366FCF44FBD2D0C15A3D8A4A28D71ADE5965C137996748EFC7FB68ED165D2480FE34EF58A3169D03D0395D94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB08391412A812DBBE4FF09E10661B7DD604481AE6EB2F89A1FC04E393B3353F7547AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6222D7DC2F78B2E3FC4C8CEAE02E3FC9D7972CA803061F534D39E4F02809C7A18A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F9536829157F62BB003C2E45042DBEBA9622508F9AACA5FE89F665A5F35BA7C26D93A84F9DC744354C73885BC59EFB657317594D34B561FC2A789C919EE08D5D68185BFB2A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E1866ED93157270FB47C81CC3076E5B381E6B03127E7AE78C54F5F35B2474F18A2461297462FFAE651BDBF3D438E30420A3BA5686483DA2EACD874CC44102C09319C10FFE87AB2099A185DFD0FDDB6393B2F61490D65F93CE565C6575C877246044FD52ED475831AFE194BB163D0FE5A023BBC435497C3C16C8C7A85FF92426B59E588978E29EC0DAD032330035B797471B74BE366FA75D79D35228004D3231654D5F301D6597B83258DBE9284121A2BB21EF66F40C17FF135201D18092FA6A72B511A456786ECE1FCFC986A28C744DD4DEBCB552C638043B0602343CC796834B13660A86C5E3CCAAA1845C5165074AEFBA7C52190845A95DC59B1E8D6B052D253EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D1B478E24D9EDAC7EC8816FA54DFDAB0F181E9E1A8A6CD77A9EC29B3E35544898EAA311411BA22E8BA6418CF252675917A88572E0CE98CE03457996BA4FD86D07C4FA2D3487400E484F4CE0A83CF490C49588DB83ED1EE2A93B78101144586427FF43F434D3A40268920A4FA3C64C0F5F4600A8E52E01CD8210965C4B212DCC942C68D589D21FEF433904C26239698EA85C32423EF7AE1ADC90744996C956FD5D0683674010173EE4A110DA2642C8E1C4BF7B5DD3DE268A3AD0A261A30AFB6AD7D54210702C635C3E707CB1F17053D475A026EF57852DEC1FDA4252FDA2E69BA95C866BD432139CA8A4E367960F85B2FBC75420737CA4843B89F053192BB086BDC0D739B2753DBE42E1D45877097F3B97FCA6F43AC15DF883C3B42D9F472F910DE579301FF7F57D9857890651B64B6C1E8A7E2227ACAC7154D97252EACF8BC5FF430E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD637170756688D9AD3002B3148ACF0009CB1C0802EB04197FBD2FCE168B5FACDD052DD46F9F0B0A34295557CF741102E7592C24FA56DEDA63ECB7A2149E406C0943E5E554767D166EBC95FAF0E9B20C1E530633CF8BD7AB2A66CB105E108C1793B0D87ABBBBA9A4679A05C94BE6A698F4758B8BD38C51371C8043FC79E749D7E41C04DC6D815B0D32A779D0AC6E80C1D56B03C8EF30F6F6CB73A089B149F46BD4671D7C13B41A5B1BCAD94C0552C12CF23352200198CD876615EDDA7257E3CC94B732D75AF6D67A67929458E2639BA4A2967D05F76C4EAED429AC246CAB410B0FC8806B84EBFE1159C88D6E71EDDCC3B956F33739AD9FF6C43168B54FD592D845A54307AD16E42AAD4621D33A037D47D1002DE1AE0BCF2ADD9B01895EB0E63742FCBB5CFDA14EC9C63D94E3387E0FC22FB1B93D9065DF33D03AFA7D156BA719EB9DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF1DF5023719932492A5EE2B7A3B40B7C7F6814D179AEEFA584D317D536645921799727CED4C3D658D5A425D2D3EB1359C975FBE1A2FB2D11F37098B7234A19628624F07698EC3658799436DB5CCE6AC18702D4F27548F61BABC4807826E95D23889575EE119A88256D4326D4BBB48D0F589C6CB22E7F95D49F6607BE258753A6120CEFBC2E6C502138AEA689B4EDA13FDC39CC0759F392860168C2BA881FF70632D05E797A4F52453418035DFE9D072F0593E8029FFC25D75FC7DE13309B0AE4509D8A315C31F0FD0F480B598ADDB0D5A8F945FE6C28C2421DDB4A0DEB478478A49D5E628799ADC5E489FBDBC9DD38686EA7943969A5AC97497B2C380CAD367A8DF3DADD2E31F759AFA47A422D2A5F7C44CCB028AEC63EAA0727231A8BB4FAC096D19BA50AEC9522A00DDBEB86ED6DEB298AB433CDB7B4F15EA4AE08EB01782B70CD59C57D485848B16B9C55BCCECC876AA99071A9A7599868A9BB42F178BF3DD0FBB7EB52A796801D67E250148584C46F3E96898AA264BCC3826317B5BF7DFF55B6F3C3F3929FB552D79FFC1D014C52965F50B446DFC1CFB3302D8C7367A6F64C93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B787B24028E369C59743659E28980F3776146D88956F5E02B3E3116B8292C2E578C8708D4B518B95E8FCB7C7D5C3B16EF976B20FD0E53DCD6D92301061F2588F693A84052F8C776D033ED7A5EC71E928DD7CC7EED8DFC585AA94D8C9CF92D9694377C0268A53536DB64565FD9F5652B0A3634B381121BDA48C2D1FD9E189991D092178D79AEE8333BB0EC988417AD6CD9DD0DCBF6EFDB0E4E8D1B38E2A3DD01B3EAAD55E1CCB1291C87E2A835E86D2E0C0C3642166D2E9BC98CF354E28B6CD3F121606F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174BE4D5805F128D4A9B00266CB6CC792C45CA4E506C8B2504D13AC93044BF3FB3357F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B82A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B275680E933FB83760E66AB8BBCD67108A95111001B9F8E85B6C96B4BBF952517D6330EB1C6AB68317C91468E90237214C46A5F496EE46E2E8069D65797581C01BA0B2DD1DFEE0F95C0AD7E426F877D0CD294CB0F3ECD1C65659D20594153630E46E4A32CA7D3B408B33227123C6449C4644192BAE44916FE60256703EAB9B2821973C8A37F2FC6B3B18FFE0E4C8036583B7E63E60A5EA8FE89401C8633BDC355FDDAD733A74922E73333FF9B2F9EAE2ABF957105197D92E7CAA56F91767E282E0910608FFA0E651B882398F8187E5203F8B56F788A4DE4130D211BAEDBE44B1DE0D729B926D5FBC98A1FA9EF01E415BE3795F085E28E1B32F86B0EC72DB22414EACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E947CA8092F4480FEC3CE1D8A6D8C4CBE3F7EB35919888B729C1CADAA559A42E1BBDA600C713EBB3487FAF3CCCC40CAFDEAE9B9C6EF40D5041B83973133A03156CE65E33173CC6EC41F0061D31797BF2D58C95B5B4E218AA783E09AAD39682072C6EAE7C52E3491E8B0345D3F6DD019D7DA6D9AE08FE40461B81D414B8D5BBE0672D892793121DDB345A2E5B1F8F3EECFFFEE5E425834717D59506DAC94BB9F31F00AC84767700A6FFBB6D93D4A9FC6F02C67F2710269A4162C284E0D9BF486ACFDB55A33CE915B41F167D533B268F96CE0C70A54377A5A76B1C8E992BD4908F6C9AE1B8A1129A6A94F2C1FA3EACE58297AB6E83568F0857FEBA399FAECFAC9FA94217BAD28BE66B04EF4EF7862DBFC7F9D86A69D63D84665C826910849A959626B2F95B16FBFAB29A97876BC2F43A43F841F6161648AA9D1689D67A4BEE2C859702320B726B0219DCC859A330C6C337AF2EFB0B9C8C689D2A7B92DC615BEF81F9488AC5E678E63D3E9C4CD4D2138F500D7967745773C58A8704107771E6AC93AA2307D387AF3CCF853E572E74624A7E40305FF4F57266A6BFBEEC78BC8CC981479D5A80F351588B5E378EC89F193C02A92E5BAB45E1C12BE0DBCAA00E85E73FF666690C4133023ACCD88989AD44530D63D54B090E115F6A25111B4F006B0EDBC73FFCA5B037240E88F9F4FDFF79F6874B6D6865B3B93037E272D66F1BB1EA9AD7952CE8F8F353C2910FBFC6F73626986970C6B1FA3F7D010A7DF2AD27ED28F727F9B6E10E08E9F23278C2C6ACA482528DFDD42021B690D777444DED9C912B2CD003DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D5023540D6CD04777ECAF4F4D58C64C158042656BCA7DFBBA61D7551154DC1535618FB3576C6A634E79E80BC56D4A77A32480711DCF387CC963BBC7A339C907928DBA6545BFEA6878A58236DC95D439F8F3061C099AEF80CB7128E0C1D3AC5841B65C0A738A16BA2EF4649CB510F512A819CD03BE1174182022DDBA30AE32DB5AB9ED29B2FCAF259886A4E479D5B5C118DFFA5529CF83978DBDC1B233C410279CC031E0EFD98F95DF6A32C1FB854F7DA54F12E0D0078F9287622542E551863DCB0B534DCA8EDE06545D0860957FF3A0C13495A47A669355FFF55DAC93C3357E5FC17274ACFCF9905705D6F32C7C6E6FCAE6086384B4939C70128CC73540E47ADC633EF01CD9E59A14EDC10AB0A9313ADC2123A4F3F3B4207CC9564D39F7CE86184505C432B568E4CCAEAA1BB93EFE4C696CA690F4B4EAC21A83E1860C5F26C6ACEE315F139E8C7543B2075D3FBF446058A1F0E0DC7893D9C78FB25914ACECE4664F58E03209D0EE1FCA892A9002B32FE67B0CD27E60F35706FC2BCE8A0F77E89FDD67DCAF4073DE5B72BFB56A87525875B0E27042175EAC158AB2D5A7B85C041FC13F81A9E78911686B33488DB258E31630B4D779F6F40E079F5094D31D70E74F2220ACCE407CB3491B80DCA95CF6126E9D2E955683F0B6BBA28885065E50309BD5E3429C626D547A87ED33769F9BFBB514F8792EB90F90C956F0148B9928189EE06BB40CE18932DB44AD96E226B6BB6A313DDC8CE4FB50C6C548BFA794FDD1EE7EAEA2F119CAA2E0DC7664B0136EE7F50B88FA4F4B1F0A665F36C56AAECC77D637637ABD7EE25BFC8B638430370B0F92FADBFE5C4F166A0B1FFDFDABA98EB3E5D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3C1578D7F6DFBFF09D46817D7C61EFDDFEC6AEB1A21EBD5AF1A0F399A2096C8E30821DCFD15298AB26911D40A97E78421AC35B6E8B47C483E1538E1C110540E6B23095AFAF8CCC9883C1BA2810AFDBC488849BF8E2BD2B63AA036BCE1BF9E6FE84C7C830C65CB9870A441512C55557F371276F3CA97910118271DC35F5A46454B02318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3FBF9F7DDEBC0995B90104C717FA2977F9559887204B56298813EAEFCE587F9D2DF49378B38F71833410D667351B1949CF406F18B0727666AA94DE7EA90B093CEEABA95EEE4D2DB043CFD3504F59CF36374C48E804535A76BB8BF67DFB39E03CE613D53D7515BBC8DF04062A185B7825FD3260B1B377B5D3CF470603B1900FC978329FE4F050A62A0440FA26E9B3D2CDA32E7F9FCFE6446B29FEC3639F068E56D446765B606D7B4FDA46826E8BB9E3FE9ADD93EBF3848B70C759922B63ADAFC8E71CA051A07FCDA3126BC8B4EAE41DB2031017A6794C6784FD8B93672BE6206ECC5F1396078719C45CEB31BDE4A3D503A56CD1BA60A875E2A5AC7CF340A79F261480A2A36EE4FE88106DD0976B8FD47010119D6D21982AF0E8E58AEF1BA68D4BF979DE633E719AAFC7A6C8AC6D127BDABFC3660711DAA2962D639D46747BC03BB269789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411923F9FC45FE90EEA617A4971AB81153088F58B488C507F5C230586CF967833C9A0DEA1CAD7FC139A9710382C46136E4F4007BBD729ACF06FBFEDFF5144533FBFED92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE598186E4905539B32F01DF3F0FA65E08B09F4F16719DAE9A987DAC3A28B2B9E001FAAAD0F03810E525D26529CBA1829D42796B65515D55BCD2315DDDB342591BE8E217286002741AD99A1565D106690A5D6277539266747D8632686C5C9061D5119998BAF8B6C09E61D13B2D91426AB98DDECE3EBC2CCA03A8B6591E2A1712FE71F847F486D6E177932521D9196CF0F637314E2329A86F733D95CAA0C2F7F08FA45A993F52B44077712B70116CA4A7DB6587E24BFEB70AFBF3A6F1A33F469D98278A6603810F6664B9BDF27388FA8C69CDD4127B39AD97A6E2432E3C2B6E0087EEBCCC54DA43837F112E61409D225BF5E5222DC107D698C0E571EE8D532C99C6CA353C02F2BC7233F1636D14FAE126DD4433CCBB5DA1C5BD079804FC920E7A7906C9579B18D7B78824CB39614E28A2091D1194C26DFBE86462EE24FA1FE24ACA85F912404458AE8DDCC5B03A0E0402BB689ECE763D0825A8D566713A013923627115705098D63351D22772A01D57BD39566F1EF058044281C3275AAB8C44F905DEA89F9D1ACD8FC3C5E9F2DF429637D635359D0A3D91D765C71E5DA37C2BCF29F1EA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23DDCEBD1114559AAA8C6621F7A7AD11AD19D6312097C99841A84C35772FF6ACF5E1028BD5885C73C78A719FE0D63D52E9F55509B7AEB252865C6720285208786A2439382CD03CA0BFA2FF1A45B734943CA586AAD35DDCFB075538B0850551967EE7D7E1261DEDE7016BAC7E1B447BED75C565A09D3F173B5F9DF4CBD86780F35E9D7D62E54A2FEFFA0FCFC5CBAB99D2F5EF5784EC92C6A9C8DF06FD4491E197B153B084BB9A5F629E4E7923220EA7981AEDC10CCBE387725C16BCD5A4CFFB3566525CB00B5295DEFA64574065D1173DAC40340878BDAED7D71811FF8EB1B55C9E3C8BB8BEB2D011A9D6DBA1522C969314EA2A7FF20000EEFAC8F760CD24975B2CD9D37FFF352B4B13CEC723C68A595E301D02E0FD881D3286582D5472DB230F77C644E02E4FD2118592D323D93CD22E55EDAEC15693758CA10E3F215E6814BC13E2DACC05A226ACAF6DACA3B9EE91B0CD0740A5B50E6E10013407A7AC9A58F2C2D41A8CC0BD39BEB52BB643AA89A1194312A69D6245A1844A03D0EE0BD92C46B5D8EA77927C48D23107C3D498427E8DCEAEAA36E368A58EABA0E06B97532BD8D2B17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A59CAF17D13F6E01699B1ED376095D3F6850ED50053CB56D83A15DF12887CC06E7B45D143CF738881A322557FBAA2381B355638DEC332B690F7A2C91AD96C5102819AC027304301756A1B970378FC0C627135DB8D5F6B0B75316DCF93F0955E37193575DD0C14961D776379DAC58F5FC1150785BBBA92D1009E1B49D7E3362CFA468D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E528FC4BAE4FCB020F4ED5EF4F2A71B9D225F7B7E6655E60877D7B7F3DCFFD8C4C77A3A3B36073A69EEE8B35F49BFA43AEC19ADE9CC7DFBB1F6A7AAFC69B3210DD8B9D2D54268336896CC79F76B441391662909A9261AE1A5D75C4F9C360AB0C19A94F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB11EC281F61A34DC4C3FA81C4C11ABA995BD4EBF44373AB98B000C9F53E39A9E09607A88AAC7AE6A1AB1E735E1D0F8F8D34253718687CFE01212B0B818030EC3F1C8F79574580A44C571456C431C52BA9DD336B1A5F8753263FFBBF6005A7AC41B11814D8CCE8CA7C6B68C4F9A56845611FD6D46C35562176A9E14B357EE8DF2B3F76950986449C0AD69B0BFEF0641CFFEE6CA5112F71E1978592018BE903F66F340EDDDF09089FB1DA7C60F76B3D92527D470E11455137D94A80082FC1AB8DFA33F518E348D50068DC6BFA59015590904AE41CAE8E6A05F2A1296D97077A04DABEC3E27E25173C60F955161EA514178875427F4018AE8CE74578E79E80310F069A611AE281EA56517083EE94B5B37A1493E614AE495D28CC5D8E5A6EA4119FF599BC8DAC4167880FB7EC2FF09007E874ACBF9CAF516CBD6E305EA8492B3FEAF23BC6571A5B800489E07BDB1F2C800BAF3E7D35B4EC997B21A3C29960A9FAA177344E6F9B9C59489A67E782B630D9CB44FB0F82922839403A85C7AD53A9F32D163A64DC226EAA21E0994B218DB931E50BC31C0E1B5651CF2098EB00153DC510E086B1FEB74661932A95116E04BF13E9E302A4CD3783C572CF52249F5FDA51AEE054682E7D3E9BE99FA215853668F015F5F788BC6DE4261C7E53A2FB9B46FAAF6C821BC64ECE7AB00F059A65EA3EA9AC7C64971F504F26D97B48817B3DF9DC46B3C106C041D1A136B4731AA2922B97DEB83A3AD798A719BAA1CC2ADDE4A34D5EA63188A0CFBD3407F3930647C3993848154841EEEAEBCDC2149D942FB644A671D50A1B51ED937765C0C2AAB1B35FC6E4E6DE85E82B4D87727BF30085AD56A27A796F53CB4D3609F07BD7645F7B32EC8B72E51592714D78514941E217E6A8A393F91A907BBEBF9804CAF5925756BB3EB09D32E125469D4413DA437C8BB4CFF2F9C23C6ABA4B90395F55E94E0113E372FDFB37E7801F0AF52AACA367BF4BF90C58D093771AF0991244B91BE5C251F9380444AA86C221D06D0BC12BD1C2DB949E7DB4A5DF1EFA0A4BD339B8F1B937F2AF48072CF8F69E47BC2E20286D2524A59F271852286AF9B8BB57C5FED3E3010743E81629BD1C366D9350DC9329BC839F7B8AD5B7E570C85EF644413F0A6974DA2CE7FD7194C30A43780D5146942339CE2B186698B8CFA564998F0DA458E36F2B66CEDA779C9E9957D987676AD23A507730959ECC0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2A75998AF280055E9105EF6A91BFDF40FC5FD0E6E97EDF27F96872351DD3E8C28F46AAC52365CF914A32E5C21626BE9E13BF80A1E7E616022639DB2A5ED92A119164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F4EFF891AF7D33883382B554819C5CBBA093B55E335D550DACD6AFF9DF70A2A92C1BA88F210224F8F1DFF0B420B6C2F673497B86A156F5F1C675D301F55D69E5D275BD43C850F39D321DBC76B0F153EF703DEF0FE7480D5C83EB1535F0FF92A37EB637DC3AB8D7C7965C8517131F5273B10A2B5E64C16C85791D41854E43BD503F0E52180E9C29499C45CE64BD97C0BA486377BFBE1C6EA2A84AE249C8AE40CF3E86989F0379B9D02694DA77F9E73560E0F38AFD05744E0A30FEC0D8DFF8A1CA3A0EC629144E96B590FD5F75D92F40E0FC0A1127486133218B844D932E038CD1B04DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BCA926D661B145AF5B8090D1A4E51D9CBF8818A4EBFC8FF1BD6CF2C76B914B8A7BEE0EB33F37ECA54E2DA3CBC29F1720DBF0A024C969D4B1E36326FB6F63C9195608C68A3D7C87AC394210D0F4CB7D858A88168FCC25B79E29197E2EA3B3D4A862B70A1D7F3251C75F02D476926DD863B778059B83198414E0672AA1F27898C8A6F035D26AA117F838EC83D453A0D5C49AA350B288F1FBCE59D86C8CCC99F14A221AA18A9F300DA266DCF084910890994ABCBD8185D28BAE4CCA4BD68D4D5790FEFBD7A6D56B8C78974F9A8675E6C410F6D5F7F6D254F1C7885F48F0391E1BEEAEC7437553D480FBA79F55DD5B19C596DC2089BCF9980959958F7FB7E6DB0358093379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E6B09F3A309D255D0B7A8B8430F7E9544A881EEB694C7282E20EA3E1ADEA50564B935D528C0372397F26B1497DFA3D0F117F7A6797C1626D1AACEC708302CB0C0E406BEF60B7F6578623EA59A005B804C009A38E0A615F1FEDABBCDA5269C9C48E148A143562E1A372C0DB9D8F249FB5A7ABE5928B4BBB17DBD747A57D9438774BAE2550A5B205FEA96912A2FFE3FBEF1D6DF372A31B1084F0715829C141B845551C086DCF8FB9BEFB43B417AF3426BAF6007DC2EFC3B4999D2A658B5A19CC61FCB3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E608E25F1C4FAED708E98E1D88193FF5DE2D33B178BCD345DAAA3ADEB8B1B6D7C3E9C2468F943A4AF0596B0AA480A159BB882857360DD34CEB848F5CF3481A660F70E49916F9A952B001E60F11A31CEFB39D3F49BF76159FF3E8B3570BBF5D759F5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7E5C5C61EC2EC722ACD680BA597A47ED44E937AA64C0E3523F1EA891BF01E2B92D54EE9A3684A122D33ACD2A6D14133A8DC35EBE37F49D59BB4BB5F24940C18E0B4B5F1349AB813E994AC43DD0420A52527147C9A0F4729F8BCFF0941B934253B98628403937D1E2DEA8BD23A2EDE0A7BCF3A2D66FFC7049C8D2D3D52B4F9479F6652462AC2D18DEBBA361721EF71168CC59501174444B5A2E58AF71E8DFC4E9F836156C1C844EE12FCA65ED97F8189FF34B8EED18C26508B5ABD7DC94DBFD37F18A514F66BEA2AB8F02DFBEF4D54850B589898EBBE0E68E9F864D4468C96BAA0BDF1C074AAF51CD47B20784CDD20DCFC3444802DF292D0B21D32A93F2DCF3154860EE0F469CF0E8BCB4BB474C2C0F6E2F97EE8C155EF5B270FAD06AEB3336087B314915E7CC95153698BC2E486441D1484052BBD641183C9F5495CE45B270E5D085F4DF45707C7615CC89197B2646196A2F382EFBB8436E3B0A09CB2384FA6D3D7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC776AA5DCD1D7D1F191AB56003FCCA1F90F9488AC0C010A6FBCF7CCC51AFC15BA2F9E678B9B2D2B44DE9B7C841C386126135E1871324C9C7D3648DCB8213473E4D006FBDD976D2854DBC257DC1C21E0199C10AA0FADFBFAEE03693930F970285460EAC6BCCDB873F2AE73A173F17CF6C07C26B3FEDC0E81E8EA4FF7D68CAACE34340EF1990F3BF44E23BF65CAC9F65B50E4AB2ED67F01DE310314B56B351691609FD835399C51AD9B35E4118BF3B26AD5DAA9A0609CE6A24C8D2A1244709F770A655DF9E80C0C7441917C8329446EB8FB371C506EADD1DFBF6646E0790637395A2C1429C60252D485BD99EB641F0FBCA951DF3698F69DA2B8E751BB02BA592AEA7DD21E7B961499C0238B93F6AC1FC73DD562C80D39493800D0A0A594F26D16FE54EE71B5AA5CCD70B5F1ABC79687AA87DD986F10FDE0002EF9D964E80940FFC39C5F2FDFB81C190A83B0AAB7BB176476712EDE00F6F97973B9FC6061EB404C24993B85BD7BDB4582903BE253ECC3C10C0B65232F5F681953B179E19D4246B0799477359E0496BE7925D46065E4AC4B5EACFA466A8DB0A62F1D1AD326063C89539BBD517FC53ED562D98D20D8A7CE4FC1404B3BCEC7D500F4573EF14C99BCD70F290E6F4206E9BF9E4052A8DF39BF57BAC1969CB4D85E43FEFC1907449AAD6475CD2A7B9F962C315ED6DCFE913A2FAE5E1A695C5BCBC0568797F5154AAC68A30E0EBB8D2F73E6975440421D001AE2076AD1C65F3ACA6C05144A65D535C89243D6F099CD26C54760517EDB1CE98AB4F9E0B6E3A06B3765D62E7812C38B23D6A92ADC6CAF95A256FB750DBAFAA6D3E937BCA9314331C3EC2BFB571E0D54D3A98D5D28522326681F2B91E5BCF4ED462CC90B4CC27225742E5C2286AD1FFADD8418B9B3FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B5705C3BC66A1916D1424D631E588FCFA838C2BF8BFE2CA2F5F6648E79942E3DA4B064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C479F17E1A29D5B6F18387D15E7AB024AAD60E6D68869726EC117084D8E0C42A3A96F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B18FEE5FE427610B9311F4173A555CC3D534439D074BB8153F99EF5C62288F9CD393B0C257FDF1AFA64BB68F3DCE632BF81FDFCFBFF93A4CF99D8D50805B18EDAFD09D086D586BF8A5D6A2026084C7DBDDE343F74C964ED3011E29C8683300EFBD9E93C68EE571CD156D8FE815579D8E5AEDB483103BED689A4CEB7EA73CB8E19A6994A01838E173EFE68E816CA53CE578B87754CB34961D83A611466478E9325529D6D15C156B2E2E06E1F624139D230DD3A32A90AD2C7097F43119E10A2E788F15795548B5470728DDDB77CFD86A6C3C6669B9A2217BC37B15B8EA558D2B9E99EEB37E105700A324FD17A5A00803F41C5317FC2445C7216FE28DD0F15BEF50566BFED945796D4F3DBB97D53204D5BD64478A75484912749D9407C09D01CCDC391BEC54A4D43C9157D0A871195C731EB746F61A3F82D6F1A9807C2BD3B275553AA6CDAAE509A3A350DA3F119521A3DF789E011E59EE8138C17EDFA2AEA5C15841D25DF2E3A1FBEE40A3CD98C275AE4FCAD2708F31D7354E4059D43FC5625858721409E990F1DAE7D7FF6B3084897B817D88A99C149497599957A667750E1CF446F5D24409E3CD2AE7F13197FA6705BFAE8C1BF36AA626D524EC10CC50F77B359D718734797BA0154CBC3CCCD88030C97386483EFFACEBA41E5061B95BEF6324AC98FD576AA2A8D264D05596B20200496C54C58146883B62C9051E5F52224294C996EA6B44F84EE277D029766D66AEA021467747DB5CE0597E5D91D92903B74DEF2A7100BFF8201F70D009B0963454C25351D8D43AF77A3E70C95BA5FF34747F55049243C06C036984C5C303378D475F841749BCB2DDE91A25C105501EEF479F2B6C68A60EB8F1A308E74EDEEF93E1E34A50CB272AC278ED9263C0DAE162B7C1FD035421A2CDA9774ADAF21B292C252B94398DF63894C88C4B5529FC5AA5A18E788D74EB6126C7FDEBE4D650E2871B25F37DB9EA8AB64FD4806121F4509D4FF190439B7A8690A81275D9C03CF2B51832B32DE2967485BF84E915F7BCA7647E09863CA48B37131815DF9E5F5A88535186C40F177A06B657B4437728EFA50AA22C45E49026053B3C2A3C554F1B2613EBE50F27CEBD3BB03C8CA17B22EE76C4200A0E85A70B6DFF7F511FA2265BB7D858556213C48436D573F120D4222BB1A5C924B2EF1605B4A1ED717EFAF63AE53B070D7C62B2F8CFDFFBD18DECB0C405E7575C6AD8CAEF4789D6164039F963F807C3B978CEFE718A83A68378F9156BF52F6A3F76E411CFFD88448BFB452ECC10CE99AE5F5E303EB099B89765A377868B0B2B3A0D631264AEE47BDA8FF3A92483D27CC269B16390B3ACCE3350DAA649AB53B9C1CFF2872B6C1F9BA67D9D22C6FBE01424A7DC815F968C77BE937563456A273992579C8E6AD585A0B3D38AAE13ED13B81D58599A43E86C4B4AE7825B358C6FB94BAD7F552544790377714DFAC7F17B9B6B3BAF2E5D6E87AE0D0769A39A5580D5347C78067D7D7C375A91B066A61E124E754549CF27779D43109D8E167423F13D05093CD1D31B7E6B76A89C6BA817D852775ACA8B385138C6CC73639FDA3AB6FDC5F84CD46DA221B2D437A51B54D43D98E6D77E31B07FF420AA12FD6FA8892C4220AFE432664F946E738DFF89EEBBFC16CB168CE1721738B4A1174265AEB27FF3808A80D3BFB6CB893D1B6B33DC27239E96108C6D0D20C912BC1EBBE7E245056220BE957E7B9D49EEE6C4D341AD73932D304798F0A0F04F31D8F70DB5E06E3ED2DA627D47E0AF1C2E14E56054A87AC9810B617A52D0DB5145FE4C2BF6D0D4AFB0F9314FE15167A5AD0FBA0C1454FBAB0705FB6BBFE5F7E39824E59DA24CC67B3AAD9491E7A40906487BF895E90F63CFE6D7C0984F1D2747676B82D09DFCCD2A8F6DD158C917DB81FDBE6213FE43780DDE17ADB969B3D64CD6BA6EF1F9ECC7D6F6207280078B10DBEBAD7581A2E8C2F83E4AAE8A26F8D1DF0F8CB45C690615EA304E5CE30D2A96C55696C6B1D82D274E9D5765C3E5D2D7D05EC6A202BFD0211B534B7C9FC684C7A72C2D619E9DEC4175477792BB930EB5888FB37198A6E1DCEEE6651038F5C0A15DEDCE6D1833CDA5CE4EE61CC144E7C5202FE532E0B274F2CE4E90D91F2BAF7808D0656D5A106EE157491277F92A36239D1CA7D26150C118F9ABCEDD5470A2A0069AC1BA97ED1CA9885FDF2B6750157AA5B72DB5E7C1140E1FDF78DC7FA04773F4570F4544281C2E9627E5F59CA9740A38B452C9F3A930956187079B4EE4C91B3E3D9F0F502F8558A092630BBA965FD8900E738FD1498FAC10E6AFDF58F32DC0824B405C0E1D962CB213D4D834D7D26199B9172CCA1A36D7A76DA603FE07CE0EB070AFD90E7A30D937A32D26419A002A32AD9043B1735AD3D0696AEDA5F47046F8A3134B8D45C090C0A54C70AE992A0916A49AE7F3006165FBC71CBA5F0611FA5140FC304CF49DF3081CEB754E9E87E4FB637D7E701D930EE23B6E7A739274EC3AEB90736D91745A92DCDC5FAEF42918E63079E07316C2F9E59D8B79062F1D816C536E8323F501A20A11D6FAA241A5CB4A04F8384206C1D4BA5BD2DC0DF41A69CCD6390270FF0451211B36B489AC95476493D812ADE03FD8EA165053401587F7A18C2F3FBF4960C82B30E9C7C30EA830FE7D052DB5A191C0F8DB73833839F0D7AE822027E19C3A899EDBB02AD49EA87E1A2D55EA6B010BD984FC6C5B12289B41264F9F2F23B8761F262598692F57DE1277F48B3EBD06762F791DAC23F5A5846795B4C4806EE0909163CF27111BE948EE0CB673F0B744707BE8189B059F6D33E52AC33BEC99DB223FD42F64BE1C3E8D505592A78D5F7D3E465A5E34C1FC7D7ADD80752A83CA5CFBDD7AE15AFFE7BC0A4BF3722EEC05E54482A88287D9850672C2DCDE120E0C7AF377659E5A3313D0FEAD9B350A80F0A5A4A480346AF02414FAD52E5108B911B7A4B877215E400B3FCD4E8786E962704A50EC2B2D2D7256777111EA6646AE8A57C84B56C30D704C4B914EBFCA60FC07CEE5DB943630CB07C872596E0E48193D8B6513232AE14EC985E19B27E231B2EDA344957695939677A09ECB8C65C93C63C6B08FE5DA691AD51D463012565EAE07805134DE6FD09BA7B3659089DB2B16DAB68A89406E67D63B3F0BC70C271C7D0295293CF5E174FE0609D593810EFAD6CD648BDF6D3253E64DCD6D2FA70FCDCEAF24B7C96A3E3E4B078E1668E5F6CB9A598FA202F0AE1DAD0AFC54BB46BEE1105C69C535390CD630A2BE448CFD70112A56A74AFEDC4CB48BD579FEE9039DF705869A1623B1596F77D7420B59F32801106F6AD8A16DB40B1ACD82415BBEADE36585C3BB47F37BFA7162C255542E8284D8EF8CFF88DB68A47249DCD14C1D2E8E5C44E258E9BA867902ADCD588A5A382A60A580458C8C59BD5F182742CA1BD6A52F35FAC26893D74C3D74429401712918098CCC493BD226EA8A9F8C7700123924131913453EF8069237ABCC4B851B0A868015162AB8B7B63B3110906B267DCCE5659F4FCA5298C4073BAAF392C5649B429D5E378557D5CA03C9A52B6208936AE2CFF83D7E28A3274398CB3586BEE9694A14396FA1D67BFA90524574B7DCF0E8C7B86C86A69FC0C2263B437016842743E7E1743802C4542DAC8E6A23D03A158BEE47F010F71E5D9A7063E26FE8C40B208160936B5CD4D13ACD22F928352902BF25A8C8D294B493907F6794A4DCC0E7CE621FE45CC6E5F33199D798FC6E833F9EA4EA54FF6A465EACF2EAC6864D3CD0057429D789466CC60CD853B829679FCC639446CB0657C15B869BFDF27AFB572303E17FF826F8C4EE2C747AE330858830F70879FC8FD6F8D7CA2BA986E5D4DA1B613DF88CE09212B99BA77FB3E3AF7AEFD4FACB02B3E3172AD43BA87A4433CE38E45C1DA3ACE463315CF5A87B14CF4745D5282B17B613A033A9FBF52A40D8265B49A49DFFFC6C71377C20F4B3EB43FE7D89D829477619A7E5B2F7CC9FD0299C838419661773087C7BB3573568DB256F94E57423B1AC21C0662B60F526AF49629B7A8F7E833F858E5C7423437ED22E6E704EA66B26E79878EDCE376E8BB682EF83EB4B9600015217C1219224381665C140C78374B80F47511C48B5238937464F3B0A5612D2F1FDCC91B74CD861CE655CBCF22B68F657EB7D8806DDDB03B4F08E52089938121B0F6B3ECDD2D23003C889FD2F9A4F6D3D4358976641511DDF513181B1C86DE10522AC021B6A301249FB9E6DB19DF42C5BA6D53F1FBF9A7A2249C516513522F8702636F688145B52B1FB6172CA96F59B9F845760677D91996B38371DAAC111D6BC59BF28F19B4E00B5E312191087255D008FEE158A8E1619CC0674E12DCAB593EAF6C99C9CBE9C700B498697A725E2F30EA74365F3CD3318AA1D0D7C07DCA4F2F6C3AC8EFF0501F8F65A07363621059517EF1BA27310ED930A1A1B0D4DA322D5FD13EF522D21A3A7D623FC499AB8648C1AA0CE2EF94316B2965A246AD7C8869E9C489AF1FD2DA40E3D688531CF77F083F281E012ECF83C4ADC97B5AE47CC38FDB41C7ECBF402AD42716821AE404A1D224363958B9E71DD4B3E77A16FC80598A3065E8E00F36F2DF940F4E99902A1D62D73470FB4923D3A46EF07E65D02963E1B5308121675F1C1973C656549030DCE1BAE145C7712A4879E2F3E219B72B673243BD71442B699F3A4E366C7B88C1266330282D0D9357FBCEC2F95AE54D87A50C8581597B0C24C2F77763B326A55EE924C4A492307610526A864CCDDF6FFC64321D570589BBC5F9CFBCDD95D0C7AD62DEC853875BA2F3C5E3FC20CFF99FF86539F37EDC56643EF7D70D0025B395061B83A100E1BE1D6096D007DC42082D4E793CCFB79CC5A06242518998D835B32B7E579AA14806AEB8A4F19E554FD72D2899617541C6B86B63AC60BD7B6185A7A86BC7702CCB91069ADA68EB4F117E239BB7A9581A56CAD59A618449EE02E2089CE3A1B97B22AE34BBB421F2194B00B80F1841480577415436FCC20FD60731E6E28138A320C9237FF656A5366890E492A318EFDAB7F22CDF81AE5CE56539034A8790E942E58118A8F141B2FC6E4559A04B9EF8827BB7C11D5A4CDAC22E42660082AEE184078053860369D354552F1CB9D798F3FDF657648A7D5BE4F41E6141FBD80732B6D3AB57C0F60D38848FD33F7E468BF7600E16F25B9552688D3AAE33DA731DFA536059D24AAD21AE940CF31E18A40508DD1623FC89EC11BE4B852EEEFD56C002C1388DCD5C54E0524BB681A25E076CFFF94EA7B5E0A0B7DA1DED8DBE3F9770536FFD43BB48C9E55E33554E5C0411BB823FE16AE3CFE51DFC9177764955DB39B08C627F74A7B9A16DCDCAAB1CC31E37B0D3B90ABA2F1EC00FD2EF6E4FF3A15358C551BACB93EF59361567E0834E72383F4EA2E8F76F000EE38B179F7F0F9A3351C5BFF81B49E8A5119C6CB5CFCF49A6875B3A99CF14E6CBABAC0F4F38FC97CBADE13BB807CEADF726AD565D65334539E879575702D58462BB2A7C7F322A16F3F1C4FE116CEDBA6094EB4712D774B8207189B700C8B84FC7D0DB49B02F7AF17A6270BD75AA54F8A79E4A1A6D588FEDF94C0829EC1496988507C8C5BB87A70DFC3FF6C7F985ED38CF6C23E04FFC8001C2958B5E0920B284A4A3A55023D13D4FB99D392A0F61281E6DE6AD1F907788504F80477B8C21454E4FF16236E42DF95C85E20DEC39B2920ED49AA540BF504E74627B678097B4EC800A37698C32118BFF564BDE9BE0E4B16A3D91A9A83FBE991DD88E7341BA96976F7694323E523B76DFE3C52F28188C8D64DFB1341EAFC98C9A28CE446C4983AC52A1C38F9CC5D8CAAABA4E8BF9B7E45E3521567A46AE5166642E89F8503F892F522A447B2FCB1BCE2EF4EC86E22F48FA99555DC193F080D3F0096A47BE3C2597FE83A27E8132D28EB55AE87B36C93F31A9E371BEF51E405037DBED6CC4916E5A855116586F7C34F33B3EE626DF600644EC881246E32B5716E9580A1733ABCB22346C4414E5FF2C085E2CBFB45BC77168F4164B7CECC874DA5594F6E8D0B7B6B36EDEEDA1342672A4D6925CA2864B93BC7F63994F8449929C3206E086738FADF14B1872973A6093B5916E565DC3B354FC544A44202598AC2326C5EB9F305C448CF68323DE4C5BD28472B340E43DEDCA0DC290CAA47238A7A26713869C6B4237D40EE2743BFCE74E5CADFC183B14075FC8088943F3B2E93FD3A96ACA364B9292413B2B67B43C855A898F877683FFA238C05E6F789ACCCC40C434FFFA494F2710C3DFA213DA7B56D5A4C273603ECE648F3E9D6EF1CBC0EAD4BFBAD01E0651103DD17A534A2CCD00CA53C713F3045B2389B81651E8E2C2B6629D127505EAE2ABD26F2086E9D6BD48CA6FC3BF98F99604F221DC203BCE9D61B756A89BB0B418249889529F7E8F070F35D35E572EFA012DABB16A98D0AC8A99E596A91468A1AAC939629FE780A45D8406B60D04C8E2B31EB7E28294FB2595F4E7071CD906FDFEC3EC3CBB02B03E38AF71EBE9EBCAE3DFC9A37E6B545DDC034C1B684A22B4C43569169D30694DA2D259C846541CD1FC1D4F3553DDDEB5650C0207248DED91C549B76BE830383E8E158E188D78CD90E7B03AB56FEAB895A3B82C1709F9FDE140EF89B847CF556D8D40BA06511E6B003080C2A9FA8E9B43888C41965DA5B6B2225206AA998AD1BB76E38DAA65F1759EBE6F4E301AB3B59D217FCD6C08C626143FE4B176E51D1B66839600593F01E40F7DEF55A9405B5F3E816E59039E3528A724CF0116508D784866E2FC9864778D5BD5F25DBF3C8023DB6AE937B028A471165990FED36BD793D165DA1A4A836FCC7B9039CE4375344659432BEB0820FFE1CE1DDF984FDAD61284FB7BF551CFFA91FDD3237950DBB9523C478C56AC1D0B5E7DC0BD88548A1946CB98BE05BAC55BFB535391558FA57EFAD67AAA9456D0F9AF82567AE1FBF375F69ED9B30324350C6FB4FAE7FEA4E7BF7012F515076835FA348D9ED6207D9A21A471AE1D5E036801694BCBF5268776EFBC9020F5101055D97EE9EB04C5CBFB4D9132855E2B0DB7C4F4C26B97A7B8DB1C2433BC12085E0E624896179924685837CF20258DD9D5F698BF4D1E5203F6CFFAACE82379CA26B15603786CE45AC18C296B05919A834CA0EBA4855F63CEE3BCA8FA2AD24C07D3B7B9F73ECFECABD9306C647F575D7ACC30ECD72329D51B7AAAFB919C0511DA596C23A520D9705BB6C5A4969346C30AF6D53D5A9032E04D1F960B87E0BE110FC1468A4E657BD55A832476E82A839B9B44199B12D51D3642F50774A9490BA404470C54A9249E772BCBB344597CCC73FA0919C4C67971C5195449D812F7A6979279C23B020C6801DCE5472B66B4457F56B7B0CE5C9AADB0955180917A72E93B10F4EDE8691ACA70109399FE9ECAEE4FDE5B687836315E7F16FABDD3FDBC2004D9ED41008D0AC77CE46DB9E402C14C08DE7C0AF9EBC927D40DA2D7C7DF9CDFB5DDAE39743E9A15C53A7999B3B35FD329FE1002975F668A2307221020F884388C0649E8A6EA76027BC254C948426CA44628071076E4E5C77C7F155AB517C5026032052792533A29E6FE7CE81A20C68786F9315C73A430429E2F2BDA55C4E3C09FA73081E19166F7F0359FA6B078F1B4EB95103698F9DF7610E30B3E801AF5BEC6D262A2B8F1D1EB0D00FA8B041F6AB95888643EE9B00F3E925455A0ADB35267FFA9E8354BC69AC46E67106979EE5B75705D80550D7173CC407A4201127FCCA7A162F00796F46DEB7CBB36311A900248FEA298EFF33A3D645E28FD183B230841F4D848A1FB51A7319D5C1474A05694C06741CD15B251FF33E95F18DC944DA035532E1F27C654C302FE8BFC7D8CB5541008B01AE4D5E7C2A09E4E5D5C5B314B67DE4A03BEF268203ACF15A4F9A148E4072710AD9C94F78A55784558C32F3A2E513E84E9B1299FBE18E607FF547B1619AAD1D63A1C761DEC8A262CBF89714EFFA189ECAFA723C81D00ADC10B09B4F678A6710BB3C64569F731E7F1BA28371905460C7E1C877F398422C48D8232DD5204089DEC49108CBA8DD493418DB492BBA225FE73C1CAA7D91D6638A2662F114A40CAC9D1D6AA16E67E0DD281EFAC4D883A25ADE30D9CD44FB2E2D24054CAB5C527301CA96B020EB0ECBDC803B9C1FF07BC50CF6921CBBBC757A2EBA28D307F9B67C752443A9859A35E14B25EF675243ACCC36641991D00E03234079C0B53E8AC99033B52967861C85D548D25DF927EC74C8AAFA5F78884B5443D8F43591451494BC12F7CA33BC42C629EF0AC93F11B942F4C8250C4A4411A6B14774EE772BC485E2C676746083A0DE3EC7D0894281E09686D13A7E628A4EEC1DEA1F847698086CCEB661AA10F54755E8E7553502F5F0431D91DD4D66B963B213D615A0DCECF5CA6195EC9610B92C3FBE750E3912180D33E3F04B29842F61CD1454CB4D0302F2BE905BE49F82F470380492429A349CE86B0EAA2E305326985321D35B1AAED5FD3324D12EE14CB3FA5BB739696228F645A1E9A9063DFCE147C2065BE5E2E7741B20B29A037974174FD42F0796CA07764153278AF8707320DD6A820EF2A72EB981A82EACE9FF55179554DFFB3F8E1796973E86BAB1C22848968823EF74DA3977108CBA1FD67EBA4170539D24F12087F5954E6FC086D915A2037E7BFCE97A394F987EA1D6FB7DAE67765939991E7F2163C33DD20950E0F00A4EF163CA7A903C0AAE22A6516C172D54A73D4EB181DEC2B1BD62671562D60192F32844EC777DB3EB698A8575787EE699402A80F6E2AD283A6EF387C23A4102463C14E2EBC5A0FACCDCBF0E359263792DAE6DCF0E2EC202ADFFA1480357A3B722DBCFBFEB8D341FB67CE96AE936A36D42113F298E3125289FD8617DC69536B2E52BC81E903A7E72CDF15A0FE289C51C35F5A04237B797D1E3E71E09FEEFEEEBA7F14A9BEE50D4ABA48BB2F39B0E6702AADC8A93BBBF9496A15C7F35AF67415973BB58626E9315042019E1D35F768D377035870264A1806AE7A142ED4FC9A3EB4A9F54185E990889BA19EA36961EAFD483802AE4AA6E7FB34B1F7A6AE378C229FE154FCC476AAB6C23C524877DA7BD994F8859B7B9DE9F841EA055A56469962133E231EFE161886085944D70F07819D4896F6E63F5A20F4EDA06DD45EBCAFEF5D5B384E7F0B2DD10809D9B84885385C12C5345DBE856A4E2513277E576581BFBC6D73F085314E0AF1D2A3364532D4EBEF4F8F960201DC635731765B4FEFB8D13C18626D5D4A955B1FAF6E5D65B87CEFA18B021B72187365C45D6FAB5B2A4AE7060C5479124B5F5CD2E6D6496E52BDECB9900686BC6DBC0848C8E71FC9D7740405ED290C5AAA70A3126A4040C5966DFFFA6CA4D20BDE82441C973D7E639F774C806964B00221ADFD7C60836F032E794DC6B814B9E36EAAF0AC330407ACA11305731003502A578C9DD2556400086DE1A137176E752AD2A0BA318FC09DC51977725ADEC2F5CC4D71BB2AAA373DA9EB4A01F5E7DA252F75FE7B94A3F80E9EAD1863D1A478E5E6D63702D7730843AD460B0522D28F9EE1F5E6AC01DBE3B76671FE88C84A4357C76C316723D855FCC4372ADE20F8746B501EB76E62E66AE390961FD58752D4914C7CA53CD0B83E168C40777F8F136502A84B6C1A338D450ACFE885E77790E4EA399EA859A3F37A5FCB8AD3679063566F14B36FABB97B125F4BAB4B60EE9B26EAB4BA86E1C81E61C1A4103D9BB2D17389A93D792C203B005A361C41D2C620CDA46919CD9F7D30E547F62CFCF3BAFC540F5E6D9CC212792ACDF91F291202C4FEDA136CA6899184C53A94B2A2B2F027760875ADAD89484F21305226C8AB81BAF359B9A9399C4E71E343043B41FB814656E62A49F75D72F8B70EDD2B3AFE68C0449920ACE28BC7B4117CAD1B78A0ABC4069B742CB4781B10664BE256B345925FC0E56EC16437374426D7330716AE3F4FAAD02FD5B5F7C01CE23E9304914C8305B39309B9A7AC172E0C8FA63812A11F4A4EB5338CBFC2287AA1490D8166BD1866CE08654BDE8069D65EDCED448117EEE3B3C69549CFEE04B802B06567FB33D41BA1FE380CAD9B3D3F732A6D065F84B401C78DA3684BAF9A559A548807ECD23CD0B75EB36AA7350E23756FBC96BDF49334FBF1ABE26E165804C5627A08B11AB1DE840350BBF7FE153011BB1BE7489EB5A211FC23BA240F5ED74AA2C3E84443939F4728AD938391C6C1CC808BF9EE734E81711868D986A1616E3CD56F1A61E1B339A057688C74A3FFA6BFF6EF62022D21CD6D7729746463A520065B66CCDBDD296771F9B5C002491191EAA0A72609EEDAB634DD69D328665D6109E9DE6284018DBD25F77234C556A474968445D85011E09E31A17FEE95798508E7762221BAEC3D6A4956DF1262A3B13B967154E369B26A70C16838260C63979DC56A02BB1E3953DEE601E69F5467F7CE20C1DC799902C391D27635BADFCD73242DB995F7B6CBC331BE00FF871DF5DB0F2A497B9B06DEE8C77ABAB0B27F2AA4FE1383668A8C3DBBDB9FC21F053171ED76E797F08043204E2FDFF63760C15373A120A95F9989194AD1D5126B4C224F0722AEB2327AFC908A6635BE840BE589401F1E97858FBF94B2295930A490117755D298A5D3E417ABBE3EAAFC8585E76C08CF7B563B2DED16B40538FA4267CDD3B3455783035CBF9258B5503F4F072D7FBF60DCACA6DA5AE3482A3CBAB760F774720BA86DCDB03E38B75F27D6DE9C06BE33B8B68983DDCF453802BEF21332B1F221BF653F58331116E31F8939F51D8FC63531DD0BADB161C8ADAB525E6DFA1F8C84C6A2AA557330DF4DAC68DFDB1D29344869792FC6E4AFA247A3DF68EC505CC8770F7B4805F2A8AF534629BC61C92A1B1C02D55656D7A19115C48616F6C813248C20901FBEF34EC0DE8C429174040458C3B431A62D2C57CE4BA13CA80063DE7BD6668384FF7CB02629C967538617C4F58E4CE1B2E26F09DC7F51E9C3548D9A99016438D9F98E2C7FE468BB5E4CDE479EC24936BE7CF353E185385BC82E7ED9A11C3193C00B923587E98DCD268AC6035FCDF802B733497FF41CEDE795BE3434A5BEB065297A701A24EAA026A4A95B5DA980020C77714A463521794DE232AE1A538FFFEBDAB46C8A6A660A338F932184DBFFC9ECE13B8A8D5808FF2ABB614C39444AE701828BDDDB7B91446894E323C9270763AB3DF7D0A4028EA99EB3823D64625AFF2E01E381ADCB40F1B7B833296CA35F17EFF716232FCA154ADC289A1C9ED14AC0E527E8243BC3540357EB5ADBA8800921611B48A81EC2482CAC88FD4693256F4755700FA47DE0807D29C71264F848D907F9C5FFBFE2581503A591C0ED2711EC0EEB80AD335F0E6435DB9AD543E6A1F881C52F867F51E5280CAAE4BF63BB222DD7AFFC0B1C5C63DCFB19E3F17AB415BADAF3A8396F15C20AD2B5A6C8603CA70742FED3128D6F9C52F3A8CC7B8473643FE4C54FE696885AEC9C1A02CBA04C5C81A4844E927DDF668ABE9A083B84FCFC15D2C747BEC2526CA293E8363F1B495CDA2573DE1BE95D2F5882C89CCF61998EEA4CF5002C3674807C9800D652AAE2A0210DD9C206B5D351C5320DAA89A79D025A365396BBAB9EF785BD4485B5D59E9A10559F3C6F7D541119DEFA26CEEBF7ADF3A0CCB0F1EF2ED7367F2EC87B335994041923C1924798925EF572912EB5C3A344B0F9724632BE4011EBAB92F9423514B19DCABA93A4A7C8F51C0EBEFBD86E50DC6820DD61C166A52DCEC9BEB5230ED209E9BC839F6F16C7F0BDCAD1BB429C8FB4403AE3A72304F178FACFEA00DA6ABA89ADFF21CAD65BD1ACDFF2F8F5AE0D89C25FBA430BC54F8B4C79A159E22750395CBF2A8296C49A74D1AAF4AF55E6A52445044C948F43E9E49CB730267A2AC636AFA84F96F935E8BC021A68CA506272C4332EA472F5A8DEBD98A002CC8E4332B542194C34BE4F493572C563AB7C44E93BCE4AE67DFFD6FED96C3F3CE2470AFB2DD4A0FF01AD6FD485649B1F262CF8C86E51D41686A9E71CDA534E02ABA6C832E92E3B664F5205509B774211D8634843245D3553D8912EAB493A8825DE21810ED60C61C3C51E702207308509BA05E78E6DFA755EB4660944FBDC0DC8AC53DAD237DB0C9531FEC555425F4B1198A2C97F75C588E490ED7806FE0EEC48450D1EFFF90512343BCF48BAF528E30F3AC1A3BF72EBC51D872CB8990435B35189DEC662F45F327CB14DFA069624F20DA2346B2C556C9AD4F692A739829F4B967054AC1222F351E7B81454AA5D594304361BA49810FD0C6DC469BC9137AFFF98D0AE0CC13BACA774394A1575CF01339CEB8085DC985DCEA36BADDE80E50FB8BE1F6165A5B6976391A6468815FC70C6A5976109930414FCBCB070F469446F0B71DA220F64D800695A0CCFAAE22E876BB0B283C3DBCE83638D571102E894F9DA43C9B4C359063DDA0B86FC9C7D45DA126C7F06E2C9ED770B17E57E860B03C64AC7E9FDD8ED8CE95E2DBC2F51122FA2B6730151B144CB6C82E3FBA42C55A5405AC1E023840771F8EED666662AF35431A463BB569839A4871AA21C4817A0144A79720F530F32A682743B9C01AEDB95FED48C38C9793F59C2098E60779293D0F8E20284C2267F03C085303AE010171256C4787EE88FEAB7B31E269142887D2CCC30B8737772DED1A9F671556BFE43A7C381D764B6318A82DD7FFFD190222B5A33F79232EFB1E767E6764A9FEFAA5165B7645FD10D7E30C735EBB49038D582E2DCA81BC47EFE21514B20795DDFE04F114C7AFB4F91881B8C03FD368F3AC30437269B521FFDB8DE0D978CA78D28C716086F58B2767A2323D46172272FE6945E6FAB674CFDEE3C8446481D1144C9AD9F8CA0DC87D99E2FE038A09F0E9741814E09511540CEAE2C0E950551E10B4BED309E2F6E7CE10500BD8B00C5BE0B5D88B01A1AF25ADD068421C0F98CF345A597427D043CB53ED18DB764F4288B2B88AD917C4F0788488D1C56B7579C7695983135EF479D902A4360389A206CCD9652672552F9726782AAE9A57D0C64034E7F124FF75B1B55AF309F0E9B4597E24BAB8DB92814987D9AE26BC0140361E4528877C2C66668F2F7A127F63F5A43C2964894036C46F90A673040FB198DC50D9866BB956364FDE3B9BB6F2E9274D4A6E05AB919609FA3DA339C75A542083E1D6CFC6AE7D40C1EBE4D9AD9358AD16D392E78C086A682FC2CA00E386764073A121157F98A15C7FADFB9525D581A7DE84DF9B0293BC1B7961BEA4A894FC598CD76D6BE49CA389D3C6D06A4E79CB682BFD8D2246D1BBDE5E9754AD3B3F5F6A8DDAB708CAFF40909EA4DF53753D1DDE1C8C959F939DE10DE4CB937C21111973B890AEC27B06C8DADFCEADA3A211FAADE3411FD5F376CD1752B91019C3D9AB949209A344D24C5F4432B6354AE4B2631811990F49E16DF01DB78577132348B7D5A4157E60D7DF14798C8B606A6240AE45D6F1448314AB98AFD0D703266671192FDBCCA33B67A469D1F600F51C4A75BAADA71838D74272B41DBEF720DF137D57F208C195144527958F7EF69D6AE9631E899DF15B8EB560E372A5618FE7319296204A68C97DE9BCAB00296957F7A1955C8EEF4484EF2617E73E5783F8A3DD61BCB40A2F2C560CD6C8EFA96A9C58B73E0D654A5C016E6C776BA3D9D13D78CD7C5B640BEAEDAC87B16D12DE8BF4BBDF77F04A917D70046C285D6CDD3AF7284C2DDB5AA9016DA50207D2C28F52CC0B924D2515271BD986DCE5659D337FD9F2D939E192E310BF0D3A00CE794F0DB51D912630E4F35A04D94E7D9A2DB86FECFE8D799AAD2059D7410D1F2FA0DDBFAA343946A16CBE0D334C8DF591C890B3EB764E29AFB3077EE99525EF898C7B3D460CDB6B8B6F42D1A62813AA0F5179B95AA5291E36345059CE4066F9A2E8AA9411A70FA0D9E51BE77C21A5D7150411086CA188254437C9F5857927E6551D4D551A930D2FF7C8FBC0E5D9C03F584AECB8EB5565279F63AC74A1E9DB16EA8A0F4B6D0845372BB842A2B08A96F1D9A16BEA070CA72101CABEE6A2B17D5E33FE91C134D0DC7CF8A2F019937101D7C02EE727A56587E440AF7D82D036D5A124C1268BD6E32D73F896A9EEAE3B67517889E2EE99BDF8960A857B4D494BAFFD01E098B1C7F95B4A8A205644212A171EC485DD2CAE014962F15B1557ECFA9205DAEC5C5DB83D9B5642C817CBD6CA12E5B56650990FE46842C425FFE5C0C18D4669CEF27800A7A7FD3F34944B63BBE4EB0A41FBD6D0FCA12CFA457C72B122EE5CFD43429E9FBE78A38FDFEDF58724519E0550EEAB0481485453FB22FCA1C0A4FB3993B48166CB0B7F88A1609FBD833A866728747DF88B798DCB7BAFF64458567EF3419C9A659EC81B8329920496E82FAC7634BB7936AA6A467FD8971C061908A0F63F52E847E9D7667FF8C7995F457C4E0DEA5E9E8ECB60E8EE3BBE3CF55321A6E2E33C6FFE922AB56E6C494445451A1A0A9F144A0FA330AFDB58D3BD0A1D0166D6CA7AF21B86F0CE184F0BE6F1CF84609AA79E8D59D5BDFD7BC69A997E3D8B51B4C9F95165D9A451DE1342A736053BD21D538F9B1A43C9CA3621526D031344B51D5DEAF78F85BDB8BAB5CF11D6AD7B1F99DD4E90CC6B4B2F524ABB33B50BDE01D046AC09CEEDDE4D32225EAC2FF4D5E6E1B4D391C3A9D20D542214D03DC25462B60E8F5D80EC469FAAB57E4AA15BA50F94AD559DB5FD02FD5E334D5988C82EFA9B94E0A347757B81ADDF735753119350C0F3E8F3657BE5F58D4EB1E51583560B0775CDADE003C320FA6650D69674B3224318E8F51A17B4F3C9A5F9B3D9C1C3F6AC472D56EB9CCFA6FF592E8397BB30F558F12E290EA0333A6A0ED58A2EB1BA457FFE88888B610C9015A7DB11850D49011898A40E01C98A129DA9BDA8C64827879842D3966619A0388ABD88CA787005B7B69FE56066A0AAB8BD9D28ACE6AADC728E3EB30E16E4ED6C0F93670891CCCF18CE0CC7822E9CEB6D9E6B2B4F0F2DCA5382887A81F7CE2AEB122F0B7429C0E0D5BB32E53DAC5094481A2385D9F65B2FD2922F84D03AEDC4CA79C4F81F0A73386FFA7E5FE5B41D1571C426D88B18861FFC16311D61DF54F123A65DDCC2A6A5380F396C5B532A657BB0A97CCCE2F7D8C46096D0883CB16EAA8C57087678D9AE57D502E9C693DD899435DFC44F274B5F7F67A09F9C62AE0C08DC225B65983E3FBBC014000B51E3AC1B6290F135DE1FD32C6B6C049314DD7546E10A1EFA5A5A715D197B27408FC04AD61ED93A1FA08A764D2932060EF61ACDBEBCA8D6A16BB146FF0F6720BE6716292D2351B3F396B25015701B1827A8805204678ADF18AC38DDE4E2B27C6B1514BD197248FA9E88655E7DD20EDF4C9060653CE3C49D3B722514C421D0DAAB0CE802C7DE6A85C247B9DAF3EE936FE2823E13632FA91B9217B749DECECC7B4CC5A30168E0661CC142B8C62D5D056FEFA683EA4B06C74AAFA0170685D3F60E68CB0CE4F343B5F2900FA928557312A390F6744D47DB83D2B1917EB736B68383A90A14011A3C5EF48C7779E5BB6413824DFFB0B584420FCA86F7B798C33F790535EE0090E7CF6A0BBC0FDCA5D8A157748B4FE5B1CC64D9F1FEC367AC4D967712B7193F05058A35D7D286686AB611F1C4807B8F6B95BC021BCACD7EE59156710476C0BC628C387C1ED619BFF0FB68593502CAEC6996845C28489039AAD9BF5F0BD92776804ADBCE3BCBFE5F9F4FAA49DB29E53F6D047427A874AAE9B37A2FF7E753B7C712BAB4B128D88420CB0B8AB746491FBD4EBB70CE6AB653DCBE5A175E92D94DDACFB6F13094DC4205EAC3F85AC3EDED83C86DDEE0A9EF785DD42BEFD4299B5F044EF271571E5DB7D5349E47F14CEB297866621578F976DDD07F01698F8312117532CA2F68F57420F77CB85A8E0F1408ADAFB96D6BA04A0E6269B9F5D9121959617885F4F75E052D09DCC32C91F56A3E86832F6764038B61CF1DF5E6D588CB1028FACC7F99AE4082E5A604A5BAAA180845045993EACC930B64AEE680A9ADAFFE21A271721A3771EE60B12B85987CF25265D0ACF2C6FB55E762E877ED8E44266941C47F410A5698102D7E263F8530FB0EE9A26E0E5603A189CD896E231EE5DE2FF695736AA9B93B48C13D6D0F9E4EBB68A1088B311D3E1696610E7DBA6023AD3BB4122BDC83FA28938AA6023D1BA84752D897BAC75911F9928A4585F3C071FD858EC3721BE2A9F5FFCD260A7A5413BA2F7BE17E59830A7DE2299D83F779D0C780EFCA74D6D71015D7F21F54DF0A5231A5577BC161BFEB7F6B2A41B5B9A3661FCCA56ABDCFE63F3B49CCEF00938CC038FD084477C91123FA149CEEAF7141CAA1467A523948869C47F4E2905E7B48A468FE615643E66BBDC55356E395381FC0C747ADF495233356FAEA046F2C18F2DCA0A7CE744C110D0E0B2DD861BB5080570DB0A2674C5F177E902E171C6A96BADB979A5DB94CA8F73BD8AE70B43C3F8E2B618097D2C796F7F92DC56092A6B0D863A04E2F4645C4817E42AFA9CDFBACF1597341DA1BCDF29F38B37B8BB135A937EC8D16BFDF3B5E1CB4C335FCCDF7F71522E7BF2004EEF77F9B73B5B69216C4EFA4DBDC170132F2E0B897A8D5DF9866CA80F54342B024ADF78B550DEAD9E1642483205723024A15DC37AAC36EA593E152A6F7F8AD2A985AABBE3F1171E738FAF2594370A0C330CCE5D06E23EB942EBCB8F68FA465FB98F8FF1604A4AC4A286629AD3AD552032A49FA27774734B8C8F0DB2DD6A28C2D4DCF2E07BF1969AC4A9F218939EC685DAD80D848A8F6E803DF90A4BD133EE88F1013942FB74E19333B4AE530EE5E7752EDB8603D0D9D962A9CDB3D2188A610CE5C6D71D6A508446BE79DAF26B866DB6EEF1ACF5A995C9EFA9B33256A9582DBB4773BBAC9DEEAC03175BC18D283E76A8815EDF736F4C3217E810807BECE4442A002B71F87F6BDED77E5780FADC3AADB2FC146788D4E7F6EFCAF95213CF7F954C210754A3E79164E2373306C87F9814A07F155BE50F9EC2968F5E9D1A620240DAD2FCBD7521D8A875F8C50E6F86DEFB1BBC6ED7E8A9E434BAD73AC655B507A7F306A1554E73683BC5626D9EBA5C68CA9017AF81F74DB79CB2C594ECE50A73C8AA927554A30444D147DB937D5664D480D85FD560225E6DF2CCC33FF2C4EFC13A9E1116A373EB9CE1A064D10DF412A0C989FDCFCE6453AF69131D21DBC2B0D2EA5690DD4C76ACE68101E8C62487E06B303B41538A6FA71F264156E58E3BB29726E527F8C2E0E8285A9600FECE97E8FEC1C23F3FAFC6BD9D87067888B619328E25178198ED8CF2EA8D064A7B4B3B23FCC20734472B21D1E953024A3EF48B6379D632663607D22B81D3733E5E0A91F2A923BCBD91869BC51392625D0AB03676E6F2493327BC2F3E22C372BD1B6F9B33979FBB4F0EAA539E0510348F54C08C8F15AD4164AE7C8AF54F1C350AB9199BCBDDB54F4A346345F8F3D2418CEC1ACAC26E0AA592417D341A561BBD234FD5592E98308464AC5075B12EC1CBBDCF6D755C1B7214DAD0D68B2E031001216D0F0E8C458ED8446C81C6A689E776128C8327153E8908A38DB062520C4674773AFAEEE925B3C147F2573BAF628B90451CD169A7CE7CD110E54FF4AADDF92D0BFA853BFA03DC7C4E56A0A9807F3D17461E018C0CFB45968788D8242B3F6BC497052C272A1D1F9AD87DF0AE450BC9CFD342C10B6D1B644607C7CE3A26E8502C3C511B4958AC2064F9341036687A2F60C1415484D044B9C1B311EC5DFC5CE73D419FA7F2FDA6A69DEE46B8B53304FFB8C6B54C28524C3F85AE319DD339EEA6EC82DB6F0E71A52ED1032A01E00E9197843D5D6CC394CD826938E3791CAB36CD64C1B96B9139B761FA05B7CE05B548AD6AF898EACC9F41EEC6F4913B0493C22354CF3FD33D7CDB1A77823945EEFF0FF14FE286D8C6C94D681870457EA2B17EB50F15F3A4FCC15D3FEE02C1755B1311C8AD40A953FEB72429989F20465C0614826D863F0F2B8B6F79506D1F4696049B87DEE0DD4F9572EC64E7DFA4E2762012D5D7501399407BBD1377A99D38BE5523D286BFE047F15A35470262B8AEF766EC1F1044BE8E8091E28337F2E6AC3CE60230CEBA94D7263F17631E7BD5AC570E4F8E9DB1295C47523F55AC69BCB6E700C96275D622DAAD8FA5EB8AC2D8596C66D9A36921AC8876DD857DF0CCCD9E995B42B9B4A35E2173167FFAD52C3EDF245E1F309A39463EE1AACB6CE436ADEEEADD3F23CB7A046AC04B1975643D26D8947B99BA98C8115AEFBFC68AE16161045F4AFB151FCB9A8B99B48DA52A16DA615960743BFC8D37DB87BC5267432EB1F3B2B7CD6BDCE900D18C7DEBEA76E74FFAE48AFB2B2F0D93BD7550EED69704645586760AB0D7A4E1EFEAD9E32C11FA3D2941403A4928F52608E56DA5841B23F9ECD188588D1E06595C8096BD8BFEC4C8026D733E6958366140C45E074A1FDDBE5E660287157668246664C17701CA69FA30AC21E2C66EB6FC2133ECBFDA9053013002A2985376E8C64E3DF2E5A1ED150A2A77DA3E48749C2FEDA06F1E4F2E13344348FCF64587B3DD571FEDEF9435C00D6B9905EC78C3CF2E2275B1CE57CD54281CD7B2653618793966DCBD52213C1DE648E00866BFF9879685D91367FEE3A0C860C40BEE995D1F83E3DD8A18826B2BB1394A3DC5ACC8D32ABD88AC3883736F1A87F1207ADC1DC24314AFA573CEC977E9CB9A872F42228CD3A3A1F2CDE0F5B48AAB9F8E57AA4DB21CD76CD4F6818DBFA5A6EEA2045FC4A5FC94232700411BBEBF3CFA3A1EA79DBD80B06A1756910DFDA987316433548788243EE97A2CA95E48FE04EC9B94409088D1A174F0C72EB9CD40C68F01185090D53C8314CD4A1E3EA7ADE58B834634D9684A9B7597FFD0F94C63E4ABCE55F0DBDF098BB25E91DC34E12B87FE7990E7F42AE93D3786BBB04EF4557645971CBE15361C9CA0334F7BC24060E7719B302BD30B03DF4F6FE0E4704171622F698F49A12A2F275B54F189D3CCBCC985E3484D6CF116B48838B7285FF2BA096B1D5922F3CE587E8E01E2D52D810E8F4A043E8E52961423CB4D5598DB0956D5571701CFAD3D7D82F6880C5DACC062B38B132B860E67D872C6C13B3A058DFB5EB2514D20349A672D4CBEA53A0992E4DB48DF060ECDEB36AE029F911F2D09C56C26659A3AB6B062FB87DAB85703921BEE6AB6753189ED1E66A6D114E98B09413F8D07C8056F393431A3CEDB33E90B8C599D41D1E62E95F4BFF1B95D16F29DA210E290E623331E35D0C751D82C935CD554F17D936A690435447DA2C31DFF0CA9A5FC732E9A9F2045AE04594F36DAE29EB90ADE939D701491E2F5EF7B3425161EBA828083733742B7D9CD69C6C51E9A574C2130C92CDF8DCC3B3A8B6659B70F64725133A9FD36DE92C29A485C582BB80B5C6609CC4C7D274BB7FAAF35EC4D80F5362F198D5B837132D84273B57B21103639CA52F910FDBD585155A2BD052051BC9E8E43C7AA006A41FE7864BBFBA510253161545DC3E660490763A929FD7A5FB32773FF52FDEA9FE7D35C141D13ABFEFA7A164D484F75B78484DACBE33271095DB0A74F25E78B1C0514641F50D62A173D20DF1B3860 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-3_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-3_256.rsp new file mode 100644 index 0000000000..e407b94de5 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-3_256.rsp @@ -0,0 +1,12 @@ +pk = 00000016BBA15DFC230A90773653F36EDD994F661301535E235D0034A34B25B25C58531B04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000160000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94ABBA15DFC230A90773653F36EDD994F661301535E235D0034A34B25B25C58531B04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D9330900000000000121C29A3D4E6C5DAA979424FCA26B0EBE6D3FEA8F078FA9A98B0F55503C2541CE0A0000000000015EB6FB8267689B81BC8E2C8950E5F59F4B43194AB167C4A60EC9BCDA7572E5980B000000000001F02838F27F104405AA4D9E111D3A0B1849F6725926BA5B3A6412DEF900E7259A0C000000000001BA1EE79A04487C5639BA096A60E3E17F7A0E9C0238FA049EA7AFF52FAF5890980D000000000001B63504B794C356EB44A98DE32960830E6B275526432F232A7729ADA72571E8D90E0000000000014DA82230B909123D34E30FE0722BDD93EB6D56243518275547CBA7C473744E6F0F0000000000017AD15652FFFF1B8B9E752AD4A07EA737B8D79DE25D7F194E19ACF003E62C48F610000000000001D6819E585CEA52B14299092F01E66E9A6E7AFC9613A69B89ADE061890A230145110000000000017FB1A159FFBC19461AD72D4E385722A08E9A942BDBC3CF8352CAECD938737D89120000000000017B2C7FC20B3305327D2F0FC3C4854B0053D00E56EE4E005E43CBE807A619BEA8130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A86CB037675575D46C48D89A7B644810666979BFDDE595E1A2362B9961A71D9F75A4A72ABF56BBE2C07844E774123A5DEED0116677B286BB3F8BCAF92D501A5FF375487D2694B089FAF47D8632DA9E213A9C914689D9FD8B0DA5320F6A89787E198248FA523B9B2E910FE55F6127ABFE1FF1EDFBAFF132A06AB9FF0F2E368AEFC6AFAAE9F61068AEEFCAF427D37CD93FC0B0D226CDCF6A7C1F007BE2E59568970AB644D475E62D7B8E7E5F7BBCEA4D007BDDAAFCF6B84E09BCBC5553F516E2E5DFFFEB66C9F5EF34559251705C736FF66A96AD2CA2C40A368602DF65045808D87B7E24CE23C67906BF64C90CF0E0F8621537D08A09290E431737F9C493DBADF98C9E250E094C6F0F7E850F5EF65E71967F69159ADD14974C1AF501C74F01D1C36AEBE604A32DC02B676BBD7CE4BC3967FA8899F3B1F654E7F3E425ADB5ACF59B6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000018F224E19E61C8A7076585BF7780AD32D73D04D66A52F0B4CB6D35D9496906BFB05000000000001C0F7248E24BEA5635FD0F3F3411F1A20316CD29E2BDE6DCCBDEF8AFD463CADB306000000000001BFE2E0B4F4BD9B2B955C3CE73D4D0E703C44BE5168224D99756D865D86689E1607000000000001EB5D1F16948BBDEB3335E0F93C3DAC5C3FF7DCB33B16BB28D3826194192729F80800000000000194BC268989E8C957203F60EFD29089692A7FA0980912BCCB1FF3D6921B9805610900000000000182B44F3F72EC96002984E059C46042E3085A35BBBA6A0CA79700D29DB34DF2FA0A000000000001174A1DED5F222EB3573B2A6CC27870F2FAB30A64FFB9601B5B8167314CD3C4AC0B000000000001CEC1E018C94D354F99802059603298AAB121FB0D1CE89A6C90B945D90A6233560C00000000000184D0355AC86A5E83CCA4300AD4EF13DCF7D6185ADD1B29F22FF24B446B6A184C0D000000000001EF0BF8DB8426844A322EACD3C79500078561868864057744206E70294F1B4FBF0E000000000001EA649E4FFD3B7A864E5C9177F8B14D91BE4CFDB050B6EBC86571996AFC1AF62C0F000000000001F80F14346EB4A8387798C08955A0CAF061B367B1F969D28F833140663D9A4B24100000000000010990AE38170C318A1CB81B1C8C6D980077F153C1C0403EC9645459C3C222225011000000000001DDF5AD2829966C243C523B4B91800973741F27929353122DFD2F0F9DE717F31D12000000000001254C2BE70DF73E405F76FFAA6BF442F41018C0C2D3823AC64CC175A601ECE527130000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA072F8AC327FD013B98A44146A45192D07A49B3FE150DB78658E659EB8546072823C7AFABE43959B08C3E239FAD4B3F0E87E872FF749B1DB73E5E9337731596C9DCE65AC0A8965DCD720A4B978015DE82E08B56B7C9D2D895861C15B766F9AB3C97E87206A7B951DA427DECC0653B7008BEE0B34E5B8A9D486832469079EECE91552F6208FDCFFD2E81B9E968F16C7A6E718FD43A6699A0E4D2F4692F3F56C2E31C33C937720276C8362A6839A6A055BDB5737525429AF0ACC1C8345BE9A2E9F269938969EE47C53A6E06BF3D9896DD79382F4210266C3BBB9F17386003F120AE41CF9F513B70D94E5A0DF54A0D52D5632495C7D6C843BBA812723C1BA75A6CD8B8FDA61F39B5EE34DABF596608877296A59158883CA4FB0402E22AEF63B5E1658DA5CD6F3BD2AD8D2846B76F86A831EF9F8E2F2EC334ADF81B976512F8FE7D2B9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA240104000000000001806EBD8412403D61AFCBD000376F11695F17BD253F82340C13342F750D09B2D205000000000001207581737977FDD59550FE1E0E62692061E1E37C554529C52E427434D2BC50AD060000000000012C3C45D74BE1C78902947B902756864EFD771DAF34009F91281FBAD0636A74EE070000000000014DC0E1A0DD7194009DC2FC5355C4D62179DA0010E19737654D7DC0E4C9761DFD0800000000000112F03C455D30919DCE22D2F8A0D4B5491A8188A32F17059A6AF994ADE911EF7509000000000001D61AF779A884D53CC99CB056977E564D49F3190CB260462D33ED4C7F0C47AEA80A00000000000174597C0DE43986083F16D33DB5D530E1771AB7CD8D0FBD09BD72854FED1D42C70B0000000000013CBB61C52DC21D115B9BBB0BA69F63D69C35C4047DE852373D70E445D4EB8F710C00000000000149B8C0E29BD2C1508E64FCE039EA36B491D678210DA046FDA6F7216B6276B64E0D0000000000016452B2D12F811FCC1544588490B05FEE831CC4B55263A2425F4AFDB7C804F5710E000000000001862BEC10334F6E0D0E998675C7F4E33F5DA105D68125FB2A8CAA0864D82B1AFF0F000000000001892D8275D3DF4A2354CA013048D86DCCD42EC388A2C20763E351DDA579550C131000000000000124BE91AFEB60D60AB3FAC980149680E6292FD0D89B416DB25C3F354084EDCC911100000000000135E8282E4B19327B8509A8F740D4C94CECB06BB8857844D40E6B38A061E75FB412000000000001B78706158F9720D3B08696410F42566DA7B34846E1D8A586FC003234F885B75A1300000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000665137D5D47667E1CA8F1B70A9029441013DB1E00D4FB39DE01E275ADE1AF6E6483B18C34D78AD814C71F370A0AF1E681C1041FFFACF9685BABB03923BDB41701F927F3316ED4DA8420A373F5471BE4A7215CFE5683EF16855C748D8FBD21DD9A6C36EBDA9BC5497F5C0C93DDBD40A717DCE151B87E8D5CCEFE5E8A0A66B3F92739B24915DA4B87BC7E555AE0554A8FC1D2514A7979DCC78E92D79C6908005648F90E5E4AB32CBDE27EF1BDE91C49C5184A3CE134D7AD33A1AC03F4A09CC245DAB6033C99636D9F6E9A723429F5EDFE118C045EDA721EB21387225EE2764A00D99625EB4FDDDAE398DBB4D8CD926310601CB34D38B7BA4BF60C66925B2E66B838C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A3692F3176BEC212C8CDDA63B223901AFF8E3CA0612978B7D97E8F2E1C000B0D2FB992BE80BE6906A967BE9949853BED6333CB070A1384B5A26ADF28D3BC5ED2236C6699909AC8EF3CE18997A672EFA2087DC9C0C38BB416613F206E136D3135C4E39F98C7C1F50DBBD69337069248EC64C3E5C6EE0EB7618396BFBC2BA26667426721DC84D3A53129AF465CAB586A54924BD35CA4BB250865AE0EFE67BDF060D8F947141B55502BD264BE2F24B40DA59C45FA59620F207E10FE94013B6A9F94182CFDA5694E19B1ADA22B18F183D7DF0A51AE2876A5D6B79D911B0B8A0D3EA283DDE8F0FC0DA1D77498ADC4DE901F89F11DE2753E8EF674622BF03110CB519AE4F6CD0ADC41A43D1929CBE5047D9B09FE60D9075C85CEAE9C825EA53585D180FB610BBA83BBA2E590AC5257DF858E7F11B8298C848F2F79D78C37F00474AEF9B5E9AEDBA4C81ABA062F24531171F8137F7FCF50FE09A38F60404B03CD1BAA934D6DB5CFCB1DC552BF873C6AA9B5FE76FAE92D4C3674E20DCA7BBF430C865F6E5FB5D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF710D288F760D8E6A64D9E2E53F680C21D30AC1439A4A90469D0C6271AB6EFBB90A4F4DBFF7D5F3875C6507DB321D81C3510D7E7F48B297881DB6FA0AFCE41645FC93A37FF04FCBA7FC19B9089BEABCF9BDF44E2C4614A73FEC80C1234162B41BDF1313F6E13AE2C48A6C4CABEF5EDE59AD461384DEFAF1935E23F5CAB3829A81E2DFFBBCF2FFB141D975EABF78FB4BD484F75E08318C08B2104A468E670786397EEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA360AB78FD9219EA890695CE44CC785A3A4DD39CB8F3C82FA5C6A3167055CF3309EB06EB90826159619E65C5E29D46D35E61C961AEC002F87B44A2B7D5C0E2111D17268FC3B147434264112A2E95AADA6ED860C50359372609ADB174741CC3AAAAD1FB50A42A560BB18D12C228F10D2776DED26752930890259A5C0F64C7D30C49383F92F1EAC6B1E8D6BA05423368AD3A8BD145D397389720E80F6EE11965E467D4D5864E164E51437277F698BEDA846AEB66DA3DEF39CA3288D30C001D3B0BCA113AFE8AD333A08D801A9E4C52DF0DDD4C63D8DF7EA938014336BDCDFA10E960DDDB4B5471263D096A49E3C83A188C46AD4EA8D2AEAAD3B1BA78CF6F116D0818BD2F38DB39D74D340546233ABC52278B381B7DEDC3A3B5DAADC8A4E7519AC9F3572A35C016CC7A8E0FABC029801012DD7454D7475E5D8B492A119AC583F4043D25CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438D81219D292421651600D48C2BD291766ABA14ADDC9186764DD212446D27C3738D2F606A9654BB310288F37CF0ECD5D38590E4D887D9D5C523527007F6501ACBE7CF36803727022D98CB15BCC0A88A509DF3B9A84E99B41843283FF2E10FBDA3C14CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D446D278BBC90D6A56B71D6DA6FCA49F332776F402F58D180482B2EBA5132D8ED67144DA06AAF952EF5B9BEBBF0CC8101E93F3BE05E58EB75D55B3CE72B9C8A07725C61C24C34DEB9A7349E51256EECB7DB61510D8BF55798B060EEDF9F9551AA615F1661F544B0779B2974A54BE8BBA388D6D7FB8E2C0956DCB23F834025CAE4BF26B798CBD5938A517C4C3B8FD3B8FE920558256C391433854481944BE487AFBD226853E385D942014B393488D554FBC143B44F7E9F348FB79920D4AB758CAEC55ED8CD388DCE4B4381D5C3A9FF36ACF9948993CF2B2E03030646852CB4193585AC6C56947193F96292D813FCF3671D46B9DF2D99D43E0AB4F1994B81235A50D5D977FA3560CA3D46CF60945C8D3E1103B6B1D13CCFAE43741BE65EAFFB9DCAB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832D381248D668B0A5ADC623F2529B02CCE42442E86382E03BA3FAF21F86FDE1C633C9A17426EF1F4923824A1E394BBAF5058C00950968357FEA01AFA8303DAA21BAE4617293B3B19A50C88C8F7D8A677A3314640452734E7FE4BA483C8AF87356E6822D943C23705352F458ED80B8375DA6F1F0DD7688CBC6101727F2AE7FE500C98A185F29DC71EE3506F8425B8D7EA94BE228679F42ACED5C9162D6A0E9AF148E5903C0ACC117C2BAAF1EC4A73A0BF73CDC646D1559EB1FA607044B5C7CA60FBDD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C6F2AE696330DD7C816130134AC101764D6B4FAFA1E71A404CEBA3406E1996391AC35A28F18E05DA188AA8FB52712696C986C25F70A31DA73957B238FAE89EE0BE4F77ED34ADFF62BB5C0838F9B645F6851BCA9241ACBCD3038BC40F40F076D1CCD8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CEC2A8424E383ACE82322B3629ADA77D454B677A60A2932B49F844A9389E73FCCB04A4A962E7382E5125E529A0E244ACA7F30287FD74C8938A6CFD5FF3857622A676F9528968A73DCB3458A2ACACFED4EE0F6C6B3EFA7207E8F13B15A8F7DF45A3024EA2D0C6179540EF44A8DD43F70222075D9A11B4C32BB0822113EABC09D37D0925C5D27FF4B27EF82812B5609734A615CDB54529EB30EF57F70B1F177F56776E9AF34A592C707753819140669172E2BA4657977CFA700911BD68BDCA9392759431A2E164C7F420B10982E4AE55E77E15C2499B4F0685AA0FFF4C5830F1CF18E0C22B855FAAEFAA6FAC5D79BB0E504D666EBE0D8F8BE770CAA37FD9A4C254357AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6861E7E10F9C70FFC41ACFDF5DF7C525935C838DFF06C5468E647D8F85F945009A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F953682934476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC59CCB9D20278F8B155728F4234D7F11EA25B128E7283D09BCB5F54A03163FCEE112A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E10F0D0BD64F607F4E22EC40D80D95808240F1E89E3F856E32304B1B30486468E5A416E66F1A2A85269A95FB827C5AAB7C55061CD2F8FD8B1B467C274A878E290B66B89AC0D71ECF1800F4DB2701176854E40F42D44AEA68CFA350E5FC1EAB4DA784E1DC80443371C10A5CB7E68EC999451FD9017D85C1413F7E13F521B8F62A2BD56DA107015044432ADDA5485CAC00CE0F17A54A9577EC30221D873FE86D21AB50B0422EA1955082CDDAFC53B4A608CE7BD87264C3B1E44D4DA3EA036C17A0C2CCE310F020942DB86B6974C0A2BC2CEBA92880041135754702C769DFA1F62499203A406C768EC14796AD5DBC55FFC30BAD441FC03BF7EAFAC09D8787C4B5F2A8EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D15998001DA4935E216F14DEB2F74D9EB3BC833378A789B550B985FE0A09EE8D8ABF84E861978642C8AF755604D8C0A0821DC1A47E813464E374F09680E752871421599B4BBD0AD2C7ABCA4223B5223616BF5FF927A2BE4997EC8D7E2C75E6C4761AD4C6F40E96BA127BFB08BC1212F7E4FBCBD839B558C5984116355EF45744AD99D74D29C3880C7C7D839C34061BE1CC4CA1FFF12AE81E5A4DFDC1A2D90039E964261BA2D0266E5193CF81859B3C8D464D8B0A7AEB3C822783C4BF41C71A04D4ADA9EC6FA901CCEDAAF06EAA15D89FA7541347EBD19D6D75DEB384B32C275685DA7B596BF37CF982D238B813055E3B929EB119B2A54E6ADB3B8D315A997B721F589100BDFCC72415407617C203AADBDE0A26C50CFB5DF1BBFCB7D484C2103D54BAE53F5401E80CEEC135F9717D3A82E7F919CD1710B254C91BC2688C8DC1D114B3B1BF9EE40897C9692586285A1553057D54A5AA1D794911CF6F4493E7C4A56B39E8C88BB5E4FEC69BA1F9A3FE964D40DD0AE57A8EF70D2C7ED2C954BE542DA5B856C01988E33CE1160823EA49E5E4D6AD4EFD2BD6EB0A5DA925C0159C4EE9714B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FE2EFDA06FBD6C189BF2DC49AF474F0198F7A896DFA96C21479389CD1B85C660AB4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AE3F0AE016E52696CB81A00C5186FDF5B3169C51128537427E443FAB85BB58EE6D9F0B43F56996ECCFF99689272C1CA1E12AA1197E29A23D0AB616D1DA9DDA0BB85E150F12E5F7A773411120EEEF802E49440D774E85754826DA02D1309E1050550F24550D49609811B6662B4E1FAA554A4B0DA3B6D79762A0AED8EFF1E0A78FCE68DBD11046CD8555D83FC03E04D766C89732A1F14D56BBE8724BDEDC4D3BC5712FAC4A5141DB75ADDFA2313FD11CFB56C0847DED068A7134B38B66338B3DDE3EEA0C1A11B95F4AD251AFA121C53B39AECB4F804F003D4B202EEF58BBEB16E8ECC1A373ED33FE945991DAC70B8C1DBB499B8F43EDE0EF546FB88837D8042E03AB9E5ADB3F6B9D7B1B95C9FD7233772FDE5DB57B2C533127B0A566BE3C386339DD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D3455ED18876287061E39313146C9975417905C247964637492577D9D6F33F4CB1E79426A67B00522DB7DC0D3942F9848287C6F1ECC38A0C93D0E666CAD000AB73B23019D08FC342C9941B31E8BABB65862DAC87CF204EEFC17B6D204F607F60F62A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573387AFEBEB8DD850B853D7C548CC8ACF1E3CEA95E9F2710A6CEEEBBF4A3C6B5A69785106B54205049A9D3C611AE5B4C793058B64536750007BDD97662E2D4C0466738B53D22288F3116F88C5BD5670FA08278385F22510070BB44827D0268FA12DFF0AEF482A87AE152C9A588C6DBB41E4B0B325FF957E45A7F6E7234A8DD609AFC3E2D553CC25C9324591794E60FDE66E2F268FCAA01768FECD57AC90DDCCC988A37AE97A46F7ED29F3D2D34A83AA3CBF17F7C34651BC1278DA9646B228247E0BE29AEA13601305C9F130DD40BAB49A9D9DEC13337A24AA2181E57014F6DAB71CA701C1DBB33A28DEBB815B034952CC68E38E566CBD1B23C1AB6DF52384591A92F8C039F240D39B2F363E8621EBECEBADA3DA938E783A72AB8B5D0D287157649EA39E6D7DCC178F2F979A1931CA6692B746A851CBE2FB336307160CFA574F4EC5319F339F2C79B060A8D875507227D8010A9D74F4E2CE9C92F14466121252B8706F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174CC1FEA72203D681B212B1890DDB2D48CA6197C5B9ABDC377723EF0884703BE27 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 8392 +sm = 00000000000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6E5E19338E14E4588FDAD9A348A2B69BB3DB947C41E74B1C49E267A77A94FE9B2438442FE81428E5791B24619D5C18E17066E74EBB881E828DE7442F7EC0F03CCBCEFD889D3361070C554580F55CDC11D8572F0E0F241E24FF7A7AC9E3BFD197FD962E4E6007A684AF87B096B9034966949F56D02660E2B7279214CEB93E6207366A0D5672F44DBB9632CE082C47A1191092030F878A87D3007016131038259D35C2EBF786119150D628A09E9E1C58F8508716FA31DCE1C2CCF7854910D291C83498AC8202BBB4017F727A5E938725AB65B75087A25A952B3F2A54A07C27A654FCEB150A192915844DBD22D5956CF2334FB69351F62036F9C7BF591274153FCF4DCFFA47AB17563DEFAC3A51C0C7E96367FD2A5BDB6420DB2F8E1FA8A1E04E02BD2F72D66DE7B1926B078E7789AF0FF371935A7E432EDF91FF02B2F55E3D348544E86EFC3CBB41204EAD55A3B933F6F3CAA2C4BE36D24A290DB58852434D7C45EBBA724670050F31569813630709AB6A4E35D66684AB154CF647FD64DA3B2E5530B4ECA5ABD9666549F8079173D267642D94F9660C76FF6D5378E015B792B13BB6A3AA55210070C4A413B056C20B2C53135921000948C58FA834135A5C0B3B2849A586CB2FF84925B00E791AD53B58AC6E577BF03A33D008112242388D1464B4616413EFF6A8317C1BA5D42DB01AE12DF2DF062E71777C618CBE7B220A76E5CBF2C0CCE36561758781EB57877CDA69BA5118EBF885452A682B2F650FB9C650884F655867F45720C67D422D5D284328E5439C2BE923E7F9C5307F30E5091A88A02B818B7E31A574796497C2AD22C79CDFF65DE6D4E12F165710A69D1474BC7FB5E4DF07EFD4A4BBDD190878F81047F477A4FF9B89DBA8ACA2B5058528061CC13CC41C207AE1E556CD36E764A42276078F723FA45F7DDE9B045FA1B2B87D528A0C4CB0B5D16C7813F05F9578CECC287D621864B54E54836F3315642DAF8E0F3A61CF1AB866C0EC37A66D86CED0DCAA7DAD8A4E71E08A856A7E8809F918430DD06389BF995302B29441CCE5279FC490F0C8016647BF4125C4E75F168CEC378A488F66EDAF3A6A71C48FA89786E1A76FE326B90AF058B1627040851A517242451CFC34CC73FDA4B0851CE702E085953B9D195E13981E55CCDBA1620CB5DA2D599570A28E55818BC0221E11D899EA733D34DF501FA99A2446DA2F93074804B56E3A7C859E35F94A4492867F7A94B9CBA5348F7071C5732563F8C1C008AD8C1767EC2D20F68C863733E6CA47A29B5851D58F687B256965482434A3643877BD2C0EEC4FF5F8CC13A89E775AB6123C3A1D8301FBA857F30B65D1961FCCDF1C0A1E541092064590954449C3DA834F44EF0A3DA76A90F5FE8EFBFEDBC1BAAE5256E6A1599B45EF51D9A6F477F108EFC9DCC7F139617993D5362ED390A73955749EF1FF0825D5728E4A8CA6264070A7F1F09CD093CAD71FE3263B0E60C73F5F8641AFAF0767651D6534AE73B220CA73A13917887367D055D38A65273890D1FB7A3AD50A7BEC3E7B693C41F717FEC260DC06486D04822DCD3BA1CEB89F12DFFE3534B51B107E7B565F6F3F7774A9CE75488FBA6FF0205FD45334A09906A3774718DDF36BB668C3739D139D5E629140BE6778F0C912343373F637A516E029047FCCECD7C99A5966B1E2CC30E6E7DC45BFDA37C100EB88E44069492CECC82E9E4EC8C7C2C9F85B06F2846EB553C0C49BBD6342D26380F215F7E213C61335DE8F2FE877D38BC2BF84DBDCE94CF1B52C96E524E7179C8ACBBCFCAB586CE6CDAC4FD71787904D4D19A3C95963CC8A0B0F4073965CD5FEBC875F971ECD647F269A6365491CFB0E6F090CEDD43D7F85EB9C9B771CB8EEA797E79F369BCE45087374A20BDC6FEB45871AF23ED0DEA058A8286493883F63B6E25C9BED28B91EC3E6DA1574ECB713557BD2FDC3BCE635C4C98CD3ABDA6B585B5B449422C4CA053D1BD0F83D42696307351BF6C2BC2E38B5392D75F260AB7393D4EC5143E08DE25ABA6FA90C13F1C3CB010C4509B13FB00DF87ED2BFDEA30928486A9363A6559C08A4ED761F5FC89A488B81BD6EB146BA166B7B203A84170E9548C89FD3F34D1B8A288200E2D803B6E5B0A46A45A8CE5E4DA1B56AF04BE0A2D9C1329842C497877D9A5E8FEEA8BD056653836DC0C5363795788CEFC6210B502DB88C434099C46316476FB3FB07E701E29075A820C8D25218B7AB81957686E1BB2C02A72AD3B067589E7E454232E6D4AED6D53228C7A86656CF2453006F1E5F826B247F52F4E7571D886BCEF76579C5A1079EB84454856FC5CBB7A94FE1E8BD05D1597E645C90A90D55196BE811AD44683DC922867C4C6EA4699B17DEA5264D74F30E6C28321576BE93430D75ECBD4D8A99DA5DA96673D115C6382653416DFFD0674E93337AD105F1C5ACDEDF7520B819C2C6669480FCD587D115B1D7951C75225493628CB4963EEF967CF17C509540AD2B7655DD0CA93368A62B937DB491F571A2CBFF957ACC7EDC2201410DB78EFDD783B77B822CD2D5C228338C8F636B590C8B4A083F22185374FB311A8C28990CB91D89E58448E57618F066065AD0653A7135CE175D55D84E19D45932534D0045CE8827E6C485A679499AC15C89843802B844E9E5A280057C9A5DCE4D75B14DCB8CF4475FB01A405403F4ADDD2097729FDE708EB369DB19FAFC35528A11EFF706445E69FF3D16410BA04D24CB605E507D60D552FAA2EC3B70B4AED58517804EC52A746859329225E1BCB7F680B66729BEAAB9C5AC5A2120C8D427E349F364F595BC1D728DAEA01CE9C99BAC79F55E0CCB1C03AF2EF2C56D45E06D33F9D3ABBC6CB4BE097379B461E10794BF16A80B825E59B4645E849AD89E8F7D867355ACE237317FFECE24D982E067547936FBB57F2C25218A230EFB1A665F3D948CDEAA9F8659900F10C43437C01BF081D2664641DB6FD5B0CBE2004A96DD26D999937817B3A8DFF74E2CB3E61134E6B4CF5811150F4276945BA08D0779468902DB915F36620A54536F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD38CE6D0281ABBF9C140B2614526F684254F54E121E3B0291C3926AFDD98DFD10D8959C450F726A8334D3B3C5FF6D5AEE8D27458A4D78040B7F5555AB46E6662EB1D0908805D2B7EAA686FCB7069283CDD505069A7AD1B5BE804548C41A4E273F58EE1E8BA7E951B2F766E1F11C03881B4CDB9A520BC04EDF8E8A9BCE919575914CA22623741D57FF97B036BC9B09C7D5162D983DD5B4D519A869CFFF53F37FD8F550B1F006A3856ECA2DA3804EBC5AB1CD68D64FD4D11747C17C6D3206CCA24C7D176B37A7DC26214FBBF555DDEF8D970B6AA840AFCEE7B674EE05845118A6FB277ABEB1A792B61CA4D24646DBBFD623564F93B74C1277C1AE4CB326411850F0371D6A848ED0BBFB8B0BC3254398F513E630D075CDD277E0AE10D8D13EBDD0CC60AB0FFC61631C5D17989AD9DDF25BADAF0BB87FD0E32975EB673434812D58CC665137D5D47667E1CA8F1B70A9029441013DB1E00D4FB39DE01E275ADE1AF6E6483B18C34D78AD814C71F370A0AF1E681C1041FFFACF9685BABB03923BDB41701F927F3316ED4DA8420A373F5471BE4A7215CFE5683EF16855C748D8FBD21DD9A6C36EBDA9BC5497F5C0C93DDBD40A717DCE151B87E8D5CCEFE5E8A0A66B3F92739B24915DA4B87BC7E555AE0554A8FC1D2514A7979DCC78E92D79C6908005648F90E5E4AB32CBDE27EF1BDE91C49C5184A3CE134D7AD33A1AC03F4A09CC245DAB6033C99636D9F6E9A723429F5EDFE118C045EDA721EB21387225EE2764A00D99625EB4FDDDAE398DBB4D8CD926310601CB34D38B7BA4BF60C66925B2E66B838C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A3692F3176BEC212C8CDDA63B223901AFF8E3CA0612978B7D97E8F2E1C000B0D2FB992BE80BE6906A967BE9949853BED6333CB070A1384B5A26ADF28D3BC5ED2236C6699909AC8EF3CE18997A672EFA2087DC9C0C38BB416613F206E136D3135C4E39F98C7C1F50DBBD69337069248EC64C3E5C6EE0EB7618396BFBC2BA26667426721DC84D3A53129AF465CAB586A54924BD35CA4BB250865AE0EFE67BDF060D8F947141B55502BD264BE2F24B40DA59C45FA59620F207E10FE94013B6A9F94182CFDA5694E19B1ADA22B18F183D7DF0A51AE2876A5D6B79D911B0B8A0D3EA283DDE8F0FC0DA1D77498ADC4DE901F89F11DE2753E8EF674622BF03110CB519AE4F6CD0ADC41A43D1929CBE5047D9B09FE60D9075C85CEAE9C825EA53585D180FB610BBA83BBA2E590AC5257DF858E7F11B8298C848F2F79D78C37F00474AEF9B5E9AEDBA4C81ABA062F24531171F8137F7FCF50FE09A38F60404B03CD1BAA934D6DB5CFCB1DC552BF873C6AA9B5FE76FAE92D4C3674E20DCA7BBF430C865F6E5FB5D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF710D288F760D8E6A64D9E2E53F680C21D30AC1439A4A90469D0C6271AB6EFBB90A4F4DBFF7D5F3875C6507DB321D81C3510D7E7F48B297881DB6FA0AFCE41645FC93A37FF04FCBA7FC19B9089BEABCF9BDF44E2C4614A73FEC80C1234162B41BDF1313F6E13AE2C48A6C4CABEF5EDE59AD461384DEFAF1935E23F5CAB3829A81E2DFFBBCF2FFB141D975EABF78FB4BD484F75E08318C08B2104A468E670786397EEE2BFA57821FD31C38432802C83B7CFEEA3D1AFE176E194B3FF5244CD558CA360AB78FD9219EA890695CE44CC785A3A4DD39CB8F3C82FA5C6A3167055CF3309EB06EB90826159619E65C5E29D46D35E61C961AEC002F87B44A2B7D5C0E2111D17268FC3B147434264112A2E95AADA6ED860C50359372609ADB174741CC3AAAAD1FB50A42A560BB18D12C228F10D2776DED26752930890259A5C0F64C7D30C49383F92F1EAC6B1E8D6BA05423368AD3A8BD145D397389720E80F6EE11965E467D4D5864E164E51437277F698BEDA846AEB66DA3DEF39CA3288D30C001D3B0BCA113AFE8AD333A08D801A9E4C52DF0DDD4C63D8DF7EA938014336BDCDFA10E960DDDB4B5471263D096A49E3C83A188C46AD4EA8D2AEAAD3B1BA78CF6F116D0818BD2F38DB39D74D340546233ABC52278B381B7DEDC3A3B5DAADC8A4E7519AC9F3572A35C016CC7A8E0FABC029801012DD7454D7475E5D8B492A119AC583F4043D25CF1BEDAE7C67F093939FE19265580FF8F199789747FAC252B22338C1F9A81546D474ED8AE3B15450C248728134A1BBC11594148305C1DF6DE9F009DB66C438D81219D292421651600D48C2BD291766ABA14ADDC9186764DD212446D27C3738D2F606A9654BB310288F37CF0ECD5D38590E4D887D9D5C523527007F6501ACBE7CF36803727022D98CB15BCC0A88A509DF3B9A84E99B41843283FF2E10FBDA3C14CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D446D278BBC90D6A56B71D6DA6FCA49F332776F402F58D180482B2EBA5132D8ED67144DA06AAF952EF5B9BEBBF0CC8101E93F3BE05E58EB75D55B3CE72B9C8A07725C61C24C34DEB9A7349E51256EECB7DB61510D8BF55798B060EEDF9F9551AA615F1661F544B0779B2974A54BE8BBA388D6D7FB8E2C0956DCB23F834025CAE4BF26B798CBD5938A517C4C3B8FD3B8FE920558256C391433854481944BE487AFBD226853E385D942014B393488D554FBC143B44F7E9F348FB79920D4AB758CAEC55ED8CD388DCE4B4381D5C3A9FF36ACF9948993CF2B2E03030646852CB4193585AC6C56947193F96292D813FCF3671D46B9DF2D99D43E0AB4F1994B81235A50D5D977FA3560CA3D46CF60945C8D3E1103B6B1D13CCFAE43741BE65EAFFB9DCAB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832D381248D668B0A5ADC623F2529B02CCE42442E86382E03BA3FAF21F86FDE1C633C9A17426EF1F4923824A1E394BBAF5058C00950968357FEA01AFA8303DAA21BAE4617293B3B19A50C88C8F7D8A677A3314640452734E7FE4BA483C8AF87356E6822D943C23705352F458ED80B8375DA6F1F0DD7688CBC6101727F2AE7FE500C98A185F29DC71EE3506F8425B8D7EA94BE228679F42ACED5C9162D6A0E9AF148E5903C0ACC117C2BAAF1EC4A73A0BF73CDC646D1559EB1FA607044B5C7CA60FBDD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C6F2AE696330DD7C816130134AC101764D6B4FAFA1E71A404CEBA3406E1996391AC35A28F18E05DA188AA8FB52712696C986C25F70A31DA73957B238FAE89EE0BE4F77ED34ADFF62BB5C0838F9B645F6851BCA9241ACBCD3038BC40F40F076D1CCD8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C0402AA349ADCC157D3B0E6852516FE480EB2B0D7C38D55BD6B1100D38E5CE79CEC2A8424E383ACE82322B3629ADA77D454B677A60A2932B49F844A9389E73FCCB22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A86CB037675575D46C48D89A7B644810666979BFDDE595E1A2362B9961A71D9F75A4A72ABF56BBE2C07844E774123A5DEED0116677B286BB3F8BCAF92D501A5FF375487D2694B089FAF47D8632DA9E213A9C914689D9FD8B0DA5320F6A89787E198248FA523B9B2E910FE55F6127ABFE1FF1EDFBAFF132A06AB9FF0F2E368AEFC6AFAAE9F61068AEEFCAF427D37CD93FC0B0D226CDCF6A7C1F007BE2E59568970AB644D475E62D7B8E7E5F7BBCEA4D007BDDAAFCF6B84E09BCBC5553F516E2E5DFFFEB66C9F5EF34559251705C736FF66A96AD2CA2C40A368602DF65045808D87B7E24CE23C67906BF64C90CF0E0F8621537D08A09290E431737F9C493DBADF98C9E250E094C6F0F7E850F5EF65E71967F69159ADD14974C1AF501C74F01D1C36AEBE604A32DC02B676BBD7CE4BC3967FA8899F3B1F654E7F3E425ADB5ACF59B604A4A962E7382E5125E529A0E244ACA7F30287FD74C8938A6CFD5FF3857622A676F9528968A73DCB3458A2ACACFED4EE0F6C6B3EFA7207E8F13B15A8F7DF45A3024EA2D0C6179540EF44A8DD43F70222075D9A11B4C32BB0822113EABC09D37D0925C5D27FF4B27EF82812B5609734A615CDB54529EB30EF57F70B1F177F56776E9AF34A592C707753819140669172E2BA4657977CFA700911BD68BDCA9392759431A2E164C7F420B10982E4AE55E77E15C2499B4F0685AA0FFF4C5830F1CF18E0C22B855FAAEFAA6FAC5D79BB0E504D666EBE0D8F8BE770CAA37FD9A4C254357AC146D900D2576B782745048927DDF67AD0A8F93E272EDB721A989D57A2B4F6861E7E10F9C70FFC41ACFDF5DF7C525935C838DFF06C5468E647D8F85F945009A54BA1D966192D8C01FFD4C877E6E6DF3A7A6A7497FE6F192558BA81F953682934476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC59CCB9D20278F8B155728F4234D7F11EA25B128E7283D09BCB5F54A03163FCEE112A2E68B183DC833EDDEA8F8D251F710D28C7C1429419DB82DE68BD7CA6EB23E10F0D0BD64F607F4E22EC40D80D95808240F1E89E3F856E32304B1B30486468E5A416E66F1A2A85269A95FB827C5AAB7C55061CD2F8FD8B1B467C274A878E290B66B89AC0D71ECF1800F4DB2701176854E40F42D44AEA68CFA350E5FC1EAB4DA784E1DC80443371C10A5CB7E68EC999451FD9017D85C1413F7E13F521B8F62A2BD56DA107015044432ADDA5485CAC00CE0F17A54A9577EC30221D873FE86D21AB50B0422EA1955082CDDAFC53B4A608CE7BD87264C3B1E44D4DA3EA036C17A0C2CCE310F020942DB86B6974C0A2BC2CEBA92880041135754702C769DFA1F62499203A406C768EC14796AD5DBC55FFC30BAD441FC03BF7EAFAC09D8787C4B5F2A8EB249CA378B495C00888BB2147B61336B38F2F31F82F7DDEBBEB5F6CFA7674D15998001DA4935E216F14DEB2F74D9EB3BC833378A789B550B985FE0A09EE8D8ABF84E861978642C8AF755604D8C0A0821DC1A47E813464E374F09680E752871421599B4BBD0AD2C7ABCA4223B5223616BF5FF927A2BE4997EC8D7E2C75E6C4761AD4C6F40E96BA127BFB08BC1212F7E4FBCBD839B558C5984116355EF45744AD99D74D29C3880C7C7D839C34061BE1CC4CA1FFF12AE81E5A4DFDC1A2D90039E964261BA2D0266E5193CF81859B3C8D464D8B0A7AEB3C822783C4BF41C71A04D4ADA9EC6FA901CCEDAAF06EAA15D89FA7541347EBD19D6D75DEB384B32C275685DA7B596BF37CF982D238B813055E3B929EB119B2A54E6ADB3B8D315A997B721F589100BDFCC72415407617C203AADBDE0A26C50CFB5DF1BBFCB7D484C2103D54BAE53F5401E80CEEC135F9717D3A82E7F919CD1710B254C91BC2688C8DC1D114B3B1BF9EE40897C9692586285A1553057D54A5AA1D794911CF6F4493E7C4A56B39E8C88BB5E4FEC69BA1F9A3FE964D40DD0AE57A8EF70D2C7ED2C954BE542DA5B856C01988E33CE1160823EA49E5E4D6AD4EFD2BD6EB0A5DA925C0159C4EE9714B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FE2EFDA06FBD6C189BF2DC49AF474F0198F7A896DFA96C21479389CD1B85C660AB4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AE3F0AE016E52696CB81A00C5186FDF5B3169C51128537427E443FAB85BB58EE6D9F0B43F56996ECCFF99689272C1CA1E12AA1197E29A23D0AB616D1DA9DDA0BB85E150F12E5F7A773411120EEEF802E49440D774E85754826DA02D1309E1050550F24550D49609811B6662B4E1FAA554A4B0DA3B6D79762A0AED8EFF1E0A78FCE68DBD11046CD8555D83FC03E04D766C89732A1F14D56BBE8724BDEDC4D3BC5712FAC4A5141DB75ADDFA2313FD11CFB56C0847DED068A7134B38B66338B3DDE3EEA0C1A11B95F4AD251AFA121C53B39AECB4F804F003D4B202EEF58BBEB16E8ECC1A373ED33FE945991DAC70B8C1DBB499B8F43EDE0EF546FB88837D8042E03AB9E5ADB3F6B9D7B1B95C9FD7233772FDE5DB57B2C533127B0A566BE3C386339DD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D3455ED18876287061E39313146C9975417905C247964637492577D9D6F33F4CB1E79426A67B00522DB7DC0D3942F9848287C6F1ECC38A0C93D0E666CAD000AB73B23019D08FC342C9941B31E8BABB65862DAC87CF204EEFC17B6D204F607F60F62A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573387AFEBEB8DD850B853D7C548CC8ACF1E3CEA95E9F2710A6CEEEBBF4A3C6B5A69785106B54205049A9D3C611AE5B4C793058B64536750007BDD97662E2D4C0466738B53D22288F3116F88C5BD5670FA08278385F22510070BB44827D0268FA12DFF0AEF482A87AE152C9A588C6DBB41E4B0B325FF957E45A7F6E7234A8DD609AFC3E2D553CC25C9324591794E60FDE66E2F268FCAA01768FECD57AC90DDCCC988A37AE97A46F7ED29F3D2D34A83AA3CBF17F7C34651BC1278DA9646B228247E0BE29AEA13601305C9F130DD40BAB49A9D9DEC13337A24AA2181E57014F6DAB71CA701C1DBB33A28DEBB815B034952CC68E38E566CBD1B23C1AB6DF52384591A92F8C039F240D39B2F363E8621EBECEBADA3DA938E783A72AB8B5D0D287157649EA39E6D7DCC178F2F979A1931CA6692B746A851CBE2FB336307160CFA574F4EC5319F339F2C79B060A8D875507227D8010A9D74F4E2CE9C92F14466121252B8706F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C0F90F4CB1FC9902522B7D47779E2B1B8D5FFDBD472931E145AAF583A359F8174CC1FEA72203D681B212B1890DDB2D48CA6197C5B9ABDC377723EF0884703BE2757F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA072F8AC327FD013B98A44146A45192D07A49B3FE150DB78658E659EB8546072823C7AFABE43959B08C3E239FAD4B3F0E87E872FF749B1DB73E5E9337731596C9DCE65AC0A8965DCD720A4B978015DE82E08B56B7C9D2D895861C15B766F9AB3C97E87206A7B951DA427DECC0653B7008BEE0B34E5B8A9D486832469079EECE91552F6208FDCFFD2E81B9E968F16C7A6E718FD43A6699A0E4D2F4692F3F56C2E31C33C937720276C8362A6839A6A055BDB5737525429AF0ACC1C8345BE9A2E9F269938969EE47C53A6E06BF3D9896DD79382F4210266C3BBB9F17386003F120AE41CF9F513B70D94E5A0DF54A0D52D5632495C7D6C843BBA812723C1BA75A6CD8B8FDA61F39B5EE34DABF596608877296A59158883CA4FB0402E22AEF63B5E1658DA5CD6F3BD2AD8D2846B76F86A831EF9F8E2F2EC334ADF81B976512F8FE7D2B9 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-6_256.rsp b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-6_256.rsp new file mode 100644 index 0000000000..9c54ac3b00 --- /dev/null +++ b/tests/KATs/sig_stfl/xmss/XMSSMT-SHAKE_60-6_256.rsp @@ -0,0 +1,12 @@ +pk = 000000171657949C495B0A1FD294C1E4123901C1A43FE62FEBC70C30CB6088378ADDBAAA04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F94 +sk = 000000170000000000000000061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA19810F5392D076276EF41277C3AB6E94A1657949C495B0A1FD294C1E4123901C1A43FE62FEBC70C30CB6088378ADDBAAA04562AD35E8ECAFAAFDA16981CDAA147606BEEA62801342AF13C8B5535F72F9400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000156F2B5178982D4946D6E968EEB01CA7D844869EB44220E8E71236F901784903C0100000000000192737A531F302A803624A0B888C55121F214DBAF6B300FE76DF64981558B49F4020000000000010AE3F3AFEC85031EB6E0FB2226818250BF20BA339D900B44D93E7C600F942280030000000000010F958C5BD8719E20C29B923A33D53A728C56602A181BFF1FA76DA4B45CB58D4D04000000000001D20B316C66BB61F992D5716DF5A5C4177FB654E362C661C16F1EE608CA6C2BDB05000000000001374E41D58A8E33A48F5FA6B7432DB7603E07767B3995B2C17C7FB16140C685800600000000000190FFE7DAD512868DAD7367C9A99404DA4A67CA8B5818F161F32970780EC146C40700000000000172C32293501F9EAB280F18B54FC472C9EEA0CBBAB14E5CFAEE3ACA59E955DA1B080000000000017297F325C0632D162BC9EC5DA3DB47673FD35A5EA4B618185A72DF8F11E7D933090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001DEAF54E0E1E211C80D56AACEC8C88A07A1462DF08B61D0ED60E7FDC8228AA00B01000000000001F42645121DCBCF871281B35BF017B4E1E16537ED183763A4F1F32EE524EC768D02000000000001113CCBBBA4734E57BAA78619199D764EE18AE83C9F18E4292A480AE29B4BC0710300000000000140E2BAC01C528A669AA060531E2E0496117E8C3493E5FC894784546EC2580A67040000000000018F224E19E61C8A7076585BF7780AD32D73D04D66A52F0B4CB6D35D9496906BFB05000000000001C0F7248E24BEA5635FD0F3F3411F1A20316CD29E2BDE6DCCBDEF8AFD463CADB306000000000001BFE2E0B4F4BD9B2B955C3CE73D4D0E703C44BE5168224D99756D865D86689E1607000000000001EB5D1F16948BBDEB3335E0F93C3DAC5C3FF7DCB33B16BB28D3826194192729F80800000000000194BC268989E8C957203F60EFD29089692A7FA0980912BCCB1FF3D6921B980561090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001521B6795E3B31C6F469147CDE5776D1FAF80EE268B570DD87C1895E195F358E50100000000000135050ED1EAD3E799B63D5EDC01FDE9B7E3E8036A429C0AB56C909CC2B6378D6F020000000000010D93E097DE2D5330AA792D234007668B3E7F9E699621D298D2AB7577E8518A0703000000000001F2616B47D5F8376AF6A5FC658A75A52D032F7A1710630905C152957F41FA240104000000000001806EBD8412403D61AFCBD000376F11695F17BD253F82340C13342F750D09B2D205000000000001207581737977FDD59550FE1E0E62692061E1E37C554529C52E427434D2BC50AD060000000000012C3C45D74BE1C78902947B902756864EFD771DAF34009F91281FBAD0636A74EE070000000000014DC0E1A0DD7194009DC2FC5355C4D62179DA0010E19737654D7DC0E4C9761DFD0800000000000112F03C455D30919DCE22D2F8A0D4B5491A8188A32F17059A6AF994ADE911EF750900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE59F8968E30E844A031BC745FED8550EE78B1266A91694B967E66785403F9FDE097DBFF047A171318C43FB2472127512463FA79877B475C7F810D28AE0BA7C5966102673F9F55653D9E546E378D2BB17CD35FAD2F50C5372DF7871B1F1DE78A72FC84F2AD1BACFB45712FB13E3773B3565B021D30A31602528EF16FE6D83795A1A8620E06BE25AAB07A8F3F1EE979687840B7C863D0D8A547A5F7197FB72024DA7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011420B60C54314ED8291B4F251FF32674EE6A3C3609140380F6B20865B7AE643401000000000001DA6EC89DAF2B01E86C06ABE8043C9A6EA0562A18C49B4A9497D347FAF8EB910002000000000001A0A42481338E08706BAC35F7B5F5D93432D40144F47A0F6790DF4B68525ED740030000000000014A9507DA8B4941DFD3D5E9A02EA050B97F9887A65D93FD8723FDC30C7E2AA4E004000000000001BDEA75F9BF80695B677BD7E643AAB0D6DEE791B64A29E66D796C51176B9F718C050000000000014F174AE6AE0AD2D1C856FD802C756287A8496B907E56C4BE48E85864F71DE7160600000000000131702A4AC2D7BD2722AD083379A254918CF9EE0656A5DAD6B07C11A74BBEC85207000000000001C2F54B401EC9CFC51F249ED76CF09A24665D8603D3747E67778075CC7817C4D708000000000001A1D56697DB12706AEF7EF31B1584DFB73FC269AEDE8C438FE9B6FE17C7A659860900000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F4532E1EFCBAA0ACFCB91F30D21D2C90F8DBB5B419D8771AF1FA14AED614FA2B5DAB9F6F85016293B0716170A972790FEA6B0967F1FF1848CD29934182A9DDEA9BB49DE7B0A8EE13DA1F0A46E2376820EE34C1CA84E4524F21B5AA5FF74310EA831A3D3D08BCE359B830828E376B3C3999A9AC6168ABC74DDA8FFF0B35D6CD022BEC9BF0527A743822DFB79CBC96A90B6CF80B4E244E8F4386B653AF3D322BCF1E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018BB8E296C7509BC115ABB151E123D4E0343D51087A3A7321FD6406381792A7DA01000000000001166966BACD855719FD325B6CB7EEE8DEC0ABA7479BEEC9A71F451BD9EC1886B002000000000001E480EE1888B362F2F00B536DC0FB57F3AA94097DD543F05D299341633DEFE5FB03000000000001522E3D23E82223C8085779A58B7ECF45EB835F4B8FF5294923C95EEC4FCA50340400000000000175597A079FE64BFEAEDAB8F7995E5E9F7C88741A0DD3F273361C01971985AC6305000000000001DF8A269F13EC6CFE6713B0E94D2C3B25A880F3BF1B34A76946666837A1A3FABF060000000000011EC3BD5D59B96FC03D21CF2A93978E5397521400E05C4BB2F66B8C53C5322DCB07000000000001462C4051C5F8F1C53FB2A73D731FA41C1CD97C3BE99C1ADE2751A405C95B683F08000000000001428C6A22C98B1969BB9E66F698DDADF342C585C26289E42FEA210E34A4C279A4090000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B9D6F51E82EA4BB5AAB4110925E014691A62121C27B5D929D24069ECDD6148B64213FCD94FB9EB6CA08C3D942DCB7FADCE9FB3917E40A455701CA8028A1456EDECC5EE3A3A27DE819CC28084BA0BA992CBA7D3DEDB39B4FBF247D2845FF9D4B455F5D29E81C17C5FFDEFFF7CA2153F968A130EED46293DACE1777C0173B089DD2DC63CA91C994E506ECC920E8A96608FB6E4F970A59145E77CBB83D1A5C22F9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001D10E76AEEA90CDFF9F15085B0834F5C0339E4C86D2CB52C234F6B18B472E8A020100000000000195C0CD14484D08075EDA691EE42CD999A552CA1A62318D9765CADAB553C1C5B90200000000000157A8A577120F2AD134FBF0E0E061E38A768CF935F4D2AA9A541C7A3D033A991503000000000001A467DDA3824B40F0D0D861A12328735CB8C23D1726982BE71F4CF68EEB492550040000000000016C6BC09F7073D85882AF0A9B60C224629A2B9BA3C0F3CBCBAD527E4DA7B9C003050000000000018ACD5F94CF14BD16B576FB1BA005CBD50AC4B03D5E54BAE131D723BC35FCD1AA06000000000001366FD19DE6022FE26A5E139A7E119C7045423D56D1C83861F263D7127DE85E9007000000000001BCCB39DEACD797170E9D863E6DD42F7C8C9B5B10CBB9130E84561B98073B1A57080000000000017937AF716807E93101BC400344D3698048E787D2FC6DD01EC7629B28F9D3F51609000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD6E7D8241F8BAB4D68DE3288296539D0DDF68497D7634A964B76E82AF13767129B7FE5BF4C85685F9C1649B8A52FCBAA9B2AF0C0C2BE1904DEB98ADA34507734E7937BE5E686F6DDD4E57D5EEF9FDC2164D60CD06AB5C9D11B840625837703C3CEB44B6542B684CFC5EB9B3297D946E7F698FD75C5A824EEA9328EDBA65225623ECF3B1F560C0D9DD03CA404DDEB74F901FA06FF4D2B0972C31F94450036B01DDD94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB0AC0CF31A27014816177F79DBE703195F44C47205EC4A5CBE62146B5246AFD86660BB52A30FCC16AC9D773E97F581C7518D007FE0489C09FDFA334F49313FAC2B579C7AF47F9946A85247DC902ACD5E0B22949F45945DDD51DF6AB0FBC225603D7377F93D29F2DF9500194E614F93DEFECBCA3AFB03D22F8FD7661D9D41D62D3F34476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC5986DAAF87F5A9E602BA73B7392923FDC5B81A6BAE67BDABA7F7D2E9410D160455BE2CC6A833BA1B0F8FE54852A576BCECECF9BDAEF1C9B426B3DBCA32353CEF2D782F9FF8C8DB114C65E259BD077E800BBF0AF92AE1083501FBCB6D736C848AFA2C836F2E20EAC0336B58D10000EE1E6FE4AF2C87B2DB73F0F695508E653A3755D0CF17516575A25E8960FFDB7B1A00FBED460A8BC7EDC370A52E214885B7DD496596F52B1697C11D5127906C27EEA91E5D3E948E752D54EDC1A8284B9330F1BAF79C2B31C41136602FB4D1A7418EE586E7386677F90D185CF9D61FD7178055651AAB6AFAF6B955469C05B619297155F922B97B7FD28FDA0C0FF3BF34081177EC83DC0433EFB8A1417D60691D76E15384DADDFE66566032B722D99F959653F5C68D4FACDEB4DB5F9CA52CAB9D78109D66D75ECA67FE82A790ADABA4C8F8EDC5663FE77361E78A43189D2B89D1F26535B1E860C9F18E7A3BC6892A68C68AF96C1F4730192CE3BF69D4E7048912FFAA309913C054E041306B4B0079D606F9EF3E08020379FC3A11CE22436F7C8BE6C5F5EE2C1C1778320456C18A68F306AD1B55954389F635A502169454E7C432BADF0A68F529903CA29C2B836DFF01B67CB745A77A9E7813A52B92C810B51BC3E71D7AAA9A9F31EE4542965AA0F6F9907D1595A31E720D4A7098FB2D72F01F8B83BF3A93D05157307E2B595F0609BF2C8B94EF6A5D60E53F20C1559A9476CD2391127B12D77357269359C424A769021D139860DCA4136B718B65880234089C1138705945AB76C815ECB06C01C73C60312FE6DE218F09C1607F528CEDD2898E077008FF6E47C4FB6B2C103BA92C399A24CC38B373B3D7F00D63E6A42412F710C62528106482F703ABC7CD198A24723A6BE730E6DC971D468EA20D76800F938E651FAFD425643ECCDE70BB4DC1D6FE4E9B3D3624C330E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD6847C7DCD156F805A9A513F17CFB60F16925F4C587744E4AD35C7127757AAD37B73E5277D6614F0C315BB9E3BE48F654AD2D343B3967FCCF5387EE8297F2F74214B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FED8B073D52EB9D1847445D2064669D9E03116C2D999F3274876F37552E2D8A04E4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AF91188FC2BBA388067FA443275DF1C06B23BEBEB418CCF1A7CA0E4BAD57780AD7D5528BD18362F273F0D97C081E502F32EFE1508B343268F1D2EB3F12914313283E40F4EC9F02AA17AA8A310FF50DF2712F49896FE31BA07A188488E45EB59D6BD6B858D527BBC0892580637EE631FDE8EAC14EDEB1E73EC75C8C241294EA628DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF47606C4D632B57BF57812D2B2CB85C631F239710C05C7743C2F4515F6C64CBBC8109E7FFA421A5A637256FFE7F44413BBDE5787EB92060591282ED69794E9D64356A585D5E293E705EFC493596D08F3E68CA984532F71A20D81C4BE0CA989A19C2FC268CACE37F8F2D5B481F2A4F387043A4715FE805C6FE2D4AB89DEBE10CAFD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D34B022FF9C01B7ABAB66A08EA5A0983E6E85954C92A6D3B2AB9D45BA49B21D45A3468B53440BB45283D3251613D162A9CE508A5766740BC16F13842C2F89F2396E3363A1934E3AF2E7221957FDBC5F2BAA72B6E62BAEB9E6D33B248A5102714178A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573D2974687D3B63D655D412B1DC0D3084791DC9CF5BC4A42D6D3787A187D4765E5C65894BA159FCFEE27FB3B36A54A9FA312C81EA09C6762770B9649872A738FA0111D745A1F9A0BC53FA819D6E7220FB07293058C8EE51270F86D956780BB52984745B68DA948F7F936345F770F38661F35198D5BED466C3E1C7A23DD56D543CFC93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B7871339ACAC858B546C9139F4B917CDA356F04B779BBF803351C1B452BD9EDD0E2DA226A5F930C3C97F43D4633BF11B8BCEBF646B8608685E36F0ECDE7C7FB5F977E4D61038C745DE151D832D47C979224CADCFDB0C82650055F1519B94680A840FA14B55B2190C71AC1F7A7AEED989BE8C8AC61149A0C809449B677AC353867D0185EB15322792A3A7E328FEE3DF2230E4B70551FD7F9BD57BBEAF02E40124C58F019EEB66602B9EA10094839EFA9070F5C2DA3AAB6CDE6EB58246A59AFFA0352106F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C013843CFEF1EDA266283A5CE4A6ACD7597519FBD097E9E460D9B071D34EDC61672D14E6D9D4F9A033B5B473A1B13476C3C447E884455A5D168DA793F9E2F09612A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B2BD0A2D4978F82258687586F9E6EE6AA21877D8A2C7AE37332573C420DB9C8754CC20EB937A8B94056D96EF571162B0106AEBFC344B5F28D52B8CD02F6168F45B321639DDDFBB333C5B872E80370F408EFFB5CC7394767F8CEC0CDCD7C9189E1B24FD29C7FBA4B14F30B8F5996155855C08A749B6AAED58C55271223A53D1E8714549EEA65B9A9245D9F5AD2EEBAE82637B9E3C78A24B5262873759CAE9AF9054C3230F88509E71CAE2238AA2DA1C25F0DCBFDE9BCC7B234BF1EA6697DD4E8B020B099CD92492855F1B528BA0B359BDEC1E77245432B7B1B2A5A7B969947A2FCFEAB2E94762E2F3F524E88E6FEFC4DBECED7EA550E6BCEDFF229E69D9C7C7803FACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E9847ED6D3A7874015F0AE87EE37FB6C478F7330A07D4C59E314847065E2F1F5F7F6DAE557F85B03FE6BB31B28A40263B64218FAD4572BC5FF2FD4E3F8F9A8894795658466BFB5DAFFCD99A69D532713CE072D81A42045933CDD30DD257F6C9848577D9F8B09B5D7BF71CF202AC4CF296E05C6A7ADF77D8FC670B88DAD02DE5A80D4168F7F72A7252B0E421F9734012AC8A8188677647D35ED6199EB300A6B71111D7CC77F04AF5E559A0D34CE1E1490576716A861E79902678C1241CB6F614176147ED88C82A99CCF2BBF62AE65572300CD4FB12DED4B6B0901D5F6BD02F036BF66B095215AAA76BAA4A07E2C0CAD2B2D76BEB56956C26ACDC11FDEFE9D42C6A698C09F0ECAC502F2F7E00233329DCA9595A191DF6C87B728E8F9B59105B9074992A62F2DFB38852C7F4BA5BF782395E906AF48136AB2DEAB4BBE7F0F79867696DDAA4176F14C9DC7A301B0DACA30332F73CA3356A62A4832A12DCCC3D696505F59E73148ED6401A34F6986428CB1CF18FD61DF1455A042455FBD97A76A404E65CD0BF41E26465281A0BA11EAA39CB48B99F2354BF5407629727B52DBA14B29C65083AE8B8891AECA5500BD15DE9E66E7D5C0104891C17A108B79D8D96D35F12170E2C930F8F16068AE3CA8511016203A1A4726CFEC7B6AAC959B67F3FF1E4AAEAD667487299703D38472B5085FC55B9BB775574AAA118BC81076CD53A4AA7E927482B1D617C09C6C24DEB07DD41C2C42B6A0BE168493CA5A40266AF5B992B9B2C65CFA82A2EFC515948A5FC521A7F49DC4BBAD296BB6FD4AA6FE1B7A7726229C03DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D973867CC37DAFE8FC39332DFD321B1ACA45587EB6D4727F5AFEC4178CDD8AF03FA0629DA84844B5131CC2AA07E2FBB8F80D3320AF5C1734031AEB68DB8B6C7358F775E8538C260FE6A79DDAE2BC7D40222B2942A2D8ADD3F295A135B5FBBA319FA3636F56D1BC8CBFA175EA61C1F53980664282E56291B4ECE5B5FF33C2141F04A3FF83EFC062CF6C635497FD03D6E56E405C43C4A31DDE872C4E277AA190D1D8350A298F16BE75BE305891F9D1084146199960A881C34318CFCF1366E82A487CEE95D5EC9F9756FFFC9DF3A1058E367160B321753C937D587130F9AAC766C19F033CCB2D886AB532683F50D360D10DF559AA16DA2C0E3203337B46EA1FCC1407675C5057052EDEFFF36BB2A6331522DC5CBC871C52CC35E95DF677771084A6E3E10A56111E6B9F7DAEB1FAA11B9CE5EA450A7D75F2B7266193CEA51A9532D8A32A2D4C275ECE75C3A59C3F02E3F9F40968642D6387F752C801A761F121A3EEF4F6B0AB83B7E815E5BB9D67EF85BF9DBF72E5E6DAEF4A6F7519130BD4F826A82D23332BC291A3D320CBFBE4BF1A143B78FAF7C1BF61F30801BCF715A05F2F7429F0D1A3B9F90D191754FE3D761A77CEA46082D3D2CA5BF26EF05257DBC8B72D156920EBCB1E064FBEC3CA43AF31CB2A53B246BA02E3F8AD4E07DE794CC1D8E3814DE61807A116F768CFFB159D16CB7214EAF1F52452B768380F4E16E2BCC10E82A027148477F2C717844DBB1677D6F2559AACA58E4759D40C7D62610399D6EDBC6DD4DA7904D2C53E4D9E07928FE181D503C5D45D6DE07E767025D9B0386F8C123C38CAEF00BE2223E8B1F46370B1D20FF0DBF78CB6A016D0F72F07820238885D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3A1E6EADFE7066FC6A5781AF310597B333977E34D01483A860E7D986357107DADB4F5D040550E524D9D1AA456CAED45FB5F6475160AB01C8AEC46EEA735384E4FBF205BB117F68C03F6D301E5C469033B05360DA23CF49DA36E050D627B2067B30983B2B426DCE0B78C0500BD15B3D2572537DC9B5F0BC0E1A12F533F58B2E21102318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3F5C33BF53D2A951EA7BE7FE2D487362EEC1DCB93920B266C5AD39FFA0FC6D4B335B1355A6D8AD3CFE51E9F69C8961A82831BD27F727C9030A816E817783DF89B519D6EC14C9CD88B73FD6152250E229BC6CD8C952777CC5D670051B18F5AFC99860FF7387C5880564703541C2883BC93C5C0EEFA57AF9E9D9D04EAB3BA87782807C37D299789C60C63CC2E86B5610ECA54D3949E17070B1978781F705E32042AFF28FA979979A511C5D14ADD08AFF7DDAE858415D7B0CBA138BF6D1C72C99A9564FE6CB5C9ED554B98D21CB796FC053CAFB4B3E8214F44643C99D9C92EA847A1B6DF3BC21FBF810F9D04B26771BC6DBAD0BDE30265D402E62EEE8ADC84CE8AF0FECBE8F68D13501515B8C28F68AD45D9D1A454904DE944A90C7500049FB74979AE952EBDCBA09DE543283CCA44D3F00EABF99DD714B8FDE3755D30105AC8CBC4569789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411935E2773E3B03C5E4959D9A2F7D55B05B8574768DF40B5EBF76FCAA69F463E0FAFC9F02B01C7B89C1AFB661B43AED07A9D54A6669DCD9022A4EA628CA69577EB10D3E331C300BBA084A239D762A49141F81E46C97BCB157E81FFD88A34862C07F224E2ABEEEDB7E701AEF0A2FBC73A73CCF9B88E0606784D0BF4E99D41EA993B5401881439CBF17699A62F3D426EBD3681942C7F6F7B40835A7C996B400565E8BC9E636698FE0B197B96767C304CC366E2279F19A9E76B8B549DB73200EA7B3F788CCA15EC4A56D86CFBA4058C3C514F3154854CA6939229C3FAD386BF62626211CDAA71529B5410E08604348A4FA025A71894B946DF27454F27BC01996F23C8677C11780437BBE7131493B77D15C667AB0012BAD1CED0DE088C3D83795C30A3E34C878413680940B88C4693DD69B53E014174D8DB87EA6138C8CA99800F4F93981189912022DDCA5B6D5AA4DD2E04C394191204492E8CD5BD3B1599292F066E4E9D5917ADC3CF954851323255BB47D6FB2B0B6E93D9C2E39E23F7F02915149F9234FB2F13E6BDE58B24DD23CAD19056B0F92E3C1449421FEB5A740C7BDD04C76D8C2AA84F1BD9CCB562B9AC66C54ACC986BCCC869025339B9EE0CD9B8C0D7025B3662F8BDAFF77D6C77324F336C1A5276F7734EB3399FEC4A5902AA5971A933EEA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23D17DB2E495CA46032D9EAB61DFB6703C7C06BA4FD0513B55B05512CECC642CBB9D75AE94922FA66546C306BB281A106EB0D25D4156DD04911DB499F9A77B8F8487EB0287D9D564EDA31C37DD33E57A8D5A33C3088F4269E28E87145AC781DC38A75D575DDDEF448BAA06A60E54E4F6EBF94B095C14E36CDFD29B45BE3455F1930F39F77150E595CF127D1FB7E8226CA954C355D7098E783D32A41E702A611115154F3DB1A8484E4C6A81D13632998E75BC4B868F7E6178F035BF1BEA7510E3A823DBF976A0741138D1D5C9B2B434076228B7C3DAEB0576CD1194E82E62A8F902F9C84A1040262E83913A179EC88A1973DA20CD50D9676DBA1B8C036B97AF2C2005F1F556D1C462DAAF0E1E720B728AE3A7187F576F6B19177F83CB2953F058E0573D795A69B4C72365CE904C9690FAD0ACBC12108D950BE728E935FB7FE0779C54C8C0CDED49F111DE5777AA6131EE9084796DDEE52FDD7567A66ACFC8BAFFE19F46D0BC02258E9CD605176480A7E11B2B7283334B1398342061098099C06B1DB47A027B6577055A67649E98A0AE2E890FAE3186EBDBC6962257DCADBD50352BF17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A593858D31D1B989FA57C694A39CF877024ADFBC5FA2386FD36B07BE137723172C0E08CDDD0185E2510CAA4E4845ECA6C9750F4501FEA182D7748CE3BC2C902DF532BFAA83B530C214A5C649102309116DEFCCD338D8AB9CBEC500C26095E4BE1521964AD4694546C8D1F3774776C0595E0ADD0203F0FE1489B43ABF5FFA96C25138D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E526C7FFB8D1DC496F047277FB03444CB5ED7342FFA18EEE7B1730925FDB23A34CEE84A5DB13C4AC46BE0B0FBF36759DA3E7B8C3289628F7E8254BDE347A1267A888D7FB18D021FC09668E7DDCC0FE714DFCBCD73AEE1395991E44B423F05043F6094F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB105FFEA84396B80DCE49EC772FC586D65A0C6FA012888B314FCA5FE7D56304AEC2B6EBCA87240731E19F8A237E3080A5B4FB92BC823AEA37AE3886609B5E4335559AB13257E92D2EE60938B3FA1A8B15958F8340A6062A0045C098A08D6A78F0C8806789322017F576BE2590AF4AFE35C2C1DD17A4EFBCE7F65B7FCED0A56A91C2D5724455D0A7A4BE1A543451792BE01E9A9614C6026623E730A21A5AA1B22EA38E983F1CB3C6AFCEE94FD813CE143F84FA32A70A97CEB20BA50BEA097D13CAB9F0E7032D052D9D9903A39F07E56690711D67081510427FE7D665D64BDD70EFD0215C6EF994CF6FD7444DBFB51DF33FD88A9B2D54BADC321512B7B57AE2AEF89959050169E710CC7D38B011611B655BA781A5B3391868F48AE12EA4F0D539BADFF7D81270E6847C387DD76569E539687B1FFF23F0226CE24125D85D229804869826671E44CD3B5942738E53432EB5267B1DFD7C80DA709A3E6ED28B83E10721F4D08519A3474C951803C0172025BE77A6CD8F5F9B9E09ED8CEB187F381D57F893F96E78A10C1AE29A306BE20246579F74C2AEDA46D2FB03A5A08C152BD736C93C7450149AFF1C0505E34E48C193F046647C61565FA6BC99044E7FCD0488716774CC0371D9ABC47CC69C415AF45B35FD240661DA201D3906863E1E0236A8A0307E854DBF000462D7217090E77A43FCA84061F881F71DC197BCE1D6B518FFC25A3E4926F64229AFFA4098F5198DCD8BBD2F99F95453723D6BD04DC5F2C732970D2AE4A9165E3AC8C8A767F0BA93BCE6F76F1E4A96D167E9EDFBA17A78E7EB3015E158630058EFDA8FFFD9D1B074C8ABE07300265DBCF6CFD550047FECFDFE05721DB0EC4FC21D4C675B7387B6D524DF052BAB92912B6DFF155F00462AF058203F94021F6388249475132A803A31E55E366AD3935EA2D7BF1FB0DD9AAB9D494ECCB3B7D0B7663374228438E11FFA2918324BAEFE443FB17B1A1950B0989D5B3379A13D82AAC83687BCCA2358DE7DA30541EB84E75DEA2D27409E7C02131C1FEFC1E02CA55584FFFA7CD7E8B6E2E2B7B685BB96710B6BD0B672334E8902CF6D49F47CA682E4343EB5DD588B7E61FD37D1972BACBC77C27CF06218B51E82E000185CB9BD13F89E6C3AF38596F181FC8A31B68C8C21DC711EC8BABA1CD7E812B4D6C939B449251718439129B95119BC9BE22C5E237B0B083582093D9DFF114C0F632A0C0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2FA7DFAE5EF6969F34FF7E1B0958C4297CECDF374312B3231354D04E61AB4B668921E65D7ED31AB5AA46E5DE9EA4F5243CBBDDF261FCE1BCD26DE90FB46AF94530DA62C28D019C7BB1B7D245E3B773871F0871B12ADB9306D31135B241A8E49D6EC6743C95469C24DAB5CE75E670357F3D22481C2E01E30215A0538DB0448CB9340D58FC633C9CA5141CFD79109D30F5943DD8A69F47F49C25E89EF486180AE64497FF2197EE4D518994942F6FA35BAB9D747CB356907B409CB427788C3D7708D77B706D9F90FAC25E492EB60F2DFAD94821D05D8F5721D46560CDC2E43963F70B64C7EC230170F2221693D7FC10B0F27CC4B154EDA86B74CF82CB44EB097E3703FE0B938346856014A50A106F64B236B17DBFEBF2B455FBB9C999CC1F9E7CC7D4DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BC0846516FEB472ACFF5EE2D7E29F7633E32E1A91E5DD713A56AABD6ED1EB967F371FE4D1A7EDF2432FC050A47F34300DC4B69F8553FA4A23509A45977E62736EC9653A51FA687A30FC0787CBD6824BCE36088AACAE7F55D877F773255A13B3A006CE4D2B2ACED5C03764B81B9DE5D9E0EBF9230164C5F75F05C4353F64A182FA15948C9BD8D89E5C6364B84ABFBEE413D0EC4D3B553A46B63FF0699542A2A7ED568B6E8A9C2C772B4F7F7FA17726174968E216636B4FC547AE59D73DD40F320D6B3329C868728B97CC704859F851149108B705C39AF3DD97EFAEBD39ACCFAAC8EE1FAAEABB32E689063B11483C47510DA0DA16B02EE4E397B146B6F777B1F2C393379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E696E1C83076E0EDE8540DE3D7AA00AC5A50E481F7BAA41C43A1C2EF09100EBFFE5EED9FCC095945F525F66ACD9A814582D6609DE9FDC132974B98454B501DEAB673C6D33AD29686E1D43912840DF6398F2468C0788D1D3B597004E6BDB7A89B57DCD4249EB51489F4DDA36B0A3B90C4EA616135B089C4D4B8DA02E695EB8657B2E12FB5554D2D833353A3FBF3FEA441A755FC4F0A49C243C3682A20B04AAB0EC430C9BFA134C383E4B6FD45DFB613E362B171F0C2B2473B38E92A21C72C100505B3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E626D2148795132C2479B65FEEFD8B38395AE4A34ACD06B005F311974D6197A0FB415D7FA5E64502FC8C878B14462F0C6458E04BE6DA9308697467937AE52099382FCDC35FD7D2734B1150C214107CA53F6EAC9D584AFF8FBC6C2AF2B711F45BCC5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7D4F6F08B57C7303472AD0369BD7B5199525024D34A0143DE46F8F3316F4A8B93DC5AE6B02A0F362EC7F9EEEF5303E3C0E13246E0F214FC2843F6116A7986920BAFDBC483B7D8F84ACCA690C6FBAF794BAEB0B687249A360CFE9E1C0A2817F2D93A166ACD35C00A1BDC4B1AC6BAEE6588B0958D5C2A0D63E6DADD81AE2ED7B8ACAA19040E7E30E454D629944FD10E1AC8ADC8C0CBCDD9868B973299A4DC927C49E944C7C00705669F96557477EE62F0E6140D613B110B9FBECAF70983B17EC4A470FFA4BFB8AEDB435FC607B957898278FC2D33E66F68E1F630D4A06B6413ED8C2B7BCD931DD4271D12B29336E47FBB378D48A956DDB447ED3A2B93E3C3A5559DB3B18505CFD0AE9377C5F87964A89B20952F5804125EACFF6CD0C256CB30288ED1BA4324F9F7850AB4A14F5107A91C3DFF05B82D1C4E3BBE38B7C6380AD2D1C41621187066598C2A314A84E55E8260D78D6220923EDF59C8CB7BB6E5B6AEB96BD7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC765A499A3E4FA7388E44F9A1F9F0D45694EAF817A3A7D068D3FF6F054145C716DD7CE747D3889E49DB2121A81EB40E2E2D08750F1CCF791EC924ED46F3C5C741E57C9CA75D7EF3C821A3A2EDACA966CDA766A3CE6EC0DEA096870022496856890CAEE492ACBDB949FE0BD8CE0C3E72468318B0322F894C64EED64AFDE22A7A1C2B22B348830444DD5B99050B4D3976A70DED872E92593215ECA63D2EF78B901B89230D2C18BFB4D50EBC5949A090DA9D27C7B9B3ADA9C787913ECD0D8E578DB0D646965DDF5C5DD3395906A9C02E7F33194DA5A6583C198A7D41CE382A6BA5B8F9E52701B31E1987E7AFE0109391E187223DBEC2E516F103BE65BF0FF2141194836BC3DA9C1031A5D51676AE1914885D9CE838DB07F72B047AC46EBB3E1FC79AE2BA473FAC3EAD512D9F1D3AC2536093EA580F0384B36F8B798C8313207EA12A1E244F0B2AE1B64664D23C8C2D7CD5EFC95C18F4EB7B196F368F29D39578DD3F53E050D351AE6D93A40AD4915927D82925BAEB09E8A877AB1C6B704775C0EE210025CEDD475823479761DB3C8CFBDD9739754C743307E5B9E81036C748B79AB78D0C56DABCB9893147A5BF4E3655329E433A0521B08DE2BDE442CBE9A2721EAA94B4F9C0DFAEC4D500FCC073568B0421444AB51CE94C9489818D4C598C1E219AB50C7F7D914FD59BC96542C72BB3636746A9C08A4A416E7E581255FEF48340CF1D9D6C5E9832B004C0F646FECA43FBF0E016BBCCDE92C1CC9AF6C92BB735640733DC1C031BD10D554E51BE3DBE3306D64CFA148779EDCAD8AEB21F5FDF085FB1DA0BE2DDEDCD1B094810903D80BE04D1FBFA7E59E17069DDBB49EEC76320B74F31C4428BDE620DE149EE74DD9BF22FE0047FF71486E339072F2B603B8055D7BA43FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B58DD435FB4D9B5D62FDB9FA0A34224FAED03B10B5FE70EA67AE1A3005D3DC4AFBB064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C494E919BD76A7C971A7731B13C4601F7B659429C2F7F7592F4B17894BC1391235 + + +count = 0 +seed = 1840C60AD9F35C900372EF38D08671A74353C965C3C5DE0668C9C3E5CF3926304322530FD9681CF3A9C71FD633D60C66 +mlen = 33 +msg = B338DD755D5618C464AB331F14DE3DD4A358BBA00D28FB35236741E902F7B248CE +smlen = 14824 +sm = 00000000000000003017CF6CDBA4AF7D6CA495B9872967AFAB62AB87100AA92CFBD66591BEE188E6CE81C6363BA48FE2B0D71D79936241991202D5104DF670AF8FD02AB7A23DE82E836BC369F2D8F1CF51071C04B6F9E53D566244F07B484199D4371F1B44303CCE8AC6CBDDD4679835304CA9F74433A62DF5524FC44D637BBAB3520CE625826DAA944B9F2B22F2D9419B5B5DB6301DDEA449F184552E9EF0F4B80893CE0D38184D844AC73D3DF74710D87286288BFC59EFDA5B93828D6EE2785EEE07487B1B36165852D62225D7554249CC1FE71B8CA3B01240808B769DC4154DB886DB5C1EF5B55644534E0F86ADE3417BE364CACDF76C0C906F64BD58A7B363C52870995A9DDE573341348D3D99C6759EE3444AC8A7C1801E45A8981573519B8C4AE4954C0AD861B94240759D2668D905F569E62A80D2FE7A221D6637D43DD890EE5DDA19C64B97C8C184673F470042729CFC1417C7D363B9EFD028AF65E4A1C95F2E6286AE6217745BD9E9B7B1FDC64E5A30640EF813AE0A4B46D5EE89A7A674E2D96BCE130D78727144332A7276950BC3A0548E270CBD4FC31004AF248BEA3BF61558946A2DDAED185C777160E9B20E4A823B470CBD2D890348594F4502BB34E2CD86B1E5C393B0896752FCAE3699AF03C2E8C8725BE6073251317D1EEFB497336A32C511CAE0FF66E62A9501705B04495C7B1052E59C094A12D534DA283FFA112C6C4F0F84481FFACD6E480671C8705E234CB846BE6A2323B69DE001457284D03FB6709B9A09BA06825E1A32451CA92D7B58785E22C755B2083EEEEBEB7071E62A3AC45C099B5A7F8E341A8CBF33A1D8338EE6696C485C3447024EAC99D174BADC9F88763968223ED5CE3170858485437C132229DB3823CF7D727E8DDC6B6BF00983947D021F22B71F638350358266320296B2E22A7495A708E30B7835A169D303A94A318A3D8AC4BADAAF808051A63BF66C7426CDFAD57168794CF4B50D8FBE4439B6416CC20ED1097E1670E2B93FA14EB1BA35D7B2C047E6BE110205B80B6F169695CDD44B935E0ACFE1323451349968E0E7B71DFAC15FC53E1FEB7E987BBCE964CF61EC44881F2AC9A8E607CB63D640D64C4433EE80CBFDFBCB0B822F192A053C5120DEA4E6B4D0E8F6B2040D9CCF85DA7C9522BD571EFF09D5B1561225886FFCD6B78810F452317BE7048D2C1679145C0E4F36E34D3A45169F8127BE584FEC80129C3DE3F2D9487FC2287870964D9F328563E36677622B3E074A980DAB585FF96FD09B7A843E4B2BA51E42D964AF28BDFA113E2853EE1051EF044C34EE020DBC7172C159B394DE8D15BFECE1FCE1884860BE12411A625BAD6A8CD7A99C157C62AC36B3DBF8805CDDF0CAB4272FFA12C062DF8602E4E53CCCA89F5A821904F2CF333CC9C4D5288AAB31781CB01B5D4A9AA378AB2DDE7F865F0933515DBA6527FA1C44C381B553342B5840124030F6004BF0D0C29A67C7601C0FEA9192B1434C362D81C65728E4A8CA6264070A7F1F09CD093CAD71FE3263B0E60C73F5F8641AFAF07676799DCF127420486671BA5E757D09573B0C09130A7C90B6D8CCDF578765B4FB0BA839339BB9AB60CB5B1F922D6C430FDF84A3A8A81B7FC0282C404FAD61A9AEC079B54A100E0E44DB333BCEC50007F239B57FAF01D826F08313BEB59A591A4BA0C6D26F71CA01814F9DB4CF438E89C2E99E26EB47DEF45EA8A595A177DA49A888B84DB5B399E45FEB575E3A4131D0DD98AE8482529815DC0CF2717E7B9EBC26524503881BFAD12C8887BD0D9C2019ED15FC5DABFEFFFBC6117388688BCD4ABFEC0610C27800BA6EF3954933656348BDE0A3D47C80581305B672BCCA2A235F654F01A3F8FD69EC9C4AD644FC10F73E8D4EAA8D202E38A3609D1034E9A9460341D78347A384EFBE009EE5ACD512C88DC34BB54340BC9B1C0CCA389E8BDE6AF14B3DB250101F04D29BDC7D2094146125ADA6A3063A0098EC13C0BE830901807F99B5155C4BB0727EF06F5BA2D821170E457D290444C80475A6DEAA1E9EB7B334F93253913A2A372B5CEC76D57348A81842EC2A2BA6D8D23C976F3CB9F3D349A8448C5FDAC524981F6F2094DC9F5FDE8F50B7F07061ECA5CF27E01B529BE1948522206C8051F01577D24C318FEBC2762DEE56090A69FA567D0C5C78126420F1A05ADA51A6AFBD1EF6E49CE8FD350DE872090DE73F0C124AE014920F104EC5BC7EA0FCEBE08F20F05310687E973E17F1B39B9436F1C1BD5CB39C7641828A7CE9326E53A330165405C68139B17268176ECDB8152C820EFE4B2A27F111680129D3CDD01F47DE9C9D7E9E73AB798649D6E629B2BA94CEAA58172565F34A2DC536D64EB4C81041F74F76D99E4FF70A47B904C80118090DA4220AC717C36C588FD89EFC4730049FA8AAD5AF60BDAFAC1B2FCCA3ECB67A59F97E752BDC33C5CFF2E1ED929D6F4214ED25F04D7E07E38C51FF1B1B3BCF0D8D38B31CD3B8A69210C1C3E5A92FB8FF9E494DD38DDE356F73A78AFA9F052468928384DE9E28DBC174230EEF55BEFCAB87909D9D5B21508BBD0D5D3876F754FE9285CA3208CA501606F0EB6B7FA672FA34C4701D464A9F05DCD14482A95871046B385D87F0CE6BE103A45B7E8F10E458448E57618F066065AD0653A7135CE175D55D84E19D45932534D0045CE8827EA5B7096A5B0960BC218F36C8BE436AF40B6FC2A6B7D8884F55DB87AB811FF571FB01A405403F4ADDD2097729FDE708EB369DB19FAFC35528A11EFF706445E69F463A8321FB76FDF380A71B9412AC6DFE1FB190D60A05F8E5FA34E90E9F735BB155DA30A254D0B3C2EF633F5E04CDB10A20311D2846AB24749D78FAB6EC47F89EDAEA01CE9C99BAC79F55E0CCB1C03AF2EF2C56D45E06D33F9D3ABBC6CB4BE09793A386048112071548CF0A71C9991DBB3A11D93483E3716D9A8BAAF62BC5BB58E24D982E067547936FBB57F2C25218A230EFB1A665F3D948CDEAA9F8659900F10C43437C01BF081D2664641DB6FD5B0CBE2004A96DD26D999937817B3A8DFF7404AC0D7D1CDB6AB21EDBB8D7AFA8D1DA69E5878F2D83BF8B926E29C2EFEB16A4F0E70EDE870D540FE22DCF51857EC30BD19ADB90CC68E6E51F3AB68DE8785CF510E7F3A5A039709DF63B801DC3323251351376715F8095ACF170629954B96795175B24E1C258AAB6CC89CED08AD7F756DEEE47A8D0D840E9B431461563DB4EED9560FC38258423E965E31E14D6074C9346404A6ADEF162D1C91432E5F83F97BE838879301613ED7190B2364158338F84A912C522F3D9E643BB90D65727628D26C8694BB2E1F35A45A4C4DC4F6974F9B8371DEDB8D4567370FB91A3AB7744D87321D2A37E808A0AF39B13AEC4593BC12BDB3FFFB32E69644B7CAB6860EA783BCDCFF142775F8C724B9F3E28C6686F9EE8422B03DBE8FE038717EE84BA5A8636DBC22FC29FBF6D07DF598B4641D4EEEE179160AC230A6A201F4127333E15975099212DA36524881CE7A2BFDEB0A69944804A6406D160D57942E851CD23F2445BCD5894006DCB4491D4429B0EE86143ED4F2C9C8BB26721581678D4C21F93B7CB931516966BA24D9585F1C0B04D660E629B3A2A3F31AEB6AC3EE8DF4DB67DABB5C332B61CC10887A0A207201703DFC4C27B774468F2CD9C6EFC711426E248C33EF946923D4C1AFA7B608F9F080410AE8F9F08CB38D5C0F6664EA0F630D34DFC55462334F617F3E4AE640E6C2D27597D4967E08EDC91704B9E3EE49EC4F0506994C3DD1027F8BE7FC46589CC21F9BEAF4F4130BC7D8325FD638235372E12CBB84FC424BAFF7D301855839698FE2E38B63BE461E681B43A02F99E466319E808084BDEFF59DC9DA0BC5F523A21D4525D81501A83F357BAB3633C061D403C7ADD90CBF38C0FD6063BFD585AF9EB65E63542A64CF0294521F768291991A27EC05F90A36918612009A7CF4A981971AB37B767BC120AA994494DA75CABF22D1FE63F1464E981A0FF2BA93D3AAF2CEEADAFCB80FB7D012A588D4E409051A44F7287EB74B23A7F9A4302D2E7EA81F9FFD74D72807123DC3529B24DA2AF50619784A32B75985FE5AF8191B1CCF65322E266C37555CC3A971BF53E46DFDBC336CE5DAB6A84AC0F17F219C1DB9BD42A4F9662C74AF602347DE8A4EF176A34EAA287C9615F90FC02ABB78D80A6327768932976729CC4BC564E870C58EE9889C877CE31BA913EA7E454C0868D80335CC063C57D0BC1FB3C5E09B3A20F8166F8BDC41B01A8EEB62127C5BF88686BB8D0350F7BE6B56E0CE6E66B0998140C6F839A1AB13D68EF718809E2973CBB24BF5D927E83DD6C16C292D94B6EFE4A1BC9E050E8D6992BFD1C6F906C0A7B81474293A86ED095FD785C5BBA70F51BA7D49E9A5FFCE8193DD10914F642178026F159AE536FC1FABC7B78A3C2DF55D0C8E1EF23883C6FDBC053B447825E75F945D8157A967B58B0574C6E0615387CE1652DC027B72C45A8E9A4287219D85A91D9705220F5AD851B47FEC4C2F700C035D20BB3D317EDB29AF8ACD0EF71E8F5F8FE70F49B939C97A521454B0944E1BF53CBAFFAF3380AD8D273EA8117B1A8277D00D5F8C835AB2820DFCFC4C8AFB2CB247B6DACFCDFB3765002D7D6EBA358848E7C7C63DA066252A81CC95E38A556ACD239ACB010A8169696B347EE86AE99CC7386155ECC56277B39192742ED8C959F142209943A017FBCE130FBDC3A491E7F650C98DAA0497D6C9CCABFD02921ABE4CFF254FB1521C702FB19F3DBBA1B691F7E44003C618C1B0C1B68A840B9763D43295E0CB779A59EEF7ED63AA1020069B2EF88BBCAB1D03693FE34C4C497F7936878D4DAB7B75BFF0FD8A0509D9A3B0CF209C9B7D09732CA0914617778AD289AC2110692D502C8DC75316530280FC926A62D46620A91EB4C89377C47ACC72884CAE39545022290B0D0EFA74045E4FFE5B7950E421091808852738371BAF20E81ADEE43642303C0F979B8EDAF4B47ADFB135B60A3E4F0BD2340A03D9F774ED36135C7C7241A89B2E9C71979E6BAA1E4D272BEA996623E399F2DA2AAAF6D0CE10191BA0853C08743DF8F9C98575E4F398BC3F19CFCBDB00B6C71E6B2B86A0E3BB72811DA873A3A318F6F334B64992648C9DA43BE0DB9CBA43FB1191DB64EA575DB1FA7F5E345ED532AEFC9F878894723ACC25CFEA3765FD8B4445453AB184E6C5A33FE8C136C8B401ED890A840BCC8C13CE2560D86119D74B6258D4381A4813572B6AEE5DB91BFA38F1E36EFF3DE17E255F8302A3A8161AD44F095659EEBB8E99100B7A19BCB8842ED58C474D1FFC28FD87A032D583050C09C64D4AE5F937743FC5E4705D9EADC758DF2CE55F240A40267311278E9198452030917F0ADB64226D6D413BCCB02C9A5C830AE5F2DBF73BCD8161132CCF43553B8FBA8E5283C953AEE50DDCE4EB59D29E4A2E5DA0530B922286F3588848CAFE9182175706266C466D65F41C3C18B000789C74952E3E2FEE44CCD9DA324807959D7DBC2E486A467DC1B72392EFC9F6FCA352D6F93756A048D58C6E04B24FDA2C3239210393254B41DA390EE357C7C175EA1DFD32FE5AADE666337542E508FAD05AA818E37539322BE1320FB587B83E86AA18434C47CA39E9850984F7339BD164FD46557BE86FB71B18CCAB5C34449AA65150D6F47A8117453D706F30DEDEB127BBA56F23193113CCBEB626F61BC4EA2D5053B489414A7F9731010D4333E72690C936D00367C343DA301A455B4CA7DCFC4215B0EE5185F1DFEAD2F09542D42C8CC1BA6ACFA452C6237454C5D115C0F5E04479131F9F1ACCA098EF0ACDFEF6FA39E4AEE14B0823E911EF2DAE145E261AE05A117E5A52E9DEDAC73742F90B4EAA8AA944F14679B0F72AADF6B56B31F3A2AA0AFA243C3DCCF6FFD2799FFA1F9861A5C04B0A8F68CC1BC8C90703AB05FBE50C15F06B04570370DEBB7612D8B7B8C25C25AEF86E08DF0B7822772BF58BFDFEA74C75B634A5D436832121C0C078E6BA4A80F1A20BD16BA90FCD04D43A0927C164582A796C12545CBD0BE45745F9E0090A47F31AB9B11E1496EED876912B13A841C06B6A5E812B11EC912A83D6B8663FBA403442AB4C70D3CCB76BE6686CD55D831E8DCCD05594F47FD58A835E3132D95EF4B4E8EBC275280999BF68305531A7F9F5EF2E8ED77C42227D0ED07B337CEB70317037ADA07819791A04BBF73646CC89806912EB3E2BABA0C80C7EB7BBAB7CE68583B609A5152A39457D51EE0A3CB4E897EB6363CB767057ADD8A1BE0814B7733DF1B811D86F8059C38D2C10318E34F24DB29F0949A3686C63F474F26E2917A9A1B025C28BAC7D53E4E150E981E0D5BA4129911F99588369CD97444E871D47141AA795560B9576AF7870E3F62BC6F010869F6CA393E48A0BF5BE7ED218D65D942EC0F815F2258A47F7A509B6BB999C17B28D46B7D3CA59061D8B99F7D2210E12828849EC8CE337D281D2246850C3DC3F9FA763B0EF81885C09FB9C3782471D5185D98077B9CD560F0F2D8109B8F2DFA711892BAF0A4A828E506417EECDAD332975E49F3E9019CE173E2ED3985D7C241AB4F7AE082E8EF49FD22CAFACCEAAF12E4C4CDA200ED92E5AB50E9E5210C963B82E0245F45BFF0E90DA76B2409FB75636B8406CF5437F84EF8CBFD76ADCF101B25F0351A8AD6C3B6ED35BD20E3610A1B543C035C020AA24164657737AEBF745F9C2675ABCAF2E9F3E2376ACB015E5688C01DCAB49E1959BF677F3CD1CED88EAF7207516AF40BA2DE6AEEB6F2E93025E817C6C694E7CF245C9A024506AF8AFD2996B227984ABB85EB960AAD8377CA5D00D65A8D7B474B45CE65D9058146C78362AA6DE23BF202BCE88C7465524F0CC26A5485B4FD693B4021AC902860D7415FC49D59900F2EBE5B8B1A1826953CF77D64CAD20EE88210A5C8D4BD3180ED4BD9A262E54484F422D56F3567A412A71EED26885FF7F21BF3A01BCDDBACB58A73A3186829582E2DA1ABAC45E466E0ACBB575FC803A925AE3D90EF26EE91B41A4DC47A11F0010177C7F63E4A6E7D8241F8BAB4D68DE3288296539D0DDF68497D7634A964B76E82AF13767129B7FE5BF4C85685F9C1649B8A52FCBAA9B2AF0C0C2BE1904DEB98ADA34507734E7937BE5E686F6DDD4E57D5EEF9FDC2164D60CD06AB5C9D11B840625837703C3CEB44B6542B684CFC5EB9B3297D946E7F698FD75C5A824EEA9328EDBA65225623ECF3B1F560C0D9DD03CA404DDEB74F901FA06FF4D2B0972C31F94450036B01DDD94C162CFDE0019DA2B04096357E7392466D2F933D14E381D7CC3085A4CADCB0AC0CF31A27014816177F79DBE703195F44C47205EC4A5CBE62146B5246AFD86660BB52A30FCC16AC9D773E97F581C7518D007FE0489C09FDFA334F49313FAC2B579C7AF47F9946A85247DC902ACD5E0B22949F45945DDD51DF6AB0FBC225603D7377F93D29F2DF9500194E614F93DEFECBCA3AFB03D22F8FD7661D9D41D62D3F34476EDB8FE887C37129998A21E92F020460D3AF85356DAA577666F5DC0BCC5986DAAF87F5A9E602BA73B7392923FDC5B81A6BAE67BDABA7F7D2E9410D160455BE2CC6A833BA1B0F8FE54852A576BCECECF9BDAEF1C9B426B3DBCA32353CEF2D782F9FF8C8DB114C65E259BD077E800BBF0AF92AE1083501FBCB6D736C848AFA2C836F2E20EAC0336B58D10000EE1E6FE4AF2C87B2DB73F0F695508E653A3755D0CF17516575A25E8960FFDB7B1A00FBED460A8BC7EDC370A52E214885B7DD496596F52B1697C11D5127906C27EEA91E5D3E948E752D54EDC1A8284B9330F1BAF79C2B31C41136602FB4D1A7418EE586E7386677F90D185CF9D61FD7178055651AAB6AFAF6B955469C05B619297155F922B97B7FD28FDA0C0FF3BF34081177EC83DC0433EFB8A1417D60691D76E15384DADDFE66566032B722D99F959653F5C68D4FACDEB4DB5F9CA52CAB9D78109D66D75ECA67FE82A790ADABA4C8F8EDC5663FE77361E78A43189D2B89D1F26535B1E860C9F18E7A3BC6892A68C68AF96C1F4730192CE3BF69D4E7048912FFAA309913C054E041306B4B0079D606F9EF3E08020379FC3A11CE22436F7C8BE6C5F5EE2C1C1778320456C18A68F306AD1B55954389F635A502169454E7C432BADF0A68F529903CA29C2B836DFF01B67CB745A77A9E7813A52B92C810B51BC3E71D7AAA9A9F31EE4542965AA0F6F9907D1595A31E720D4A7098FB2D72F01F8B83BF3A93D05157307E2B595F0609BF2C8B94EF6A5D60E53F20C1559A9476CD2391127B12D77357269359C424A769021D139860DCA4136B718B65880234089C1138705945AB76C815ECB06C01C73C60312FE6DE218F09C1607F528CEDD2898E077008FF6E47C4FB6B2C103BA92C399A24CC38B373B3D7F00D63E6A42412F710C62528106482F703ABC7CD198A24723A6BE730E6DC971D468EA20D76800F938E651FAFD425643ECCDE70BB4DC1D6FE4E9B3D3624C330E3713065721BA000D6683DE4263DBBD2FFB0E5AD20E33F6003B0E85356FCD6847C7DCD156F805A9A513F17CFB60F16925F4C587744E4AD35C7127757AAD37B73E5277D6614F0C315BB9E3BE48F654AD2D343B3967FCCF5387EE8297F2F74214B7B154E1D715C8FEB898A1DA31D5A8ABAB9CDBAB991459E62BE9F0E0A69791265ACD8F7AEDAF736FB944D3CEA82A1B3F23ED9AC0025760D260009668580A7FED8B073D52EB9D1847445D2064669D9E03116C2D999F3274876F37552E2D8A04E4409EFB415FFD9571BBCCFDA01333286A5A934E32D7C6D7EF3A20DD86ED5391AF91188FC2BBA388067FA443275DF1C06B23BEBEB418CCF1A7CA0E4BAD57780AD7D5528BD18362F273F0D97C081E502F32EFE1508B343268F1D2EB3F12914313283E40F4EC9F02AA17AA8A310FF50DF2712F49896FE31BA07A188488E45EB59D6BD6B858D527BBC0892580637EE631FDE8EAC14EDEB1E73EC75C8C241294EA628DE7ED2D9FEE1453299D45B2EEF3039D2CC80F131306006DA1BD9D68084F72AFF47606C4D632B57BF57812D2B2CB85C631F239710C05C7743C2F4515F6C64CBBC8109E7FFA421A5A637256FFE7F44413BBDE5787EB92060591282ED69794E9D64356A585D5E293E705EFC493596D08F3E68CA984532F71A20D81C4BE0CA989A19C2FC268CACE37F8F2D5B481F2A4F387043A4715FE805C6FE2D4AB89DEBE10CAFD406F37450F0E477859629CE2B957F3415CC4E2CDB795EB766193DB9CC1E5D34B022FF9C01B7ABAB66A08EA5A0983E6E85954C92A6D3B2AB9D45BA49B21D45A3468B53440BB45283D3251613D162A9CE508A5766740BC16F13842C2F89F2396E3363A1934E3AF2E7221957FDBC5F2BAA72B6E62BAEB9E6D33B248A5102714178A60CD3A02B6E121E1CE591185608500C11AAAEB039497472C12F766386647573D2974687D3B63D655D412B1DC0D3084791DC9CF5BC4A42D6D3787A187D4765E5C65894BA159FCFEE27FB3B36A54A9FA312C81EA09C6762770B9649872A738FA0111D745A1F9A0BC53FA819D6E7220FB07293058C8EE51270F86D956780BB52984745B68DA948F7F936345F770F38661F35198D5BED466C3E1C7A23DD56D543CFC93078FCC7266BB8219611568877CFED4D596D7218D1AB6764E422874981B7871339ACAC858B546C9139F4B917CDA356F04B779BBF803351C1B452BD9EDD0E2DA226A5F930C3C97F43D4633BF11B8BCEBF646B8608685E36F0ECDE7C7FB5F977E4D61038C745DE151D832D47C979224CADCFDB0C82650055F1519B94680A840FA14B55B2190C71AC1F7A7AEED989BE8C8AC61149A0C809449B677AC353867D0185EB15322792A3A7E328FEE3DF2230E4B70551FD7F9BD57BBEAF02E40124C58F019EEB66602B9EA10094839EFA9070F5C2DA3AAB6CDE6EB58246A59AFFA0352106F2360946C26969F0372852E46749AFF6713022F5F8FA138D1D17A01F42B44C013843CFEF1EDA266283A5CE4A6ACD7597519FBD097E9E460D9B071D34EDC61672D14E6D9D4F9A033B5B473A1B13476C3C447E884455A5D168DA793F9E2F096157F1B5CC674FB289CFDDADB63DF46F2753E7B2775A411DEE754770918335AA96CB5D9CD1C95E50A0CB6B42693E728A0BA9D012330F3FD5ED1F8BB85AE97835CD6350671EA5FAE17751E2924E3CA8B377788D44E06EB9CD7366B406F61444068CA52174641AA678DBFA7BC12592E766B5C27CE49C72A8AB86CC68E2FBD6211FFA124FCE56A5AC28B94FB88ACC2A8AF25A40E3A79348167B5509DC5EB24A6CC5B832C73668D17AF4C29F2A72A1E8DC0D74C9F2446DE7A42F50A5DCA2F12EE84A91F75004E452A4E5FC799176A42B4D0A0A0CDAD9B44CC246872114650941B08315BA68E4B39A713B08A66F1715FE9300E5AAC533E37AE289B74341BC1DC7C75725C9838412E48A4CE312DEBC345B16A3A1F6388F350997448653448F6C7C91B7BE24118C3A0F4E431E88766E5A6C6113C8A2D1D2646B5EA5821C90CBE2CCB6CCA02A7306B38F3FD08B3D8A4177B44DD50D8F1ECBE9C5F7730EA926D482C3D845B2BD0A2D4978F82258687586F9E6EE6AA21877D8A2C7AE37332573C420DB9C8754CC20EB937A8B94056D96EF571162B0106AEBFC344B5F28D52B8CD02F6168F45B321639DDDFBB333C5B872E80370F408EFFB5CC7394767F8CEC0CDCD7C9189E1B24FD29C7FBA4B14F30B8F5996155855C08A749B6AAED58C55271223A53D1E8714549EEA65B9A9245D9F5AD2EEBAE82637B9E3C78A24B5262873759CAE9AF9054C3230F88509E71CAE2238AA2DA1C25F0DCBFDE9BCC7B234BF1EA6697DD4E8B020B099CD92492855F1B528BA0B359BDEC1E77245432B7B1B2A5A7B969947A2FCFEAB2E94762E2F3F524E88E6FEFC4DBECED7EA550E6BCEDFF229E69D9C7C7803FACF0284529618EC64E05B0A916DE5463E27597B745C58C05BCBB58C5200FE3E9847ED6D3A7874015F0AE87EE37FB6C478F7330A07D4C59E314847065E2F1F5F7F6DAE557F85B03FE6BB31B28A40263B64218FAD4572BC5FF2FD4E3F8F9A8894795658466BFB5DAFFCD99A69D532713CE072D81A42045933CDD30DD257F6C9848577D9F8B09B5D7BF71CF202AC4CF296E05C6A7ADF77D8FC670B88DAD02DE5A80D4168F7F72A7252B0E421F9734012AC8A8188677647D35ED6199EB300A6B71111D7CC77F04AF5E559A0D34CE1E1490576716A861E79902678C1241CB6F614176147ED88C82A99CCF2BBF62AE65572300CD4FB12DED4B6B0901D5F6BD02F036BF66B095215AAA76BAA4A07E2C0CAD2B2D76BEB56956C26ACDC11FDEFE9D42C6A698C09F0ECAC502F2F7E00233329DCA9595A191DF6C87B728E8F9B59105B9074992A62F2DFB38852C7F4BA5BF782395E906AF48136AB2DEAB4BBE7F0F79867696DDAA4176F14C9DC7A301B0DACA30332F73CA3356A62A4832A12DCCC3D696505F59E73148ED6401A34F6986428CB1CF18FD61DF1455A042455FBD97A76A404E65CD0BF41E26465281A0BA11EAA39CB48B99F2354BF5407629727B52DBA14B29C65083AE8B8891AECA5500BD15DE9E66E7D5C0104891C17A108B79D8D96D35F12170E2C930F8F16068AE3CA8511016203A1A4726CFEC7B6AAC959B67F3FF1E4AAEAD667487299703D38472B5085FC55B9BB775574AAA118BC81076CD53A4AA7E927482B1D617C09C6C24DEB07DD41C2C42B6A0BE168493CA5A40266AF5B992B9B2C65CFA82A2EFC515948A5FC521A7F49DC4BBAD296BB6FD4AA6FE1B7A7726229C03DD1043AE89A5349A1F9192CEA32FF331C51B99029914DED316746351E9B641D973867CC37DAFE8FC39332DFD321B1ACA45587EB6D4727F5AFEC4178CDD8AF03FA0629DA84844B5131CC2AA07E2FBB8F80D3320AF5C1734031AEB68DB8B6C7358F775E8538C260FE6A79DDAE2BC7D40222B2942A2D8ADD3F295A135B5FBBA319FA3636F56D1BC8CBFA175EA61C1F53980664282E56291B4ECE5B5FF33C2141F04A3FF83EFC062CF6C635497FD03D6E56E405C43C4A31DDE872C4E277AA190D1D8350A298F16BE75BE305891F9D1084146199960A881C34318CFCF1366E82A487CEE95D5EC9F9756FFFC9DF3A1058E367160B321753C937D587130F9AAC766C19F033CCB2D886AB532683F50D360D10DF559AA16DA2C0E3203337B46EA1FCC1407675C5057052EDEFFF36BB2A6331522DC5CBC871C52CC35E95DF677771084A6E3E10A56111E6B9F7DAEB1FAA11B9CE5EA450A7D75F2B7266193CEA51A9532D8A32A2D4C275ECE75C3A59C3F02E3F9F40968642D6387F752C801A761F121A3EEF4F6B0AB83B7E815E5BB9D67EF85BF9DBF72E5E6DAEF4A6F7519130BD4F826A82D23332BC291A3D320CBFBE4BF1A143B78FAF7C1BF61F30801BCF715A05F2F7429F0D1A3B9F90D191754FE3D761A77CEA46082D3D2CA5BF26EF05257DBC8B72D156920EBCB1E064FBEC3CA43AF31CB2A53B246BA02E3F8AD4E07DE794CC1D8E3814DE61807A116F768CFFB159D16CB7214EAF1F52452B768380F4E16E2BCC10E82A027148477F2C717844DBB1677D6F2559AACA58E4759D40C7D62610399D6EDBC6DD4DA7904D2C53E4D9E07928FE181D503C5D45D6DE07E767025D9B0386F8C123C38CAEF00BE2223E8B1F46370B1D20FF0DBF78CB6A016D0F72F07820238885D3269D22E4E45462E1FC4283961785820FE1AF085BADDD385B99F1DFB5C16A3A1E6EADFE7066FC6A5781AF310597B333977E34D01483A860E7D986357107DADB4F5D040550E524D9D1AA456CAED45FB5F6475160AB01C8AEC46EEA735384E4FBF205BB117F68C03F6D301E5C469033B05360DA23CF49DA36E050D627B2067B30983B2B426DCE0B78C0500BD15B3D2572537DC9B5F0BC0E1A12F533F58B2E21102318B0AB3341FC2C6D237287114820AE20D45FB96325D2A1D2FDF104108EF3F5C33BF53D2A951EA7BE7FE2D487362EEC1DCB93920B266C5AD39FFA0FC6D4B335B1355A6D8AD3CFE51E9F69C8961A82831BD27F727C9030A816E817783DF89B519D6EC14C9CD88B73FD6152250E229BC6CD8C952777CC5D670051B18F5AFC99860FF7387C5880564703541C2883BC93C5C0EEFA57AF9E9D9D04EAB3BA87782807C37D299789C60C63CC2E86B5610ECA54D3949E17070B1978781F705E32042AFF28FA979979A511C5D14ADD08AFF7DDAE858415D7B0CBA138BF6D1C72C99A9564FE6CB5C9ED554B98D21CB796FC053CAFB4B3E8214F44643C99D9C92EA847A1B6DF3BC21FBF810F9D04B26771BC6DBAD0BDE30265D402E62EEE8ADC84CE8AF0FECBE8F68D13501515B8C28F68AD45D9D1A454904DE944A90C7500049FB74979AE952EBDCBA09DE543283CCA44D3F00EABF99DD714B8FDE3755D30105AC8CBC4569789B900129140D740E82653975625288323BAB5437CE832A600D1F344C411935E2773E3B03C5E4959D9A2F7D55B05B8574768DF40B5EBF76FCAA69F463E0FAFC9F02B01C7B89C1AFB661B43AED07A9D54A6669DCD9022A4EA628CA69577EB1D92A0648FBA768C9539AB22C6A7FFCA85858F1BFF4AD7043CC3CFCB3E69E2D6EA8BD1B2082A8D546E56C4B994E44CD8342621BD2027E5880AEF36EE7DDC8A8900875DE5D77074DEA0AA6AF1C0D403ACCE8E220D2AC30693BA865C46BF7416F2E53CD57DC43DCB9D0FA3300DF706BA4ED6872B2A3E417ECE57E42541D95EBEB238A881DF4445CB68718B3616B3456930494CD31924E7B60BCA6F85CFCEC61AE59F8968E30E844A031BC745FED8550EE78B1266A91694B967E66785403F9FDE097DBFF047A171318C43FB2472127512463FA79877B475C7F810D28AE0BA7C5966102673F9F55653D9E546E378D2BB17CD35FAD2F50C5372DF7871B1F1DE78A72FC84F2AD1BACFB45712FB13E3773B3565B021D30A31602528EF16FE6D83795A1A8620E06BE25AAB07A8F3F1EE979687840B7C863D0D8A547A5F7197FB72024DA7F0D3E331C300BBA084A239D762A49141F81E46C97BCB157E81FFD88A34862C07F224E2ABEEEDB7E701AEF0A2FBC73A73CCF9B88E0606784D0BF4E99D41EA993B5401881439CBF17699A62F3D426EBD3681942C7F6F7B40835A7C996B400565E8BC9E636698FE0B197B96767C304CC366E2279F19A9E76B8B549DB73200EA7B3F788CCA15EC4A56D86CFBA4058C3C514F3154854CA6939229C3FAD386BF62626211CDAA71529B5410E08604348A4FA025A71894B946DF27454F27BC01996F23C8677C11780437BBE7131493B77D15C667AB0012BAD1CED0DE088C3D83795C30A3E34C878413680940B88C4693DD69B53E014174D8DB87EA6138C8CA99800F4F93981189912022DDCA5B6D5AA4DD2E04C394191204492E8CD5BD3B1599292F066E4E9D5917ADC3CF954851323255BB47D6FB2B0B6E93D9C2E39E23F7F02915149F9234FB2F13E6BDE58B24DD23CAD19056B0F92E3C1449421FEB5A740C7BDD04C76D8C2AA84F1BD9CCB562B9AC66C54ACC986BCCC869025339B9EE0CD9B8C0D7025B3662F8BDAFF77D6C77324F336C1A5276F7734EB3399FEC4A5902AA5971A933EEA9AEE40BCF69C70168BC10F1E9576CD541325A8A729566CAD7C0483ACC8E23D17DB2E495CA46032D9EAB61DFB6703C7C06BA4FD0513B55B05512CECC642CBB9D75AE94922FA66546C306BB281A106EB0D25D4156DD04911DB499F9A77B8F8487EB0287D9D564EDA31C37DD33E57A8D5A33C3088F4269E28E87145AC781DC38A75D575DDDEF448BAA06A60E54E4F6EBF94B095C14E36CDFD29B45BE3455F1930F39F77150E595CF127D1FB7E8226CA954C355D7098E783D32A41E702A611115154F3DB1A8484E4C6A81D13632998E75BC4B868F7E6178F035BF1BEA7510E3A823DBF976A0741138D1D5C9B2B434076228B7C3DAEB0576CD1194E82E62A8F902F9C84A1040262E83913A179EC88A1973DA20CD50D9676DBA1B8C036B97AF2C2005F1F556D1C462DAAF0E1E720B728AE3A7187F576F6B19177F83CB2953F058E0573D795A69B4C72365CE904C9690FAD0ACBC12108D950BE728E935FB7FE0779C54C8C0CDED49F111DE5777AA6131EE9084796DDEE52FDD7567A66ACFC8BAFFE19F46D0BC02258E9CD605176480A7E11B2B7283334B1398342061098099C06B1DB47A027B6577055A67649E98A0AE2E890FAE3186EBDBC6962257DCADBD50352BF17A03933D6BB6E00C1AA62CFEF7C7834BB0705A50205C4EF8D3270C4A0716A593858D31D1B989FA57C694A39CF877024ADFBC5FA2386FD36B07BE137723172C0E08CDDD0185E2510CAA4E4845ECA6C9750F4501FEA182D7748CE3BC2C902DF532BFAA83B530C214A5C649102309116DEFCCD338D8AB9CBEC500C26095E4BE1521964AD4694546C8D1F3774776C0595E0ADD0203F0FE1489B43ABF5FFA96C25138D539203E53FE2EDF38BA68448A3520CCF623D8427DE666CFB05E0BC25452E526C7FFB8D1DC496F047277FB03444CB5ED7342FFA18EEE7B1730925FDB23A34CEE84A5DB13C4AC46BE0B0FBF36759DA3E7B8C3289628F7E8254BDE347A1267A888D7FB18D021FC09668E7DDCC0FE714DFCBCD73AEE1395991E44B423F05043F6094F3930B33ABF6EF6D5AD18ECADDB1B477C019334C76E553210D4C89E4C32DB105FFEA84396B80DCE49EC772FC586D65A0C6FA012888B314FCA5FE7D56304AEC2B6EBCA87240731E19F8A237E3080A5B4FB92BC823AEA37AE3886609B5E4335559AB13257E92D2EE60938B3FA1A8B15958F8340A6062A0045C098A08D6A78F0C8806789322017F576BE2590AF4AFE35C2C1DD17A4EFBCE7F65B7FCED0A56A91C2D5724455D0A7A4BE1A543451792BE01E9A9614C6026623E730A21A5AA1B22EA38E983F1CB3C6AFCEE94FD813CE143F84FA32A70A97CEB20BA50BEA097D13CAB9F0E7032D052D9D9903A39F07E56690711D67081510427FE7D665D64BDD70EFD0215C6EF994CF6FD7444DBFB51DF33FD88A9B2D54BADC321512B7B57AE2AEF89959050169E710CC7D38B011611B655BA781A5B3391868F48AE12EA4F0D539BADFF7D81270E6847C387DD76569E539687B1FFF23F0226CE24125D85D229804869826671E44CD3B5942738E53432EB5267B1DFD7C80DA709A3E6ED28B83E10721F4D08519A3474C951803C0172025BE77A6CD8F5F9B9E09ED8CEB187F381D57F893F96E78A10C1AE29A306BE20246579F74C2AEDA46D2FB03A5A08C152BD736C93C7450149AFF1C0505E34E48C193F046647C61565FA6BC99044E7FCD0488716774CC0371D9ABC47CC69C415AF45B35FD240661DA201D3906863E1E0236A8A0307E854DBF000462D7217090E77A43FCA84061F881F71DC197BCE1D6B518FFC25A3E4926F64229AFFA4098F5198DCD8BBD2F99F95453723D6BD04DC5F2C732970D2AE4A9165E3AC8C8A767F0BA93BCE6F76F1E4A96D167E9EDFBA17A78E7EB3015E158630058EFDA8FFFD9D1B074C8ABE07300265DBCF6CFD550047FECFDFE05721DB0EC4FC21D4C675B7387B6D524DF052BAB92912B6DFF155F00462AF058203F94021F6388249475132A803A31E55E366AD3935EA2D7BF1FB0DD9AAB9D494ECCB3B7D0B7663374228438E11FFA2918324BAEFE443FB17B1A1950B0989D5B3379A13D82AAC83687BCCA2358DE7DA30541EB84E75DEA2D27409E7C02131C1FEFC1E02CA55584FFFA7CD7E8B6E2E2B7B685BB96710B6BD0B672334E8902CF6D49F47CA682E4343EB5DD588B7E61FD37D1972BACBC77C27CF06218B51E82E000185CB9BD13F89E6C3AF38596F181FC8A31B68C8C21DC711EC8BABA1CD7E812B4D6C939B449251718439129B95119BC9BE22C5E237B0B083582093D9DFF114C0F632A0C0016FF3A53167DB27B2F226A2B4B5EB7A409915DD46A882362462CB5BB7C3D2FA7DFAE5EF6969F34FF7E1B0958C4297CECDF374312B3231354D04E61AB4B668921E65D7ED31AB5AA46E5DE9EA4F5243CBBDDF261FCE1BCD26DE90FB46AF9453164A3FE6DFD83DBEFCE4CFEF2250893E21030934A382A288C69BF0FC7E9C92280906A4BA331C652BC4F904B9B54DCF3DB0651E43A6C83FB9843F85F0DBCA8D2E7F492200039906CF62A95D7B1830FDECAC0306B1A98B6F7B399E406A172202E29FA157E168F4B9C6979150F5AC2EF7769E4A729B6D59DD8F944E9A4A118FD06355D19B28ABDF256B4390DCD5C098DE989678AC25659763FC22E05FC4EB5860F4532E1EFCBAA0ACFCB91F30D21D2C90F8DBB5B419D8771AF1FA14AED614FA2B5DAB9F6F85016293B0716170A972790FEA6B0967F1FF1848CD29934182A9DDEA9BB49DE7B0A8EE13DA1F0A46E2376820EE34C1CA84E4524F21B5AA5FF74310EA831A3D3D08BCE359B830828E376B3C3999A9AC6168ABC74DDA8FFF0B35D6CD022BEC9BF0527A743822DFB79CBC96A90B6CF80B4E244E8F4386B653AF3D322BCF1E0DA62C28D019C7BB1B7D245E3B773871F0871B12ADB9306D31135B241A8E49D6EC6743C95469C24DAB5CE75E670357F3D22481C2E01E30215A0538DB0448CB9340D58FC633C9CA5141CFD79109D30F5943DD8A69F47F49C25E89EF486180AE64497FF2197EE4D518994942F6FA35BAB9D747CB356907B409CB427788C3D7708D77B706D9F90FAC25E492EB60F2DFAD94821D05D8F5721D46560CDC2E43963F70B64C7EC230170F2221693D7FC10B0F27CC4B154EDA86B74CF82CB44EB097E3703FE0B938346856014A50A106F64B236B17DBFEBF2B455FBB9C999CC1F9E7CC7D4DF12E1EC6CEC249345EAF4DACF0D38453A533E5193257BB55AA785666C64B91491B0A5DB93688FBE07D66D926759B669E18521210CAD05EF3F8972754DEA64BC0846516FEB472ACFF5EE2D7E29F7633E32E1A91E5DD713A56AABD6ED1EB967F371FE4D1A7EDF2432FC050A47F34300DC4B69F8553FA4A23509A45977E62736EC9653A51FA687A30FC0787CBD6824BCE36088AACAE7F55D877F773255A13B3A006CE4D2B2ACED5C03764B81B9DE5D9E0EBF9230164C5F75F05C4353F64A182FA15948C9BD8D89E5C6364B84ABFBEE413D0EC4D3B553A46B63FF0699542A2A7ED568B6E8A9C2C772B4F7F7FA17726174968E216636B4FC547AE59D73DD40F320D6B3329C868728B97CC704859F851149108B705C39AF3DD97EFAEBD39ACCFAAC8EE1FAAEABB32E689063B11483C47510DA0DA16B02EE4E397B146B6F777B1F2C393379414F67BCE670BDDBC67BC8ACE419C2E48C5B57EC624C5693562B719C7E696E1C83076E0EDE8540DE3D7AA00AC5A50E481F7BAA41C43A1C2EF09100EBFFE5EED9FCC095945F525F66ACD9A814582D6609DE9FDC132974B98454B501DEAB673C6D33AD29686E1D43912840DF6398F2468C0788D1D3B597004E6BDB7A89B57DCD4249EB51489F4DDA36B0A3B90C4EA616135B089C4D4B8DA02E695EB8657B2E12FB5554D2D833353A3FBF3FEA441A755FC4F0A49C243C3682A20B04AAB0EC430C9BFA134C383E4B6FD45DFB613E362B171F0C2B2473B38E92A21C72C100505B3E2ED5EB14D1ADEF650C7254F5163A2FC01B987E3000517DCD878B3D9268E912CA3675000B10E53F5B8172477AF6FE3778CB0E5D279309245647970C216E2E626D2148795132C2479B65FEEFD8B38395AE4A34ACD06B005F311974D6197A0FB415D7FA5E64502FC8C878B14462F0C6458E04BE6DA9308697467937AE52099382FCDC35FD7D2734B1150C214107CA53F6EAC9D584AFF8FBC6C2AF2B711F45BCC5626B1FACEDF4AD03E261A7E095044665CE61C3359BA5A046E44C8E5506E2BD7D4F6F08B57C7303472AD0369BD7B5199525024D34A0143DE46F8F3316F4A8B93DC5AE6B02A0F362EC7F9EEEF5303E3C0E13246E0F214FC2843F6116A7986920BAFDBC483B7D8F84ACCA690C6FBAF794BAEB0B687249A360CFE9E1C0A2817F2D93A166ACD35C00A1BDC4B1AC6BAEE6588B0958D5C2A0D63E6DADD81AE2ED7B8ACAA19040E7E30E454D629944FD10E1AC8ADC8C0CBCDD9868B973299A4DC927C49E944C7C00705669F96557477EE62F0E6140D613B110B9FBECAF70983B17EC4A470FFA4BFB8AEDB435FC607B957898278FC2D33E66F68E1F630D4A06B6413ED8C2B7BCD931DD4271D12B29336E47FBB378D48A956DDB447ED3A2B93E3C3A5559DB3B18505CFD0AE9377C5F87964A89B20952F5804125EACFF6CD0C256CB30288ED1BA4324F9F7850AB4A14F5107A91C3DFF05B82D1C4E3BBE38B7C6380AD2D1C41621187066598C2A314A84E55E8260D78D6220923EDF59C8CB7BB6E5B6AEB96BD7E436D19DBCAF897D8A2B3B41D17163C52CCCCE010274A70B6B985545072CC765A499A3E4FA7388E44F9A1F9F0D45694EAF817A3A7D068D3FF6F054145C716DD7CE747D3889E49DB2121A81EB40E2E2D08750F1CCF791EC924ED46F3C5C741E57C9CA75D7EF3C821A3A2EDACA966CDA766A3CE6EC0DEA096870022496856890CAEE492ACBDB949FE0BD8CE0C3E72468318B0322F894C64EED64AFDE22A7A1C2B22B348830444DD5B99050B4D3976A70DED872E92593215ECA63D2EF78B901B89230D2C18BFB4D50EBC5949A090DA9D27C7B9B3ADA9C787913ECD0D8E578DB0D646965DDF5C5DD3395906A9C02E7F33194DA5A6583C198A7D41CE382A6BA5B8F9E52701B31E1987E7AFE0109391E187223DBEC2E516F103BE65BF0FF2141194836BC3DA9C1031A5D51676AE1914885D9CE838DB07F72B047AC46EBB3E1FC79AE2BA473FAC3EAD512D9F1D3AC2536093EA580F0384B36F8B798C8313207EA12A1E244F0B2AE1B64664D23C8C2D7CD5EFC95C18F4EB7B196F368F29D39578DD3F53E050D351AE6D93A40AD4915927D82925BAEB09E8A877AB1C6B704775C0EE210025CEDD475823479761DB3C8CFBDD9739754C743307E5B9E81036C748B79AB78D0C56DABCB9893147A5BF4E3655329E433A0521B08DE2BDE442CBE9A2721EAA94B4F9C0DFAEC4D500FCC073568B0421444AB51CE94C9489818D4C598C1E219AB50C7F7D914FD59BC96542C72BB3636746A9C08A4A416E7E581255FEF48340CF1D9D6C5E9832B004C0F646FECA43FBF0E016BBCCDE92C1CC9AF6C92BB735640733DC1C031BD10D554E51BE3DBE3306D64CFA148779EDCAD8AEB21F5FDF085FB1DA0BE2DDEDCD1B094810903D80BE04D1FBFA7E59E17069DDBB49EEC76320B74F31C4428BDE620DE149EE74DD9BF22FE0047FF71486E339072F2B603B8055D7BA43FD71B3CAB178F34703FDB8ABDD8F5C1461F89446ADB1175E35428091CC0A3B58DD435FB4D9B5D62FDB9FA0A34224FAED03B10B5FE70EA67AE1A3005D3DC4AFBB064A22AD6A9BB05C15228E1D20D4A4E8D041BEF83790E9707A581DBB7689E032A083381899EEF508E4B2A897FFAB447F821C848EED8CA09616CE2EFD13966C494E919BD76A7C971A7731B13C4601F7B659429C2F7F7592F4B17894BC139123596F5B92139A4B5768CDF2E35810BD1AB3BB40DCE3F38853783F6856552BF95A4A835590582BB7206044086C1CA3BD9B8ADFB09C40A838DEE80E1B3756F98073651454C1567EBB9BB8D9FEA16E9CB0F30FA5E7944CCFE2732FB90178A6F439EF2C83D0FD90FA196CBBECA9DE1DA63AB609F53BF11303F3AE2283195AD62587795E7CE13CCB19132890CE25B085F7AE282F8DE315DED51D9E7B4652285ECB3929B9D6F51E82EA4BB5AAB4110925E014691A62121C27B5D929D24069ECDD6148B64213FCD94FB9EB6CA08C3D942DCB7FADCE9FB3917E40A455701CA8028A1456EDECC5EE3A3A27DE819CC28084BA0BA992CBA7D3DEDB39B4FBF247D2845FF9D4B455F5D29E81C17C5FFDEFFF7CA2153F968A130EED46293DACE1777C0173B089DD2DC63CA91C994E506ECC920E8A96608FB6E4F970A59145E77CBB83D1A5C22F917 +remain = 1152921504606846974 +max = 1152921504606846975 diff --git a/tests/dump_alg_info.c b/tests/dump_alg_info.c index 6b07b40155..3bee2d2737 100644 --- a/tests/dump_alg_info.c +++ b/tests/dump_alg_info.c @@ -54,6 +54,25 @@ int main(void) { printf(" length-signature: %zu\n", sig->length_signature); OQS_SIG_free(sig); } + + // iterate through stateful signature schemes and print info + printf("SIG_STFLs:\n"); + for (size_t i = 0; i < OQS_SIG_STFL_algs_length; i++) { + const char *sig_name = OQS_SIG_STFL_alg_identifier(i); + printf(" %s:\n", sig_name); + OQS_SIG_STFL *sig = OQS_SIG_STFL_new(sig_name); + if (sig == NULL) { + printf(" isnull: true\n"); + continue; + } + printf(" isnull: false\n"); + printf(" claimed-security: %s\n", sig->euf_cma ? "EUF-CMA" : "none"); + printf(" length-public-key: %zu\n", sig->length_public_key); + printf(" length-secret-key: %zu\n", sig->length_secret_key); + printf(" length-signature: %zu\n", sig->length_signature); + OQS_SIG_STFL_free(sig); + } + OQS_destroy(); } diff --git a/tests/example_sig_stfl.c b/tests/example_sig_stfl.c new file mode 100644 index 0000000000..f653ccba4c --- /dev/null +++ b/tests/example_sig_stfl.c @@ -0,0 +1,164 @@ +/* + * example_sig_stfl.c + * + * Minimal example of using a post-quantum stateful signature implemented in liboqs. + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include + +#include + +#define MESSAGE_LEN 50 + +static OQS_STATUS do_nothing_save(uint8_t *key_buf, size_t buf_len, void *context) { + (void)(context); + (void)(buf_len); + return key_buf != NULL ? OQS_SUCCESS : OQS_ERROR; +} + +/* This function gives an example of the signing operations, + * allocating variables dynamically on the heap and calling the + * OQS_SIG_STFL and OQS_SIG_STFL_SECRET_KEY objects. + * + * This does not require the use of compile-time macros to check if the + * algorithm in question was enabled at compile-time; instead, the caller + * must check that the OQS_SIG object returned is not NULL. + */ +static OQS_STATUS stfl_example(char *method_name) { + + OQS_SIG_STFL *sig = NULL; + uint8_t *public_key = NULL; + OQS_SIG_STFL_SECRET_KEY *secret_key = NULL; + uint8_t *message = NULL; + uint8_t *signature = NULL; + size_t message_len = MESSAGE_LEN; + size_t signature_len; + char *sk_fname = NULL; + OQS_STATUS rc = OQS_ERROR; + + /* + * Steps + * 1. create stateful signature object + * 2. create secret key object + * 3. set key storage callback function + * set mutex if necessary + * 4. Generate key-pair + * 5. Signature generation + * 6. verify signature + */ + sig = OQS_SIG_STFL_new(method_name); + if (sig == NULL) { + printf("[Stateful sig] %s new failed.\n", method_name); + return OQS_ERROR; + } + + secret_key = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (secret_key == NULL) { + printf("[Stateful secret key] %s new failed.\n", method_name); + goto err; + } + + /* + * Allocate storage for public key, secret key filename, message and signature + */ + public_key = malloc(sig->length_public_key); + sk_fname = malloc(strlen(method_name) + strlen(".sk")); + message = malloc(message_len); + signature = malloc(sig->length_signature); + if ((public_key == NULL) || (message == NULL) || (signature == NULL) || (sk_fname == NULL)) { + fprintf(stderr, "ERROR: malloc failed!\n"); + goto err; + } + + strcpy(sk_fname, method_name); + strcat(sk_fname, ".sk"); + /* + * set callback to securely store the secret key + * secret keys are one time use only. So after a signature gen + * the secret key most be advanced to the next + */ + OQS_SIG_STFL_SECRET_KEY_SET_store_cb(secret_key, do_nothing_save, (void *)sk_fname); + + /* + * Generate key pair + */ + rc = OQS_SIG_STFL_keypair(sig, public_key, secret_key); + if (rc != OQS_SUCCESS) { + printf("[Stateful key pair generation] %s new failed.\n", method_name); + goto err; + } + + // let's create a random test message to sign + OQS_randombytes(message, message_len); + + rc = OQS_SIG_STFL_sign(sig, signature, &signature_len, message, message_len, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_sign failed %s!\n", method_name); + goto err; + } + rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_verify failed %s!\n", method_name); + goto err; + } + + printf("[Stateful signature] %s operations completed.\n", method_name); +err: +//cleanup + OQS_MEM_insecure_free(public_key); + OQS_MEM_insecure_free(sk_fname); + OQS_MEM_secure_free(message, message_len); + OQS_MEM_insecure_free(signature); + OQS_SIG_STFL_free(sig); + OQS_SIG_STFL_SECRET_KEY_free(secret_key); + + return rc; +} + +int main(void) { +#ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + OQS_init(); + printf("Stateful signature algorithms key and signature generation is not enabled.\n"); + if (stfl_example((char *)"XMSS-SHA2_10_256") == OQS_ERROR && stfl_example((char *)"LMS_SHA256_H10_W4") == OQS_ERROR) { + OQS_destroy(); + return EXIT_SUCCESS; + } else { + OQS_destroy(); + return EXIT_FAILURE; + } +#else + OQS_STATUS lms_status; + OQS_STATUS xmss_status; + OQS_init(); + xmss_status = stfl_example((char *)"XMSS-SHA2_10_256"); + lms_status = stfl_example((char *)"LMS_SHA256_H10_W4"); + OQS_destroy(); + +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + if (xmss_status == OQS_ERROR) { + xmss_status = OQS_SUCCESS; + } else { + xmss_status = OQS_ERROR; + } +#endif +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + if (lms_status == OQS_ERROR) { + lms_status = OQS_SUCCESS; + } else { + lms_status = OQS_ERROR; + } +#endif + if ((xmss_status == OQS_SUCCESS) && (lms_status == OQS_SUCCESS)) { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } +#endif +} + + diff --git a/tests/helpers.py b/tests/helpers.py index fc22ef809f..077b4d428f 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -12,6 +12,7 @@ kats = {} kats["kem"] = None kats["sig"] = None +kats["sig_stfl"] = None def run_subprocess(command, working_dir='.', env=None, expected_returncode=0, input=None, ignore_returncode=False): """ @@ -108,6 +109,39 @@ def is_sig_enabled_by_name(name): return True return False +def available_sig_stfls_by_name(): + available_names = [] + with open(os.path.join('src', 'sig_stfl', 'sig_stfl.h')) as fh: + for line in fh: + if line.startswith("#define OQS_SIG_STFL_alg_"): + sig_stfl_name = line.split(' ')[2].strip() + sig_stfl_name = sig_stfl_name[1:-1] + available_names.append(sig_stfl_name) + return available_names + +def is_sig_stfl_enabled_by_name(name): + symbol = None + with open(os.path.join('src', 'sig_stfl', 'sig_stfl.h')) as fh: + for line in fh: + if line.startswith("#define OQS_SIG_STFL_alg_"): + sig_stfl_symbol = line.split(' ')[1] + sig_stfl_symbol = sig_stfl_symbol[len("OQS_SIG_STFL_alg_"):] + sig_stfl_name = line.split(' ')[2].strip() + sig_stfl_name = sig_stfl_name[1:-1] + if sig_stfl_name == name: + symbol = sig_stfl_symbol + break + if symbol == None: return False + header = os.path.join(get_current_build_dir_name(), 'include', 'oqs', 'oqsconfig.h') + with open(header) as fh: + for line in fh: + if line.startswith("#define OQS_ENABLE_SIG_STFL_"): + sig_stfl_symbol = line.split(' ')[1] + sig_stfl_symbol = sig_stfl_symbol[len("OQS_ENABLE_SIG_STFL_"):].rstrip() + if sig_stfl_symbol == symbol: + return True + return False + def filtered_test(func): funcname = func.__name__[len("test_"):] @@ -141,7 +175,8 @@ def path_to_executable(program_name): for executable in [ os.path.join(path, program_name), os.path.join(path, program_name + ".EXE"), - os.path.join(path, program_name + ".exe")]: + os.path.join(path, program_name + ".exe"), + os.path.join(path, "Debug", program_name + ".exe"),]: if os.path.isfile(executable): return executable assert False, "Unable to find executable file {}".format(program_name) @@ -159,10 +194,24 @@ def is_use_option_enabled_by_name(name): return name in available_use_options_by_name() def get_kats(t): - if kats[t] is None: - with open(os.path.join('tests', 'KATs', t, 'kats.json'), 'r') as fp: - kats[t] = json.load(fp) - return kats[t] + if kats[t] is None: + with open(os.path.join('tests', 'KATs', t, 'kats.json'), 'r') as fp: + kats[t] = json.load(fp) + return kats[t] + +def get_katfile(t: str, sig_stfl_name: str) -> str: + algo_dir = '' + if "XMSS" in sig_stfl_name: + algo_dir = 'xmss' + if "LMS" in sig_stfl_name: + algo_dir = 'lms' + if algo_dir == '': + return '' + # Replace the "/" to "-" in XMSSMT parameters + clean_sig_stfl_name = sig_stfl_name.replace("/", "-", 1) + kat_filename = f"{clean_sig_stfl_name}.rsp" + katfile = os.path.join('tests', 'KATs', t, algo_dir, kat_filename) + return katfile @functools.lru_cache() def get_valgrind_version(): diff --git a/tests/kat_sig_stfl.c b/tests/kat_sig_stfl.c new file mode 100644 index 0000000000..5c99f5d5bd --- /dev/null +++ b/tests/kat_sig_stfl.c @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: MIT + +// This KAT test only generates a subset of the NIST KAT files. +// To extract the subset from a submission file, use the command: + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "test_helpers.h" + +#include "system_info.c" + +#define MAX_MARKER_LEN 50 + +static OQS_STATUS do_nothing_save(uint8_t *key_buf, size_t buf_len, void *context) { + (void)(context); + (void)(buf_len); + return key_buf != NULL ? OQS_SUCCESS : OQS_ERROR; +} + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +int FindMarker(FILE *infile, const char *marker) { + char line[MAX_MARKER_LEN]; + unsigned long i, len; + int curr_line; + + len = strlen(marker); + if (len > MAX_MARKER_LEN - 1) { + len = MAX_MARKER_LEN - 1; + } + + for (i = 0; i < len; i++) { + curr_line = fgetc(infile); + line[i] = (char)curr_line; + if (curr_line == EOF) { + return 0; + } + } + line[len] = '\0'; + + while (1) { + if (!strncmp(line, marker, len)) { + return 1; + } + + for (i = 0; i < len - 1; i++) { + line[i] = line[i + 1]; + } + curr_line = fgetc(infile); + line[len - 1] = (char)curr_line; + if (curr_line == EOF) { + return 0; + } + line[len] = '\0'; + } + + // shouldn't get here + return 0; +} + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +size_t ReadHex(FILE *infile, unsigned char *a, unsigned long Length, const char *str) { + int ch, started; + unsigned long i; + unsigned char ich; + + /* + * Caller is just trying to get the length target data + */ + if ((Length == 0) && (a == NULL)) { + i = 0; + if (FindMarker(infile, str)) { + while ((ch = fgetc(infile)) != EOF) { + if (!isxdigit(ch)) { + if (ch == '\n') { + break; + } + } + i += 1; + } + } + return (i / 2); + } + + if (Length == 0) { + a[0] = 0x00; + return 1; + } + memset(a, 0x00, Length); + started = 0; + if (FindMarker(infile, str)) + while ((ch = fgetc(infile)) != EOF) { + if (!isxdigit(ch)) { + if (!started) { + if (ch == '\n') { + break; + } else { + continue; + } + } else { + break; + } + } + started = 1; + if ((ch >= '0') && (ch <= '9')) { + ich = (unsigned char)ch - '0'; + } else if ((ch >= 'A') && (ch <= 'F')) { + ich = (unsigned char)ch - 'A' + 10; + } else if ((ch >= 'a') && (ch <= 'f')) { + ich = (unsigned char)ch - 'a' + 10; + } else { + // shouldn't ever get here + ich = 0; + } + + for (i = 0; i < Length - 1; i++) { + a[i] = (unsigned char) (a[i] << 4) | (unsigned char) (a[i + 1] >> 4); + } + a[Length - 1] = (unsigned char) (a[Length - 1] << 4) | (unsigned char) ich; + } else { + return 0; + } + + return 1; +} + +void fprint_l_str(FILE *fp, const char *S, const uint8_t *A, size_t L) { + size_t i; + fprintf(fp, "%s", S); + for (i = 0; i < L; i++) { + fprintf(fp, "%02x", A[i]); + } + if (L == 0) { + fprintf(fp, "00"); + } + fprintf(fp, "\n"); +} + +OQS_STATUS sig_stfl_kat(const char *method_name, const char *katfile) { + + uint8_t seed[48]; + FILE *fh = NULL; + FILE *fp_rsp = NULL; + OQS_SIG_STFL *sig = NULL; + uint8_t *msg = NULL, *msg_rand = NULL; + size_t msg_len = 0; + uint8_t *public_key = NULL; + OQS_SIG_STFL_SECRET_KEY *secret_key = NULL; + uint8_t *signature = NULL, *signature_kat = NULL; + uint8_t *signed_msg = NULL; + size_t signature_len = 0; + size_t signed_msg_len = 0; + unsigned long long sigs_remain = 0; + unsigned long long sigs_maximum = 0; + OQS_STATUS rc, ret = OQS_ERROR; + OQS_KAT_PRNG *prng = NULL; + + prng = OQS_KAT_PRNG_new(method_name); + if (prng == NULL) { + goto err; + } + + sig = OQS_SIG_STFL_new(method_name); + if (sig == NULL) { + fprintf(stderr, "[sig_stfl_kat] %s was not enabled at compile-time.\n", method_name); + goto algo_not_enabled; + } + + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + return OQS_ERROR; + } + + // Grab the pk and sk from KAT file + public_key = malloc(sig->length_public_key); + secret_key = OQS_SIG_STFL_SECRET_KEY_new(sig->method_name); + OQS_SIG_STFL_SECRET_KEY_SET_store_cb(secret_key, do_nothing_save, NULL); + + signature = calloc(sig->length_signature, sizeof(uint8_t)); + signature_kat = calloc(sig->length_signature, sizeof(uint8_t)); + + if ((public_key == NULL) || (secret_key == NULL) || (signature == NULL)) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: malloc failed!\n", method_name); + goto err; + } + + if (!ReadHex(fp_rsp, public_key, sig->length_public_key, "pk = ")) { + fprintf(stderr, "ERROR: unable to read 'pk' from <%s>\n", katfile); + goto err; + } + + if (!ReadHex(fp_rsp, secret_key->secret_key_data, sig->length_secret_key, "sk = ")) { + fprintf(stderr, "ERROR: unable to read 'sk' from <%s>\n", katfile); + goto err; + } + + fh = stdout; + + OQS_fprintBstr(fh, "pk = ", public_key, sig->length_public_key); + OQS_fprintBstr(fh, "sk = ", secret_key->secret_key_data, sig->length_secret_key); + fprintf(fh, "\n\n"); + + fprintf(fh, "count = 0\n"); + if (!ReadHex(fp_rsp, seed, 48, "seed = ")) { + fprintf(stderr, "ERROR: unable to read 'seed' from <%s>\n", katfile); + goto err; + } + + OQS_fprintBstr(fh, "seed = ", seed, 48); + OQS_KAT_PRNG_seed(prng, seed, NULL); + + msg_len = 33 * (0 + 1); + fprintf(fh, "mlen = %zu\n", msg_len); + msg = malloc(msg_len); + msg_rand = malloc(msg_len); + + if (!ReadHex(fp_rsp, msg, msg_len, "msg = ")) { + fprintf(stderr, "ERROR: unable to read 'msg' from <%s>\n", katfile); + goto err; + } + + OQS_randombytes(msg_rand, msg_len); + + if (memcmp(msg_rand, msg, msg_len)) { + fprintf(stderr, "randombytes data unaligned\n"); + OQS_fprintBstr(fh, "m = ", msg, msg_len); + OQS_fprintBstr(fh, "m_rand = ", msg_rand, msg_len); + goto err; + } + + OQS_fprintBstr(fh, "msg = ", msg, msg_len); + +#ifdef OQS_ALLOW_STFL_KEY_AND_SIG_GEN + rc = OQS_SIG_STFL_sign(sig, signature, &signature_len, msg, msg_len, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sign failed!\n", method_name); + goto err; + } + fprintf(fh, "smlen = %zu\n", signature_len); + OQS_fprintBstr(fh, "sm = ", signature, signature_len); + + if (signature_len != sig->length_signature) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sign incorrect length of signature!\n", method_name); + goto err; + } + + if (!ReadHex(fp_rsp, signature_kat, signature_len, "sm = ")) { + fprintf(stderr, "ERROR: unable to read 'msg' from <%s>\n", katfile); + goto err; + } + + if (memcmp(signature, signature_kat, signature_len)) { + OQS_fprintBstr(fh, "sm_kat = ", signature_kat, signature_len); + fprintf(stderr, "Incorrect signature output\n"); + goto err; + } + + rc = OQS_SIG_STFL_verify(sig, msg, msg_len, signature, signature_len, public_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_verify failed!\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining(sig, &sigs_remain, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_remaining failed!\n", method_name); + goto err; + } + fprintf(fh, "remain = %llu\n", sigs_remain); + + rc = OQS_SIG_STFL_sigs_total(sig, &sigs_maximum, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_total failed!\n", method_name); + goto err; + } + fprintf(fh, "max = %llu\n", sigs_maximum); + + ret = OQS_SUCCESS; + goto cleanup; +#else + /* + * Signature generation is disabled so only signature verification can be tested. + */ + signature_len = sig->length_signature; + if (!ReadHex(fp_rsp, signature_kat, signature_len, "sm = ")) { + fprintf(stderr, "ERROR: unable to read 'msg' from <%s>\n", katfile); + goto err; + } + + // Echo back the signature read to keep the test tool happy. + fprintf(fh, "smlen = %zu\n", sig->length_signature); + OQS_fprintBstr(fh, "sm = ", signature_kat, sig->length_signature); + + rc = OQS_SIG_STFL_verify(sig, msg, msg_len, signature_kat, signature_len, public_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_verify failed!\n", method_name); + goto err; + } + + // Echo back remain + if (FindMarker(fp_rsp, "remain = ")) { + fscanf(fp_rsp, "%llu", &sigs_remain); + fprintf(fh, "remain = %llu\n", sigs_remain); + } else { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_remaining failed!\n", method_name); + goto err; + } + + // Echo back max + if (FindMarker(fp_rsp, "max = ")) { + fscanf(fp_rsp, "%llu", &sigs_maximum); + fprintf(fh, "max = %llu\n", sigs_maximum); + } else { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_total failed!\n", method_name); + goto err; + } + + ret = OQS_SUCCESS; + goto cleanup; +#endif +err: + ret = OQS_ERROR; + goto cleanup; + +algo_not_enabled: + ret = OQS_SUCCESS; + +cleanup: + if (sig != NULL) { + OQS_MEM_secure_free(signed_msg, signed_msg_len); + } + OQS_MEM_insecure_free(public_key); + OQS_SIG_STFL_SECRET_KEY_free(secret_key); + OQS_MEM_insecure_free(signature); + OQS_MEM_insecure_free(signature_kat); + OQS_MEM_insecure_free(msg); + OQS_MEM_insecure_free(msg_rand); + OQS_SIG_STFL_free(sig); + OQS_KAT_PRNG_free(prng); + if (fp_rsp != NULL) { + fclose(fp_rsp); + } + return ret; +} + +/* + * LMS Test Vector + */ +static OQS_STATUS test_lms_kat(const char *method_name, const char *katfile) { + OQS_STATUS rc = OQS_ERROR; + OQS_SIG_STFL *sig = NULL; + uint8_t *public_key = NULL; + uint8_t *msg = NULL; + size_t msg_len = 0; + uint8_t *sm = NULL; + FILE *fp_rsp = NULL; + FILE *fh = NULL; + + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + goto err; + } + + //Allocate a OQS stateful signature struct + sig = OQS_SIG_STFL_new(method_name); + if (sig == NULL) { + fprintf(stderr, "ERROR: Failed to create signature object for %s\n", method_name); + goto err; + } + + /* + * Get the message length + * Zero length means no KAT is currently available, so skip this method + * and return success + */ + msg_len = ReadHex(fp_rsp, 0, 0, "msg = "); + if (!(msg_len > 0)) { + fprintf(stderr, "No msg present\n"); + goto err; + } + + fclose(fp_rsp); + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + goto err; + } + + public_key = malloc(sig->length_public_key); + sm = malloc(sig->length_signature); + msg = malloc((unsigned long)msg_len); + + if ((!msg || !sm || !public_key)) { + fprintf(stderr, "ERROR: unable to allocate memory.\n"); + goto err; + } + + /* + * Read signature and public key, msg and signature data from KAT file + */ + if (!ReadHex(fp_rsp, public_key, sig->length_public_key, "pk = ")) { + fprintf(stderr, "ERROR: unable to read 'pk' from <%s>\n", katfile); + goto err; + } + fclose(fp_rsp); + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + goto err; + } + + if (!ReadHex(fp_rsp, msg, msg_len, "msg = ")) { + fprintf(stderr, "ERROR: unable to read 'msg' from <%s>\n", katfile); + goto err; + } + fclose(fp_rsp); + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + goto err; + } + + if (!ReadHex(fp_rsp, sm, sig->length_signature, "sm = ")) { + fprintf(stderr, "ERROR: unable to read 'sm' from <%s>\n", katfile); + goto err; + } + + // Verify KAT + rc = OQS_SIG_STFL_verify(sig, msg, msg_len, sm, sig->length_signature, public_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: Verify test vector failed: %s\n", method_name); + } else { + fh = stdout; + fprint_l_str(fh, "msg = ", msg, msg_len); + fprintf(fh, "\n"); + fprint_l_str(fh, "sm = ", sm, sig->length_signature); + fprintf(fh, "\n"); + fprint_l_str(fh, "pk = ", public_key, sig->length_public_key); + fprintf(fh, "\n"); + } +err: + OQS_SIG_STFL_free(sig); + OQS_MEM_insecure_free(sm); + OQS_MEM_insecure_free(public_key); + OQS_MEM_insecure_free(msg); + if (fp_rsp) { + fclose(fp_rsp); + } + return rc; +} + +int main(int argc, char **argv) { + OQS_STATUS rc; + OQS_init(); + + if (argc != 3) { + fprintf(stderr, "Usage: kat_stfl_sig algname katfile\n"); + fprintf(stderr, " algname: "); + for (size_t i = 0; i < OQS_SIG_STFL_algs_length; i++) { + if (i > 0) { + fprintf(stderr, ", "); + } + fprintf(stderr, "%s", OQS_SIG_STFL_alg_identifier(i)); + } + fprintf(stderr, "\n"); + printf("\n"); + print_system_info(); + OQS_destroy(); + return EXIT_FAILURE; + } + + char *alg_name = argv[1]; + char *katfile = argv[2]; + if (strncmp(alg_name, "LMS", 3) == 0) { + rc = test_lms_kat(alg_name, katfile); + } else { + rc = sig_stfl_kat(alg_name, katfile); + } + if (rc != OQS_SUCCESS) { + OQS_destroy(); + return EXIT_FAILURE; + } + OQS_destroy(); + return EXIT_SUCCESS; +} diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 5575fd4ffd..ca24bf92f9 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -28,6 +28,22 @@ def test_sig(sig_name): [helpers.path_to_executable('test_sig'), sig_name], ) +@helpers.filtered_test +@pytest.mark.parametrize('sig_stfl_name', helpers.available_sig_stfls_by_name()) +def test_sig_stfl(sig_stfl_name): + if not(helpers.is_sig_stfl_enabled_by_name(sig_stfl_name)): pytest.skip('Not enabled') + # Test with KATs apply for XMSS + if sig_stfl_name.startswith("XMSS"): + katfile = helpers.get_katfile("sig_stfl", sig_stfl_name) + if not katfile: pytest.skip("KATs file is missing") + helpers.run_subprocess( + [helpers.path_to_executable('test_sig_stfl'), sig_stfl_name, katfile], + ) + else: + helpers.run_subprocess( + [helpers.path_to_executable('test_sig_stfl'), sig_stfl_name], + ) + if __name__ == "__main__": import sys pytest.main(sys.argv) diff --git a/tests/test_hash.c b/tests/test_hash.c index 022fb61a7b..788f41ffb2 100644 --- a/tests/test_hash.c +++ b/tests/test_hash.c @@ -50,16 +50,25 @@ static int do_sha256(void) { fprintf(stderr, "ERROR reading from stdin\n"); return -1; } + // run main SHA-256 API uint8_t output[32]; OQS_SHA2_sha256(output, msg, msg_len); + // run incremental SHA-256 API uint8_t output_inc[32]; + uint8_t output_inc_2[32]; OQS_SHA2_sha256_ctx state; OQS_SHA2_sha256_inc_init(&state); + // clone state - OQS_SHA2_sha256_ctx state2; + OQS_SHA2_sha256_ctx state2, state3, state4, state5, state6; OQS_SHA2_sha256_inc_ctx_clone(&state2, &state); + OQS_SHA2_sha256_inc_ctx_clone(&state3, &state); + OQS_SHA2_sha256_inc_ctx_clone(&state4, &state); + OQS_SHA2_sha256_inc_ctx_clone(&state5, &state); + OQS_SHA2_sha256_inc_ctx_clone(&state6, &state); + // hash with first state if (msg_len > 64) { OQS_SHA2_sha256_inc_blocks(&state, msg, 1); @@ -67,6 +76,7 @@ static int do_sha256(void) { } else { OQS_SHA2_sha256_inc_finalize(output_inc, &state, msg, msg_len); } + if (memcmp(output, output_inc, 32) != 0) { fprintf(stderr, "ERROR: Incremental API does not match main API\n"); free(msg); @@ -84,6 +94,58 @@ static int do_sha256(void) { free(msg); return -3; } + + // hash with increment 1 byte at a time + size_t i = 0; + for (i = 0; i < msg_len; i++) { + OQS_SHA2_sha256_inc(&state3, &msg[i], 1); + } + OQS_SHA2_sha256_inc_finalize(output_inc_2, &state3, &msg[i], 0); + if (memcmp(output, output_inc_2, 32) != 0) { + fprintf(stderr, "ERROR: Non-block Incremental API with cloned state does not match main API\n"); + free(msg); + return -4; + } + + // hash increment with the entire msg len + OQS_SHA2_sha256_inc(&state6, msg, msg_len); + OQS_SHA2_sha256_inc_finalize(output_inc, &state6, NULL, 0); + if (memcmp(output, output_inc, 32) != 0) { + fprintf(stderr, "ERROR: Incremental API with the entire msg.\n"); + free(msg); + return -3; + } + + // hash with combination of block-size increments and non block-size increments [64 bytes] + [n < 64 bytes] + if (msg_len > 64) { + OQS_SHA2_sha256_inc_blocks(&state4, msg, 1); + for (i = 0; i < (msg_len - 64); i++) { + OQS_SHA2_sha256_inc(&state4, &msg[64 + i], 1); + } + OQS_SHA2_sha256_inc_finalize(output_inc_2, &state4, &msg[msg_len - 1], 0); + } else { + OQS_SHA2_sha256_inc_finalize(output_inc_2, &state4, msg, msg_len); + } + if (memcmp(output, output_inc_2, 32) != 0) { + fprintf(stderr, "ERROR: Combined block increments with non-block size failed to match main API\n"); + free(msg); + return -5; + } + + // hash with combination of non block-size and block-size [n < 64 bytes] + [64 bytes] + if (msg_len > 64) { + OQS_SHA2_sha256_inc(&state5, msg, 1); + OQS_SHA2_sha256_inc_blocks(&state5, &msg[1], 1); + OQS_SHA2_sha256_inc_finalize(output_inc_2, &state5, &msg[65], msg_len - 65); + } else { + OQS_SHA2_sha256_inc_finalize(output_inc_2, &state5, msg, msg_len); + } + if (memcmp(output, output_inc_2, 32) != 0) { + fprintf(stderr, "ERROR: Combined non-block size and block increments failed to match main API\n"); + free(msg); + return -5; + } + //Test inc API print_hex(output, 32); free(msg); return 0; diff --git a/tests/test_helpers.h b/tests/test_helpers.h index 5b1c17d7bc..a4ab668c2a 100644 --- a/tests/test_helpers.h +++ b/tests/test_helpers.h @@ -7,6 +7,7 @@ #include #include +#include typedef union { OQS_SHA3_shake256_inc_ctx hqc_state; diff --git a/tests/test_kat.py b/tests/test_kat.py index 2ce19d3593..c69f76c981 100644 --- a/tests/test_kat.py +++ b/tests/test_kat.py @@ -35,6 +35,22 @@ def test_sig(sig_name): assert(kats[sig_name]['single'] == h256.hexdigest()) +@helpers.filtered_test +@pytest.mark.parametrize('sig_stfl_name', helpers.available_sig_stfls_by_name()) +def test_sig_stfl(sig_stfl_name): + kats = helpers.get_kats("sig_stfl") + if not(helpers.is_sig_stfl_enabled_by_name(sig_stfl_name)): pytest.skip('Not enabled') + katfile = helpers.get_katfile("sig_stfl", sig_stfl_name) + if not katfile: pytest.skip("KATs file is missing") + output = helpers.run_subprocess( + [helpers.path_to_executable('kat_sig_stfl'), sig_stfl_name, katfile], + ) + output = output.replace("\r\n", "\n") + h256 = sha256() + h256.update(output.encode()) + + assert(kats[sig_stfl_name] == h256.hexdigest()) + if __name__ == "__main__": import sys pytest.main(sys.argv) diff --git a/tests/test_leaks.py b/tests/test_leaks.py index e0e8f395d3..f75fece11a 100644 --- a/tests/test_leaks.py +++ b/tests/test_leaks.py @@ -24,6 +24,22 @@ def test_sig_leak(sig_name): ["valgrind", "-s", "--error-exitcode=1", "--leak-check=full", "--show-leak-kinds=all", helpers.path_to_executable('test_sig'), sig_name], ) +@helpers.filtered_test +@pytest.mark.parametrize('sig_stfl_name', helpers.available_sig_stfls_by_name()) +def test_sig_stfl_leak(sig_stfl_name): + if not(helpers.is_sig_stfl_enabled_by_name(sig_stfl_name)): pytest.skip('Not enabled') + if sys.platform != "linux" or os.system("grep ubuntu /etc/os-release") != 0 or os.system("uname -a | grep x86_64") != 0: pytest.skip('Leak testing not supported on this platform') + if sig_stfl_name.startswith("XMSS"): + katfile = helpers.get_katfile("sig_stfl", sig_stfl_name) + if not katfile: pytest.skip("KATs file is missing") + helpers.run_subprocess( + ["valgrind", "-s", "--error-exitcode=1", "--leak-check=full", "--show-leak-kinds=all", helpers.path_to_executable('test_sig_stfl'), sig_stfl_name, katfile], + ) + else: + helpers.run_subprocess( + ["valgrind", "-s", "--error-exitcode=1", "--leak-check=full", "--show-leak-kinds=all", helpers.path_to_executable('test_sig_stfl'), sig_stfl_name], + ) + if __name__ == "__main__": import sys pytest.main(sys.argv) diff --git a/tests/test_sig.c b/tests/test_sig.c index eb3ab0af12..90990adad2 100644 --- a/tests/test_sig.c +++ b/tests/test_sig.c @@ -129,7 +129,7 @@ static OQS_STATUS sig_test_correctness(const char *method_name) { rv |= memcmp(message - sizeof(magic_t), magic.val, sizeof(magic_t)); rv |= memcmp(signature - sizeof(magic_t), magic.val, sizeof(magic_t)); if (rv) { - fprintf(stderr, "ERROR: Magic numbers do not mtach\n"); + fprintf(stderr, "ERROR: Magic numbers do not match\n"); goto err; } #endif diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c new file mode 100644 index 0000000000..a21119138a --- /dev/null +++ b/tests/test_sig_stfl.c @@ -0,0 +1,1206 @@ +// SPDX-License-Identifier: MIT + +#if defined(_WIN32) +#pragma warning(disable : 4244 4293) +#endif + +#include +#include +#include +#if defined(_WIN32) +#include +#define strcasecmp _stricmp +#else +#include +#endif + +#include + +#include +#include "tmp_store.c" +#include "system_info.c" + +#if OQS_USE_PTHREADS_IN_TESTS +#include + +static pthread_mutex_t *test_sk_lock = NULL; +static pthread_mutex_t *sk_lock = NULL; +#endif + +#ifdef OQS_ENABLE_TEST_CONSTANT_TIME +#include +#define OQS_TEST_CT_CLASSIFY(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) +#define OQS_TEST_CT_DECLASSIFY(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len) +#else +#define OQS_TEST_CT_CLASSIFY(addr, len) +#define OQS_TEST_CT_DECLASSIFY(addr, len) +#endif + +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +/* + * For stateful signature, we skip key generation because it can takes hours to complete. + * So the ReadHex and and FindMarker serve the purpose of reading pre-generate keypair from KATs. + */ +#define MAX_MARKER_LEN 50 + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +int FindMarker(FILE *infile, const char *marker) { + char line[MAX_MARKER_LEN]; + unsigned long i, len; + int curr_line; + + memset(line, 0, MAX_MARKER_LEN); + len = strlen(marker); + if (len > MAX_MARKER_LEN - 1) { + len = MAX_MARKER_LEN - 1; + } + + for (i = 0; i < len; i++) { + curr_line = fgetc(infile); + line[i] = (char)curr_line; + if (curr_line == EOF) { + return 0; + } + } + line[len] = '\0'; + + while (1) { + if (!strncmp(line, marker, len)) { + return 1; + } + + for (i = 0; i < len - 1; i++) { + line[i] = line[i + 1]; + } + curr_line = fgetc(infile); + line[len - 1] = (char)curr_line; + if (curr_line == EOF) { + return 0; + } + line[len] = '\0'; + } + + // shouldn't get here + return 0; +} + +// +// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) +// +int ReadHex(FILE *infile, unsigned char *a, unsigned long Length, char *str) { + int ch, started; + unsigned long i; + unsigned char ich; + + if (Length == 0) { + a[0] = 0x00; + return 1; + } + memset(a, 0x00, Length); + started = 0; + if (FindMarker(infile, str)) + while ((ch = fgetc(infile)) != EOF) { + if (!isxdigit(ch)) { + if (!started) { + if (ch == '\n') { + break; + } else { + continue; + } + } else { + break; + } + } + started = 1; + if ((ch >= '0') && (ch <= '9')) { + ich = (unsigned char)ch - '0'; + } else if ((ch >= 'A') && (ch <= 'F')) { + ich = (unsigned char)ch - 'A' + 10; + } else if ((ch >= 'a') && (ch <= 'f')) { + ich = (unsigned char)ch - 'a' + 10; + } else { + // shouldn't ever get here + ich = 0; + } + + for (i = 0; i < Length - 1; i++) { + a[i] = (unsigned char) (a[i] << 4) | (unsigned char) (a[i + 1] >> 4); + } + a[Length - 1] = (unsigned char) (a[Length - 1] << 4) | (unsigned char) ich; + } else { + return 0; + } + + return 1; +} + +/* + * Write stateful secret keys to disk. + */ +static OQS_STATUS save_secret_key(uint8_t *key_buf, size_t buf_len, void *context) { + if (key_buf == NULL || buf_len == 0 || context == NULL) { + return OQS_ERROR; + } + const char *context_char = context; + + if (oqs_fstore("sk", context_char, key_buf, buf_len) == OQS_SUCCESS) { + printf("\n================================================================================\n"); + printf("Updated STFL SK <%s>.\n", context_char); + printf("================================================================================\n"); + return OQS_SUCCESS; + } + + return OQS_ERROR; +} + +#if OQS_USE_PTHREADS_IN_TESTS + +static OQS_SIG_STFL_SECRET_KEY *lock_test_sk = NULL; +static OQS_SIG_STFL *lock_test_sig_obj = NULL; +static uint8_t *lock_test_public_key = NULL; +static char *lock_test_context = NULL; +static uint8_t *signature_1 = NULL; +static uint8_t *signature_2 = NULL; +static size_t signature_len_1; +static size_t signature_len_2; +static uint8_t message_1[] = "The quick brown fox ..."; +static uint8_t message_2[] = "The quick brown fox jumped from the tree."; + +static OQS_STATUS lock_sk_key(void *mutex) { + if (mutex == NULL) { + return OQS_ERROR; + } + + if (pthread_mutex_lock((pthread_mutex_t *)mutex)) { + return OQS_ERROR; + } + return OQS_SUCCESS; +} + +static OQS_STATUS unlock_sk_key(void *mutex) { + if (mutex == NULL) { + return OQS_ERROR; + } + + if (pthread_mutex_unlock((pthread_mutex_t *)mutex)) { + return OQS_ERROR; + } + return OQS_SUCCESS; +} +#else +static OQS_STATUS lock_sk_key(UNUSED void *mutex) { + return OQS_SUCCESS; +} + +static OQS_STATUS unlock_sk_key(UNUSED void *mutex) { + return OQS_SUCCESS; +} +#endif + +OQS_STATUS sig_stfl_keypair_from_keygen(OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key) { + OQS_STATUS rc; + + rc = OQS_SIG_STFL_keypair(sig, public_key, secret_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + return OQS_ERROR; + } + return OQS_SUCCESS; +} + +OQS_STATUS sig_stfl_keypair_from_KATs(OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key, const char *katfile) { + OQS_STATUS ret = OQS_ERROR; + FILE *fp_rsp = NULL; + + if ((fp_rsp = fopen(katfile, "r")) == NULL) { + fprintf(stderr, "Couldn't open <%s> for read\n", katfile); + goto err; + } + + // Grab the pk and sk from KAT file + if (!ReadHex(fp_rsp, public_key, sig->length_public_key, (char *)"pk = ")) { + fprintf(stderr, "ERROR: unable to read 'pk' from <%s>\n", katfile); + goto err; + } + + if (!ReadHex(fp_rsp, secret_key->secret_key_data, sig->length_secret_key, (char *)"sk = ")) { + fprintf(stderr, "ERROR: unable to read 'sk' from <%s>\n", katfile); + goto err; + } + + // We are done reading, clean up and exit + ret = OQS_SUCCESS; + goto cleanup; + +err: + ret = OQS_ERROR; + +cleanup: + fclose(fp_rsp); + return ret; +} + +/* + * We read from KATs these parameters: + * XMSS-SHA2_16_256 + * XMSS-SHA2_20_256 + * XMSS-SHAKE_16_256 + * XMSS-SHAKE_20_256 + * XMSSMT-SHA2_40/2_256 + * XMSSMT-SHA2_60/3_256 + * XMSSMT-SHAKE_40/2_256 + * XMSSMT-SHAKE_60/3_256 + */ +OQS_STATUS sig_stfl_KATs_keygen(OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key, const char *katfile) { + if (sig == NULL || public_key == NULL || secret_key == NULL ) { + return OQS_ERROR; + } + +#ifdef OQS_ENABLE_SIG_STFL_XMSS + if (0) { +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h16 + } else if (strcmp(sig->method_name, OQS_SIG_STFL_alg_xmss_sha256_h16) == 0) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha256_h20 + } else if (strcmp(sig->method_name, OQS_SIG_STFL_alg_xmss_sha256_h20) == 0) { + goto from_kats; +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h16 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_shake128_h16)) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake128_h20 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_shake128_h20)) { + goto from_kats; +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h16 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_sha512_h16)) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmss_sha512_h20 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_sha512_h20)) { + goto from_kats; +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h16 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_shake256_h16)) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmss_shake256_h20 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmss_shake256_h20)) { + goto from_kats; +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h40_2 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_2)) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_sha256_h60_3 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_3)) { + goto from_kats; +#endif + +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h40_2 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_2)) { + goto from_kats; +#endif +#ifdef OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_3 + } else if (0 == strcasecmp(sig->method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_3)) { + goto from_kats; +#endif + } else { + goto from_keygen; + } +from_kats: + return sig_stfl_keypair_from_KATs(sig, public_key, secret_key, katfile); + +from_keygen: +#endif //OQS_ENABLE_SIG_STFL_XMSS + (void)(katfile); + return sig_stfl_keypair_from_keygen(sig, public_key, secret_key); +} + +typedef struct magic_s { + uint8_t val[31]; +} magic_t; + +static char *convert_method_name_to_file_name(const char *method_name) { + if (method_name == NULL) { + return NULL; + } + + const char *file_store = NULL; + if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_2) == 0) { + file_store = "XMSSMT-SHA2_20-2_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h20_4) == 0) { + file_store = "XMSSMT-SHA2_20-4_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_2) == 0) { + file_store = "XMSSMT-SHA2_40-2_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_4) == 0) { + file_store = "XMSSMT-SHA2_40-4_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h40_8) == 0) { + file_store = "XMSSMT-SHA2_40-8_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_3) == 0) { + file_store = "XMSSMT-SHA2_60-3_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_6) == 0) { + file_store = "XMSSMT-SHA2_60-6_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_sha256_h60_12) == 0) { + file_store = "XMSSMT-SHA2_60-12_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_2) == 0) { + file_store = "XMSSMT-SHAKE_20-2_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h20_4) == 0) { + file_store = "XMSSMT-SHAKE_20-4_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_2) == 0) { + file_store = "XMSSMT-SHAKE_40-2_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_4) == 0) { + file_store = "XMSSMT-SHAKE_40-4_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h40_8) == 0) { + file_store = "XMSSMT-SHAKE_40-8_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_3) == 0) { + file_store = "XMSSMT-SHAKE_60-3_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_6) == 0) { + file_store = "XMSSMT-SHAKE_60-6_256"; + } else if (strcmp(method_name, OQS_SIG_STFL_alg_xmssmt_shake128_h60_12) == 0) { + file_store = "XMSSMT-SHAKE_60-12_256"; + } else { + file_store = method_name; + } + + return strdup(file_store); +} + +static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char *katfile) { + + OQS_SIG_STFL *sig = NULL; + uint8_t *public_key = NULL; + OQS_SIG_STFL_SECRET_KEY *secret_key = NULL; + OQS_SIG_STFL_SECRET_KEY *secret_key_rd = NULL; + uint8_t *message = NULL; + size_t message_len = 100; + uint8_t *signature = NULL; + size_t signature_len; + + uint8_t *sk_buf = NULL; + uint8_t *read_pk_buf = NULL; + char *context = NULL; + char *file_store = NULL; + size_t sk_buf_len = 0; + size_t read_pk_len = 0; + + magic_t magic; + + OQS_STATUS rc, ret = OQS_ERROR; + + //The magic numbers are random values. + //The length of the magic number was chosen to be 31 to break alignment + OQS_randombytes(magic.val, sizeof(magic_t)); + + sig = OQS_SIG_STFL_new(method_name); + if (sig == NULL) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Sample computation for stateful signature %s\n", sig->method_name); + printf("================================================================================\n"); + + secret_key = OQS_SIG_STFL_SECRET_KEY_new(sig->method_name); + secret_key_rd = OQS_SIG_STFL_SECRET_KEY_new(sig->method_name); + + OQS_SIG_STFL_SECRET_KEY_SET_lock(secret_key, lock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_unlock(secret_key, unlock_sk_key); + + file_store = convert_method_name_to_file_name(sig->method_name); + if (file_store == NULL) { + fprintf(stderr, "%s: file_store is null\n", __func__); + goto err; + } + + /* set context and secure store callback */ + context = strdup(((file_store))); + OQS_SIG_STFL_SECRET_KEY_SET_store_cb(secret_key, save_secret_key, (void *)context); + +#if OQS_USE_PTHREADS_IN_TESTS + OQS_SIG_STFL_SECRET_KEY_SET_mutex(secret_key, sk_lock); +#endif + public_key = malloc(sig->length_public_key + 2 * sizeof(magic_t)); + message = malloc(message_len + 2 * sizeof(magic_t)); + signature = malloc(sig->length_signature + 2 * sizeof(magic_t)); + + if ((public_key == NULL) || (secret_key == NULL) || (message == NULL) || (signature == NULL)) { + fprintf(stderr, "ERROR: malloc failed\n"); + goto err; + } + + //Set the magic numbers before + memcpy(public_key, magic.val, sizeof(magic_t)); + memcpy(message, magic.val, sizeof(magic_t)); + memcpy(signature, magic.val, sizeof(magic_t)); + + public_key += sizeof(magic_t); + message += sizeof(magic_t); + signature += sizeof(magic_t); + + // and after + memcpy(public_key + sig->length_public_key, magic.val, sizeof(magic_t)); + memcpy(message + message_len, magic.val, sizeof(magic_t)); + memcpy(signature + sig->length_signature, magic.val, sizeof(magic_t)); + + OQS_randombytes(message, message_len); + OQS_TEST_CT_DECLASSIFY(message, message_len); + + /* + * Some keypair generation is fast, so we only read keypair from KATs for slow XMSS parameters + */ + rc = sig_stfl_KATs_keygen(sig, public_key, secret_key, katfile); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_keypair failed\n"); + goto err; + } + + rc = OQS_SIG_STFL_SECRET_KEY_serialize(&sk_buf, &sk_buf_len, secret_key); + if (rc != OQS_SUCCESS) { + goto err; + } + + /* write key pair to disk */ + if (oqs_fstore("sk", file_store, sk_buf, sk_buf_len) != OQS_SUCCESS) { + goto err; + } + + if (oqs_fstore("pk", file_store, public_key, sig->length_public_key) != OQS_SUCCESS) { + goto err; + } + + rc = OQS_SIG_STFL_sign(sig, signature, &signature_len, message, message_len, secret_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_sign failed\n"); + goto err; + } + + OQS_TEST_CT_DECLASSIFY(public_key, sig->length_public_key); + OQS_TEST_CT_DECLASSIFY(signature, signature_len); + rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_verify failed\n"); + goto err; + } + + /* Read public key and re-test verify.*/ + read_pk_buf = malloc(sig->length_public_key); + if (oqs_fload("pk", file_store, read_pk_buf, sig->length_public_key, &read_pk_len) != OQS_SUCCESS) { + goto err; + } + rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, read_pk_buf); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: 2nd Verify with restored public key OQS_SIG_STFL_verify failed\n"); + } + + /* modify the signature to invalidate it */ + OQS_randombytes(signature, signature_len); + OQS_TEST_CT_DECLASSIFY(signature, signature_len); + rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_ERROR) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_verify should have failed!\n"); + goto err; + } + +#ifndef OQS_ENABLE_TEST_CONSTANT_TIME + /* check magic values */ + int rv = memcmp(public_key + sig->length_public_key, magic.val, sizeof(magic_t)); + rv |= memcmp(message + message_len, magic.val, sizeof(magic_t)); + rv |= memcmp(signature + sig->length_signature, magic.val, sizeof(magic_t)); + rv |= memcmp(public_key - sizeof(magic_t), magic.val, sizeof(magic_t)); + rv |= memcmp(message - sizeof(magic_t), magic.val, sizeof(magic_t)); + rv |= memcmp(signature - sizeof(magic_t), magic.val, sizeof(magic_t)); + if (rv) { + fprintf(stderr, "ERROR: Magic numbers do not match\n"); + goto err; + } +#endif + + ret = OQS_SUCCESS; + goto cleanup; + +err: + ret = OQS_ERROR; + +cleanup: + OQS_SIG_STFL_SECRET_KEY_free(secret_key); + OQS_SIG_STFL_SECRET_KEY_free(secret_key_rd); + if (public_key) { + OQS_MEM_insecure_free(public_key - sizeof(magic_t)); + } + if (message) { + OQS_MEM_insecure_free(message - sizeof(magic_t)); + } + if (signature) { + OQS_MEM_insecure_free(signature - sizeof(magic_t)); + } + OQS_MEM_secure_free(sk_buf, sk_buf_len); + OQS_SIG_STFL_free(sig); + + OQS_MEM_insecure_free(read_pk_buf); + OQS_MEM_insecure_free(context); + OQS_MEM_insecure_free(file_store); + + return ret; +} + +static OQS_STATUS sig_stfl_test_secret_key(const char *method_name, const char *katfile) { + OQS_STATUS rc = OQS_SUCCESS; + OQS_SIG_STFL_SECRET_KEY *sk = NULL; + OQS_SIG_STFL_SECRET_KEY *sk_from_file = NULL; + unsigned long long num_sig_left = 0, max_num_sigs = 0; + OQS_SIG_STFL *sig_obj = NULL; + uint8_t *public_key = NULL; + uint8_t *from_file_sk_buf = NULL; + uint8_t *to_file_sk_buf = NULL; + size_t from_file_sk_len = 0; + size_t to_file_sk_len = 0; + char *context = NULL; + char *context_2 = NULL; + char *file_store_name = NULL; + + /* + * Temporarily skip algs with long key generation times. + */ + + printf("================================================================================\n"); + printf("Create stateful Signature %s\n", method_name); + printf("================================================================================\n"); + + sig_obj = OQS_SIG_STFL_new(method_name); + if (sig_obj == NULL) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); + goto err; + } + + public_key = malloc(sig_obj->length_public_key * sizeof(uint8_t)); + + printf("================================================================================\n"); + printf("Create stateful Secret Key %s\n", method_name); + printf("================================================================================\n"); + + sk = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (sk == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Generate keypair %s\n", method_name); + printf("================================================================================\n"); + + rc = sig_stfl_KATs_keygen(sig_obj, public_key, sk, katfile); + + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key gen failed.\n"); + goto err; + } + + /* + * Get max num signature and the amount remaining + */ + rc = OQS_SIG_STFL_sigs_total((const OQS_SIG_STFL *)sig_obj, &max_num_sigs, (const OQS_SIG_STFL_SECRET_KEY *)sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get max number of sig from %s.\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining((const OQS_SIG_STFL *)sig_obj, &num_sig_left, (const OQS_SIG_STFL_SECRET_KEY *)sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get the remaining number of sig from %s.\n", method_name); + goto err; + } + + /* write sk key to disk */ + rc = OQS_SIG_STFL_SECRET_KEY_serialize(&to_file_sk_buf, &to_file_sk_len, sk); + if (rc != OQS_SUCCESS) { + goto err; + } + + file_store_name = convert_method_name_to_file_name(sig_obj->method_name); + if (oqs_fstore("sk", file_store_name, to_file_sk_buf, to_file_sk_len) != OQS_SUCCESS) { + goto err; + } + + if (sk->secret_key_data == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); + goto err; + } + + /* set context and secure store callback */ + if (sk->set_scrt_key_store_cb != NULL) { + context = strdup(file_store_name); + sk->set_scrt_key_store_cb(sk, save_secret_key, (void *)context); + } + + /* read secret key from disk */ + from_file_sk_buf = malloc(to_file_sk_len); + if (oqs_fload("sk", file_store_name, from_file_sk_buf, to_file_sk_len, &from_file_sk_len) != OQS_SUCCESS) { + goto err; + } + if (to_file_sk_len != from_file_sk_len) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new stored length not equal read length\n"); + goto err; + } + + sk_from_file = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (sk_from_file == NULL) { + fprintf(stderr, "ERROR: 2nd OQS_SECRET_KEY_new failed\n"); + goto err; + } + + context_2 = strdup(file_store_name); + rc = OQS_SIG_STFL_SECRET_KEY_deserialize(sk_from_file, from_file_sk_buf, from_file_sk_len, (void *)context_2); + + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS restore %s from file failed.\n", method_name); + goto err; + } + + rc = OQS_SUCCESS; + goto cleanup; + +err: + rc = OQS_ERROR; +cleanup: + + OQS_SIG_STFL_SECRET_KEY_free(sk); + OQS_SIG_STFL_SECRET_KEY_free(sk_from_file); + + OQS_MEM_insecure_free(public_key); + OQS_MEM_secure_free(to_file_sk_buf, to_file_sk_len); + OQS_MEM_secure_free(from_file_sk_buf, from_file_sk_len); + OQS_SIG_STFL_free(sig_obj); + OQS_MEM_insecure_free(context); + OQS_MEM_insecure_free(context_2); + OQS_MEM_insecure_free(file_store_name); + return rc; +} + +#ifdef OQS_ENABLE_TEST_CONSTANT_TIME +static void TEST_SIG_STFL_randombytes(uint8_t *random_array, size_t bytes_to_read) { + // We can't make direct calls to the system randombytes on some platforms, + // so we have to swap out the OQS_randombytes provider. + + OQS_randombytes_switch_algorithm("system"); + OQS_randombytes(random_array, bytes_to_read); + OQS_randombytes_custom_algorithm(&TEST_SIG_STFL_randombytes); + + // OQS_TEST_CT_CLASSIFY tells Valgrind's memcheck tool to issue a warning if + // the program branches on any byte that depends on random_array. This helps us + // identify timing side-channels, as these bytes often contain secret data. + OQS_TEST_CT_CLASSIFY(random_array, bytes_to_read); +} +#endif + +#if OQS_USE_PTHREADS_IN_TESTS +static OQS_STATUS sig_stfl_test_query_key(const char *method_name) { + OQS_STATUS rc = OQS_SUCCESS; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); + + /* + * Temporarily skip algs with long key generation times. + */ + + printf("================================================================================\n"); + printf("Testing stateful Signature Verification %s\n", method_name); + printf("================================================================================\n"); + + if ( lock_test_sk == NULL || lock_test_sig_obj == NULL || + signature_1 == NULL || signature_2 == NULL || + lock_test_public_key == NULL) { + return OQS_ERROR; + } + + printf("================================================================================\n"); + printf("Sig Verify 1 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_1, message_len_1, signature_1, signature_len_1, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Sig Verify 2 %s\n", method_name); + printf("================================================================================\n"); + + rc = OQS_SIG_STFL_verify(lock_test_sig_obj, message_2, message_len_2, signature_2, signature_len_2, lock_test_public_key); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_verify failed\n"); + goto err; + } + printf("================================================================================\n"); + printf("Stateful Signature Verification %s Passed.\n", method_name); + printf("================================================================================\n"); + + return OQS_SUCCESS; + +err: + return OQS_ERROR; +} + +static OQS_STATUS sig_stfl_test_sig_gen(const char *method_name) { + OQS_STATUS rc = OQS_SUCCESS; + size_t message_len_1 = sizeof(message_1); + size_t message_len_2 = sizeof(message_2); + + char *context = NULL; + char *key_store_name = NULL; + + /* + * Temporarily skip algs with long key generation times. + */ + + printf("================================================================================\n"); + printf("Testing stateful Signature Generation %s\n", method_name); + printf("================================================================================\n"); + + if ( lock_test_sk == NULL || lock_test_sig_obj == NULL) { + return OQS_ERROR; + } + + key_store_name = convert_method_name_to_file_name(method_name); + /* set context and secure store callback */ + context = strdup(((key_store_name))); + OQS_SIG_STFL_SECRET_KEY_SET_store_cb(lock_test_sk, save_secret_key, (void *)context); + + /* + * Get max num signature and the amount remaining + */ + unsigned long long num_sig_left = 0, max_num_sigs = 0; + rc = OQS_SIG_STFL_sigs_total((const OQS_SIG_STFL *)lock_test_sig_obj, &max_num_sigs, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get max number of sig from %s.\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining((const OQS_SIG_STFL *)lock_test_sig_obj, &num_sig_left, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get the remaining number of sig from %s.\n", method_name); + goto err; + } + + printf("================================================================================\n"); + printf("Sig Gen 1 %s\n", method_name); + printf("================================================================================\n"); + + signature_1 = malloc(lock_test_sig_obj->length_signature); + + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_1, &signature_len_1, message_1, message_len_1, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } + + /* + * Get max num signature and the amount remaining + */ + num_sig_left = 0, max_num_sigs = 0; + rc = OQS_SIG_STFL_sigs_total((const OQS_SIG_STFL *)lock_test_sig_obj, &max_num_sigs, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get max number of sig from %s.\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining((const OQS_SIG_STFL *)lock_test_sig_obj, &num_sig_left, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get the remaining number of sig from %s.\n", method_name); + goto err; + } + + printf("================================================================================\n"); + printf("Sig Gen 2 %s\n", method_name); + printf("================================================================================\n"); + + signature_2 = malloc(lock_test_sig_obj->length_signature); + + rc = OQS_SIG_STFL_sign(lock_test_sig_obj, signature_2, &signature_len_2, message_2, message_len_2, lock_test_sk); + OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "ERROR: lock thread test OQS_SIG_STFL_sign failed\n"); + goto err; + } + + printf("================================================================================\n"); + printf("Stateful Key Gen %s Passed.\n", method_name); + printf("================================================================================\n"); + + /* + * Get max num signature and the amount remaining + */ + num_sig_left = 0, max_num_sigs = 0; + rc = OQS_SIG_STFL_sigs_total((const OQS_SIG_STFL *)lock_test_sig_obj, &max_num_sigs, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get max number of sig from %s.\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining((const OQS_SIG_STFL *)lock_test_sig_obj, &num_sig_left, (const OQS_SIG_STFL_SECRET_KEY *)lock_test_sk); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key: Failed to get the remaining number of sig from %s.\n", method_name); + goto err; + } + + rc = OQS_SUCCESS; + goto cleanup; +err: + rc = OQS_ERROR; +cleanup: + OQS_MEM_insecure_free(context); + OQS_MEM_insecure_free(key_store_name); + + return rc; +} + +static OQS_STATUS sig_stfl_test_secret_key_lock(const char *method_name, const char *katfile) { + OQS_STATUS rc = OQS_SUCCESS; + + printf("================================================================================\n"); + printf("Testing stateful Signature locks %s\n", method_name); + printf("================================================================================\n"); + + /* + * Temporarily skip algs with long key generation times. + */ + + printf("================================================================================\n"); + printf("Create stateful Signature %s\n", method_name); + printf("================================================================================\n"); + + lock_test_sig_obj = OQS_SIG_STFL_new(method_name); + if (lock_test_sig_obj == NULL) { + fprintf(stderr, "ERROR: OQS_SIG_STFL_new failed\n"); + goto err; + } + + lock_test_public_key = malloc(lock_test_sig_obj->length_public_key * sizeof(uint8_t)); + + printf("================================================================================\n"); + printf("Create stateful Secret Key %s\n", method_name); + printf("================================================================================\n"); + + lock_test_sk = OQS_SIG_STFL_SECRET_KEY_new(method_name); + if (lock_test_sk == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new failed\n"); + goto err; + } + + OQS_SIG_STFL_SECRET_KEY_SET_lock(lock_test_sk, lock_sk_key); + OQS_SIG_STFL_SECRET_KEY_SET_unlock(lock_test_sk, unlock_sk_key); + + OQS_SIG_STFL_SECRET_KEY_SET_mutex(lock_test_sk, test_sk_lock); + + printf("================================================================================\n"); + printf("Generate keypair %s\n", method_name); + printf("================================================================================\n"); + + rc = sig_stfl_KATs_keygen(lock_test_sig_obj, lock_test_public_key, lock_test_sk, katfile); + + if (rc != OQS_SUCCESS) { + fprintf(stderr, "OQS STFL key gen failed.\n"); + goto err; + } + + if (lock_test_sk->secret_key_data == NULL) { + fprintf(stderr, "ERROR: OQS_SECRET_KEY_new incomplete.\n"); + goto err; + } + + /* set context and secure store callback */ + if (lock_test_sk->set_scrt_key_store_cb) { + lock_test_context = convert_method_name_to_file_name(method_name); + lock_test_sk->set_scrt_key_store_cb(lock_test_sk, save_secret_key, (void *)lock_test_context); + } + + return OQS_SUCCESS; + +err: + return OQS_ERROR; +} + + +typedef struct thread_data { + const char *alg_name; + const char *katfile; + OQS_STATUS rc; + // OQS_STATUS rc1; +} thread_data_t; + +typedef struct lock_test_data { + const char *alg_name; + const char *katfile; + OQS_STATUS rc; +} lock_test_data_t; + +void *test_query_key(void *arg) { + struct lock_test_data *td = arg; + printf("\n%s: Start Query Stateful Key info\n", __func__); + td->rc = sig_stfl_test_query_key(td->alg_name); + printf("%s: End Query Stateful Key info\n\n", __func__); + return NULL; +} + +void *test_sig_gen(void *arg) { + struct lock_test_data *td = arg; + printf("\n%s: Start Generate Stateful Signature\n", __func__); + td->rc = sig_stfl_test_sig_gen(td->alg_name); + printf("%s: End Generate Stateful Signature\n\n", __func__); + return NULL; +} + +void *test_create_keys(void *arg) { + struct lock_test_data *td = arg; + printf("\n%s: Start Generate Keys\n", __func__); + td->rc = sig_stfl_test_secret_key_lock(td->alg_name, td->katfile); + printf("%s: End Generate Stateful Keys\n\n", __func__); + return NULL; +} + +void *test_correctness_wrapper(void *arg) { + struct thread_data *td = arg; + td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); + return NULL; +} + +void *test_secret_key_wrapper(void *arg) { + struct thread_data *td = arg; + td->rc = sig_stfl_test_secret_key(td->alg_name, td->katfile); + return NULL; +} +#endif + +/* + * When key and signature generation is off + * these operations should fail. So flip the results. + */ +static OQS_STATUS update_test_result( OQS_STATUS rc, int xmss_or_lms) { + OQS_STATUS rc_update = rc; + if (xmss_or_lms) { + ; +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + if (rc_update == OQS_ERROR) { + rc_update = OQS_SUCCESS; + } else { + rc_update = OQS_ERROR; + } +#endif + } else { + ; +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + if (rc_update == OQS_ERROR) { + rc_update = OQS_SUCCESS; + } else { + rc_update = OQS_ERROR; + } +#endif + } + return rc_update; +} + +int main(int argc, char **argv) { + OQS_init(); + oqs_fstore_init(); + + printf("Testing stateful signature algorithms using liboqs version %s\n", OQS_version()); + + if (argc < 2) { + fprintf(stderr, "Usage: test_sig_stfl algname [katfile]\n"); + fprintf(stderr, " algname: "); + for (size_t i = 0; i < OQS_SIG_STFL_algs_length; i++) { + if (i > 0) { + fprintf(stderr, ", "); + } + fprintf(stderr, "%s", OQS_SIG_STFL_alg_identifier(i)); + } + fprintf(stderr, "\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + + print_system_info(); + + const char *alg_name = argv[1]; + const char *katfile = argv[2]; + int is_xmss = 0; + if (strstr(alg_name, "XMSS") != NULL) { + is_xmss = 1; + if (argc < 3) { + fprintf(stderr, "KAT file must be provided for XMSS.\n"); + OQS_destroy(); + return EXIT_FAILURE; + } + } + + /* + * Tests executed by CI/DI only run algoritms that have been emabled. + * + */ + if (!OQS_SIG_STFL_alg_is_enabled(alg_name)) { + printf("Stateful signature algorithm %s not enabled!\n", alg_name); + OQS_destroy(); + if (is_xmss) { +#ifndef OQS_ENABLE_SIG_STFL_XMSS + return EXIT_SUCCESS; +#else + return EXIT_FAILURE; +#endif + } else { +#ifndef OQS_ENABLE_SIG_STFL_LMS + return EXIT_SUCCESS; +#else + return EXIT_FAILURE; +#endif + } + } + +#ifdef OQS_ENABLE_TEST_CONSTANT_TIME + OQS_randombytes_custom_algorithm(&TEST_SIG_STFL_randombytes); +#else + OQS_randombytes_switch_algorithm("system"); +#endif + + OQS_STATUS rc = OQS_ERROR, rc1 = OQS_ERROR; + int exit_status = EXIT_SUCCESS; + +#if OQS_USE_PTHREADS_IN_TESTS +#define MAX_LEN_SIG_NAME_ 64 + OQS_STATUS rc_create = OQS_ERROR, rc_sign = OQS_ERROR, rc_query = OQS_ERROR; + + pthread_t thread; + pthread_t create_key_thread; + pthread_t sign_key_thread; + pthread_t query_key_thread; + + thread_data_t td = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + thread_data_t td_2 = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + + lock_test_data_t td_create = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + lock_test_data_t td_sign = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + lock_test_data_t td_query = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + + test_sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (test_sk_lock == NULL) { + goto err; + } + sk_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (sk_lock == NULL) { + goto err; + } + + if (pthread_mutex_init(test_sk_lock, NULL) || pthread_mutex_init(sk_lock, NULL)) { + fprintf(stderr, "ERROR: Initializing mutex\n"); + exit_status = EXIT_FAILURE; + goto err; + } + + if (pthread_create(&thread, NULL, test_correctness_wrapper, &td)) { + fprintf(stderr, "ERROR: Creating pthread for test_wrapper\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(thread, NULL); + rc = td.rc; + rc = update_test_result(rc, is_xmss); + + if (pthread_create(&thread, NULL, test_secret_key_wrapper, &td_2)) { + fprintf(stderr, "ERROR: Creating pthread for test_wrapper_2\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(thread, NULL); + rc1 = td_2.rc; + rc1 = update_test_result(rc1, is_xmss); + + if (pthread_create(&create_key_thread, NULL, test_create_keys, &td_create)) { + fprintf(stderr, "ERROR: Creating pthread for test_create_keys\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(create_key_thread, NULL); + rc_create = td_create.rc; + rc_create = update_test_result(rc_create, is_xmss); + + if (pthread_create(&sign_key_thread, NULL, test_sig_gen, &td_sign)) { + fprintf(stderr, "ERROR: Creating pthread for test_sig_gen\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(sign_key_thread, NULL); + rc_sign = td_sign.rc; + rc_sign = update_test_result(rc_sign, is_xmss); + + if (pthread_create(&query_key_thread, NULL, test_query_key, &td_query)) { + fprintf(stderr, "ERROR: Creating pthread for test_query_key\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(query_key_thread, NULL); + rc_query = td_query.rc; + rc_query = update_test_result(rc_query, is_xmss); + +err: + if (test_sk_lock) { + pthread_mutex_destroy(test_sk_lock); + } + if (sk_lock) { + pthread_mutex_destroy(sk_lock); + } + + OQS_SIG_STFL_SECRET_KEY_free(lock_test_sk); + OQS_MEM_insecure_free(lock_test_public_key); + OQS_SIG_STFL_free(lock_test_sig_obj); + OQS_MEM_insecure_free(lock_test_context); + OQS_MEM_insecure_free(signature_1); + OQS_MEM_insecure_free(signature_2); + + OQS_destroy(); + if (rc != OQS_SUCCESS || rc1 != OQS_SUCCESS) { + return EXIT_FAILURE; + } + +#if OQS_USE_PTHREADS_IN_TESTS + if (rc_create != OQS_SUCCESS || rc_sign != OQS_SUCCESS || rc_query != OQS_SUCCESS) { + return EXIT_FAILURE; + } +#endif + return exit_status; +#else + rc = sig_stfl_test_correctness(alg_name, katfile); + rc1 = sig_stfl_test_secret_key(alg_name, katfile); + + OQS_destroy(); + rc = update_test_result(rc, is_xmss); + rc1 = update_test_result(rc1, is_xmss); + + + if (rc != OQS_SUCCESS || rc1 != OQS_SUCCESS) { + return EXIT_FAILURE; + } + return exit_status; +#endif +} From 39688e908b239b77b9775c5469df244021953d5d Mon Sep 17 00:00:00 2001 From: Spencer Wilson Date: Tue, 11 Jun 2024 14:55:29 -0400 Subject: [PATCH 08/10] Forward-declare OQS_SIG type in sig_stfl.h (#1820) Signed-off-by: Spencer Wilson --- src/sig_stfl/sig_stfl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sig_stfl/sig_stfl.h b/src/sig_stfl/sig_stfl.h index 6154f47a64..0f31e83da2 100644 --- a/src/sig_stfl/sig_stfl.h +++ b/src/sig_stfl/sig_stfl.h @@ -179,6 +179,7 @@ OQS_API int OQS_SIG_STFL_alg_count(void); OQS_API int OQS_SIG_STFL_alg_is_enabled(const char *method_name); #ifndef OQS_ALLOW_STFL_KEY_AND_SIG_GEN +typedef struct OQS_SIG OQS_SIG; #define OQS_SIG_STFL OQS_SIG #else /** From 6ee5de25220e490cf7c895939c0fa001e5f8e2ce Mon Sep 17 00:00:00 2001 From: Spencer Wilson Date: Tue, 11 Jun 2024 15:47:30 -0400 Subject: [PATCH 09/10] Move Linux ARM64 "build" test from CircleCI to GitHub Actions (#1814) --------- Signed-off-by: Spencer Wilson --- .circleci/config.yml | 46 -------------------------------------- .github/workflows/unix.yml | 34 +++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a5a31cd1c0..4cea11f8a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,47 +144,6 @@ jobs: command: scan-build-15 --status-bugs ninja working_directory: build - arm_machine: - description: A template for running liboqs tests on ARM(presently only 64) machines - parameters: - CMAKE_ARGS: - description: "Arguments to pass to CMake." - type: string - default: '' - PYTEST_ARGS: - description: "Arguments to pass to pytest." - type: string - # Not every executor handles --numprocesses=auto being passed to pytest well - # See https://github.com/open-quantum-safe/liboqs/issues/738#issuecomment-621394744 - default: --numprocesses=auto - machine: - image: default # analogous to ubuntu-latest on GH Actions - resource_class: arm.medium - steps: - - checkout - # It seems the machine doesn't contain all preprequisites, and we don't have permission to add them explicitly, - # so we can only run in a prepared ARM64 CI image - - run: - name: Build and run tests in docker - no_output_timeout: 1h - command: |2 - docker run -it -e CMAKE_ARGS="<< parameters.CMAKE_ARGS >>" \ - -e PYTEST_ARGS="<< parameters.PYTEST_ARGS >>" \ - -v `pwd`:/root/project \ - openquantumsafe/ci-ubuntu-focal-arm64:latest bash \ - -c 'cd /root/project && \ - uname -a && \ - mkdir build && cd build && source ~/.bashrc && \ - cmake -GNinja -DOQS_STRICT_WARNINGS=ON $CMAKE_ARGS .. && cmake -LA .. && ninja && \ - cd .. && mkdir -p tmp && \ - python3 -m pytest --verbose \ - --ignore=tests/test_code_conventions.py \ - --junitxml=build/test-results/pytest/test-results.xml $PYTEST_ARGS' - - store_test_results: # Note that this command will fail when running CircleCI locally, that is expected behaviour - path: build/test-results - - store_artifacts: - path: build/test-results - trigger-downstream-ci: docker: - image: cimg/base:2020.01 @@ -340,11 +299,6 @@ workflows: CONTAINER: openquantumsafe/ci-ubuntu-bionic-i386:latest CMAKE_ARGS: -DCMAKE_TOOLCHAIN_FILE=../.CMake/toolchain_x86.cmake PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py - - arm_machine: - <<: *require_buildcheck - name: arm64 - PYTEST_ARGS: --numprocesses=auto --maxprocesses=10 --ignore=tests/test_kat_all.py - CMAKE_ARGS: -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON commit-to-main: when: diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index bcb1e453c7..9775357267 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -38,9 +38,16 @@ jobs: buildcheck: name: Check that code passes a basic build before starting heavier tests - container: openquantumsafe/ci-ubuntu-focal-x86_64:latest needs: [stylecheck, upstreamcheck] - runs-on: ubuntu-latest + strategy: + matrix: + include: + - arch: arm64 + runner: oqs-arm64 + - arch: x86_64 + runner: ubuntu-latest + runs-on: ${{ matrix.runner }} + container: openquantumsafe/ci-ubuntu-focal-${{ matrix.arch }}:latest env: KEM_NAME: kyber_768 SIG_NAME: dilithium_3 @@ -64,50 +71,65 @@ jobs: - name: Build documentation run: ninja gen_docs working-directory: build + if: matrix.arch == 'x86_64' - linux_intel: + linux: needs: buildcheck - runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: + - name: arm64 + runner: oqs-arm64 + container: openquantumsafe/ci-ubuntu-focal-arm64:latest + PYTEST_ARGS: --numprocesses=auto --maxprocesses=10 --ignore=tests/test_kat_all.py + CMAKE_ARGS: -DOQS_ENABLE_SIG_STFL_LMS=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON - name: alpine + runner: ubuntu-latest container: openquantumsafe/ci-alpine-amd64:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: alpine-no-stfl-key-sig-gen + runner: ubuntu-latest container: openquantumsafe/ci-alpine-amd64:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=OFF -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: alpine-openssl-all + runner: ubuntu-latest container: openquantumsafe/ci-alpine-amd64:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=ON -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_SHA2_OPENSSL=ON -DOQS_USE_SHA3_OPENSSL=ON -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: alpine-noopenssl + runner: ubuntu-latest container: openquantumsafe/ci-alpine-amd64:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_USE_OPENSSL=OFF -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_alg_info.py --ignore=tests/test_kat_all.py - name: focal-nistr4-openssl + runner: ubuntu-latest container: openquantumsafe/ci-ubuntu-focal-x86_64:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=NIST_R4 PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py - name: jammy-std-openssl3 + runner: ubuntu-latest container: openquantumsafe/ci-ubuntu-jammy:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD -DBUILD_SHARED_LIBS=ON PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py - name: jammy-std-openssl3-dlopen + runner: ubuntu-latest container: openquantumsafe/ci-ubuntu-jammy:latest CMAKE_ARGS: -DOQS_STRICT_WARNINGS=ON -DOQS_ALGS_ENABLED=STD -DBUILD_SHARED_LIBS=ON -DOQS_DLOPEN_OPENSSL=ON PYTEST_ARGS: --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py - name: address-sanitizer + runner: ubuntu-latest container: openquantumsafe/ci-ubuntu-focal-x86_64:latest CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=ON -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_distbuild.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py --numprocesses=auto --maxprocesses=10 - name: address-sanitizer-no-stfl-key-sig-gen + runner: ubuntu-latest container: openquantumsafe/ci-ubuntu-focal-x86_64:latest CMAKE_ARGS: -DCMAKE_C_COMPILER=clang-9 -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=Address -DOQS_HAZARDOUS_EXPERIMENTAL_ENABLE_SIG_STFL_KEY_SIG_GEN=OFF -DOQS_ENABLE_SIG_STFL_XMSS=ON -DOQS_ENABLE_SIG_STFL_LMS=ON PYTEST_ARGS: --ignore=tests/test_distbuild.py --ignore=tests/test_leaks.py --ignore=tests/test_kat_all.py --numprocesses=auto --maxprocesses=10 + runs-on: ${{ matrix.runner }} container: image: ${{ matrix.container }} steps: @@ -122,11 +144,11 @@ jobs: timeout-minutes: 60 run: mkdir -p tmp && python3 -m pytest --verbose --ignore=tests/test_code_conventions.py ${{ matrix.PYTEST_ARGS }} - name: Package .deb - if: ${{ matrix.name }} == 'jammy-std-openssl3' + if: matrix.name == 'jammy-std-openssl3' run: cpack working-directory: build - name: Retain .deb file - if: ${{ matrix.name }} == 'jammy-std-openssl3' + if: matrix.name == 'jammy-std-openssl3' uses: actions/upload-artifact@v3 with: name: liboqs-openssl3-shared-x64 From c8a2beb5a6f73d3e4b1180b8f9bb25c43e3858d9 Mon Sep 17 00:00:00 2001 From: qnfm <104289862+qnfm@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:19:22 +0000 Subject: [PATCH 10/10] Fix test_alg_info.py on Windows platform (#1821) * Fix test_alg_info.py on Windows platform Signed-off-by: zinag * Remove incorrect print Signed-off-by: zinag --------- Signed-off-by: zinag --- tests/test_alg_info.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_alg_info.py b/tests/test_alg_info.py index bbe30c4b39..fc7032e699 100644 --- a/tests/test_alg_info.py +++ b/tests/test_alg_info.py @@ -16,7 +16,11 @@ def test_alg_info_kem(kem_name): alg_info = yaml.safe_load(output)['KEMs'][kem_name] assert(not(alg_info['isnull'])) # find and load the datasheet - datasheet_filename = helpers.run_subprocess(['grep', '-r', '-l', kem_name, 'docs/algorithms/kem']).splitlines()[0] + if platform.system() == 'Windows': + command = f"Select-String -Path 'docs/algorithms/kem/*' -Pattern '{kem_name}' -SimpleMatch -List | Select-Object -ExpandProperty Path" + datasheet_filename = helpers.run_subprocess(['powershell', '-Command', command]).splitlines()[0] + else: + datasheet_filename = helpers.run_subprocess(['grep', '-r', '-l', kem_name, 'docs/algorithms/kem']).splitlines()[0] datasheet_filename = datasheet_filename.replace('.md','.yml') with open(datasheet_filename, 'r', encoding='utf8') as datasheet_fh: datasheet = yaml.safe_load(datasheet_fh.read()) @@ -45,7 +49,11 @@ def test_alg_info_sig(sig_name): alg_info = yaml.safe_load(output)['SIGs'][sig_name] assert(not(alg_info['isnull'])) # find and load the datasheet - datasheet_filename = helpers.run_subprocess(['grep', '-r', '-l', sig_name, 'docs/algorithms/sig']).splitlines()[0] + if platform.system() == 'Windows': + command = f"Select-String -Path 'docs/algorithms/sig/*' -Pattern '{sig_name}' -SimpleMatch -List | Select-Object -ExpandProperty Path" + datasheet_filename = helpers.run_subprocess(['powershell', '-Command', command]).splitlines()[0] + else: + datasheet_filename = helpers.run_subprocess(['grep', '-r', '-l', sig_name, 'docs/algorithms/sig']).splitlines()[0] datasheet_filename = datasheet_filename.replace('.md','.yml') with open(datasheet_filename, 'r', encoding='utf8') as datasheet_fh: datasheet = yaml.safe_load(datasheet_fh.read())