Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Common values and helper functions for the ChaCha and XChaCha stream ciphers.
0004  *
0005  * XChaCha extends ChaCha's nonce to 192 bits, while provably retaining ChaCha's
0006  * security.  Here they share the same key size, tfm context, and setkey
0007  * function; only their IV size and encrypt/decrypt function differ.
0008  *
0009  * The ChaCha paper specifies 20, 12, and 8-round variants.  In general, it is
0010  * recommended to use the 20-round variant ChaCha20.  However, the other
0011  * variants can be needed in some performance-sensitive scenarios.  The generic
0012  * ChaCha code currently allows only the 20 and 12-round variants.
0013  */
0014 
0015 #ifndef _CRYPTO_CHACHA_H
0016 #define _CRYPTO_CHACHA_H
0017 
0018 #include <asm/unaligned.h>
0019 #include <linux/types.h>
0020 
0021 /* 32-bit stream position, then 96-bit nonce (RFC7539 convention) */
0022 #define CHACHA_IV_SIZE      16
0023 
0024 #define CHACHA_KEY_SIZE     32
0025 #define CHACHA_BLOCK_SIZE   64
0026 #define CHACHAPOLY_IV_SIZE  12
0027 
0028 #define CHACHA_STATE_WORDS  (CHACHA_BLOCK_SIZE / sizeof(u32))
0029 
0030 /* 192-bit nonce, then 64-bit stream position */
0031 #define XCHACHA_IV_SIZE     32
0032 
0033 void chacha_block_generic(u32 *state, u8 *stream, int nrounds);
0034 static inline void chacha20_block(u32 *state, u8 *stream)
0035 {
0036     chacha_block_generic(state, stream, 20);
0037 }
0038 
0039 void hchacha_block_arch(const u32 *state, u32 *out, int nrounds);
0040 void hchacha_block_generic(const u32 *state, u32 *out, int nrounds);
0041 
0042 static inline void hchacha_block(const u32 *state, u32 *out, int nrounds)
0043 {
0044     if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
0045         hchacha_block_arch(state, out, nrounds);
0046     else
0047         hchacha_block_generic(state, out, nrounds);
0048 }
0049 
0050 enum chacha_constants { /* expand 32-byte k */
0051     CHACHA_CONSTANT_EXPA = 0x61707865U,
0052     CHACHA_CONSTANT_ND_3 = 0x3320646eU,
0053     CHACHA_CONSTANT_2_BY = 0x79622d32U,
0054     CHACHA_CONSTANT_TE_K = 0x6b206574U
0055 };
0056 
0057 static inline void chacha_init_consts(u32 *state)
0058 {
0059     state[0]  = CHACHA_CONSTANT_EXPA;
0060     state[1]  = CHACHA_CONSTANT_ND_3;
0061     state[2]  = CHACHA_CONSTANT_2_BY;
0062     state[3]  = CHACHA_CONSTANT_TE_K;
0063 }
0064 
0065 void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv);
0066 static inline void chacha_init_generic(u32 *state, const u32 *key, const u8 *iv)
0067 {
0068     chacha_init_consts(state);
0069     state[4]  = key[0];
0070     state[5]  = key[1];
0071     state[6]  = key[2];
0072     state[7]  = key[3];
0073     state[8]  = key[4];
0074     state[9]  = key[5];
0075     state[10] = key[6];
0076     state[11] = key[7];
0077     state[12] = get_unaligned_le32(iv +  0);
0078     state[13] = get_unaligned_le32(iv +  4);
0079     state[14] = get_unaligned_le32(iv +  8);
0080     state[15] = get_unaligned_le32(iv + 12);
0081 }
0082 
0083 static inline void chacha_init(u32 *state, const u32 *key, const u8 *iv)
0084 {
0085     if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
0086         chacha_init_arch(state, key, iv);
0087     else
0088         chacha_init_generic(state, key, iv);
0089 }
0090 
0091 void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src,
0092                unsigned int bytes, int nrounds);
0093 void chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src,
0094               unsigned int bytes, int nrounds);
0095 
0096 static inline void chacha_crypt(u32 *state, u8 *dst, const u8 *src,
0097                 unsigned int bytes, int nrounds)
0098 {
0099     if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA))
0100         chacha_crypt_arch(state, dst, src, bytes, nrounds);
0101     else
0102         chacha_crypt_generic(state, dst, src, bytes, nrounds);
0103 }
0104 
0105 static inline void chacha20_crypt(u32 *state, u8 *dst, const u8 *src,
0106                   unsigned int bytes)
0107 {
0108     chacha_crypt(state, dst, src, bytes, 20);
0109 }
0110 
0111 #endif /* _CRYPTO_CHACHA_H */