/* * Copyright (C) 2022 - 2025, Stephan Mueller * * License: see LICENSE file in root directory * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /* * This code is derived in parts from the code distribution provided with * https://github.com/pq-crystals/kyber * * That code is released under Public Domain * (https://creativecommons.org/share-your-work/public-domain/cc0/). */ #ifndef LC_KYBER_768_H #define LC_KYBER_768_H #ifndef __ASSEMBLER__ #include "ext_headers.h" #include "lc_rng.h" #endif /* __ASSEMBLER__ */ #ifdef __cplusplus extern "C" { #endif /// \cond DO_NOT_DOCUMENT /* * Kyber 512: K == 2 - NIST security category 1 * Kyber 768: K == 3 - NIST security category 3 * Kyber 1024: K == 4 - NIST security category 5 */ #define LC_KYBER_K 3 #define LC_KYBER_N 256 #define LC_KYBER_Q 3329 #define LC_KYBER_SYMBYTES 32 /* size in bytes of hashes, and seeds */ #define LC_KYBER_SSBYTES 32 /* size in bytes of shared key */ #define LC_KYBER_POLYBYTES 384 #define LC_KYBER_POLYVECBYTES (LC_KYBER_K * LC_KYBER_POLYBYTES) #if LC_KYBER_K == 2 #define LC_KYBER_ETA1 3 #define LC_KYBER_POLYCOMPRESSEDBYTES 128 #define LC_KYBER_POLYVECCOMPRESSEDBYTES (LC_KYBER_K * 320) #elif LC_KYBER_K == 3 #define LC_KYBER_ETA1 2 #define LC_KYBER_POLYCOMPRESSEDBYTES 128 #define LC_KYBER_POLYVECCOMPRESSEDBYTES (LC_KYBER_K * 320) #elif LC_KYBER_K == 4 #define LC_KYBER_ETA1 2 #define LC_KYBER_POLYCOMPRESSEDBYTES 160 #define LC_KYBER_POLYVECCOMPRESSEDBYTES (LC_KYBER_K * 352) #endif #define LC_KYBER_ETA2 2 #define LC_KYBER_INDCPA_MSGBYTES (LC_KYBER_SYMBYTES) #define LC_KYBER_INDCPA_PUBLICKEYBYTES \ (LC_KYBER_POLYVECBYTES + LC_KYBER_SYMBYTES) #define LC_KYBER_INDCPA_SECRETKEYBYTES (LC_KYBER_POLYVECBYTES) #define LC_KYBER_INDCPA_BYTES \ (LC_KYBER_POLYVECCOMPRESSEDBYTES + LC_KYBER_POLYCOMPRESSEDBYTES) /* * Sizes of the different Kyber buffer types. * * WARNING: Do not use these defines in your code. If you need the sizes of * the different variable sizes, use sizeof of the different variable structs * or use the different *_size functions offered below for the particular sizes * of a given parameter. */ #define LC_KYBER_PUBLICKEYBYTES (LC_KYBER_INDCPA_PUBLICKEYBYTES) /* 32 bytes of additional space to save H(pk) */ #define LC_KYBER_SECRETKEYBYTES \ (LC_KYBER_INDCPA_SECRETKEYBYTES + LC_KYBER_INDCPA_PUBLICKEYBYTES + \ 2 * LC_KYBER_SYMBYTES) #define LC_KYBER_CIPHERTEXTBYTES (LC_KYBER_INDCPA_BYTES) #define LC_CRYPTO_SECRETKEYBYTES LC_KYBER_SECRETKEYBYTES #define LC_CRYPTO_PUBLICKEYBYTES LC_KYBER_PUBLICKEYBYTES #define LC_CRYPTO_CIPHERTEXTBYTES LC_KYBER_CIPHERTEXTBYTES #define LC_CRYPTO_BYTES LC_KYBER_SSBYTES /// \endcond #ifndef __ASSEMBLER__ /** * General KEM API considerations: * * * all APIs starting with lc_kyber_512 / lc_kex_512 use Kyber-512 * * all APIs starting with lc_kyber_768 / lc_kex_768 use Kyber-768 * * all APIs starting with lc_kyber_1024 / lc_kex_1024 use Kyber-1024 */ /************************************* KEM ************************************/ /** * @brief Kyber secret key */ struct lc_kyber_768_sk { uint8_t sk[LC_KYBER_SECRETKEYBYTES]; }; /** * @brief Kyber public key */ struct lc_kyber_768_pk { uint8_t pk[LC_KYBER_PUBLICKEYBYTES]; }; /** * @brief Kyber ciphertext */ struct lc_kyber_768_ct { uint8_t ct[LC_CRYPTO_CIPHERTEXTBYTES]; }; /** * @brief Kyber shared secret */ struct lc_kyber_768_ss { uint8_t ss[LC_KYBER_SSBYTES]; }; /** * @brief Return the size of the Kyber secret key. */ LC_PURE static inline unsigned int lc_kyber_768_sk_size(void) { return lc_member_size(struct lc_kyber_768_sk, sk); } /** * @brief Return the size of the Kyber public key. */ LC_PURE static inline unsigned int lc_kyber_768_pk_size(void) { return lc_member_size(struct lc_kyber_768_pk, pk); } /** * @brief Return the size of the Kyber ciphertext. */ LC_PURE static inline unsigned int lc_kyber_768_ct_size(void) { return lc_member_size(struct lc_kyber_768_ct, ct); } /** * @brief Return the size of the Kyber shared secret. */ LC_PURE static inline unsigned int lc_kyber_768_ss_size(void) { return lc_member_size(struct lc_kyber_768_ss, ss); } /** * @brief lc_kyber_keypair - Generates public and private key for * IND-CCA2-secure Kyber key encapsulation mechanism * * @param [out] pk pointer to already allocated output public key * @param [out] sk pointer to already allocated output private key * @param [in] rng_ctx pointer to seeded random number generator context * * @return 0 (success) or < 0 on error */ int lc_kyber_768_keypair(struct lc_kyber_768_pk *pk, struct lc_kyber_768_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @brief lc_kyber__keypair_from_seed - Generates Kyber public and private key * from a given seed. * * The idea of the function is the allowance of FIPS 203 to maintain the seed * used to generate a key pair in lieu of maintaining a private key or the * key pair (which used much more memory). The seed must be treated equally * sensitive as a private key. * * The seed is generated by simply obtaining 64 bytes from a properly seeded * DRNG, i.e. the same way as a symmetric key would be generated. * * Compliant to the notation of FIPS 203 the following definition applies: * seed = d || z * * @param [out] pk pointer to allocated output public key * @param [out] sk pointer to allocated output private key * @param [in] seed buffer with the seed data which must be exactly 64 bytes * in size * @param [in] seedlen length of the seed buffer * * @return 0 (success) or < 0 on error */ int lc_kyber_768_keypair_from_seed(struct lc_kyber_768_pk *pk, struct lc_kyber_768_sk *sk, const uint8_t *seed, size_t seedlen); /** * @brief lc_kyber_enc - Key encapsulation * * Generates cipher text and shared secret for given public key. * * @param [out] ct pointer to output cipher text to used for decapsulation * @param [out] ss pointer to output shared secret that will be also produced * during decapsulation * @param [in] pk pointer to input public key * * Returns 0 (success) or < 0 on error */ int lc_kyber_768_enc(struct lc_kyber_768_ct *ct, struct lc_kyber_768_ss *ss, const struct lc_kyber_768_pk *pk); /** * @brief lc_kyber_768_enc_kdf - Key encapsulation with KDF applied to shared secret * * Generates cipher text and shared secret for given public key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS, X = Kyber-CT, L = requested SS length, * S = "Kyber KEM SS") * * @param [out] ct pointer to output cipher text to used for decapsulation * @param [out] ss pointer to output shared secret that will be also produced * during decapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] pk pointer to input public key * * Returns 0 (success) or < 0 on error */ int lc_kyber_768_enc_kdf(struct lc_kyber_768_ct *ct, uint8_t *ss, size_t ss_len, const struct lc_kyber_768_pk *pk); /** * @brief lc_kyber_dec - Key decapsulation * * Generates shared secret for given cipher text and private key * * @param [out] ss pointer to output shared secret that is the same as produced * during encapsulation * @param [in] ct pointer to input cipher text generated during encapsulation * @param [in] sk pointer to input private key * * @return 0 * * On failure, ss will contain a pseudo-random value. */ int lc_kyber_768_dec(struct lc_kyber_768_ss *ss, const struct lc_kyber_768_ct *ct, const struct lc_kyber_768_sk *sk); /** * @brief lc_kyber_dec_kdf - Key decapsulation with KDF applied to shared secret * * Generates cipher text and shared secret for given private key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS, X = Kyber-CT, L = requested SS length, * S = "Kyber KEM SS") * * @param [out] ss pointer to output shared secret that is the same as produced * during encapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] ct pointer to input cipher text generated during encapsulation * @param [in] sk pointer to input private key * * @return 0 * * On failure, ss will contain a pseudo-random value. */ int lc_kyber_768_dec_kdf(uint8_t *ss, size_t ss_len, const struct lc_kyber_768_ct *ct, const struct lc_kyber_768_sk *sk); /************************************* KEX ************************************/ /** * Unilaterally authenticated key exchange * * The key exchange provides a shared secret between two communication parties. * Only the initiator authenticates the key exchange with his private key. * * The idea is that the pk_r/sk_r key pair is a static key pair that is * generated and exchanged before the KEX handshake. For the unilaterally * authenticated key exchange, only the initiator uses the responder's public * key which implies that the initiator authenticates the responder. *``` * Alice (initiator) Bob (responder) * * Step 1 generate static keypair * Result: * public key pk_r * secret key sk_r * * Step 2 send public key * pk_r <------------------------- pk_r * * Step 3 initiate key exchange * Result: * Public key pk_e_i * Cipher text ct_e_i * KEM shared secret tk * Secret key sk_e * * Step 4 send kex data * Public key pk_e_i ------------> Public key pk_e_i * Cipher text ct_e_i -----------> Cipher text ct_e_i * * Step 5 calculate shared secret * Result: * Cipher text ct_e_r * Shared secret SS * * Step 6 send kex data * Cipher text ct_e_r <----------- Cipher text ct_e_r * * Step 7 calculate shared secret * Result: * Shared secret SS *``` */ /** * @brief lc_kex_uake_initiator_init - Initialize unilaterally authenticated * key exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_uake_initiator_init(struct lc_kyber_768_pk *pk_e_i, struct lc_kyber_768_ct *ct_e_i, struct lc_kyber_768_ss *tk, struct lc_kyber_768_sk *sk_e, const struct lc_kyber_768_pk *pk_r); /** * @brief lc_kex_uake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r responder's ephemeral cipher text to be sent to the * initiator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initiator's ephemeral public key * @param [in] ct_e_i initiator's ephemeral cipher text * @param [in] sk_r responder's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_uake_responder_ss(struct lc_kyber_768_ct *ct_e_r, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_pk *pk_e_i, const struct lc_kyber_768_ct *ct_e_i, const struct lc_kyber_768_sk *sk_r); /** * @brief lc_kex_uake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initiator's initialization * @param [in] sk_e initiator's ephemeral secret that was generated during the * initiator's initialization * * @return 0 (success) or < 0 on error */ int lc_kex_768_uake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_ct *ct_e_r, const struct lc_kyber_768_ss *tk, const struct lc_kyber_768_sk *sk_e); /** * Authenticated key exchange * * The key exchange provides a shared secret between two communication parties. * The initiator and responder authenticates the key exchange with their private * keys. * * The idea is that the pk_i/sk_i and pk_r/sk_r key pairs are static key pairs * that are generated and exchanged before the KEX handshake. For the * authenticated key exchange, both sides use the respective peer's public key * which implies either side authenticates the other end. *``` * Alice (initiator) Bob (responder) * * Step 1 generate static keypair generate static keypair * Result: Result: * public key pk_i public key pk_r * secret key sk_i secret key sk_r * * Step 2 send public key send public key * pk_r <------------------------- pk_r * pk_i -------------------------> pk_i * * Step 3 initiate key exchange * Result: * Public key pk_e_i * Cipher text ct_e_i * KEM shared secret tk * Secret key sk_e * * Step 4 send kex data * Public key pk_e_i ------------> Public key pk_e_i * Cipher text ct_e_i -----------> Cipher text ct_e_i * * Step 5 calculate shared secret * Result: * Cipher text ct_e_r_1 * Cipher text ct_e_r_2 * Shared secret SS * * Step 6 send kex data * Cipher text ct_e_r_1 <--------- Cipher text ct_e_r_1 * Cipher text ct_e_r_2 <--------- Cipher text ct_e_r_2 * * Step 7 calculate shared secret * Result: * Shared secret SS *``` */ /** * @brief lc_kex_ake_initiator_init - Initialize authenticated key exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_ake_initiator_init(struct lc_kyber_768_pk *pk_e_i, struct lc_kyber_768_ct *ct_e_i, struct lc_kyber_768_ss *tk, struct lc_kyber_768_sk *sk_e, const struct lc_kyber_768_pk *pk_r); /** * @brief lc_kex_ake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r_1 responder's ephemeral cipher text to be sent to the * initator * @param [out] ct_e_r_2 responder's ephemeral cipher text to be sent to the * initator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initator's ephemeral public key * @param [in] ct_e_i initator's ephemeral cipher text * @param [in] sk_r responder's secret key * @param [in] pk_i initator's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_ake_responder_ss(struct lc_kyber_768_ct *ct_e_r_1, struct lc_kyber_768_ct *ct_e_r_2, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_pk *pk_e_i, const struct lc_kyber_768_ct *ct_e_i, const struct lc_kyber_768_sk *sk_r, const struct lc_kyber_768_pk *pk_i); /** * @brief lc_kex_ake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r_1 responder's ephemeral cipher text * @param [in] ct_e_r_2 responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initator's initialization * @param [in] sk_e initator's ephemeral secret that was generated during the * initator's initialization * @param [in] sk_i initator's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_ake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_ct *ct_e_r_1, const struct lc_kyber_768_ct *ct_e_r_2, const struct lc_kyber_768_ss *tk, const struct lc_kyber_768_sk *sk_e, const struct lc_kyber_768_sk *sk_i); /************************************* IES ************************************/ /* Macro set during leancrypto compile time for target platform */ #define LC_KYBER_IES #ifdef LC_KYBER_IES #include "lc_aead.h" /** * @brief lc_kyber_ies_enc - KyberIES encryption oneshot * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * * @return 0 on success, < 0 on error */ int lc_kyber_768_ies_enc(const struct lc_kyber_768_pk *pk, struct lc_kyber_768_ct *ct, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen, const uint8_t *aad, size_t aadlen, uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_ies_enc_init - KyberIES encryption stream operation * initialization * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_ies_enc_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * * @return 0 on success, < 0 on error */ int lc_kyber_768_ies_enc_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_pk *pk, struct lc_kyber_768_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_ies_enc_update - KyberIES encryption stream operation * add more data * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_ies_enc_update(struct lc_aead_ctx *aead, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen) { return lc_aead_enc_update(aead, plaintext, ciphertext, datalen); } /** * @brief lc_kyber_ies_enc_final - KyberIES encryption stream operation * finalization / integrity test * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_ies_enc_final(struct lc_aead_ctx *aead, uint8_t *tag, size_t taglen) { return lc_aead_enc_final(aead, tag, taglen); } /** * @brief lc_kyber_ies_dec - KyberIES decryption oneshot * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ int lc_kyber_768_ies_dec(const struct lc_kyber_768_sk *sk, const struct lc_kyber_768_ct *ct, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen, const uint8_t *aad, size_t aadlen, const uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_ies_dec_init - KyberIES decryption stream operation * initialization * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_768_ies_dec_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @return 0 on success, < 0 on error */ int lc_kyber_768_ies_dec_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_sk *sk, const struct lc_kyber_768_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_ies_dec_update - KyberIES decryption stream operation * add more data * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_ies_dec_update(struct lc_aead_ctx *aead, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen) { return lc_aead_dec_update(aead, ciphertext, plaintext, datalen); } /** * @brief lc_kyber_ies_dec_final - KyberIES decryption stream operation * finalization / integrity test * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ static inline int lc_kyber_768_ies_dec_final(struct lc_aead_ctx *aead, const uint8_t *tag, size_t taglen) { return lc_aead_dec_final(aead, tag, taglen); } #endif /* LC_KYBER_IES */ /****************************** Kyber X25519 KEM ******************************/ /* * The double KEM implements Kyber KEM together with the X25519 elliptic curve * KEX. The use is identical as the Kyber KEM. The only difference is that * the transmitted pk and ct has a different content. */ /* Macro set during leancrypto compile time for target platform */ #define LC_KYBER_X25519_KEM #ifdef LC_KYBER_X25519_KEM #include "lc_x25519.h" /** * @brief Kyber secret key */ struct lc_kyber_768_x25519_sk { struct lc_kyber_768_sk sk; struct lc_x25519_sk sk_x25519; }; /** * @brief Kyber public key */ struct lc_kyber_768_x25519_pk { struct lc_kyber_768_pk pk; struct lc_x25519_pk pk_x25519; }; /** * @brief Kyber ciphertext */ struct lc_kyber_768_x25519_ct { struct lc_kyber_768_ct ct; struct lc_x25519_pk pk_x25519; }; /** * @brief Kyber shared secret */ struct lc_kyber_768_x25519_ss { struct lc_kyber_768_ss ss; struct lc_x25519_ss ss_x25519; }; /** * @brief lc_kyber_x25519_keypair - Generates public and private key for * IND-CCA2-secure Kyber key encapsulation * mechanism * * @param [out] pk pointer to already allocated output public key * @param [out] sk pointer to already allocated output private key * @param [in] rng_ctx pointer to seeded random number generator context * * @return 0 (success) or < 0 on error */ int lc_kyber_768_x25519_keypair(struct lc_kyber_768_x25519_pk *pk, struct lc_kyber_768_x25519_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @brief lc_kyber_x25519_enc_kdf - Key encapsulation with KDF applied to shared * secret * * Generates cipher text and shared secret for given public key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS || X25519-SS, X = Kyber-CT, * L = requested SS length, S = "Kyber KEM Double SS") * * NOTE: The concatenatino of Kyber-SS || ECC-SS complies with SP800-56C rev 2 * chapter 2 defining the hybrid shared secret of the form Z' = Z || T where * Z is the "standard shared secret" from Kyber followed by the auxiliary * shared secret T that has been generated by some other method. * * @param [out] ct pointer to output cipher text to used for decapsulation * @param [out] ss pointer to output shared secret that will be also produced * during decapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] pk pointer to input public key * * Returns 0 (success) or < 0 on error */ int lc_kyber_768_x25519_enc_kdf(struct lc_kyber_768_x25519_ct *ct, uint8_t *ss, size_t ss_len, const struct lc_kyber_768_x25519_pk *pk); /** * @brief lc_kyber_x25519_dec_kdf - Key decapsulation with KDF applied to shared * secret * * Generates cipher text and shared secret for given private key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS || X25519-SS, X = Kyber-CT, * L = requested SS length, S = "Kyber KEM Double SS") * * @param [out] ss pointer to output shared secret that is the same as produced * during encapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] ct pointer to input cipher text generated during encapsulation * @param [in] sk pointer to input private key * * @return 0 * * On failure, ss will contain a pseudo-random value. */ int lc_kyber_768_x25519_dec_kdf(uint8_t *ss, size_t ss_len, const struct lc_kyber_768_x25519_ct *ct, const struct lc_kyber_768_x25519_sk *sk); /****************************** Kyber X25519 KEX ******************************/ /** * @brief lc_kex_x25519_uake_initiator_init - Initialize unilaterally * authenticated key exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_uake_initiator_init(struct lc_kyber_768_x25519_pk *pk_e_i, struct lc_kyber_768_x25519_ct *ct_e_i, struct lc_kyber_768_x25519_ss *tk, struct lc_kyber_768_x25519_sk *sk_e, const struct lc_kyber_768_x25519_pk *pk_r); /** * @brief lc_kex_x25519_uake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r responder's ephemeral cipher text to be sent to the * initiator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initiator's ephemeral public key * @param [in] ct_e_i initiator's ephemeral cipher text * @param [in] sk_r responder's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_uake_responder_ss(struct lc_kyber_768_x25519_ct *ct_e_r, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x25519_pk *pk_e_i, const struct lc_kyber_768_x25519_ct *ct_e_i, const struct lc_kyber_768_x25519_sk *sk_r); /** * @brief lc_kex_x25519_uake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initiator's initialization * @param [in] sk_e initiator's ephemeral secret that was generated during the * initiator's initialization * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_uake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x25519_ct *ct_e_r, const struct lc_kyber_768_x25519_ss *tk, const struct lc_kyber_768_x25519_sk *sk_e); /** * @brief lc_kex_x25519_ake_initiator_init - Initialize authenticated key * exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_ake_initiator_init(struct lc_kyber_768_x25519_pk *pk_e_i, struct lc_kyber_768_x25519_ct *ct_e_i, struct lc_kyber_768_x25519_ss *tk, struct lc_kyber_768_x25519_sk *sk_e, const struct lc_kyber_768_x25519_pk *pk_r); /** * @brief lc_kex_x25519_ake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r_1 responder's ephemeral cipher text to be sent to the * initator * @param [out] ct_e_r_2 responder's ephemeral cipher text to be sent to the * initator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initator's ephemeral public key * @param [in] ct_e_i initator's ephemeral cipher text * @param [in] sk_r responder's secret key * @param [in] pk_i initator's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_ake_responder_ss(struct lc_kyber_768_x25519_ct *ct_e_r_1, struct lc_kyber_768_x25519_ct *ct_e_r_2, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x25519_pk *pk_e_i, const struct lc_kyber_768_x25519_ct *ct_e_i, const struct lc_kyber_768_x25519_sk *sk_r, const struct lc_kyber_768_x25519_pk *pk_i); /** * @brief lc_kex_x25519_ake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r_1 responder's ephemeral cipher text * @param [in] ct_e_r_2 responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initator's initialization * @param [in] sk_e initator's ephemeral secret that was generated during the * initator's initialization * @param [in] sk_i initator's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x25519_ake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x25519_ct *ct_e_r_1, const struct lc_kyber_768_x25519_ct *ct_e_r_2, const struct lc_kyber_768_x25519_ss *tk, const struct lc_kyber_768_x25519_sk *sk_e, const struct lc_kyber_768_x25519_sk *sk_i); /****************************** Kyber X25519 IES ******************************/ #ifdef LC_KYBER_IES /** * @brief lc_kyber_x25519_ies_enc - KyberIES encryption oneshot * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * * @return 0 on success, < 0 on error */ int lc_kyber_768_x25519_ies_enc(const struct lc_kyber_768_x25519_pk *pk, struct lc_kyber_768_x25519_ct *ct, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen, const uint8_t *aad, size_t aadlen, uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_x25519_ies_enc_init - KyberIES encryption stream operation * initialization * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_x25519_ies_enc_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * * @return 0 on success, < 0 on error */ int lc_kyber_768_x25519_ies_enc_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_x25519_pk *pk, struct lc_kyber_768_x25519_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_x25519_ies_enc_update - KyberIES encryption stream operation * add more data * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer */ static inline int lc_kyber_768_x25519_ies_enc_update(struct lc_aead_ctx *aead, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen) { return lc_aead_enc_update(aead, plaintext, ciphertext, datalen); } /** * @brief lc_kyber_x25519_ies_enc_final - KyberIES encryption stream operation * finalization / integrity test * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_x25519_ies_enc_final(struct lc_aead_ctx *aead, uint8_t *tag, size_t taglen) { return lc_aead_enc_final(aead, tag, taglen); } /** * @brief lc_kyber_x25519_ies_dec - KyberIES decryption oneshot * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ int lc_kyber_768_x25519_ies_dec(const struct lc_kyber_768_x25519_sk *sk, const struct lc_kyber_768_x25519_ct *ct, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen, const uint8_t *aad, size_t aadlen, const uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_x25519_ies_dec_init - KyberIES decryption stream operation * initialization * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_x25519_ies_dec_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * * @return 0 on success, < 0 on error */ int lc_kyber_768_x25519_ies_dec_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_x25519_sk *sk, const struct lc_kyber_768_x25519_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_x25519_ies_dec_update - KyberIES decryption stream operation * add more data * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_x25519_ies_dec_update(struct lc_aead_ctx *aead, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen) { return lc_aead_dec_update(aead, ciphertext, plaintext, datalen); } /** * @brief lc_kyber _x25519_ies_dec_final - KyberIES decryption stream operation * finalization / integrity test * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ static inline int lc_kyber_768_x25519_ies_dec_final(struct lc_aead_ctx *aead, const uint8_t *tag, size_t taglen) { return lc_aead_dec_final(aead, tag, taglen); } #endif /* LC_KYBER_IES */ #endif /* LC_KYBER_X25519_KEM */ /****************************** Kyber X448 KEM ******************************/ /* * The double KEM implements Kyber KEM together with the X448 elliptic curve * KEX. The use is identical as the Kyber KEM. The only difference is that * the transmitted pk and ct has a different content. */ /* Macro set during leancrypto compile time for target platform */ #define LC_KYBER_X448_KEM #ifdef LC_KYBER_X448_KEM #include "lc_x448.h" /** * @brief Kyber secret key */ struct lc_kyber_768_x448_sk { struct lc_kyber_768_sk sk; struct lc_x448_sk sk_x448; }; /** * @brief Kyber public key */ struct lc_kyber_768_x448_pk { struct lc_kyber_768_pk pk; struct lc_x448_pk pk_x448; }; /** * @brief Kyber ciphertext */ struct lc_kyber_768_x448_ct { struct lc_kyber_768_ct ct; struct lc_x448_pk pk_x448; }; /** * @brief Kyber shared secret */ struct lc_kyber_768_x448_ss { struct lc_kyber_768_ss ss; struct lc_x448_ss ss_x448; }; /** * @brief lc_kyber_x448_keypair - Generates public and private key for * IND-CCA2-secure Kyber key encapsulation * mechanism * * @param [out] pk pointer to already allocated output public key * @param [out] sk pointer to already allocated output private key * @param [in] rng_ctx pointer to seeded random number generator context * * @return 0 (success) or < 0 on error */ int lc_kyber_768_x448_keypair(struct lc_kyber_768_x448_pk *pk, struct lc_kyber_768_x448_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @brief lc_kyber_x448_enc_kdf - Key encapsulation with KDF applied to shared * secret * * Generates cipher text and shared secret for given public key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS || X448-SS, X = Kyber-CT, * L = requested SS length, S = "Kyber KEM Double SS") * * NOTE: The concatenatino of Kyber-SS || ECC-SS complies with SP800-56C rev 2 * chapter 2 defining the hybrid shared secret of the form Z' = Z || T where * Z is the "standard shared secret" from Kyber followed by the auxiliary * shared secret T that has been generated by some other method. * * @param [out] ct pointer to output cipher text to used for decapsulation * @param [out] ss pointer to output shared secret that will be also produced * during decapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] pk pointer to input public key * * Returns 0 (success) or < 0 on error */ int lc_kyber_768_x448_enc_kdf(struct lc_kyber_768_x448_ct *ct, uint8_t *ss, size_t ss_len, const struct lc_kyber_768_x448_pk *pk); /** * @brief lc_kyber_x448_dec_kdf - Key decapsulation with KDF applied to shared * secret * * Generates cipher text and shared secret for given private key. The shared * secret is derived from the Kyber SS using the KDF derived from the round 3 * definition of Kyber: * * SS <- KMAC256(K = Kyber-SS || X448-SS, X = Kyber-CT, * L = requested SS length, S = "Kyber KEM Double SS") * * @param [out] ss pointer to output shared secret that is the same as produced * during encapsulation * @param [in] ss_len length of shared secret to be generated * @param [in] ct pointer to input cipher text generated during encapsulation * @param [in] sk pointer to input private key * * @return 0 * * On failure, ss will contain a pseudo-random value. */ int lc_kyber_768_x448_dec_kdf(uint8_t *ss, size_t ss_len, const struct lc_kyber_768_x448_ct *ct, const struct lc_kyber_768_x448_sk *sk); /****************************** Kyber X448 KEX ******************************/ /** * @brief lc_kex_x448_uake_initiator_init - Initialize unilaterally * authenticated key exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_uake_initiator_init(struct lc_kyber_768_x448_pk *pk_e_i, struct lc_kyber_768_x448_ct *ct_e_i, struct lc_kyber_768_x448_ss *tk, struct lc_kyber_768_x448_sk *sk_e, const struct lc_kyber_768_x448_pk *pk_r); /** * @brief lc_kex_x448_uake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r responder's ephemeral cipher text to be sent to the * initiator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initiator's ephemeral public key * @param [in] ct_e_i initiator's ephemeral cipher text * @param [in] sk_r responder's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_uake_responder_ss(struct lc_kyber_768_x448_ct *ct_e_r, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x448_pk *pk_e_i, const struct lc_kyber_768_x448_ct *ct_e_i, const struct lc_kyber_768_x448_sk *sk_r); /** * @brief lc_kex_x448_uake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initiator's initialization * @param [in] sk_e initiator's ephemeral secret that was generated during the * initiator's initialization * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_uake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x448_ct *ct_e_r, const struct lc_kyber_768_x448_ss *tk, const struct lc_kyber_768_x448_sk *sk_e); /** * @brief lc_kex_x448_ake_initiator_init - Initialize authenticated key * exchange * * @param [out] pk_e_i initiator's ephemeral public key to be sent to the * responder * @param [out] ct_e_i initiator's ephemeral cipher text to be sent to the * responder * @param [out] tk KEM shared secret data to be used for the initiator's shared * secret generation * @param [out] sk_e initiator's ephemeral secret key to be used for the * initiator's shared secret generation * @param [in] pk_r responder's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_ake_initiator_init(struct lc_kyber_768_x448_pk *pk_e_i, struct lc_kyber_768_x448_ct *ct_e_i, struct lc_kyber_768_x448_ss *tk, struct lc_kyber_768_x448_sk *sk_e, const struct lc_kyber_768_x448_pk *pk_r); /** * @brief lc_kex_x448_ake_responder_ss - Initiator's shared secret generation * * @param [out] ct_e_r_1 responder's ephemeral cipher text to be sent to the * initator * @param [out] ct_e_r_2 responder's ephemeral cipher text to be sent to the * initator * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] pk_e_i initator's ephemeral public key * @param [in] ct_e_i initator's ephemeral cipher text * @param [in] sk_r responder's secret key * @param [in] pk_i initator's public key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_ake_responder_ss(struct lc_kyber_768_x448_ct *ct_e_r_1, struct lc_kyber_768_x448_ct *ct_e_r_2, uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x448_pk *pk_e_i, const struct lc_kyber_768_x448_ct *ct_e_i, const struct lc_kyber_768_x448_sk *sk_r, const struct lc_kyber_768_x448_pk *pk_i); /** * @brief lc_kex_x448_ake_initiator_ss - Responder's shared secret generation * * @param [out] shared_secret Shared secret between initiator and responder * @param [in] shared_secret_len Requested size of the shared secret * @param [in] kdf_nonce An optional nonce that is concatenated at the end of * the Kyber KEX-generated data to be inserted into * the KDF. If not required, use NULL. * @param [in] kdf_nonce_len Length of the kdf_nonce. * @param [in] ct_e_r_1 responder's ephemeral cipher text * @param [in] ct_e_r_2 responder's ephemeral cipher text * @param [in] tk KEM shared secret data that was generated during the * initator's initialization * @param [in] sk_e initator's ephemeral secret that was generated during the * initator's initialization * @param [in] sk_i initator's secret key * * @return 0 (success) or < 0 on error */ int lc_kex_768_x448_ake_initiator_ss(uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *kdf_nonce, size_t kdf_nonce_len, const struct lc_kyber_768_x448_ct *ct_e_r_1, const struct lc_kyber_768_x448_ct *ct_e_r_2, const struct lc_kyber_768_x448_ss *tk, const struct lc_kyber_768_x448_sk *sk_e, const struct lc_kyber_768_x448_sk *sk_i); /****************************** Kyber X448 IES ******************************/ #ifdef LC_KYBER_IES /** * @brief lc_kyber_x448_ies_enc - KyberIES encryption oneshot * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * * @return 0 on success, < 0 on error */ int lc_kyber_768_x448_ies_enc(const struct lc_kyber_768_x448_pk *pk, struct lc_kyber_768_x448_ct *ct, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen, const uint8_t *aad, size_t aadlen, uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_x448_ies_enc_init - KyberIES encryption stream operation * initialization * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_x448_ies_enc_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] pk Kyber public key of data owner * @param [out] ct Kyber ciphertext to be sent to the decryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * * @return 0 on success, < 0 on error */ int lc_kyber_768_x448_ies_enc_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_x448_pk *pk, struct lc_kyber_768_x448_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_x448_ies_enc_update - KyberIES encryption stream operation * add more data * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] plaintext Plaintext data to be encrypted * @param [out] ciphertext Buffer of equal size as plaintext that will be filled * with the encryption result * @param [in] datalen Length of the plaintext buffer */ static inline int lc_kyber_768_x448_ies_enc_update(struct lc_aead_ctx *aead, const uint8_t *plaintext, uint8_t *ciphertext, size_t datalen) { return lc_aead_enc_update(aead, plaintext, ciphertext, datalen); } /** * @brief lc_kyber_x448_ies_enc_final - KyberIES encryption stream operation * finalization / integrity test * * The implementation supports an in-place data encryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [out] tag Buffer that will be filled with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_x448_ies_enc_final(struct lc_aead_ctx *aead, uint8_t *tag, size_t taglen) { return lc_aead_enc_final(aead, tag, taglen); } /** * @brief lc_kyber_x448_ies_dec - KyberIES decryption oneshot * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ int lc_kyber_768_x448_ies_dec(const struct lc_kyber_768_x448_sk *sk, const struct lc_kyber_768_x448_ct *ct, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen, const uint8_t *aad, size_t aadlen, const uint8_t *tag, size_t taglen, struct lc_aead_ctx *aead); /** * @brief lc_kyber_x448_ies_dec_init - KyberIES decryption stream operation * initialization * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * The aead context is initialized such that it can be used with * lc_kyber_x448_ies_dec_[update|final]. * * @param [out] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] sk Kyber secret key of data owner * @param [in] ct Kyber ciphertext received from the encryption operation * @param [in] aad Additional authenticate data to be processed - this is data * which is not encrypted, but considered as part of the * authentication. * @param [in] aadlen Length of the AAD buffer * * @return 0 on success, < 0 on error */ int lc_kyber_768_x448_ies_dec_init(struct lc_aead_ctx *aead, const struct lc_kyber_768_x448_sk *sk, const struct lc_kyber_768_x448_ct *ct, const uint8_t *aad, size_t aadlen); /** * @brief lc_kyber_x448_ies_dec_update - KyberIES decryption stream operation * add more data * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] ciphertext Ciphertext data to be encrypted * @param [out] plaintext Buffer of equal size as ciphertext that will be * filled with the decryption result * @param [in] datalen Length of the ciphertext buffer * * @return 0 on success, < 0 on error */ static inline int lc_kyber_768_x448_ies_dec_update(struct lc_aead_ctx *aead, const uint8_t *ciphertext, uint8_t *plaintext, size_t datalen) { return lc_aead_dec_update(aead, ciphertext, plaintext, datalen); } /** * @brief lc_kyber _x448_ies_dec_final - KyberIES decryption stream operation * finalization / integrity test * * The implementation supports an in-place data decryption where the * plaintext and ciphertext buffer pointers refer to the same memory location. * * The function entirely operates on stack memory. * * @param [in] aead Allocated AEAD algorithm - the caller only needs to provide * an allocated but otherwise unused instance of an AEAD * algorithm. This allows the caller to define the AEAD * algorithm type. The caller must zeroize and release the * context after completion. * @param [in] tag Buffer with the authentication tag * @param [in] taglen Length of the tag buffer * * @return 0 on success, < 0 on error (-EBADMSG on integrity error) */ static inline int lc_kyber_768_x448_ies_dec_final(struct lc_aead_ctx *aead, const uint8_t *tag, size_t taglen) { return lc_aead_dec_final(aead, tag, taglen); } #endif /* LC_KYBER_IES */ #endif /* LC_KYBER_X448_KEM */ #endif /* __ASSEMBLER__ */ /* * To allow including the different lc_kyber_*.h files, these macros need to be * undefined. Only during compilation of leancrypto, these macros remain defined * as this header file is not included multiple times. */ #ifndef LC_KYBER_INTERNAL #undef LC_KYBER_K #undef LC_KYBER_N #undef LC_KYBER_Q #undef LC_KYBER_SYMBYTES #undef LC_KYBER_SSBYTES #undef LC_KYBER_POLYBYTES #undef LC_KYBER_POLYVECBYTES #undef LC_KYBER_ETA1 #undef LC_KYBER_POLYCOMPRESSEDBYTES #undef LC_KYBER_POLYVECCOMPRESSEDBYTES #undef LC_KYBER_ETA2 #undef LC_KYBER_INDCPA_MSGBYTES #undef LC_KYBER_INDCPA_PUBLICKEYBYTES #undef LC_KYBER_INDCPA_SECRETKEYBYTES #undef LC_KYBER_INDCPA_BYTES #undef LC_KYBER_PUBLICKEYBYTES #undef LC_KYBER_SECRETKEYBYTES #undef LC_KYBER_CIPHERTEXTBYTES #undef LC_CRYPTO_SECRETKEYBYTES #undef LC_CRYPTO_PUBLICKEYBYTES #undef LC_CRYPTO_CIPHERTEXTBYTES #undef LC_CRYPTO_BYTES #endif /* LC_KYBER_INTERNAL */ #ifdef __cplusplus } #endif #endif /* LC_KYBER_768_H */