Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/crypto/arm64/chacha-neon-glue.c
26285 views
1
/*
2
* ChaCha and HChaCha functions (ARM64 optimized)
3
*
4
* Copyright (C) 2016 - 2017 Linaro, Ltd. <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*
10
* Based on:
11
* ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
12
*
13
* Copyright (C) 2015 Martin Willi
14
*
15
* This program is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License as published by
17
* the Free Software Foundation; either version 2 of the License, or
18
* (at your option) any later version.
19
*/
20
21
#include <crypto/chacha.h>
22
#include <crypto/internal/simd.h>
23
#include <linux/jump_label.h>
24
#include <linux/kernel.h>
25
#include <linux/module.h>
26
27
#include <asm/hwcap.h>
28
#include <asm/neon.h>
29
#include <asm/simd.h>
30
31
asmlinkage void chacha_block_xor_neon(const struct chacha_state *state,
32
u8 *dst, const u8 *src, int nrounds);
33
asmlinkage void chacha_4block_xor_neon(const struct chacha_state *state,
34
u8 *dst, const u8 *src,
35
int nrounds, int bytes);
36
asmlinkage void hchacha_block_neon(const struct chacha_state *state,
37
u32 out[HCHACHA_OUT_WORDS], int nrounds);
38
39
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
40
41
static void chacha_doneon(struct chacha_state *state, u8 *dst, const u8 *src,
42
int bytes, int nrounds)
43
{
44
while (bytes > 0) {
45
int l = min(bytes, CHACHA_BLOCK_SIZE * 5);
46
47
if (l <= CHACHA_BLOCK_SIZE) {
48
u8 buf[CHACHA_BLOCK_SIZE];
49
50
memcpy(buf, src, l);
51
chacha_block_xor_neon(state, buf, buf, nrounds);
52
memcpy(dst, buf, l);
53
state->x[12] += 1;
54
break;
55
}
56
chacha_4block_xor_neon(state, dst, src, nrounds, l);
57
bytes -= l;
58
src += l;
59
dst += l;
60
state->x[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE);
61
}
62
}
63
64
void hchacha_block_arch(const struct chacha_state *state,
65
u32 out[HCHACHA_OUT_WORDS], int nrounds)
66
{
67
if (!static_branch_likely(&have_neon) || !crypto_simd_usable()) {
68
hchacha_block_generic(state, out, nrounds);
69
} else {
70
kernel_neon_begin();
71
hchacha_block_neon(state, out, nrounds);
72
kernel_neon_end();
73
}
74
}
75
EXPORT_SYMBOL(hchacha_block_arch);
76
77
void chacha_crypt_arch(struct chacha_state *state, u8 *dst, const u8 *src,
78
unsigned int bytes, int nrounds)
79
{
80
if (!static_branch_likely(&have_neon) || bytes <= CHACHA_BLOCK_SIZE ||
81
!crypto_simd_usable())
82
return chacha_crypt_generic(state, dst, src, bytes, nrounds);
83
84
do {
85
unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
86
87
kernel_neon_begin();
88
chacha_doneon(state, dst, src, todo, nrounds);
89
kernel_neon_end();
90
91
bytes -= todo;
92
src += todo;
93
dst += todo;
94
} while (bytes);
95
}
96
EXPORT_SYMBOL(chacha_crypt_arch);
97
98
bool chacha_is_arch_optimized(void)
99
{
100
return static_key_enabled(&have_neon);
101
}
102
EXPORT_SYMBOL(chacha_is_arch_optimized);
103
104
static int __init chacha_simd_mod_init(void)
105
{
106
if (cpu_have_named_feature(ASIMD))
107
static_branch_enable(&have_neon);
108
return 0;
109
}
110
subsys_initcall(chacha_simd_mod_init);
111
112
static void __exit chacha_simd_mod_exit(void)
113
{
114
}
115
module_exit(chacha_simd_mod_exit);
116
117
MODULE_DESCRIPTION("ChaCha and HChaCha functions (ARM64 optimized)");
118
MODULE_AUTHOR("Ard Biesheuvel <[email protected]>");
119
MODULE_LICENSE("GPL v2");
120
121