2016-06-13 01:13:36 +03:00
/*
* ChaCha20 256 - bit cipher algorithm , RFC7539
*
* Copyright ( C ) 2015 Martin Willi
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/kernel.h>
# include <linux/export.h>
# include <linux/bitops.h>
# include <linux/cryptohash.h>
# include <asm/unaligned.h>
# include <crypto/chacha20.h>
2017-11-22 22:51:39 +03:00
void chacha20_block ( u32 * state , u32 * stream )
2016-06-13 01:13:36 +03:00
{
u32 x [ 16 ] , * out = stream ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( x ) ; i + + )
x [ i ] = state [ i ] ;
for ( i = 0 ; i < 20 ; i + = 2 ) {
2018-01-01 03:02:45 +03:00
x [ 0 ] + = x [ 4 ] ; x [ 12 ] = rol32 ( x [ 12 ] ^ x [ 0 ] , 16 ) ;
x [ 1 ] + = x [ 5 ] ; x [ 13 ] = rol32 ( x [ 13 ] ^ x [ 1 ] , 16 ) ;
x [ 2 ] + = x [ 6 ] ; x [ 14 ] = rol32 ( x [ 14 ] ^ x [ 2 ] , 16 ) ;
x [ 3 ] + = x [ 7 ] ; x [ 15 ] = rol32 ( x [ 15 ] ^ x [ 3 ] , 16 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 8 ] + = x [ 12 ] ; x [ 4 ] = rol32 ( x [ 4 ] ^ x [ 8 ] , 12 ) ;
x [ 9 ] + = x [ 13 ] ; x [ 5 ] = rol32 ( x [ 5 ] ^ x [ 9 ] , 12 ) ;
x [ 10 ] + = x [ 14 ] ; x [ 6 ] = rol32 ( x [ 6 ] ^ x [ 10 ] , 12 ) ;
x [ 11 ] + = x [ 15 ] ; x [ 7 ] = rol32 ( x [ 7 ] ^ x [ 11 ] , 12 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 0 ] + = x [ 4 ] ; x [ 12 ] = rol32 ( x [ 12 ] ^ x [ 0 ] , 8 ) ;
x [ 1 ] + = x [ 5 ] ; x [ 13 ] = rol32 ( x [ 13 ] ^ x [ 1 ] , 8 ) ;
x [ 2 ] + = x [ 6 ] ; x [ 14 ] = rol32 ( x [ 14 ] ^ x [ 2 ] , 8 ) ;
x [ 3 ] + = x [ 7 ] ; x [ 15 ] = rol32 ( x [ 15 ] ^ x [ 3 ] , 8 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 8 ] + = x [ 12 ] ; x [ 4 ] = rol32 ( x [ 4 ] ^ x [ 8 ] , 7 ) ;
x [ 9 ] + = x [ 13 ] ; x [ 5 ] = rol32 ( x [ 5 ] ^ x [ 9 ] , 7 ) ;
x [ 10 ] + = x [ 14 ] ; x [ 6 ] = rol32 ( x [ 6 ] ^ x [ 10 ] , 7 ) ;
x [ 11 ] + = x [ 15 ] ; x [ 7 ] = rol32 ( x [ 7 ] ^ x [ 11 ] , 7 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 0 ] + = x [ 5 ] ; x [ 15 ] = rol32 ( x [ 15 ] ^ x [ 0 ] , 16 ) ;
x [ 1 ] + = x [ 6 ] ; x [ 12 ] = rol32 ( x [ 12 ] ^ x [ 1 ] , 16 ) ;
x [ 2 ] + = x [ 7 ] ; x [ 13 ] = rol32 ( x [ 13 ] ^ x [ 2 ] , 16 ) ;
x [ 3 ] + = x [ 4 ] ; x [ 14 ] = rol32 ( x [ 14 ] ^ x [ 3 ] , 16 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 10 ] + = x [ 15 ] ; x [ 5 ] = rol32 ( x [ 5 ] ^ x [ 10 ] , 12 ) ;
x [ 11 ] + = x [ 12 ] ; x [ 6 ] = rol32 ( x [ 6 ] ^ x [ 11 ] , 12 ) ;
x [ 8 ] + = x [ 13 ] ; x [ 7 ] = rol32 ( x [ 7 ] ^ x [ 8 ] , 12 ) ;
x [ 9 ] + = x [ 14 ] ; x [ 4 ] = rol32 ( x [ 4 ] ^ x [ 9 ] , 12 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 0 ] + = x [ 5 ] ; x [ 15 ] = rol32 ( x [ 15 ] ^ x [ 0 ] , 8 ) ;
x [ 1 ] + = x [ 6 ] ; x [ 12 ] = rol32 ( x [ 12 ] ^ x [ 1 ] , 8 ) ;
x [ 2 ] + = x [ 7 ] ; x [ 13 ] = rol32 ( x [ 13 ] ^ x [ 2 ] , 8 ) ;
x [ 3 ] + = x [ 4 ] ; x [ 14 ] = rol32 ( x [ 14 ] ^ x [ 3 ] , 8 ) ;
2016-06-13 01:13:36 +03:00
2018-01-01 03:02:45 +03:00
x [ 10 ] + = x [ 15 ] ; x [ 5 ] = rol32 ( x [ 5 ] ^ x [ 10 ] , 7 ) ;
x [ 11 ] + = x [ 12 ] ; x [ 6 ] = rol32 ( x [ 6 ] ^ x [ 11 ] , 7 ) ;
x [ 8 ] + = x [ 13 ] ; x [ 7 ] = rol32 ( x [ 7 ] ^ x [ 8 ] , 7 ) ;
x [ 9 ] + = x [ 14 ] ; x [ 4 ] = rol32 ( x [ 4 ] ^ x [ 9 ] , 7 ) ;
2016-06-13 01:13:36 +03:00
}
for ( i = 0 ; i < ARRAY_SIZE ( x ) ; i + + )
out [ i ] = cpu_to_le32 ( x [ i ] + state [ i ] ) ;
state [ 12 ] + + ;
}
EXPORT_SYMBOL ( chacha20_block ) ;