aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/hash/sha1/sha160.cpp7
-rw-r--r--src/lib/hash/sha1/sha160.h6
-rw-r--r--src/lib/hash/sha1/sha1_armv8/info.txt13
-rw-r--r--src/lib/hash/sha1/sha1_armv8/sha1_armv8.cpp205
-rw-r--r--src/lib/hash/sha2_32/sha2_32.cpp57
-rw-r--r--src/lib/hash/sha2_32/sha2_32.h27
-rw-r--r--src/lib/hash/sha2_32/sha2_32_armv8/info.txt13
-rw-r--r--src/lib/hash/sha2_32/sha2_32_armv8/sha2_32_armv8.cpp202
-rw-r--r--src/lib/hash/sha2_32/sha2_32_x86/sha2_32_x86.cpp2
-rw-r--r--src/lib/x509/x509cert.cpp2
-rw-r--r--src/lib/x509/x509path.cpp37
-rw-r--r--src/tests/data/extended_x509/01/end.crt19
-rw-r--r--src/tests/data/extended_x509/01/int.crt18
-rw-r--r--src/tests/data/extended_x509/01/root.crt18
-rw-r--r--src/tests/data/extended_x509/02/end.crt20
-rw-r--r--src/tests/data/extended_x509/02/int1-2.crt20
-rw-r--r--src/tests/data/extended_x509/02/int1.crt20
-rw-r--r--src/tests/data/extended_x509/02/root.crt20
-rw-r--r--src/tests/data/extended_x509/03/end.crt20
-rw-r--r--src/tests/data/extended_x509/03/int1.crt20
-rw-r--r--src/tests/data/extended_x509/03/root.crt20
-rw-r--r--src/tests/data/extended_x509/expected.txt3
-rw-r--r--src/tests/data/hash/sha1.vec2
-rw-r--r--src/tests/data/hash/sha2_32.vec389
-rw-r--r--src/tests/test_x509_path.cpp78
-rw-r--r--src/tests/tests.cpp19
26 files changed, 1200 insertions, 57 deletions
diff --git a/src/lib/hash/sha1/sha160.cpp b/src/lib/hash/sha1/sha160.cpp
index 13f9c24d7..6ebdba73f 100644
--- a/src/lib/hash/sha1/sha160.cpp
+++ b/src/lib/hash/sha1/sha160.cpp
@@ -68,6 +68,13 @@ void SHA_160::compress_n(const uint8_t input[], size_t blocks)
}
#endif
+#if defined(BOTAN_HAS_SHA1_ARMV8)
+ if(CPUID::has_arm_sha1())
+ {
+ return sha1_armv8_compress_n(m_digest, input, blocks);
+ }
+#endif
+
#if defined(BOTAN_HAS_SHA1_SSE2)
if(CPUID::has_sse2())
{
diff --git a/src/lib/hash/sha1/sha160.h b/src/lib/hash/sha1/sha160.h
index 7333ca827..f2ed61b64 100644
--- a/src/lib/hash/sha1/sha160.h
+++ b/src/lib/hash/sha1/sha160.h
@@ -32,6 +32,12 @@ class BOTAN_DLL SHA_160 final : public MDx_HashFunction
private:
void compress_n(const uint8_t[], size_t blocks) override;
+#if defined(BOTAN_HAS_SHA1_ARMV8)
+ static void sha1_armv8_compress_n(secure_vector<uint32_t>& digest,
+ const uint8_t blocks[],
+ size_t block_count);
+#endif
+
#if defined(BOTAN_HAS_SHA1_SSE2)
static void sse2_compress_n(secure_vector<uint32_t>& digest,
const uint8_t blocks[],
diff --git a/src/lib/hash/sha1/sha1_armv8/info.txt b/src/lib/hash/sha1/sha1_armv8/info.txt
new file mode 100644
index 000000000..7e9f7ba22
--- /dev/null
+++ b/src/lib/hash/sha1/sha1_armv8/info.txt
@@ -0,0 +1,13 @@
+<defines>
+SHA1_ARMV8 -> 20170117
+</defines>
+
+<arch>
+#arm32
+arm64
+</arch>
+
+<cc>
+gcc:4.9
+clang:3.8
+</cc>
diff --git a/src/lib/hash/sha1/sha1_armv8/sha1_armv8.cpp b/src/lib/hash/sha1/sha1_armv8/sha1_armv8.cpp
new file mode 100644
index 000000000..97e56bfd0
--- /dev/null
+++ b/src/lib/hash/sha1/sha1_armv8/sha1_armv8.cpp
@@ -0,0 +1,205 @@
+/*
+* SHA-1 using CPU instructions in ARMv8
+*
+* Contributed by Jeffrey Walton. Based on public domain code by
+* Johannes Schneiders, Skip Hovsmith and Barry O'Rourke.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sha160.h>
+#include <arm_neon.h>
+
+namespace Botan {
+
+/*
+* SHA-1 using CPU instructions in ARMv8
+*/
+//static
+BOTAN_FUNC_ISA("+crypto")
+void SHA_160::sha1_armv8_compress_n(secure_vector<uint32_t>& digest, const uint8_t input8[], size_t blocks)
+ {
+ uint32x4_t C0, C1, C2, C3;
+ uint32x4_t ABCD, ABCD_SAVED;
+ uint32_t E0, E0_SAVED, E1;
+
+ // Load initial values
+ C0 = vdupq_n_u32(0x5A827999);
+ C1 = vdupq_n_u32(0x6ED9EBA1);
+ C2 = vdupq_n_u32(0x8F1BBCDC);
+ C3 = vdupq_n_u32(0xCA62C1D6);
+
+ ABCD = vld1q_u32(&digest[0]);
+ E0 = digest[4];
+
+ // Intermediate void* cast due to http://llvm.org/bugs/show_bug.cgi?id=20670
+ const uint32_t* input32 = reinterpret_cast<const uint32_t*>(reinterpret_cast<const void*>(input8));
+
+ while (blocks)
+ {
+ uint32x4_t MSG0, MSG1, MSG2, MSG3;
+ uint32x4_t TMP0, TMP1;
+
+ // Save current hash
+ ABCD_SAVED = ABCD;
+ E0_SAVED = E0;
+
+ MSG0 = vld1q_u32(input32 + 0);
+ MSG1 = vld1q_u32(input32 + 4);
+ MSG2 = vld1q_u32(input32 + 8);
+ MSG3 = vld1q_u32(input32 + 12);
+
+ MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0)));
+ MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1)));
+ MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2)));
+ MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3)));
+
+ TMP0 = vaddq_u32(MSG0, C0);
+ TMP1 = vaddq_u32(MSG1, C0);
+
+ // Rounds 0-3
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1cq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG2, C0);
+ MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
+
+ // Rounds 4-7
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1cq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG3, C0);
+ MSG0 = vsha1su1q_u32(MSG0, MSG3);
+ MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
+
+ // Rounds 8-11
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1cq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG0, C0);
+ MSG1 = vsha1su1q_u32(MSG1, MSG0);
+ MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
+
+ // Rounds 12-15
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1cq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG1, C1);
+ MSG2 = vsha1su1q_u32(MSG2, MSG1);
+ MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
+
+ // Rounds 16-19
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1cq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG2, C1);
+ MSG3 = vsha1su1q_u32(MSG3, MSG2);
+ MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
+
+ // Rounds 20-23
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG3, C1);
+ MSG0 = vsha1su1q_u32(MSG0, MSG3);
+ MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
+
+ // Rounds 24-27
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG0, C1);
+ MSG1 = vsha1su1q_u32(MSG1, MSG0);
+ MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
+
+ // Rounds 28-31
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG1, C1);
+ MSG2 = vsha1su1q_u32(MSG2, MSG1);
+ MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
+
+ // Rounds 32-35
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG2, C2);
+ MSG3 = vsha1su1q_u32(MSG3, MSG2);
+ MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
+
+ // Rounds 36-39
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG3, C2);
+ MSG0 = vsha1su1q_u32(MSG0, MSG3);
+ MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
+
+ // Rounds 40-43
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1mq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG0, C2);
+ MSG1 = vsha1su1q_u32(MSG1, MSG0);
+ MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
+
+ // Rounds 44-47
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1mq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG1, C2);
+ MSG2 = vsha1su1q_u32(MSG2, MSG1);
+ MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
+
+ // Rounds 48-51
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1mq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG2, C2);
+ MSG3 = vsha1su1q_u32(MSG3, MSG2);
+ MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
+
+ // Rounds 52-55
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1mq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG3, C3);
+ MSG0 = vsha1su1q_u32(MSG0, MSG3);
+ MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
+
+ // Rounds 56-59
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1mq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG0, C3);
+ MSG1 = vsha1su1q_u32(MSG1, MSG0);
+ MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
+
+ // Rounds 60-63
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG1, C3);
+ MSG2 = vsha1su1q_u32(MSG2, MSG1);
+ MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
+
+ // Rounds 64-67
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E0, TMP0);
+ TMP0 = vaddq_u32(MSG2, C3);
+ MSG3 = vsha1su1q_u32(MSG3, MSG2);
+ MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
+
+ // Rounds 68-71
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+ TMP1 = vaddq_u32(MSG3, C3);
+ MSG0 = vsha1su1q_u32(MSG0, MSG3);
+
+ // Rounds 72-75
+ E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E0, TMP0);
+
+ // Rounds 76-79
+ E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
+ ABCD = vsha1pq_u32(ABCD, E1, TMP1);
+
+ // Add state back
+ E0 += E0_SAVED;
+ ABCD = vaddq_u32(ABCD_SAVED, ABCD);
+
+ input32 += 64/4;
+ blocks--;
+ }
+
+ // Save digest
+ vst1q_u32(&digest[0], ABCD);
+ digest[4] = E0;
+ }
+
+}
diff --git a/src/lib/hash/sha2_32/sha2_32.cpp b/src/lib/hash/sha2_32/sha2_32.cpp
index c4d76b0f6..ab6903fa7 100644
--- a/src/lib/hash/sha2_32/sha2_32.cpp
+++ b/src/lib/hash/sha2_32/sha2_32.cpp
@@ -11,51 +11,40 @@
namespace Botan {
-namespace {
-
-namespace SHA2_32 {
-
-/*
-* SHA-256 Rho Function
-*/
-inline uint32_t rho(uint32_t X, uint32_t rot1, uint32_t rot2, uint32_t rot3)
- {
- return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^
- rotate_right(X, rot3));
- }
-
-/*
-* SHA-256 Sigma Function
-*/
-inline uint32_t sigma(uint32_t X, uint32_t rot1, uint32_t rot2, uint32_t shift)
- {
- return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift));
- }
-
/*
* SHA-256 F1 Function
*
* Use a macro as many compilers won't inline a function this big,
* even though it is much faster if inlined.
*/
-#define SHA2_32_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) \
- do { \
- H += magic + rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + M1; \
- D += H; \
- H += rho(A, 2, 13, 22) + ((A & B) | ((A | B) & C)); \
- M1 += sigma(M2, 17, 19, 10) + M3 + sigma(M4, 7, 18, 3); \
+#define SHA2_32_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) do { \
+ uint32_t A_rho = rotate_right(A, 2) ^ rotate_right(A, 13) ^ rotate_right(A, 22); \
+ uint32_t E_rho = rotate_right(E, 6) ^ rotate_right(E, 11) ^ rotate_right(E, 25); \
+ uint32_t M2_sigma = rotate_right(M2, 17) ^ rotate_right(M2, 19) ^ (M2 >> 10); \
+ uint32_t M4_sigma = rotate_right(M4, 7) ^ rotate_right(M4, 18) ^ (M4 >> 3); \
+ H += magic + E_rho + ((E & F) ^ (~E & G)) + M1; \
+ D += H; \
+ H += A_rho + ((A & B) | ((A | B) & C)); \
+ M1 += M2_sigma + M3 + M4_sigma; \
} while(0);
/*
* SHA-224 / SHA-256 compression function
*/
-void compress(secure_vector<uint32_t>& digest,
- const uint8_t input[], size_t blocks)
+void SHA_256::compress_digest(secure_vector<uint32_t>& digest,
+ const uint8_t input[], size_t blocks)
{
#if defined(BOTAN_HAS_SHA2_32_X86)
if(CPUID::has_intel_sha())
{
- return sha2_compress_x86(digest.data(), input, blocks);
+ return SHA_256::compress_digest_x86(digest, input, blocks);
+ }
+#endif
+
+#if defined(BOTAN_HAS_SHA2_32_ARMV8)
+ if(CPUID::has_arm_sha2())
+ {
+ return SHA_256::compress_digest_armv8(digest, input, blocks);
}
#endif
@@ -160,16 +149,12 @@ void compress(secure_vector<uint32_t>& digest,
}
}
-}
-
-}
-
/*
* SHA-224 compression function
*/
void SHA_224::compress_n(const uint8_t input[], size_t blocks)
{
- SHA2_32::compress(m_digest, input, blocks);
+ SHA_256::compress_digest(m_digest, input, blocks);
}
/*
@@ -201,7 +186,7 @@ void SHA_224::clear()
*/
void SHA_256::compress_n(const uint8_t input[], size_t blocks)
{
- SHA2_32::compress(m_digest, input, blocks);
+ SHA_256::compress_digest(m_digest, input, blocks);
}
/*
diff --git a/src/lib/hash/sha2_32/sha2_32.h b/src/lib/hash/sha2_32/sha2_32.h
index 5a687efbe..ecf2e0ece 100644
--- a/src/lib/hash/sha2_32/sha2_32.h
+++ b/src/lib/hash/sha2_32/sha2_32.h
@@ -49,20 +49,33 @@ class BOTAN_DLL SHA_256 final : public MDx_HashFunction
SHA_256() : MDx_HashFunction(64, true, true), m_digest(8)
{ clear(); }
+ /*
+ * Perform a SHA-256 compression. For internal use
+ */
+ static void compress_digest(secure_vector<uint32_t>& digest,
+ const uint8_t input[],
+ size_t blocks);
+
private:
+
+#if defined(BOTAN_HAS_SHA2_32_ARMV8)
+ static void compress_digest_armv8(secure_vector<uint32_t>& digest,
+ const uint8_t input[],
+ size_t blocks);
+#endif
+
+#if defined(BOTAN_HAS_SHA2_32_X86)
+ static void compress_digest_x86(secure_vector<uint32_t>& digest,
+ const uint8_t input[],
+ size_t blocks);
+#endif
+
void compress_n(const uint8_t[], size_t blocks) override;
void copy_out(uint8_t[]) override;
secure_vector<uint32_t> m_digest;
};
-#if defined(BOTAN_HAS_SHA2_32_X86)
-/*
-* SHA-256 compression using Goldmont x86 extensions. Not for public consumption.
-*/
-void sha2_compress_x86(uint32_t digest[8], const uint8_t input[], size_t blocks);
-#endif
-
}
#endif
diff --git a/src/lib/hash/sha2_32/sha2_32_armv8/info.txt b/src/lib/hash/sha2_32/sha2_32_armv8/info.txt
new file mode 100644
index 000000000..88e5c2b80
--- /dev/null
+++ b/src/lib/hash/sha2_32/sha2_32_armv8/info.txt
@@ -0,0 +1,13 @@
+<defines>
+SHA2_32_ARMV8 -> 20170117
+</defines>
+
+<arch>
+#arm32
+arm64
+</arch>
+
+<cc>
+gcc:4.9
+clang:3.8
+</cc>
diff --git a/src/lib/hash/sha2_32/sha2_32_armv8/sha2_32_armv8.cpp b/src/lib/hash/sha2_32/sha2_32_armv8/sha2_32_armv8.cpp
new file mode 100644
index 000000000..9bf05047d
--- /dev/null
+++ b/src/lib/hash/sha2_32/sha2_32_armv8/sha2_32_armv8.cpp
@@ -0,0 +1,202 @@
+/*
+* SHA-256 using CPU instructions in ARMv8
+*
+* Contributed by Jeffrey Walton. Based on public domain code by
+* Johannes Schneiders, Skip Hovsmith and Barry O'Rourke.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sha2_32.h>
+#include <arm_neon.h>
+
+namespace Botan {
+
+/*
+* SHA-256 using CPU instructions in ARMv8
+*/
+//static
+BOTAN_FUNC_ISA("+crypto")
+void SHA_256::compress_digest_armv8(secure_vector<uint32_t>& digest, const uint8_t input8[], size_t blocks)
+ {
+ static const uint32_t K[] = {
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+ };
+
+ uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE;
+ uint32x4_t MSG0, MSG1, MSG2, MSG3;
+ uint32x4_t TMP0, TMP1, TMP2;
+
+ // Load initial values
+ STATE0 = vld1q_u32(&digest[0]);
+ STATE1 = vld1q_u32(&digest[4]);
+
+ // Intermediate void* cast due to http://llvm.org/bugs/show_bug.cgi?id=20670
+ const uint32_t* input32 = reinterpret_cast<const uint32_t*>(reinterpret_cast<const void*>(input8));
+
+ while (blocks)
+ {
+ // Save current state
+ ABEF_SAVE = STATE0;
+ CDGH_SAVE = STATE1;
+
+ MSG0 = vld1q_u32(input32 + 0);
+ MSG1 = vld1q_u32(input32 + 4);
+ MSG2 = vld1q_u32(input32 + 8);
+ MSG3 = vld1q_u32(input32 + 12);
+
+ MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0)));
+ MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1)));
+ MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2)));
+ MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3)));
+
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x00]));
+
+ // Rounds 0-3
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x04]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 4-7
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x08]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 8-11
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x0c]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 12-15
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x10]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 16-19
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x14]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 20-23
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x18]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 24-27
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x1c]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 28-31
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x20]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 32-35
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x24]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 36-39
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x28]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 40-43
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x2c]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 44-47
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x30]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 48-51
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x34]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Rounds 52-55
+ TMP2 = STATE0;
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x38]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+
+ // Rounds 56-59
+ TMP2 = STATE0;
+ TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x3c]));
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Rounds 60-63
+ TMP2 = STATE0;
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1);
+
+ // Add back to state
+ STATE0 = vaddq_u32(STATE0, ABEF_SAVE);
+ STATE1 = vaddq_u32(STATE1, CDGH_SAVE);
+
+ input32 += 64/4;
+ blocks--;
+ }
+
+ // Save state
+ vst1q_u32(&digest[0], STATE0);
+ vst1q_u32(&digest[4], STATE1);
+ }
+
+}
diff --git a/src/lib/hash/sha2_32/sha2_32_x86/sha2_32_x86.cpp b/src/lib/hash/sha2_32/sha2_32_x86/sha2_32_x86.cpp
index 8f90ec5a9..aadb48710 100644
--- a/src/lib/hash/sha2_32/sha2_32_x86/sha2_32_x86.cpp
+++ b/src/lib/hash/sha2_32/sha2_32_x86/sha2_32_x86.cpp
@@ -12,7 +12,7 @@
namespace Botan {
// called from sha2_32.cpp
-void sha2_compress_x86(uint32_t digest[8], const uint8_t input[], size_t blocks)
+void SHA_256::compress_digest_x86(secure_vector<uint32_t>& digest, const uint8_t input[], size_t blocks)
{
__m128i STATE0, STATE1;
__m128i MSG, TMP, MASK;
diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp
index 512e4aa63..40bdbf477 100644
--- a/src/lib/x509/x509cert.cpp
+++ b/src/lib/x509/x509cert.cpp
@@ -334,7 +334,7 @@ bool X509_Certificate::has_ex_constraint(const std::string& ex_constraint) const
*/
uint32_t X509_Certificate::path_limit() const
{
- return m_subject.get1_uint32("X509v3.BasicConstraints.path_constraint", 0);
+ return m_subject.get1_uint32("X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT);
}
/*
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index 8521e51a7..a06df2460 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -76,13 +76,9 @@ PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& ce
status.insert(Certificate_Status_Code::CERT_HAS_EXPIRED);
// Check issuer constraints
-
if(!issuer->is_CA_cert() && !self_signed_ee_cert)
status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER);
- if(issuer->path_limit() < i)
- status.insert(Certificate_Status_Code::CERT_CHAIN_TOO_LONG);
-
std::unique_ptr<Public_Key> issuer_key(issuer->subject_public_key());
if(!issuer_key)
@@ -115,6 +111,39 @@ PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& ce
}
}
+ // path len check
+ size_t max_path_length = cert_path.size();
+ for(size_t i = cert_path.size() - 1; i > 0 ; --i)
+ {
+ std::set<Certificate_Status_Code>& status = cert_status.at(i);
+ const std::shared_ptr<const X509_Certificate>& subject = cert_path[i];
+
+ /*
+ * If the certificate was not self-issued, verify that max_path_length is
+ * greater than zero and decrement max_path_length by 1.
+ */
+ if(subject->subject_dn() != subject->issuer_dn())
+ {
+ if(max_path_length > 0)
+ {
+ --max_path_length;
+ }
+ else
+ {
+ status.insert(Certificate_Status_Code::CERT_CHAIN_TOO_LONG);
+ }
+ }
+
+ /*
+ * If pathLenConstraint is present in the certificate and is less than max_path_length,
+ * set max_path_length to the value of pathLenConstraint.
+ */
+ if(subject->path_limit() != Cert_Extension::NO_CERT_PATH_LIMIT && subject->path_limit() < max_path_length)
+ {
+ max_path_length = subject->path_limit();
+ }
+ }
+
return cert_status;
}
diff --git a/src/tests/data/extended_x509/01/end.crt b/src/tests/data/extended_x509/01/end.crt
new file mode 100644
index 000000000..5d05a8e5e
--- /dev/null
+++ b/src/tests/data/extended_x509/01/end.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAbMQswCQYDVQQGEwJERTEM
+MAoGA1UEAxMDSW50MB4XDTE3MDMzMTIwMzYwMFoXDTE4MDMzMTIwMzYwMFowGjEL
+MAkGA1UEBhMCREUxCzAJBgNVBAMTAkVFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAt3ZPYYEIMIAViK68jKugGUMIISV4X7JjUz3/k44E2E2ovPem7mhq
+JPOzKpaS9+AOzEIJQIT+a6Re4+DmUNvW9Zm6P2J4Lrc8ixoCejMSwrtyqCCTJ+ef
+i6o82d0Tgge4ZnudiIzozUJy1rAS5T+rV6re3SUdKdjgLkva735Bve67/gS9eh5L
+AIQpN8ZPa4+qzbwfGZe3PGgOV2701LzQCrVRe7KWpm1ZjOi5WTRh0xAHiC6WpM2F
+eF0aRkC18Sat3FTi0ba2cqikttPnghFhShLUyUvn/LrLsk/ajGaArbV88Hk+p8l/
+pXhNh1X0zftxS/Fa1QCFbb4OxQMSmGZgMwIDAQABo1wwWjAMBgNVHRMBAf8EAjAA
+MB0GA1UdDgQWBBRH3e2M6wVjMMj76gDRe1/q5KkFwDALBgNVHQ8EBAMCBLAwHgYJ
+YIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEA
+TF2AdhF57cBnjmeiv+HKKgjybWvA2X14k+rdRasNg87oJ/v2Kf/llJkUu2vs44tQ
+8HrmET6nq+0dPdJL4SsgyYqCW82hGh0W1saSFyCq+Wbk4DSFbHopOxlbbgX4GUJ/
+wfRY6BVRhz3IdPR4TM0zJ4o3nk+OTfBi+3ckfaK5DYNsnYbZwoG92ISMSRHGmg6g
+UYXOVmHmzIFK0ESl8+om2VsbWPRUCBOtU1BJLYwpx4RyIBBYPHR4npu+OpNrcBzR
+MaZuHuoKbqvZlvCclbd37YffyWryOGEf+YcjQPy8BqFMUQBBRH9gW4Ph819UYFpb
+IozFU/jYzXzXoxG4hMqtHA==
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/01/int.crt b/src/tests/data/extended_x509/01/int.crt
new file mode 100644
index 000000000..b6708f169
--- /dev/null
+++ b/src/tests/data/extended_x509/01/int.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAdmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJERTEN
+MAsGA1UEAxMEUm9vdDAeFw0xNzAzMzEyMDM1MDBaFw0yNzAzMzEyMDM1MDBaMBsx
+CzAJBgNVBAYTAkRFMQwwCgYDVQQDEwNJbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC7vyhLG+LWNHi/7MdX971HRqc8TD0aSG4nbclEeV+mGPRhdbVD
+A+ZQn8Bj26iqRMJ8WT6+/M1rycOaAcEsfGSjPCSqrBuyo973nqMgiTfCgucFYtj/
+jkUArJQ8yuNJkLXkQK+4S0iSA1h7nPLwC967qPKcJnQgeHJDjKU9AefXoda66zxO
+kbaX4y5oY346tWP/0pjDeo2zix15jajPrAvCtDFJrYni71ixFNHZRI159cscSvfR
+I2lNnkUJ/M/6UnwflYgin7N/DHk/oad96bXatuKmdCWA/5R4FAnAhwdL7sbTy4LL
+jV8amewEhSn51iSFqVIm6wO7NiZw8D3/603TAgMBAAGjPzA9MA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFHs9prehJUV7V9rn0KlYPmZqzRXXMAsGA1UdDwQEAwIB
+BjANBgkqhkiG9w0BAQsFAAOCAQEADsKaZEuxy9upg0HTxWy2RfY8im+Xg5qkU2IW
++vSFr1QoZWVn59y3WzeoBqi9dFquQyUjTvPUHJoplh9CvHWZbL0ih/NUt70uy/Jz
+kyacpcFEbiAZD6sPCe6JwOSrEAEnTRDpP2Gn6gRxVOXGptMFpX54yxf4shZJnyy/
+r1iY11WQGy4qJS+20eUj4CxqletBzKfMiar9oX9sJl/Go1KzZexnIqli2v1/KevX
+6PRc+ubmz4aZzkRzP9v0Ie8YxJmjY5LLnhjY/G2GV8I6p8y5UqYkYRPvGJXB5WAi
+1b6uvuEhgatAelk1mn95Pv7W8ASLWbbV4OippdZUdOCkxs/D+w==
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/01/root.crt b/src/tests/data/extended_x509/01/root.crt
new file mode 100644
index 000000000..f83c6c516
--- /dev/null
+++ b/src/tests/data/extended_x509/01/root.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC9TCCAd2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJERTEN
+MAsGA1UEAxMEUm9vdDAeFw0xNzAzMzEyMDMzMDBaFw0yNzAzMzEyMDMzMDBaMBwx
+CzAJBgNVBAYTAkRFMQ0wCwYDVQQDEwRSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA86tiSCsS6wRGe/iylnLS3WnxcWM/x8qrQZQ5JAaB7LMR6Dfp
+DSBk9vU4/h0CbYVr9+7an3dEDA6Raoh+qLDklspqDQ5cXlYee8GMutQbSTxtKA+4
+fgIrT18JyBu993IBszwj01BVD+Ibun+Bw/pg7dYD3w+T60njMb4EirU5/0e1CKxB
+iv5UEY7R6DkIU4QXHzvj0Dstls5XTsIAODuh4IEwsnMq9ZQi7Cl4AflUABAY0w6B
+nEhbb3wMmg1ndDnv9RcOP3IQzIFuQG3i8SdH1Rik/00N9Mom7sRCulrPhZoNFbTV
+tQ9PZ8iQPUNzJNrIkWZ/O9uN023wtbiGlgSytQIDAQABo0IwQDASBgNVHRMBAf8E
+CDAGAQH/AgEBMB0GA1UdDgQWBBRfG0Pzn9XuCESFgLCJOWpwAC/XFDALBgNVHQ8E
+BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAH2RqhCbx3SjljbbqPq8dxUccLvtIf/S
+oxPn7ogdG3WuwfCQzXJ7v0HwcLTytF+/zYYgPTip9RmQdVqym9YjlDAG5NlFQm3b
+jYZQ0gUrG56tb57K1YjQcrUU15ewbILZU0N0gfs+p1PMUkFsVVsPienO7j0aRKmB
+U6Ecgma8kS/++QvlFlgXE+shdzXjN92nuqHeJ8aNaPb7ueD6b82+LK8ZuCPPtHUN
+EdCzKWYlHzMKklLVbfzXbHG5yiiim9OaFqsY+7ljWJiT//s5bbGRJjBb2GCSwVvI
+wOubEvVrJ02l7U69LxaHsXXRlKw3vq1Z3HbKAIJlWMIPvaFQKnY9RdI=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/end.crt b/src/tests/data/extended_x509/02/end.crt
new file mode 100644
index 000000000..b0dc343b6
--- /dev/null
+++ b/src/tests/data/extended_x509/02/end.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQyMDBaFw0xODA1MTcxMjQyMDBa
+MBoxGDAWBgNVBAMTD1BhdGhMZW4gVGVzdCBFRTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrhTUs/sAT4S2JMYFh8Z7bSzgQLqt3l+cAW1mgiw3ydh0+L
+aytLRmyJrX0K6B2zEZKilbPXPJW2O1fY5lIvrYz0HGJRcQWRhZ9IaAqkWNSrIGR6
+bCodpDH/Lr3nUuvsaLobFs+e+YLdXu1TwQMBieIi5eXuwaPIpcGi8Byl2iBsS9UT
+CYDj08rwOwF8f/zgWJK/2to2TraHTHw+rjlOL5MEXxjLC50ZnKaAzw4K49mnRv8U
+exzs67250Sa0ZONB3nh1/Z+FBNIsdXcNDoMtn04/sk1F/TF3f8jA3h+HOvfGrE6O
+dqJ6DJK4UD/RqfRiD0+6Spcx+eu2rR2ss9ISKJ8CAwEAAaOBhjCBgzAMBgNVHRMB
+Af8EAjAAMB0GA1UdDgQWBBTrUJdF9MaI2YaBus2Teo09rq/YEDBHBgNVHSMEQDA+
+gBRBtmp9tx8Q7LqmvCh8n9jxgmLcsqEjpCEwHzEdMBsGA1UEAxMUUGF0aExlbiBU
+ZXN0IEludDEgQ0GCAQMwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBAQBA
+q9bK4nMz0H2vLmSfiqbNB7chjKztAzQkD1YZTDmyuDVFXNu6ooClWOIOAPj0/XrL
+s2LHz0KodS4QkEStoK8lsFDmo6lNCKVkGsSNUUwmWa2P43EpmzZdVSd0tk/BSA0O
+dPifwTncW9hsseHoe5G29ddLdnRE9MH/5rrLOMFPSa0wHOXNqbt6wAANTwrBY+QV
+xFQSmkBiICqJqCpcqe7gH/x9lgNYdQxBCnR6pitj6uxmOLl40qzfVfzKQe8hovyA
+piOjaYJ4i4j7xl3nlsw4CjaRitpDwLXjL8LQfdoOD/FWj18+DFcH59azqBjoyr6x
+OtnVSv2VDcvcvhNHiqCy
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/int1-2.crt b/src/tests/data/extended_x509/02/int1-2.crt
new file mode 100644
index 000000000..6c93d0492
--- /dev/null
+++ b/src/tests/data/extended_x509/02/int1-2.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQxMDBaFw0yNzA1MTcxMjQxMDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAoQGuLP6gafHVnoyFbtTVBV+Svc6TwG6nBLWMj5oI
+csWF5815WuDKJCIef0FzT81ew2PqxJKqvwu68+IW6v5EmIMO99fig80/o/IVWwuv
+/ycRIth4UJsEpg25QUiFwBcmeJ3Hhjrf+2cPqKLT7dCiz+FJY6fXQdpo8vtJVMSa
+8u5oA0NoSYnVnRrT8mDP2io1egWkwdFjn4JLZ99UYVBCEi/Pp3DNhtkn3rwaIm6v
+SGxKxtgHWqTmldeCB+k7YVOPOYLbAlhNknpXFiU4Op0hEFMtgnUXGH5s2bJNM0sS
+VOBG78UIfRPxumkPYelzPCUsYbRJ7PulybtNdtWFPtlDewIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFEG2an23HxDsuqa8KHyf2PGCYtyy
+MEcGA1UdIwRAMD6AFNtU+/YoX0TQdnd50WtkXsyilRoGoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBAjALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAKWTS0/h4bDNbBQaELSMbYyyNw+WQKRJKRawoC9d89JywD/1xjM2
+byCySAOdsuWX5t8PuDIHjLu4vykF792Cpx3ToWztHTPYkpg/Ci25H4Vvhbdlb62X
+h712cQ0hEdrNC5Uahl3jUpYfdktF8un3fp33yazlF2PHswWtgFBpU3u0GZi4R7ft
+CsY1XzzxaEjBwfu8vDLf/kkdJBpXh97rkGhfogNSJ4+EAlqbJ+rTj1ucW7ou9M9d
+vvIHAx1lJWERoSDUDOIigpJaHSs2kIvF1/+pCW7pJiZ2EwD5S0Kj0m+6Evic/Vo0
+6Ff9EE6WPEMY4p3ykFc6+TIOj8Xbw03VFWI=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/int1.crt b/src/tests/data/extended_x509/02/int1.crt
new file mode 100644
index 000000000..66a5d9a8c
--- /dev/null
+++ b/src/tests/data/extended_x509/02/int1.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjQxMDBaFw0yNzA1MTcxMjQxMDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAvcX2nM3+B9OTzmVbl80c6rBnoCCINvrsRNEqPET5
+zF5NSGZzJJo3GF9iZCov4rLSWIgyHqekWIbs5JximdIc5JaNkEeic6RYU4u+5GFI
+ki2qXfNiqIPgxAO2F8/7W0nXa5B+2kH8d62m2um8ONY6f1NkBM+bTLgMb78K3js4
+eftYjRVd3EFzBEiIVKj3VyGRtbiNWZCRbT7/X4tCjYVwjFZejbyZkQJv5qhbWv0X
+Il/6gNbvN5P1Iumy5yBfKwonJiYyLv3DZME5sexzAJa7OxNEwJApuY+93soA0iLd
+1WyzNpeL4hzNvpYUi5YuiLjA5oHLPmFYN96wKUAP9yWhfwIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFNtU+/YoX0TQdnd50WtkXsyilRoG
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHyi1KRBgrpu/bxiioRchfZN9AtVS2qeohA0WkDZbdbgI5j/sqgy
+IfVVQizBJVeTfFuv6C2davHnnpoDUTYwY4tiQz4ZJtTm2zLmUw3ennujlLJeBP5O
+ykjcU7lxAmf6vAdMvqRuIHvx/nYgE2G3T6sx7Doa5kdruCHosLvuUU6sP0cQjxsH
+x0gbDTvE+DjIjrSlCAVBwNB0zcOHG0A/fV2SEHy4Pi/JthEvXExngXnNMFlPEA58
+1FL8M0bpxW3M2tchFoGhTrSDt4hkYqsV1kGK8zXgqT9PxyaSE9lvNjBVtGNbt+9Q
+jMbhRokpXaUALVxpHN5gC2YOO9yYD40EPUU=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/root.crt b/src/tests/data/extended_x509/02/root.crt
new file mode 100644
index 000000000..c66ac1c00
--- /dev/null
+++ b/src/tests/data/extended_x509/02/root.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjM5MDBaFw0yNzA1MTcxMjM5MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAwGl+aRGnJVyfSZlnoD+r9R8KjsJE6aduNtmDrTxE
+XkKceCfcqDyCVyF7jufmxrLnSEHEz4cx3hMGkG3SrsWmpzoIrSbvLliJs8uopBHv
+yojTRoCMHP6BQeRIFl/Z9g0NMpP+wC2a2pLL6Notsc2WCMbZOelx8JpyZDgHMmgg
+JiHydtTf5jw6U8O/KRoAJcd8cNMnWHb+ibwZ621WpFk38C9RA95lNhF3GoAKRAxb
+4VV0b1UXDfWEo2ame7PHJv2COv4ufWfMVn011nrUYU8AuzJX+mZj3dFqbvri9rB1
+KVzYkZkhf+ih3BMbH/ZZn18LU3IDwkLubYpE9Vnd75DxsQIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFOphOYxY6kM+m0UT5FTvNLzki+2H
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHAIh/0/urh5Z5uY0D5XtGQ5ZVHSGb23i15mVFDQafMy1G5wsKRx
+/cO/Gg7U0TuAl8mxvOlJtLCIC/1RybRegmhkzsxWZVaavxlZvRW+mpquJBA32+Qn
+Tc8tdYftICzgowdCl0m2RlZJXDOc6//8LUqcIsz85XOeBjMMRSrkGIJU/Iq4xSyd
+zIqH+iilsP5r9MzBWCtwWFzy/noZAtl9aaHFtCPVTAE6L4rXxPEKFJ65nQdSl2pN
+4KqR6JImoGLoat87sVDjs4GJdbcyx6GSo8Qgj7cbxGkkD87jfPeqFMCJlf0bkTxX
+xgbGs+HNsuzjl5bfZtCFLDYVGrJ+TlFTn/s=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/end.crt b/src/tests/data/extended_x509/03/end.crt
new file mode 100644
index 000000000..d4ef54dcf
--- /dev/null
+++ b/src/tests/data/extended_x509/03/end.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQ2MDBaFw0yNzA1MTcxMjQ2MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQyIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAoQGuLP6gafHVnoyFbtTVBV+Svc6TwG6nBLWMj5oI
+csWF5815WuDKJCIef0FzT81ew2PqxJKqvwu68+IW6v5EmIMO99fig80/o/IVWwuv
+/ycRIth4UJsEpg25QUiFwBcmeJ3Hhjrf+2cPqKLT7dCiz+FJY6fXQdpo8vtJVMSa
+8u5oA0NoSYnVnRrT8mDP2io1egWkwdFjn4JLZ99UYVBCEi/Pp3DNhtkn3rwaIm6v
+SGxKxtgHWqTmldeCB+k7YVOPOYLbAlhNknpXFiU4Op0hEFMtgnUXGH5s2bJNM0sS
+VOBG78UIfRPxumkPYelzPCUsYbRJ7PulybtNdtWFPtlDewIDAQABo4GJMIGGMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEG2an23HxDsuqa8KHyf2PGCYtyyMEcG
+A1UdIwRAMD6AFNtU+/YoX0TQdnd50WtkXsyilRoGoSOkITAfMR0wGwYDVQQDExRQ
+YXRoTGVuIFRlc3QgUm9vdCBDQYIBAzALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL
+BQADggEBAJMJUlCtT9OCt6G/jNRcZrsxprlVvGBpLItHF6Kol+gs/Pz93c3rLxj6
+czp2OqjZFsm6k0Fl6kSrBQHRH/dZdKZlsNtMnrF0RXonuJVBaSONKC6SFOc4E9qa
+nNfx/AB40IGdhKbgHNS/92Q4kIwV2JfbQPXTmOvFTtFH/saUoTmlMWaBIeEEjQX2
+/NjyCvSUvKVwAgTF/HWspzjuEVukiCszVOQV8UuhEnLSdvztuguf0CkM93W17x7t
+//R04hz+TOLCAp5OzeZB4y4UE+oroo1ynzdTnQ7PHMxh67+mX2piawc00zyHqqTf
+09z9uN4HmyJNQ4FXUvhC0Q+tISCaB68=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/int1.crt b/src/tests/data/extended_x509/03/int1.crt
new file mode 100644
index 000000000..1e4ec713e
--- /dev/null
+++ b/src/tests/data/extended_x509/03/int1.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjQ1MDBaFw0yNzA1MTcxMjQ1MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAvcX2nM3+B9OTzmVbl80c6rBnoCCINvrsRNEqPET5
+zF5NSGZzJJo3GF9iZCov4rLSWIgyHqekWIbs5JximdIc5JaNkEeic6RYU4u+5GFI
+ki2qXfNiqIPgxAO2F8/7W0nXa5B+2kH8d62m2um8ONY6f1NkBM+bTLgMb78K3js4
+eftYjRVd3EFzBEiIVKj3VyGRtbiNWZCRbT7/X4tCjYVwjFZejbyZkQJv5qhbWv0X
+Il/6gNbvN5P1Iumy5yBfKwonJiYyLv3DZME5sexzAJa7OxNEwJApuY+93soA0iLd
+1WyzNpeL4hzNvpYUi5YuiLjA5oHLPmFYN96wKUAP9yWhfwIDAQABo4GJMIGGMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNtU+/YoX0TQdnd50WtkXsyilRoGMEcG
+A1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQDExRQ
+YXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL
+BQADggEBAK+euvQn4INuV1Dy12Vf8MYQQgFptU+ysBI8pXHxVjrR3VSk+LlNNwQ3
+50bKF/fNOb9YjosBYnPf/oL1O6yUEN+lNfsDwDK7P42poiUy4x+1oRua9AVYFKdP
+LTDhyfK/LQNMG3UizZLU7UwHZDTGpzeozUQB8yRIIJpnBw3hkD3ZK1GUGHiGPCN7
+A3f/D6sCRU3K9JIGrPjx8Nfuh9OEMsVDMCE2rGyhNz24EajFZoX+4C6lxzwDHMqR
+l7dW7TeplPalUHlpp1o+rJiJVxXTuL1cJr6jqmM1Uzbm/d/b2kwDyyX5xmTQBJ2g
+MqKPmIPvcEEsfuzOZCDb2HhSiaUI39M=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/root.crt b/src/tests/data/extended_x509/03/root.crt
new file mode 100644
index 000000000..c66ac1c00
--- /dev/null
+++ b/src/tests/data/extended_x509/03/root.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjM5MDBaFw0yNzA1MTcxMjM5MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAwGl+aRGnJVyfSZlnoD+r9R8KjsJE6aduNtmDrTxE
+XkKceCfcqDyCVyF7jufmxrLnSEHEz4cx3hMGkG3SrsWmpzoIrSbvLliJs8uopBHv
+yojTRoCMHP6BQeRIFl/Z9g0NMpP+wC2a2pLL6Notsc2WCMbZOelx8JpyZDgHMmgg
+JiHydtTf5jw6U8O/KRoAJcd8cNMnWHb+ibwZ621WpFk38C9RA95lNhF3GoAKRAxb
+4VV0b1UXDfWEo2ame7PHJv2COv4ufWfMVn011nrUYU8AuzJX+mZj3dFqbvri9rB1
+KVzYkZkhf+ih3BMbH/ZZn18LU3IDwkLubYpE9Vnd75DxsQIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFOphOYxY6kM+m0UT5FTvNLzki+2H
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHAIh/0/urh5Z5uY0D5XtGQ5ZVHSGb23i15mVFDQafMy1G5wsKRx
+/cO/Gg7U0TuAl8mxvOlJtLCIC/1RybRegmhkzsxWZVaavxlZvRW+mpquJBA32+Qn
+Tc8tdYftICzgowdCl0m2RlZJXDOc6//8LUqcIsz85XOeBjMMRSrkGIJU/Iq4xSyd
+zIqH+iilsP5r9MzBWCtwWFzy/noZAtl9aaHFtCPVTAE6L4rXxPEKFJ65nQdSl2pN
+4KqR6JImoGLoat87sVDjs4GJdbcyx6GSo8Qgj7cbxGkkD87jfPeqFMCJlf0bkTxX
+xgbGs+HNsuzjl5bfZtCFLDYVGrJ+TlFTn/s=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/expected.txt b/src/tests/data/extended_x509/expected.txt
new file mode 100644
index 000000000..ee6fc5943
--- /dev/null
+++ b/src/tests/data/extended_x509/expected.txt
@@ -0,0 +1,3 @@
+01:Verified
+02:Verified
+03:Verified \ No newline at end of file
diff --git a/src/tests/data/hash/sha1.vec b/src/tests/data/hash/sha1.vec
index 395de6efc..c1435958b 100644
--- a/src/tests/data/hash/sha1.vec
+++ b/src/tests/data/hash/sha1.vec
@@ -1,4 +1,4 @@
-#test cpuid sse2 sha
+#test cpuid sse2 sha armv8sha1
[SHA-160]
In =
diff --git a/src/tests/data/hash/sha2_32.vec b/src/tests/data/hash/sha2_32.vec
index d71f49f20..602891ea1 100644
--- a/src/tests/data/hash/sha2_32.vec
+++ b/src/tests/data/hash/sha2_32.vec
@@ -1,4 +1,4 @@
-#test cpuid sha
+#test cpuid sha armv8sha2
[SHA-224]
In =
@@ -794,3 +794,390 @@ Out = 9267D3DBED802941483F1AFA2A6BC68DE5F653128ACA9BF1461C5D0A3AD36ED2
In = 0000000000000000000000000000000000000000000000000000000000000001
Out = EC4916DD28FC4C10D78E287CA5D9CC51EE1AE73CBFDE08C6B37324CBFAAC8BC5
+
+# Randomly generated inputs length 1 ... 129 generated by OpenSSL
+
+In = FF
+Out = A8100AE6AA1940D0B663BB31CD466142EBBDBD5187131B92D93818987832EB89
+
+In = 973A
+Out = 149B712A766C0A02B72C6C3A7AFFADD4085D7B05931B4516EDC65A9EB6E22680
+
+In = 3009B8
+Out = 96A75387879E8D57480DF10DCE407C6ED6797EB43256F5410EDE8755EA05D4A8
+
+In = F88519BB
+Out = 9658E45D0AE5F088CD673E167919285968A2878CF9D1CC63A10F09FDE37C997A
+
+In = 8701E337BB
+Out = 3A309AFCFD5ED8E1CE622A8D559961E428664A6F727DF4C22136FC4EBA08ED23
+
+In = 0D90326391F9
+Out = 00037AD7367512D5AAD2F2A804722D3155D2D0C98DE3935F2174F922975EE15D
+
+In = 5D10FA95BD08F9
+Out = 57511743DC186AAFF0F93B4040AB48CB49139E7C3CDEE653F61B5E5F61C71D36
+
+In = 4984CB3608F9645D
+Out = 8B68120DC066C80F689DE09BF75A661848657589D362FDC528A2ED63409B5DBC
+
+In = F64202A9B1DA2E688A
+Out = 4E49C74F6DECA3FF64CC1280E2BE7C8568A02999AFB9E5C0ED9EE78322B7A9CE
+
+In = 86F8219D69CFDE40A2D1
+Out = 5CF4657D7B134962D64F46DCE6E09F94262123A0F693360F842345FD3F475665
+
+In = 3D075A7686D6F2B0D933D5
+Out = 476EED19A66A112B7991A04062FF281B9595A4BC45C101629E92E3DD402F8EA5
+
+In = EB6BF5BA40801B27104A5FB3
+Out = A1A726DE33B6028F6D75BEB140C0FEC93ABBCD0B985E6DDA3BF818AF8E2B7096
+
+In = 23501486108F3DE2E9524C2EFE
+Out = B3883F5C7978D40CFA25F60E26AF8E26480586DF3BFB5F238E53F3A5F241FB92
+
+In = 6E33B6D645ACD2C80CEDB84500CD
+Out = E208985459AA801305493A313178D45D74E73B26AB268ECC57762D1F219B1DBD
+
+In = EAFFF26976BD4F943A705E36E62A69
+Out = 48A1434C314BC67604FCAE1EFF83F17CF05AE693B6427CFAE3B1F6692488D8FB
+
+In = 522051983C571EFF97886F19B08FBE69
+Out = 1F73010D11DBC5C283BD2ECF00B1E8D3745095260E1FCF00A3ABE0F0CCA4A2E5
+
+In = FB487FFDC5115F00EE6D5B7437E990B78A
+Out = FFE14FF1BEC3D445A8E6C6F8CF66D054D9B0FD00032DD1FE7FEA7DEFE2CB88E3
+
+In = E5158768A77C5FB06ED06ED333AA54A6C185
+Out = 8BF02C8642733293011185538969D1799F5CE86DF439930F995C4E3E530089FB
+
+In = 87583947BEFAAD4B43B4DD48FBA48D659F679C
+Out = 12B778AA6A84E7FFA6449F394E4A2F90AF4BEA3DC85E55AB2476216A87689B82
+
+In = 620418D700021FBE28E0173CE6102DFD3BC0A303
+Out = 186ACEBBF96463131AA08F68E1ECF96BD17A041BF4FF054585DE252B85EFCF6A
+
+In = 68F055AEB433075CE3E29C4763A49A5919D90CDCCD
+Out = DBF521256DAFD25F7E35E58E3BE51664F950292073A18EBD9A13E06B5B82965A
+
+In = C1FAEBFFAD2BF41EF1B65C68632CA044ED9A572A4CB0
+Out = B62C1A8FD2258E256B06315D1C2D98746AC18D7B170EAD81999B6110EBF69601
+
+In = 5C861F96020CC754B59066431EC96978FE0AB7FD9D1D0D
+Out = 5D3F355244C3B1E8904C7BED52BFC412B5CB8922634A20088D7EE7061BF2FB33
+
+In = 9BBAC4E256126423DFDEA90BE07315FB057F1523137C9C02
+Out = F9508865F80493F20A01A0277BED6E111149DBD99B9808578ABCC26CFE090A0A
+
+In = EC77F4ECC1F6EDFC63DFFBFE2EDF3FC9D348D3544A70888C1E
+Out = AF0CA3504E8364FFCEAEB3601E260F0FC43F9C565E76C3434CF16166EF62CBC1
+
+In = 8758D30E8DD41C7F4449C4F719F4AAFA900D836D3919F6BED77B
+Out = AE4BB846E12B020A438565FC6001340B8C05C2F9DA4CA416C60061D7F271A582
+
+In = D4F2A3729002173AB3F226C88FBC8C6B3CF7B73F9BAD2BB8888569
+Out = A0D93864B001794CA7E99E354DDB595929863F3338C5840598988D5782BD28DB
+
+In = E4D8EBFCE3D71014659AC8AFFF185E6C96A6D404ACCFA70D794FF56E
+Out = C8A86EE18A1F5BE4A513B647AFDE990ACC08699A66862C21879DE3D10E73A0FB
+
+In = 0F212467411D16E92AFBFE5B622DE745B41D631B2EB5477153BE84FF95
+Out = D5987E1E058D24E929C4ACDB342A8AD290DE72BF95D534D84B49629C4A4E4200
+
+In = 4EDA3360C3E4BD5E40ED0B9EFA421A43DC364752333FA9F317DB86B6E5D8
+Out = 68C0C4F2390A0A5415D9ACF86C659B148372EC1882687586251997C7CE519CB7
+
+In = 95A4F9B80AD217FDF65AC46BF3BE11D49CF03F013E72FDF6B3D9C6BE560508
+Out = A08A038DEBFE196F35D8F0087F9F2FAB1C0A10E3B01E6B2B80376A3DA25C0B1F
+
+In = A0FBA76B5E023C7E0CDA8B843B4105A7F0091092FDC254DF303B3C26F4A1F8D3
+Out = 9F3D31E526C953D6D14ACC8768D890F800D09DDFA361797571F30B854B53D9C0
+
+In = E58FD27C82C2F2605600D10CDCE144C54DC24F90C2D6E7CE7E8FA02FC32F247565
+Out = 95D42CA4521F927BD726FABD165F37E0DA75B93407BF207EB2CCC8BD8EA1A8A9
+
+In = 7B92504499E1290321C0FC7203F6C7D9912CC4BE9521AEA911AB14FDBFBA79BC112D
+Out = EFF00679E3B10E40E7F3F2B15070EBB8A5F0897EFEC7AC7AE55B39C569C2CB00
+
+In = D515195525F3D271CA8072E23B86A00C603B0949C5A23A3E13078319046519671169DC
+Out = D2E644512D4B18F01DCE2F8481AB99AF5E7BFCD0E82C67FB36EB09DFB0399858
+
+In = C399A4765AA46378B1CB64B7BD9D84ED6E288052D1D1CF5DFF6C0D0B12DAD359578FFF51
+Out = F08F6B46673F1A596EE4E493CB5136DFD5020E2AF13869B1C297E0341AE99DE5
+
+In = D1E565EDF6F4EE2B12A16B440712D9E52D890C96F3EE91495E53156A196FBBFA46A7474F64
+Out = B8EDC023612884C4D42B55161455C250E3F560962A835A2AFBDFBB25A4B51C39
+
+In = 31A55CAA88925A63484E53D946B5FE86B34A221519FD341AE1E77C7C4196DDCD174F16C98263
+Out = DB84214C82F246EF781652F39E39D8594B5DEE43A2D9FFA3F67B4BB11CCAC40D
+
+In = 3D888A1040AFFD114A719D42EF733314612618ACA03AB040F35EC71543EE1F02EDC37CE6A84C49
+Out = 2447EFDBA2DD415FA6454A944C43753F9191AE5C7B0DBB065CA5C468DA0E4CC7
+
+In = 0F801C7FC8FF2EE603C63CF1AE42D1DC9D73497245341986C2C39D08075E624998C47694E038806C
+Out = 4A5051FB9AD23815D88B9E003883169B25FD02BB1A06FACB36AAB35E252D62F0
+
+In = BEDE92EC1AB0BF966C7BC098DB7807B86A735A2B89CA7712F1F93B3FABA69F2A867A5F361CA235A088
+Out = 39A6B566A9D5A3AB3BE43D022D06A77338821A891BB952431DC500220E3D62C8
+
+In = 47B80BC42FAD7773884849297B4BA941DDD42FC14FCA3C39E2DFCC48C6AFCA7D8C9D55D5156473C3440A
+Out = 28CA6AB9E8B5ABA81389EBB03273F09F54E398497632A5826B39B41920CEC687
+
+In = 9522C8A3990D3D4CCB4C3D41C9B4655DDD35C33307D4EFEB74C583C29BFB84A98954CC5868C23C78127589
+Out = E0A7C694A3700FEC0A16335375641371A9C2B2C68B4DA08AE67CA1FEADA33AE8
+
+In = 169B7817ED75369341658CC854EBBC0AC11A531F94C1F4B9260732610803B0F2096A2E9A65B6C642C2546442
+Out = 12BD7465B0E681478552B94DCF6074CA70529D18492D857FC8E658C3398AE5B1
+
+In = 4F52B6723E7165F12D76A70BB311C04FDA7E68FAF091BCAF77065ED3E77015D82314A252EFBD7CC4A92473CF60
+Out = C0CA351E2A50E8D1E2E0E994A7F91FC6CF338822FB0FCDC388342A5F99F0A62F
+
+In = F38B8C4FDC73F40E3253C1B3B14F196558380A3413D34924E0487F5AA77B3384E9F6E046309AA062F7C813B601E1
+Out = 6DA821D8B24A88EAA765D0BFC4ABC03E147E15BD62DDDDE622FEDE4532944D52
+
+In = 41705AE5A1D12FBCCB4426CC811262D21C0C46DFD2DCD8AD7B92CC939B5549E063AC399A1E5613B545364F18F7BF4E
+Out = 6EEAC8187BC0564F68E63CD9231FF6F352C18461907A2FB1C2DE93ACD44940BB
+
+In = CC70E84AF58D027F5FF15B6FDE96AD30450D7F871C423A3531AE6FFADC8DC87ACDED57D0421BA15E237575C04ABE8E12
+Out = F0B28375878E437940D7EE4E7BC2DB4C4C8B5D3B6BE0C0755C10AEAB00A29CA3
+
+In = 2DADCC9FD75291B810439AD51B29502464F810F66E6998F348F4E2B5D5F128570ECB1FD671C9423E71DA3EB5F6DF1E2F33
+Out = 510F97486B03FF7AF1FECA9D0308239F63B4F8349F1FE2A577CF9DA93E23AC3E
+
+In = 0C086B9C06E92746E5325B86C9D8423ABBEE782E0CFF47BFC618FCF49A1E09FB5C031089137553268D63AAEE75A662D93C87
+Out = BA5369C00659AC9C5337A38E51FEAE0F005B0123C9909FAD5BD4605BDFE9C445
+
+In = DDBB8C24637FF24E073E9EE299AD5E73493C6A3AD0EEBE0D5130A65F3336906378A02E84B2DF4D925DDDBD44E84234F80B025C
+Out = A7F11830A67D3E2C7F4A37A4B5D274D4D0F3840B86148F1AF85170E230333188
+
+In = 6651A6054E16D4988752FE56B3E4088CF86FF6CA90EEBC0E3E5C4A5F14BF9CF643BF8652827F439F6549351356D2761632BB14A0
+Out = 3F400EC10FB5EBD455EE9175661657ED36D44AA6EAD84F3772FB7B164D40B29B
+
+In = 18532AF22D7F1E2A18ABC479CF6E899561C4A9A92AB27967D2E079AE69B651F01A9C95AA6908623D2DED86AED3A14E361D7ACC465B
+Out = D523310B1FAF11C3FA9FFDEC513EF15B41DEFDB877B4E9525B2519C8B1E5C909
+
+In = C022F99C785A0F2F1210F27D94CFD60D9C99368C469882C18899F7FDF2BF12E6BE231BA8F6858368678596D64328FBA2870F526D4C0E
+Out = 7F9ECD5C9F908D5794A065D457DCD31DFE6469AA680F1B58C8CB666ABD17C1A9
+
+In = 966D0D84D3F2BDC957935613D946509145B3345C90BA2244810EA6095EABB9C4F785868E61115B23AADB8CDCDE99FC83509D52CC67D582
+Out = BCF40210B6A8CAEE5751984946EEBF7FB411F8E5E0FD5162E5C640E6B2A85075
+
+In = 7B5E2FF358964BCE486DEA8C9B85176EBE361CA9C8A81487187D72773232BF2EE9576E02568AE3CB740C05B8A2BCFD7FB9B03EAFE41B9A93
+Out = 1CF74EC4B3315D56FAAC576D2DBAF1D62D53E0D59A256E6F5C83C496A71887A6
+
+In = DFC064E095B6E2CC8DCEE66470FE361EF1DCEA43B9513E7154D2C12C357C5A1C86F59BA0837C1AD55314A5D2D36BBDE483EE7700CFB0ABBFC7
+Out = 5B8E6CA7EBFBF16B9AB45D9BEB2789990713D61CE01823569D7B5A34CDB4B9C0
+
+In = EA76A6E9F25F8B634F9997BDBDF34780D6D1E206C404D1ADF7DF45EA579D64E5EEC7D847FAA1423636CCE2823333E0BF7B2789F9968F997B45E3
+Out = EC7994335933794F14BFE62ED48841383B163AF4D916B10C60614D1796F06D37
+
+In = D73F2D890A180AE81922E250E43F13484EF5679BD5CF8BAAC362DEA4FE58F60CB9CB87802D72FAB4132C505695FA4E5E499B6D8F8CA5A13E57C508
+Out = 139508399C2B7AC0A49FF2B316443046860E7D932F21E7517CBBF6172542FDDF
+
+In = 970DD3B6376C81F6FC633F10C32A14F5CE0DEC000C4D47578C5E6EF7AEE8F31FDB3767D46E1376097193E1C030D8E1CCDDE953F8B0C1C78D5FA42FB8
+Out = A5674DE8D6BFFAA12D400C8846E8748CB13273C649779BAF62ED258A4792DC01
+
+In = 5506B56C3090990E3D33CF5E7AB66AD5A55CFED9E960D43CACA74437CBBEF28CF748F80A53F730E4B124B21D6C4823BD4BEF135CD33E8ABE6279A343EA
+Out = E76FAB992242DA701C8238FF19FF2681ED304BD846DF5CDC843BE66DCA51A5DA
+
+In = 7C72DED849BBEBAEB8E56854039DF5B4F8713840A992D4B4643EFF24F2A60573E7F89EAF10EFE903116A033F63A62017196DC27D189C55841C227795958F
+Out = 98E5DE57125A1DAB829FC0DE9CB014B60267F3A4AF412BEAA2417A7F9C5CCFEF
+
+In = AE4798B1AB6E006BE45ACC330BAA0FE66CB17164B18F169026FDDEFB16CAD07283C382008A0D7DEAF08266D07627B7FA34E1299280F07AD1142A988B2061F0
+Out = 75A55F359DBFDA6DE4750467C18EBC50BBA0F86C15AE146F00D2A319C16F1928
+
+In = 3B47876F88F7C4E7CE09F8BB35240915391CD5D335F12B40B3DA5E30EB504A196B484F864929C89793F93691AD4C062EE4861E811EF2C0C047266752BA43524D
+Out = 14609C054E038A8CB4F0886DE99B31307F2E707A072C674ABFA646161B6BFF63
+
+In = 293BA657B574043AFB815D8BAEB83B03499D61EE9229A32DB39A8DEB5EDEA3509D62CF54A15EFEFA68396940381B780410A53A1D742149729083BEB205BAD17205
+Out = 1A4E8DF414957FAC9338AD0031F77176CCCE4575F40D5EEB44C18BCE5A7AD812
+
+In = 087ECFD0DDE2F63A7246AAFE357D3168B810E47A07F8EEB24082B157CDEE2B8D86723F4DCF08047E1BC238C3E649808263312FC766DD0ED9346F07B91C5E8AA2856E
+Out = C446A79314DAB7D4E93C1A06DC561C1EDCE3DBD41A9216E745DB5CFB58B4BD10
+
+In = C06E7A4D50F1038D0CC42B915D6D500297DA6BAA9311A946B381DF248D5F1C9C4FFE52BA6C15F174D5A0365B193A8854C74616C4E2178E77A5286D86EA5E5E5F1D00FD
+Out = 0EE3A6C829C9A0A47D567B4ADD3224521AD9E2F3B7D5C1110A974C725F625B05
+
+In = 676C2841C4945535A4BE0407946507018FFD9A56A05D3CCEE17549038E5DF00366C7AAFFA9063547685F0A0D2D6BEE151D923DED73D06A7A468BF79D48B93694A513D973
+Out = 65B35BA31CBB29AD6BF5C885B3FA81C8E432BF4FC35B38B1031006113CEFD14E
+
+In = ECA5C2A10879DEA022D18594548871F3D55310A113FA9FBC303B7FCEE224AAB34628637E19DD4A0128D28418630E6BD5717EFACC1A944AEF9529D8B014FC8049A4FA5F6B28
+Out = 70D209943C26F74C32132F6C72B387CEB8C7375E67B214930A306B4ED71117C7
+
+In = 5FCA053E81D9D1165E2DCB05C61AF6DAEE510620D12CD359F55B91CF4D26A1FB5275E787E649F79040DD2E61FE42AB9E17403120921C62CA0BBA185DE631E9F0629F67499ADE
+Out = ABEB92AC392AC96787D04481026BEC5210C96A9CC9DB2735D7CCA73A53EB5D5C
+
+In = 897704D8AA9A96F684A999E6E04A4E00E13C363F0DBDC4866B4CEBBD0A9A181AF61FBC13B546135248BF78C4CC8DE88D297191489BD6D6D6E54BE31550EEA0B2A6FFDC78BE579D
+Out = AECC884DB001CA82ACB3E8568FE1934ABDCADF0ED4B76ED5F68600A0671A30BB
+
+In = 069E2C17B8A2B2C69979863A53D7C5A83CAE7F51CEE7B496D8D6E5628239B4FBDC9692B2B2CB7663C68290117BF15EFDA791654F9517FE08CD96814B3202324F9BBCD7AF76F408D4
+Out = 7B9F7E72E2DC21D382EF002EDA3404BB4707FA085B0F8C68142A31748B78C338
+
+In = 554B3377A960EDA40EFEA9FB9F97C68DA8D9B269036558D5C40CC1D386F57C2BEF45D07907B0D086BCA6CB13131E9C5439CAC1FC839D5A6E3C4132C5950DEF0DD075D38C62926BFF40
+Out = F3CD66A5AEC9E1896A988E2BF1FD24A7C394F987E70EDF2BF58D4BC988CB2C6F
+
+In = 5B63E62B236AAF438D7774F53B76AD569B670E6689537F51CA0AB7FE23E89283305718759AD4C588194E3B76366873ACED496FB763F0D77C2E3A544AA07F470D7A4023EC39C200FA52D8
+Out = 389D006116A6B368EA275B0152E7535B6C0D0ACC19FC9AA1F217BB76164A6747
+
+In = A827215DF69240B9FA27A5F0D01C81824725BB3B89AC58EAEF5658657FFA5157B3EE6AEFEE529F7A0EE4160F5BAEFEEFCB542DD8E96A43170B6E3BF3FBC5F41D6A00CB2C229790F801C86F
+Out = A622312F496564E08EDD2526C31D1232523BBE051BAF351CB08B829B4CFEC272
+
+In = 793F35FECF83366E0F252FF50B639F70988BD87441FE3F6A01F60DE59E2E331FA68E9E12C20D3918F4895392051D3958FE3248CD43BF298B7F417D6448E29A7EA96D7731B7E885E014374410
+Out = CDFDEE23FAD49434B697448122522CCEEE85ABD664B30D216E923FDA6BCE24BB
+
+In = C41419D5EED53E00812BB5FE549963C1E1DF6A6A9450767F37774FE604033BBC2DEE6348E2B2CA7E43697CCC45957EC27AA030A7C136FEB81DF63914CB0D38FDE7F1BE96009A993D62CBF27791
+Out = E65F755C8890D288E8B234D490B5063996DA0D9C47301D965F6EA87C7B1936D4
+
+In = 38A6136F07C7C11C99B2255A8E5DDF3E5C0825CFB4F9C5245E8CBE8EBFFABD28CAE44117F52CB704E6928B07D0EADEAA10684F8A3A9727D94D1232A4D448B65B793ED71ED666E6BB239E8A6FF8A4
+Out = 9B87FD77DACB93CF2FB316C78BDBC5E5CC7FC480718823CD16CC0CC527BAAC46
+
+In = 3326D34CA091609AF2C5174D0D08EB2DDF0B341DE4411D72BE44228CBEDEA4047CDC388800EE6A557F260DA19C23C016951970699D95D67CCFF825F7D5F9C140CF484BD6DDCA7E66AA8E8F3D7E0835
+Out = B0BB87B246AAD67CCCB9A306E4768BAD5F95E06F0E08A784B5A86DAB9BA52B02
+
+In = 3BAD194F1615792001AA4805F0328ECA6227AD785D6217285B9DC1CB79CA71E01E95BA91597781DF728F6DD4D115C1848FB8F3DCB367CDA35F17CB8EE897492F8FE067130B3B40B542D7929AFB4F08E3
+Out = B1F0065C655CDD4BC3CA68BDAE1194DF719A6ED45F299BB597C9FED006C36B87
+
+In = 23EBD4B1D86BBF9ED8E1648B7BDBC2EC8C2F82C64018335C5C76E2CF908B11EB9C6EB2758CD0CC73F215C5979334B810F51AE39BBDCAE98F8DE9753E65E1C80B7606F3FCDE32772A1603A4FDCD6FE3D109
+Out = 34745040DF3050620965DF4BAA159AD79F1BE50D93FD02C804C7CAB741B2AE8D
+
+In = E6E89AB035B35FD24D2EFD0465854F886539B8218D1F4614C9929D72EBFB33D574EC4B97AE51238C542570729DB8053BEC8BF770B63F5B3332B2BB5D3F6E3FD4A942804AE06B2E9850454A28BD9C8FD9D1A8
+Out = A93E25F37D70EFD4FE4E37754083EFC23AD924BB41E944CFC7BEFBB1D828B2D6
+
+In = 760CF0A6724676CF48CF494A4DD4B90040BF0622A3E3A6A315F587AF8856B7C5899CB5C91FE499A334134AD6578DDB71CC255E087756929A972D282661B93618DFDCC9335D8C91AEEB94C7AE1D778468CD25F0
+Out = 4E77A9EE0224B965103C9125D0684B5D98C6935ACD5644CAE9917E834F693F9A
+
+In = 1A687B6941E5CCF1292FE0EE45AA19429A5852B4C0CD8EA6074797DBBBE796DD694C4371F6BF1D8C73B6871A8B2E7C57525A3125BC7361E77581A7E27E6D38D925EBEB3DF8C46AD3F650F48C6CC7F80F2B368C17
+Out = 5B831CC26F5BBCC8B6D0A62DF829E8017DFD1773A80B138B5CA4D6565AC28D4C
+
+In = 18340BCB8BAEF6D990D90F5CFB9FEAD4E380897219AE35073BB1DB33F2653E58A0394DAC354DDCB8444C5DEB25844393EAD5EE25211E944B222E9AAF73D3A6275B1F7F31459F1E6FB55C64AAB1E482DD8C91FCD1C1
+Out = DD331C4E1982F2A115B8C516156363B1C58D453FC68593038F568A61375E40E2
+
+In = E8507672C6D566D62970EE499C67F5AC9C44FB3C5D577C78E8FBB12AB48458259765E8F2F6D0E7A343E2D20ABEA2B3DC094CD26379F73A79AF40EBAEB0304C01DA08F4BA2F682D48291C05C056617AD340B60581AF70
+Out = F211D53A0E2E172FC456F23396E3A631E1A153F179E28D06529ACA5C39CECA74
+
+In = A5E5D8F4CF5371C4702543F89FF7C1B46918288B5F06282D3E26489248B7B3E8135D9C71E9B2FA4436F004C45322DA8476454B9C350E1BC477ED575504997A768B30D8FFB16023241E9C6D200819D3D9558D0AF6D74211
+Out = 4DA2AB81C2245FCD196D7CBC7AC5BD262E11AC7B34ABB3B2E09A6534FD2A52D7
+
+In = 790168DA4356E71A50575F5629FB1BCE51EF4CE99E9CE9988AECEB1F1624662526A300A4EA3B68225C86BDD7AE48E2B09764E0E939A6120EC30B8563B20ABBACF42849E190A3483EA681A1910FAB84210DD9443331AE39D8
+Out = 727954B75AB7A1E4513B113E05055CF8A78940241E319D359B7A92A7C78EDA3A
+
+In = CD713C0D54E47C64AD36CF54769D87FC653E45B75622BD71AB444B8ADA3D247CF6DE7CBD68136B65FD7DCC46B829120C7D6EF12B416AA027C064F830342BD5426B91C4F4C6531779003F0F4A4850091A299C7B2D284D3CB84A
+Out = 52D52244B334667F16F8C4367C32E07B4B61D3CE1841CD0EC1128253BA225924
+
+In = A3786164B8B87A3D4A32D1CE5151341AB96068EE556E339E519C7C83CA19AAAA0577BB6502973F8F40CE87D6279F3384201FB7817075B92423BEB339043512C4FA94707CA823E3FF4EEFEC142EFF91838651679F198F2563E67F
+Out = F61822440C88CE3B83CE2372A2A4B201139A324E6E19EC8797667B13ABE18010
+
+In = FA6D2D40E0653597F75E394F45DC0B362B528CF2CC21A289FD280506A710E7CA844298F430CAF1E4E0F021742EEFCD301180A1D0A7A7FBC0DFD0DB8C660EFE9C833C6F1C9FF9B26EB4CE1BE198487FD5127D953F6003B431560AA2
+Out = 153419B335D6AB697EE165364803812D80617DDA1E4F053BAAEEA1FFBC148EA4
+
+In = 3050EE1DC8F4C9AE18E85BEBCF8DE0412B8905C1582C0864DBA61BB4BE0EC35792C7DE9C9DE93DDD2B36AA6919A5FD955871C3A47DC307BBD804DCEE613D55DB0953C0354FE2613072F0602E9633FF0920159A1E6364DC6F81DD07C5
+Out = 37F1D7184E1308664D81F076231E0ECED20D8D1E1AF28DCC26E38D24084821E1
+
+In = 27C57B7AF9E3D12BD0080589E341E17D3A6005AAF22374C94C851CCD54FC8D1C5214055491032D16123C3E13BD1EB14DF38DC775D04436AF6EC77FF523B893DF1FBA68F785E77DDEAB75AEBA9B246901975C213F8F8946F716C657C967
+Out = 7E5CDE6276BE0FDB98C230B2EA39A511FAC1B0CFD811A68D0F312AF05D3ADFE2
+
+In = 92CA69E867F9761D84CB348535AD0A256F51E3A883CB81F2CF0B98803C76C7F35F7C24F960653B133E151097CB7DCC7D2FE1C4B4B295C4B1AD09D22CFD6F46719C55C5D479FF883811EE80AB458F5A73D97B6B16A9052E02248BCCD04F46
+Out = EF177EBE105881BB17D3130A8F88883F1EE8C75B9843AA24955CCFFCECF35B4B
+
+In = AF577FE64CB9E83B8DB1213EB42E695361B09027FE028DAE2CAAD2053896884D10369EDA5C4E221115C306E2295845B84D37D416C24F48901CE10BA9AD9CB935182DD8C7C63E60A0C7B82A65A0C759A806A4B6F99B912F4334153A6C14850C
+Out = C43D14A7250B39E1E39E628ED7D5DBFB1C77818AD49F959B7A99266E55CA06EA
+
+In = D60684AD738ECEA11C36540BBC74B3C098BF0AC9D930708D09777F8D0BDAEAD29280DD0A547DFB173A499F27AB63B47BAC72A378ED7A08C7B8CE3241E559A49CE8FE8298BAAAC3D1DF3B12CB1976C850856798C9B5424F0E93F0E2EB808E018F
+Out = 37607B2655B0C134658E9C80063F875156DEDA87BFF4675200D3665CBEC59F44
+
+In = 57C98FCDC1C6C073F316CF07B4CEFB38F088E6CC29FD7504557DB22A711CD71776743E9F1174D205B7A28737515BDD8AD90A68F86663AD0CC32E7EA77B8BBAB2CD4555B2AC07C5550A4B3A9F6BD1A6CD4C88D309FED9434723B90E5F51C098FC59
+Out = 77E8C3F2FB95D755C575B43A86DC0B5E8D49F6DD72A79A47B0317207E92581F4
+
+In = 89D5D2F1C2906224E80D259AAF9CEB4E3EAF10B4FF871DFF0FD18699773B9C200DB8FA2AF9A1361363D6B588B56651F3FF05990BCC57E6975EE83FF5964AF4647F423A2D32BF65718A4291665B158613AF16F1F048D8F5872B350BC54640DA3BDF4C
+Out = 755CAB9ED51681C7E71795BFDB66015123F70A8F1190D4B41F3130AACE642CCC
+
+In = 23DE91FBD7311A58B821B5625C7D055194DC1E5000BE5D94178AD3FD67967941B5EAB62A6B0F17E9635FD5C818EE6A51206A9A98B4177BCE0ADBD3B9844F69C941D3941A9345CAFD5EFBBBE70C287A6CC3063F1F941ABE0229F4CE72E2BCCC4E59700C
+Out = 596FBFF31FF4E7163C27D3CD23D4CE7FC2A5192A22F3706F8727943FD7944E14
+
+In = 876DBCD4E797BA073549E370B4D5D8EBD74913E72006CD9763CAD301765D79236D876B168144C0FE621F1E80471CAEED2024758967FC653C859229824F73977E55F8CF0078E098191CD077E3EC744534965A9C8AC1A92E566CEC1125E397125B193A3AA2
+Out = 72F557042BA095FB1D73ECCBF2D2E70F1CEBADA211C513BC3AC52D2C0B356279
+
+In = D81C941C365CD3532572CAA53FAF31D7C1666FE0AE5AACAD7F69523386C6BF215E2AEA59297B82FACCBE4CADC22545D6BD882C8310D9DF274D1FDEC6060CE65A55303840FC7545900213B2B03032E6B1D0D8A35FAB6A47772F653D1AF8776705A5B4106CD8
+Out = 1D4B5DC2C54CF61381519D0B879E063D582A129DC5CFF9226C4F406E28A25047
+
+In = A841FFA8DC92FEE6791F624CC8C24D4B5F43E488EB555AC4932F8FAE7C9E66382968084C3C548C72164247EA3EEB3FBC6391DE092A100203FFA94854E494EFC102B1A8E2493F5DD501F25CE29096AC55AD85F44829E6636563EE6BE0A3831295AF5D09E0C37A
+Out = 4F8296D2E2E3EFCF851DB491B68595676FB52A022817F72A5092C7D7210FAD6B
+
+In = C4F0218C4E732A65DE55D513068ACA367B59CC77AC172159D10335B3B6B3CDAFC497B870E5C8124826F2E8DCD819FA9DAF5353CE8BFA06D0A3A51BE5926BC5B1C48A7F8DF8BE079DF93A5E31A83CEE77689A9BC6A182DED5B416AB132C80953F8686297D8F5E1A
+Out = 8961C85D32AEBA936958AC84D937155007A8A6C57FEC71E74D5150C28C08B511
+
+In = 7268F226B77B788B1D9117158BC9AFC8BADD165CDFA25B0BCA050BE6A571C043965D3C56D876A79EBCD2C4ACB35FF08C8EBED3EA56717AAB0D3D14542C478878CA5EAEBD216B35EE6D0ACF6DE10696AC58D54F073923FA94E431FADB572B840C6C713A90EF45A1E0
+Out = D50CBD42F2C915C3F295A920E22A0304E9752B8FB2595D92472599BD67D31DFF
+
+In = C73E0B4A4053AABDF1E29A65B09D022F1394277BB21E0CF1BD1F9459BC7FB3835FBA1C0B812E2867CCEF884231F2EA42D9F11A689A4AEA58FFE2C9A991F3BEF2E779CF10D7326A3177CF14BE3A607B86B4D57264DD6AE4A1E0984E520F286D865CC589AB8D56A85875
+Out = 16F36A7376AE6F436FC9B406E396E2ACA7B198C75278963F2356BA8250B8FA45
+
+In = 1A3800E5F2E087BD943B82F4A8E058078E08688112B90844DBC6862CDBCB5F94AE25F751222583EDDF91FAC7E07873CE903BF60B1F87EDE724FB000B532B556524B4F39BCC2F18050074F3E75A9ECA9E18746ADFC6606524969E78764BF6B00D9A6B151E51EE1C289D57
+Out = 9BF5C1147B6B51F1282F17DFCADF9A145183D59E7787D2B1B66880072354A545
+
+In = 7BE4EA6FC4B5657A402CF56600A531050C2F0399E24A7355A70D0DCEB2F7E9EA4D7B23EC4CF717ECDCA6128E823CFA294BF77EF1130496BD55C4218FFBB5C3A13F5697AC9F274E5C023D1681C5EAA49D4242EF1C09E24BA809657AC70F14B7BE3CDAAA1F9C086629C8ED33
+Out = 8E5FACB215D8CDA215F92E89837436A599781E4A4CF8969E01F60855E7FD0636
+
+In = 53D2469D8AB1BACCBC356941D1E46B57B619256DFED64CFC57FC8C0741E402C83F7D8423F216C92D16653403373FC1BADADD248E2FB09DA4ED919EAE75A87E4A2EEBE143C12CCC1122AAAB91CD1BA00CD2E767F1372B2201A163678DAB11C688DA47EB4E0CBA81EFEDFD7978
+Out = C22C82136ACA63FAA9E94057DF45AC1F1E0A42B76ACA0C09A1391A1109AAE1F1
+
+In = 9AC84800C6414AD40047F215B244AE0080DBE0AD6D7DF75C0080EAD0B02F2FA06649F7DBADDA4ACBA223A097BFCBF2040E13886C1733D5827D6FEAE5DE7A60498AB0DE5BACF4DB7BFEE612440903B91B66D836D643780AF9CB6A703EADD3D9B1C66E0DB2832EECBD892D86901A
+Out = BB99E1ADACB814E5A6515001EDCF2444851B2DAB7EE9BAAD7C7A6D47EC8C3AB7
+
+In = 56504F109A5E577010EB5E98C6558E231943E0CFA32C0B2B0F3C2CD6A0054A2B9E9D75FA68877767DACED55851447271F3AF2CCB686F129CBEAD4C293E20C00D52FD75D1F99B19C124C24D455526FE1DF9F9D219FCFA92972CD38C83A8138874B7366662F94C0BBE5D9B8365B9FB
+Out = EC6C767C53B9B5184D548507B866BE140107590733D8E7056607D9199479731E
+
+In = 56BD9CA50966C8DC38740BACAC77464870C10129F70AE0E6555BA1D10118BD050260C51AE20204BE89E89AE584B7B0BD1C21F31B009298B516284BCD34C792735AE5B16FBE392D85AF6528B6F262087B122BF7DA5BE633415934AFC4BD492A6B5603AB3FA58944C6B65D327799E879
+Out = D80BF63CF3F88309D76BEE0DCFF42E09C6AF9A750DF7328DF23CD93ED6CF40ED
+
+In = 9E6683645A4134573220706F51BC6FDBB0F68AC43CA634992ECE5AF9C8C25686456945FDABD1796FD541576D4A7399B1048548E43354381F170038838EDD5E65225F0F0D3D286B1BE618B4F55F4A7B7E549FFB1025FD6D5C1591678F8EC70F45F1A7C4EE6611169DDB2D04B9532F207E
+Out = D8CC725D6A64608D317D677560488645603C8393F46C4DA329D7DAE6B496ADCA
+
+In = 5D96BE06103AE7DB1A3FFEB6FD3A36767A75ABBC12A2054FCE11F0FDAFFF02A860D2E70633E37CBC7A5A2245A44850928D23278A2C77623E5E600C3317B04C7534AC373B557FD23BA7482CD984283DD8122D21AAD43B0297950677CE46AED23151C5434908AA4452354810376B4B7F7B08
+Out = D31D217A9D2529F9ED1447D0EF3299C1779D31569D9D05FDF5B3513FEA6CE77E
+
+In = D985F6C0066654A39B02E59F699FBBC50FF748C08F6850EC5BF14133E7A4620FE28FE422BD9889139C1C9AC2650680631B22B68BD034D93980B65AC4E5EBB07CF5100C9728FFCC0FF6EEA69A676E4BDD0017A24771EA83661952ABF4E1D0E3F7F24B7862DD9D1AAAD3D24DC05914DF864C89
+Out = F1DBA5717F9C7B691170F1E231FC99FFA4E104AC58B9BF0FAEC98DEE31CBC939
+
+In = B548C6F1220F0FA73D3ED439C1432F60A4E46AB6F83D926DC946D4C252470391EC2B44D9F1436B2C9B55F20238576020D95352180A94D6040204A74378219346A849685B7BC28BD164595E2C97329DD59631119CBB9E1D323BB1A83F7ACF06F802659D1393485A7341AD04799E06B7814D0A81
+Out = 18B70142489C3C3558B779E0D4CDA50350EBB1B143568A2D4F9501B0F9DC8F12
+
+In = B60732DCFEA1FDC4149F277D7025BD5884C47283B7FCA241AC21E217D7DEB491F94F53D629FDB6DC61302F3B7CD14AA7FD91B9E703447B42395D82322E2E4F176C6E83F0924886A2EF0CCD14CFADDA53F2ABA7918E8A4C8DBD3F8075648B508F2C241C15F5177DD5ACBC4D12EE4002D236267482
+Out = 9FF5DE03F07CA1F14F9DAE20AEB83F1BC68C062F20BB71F3CBF710080EF1D1B8
+
+In = 89E1B7A0B3BDEDBDBEC67E260681DBCF2AFCF814565A955604EFFF8D00409537FBC4077399F7626C11B342269A0B4B70BEFF1C496D7268F51AF61586F179FA59B6A31FF530F3C72A7E35CA78C626C196B4F49553B7C87DFD0D6AECC7A10DCF535DCEC1A63440765429294EF344EE49B68440B1BA3B
+Out = 77724AB3BA98A411D4BDEA831E74FA65455367FCF893511B46DEB8B69528E010
+
+In = 9919ED7C116A6B2295385CC53914134CEC53A09EE205C52E5BC7AAE85CDFB1E5B901B1FE3E5A4B260C826CDDC7603F050CC717C4831AF65E3D6DF0B72D5D4DC19137E8C1EA1952B62CA0FD0924D5BD4C875BE68EBA59672D28F38667B612C035C60C963F989104356B237E2478667DC09EB85DC50CEF
+Out = 9579CBB4CC270B4833D0D2D5A8CEED5B2A9BA197ED3925CBACEC39B8FFE88EB2
+
+In = FDE621E8F6C28A3116D051DDDE0CE49D951FDB32C699C794D272E2544034530D16660797BD9A2DD041AA1A52C88667C56E1972973689505216149814F8097CCE392831B4F00D104837B22751FCC1B492F0F946D30C329D77E985F1D8AD2523489E980CFA25ABD4CEE8404262AC0BFDAE59495AF51DE394
+Out = 84BC7E5CC1CD2451C1F4006423DE65348FF516CA234D3E1DB5974F2CACEEA7F3
+
+In = 0BD9B05363D85A8C29335B7A0FC8775A14E4B3D318A07020C1760405FED790DA50429BCD4107C316F52707603AF7E7283CFCCA0F5D7E265B53CC1899AF5C2386A8F3D30A476289255EB3A8504423E8F9AFD46B71DAD21BBFFD6CDF0F7C37FF811805F9E9F727966AB279BEC9124384EE12E91556135AC64B
+Out = 0F25EB2A310B897D9FE5296E86FB54CA90A24A33C2350F7214871A76D83ACDB7
+
+In = E01B90E74C37529AE3630977BB67D135CD40BB856EF72B5ACF2CB1779CB4466B7EE622FAA605D184A599F8EAFFA1A4B66FA82F0F1CF3B6E8D61BE885B346E6FBD0A7D3AB9001D5D092B4769149987DE7AA07783E33C0BCA6E04F2D51B06CB8D10FA1C6F8189E9F168F8BD1D179E736E089330D999DD1DE1804
+Out = 2B202A19499AEB7EC32887183974BA38D222F1DDDC1957E891C7637866C6D02B
+
+In = 69DE25ED8B06C25730DE7D4F0F0B721418F7DA3FFD0FED184D89EC7CC68C2FFF7BBA7328D5646BA5E1DE9A10C7D8C48738500684F1C37F3F5627085F9C532F3369C79BC20D8FC4EEA6098EEFE809CE2FABE6815A73AD5BC596BCA47229F15915138AF98EBE1FD7A9DBF47E9CFA4236B8158187C8C7D6B0AA413A
+Out = 8E1578C57746970BBCF5208FED44A07297407A3B88050C9C1B2AA4DFBC371BB3
+
+In = EF8E3CE9E94140F5F23BDF1571A99524ABBC97559C04C758AC7D38B2461CEEB8B9526069866D4DEBC20451CA7BABE6938B619A7231C1E27AF42AA0DEB7533E08E768029BCD14F8E26354D672AE6633D75BCA0B96AEFBE1E553E3D27A77BF97B0B5DFE7801FCC98552A97E2A7CA6BFF07A7DCAD0B8758E00BE9C9B6
+Out = 191951344B69CBAB81A8C5161683D523959547443C7D991370E602E89C657D65
+
+In = C6BA237FF92B7017164B862F6423F427A2F7FC6B9E08DB177AE8A0F525B96A5F8E6D3CEC815FD0BC67082BD87EE4BE865D207344F75E14BAB8370CBFF15535FE08BF69ADDD46D483CA0BFE3407D067885722A644346D401811827F6FF66BF32B7BFE7FFCEA9ABC33D0EDC38183FDE134EEFA3E7F35EDCD8CD96ED598
+Out = D49655944CF84E2C736CAA721990D87EC4A206D97697A6E69317C60CFE2FF880
+
+In = 94A5B0B0884EC2A5B6EF06867FF449A256A905EC5353C2DDE56722C1020E4B7A6C2AE6FB81907A8EA4A48FB1B5CD5821446F561488AFECDE2DE4980CF60DE4C4E8BDA2E3B09FEC46592134131BE45B4105DDF7857BB793B94F7D58AD27D1856048F0896846791E17DBB050AA0B623884666EE13D2A0BED0963E054738E
+Out = 7715F423CB25126E8F60A84860D8E38D5A6DD405CEA7B87928A855FA0CCD413A
+
+In = 04FAC7EC9EE4765731C4373BA10AB30E61902FC70B6EBF653BD1396157C05CCAFC821928706BBC0346E750FBA1C37C4B5B930EF70967C621B786DA91055AD6D8A90E374D27CC65A830BFBB7346D3F6BADE676D690394AF5D02588B48C9482F651F0A4C9154A93B166F4B75F867AF9DD34A943BD268A69456F4753F24368C
+Out = 32F8C89FF99FC942BEBC45EEF397B2E6957CB87A20887C8576FB1574C509956F
+
+In = 16488821759E6757A19CBBDAD74E956C576E55B76D6C652C8AB1683591E53845BD8943E6C63EE98F3735624D51975240B86043B36E904267A79679F685E1924CDB8C49700722E8B360F83B2747D00B982C568488EAB5AD9D2860F20750EE11BAEBBE116EBEAB2BA4DC12B21875019D29E78673404E6C5B2CF0174F93C41255
+Out = 9131972A3CDEAADD1BF73F449F89DC1BC8B0DFFFA75FF6D32824C52695A39EFA
+
+In = 075D68D52224EE85A0F029E116C1894B0C673DED797F803EA298163D316C6B59C9584A0203D08F5F79F36891FABF8430CF9212C02FB2A287DEC3DDC772003167909D68E912DE0192817C085A6FB729ACCADB2ACAB6D5E91ABEB92F4CE68123DCD4FAD9F6ED80515142EF1081981A6C2D62B1630EEF02690DCC71F120E661DCD1
+Out = C00F6356A020B716EF4BB1C89C82BF7CE6E5DD167BFBF2C81AC5DF42217DC3FD
+
diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp
index 5fc20e3d7..e7cd9c18c 100644
--- a/src/tests/test_x509_path.cpp
+++ b/src/tests/test_x509_path.cpp
@@ -240,6 +240,84 @@ std::vector<Test::Result> NIST_Path_Validation_Tests::run()
BOTAN_REGISTER_TEST("x509_path_nist", NIST_Path_Validation_Tests);
+class Extended_Path_Validation_Tests : public Test
+ {
+ public:
+ std::vector<Test::Result> run() override;
+ };
+
+std::vector<Test::Result> Extended_Path_Validation_Tests::run()
+ {
+ std::vector<Test::Result> results;
+
+ const std::string extended_x509_test_dir = Test::data_dir() + "/extended_x509";
+
+ try
+ {
+ // Do nothing, just test filesystem access
+ Botan::get_files_recursive(extended_x509_test_dir);
+ }
+ catch(Botan::No_Filesystem_Access&)
+ {
+ Test::Result result("Extended x509 path validation");
+ result.test_note("Skipping due to missing filesystem access");
+ results.push_back(result);
+ return results;
+ }
+
+ std::map<std::string, std::string> expected =
+ read_results(Test::data_file("extended_x509/expected.txt"));
+
+ for(auto i = expected.begin(); i != expected.end(); ++i)
+ {
+ const std::string test_name = i->first;
+ const std::string expected_result = i->second;
+
+ const std::string test_dir = extended_x509_test_dir + "/" + test_name;
+
+ Test::Result result("Extended X509 path validation");
+ result.start_timer();
+
+ const std::vector<std::string> all_files = Botan::get_files_recursive(test_dir);
+
+ if(all_files.empty())
+ {
+ result.test_failure("No test files found in " + test_dir);
+ results.push_back(result);
+ continue;
+ }
+
+ Botan::Certificate_Store_In_Memory store;
+
+ for(auto const& file : all_files)
+ {
+ if(file.find(".crt") != std::string::npos && file != "end.crt")
+ {
+ store.add_certificate(Botan::X509_Certificate(file));
+ }
+ }
+
+ Botan::X509_Certificate end_user(test_dir + "/end.crt");
+
+ Botan::Path_Validation_Restrictions restrictions;
+ Botan::Path_Validation_Result validation_result =
+ Botan::x509_path_validate(end_user,
+ restrictions,
+ store);
+
+ result.test_eq(test_name + " path validation result",
+ validation_result.result_string(),
+ expected_result);
+
+ result.end_timer();
+ results.push_back(result);
+ }
+
+ return results;
+ }
+
+BOTAN_REGISTER_TEST("x509_path_extended", Extended_Path_Validation_Tests);
+
#endif
}
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index 1886aa122..8f8aeec82 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -887,19 +887,26 @@ std::vector<Botan::CPUID::CPUID_bits> map_cpuid_string(const std::string& tok)
return {Botan::CPUID::CPUID_AVX2_BIT};
if(tok == "sha")
return {Botan::CPUID::CPUID_SHA_BIT};
-#endif
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
if(tok == "altivec" || tok == "simd")
return {Botan::CPUID::CPUID_ALTIVEC_BIT};
-#endif
-#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
if(tok == "neon" || tok == "simd")
return {Botan::CPUID::CPUID_ARM_NEON_BIT};
-#endif
-
+ if(tok == "armv8sha1")
+ return {Botan::CPUID::CPUID_ARM_SHA1_BIT};
+ if(tok == "armv8sha2")
+ return {Botan::CPUID::CPUID_ARM_SHA2_BIT};
+ if(tok == "armv8aes")
+ return {Botan::CPUID::CPUID_ARM_AES_BIT};
+ if(tok == "armv8pmull")
+ return {Botan::CPUID::CPUID_ARM_PMULL_BIT};
+
+#else
BOTAN_UNUSED(tok);
+#endif
return {};
}