#include #include #include "kyber512r3_params.h" #include "kyber512r3_symmetric.h" #include "kyber512r3_indcpa.h" #include "tls/s2n_kem.h" #include "utils/s2n_safety.h" #include "pq-crypto/s2n_pq_random.h" #include "pq-crypto/s2n_pq.h" /************************************************* * Name: crypto_kem_keypair * * Description: Generates public and private key * for CCA-secure Kyber key encapsulation mechanism * * Arguments: - unsigned char *pk: pointer to output public key * (an already allocated array of S2N_KYBER_512_R3_PUBLIC_KEY_BYTES bytes) * - unsigned char *sk: pointer to output private key * (an already allocated array of S2N_KYBER_512_R3_SECRET_KEY_BYTES bytes) * * Returns 0 (success) **************************************************/ int s2n_kyber_512_r3_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); POSIX_GUARD(indcpa_keypair(pk, sk)); for(size_t i = 0; i < S2N_KYBER_512_R3_INDCPA_PUBLICKEYBYTES; i++) { sk[i + S2N_KYBER_512_R3_INDCPA_SECRETKEYBYTES] = pk[i]; } sha3_256(sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-2*S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES); /* Value z for pseudo-random output on reject */ POSIX_GUARD_RESULT(s2n_get_random_bytes(sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-S2N_KYBER_512_R3_SYMBYTES, S2N_KYBER_512_R3_SYMBYTES)); return S2N_SUCCESS; } /************************************************* * Name: crypto_kem_enc * * Description: Generates cipher text and shared * secret for given public key * * Arguments: - unsigned char *ct: pointer to output cipher text * (an already allocated array of S2N_KYBER_512_R3_CIPHERTEXT_BYTES bytes) * - unsigned char *ss: pointer to output shared secret * (an already allocated array of S2N_KYBER_512_R3_SHARED_SECRET_BYTES bytes) * - const unsigned char *pk: pointer to input public key * (an already allocated array of S2N_KYBER_512_R3_PUBLIC_KEY_BYTES bytes) * * Returns 0 (success) **************************************************/ int s2n_kyber_512_r3_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); uint8_t buf[2*S2N_KYBER_512_R3_SYMBYTES]; /* Will contain key, coins */ uint8_t kr[2*S2N_KYBER_512_R3_SYMBYTES]; POSIX_GUARD_RESULT(s2n_get_random_bytes(buf, S2N_KYBER_512_R3_SYMBYTES)); /* Don't release system RNG output */ sha3_256(buf, buf, S2N_KYBER_512_R3_SYMBYTES); /* Multitarget countermeasure for coins + contributory KEM */ sha3_256(buf+S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES); sha3_512(kr, buf, 2*S2N_KYBER_512_R3_SYMBYTES); /* coins are in kr+S2N_KYBER_512_R3_SYMBYTES */ indcpa_enc(ct, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES); /* overwrite coins in kr with H(c) */ sha3_256(kr+S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES); /* hash concatenation of pre-k and H(c) to k */ shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2*S2N_KYBER_512_R3_SYMBYTES); return S2N_SUCCESS; } /************************************************* * Name: crypto_kem_dec * * Description: Generates shared secret for given * cipher text and private key * * Arguments: - unsigned char *ss: pointer to output shared secret * (an already allocated array of S2N_KYBER_512_R3_SHARED_SECRET_BYTES bytes) * - const unsigned char *ct: pointer to input cipher text * (an already allocated array of S2N_KYBER_512_R3_CIPHERTEXT_BYTES bytes) * - const unsigned char *sk: pointer to input private key * (an already allocated array of S2N_KYBER_512_R3_SECRET_KEY_BYTES bytes) * * Returns 0. * * On failure, ss will contain a pseudo-random value. **************************************************/ int s2n_kyber_512_r3_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); uint8_t buf[2*S2N_KYBER_512_R3_SYMBYTES]; /* Will contain key, coins */ uint8_t kr[2*S2N_KYBER_512_R3_SYMBYTES]; uint8_t cmp[S2N_KYBER_512_R3_CIPHERTEXT_BYTES]; const uint8_t *pk = sk+S2N_KYBER_512_R3_INDCPA_SECRETKEYBYTES; indcpa_dec(buf, ct, sk); /* Multitarget countermeasure for coins + contributory KEM */ for(size_t i = 0; i < S2N_KYBER_512_R3_SYMBYTES; i++) { buf[S2N_KYBER_512_R3_SYMBYTES + i] = sk[S2N_KYBER_512_R3_SECRET_KEY_BYTES - 2 * S2N_KYBER_512_R3_SYMBYTES + i]; } sha3_512(kr, buf, 2*S2N_KYBER_512_R3_SYMBYTES); /* coins are in kr+S2N_KYBER_512_R3_SYMBYTES */ indcpa_enc(cmp, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES); /* If ct and cmp are equal (dont_copy = 1), decryption has succeeded and we do NOT overwrite pre-k below. * If ct and cmp are not equal (dont_copy = 0), decryption fails and we do overwrite pre-k. */ int dont_copy = s2n_constant_time_equals(ct, cmp, S2N_KYBER_512_R3_CIPHERTEXT_BYTES); /* overwrite coins in kr with H(c) */ sha3_256(kr+S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES); /* Overwrite pre-k with z on re-encryption failure */ POSIX_GUARD(s2n_constant_time_copy_or_dont(kr, sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-S2N_KYBER_512_R3_SYMBYTES, S2N_KYBER_512_R3_SYMBYTES, dont_copy)); /* hash concatenation of pre-k and H(c) to k */ shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2*S2N_KYBER_512_R3_SYMBYTES); return S2N_SUCCESS; }