2 * Copyright (c) 2003-2009 RMI Corporation
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.
13 * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
41 #include <sys/module.h>
44 #include <sys/mutex.h>
45 #include <sys/sysctl.h>
47 #include <sys/random.h>
51 #include <opencrypto/cryptodev.h>
53 #include "cryptodev_if.h"
58 #include <mips/rmi/dev/sec/rmilib.h>
60 /* #define RMI_SEC_DEBUG */
62 void xlr_sec_print_data(struct cryptop *crp);
64 static int xlr_sec_newsession(device_t dev, uint32_t * sidp, struct cryptoini *cri);
65 static int xlr_sec_freesession(device_t dev, uint64_t tid);
66 static int xlr_sec_process(device_t dev, struct cryptop *crp, int hint);
68 static int xlr_sec_probe(device_t);
69 static int xlr_sec_attach(device_t);
70 static int xlr_sec_detach(device_t);
73 static device_method_t xlr_sec_methods[] = {
74 /* device interface */
75 DEVMETHOD(device_probe, xlr_sec_probe),
76 DEVMETHOD(device_attach, xlr_sec_attach),
77 DEVMETHOD(device_detach, xlr_sec_detach),
80 DEVMETHOD(bus_print_child, bus_generic_print_child),
81 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
83 /* crypto device methods */
84 DEVMETHOD(cryptodev_newsession, xlr_sec_newsession),
85 DEVMETHOD(cryptodev_freesession,xlr_sec_freesession),
86 DEVMETHOD(cryptodev_process, xlr_sec_process),
91 static driver_t xlr_sec_driver = {
94 sizeof(struct xlr_sec_softc)
96 static devclass_t xlr_sec_devclass;
98 DRIVER_MODULE(rmisec, iodi, xlr_sec_driver, xlr_sec_devclass, 0, 0);
99 MODULE_DEPEND(rmisec, crypto, 1, 1, 1);
102 xlr_sec_probe(device_t dev)
105 device_set_desc(dev, "XLR Security Accelerator");
106 return (BUS_PROBE_DEFAULT);
110 * Attach an interface that successfully probed.
113 xlr_sec_attach(device_t dev)
115 struct xlr_sec_softc *sc = device_get_softc(dev);
118 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "rmi crypto driver",
120 sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
121 if (sc->sc_cid < 0) {
122 printf("xlr_sec - error : could not get the driver id\n");
125 if (crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0) != 0)
126 printf("register failed for CRYPTO_DES_CBC\n");
128 if (crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0) != 0)
129 printf("register failed for CRYPTO_3DES_CBC\n");
131 if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0) != 0)
132 printf("register failed for CRYPTO_AES_CBC\n");
134 if (crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0) != 0)
135 printf("register failed for CRYPTO_ARC4\n");
137 if (crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0) != 0)
138 printf("register failed for CRYPTO_MD5\n");
140 if (crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0) != 0)
141 printf("register failed for CRYPTO_SHA1\n");
143 if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0) != 0)
144 printf("register failed for CRYPTO_MD5_HMAC\n");
146 if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0) != 0)
147 printf("register failed for CRYPTO_SHA1_HMAC\n");
150 device_printf(dev, "Initialization complete!\n");
159 * Detach an interface that successfully probed.
162 xlr_sec_detach(device_t dev)
165 struct xlr_sec_softc *sc = device_get_softc(dev);
166 struct xlr_sec_session *ses = NULL;
169 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
170 ses = &sc->sc_sessions[sesn];
171 desc = (symkey_desc_pt) ses->desc_ptr;
172 free(desc->user.kern_src, M_DEVBUF);
173 free(desc->user.kern_dest, M_DEVBUF);
174 free(desc->next_src_buf, M_DEVBUF);
175 free(desc->next_dest_buf, M_DEVBUF);
176 free(ses->desc_ptr, M_DEVBUF);
183 * Allocate a new 'session' and return an encoded session id. 'sidp'
184 * contains our registration id, and should contain an encoded session
185 * id on successful allocation.
188 xlr_sec_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
191 struct xlr_sec_softc *sc = device_get_softc(dev);
192 int mac = 0, cry = 0, sesn;
193 struct xlr_sec_session *ses = NULL;
195 if (sidp == NULL || cri == NULL || sc == NULL)
198 if (sc->sc_sessions == NULL) {
199 ses = sc->sc_sessions = (struct xlr_sec_session *)malloc(
200 sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
204 sc->sc_nsessions = 1;
206 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
207 if (!sc->sc_sessions[sesn].hs_used) {
208 ses = &sc->sc_sessions[sesn];
214 sesn = sc->sc_nsessions;
215 ses = (struct xlr_sec_session *)malloc((sesn + 1) *
216 sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
219 bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
220 bzero(sc->sc_sessions, sesn * sizeof(*ses));
221 free(sc->sc_sessions, M_DEVBUF);
222 sc->sc_sessions = ses;
223 ses = &sc->sc_sessions[sesn];
227 bzero(ses, sizeof(*ses));
228 ses->sessionid = sesn;
229 ses->desc_ptr = xlr_sec_allocate_desc(ses);
230 if (ses->desc_ptr == NULL)
234 for (c = cri; c != NULL; c = c->cri_next) {
235 switch (c->cri_alg) {
238 case CRYPTO_MD5_HMAC:
239 case CRYPTO_SHA1_HMAC:
243 ses->hs_mlen = c->cri_mlen;
244 if (ses->hs_mlen == 0) {
245 switch (c->cri_alg) {
247 case CRYPTO_MD5_HMAC:
251 case CRYPTO_SHA1_HMAC:
258 case CRYPTO_3DES_CBC:
260 /* XXX this may read fewer, does it matter? */
262 * read_random(ses->hs_iv, c->cri_alg ==
263 * CRYPTO_AES_CBC ? XLR_SEC_AES_IV_LENGTH :
264 * XLR_SEC_IV_LENGTH);
276 if (mac == 0 && cry == 0)
279 *sidp = XLR_SEC_SID(device_get_unit(sc->sc_dev), sesn);
284 * Deallocate a session.
285 * XXX this routine should run a zero'd mac/encrypt key into context ram.
286 * XXX to blow away any keys already stored there.
289 xlr_sec_freesession(device_t dev, u_int64_t tid)
291 struct xlr_sec_softc *sc = device_get_softc(dev);
293 u_int32_t sid = CRYPTO_SESID2LID(tid);
298 session = XLR_SEC_SESSION(sid);
299 if (session >= sc->sc_nsessions)
302 sc->sc_sessions[session].hs_used = 0;
309 xlr_sec_print_data(struct cryptop *crp)
312 struct cryptodesc *crp_desc;
314 printf("session id = 0x%llx, crp_ilen = %d, crp_olen=%d \n",
315 crp->crp_sid, crp->crp_ilen, crp->crp_olen);
317 printf("crp_flags = 0x%x\n", crp->crp_flags);
320 printf("crp buf:\n");
321 for (i = 0; i < crp->crp_ilen; i++) {
322 printf("%c ", crp->crp_buf[i]);
328 printf("****************** desc ****************\n");
329 crp_desc = crp->crp_desc;
330 printf("crd_skip=%d, crd_len=%d, crd_flags=0x%x, crd_alg=%d\n",
331 crp_desc->crd_skip, crp_desc->crd_len, crp_desc->crd_flags, crp_desc->crd_alg);
333 key_len = crp_desc->crd_klen / 8;
334 printf("key(%d) :\n", key_len);
335 for (i = 0; i < key_len; i++)
336 printf("%d", crp_desc->crd_key[i]);
340 for (i = 0; i < EALG_MAX_BLOCK_LEN; i++)
341 printf("%d", crp_desc->crd_iv[i]);
344 printf("crd_next=%p\n", crp_desc->crd_next);
351 xlr_sec_process(device_t dev, struct cryptop *crp, int hint)
353 struct xlr_sec_softc *sc = device_get_softc(dev);
354 struct xlr_sec_command *cmd = NULL;
356 struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
357 struct xlr_sec_session *ses;
359 if (crp == NULL || crp->crp_callback == NULL) {
362 session = XLR_SEC_SESSION(crp->crp_sid);
363 if (sc == NULL || session >= sc->sc_nsessions) {
367 ses = &sc->sc_sessions[session];
374 crd1 = crp->crp_desc;
379 crd2 = crd1->crd_next;
382 if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
383 crd1->crd_alg == CRYPTO_SHA1_HMAC ||
384 crd1->crd_alg == CRYPTO_SHA1 ||
385 crd1->crd_alg == CRYPTO_MD5) {
388 } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
389 crd1->crd_alg == CRYPTO_3DES_CBC ||
390 crd1->crd_alg == CRYPTO_AES_CBC ||
391 crd1->crd_alg == CRYPTO_ARC4) {
399 if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
400 crd1->crd_alg == CRYPTO_SHA1_HMAC ||
401 crd1->crd_alg == CRYPTO_MD5 ||
402 crd1->crd_alg == CRYPTO_SHA1) &&
403 (crd2->crd_alg == CRYPTO_DES_CBC ||
404 crd2->crd_alg == CRYPTO_3DES_CBC ||
405 crd2->crd_alg == CRYPTO_AES_CBC ||
406 crd2->crd_alg == CRYPTO_ARC4)) {
409 } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
410 crd1->crd_alg == CRYPTO_ARC4 ||
411 crd1->crd_alg == CRYPTO_3DES_CBC ||
412 crd1->crd_alg == CRYPTO_AES_CBC) &&
413 (crd2->crd_alg == CRYPTO_MD5_HMAC ||
414 crd2->crd_alg == CRYPTO_SHA1_HMAC ||
415 crd2->crd_alg == CRYPTO_MD5 ||
416 crd2->crd_alg == CRYPTO_SHA1) &&
417 (crd1->crd_flags & CRD_F_ENCRYPT)) {
426 bzero(&cmd->op, sizeof(xlr_sec_io_t));
428 cmd->op.source_buf = (uint64_t) (unsigned long)crp->crp_buf;
429 cmd->op.source_buf_size = crp->crp_ilen;
430 if (crp->crp_flags & CRYPTO_F_REL) {
431 cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
432 cmd->op.dest_buf_size = crp->crp_ilen;
434 cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
435 cmd->op.dest_buf_size = crp->crp_ilen;
437 cmd->op.num_packets = 1;
438 cmd->op.num_fragments = 1;
440 if (cmd->op.source_buf_size > SEC_MAX_FRAG_LEN) {
441 ses->multi_frag_flag = 1;
443 ses->multi_frag_flag = 0;
447 cmd->maccrd = maccrd;
448 cmd->op.cipher_op = XLR_SEC_CIPHER_MODE_PASS;
449 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_NONE;
450 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_NONE;
451 cmd->op.cipher_init = 0;
452 cmd->op.cipher_offset = 0;
454 switch (maccrd->crd_alg) {
456 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_MD5;
457 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_NEWKEY;
458 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
459 cmd->op.digest_offset = 0;
461 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
462 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
463 cmd->op.cksum_offset = 0;
465 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
466 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
467 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
468 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
469 cmd->op.pkt_iv = XLR_SEC_PKT_IV_OLD;
470 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
473 printf("currently not handled\n");
477 cmd->enccrd = enccrd;
480 xlr_sec_print_data(crp);
483 if (enccrd->crd_flags & CRD_F_ENCRYPT) {
484 cmd->op.cipher_op = XLR_SEC_CIPHER_OP_ENCRYPT;
486 cmd->op.cipher_op = XLR_SEC_CIPHER_OP_DECRYPT;
488 switch (enccrd->crd_alg) {
490 case CRYPTO_3DES_CBC:
491 if (enccrd->crd_alg == CRYPTO_DES_CBC) {
492 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_DES;
493 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_DES_KEY_LENGTH);
495 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_3DES;
496 //if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
498 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
499 XLR_SEC_3DES_KEY_LENGTH);
503 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
504 cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
505 cmd->op.cipher_offset = XLR_SEC_DES_IV_LENGTH;
507 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
508 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
509 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
510 cmd->op.digest_offset = 0;
512 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
513 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
514 cmd->op.cksum_offset = 0;
516 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
517 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
518 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
519 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
520 cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
521 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
523 //if ((!(enccrd->crd_flags & CRD_F_IV_PRESENT)) &&
524 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
525 memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
526 XLR_SEC_DES_IV_LENGTH);
531 if (enccrd->crd_alg == CRYPTO_AES_CBC) {
532 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_AES128;
533 //if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
535 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
536 XLR_SEC_AES128_KEY_LENGTH);
539 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
540 cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
541 cmd->op.cipher_offset = XLR_SEC_AES_BLOCK_SIZE;
543 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
544 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
545 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
546 cmd->op.digest_offset = 0;
548 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
549 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
550 cmd->op.cksum_offset = 0;
552 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
553 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
554 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
555 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
556 cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
557 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
559 //if (!(enccrd->crd_flags & CRD_F_IV_PRESENT)) {
560 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
561 memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
562 XLR_SEC_AES_BLOCK_SIZE);
569 cmd->session_num = session;
570 xlr_sec_setup(ses, cmd, (symkey_desc_pt) ses->desc_ptr);
577 crp->crp_etype = err;