cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

chacha.c (3813B)


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