crypto: mips/chacha - wire up accelerated 32r2 code from Zinc
[linux-block.git] / crypto / chacha_generic.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
c08d0e64 2/*
aa762409 3 * ChaCha and XChaCha stream ciphers, including ChaCha20 (RFC7539)
c08d0e64
MW
4 *
5 * Copyright (C) 2015 Martin Willi
de61d7ae 6 * Copyright (C) 2018 Google LLC
c08d0e64
MW
7 */
8
dbd872a1 9#include <asm/unaligned.h>
c08d0e64 10#include <crypto/algapi.h>
5fb8ef25 11#include <crypto/internal/chacha.h>
9ae433bc
AB
12#include <crypto/internal/skcipher.h>
13#include <linux/module.h>
c08d0e64 14
1ca1b917 15static int chacha_stream_xor(struct skcipher_request *req,
860ab2e5 16 const struct chacha_ctx *ctx, const u8 *iv)
de61d7ae
EB
17{
18 struct skcipher_walk walk;
19 u32 state[16];
20 int err;
21
22 err = skcipher_walk_virt(&walk, req, false);
23
1ca1b917 24 crypto_chacha_init(state, ctx, iv);
de61d7ae
EB
25
26 while (walk.nbytes > 0) {
27 unsigned int nbytes = walk.nbytes;
28
29 if (nbytes < walk.total)
7aceaaef 30 nbytes = round_down(nbytes, CHACHA_BLOCK_SIZE);
de61d7ae 31
5fb8ef25
AB
32 chacha_crypt_generic(state, walk.dst.virt.addr,
33 walk.src.virt.addr, nbytes, ctx->nrounds);
de61d7ae
EB
34 err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
35 }
36
37 return err;
38}
39
860ab2e5 40void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv)
c08d0e64 41{
5fb8ef25 42 chacha_init_generic(state, ctx->key, iv);
c08d0e64 43}
1ca1b917 44EXPORT_SYMBOL_GPL(crypto_chacha_init);
c08d0e64 45
1ca1b917
EB
46int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
47 unsigned int keysize)
48{
49 return chacha_setkey(tfm, key, keysize, 20);
50}
31d7247d 51EXPORT_SYMBOL_GPL(crypto_chacha20_setkey);
c08d0e64 52
aa762409
EB
53int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
54 unsigned int keysize)
55{
56 return chacha_setkey(tfm, key, keysize, 12);
57}
58EXPORT_SYMBOL_GPL(crypto_chacha12_setkey);
59
1ca1b917 60int crypto_chacha_crypt(struct skcipher_request *req)
c08d0e64 61{
9ae433bc 62 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
1ca1b917 63 struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
c08d0e64 64
1ca1b917 65 return chacha_stream_xor(req, ctx, req->iv);
de61d7ae 66}
1ca1b917 67EXPORT_SYMBOL_GPL(crypto_chacha_crypt);
c08d0e64 68
1ca1b917 69int crypto_xchacha_crypt(struct skcipher_request *req)
de61d7ae
EB
70{
71 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
1ca1b917
EB
72 struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
73 struct chacha_ctx subctx;
de61d7ae
EB
74 u32 state[16];
75 u8 real_iv[16];
4de43726 76
de61d7ae 77 /* Compute the subkey given the original key and first 128 nonce bits */
1ca1b917 78 crypto_chacha_init(state, ctx, req->iv);
5fb8ef25 79 hchacha_block_generic(state, subctx.key, ctx->nrounds);
1ca1b917 80 subctx.nrounds = ctx->nrounds;
4de43726 81
de61d7ae
EB
82 /* Build the real IV */
83 memcpy(&real_iv[0], req->iv + 24, 8); /* stream position */
84 memcpy(&real_iv[8], req->iv + 16, 8); /* remaining 64 nonce bits */
c08d0e64 85
de61d7ae 86 /* Generate the stream and XOR it with the data */
1ca1b917 87 return chacha_stream_xor(req, &subctx, real_iv);
c08d0e64 88}
1ca1b917 89EXPORT_SYMBOL_GPL(crypto_xchacha_crypt);
de61d7ae
EB
90
91static struct skcipher_alg algs[] = {
92 {
93 .base.cra_name = "chacha20",
94 .base.cra_driver_name = "chacha20-generic",
95 .base.cra_priority = 100,
96 .base.cra_blocksize = 1,
1ca1b917 97 .base.cra_ctxsize = sizeof(struct chacha_ctx),
de61d7ae
EB
98 .base.cra_module = THIS_MODULE,
99
1ca1b917
EB
100 .min_keysize = CHACHA_KEY_SIZE,
101 .max_keysize = CHACHA_KEY_SIZE,
102 .ivsize = CHACHA_IV_SIZE,
103 .chunksize = CHACHA_BLOCK_SIZE,
de61d7ae 104 .setkey = crypto_chacha20_setkey,
1ca1b917
EB
105 .encrypt = crypto_chacha_crypt,
106 .decrypt = crypto_chacha_crypt,
de61d7ae
EB
107 }, {
108 .base.cra_name = "xchacha20",
109 .base.cra_driver_name = "xchacha20-generic",
110 .base.cra_priority = 100,
111 .base.cra_blocksize = 1,
1ca1b917 112 .base.cra_ctxsize = sizeof(struct chacha_ctx),
de61d7ae
EB
113 .base.cra_module = THIS_MODULE,
114
1ca1b917
EB
115 .min_keysize = CHACHA_KEY_SIZE,
116 .max_keysize = CHACHA_KEY_SIZE,
117 .ivsize = XCHACHA_IV_SIZE,
118 .chunksize = CHACHA_BLOCK_SIZE,
de61d7ae 119 .setkey = crypto_chacha20_setkey,
1ca1b917
EB
120 .encrypt = crypto_xchacha_crypt,
121 .decrypt = crypto_xchacha_crypt,
aa762409
EB
122 }, {
123 .base.cra_name = "xchacha12",
124 .base.cra_driver_name = "xchacha12-generic",
125 .base.cra_priority = 100,
126 .base.cra_blocksize = 1,
127 .base.cra_ctxsize = sizeof(struct chacha_ctx),
128 .base.cra_module = THIS_MODULE,
129
130 .min_keysize = CHACHA_KEY_SIZE,
131 .max_keysize = CHACHA_KEY_SIZE,
132 .ivsize = XCHACHA_IV_SIZE,
133 .chunksize = CHACHA_BLOCK_SIZE,
134 .setkey = crypto_chacha12_setkey,
135 .encrypt = crypto_xchacha_crypt,
136 .decrypt = crypto_xchacha_crypt,
de61d7ae 137 }
c08d0e64
MW
138};
139
1ca1b917 140static int __init chacha_generic_mod_init(void)
c08d0e64 141{
de61d7ae 142 return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
c08d0e64
MW
143}
144
1ca1b917 145static void __exit chacha_generic_mod_fini(void)
c08d0e64 146{
de61d7ae 147 crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
c08d0e64
MW
148}
149
c4741b23 150subsys_initcall(chacha_generic_mod_init);
1ca1b917 151module_exit(chacha_generic_mod_fini);
c08d0e64
MW
152
153MODULE_LICENSE("GPL");
154MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
1ca1b917 155MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (generic)");
c08d0e64
MW
156MODULE_ALIAS_CRYPTO("chacha20");
157MODULE_ALIAS_CRYPTO("chacha20-generic");
de61d7ae
EB
158MODULE_ALIAS_CRYPTO("xchacha20");
159MODULE_ALIAS_CRYPTO("xchacha20-generic");
aa762409
EB
160MODULE_ALIAS_CRYPTO("xchacha12");
161MODULE_ALIAS_CRYPTO("xchacha12-generic");