1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
#include <stddef.h>
#include <stdint.h>
#include "kyber512r3_params.h"
#include "kyber512r3_symmetric.h"
#include "kyber512r3_indcpa.h"
#include "kyber512r3_indcpa_avx2.h"
#include "tls/s2n_kem.h"
#include "utils/s2n_safety.h"
#include "pq-crypto/s2n_pq_random.h"
#include "pq-crypto/s2n_pq.h"
S2N_ENSURE_PORTABLE_OPTIMIZATIONS
/*************************************************
* 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(uint8_t *pk, uint8_t *sk)
{
POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
POSIX_GUARD(indcpa_keypair_avx2(pk, sk));
}else
#endif
{
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(uint8_t *ct, uint8_t *ss, const uint8_t *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 */
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
indcpa_enc_avx2(ct, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
}else
#endif
{
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(uint8_t *ss, const uint8_t *ct, const uint8_t *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;
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
indcpa_dec_avx2(buf, ct, sk);
}else
#endif
{
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 */
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
indcpa_enc_avx2(cmp, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
}else
#endif
{
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;
}
|