9 #include <botan/ecies.h>
10 #include <botan/cipher_mode.h>
12 #include <botan/internal/ct_utils.h>
13 #include <botan/internal/pk_ops_impl.h>
22 class ECIES_PrivateKey :
public EC_PrivateKey,
public PK_Key_Agreement_Key
25 explicit ECIES_PrivateKey(
const ECDH_PrivateKey& private_key) :
26 EC_PublicKey(private_key),
27 EC_PrivateKey(private_key),
28 PK_Key_Agreement_Key(),
33 std::vector<uint8_t> public_value()
const override
35 return m_key.public_value();
38 std::string algo_name()
const override
43 std::unique_ptr<PK_Ops::Key_Agreement>
44 create_key_agreement_op(RandomNumberGenerator& rng,
45 const std::string& params,
46 const std::string& provider)
const override;
55 class ECIES_ECDH_KA_Operation :
public PK_Ops::Key_Agreement_with_KDF
58 ECIES_ECDH_KA_Operation(
const ECIES_PrivateKey& private_key, RandomNumberGenerator& rng) :
59 PK_Ops::Key_Agreement_with_KDF(
"Raw"),
65 secure_vector<uint8_t> raw_agree(
const uint8_t w[],
size_t w_len)
override
67 const CurveGFp& curve =
m_key.domain().get_curve();
68 PointGFp point =
OS2ECP(w, w_len, curve);
69 Blinded_Point_Multiply blinder(point,
m_key.domain().get_order());
70 PointGFp S = blinder.blinded_multiply(
m_key.private_value(),
m_rng);
71 BOTAN_ASSERT(S.on_the_curve(),
"ECDH agreed value was on the curve");
76 ECIES_PrivateKey
m_key;
80 std::unique_ptr<PK_Ops::Key_Agreement>
81 ECIES_PrivateKey::create_key_agreement_op(RandomNumberGenerator& rng,
83 const std::string& )
const
85 return std::unique_ptr<PK_Ops::Key_Agreement>(
new ECIES_ECDH_KA_Operation(*
this, rng));
97 PK_Key_Agreement create_key_agreement(
const PK_Key_Agreement_Key& private_key,
98 const ECIES_KA_Params& ecies_params,
100 RandomNumberGenerator& rng)
102 const ECDH_PrivateKey* ecdh_key =
dynamic_cast<const ECDH_PrivateKey*
>(&private_key);
104 if(ecdh_key ==
nullptr && (ecies_params.cofactor_mode() || ecies_params.old_cofactor_mode()
105 || ecies_params.check_mode()))
111 throw Invalid_Argument(
"ECIES: cofactor, old cofactor and check mode are only supported for ECDH_PrivateKey");
114 if(ecdh_key && (for_encryption || !ecies_params.cofactor_mode()))
117 return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), rng,
"Raw");
120 return PK_Key_Agreement(private_key, rng,
"Raw");
128 m_ka(create_key_agreement(private_key, ecies_params, for_encryption, rng)),
129 m_params(ecies_params)
137 const PointGFp& other_public_key_point)
const
139 if(other_public_key_point.
is_zero())
146 PointGFp other_point = other_public_key_point;
159 derivation_input += eph_public_key_bin;
167 derivation_input.insert(derivation_input.end(), peh.
begin(), peh.
end());
170 return kdf->derive_key(m_params.
secret_length(), derivation_input);
177 m_kdf_spec(kdf_spec),
179 m_compression_mode(compression_type),
185 const std::string& dem_algo_spec,
size_t dem_key_len,
186 const std::string& mac_spec,
size_t mac_key_len,
188 ECIES_KA_Params(domain, kdf_spec, dem_key_len + mac_key_len, compression_type, flags),
189 m_dem_spec(dem_algo_spec),
190 m_dem_keylen(dem_key_len),
191 m_mac_spec(mac_spec),
192 m_mac_keylen(mac_key_len)
197 throw Invalid_Argument(
"ECIES: only one of cofactor_mode, old_cofactor_mode and check_mode can be set");
202 const std::string& dem_algo_spec,
size_t dem_key_len,
203 const std::string& mac_spec,
size_t mac_key_len) :
217 if(cipher ==
nullptr)
221 return std::unique_ptr<Cipher_Mode>(cipher);
231 m_ka(private_key, ecies_params, true, rng),
232 m_params(ecies_params),
233 m_eph_public_key_bin(private_key.public_value()),
259 std::vector<uint8_t> ECIES_Encryptor::enc(
const uint8_t data[],
size_t length,
RandomNumberGenerator&)
const
277 secure_vector<uint8_t> encrypted_data(data, data + length);
278 cipher->finish(encrypted_data);
281 std::unique_ptr<MessageAuthenticationCode> mac = m_params.
create_mac();
284 secure_vector<uint8_t> out(m_eph_public_key_bin.size() + encrypted_data.size() + mac->output_length());
286 buffer_insert(out, m_eph_public_key_bin.size(), encrypted_data);
290 mac->update(encrypted_data);
293 mac->update(m_label);
295 mac->final(out.data() + m_eph_public_key_bin.size() + encrypted_data.size());
304 m_ka(key, ecies_params, false, rng),
305 m_params(ecies_params),
315 throw Invalid_Argument(
"ECIES: gcd of cofactor and order must be 1 if check_mode is 0");
323 secure_vector<uint8_t> ECIES_Decryptor::do_decrypt(uint8_t& valid_mask,
const uint8_t in[],
size_t in_len)
const
332 std::unique_ptr<MessageAuthenticationCode> mac = m_params.
create_mac();
335 if(in_len < point_size + mac->output_length())
337 throw Decoding_Error(
"ECIES decryption: ciphertext is too short");
341 const std::vector<uint8_t> other_public_key_bin(in, in + point_size);
342 const std::vector<uint8_t> encrypted_data(in + point_size, in + in_len - mac->output_length());
343 const std::vector<uint8_t> mac_data(in + in_len - mac->output_length(), in + in_len);
349 if(m_params.
check_mode() && !other_public_key.on_the_curve())
351 throw Decoding_Error(
"ECIES decryption: received public key is not on the curve");
360 mac->update(encrypted_data);
363 mac->update(m_label);
365 const secure_vector<uint8_t> calculated_mac = mac->final();
366 valid_mask = CT::expand_mask<uint8_t>(
same_mem(mac_data.data(), calculated_mac.data(), mac_data.size()));
384 secure_vector<uint8_t> decrypted_data(encrypted_data.begin(), encrypted_data.end());
385 cipher->finish(decrypted_data);
386 return decrypted_data;
393 return secure_vector<uint8_t>();
secure_vector< uint8_t > bits_of() const
std::unique_ptr< MessageAuthenticationCode > create_mac() const
creates an instance of the message authentication code
ECIES_KA_Params(const EC_Group &domain, const std::string &kdf_spec, size_t length, PointGFp::Compression_Type compression_type, ECIES_Flags flags)
bool same_mem(const T *p1, const T *p2, size_t n)
secure_vector< uint8_t > EC2OSP(const PointGFp &point, uint8_t format)
BigInt gcd(const BigInt &a, const BigInt &b)
SymmetricKey derive_key(size_t key_len, const uint8_t in[], size_t in_len, const uint8_t params[], size_t params_len) const
Cipher_Mode * get_cipher_mode(const std::string &algo, Cipher_Dir direction)
size_t dem_keylen() const
returns the length of the key used by the data encryption method
SymmetricKey derive_secret(const std::vector< uint8_t > &eph_public_key_bin, const PointGFp &other_public_key_point) const
bool single_hash_mode() const
ECIES_Encryptor(const PK_Key_Agreement_Key &private_key, const ECIES_System_Params &ecies_params, RandomNumberGenerator &rng)
const uint8_t * end() const
const EC_Group & domain() const
#define BOTAN_ASSERT(expr, assertion_made)
ECIES_KA_Operation(const PK_Key_Agreement_Key &private_key, const ECIES_KA_Params &ecies_params, bool for_encryption, RandomNumberGenerator &rng)
const CurveGFp & get_curve() const
std::vector< T, secure_allocator< T >> secure_vector
size_t secret_length() const
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 OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
const BigInt & get_order() const
size_t mac_keylen() const
returns the length of the key used by the message authentication code
bool cofactor_mode() const
std::unique_ptr< Cipher_Mode > create_cipher(Botan::Cipher_Dir direction) const
creates an instance of the data encryption method
std::vector< T > unlock(const secure_vector< T > &in)
const BigInt & get_p() const
ECIES_Decryptor(const PK_Key_Agreement_Key &private_key, const ECIES_System_Params &ecies_params, RandomNumberGenerator &rng)
const std::string & kdf_spec() const
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
PointGFp::Compression_Type compression_type() const
const uint8_t * begin() const
static std::unique_ptr< KDF > create_or_throw(const std::string &algo_spec, const std::string &provider="")
RandomNumberGenerator & m_rng
const BigInt & get_cofactor() const
bool old_cofactor_mode() const