Blame view

lib/chacha.c 3.64 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
e192be9d9   Theodore Ts'o   random: replace n...
2
  /*
1ca1b9179   Eric Biggers   crypto: chacha20-...
3
   * The "hash function" used as the core of the ChaCha stream cipher (RFC7539)
e192be9d9   Theodore Ts'o   random: replace n...
4
5
   *
   * Copyright (C) 2015 Martin Willi
e192be9d9   Theodore Ts'o   random: replace n...
6
7
8
9
10
11
12
   */
  
  #include <linux/kernel.h>
  #include <linux/export.h>
  #include <linux/bitops.h>
  #include <linux/cryptohash.h>
  #include <asm/unaligned.h>
1ca1b9179   Eric Biggers   crypto: chacha20-...
13
  #include <crypto/chacha.h>
e192be9d9   Theodore Ts'o   random: replace n...
14

1ca1b9179   Eric Biggers   crypto: chacha20-...
15
  static void chacha_permute(u32 *x, int nrounds)
e192be9d9   Theodore Ts'o   random: replace n...
16
  {
e192be9d9   Theodore Ts'o   random: replace n...
17
  	int i;
1ca1b9179   Eric Biggers   crypto: chacha20-...
18
  	/* whitelist the allowed round counts */
aa7624093   Eric Biggers   crypto: chacha - ...
19
  	WARN_ON_ONCE(nrounds != 20 && nrounds != 12);
1ca1b9179   Eric Biggers   crypto: chacha20-...
20
21
  
  	for (i = 0; i < nrounds; i += 2) {
7660b1fb3   Eric Biggers   crypto: chacha20 ...
22
23
24
25
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
26

7660b1fb3   Eric Biggers   crypto: chacha20 ...
27
28
29
30
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
31

7660b1fb3   Eric Biggers   crypto: chacha20 ...
32
33
34
35
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
36

7660b1fb3   Eric Biggers   crypto: chacha20 ...
37
38
39
40
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
41

7660b1fb3   Eric Biggers   crypto: chacha20 ...
42
43
44
45
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
46

7660b1fb3   Eric Biggers   crypto: chacha20 ...
47
48
49
50
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
51

7660b1fb3   Eric Biggers   crypto: chacha20 ...
52
53
54
55
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
56

7660b1fb3   Eric Biggers   crypto: chacha20 ...
57
58
59
60
  		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);
e192be9d9   Theodore Ts'o   random: replace n...
61
  	}
dd333449d   Eric Biggers   crypto: chacha20-...
62
63
64
  }
  
  /**
1ca1b9179   Eric Biggers   crypto: chacha20-...
65
   * chacha_block - generate one keystream block and increment block counter
dd333449d   Eric Biggers   crypto: chacha20-...
66
67
   * @state: input state matrix (16 32-bit words)
   * @stream: output keystream block (64 bytes)
aa7624093   Eric Biggers   crypto: chacha - ...
68
   * @nrounds: number of rounds (20 or 12; 20 is recommended)
dd333449d   Eric Biggers   crypto: chacha20-...
69
   *
1ca1b9179   Eric Biggers   crypto: chacha20-...
70
71
72
   * This is the ChaCha core, a function from 64-byte strings to 64-byte strings.
   * The caller has already converted the endianness of the input.  This function
   * also handles incrementing the block counter in the input matrix.
dd333449d   Eric Biggers   crypto: chacha20-...
73
   */
1ca1b9179   Eric Biggers   crypto: chacha20-...
74
  void chacha_block(u32 *state, u8 *stream, int nrounds)
dd333449d   Eric Biggers   crypto: chacha20-...
75
76
77
78
79
  {
  	u32 x[16];
  	int i;
  
  	memcpy(x, state, 64);
1ca1b9179   Eric Biggers   crypto: chacha20-...
80
  	chacha_permute(x, nrounds);
e192be9d9   Theodore Ts'o   random: replace n...
81
82
  
  	for (i = 0; i < ARRAY_SIZE(x); i++)
a5e9f5570   Eric Biggers   crypto: chacha20 ...
83
  		put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]);
e192be9d9   Theodore Ts'o   random: replace n...
84
85
86
  
  	state[12]++;
  }
1ca1b9179   Eric Biggers   crypto: chacha20-...
87
  EXPORT_SYMBOL(chacha_block);
dd333449d   Eric Biggers   crypto: chacha20-...
88
89
  
  /**
1ca1b9179   Eric Biggers   crypto: chacha20-...
90
   * hchacha_block - abbreviated ChaCha core, for XChaCha
dd333449d   Eric Biggers   crypto: chacha20-...
91
92
   * @in: input state matrix (16 32-bit words)
   * @out: output (8 32-bit words)
aa7624093   Eric Biggers   crypto: chacha - ...
93
   * @nrounds: number of rounds (20 or 12; 20 is recommended)
dd333449d   Eric Biggers   crypto: chacha20-...
94
   *
1ca1b9179   Eric Biggers   crypto: chacha20-...
95
96
97
98
   * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step
   * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf).  HChaCha
   * skips the final addition of the initial state, and outputs only certain words
   * of the state.  It should not be used for streaming directly.
dd333449d   Eric Biggers   crypto: chacha20-...
99
   */
1ca1b9179   Eric Biggers   crypto: chacha20-...
100
  void hchacha_block(const u32 *in, u32 *out, int nrounds)
dd333449d   Eric Biggers   crypto: chacha20-...
101
102
103
104
  {
  	u32 x[16];
  
  	memcpy(x, in, 64);
1ca1b9179   Eric Biggers   crypto: chacha20-...
105
  	chacha_permute(x, nrounds);
dd333449d   Eric Biggers   crypto: chacha20-...
106
107
108
109
  
  	memcpy(&out[0], &x[0], 16);
  	memcpy(&out[4], &x[12], 16);
  }
1ca1b9179   Eric Biggers   crypto: chacha20-...
110
  EXPORT_SYMBOL(hchacha_block);