1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0"
*
* Written by Nir Drucker and Shay Gueron
* AWS Cryptographic Algorithms Group.
* (ndrucker@amazon.com, gueron@amazon.com)
*/
#include "sampling.h"
#include <assert.h>
#include <string.h>
_INLINE_ ret_t
get_rand_mod_len(OUT uint32_t * rand_pos,
IN const uint32_t len,
IN OUT aes_ctr_prf_state_t *prf_state)
{
const uint64_t mask = MASK(bit_scan_reverse(len));
do
{
// Generate 128bit of random numbers
POSIX_GUARD(aes_ctr_prf((uint8_t *)rand_pos, prf_state, sizeof(*rand_pos)));
// Mask only relevant bits
(*rand_pos) &= mask;
// Break if a number smaller than len is found
if((*rand_pos) < len)
{
break;
}
} while(1);
return SUCCESS;
}
_INLINE_ void
make_odd_weight(IN OUT r_t *r)
{
if(((r_bits_vector_weight(r) % 2) == 1))
{
// Already odd
return;
}
r->raw[0] ^= 1;
}
// IN: must_be_odd - 1 true, 0 not
ret_t
sample_uniform_r_bits_with_fixed_prf_context(OUT r_t *r,
IN OUT
aes_ctr_prf_state_t *prf_state,
IN const must_be_odd_t must_be_odd)
{
// Generate random data
POSIX_GUARD(aes_ctr_prf(r->raw, prf_state, R_SIZE));
// Mask upper bits of the MSByte
r->raw[R_SIZE - 1] &= MASK(R_BITS + 8 - (R_SIZE * 8));
if(must_be_odd == MUST_BE_ODD)
{
make_odd_weight(r);
}
return SUCCESS;
}
_INLINE_ int
is_new(IN const idx_t wlist[], IN const uint32_t ctr)
{
for(uint32_t i = 0; i < ctr; i++)
{
if(wlist[i] == wlist[ctr])
{
return 0;
}
}
return 1;
}
// Assumption 1) paddded_len % 64 = 0!
// Assumption 2) a is a len bits array. It is padded to be a padded_len
// bytes array. The padded area may be modified and should
// be ignored outside the function scope.
ret_t
generate_sparse_rep(OUT uint64_t * a,
OUT idx_t wlist[],
IN const uint32_t weight,
IN const uint32_t len,
IN const uint32_t padded_len,
IN OUT aes_ctr_prf_state_t *prf_state)
{
assert(padded_len % 64 == 0);
// Bits comparison
assert((padded_len * 8) >= len);
uint64_t ctr = 0;
// Generate weight rand numbers
do
{
POSIX_GUARD(get_rand_mod_len(&wlist[ctr], len, prf_state));
ctr += is_new(wlist, ctr);
} while(ctr < weight);
// Initialize to zero
memset(a, 0, (len + 7) >> 3);
// Assign values to "a"
secure_set_bits(a, wlist, padded_len, weight);
return SUCCESS;
}
|