1/*	$NetBSD: aes_sse2_4x32_impl.c,v 1.1 2025/11/23 22:48:26 riastradh Exp $	*/
2
3/*-
4 * Copyright (c) 2025 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/cdefs.h>
30__KERNEL_RCSID(1, "$NetBSD: aes_sse2_4x32_impl.c,v 1.1 2025/11/23 22:48:26 riastradh Exp $");
31
32#include <sys/types.h>
33#include <sys/endian.h>
34
35#include <crypto/aes/aes.h>
36#include <crypto/aes/aes_impl.h>
37#include <crypto/aes/arch/x86/aes_sse2_4x32.h>
38
39#ifdef _KERNEL
40#include <x86/cpu.h>
41#include <x86/cpuvar.h>
42#include <x86/fpu.h>
43#include <x86/specialreg.h>
44#else
45#include <cpuid.h>
46#define	fpu_kern_enter()	((void)0)
47#define	fpu_kern_leave()	((void)0)
48#endif
49
50#include "aes_sse2_4x32_subr.h"
51
52static void
53aes_sse2_4x32_setenckey_impl(struct aesenc *enc, const uint8_t *key,
54    uint32_t nrounds)
55{
56
57	fpu_kern_enter();
58	aes_sse2_4x32_setkey(enc->aese_aes.aes_rk, key, nrounds);
59	fpu_kern_leave();
60}
61
62static void
63aes_sse2_4x32_setdeckey_impl(struct aesdec *dec, const uint8_t *key,
64    uint32_t nrounds)
65{
66
67	fpu_kern_enter();
68	/*
69	 * BearSSL computes InvMixColumns on the fly -- no need for
70	 * distinct decryption round keys.
71	 */
72	aes_sse2_4x32_setkey(dec->aesd_aes.aes_rk, key, nrounds);
73	fpu_kern_leave();
74}
75
76static void
77aes_sse2_4x32_enc_impl(const struct aesenc *enc, const uint8_t in[static 16],
78    uint8_t out[static 16], uint32_t nrounds)
79{
80
81	fpu_kern_enter();
82	aes_sse2_4x32_enc(enc, in, out, nrounds);
83	fpu_kern_leave();
84}
85
86static void
87aes_sse2_4x32_dec_impl(const struct aesdec *dec, const uint8_t in[static 16],
88    uint8_t out[static 16], uint32_t nrounds)
89{
90
91	fpu_kern_enter();
92	aes_sse2_4x32_dec(dec, in, out, nrounds);
93	fpu_kern_leave();
94}
95
96static void
97aes_sse2_4x32_cbc_enc_impl(const struct aesenc *enc,
98    const uint8_t in[static 16], uint8_t out[static 16],
99    size_t nbytes, uint8_t iv[static 16], uint32_t nrounds)
100{
101
102	if (nbytes == 0)
103		return;
104	fpu_kern_enter();
105	aes_sse2_4x32_cbc_enc(enc, in, out, nbytes, iv, nrounds);
106	fpu_kern_leave();
107}
108
109static void
110aes_sse2_4x32_cbc_dec_impl(const struct aesdec *dec,
111    const uint8_t in[static 16], uint8_t out[static 16],
112    size_t nbytes, uint8_t iv[static 16], uint32_t nrounds)
113{
114
115	if (nbytes == 0)
116		return;
117	fpu_kern_enter();
118	aes_sse2_4x32_cbc_dec(dec, in, out, nbytes, iv, nrounds);
119	fpu_kern_leave();
120}
121
122static void
123aes_sse2_4x32_xts_enc_impl(const struct aesenc *enc,
124    const uint8_t in[static 16], uint8_t out[static 16],
125    size_t nbytes, uint8_t tweak[static 16], uint32_t nrounds)
126{
127
128	if (nbytes == 0)
129		return;
130	fpu_kern_enter();
131	aes_sse2_4x32_xts_enc(enc, in, out, nbytes, tweak, nrounds);
132	fpu_kern_leave();
133}
134
135static void
136aes_sse2_4x32_xts_dec_impl(const struct aesdec *dec,
137    const uint8_t in[static 16], uint8_t out[static 16],
138    size_t nbytes, uint8_t tweak[static 16], uint32_t nrounds)
139{
140
141	if (nbytes == 0)
142		return;
143	fpu_kern_enter();
144	aes_sse2_4x32_xts_dec(dec, in, out, nbytes, tweak, nrounds);
145	fpu_kern_leave();
146}
147
148static void
149aes_sse2_4x32_cbcmac_update1_impl(const struct aesenc *enc,
150    const uint8_t in[static 16], size_t nbytes, uint8_t auth[static 16],
151    uint32_t nrounds)
152{
153
154	fpu_kern_enter();
155	aes_sse2_4x32_cbcmac_update1(enc, in, nbytes, auth, nrounds);
156	fpu_kern_leave();
157}
158
159static void
160aes_sse2_4x32_ccm_enc1_impl(const struct aesenc *enc,
161    const uint8_t *in, uint8_t *out,
162    size_t nbytes, uint8_t authctr[32], uint32_t nrounds)
163{
164
165	fpu_kern_enter();
166	aes_sse2_4x32_ccm_enc1(enc, in, out, nbytes, authctr, nrounds);
167	fpu_kern_leave();
168}
169
170static void
171aes_sse2_4x32_ccm_dec1_impl(const struct aesenc *enc,
172    const uint8_t *in, uint8_t *out,
173    size_t nbytes, uint8_t authctr[32], uint32_t nrounds)
174{
175
176	fpu_kern_enter();
177	aes_sse2_4x32_ccm_dec1(enc, in, out, nbytes, authctr, nrounds);
178	fpu_kern_leave();
179}
180
181static int
182aes_sse2_4x32_probe(void)
183{
184	int result = 0;
185
186	/* Verify that the CPU supports SSE and SSE2.  */
187#ifdef _KERNEL
188	if (!i386_has_sse)
189		return -1;
190	if (!i386_has_sse2)
191		return -1;
192#else
193	unsigned eax, ebx, ecx, edx;
194	if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
195		return -1;
196	if ((edx & bit_SSE) == 0)
197		return -1;
198	if ((edx & bit_SSE2) == 0)
199		return -1;
200#endif
201
202	fpu_kern_enter();
203	result = aes_sse2_4x32_selftest();
204	fpu_kern_leave();
205
206	return result;
207}
208
209struct aes_impl aes_sse2_4x32_impl = {
210	.ai_name = "Intel SSE2 4x32 bitsliced",
211	.ai_probe = aes_sse2_4x32_probe,
212	.ai_setenckey = aes_sse2_4x32_setenckey_impl,
213	.ai_setdeckey = aes_sse2_4x32_setdeckey_impl,
214	.ai_enc = aes_sse2_4x32_enc_impl,
215	.ai_dec = aes_sse2_4x32_dec_impl,
216	.ai_cbc_enc = aes_sse2_4x32_cbc_enc_impl,
217	.ai_cbc_dec = aes_sse2_4x32_cbc_dec_impl,
218	.ai_xts_enc = aes_sse2_4x32_xts_enc_impl,
219	.ai_xts_dec = aes_sse2_4x32_xts_dec_impl,
220	.ai_cbcmac_update1 = aes_sse2_4x32_cbcmac_update1_impl,
221	.ai_ccm_enc1 = aes_sse2_4x32_ccm_enc1_impl,
222	.ai_ccm_dec1 = aes_sse2_4x32_ccm_dec1_impl,
223};
224