1 /* $NetBSD: chacha_impl.c,v 1.4 2022/11/05 17:36:33 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/types.h>
30 #include <sys/cdefs.h>
31 #include <sys/errno.h>
32 #include <sys/module.h>
33 #include <sys/once.h>
34 #include <sys/sysctl.h>
35
36 #include <lib/libkern/libkern.h>
37
38 #include "chacha.h"
39 #include "chacha_ref.h"
40
41 static const struct chacha_impl *chacha_md_impl __read_mostly;
42 static const struct chacha_impl *chacha_impl __read_mostly = &chacha_ref_impl;
43
44 static int
sysctl_kern_crypto_chacha_selected(SYSCTLFN_ARGS)45 sysctl_kern_crypto_chacha_selected(SYSCTLFN_ARGS)
46 {
47 struct sysctlnode node;
48
49 node = *rnode;
50 node.sysctl_data = __UNCONST(chacha_impl->ci_name);
51 node.sysctl_size = strlen(chacha_impl->ci_name) + 1;
52 return sysctl_lookup(SYSCTLFN_CALL(&node));
53 }
54
55 SYSCTL_SETUP(sysctl_kern_crypto_chacha_setup, "sysctl kern.crypto.chacha setup")
56 {
57 const struct sysctlnode *cnode;
58 const struct sysctlnode *chacha_node;
59
60 sysctl_createv(clog, 0, NULL, &cnode, 0, CTLTYPE_NODE, "crypto",
61 SYSCTL_DESCR("Kernel cryptography"),
62 NULL, 0, NULL, 0,
63 CTL_KERN, CTL_CREATE, CTL_EOL);
64 sysctl_createv(clog, 0, &cnode, &chacha_node, 0, CTLTYPE_NODE, "chacha",
65 SYSCTL_DESCR("ChaCha"),
66 NULL, 0, NULL, 0,
67 CTL_CREATE, CTL_EOL);
68 sysctl_createv(clog, 0, &chacha_node, NULL,
69 CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING, "selected",
70 SYSCTL_DESCR("Selected ChaCha implementation"),
71 sysctl_kern_crypto_chacha_selected, 0, NULL, 0,
72 CTL_CREATE, CTL_EOL);
73 }
74
75 static int
chacha_select(void)76 chacha_select(void)
77 {
78
79 if (chacha_md_impl) {
80 if (chacha_selftest(chacha_md_impl))
81 aprint_error("chacha: self-test failed: %s\n",
82 chacha_md_impl->ci_name);
83 else
84 chacha_impl = chacha_md_impl;
85 }
86
87 aprint_debug("chacha: %s\n", chacha_impl->ci_name);
88 return 0;
89 }
90
91 MODULE(MODULE_CLASS_MISC, chacha, NULL);
92
93 static int
chacha_modcmd(modcmd_t cmd,void * opaque)94 chacha_modcmd(modcmd_t cmd, void *opaque)
95 {
96
97 switch (cmd) {
98 case MODULE_CMD_INIT:
99 return chacha_select();
100 case MODULE_CMD_FINI:
101 return 0;
102 default:
103 return ENOTTY;
104 }
105 }
106
107 void
chacha_md_init(const struct chacha_impl * impl)108 chacha_md_init(const struct chacha_impl *impl)
109 {
110
111 KASSERT(cold);
112 KASSERTMSG(chacha_md_impl == NULL,
113 "ChaCha implementation `%s' already offered, can't offer `%s'",
114 chacha_md_impl->ci_name, impl->ci_name);
115
116 chacha_md_impl = impl;
117 }
118
119 void
chacha_core(uint8_t out[restrict static CHACHA_CORE_OUTBYTES],const uint8_t in[static CHACHA_CORE_INBYTES],const uint8_t k[static CHACHA_CORE_KEYBYTES],const uint8_t c[static CHACHA_CORE_CONSTBYTES],unsigned nr)120 chacha_core(uint8_t out[restrict static CHACHA_CORE_OUTBYTES],
121 const uint8_t in[static CHACHA_CORE_INBYTES],
122 const uint8_t k[static CHACHA_CORE_KEYBYTES],
123 const uint8_t c[static CHACHA_CORE_CONSTBYTES],
124 unsigned nr)
125 {
126
127 (*chacha_impl->ci_chacha_core)(out, in, k, c, nr);
128 }
129
130 void
hchacha(uint8_t out[restrict static HCHACHA_OUTBYTES],const uint8_t in[static HCHACHA_INBYTES],const uint8_t k[static HCHACHA_KEYBYTES],const uint8_t c[static HCHACHA_CONSTBYTES],unsigned nr)131 hchacha(uint8_t out[restrict static HCHACHA_OUTBYTES],
132 const uint8_t in[static HCHACHA_INBYTES],
133 const uint8_t k[static HCHACHA_KEYBYTES],
134 const uint8_t c[static HCHACHA_CONSTBYTES],
135 unsigned nr)
136 {
137
138 (*chacha_impl->ci_hchacha)(out, in, k, c, nr);
139 }
140
141 void
chacha_stream(uint8_t * restrict s,size_t nbytes,uint32_t blkno,const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES],const uint8_t key[static CHACHA_STREAM_KEYBYTES],unsigned nr)142 chacha_stream(uint8_t *restrict s, size_t nbytes, uint32_t blkno,
143 const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES],
144 const uint8_t key[static CHACHA_STREAM_KEYBYTES],
145 unsigned nr)
146 {
147
148 (*chacha_impl->ci_chacha_stream)(s, nbytes, blkno, nonce, key, nr);
149 }
150
151 void
chacha_stream_xor(uint8_t * c,const uint8_t * p,size_t nbytes,uint32_t blkno,const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES],const uint8_t key[static CHACHA_STREAM_KEYBYTES],unsigned nr)152 chacha_stream_xor(uint8_t *c, const uint8_t *p, size_t nbytes, uint32_t blkno,
153 const uint8_t nonce[static CHACHA_STREAM_NONCEBYTES],
154 const uint8_t key[static CHACHA_STREAM_KEYBYTES],
155 unsigned nr)
156 {
157
158 (*chacha_impl->ci_chacha_stream_xor)(c, p, nbytes, blkno, nonce, key,
159 nr);
160 }
161
162 void
xchacha_stream(uint8_t * restrict s,size_t nbytes,uint32_t blkno,const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES],const uint8_t key[static XCHACHA_STREAM_KEYBYTES],unsigned nr)163 xchacha_stream(uint8_t *restrict s, size_t nbytes, uint32_t blkno,
164 const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES],
165 const uint8_t key[static XCHACHA_STREAM_KEYBYTES],
166 unsigned nr)
167 {
168
169 (*chacha_impl->ci_xchacha_stream)(s, nbytes, blkno, nonce, key, nr);
170 }
171
172 void
xchacha_stream_xor(uint8_t * c,const uint8_t * p,size_t nbytes,uint32_t blkno,const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES],const uint8_t key[static XCHACHA_STREAM_KEYBYTES],unsigned nr)173 xchacha_stream_xor(uint8_t *c, const uint8_t *p, size_t nbytes, uint32_t blkno,
174 const uint8_t nonce[static XCHACHA_STREAM_NONCEBYTES],
175 const uint8_t key[static XCHACHA_STREAM_KEYBYTES],
176 unsigned nr)
177 {
178
179 (*chacha_impl->ci_xchacha_stream_xor)(c, p, nbytes, blkno, nonce, key,
180 nr);
181 }
182