@@ -3,10 +3,15 @@ use crate::data_types::{get_size_in_bits, get_types_vector, Type, UINT64};
3
3
use crate :: data_values:: Value ;
4
4
use crate :: errors:: Result ;
5
5
6
- use openssl:: symm:: { Cipher , Crypter , Mode } ;
6
+ use aes:: cipher:: KeyInit ;
7
+ use aes:: cipher:: { generic_array:: GenericArray , BlockEncrypt } ;
8
+ use aes:: Aes128 ;
9
+ use cipher:: block_padding:: NoPadding ;
7
10
use rand:: rngs:: OsRng ;
8
11
use rand:: RngCore ;
9
12
13
+ const BLOCK_SIZE : usize = 16 ;
14
+
10
15
/// It is possible that when used during early boot
11
16
/// the first call to OsRng will block until the system’s RNG is initialised.
12
17
/// It is also possible (though highly unlikely) for OsRng to fail on some platforms,
@@ -34,14 +39,13 @@ const INITIAL_BUFFER_SIZE: usize = 64;
34
39
/// The empirical randomness properties of AES output is shown in "Empirical Evidence Concerning AES"
35
40
/// by Peter Hellekalek and Stefan Wegenkittl.
36
41
pub struct PRNG {
37
- aes : Crypter ,
42
+ aes : Aes128 ,
38
43
random_source : PrfSession ,
39
44
}
40
45
/// The following implementation is not thread-safe as several copies of PRNG
41
46
/// can concurrently access the system random generator
42
47
impl PRNG {
43
48
pub fn new ( seed : Option < [ u8 ; SEED_SIZE ] > ) -> Result < PRNG > {
44
- let err = |_| runtime_error ! ( "Crypter didn't initialize" ) ;
45
49
let bytes = match seed {
46
50
Some ( bytes) => bytes,
47
51
None => {
@@ -50,18 +54,16 @@ impl PRNG {
50
54
bytes
51
55
}
52
56
} ;
53
- let mut c =
54
- Crypter :: new ( Cipher :: aes_128_ecb ( ) , Mode :: Encrypt , & bytes, None ) . map_err ( err) ?;
55
- c. pad ( false ) ;
57
+ let aes = aes:: Aes128 :: new ( GenericArray :: from_slice ( & bytes) ) ;
56
58
Ok ( PRNG {
57
- aes : c ,
59
+ aes,
58
60
random_source : PrfSession :: new ( 0 , BUFFER_SIZE ) ?,
59
61
} )
60
62
}
61
63
62
64
pub fn get_random_bytes ( & mut self , n : usize ) -> Result < Vec < u8 > > {
63
65
self . random_source
64
- . generate_random_bytes ( & mut self . aes , n as u64 )
66
+ . generate_random_bytes ( & self . aes , n as u64 )
65
67
}
66
68
67
69
fn get_random_key ( & mut self ) -> Result < [ u8 ; SEED_SIZE ] > {
@@ -129,33 +131,30 @@ impl PRNG {
129
131
/// PRF(Prf) output is extended by computing AES_k(0|input)|...|AES_k(n-1|input)
130
132
/// (see e.g. p.16 of [Kolesnikov et al.](https://eprint.iacr.org/2016/799.pdf)).
131
133
pub ( super ) struct Prf {
132
- aes : Crypter ,
134
+ aes : Aes128 ,
133
135
}
134
136
135
137
impl Prf {
136
138
pub fn new ( key : Option < [ u8 ; SEED_SIZE ] > ) -> Result < Prf > {
137
- let err = |_| runtime_error ! ( "Crypter didn't initialize" ) ;
138
139
let key_bytes = match key {
139
140
Some ( bytes) => bytes,
140
141
None => {
141
142
let mut gen = PRNG :: new ( None ) ?;
142
143
gen. get_random_key ( ) ?
143
144
}
144
145
} ;
145
- let mut c =
146
- Crypter :: new ( Cipher :: aes_128_ecb ( ) , Mode :: Encrypt , & key_bytes, None ) . map_err ( err) ?;
147
- c. pad ( false ) ;
148
- Ok ( Prf { aes : c } )
146
+ let aes = aes:: Aes128 :: new ( GenericArray :: from_slice ( & key_bytes) ) ;
147
+ Ok ( Prf { aes } )
149
148
}
150
149
151
150
#[ cfg( test) ]
152
151
fn output_bytes ( & mut self , input : u64 , n : u64 ) -> Result < Vec < u8 > > {
153
152
let initial_buffer_size = usize:: min ( BUFFER_SIZE , n as usize ) ;
154
- PrfSession :: new ( input, initial_buffer_size) ?. generate_random_bytes ( & mut self . aes , n)
153
+ PrfSession :: new ( input, initial_buffer_size) ?. generate_random_bytes ( & self . aes , n)
155
154
}
156
155
157
156
pub ( super ) fn output_value ( & mut self , input : u64 , t : Type ) -> Result < Value > {
158
- PrfSession :: new ( input, INITIAL_BUFFER_SIZE ) ?. recursively_generate_value ( & mut self . aes , t)
157
+ PrfSession :: new ( input, INITIAL_BUFFER_SIZE ) ?. recursively_generate_value ( & self . aes , t)
159
158
}
160
159
161
160
pub ( super ) fn output_permutation ( & mut self , input : u64 , n : u64 ) -> Result < Value > {
@@ -168,7 +167,7 @@ impl Prf {
168
167
let mut session = PrfSession :: new ( input, initial_buffer_size) ?;
169
168
let mut a: Vec < u64 > = ( 0 ..n) . collect ( ) ;
170
169
for i in 1 ..n {
171
- let j = session. generate_u32_in_range ( & mut self . aes , i as u32 + 1 ) ?;
170
+ let j = session. generate_u32_in_range ( & self . aes , i as u32 + 1 ) ?;
172
171
a. swap ( i as usize , j as usize ) ;
173
172
}
174
173
Value :: from_flattened_array_u64 ( & a, UINT64 )
@@ -189,39 +188,31 @@ struct PrfSession {
189
188
190
189
impl PrfSession {
191
190
pub fn new ( input : u64 , initial_buffer_size : usize ) -> Result < Self > {
192
- // Round up to the nearest multiple of 16 .
193
- let initial_buffer_size = ( initial_buffer_size + 15 ) / 16 * 16 ;
191
+ // Round up to the nearest multiple of BLOCK_SIZE .
192
+ let initial_buffer_size = ( initial_buffer_size + BLOCK_SIZE - 1 ) / BLOCK_SIZE * BLOCK_SIZE ;
194
193
Ok ( Self {
195
194
input : ( input as u128 ) << 64 ,
196
195
// Note: we'll drop the "leftover" bytes when PrfSession is destroyed. They are not useful, but if there
197
196
// are many small PRFs, this can be wasteful.
198
- buffer : vec ! [ 0u8 ; initial_buffer_size + Cipher :: aes_128_cbc ( ) . block_size ( ) ] ,
197
+ buffer : vec ! [ 0u8 ; initial_buffer_size] ,
199
198
next_byte : initial_buffer_size,
200
199
current_buffer_size : initial_buffer_size,
201
200
next_buffer_size : initial_buffer_size,
202
201
} )
203
202
}
204
203
205
- fn generate_one_batch ( & mut self , aes : & mut Crypter ) -> Result < ( ) > {
204
+ fn generate_one_batch ( & mut self , aes : & Aes128 ) -> Result < ( ) > {
206
205
let mut i_bytes = vec ! [ 0u8 ; self . next_buffer_size] ;
207
206
for i in ( 0 ..i_bytes. len ( ) ) . step_by ( 16 ) {
208
207
i_bytes[ i..i + 16 ] . copy_from_slice ( & self . input . to_le_bytes ( ) ) ;
209
208
self . input = self . input . wrapping_add ( 1 ) ;
210
209
}
211
- let buffer_len = self . next_buffer_size + Cipher :: aes_128_cbc ( ) . block_size ( ) ;
210
+ let buffer_len = self . next_buffer_size ;
212
211
if buffer_len != self . buffer . len ( ) {
213
212
self . buffer . resize ( buffer_len, 0 ) ;
214
213
}
215
- let count = aes
216
- . update ( & i_bytes, & mut self . buffer )
217
- . map_err ( |_| runtime_error ! ( "Crypter didn't manage to update" ) ) ?;
218
- // finalization of Crypter is unnecessary since padding is turned off
219
- // check here https://www.openssl.org/docs/manmaster/man3/EVP_CipherUpdate.html
220
- if count != self . next_buffer_size {
221
- return Err ( runtime_error ! (
222
- "AES encryption returned a wrong number of bytes"
223
- ) ) ;
224
- }
214
+ aes. encrypt_padded_b2b :: < NoPadding > ( & i_bytes, & mut self . buffer )
215
+ . map_err ( |e| runtime_error ! ( "Encryption error: {e:?}" ) ) ?;
225
216
self . current_buffer_size = self . next_buffer_size ;
226
217
if self . next_buffer_size < BUFFER_SIZE {
227
218
self . next_buffer_size = usize:: min ( BUFFER_SIZE , self . next_buffer_size * 2 ) ;
@@ -230,13 +221,13 @@ impl PrfSession {
230
221
Ok ( ( ) )
231
222
}
232
223
233
- fn generate_random_bytes ( & mut self , aes : & mut Crypter , n : u64 ) -> Result < Vec < u8 > > {
224
+ fn generate_random_bytes ( & mut self , aes : & Aes128 , n : u64 ) -> Result < Vec < u8 > > {
234
225
let mut bytes = vec ! [ 0u8 ; n as usize ] ;
235
226
self . fill_random_bytes ( aes, bytes. as_mut_slice ( ) ) ?;
236
227
Ok ( bytes)
237
228
}
238
229
239
- fn fill_random_bytes ( & mut self , aes : & mut Crypter , mut buff : & mut [ u8 ] ) -> Result < ( ) > {
230
+ fn fill_random_bytes ( & mut self , aes : & Aes128 , mut buff : & mut [ u8 ] ) -> Result < ( ) > {
240
231
while !buff. is_empty ( ) {
241
232
let need_bytes = buff. len ( ) ;
242
233
let ready_bytes = & self . buffer [ self . next_byte ..self . current_buffer_size ] ;
@@ -254,7 +245,7 @@ impl PrfSession {
254
245
Ok ( ( ) )
255
246
}
256
247
257
- fn recursively_generate_value ( & mut self , aes : & mut Crypter , tp : Type ) -> Result < Value > {
248
+ fn recursively_generate_value ( & mut self , aes : & Aes128 , tp : Type ) -> Result < Value > {
258
249
match tp {
259
250
Type :: Scalar ( _) | Type :: Array ( _, _) => {
260
251
let bit_size = get_size_in_bits ( tp) ?;
@@ -283,13 +274,11 @@ impl PrfSession {
283
274
// Generates a random number from 0..2^(8 * NEED_BYTES).
284
275
fn generate_random_number_const < const NEED_BYTES : usize > (
285
276
& mut self ,
286
- aes : & mut Crypter ,
277
+ aes : & Aes128 ,
287
278
) -> Result < u64 > {
288
279
let mut res = [ 0u8 ; 8 ] ;
289
- // Note: sometimes we copy garbage bytes, but they are discarded later.
290
- res. copy_from_slice ( & self . buffer [ self . next_byte ..self . next_byte + 8 ] ) ;
291
-
292
280
let use_bytes = std:: cmp:: min ( self . current_buffer_size - self . next_byte , NEED_BYTES ) ;
281
+ res[ ..use_bytes] . copy_from_slice ( & self . buffer [ self . next_byte ..self . next_byte + use_bytes] ) ;
293
282
if use_bytes == NEED_BYTES {
294
283
self . next_byte += use_bytes;
295
284
} else {
@@ -306,7 +295,7 @@ impl PrfSession {
306
295
}
307
296
308
297
// Generates a random number from 0..2^(8 * need_bytes).
309
- fn generate_random_number ( & mut self , aes : & mut Crypter , need_bytes : usize ) -> Result < u64 > {
298
+ fn generate_random_number ( & mut self , aes : & Aes128 , need_bytes : usize ) -> Result < u64 > {
310
299
match need_bytes {
311
300
1 => self . generate_random_number_const :: < 1 > ( aes) ,
312
301
2 => self . generate_random_number_const :: < 2 > ( aes) ,
@@ -320,7 +309,7 @@ impl PrfSession {
320
309
}
321
310
}
322
311
323
- fn generate_u32_in_range ( & mut self , aes : & mut Crypter , modulus : u32 ) -> Result < u32 > {
312
+ fn generate_u32_in_range ( & mut self , aes : & Aes128 , modulus : u32 ) -> Result < u32 > {
324
313
let modulus = modulus as u64 ;
325
314
// Generate one extra byte of randomness to have reasonably low resampling probability.
326
315
let need_bytes = ( modulus. next_power_of_two ( ) . trailing_zeros ( ) + 7 ) / 8 + 1 ;
0 commit comments