Blame view
crypto/chacha_generic.c
5.82 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
c08d0e647 crypto: chacha20 ... |
2 |
/* |
aa7624093 crypto: chacha - ... |
3 |
* ChaCha and XChaCha stream ciphers, including ChaCha20 (RFC7539) |
c08d0e647 crypto: chacha20 ... |
4 5 |
* * Copyright (C) 2015 Martin Willi |
de61d7ae5 crypto: chacha20-... |
6 |
* Copyright (C) 2018 Google LLC |
c08d0e647 crypto: chacha20 ... |
7 |
*/ |
dbd872a12 crypto: chacha20 ... |
8 |
#include <asm/unaligned.h> |
c08d0e647 crypto: chacha20 ... |
9 |
#include <crypto/algapi.h> |
1ca1b9179 crypto: chacha20-... |
10 |
#include <crypto/chacha.h> |
9ae433bc7 crypto: chacha20 ... |
11 12 |
#include <crypto/internal/skcipher.h> #include <linux/module.h> |
c08d0e647 crypto: chacha20 ... |
13 |
|
1ca1b9179 crypto: chacha20-... |
14 15 |
static void chacha_docrypt(u32 *state, u8 *dst, const u8 *src, unsigned int bytes, int nrounds) |
c08d0e647 crypto: chacha20 ... |
16 |
{ |
a5e9f5570 crypto: chacha20 ... |
17 |
/* aligned to potentially speed up crypto_xor() */ |
1ca1b9179 crypto: chacha20-... |
18 |
u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long)); |
c08d0e647 crypto: chacha20 ... |
19 |
|
1ca1b9179 crypto: chacha20-... |
20 21 |
while (bytes >= CHACHA_BLOCK_SIZE) { chacha_block(state, stream, nrounds); |
29d97dec2 crypto: chacha-ge... |
22 |
crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE); |
1ca1b9179 crypto: chacha20-... |
23 24 |
bytes -= CHACHA_BLOCK_SIZE; dst += CHACHA_BLOCK_SIZE; |
29d97dec2 crypto: chacha-ge... |
25 |
src += CHACHA_BLOCK_SIZE; |
c08d0e647 crypto: chacha20 ... |
26 27 |
} if (bytes) { |
1ca1b9179 crypto: chacha20-... |
28 |
chacha_block(state, stream, nrounds); |
29d97dec2 crypto: chacha-ge... |
29 |
crypto_xor_cpy(dst, src, stream, bytes); |
c08d0e647 crypto: chacha20 ... |
30 31 |
} } |
1ca1b9179 crypto: chacha20-... |
32 |
static int chacha_stream_xor(struct skcipher_request *req, |
860ab2e50 crypto: chacha - ... |
33 |
const struct chacha_ctx *ctx, const u8 *iv) |
de61d7ae5 crypto: chacha20-... |
34 35 36 37 38 39 |
{ struct skcipher_walk walk; u32 state[16]; int err; err = skcipher_walk_virt(&walk, req, false); |
1ca1b9179 crypto: chacha20-... |
40 |
crypto_chacha_init(state, ctx, iv); |
de61d7ae5 crypto: chacha20-... |
41 42 43 44 45 |
while (walk.nbytes > 0) { unsigned int nbytes = walk.nbytes; if (nbytes < walk.total) |
7aceaaef0 crypto: chacha-ge... |
46 |
nbytes = round_down(nbytes, CHACHA_BLOCK_SIZE); |
de61d7ae5 crypto: chacha20-... |
47 |
|
1ca1b9179 crypto: chacha20-... |
48 49 |
chacha_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr, nbytes, ctx->nrounds); |
de61d7ae5 crypto: chacha20-... |
50 51 52 53 54 |
err = skcipher_walk_done(&walk, walk.nbytes - nbytes); } return err; } |
860ab2e50 crypto: chacha - ... |
55 |
void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv) |
c08d0e647 crypto: chacha20 ... |
56 |
{ |
ecf3220d8 crypto: chacha20 ... |
57 58 59 60 |
state[0] = 0x61707865; /* "expa" */ state[1] = 0x3320646e; /* "nd 3" */ state[2] = 0x79622d32; /* "2-by" */ state[3] = 0x6b206574; /* "te k" */ |
c08d0e647 crypto: chacha20 ... |
61 62 63 64 65 66 67 68 |
state[4] = ctx->key[0]; state[5] = ctx->key[1]; state[6] = ctx->key[2]; state[7] = ctx->key[3]; state[8] = ctx->key[4]; state[9] = ctx->key[5]; state[10] = ctx->key[6]; state[11] = ctx->key[7]; |
dbd872a12 crypto: chacha20 ... |
69 70 71 72 |
state[12] = get_unaligned_le32(iv + 0); state[13] = get_unaligned_le32(iv + 4); state[14] = get_unaligned_le32(iv + 8); state[15] = get_unaligned_le32(iv + 12); |
c08d0e647 crypto: chacha20 ... |
73 |
} |
1ca1b9179 crypto: chacha20-... |
74 |
EXPORT_SYMBOL_GPL(crypto_chacha_init); |
c08d0e647 crypto: chacha20 ... |
75 |
|
1ca1b9179 crypto: chacha20-... |
76 77 |
static int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keysize, int nrounds) |
c08d0e647 crypto: chacha20 ... |
78 |
{ |
1ca1b9179 crypto: chacha20-... |
79 |
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); |
c08d0e647 crypto: chacha20 ... |
80 |
int i; |
1ca1b9179 crypto: chacha20-... |
81 |
if (keysize != CHACHA_KEY_SIZE) |
c08d0e647 crypto: chacha20 ... |
82 83 84 |
return -EINVAL; for (i = 0; i < ARRAY_SIZE(ctx->key); i++) |
dbd872a12 crypto: chacha20 ... |
85 |
ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32)); |
c08d0e647 crypto: chacha20 ... |
86 |
|
1ca1b9179 crypto: chacha20-... |
87 |
ctx->nrounds = nrounds; |
c08d0e647 crypto: chacha20 ... |
88 89 |
return 0; } |
1ca1b9179 crypto: chacha20-... |
90 91 92 93 94 95 |
int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keysize) { return chacha_setkey(tfm, key, keysize, 20); } |
31d7247da crypto: chacha20 ... |
96 |
EXPORT_SYMBOL_GPL(crypto_chacha20_setkey); |
c08d0e647 crypto: chacha20 ... |
97 |
|
aa7624093 crypto: chacha - ... |
98 99 100 101 102 103 |
int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keysize) { return chacha_setkey(tfm, key, keysize, 12); } EXPORT_SYMBOL_GPL(crypto_chacha12_setkey); |
1ca1b9179 crypto: chacha20-... |
104 |
int crypto_chacha_crypt(struct skcipher_request *req) |
c08d0e647 crypto: chacha20 ... |
105 |
{ |
9ae433bc7 crypto: chacha20 ... |
106 |
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
1ca1b9179 crypto: chacha20-... |
107 |
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); |
c08d0e647 crypto: chacha20 ... |
108 |
|
1ca1b9179 crypto: chacha20-... |
109 |
return chacha_stream_xor(req, ctx, req->iv); |
de61d7ae5 crypto: chacha20-... |
110 |
} |
1ca1b9179 crypto: chacha20-... |
111 |
EXPORT_SYMBOL_GPL(crypto_chacha_crypt); |
c08d0e647 crypto: chacha20 ... |
112 |
|
1ca1b9179 crypto: chacha20-... |
113 |
int crypto_xchacha_crypt(struct skcipher_request *req) |
de61d7ae5 crypto: chacha20-... |
114 115 |
{ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
1ca1b9179 crypto: chacha20-... |
116 117 |
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); struct chacha_ctx subctx; |
de61d7ae5 crypto: chacha20-... |
118 119 |
u32 state[16]; u8 real_iv[16]; |
4de437265 crypto: chacha20 ... |
120 |
|
de61d7ae5 crypto: chacha20-... |
121 |
/* Compute the subkey given the original key and first 128 nonce bits */ |
1ca1b9179 crypto: chacha20-... |
122 123 124 |
crypto_chacha_init(state, ctx, req->iv); hchacha_block(state, subctx.key, ctx->nrounds); subctx.nrounds = ctx->nrounds; |
4de437265 crypto: chacha20 ... |
125 |
|
de61d7ae5 crypto: chacha20-... |
126 127 128 |
/* Build the real IV */ memcpy(&real_iv[0], req->iv + 24, 8); /* stream position */ memcpy(&real_iv[8], req->iv + 16, 8); /* remaining 64 nonce bits */ |
c08d0e647 crypto: chacha20 ... |
129 |
|
de61d7ae5 crypto: chacha20-... |
130 |
/* Generate the stream and XOR it with the data */ |
1ca1b9179 crypto: chacha20-... |
131 |
return chacha_stream_xor(req, &subctx, real_iv); |
c08d0e647 crypto: chacha20 ... |
132 |
} |
1ca1b9179 crypto: chacha20-... |
133 |
EXPORT_SYMBOL_GPL(crypto_xchacha_crypt); |
de61d7ae5 crypto: chacha20-... |
134 135 136 137 138 139 140 |
static struct skcipher_alg algs[] = { { .base.cra_name = "chacha20", .base.cra_driver_name = "chacha20-generic", .base.cra_priority = 100, .base.cra_blocksize = 1, |
1ca1b9179 crypto: chacha20-... |
141 |
.base.cra_ctxsize = sizeof(struct chacha_ctx), |
de61d7ae5 crypto: chacha20-... |
142 |
.base.cra_module = THIS_MODULE, |
1ca1b9179 crypto: chacha20-... |
143 144 145 146 |
.min_keysize = CHACHA_KEY_SIZE, .max_keysize = CHACHA_KEY_SIZE, .ivsize = CHACHA_IV_SIZE, .chunksize = CHACHA_BLOCK_SIZE, |
de61d7ae5 crypto: chacha20-... |
147 |
.setkey = crypto_chacha20_setkey, |
1ca1b9179 crypto: chacha20-... |
148 149 |
.encrypt = crypto_chacha_crypt, .decrypt = crypto_chacha_crypt, |
de61d7ae5 crypto: chacha20-... |
150 151 152 153 154 |
}, { .base.cra_name = "xchacha20", .base.cra_driver_name = "xchacha20-generic", .base.cra_priority = 100, .base.cra_blocksize = 1, |
1ca1b9179 crypto: chacha20-... |
155 |
.base.cra_ctxsize = sizeof(struct chacha_ctx), |
de61d7ae5 crypto: chacha20-... |
156 |
.base.cra_module = THIS_MODULE, |
1ca1b9179 crypto: chacha20-... |
157 158 159 160 |
.min_keysize = CHACHA_KEY_SIZE, .max_keysize = CHACHA_KEY_SIZE, .ivsize = XCHACHA_IV_SIZE, .chunksize = CHACHA_BLOCK_SIZE, |
de61d7ae5 crypto: chacha20-... |
161 |
.setkey = crypto_chacha20_setkey, |
1ca1b9179 crypto: chacha20-... |
162 163 |
.encrypt = crypto_xchacha_crypt, .decrypt = crypto_xchacha_crypt, |
aa7624093 crypto: chacha - ... |
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
}, { .base.cra_name = "xchacha12", .base.cra_driver_name = "xchacha12-generic", .base.cra_priority = 100, .base.cra_blocksize = 1, .base.cra_ctxsize = sizeof(struct chacha_ctx), .base.cra_module = THIS_MODULE, .min_keysize = CHACHA_KEY_SIZE, .max_keysize = CHACHA_KEY_SIZE, .ivsize = XCHACHA_IV_SIZE, .chunksize = CHACHA_BLOCK_SIZE, .setkey = crypto_chacha12_setkey, .encrypt = crypto_xchacha_crypt, .decrypt = crypto_xchacha_crypt, |
de61d7ae5 crypto: chacha20-... |
179 |
} |
c08d0e647 crypto: chacha20 ... |
180 |
}; |
1ca1b9179 crypto: chacha20-... |
181 |
static int __init chacha_generic_mod_init(void) |
c08d0e647 crypto: chacha20 ... |
182 |
{ |
de61d7ae5 crypto: chacha20-... |
183 |
return crypto_register_skciphers(algs, ARRAY_SIZE(algs)); |
c08d0e647 crypto: chacha20 ... |
184 |
} |
1ca1b9179 crypto: chacha20-... |
185 |
static void __exit chacha_generic_mod_fini(void) |
c08d0e647 crypto: chacha20 ... |
186 |
{ |
de61d7ae5 crypto: chacha20-... |
187 |
crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); |
c08d0e647 crypto: chacha20 ... |
188 |
} |
c4741b230 crypto: run initc... |
189 |
subsys_initcall(chacha_generic_mod_init); |
1ca1b9179 crypto: chacha20-... |
190 |
module_exit(chacha_generic_mod_fini); |
c08d0e647 crypto: chacha20 ... |
191 192 193 |
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Willi <martin@strongswan.org>"); |
1ca1b9179 crypto: chacha20-... |
194 |
MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (generic)"); |
c08d0e647 crypto: chacha20 ... |
195 196 |
MODULE_ALIAS_CRYPTO("chacha20"); MODULE_ALIAS_CRYPTO("chacha20-generic"); |
de61d7ae5 crypto: chacha20-... |
197 198 |
MODULE_ALIAS_CRYPTO("xchacha20"); MODULE_ALIAS_CRYPTO("xchacha20-generic"); |
aa7624093 crypto: chacha - ... |
199 200 |
MODULE_ALIAS_CRYPTO("xchacha12"); MODULE_ALIAS_CRYPTO("xchacha12-generic"); |