diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/pubkey/pubkey.h')
-rw-r--r-- | comm/third_party/botan/src/lib/pubkey/pubkey.h | 800 |
1 files changed, 800 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/pubkey/pubkey.h b/comm/third_party/botan/src/lib/pubkey/pubkey.h new file mode 100644 index 0000000000..2aa8ea9164 --- /dev/null +++ b/comm/third_party/botan/src/lib/pubkey/pubkey.h @@ -0,0 +1,800 @@ +/* +* Public Key Interface +* (C) 1999-2010 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_PUBKEY_H_ +#define BOTAN_PUBKEY_H_ + +#include <botan/pk_keys.h> +#include <botan/pk_ops_fwd.h> +#include <botan/symkey.h> +#include <string> + +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> + #define BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS +#endif + +namespace Botan { + +class RandomNumberGenerator; + +/** +* Public Key Encryptor +* This is the primary interface for public key encryption +*/ +class BOTAN_PUBLIC_API(2,0) PK_Encryptor + { + public: + + /** + * Encrypt a message. + * @param in the message as a byte array + * @param length the length of the above byte array + * @param rng the random number source to use + * @return encrypted message + */ + std::vector<uint8_t> encrypt(const uint8_t in[], size_t length, + RandomNumberGenerator& rng) const + { + return enc(in, length, rng); + } + + /** + * Encrypt a message. + * @param in the message + * @param rng the random number source to use + * @return encrypted message + */ + template<typename Alloc> + std::vector<uint8_t> encrypt(const std::vector<uint8_t, Alloc>& in, + RandomNumberGenerator& rng) const + { + return enc(in.data(), in.size(), rng); + } + + /** + * Return the maximum allowed message size in bytes. + * @return maximum message size in bytes + */ + virtual size_t maximum_input_size() const = 0; + + /** + * Return an upper bound on the ciphertext length + */ + virtual size_t ciphertext_length(size_t ctext_len) const = 0; + + PK_Encryptor() = default; + virtual ~PK_Encryptor() = default; + + PK_Encryptor(const PK_Encryptor&) = delete; + PK_Encryptor& operator=(const PK_Encryptor&) = delete; + + private: + virtual std::vector<uint8_t> enc(const uint8_t[], size_t, + RandomNumberGenerator&) const = 0; + }; + +/** +* Public Key Decryptor +*/ +class BOTAN_PUBLIC_API(2,0) PK_Decryptor + { + public: + /** + * Decrypt a ciphertext, throwing an exception if the input + * seems to be invalid (eg due to an accidental or malicious + * error in the ciphertext). + * + * @param in the ciphertext as a byte array + * @param length the length of the above byte array + * @return decrypted message + */ + secure_vector<uint8_t> decrypt(const uint8_t in[], size_t length) const; + + /** + * Same as above, but taking a vector + * @param in the ciphertext + * @return decrypted message + */ + template<typename Alloc> + secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc>& in) const + { + return decrypt(in.data(), in.size()); + } + + /** + * Decrypt a ciphertext. If the ciphertext is invalid (eg due to + * invalid padding) or is not the expected length, instead + * returns a random string of the expected length. Use to avoid + * oracle attacks, especially against PKCS #1 v1.5 decryption. + */ + secure_vector<uint8_t> + decrypt_or_random(const uint8_t in[], + size_t length, + size_t expected_pt_len, + RandomNumberGenerator& rng) const; + + /** + * Decrypt a ciphertext. If the ciphertext is invalid (eg due to + * invalid padding) or is not the expected length, instead + * returns a random string of the expected length. Use to avoid + * oracle attacks, especially against PKCS #1 v1.5 decryption. + * + * Additionally checks (also in const time) that: + * contents[required_content_offsets[i]] == required_content_bytes[i] + * for 0 <= i < required_contents + * + * Used for example in TLS, which encodes the client version in + * the content bytes: if there is any timing variation the version + * check can be used as an oracle to recover the key. + */ + secure_vector<uint8_t> + decrypt_or_random(const uint8_t in[], + size_t length, + size_t expected_pt_len, + RandomNumberGenerator& rng, + const uint8_t required_content_bytes[], + const uint8_t required_content_offsets[], + size_t required_contents) const; + + /** + * Return an upper bound on the plaintext length for a particular + * ciphertext input length + */ + virtual size_t plaintext_length(size_t ctext_len) const = 0; + + PK_Decryptor() = default; + virtual ~PK_Decryptor() = default; + + PK_Decryptor(const PK_Decryptor&) = delete; + PK_Decryptor& operator=(const PK_Decryptor&) = delete; + + private: + virtual secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask, + const uint8_t in[], size_t in_len) const = 0; + }; + +/** +* Public Key Signer. Use the sign_message() functions for small +* messages. Use multiple calls update() to process large messages and +* generate the signature by finally calling signature(). +*/ +class BOTAN_PUBLIC_API(2,0) PK_Signer final + { + public: + + /** + * Construct a PK Signer. + * @param key the key to use inside this signer + * @param rng the random generator to use + * @param emsa the EMSA to use + * An example would be "EMSA1(SHA-224)". + * @param format the signature format to use + * @param provider the provider to use + */ + PK_Signer(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& emsa, + Signature_Format format = IEEE_1363, + const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct a PK Signer. + * @param key the key to use inside this signer + * @param emsa the EMSA to use + * An example would be "EMSA1(SHA-224)". + * @param format the signature format to use + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Signer(const Private_Key& key, + const std::string& emsa, + Signature_Format format = IEEE_1363, + const std::string& provider = "") : + PK_Signer(key, system_rng(), emsa, format, provider) + {} +#endif + + ~PK_Signer(); + + PK_Signer(const PK_Signer&) = delete; + PK_Signer& operator=(const PK_Signer&) = delete; + + /** + * Sign a message all in one go + * @param in the message to sign as a byte array + * @param length the length of the above byte array + * @param rng the rng to use + * @return signature + */ + std::vector<uint8_t> sign_message(const uint8_t in[], size_t length, + RandomNumberGenerator& rng) + { + this->update(in, length); + return this->signature(rng); + } + + /** + * Sign a message. + * @param in the message to sign + * @param rng the rng to use + * @return signature + */ + template<typename Alloc> + std::vector<uint8_t> sign_message(const std::vector<uint8_t, Alloc>& in, + RandomNumberGenerator& rng) + { + return sign_message(in.data(), in.size(), rng); + } + + /** + * Add a message part (single byte). + * @param in the byte to add + */ + void update(uint8_t in) { update(&in, 1); } + + /** + * Add a message part. + * @param in the message part to add as a byte array + * @param length the length of the above byte array + */ + void update(const uint8_t in[], size_t length); + + /** + * Add a message part. + * @param in the message part to add + */ + template<typename Alloc> + void update(const std::vector<uint8_t, Alloc>& in) + { + update(in.data(), in.size()); + } + + /** + * Add a message part. + * @param in the message part to add + */ + void update(const std::string& in) + { + update(cast_char_ptr_to_uint8(in.data()), in.size()); + } + + /** + * Get the signature of the so far processed message (provided by the + * calls to update()). + * @param rng the rng to use + * @return signature of the total message + */ + std::vector<uint8_t> signature(RandomNumberGenerator& rng); + + + /** + * Set the output format of the signature. + * @param format the signature format to use + */ + void set_output_format(Signature_Format format) { m_sig_format = format; } + + /** + * Return an upper bound on the length of the signatures this + * PK_Signer will produce + */ + size_t signature_length() const; + + private: + std::unique_ptr<PK_Ops::Signature> m_op; + Signature_Format m_sig_format; + size_t m_parts, m_part_size; + }; + +/** +* Public Key Verifier. Use the verify_message() functions for small +* messages. Use multiple calls update() to process large messages and +* verify the signature by finally calling check_signature(). +*/ +class BOTAN_PUBLIC_API(2,0) PK_Verifier final + { + public: + /** + * Construct a PK Verifier. + * @param pub_key the public key to verify against + * @param emsa the EMSA to use (eg "EMSA3(SHA-1)") + * @param format the signature format to use + * @param provider the provider to use + */ + PK_Verifier(const Public_Key& pub_key, + const std::string& emsa, + Signature_Format format = IEEE_1363, + const std::string& provider = ""); + + ~PK_Verifier(); + + PK_Verifier& operator=(const PK_Verifier&) = delete; + PK_Verifier(const PK_Verifier&) = delete; + + /** + * Verify a signature. + * @param msg the message that the signature belongs to, as a byte array + * @param msg_length the length of the above byte array msg + * @param sig the signature as a byte array + * @param sig_length the length of the above byte array sig + * @return true if the signature is valid + */ + bool verify_message(const uint8_t msg[], size_t msg_length, + const uint8_t sig[], size_t sig_length); + /** + * Verify a signature. + * @param msg the message that the signature belongs to + * @param sig the signature + * @return true if the signature is valid + */ + template<typename Alloc, typename Alloc2> + bool verify_message(const std::vector<uint8_t, Alloc>& msg, + const std::vector<uint8_t, Alloc2>& sig) + { + return verify_message(msg.data(), msg.size(), + sig.data(), sig.size()); + } + + /** + * Add a message part (single byte) of the message corresponding to the + * signature to be verified. + * @param in the byte to add + */ + void update(uint8_t in) { update(&in, 1); } + + /** + * Add a message part of the message corresponding to the + * signature to be verified. + * @param msg_part the new message part as a byte array + * @param length the length of the above byte array + */ + void update(const uint8_t msg_part[], size_t length); + + /** + * Add a message part of the message corresponding to the + * signature to be verified. + * @param in the new message part + */ + template<typename Alloc> + void update(const std::vector<uint8_t, Alloc>& in) + { + update(in.data(), in.size()); + } + + /** + * Add a message part of the message corresponding to the + * signature to be verified. + */ + void update(const std::string& in) + { + update(cast_char_ptr_to_uint8(in.data()), in.size()); + } + + /** + * Check the signature of the buffered message, i.e. the one build + * by successive calls to update. + * @param sig the signature to be verified as a byte array + * @param length the length of the above byte array + * @return true if the signature is valid, false otherwise + */ + bool check_signature(const uint8_t sig[], size_t length); + + /** + * Check the signature of the buffered message, i.e. the one build + * by successive calls to update. + * @param sig the signature to be verified + * @return true if the signature is valid, false otherwise + */ + template<typename Alloc> + bool check_signature(const std::vector<uint8_t, Alloc>& sig) + { + return check_signature(sig.data(), sig.size()); + } + + /** + * Set the format of the signatures fed to this verifier. + * @param format the signature format to use + */ + void set_input_format(Signature_Format format); + + private: + std::unique_ptr<PK_Ops::Verification> m_op; + Signature_Format m_sig_format; + size_t m_parts, m_part_size; + }; + +/** +* Object used for key agreement +*/ +class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final + { + public: + + /** + * Construct a PK Key Agreement. + * @param key the key to use + * @param rng the random generator to use + * @param kdf name of the KDF to use (or 'Raw' for no KDF) + * @param provider the algo provider to use (or empty for default) + */ + PK_Key_Agreement(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& kdf, + const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct a PK Key Agreement. + * @param key the key to use + * @param kdf name of the KDF to use (or 'Raw' for no KDF) + * @param provider the algo provider to use (or empty for default) + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Key_Agreement(const Private_Key& key, + const std::string& kdf, + const std::string& provider = "") : + PK_Key_Agreement(key, system_rng(), kdf, provider) + {} +#endif + + ~PK_Key_Agreement(); + + // For ECIES + PK_Key_Agreement& operator=(PK_Key_Agreement&&); + PK_Key_Agreement(PK_Key_Agreement&&); + + PK_Key_Agreement& operator=(const PK_Key_Agreement&) = delete; + PK_Key_Agreement(const PK_Key_Agreement&) = delete; + + /** + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(size_t key_len, + const uint8_t in[], + size_t in_len, + const uint8_t params[], + size_t params_len) const; + + /** + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(size_t key_len, + const std::vector<uint8_t>& in, + const uint8_t params[], + size_t params_len) const + { + return derive_key(key_len, in.data(), in.size(), + params, params_len); + } + + /** + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + */ + SymmetricKey derive_key(size_t key_len, + const uint8_t in[], size_t in_len, + const std::string& params = "") const + { + return derive_key(key_len, in, in_len, + cast_char_ptr_to_uint8(params.data()), + params.length()); + } + + /** + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param params extra derivation params + */ + SymmetricKey derive_key(size_t key_len, + const std::vector<uint8_t>& in, + const std::string& params = "") const + { + return derive_key(key_len, in.data(), in.size(), + cast_char_ptr_to_uint8(params.data()), + params.length()); + } + + /** + * Return the underlying size of the value that is agreed. + * If derive_key is called with a length of 0 with a "Raw" + * KDF, it will return a value of this size. + */ + size_t agreed_value_size() const; + + private: + std::unique_ptr<PK_Ops::Key_Agreement> m_op; + }; + +/** +* Encryption using a standard message recovery algorithm like RSA or +* ElGamal, paired with an encoding scheme like OAEP. +*/ +class BOTAN_PUBLIC_API(2,0) PK_Encryptor_EME final : public PK_Encryptor + { + public: + size_t maximum_input_size() const override; + + /** + * Construct an instance. + * @param key the key to use inside the encryptor + * @param rng the RNG to use + * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)") + * @param provider the provider to use + */ + PK_Encryptor_EME(const Public_Key& key, + RandomNumberGenerator& rng, + const std::string& padding, + const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct an instance. + * @param key the key to use inside the encryptor + * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)") + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Encryptor_EME(const Public_Key& key, + const std::string& padding, + const std::string& provider = "") : + PK_Encryptor_EME(key, system_rng(), padding, provider) {} +#endif + + ~PK_Encryptor_EME(); + + PK_Encryptor_EME& operator=(const PK_Encryptor_EME&) = delete; + PK_Encryptor_EME(const PK_Encryptor_EME&) = delete; + + /** + * Return an upper bound on the ciphertext length for a particular + * plaintext input length + */ + size_t ciphertext_length(size_t ptext_len) const override; + private: + std::vector<uint8_t> enc(const uint8_t[], size_t, + RandomNumberGenerator& rng) const override; + + std::unique_ptr<PK_Ops::Encryption> m_op; + }; + +/** +* Decryption with an MR algorithm and an EME. +*/ +class BOTAN_PUBLIC_API(2,0) PK_Decryptor_EME final : public PK_Decryptor + { + public: + /** + * Construct an instance. + * @param key the key to use inside the decryptor + * @param rng the random generator to use + * @param eme the EME to use + * @param provider the provider to use + */ + PK_Decryptor_EME(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& eme, + const std::string& provider = ""); + + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct an instance. + * @param key the key to use inside the decryptor + * @param eme the message encoding scheme to use (eg "OAEP(SHA-256)") + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Decryptor_EME(const Private_Key& key, + const std::string& eme, + const std::string& provider = "") : + PK_Decryptor_EME(key, system_rng(), eme, provider) {} +#endif + + size_t plaintext_length(size_t ptext_len) const override; + + ~PK_Decryptor_EME(); + PK_Decryptor_EME& operator=(const PK_Decryptor_EME&) = delete; + PK_Decryptor_EME(const PK_Decryptor_EME&) = delete; + private: + secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask, + const uint8_t in[], + size_t in_len) const override; + + std::unique_ptr<PK_Ops::Decryption> m_op; + }; + +/** +* Public Key Key Encapsulation Mechanism Encryption. +*/ +class BOTAN_PUBLIC_API(2,0) PK_KEM_Encryptor final + { + public: + /** + * Construct an instance. + * @param key the key to use inside the encryptor + * @param rng the RNG to use + * @param kem_param additional KEM parameters + * @param provider the provider to use + */ + PK_KEM_Encryptor(const Public_Key& key, + RandomNumberGenerator& rng, + const std::string& kem_param = "", + const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_KEM_Encryptor(const Public_Key& key, + const std::string& kem_param = "", + const std::string& provider = "") : + PK_KEM_Encryptor(key, system_rng(), kem_param, provider) {} +#endif + + ~PK_KEM_Encryptor(); + + PK_KEM_Encryptor& operator=(const PK_KEM_Encryptor&) = delete; + PK_KEM_Encryptor(const PK_KEM_Encryptor&) = delete; + + /** + * Generate a shared key for data encryption. + * @param out_encapsulated_key the generated encapsulated key + * @param out_shared_key the generated shared key + * @param desired_shared_key_len desired size of the shared key in bytes + * @param rng the RNG to use + * @param salt a salt value used in the KDF + * @param salt_len size of the salt value in bytes + */ + void encrypt(secure_vector<uint8_t>& out_encapsulated_key, + secure_vector<uint8_t>& out_shared_key, + size_t desired_shared_key_len, + Botan::RandomNumberGenerator& rng, + const uint8_t salt[], + size_t salt_len); + + /** + * Generate a shared key for data encryption. + * @param out_encapsulated_key the generated encapsulated key + * @param out_shared_key the generated shared key + * @param desired_shared_key_len desired size of the shared key in bytes + * @param rng the RNG to use + * @param salt a salt value used in the KDF + */ + template<typename Alloc> + void encrypt(secure_vector<uint8_t>& out_encapsulated_key, + secure_vector<uint8_t>& out_shared_key, + size_t desired_shared_key_len, + Botan::RandomNumberGenerator& rng, + const std::vector<uint8_t, Alloc>& salt) + { + this->encrypt(out_encapsulated_key, + out_shared_key, + desired_shared_key_len, + rng, + salt.data(), salt.size()); + } + + + /** + * Generate a shared key for data encryption. + * @param out_encapsulated_key the generated encapsulated key + * @param out_shared_key the generated shared key + * @param desired_shared_key_len desired size of the shared key in bytes + * @param rng the RNG to use + */ + void encrypt(secure_vector<uint8_t>& out_encapsulated_key, + secure_vector<uint8_t>& out_shared_key, + size_t desired_shared_key_len, + Botan::RandomNumberGenerator& rng) + { + this->encrypt(out_encapsulated_key, + out_shared_key, + desired_shared_key_len, + rng, + nullptr, + 0); + } + + private: + std::unique_ptr<PK_Ops::KEM_Encryption> m_op; + }; + +/** +* Public Key Key Encapsulation Mechanism Decryption. +*/ +class BOTAN_PUBLIC_API(2,0) PK_KEM_Decryptor final + { + public: + /** + * Construct an instance. + * @param key the key to use inside the decryptor + * @param rng the RNG to use + * @param kem_param additional KEM parameters + * @param provider the provider to use + */ + PK_KEM_Decryptor(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& kem_param = "", + const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_KEM_Decryptor(const Private_Key& key, + const std::string& kem_param = "", + const std::string& provider = "") : + PK_KEM_Decryptor(key, system_rng(), kem_param, provider) + {} +#endif + + ~PK_KEM_Decryptor(); + PK_KEM_Decryptor& operator=(const PK_KEM_Decryptor&) = delete; + PK_KEM_Decryptor(const PK_KEM_Decryptor&) = delete; + + /** + * Decrypts the shared key for data encryption. + * @param encap_key the encapsulated key + * @param encap_key_len size of the encapsulated key in bytes + * @param desired_shared_key_len desired size of the shared key in bytes + * @param salt a salt value used in the KDF + * @param salt_len size of the salt value in bytes + * @return the shared data encryption key + */ + secure_vector<uint8_t> decrypt(const uint8_t encap_key[], + size_t encap_key_len, + size_t desired_shared_key_len, + const uint8_t salt[], + size_t salt_len); + + /** + * Decrypts the shared key for data encryption. + * @param encap_key the encapsulated key + * @param encap_key_len size of the encapsulated key in bytes + * @param desired_shared_key_len desired size of the shared key in bytes + * @return the shared data encryption key + */ + secure_vector<uint8_t> decrypt(const uint8_t encap_key[], + size_t encap_key_len, + size_t desired_shared_key_len) + { + return this->decrypt(encap_key, encap_key_len, + desired_shared_key_len, + nullptr, 0); + } + + /** + * Decrypts the shared key for data encryption. + * @param encap_key the encapsulated key + * @param desired_shared_key_len desired size of the shared key in bytes + * @param salt a salt value used in the KDF + * @return the shared data encryption key + */ + template<typename Alloc1, typename Alloc2> + secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc1>& encap_key, + size_t desired_shared_key_len, + const std::vector<uint8_t, Alloc2>& salt) + { + return this->decrypt(encap_key.data(), encap_key.size(), + desired_shared_key_len, + salt.data(), salt.size()); + } + + private: + std::unique_ptr<PK_Ops::KEM_Decryption> m_op; + }; + +} + +#endif |