diff options
author | Jack Lloyd <[email protected]> | 2019-10-25 05:31:06 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2019-10-25 05:31:06 -0400 |
commit | cc3caa20974e30b145a5e16135f85bf8a76a2233 (patch) | |
tree | 661ad6080317cb4b60f00eea282021255c952c73 | |
parent | fbbb4c211620e00b7c681a2281f815138a2024bd (diff) | |
parent | a7b7fa47c7173b1c9e145cffe0ad1cbbc816f355 (diff) |
Merge GH #2172 Add support for XMSS X.509 certs
-rw-r--r-- | src/build-data/oids.txt | 8 | ||||
-rw-r--r-- | src/lib/asn1/oid_maps.cpp | 8 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_parameters.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_privatekey.cpp | 30 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_privatekey.h | 1 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_publickey.cpp | 36 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_publickey.h | 32 | ||||
-rw-r--r-- | src/lib/x509/x509_dn_ub.cpp | 2 | ||||
-rw-r--r-- | src/lib/x509/x509_obj.cpp | 12 | ||||
-rwxr-xr-x | src/scripts/oids.py | 2 | ||||
-rwxr-xr-x | src/scripts/test_cli.py | 10 | ||||
-rw-r--r-- | src/tests/data/x509/xmss/xmss_bouncycastle_sha256_10_root.pem | 64 | ||||
-rw-r--r-- | src/tests/data/x509/xmss/xmss_isara_root.pem | 71 | ||||
-rw-r--r-- | src/tests/test_x509_path.cpp | 48 |
14 files changed, 286 insertions, 40 deletions
diff --git a/src/build-data/oids.txt b/src/build-data/oids.txt index 063f52069..03ce80a84 100644 --- a/src/build-data/oids.txt +++ b/src/build-data/oids.txt @@ -13,10 +13,14 @@ 1.3.6.1.4.1.3029.1.2.1 = ElGamal 1.3.6.1.4.1.25258.1.3 = McEliece 1.3.101.110 = Curve25519 -1.3.6.1.4.1.25258.1.5 = XMSS-draft6 -1.3.6.1.4.1.25258.1.8 = XMSS 1.3.101.112 = Ed25519 +# XMSS +1.3.6.1.4.1.25258.1.5 = XMSS-draft6 +1.3.6.1.4.1.25258.1.8 = XMSS-draft12 +# draft-vangeest-x509-hash-sigs-03 +0.4.0.127.0.15.1.1.13.0 = XMSS + # X9.62 ecPublicKey, valid for ECDSA and ECDH (RFC 3279 sec 2.3.5) 1.2.840.10045.2.1 = ECDSA 1.3.132.1.12 = ECDH diff --git a/src/lib/asn1/oid_maps.cpp b/src/lib/asn1/oid_maps.cpp index 47d418271..d385dfd84 100644 --- a/src/lib/asn1/oid_maps.cpp +++ b/src/lib/asn1/oid_maps.cpp @@ -1,7 +1,7 @@ /* * OID maps * -* This file was automatically generated by ./src/scripts/oids.py on 2019-08-03 +* This file was automatically generated by ./src/scripts/oids.py on 2019-10-21 * * All manual edits to this file will be lost. Edit the script * then regenerate this source file. @@ -20,6 +20,7 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map() { "0.3.4401.5.3.1.9.26", "Camellia-192/GCM" }, { "0.3.4401.5.3.1.9.46", "Camellia-256/GCM" }, { "0.3.4401.5.3.1.9.6", "Camellia-128/GCM" }, + { "0.4.0.127.0.15.1.1.13.0", "XMSS" }, { "1.0.14888.3.0.5", "ECKCDSA" }, { "1.2.156.10197.1.104.100", "SM4/OCB" }, { "1.2.156.10197.1.104.2", "SM4/CBC" }, @@ -141,7 +142,7 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map() { "1.3.6.1.4.1.25258.1.3", "McEliece" }, { "1.3.6.1.4.1.25258.1.5", "XMSS-draft6" }, { "1.3.6.1.4.1.25258.1.6.1", "GOST-34.10-2012-256/EMSA1(SHA-256)" }, - { "1.3.6.1.4.1.25258.1.8", "XMSS" }, + { "1.3.6.1.4.1.25258.1.8", "XMSS-draft12" }, { "1.3.6.1.4.1.25258.3.1", "Serpent/CBC" }, { "1.3.6.1.4.1.25258.3.101", "Serpent/GCM" }, { "1.3.6.1.4.1.25258.3.102", "Twofish/GCM" }, @@ -470,7 +471,8 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map() { "X520.StreetAddress", OID({2,5,4,9}) }, { "X520.Surname", OID({2,5,4,4}) }, { "X520.Title", OID({2,5,4,12}) }, - { "XMSS", OID({1,3,6,1,4,1,25258,1,8}) }, + { "XMSS", OID({0,4,0,127,0,15,1,1,13,0}) }, + { "XMSS-draft12", OID({1,3,6,1,4,1,25258,1,8}) }, { "XMSS-draft6", OID({1,3,6,1,4,1,25258,1,5}) }, { "brainpool160r1", OID({1,3,36,3,3,2,8,1,1,1}) }, { "brainpool192r1", OID({1,3,36,3,3,2,8,1,1,3}) }, diff --git a/src/lib/pubkey/xmss/xmss_parameters.cpp b/src/lib/pubkey/xmss/xmss_parameters.cpp index 933072da6..0654821fd 100644 --- a/src/lib/pubkey/xmss/xmss_parameters.cpp +++ b/src/lib/pubkey/xmss/xmss_parameters.cpp @@ -176,7 +176,7 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid) m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE_512; break; default: - throw Not_Implemented("Algorithm id does not match any known XMSS algorithm id."); + throw Not_Implemented("Algorithm id does not match any known XMSS algorithm id:" + std::to_string(oid)); break; } } diff --git a/src/lib/pubkey/xmss/xmss_privatekey.cpp b/src/lib/pubkey/xmss/xmss_privatekey.cpp index d4a353d3c..6a728ac72 100644 --- a/src/lib/pubkey/xmss/xmss_privatekey.cpp +++ b/src/lib/pubkey/xmss/xmss_privatekey.cpp @@ -17,6 +17,7 @@ #include <botan/xmss_privatekey.h> #include <botan/internal/xmss_signature_operation.h> +#include <botan/ber_dec.h> #if defined(BOTAN_HAS_THREAD_UTILS) #include <botan/internal/thread_pool.h> @@ -24,8 +25,27 @@ namespace Botan { -XMSS_PrivateKey::XMSS_PrivateKey(const secure_vector<uint8_t>& raw_key) - : XMSS_PublicKey(unlock(raw_key)), +namespace { + +// fall back to raw decoding for previous versions, which did not encode an OCTET STRING +secure_vector<uint8_t> extract_raw_key(const secure_vector<uint8_t>& key_bits) +{ + secure_vector<uint8_t> raw_key; + try + { + BER_Decoder(key_bits).decode(raw_key, OCTET_STRING); + } + catch(Decoding_Error& e) + { + raw_key = key_bits; + } + return raw_key; +} + +} + +XMSS_PrivateKey::XMSS_PrivateKey(const secure_vector<uint8_t>& key_bits) + : XMSS_PublicKey(unlock(key_bits)), XMSS_Common_Ops(XMSS_PublicKey::m_xmss_params.oid()), m_wots_priv_key(m_wots_params.oid(), m_public_seed), m_index_reg(XMSS_Index_Registry::get_instance()) @@ -40,12 +60,14 @@ XMSS_PrivateKey::XMSS_PrivateKey(const secure_vector<uint8_t>& raw_key) */ static_assert(sizeof(size_t) >= 4, "size_t is big enough to support leaf index"); + secure_vector<uint8_t> raw_key = extract_raw_key(key_bits); + if(raw_key.size() != XMSS_PrivateKey::size()) { - throw Decoding_Error("Invalid XMSS private key size detected."); + throw Decoding_Error("Invalid XMSS private key size"); } - // extract & copy unused leaf index from raw_key. + // extract & copy unused leaf index from raw_key uint64_t unused_leaf = 0; auto begin = (raw_key.begin() + XMSS_PublicKey::size()); auto end = raw_key.begin() + XMSS_PublicKey::size() + sizeof(uint32_t); diff --git a/src/lib/pubkey/xmss/xmss_privatekey.h b/src/lib/pubkey/xmss/xmss_privatekey.h index 2bfcbc82e..301fef04b 100644 --- a/src/lib/pubkey/xmss/xmss_privatekey.h +++ b/src/lib/pubkey/xmss/xmss_privatekey.h @@ -202,6 +202,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PrivateKey final : public virtual XMSS_PublicKe secure_vector<uint8_t> private_key_bits() const override { + return DER_Encoder().encode(raw_private_key(), OCTET_STRING).get_contents(); return raw_private_key(); } diff --git a/src/lib/pubkey/xmss/xmss_publickey.cpp b/src/lib/pubkey/xmss/xmss_publickey.cpp index 7c7c19fc1..43f7417cf 100644 --- a/src/lib/pubkey/xmss/xmss_publickey.cpp +++ b/src/lib/pubkey/xmss/xmss_publickey.cpp @@ -16,26 +16,48 @@ #include <botan/internal/xmss_verification_operation.h> #include <botan/xmss_publickey.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> namespace Botan { -XMSS_PublicKey::XMSS_PublicKey(const std::vector<uint8_t>& raw_key) - : m_xmss_params(XMSS_PublicKey::deserialize_xmss_oid(raw_key)), +namespace { + +// fall back to raw decoding for previous versions, which did not encode an OCTET STRING +std::vector<uint8_t> extract_raw_key(const std::vector<uint8_t>& key_bits) +{ + std::vector<uint8_t> raw_key; + try + { + BER_Decoder(key_bits).decode(raw_key, OCTET_STRING); + } + catch(Decoding_Error& e) + { + raw_key = key_bits; + } + return raw_key; +} + +} + +XMSS_PublicKey::XMSS_PublicKey(const std::vector<uint8_t>& key_bits) + : m_raw_key(extract_raw_key(key_bits)), + m_xmss_params(XMSS_PublicKey::deserialize_xmss_oid(m_raw_key)), m_wots_params(m_xmss_params.ots_oid()) { - if(raw_key.size() < XMSS_PublicKey::size()) + if(m_raw_key.size() < XMSS_PublicKey::size()) { - throw Decoding_Error("Invalid XMSS public key size detected."); + throw Decoding_Error("Invalid XMSS public key size detected"); } - // extract & copy root from raw key. + // extract & copy root from raw key m_root.clear(); m_root.reserve(m_xmss_params.element_size()); - auto begin = raw_key.begin() + sizeof(uint32_t); + auto begin = m_raw_key.begin() + sizeof(uint32_t); auto end = begin + m_xmss_params.element_size(); std::copy(begin, end, std::back_inserter(m_root)); - // extract & copy public seed from raw key. + // extract & copy public seed from raw key begin = end; end = begin + m_xmss_params.element_size(); m_public_seed.clear(); diff --git a/src/lib/pubkey/xmss/xmss_publickey.h b/src/lib/pubkey/xmss/xmss_publickey.h index ff56c1378..e055d3a3a 100644 --- a/src/lib/pubkey/xmss/xmss_publickey.h +++ b/src/lib/pubkey/xmss/xmss_publickey.h @@ -1,6 +1,7 @@ /* * XMSS Public Key * (C) 2016,2017 Matthias Gierlings + * (C) 2019 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) **/ @@ -29,8 +30,6 @@ class XMSS_Verification_Operation; /** * An XMSS: Extended Hash-Based Signature public key. - * The XMSS public key does not support the X509 standard. Instead the - * raw format described in [1] is used. * * [1] XMSS: Extended Hash-Based Signatures, * Request for Comments: 8391 @@ -56,10 +55,14 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key m_public_seed(rng.random_vec(m_xmss_params.element_size())) {} /** - * Creates an XMSS public key from a byte sequence produced by - * raw_private_key(). - **/ - XMSS_PublicKey(const std::vector<uint8_t>& raw_key); + * Loads a public key. + * + * Public key must be encoded as in RFC + * draft-vangeest-x509-hash-sigs-03. + * + * @param key_bits DER encoded public key bits + */ + XMSS_PublicKey(const std::vector<uint8_t>& key_bits); /** * Creates a new XMSS public key for a chosen XMSS signature method as @@ -121,7 +124,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key /** * Retrieves the Winternitz One Time Signature (WOTS) method, - * corrseponding to the chosen XMSS signature method. + * corresponding to the chosen XMSS signature method. * * @return XMSS WOTS signature method identifier. **/ @@ -188,7 +191,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key AlgorithmIdentifier algorithm_identifier() const override { - return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_NULL_PARAM); + return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM); } bool check_key(RandomNumberGenerator&, bool) const override @@ -211,14 +214,16 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key } /** - * Returns a raw byte sequence as defined in [1]. - * This method acts as an alias for raw_public_key(). + * Returns the encoded public key as defined in RFC + * draft-vangeest-x509-hash-sigs-03. * - * @return raw public key bits. + * @return encoded public key bits **/ std::vector<uint8_t> public_key_bits() const override { - return raw_public_key(); + std::vector<uint8_t> output; + DER_Encoder(output).encode(raw_public_key(), OCTET_STRING); + return output; } /** @@ -233,7 +238,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key } /** - * Generates a non standardized byte sequence representing the XMSS + * Generates a byte sequence representing the XMSS * public key, as defined in [1] (p. 23, "XMSS Public Key") * * @return 4-byte OID, followed by n-byte root node, followed by @@ -242,6 +247,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key virtual std::vector<uint8_t> raw_public_key() const; protected: + std::vector<uint8_t> m_raw_key; XMSS_Parameters m_xmss_params; XMSS_WOTS_Parameters m_wots_params; secure_vector<uint8_t> m_root; diff --git a/src/lib/x509/x509_dn_ub.cpp b/src/lib/x509/x509_dn_ub.cpp index d8663124e..d41168b95 100644 --- a/src/lib/x509/x509_dn_ub.cpp +++ b/src/lib/x509/x509_dn_ub.cpp @@ -1,7 +1,7 @@ /* * DN_UB maps: Upper bounds on the length of DN strings * -* This file was automatically generated by ./src/scripts/oids.py on 2019-08-04 +* This file was automatically generated by ./src/scripts/oids.py on 2019-10-21 * * All manual edits to this file will be lost. Edit the script * then regenerate this source file. diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp index e6767ea98..644a1ca5e 100644 --- a/src/lib/x509/x509_obj.cpp +++ b/src/lib/x509/x509_obj.cpp @@ -192,7 +192,7 @@ Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) std::string padding; if(sig_info.size() == 2) padding = sig_info[1]; - else if(sig_info[0] == "Ed25519") + else if(sig_info[0] == "Ed25519" || sig_info[0] == "XMSS") padding = "Pure"; else return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; @@ -313,6 +313,16 @@ std::string choose_sig_algo(AlgorithmIdentifier& sig_algo, { padding = "Pure"; } + else if(algo_name == "XMSS") + { + if(user_specified.empty() == true) + { + throw Invalid_Argument("XMSS requires padding scheme"); + } + padding = user_specified; + sig_algo = AlgorithmIdentifier(OID::from_string("XMSS"), AlgorithmIdentifier::USE_EMPTY_PARAM); + return padding; + } else { throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name); diff --git a/src/scripts/oids.py b/src/scripts/oids.py index 7036dbab6..323b6efb5 100755 --- a/src/scripts/oids.py +++ b/src/scripts/oids.py @@ -256,7 +256,7 @@ bool sig_algo_and_pad_ok(const std::string algo, std::string padding) def main(args = None): - """ Print header files (oids.cpp, dn_ub.cpp) depending on the first argument and on srs/build-data/oids.txt + """ Print header files (oids.cpp, dn_ub.cpp) depending on the first argument and on src/build-data/oids.txt Choose 'oids' to print oids.cpp, needs to be written to src/lib/asn1/oids.cpp Choose 'dn_ub' to print dn_ub.cpp, needs to be written to src/lib/x509/X509_dn_ub.cpp diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py index c0f8677d1..e4da5a898 100755 --- a/src/scripts/test_cli.py +++ b/src/scripts/test_cli.py @@ -361,27 +361,27 @@ def cli_xmss_sign_tests(tmp_dir): test_cli("hash", ["--no-fsname", msg], "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855") test_cli("keygen", ["--algo=XMSS", "--output=%s" % (priv_key)], "") - test_cli("hash", ["--no-fsname", priv_key], "32397312E3FAC9D6396C55FEEFFF11EE195E2D2D5B34279D2544AF27763B0946") + test_cli("hash", ["--no-fsname", priv_key], "5B38F737BA41BE7F40433DB30EAEF7C41ABB0F7D9E7A09DEB5FDCE7B6811693F") test_cli("pkcs8", "--pub-out --output=%s %s" % (pub_key, priv_key), "") test_cli("fingerprint", ['--no-fsname', pub_key], - "E2:BE:C8:6D:CF:4B:5D:67:AB:A1:C1:F8:36:79:D5:3B:D8:17:D5:E3:5B:BE:29:08:03:7E:6E:07:27:4E:16:46") + "B0:F4:98:6E:D8:4E:05:63:A1:D8:4B:37:61:5A:A0:41:78:7E:DE:0E:72:46:E0:A8:D6:CF:09:54:08:DA:A4:22") # verify the key is updated after each signature: test_cli("sign", [priv_key, msg, "--output=%s" % (sig1)], "") test_cli("verify", [pub_key, msg, sig1], "Signature is valid") test_cli("hash", ["--no-fsname", sig1], "04AF45451C7A9AF2D828E1AD6EC262E012436F4087C5DA6F32C689D781E597D0") - test_cli("hash", ["--no-fsname", priv_key], "649E54D334F78A6AAAE34CFABF62121C74909D80E4DC2FA240A6EE1848526094") + test_cli("hash", ["--no-fsname", priv_key], "67929FAEC636E43DE828C1CD7E2D11CE7C3388CE90DD0A0F687C6627FFA850CD") test_cli("sign", [priv_key, msg, "--output=%s" % (sig2)], "") test_cli("verify", [pub_key, msg, sig2], "Signature is valid") test_cli("hash", ["--no-fsname", sig2], "0785A6AD54CC7D01F2BE2BC6463A3EAA1159792E52210ED754992C5068E8F24F") - test_cli("hash", ["--no-fsname", priv_key], "04483FA5367A7340F4BF6160FABD5742258009E05F9584E8D9732660B132608E") + test_cli("hash", ["--no-fsname", priv_key], "1940945D68B1CF54D79E05DD7913A4D0B4959183F1E12B81A4E43EF4E63FBD20") # private key updates, public key is unchanged: test_cli("pkcs8", "--pub-out --output=%s %s" % (pub_key2, priv_key), "") test_cli("fingerprint", ['--no-fsname', pub_key2], - "E2:BE:C8:6D:CF:4B:5D:67:AB:A1:C1:F8:36:79:D5:3B:D8:17:D5:E3:5B:BE:29:08:03:7E:6E:07:27:4E:16:46") + "B0:F4:98:6E:D8:4E:05:63:A1:D8:4B:37:61:5A:A0:41:78:7E:DE:0E:72:46:E0:A8:D6:CF:09:54:08:DA:A4:22") def cli_pbkdf_tune_tests(_tmp_dir): if not check_for_command("pbkdf_tune"): diff --git a/src/tests/data/x509/xmss/xmss_bouncycastle_sha256_10_root.pem b/src/tests/data/x509/xmss/xmss_bouncycastle_sha256_10_root.pem new file mode 100644 index 000000000..24db08b86 --- /dev/null +++ b/src/tests/data/x509/xmss/xmss_bouncycastle_sha256_10_root.pem @@ -0,0 +1,64 @@ +-----BEGIN CERTIFICATE----- +MIILizCCAbGgAwIBAgIBATALBgkEAH8ADwEBDQAwgY8xCzAJBgNVBAYTAkFVMSgw +JgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQH +DAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBm +ZWVkYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0xOTEwMDgwNDQ0MjRa +Fw0xOTEwMDgwNDQ2MDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UECgwfVGhlIExl +Z2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBwwJTWVsYm91cm5lMREw +DwYDVQQIDAhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRv +QGJvdW5jeWNhc3RsZS5vcmcwVjALBgkEAH8ADwEBDQADRwAERAAAAAFWJwchaHXu +HqYEWHM/sxvzb5uMNgsNnfzBWQ6ms4iX0CerRixLDoDVhhyVbQFyR2lzigXz1blz +SbPHlBoWLRDiMAsGCQQAfwAPAQENAAOCCcUAAAAAAGScYlJ/B/oWlOBgnIGlnYhT +EPDzn4sHDqic8HJOMMdkBsyGrR0XkqgRDnVI4PEctP8bndw7M327VGlM8Dpprcov +lisvu7j8cV8J6Nksef/AxeIf5z+wsx0zKi7j/n1A3LkC1m3uclesJiifwfNzQYhu +EFE87E6E7QJimr/6tzvU0jDOUB4Fcl/F3mze/c+vtR9xEjKdK2VC3Crftw8eo7jH +kz1pz0JHHYCK2tKh9k3lYIqZMv0RQmfUT3HTQYf5nU+3gMmLUX3gDefZRVYTLX9T +Q3/ctpbLkQ6KmW+8/3nD9X0d49C+pU6AyZHC+Ms7GN7igZhdPh8piI+0uUv1uKDv +u+FZ/yLrLpQ9Ju/qISHXTc8q40ZXUAi77g1kWRaalXArY4j6JudIxJissWZt6w3q +K0ouaygQQCjIydIYjKMRlf5k01basXgT8NyrVsZRl6zKvEO7HM5xgRwcB/2S5yO0 +Rec7anG2SBqL5EXRSTQQhX2cyw6tQU2zBfL6H37Gyf8ezPhdL19zHril2mQuOwgQ +DQ/TsrU/+gfifn78JUDbdBoyflRQnrk0QDmKxOOTUnQXITDrC3773sIv2QUh3h4m +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 +-----END CERTIFICATE----- diff --git a/src/tests/data/x509/xmss/xmss_isara_root.pem b/src/tests/data/x509/xmss/xmss_isara_root.pem new file mode 100644 index 000000000..07f3a6ab5 --- /dev/null +++ b/src/tests/data/x509/xmss/xmss_isara_root.pem @@ -0,0 +1,71 @@ +-----BEGIN CERTIFICATE----- +MIIMwTCCAuegAwIBAgICH1AwCwYJBAB/AA8BAQ0AMIGeMQswCQYDVQQGEwJDQTEQ +MA4GA1UECAwHT250YXJpbzERMA8GA1UEBwwIV2F0ZXJsb28xGjAYBgNVBAoMEUlT +QVJBIENvcnBvcmF0aW9uMRcwFQYDVQQLDA5EZXZlbG9wZXIgVGVhbTENMAsGA1UE +AwwEcm9vdDEmMCQGCSqGSIb3DQEJARYXcm9vdEBmYWtlLmlzYXJhY29ycC5jb20w +HhcNMTkxMDA3MTg0MDAwWhcNMTkxMTA2MTg0MDAwWjCBnjELMAkGA1UEBhMCQ0Ex +EDAOBgNVBAgMB09udGFyaW8xETAPBgNVBAcMCFdhdGVybG9vMRowGAYDVQQKDBFJ +U0FSQSBDb3Jwb3JhdGlvbjEXMBUGA1UECwwORGV2ZWxvcGVyIFRlYW0xDTALBgNV +BAMMBHJvb3QxJjAkBgkqhkiG9w0BCQEWF3Jvb3RAZmFrZS5pc2FyYWNvcnAuY29t +MFYwCwYJBAB/AA8BAQ0AA0cABEQAAAABIp/dzWhnKoTmW30crhrq5TzXYp8k+7qK +jk0x17pdgXMrvNkPrRUcK3Wgp/afgUAaGHlo9zuRckNBp7pPXGPmHaOCARMwggEP +MB0GA1UdDgQWBBSYjbGo++onbH3AB7RVNQ9GrWGgHjCBzAYDVR0jBIHEMIHBgBSY +jbGo++onbH3AB7RVNQ9GrWGgHqGBpKSBoTCBnjELMAkGA1UEBhMCQ0ExEDAOBgNV +BAgMB09udGFyaW8xETAPBgNVBAcMCFdhdGVybG9vMRowGAYDVQQKDBFJU0FSQSBD +b3Jwb3JhdGlvbjEXMBUGA1UECwwORGV2ZWxvcGVyIFRlYW0xDTALBgNVBAMMBHJv +b3QxJjAkBgkqhkiG9w0BCQEWF3Jvb3RAZmFrZS5pc2FyYWNvcnAuY29tggIfUDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjALBgkEAH8ADwEBDQADggnF +AAAAAABDguB8TKHavz3/+LmBcG+TZGB9GzDMQJnINHW9egH4oB56LYdw49wBDcxo ++so3RLjOgaB2TBnR40QKowmTf8U4edk5IIfQbiwhQKLZC6vTHbiYD7cuLmtIzxx7 +12ko50ltsPRn/IXBq3JmNxDS0g78R2x6+V464C5PRETQ0SnRiY3yXNxXB9Lb2+sm +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 +DeJ/1Y0= +-----END CERTIFICATE----- diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp index 8715f3f54..3e07832c3 100644 --- a/src/tests/test_x509_path.cpp +++ b/src/tests/test_x509_path.cpp @@ -28,7 +28,9 @@ namespace Botan_Tests { namespace { -#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EMSA_PKCS1) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) +#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) + +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EMSA_PKCS1) std::map<std::string, std::string> read_results(const std::string& results_file, const char delim = ':') { @@ -118,7 +120,7 @@ class X509test_Path_Validation_Tests final : public Test results.push_back(result); } - // test softfail + // test softfail { Test::Result result("X509test path validation softfail"); result.start_timer(); @@ -897,6 +899,48 @@ BOTAN_REGISTER_TEST("x509_path_with_ocsp", Path_Validation_With_OCSP_Tests); #endif +#if defined(BOTAN_HAS_XMSS_RFC8391) + +class XMSS_Path_Validation_Tests final : public Test + { + public: + Test::Result validate_self_signed(const std::string& name, const std::string& file) + { + Test::Result result(name); + + Botan::Path_Validation_Restrictions restrictions; + auto self_signed = Botan::X509_Certificate(Test::data_dir() + "/x509/xmss/" + file); + + auto cert_path = std::vector<std::shared_ptr<const Botan::X509_Certificate>>{ + std::make_shared<const Botan::X509_Certificate>(self_signed)}; + auto valid_time = Botan::calendar_point(2019, 10, 8, 4, 45, 0).to_std_timepoint(); + + auto status = Botan::PKIX::overall_status(Botan::PKIX::check_chain(cert_path, valid_time, + "", Botan::Usage_Type::UNSPECIFIED, restrictions.minimum_key_strength(), restrictions.trusted_hashes())); + result.test_eq("Cert validation status", + Botan::to_string(status), "Verified"); + return result; + } + + std::vector<Test::Result> run() override + { + if(Botan::has_filesystem_impl() == false) + { + return {Test::Result::Note("XMSS path validation", + "Skipping due to missing filesystem access")}; + } + + return {validate_self_signed("XMSS path validation with certificate created by ISARA corp", "xmss_isara_root.pem"), + validate_self_signed("XMSS path validation with certificate created by BouncyCastle", "xmss_bouncycastle_sha256_10_root.pem")}; + } + }; + +BOTAN_REGISTER_TEST("x509_path_xmss", XMSS_Path_Validation_Tests); + +#endif + +#endif + } } |