aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/kdf/kdf.cpp8
-rw-r--r--src/lib/kdf/kdf1_iso18033/info.txt1
-rw-r--r--src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp35
-rw-r--r--src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h37
-rw-r--r--src/lib/pubkey/ecies/ecies.cpp399
-rw-r--r--src/lib/pubkey/ecies/ecies.h293
-rw-r--r--src/lib/pubkey/ecies/info.txt9
7 files changed, 782 insertions, 0 deletions
diff --git a/src/lib/kdf/kdf.cpp b/src/lib/kdf/kdf.cpp
index 7f4488d32..66296bf96 100644
--- a/src/lib/kdf/kdf.cpp
+++ b/src/lib/kdf/kdf.cpp
@@ -21,6 +21,10 @@
#include <botan/kdf2.h>
#endif
+#if defined(BOTAN_HAS_KDF1_18033)
+#include <botan/kdf1_iso18033.h>
+#endif
+
#if defined(BOTAN_HAS_TLS_V10_PRF)
#include <botan/prf_tls.h>
#endif
@@ -89,6 +93,10 @@ BOTAN_REGISTER_KDF_1HASH(KDF1, "KDF1");
BOTAN_REGISTER_KDF_1HASH(KDF2, "KDF2");
#endif
+#if defined(BOTAN_HAS_KDF1_18033)
+BOTAN_REGISTER_KDF_1HASH( KDF1_18033, "KDF1-18033" );
+#endif
+
#if defined(BOTAN_HAS_TLS_V10_PRF)
BOTAN_REGISTER_KDF_NOARGS(TLS_PRF, "TLS-PRF");
#endif
diff --git a/src/lib/kdf/kdf1_iso18033/info.txt b/src/lib/kdf/kdf1_iso18033/info.txt
new file mode 100644
index 000000000..507a04561
--- /dev/null
+++ b/src/lib/kdf/kdf1_iso18033/info.txt
@@ -0,0 +1 @@
+define KDF1_18033 20160128
diff --git a/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp
new file mode 100644
index 000000000..3ff717993
--- /dev/null
+++ b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp
@@ -0,0 +1,35 @@
+/*
+* KDF1 from ISO 18033
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/kdf1_iso18033.h>
+
+namespace Botan {
+
+size_t KDF1_18033::kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const
+ {
+ u32bit counter = 0;
+ secure_vector<byte> h;
+
+ size_t offset = 0;
+ while(offset != key_len && counter != 0xFFFFFFFF)
+ {
+ m_hash->update(secret, secret_len);
+ m_hash->update_be(counter++);
+ m_hash->update(salt, salt_len);
+ m_hash->final(h);
+
+ const size_t added = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), added);
+ offset += added;
+ }
+
+ return offset;
+ }
+
+}
diff --git a/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h
new file mode 100644
index 000000000..6ec7ead8e
--- /dev/null
+++ b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h
@@ -0,0 +1,37 @@
+/*
+* KDF1 from ISO 18033
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KDF1_18033_H__
+#define BOTAN_KDF1_18033_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* KDF1, from IEEE 1363
+*/
+class BOTAN_DLL KDF1_18033 : public KDF
+ {
+ public:
+ std::string name() const override { return "KDF1-18033(" + m_hash->name() + ")"; }
+
+ KDF* clone() const override { return new KDF1_18033(m_hash->clone()); }
+
+ size_t kdf(byte key[], size_t key_len,
+ const byte secret[], size_t secret_len,
+ const byte salt[], size_t salt_len) const override;
+
+ KDF1_18033(HashFunction* h) : m_hash(h) {}
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp
new file mode 100644
index 000000000..0efdc64e1
--- /dev/null
+++ b/src/lib/pubkey/ecies/ecies.cpp
@@ -0,0 +1,399 @@
+/*
+* ECIES
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ecies.h>
+#include <botan/cipher_mode.h>
+#include <botan/pipe.h>
+
+#include <botan/internal/ct_utils.h>
+#include <botan/internal/pk_utils.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* Private key type for ECIES_ECDH_KA_Operation
+*/
+class ECIES_PrivateKey : public EC_PrivateKey, public PK_Key_Agreement_Key
+ {
+ public:
+ explicit ECIES_PrivateKey(const ECDH_PrivateKey& private_key) :
+ EC_PublicKey(private_key),
+ EC_PrivateKey(private_key),
+ PK_Key_Agreement_Key(),
+ m_key(private_key)
+ {
+ }
+
+ std::vector<byte> public_value() const override
+ {
+ return m_key.public_value();
+ }
+
+ std::string algo_name() const override
+ {
+ return "ECIES";
+ }
+
+ size_t max_input_bits() const override
+ {
+ return m_key.max_input_bits();
+ }
+
+ private:
+ ECDH_PrivateKey m_key;
+ };
+
+/**
+* Implements ECDH key agreement without using the cofactor mode
+*/
+class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF
+ {
+ public:
+ typedef ECIES_PrivateKey Key_Type;
+
+ ECIES_ECDH_KA_Operation(const ECIES_PrivateKey& private_key, const std::string&) :
+ PK_Ops::Key_Agreement_with_KDF("Raw"),
+ m_key(private_key)
+ {
+ }
+
+ secure_vector<byte> raw_agree(const byte w[], size_t w_len) override
+ {
+ const CurveGFp& curve = m_key.domain().get_curve();
+ PointGFp point = OS2ECP(w, w_len, curve);
+ PointGFp S = point * m_key.private_value();
+ BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve");
+ return BigInt::encode_1363(S.get_affine_x(), curve.get_p().bytes());
+ }
+
+ private:
+ ECIES_PrivateKey m_key;
+ };
+
+/**
+* Creates a PK_Key_Agreement instance for the given key and ecies_params
+* Returns either ECIES_ECDH_KA_Operation or the default implementation for the given key,
+* depending on the key and ecies_params
+* @param private_key the private key used for the key agreement
+* @param ecies_params settings for ecies
+* @param for_encryption disable cofactor mode if the secret will be used for encryption
+* (according to ISO 18033 cofactor mode is only used during decryption)
+*/
+PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params,
+ bool for_encryption)
+ {
+ const ECDH_PrivateKey* ecdh_key = dynamic_cast<const ECDH_PrivateKey*>(&private_key);
+
+ if(ecdh_key == nullptr && (ecies_params.cofactor_mode() || ecies_params.old_cofactor_mode()
+ || ecies_params.check_mode()))
+ {
+ // assume we have a private key from an external provider (e.g. pkcs#11):
+ // there is no way to determine or control whether the provider uses cofactor mode or not.
+ // ISO 18033 does not allow cofactor mode in combination with old cofactor mode or check mode
+ // => disable cofactor mode, old cofactor mode and check mode for unknown keys/providers (as a precaution).
+ throw Invalid_Argument("ECIES: cofactor, old cofactor and check mode are only supported for ECDH_PrivateKey");
+ }
+
+ if(ecdh_key && (for_encryption || !ecies_params.cofactor_mode()))
+ {
+ // ECDH_KA_Operation uses cofactor mode: use own key agreement method if cofactor should not be used.
+ return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), "Raw");
+ }
+
+ return PK_Key_Agreement(private_key, "Raw"); // use default implementation
+ }
+}
+
+BOTAN_REGISTER_PK_KEY_AGREE_OP("ECIES", ECIES_ECDH_KA_Operation);
+
+ECIES_KA_Operation::ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params,
+ bool for_encryption) :
+ m_ka(create_key_agreement(private_key, ecies_params, for_encryption)),
+ m_params(ecies_params)
+ {
+ }
+
+/**
+* ECIES secret derivation according to ISO 18033-2
+*/
+SymmetricKey ECIES_KA_Operation::derive_secret(const std::vector<byte>& eph_public_key_bin,
+ const PointGFp& other_public_key_point) const
+ {
+ if(other_public_key_point.is_zero())
+ {
+ throw Invalid_Argument("ECIES: other public key point is zero");
+ }
+
+ std::unique_ptr<KDF> kdf = m_params.create_kdf();
+ BOTAN_ASSERT(kdf != nullptr, "KDF is found");
+
+ PointGFp other_point = other_public_key_point;
+
+ // ISO 18033: step b
+ if(m_params.old_cofactor_mode())
+ {
+ other_point *= m_params.domain().get_cofactor();
+ }
+
+ secure_vector<byte> derivation_input;
+
+ // ISO 18033: encryption step e / decryption step g
+ if(!m_params.single_hash_mode())
+ {
+ derivation_input += eph_public_key_bin;
+ }
+
+ // ISO 18033: encryption step f / decryption step h
+ secure_vector<byte> other_public_key_bin = EC2OSP(other_point, static_cast<byte>(m_params.compression_type()));
+ // Note: the argument `m_params.secret_length()` passed for `key_len` will only be used by providers because
+ // "Raw" is passed to the `PK_Key_Agreement` if the implementation of botan is used.
+ const SymmetricKey peh = m_ka.derive_key(m_params.domain().get_order().bytes(), other_public_key_bin.data(), other_public_key_bin.size());
+ derivation_input.insert(derivation_input.end(), peh.begin(), peh.end());
+
+ // ISO 18033: encryption step g / decryption step i
+ return kdf->derive_key(m_params.secret_length(), derivation_input);
+ }
+
+
+ECIES_KA_Params::ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length,
+ PointGFp::Compression_Type compression_type, ECIES_Flags flags) :
+ m_domain(domain),
+ m_kdf_spec(kdf_spec),
+ m_length(length),
+ m_compression_mode(compression_type),
+ m_flags(flags)
+ {
+ }
+
+std::unique_ptr<KDF> ECIES_KA_Params::create_kdf() const
+ {
+ std::unique_ptr<KDF> kdf = Botan::KDF::create(m_kdf_spec);
+ if(kdf == nullptr)
+ {
+ throw Algorithm_Not_Found(m_kdf_spec);
+ }
+ return kdf;
+ }
+
+
+ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec,
+ const std::string& dem_algo_spec, size_t dem_key_len,
+ const std::string& mac_spec, size_t mac_key_len,
+ PointGFp::Compression_Type compression_type, ECIES_Flags flags) :
+ ECIES_KA_Params(domain, kdf_spec, dem_key_len + mac_key_len, compression_type, flags),
+ m_dem_spec(dem_algo_spec),
+ m_dem_keylen(dem_key_len),
+ m_mac_spec(mac_spec),
+ m_mac_keylen(mac_key_len)
+ {
+ // ISO 18033: "At most one of CofactorMode, OldCofactorMode, and CheckMode may be 1."
+ if(cofactor_mode() + old_cofactor_mode() + check_mode() > 1)
+ {
+ throw Invalid_Argument("ECIES: only one of cofactor_mode, old_cofactor_mode and check_mode can be set");
+ }
+ }
+
+ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec,
+ const std::string& dem_algo_spec, size_t dem_key_len,
+ const std::string& mac_spec, size_t mac_key_len) :
+ ECIES_System_Params(domain, kdf_spec, dem_algo_spec, dem_key_len, mac_spec, mac_key_len, PointGFp::UNCOMPRESSED,
+ ECIES_Flags::NONE)
+ {
+ }
+
+std::unique_ptr<MessageAuthenticationCode> ECIES_System_Params::create_mac() const
+ {
+ std::unique_ptr<MessageAuthenticationCode> mac = Botan::MessageAuthenticationCode::create(m_mac_spec);
+ if(mac == nullptr)
+ {
+ throw Algorithm_Not_Found(m_mac_spec);
+ }
+ return mac;
+ }
+
+std::unique_ptr<Keyed_Filter> ECIES_System_Params::create_cipher(Botan::Cipher_Dir direction) const
+ {
+ Keyed_Filter* cipher = get_cipher(m_dem_spec, direction);
+ if(cipher == nullptr)
+ {
+ throw Algorithm_Not_Found(m_dem_spec);
+ }
+ return std::unique_ptr<Keyed_Filter>(cipher);
+ }
+
+
+/*
+* ECIES_Encryptor Constructor
+*/
+ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params) :
+ m_ka(private_key, ecies_params, true),
+ m_params(ecies_params),
+ m_eph_public_key_bin(private_key.public_value()), // returns the uncompressed public key, see conversion below
+ m_iv(),
+ m_other_point(),
+ m_label()
+ {
+ if(ecies_params.compression_type() != PointGFp::UNCOMPRESSED)
+ {
+ // ISO 18033: step d
+ // convert only if necessary; m_eph_public_key_bin has been initialized with the uncompressed format
+ m_eph_public_key_bin = unlock(EC2OSP(OS2ECP(m_eph_public_key_bin, m_params.domain().get_curve()),
+ static_cast<byte>(ecies_params.compression_type())));
+ }
+ }
+
+/*
+* ECIES_Encryptor Constructor
+*/
+ECIES_Encryptor::ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params) :
+ ECIES_Encryptor(ECDH_PrivateKey(rng, ecies_params.domain()), ecies_params)
+ {
+ }
+
+
+/*
+* ECIES Encryption according to ISO 18033-2
+*/
+std::vector<byte> ECIES_Encryptor::enc(const byte data[], size_t length, RandomNumberGenerator&) const
+ {
+ if(m_other_point.is_zero())
+ {
+ throw Invalid_State("ECIES: the other key is zero");
+ }
+
+ const SymmetricKey secret_key = m_ka.derive_secret(m_eph_public_key_bin, m_other_point);
+
+ // encryption
+ std::unique_ptr<Keyed_Filter> cipher = m_params.create_cipher(ENCRYPTION);
+ BOTAN_ASSERT(cipher != nullptr, "Cipher is found");
+
+ cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen()));
+ if(m_iv.size() != 0)
+ {
+ cipher->set_iv(m_iv);
+ }
+ Pipe pipe(cipher.release());
+ pipe.process_msg(data, length);
+ const secure_vector<byte> encrypted_data = pipe.read_all(0);
+
+ // concat elements
+ std::unique_ptr<MessageAuthenticationCode> mac = m_params.create_mac();
+ BOTAN_ASSERT(mac != nullptr, "MAC is found");
+
+ secure_vector<byte> out(m_eph_public_key_bin.size() + encrypted_data.size() + mac->output_length());
+ buffer_insert(out, 0, m_eph_public_key_bin);
+ buffer_insert(out, m_eph_public_key_bin.size(), encrypted_data);
+
+ // mac
+ mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen());
+ mac->update(encrypted_data);
+ if(!m_label.empty())
+ {
+ mac->update(m_label);
+ }
+ mac->final(out.data() + m_eph_public_key_bin.size() + encrypted_data.size());
+
+ return unlock(out);
+ }
+
+
+ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key, const ECIES_System_Params& ecies_params) :
+ m_ka(key, ecies_params, false),
+ m_params(ecies_params),
+ m_iv(),
+ m_label()
+ {
+ // ISO 18033: "If v > 1 and CheckMode = 0, then we must have gcd(�, v) = 1." (v = index, � = order)
+ if(!ecies_params.check_mode())
+ {
+ Botan::BigInt cofactor = m_params.domain().get_cofactor();
+ if(cofactor > 1 && Botan::gcd(cofactor, m_params.domain().get_order()) != 1)
+ {
+ throw Invalid_Argument("ECIES: gcd of cofactor and order must be 1 if check_mode is 0");
+ }
+ }
+ }
+
+/**
+* ECIES Decryption according to ISO 18033-2
+*/
+secure_vector<byte> ECIES_Decryptor::do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const
+ {
+ size_t point_size = m_params.domain().get_curve().get_p().bytes();
+ if(m_params.compression_type() != PointGFp::COMPRESSED)
+ {
+ point_size *= 2; // uncompressed and hybrid contains x AND y
+ }
+ point_size += 1; // format byte
+
+ std::unique_ptr<MessageAuthenticationCode> mac = m_params.create_mac();
+ BOTAN_ASSERT(mac != nullptr, "MAC is found");
+
+ if(in_len < point_size + mac->output_length())
+ {
+ throw Decoding_Error("ECIES decryption: ciphertext is too short");
+ }
+
+ // extract data
+ const std::vector<byte> other_public_key_bin(in, in + point_size); // the received (ephemeral) public key
+ const std::vector<byte> encrypted_data(in + point_size, in + in_len - mac->output_length());
+ const std::vector<byte> mac_data(in + in_len - mac->output_length(), in + in_len);
+
+ // ISO 18033: step a
+ PointGFp other_public_key = OS2ECP(other_public_key_bin, m_params.domain().get_curve());
+
+ // ISO 18033: step b
+ if(m_params.check_mode() && !other_public_key.on_the_curve())
+ {
+ throw Decoding_Error("ECIES decryption: received public key is not on the curve");
+ }
+
+ // ISO 18033: step e (and step f because get_affine_x (called by ECDH_KA_Operation::raw_agree)
+ // throws Illegal_Transformation if the point is zero)
+ const SymmetricKey secret_key = m_ka.derive_secret(other_public_key_bin, other_public_key);
+
+ // validate mac
+ mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen());
+ mac->update(encrypted_data);
+ if(!m_label.empty())
+ {
+ mac->update(m_label);
+ }
+ const secure_vector<byte> calculated_mac = mac->final();
+ valid_mask = CT::expand_mask<byte>(same_mem(mac_data.data(), calculated_mac.data(), mac_data.size()));
+
+ if(valid_mask)
+ {
+ // decrypt data
+ std::unique_ptr<Keyed_Filter> cipher = m_params.create_cipher(DECRYPTION);
+ BOTAN_ASSERT(cipher != nullptr, "Cipher is found");
+
+ cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen()));
+ if(m_iv.size() != 0)
+ {
+ cipher->set_iv(m_iv);
+ }
+
+ try
+ {
+ // the decryption can fail:
+ // e.g. Integrity_Failure is thrown if GCM is used and the message does not have a valid tag
+ Pipe pipe(cipher.release());
+ pipe.process_msg(encrypted_data);
+ return pipe.read_all(0);
+ }
+ catch(...)
+ {
+ valid_mask = 0;
+ }
+ }
+ return secure_vector<byte>();
+ }
+
+}
diff --git a/src/lib/pubkey/ecies/ecies.h b/src/lib/pubkey/ecies/ecies.h
new file mode 100644
index 000000000..07937556c
--- /dev/null
+++ b/src/lib/pubkey/ecies/ecies.h
@@ -0,0 +1,293 @@
+/*
+* ECIES
+* (C) 2016 Philipp Weber
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ECIES_H__
+#define BOTAN_ECIES_H__
+
+#include <botan/ecdh.h>
+#include <botan/ec_group.h>
+#include <botan/kdf.h>
+#include <botan/key_filt.h>
+#include <botan/mac.h>
+#include <botan/point_gfp.h>
+#include <botan/pubkey.h>
+#include <botan/secmem.h>
+#include <botan/symkey.h>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+enum class ECIES_Flags : uint32_t
+ {
+ NONE = 0,
+
+ /// if set: prefix the input of the (ecdh) key agreement with the encoded (ephemeral) public key
+ SINGLE_HASH_MODE = 1,
+
+ /// (decryption only) if set: use cofactor multiplication during (ecdh) key agreement
+ COFACTOR_MODE = 2,
+
+ /// if set: use ecdhc instead of ecdh
+ OLD_COFACTOR_MODE = 4,
+
+ /// (decryption only) if set: test if the (ephemeral) public key is on the curve
+ CHECK_MODE = 8
+ };
+
+inline ECIES_Flags operator |(ECIES_Flags a, ECIES_Flags b)
+ {
+ return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
+ }
+
+inline ECIES_Flags operator &(ECIES_Flags a, ECIES_Flags b)
+ {
+ return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
+ }
+
+/**
+* Parameters for ecies secret derivation
+*/
+class BOTAN_DLL ECIES_KA_Params
+ {
+ public:
+ /**
+ * @param domain ec domain parameters of the involved ec keys
+ * @param kdf_spec name of the key derivation function
+ * @param length length of the secret to be derived
+ * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used)
+ * @param flags options, see documentation of ECIES_Flags
+ */
+ ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length,
+ PointGFp::Compression_Type compression_type, ECIES_Flags flags);
+
+ virtual ~ECIES_KA_Params() = default;
+
+ std::unique_ptr<KDF> create_kdf() const;
+
+ inline const EC_Group& domain() const
+ {
+ return m_domain;
+ }
+
+ inline size_t secret_length() const
+ {
+ return m_length;
+ }
+
+ inline bool single_hash_mode() const
+ {
+ return (m_flags & ECIES_Flags::SINGLE_HASH_MODE) == ECIES_Flags::SINGLE_HASH_MODE;
+ }
+
+ inline bool cofactor_mode() const
+ {
+ return (m_flags & ECIES_Flags::COFACTOR_MODE) == ECIES_Flags::COFACTOR_MODE;
+ }
+
+ inline bool old_cofactor_mode() const
+ {
+ return (m_flags & ECIES_Flags::OLD_COFACTOR_MODE) == ECIES_Flags::OLD_COFACTOR_MODE;
+ }
+
+ inline bool check_mode() const
+ {
+ return (m_flags & ECIES_Flags::CHECK_MODE) == ECIES_Flags::CHECK_MODE;
+ }
+
+ inline PointGFp::Compression_Type compression_type() const
+ {
+ return m_compression_mode;
+ }
+
+ private:
+ const EC_Group m_domain;
+ const std::string m_kdf_spec;
+ const size_t m_length;
+ const PointGFp::Compression_Type m_compression_mode;
+ const ECIES_Flags m_flags;
+ };
+
+
+class BOTAN_DLL ECIES_System_Params : public ECIES_KA_Params
+ {
+ public:
+ /**
+ * @param domain ec domain parameters of the involved ec keys
+ * @param kdf_spec name of the key derivation function
+ * @param dem_algo_spec name of the data encryption method
+ * @param dem_key_len length of the key used for the data encryption method
+ * @param mac_spec name of the message authentication code
+ * @param mac_key_len length of the key used for the message authentication code
+ * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used)
+ * @param flags options, see documentation of ECIES_Flags
+ */
+ ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec,
+ size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len);
+
+ /**
+ * @param domain ec domain parameters of the involved ec keys
+ * @param kdf_spec name of the key derivation function
+ * @param dem_algo_spec name of the data encryption method
+ * @param dem_key_len length of the key used for the data encryption method
+ * @param mac_spec name of the message authentication code
+ * @param mac_key_len length of the key used for the message authentication code
+ */
+ ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec,
+ size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len,
+ PointGFp::Compression_Type compression_type, ECIES_Flags flags);
+
+ virtual ~ECIES_System_Params() = default;
+
+ /// creates an instance of the message authentication code
+ std::unique_ptr<MessageAuthenticationCode> create_mac() const;
+
+ /// creates an instance of the data encryption method
+ std::unique_ptr<Keyed_Filter> create_cipher(Botan::Cipher_Dir direction) const;
+
+ /// returns the length of the key used by the data encryption method
+ inline size_t dem_keylen() const
+ {
+ return m_dem_keylen;
+ }
+
+ /// returns the length of the key used by the message authentication code
+ inline size_t mac_keylen() const
+ {
+ return m_mac_keylen;
+ }
+
+ private:
+ const std::string m_dem_spec;
+ const size_t m_dem_keylen;
+ const std::string m_mac_spec;
+ const size_t m_mac_keylen;
+ };
+
+
+/**
+* ECIES secret derivation according to ISO 18033-2
+*/
+class BOTAN_DLL ECIES_KA_Operation
+ {
+ public:
+ /**
+ * @param private_key the (ephemeral) private key which is used to derive the secret
+ * @param ecies_params settings for ecies
+ * @param for_encryption disable cofactor mode if the secret will be used for encryption
+ * (according to ISO 18033 cofactor mode is only used during decryption)
+ */
+ ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params,
+ bool for_encryption);
+
+ /**
+ * Performs a key agreement with the provided keys and derives the secret from the result
+ * @param eph_public_key_bin the encoded (ephemeral) public key which belongs to the used (ephemeral) private key
+ * @param other_public_key_point public key point of the other party
+ */
+ SymmetricKey derive_secret(const std::vector<byte>& eph_public_key_bin,
+ const PointGFp& other_public_key_point) const;
+
+ private:
+ const PK_Key_Agreement m_ka;
+ const ECIES_KA_Params m_params;
+ };
+
+
+/**
+* ECIES Encryption according to ISO 18033-2
+*/
+class BOTAN_DLL ECIES_Encryptor : public PK_Encryptor
+ {
+ public:
+ /**
+ * @param private_key the (ephemeral) private key which is used for the key agreement
+ * @param ecies_params settings for ecies
+ */
+ ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params);
+
+ /**
+ * Creates an ephemeral private key which is used for the key agreement
+ * @param rng random generator used during private key generation
+ * @param ecies_params settings for ecies
+ */
+ ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params);
+
+ /// Set the public key of the other party
+ inline void set_other_key(const Botan::PointGFp& public_point)
+ {
+ m_other_point = public_point;
+ }
+
+ /// Set the initialization vector for the data encryption method
+ inline void set_initialization_vector(const InitializationVector& iv)
+ {
+ m_iv = iv;
+ }
+
+ /// Set the label which is appended to the input for the message authentication code
+ inline void set_label(const std::string& label)
+ {
+ m_label = std::vector<byte>(label.begin(), label.end());
+ }
+
+ private:
+ std::vector<byte> enc(const byte data[], size_t length, RandomNumberGenerator&) const override;
+
+ inline size_t maximum_input_size() const override
+ {
+ return std::numeric_limits<size_t>::max();
+ }
+
+ const ECIES_KA_Operation m_ka;
+ const ECIES_System_Params m_params;
+ std::vector<byte> m_eph_public_key_bin;
+ InitializationVector m_iv;
+ PointGFp m_other_point;
+ std::vector<byte> m_label;
+ };
+
+
+/**
+* ECIES Decryption according to ISO 18033-2
+*/
+class BOTAN_DLL ECIES_Decryptor : public PK_Decryptor
+ {
+ public:
+ /**
+ * @param private_key the private key which is used for the key agreement
+ * @param ecies_params settings for ecies
+ */
+ ECIES_Decryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params);
+
+ /// Set the initialization vector for the data encryption method
+ inline void set_initialization_vector(const InitializationVector& iv)
+ {
+ m_iv = iv;
+ }
+
+ /// Set the label which is appended to the input for the message authentication code
+ inline void set_label(const std::string& label)
+ {
+ m_label = std::vector<byte>(label.begin(), label.end());
+ }
+
+ private:
+ secure_vector<byte> do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const;
+
+ const ECIES_KA_Operation m_ka;
+ const ECIES_System_Params m_params;
+ InitializationVector m_iv;
+ std::vector<byte> m_label;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ecies/info.txt b/src/lib/pubkey/ecies/info.txt
new file mode 100644
index 000000000..dacefc88a
--- /dev/null
+++ b/src/lib/pubkey/ecies/info.txt
@@ -0,0 +1,9 @@
+define ECIES 20160128
+
+<requires>
+kdf
+mac
+ecdh
+modes
+filters
+</requires> \ No newline at end of file