aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/pq-crypto/bike_r2/sampling.c
blob: 1efde4ddd19bc6623551fb92397f9aae7d67771a (plain) (blame)
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 
    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 
  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 
  { 
    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; 
}