1 // SPDX-License-Identifier: GPL-2.0-only
3 * ChaCha20 using the RISC-V vector crypto extensions
5 * Copyright (C) 2023 SiFive, Inc.
6 * Author: Jerry Shih <jerry.shih@sifive.com>
10 #include <asm/vector.h>
11 #include <crypto/internal/chacha.h>
12 #include <crypto/internal/skcipher.h>
13 #include <linux/linkage.h>
14 #include <linux/module.h>
16 asmlinkage
void chacha20_zvkb(const u32 key
[8], const u8
*in
, u8
*out
,
17 size_t len
, const u32 iv
[4]);
19 static int riscv64_chacha20_crypt(struct skcipher_request
*req
)
21 u32 iv
[CHACHA_IV_SIZE
/ sizeof(u32
)];
22 u8 block_buffer
[CHACHA_BLOCK_SIZE
];
23 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
24 const struct chacha_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
25 struct skcipher_walk walk
;
27 unsigned int tail_bytes
;
30 iv
[0] = get_unaligned_le32(req
->iv
);
31 iv
[1] = get_unaligned_le32(req
->iv
+ 4);
32 iv
[2] = get_unaligned_le32(req
->iv
+ 8);
33 iv
[3] = get_unaligned_le32(req
->iv
+ 12);
35 err
= skcipher_walk_virt(&walk
, req
, false);
37 nbytes
= walk
.nbytes
& ~(CHACHA_BLOCK_SIZE
- 1);
38 tail_bytes
= walk
.nbytes
& (CHACHA_BLOCK_SIZE
- 1);
39 kernel_vector_begin();
41 chacha20_zvkb(ctx
->key
, walk
.src
.virt
.addr
,
42 walk
.dst
.virt
.addr
, nbytes
, iv
);
43 iv
[0] += nbytes
/ CHACHA_BLOCK_SIZE
;
45 if (walk
.nbytes
== walk
.total
&& tail_bytes
> 0) {
46 memcpy(block_buffer
, walk
.src
.virt
.addr
+ nbytes
,
48 chacha20_zvkb(ctx
->key
, block_buffer
, block_buffer
,
49 CHACHA_BLOCK_SIZE
, iv
);
50 memcpy(walk
.dst
.virt
.addr
+ nbytes
, block_buffer
,
56 err
= skcipher_walk_done(&walk
, tail_bytes
);
62 static struct skcipher_alg riscv64_chacha_alg
= {
63 .setkey
= chacha20_setkey
,
64 .encrypt
= riscv64_chacha20_crypt
,
65 .decrypt
= riscv64_chacha20_crypt
,
66 .min_keysize
= CHACHA_KEY_SIZE
,
67 .max_keysize
= CHACHA_KEY_SIZE
,
68 .ivsize
= CHACHA_IV_SIZE
,
69 .chunksize
= CHACHA_BLOCK_SIZE
,
70 .walksize
= 4 * CHACHA_BLOCK_SIZE
,
73 .cra_ctxsize
= sizeof(struct chacha_ctx
),
75 .cra_name
= "chacha20",
76 .cra_driver_name
= "chacha20-riscv64-zvkb",
77 .cra_module
= THIS_MODULE
,
81 static int __init
riscv64_chacha_mod_init(void)
83 if (riscv_isa_extension_available(NULL
, ZVKB
) &&
84 riscv_vector_vlen() >= 128)
85 return crypto_register_skcipher(&riscv64_chacha_alg
);
90 static void __exit
riscv64_chacha_mod_exit(void)
92 crypto_unregister_skcipher(&riscv64_chacha_alg
);
95 module_init(riscv64_chacha_mod_init
);
96 module_exit(riscv64_chacha_mod_exit
);
98 MODULE_DESCRIPTION("ChaCha20 (RISC-V accelerated)");
99 MODULE_AUTHOR("Jerry Shih <jerry.shih@sifive.com>");
100 MODULE_LICENSE("GPL");
101 MODULE_ALIAS_CRYPTO("chacha20");