Botan 3.12.0
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 Signature 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/rng.h>
22#include <botan/internal/buffer_slicer.h>
23#include <botan/internal/concat_util.h>
24#include <botan/internal/loadstor.h>
25#include <botan/internal/xmss_verification_operation.h>
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 {
50
51 // Smoke check the decoded key. Valid raw keys might be decodable as BER
52 // and they might be either a sole public key or a concatenation of public
53 // and private key (with the optional WOTS+ derivation identifier).
54 const XMSS_Parameters params = XMSS_Parameters::from_id(deserialize_xmss_oid(raw_key));
55 if(raw_key.size() != params.raw_public_key_size() && raw_key.size() != params.raw_private_key_size() &&
56 raw_key.size() != params.raw_legacy_private_key_size()) {
57 throw Decoding_Error("unpacked XMSS key does not have the correct length");
58 }
59 } catch(Decoding_Error&) {
60 raw_key.assign(key_bits.begin(), key_bits.end());
61 } catch(Not_Implemented&) {
62 raw_key.assign(key_bits.begin(), key_bits.end());
63 }
64
65 return raw_key;
66}
67
68} // namespace
69
70class XMSS_PublicKey_Internal final {
71 public:
72 XMSS_PublicKey_Internal(const XMSS_Parameters& params,
74 secure_vector<uint8_t> public_seed) :
75 m_xmss_params(params),
76 m_wots_params(m_xmss_params.wots_parameters()),
77 m_root(std::move(root)),
78 m_public_seed(std::move(public_seed)) {}
79
80 const XMSS_Parameters& xmss_parameters() const { return m_xmss_params; }
81
82 const XMSS_WOTS_Parameters& wots_parameters() const { return m_wots_params; }
83
84 const secure_vector<uint8_t>& root() const { return m_root; }
85
86 const secure_vector<uint8_t>& public_seed() const { return m_public_seed; }
87
88 void set_root(secure_vector<uint8_t> root) { m_root = std::move(root); }
89
90 std::vector<uint8_t> raw_public_key_bits() const {
92 store_be(static_cast<uint32_t>(m_xmss_params.oid())), m_root, m_public_seed);
93 }
94
95 private:
96 XMSS_Parameters m_xmss_params;
97 XMSS_WOTS_Parameters m_wots_params;
99 secure_vector<uint8_t> m_public_seed;
100};
101
103 const auto params = XMSS_Parameters::from_id(xmss_oid);
104 m_public_key = std::make_shared<XMSS_PublicKey_Internal>(
105 params, secure_vector<uint8_t>(params.element_size()), rng.random_vec(params.element_size()));
106}
107
108XMSS_PublicKey::XMSS_PublicKey(std::span<const uint8_t> key_bits) {
109 const auto raw_key = extract_raw_public_key(key_bits);
110 const auto xmss_oid = deserialize_xmss_oid(raw_key);
111 const auto params = XMSS_Parameters::from_id(xmss_oid);
112 if(raw_key.size() < params.raw_public_key_size()) {
113 throw Decoding_Error("Invalid XMSS public key size detected");
114 }
115
116 BufferSlicer s(raw_key);
117 s.skip(4 /* algorithm ID -- already consumed by `deserialize_xmss_oid()` */);
118
119 auto root = s.copy_as_secure_vector(params.element_size());
120 auto public_seed = s.copy_as_secure_vector(params.element_size());
121
122 m_public_key = std::make_shared<XMSS_PublicKey_Internal>(params, std::move(root), std::move(public_seed));
123}
124
128 const auto params = XMSS_Parameters::from_id(xmss_oid);
129 BOTAN_ARG_CHECK(root.size() == params.element_size(), "XMSS: unexpected byte length of root hash");
130 BOTAN_ARG_CHECK(public_seed.size() == params.element_size(), "XMSS: unexpected byte length of public seed");
131 m_public_key = std::make_shared<XMSS_PublicKey_Internal>(params, std::move(root), std::move(public_seed));
132}
133
135 return m_public_key->public_seed();
136}
137
139 return m_public_key->root();
140}
141
143 return m_public_key->xmss_parameters();
144}
145
147 m_public_key->set_root(std::move(root));
148}
149
153
157
158bool XMSS_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
159 // The public key consists of (OID, root hash, public seed). The OID is
160 // validated and the byte lengths of root and public_seed are verified
161 // against the parameter set during deserialization. These are opaque
162 // hash outputs with no further structural invariants to check.
163 return true;
164}
165
166std::unique_ptr<PK_Ops::Verification> XMSS_PublicKey::create_verification_op(std::string_view /*params*/,
167 std::string_view provider) const {
168 if(provider == "base" || provider.empty()) {
169 return std::make_unique<XMSS_Verification_Operation>(*this);
170 }
171 throw Provider_Not_Found(algo_name(), provider);
172}
173
174std::unique_ptr<PK_Ops::Verification> XMSS_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
175 std::string_view provider) const {
176 if(provider == "base" || provider.empty()) {
177 if(alg_id != this->algorithm_identifier()) {
178 throw Decoding_Error("Unexpected AlgorithmIdentifier for XMSS X509 signature");
179 }
180 return std::make_unique<XMSS_Verification_Operation>(*this);
181 }
182 throw Provider_Not_Found(algo_name(), provider);
183}
184
185std::vector<uint8_t> XMSS_PublicKey::raw_public_key_bits() const {
186 return m_public_key->raw_public_key_bits();
187}
188
189std::vector<uint8_t> XMSS_PublicKey::public_key_bits() const {
190 std::vector<uint8_t> output;
192 return output;
193}
194
195std::vector<uint8_t> XMSS_PublicKey::raw_public_key() const {
196 return raw_public_key_bits();
197}
198
199std::unique_ptr<Private_Key> XMSS_PublicKey::generate_another(RandomNumberGenerator& rng) const {
200 // Note: Given only an XMSS public key we cannot know which WOTS key
201 // derivation method was used to build the XMSS tree. Hence, we have to
202 // use the default here.
203 return std::make_unique<XMSS_PrivateKey>(xmss_parameters().oid(), rng);
204}
205
206} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
static Limits DER()
Definition ber_dec.h:35
BER_Decoder & decode(bool &out)
Definition ber_dec.h:220
BER_Decoder & verify_end()
Definition ber_dec.cpp:381
void skip(const size_t count)
auto copy_as_secure_vector(const size_t count)
DER_Encoder & encode(bool b)
Definition der_enc.cpp:245
void random_vec(std::span< uint8_t > v)
Definition rng.h:204
size_t estimated_strength() const
static XMSS_Parameters from_id(xmss_algorithm_t id)
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &alg_id, std::string_view provider) const override
const secure_vector< uint8_t > & root() const
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::vector< uint8_t > public_key_bits() const override
std::vector< uint8_t > raw_public_key_bits() const override
const secure_vector< uint8_t > & public_seed() const
const XMSS_Parameters & xmss_parameters() const
std::vector< uint8_t > raw_public_key() const
void set_root(secure_vector< uint8_t > root)
size_t estimated_strength() const override
size_t key_length() const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::string algo_name() const override
Definition xmss.h:71
AlgorithmIdentifier algorithm_identifier() const override
Definition xmss.h:73
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
constexpr auto concat(Rs &&... ranges)
Definition concat_util.h:90
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745