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,38) && !defined(AUTOCONF_INCLUDED)
32 #include <linux/config.h>
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/list.h>
37 #include <linux/slab.h>
38 #include <linux/sched.h>
39 #include <linux/wait.h>
40 #include <linux/crypto.h>
42 #include <linux/skbuff.h>
43 #include <linux/random.h>
44 #include <linux/scatterlist.h>
46 #include <cryptodev.h>
50 softc_device_decl sc_dev
;
53 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
57 #define MAX_CIPHER_KEYLEN 64
58 char octo_enckey
[MAX_CIPHER_KEYLEN
];
62 #define MAX_HASH_KEYLEN 64
63 char octo_mackey
[MAX_HASH_KEYLEN
];
70 int (*octo_encrypt
)(struct octo_sess
*od
,
71 struct scatterlist
*sg
, int sg_len
,
72 int auth_off
, int auth_len
,
73 int crypt_off
, int crypt_len
,
74 int icv_off
, uint8_t *ivp
);
75 int (*octo_decrypt
)(struct octo_sess
*od
,
76 struct scatterlist
*sg
, int sg_len
,
77 int auth_off
, int auth_len
,
78 int crypt_off
, int crypt_len
,
79 int icv_off
, uint8_t *ivp
);
81 uint64_t octo_hminner
[3];
82 uint64_t octo_hmouter
[3];
86 module_param(octo_id
, int, 0444);
87 MODULE_PARM_DESC(octo_id
, "Read-Only OCF ID for cryptocteon driver");
89 static struct octo_sess
**octo_sessions
= NULL
;
90 static u_int32_t octo_sesnum
= 0;
92 static int octo_process(device_t
, struct cryptop
*, int);
93 static int octo_newsession(device_t
, u_int32_t
*, struct cryptoini
*);
94 static int octo_freesession(device_t
, u_int64_t
);
96 static device_method_t octo_methods
= {
97 /* crypto device methods */
98 DEVMETHOD(cryptodev_newsession
, octo_newsession
),
99 DEVMETHOD(cryptodev_freesession
,octo_freesession
),
100 DEVMETHOD(cryptodev_process
, octo_process
),
103 #define debug octo_debug
105 module_param(octo_debug
, int, 0644);
106 MODULE_PARM_DESC(octo_debug
, "Enable debug");
109 #include "cavium_crypto.c"
113 * Generate a new octo session. We artifically limit it to a single
114 * hash/cipher or hash-cipher combo just to make it easier, most callers
115 * do not expect more than this anyway.
118 octo_newsession(device_t dev
, u_int32_t
*sid
, struct cryptoini
*cri
)
120 struct cryptoini
*c
, *encini
= NULL
, *macini
= NULL
;
121 struct octo_sess
**ocd
;
124 dprintk("%s()\n", __FUNCTION__
);
125 if (sid
== NULL
|| cri
== NULL
) {
126 dprintk("%s,%d - EINVAL\n", __FILE__
, __LINE__
);
131 * To keep it simple, we only handle hash, cipher or hash/cipher in a
132 * session, you cannot currently do multiple ciphers/hashes in one
133 * session even though it would be possibel to code this driver to
136 for (i
= 0, c
= cri
; c
&& i
< 2; i
++) {
137 if (c
->cri_alg
== CRYPTO_MD5_HMAC
||
138 c
->cri_alg
== CRYPTO_SHA1_HMAC
||
139 c
->cri_alg
== CRYPTO_NULL_HMAC
) {
145 if (c
->cri_alg
== CRYPTO_DES_CBC
||
146 c
->cri_alg
== CRYPTO_3DES_CBC
||
147 c
->cri_alg
== CRYPTO_AES_CBC
||
148 c
->cri_alg
== CRYPTO_NULL_CBC
) {
156 if (!macini
&& !encini
) {
157 dprintk("%s,%d - EINVAL bad cipher/hash or combination\n",
162 dprintk("%s,%d - EINVAL cannot handle chained cipher/hash combos\n",
168 * So we have something we can do, lets setup the session
172 for (i
= 1; i
< octo_sesnum
; i
++)
173 if (octo_sessions
[i
] == NULL
)
176 i
= 1; /* NB: to silence compiler warning */
178 if (octo_sessions
== NULL
|| i
== octo_sesnum
) {
179 if (octo_sessions
== NULL
) {
180 i
= 1; /* We leave octo_sessions[0] empty */
181 octo_sesnum
= CRYPTO_SW_SESSIONS
;
185 ocd
= kmalloc(octo_sesnum
* sizeof(struct octo_sess
*), SLAB_ATOMIC
);
187 /* Reset session number */
188 if (octo_sesnum
== CRYPTO_SW_SESSIONS
)
192 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
195 memset(ocd
, 0, octo_sesnum
* sizeof(struct octo_sess
*));
197 /* Copy existing sessions */
199 memcpy(ocd
, octo_sessions
,
200 (octo_sesnum
/ 2) * sizeof(struct octo_sess
*));
201 kfree(octo_sessions
);
207 ocd
= &octo_sessions
[i
];
211 *ocd
= (struct octo_sess
*) kmalloc(sizeof(struct octo_sess
), SLAB_ATOMIC
);
213 octo_freesession(NULL
, i
);
214 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
217 memset(*ocd
, 0, sizeof(struct octo_sess
));
219 if (encini
&& encini
->cri_key
) {
220 (*ocd
)->octo_encklen
= (encini
->cri_klen
+ 7) / 8;
221 memcpy((*ocd
)->octo_enckey
, encini
->cri_key
, (*ocd
)->octo_encklen
);
224 if (macini
&& macini
->cri_key
) {
225 (*ocd
)->octo_macklen
= (macini
->cri_klen
+ 7) / 8;
226 memcpy((*ocd
)->octo_mackey
, macini
->cri_key
, (*ocd
)->octo_macklen
);
229 (*ocd
)->octo_mlen
= 0;
230 if (encini
&& encini
->cri_mlen
)
231 (*ocd
)->octo_mlen
= encini
->cri_mlen
;
232 else if (macini
&& macini
->cri_mlen
)
233 (*ocd
)->octo_mlen
= macini
->cri_mlen
;
235 (*ocd
)->octo_mlen
= 12;
238 * point c at the enc if it exists, otherwise the mac
240 c
= encini
? encini
: macini
;
242 switch (c
->cri_alg
) {
244 case CRYPTO_3DES_CBC
:
245 (*ocd
)->octo_ivsize
= 8;
246 switch (macini
? macini
->cri_alg
: -1) {
247 case CRYPTO_MD5_HMAC
:
248 (*ocd
)->octo_encrypt
= octo_des_cbc_md5_encrypt
;
249 (*ocd
)->octo_decrypt
= octo_des_cbc_md5_decrypt
;
250 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
251 (*ocd
)->octo_hmouter
);
253 case CRYPTO_SHA1_HMAC
:
254 (*ocd
)->octo_encrypt
= octo_des_cbc_sha1_encrypt
;
255 (*ocd
)->octo_decrypt
= octo_des_cbc_sha1_decrypt
;
256 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
257 (*ocd
)->octo_hmouter
);
260 (*ocd
)->octo_encrypt
= octo_des_cbc_encrypt
;
261 (*ocd
)->octo_decrypt
= octo_des_cbc_decrypt
;
264 octo_freesession(NULL
, i
);
265 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
270 (*ocd
)->octo_ivsize
= 16;
271 switch (macini
? macini
->cri_alg
: -1) {
272 case CRYPTO_MD5_HMAC
:
273 (*ocd
)->octo_encrypt
= octo_aes_cbc_md5_encrypt
;
274 (*ocd
)->octo_decrypt
= octo_aes_cbc_md5_decrypt
;
275 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
276 (*ocd
)->octo_hmouter
);
278 case CRYPTO_SHA1_HMAC
:
279 (*ocd
)->octo_encrypt
= octo_aes_cbc_sha1_encrypt
;
280 (*ocd
)->octo_decrypt
= octo_aes_cbc_sha1_decrypt
;
281 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
282 (*ocd
)->octo_hmouter
);
285 (*ocd
)->octo_encrypt
= octo_aes_cbc_encrypt
;
286 (*ocd
)->octo_decrypt
= octo_aes_cbc_decrypt
;
289 octo_freesession(NULL
, i
);
290 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
294 case CRYPTO_MD5_HMAC
:
295 (*ocd
)->octo_encrypt
= octo_null_md5_encrypt
;
296 (*ocd
)->octo_decrypt
= octo_null_md5_encrypt
; /* encrypt == decrypt */
297 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
298 (*ocd
)->octo_hmouter
);
300 case CRYPTO_SHA1_HMAC
:
301 (*ocd
)->octo_encrypt
= octo_null_sha1_encrypt
;
302 (*ocd
)->octo_decrypt
= octo_null_sha1_encrypt
; /* encrypt == decrypt */
303 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
304 (*ocd
)->octo_hmouter
);
307 octo_freesession(NULL
, i
);
308 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
312 (*ocd
)->octo_encalg
= encini
? encini
->cri_alg
: -1;
313 (*ocd
)->octo_macalg
= macini
? macini
->cri_alg
: -1;
322 octo_freesession(device_t dev
, u_int64_t tid
)
324 u_int32_t sid
= CRYPTO_SESID2LID(tid
);
326 dprintk("%s()\n", __FUNCTION__
);
327 if (sid
> octo_sesnum
|| octo_sessions
== NULL
||
328 octo_sessions
[sid
] == NULL
) {
329 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
333 /* Silently accept and return */
337 if (octo_sessions
[sid
])
338 kfree(octo_sessions
[sid
]);
339 octo_sessions
[sid
] = NULL
;
347 octo_process(device_t dev
, struct cryptop
*crp
, int hint
)
349 struct cryptodesc
*crd
;
350 struct octo_sess
*od
;
352 #define SCATTERLIST_MAX 16
353 struct scatterlist sg
[SCATTERLIST_MAX
];
355 struct sk_buff
*skb
= NULL
;
356 struct uio
*uiop
= NULL
;
357 struct cryptodesc
*enccrd
= NULL
, *maccrd
= NULL
;
358 unsigned char *ivp
= NULL
;
359 unsigned char iv_data
[HASH_MAX_LEN
];
360 int auth_off
= 0, auth_len
= 0, crypt_off
= 0, crypt_len
= 0, icv_off
= 0;
362 dprintk("%s()\n", __FUNCTION__
);
365 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
371 if (crp
->crp_desc
== NULL
|| crp
->crp_buf
== NULL
) {
372 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
373 crp
->crp_etype
= EINVAL
;
377 lid
= crp
->crp_sid
& 0xffffffff;
378 if (lid
>= octo_sesnum
|| lid
== 0 || octo_sessions
== NULL
||
379 octo_sessions
[lid
] == NULL
) {
380 crp
->crp_etype
= ENOENT
;
381 dprintk("%s,%d: ENOENT\n", __FILE__
, __LINE__
);
384 od
= octo_sessions
[lid
];
387 * do some error checking outside of the loop for SKB and IOV processing
388 * this leaves us with valid skb or uiop pointers for later
390 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
391 skb
= (struct sk_buff
*) crp
->crp_buf
;
392 if (skb_shinfo(skb
)->nr_frags
>= SCATTERLIST_MAX
) {
393 printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__
, __LINE__
,
394 skb_shinfo(skb
)->nr_frags
);
397 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
398 uiop
= (struct uio
*) crp
->crp_buf
;
399 if (uiop
->uio_iovcnt
> SCATTERLIST_MAX
) {
400 printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__
, __LINE__
,
406 /* point our enccrd and maccrd appropriately */
408 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
409 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
412 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
413 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
417 crp
->crp_etype
= EINVAL
;
418 dprintk("%s,%d: ENOENT - descriptors do not match session\n",
424 if (enccrd
->crd_flags
& CRD_F_ENCRYPT
) {
425 if (enccrd
->crd_flags
& CRD_F_IV_EXPLICIT
)
426 ivp
= enccrd
->crd_iv
;
428 read_random((ivp
= iv_data
), od
->octo_ivsize
);
429 if ((enccrd
->crd_flags
& CRD_F_IV_PRESENT
) == 0)
430 crypto_copyback(crp
->crp_flags
, crp
->crp_buf
,
431 enccrd
->crd_inject
, od
->octo_ivsize
, ivp
);
433 if (enccrd
->crd_flags
& CRD_F_IV_EXPLICIT
) {
434 ivp
= enccrd
->crd_iv
;
437 crypto_copydata(crp
->crp_flags
, crp
->crp_buf
,
438 enccrd
->crd_inject
, od
->octo_ivsize
, (caddr_t
) ivp
);
443 auth_off
= maccrd
->crd_skip
;
444 auth_len
= maccrd
->crd_len
;
445 icv_off
= maccrd
->crd_inject
;
448 crypt_off
= enccrd
->crd_skip
;
449 crypt_len
= enccrd
->crd_len
;
450 } else { /* if (maccrd) */
451 auth_off
= maccrd
->crd_skip
;
452 auth_len
= maccrd
->crd_len
;
453 icv_off
= maccrd
->crd_inject
;
458 * setup the SG list to cover the buffer
460 memset(sg
, 0, sizeof(sg
));
461 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
467 len
= skb_headlen(skb
);
468 sg_set_page(&sg
[sg_num
], virt_to_page(skb
->data
), len
,
469 offset_in_page(skb
->data
));
473 for (i
= 0; i
< skb_shinfo(skb
)->nr_frags
&& sg_num
< SCATTERLIST_MAX
;
475 len
= skb_shinfo(skb
)->frags
[i
].size
;
476 sg_set_page(&sg
[sg_num
], skb_frag_page(&skb_shinfo(skb
)->frags
[i
]),
477 len
, skb_shinfo(skb
)->frags
[i
].page_offset
);
481 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
485 for (sg_num
= 0; sg_len
< crp
->crp_ilen
&&
486 sg_num
< uiop
->uio_iovcnt
&&
487 sg_num
< SCATTERLIST_MAX
; sg_num
++) {
488 len
= uiop
->uio_iov
[sg_num
].iov_len
;
489 sg_set_page(&sg
[sg_num
],
490 virt_to_page(uiop
->uio_iov
[sg_num
].iov_base
), len
,
491 offset_in_page(uiop
->uio_iov
[sg_num
].iov_base
));
495 sg_len
= crp
->crp_ilen
;
496 sg_set_page(&sg
[0], virt_to_page(crp
->crp_buf
), sg_len
,
497 offset_in_page(crp
->crp_buf
));
503 * setup a new explicit key
506 if (enccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
507 od
->octo_encklen
= (enccrd
->crd_klen
+ 7) / 8;
508 memcpy(od
->octo_enckey
, enccrd
->crd_key
, od
->octo_encklen
);
512 if (maccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
513 od
->octo_macklen
= (maccrd
->crd_klen
+ 7) / 8;
514 memcpy(od
->octo_mackey
, maccrd
->crd_key
, od
->octo_macklen
);
515 od
->octo_mackey_set
= 0;
517 if (!od
->octo_mackey_set
) {
518 octo_calc_hash(maccrd
->crd_alg
== CRYPTO_MD5_HMAC
? 0 : 1,
519 maccrd
->crd_key
, od
->octo_hminner
, od
->octo_hmouter
);
520 od
->octo_mackey_set
= 1;
525 if (!enccrd
|| (enccrd
->crd_flags
& CRD_F_ENCRYPT
))
526 (*od
->octo_encrypt
)(od
, sg
, sg_len
,
527 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
529 (*od
->octo_decrypt
)(od
, sg
, sg_len
,
530 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
538 cryptocteon_init(void)
540 dprintk("%s(%p)\n", __FUNCTION__
, cryptocteon_init
);
542 softc_device_init(&octo_softc
, "cryptocteon", 0, octo_methods
);
544 octo_id
= crypto_get_driverid(softc_get_device(&octo_softc
),
545 CRYPTOCAP_F_HARDWARE
| CRYPTOCAP_F_SYNC
);
547 printk("Cryptocteon device cannot initialize!");
551 crypto_register(octo_id
, CRYPTO_MD5_HMAC
, 0,0);
552 crypto_register(octo_id
, CRYPTO_SHA1_HMAC
, 0,0);
553 //crypto_register(octo_id, CRYPTO_MD5, 0,0);
554 //crypto_register(octo_id, CRYPTO_SHA1, 0,0);
555 crypto_register(octo_id
, CRYPTO_DES_CBC
, 0,0);
556 crypto_register(octo_id
, CRYPTO_3DES_CBC
, 0,0);
557 crypto_register(octo_id
, CRYPTO_AES_CBC
, 0,0);
563 cryptocteon_exit(void)
565 dprintk("%s()\n", __FUNCTION__
);
566 crypto_unregister_all(octo_id
);
570 module_init(cryptocteon_init
);
571 module_exit(cryptocteon_exit
);
573 MODULE_LICENSE("BSD");
574 MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
575 MODULE_DESCRIPTION("Cryptocteon (OCF module for Cavium OCTEON crypto)");