Botan 3.6.1
Crypto and TLS for C&
xmss_publickey.cpp
Go to the documentation of this file.
1/*
2 * XMSS Public Key
3 * An XMSS: Extended Hash-Based Siganture public key.
4 * The XMSS public key does not support the X509 standard. Instead the
5 * raw format described in [1] is used.
6 *
7 * [1] XMSS: Extended Hash-Based Signatures,
8 * Request for Comments: 8391
9 * Release: May 2018.
10 * https://datatracker.ietf.org/doc/rfc8391/
11 *
12 * (C) 2016,2017 Matthias Gierlings
13 *
14 * Botan is released under the Simplified BSD License (see license.txt)
15 **/
16
17#include <botan/xmss.h>
18
19#include <botan/ber_dec.h>
20#include <botan/der_enc.h>
21#include <botan/internal/loadstor.h>
22#include <botan/internal/stl_util.h>
23#include <botan/internal/xmss_verification_operation.h>
24
25#include <iterator>
26
27namespace Botan {
28
29namespace {
30
31XMSS_Parameters::xmss_algorithm_t deserialize_xmss_oid(std::span<const uint8_t> raw_key) {
32 if(raw_key.size() < 4) {
33 throw Decoding_Error("XMSS signature OID missing.");
34 }
35
36 // extract and convert algorithm id to enum type
37 uint32_t raw_id = 0;
38 for(size_t i = 0; i < 4; i++) {
39 raw_id = ((raw_id << 8) | raw_key[i]);
40 }
41
42 return static_cast<XMSS_Parameters::xmss_algorithm_t>(raw_id);
43}
44
45// fall back to raw decoding for previous versions, which did not encode an OCTET STRING
46std::vector<uint8_t> extract_raw_public_key(std::span<const uint8_t> key_bits) {
47 std::vector<uint8_t> raw_key;
48 try {
49 DataSource_Memory src(key_bits);
50 BER_Decoder(src).decode(raw_key, ASN1_Type::OctetString).verify_end();
51
52 // Smoke check the decoded key. Valid raw keys might be decodeable as BER
53 // and they might be either a sole public key or a concatenation of public
54 // and private key (with the optional WOTS+ derivation identifier).
55 XMSS_Parameters params(deserialize_xmss_oid(raw_key));
56 if(raw_key.size() != params.raw_public_key_size() && raw_key.size() != params.raw_private_key_size() &&
57 raw_key.size() != params.raw_legacy_private_key_size()) {
58 throw Decoding_Error("unpacked XMSS key does not have the correct length");
59 }
60 } catch(Decoding_Error&) {
61 raw_key.assign(key_bits.begin(), key_bits.end());
62 } catch(Not_Implemented&) {
63 raw_key.assign(key_bits.begin(), key_bits.end());
64 }
65
66 return raw_key;
67}
68
69} // namespace
70
72 m_xmss_params(xmss_oid),
73 m_wots_params(m_xmss_params.ots_oid()),
74 m_root(m_xmss_params.element_size()),
75 m_public_seed(rng.random_vec(m_xmss_params.element_size())) {}
76
77XMSS_PublicKey::XMSS_PublicKey(std::span<const uint8_t> key_bits) :
78 m_raw_key(extract_raw_public_key(key_bits)),
79 m_xmss_params(deserialize_xmss_oid(m_raw_key)),
80 m_wots_params(m_xmss_params.ots_oid()) {
82 throw Decoding_Error("Invalid XMSS public key size detected");
83 }
84
86 s.skip(4 /* algorithm ID -- already consumed by `deserialize_xmss_oid()` */);
87
88 m_root = s.copy_as_secure_vector(m_xmss_params.element_size());
89 m_public_seed = s.copy_as_secure_vector(m_xmss_params.element_size());
90}
91
94 secure_vector<uint8_t> public_seed) :
95 m_xmss_params(xmss_oid),
96 m_wots_params(m_xmss_params.ots_oid()),
97 m_root(std::move(root)),
98 m_public_seed(std::move(public_seed)) {
99 BOTAN_ARG_CHECK(m_root.size() == m_xmss_params.element_size(), "XMSS: unexpected byte length of root hash");
100 BOTAN_ARG_CHECK(m_public_seed.size() == m_xmss_params.element_size(), "XMSS: unexpected byte length of public seed");
101}
102
103std::unique_ptr<PK_Ops::Verification> XMSS_PublicKey::create_verification_op(std::string_view /*params*/,
104 std::string_view provider) const {
105 if(provider == "base" || provider.empty()) {
106 return std::make_unique<XMSS_Verification_Operation>(*this);
107 }
108 throw Provider_Not_Found(algo_name(), provider);
109}
110
111std::unique_ptr<PK_Ops::Verification> XMSS_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
112 std::string_view provider) const {
113 if(provider == "base" || provider.empty()) {
114 if(alg_id != this->algorithm_identifier()) {
115 throw Decoding_Error("Unexpected AlgorithmIdentifier for XMSS X509 signature");
116 }
117 return std::make_unique<XMSS_Verification_Operation>(*this);
118 }
119 throw Provider_Not_Found(algo_name(), provider);
120}
121
122std::vector<uint8_t> XMSS_PublicKey::raw_public_key_bits() const {
123 return concat<std::vector<uint8_t>>(store_be(static_cast<uint32_t>(m_xmss_params.oid())), m_root, m_public_seed);
124}
125
126std::vector<uint8_t> XMSS_PublicKey::public_key_bits() const {
127 std::vector<uint8_t> output;
129 return output;
130}
131
132std::vector<uint8_t> XMSS_PublicKey::raw_public_key() const {
133 return raw_public_key_bits();
134}
135
136std::unique_ptr<Private_Key> XMSS_PublicKey::generate_another(RandomNumberGenerator& rng) const {
137 // Note: Given only an XMSS public key we cannot know which WOTS key
138 // derivation method was used to build the XMSS tree. Hence, we have to
139 // use the default here.
140 return std::make_unique<XMSS_PrivateKey>(m_xmss_params.oid(), rng);
141}
142
143} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
void skip(const size_t count)
Definition stl_util.h:125
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
size_t raw_public_key_size() const
xmss_algorithm_t oid() const
size_t element_size() const
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &alg_id, std::string_view provider) const override
secure_vector< uint8_t > m_root
Definition xmss.h:126
std::vector< uint8_t > public_key_bits() const override
std::vector< uint8_t > raw_public_key_bits() const override
secure_vector< uint8_t > m_public_seed
Definition xmss.h:127
XMSS_Parameters m_xmss_params
Definition xmss.h:124
std::vector< uint8_t > m_raw_key
Definition xmss.h:123
std::vector< uint8_t > raw_public_key() const
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::string algo_name() const override
Definition xmss.h:72
AlgorithmIdentifier algorithm_identifier() const override
Definition xmss.h:74
XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid, RandomNumberGenerator &rng)
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:263
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:773