Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * The "hash function" used as the core of the ChaCha stream cipher (RFC7539) 4 : : * 5 : : * Copyright (C) 2015 Martin Willi 6 : : */ 7 : : 8 : : #include <linux/kernel.h> 9 : : #include <linux/export.h> 10 : : #include <linux/bitops.h> 11 : : #include <linux/cryptohash.h> 12 : : #include <asm/unaligned.h> 13 : : #include <crypto/chacha.h> 14 : : 15 : 3 : static void chacha_permute(u32 *x, int nrounds) 16 : : { 17 : : int i; 18 : : 19 : : /* whitelist the allowed round counts */ 20 : 3 : WARN_ON_ONCE(nrounds != 20 && nrounds != 12); 21 : : 22 : 3 : for (i = 0; i < nrounds; i += 2) { 23 : 3 : x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16); 24 : 3 : x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16); 25 : 3 : x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16); 26 : 3 : x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16); 27 : : 28 : 3 : x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12); 29 : 3 : x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12); 30 : 3 : x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12); 31 : 3 : x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12); 32 : : 33 : 3 : x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8); 34 : 3 : x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8); 35 : 3 : x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8); 36 : 3 : x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8); 37 : : 38 : 3 : x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7); 39 : 3 : x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7); 40 : 3 : x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7); 41 : 3 : x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7); 42 : : 43 : 3 : x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16); 44 : 3 : x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16); 45 : 3 : x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16); 46 : 3 : x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16); 47 : : 48 : 3 : x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12); 49 : 3 : x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12); 50 : 3 : x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12); 51 : 3 : x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12); 52 : : 53 : 3 : x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8); 54 : 3 : x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8); 55 : 3 : x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8); 56 : 3 : x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8); 57 : : 58 : 3 : x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7); 59 : 3 : x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7); 60 : 3 : x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7); 61 : 3 : x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7); 62 : : } 63 : 3 : } 64 : : 65 : : /** 66 : : * chacha_block - generate one keystream block and increment block counter 67 : : * @state: input state matrix (16 32-bit words) 68 : : * @stream: output keystream block (64 bytes) 69 : : * @nrounds: number of rounds (20 or 12; 20 is recommended) 70 : : * 71 : : * This is the ChaCha core, a function from 64-byte strings to 64-byte strings. 72 : : * The caller has already converted the endianness of the input. This function 73 : : * also handles incrementing the block counter in the input matrix. 74 : : */ 75 : 3 : void chacha_block(u32 *state, u8 *stream, int nrounds) 76 : : { 77 : : u32 x[16]; 78 : : int i; 79 : : 80 : 3 : memcpy(x, state, 64); 81 : : 82 : 3 : chacha_permute(x, nrounds); 83 : : 84 : 3 : for (i = 0; i < ARRAY_SIZE(x); i++) 85 : 3 : put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]); 86 : : 87 : 3 : state[12]++; 88 : 3 : } 89 : : EXPORT_SYMBOL(chacha_block); 90 : : 91 : : /** 92 : : * hchacha_block - abbreviated ChaCha core, for XChaCha 93 : : * @in: input state matrix (16 32-bit words) 94 : : * @out: output (8 32-bit words) 95 : : * @nrounds: number of rounds (20 or 12; 20 is recommended) 96 : : * 97 : : * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step 98 : : * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha 99 : : * skips the final addition of the initial state, and outputs only certain words 100 : : * of the state. It should not be used for streaming directly. 101 : : */ 102 : 0 : void hchacha_block(const u32 *in, u32 *out, int nrounds) 103 : : { 104 : : u32 x[16]; 105 : : 106 : 0 : memcpy(x, in, 64); 107 : : 108 : 0 : chacha_permute(x, nrounds); 109 : : 110 : 0 : memcpy(&out[0], &x[0], 16); 111 : 0 : memcpy(&out[4], &x[12], 16); 112 : 0 : } 113 : : EXPORT_SYMBOL(hchacha_block);