/* * Copyright (c) 2023, [MTG AG](https://www.mtg.de). * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RNP_KYBER_ECDH_COMPOSITE_H_ #define RNP_KYBER_ECDH_COMPOSITE_H_ #include "config.h" #include #include #include #include "crypto/rng.h" #include "crypto/kyber.h" #include "crypto/kyber_common.h" #include "crypto/ecdh.h" #include "crypto/exdsa_ecdhkem.h" #include struct pgp_kyber_ecdh_key_t; /* forward declaration */ class pgp_kyber_ecdh_composite_key_t { public: virtual ~pgp_kyber_ecdh_composite_key_t() = 0; static rnp_result_t gen_keypair(rnp::RNG * rng, pgp_kyber_ecdh_key_t *key, pgp_pubkey_alg_t alg); static size_t ecdh_curve_privkey_size(pgp_curve_t curve); static size_t ecdh_curve_pubkey_size(pgp_curve_t curve); static size_t ecdh_curve_ephemeral_size(pgp_curve_t curve); static size_t ecdh_curve_keyshare_size(pgp_curve_t curve); static pgp_curve_t pk_alg_to_curve_id(pgp_pubkey_alg_t pk_alg); static kyber_parameter_e pk_alg_to_kyber_id(pgp_pubkey_alg_t pk_alg); bool is_initialized() const { return is_initialized_; } protected: bool is_initialized_ = false; void initialized_or_throw() const; }; typedef struct pgp_kyber_ecdh_encrypted_t { std::vector composite_ciphertext; std::vector wrapped_sesskey; static size_t composite_ciphertext_size(pgp_pubkey_alg_t pk_alg) { return kyber_ciphertext_size( pgp_kyber_ecdh_composite_key_t::pk_alg_to_kyber_id(pk_alg)) + pgp_kyber_ecdh_composite_key_t::ecdh_curve_ephemeral_size( pgp_kyber_ecdh_composite_key_t::pk_alg_to_curve_id(pk_alg)); } } pgp_kyber_ecdh_encrypted_t; class pgp_kyber_ecdh_composite_private_key_t : public pgp_kyber_ecdh_composite_key_t { public: pgp_kyber_ecdh_composite_private_key_t(const uint8_t * key_encoded, size_t key_encoded_len, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_private_key_t(std::vector const &ecdh_key_encoded, std::vector const &kyber_key_encoded, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_private_key_t(std::vector const &key_encoded, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_private_key_t &operator=( const pgp_kyber_ecdh_composite_private_key_t &other); pgp_kyber_ecdh_composite_private_key_t( const pgp_kyber_ecdh_composite_private_key_t &other); pgp_kyber_ecdh_composite_private_key_t() = default; rnp_result_t decrypt(rnp::RNG * rng, uint8_t * out, size_t * out_len, const pgp_kyber_ecdh_encrypted_t *enc) const; bool is_valid(rnp::RNG *rng) const; std::vector get_encoded() const; pgp_pubkey_alg_t pk_alg() const { return pk_alg_; } void secure_clear(); static size_t encoded_size(pgp_pubkey_alg_t pk_alg); private: void parse_component_keys(std::vector key_encoded); pgp_pubkey_alg_t pk_alg_; /* kyber part */ std::unique_ptr kyber_key_; /* ecc part*/ std::unique_ptr ecdh_key_; }; class pgp_kyber_ecdh_composite_public_key_t : public pgp_kyber_ecdh_composite_key_t { public: pgp_kyber_ecdh_composite_public_key_t(const uint8_t * key_encoded, size_t key_encoded_len, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_public_key_t(std::vector const &ecdh_key_encoded, std::vector const &kyber_key_encoded, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_public_key_t(std::vector const &key_encoded, pgp_pubkey_alg_t pk_alg); pgp_kyber_ecdh_composite_public_key_t() = default; bool operator==(const pgp_kyber_ecdh_composite_public_key_t &rhs) const { return (pk_alg_ == rhs.pk_alg_) && (kyber_key_ == rhs.kyber_key_) && (ecdh_key_ == rhs.ecdh_key_); } rnp_result_t encrypt(rnp::RNG * rng, pgp_kyber_ecdh_encrypted_t *out, const uint8_t * in, size_t in_len) const; bool is_valid(rnp::RNG *rng) const; std::vector get_encoded() const; pgp_pubkey_alg_t pk_alg() const { return pk_alg_; } static size_t encoded_size(pgp_pubkey_alg_t pk_alg); private: void parse_component_keys(std::vector key_encoded); pgp_pubkey_alg_t pk_alg_; /* kyber part */ pgp_kyber_public_key_t kyber_key_; /* ecc part*/ ecdh_kem_public_key_t ecdh_key_; }; typedef struct pgp_kyber_ecdh_key_t { pgp_kyber_ecdh_composite_private_key_t priv; pgp_kyber_ecdh_composite_public_key_t pub; } pgp_kyber_ecdh_key_t; rnp_result_t kyber_ecdh_validate_key(rnp::RNG * rng, const pgp_kyber_ecdh_key_t *key, bool secret); #endif