Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/crypto/via/padlock.c
39492 views
1
/*-
2
* Copyright (c) 2005-2008 Pawel Jakub Dawidek <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <sys/param.h>
28
#include <sys/systm.h>
29
#include <sys/kernel.h>
30
#include <sys/module.h>
31
#include <sys/lock.h>
32
#include <sys/rwlock.h>
33
#include <sys/malloc.h>
34
#include <sys/libkern.h>
35
#if defined(__amd64__) || defined(__i386__)
36
#include <machine/cpufunc.h>
37
#include <machine/cputypes.h>
38
#include <machine/fpu.h>
39
#include <machine/md_var.h>
40
#include <machine/specialreg.h>
41
#endif
42
43
#include <opencrypto/cryptodev.h>
44
45
#include <crypto/via/padlock.h>
46
47
#include <sys/kobj.h>
48
#include <sys/bus.h>
49
#include "cryptodev_if.h"
50
51
/*
52
* Technical documentation about the PadLock engine can be found here:
53
*
54
* http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
55
*/
56
57
struct padlock_softc {
58
int32_t sc_cid;
59
};
60
61
static int padlock_probesession(device_t, const struct crypto_session_params *);
62
static int padlock_newsession(device_t, crypto_session_t cses,
63
const struct crypto_session_params *);
64
static void padlock_freesession(device_t, crypto_session_t cses);
65
static void padlock_freesession_one(struct padlock_session *ses);
66
static int padlock_process(device_t, struct cryptop *crp, int hint __unused);
67
68
MALLOC_DEFINE(M_PADLOCK, "padlock_data", "PadLock Data");
69
70
static void
71
padlock_identify(driver_t *drv, device_t parent)
72
{
73
/* NB: order 10 is so we get attached after h/w devices */
74
if (device_find_child(parent, "padlock", DEVICE_UNIT_ANY) == NULL &&
75
BUS_ADD_CHILD(parent, 10, "padlock", DEVICE_UNIT_ANY) == 0)
76
panic("padlock: could not attach");
77
}
78
79
static int
80
padlock_probe(device_t dev)
81
{
82
#if defined(__amd64__) || defined(__i386__)
83
/* If there is no AES support, we has nothing to do here. */
84
if (!(via_feature_xcrypt & VIA_HAS_AES)) {
85
device_printf(dev, "No ACE support.\n");
86
return (EINVAL);
87
}
88
device_set_descf(dev, "AES-CBC%s",
89
(via_feature_xcrypt & VIA_HAS_SHA) ? ",SHA1,SHA256" : "");
90
return (0);
91
#else
92
return (EINVAL);
93
#endif
94
}
95
96
static int
97
padlock_attach(device_t dev)
98
{
99
struct padlock_softc *sc = device_get_softc(dev);
100
101
sc->sc_cid = crypto_get_driverid(dev, sizeof(struct padlock_session),
102
CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
103
CRYPTOCAP_F_ACCEL_SOFTWARE);
104
if (sc->sc_cid < 0) {
105
device_printf(dev, "Could not get crypto driver id.\n");
106
return (ENOMEM);
107
}
108
109
return (0);
110
}
111
112
static int
113
padlock_detach(device_t dev)
114
{
115
struct padlock_softc *sc = device_get_softc(dev);
116
117
crypto_unregister_all(sc->sc_cid);
118
return (0);
119
}
120
121
static int
122
padlock_probesession(device_t dev, const struct crypto_session_params *csp)
123
{
124
125
if (csp->csp_flags != 0)
126
return (EINVAL);
127
128
/*
129
* We only support HMAC algorithms to be able to work with
130
* ipsec(4), so if we are asked only for authentication without
131
* encryption, don't pretend we can accelerate it.
132
*
133
* XXX: For CPUs with SHA instructions we should probably
134
* permit CSP_MODE_DIGEST so that those can be tested.
135
*/
136
switch (csp->csp_mode) {
137
case CSP_MODE_ETA:
138
if (!padlock_hash_check(csp))
139
return (EINVAL);
140
/* FALLTHROUGH */
141
case CSP_MODE_CIPHER:
142
switch (csp->csp_cipher_alg) {
143
case CRYPTO_AES_CBC:
144
if (csp->csp_ivlen != AES_BLOCK_LEN)
145
return (EINVAL);
146
break;
147
default:
148
return (EINVAL);
149
}
150
break;
151
default:
152
return (EINVAL);
153
}
154
155
return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
156
}
157
158
static int
159
padlock_newsession(device_t dev, crypto_session_t cses,
160
const struct crypto_session_params *csp)
161
{
162
struct padlock_session *ses;
163
struct thread *td;
164
int error;
165
166
ses = crypto_get_driver_session(cses);
167
168
error = padlock_cipher_setup(ses, csp);
169
if (error != 0) {
170
padlock_freesession_one(ses);
171
return (error);
172
}
173
174
if (csp->csp_mode == CSP_MODE_ETA) {
175
td = curthread;
176
fpu_kern_enter(td, NULL, FPU_KERN_NORMAL | FPU_KERN_NOCTX);
177
error = padlock_hash_setup(ses, csp);
178
fpu_kern_leave(td, NULL);
179
if (error != 0) {
180
padlock_freesession_one(ses);
181
return (error);
182
}
183
}
184
185
return (0);
186
}
187
188
static void
189
padlock_freesession_one(struct padlock_session *ses)
190
{
191
192
padlock_hash_free(ses);
193
}
194
195
static void
196
padlock_freesession(device_t dev, crypto_session_t cses)
197
{
198
struct padlock_session *ses;
199
200
ses = crypto_get_driver_session(cses);
201
padlock_freesession_one(ses);
202
}
203
204
static int
205
padlock_process(device_t dev, struct cryptop *crp, int hint __unused)
206
{
207
const struct crypto_session_params *csp;
208
struct padlock_session *ses;
209
int error;
210
211
if ((crp->crp_payload_length % AES_BLOCK_LEN) != 0) {
212
error = EINVAL;
213
goto out;
214
}
215
216
ses = crypto_get_driver_session(crp->crp_session);
217
csp = crypto_get_params(crp->crp_session);
218
219
/* Perform data authentication if requested before decryption. */
220
if (csp->csp_mode == CSP_MODE_ETA &&
221
!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
222
error = padlock_hash_process(ses, crp, csp);
223
if (error != 0)
224
goto out;
225
}
226
227
error = padlock_cipher_process(ses, crp, csp);
228
if (error != 0)
229
goto out;
230
231
/* Perform data authentication if requested after encryption. */
232
if (csp->csp_mode == CSP_MODE_ETA &&
233
CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
234
error = padlock_hash_process(ses, crp, csp);
235
if (error != 0)
236
goto out;
237
}
238
239
out:
240
#if 0
241
/*
242
* This code is not necessary, because contexts will be freed on next
243
* padlock_setup_mackey() call or at padlock_freesession() call.
244
*/
245
if (ses != NULL && maccrd != NULL &&
246
(maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
247
padlock_free_ctx(ses->ses_axf, ses->ses_ictx);
248
padlock_free_ctx(ses->ses_axf, ses->ses_octx);
249
}
250
#endif
251
crp->crp_etype = error;
252
crypto_done(crp);
253
return (0);
254
}
255
256
static device_method_t padlock_methods[] = {
257
DEVMETHOD(device_identify, padlock_identify),
258
DEVMETHOD(device_probe, padlock_probe),
259
DEVMETHOD(device_attach, padlock_attach),
260
DEVMETHOD(device_detach, padlock_detach),
261
262
DEVMETHOD(cryptodev_probesession, padlock_probesession),
263
DEVMETHOD(cryptodev_newsession, padlock_newsession),
264
DEVMETHOD(cryptodev_freesession,padlock_freesession),
265
DEVMETHOD(cryptodev_process, padlock_process),
266
267
{0, 0},
268
};
269
270
static driver_t padlock_driver = {
271
"padlock",
272
padlock_methods,
273
sizeof(struct padlock_softc),
274
};
275
276
/* XXX where to attach */
277
DRIVER_MODULE(padlock, nexus, padlock_driver, 0, 0);
278
MODULE_VERSION(padlock, 1);
279
MODULE_DEPEND(padlock, crypto, 1, 1, 1);
280
281