18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Common values and helper functions for the ChaCha and XChaCha stream ciphers. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * XChaCha extends ChaCha's nonce to 192 bits, while provably retaining ChaCha's 68c2ecf20Sopenharmony_ci * security. Here they share the same key size, tfm context, and setkey 78c2ecf20Sopenharmony_ci * function; only their IV size and encrypt/decrypt function differ. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * The ChaCha paper specifies 20, 12, and 8-round variants. In general, it is 108c2ecf20Sopenharmony_ci * recommended to use the 20-round variant ChaCha20. However, the other 118c2ecf20Sopenharmony_ci * variants can be needed in some performance-sensitive scenarios. The generic 128c2ecf20Sopenharmony_ci * ChaCha code currently allows only the 20 and 12-round variants. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifndef _CRYPTO_CHACHA_H 168c2ecf20Sopenharmony_ci#define _CRYPTO_CHACHA_H 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 198c2ecf20Sopenharmony_ci#include <linux/types.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 32-bit stream position, then 96-bit nonce (RFC7539 convention) */ 228c2ecf20Sopenharmony_ci#define CHACHA_IV_SIZE 16 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define CHACHA_KEY_SIZE 32 258c2ecf20Sopenharmony_ci#define CHACHA_BLOCK_SIZE 64 268c2ecf20Sopenharmony_ci#define CHACHAPOLY_IV_SIZE 12 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define CHACHA_STATE_WORDS (CHACHA_BLOCK_SIZE / sizeof(u32)) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 192-bit nonce, then 64-bit stream position */ 318c2ecf20Sopenharmony_ci#define XCHACHA_IV_SIZE 32 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid chacha_block_generic(u32 *state, u8 *stream, int nrounds); 348c2ecf20Sopenharmony_cistatic inline void chacha20_block(u32 *state, u8 *stream) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci chacha_block_generic(state, stream, 20); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_civoid hchacha_block_arch(const u32 *state, u32 *out, int nrounds); 408c2ecf20Sopenharmony_civoid hchacha_block_generic(const u32 *state, u32 *out, int nrounds); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic inline void hchacha_block(const u32 *state, u32 *out, int nrounds) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) 458c2ecf20Sopenharmony_ci hchacha_block_arch(state, out, nrounds); 468c2ecf20Sopenharmony_ci else 478c2ecf20Sopenharmony_ci hchacha_block_generic(state, out, nrounds); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cienum chacha_constants { /* expand 32-byte k */ 518c2ecf20Sopenharmony_ci CHACHA_CONSTANT_EXPA = 0x61707865U, 528c2ecf20Sopenharmony_ci CHACHA_CONSTANT_ND_3 = 0x3320646eU, 538c2ecf20Sopenharmony_ci CHACHA_CONSTANT_2_BY = 0x79622d32U, 548c2ecf20Sopenharmony_ci CHACHA_CONSTANT_TE_K = 0x6b206574U 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline void chacha_init_consts(u32 *state) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci state[0] = CHACHA_CONSTANT_EXPA; 608c2ecf20Sopenharmony_ci state[1] = CHACHA_CONSTANT_ND_3; 618c2ecf20Sopenharmony_ci state[2] = CHACHA_CONSTANT_2_BY; 628c2ecf20Sopenharmony_ci state[3] = CHACHA_CONSTANT_TE_K; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid chacha_init_arch(u32 *state, const u32 *key, const u8 *iv); 668c2ecf20Sopenharmony_cistatic inline void chacha_init_generic(u32 *state, const u32 *key, const u8 *iv) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci chacha_init_consts(state); 698c2ecf20Sopenharmony_ci state[4] = key[0]; 708c2ecf20Sopenharmony_ci state[5] = key[1]; 718c2ecf20Sopenharmony_ci state[6] = key[2]; 728c2ecf20Sopenharmony_ci state[7] = key[3]; 738c2ecf20Sopenharmony_ci state[8] = key[4]; 748c2ecf20Sopenharmony_ci state[9] = key[5]; 758c2ecf20Sopenharmony_ci state[10] = key[6]; 768c2ecf20Sopenharmony_ci state[11] = key[7]; 778c2ecf20Sopenharmony_ci state[12] = get_unaligned_le32(iv + 0); 788c2ecf20Sopenharmony_ci state[13] = get_unaligned_le32(iv + 4); 798c2ecf20Sopenharmony_ci state[14] = get_unaligned_le32(iv + 8); 808c2ecf20Sopenharmony_ci state[15] = get_unaligned_le32(iv + 12); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline void chacha_init(u32 *state, const u32 *key, const u8 *iv) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) 868c2ecf20Sopenharmony_ci chacha_init_arch(state, key, iv); 878c2ecf20Sopenharmony_ci else 888c2ecf20Sopenharmony_ci chacha_init_generic(state, key, iv); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_civoid chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, 928c2ecf20Sopenharmony_ci unsigned int bytes, int nrounds); 938c2ecf20Sopenharmony_civoid chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src, 948c2ecf20Sopenharmony_ci unsigned int bytes, int nrounds); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void chacha_crypt(u32 *state, u8 *dst, const u8 *src, 978c2ecf20Sopenharmony_ci unsigned int bytes, int nrounds) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) 1008c2ecf20Sopenharmony_ci chacha_crypt_arch(state, dst, src, bytes, nrounds); 1018c2ecf20Sopenharmony_ci else 1028c2ecf20Sopenharmony_ci chacha_crypt_generic(state, dst, src, bytes, nrounds); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic inline void chacha20_crypt(u32 *state, u8 *dst, const u8 *src, 1068c2ecf20Sopenharmony_ci unsigned int bytes) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci chacha_crypt(state, dst, src, bytes, 20); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#endif /* _CRYPTO_CHACHA_H */ 112