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