Back to home page

LXR

 
 

    


0001 /*
0002  * ChaCha20 256-bit cipher algorithm, RFC7539
0003  *
0004  * Copyright (C) 2015 Martin Willi
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/export.h>
0014 #include <linux/bitops.h>
0015 #include <linux/cryptohash.h>
0016 #include <asm/unaligned.h>
0017 #include <crypto/chacha20.h>
0018 
0019 static inline u32 rotl32(u32 v, u8 n)
0020 {
0021     return (v << n) | (v >> (sizeof(v) * 8 - n));
0022 }
0023 
0024 extern void chacha20_block(u32 *state, void *stream)
0025 {
0026     u32 x[16], *out = stream;
0027     int i;
0028 
0029     for (i = 0; i < ARRAY_SIZE(x); i++)
0030         x[i] = state[i];
0031 
0032     for (i = 0; i < 20; i += 2) {
0033         x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],  16);
0034         x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],  16);
0035         x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],  16);
0036         x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],  16);
0037 
0038         x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],  12);
0039         x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],  12);
0040         x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10], 12);
0041         x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11], 12);
0042 
0043         x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],   8);
0044         x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],   8);
0045         x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],   8);
0046         x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],   8);
0047 
0048         x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],   7);
0049         x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],   7);
0050         x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10],  7);
0051         x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11],  7);
0052 
0053         x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],  16);
0054         x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],  16);
0055         x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],  16);
0056         x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],  16);
0057 
0058         x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10], 12);
0059         x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11], 12);
0060         x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],  12);
0061         x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],  12);
0062 
0063         x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],   8);
0064         x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],   8);
0065         x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],   8);
0066         x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],   8);
0067 
0068         x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10],  7);
0069         x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11],  7);
0070         x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],   7);
0071         x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],   7);
0072     }
0073 
0074     for (i = 0; i < ARRAY_SIZE(x); i++)
0075         out[i] = cpu_to_le32(x[i] + state[i]);
0076 
0077     state[12]++;
0078 }
0079 EXPORT_SYMBOL(chacha20_block);