2019-04-10 17:11:27 +01:00
|
|
|
/********************************************************************************************
|
|
|
|
* FrodoKEM: Learning with Errors Key Encapsulation
|
|
|
|
*
|
|
|
|
* Abstract: noise sampling functions
|
|
|
|
*********************************************************************************************/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "api.h"
|
2019-04-13 16:47:29 +01:00
|
|
|
#include "common.h"
|
2019-04-10 17:11:27 +01:00
|
|
|
#include "params.h"
|
|
|
|
|
2019-07-18 12:42:37 +01:00
|
|
|
static const uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA;
|
2019-04-10 17:11:27 +01:00
|
|
|
|
2019-04-13 16:47:29 +01:00
|
|
|
void PQCLEAN_FRODOKEM976AES_CLEAN_sample_n(uint16_t *s, size_t n) {
|
2019-04-10 17:11:27 +01:00
|
|
|
// Fills vector s with n samples from the noise distribution which requires 16 bits to sample.
|
|
|
|
// The distribution is specified by its CDF.
|
|
|
|
// Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output.
|
2019-04-16 11:45:34 +01:00
|
|
|
size_t i;
|
|
|
|
unsigned int j;
|
2019-04-10 17:11:27 +01:00
|
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
2019-05-05 23:33:34 +01:00
|
|
|
uint16_t sample = 0;
|
2019-04-10 17:11:27 +01:00
|
|
|
uint16_t prnd = s[i] >> 1; // Drop the least significant bit
|
2019-05-05 23:33:34 +01:00
|
|
|
uint16_t sign = s[i] & 0x1; // Pick the least significant bit
|
2019-04-10 17:11:27 +01:00
|
|
|
|
|
|
|
// No need to compare with the last value.
|
|
|
|
for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) {
|
|
|
|
// Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits.
|
|
|
|
sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15;
|
|
|
|
}
|
|
|
|
// Assuming that sign is either 0 or 1, flips sample iff sign = 1
|
|
|
|
s[i] = ((-sign) ^ sample) + sign;
|
|
|
|
}
|
|
|
|
}
|