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