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),
79 /* crypto device methods */
80 DEVMETHOD(cryptodev_newsession, xlr_sec_newsession),
81 DEVMETHOD(cryptodev_freesession,xlr_sec_freesession),
82 DEVMETHOD(cryptodev_process, xlr_sec_process),
87 static driver_t xlr_sec_driver = {
90 sizeof(struct xlr_sec_softc)
92 static devclass_t xlr_sec_devclass;
94 DRIVER_MODULE(rmisec, iodi, xlr_sec_driver, xlr_sec_devclass, 0, 0);
95 MODULE_DEPEND(rmisec, crypto, 1, 1, 1);
98 xlr_sec_probe(device_t dev)
101 device_set_desc(dev, "XLR Security Accelerator");
102 return (BUS_PROBE_DEFAULT);
106 * Attach an interface that successfully probed.
109 xlr_sec_attach(device_t dev)
111 struct xlr_sec_softc *sc = device_get_softc(dev);
114 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "rmi crypto driver",
116 sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
117 if (sc->sc_cid < 0) {
118 printf("xlr_sec - error : could not get the driver id\n");
121 if (crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0) != 0)
122 printf("register failed for CRYPTO_DES_CBC\n");
124 if (crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0) != 0)
125 printf("register failed for CRYPTO_3DES_CBC\n");
127 if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0) != 0)
128 printf("register failed for CRYPTO_AES_CBC\n");
130 if (crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0) != 0)
131 printf("register failed for CRYPTO_ARC4\n");
133 if (crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0) != 0)
134 printf("register failed for CRYPTO_MD5\n");
136 if (crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0) != 0)
137 printf("register failed for CRYPTO_SHA1\n");
139 if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0) != 0)
140 printf("register failed for CRYPTO_MD5_HMAC\n");
142 if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0) != 0)
143 printf("register failed for CRYPTO_SHA1_HMAC\n");
146 device_printf(dev, "Initialization complete!\n");
155 * Detach an interface that successfully probed.
158 xlr_sec_detach(device_t dev)
161 struct xlr_sec_softc *sc = device_get_softc(dev);
162 struct xlr_sec_session *ses = NULL;
165 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
166 ses = &sc->sc_sessions[sesn];
167 desc = (symkey_desc_pt) ses->desc_ptr;
168 free(desc->user.kern_src, M_DEVBUF);
169 free(desc->user.kern_dest, M_DEVBUF);
170 free(desc->next_src_buf, M_DEVBUF);
171 free(desc->next_dest_buf, M_DEVBUF);
172 free(ses->desc_ptr, M_DEVBUF);
179 * Allocate a new 'session' and return an encoded session id. 'sidp'
180 * contains our registration id, and should contain an encoded session
181 * id on successful allocation.
184 xlr_sec_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
187 struct xlr_sec_softc *sc = device_get_softc(dev);
188 int mac = 0, cry = 0, sesn;
189 struct xlr_sec_session *ses = NULL;
191 if (sidp == NULL || cri == NULL || sc == NULL)
194 if (sc->sc_sessions == NULL) {
195 ses = sc->sc_sessions = (struct xlr_sec_session *)malloc(
196 sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
200 sc->sc_nsessions = 1;
202 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
203 if (!sc->sc_sessions[sesn].hs_used) {
204 ses = &sc->sc_sessions[sesn];
210 sesn = sc->sc_nsessions;
211 ses = (struct xlr_sec_session *)malloc((sesn + 1) *
212 sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
215 bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
216 bzero(sc->sc_sessions, sesn * sizeof(*ses));
217 free(sc->sc_sessions, M_DEVBUF);
218 sc->sc_sessions = ses;
219 ses = &sc->sc_sessions[sesn];
223 bzero(ses, sizeof(*ses));
224 ses->sessionid = sesn;
225 ses->desc_ptr = xlr_sec_allocate_desc(ses);
226 if (ses->desc_ptr == NULL)
230 for (c = cri; c != NULL; c = c->cri_next) {
231 switch (c->cri_alg) {
234 case CRYPTO_MD5_HMAC:
235 case CRYPTO_SHA1_HMAC:
239 ses->hs_mlen = c->cri_mlen;
240 if (ses->hs_mlen == 0) {
241 switch (c->cri_alg) {
243 case CRYPTO_MD5_HMAC:
247 case CRYPTO_SHA1_HMAC:
254 case CRYPTO_3DES_CBC:
256 /* XXX this may read fewer, does it matter? */
258 * read_random(ses->hs_iv, c->cri_alg ==
259 * CRYPTO_AES_CBC ? XLR_SEC_AES_IV_LENGTH :
260 * XLR_SEC_IV_LENGTH);
272 if (mac == 0 && cry == 0)
275 *sidp = XLR_SEC_SID(device_get_unit(sc->sc_dev), sesn);
280 * Deallocate a session.
281 * XXX this routine should run a zero'd mac/encrypt key into context ram.
282 * XXX to blow away any keys already stored there.
285 xlr_sec_freesession(device_t dev, u_int64_t tid)
287 struct xlr_sec_softc *sc = device_get_softc(dev);
289 u_int32_t sid = CRYPTO_SESID2LID(tid);
294 session = XLR_SEC_SESSION(sid);
295 if (session >= sc->sc_nsessions)
298 sc->sc_sessions[session].hs_used = 0;
305 xlr_sec_print_data(struct cryptop *crp)
308 struct cryptodesc *crp_desc;
310 printf("session id = 0x%llx, crp_ilen = %d, crp_olen=%d \n",
311 crp->crp_sid, crp->crp_ilen, crp->crp_olen);
313 printf("crp_flags = 0x%x\n", crp->crp_flags);
316 printf("crp buf:\n");
317 for (i = 0; i < crp->crp_ilen; i++) {
318 printf("%c ", crp->crp_buf[i]);
324 printf("****************** desc ****************\n");
325 crp_desc = crp->crp_desc;
326 printf("crd_skip=%d, crd_len=%d, crd_flags=0x%x, crd_alg=%d\n",
327 crp_desc->crd_skip, crp_desc->crd_len, crp_desc->crd_flags, crp_desc->crd_alg);
329 key_len = crp_desc->crd_klen / 8;
330 printf("key(%d) :\n", key_len);
331 for (i = 0; i < key_len; i++)
332 printf("%d", crp_desc->crd_key[i]);
336 for (i = 0; i < EALG_MAX_BLOCK_LEN; i++)
337 printf("%d", crp_desc->crd_iv[i]);
340 printf("crd_next=%p\n", crp_desc->crd_next);
347 xlr_sec_process(device_t dev, struct cryptop *crp, int hint)
349 struct xlr_sec_softc *sc = device_get_softc(dev);
350 struct xlr_sec_command *cmd = NULL;
352 struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
353 struct xlr_sec_session *ses;
355 if (crp == NULL || crp->crp_callback == NULL) {
358 session = XLR_SEC_SESSION(crp->crp_sid);
359 if (sc == NULL || session >= sc->sc_nsessions) {
363 ses = &sc->sc_sessions[session];
370 crd1 = crp->crp_desc;
375 crd2 = crd1->crd_next;
378 if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
379 crd1->crd_alg == CRYPTO_SHA1_HMAC ||
380 crd1->crd_alg == CRYPTO_SHA1 ||
381 crd1->crd_alg == CRYPTO_MD5) {
384 } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
385 crd1->crd_alg == CRYPTO_3DES_CBC ||
386 crd1->crd_alg == CRYPTO_AES_CBC ||
387 crd1->crd_alg == CRYPTO_ARC4) {
395 if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
396 crd1->crd_alg == CRYPTO_SHA1_HMAC ||
397 crd1->crd_alg == CRYPTO_MD5 ||
398 crd1->crd_alg == CRYPTO_SHA1) &&
399 (crd2->crd_alg == CRYPTO_DES_CBC ||
400 crd2->crd_alg == CRYPTO_3DES_CBC ||
401 crd2->crd_alg == CRYPTO_AES_CBC ||
402 crd2->crd_alg == CRYPTO_ARC4)) {
405 } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
406 crd1->crd_alg == CRYPTO_ARC4 ||
407 crd1->crd_alg == CRYPTO_3DES_CBC ||
408 crd1->crd_alg == CRYPTO_AES_CBC) &&
409 (crd2->crd_alg == CRYPTO_MD5_HMAC ||
410 crd2->crd_alg == CRYPTO_SHA1_HMAC ||
411 crd2->crd_alg == CRYPTO_MD5 ||
412 crd2->crd_alg == CRYPTO_SHA1) &&
413 (crd1->crd_flags & CRD_F_ENCRYPT)) {
422 bzero(&cmd->op, sizeof(xlr_sec_io_t));
424 cmd->op.source_buf = (uint64_t) (unsigned long)crp->crp_buf;
425 cmd->op.source_buf_size = crp->crp_ilen;
426 if (crp->crp_flags & CRYPTO_F_REL) {
427 cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
428 cmd->op.dest_buf_size = crp->crp_ilen;
430 cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
431 cmd->op.dest_buf_size = crp->crp_ilen;
433 cmd->op.num_packets = 1;
434 cmd->op.num_fragments = 1;
436 if (cmd->op.source_buf_size > SEC_MAX_FRAG_LEN) {
437 ses->multi_frag_flag = 1;
439 ses->multi_frag_flag = 0;
443 cmd->maccrd = maccrd;
444 cmd->op.cipher_op = XLR_SEC_CIPHER_MODE_PASS;
445 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_NONE;
446 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_NONE;
447 cmd->op.cipher_init = 0;
448 cmd->op.cipher_offset = 0;
450 switch (maccrd->crd_alg) {
452 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_MD5;
453 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_NEWKEY;
454 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
455 cmd->op.digest_offset = 0;
457 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
458 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
459 cmd->op.cksum_offset = 0;
461 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
462 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
463 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
464 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
465 cmd->op.pkt_iv = XLR_SEC_PKT_IV_OLD;
466 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
469 printf("currently not handled\n");
473 cmd->enccrd = enccrd;
476 xlr_sec_print_data(crp);
479 if (enccrd->crd_flags & CRD_F_ENCRYPT) {
480 cmd->op.cipher_op = XLR_SEC_CIPHER_OP_ENCRYPT;
482 cmd->op.cipher_op = XLR_SEC_CIPHER_OP_DECRYPT;
484 switch (enccrd->crd_alg) {
486 case CRYPTO_3DES_CBC:
487 if (enccrd->crd_alg == CRYPTO_DES_CBC) {
488 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_DES;
489 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_DES_KEY_LENGTH);
491 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_3DES;
492 //if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
494 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
495 XLR_SEC_3DES_KEY_LENGTH);
499 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
500 cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
501 cmd->op.cipher_offset = XLR_SEC_DES_IV_LENGTH;
503 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
504 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
505 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
506 cmd->op.digest_offset = 0;
508 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
509 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
510 cmd->op.cksum_offset = 0;
512 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
513 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
514 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
515 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
516 cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
517 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
519 //if ((!(enccrd->crd_flags & CRD_F_IV_PRESENT)) &&
520 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
521 memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
522 XLR_SEC_DES_IV_LENGTH);
527 if (enccrd->crd_alg == CRYPTO_AES_CBC) {
528 cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_AES128;
529 //if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
531 memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
532 XLR_SEC_AES128_KEY_LENGTH);
535 cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
536 cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
537 cmd->op.cipher_offset = XLR_SEC_AES_BLOCK_SIZE;
539 cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
540 cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
541 cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
542 cmd->op.digest_offset = 0;
544 cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
545 cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
546 cmd->op.cksum_offset = 0;
548 cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
549 cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
550 cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
551 cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
552 cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
553 cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
555 //if (!(enccrd->crd_flags & CRD_F_IV_PRESENT)) {
556 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
557 memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
558 XLR_SEC_AES_BLOCK_SIZE);
565 cmd->session_num = session;
566 xlr_sec_setup(ses, cmd, (symkey_desc_pt) ses->desc_ptr);
573 crp->crp_etype = err;