Merge branch 'master' into fix-sphincs-windows

This commit is contained in:
mergify[bot] 2020-06-22 11:47:48 +00:00 committed by GitHub
commit a80abd64ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 488 additions and 158 deletions

View File

@ -24,6 +24,9 @@ Use at your own risk.
### 2019-XX-XX ### 2019-XX-XX
--> -->
### 2020-06-19
* A potential timing leak was present in the FrodoKEM decapsulation routine, as identified by [Guo, Johansson, and Nilsson](https://eprint.iacr.org/2020/743). This was fixed in [PR #303](https://github.com/PQClean/PQClean/pull/303).
### 2019-09-24 ### 2019-09-24
* All Falcon implementations before [PR #235][PR 235] got merged were insecure. See [EPRINT report 2019/893][2019/893]. * All Falcon implementations before [PR #235][PR 235] got merged were insecure. See [EPRINT report 2019/893][2019/893].

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM1344AES_CLEAN_key_encode(uint16_t *out, const uint16_t *in)
void PQCLEAN_FRODOKEM1344AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM1344AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM1344AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM1344AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM1344AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM1344AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM1344AES_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM1344AES_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM1344AES_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344AES_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM1344AES_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344AES_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM1344AES_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM1344AES_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM1344AES_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM1344AES_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM1344AES_CLEAN_unpack(uint16_t *out, size_t outlen, const ui
} }
int8_t PQCLEAN_FRODOKEM1344AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM1344AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM1344AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM1344AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM1344AES_OPT_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM1344AES_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM1344AES_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM1344AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM1344AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM1344AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM1344AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, c
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM1344AES_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM1344AES_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM1344AES_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM1344AES_OPT_unpack(uint16_t *out, size_t outlen, const uint
} }
int8_t PQCLEAN_FRODOKEM1344AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM1344AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *i
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM1344SHAKE_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *c
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const
} }
int8_t PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM1344SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in)
void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const ui
} }
int8_t PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM1344SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM640AES_CLEAN_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM640AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM640AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM640AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM640AES_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM640AES_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM640AES_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM640AES_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM640AES_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM640AES_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM640AES_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM640AES_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM640AES_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM640AES_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM640AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uin
} }
int8_t PQCLEAN_FRODOKEM640AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM640AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM640AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM640AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM640AES_OPT_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640AES_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640AES_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM640AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM640AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM640AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, co
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM640AES_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM640AES_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM640AES_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM640AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8
} }
int8_t PQCLEAN_FRODOKEM640AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM640AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const u
} }
int8_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM640SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM640SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM640SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM640SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM640SHAKE_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM640SHAKE_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uin
} }
int8_t PQCLEAN_FRODOKEM640SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM640SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM976AES_CLEAN_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM976AES_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976AES_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM976AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM976AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM976AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM976AES_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM976AES_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM976AES_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM976AES_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM976AES_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM976AES_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM976AES_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM976AES_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM976AES_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM976AES_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM976AES_CLEAN_unpack(uint16_t *out, size_t outlen, const uin
} }
int8_t PQCLEAN_FRODOKEM976AES_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM976AES_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM976AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM976AES_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM976AES_OPT_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976AES_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM976AES_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM976AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM976AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM976AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, co
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM976AES_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM976AES_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM976AES_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM976AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8
} }
int8_t PQCLEAN_FRODOKEM976AES_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM976AES_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM976SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM976SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM976SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM976SHAKE_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM976SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const u
} }
int8_t PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM976SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM976SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -12,6 +12,8 @@ void PQCLEAN_FRODOKEM976SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM976SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in);
void PQCLEAN_FRODOKEM976SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb);
void PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb);
int8_t PQCLEAN_FRODOKEM976SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
void PQCLEAN_FRODOKEM976SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n);
uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(uint16_t n);
uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(uint16_t n); uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(uint16_t n);

View File

@ -214,14 +214,13 @@ int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct,
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
} }
// Is (Bp == BBp & C == CC) = true // If (Bp == BBp & C == CC) then ss = F(ct || k'), else ss = F(ct || s)
if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Needs to avoid branching on secret data as per:
// Load k' to do ss = F(ct || k') // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum
memcpy(Fin_k, kprime, CRYPTO_BYTES); // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020.
} else { int8_t selector = PQCLEAN_FRODOKEM976SHAKE_OPT_ct_verify(Bp, BBp, PARAMS_N * PARAMS_NBAR) | PQCLEAN_FRODOKEM976SHAKE_OPT_ct_verify(C, CC, PARAMS_NBAR * PARAMS_NBAR);
// Load s to do ss = F(ct || s) // If (selector == 0) then load k' to do ss = F(ct || k'), else if (selector == -1) load s to do ss = F(ct || s)
memcpy(Fin_k, sk_s, CRYPTO_BYTES); PQCLEAN_FRODOKEM976SHAKE_OPT_ct_select((uint8_t *)Fin_k, (uint8_t *)kprime, (uint8_t *)sk_s, CRYPTO_BYTES, selector);
}
shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
// Cleanup: // Cleanup:

View File

@ -224,6 +224,30 @@ void PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uin
} }
int8_t PQCLEAN_FRODOKEM976SHAKE_OPT_ct_verify(const uint16_t *a, const uint16_t *b, size_t len) {
// Compare two arrays in constant time.
// Returns 0 if the byte arrays are equal, -1 otherwise.
uint16_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (-(int16_t)r) >> (8 * sizeof(uint16_t) -1);
return (int8_t)r;
}
void PQCLEAN_FRODOKEM976SHAKE_OPT_ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector) {
// Select one of the two input arrays to be moved to r
// If (selector == 0) then load r with a, else if (selector == -1) load r with b
for (size_t i = 0; i < len; i++) {
r[i] = (~selector & a[i]) | (selector & b[i]);
}
}
void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) {
// Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
// This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.

View File

@ -29,7 +29,6 @@ implementations:
operating_systems: operating_systems:
- Linux - Linux
required_flags: required_flags:
- aes
- avx2 - avx2
- bmi2 - bmi2
- popcnt - popcnt

View File

@ -29,7 +29,6 @@ implementations:
operating_systems: operating_systems:
- Linux - Linux
required_flags: required_flags:
- aes
- avx2 - avx2
- bmi2 - bmi2
- popcnt - popcnt

View File

@ -6,7 +6,7 @@ length-public-key: 1824
length-secret-key: 3680 length-secret-key: 3680
length-ciphertext: 2208 length-ciphertext: 2208
length-shared-secret: 32 length-shared-secret: 32
nistkat-sha256: 8500b88222b3a62e57a6ecaac57f79258f08af49211e0c3f2ca7eab8089c0ce0 nistkat-sha256: 4a21f329bb5402a90d343af01ec1c8bc8ffffa8098cb0b89e1d2129f5157a073
principal-submitters: principal-submitters:
- Thomas Pöppelmann - Thomas Pöppelmann
auxiliary-submitters: auxiliary-submitters:

View File

@ -101,8 +101,9 @@ void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_keypair(unsigned char *pk,
unsigned char *publicseed = z; unsigned char *publicseed = z;
unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; unsigned char *noiseseed = z + NEWHOPE_SYMBYTES;
randombytes(z, NEWHOPE_SYMBYTES); z[0] = 0x01;
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); randombytes(z + 1, NEWHOPE_SYMBYTES);
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES + 1);
gen_a(&ahat, publicseed); gen_a(&ahat, publicseed);

View File

@ -52,16 +52,18 @@ int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned
**************************************************/ **************************************************/
int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES + 1];
int i; int i;
randombytes(buf, NEWHOPE_SYMBYTES); buf[0] = 0x04;
randombytes(buf + 1, NEWHOPE_SYMBYTES);
shake256(buf, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ shake256(buf + 1, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES + 1); /* Don't release system RNG output */
shake256(buf + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ shake256(buf + 1 + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); buf[0] = 0x08;
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES + 1);
PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct, buf + 1, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (i = 0; i < NEWHOPE_SYMBYTES; i++) {
ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */ ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */
@ -89,18 +91,19 @@ int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char
int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
int i, fail; int i, fail;
unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES]; unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES];
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES + 1];
unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */
const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES; const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES;
PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_dec(buf, ct, sk); buf[0] = 0x08;
PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_dec(buf + 1, ct, sk);
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */ for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */
buf[NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i]; buf[1 + NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i];
} }
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES + 1);
PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct_cmp, buf + 1, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (i = 0; i < NEWHOPE_SYMBYTES; i++) {
ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES];

View File

@ -6,7 +6,7 @@ length-public-key: 1824
length-secret-key: 1792 length-secret-key: 1792
length-ciphertext: 2176 length-ciphertext: 2176
length-shared-secret: 32 length-shared-secret: 32
nistkat-sha256: f48b42b21a51d7f9325abc5fbda74872d62feaa8cbf818bee87f29bf96630a2f nistkat-sha256: 440e2afb40d212a44d1bb1dc9963d7c942fa6ceb16fed2b1ccf015fa75ab115b
principal-submitters: principal-submitters:
- Thomas Pöppelmann - Thomas Pöppelmann
auxiliary-submitters: auxiliary-submitters:

View File

@ -101,8 +101,9 @@ void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_keypair(unsigned char *pk,
unsigned char *publicseed = z; unsigned char *publicseed = z;
unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; unsigned char *noiseseed = z + NEWHOPE_SYMBYTES;
randombytes(z, NEWHOPE_SYMBYTES); z[0] = 0x01;
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); randombytes(z + 1, NEWHOPE_SYMBYTES);
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES + 1);
gen_a(&ahat, publicseed); gen_a(&ahat, publicseed);

View File

@ -39,9 +39,10 @@ int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned
int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES];
randombytes(buf, NEWHOPE_SYMBYTES); buf[0] = 0x02;
randombytes(buf + 1, NEWHOPE_SYMBYTES);
shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES + 1); /* Don't release system RNG output */
PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */

View File

@ -6,7 +6,7 @@ length-public-key: 928
length-secret-key: 1888 length-secret-key: 1888
length-ciphertext: 1120 length-ciphertext: 1120
length-shared-secret: 32 length-shared-secret: 32
nistkat-sha256: 5b0389f8d9c30055ad0fb83da540ca36969dde041bebe6f1018c37768c5e1479 nistkat-sha256: 4290da64305e70e65766be5d4e488dee2b4b238172876ceefc931934b6964a7d
principal-submitters: principal-submitters:
- Thomas Pöppelmann - Thomas Pöppelmann
auxiliary-submitters: auxiliary-submitters:

View File

@ -101,8 +101,9 @@ void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_keypair(unsigned char *pk,
unsigned char *publicseed = z; unsigned char *publicseed = z;
unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; unsigned char *noiseseed = z + NEWHOPE_SYMBYTES;
randombytes(z, NEWHOPE_SYMBYTES); z[0] = 0x01;
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); randombytes(z + 1, NEWHOPE_SYMBYTES);
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES + 1);
gen_a(&ahat, publicseed); gen_a(&ahat, publicseed);

View File

@ -52,16 +52,18 @@ int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned c
**************************************************/ **************************************************/
int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES + 1];
int i; int i;
randombytes(buf, NEWHOPE_SYMBYTES); buf[0] = 0x04;
randombytes(buf + 1, NEWHOPE_SYMBYTES);
shake256(buf, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ shake256(buf + 1, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES + 1); /* Don't release system RNG output */
shake256(buf + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ shake256(buf + 1 + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); buf[0] = 0x08;
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES + 1);
PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct, buf + 1, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (i = 0; i < NEWHOPE_SYMBYTES; i++) {
ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */ ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */
@ -89,18 +91,19 @@ int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char
int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
int i, fail; int i, fail;
unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES]; unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES];
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES + 1];
unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */
const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES; const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES;
PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_dec(buf, ct, sk); buf[0] = 0x08;
PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_dec(buf + 1, ct, sk);
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */ for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */
buf[NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i]; buf[1 + NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i];
} }
shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES + 1);
PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct_cmp, buf + 1, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */
for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (i = 0; i < NEWHOPE_SYMBYTES; i++) {
ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES];

View File

@ -6,7 +6,7 @@ length-public-key: 928
length-secret-key: 896 length-secret-key: 896
length-ciphertext: 1088 length-ciphertext: 1088
length-shared-secret: 32 length-shared-secret: 32
nistkat-sha256: 42444446b96f45c9b7221c4fde8afd5dfc0b3c2ff05b9a88ff12ea3949fbb76c nistkat-sha256: 7df3eae4740483a61d13610f6bc2221f27e32c7849cf371e9770f986ce6fdb54
principal-submitters: principal-submitters:
- Thomas Pöppelmann - Thomas Pöppelmann
auxiliary-submitters: auxiliary-submitters:

View File

@ -101,8 +101,9 @@ void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_keypair(unsigned char *pk,
unsigned char *publicseed = z; unsigned char *publicseed = z;
unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; unsigned char *noiseseed = z + NEWHOPE_SYMBYTES;
randombytes(z, NEWHOPE_SYMBYTES); z[0] = 0x01;
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); randombytes(z + 1, NEWHOPE_SYMBYTES);
shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES + 1);
gen_a(&ahat, publicseed); gen_a(&ahat, publicseed);

View File

@ -39,9 +39,10 @@ int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned c
int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES];
randombytes(buf, NEWHOPE_SYMBYTES); buf[0] = 0x02;
randombytes(buf + 1, NEWHOPE_SYMBYTES);
shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES + 1); /* Don't release system RNG output */
PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */ PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */

View File

@ -2,11 +2,13 @@ import atexit
import functools import functools
import logging import logging
import os import os
import secrets
import shutil import shutil
import string
import subprocess import subprocess
import sys import sys
import tempfile
import unittest import unittest
from functools import lru_cache
import pqclean import pqclean
@ -22,6 +24,12 @@ def cleanup_testcases():
TEST_TEMPDIRS = [] TEST_TEMPDIRS = []
ALPHABET = string.ascii_letters + string.digits + '_'
def mktmpdir(parent, prefix):
"""Returns a unique directory name"""
uniq = ''.join(secrets.choice(ALPHABET) for i in range(8))
return os.path.join(parent, "{}_{}".format(prefix, uniq))
def isolate_test_files(impl_path, test_prefix, def isolate_test_files(impl_path, test_prefix,
dir=os.path.join('..', 'testcases')): dir=os.path.join('..', 'testcases')):
@ -34,24 +42,22 @@ def isolate_test_files(impl_path, test_prefix,
os.mkdir(dir) os.mkdir(dir)
except FileExistsError: except FileExistsError:
pass pass
test_dir = tempfile.mkdtemp(prefix=test_prefix, dir=dir) test_dir = mktmpdir(dir, test_prefix)
test_dir = os.path.abspath(test_dir) test_dir = os.path.abspath(test_dir)
TEST_TEMPDIRS.append(test_dir) TEST_TEMPDIRS.append(test_dir)
# Create layers in folder structure
nested_dir = os.path.join(test_dir, 'crypto_bla')
os.mkdir(nested_dir)
nested_dir = os.path.join(nested_dir, 'scheme')
os.mkdir(nested_dir)
# Create test dependencies structure
os.mkdir(os.path.join(test_dir, 'test'))
# the implementation will go here. # the implementation will go here.
new_impl_dir = os.path.abspath(os.path.join(nested_dir, 'impl')) scheme_dir = os.path.join(test_dir, 'crypto_bla', 'scheme')
new_impl_dir = os.path.abspath(os.path.join(scheme_dir, 'impl'))
def initializer(): def initializer():
"""Isolate the files to be tested""" """Isolate the files to be tested"""
# Create layers in folder structure
os.makedirs(scheme_dir)
# Create test dependencies structure
os.mkdir(os.path.join(test_dir, 'test'))
# Copy common files (randombytes.c, aes.c, ...) # Copy common files (randombytes.c, aes.c, ...)
shutil.copytree( shutil.copytree(
os.path.join('..', 'common'), os.path.join(test_dir, 'common')) os.path.join('..', 'common'), os.path.join(test_dir, 'common'))
@ -160,6 +166,7 @@ def slow_test(f):
return wrapper return wrapper
@lru_cache(maxsize=None)
def ensure_available(executable): def ensure_available(executable):
""" """
Checks if a command is available. Checks if a command is available.
@ -278,18 +285,16 @@ def filtered_test(func):
return wrapper return wrapper
__CPUINFO = None @lru_cache(maxsize=1)
def get_cpu_info(): def get_cpu_info():
global __CPUINFO the_info = None
while __CPUINFO is None or 'flags' not in __CPUINFO: while the_info is None or 'flags' not in the_info:
import cpuinfo import cpuinfo
__CPUINFO = cpuinfo.get_cpu_info() the_info = cpuinfo.get_cpu_info()
# CPUINFO is unreliable on Travis CI Macs # CPUINFO is unreliable on Travis CI Macs
if 'CI' in os.environ and sys.platform == 'darwin': if 'CI' in os.environ and sys.platform == 'darwin':
__CPUINFO['flags'] = [ the_info['flags'] = [
'aes', 'apic', 'avx1.0', 'clfsh', 'cmov', 'cx16', 'cx8', 'de', 'aes', 'apic', 'avx1.0', 'clfsh', 'cmov', 'cx16', 'cx8', 'de',
'em64t', 'erms', 'f16c', 'fpu', 'fxsr', 'lahf', 'mca', 'mce', 'em64t', 'erms', 'f16c', 'fpu', 'fxsr', 'lahf', 'mca', 'mce',
'mmx', 'mon', 'msr', 'mtrr', 'osxsave', 'pae', 'pat', 'pcid', 'mmx', 'mon', 'msr', 'mtrr', 'osxsave', 'pae', 'pat', 'pcid',
@ -299,4 +304,4 @@ def get_cpu_info():
'tsc_thread_offset', 'tsci', 'tsctmr', 'vme', 'vmm', 'x2apic', 'tsc_thread_offset', 'tsci', 'tsctmr', 'vme', 'vmm', 'x2apic',
'xd', 'xsave'] 'xd', 'xsave']
return __CPUINFO return the_info

View File

@ -1,6 +1,7 @@
import glob import glob
import os import os
from typing import Optional from typing import Optional
from functools import lru_cache
import yaml import yaml
import platform import platform
@ -20,6 +21,7 @@ class Scheme:
return 'PQCLEAN_{}_'.format(self.name.upper()).replace('-', '') return 'PQCLEAN_{}_'.format(self.name.upper()).replace('-', '')
@staticmethod @staticmethod
@lru_cache(maxsize=None)
def by_name(scheme_name): def by_name(scheme_name):
for scheme in Scheme.all_schemes(): for scheme in Scheme.all_schemes():
if scheme.name == scheme_name: if scheme.name == scheme_name:
@ -27,6 +29,7 @@ class Scheme:
raise KeyError() raise KeyError()
@staticmethod @staticmethod
@lru_cache(maxsize=1)
def all_schemes(): def all_schemes():
schemes = [] schemes = []
schemes.extend(Scheme.all_schemes_of_type('kem')) schemes.extend(Scheme.all_schemes_of_type('kem'))
@ -34,6 +37,7 @@ class Scheme:
return schemes return schemes
@staticmethod @staticmethod
@lru_cache(maxsize=1)
def all_implementations(): def all_implementations():
implementations = [] implementations = []
for scheme in Scheme.all_schemes(): for scheme in Scheme.all_schemes():
@ -41,11 +45,13 @@ class Scheme:
return implementations return implementations
@staticmethod @staticmethod
@lru_cache(maxsize=1)
def all_supported_implementations(): def all_supported_implementations():
return [impl for impl in Scheme.all_implementations() return [impl for impl in Scheme.all_implementations()
if impl.supported_on_current_platform()] if impl.supported_on_current_platform()]
@staticmethod @staticmethod
@lru_cache(maxsize=32)
def all_schemes_of_type(type: str) -> list: def all_schemes_of_type(type: str) -> list:
schemes = [] schemes = []
p = os.path.join('..', 'crypto_' + type) p = os.path.join('..', 'crypto_' + type)
@ -60,12 +66,13 @@ class Scheme:
assert('Unknown type') assert('Unknown type')
return schemes return schemes
@lru_cache(maxsize=None)
def metadata(self): def metadata(self):
metafile = os.path.join(self.path(), 'META.yml') metafile = os.path.join(self.path(), 'META.yml')
try: try:
with open(metafile, encoding='utf-8') as f: with open(metafile, encoding='utf-8') as f:
metadata = yaml.safe_load(f.read()) metadata = yaml.safe_load(f)
return metadata return metadata
except Exception as e: except Exception as e:
print("Can't open {}: {}".format(metafile, e)) print("Can't open {}: {}".format(metafile, e))
return None return None
@ -80,6 +87,7 @@ class Implementation:
self.scheme = scheme self.scheme = scheme
self.name = name self.name = name
@lru_cache(maxsize=None)
def metadata(self): def metadata(self):
for i in self.scheme.metadata()['implementations']: for i in self.scheme.metadata()['implementations']:
if i['name'] == self.name: if i['name'] == self.name:
@ -104,6 +112,7 @@ class Implementation:
'*.o' if os.name != 'nt' else '*.obj')) '*.o' if os.name != 'nt' else '*.obj'))
@staticmethod @staticmethod
@lru_cache(maxsize=None)
def by_name(scheme_name, implementation_name): def by_name(scheme_name, implementation_name):
scheme = Scheme.by_name(scheme_name) scheme = Scheme.by_name(scheme_name)
for implementation in scheme.implementations: for implementation in scheme.implementations:
@ -112,6 +121,7 @@ class Implementation:
raise KeyError() raise KeyError()
@staticmethod @staticmethod
@lru_cache(maxsize=None)
def all_implementations(scheme: Scheme) -> list: def all_implementations(scheme: Scheme) -> list:
implementations = [] implementations = []
for d in os.listdir(scheme.path()): for d in os.listdir(scheme.path()):
@ -143,6 +153,7 @@ class Implementation:
return True return True
@lru_cache(maxsize=10000)
def supported_on_current_platform(self) -> bool: def supported_on_current_platform(self) -> bool:
if 'supported_platforms' not in self.metadata(): if 'supported_platforms' not in self.metadata():
return True return True

View File

@ -2,3 +2,4 @@
norecursedirs = .git * norecursedirs = .git *
empty_parameter_set_mark = fail_at_collect empty_parameter_set_mark = fail_at_collect
junit_log_passing_tests = False junit_log_passing_tests = False
junit_family=xunit2