@@ -438,7 +438,8 @@ static int crng_init_cnt = 0;
438
438
#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
439
439
static void _extract_crng (struct crng_state * crng ,
440
440
__u8 out [CHACHA20_BLOCK_SIZE ]);
441
- static void extract_crng (__u8 out [CHACHA20_BLOCK_SIZE ]);
441
+ static void _crng_backtrack_protect (struct crng_state * crng ,
442
+ __u8 tmp [CHACHA20_BLOCK_SIZE ], int used );
442
443
static void process_random_ready_list (void );
443
444
444
445
/**********************************************************************
@@ -826,8 +827,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
826
827
num = extract_entropy (r , & buf , 32 , 16 , 0 );
827
828
if (num == 0 )
828
829
return ;
829
- } else
830
+ } else {
830
831
_extract_crng (& primary_crng , buf .block );
832
+ _crng_backtrack_protect (& primary_crng , buf .block ,
833
+ CHACHA20_KEY_SIZE );
834
+ }
831
835
spin_lock_irqsave (& primary_crng .lock , flags );
832
836
for (i = 0 ; i < 8 ; i ++ ) {
833
837
unsigned long rv ;
@@ -889,9 +893,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
889
893
_extract_crng (crng , out );
890
894
}
891
895
896
+ /*
897
+ * Use the leftover bytes from the CRNG block output (if there is
898
+ * enough) to mutate the CRNG key to provide backtracking protection.
899
+ */
900
+ static void _crng_backtrack_protect (struct crng_state * crng ,
901
+ __u8 tmp [CHACHA20_BLOCK_SIZE ], int used )
902
+ {
903
+ unsigned long flags ;
904
+ __u32 * s , * d ;
905
+ int i ;
906
+
907
+ used = round_up (used , sizeof (__u32 ));
908
+ if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE ) {
909
+ extract_crng (tmp );
910
+ used = 0 ;
911
+ }
912
+ spin_lock_irqsave (& crng -> lock , flags );
913
+ s = (__u32 * ) & tmp [used ];
914
+ d = & crng -> state [4 ];
915
+ for (i = 0 ; i < 8 ; i ++ )
916
+ * d ++ ^= * s ++ ;
917
+ spin_unlock_irqrestore (& crng -> lock , flags );
918
+ }
919
+
920
+ static void crng_backtrack_protect (__u8 tmp [CHACHA20_BLOCK_SIZE ], int used )
921
+ {
922
+ struct crng_state * crng = NULL ;
923
+
924
+ #ifdef CONFIG_NUMA
925
+ if (crng_node_pool )
926
+ crng = crng_node_pool [numa_node_id ()];
927
+ if (crng == NULL )
928
+ #endif
929
+ crng = & primary_crng ;
930
+ _crng_backtrack_protect (crng , tmp , used );
931
+ }
932
+
892
933
static ssize_t extract_crng_user (void __user * buf , size_t nbytes )
893
934
{
894
- ssize_t ret = 0 , i ;
935
+ ssize_t ret = 0 , i = CHACHA20_BLOCK_SIZE ;
895
936
__u8 tmp [CHACHA20_BLOCK_SIZE ];
896
937
int large_request = (nbytes > 256 );
897
938
@@ -916,6 +957,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
916
957
buf += i ;
917
958
ret += i ;
918
959
}
960
+ crng_backtrack_protect (tmp , i );
919
961
920
962
/* Wipe data just written to memory */
921
963
memzero_explicit (tmp , sizeof (tmp ));
@@ -1473,8 +1515,10 @@ void get_random_bytes(void *buf, int nbytes)
1473
1515
if (nbytes > 0 ) {
1474
1516
extract_crng (tmp );
1475
1517
memcpy (buf , tmp , nbytes );
1476
- memzero_explicit (tmp , nbytes );
1477
- }
1518
+ crng_backtrack_protect (tmp , nbytes );
1519
+ } else
1520
+ crng_backtrack_protect (tmp , CHACHA20_BLOCK_SIZE );
1521
+ memzero_explicit (tmp , sizeof (tmp ));
1478
1522
}
1479
1523
EXPORT_SYMBOL (get_random_bytes );
1480
1524
0 commit comments