2 * Copyright (c) 2005-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/sys/crypto/via/padlock.c,v 1.23 2009/02/05 19:30:28 imp Exp $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/module.h>
34 #include <sys/malloc.h>
35 #include <sys/libkern.h>
36 #if defined(__x86_64__) || defined(__i386__)
37 #include <machine/cpufunc.h>
38 #include <machine/cputypes.h>
39 #include <machine/md_var.h>
40 #include <machine/specialreg.h>
43 #include <opencrypto/cryptodev.h>
45 #include <crypto/via/padlock.h>
49 #include "cryptodev_if.h"
52 * Technical documentation about the PadLock engine can be found here:
54 * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
57 struct padlock_softc
{
60 TAILQ_HEAD(padlock_sessions_head
, padlock_session
) sc_sessions
;
61 struct lock sc_sessions_lock
;
64 static int padlock_newsession(device_t
, uint32_t *sidp
, struct cryptoini
*cri
);
65 static int padlock_freesession(device_t
, uint64_t tid
);
66 static void padlock_freesession_one(struct padlock_softc
*sc
,
67 struct padlock_session
*ses
, int locked
);
68 static int padlock_process(device_t
, struct cryptop
*crp
, int hint __unused
);
70 MALLOC_DEFINE(M_PADLOCK
, "padlock_data", "PadLock Data");
73 padlock_identify(driver_t
*drv
, device_t parent
)
75 /* NB: order 10 is so we get attached after h/w devices */
76 /* XXX: wouldn't bet about this BUS_ADD_CHILD correctness */
77 if (device_find_child(parent
, "padlock", -1) == NULL
&&
78 BUS_ADD_CHILD(parent
, parent
, 10, "padlock", -1) == 0)
79 panic("padlock: could not attach");
83 padlock_probe(device_t dev
)
87 #if defined(__x86_64__) || defined(__i386__)
88 /* If there is no AES support, we has nothing to do here. */
89 if (!(via_feature_xcrypt
& VIA_HAS_AES
)) {
90 device_printf(dev
, "No ACE support.\n");
93 strlcpy(capp
, "AES-CBC", sizeof(capp
));
95 strlcat(capp
, ",AES-EBC", sizeof(capp
));
96 strlcat(capp
, ",AES-CFB", sizeof(capp
));
97 strlcat(capp
, ",AES-OFB", sizeof(capp
));
99 if (via_feature_xcrypt
& VIA_HAS_SHA
) {
100 strlcat(capp
, ",SHA1", sizeof(capp
));
101 strlcat(capp
, ",SHA256", sizeof(capp
));
104 if (via_feature_xcrypt
& VIA_HAS_AESCTR
)
105 strlcat(capp
, ",AES-CTR", sizeof(capp
));
106 if (via_feature_xcrypt
& VIA_HAS_MM
)
107 strlcat(capp
, ",RSA", sizeof(capp
));
109 device_set_desc_copy(dev
, capp
);
117 padlock_attach(device_t dev
)
119 struct padlock_softc
*sc
= device_get_softc(dev
);
121 TAILQ_INIT(&sc
->sc_sessions
);
124 sc
->sc_cid
= crypto_get_driverid(dev
, CRYPTOCAP_F_HARDWARE
);
125 if (sc
->sc_cid
< 0) {
126 device_printf(dev
, "Could not get crypto driver id.\n");
130 lockinit(&sc
->sc_sessions_lock
, "padlock_lock", 0, 0);
131 crypto_register(sc
->sc_cid
, CRYPTO_AES_CBC
, 0, 0);
132 crypto_register(sc
->sc_cid
, CRYPTO_MD5_HMAC
, 0, 0);
133 crypto_register(sc
->sc_cid
, CRYPTO_SHA1_HMAC
, 0, 0);
134 crypto_register(sc
->sc_cid
, CRYPTO_RIPEMD160_HMAC
, 0, 0);
135 crypto_register(sc
->sc_cid
, CRYPTO_SHA2_256_HMAC
, 0, 0);
136 crypto_register(sc
->sc_cid
, CRYPTO_SHA2_384_HMAC
, 0, 0);
137 crypto_register(sc
->sc_cid
, CRYPTO_SHA2_512_HMAC
, 0, 0);
142 padlock_detach(device_t dev
)
144 struct padlock_softc
*sc
= device_get_softc(dev
);
145 struct padlock_session
*ses
;
147 lockmgr(&sc
->sc_sessions_lock
, LK_SHARED
);
148 TAILQ_FOREACH(ses
, &sc
->sc_sessions
, ses_next
) {
150 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
152 "Cannot detach, sessions still active.\n");
156 while ((ses
= TAILQ_FIRST(&sc
->sc_sessions
)) != NULL
) {
157 TAILQ_REMOVE(&sc
->sc_sessions
, ses
, ses_next
);
158 kfree(ses
, M_PADLOCK
);
160 lockuninit(&sc
->sc_sessions_lock
);
161 crypto_unregister_all(sc
->sc_cid
);
166 padlock_newsession(device_t dev
, uint32_t *sidp
, struct cryptoini
*cri
)
168 struct padlock_softc
*sc
= device_get_softc(dev
);
169 struct padlock_session
*ses
= NULL
;
170 struct cryptoini
*encini
, *macini
;
173 if (sidp
== NULL
|| cri
== NULL
)
176 encini
= macini
= NULL
;
177 for (; cri
!= NULL
; cri
= cri
->cri_next
) {
178 switch (cri
->cri_alg
) {
179 case CRYPTO_NULL_HMAC
:
180 case CRYPTO_MD5_HMAC
:
181 case CRYPTO_SHA1_HMAC
:
182 case CRYPTO_RIPEMD160_HMAC
:
183 case CRYPTO_SHA2_256_HMAC
:
184 case CRYPTO_SHA2_384_HMAC
:
185 case CRYPTO_SHA2_512_HMAC
:
201 * We only support HMAC algorithms to be able to work with
202 * ipsec(4), so if we are asked only for authentication without
203 * encryption, don't pretend we can accellerate it.
209 * Let's look for a free session structure.
211 lockmgr(&sc
->sc_sessions_lock
, LK_SHARED
);
213 * Free sessions goes first, so if first session is used, we need to
216 ses
= TAILQ_FIRST(&sc
->sc_sessions
);
217 if (ses
== NULL
|| ses
->ses_used
) {
218 ses
= kmalloc(sizeof(*ses
), M_PADLOCK
, M_NOWAIT
| M_ZERO
);
220 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
223 ses
->ses_id
= sc
->sc_sid
++;
225 TAILQ_REMOVE(&sc
->sc_sessions
, ses
, ses_next
);
228 TAILQ_INSERT_TAIL(&sc
->sc_sessions
, ses
, ses_next
);
229 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
231 error
= padlock_cipher_setup(ses
, encini
);
233 padlock_freesession_one(sc
, ses
, 0);
237 if (macini
!= NULL
) {
238 error
= padlock_hash_setup(ses
, macini
);
240 padlock_freesession_one(sc
, ses
, 0);
250 padlock_freesession_one(struct padlock_softc
*sc
, struct padlock_session
*ses
,
253 uint32_t sid
= ses
->ses_id
;
256 lockmgr(&sc
->sc_sessions_lock
, LK_SHARED
);
257 TAILQ_REMOVE(&sc
->sc_sessions
, ses
, ses_next
);
258 padlock_hash_free(ses
);
259 bzero(ses
, sizeof(*ses
));
262 TAILQ_INSERT_HEAD(&sc
->sc_sessions
, ses
, ses_next
);
264 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
268 padlock_freesession(device_t dev
, uint64_t tid
)
270 struct padlock_softc
*sc
= device_get_softc(dev
);
271 struct padlock_session
*ses
;
272 uint32_t sid
= ((uint32_t)tid
) & 0xffffffff;
274 lockmgr(&sc
->sc_sessions_lock
, LK_SHARED
);
275 TAILQ_FOREACH_REVERSE(ses
, &sc
->sc_sessions
, padlock_sessions_head
,
277 if (ses
->ses_id
== sid
)
281 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
284 padlock_freesession_one(sc
, ses
, 1);
285 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
290 padlock_process(device_t dev
, struct cryptop
*crp
, int hint __unused
)
292 struct padlock_softc
*sc
= device_get_softc(dev
);
293 struct padlock_session
*ses
= NULL
;
294 struct cryptodesc
*crd
, *enccrd
, *maccrd
;
297 enccrd
= maccrd
= NULL
;
303 if (crp
->crp_callback
== NULL
|| crp
->crp_desc
== NULL
) {
308 for (crd
= crp
->crp_desc
; crd
!= NULL
; crd
= crd
->crd_next
) {
309 switch (crd
->crd_alg
) {
310 case CRYPTO_NULL_HMAC
:
311 case CRYPTO_MD5_HMAC
:
312 case CRYPTO_SHA1_HMAC
:
313 case CRYPTO_RIPEMD160_HMAC
:
314 case CRYPTO_SHA2_256_HMAC
:
315 case CRYPTO_SHA2_384_HMAC
:
316 case CRYPTO_SHA2_512_HMAC
:
317 if (maccrd
!= NULL
) {
324 if (enccrd
!= NULL
) {
334 if (enccrd
== NULL
|| (enccrd
->crd_len
% AES_BLOCK_LEN
) != 0) {
339 lockmgr(&sc
->sc_sessions_lock
, LK_SHARED
);
340 TAILQ_FOREACH_REVERSE(ses
, &sc
->sc_sessions
, padlock_sessions_head
,
342 if (ses
->ses_id
== (crp
->crp_sid
& 0xffffffff))
345 lockmgr(&sc
->sc_sessions_lock
, LK_RELEASE
);
351 /* Perform data authentication if requested before encryption. */
352 if (maccrd
!= NULL
&& maccrd
->crd_next
== enccrd
) {
353 error
= padlock_hash_process(ses
, maccrd
, crp
);
358 error
= padlock_cipher_process(ses
, enccrd
, crp
);
362 /* Perform data authentication if requested after encryption. */
363 if (maccrd
!= NULL
&& enccrd
->crd_next
== maccrd
) {
364 error
= padlock_hash_process(ses
, maccrd
, crp
);
372 * This code is not necessary, because contexts will be freed on next
373 * padlock_setup_mackey() call or at padlock_freesession() call.
375 if (ses
!= NULL
&& maccrd
!= NULL
&&
376 (maccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) != 0) {
377 padlock_free_ctx(ses
->ses_axf
, ses
->ses_ictx
);
378 padlock_free_ctx(ses
->ses_axf
, ses
->ses_octx
);
381 crp
->crp_etype
= error
;
386 static device_method_t padlock_methods
[] = {
387 DEVMETHOD(device_identify
, padlock_identify
),
388 DEVMETHOD(device_probe
, padlock_probe
),
389 DEVMETHOD(device_attach
, padlock_attach
),
390 DEVMETHOD(device_detach
, padlock_detach
),
392 DEVMETHOD(cryptodev_newsession
, padlock_newsession
),
393 DEVMETHOD(cryptodev_freesession
,padlock_freesession
),
394 DEVMETHOD(cryptodev_process
, padlock_process
),
399 static driver_t padlock_driver
= {
402 sizeof(struct padlock_softc
),
404 static devclass_t padlock_devclass
;
406 /* XXX where to attach */
407 DRIVER_MODULE(padlock
, nexus
, padlock_driver
, padlock_devclass
, 0, 0);
408 MODULE_VERSION(padlock
, 1);
409 MODULE_DEPEND(padlock
, crypto
, 1, 1, 1);