aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorMatthias Gierlings <[email protected]>2016-11-06 22:20:20 +0100
committerMatthias Gierlings <[email protected]>2016-11-12 21:00:31 +0100
commit8ae1f77cf639e2589efb8ac12dc689029737b3be (patch)
treeb25060008081b8d7e4d5c7d7c234b2ac454e140f /src/lib
parentd16fd1d9b35698852e7b7aed023dc5057d630098 (diff)
Adds optional XMSS WOTS stand-alone components
The main XMSS implementation does not expose stand-alone access to XMSS Winternitz One Time Signatures through the Botan::PK_Ops interfaces. XMSS WOTS is used by XMSS internally though. This PR implements a possible XMSS WOTS interface for stand-alone use. XMSS WOTS is tested through the XMSS tests, therefore there are no dedicated XMSS WOTS test vectors and test bench components implemented in this PR.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/asn1/oids.cpp4
-rw-r--r--src/lib/pubkey/xmss/info.txt8
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_addressed_privatekey.h68
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_addressed_publickey.h107
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_common_ops.cpp40
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_common_ops.h55
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_privatekey.cpp13
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_privatekey.h5
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_publickey.cpp13
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_publickey.h5
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_signature_operation.cpp52
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_signature_operation.h74
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_verification_operation.cpp68
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_verification_operation.h66
14 files changed, 566 insertions, 12 deletions
diff --git a/src/lib/asn1/oids.cpp b/src/lib/asn1/oids.cpp
index f3536216b..fb2aa0043 100644
--- a/src/lib/asn1/oids.cpp
+++ b/src/lib/asn1/oids.cpp
@@ -15,8 +15,6 @@ namespace OIDS {
std::string lookup(const OID& oid)
{
const std::string oid_str = oid.as_string();
- if(oid_str == "0.0.0.0.0.0.0") return "XMSS"; // FIXME: Preliminary OID
- // update once XMSS OIDs are available.
if(oid_str == "1.0.14888.3.0.5") return "ECKCDSA";
if(oid_str == "1.2.250.1.223.101.256.1") return "frp256v1";
if(oid_str == "1.2.410.200004.1.100.4.3") return "ECKCDSA/EMSA1(SHA-1)";
@@ -184,8 +182,6 @@ std::string lookup(const OID& oid)
OID lookup(const std::string& name)
{
- if(name == "XMSS") return OID("0.0.0.0.0.0.0"); // FIXME: Preliminary OID
- // update once XMSS OIDs are available.
if(name == "AES-128/CBC") return OID("2.16.840.1.101.3.4.1.2");
if(name == "AES-128/GCM") return OID("2.16.840.1.101.3.4.1.6");
if(name == "AES-128/OCB") return OID("1.3.6.1.4.1.25258.3.2.1");
diff --git a/src/lib/pubkey/xmss/info.txt b/src/lib/pubkey/xmss/info.txt
index bab541625..f23bb847b 100644
--- a/src/lib/pubkey/xmss/info.txt
+++ b/src/lib/pubkey/xmss/info.txt
@@ -10,9 +10,12 @@ xmss_publickey.cpp
xmss_signature.cpp
xmss_signature_operation.cpp
xmss_verification_operation.cpp
+xmss_wots_common_ops.cpp
xmss_wots_parameters.cpp
xmss_wots_privatekey.cpp
xmss_wots_publickey.cpp
+xmss_wots_signature_operation.cpp
+xmss_wots_verification_operation.cpp
</source>
<header:public>
@@ -33,6 +36,11 @@ xmss_wots_publickey.h
</header:public>
<header:internal>
+xmss_wots_addressed_privatekey.h
+xmss_wots_addressed_publickey.h
+xmss_wots_common_ops.h
+xmss_wots_signature_operation.h
+xmss_wots_verification_operation.h
xmss_signature.h
xmss_signature_operation.h
xmss_verification_operation.h
diff --git a/src/lib/pubkey/xmss/xmss_wots_addressed_privatekey.h b/src/lib/pubkey/xmss/xmss_wots_addressed_privatekey.h
new file mode 100644
index 000000000..e82cd1638
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_addressed_privatekey.h
@@ -0,0 +1,68 @@
+/**
+ * XMSS WOTS Addressed Private Key
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#ifndef BOTAN_XMSS_WOTS_ADDRESSED_PRIVATEKEY_H__
+#define BOTAN_XMSS_WOTS_ADDRESSED_PRIVATEKEY_H__
+
+#include <botan/xmss_address.h>
+#include <botan/internal/xmss_wots_addressed_publickey.h>
+#include <botan/xmss_wots_privatekey.h>
+
+namespace Botan {
+
+/**
+ * Wrapper class to pair an XMSS_WOTS_PrivateKey with an XMSS Address. Since
+ * the PK_Ops::Signature interface does not allow an extra address
+ * parameter to be passed to the sign(RandomNumberGenerator&), the address
+ * needs to be stored together with the key and passed to the
+ * XMSS_WOTS_Signature_Operation() on creation.
+ **/
+class XMSS_WOTS_Addressed_PrivateKey
+ : public virtual XMSS_WOTS_Addressed_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ XMSS_WOTS_Addressed_PrivateKey(const XMSS_WOTS_PrivateKey& private_key)
+ : XMSS_WOTS_Addressed_PublicKey(private_key),
+ m_priv_key(private_key) {}
+
+ XMSS_WOTS_Addressed_PrivateKey(const XMSS_WOTS_PrivateKey& private_key,
+ const XMSS_Address& adrs)
+ : XMSS_WOTS_Addressed_PublicKey(private_key, adrs),
+ m_priv_key(private_key) {}
+
+ XMSS_WOTS_Addressed_PrivateKey(XMSS_WOTS_PrivateKey&& private_key)
+ : XMSS_WOTS_Addressed_PublicKey(XMSS_WOTS_PublicKey(private_key)),
+ m_priv_key(std::move(private_key)) {}
+
+ XMSS_WOTS_Addressed_PrivateKey(XMSS_WOTS_PrivateKey&& private_key,
+ XMSS_Address&& adrs)
+ : XMSS_WOTS_Addressed_PublicKey(XMSS_WOTS_PublicKey(private_key),
+ std::move(adrs)),
+ m_priv_key(std::move(private_key)) {}
+
+ const XMSS_WOTS_PrivateKey& private_key() const { return m_priv_key; }
+ XMSS_WOTS_PrivateKey& private_key() { return m_priv_key; }
+
+ virtual AlgorithmIdentifier
+ pkcs8_algorithm_identifier() const override
+ {
+ return m_priv_key.pkcs8_algorithm_identifier();
+ }
+
+ virtual secure_vector<byte> pkcs8_private_key() const override
+ {
+ return m_priv_key.pkcs8_private_key();
+ }
+
+ private:
+ XMSS_WOTS_PrivateKey m_priv_key;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/xmss/xmss_wots_addressed_publickey.h b/src/lib/pubkey/xmss/xmss_wots_addressed_publickey.h
new file mode 100644
index 000000000..52165684f
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_addressed_publickey.h
@@ -0,0 +1,107 @@
+/**
+ * XMSS WOTS Addressed Public Key
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+
+#ifndef BOTAN_XMSS_WOTS_ADDRESSED_PUBLICKEY_H__
+#define BOTAN_XMSS_WOTS_ADDRESSED_PUBLICKEY_H__
+
+#include <botan/xmss_address.h>
+#include <botan/xmss_wots_publickey.h>
+
+namespace Botan {
+
+/**
+ * Wrapper class to pair a XMSS_WOTS_PublicKey with an XMSS Address. Since
+ * the PK_Ops::Verification interface does not allow an extra address
+ * parameter to be passed to the sign(RandomNumberGenerator&), the address
+ * needs to be stored together with the key and passed to the
+ * XMSS_WOTS_Verification_Operation() on creation.
+ **/
+class XMSS_WOTS_Addressed_PublicKey : public virtual Public_Key
+ {
+ public:
+ XMSS_WOTS_Addressed_PublicKey(const XMSS_WOTS_PublicKey& public_key)
+ : m_pub_key(public_key), m_adrs() {}
+
+ XMSS_WOTS_Addressed_PublicKey(const XMSS_WOTS_PublicKey& public_key,
+ const XMSS_Address& adrs)
+ : m_pub_key(public_key), m_adrs(adrs) {}
+
+ XMSS_WOTS_Addressed_PublicKey(XMSS_WOTS_PublicKey&& public_key)
+ : m_pub_key(std::move(public_key)), m_adrs() {}
+
+ XMSS_WOTS_Addressed_PublicKey(XMSS_WOTS_PublicKey&& public_key,
+ XMSS_Address&& adrs)
+ : m_pub_key(std::move(public_key)), m_adrs(std::move(adrs)) {}
+
+ const XMSS_WOTS_PublicKey& public_key() const { return m_pub_key; }
+ XMSS_WOTS_PublicKey& public_key() { return m_pub_key; }
+
+ const XMSS_Address& address() const { return m_adrs; }
+ XMSS_Address& address() { return m_adrs; }
+
+ virtual std::string algo_name() const override
+ {
+ return m_pub_key.algo_name();
+ }
+
+ virtual AlgorithmIdentifier algorithm_identifier() const override
+ {
+ return m_pub_key.algorithm_identifier();
+ }
+
+ virtual bool check_key(RandomNumberGenerator& rng,
+ bool strong) const override
+ {
+ return m_pub_key.check_key(rng, strong);
+ }
+
+ virtual std::unique_ptr<PK_Ops::Verification>
+ create_verification_op(const std::string& params,
+ const std::string& provider) const override
+ {
+ return m_pub_key.create_verification_op(params, provider);
+ }
+
+ virtual OID get_oid() const override
+ {
+ return m_pub_key.get_oid();
+ }
+
+ virtual size_t estimated_strength() const override
+ {
+ return m_pub_key.estimated_strength();
+ }
+
+ virtual size_t max_input_bits() const override
+ {
+ return m_pub_key.max_input_bits();
+ }
+
+ virtual size_t message_part_size() const override
+ {
+ return m_pub_key.message_part_size();
+ }
+
+ virtual size_t message_parts() const override
+ {
+ return m_pub_key.message_parts();
+ }
+
+ virtual std::vector<byte> x509_subject_public_key() const override
+ {
+ return m_pub_key.x509_subject_public_key();
+ }
+
+ protected:
+ XMSS_WOTS_PublicKey m_pub_key;
+ XMSS_Address m_adrs;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/xmss/xmss_wots_common_ops.cpp b/src/lib/pubkey/xmss/xmss_wots_common_ops.cpp
new file mode 100644
index 000000000..5d0349677
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_common_ops.cpp
@@ -0,0 +1,40 @@
+/**
+ * XMSS WOTS Common Ops
+ * Operations shared by XMSS WOTS signature generation and verification
+ * operations.
+ *
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#include <botan/internal/xmss_wots_common_ops.h>
+
+namespace Botan {
+
+void
+XMSS_WOTS_Common_Ops::chain(secure_vector<byte>& result,
+ size_t start_idx,
+ size_t steps,
+ XMSS_Address& adrs,
+ const secure_vector<byte>& seed)
+ {
+ for(size_t i = start_idx;
+ i < (start_idx + steps) && i < m_wots_params.wots_parameter();
+ i++)
+ {
+ adrs.set_hash_address(i);
+
+ //Calculate tmp XOR bitmask
+ adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Mask_Mode);
+ xor_buf(result, m_hash.prf(seed, adrs.bytes()), result.size());
+
+ // Calculate key
+ adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Key_Mode);
+
+ //Calculate f(key, tmp XOR bitmask)
+ m_hash.f(result, m_hash.prf(seed, adrs.bytes()), result);
+ }
+ }
+
+}
diff --git a/src/lib/pubkey/xmss/xmss_wots_common_ops.h b/src/lib/pubkey/xmss/xmss_wots_common_ops.h
new file mode 100644
index 000000000..f3153515c
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_common_ops.h
@@ -0,0 +1,55 @@
+/**
+ * XMSS WOTS Common Operations
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#ifndef BOTAN_XMSS_WOTS_COMMON_OPS_H__
+#define BOTAN_XMSS_WOTS_COMMON_OPS_H__
+
+#include <cstddef>
+#include <botan/types.h>
+#include <botan/xmss_wots_parameters.h>
+#include <botan/xmss_address.h>
+#include <botan/xmss_hash.h>
+
+namespace Botan {
+
+/**
+ * Operations shared by XMSS WOTS signature generation and verification
+ * operations.
+ **/
+class XMSS_WOTS_Common_Ops
+ {
+ public:
+ XMSS_WOTS_Common_Ops(XMSS_WOTS_Parameters::ots_algorithm_t oid)
+ : m_wots_params(oid), m_hash(m_wots_params.hash_function_name()) {}
+
+
+ protected:
+ /**
+ * Algorithm 2: Chaining Function.
+ *
+ * @param[out] result Contains the n-byte input string "x" upon call to chain(),
+ * that will be replaced with the value obtained by iterating
+ * the cryptographic hash function "F" steps times on the
+ * input x using the outputs of the PRNG "G".
+ * @param[in] start_idx The start index.
+ * @param[in] steps A number of steps.
+ * @param[in] adrs An OTS Hash Address.
+ * @param[in] seed A Seed.
+ **/
+ void chain(secure_vector<byte>& result,
+ size_t start_idx,
+ size_t steps,
+ XMSS_Address& adrs,
+ const secure_vector<byte>& seed);
+
+ XMSS_WOTS_Parameters m_wots_params;
+ XMSS_Hash m_hash;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/xmss/xmss_wots_privatekey.cpp b/src/lib/pubkey/xmss/xmss_wots_privatekey.cpp
index 1a68b187d..13568e0b9 100644
--- a/src/lib/pubkey/xmss/xmss_wots_privatekey.cpp
+++ b/src/lib/pubkey/xmss/xmss_wots_privatekey.cpp
@@ -8,6 +8,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
**/
+#include <botan/internal/xmss_wots_signature_operation.h>
#include <botan/xmss_wots_privatekey.h>
namespace Botan {
@@ -77,4 +78,16 @@ XMSS_WOTS_PrivateKey::sign(
return sig;
}
+std::unique_ptr<PK_Ops::Signature>
+XMSS_WOTS_PrivateKey::create_signature_op(RandomNumberGenerator&,
+ const std::string&,
+ const std::string& provider) const
+ {
+ if(provider == "base" || provider.empty())
+ return std::unique_ptr<PK_Ops::Signature>(
+ new XMSS_WOTS_Signature_Operation(*this));
+
+ throw Provider_Not_Found(algo_name(), provider);
+ }
+
}
diff --git a/src/lib/pubkey/xmss/xmss_wots_privatekey.h b/src/lib/pubkey/xmss/xmss_wots_privatekey.h
index 1a6e50fe8..312db8b7b 100644
--- a/src/lib/pubkey/xmss/xmss_wots_privatekey.h
+++ b/src/lib/pubkey/xmss/xmss_wots_privatekey.h
@@ -234,10 +234,7 @@ class BOTAN_DLL XMSS_WOTS_PrivateKey : public virtual XMSS_WOTS_PublicKey,
virtual std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator&,
const std::string&,
- const std::string&) const override
- {
- BOTAN_ASSERT(false, "XMSS_WOTS_Signature_Operation not available.");
- }
+ const std::string& provider) const override;
virtual secure_vector<byte> pkcs8_private_key() const override
{
diff --git a/src/lib/pubkey/xmss/xmss_wots_publickey.cpp b/src/lib/pubkey/xmss/xmss_wots_publickey.cpp
index aa0240be8..9a7df1682 100644
--- a/src/lib/pubkey/xmss/xmss_wots_publickey.cpp
+++ b/src/lib/pubkey/xmss/xmss_wots_publickey.cpp
@@ -8,6 +8,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
**/
+#include <botan/internal/xmss_wots_verification_operation.h>
#include <botan/xmss_wots_publickey.h>
namespace Botan {
@@ -63,4 +64,16 @@ XMSS_WOTS_PublicKey::pub_key_from_signature(const secure_vector<byte>& msg,
return result;
}
+std::unique_ptr<PK_Ops::Verification>
+XMSS_WOTS_PublicKey::create_verification_op(const std::string&,
+ const std::string& provider) const
+ {
+ if(provider == "base" || provider.empty())
+ {
+ return std::unique_ptr<PK_Ops::Verification>(
+ new XMSS_WOTS_Verification_Operation(*this));
+ }
+ throw Provider_Not_Found(algo_name(), provider);
+ }
+
}
diff --git a/src/lib/pubkey/xmss/xmss_wots_publickey.h b/src/lib/pubkey/xmss/xmss_wots_publickey.h
index a3e5232e8..9efb04667 100644
--- a/src/lib/pubkey/xmss/xmss_wots_publickey.h
+++ b/src/lib/pubkey/xmss/xmss_wots_publickey.h
@@ -243,10 +243,7 @@ class BOTAN_DLL XMSS_WOTS_PublicKey : virtual public Public_Key
virtual std::unique_ptr<PK_Ops::Verification>
create_verification_op(const std::string&,
- const std::string&) const override
- {
- BOTAN_ASSERT(false, "XMSS_WOTS_Verification_Operation not available.");
- }
+ const std::string& provider) const override;
virtual size_t estimated_strength() const override
{
diff --git a/src/lib/pubkey/xmss/xmss_wots_signature_operation.cpp b/src/lib/pubkey/xmss/xmss_wots_signature_operation.cpp
new file mode 100644
index 000000000..82f32b88e
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_signature_operation.cpp
@@ -0,0 +1,52 @@
+/**
+ * XMSS WOTS Signature Operation
+ * Signature generation operation for Winternitz One Time Signatures for use
+ * in Extended Hash-Based Signatures (XMSS).
+ *
+ * This operation is not intended for stand-alone use and thus not registered
+ * in the Botan algorithm registry.
+ *
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#include <botan/internal/xmss_wots_signature_operation.h>
+
+namespace Botan {
+
+XMSS_WOTS_Signature_Operation::XMSS_WOTS_Signature_Operation(
+ const XMSS_WOTS_Addressed_PrivateKey& private_key)
+ : XMSS_WOTS_Common_Ops(private_key.private_key().wots_parameters().oid()),
+ m_priv_key(private_key),
+ m_msg_buf(0)
+ {
+ m_msg_buf.reserve(m_priv_key.message_part_size());
+ }
+
+void
+XMSS_WOTS_Signature_Operation::update(const byte msg[], size_t msg_len)
+ {
+ BOTAN_ASSERT(msg_len == message_part_size() &&
+ m_msg_buf.size() == 0,
+ "XMSS WOTS only supports one message part of size n.");
+
+ for(size_t i = 0; i < msg_len; i++)
+ m_msg_buf.push_back(msg[i]);
+ }
+
+secure_vector<byte>
+XMSS_WOTS_Signature_Operation::sign(RandomNumberGenerator&)
+ {
+ secure_vector<byte> result(0);
+ result.reserve(m_wots_params.len() * m_wots_params.element_size());
+ XMSS_WOTS_PrivateKey& priv_key = m_priv_key.private_key();
+ for(const auto& node : priv_key.sign(m_msg_buf, m_priv_key.address()))
+ {
+ std::copy(node.begin(), node.end(), std::back_inserter(result));
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/lib/pubkey/xmss/xmss_wots_signature_operation.h b/src/lib/pubkey/xmss/xmss_wots_signature_operation.h
new file mode 100644
index 000000000..2b469e200
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_signature_operation.h
@@ -0,0 +1,74 @@
+/**
+ * XMSS WOTS Signature Operation
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#ifndef BOTAN_XMSS_WOTS_SIGNATURE_OPERATION_H__
+#define BOTAN_XMSS_WOTS_SIGNATURE_OPERATION_H__
+
+#include <cstddef>
+#include <iterator>
+#include <botan/assert.h>
+#include <botan/types.h>
+#include <botan/internal/pk_ops.h>
+#include <botan/internal/xmss_wots_addressed_privatekey.h>
+#include <botan/internal/xmss_wots_common_ops.h>
+
+namespace Botan {
+
+/**
+ * Signature generation operation for Winternitz One Time Signatures for use
+ * in Extended Hash-Based Signatures (XMSS).
+ *
+ * This operation is not intended for stand-alone use and thus not registered
+ * in the Botan algorithm registry.
+ ***/
+class XMSS_WOTS_Signature_Operation : public virtual PK_Ops::Signature,
+ public XMSS_WOTS_Common_Ops
+ {
+ public:
+ typedef XMSS_WOTS_Addressed_PrivateKey Key_Type;
+
+ XMSS_WOTS_Signature_Operation(
+ const XMSS_WOTS_Addressed_PrivateKey& private_key);
+
+ virtual ~XMSS_WOTS_Signature_Operation() {}
+
+ virtual size_t message_part_size() const override
+ {
+ return m_priv_key.message_part_size();
+ }
+
+ virtual size_t message_parts() const override
+ {
+ return m_priv_key.message_parts();
+ }
+
+ /**
+ * Creates a XMSS WOTS signature for the message provided through call
+ * to update(). XMSS wots only supports one message part and a fixed
+ * message size of "n" bytes where "n" equals the element size of
+ * the chosen XMSS WOTS signature method. The random number generator
+ * argument is supplied for interface compatibility and remains unused.
+ *
+ * @return serialized Winternitz One Time Signature.
+ **/
+ secure_vector<byte> sign(RandomNumberGenerator&) override;
+
+ void update(const byte msg[], size_t msg_len) override;
+
+ private:
+ wots_keysig_t sign(const secure_vector<byte>& msg,
+ const wots_keysig_t& priv_key,
+ XMSS_Address& adrs,
+ const secure_vector<byte>& seed);
+ XMSS_WOTS_Addressed_PrivateKey m_priv_key;
+ secure_vector<byte> m_msg_buf;
+ };
+
+}
+
+#endif
+
diff --git a/src/lib/pubkey/xmss/xmss_wots_verification_operation.cpp b/src/lib/pubkey/xmss/xmss_wots_verification_operation.cpp
new file mode 100644
index 000000000..6bff05b93
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_verification_operation.cpp
@@ -0,0 +1,68 @@
+/**
+ * XMSS WOTS Verification Operation
+ * Provides signature verification capabilities for Winternitz One Time
+ * Signatures used in Extended Hash-Based Signatures (XMSS).
+ *
+ * This operation is not intended for stand-alone use and thus not registered
+ * in the Botan algorithm registry.
+ *
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#include <botan/internal/xmss_wots_verification_operation.h>
+
+namespace Botan {
+
+XMSS_WOTS_Verification_Operation::XMSS_WOTS_Verification_Operation(
+ const XMSS_WOTS_Addressed_PublicKey& public_key)
+ : XMSS_WOTS_Common_Ops(public_key.public_key().wots_parameters().oid()),
+ m_pub_key(public_key),
+ m_msg_buf(0)
+ {
+ m_msg_buf.reserve(m_pub_key.message_part_size());
+ }
+
+void
+XMSS_WOTS_Verification_Operation::update(const byte msg[], size_t msg_len)
+ {
+ BOTAN_ASSERT(msg_len == message_part_size() &&
+ m_msg_buf.size() == 0,
+ "XMSS WOTS only supports one message part of size n.");
+
+ for(size_t i = 0; i < msg_len; i++)
+ m_msg_buf.push_back(msg[i]);
+ }
+
+bool XMSS_WOTS_Verification_Operation::is_valid_signature(const byte sig[],
+ size_t sig_len)
+ {
+ const XMSS_WOTS_Parameters& w = m_pub_key.public_key().wots_parameters();
+
+ BOTAN_ASSERT(sig_len == w.element_size() * w.len(),
+ "Invalid signature size.");
+
+ wots_keysig_t signature(0);
+ signature.reserve(sig_len);
+
+ size_t begin = 0;
+ size_t end = 0;
+ while(signature.size() < w.len())
+ {
+ begin = end;
+ end = begin + w.element_size();
+ signature.push_back(secure_vector<byte>(sig + begin, sig + end));
+ }
+
+ XMSS_WOTS_PublicKey pubkey_msg(w.oid(),
+ m_msg_buf,
+ signature,
+ m_pub_key.address(),
+ m_pub_key.public_key().public_seed());
+
+ return pubkey_msg.key_data() == m_pub_key.public_key().key_data();
+ }
+
+}
+
diff --git a/src/lib/pubkey/xmss/xmss_wots_verification_operation.h b/src/lib/pubkey/xmss/xmss_wots_verification_operation.h
new file mode 100644
index 000000000..d4d961e80
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_wots_verification_operation.h
@@ -0,0 +1,66 @@
+/**
+ * XMSS_WOTS_Verification_Operation.h
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#ifndef BOTAN_XMSS_WOTS_VERIFICATION_OPERATION_H__
+#define BOTAN_XMSS_WOTS_VERIFICATION_OPERATION_H__
+
+#include <cstddef>
+#include <iterator>
+#include <botan/types.h>
+#include <botan/internal/pk_ops.h>
+#include <botan/internal/xmss_wots_addressed_publickey.h>
+#include <botan/internal/xmss_wots_common_ops.h>
+
+namespace Botan {
+
+/**
+ * Provides signature verification capabilities for Winternitz One Time
+ * Signatures used in Extended Merkle Tree Signatures (XMSS).
+ *
+ * This operation is not intended for stand-alone use and thus not registered
+ * in the Botan algorithm registry.
+ **/
+class XMSS_WOTS_Verification_Operation
+ : public virtual PK_Ops::Verification,
+ public XMSS_WOTS_Common_Ops
+ {
+ public:
+ typedef XMSS_WOTS_Addressed_PublicKey Key_Type;
+
+ XMSS_WOTS_Verification_Operation(
+ const XMSS_WOTS_Addressed_PublicKey& public_key);
+
+ virtual ~XMSS_WOTS_Verification_Operation() {}
+
+ virtual size_t max_input_bits() const override
+ {
+ return m_pub_key.max_input_bits();
+ }
+
+ virtual size_t message_part_size() const override
+ {
+ return m_pub_key.message_part_size();
+ }
+
+ virtual size_t message_parts() const override
+ {
+ return m_pub_key.message_parts();
+ }
+
+ virtual bool is_valid_signature(const byte sig[],
+ size_t sig_len) override;
+
+ void update(const byte msg[], size_t msg_len) override;
+
+ private:
+ XMSS_WOTS_Addressed_PublicKey m_pub_key;
+ secure_vector<byte> m_msg_buf;
+ };
+
+}
+
+#endif