SIKE/p434 goes thru KATs
This commit is contained in:
parent
a2a2b08a84
commit
8711dcce1a
@ -18,6 +18,7 @@ Users shouldn't expect any level of security provided by this code. The library
|
|||||||
| Falcon | 2 | |
|
| Falcon | 2 | |
|
||||||
| Rainbow | 3 | |
|
| Rainbow | 3 | |
|
||||||
| SPHINCS+ SHA256/SHAKE256 | 3 | x |
|
| SPHINCS+ SHA256/SHAKE256 | 3 | x |
|
||||||
|
| SIKE/p434 | 3 | x |
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
@ -49,26 +49,33 @@
|
|||||||
const uint8_t priv_key[SIKE_PRV_BYTESZ]);
|
const uint8_t priv_key[SIKE_PRV_BYTESZ]);
|
||||||
|
|
||||||
// boilerplate needed for integration
|
// boilerplate needed for integration
|
||||||
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_SECRETKEYBYTES SIKE_PRV_BYTESZ
|
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_SECRETKEYBYTES SIKE_PRV_BYTESZ+SIKE_MSG_BYTESZ
|
||||||
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_PUBLICKEYBYTES SIKE_PUB_BYTESZ
|
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_PUBLICKEYBYTES SIKE_PUB_BYTESZ
|
||||||
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_CIPHERTEXTBYTES SIKE_CT_BYTESZ
|
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_CIPHERTEXTBYTES SIKE_CT_BYTESZ
|
||||||
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_BYTES SIKE_SS_BYTESZ
|
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_BYTES SIKE_SS_BYTESZ
|
||||||
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_ALGNAME "SIKE/p434"
|
#define PQCLEAN_SIKE434_CLEAN_CRYPTO_ALGNAME "SIKE/p434"
|
||||||
|
|
||||||
|
#define PQCLEAN_SIKE434_AVX2_CRYPTO_SECRETKEYBYTES SIKE_PRV_BYTESZ+SIKE_MSG_BYTESZ
|
||||||
|
#define PQCLEAN_SIKE434_AVX2_CRYPTO_PUBLICKEYBYTES SIKE_PUB_BYTESZ
|
||||||
|
#define PQCLEAN_SIKE434_AVX2_CRYPTO_CIPHERTEXTBYTES SIKE_CT_BYTESZ
|
||||||
|
#define PQCLEAN_SIKE434_AVX2_CRYPTO_BYTES SIKE_SS_BYTESZ
|
||||||
|
#define PQCLEAN_SIKE434_AVX2_CRYPTO_ALGNAME "SIKE/p434"
|
||||||
|
|
||||||
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
|
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
|
||||||
randombytes(sk, SIKE_MSG_BYTESZ);
|
SIKE_keypair(sk, pk);
|
||||||
SIKE_keypair(sk+SIKE_MSG_BYTESZ, pk);
|
// KATs require the public key to be concatenated after private key
|
||||||
memcpy(&sk[SIKE_PRV_BYTESZ+SIKE_MSG_BYTESZ], pk, SIKE_PUB_BYTESZ);
|
// OZAPTF: maybe change KAT tester
|
||||||
return 1;
|
memcpy(&sk[SIKE_MSG_BYTESZ+SIKE_PRV_BYTESZ], pk, SIKE_PUB_BYTESZ);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
|
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
|
||||||
SIKE_encaps(ss,ct,pk);
|
SIKE_encaps(ss,ct,pk);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
|
static inline int PQCLEAN_SIKE434_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
|
||||||
SIKE_decaps(ss, ct, &sk[SIKE_PRV_BYTESZ+SIKE_MSG_BYTESZ], sk);
|
SIKE_decaps(ss, ct, &sk[SIKE_PRV_BYTESZ+SIKE_MSG_BYTESZ], sk);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -411,10 +411,10 @@ int SIKE_keypair(uint8_t out_priv[SIKE_PRV_BYTESZ],
|
|||||||
uint8_t out_pub[SIKE_PUB_BYTESZ]) {
|
uint8_t out_pub[SIKE_PUB_BYTESZ]) {
|
||||||
// Calculate private key for Alice. Needs to be in range [0, 2^0xFA - 1] and <
|
// Calculate private key for Alice. Needs to be in range [0, 2^0xFA - 1] and <
|
||||||
// 253 bits
|
// 253 bits
|
||||||
randombytes(out_priv, SIKE_PRV_BYTESZ);
|
randombytes(out_priv, SIKE_MSG_BYTESZ);
|
||||||
out_priv[31] = (out_priv[31] | 0x01) & 0x03;
|
randombytes(&out_priv[SIKE_MSG_BYTESZ], SIKE_PRV_BYTESZ);
|
||||||
|
out_priv[SIKE_MSG_BYTESZ+28-1] = (out_priv[SIKE_MSG_BYTESZ+28-1] & 0x01);
|
||||||
gen_iso_B(out_priv, out_pub);
|
gen_iso_B(&out_priv[SIKE_MSG_BYTESZ], out_pub);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ void SIKE_encaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
shake256incctx ctx;
|
shake256incctx ctx;
|
||||||
|
|
||||||
// Generate secret key for A
|
// Generate secret key for A
|
||||||
// secret key A = SHA256({0,1}^n || pub_key)) mod SIDH_PRV_A_BITSZ
|
// secret key A = SHAKE256({0,1}^n || pub_key)) mod SIDH_PRV_A_BITSZ
|
||||||
randombytes(temp, SIKE_MSG_BYTESZ);
|
randombytes(temp, SIKE_MSG_BYTESZ);
|
||||||
|
|
||||||
shake256_inc_init(&ctx);
|
shake256_inc_init(&ctx);
|
||||||
@ -444,7 +444,7 @@ void SIKE_encaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
gen_iso_A(secret, out_ciphertext);
|
gen_iso_A(secret, out_ciphertext);
|
||||||
|
|
||||||
// Generate c1:
|
// Generate c1:
|
||||||
// h = SHA256(j-invariant)
|
// h = SHAKE256(j-invariant)
|
||||||
// c1 = h ^ m
|
// c1 = h ^ m
|
||||||
ex_iso_A(secret, pub_key, j);
|
ex_iso_A(secret, pub_key, j);
|
||||||
shake256(secret, sizeof secret, j, sizeof j);
|
shake256(secret, sizeof secret, j, sizeof j);
|
||||||
@ -461,14 +461,14 @@ void SIKE_encaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
shake256_inc_finalize(&ctx);
|
shake256_inc_finalize(&ctx);
|
||||||
shake256_inc_squeeze(secret, 32, &ctx);
|
shake256_inc_squeeze(secret, 32, &ctx);
|
||||||
shake256_inc_ctx_release(&ctx);
|
shake256_inc_ctx_release(&ctx);
|
||||||
// Generate shared secret out_shared_key = SHA256(m||out_ciphertext)
|
// Generate shared secret out_shared_key = SHAKE256(m||out_ciphertext)
|
||||||
memcpy(out_shared_key, secret, SIKE_SS_BYTESZ);
|
memcpy(out_shared_key, secret, SIKE_SS_BYTESZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
||||||
const uint8_t ciphertext[SIKE_CT_BYTESZ],
|
const uint8_t ciphertext[SIKE_CT_BYTESZ],
|
||||||
const uint8_t pub_key[SIKE_PUB_BYTESZ],
|
const uint8_t pub_key[SIKE_PUB_BYTESZ],
|
||||||
const uint8_t priv_key[SIKE_PRV_BYTESZ]) {
|
const uint8_t priv_key[SIKE_MSG_BYTESZ + SIKE_PRV_BYTESZ]) {
|
||||||
// Secret buffer is reused by the function to store some ephemeral
|
// Secret buffer is reused by the function to store some ephemeral
|
||||||
// secret data. It's size must be maximum of 64,
|
// secret data. It's size must be maximum of 64,
|
||||||
// SIKE_MSG_BYTESZ and SIDH_PRV_A_BITSZ in bytes.
|
// SIKE_MSG_BYTESZ and SIDH_PRV_A_BITSZ in bytes.
|
||||||
@ -476,16 +476,12 @@ void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
uint8_t j[SIDH_JINV_BYTESZ];
|
uint8_t j[SIDH_JINV_BYTESZ];
|
||||||
uint8_t c0[SIKE_PUB_BYTESZ];
|
uint8_t c0[SIKE_PUB_BYTESZ];
|
||||||
uint8_t temp[SIKE_MSG_BYTESZ];
|
uint8_t temp[SIKE_MSG_BYTESZ];
|
||||||
uint8_t shared_nok[SIKE_MSG_BYTESZ];
|
|
||||||
shake256incctx ctx;
|
shake256incctx ctx;
|
||||||
|
|
||||||
// This is OK as we are only using ephemeral keys in BoringSSL
|
|
||||||
randombytes(shared_nok, SIKE_MSG_BYTESZ);
|
|
||||||
|
|
||||||
// Recover m
|
// Recover m
|
||||||
// Let ciphertext = c0 || c1 - both have fixed sizes
|
// Let ciphertext = c0 || c1 - both have fixed sizes
|
||||||
// m = F(j-invariant(c0, priv_key)) ^ c1
|
// m = F(j-invariant(c0, priv_key)) ^ c1
|
||||||
ex_iso_B(priv_key, ciphertext, j);
|
ex_iso_B(&priv_key[SIKE_MSG_BYTESZ], ciphertext, j);
|
||||||
|
|
||||||
shake256(secret, sizeof secret, j, sizeof j);
|
shake256(secret, sizeof secret, j, sizeof j);
|
||||||
|
|
||||||
@ -507,7 +503,7 @@ void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
crypto_word_t ok = ct_uint_eq(
|
crypto_word_t ok = ct_uint_eq(
|
||||||
ct_mem_eq(c0, ciphertext, SIKE_PUB_BYTESZ), 1);
|
ct_mem_eq(c0, ciphertext, SIKE_PUB_BYTESZ), 1);
|
||||||
for (size_t i = 0; i < SIKE_MSG_BYTESZ; i++) {
|
for (size_t i = 0; i < SIKE_MSG_BYTESZ; i++) {
|
||||||
temp[i] = ct_select_8(ok, temp[i], shared_nok[i]);
|
temp[i] = ct_select_8(ok, temp[i], priv_key[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
shake256_inc_init(&ctx);
|
shake256_inc_init(&ctx);
|
||||||
@ -517,6 +513,6 @@ void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ],
|
|||||||
shake256_inc_squeeze(secret, 32, &ctx);
|
shake256_inc_squeeze(secret, 32, &ctx);
|
||||||
shake256_inc_ctx_release(&ctx);
|
shake256_inc_ctx_release(&ctx);
|
||||||
|
|
||||||
// Generate shared secret out_shared_key = SHA256(m||ciphertext)
|
// Generate shared secret out_shared_key = SHAKE256(m||ciphertext)
|
||||||
memcpy(out_shared_key, secret, SIKE_SS_BYTESZ);
|
memcpy(out_shared_key, secret, SIKE_SS_BYTESZ);
|
||||||
}
|
}
|
||||||
|
@ -11,4 +11,4 @@ hex = "0.4.2"
|
|||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
rust-crypto = "^0.2"
|
rust-crypto = "^0.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
aes_ctr_drbg = "0.0.2"
|
aes_ctr_drbg = "0.0.2"
|
||||||
|
@ -130,9 +130,10 @@ fn test_kem_vector(el: &TestVector) {
|
|||||||
// Check keygen
|
// Check keygen
|
||||||
pk.resize(el.kem.pk.len(), 0);
|
pk.resize(el.kem.pk.len(), 0);
|
||||||
sk.resize(el.kem.sk.len(), 0);
|
sk.resize(el.kem.sk.len(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pqc_keygen(p, pk.as_mut_ptr(), sk.as_mut_ptr()),
|
pqc_keygen(p, pk.as_mut_ptr(), sk.as_mut_ptr()),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
assert_eq!(sk, el.kem.sk);
|
assert_eq!(sk, el.kem.sk);
|
||||||
assert_eq!(pk, el.kem.pk);
|
assert_eq!(pk, el.kem.pk);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user