2 * Octeon Crypto for OCF
4 * Written by David McCullough <david_mccullough@mcafee.com>
5 * Copyright (C) 2009-2010 David McCullough
9 * The free distribution and use of this software in both source and binary
10 * form is allowed (with or without changes) provided that:
12 * 1. distributions of this source code include the above copyright
13 * notice, this list of conditions and the following disclaimer;
15 * 2. distributions in binary form include the above copyright
16 * notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other associated materials;
19 * 3. the copyright holder's name is not used to endorse products
20 * built using this software without specific written permission.
24 * This software is provided 'as is' with no explicit or implied warranties
25 * in respect of its properties, including, but not limited to, correctness
26 * and/or fitness for purpose.
27 * ---------------------------------------------------------------------------
30 #include <linux/version.h>
31 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
32 #include <generated/autoconf.h>
34 #include <linux/autoconf.h>
36 #include <linux/module.h>
37 #include <linux/init.h>
38 #include <linux/list.h>
39 #include <linux/slab.h>
40 #include <linux/sched.h>
41 #include <linux/wait.h>
42 #include <linux/crypto.h>
44 #include <linux/skbuff.h>
45 #include <linux/random.h>
46 #include <linux/scatterlist.h>
48 #include <cryptodev.h>
52 softc_device_decl sc_dev
;
55 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
59 #define MAX_CIPHER_KEYLEN 64
60 char octo_enckey
[MAX_CIPHER_KEYLEN
];
64 #define MAX_HASH_KEYLEN 64
65 char octo_mackey
[MAX_HASH_KEYLEN
];
73 int (*octo_decrypt
)(struct scatterlist
*sg
, int sg_len
,
74 uint8_t *key
, int key_len
, uint8_t * iv
,
75 uint64_t *hminner
, uint64_t *hmouter
);
77 int (*octo_encrypt
)(struct scatterlist
*sg
, int sg_len
,
78 uint8_t *key
, int key_len
, uint8_t * iv
,
79 uint64_t *hminner
, uint64_t *hmouter
);
81 int (*octo_encrypt
)(struct octo_sess
*od
,
82 struct scatterlist
*sg
, int sg_len
,
83 int auth_off
, int auth_len
,
84 int crypt_off
, int crypt_len
,
85 int icv_off
, uint8_t *ivp
);
86 int (*octo_decrypt
)(struct octo_sess
*od
,
87 struct scatterlist
*sg
, int sg_len
,
88 int auth_off
, int auth_len
,
89 int crypt_off
, int crypt_len
,
90 int icv_off
, uint8_t *ivp
);
93 uint64_t octo_hminner
[3];
94 uint64_t octo_hmouter
[3];
98 module_param(octo_id
, int, 0444);
99 MODULE_PARM_DESC(octo_id
, "Read-Only OCF ID for cryptocteon driver");
101 static struct octo_sess
**octo_sessions
= NULL
;
102 static u_int32_t octo_sesnum
= 0;
104 static int octo_process(device_t
, struct cryptop
*, int);
105 static int octo_newsession(device_t
, u_int32_t
*, struct cryptoini
*);
106 static int octo_freesession(device_t
, u_int64_t
);
108 static device_method_t octo_methods
= {
109 /* crypto device methods */
110 DEVMETHOD(cryptodev_newsession
, octo_newsession
),
111 DEVMETHOD(cryptodev_freesession
,octo_freesession
),
112 DEVMETHOD(cryptodev_process
, octo_process
),
115 #define debug octo_debug
117 module_param(octo_debug
, int, 0644);
118 MODULE_PARM_DESC(octo_debug
, "Enable debug");
121 #include "cavium_crypto.c"
125 * Generate a new octo session. We artifically limit it to a single
126 * hash/cipher or hash-cipher combo just to make it easier, most callers
127 * do not expect more than this anyway.
130 octo_newsession(device_t dev
, u_int32_t
*sid
, struct cryptoini
*cri
)
132 struct cryptoini
*c
, *encini
= NULL
, *macini
= NULL
;
133 struct octo_sess
**ocd
;
136 dprintk("%s()\n", __FUNCTION__
);
137 if (sid
== NULL
|| cri
== NULL
) {
138 dprintk("%s,%d - EINVAL\n", __FILE__
, __LINE__
);
143 * To keep it simple, we only handle hash, cipher or hash/cipher in a
144 * session, you cannot currently do multiple ciphers/hashes in one
145 * session even though it would be possibel to code this driver to
148 for (i
= 0, c
= cri
; c
&& i
< 2; i
++) {
149 if (c
->cri_alg
== CRYPTO_MD5_HMAC
||
150 c
->cri_alg
== CRYPTO_SHA1_HMAC
||
151 c
->cri_alg
== CRYPTO_NULL_HMAC
) {
157 if (c
->cri_alg
== CRYPTO_DES_CBC
||
158 c
->cri_alg
== CRYPTO_3DES_CBC
||
159 c
->cri_alg
== CRYPTO_AES_CBC
||
160 c
->cri_alg
== CRYPTO_NULL_CBC
) {
168 if (!macini
&& !encini
) {
169 dprintk("%s,%d - EINVAL bad cipher/hash or combination\n",
174 dprintk("%s,%d - EINVAL cannot handle chained cipher/hash combos\n",
180 * So we have something we can do, lets setup the session
184 for (i
= 1; i
< octo_sesnum
; i
++)
185 if (octo_sessions
[i
] == NULL
)
188 i
= 1; /* NB: to silence compiler warning */
190 if (octo_sessions
== NULL
|| i
== octo_sesnum
) {
191 if (octo_sessions
== NULL
) {
192 i
= 1; /* We leave octo_sessions[0] empty */
193 octo_sesnum
= CRYPTO_SW_SESSIONS
;
197 ocd
= kmalloc(octo_sesnum
* sizeof(struct octo_sess
*), SLAB_ATOMIC
);
199 /* Reset session number */
200 if (octo_sesnum
== CRYPTO_SW_SESSIONS
)
204 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
207 memset(ocd
, 0, octo_sesnum
* sizeof(struct octo_sess
*));
209 /* Copy existing sessions */
211 memcpy(ocd
, octo_sessions
,
212 (octo_sesnum
/ 2) * sizeof(struct octo_sess
*));
213 kfree(octo_sessions
);
219 ocd
= &octo_sessions
[i
];
223 *ocd
= (struct octo_sess
*) kmalloc(sizeof(struct octo_sess
), SLAB_ATOMIC
);
225 octo_freesession(NULL
, i
);
226 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
229 memset(*ocd
, 0, sizeof(struct octo_sess
));
231 if (encini
&& encini
->cri_key
) {
232 (*ocd
)->octo_encklen
= (encini
->cri_klen
+ 7) / 8;
233 memcpy((*ocd
)->octo_enckey
, encini
->cri_key
, (*ocd
)->octo_encklen
);
236 if (macini
&& macini
->cri_key
) {
237 (*ocd
)->octo_macklen
= (macini
->cri_klen
+ 7) / 8;
238 memcpy((*ocd
)->octo_mackey
, macini
->cri_key
, (*ocd
)->octo_macklen
);
241 (*ocd
)->octo_mlen
= 0;
242 if (encini
&& encini
->cri_mlen
)
243 (*ocd
)->octo_mlen
= encini
->cri_mlen
;
244 else if (macini
&& macini
->cri_mlen
)
245 (*ocd
)->octo_mlen
= macini
->cri_mlen
;
247 (*ocd
)->octo_mlen
= 12;
250 * point c at the enc if it exists, otherwise the mac
252 c
= encini
? encini
: macini
;
254 switch (c
->cri_alg
) {
256 case CRYPTO_3DES_CBC
:
257 (*ocd
)->octo_ivsize
= 8;
258 switch (macini
? macini
->cri_alg
: -1) {
259 case CRYPTO_MD5_HMAC
:
260 (*ocd
)->octo_encrypt
= octo_des_cbc_md5_encrypt
;
261 (*ocd
)->octo_decrypt
= octo_des_cbc_md5_decrypt
;
262 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
263 (*ocd
)->octo_hmouter
);
265 case CRYPTO_SHA1_HMAC
:
266 (*ocd
)->octo_encrypt
= octo_des_cbc_sha1_encrypt
;
267 (*ocd
)->octo_decrypt
= octo_des_cbc_sha1_encrypt
;
268 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
269 (*ocd
)->octo_hmouter
);
272 (*ocd
)->octo_encrypt
= octo_des_cbc_encrypt
;
273 (*ocd
)->octo_decrypt
= octo_des_cbc_decrypt
;
276 octo_freesession(NULL
, i
);
277 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
282 (*ocd
)->octo_ivsize
= 16;
283 switch (macini
? macini
->cri_alg
: -1) {
284 case CRYPTO_MD5_HMAC
:
285 (*ocd
)->octo_encrypt
= octo_aes_cbc_md5_encrypt
;
286 (*ocd
)->octo_decrypt
= octo_aes_cbc_md5_decrypt
;
287 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
288 (*ocd
)->octo_hmouter
);
290 case CRYPTO_SHA1_HMAC
:
291 (*ocd
)->octo_encrypt
= octo_aes_cbc_sha1_encrypt
;
292 (*ocd
)->octo_decrypt
= octo_aes_cbc_sha1_decrypt
;
293 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
294 (*ocd
)->octo_hmouter
);
297 (*ocd
)->octo_encrypt
= octo_aes_cbc_encrypt
;
298 (*ocd
)->octo_decrypt
= octo_aes_cbc_decrypt
;
301 octo_freesession(NULL
, i
);
302 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
306 case CRYPTO_MD5_HMAC
:
307 (*ocd
)->octo_encrypt
= octo_null_md5_encrypt
;
308 (*ocd
)->octo_decrypt
= octo_null_md5_encrypt
;
309 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
310 (*ocd
)->octo_hmouter
);
312 case CRYPTO_SHA1_HMAC
:
313 (*ocd
)->octo_encrypt
= octo_null_sha1_encrypt
;
314 (*ocd
)->octo_decrypt
= octo_null_sha1_encrypt
;
315 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
316 (*ocd
)->octo_hmouter
);
319 octo_freesession(NULL
, i
);
320 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
324 (*ocd
)->octo_encalg
= encini
? encini
->cri_alg
: -1;
325 (*ocd
)->octo_macalg
= macini
? macini
->cri_alg
: -1;
334 octo_freesession(device_t dev
, u_int64_t tid
)
336 u_int32_t sid
= CRYPTO_SESID2LID(tid
);
338 dprintk("%s()\n", __FUNCTION__
);
339 if (sid
> octo_sesnum
|| octo_sessions
== NULL
||
340 octo_sessions
[sid
] == NULL
) {
341 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
345 /* Silently accept and return */
349 if (octo_sessions
[sid
])
350 kfree(octo_sessions
[sid
]);
351 octo_sessions
[sid
] = NULL
;
359 octo_process(device_t dev
, struct cryptop
*crp
, int hint
)
361 struct cryptodesc
*crd
;
362 struct octo_sess
*od
;
364 #define SCATTERLIST_MAX 16
365 struct scatterlist sg
[SCATTERLIST_MAX
];
367 struct sk_buff
*skb
= NULL
;
368 struct uio
*uiop
= NULL
;
369 struct cryptodesc
*enccrd
= NULL
, *maccrd
= NULL
;
370 unsigned char *ivp
= NULL
;
371 unsigned char iv_data
[HASH_MAX_LEN
];
372 int auth_off
= 0, auth_len
= 0, crypt_off
= 0, crypt_len
= 0, icv_off
= 0;
374 dprintk("%s()\n", __FUNCTION__
);
377 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
383 if (crp
->crp_desc
== NULL
|| crp
->crp_buf
== NULL
) {
384 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
385 crp
->crp_etype
= EINVAL
;
389 lid
= crp
->crp_sid
& 0xffffffff;
390 if (lid
>= octo_sesnum
|| lid
== 0 || octo_sessions
== NULL
||
391 octo_sessions
[lid
] == NULL
) {
392 crp
->crp_etype
= ENOENT
;
393 dprintk("%s,%d: ENOENT\n", __FILE__
, __LINE__
);
396 od
= octo_sessions
[lid
];
399 * do some error checking outside of the loop for SKB and IOV processing
400 * this leaves us with valid skb or uiop pointers for later
402 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
403 skb
= (struct sk_buff
*) crp
->crp_buf
;
404 if (skb_shinfo(skb
)->nr_frags
>= SCATTERLIST_MAX
) {
405 printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__
, __LINE__
,
406 skb_shinfo(skb
)->nr_frags
);
409 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
410 uiop
= (struct uio
*) crp
->crp_buf
;
411 if (uiop
->uio_iovcnt
> SCATTERLIST_MAX
) {
412 printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__
, __LINE__
,
418 /* point our enccrd and maccrd appropriately */
420 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
421 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
424 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
425 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
429 crp
->crp_etype
= EINVAL
;
430 dprintk("%s,%d: ENOENT - descriptors do not match session\n",
436 if (enccrd
->crd_flags
& CRD_F_IV_EXPLICIT
) {
437 ivp
= enccrd
->crd_iv
;
440 crypto_copydata(crp
->crp_flags
, crp
->crp_buf
,
441 enccrd
->crd_inject
, od
->octo_ivsize
, (caddr_t
) ivp
);
445 auth_off
= maccrd
->crd_skip
;
446 auth_len
= maccrd
->crd_len
;
447 icv_off
= maccrd
->crd_inject
;
450 crypt_off
= enccrd
->crd_skip
;
451 crypt_len
= enccrd
->crd_len
;
452 } else { /* if (maccrd) */
453 auth_off
= maccrd
->crd_skip
;
454 auth_len
= maccrd
->crd_len
;
455 icv_off
= maccrd
->crd_inject
;
460 * setup the SG list to cover the buffer
462 memset(sg
, 0, sizeof(sg
));
463 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
469 len
= skb_headlen(skb
);
470 sg_set_page(&sg
[sg_num
], virt_to_page(skb
->data
), len
,
471 offset_in_page(skb
->data
));
475 for (i
= 0; i
< skb_shinfo(skb
)->nr_frags
&& sg_num
< SCATTERLIST_MAX
;
477 len
= skb_shinfo(skb
)->frags
[i
].size
;
478 sg_set_page(&sg
[sg_num
], skb_shinfo(skb
)->frags
[i
].page
,
479 len
, skb_shinfo(skb
)->frags
[i
].page_offset
);
483 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
487 for (sg_num
= 0; sg_len
< crp
->crp_ilen
&&
488 sg_num
< uiop
->uio_iovcnt
&&
489 sg_num
< SCATTERLIST_MAX
; sg_num
++) {
490 len
= uiop
->uio_iov
[sg_num
].iov_len
;
491 sg_set_page(&sg
[sg_num
],
492 virt_to_page(uiop
->uio_iov
[sg_num
].iov_base
), len
,
493 offset_in_page(uiop
->uio_iov
[sg_num
].iov_base
));
497 sg_len
= crp
->crp_ilen
;
498 sg_set_page(&sg
[0], virt_to_page(crp
->crp_buf
), sg_len
,
499 offset_in_page(crp
->crp_buf
));
505 * setup a new explicit key
508 if (enccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
509 od
->octo_encklen
= (enccrd
->crd_klen
+ 7) / 8;
510 memcpy(od
->octo_enckey
, enccrd
->crd_key
, od
->octo_encklen
);
514 if (maccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
515 od
->octo_macklen
= (maccrd
->crd_klen
+ 7) / 8;
516 memcpy(od
->octo_mackey
, maccrd
->crd_key
, od
->octo_macklen
);
517 od
->octo_mackey_set
= 0;
519 if (!od
->octo_mackey_set
) {
520 octo_calc_hash(maccrd
->crd_alg
== CRYPTO_MD5_HMAC
? 0 : 1,
521 maccrd
->crd_key
, od
->octo_hminner
, od
->octo_hmouter
);
522 od
->octo_mackey_set
= 1;
527 if (!enccrd
|| (enccrd
->crd_flags
& CRD_F_ENCRYPT
))
528 (*od
->octo_encrypt
)(od
, sg
, sg_len
,
529 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
531 (*od
->octo_decrypt
)(od
, sg
, sg_len
,
532 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
540 cryptocteon_init(void)
542 dprintk("%s(%p)\n", __FUNCTION__
, cryptocteon_init
);
544 softc_device_init(&octo_softc
, "cryptocteon", 0, octo_methods
);
546 octo_id
= crypto_get_driverid(softc_get_device(&octo_softc
),
547 CRYPTOCAP_F_HARDWARE
| CRYPTOCAP_F_SYNC
);
549 printk("Cryptocteon device cannot initialize!");
553 crypto_register(octo_id
, CRYPTO_MD5_HMAC
, 0,0);
554 crypto_register(octo_id
, CRYPTO_SHA1_HMAC
, 0,0);
555 //crypto_register(octo_id, CRYPTO_MD5, 0,0);
556 //crypto_register(octo_id, CRYPTO_SHA1, 0,0);
557 crypto_register(octo_id
, CRYPTO_DES_CBC
, 0,0);
558 crypto_register(octo_id
, CRYPTO_3DES_CBC
, 0,0);
559 crypto_register(octo_id
, CRYPTO_AES_CBC
, 0,0);
565 cryptocteon_exit(void)
567 dprintk("%s()\n", __FUNCTION__
);
568 crypto_unregister_all(octo_id
);
572 module_init(cryptocteon_init
);
573 module_exit(cryptocteon_exit
);
575 MODULE_LICENSE("BSD");
576 MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
577 MODULE_DESCRIPTION("Cryptocteon (OCF module for Cavium OCTEON crypto)");