~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/crypto/chacha_generic.c

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp