/* * Copyright (C) 2024 - 2026, 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. */ #ifndef LC_BIKE_H #define LC_BIKE_H #include "ext_headers.h" #if defined __has_include #if __has_include("lc_bike_5.h") #include "lc_bike_5.h" #define LC_BIKE_5_ENABLED #endif #if __has_include("lc_bike_3.h") #include "lc_bike_3.h" #define LC_BIKE_3_ENABLED #endif #if __has_include("lc_bike_1.h") #include "lc_bike_1.h" #define LC_BIKE_1_ENABLED #endif #else #error "Compiler misses __has_include" #endif #ifdef __cplusplus extern "C" { #endif enum lc_bike_type { LC_BIKE_UNKNOWN, /** Unknown key type */ LC_BIKE_5, /** BIKE 5 */ LC_BIKE_3, /** BIKE 3 */ LC_BIKE_1, /** BIKE 1 */ }; /** @defgroup BIKE BIKE Key Encapsulation Mechanism * * BIKE API concept * * The BIKE API is accessible via the following header files with the mentioned * purpose. * * * lc_bike.h: This API is the generic API allowing the caller to select * which BIKE type (BIKE 5, 3 or 1) are to be used. The selection is * made either with the flag specified during key generation or by matching * the size of the imported data with the different lc_bike_*_load API calls. * All remaining APIs take the information about the BIKE type from the * provided input data. * * This header file only provides inline functions which selectively call * the API provided with the header files below. * * * lc_bike_5.h: Direct access to BIKE 5. * * * lc_bike_3.h: Direct access to BIKE 3. * * * lc_bike_1.h: Direct access to BIKE 1. */ /************************************* KEM ************************************/ /** * @brief BIKE secret key */ struct lc_bike_sk { enum lc_bike_type bike_type; union { #ifdef LC_BIKE_5_ENABLED struct lc_bike_5_sk sk_5; #endif #ifdef LC_BIKE_3_ENABLED struct lc_bike_3_sk sk_3; #endif #ifdef LC_BIKE_1_ENABLED struct lc_bike_1_sk sk_1; #endif } key; }; /** * @brief BIKE public key */ struct lc_bike_pk { enum lc_bike_type bike_type; union { #ifdef LC_BIKE_5_ENABLED struct lc_bike_5_pk pk_5; #endif #ifdef LC_BIKE_3_ENABLED struct lc_bike_3_pk pk_3; #endif #ifdef LC_BIKE_1_ENABLED struct lc_bike_1_pk pk_1; #endif } key; }; /** * @brief BIKE ciphertext */ struct lc_bike_ct { enum lc_bike_type bike_type; union { #ifdef LC_BIKE_5_ENABLED struct lc_bike_5_ct ct_5; #endif #ifdef LC_BIKE_3_ENABLED struct lc_bike_3_ct ct_3; #endif #ifdef LC_BIKE_1_ENABLED struct lc_bike_1_ct ct_1; #endif } key; }; /** * @brief BIKE shared secret */ struct lc_bike_ss { enum lc_bike_type bike_type; union { #ifdef LC_BIKE_5_ENABLED struct lc_bike_5_ss ss_5; #endif #ifdef LC_BIKE_3_ENABLED struct lc_bike_3_ss ss_3; #endif #ifdef LC_BIKE_1_ENABLED struct lc_bike_1_ss ss_1; #endif } key; }; /** * @ingroup BIKE * @brief Obtain BIKE type from secret key * * @param [in] sk Secret key from which the type is to be obtained * * @return key type */ enum lc_bike_type lc_bike_sk_type(const struct lc_bike_sk *sk); /** * @ingroup BIKE * @brief Obtain BIKE type from public key * * @param [in] pk Public key from which the type is to be obtained * * @return key type */ enum lc_bike_type lc_bike_pk_type(const struct lc_bike_pk *pk); /** * @ingroup BIKE * @brief Obtain BIKE type from BIKE ciphertext * * @param [in] ct Ciphertext from which the type is to be obtained * * @return key type */ enum lc_bike_type lc_bike_ct_type(const struct lc_bike_ct *ct); /** * @ingroup BIKE * @brief Obtain BIKE type from shared secret * * @param [in] ss Shared secret key from which the type is to be obtained * * @return key type */ enum lc_bike_type lc_bike_ss_type(const struct lc_bike_ss *ss); /** * @ingroup BIKE * @brief Return the size of the BIKE secret key. * * @param [in] bike_type BIKE type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_bike_sk_size(enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief Return the size of the BIKE public key. * * @param [in] bike_type BIKE type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_bike_pk_size(enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief Return the size of the BIKE ciphertext. * * @param [in] bike_type BIKE type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_bike_ct_size(enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief Return the size of the BIKE shared secret. * * @param [in] bike_type BIKE type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_bike_ss_size(enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief Load a BIKE secret key provided with a buffer into the leancrypto * data structure. * * @param [out] sk Secret key to be filled (the caller must have it allocated) * @param [in] src_key Buffer that holds the key to be imported * @param [in] src_key_len Buffer length that holds the key to be imported * * @return 0 on success or < 0 on error */ int lc_bike_sk_load(struct lc_bike_sk *sk, const uint8_t *src_key, size_t src_key_len); /** * @ingroup BIKE * @brief Load a BIKE public key provided with a buffer into the leancrypto * data structure. * * @param [out] pk Public key to be filled (the caller must have it allocated) * @param [in] src_key Buffer that holds the key to be imported * @param [in] src_key_len Buffer length that holds the key to be imported * * @return 0 on success or < 0 on error */ int lc_bike_pk_load(struct lc_bike_pk *pk, const uint8_t *src_key, size_t src_key_len); /** * @ingroup BIKE * @brief Load a BIKE ciphertext key provided with a buffer into the leancrypto * data structure. * * @param [out] ct BIKE ciphertext to be filled (the caller must have it * allocated) * @param [in] src_key Buffer that holds the ciphertext to be imported * @param [in] src_key_len Buffer length that holds the ciphertext to be * imported * * @return 0 on success or < 0 on error */ int lc_bike_ct_load(struct lc_bike_ct *ct, const uint8_t *src_key, size_t src_key_len); /** * @ingroup BIKE * @brief Load a BIKE shared secret provided with a buffer into the leancrypto * data structure. * * @param [out] ss BIKE shared secret to be filled (the caller must have it * allocated) * @param [in] src_key Buffer that holds the shared secret to be imported * @param [in] src_key_len Buffer length that holds the shared secret to be * imported * * @return 0 on success or < 0 on error */ int lc_bike_ss_load(struct lc_bike_ss *ss, const uint8_t *src_key, size_t src_key_len); /** * @ingroup BIKE * @brief Obtain the reference to the BIKE key and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto key, too. * * @param [out] bike_key BIKE key pointer * @param [out] bike_key_len Length of the key buffer * @param [in] sk BIKE secret key from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_bike_sk_ptr(uint8_t **bike_key, size_t *bike_key_len, struct lc_bike_sk *sk); /** * @ingroup BIKE * @brief Obtain the reference to the BIKE key and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto key, too. * * @param [out] bike_key BIKE key pointer * @param [out] bike_key_len Length of the key buffer * @param [in] pk BIKE public key from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_bike_pk_ptr(uint8_t **bike_key, size_t *bike_key_len, struct lc_bike_pk *pk); /** * @ingroup BIKE * @brief Obtain the reference to the BIKE ciphertext and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto ciphertext, * too. * * @param [out] bike_ct BIKE ciphertext pointer * @param [out] bike_ct_len Length of the ciphertext buffer * @param [in] ct BIKE ciphertext from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_bike_ct_ptr(uint8_t **bike_ct, size_t *bike_ct_len, struct lc_bike_ct *ct); /** * @ingroup BIKE * @brief Obtain the reference to the BIKE shared secret and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto shared secret, * too. * * @param [out] bike_ss BIKE shared secret pointer * @param [out] bike_ss_len Length of the shared secret buffer * @param [in] ss BIKE shared secret from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_bike_ss_ptr(uint8_t **bike_ss, size_t *bike_ss_len, struct lc_bike_ss *ss); /** * @ingroup BIKE * @brief Generates public and private key for IND-CCA2-secure BIKE 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 * @param [in] bike_type type of the BIKE key to generate * * @return 0 (success) or < 0 on error */ int lc_bike_keypair(struct lc_bike_pk *pk, struct lc_bike_sk *sk, struct lc_rng_ctx *rng_ctx, enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief Generates BIKE 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. * * @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 * @param [in] bike_type type of the BIKE key to generate * * @return 0 (success) or < 0 on error */ int lc_bike_keypair_from_seed(struct lc_bike_pk *pk, struct lc_bike_sk *sk, const uint8_t *seed, size_t seedlen, enum lc_bike_type bike_type); /** * @ingroup BIKE * @brief 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_bike_enc(struct lc_bike_ct *ct, struct lc_bike_ss *ss, const struct lc_bike_pk *pk); /** * @ingroup BIKE * @brief 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 BIKE SS using the KDF derived from the round 3 * definition of BIKE: *``` * SS <- KMAC256(K = BIKE-SS, X = BIKE-CT, L = requested SS length, * S = "BIKE 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_bike_enc_kdf(struct lc_bike_ct *ct, uint8_t *ss, size_t ss_len, const struct lc_bike_pk *pk); /** * @ingroup BIKE * @brief 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_bike_dec(struct lc_bike_ss *ss, const struct lc_bike_ct *ct, const struct lc_bike_sk *sk); /** * @ingroup BIKE * @brief 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 BIKE SS using the KDF derived from the round 3 * definition of BIKE: *``` * SS <- KMAC256(K = BIKE-SS, X = BIKE-CT, L = requested SS length, * S = "BIKE 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_bike_dec_kdf(uint8_t *ss, size_t ss_len, const struct lc_bike_ct *ct, const struct lc_bike_sk *sk); enum lc_bike_alg_operation { /** Unknown operation */ lc_alg_operation_bike_unknown, /** BIKE: key generation operation */ lc_alg_operation_bike_keygen, /** BIKE: encapsulation operation */ lc_alg_operation_bike_enc, /** BIKE: decapsulation operation */ lc_alg_operation_bike_dec, /** BIKE: encapsulation operation with KDF */ lc_alg_operation_bike_enc_kdf, /** BIKE: decapsulation operation with KDF */ lc_alg_operation_bike_dec_kdf, }; /** * @ingroup BIKE * @brief Obtain algorithm status * * @param [in] bike_type BIKE algorithm type * @param [in] operation BIKE algorithm operation * * @return algorithm status */ enum lc_alg_status_val lc_bike_alg_status(const enum lc_bike_type bike_type, const enum lc_bike_alg_operation operation); #ifdef __cplusplus } #endif #endif /* LC_BIKE_H */