1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* Adapted from the public domain code by D. Bernstein from SUPERCOP. */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <string.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include "internal/endian.h" 15e1051a39Sopenharmony_ci#include "crypto/chacha.h" 16e1051a39Sopenharmony_ci#include "crypto/ctype.h" 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_citypedef unsigned int u32; 19e1051a39Sopenharmony_citypedef unsigned char u8; 20e1051a39Sopenharmony_citypedef union { 21e1051a39Sopenharmony_ci u32 u[16]; 22e1051a39Sopenharmony_ci u8 c[64]; 23e1051a39Sopenharmony_ci} chacha_buf; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci# define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci# define U32TO8_LITTLE(p, v) do { \ 28e1051a39Sopenharmony_ci (p)[0] = (u8)(v >> 0); \ 29e1051a39Sopenharmony_ci (p)[1] = (u8)(v >> 8); \ 30e1051a39Sopenharmony_ci (p)[2] = (u8)(v >> 16); \ 31e1051a39Sopenharmony_ci (p)[3] = (u8)(v >> 24); \ 32e1051a39Sopenharmony_ci } while(0) 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */ 35e1051a39Sopenharmony_ci# define QUARTERROUND(a,b,c,d) ( \ 36e1051a39Sopenharmony_ci x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \ 37e1051a39Sopenharmony_ci x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \ 38e1051a39Sopenharmony_ci x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \ 39e1051a39Sopenharmony_ci x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7) ) 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_ci/* chacha_core performs 20 rounds of ChaCha on the input words in 42e1051a39Sopenharmony_ci * |input| and writes the 64 output bytes to |output|. */ 43e1051a39Sopenharmony_cistatic void chacha20_core(chacha_buf *output, const u32 input[16]) 44e1051a39Sopenharmony_ci{ 45e1051a39Sopenharmony_ci u32 x[16]; 46e1051a39Sopenharmony_ci int i; 47e1051a39Sopenharmony_ci DECLARE_IS_ENDIAN; 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci memcpy(x, input, sizeof(x)); 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci for (i = 20; i > 0; i -= 2) { 52e1051a39Sopenharmony_ci QUARTERROUND(0, 4, 8, 12); 53e1051a39Sopenharmony_ci QUARTERROUND(1, 5, 9, 13); 54e1051a39Sopenharmony_ci QUARTERROUND(2, 6, 10, 14); 55e1051a39Sopenharmony_ci QUARTERROUND(3, 7, 11, 15); 56e1051a39Sopenharmony_ci QUARTERROUND(0, 5, 10, 15); 57e1051a39Sopenharmony_ci QUARTERROUND(1, 6, 11, 12); 58e1051a39Sopenharmony_ci QUARTERROUND(2, 7, 8, 13); 59e1051a39Sopenharmony_ci QUARTERROUND(3, 4, 9, 14); 60e1051a39Sopenharmony_ci } 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci if (IS_LITTLE_ENDIAN) { 63e1051a39Sopenharmony_ci for (i = 0; i < 16; ++i) 64e1051a39Sopenharmony_ci output->u[i] = x[i] + input[i]; 65e1051a39Sopenharmony_ci } else { 66e1051a39Sopenharmony_ci for (i = 0; i < 16; ++i) 67e1051a39Sopenharmony_ci U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i])); 68e1051a39Sopenharmony_ci } 69e1051a39Sopenharmony_ci} 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_civoid ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, 72e1051a39Sopenharmony_ci size_t len, const unsigned int key[8], 73e1051a39Sopenharmony_ci const unsigned int counter[4]) 74e1051a39Sopenharmony_ci{ 75e1051a39Sopenharmony_ci u32 input[16]; 76e1051a39Sopenharmony_ci chacha_buf buf; 77e1051a39Sopenharmony_ci size_t todo, i; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci /* sigma constant "expand 32-byte k" in little-endian encoding */ 80e1051a39Sopenharmony_ci input[0] = ((u32)ossl_toascii('e')) | ((u32)ossl_toascii('x') << 8) 81e1051a39Sopenharmony_ci | ((u32)ossl_toascii('p') << 16) 82e1051a39Sopenharmony_ci | ((u32)ossl_toascii('a') << 24); 83e1051a39Sopenharmony_ci input[1] = ((u32)ossl_toascii('n')) | ((u32)ossl_toascii('d') << 8) 84e1051a39Sopenharmony_ci | ((u32)ossl_toascii(' ') << 16) 85e1051a39Sopenharmony_ci | ((u32)ossl_toascii('3') << 24); 86e1051a39Sopenharmony_ci input[2] = ((u32)ossl_toascii('2')) | ((u32)ossl_toascii('-') << 8) 87e1051a39Sopenharmony_ci | ((u32)ossl_toascii('b') << 16) 88e1051a39Sopenharmony_ci | ((u32)ossl_toascii('y') << 24); 89e1051a39Sopenharmony_ci input[3] = ((u32)ossl_toascii('t')) | ((u32)ossl_toascii('e') << 8) 90e1051a39Sopenharmony_ci | ((u32)ossl_toascii(' ') << 16) 91e1051a39Sopenharmony_ci | ((u32)ossl_toascii('k') << 24); 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci input[4] = key[0]; 94e1051a39Sopenharmony_ci input[5] = key[1]; 95e1051a39Sopenharmony_ci input[6] = key[2]; 96e1051a39Sopenharmony_ci input[7] = key[3]; 97e1051a39Sopenharmony_ci input[8] = key[4]; 98e1051a39Sopenharmony_ci input[9] = key[5]; 99e1051a39Sopenharmony_ci input[10] = key[6]; 100e1051a39Sopenharmony_ci input[11] = key[7]; 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci input[12] = counter[0]; 103e1051a39Sopenharmony_ci input[13] = counter[1]; 104e1051a39Sopenharmony_ci input[14] = counter[2]; 105e1051a39Sopenharmony_ci input[15] = counter[3]; 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci while (len > 0) { 108e1051a39Sopenharmony_ci todo = sizeof(buf); 109e1051a39Sopenharmony_ci if (len < todo) 110e1051a39Sopenharmony_ci todo = len; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci chacha20_core(&buf, input); 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci for (i = 0; i < todo; i++) 115e1051a39Sopenharmony_ci out[i] = inp[i] ^ buf.c[i]; 116e1051a39Sopenharmony_ci out += todo; 117e1051a39Sopenharmony_ci inp += todo; 118e1051a39Sopenharmony_ci len -= todo; 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci /* 121e1051a39Sopenharmony_ci * Advance 32-bit counter. Note that as subroutine is so to 122e1051a39Sopenharmony_ci * say nonce-agnostic, this limited counter width doesn't 123e1051a39Sopenharmony_ci * prevent caller from implementing wider counter. It would 124e1051a39Sopenharmony_ci * simply take two calls split on counter overflow... 125e1051a39Sopenharmony_ci */ 126e1051a39Sopenharmony_ci input[12]++; 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci} 129