Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement low-level derand API for Kyber #1552

Merged
merged 5 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions crypto/kyber/pqcrystals_kyber_ref_common/indcpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,13 @@ void gen_matrix(polyvec *a, const uint8_t seed[KYBER_SYMBYTES], int transposed)
* Arguments: - uint8_t *pk: pointer to output public key
* (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
(of length KYBER_INDCPA_SECRETKEYBYTES bytes)
* (of length KYBER_INDCPA_SECRETKEYBYTES bytes)
* - const uint8_t *coins: pointer to input randomness
* (of length KYBER_SYMBYTES bytes)
**************************************************/
void indcpa_keypair(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES])
void indcpa_keypair_derand(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES],
const uint8_t coins[KYBER_SYMBYTES])
{
unsigned int i;
uint8_t buf[2*KYBER_SYMBYTES];
Expand All @@ -212,8 +215,7 @@ void indcpa_keypair(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t nonce = 0;
polyvec a[KYBER_K], e, pkpv, skpv;

pq_custom_randombytes(buf, KYBER_SYMBYTES);
hash_g(buf, buf, KYBER_SYMBYTES);
hash_g(buf, coins, KYBER_SYMBYTES);

gen_a(a, publicseed);

Expand Down
7 changes: 4 additions & 3 deletions crypto/kyber/pqcrystals_kyber_ref_common/indcpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

#define gen_matrix KYBER_NAMESPACE(gen_matrix)
void gen_matrix(polyvec *a, const uint8_t seed[KYBER_SYMBYTES], int transposed);
#define indcpa_keypair KYBER_NAMESPACE(indcpa_keypair)
void indcpa_keypair(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES]);
#define indcpa_keypair_derand KYBER_NAMESPACE(indcpa_keypair_derand)
void indcpa_keypair_derand(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES],
const uint8_t coins[KYBER_SYMBYTES]);

#define indcpa_enc KYBER_NAMESPACE(indcpa_enc)
void indcpa_enc(uint8_t c[KYBER_INDCPA_BYTES],
Expand Down
78 changes: 65 additions & 13 deletions crypto/kyber/pqcrystals_kyber_ref_common/kem.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
#include "kem.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "indcpa.h"
#include "params.h"
#include "symmetric.h"
#include "verify.h"
#include "../../rand_extra/pq_custom_randombytes.h"

/*************************************************
* Name: crypto_kem_keypair_derand
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - uint8_t *pk: pointer to output public key
* (an already allocated array of KYBER_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
* (an already allocated array of KYBER_SECRETKEYBYTES bytes)
* - uint8_t *coins: pointer to input randomness
* (an already allocated array filled with 2*KYBER_SYMBYTES random bytes)
**
* Returns 0 (success)
**************************************************/
int crypto_kem_keypair_derand(uint8_t *pk,
uint8_t *sk,
const uint8_t *coins)
{
indcpa_keypair_derand(pk, sk, coins);
memcpy(sk+KYBER_INDCPA_SECRETKEYBYTES, pk, KYBER_PUBLICKEYBYTES);
andrewhop marked this conversation as resolved.
Show resolved Hide resolved
hash_h(sk+KYBER_SECRETKEYBYTES-2*KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
/* Value z for pseudo-random output on reject */
memcpy(sk+KYBER_SECRETKEYBYTES-KYBER_SYMBYTES, coins+KYBER_SYMBYTES, KYBER_SYMBYTES);
dkostic marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also is there a way to test/ensure this is using a separate part of the coins? I verified the firs call up on 30 indcpa_keypair_derand(pk, sk, coins); uses KYBER_SYMBYTES and then here you offset that KYBER_SYMBYTES. But this seems fragile and could a future update to indcpa_keypair_derand read more data from the coins and we reuse a part of the coins in a dangerous way? Do you think it's reasonable for crypto_kem_keypair_derand to take two coin variables so it's easier to keep them separate? If we messed up this accounting would the KATs break?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather leave more invasive changes for later when we decide to do proper refactoring of Kyber/ML-KEM. Right now, I'm just trying to apply what's done in pq-crystals/kyber@289b852.

return 0;
}

/*************************************************
* Name: crypto_kem_keypair
*
Expand All @@ -23,18 +51,15 @@
int crypto_kem_keypair(uint8_t *pk,
uint8_t *sk)
{
size_t i;
indcpa_keypair(pk, sk);
for(i=0;i<KYBER_INDCPA_PUBLICKEYBYTES;i++)
sk[i+KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
hash_h(sk+KYBER_SECRETKEYBYTES-2*KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
/* Value z for pseudo-random output on reject */
pq_custom_randombytes(sk+KYBER_SECRETKEYBYTES-KYBER_SYMBYTES, KYBER_SYMBYTES);
uint8_t coins[2*KYBER_SYMBYTES];
pq_custom_randombytes(coins, KYBER_SYMBYTES);
pq_custom_randombytes(coins+KYBER_SYMBYTES, KYBER_SYMBYTES);
dkostic marked this conversation as resolved.
Show resolved Hide resolved
crypto_kem_keypair_derand(pk, sk, coins);
return 0;
}

/*************************************************
* Name: crypto_kem_enc
* Name: crypto_kem_enc_derand
*
* Description: Generates cipher text and shared
* secret for given public key
Expand All @@ -45,20 +70,22 @@ int crypto_kem_keypair(uint8_t *pk,
* (an already allocated array of KYBER_SSBYTES bytes)
* - const uint8_t *pk: pointer to input public key
* (an already allocated array of KYBER_PUBLICKEYBYTES bytes)
* - const uint8_t *coins: pointer to input randomness
* (an already allocated array filled with KYBER_SYMBYTES random bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_enc(uint8_t *ct,
uint8_t *ss,
const uint8_t *pk)
int crypto_kem_enc_derand(uint8_t *ct,
uint8_t *ss,
const uint8_t *pk,
const uint8_t *coins)
dkostic marked this conversation as resolved.
Show resolved Hide resolved
{
uint8_t buf[2*KYBER_SYMBYTES];
/* Will contain key, coins */
uint8_t kr[2*KYBER_SYMBYTES];

pq_custom_randombytes(buf, KYBER_SYMBYTES);
/* Don't release system RNG output */
hash_h(buf, buf, KYBER_SYMBYTES);
hash_h(buf, coins, KYBER_SYMBYTES);

/* Multitarget countermeasure for coins + contributory KEM */
hash_h(buf+KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
Expand All @@ -74,6 +101,31 @@ int crypto_kem_enc(uint8_t *ct,
return 0;
}

/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - uint8_t *ct: pointer to output cipher text
* (an already allocated array of KYBER_CIPHERTEXTBYTES bytes)
* - uint8_t *ss: pointer to output shared secret
* (an already allocated array of KYBER_SSBYTES bytes)
* - const uint8_t *pk: pointer to input public key
* (an already allocated array of KYBER_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_enc(uint8_t *ct,
uint8_t *ss,
const uint8_t *pk)
{
uint8_t coins[KYBER_SYMBYTES];
pq_custom_randombytes(coins, KYBER_SYMBYTES);
crypto_kem_enc_derand(ct, ss, pk, coins);
return 0;
}

/*************************************************
* Name: crypto_kem_dec
*
Expand Down
6 changes: 6 additions & 0 deletions crypto/kyber/pqcrystals_kyber_ref_common/kem.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@
#endif
#endif

#define crypto_kem_keypair_derand KYBER_NAMESPACE(keypair_derand)
int crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk, const uint8_t *coins);
dkostic marked this conversation as resolved.
Show resolved Hide resolved

#define crypto_kem_keypair KYBER_NAMESPACE(keypair)
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk);

#define crypto_kem_enc_derand KYBER_NAMESPACE(enc_derand)
int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss, const uint8_t *pk, const uint8_t *coins);

#define crypto_kem_enc KYBER_NAMESPACE(enc)
int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);

Expand Down
Loading