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 #ifndef AUTOCONF_INCLUDED
31 #include <linux/config.h>
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/list.h>
36 #include <linux/slab.h>
37 #include <linux/sched.h>
38 #include <linux/wait.h>
39 #include <linux/crypto.h>
41 #include <linux/skbuff.h>
42 #include <linux/random.h>
43 #include <linux/scatterlist.h>
45 #include <cryptodev.h>
49 softc_device_decl sc_dev
;
52 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
56 #define MAX_CIPHER_KEYLEN 64
57 char octo_enckey
[MAX_CIPHER_KEYLEN
];
61 #define MAX_HASH_KEYLEN 64
62 char octo_mackey
[MAX_HASH_KEYLEN
];
70 int (*octo_decrypt
)(struct scatterlist
*sg
, int sg_len
,
71 uint8_t *key
, int key_len
, uint8_t * iv
,
72 uint64_t *hminner
, uint64_t *hmouter
);
74 int (*octo_encrypt
)(struct scatterlist
*sg
, int sg_len
,
75 uint8_t *key
, int key_len
, uint8_t * iv
,
76 uint64_t *hminner
, uint64_t *hmouter
);
78 int (*octo_encrypt
)(struct octo_sess
*od
,
79 struct scatterlist
*sg
, int sg_len
,
80 int auth_off
, int auth_len
,
81 int crypt_off
, int crypt_len
,
82 int icv_off
, uint8_t *ivp
);
83 int (*octo_decrypt
)(struct octo_sess
*od
,
84 struct scatterlist
*sg
, int sg_len
,
85 int auth_off
, int auth_len
,
86 int crypt_off
, int crypt_len
,
87 int icv_off
, uint8_t *ivp
);
90 uint64_t octo_hminner
[3];
91 uint64_t octo_hmouter
[3];
95 module_param(octo_id
, int, 0444);
96 MODULE_PARM_DESC(octo_id
, "Read-Only OCF ID for cryptocteon driver");
98 static struct octo_sess
**octo_sessions
= NULL
;
99 static u_int32_t octo_sesnum
= 0;
101 static int octo_process(device_t
, struct cryptop
*, int);
102 static int octo_newsession(device_t
, u_int32_t
*, struct cryptoini
*);
103 static int octo_freesession(device_t
, u_int64_t
);
105 static device_method_t octo_methods
= {
106 /* crypto device methods */
107 DEVMETHOD(cryptodev_newsession
, octo_newsession
),
108 DEVMETHOD(cryptodev_freesession
,octo_freesession
),
109 DEVMETHOD(cryptodev_process
, octo_process
),
112 #define debug octo_debug
114 module_param(octo_debug
, int, 0644);
115 MODULE_PARM_DESC(octo_debug
, "Enable debug");
118 #include "cavium_crypto.c"
122 * Generate a new octo session. We artifically limit it to a single
123 * hash/cipher or hash-cipher combo just to make it easier, most callers
124 * do not expect more than this anyway.
127 octo_newsession(device_t dev
, u_int32_t
*sid
, struct cryptoini
*cri
)
129 struct cryptoini
*c
, *encini
= NULL
, *macini
= NULL
;
130 struct octo_sess
**ocd
;
133 dprintk("%s()\n", __FUNCTION__
);
134 if (sid
== NULL
|| cri
== NULL
) {
135 dprintk("%s,%d - EINVAL\n", __FILE__
, __LINE__
);
140 * To keep it simple, we only handle hash, cipher or hash/cipher in a
141 * session, you cannot currently do multiple ciphers/hashes in one
142 * session even though it would be possibel to code this driver to
145 for (i
= 0, c
= cri
; c
&& i
< 2; i
++) {
146 if (c
->cri_alg
== CRYPTO_MD5_HMAC
||
147 c
->cri_alg
== CRYPTO_SHA1_HMAC
||
148 c
->cri_alg
== CRYPTO_NULL_HMAC
) {
154 if (c
->cri_alg
== CRYPTO_DES_CBC
||
155 c
->cri_alg
== CRYPTO_3DES_CBC
||
156 c
->cri_alg
== CRYPTO_AES_CBC
||
157 c
->cri_alg
== CRYPTO_NULL_CBC
) {
165 if (!macini
&& !encini
) {
166 dprintk("%s,%d - EINVAL bad cipher/hash or combination\n",
171 dprintk("%s,%d - EINVAL cannot handle chained cipher/hash combos\n",
177 * So we have something we can do, lets setup the session
181 for (i
= 1; i
< octo_sesnum
; i
++)
182 if (octo_sessions
[i
] == NULL
)
185 i
= 1; /* NB: to silence compiler warning */
187 if (octo_sessions
== NULL
|| i
== octo_sesnum
) {
188 if (octo_sessions
== NULL
) {
189 i
= 1; /* We leave octo_sessions[0] empty */
190 octo_sesnum
= CRYPTO_SW_SESSIONS
;
194 ocd
= kmalloc(octo_sesnum
* sizeof(struct octo_sess
*), SLAB_ATOMIC
);
196 /* Reset session number */
197 if (octo_sesnum
== CRYPTO_SW_SESSIONS
)
201 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
204 memset(ocd
, 0, octo_sesnum
* sizeof(struct octo_sess
*));
206 /* Copy existing sessions */
208 memcpy(ocd
, octo_sessions
,
209 (octo_sesnum
/ 2) * sizeof(struct octo_sess
*));
210 kfree(octo_sessions
);
216 ocd
= &octo_sessions
[i
];
220 *ocd
= (struct octo_sess
*) kmalloc(sizeof(struct octo_sess
), SLAB_ATOMIC
);
222 octo_freesession(NULL
, i
);
223 dprintk("%s,%d: ENOBUFS\n", __FILE__
, __LINE__
);
226 memset(*ocd
, 0, sizeof(struct octo_sess
));
228 if (encini
&& encini
->cri_key
) {
229 (*ocd
)->octo_encklen
= (encini
->cri_klen
+ 7) / 8;
230 memcpy((*ocd
)->octo_enckey
, encini
->cri_key
, (*ocd
)->octo_encklen
);
233 if (macini
&& macini
->cri_key
) {
234 (*ocd
)->octo_macklen
= (macini
->cri_klen
+ 7) / 8;
235 memcpy((*ocd
)->octo_mackey
, macini
->cri_key
, (*ocd
)->octo_macklen
);
238 (*ocd
)->octo_mlen
= 0;
239 if (encini
&& encini
->cri_mlen
)
240 (*ocd
)->octo_mlen
= encini
->cri_mlen
;
241 else if (macini
&& macini
->cri_mlen
)
242 (*ocd
)->octo_mlen
= macini
->cri_mlen
;
244 (*ocd
)->octo_mlen
= 12;
247 * point c at the enc if it exists, otherwise the mac
249 c
= encini
? encini
: macini
;
251 switch (c
->cri_alg
) {
253 case CRYPTO_3DES_CBC
:
254 (*ocd
)->octo_ivsize
= 8;
255 switch (macini
? macini
->cri_alg
: -1) {
256 case CRYPTO_MD5_HMAC
:
257 (*ocd
)->octo_encrypt
= octo_des_cbc_md5_encrypt
;
258 (*ocd
)->octo_decrypt
= octo_des_cbc_md5_decrypt
;
259 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
260 (*ocd
)->octo_hmouter
);
262 case CRYPTO_SHA1_HMAC
:
263 (*ocd
)->octo_encrypt
= octo_des_cbc_sha1_encrypt
;
264 (*ocd
)->octo_decrypt
= octo_des_cbc_sha1_encrypt
;
265 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
266 (*ocd
)->octo_hmouter
);
269 (*ocd
)->octo_encrypt
= octo_des_cbc_encrypt
;
270 (*ocd
)->octo_decrypt
= octo_des_cbc_decrypt
;
273 octo_freesession(NULL
, i
);
274 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
279 (*ocd
)->octo_ivsize
= 16;
280 switch (macini
? macini
->cri_alg
: -1) {
281 case CRYPTO_MD5_HMAC
:
282 (*ocd
)->octo_encrypt
= octo_aes_cbc_md5_encrypt
;
283 (*ocd
)->octo_decrypt
= octo_aes_cbc_md5_decrypt
;
284 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
285 (*ocd
)->octo_hmouter
);
287 case CRYPTO_SHA1_HMAC
:
288 (*ocd
)->octo_encrypt
= octo_aes_cbc_sha1_encrypt
;
289 (*ocd
)->octo_decrypt
= octo_aes_cbc_sha1_decrypt
;
290 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
291 (*ocd
)->octo_hmouter
);
294 (*ocd
)->octo_encrypt
= octo_aes_cbc_encrypt
;
295 (*ocd
)->octo_decrypt
= octo_aes_cbc_decrypt
;
298 octo_freesession(NULL
, i
);
299 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
303 case CRYPTO_MD5_HMAC
:
304 (*ocd
)->octo_encrypt
= octo_null_md5_encrypt
;
305 (*ocd
)->octo_decrypt
= octo_null_md5_encrypt
;
306 octo_calc_hash(0, macini
->cri_key
, (*ocd
)->octo_hminner
,
307 (*ocd
)->octo_hmouter
);
309 case CRYPTO_SHA1_HMAC
:
310 (*ocd
)->octo_encrypt
= octo_null_sha1_encrypt
;
311 (*ocd
)->octo_decrypt
= octo_null_sha1_encrypt
;
312 octo_calc_hash(1, macini
->cri_key
, (*ocd
)->octo_hminner
,
313 (*ocd
)->octo_hmouter
);
316 octo_freesession(NULL
, i
);
317 dprintk("%s,%d: EINVALn", __FILE__
, __LINE__
);
321 (*ocd
)->octo_encalg
= encini
? encini
->cri_alg
: -1;
322 (*ocd
)->octo_macalg
= macini
? macini
->cri_alg
: -1;
331 octo_freesession(device_t dev
, u_int64_t tid
)
333 u_int32_t sid
= CRYPTO_SESID2LID(tid
);
335 dprintk("%s()\n", __FUNCTION__
);
336 if (sid
> octo_sesnum
|| octo_sessions
== NULL
||
337 octo_sessions
[sid
] == NULL
) {
338 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
342 /* Silently accept and return */
346 if (octo_sessions
[sid
])
347 kfree(octo_sessions
[sid
]);
348 octo_sessions
[sid
] = NULL
;
356 octo_process(device_t dev
, struct cryptop
*crp
, int hint
)
358 struct cryptodesc
*crd
;
359 struct octo_sess
*od
;
361 #define SCATTERLIST_MAX 16
362 struct scatterlist sg
[SCATTERLIST_MAX
];
364 struct sk_buff
*skb
= NULL
;
365 struct uio
*uiop
= NULL
;
366 struct cryptodesc
*enccrd
= NULL
, *maccrd
= NULL
;
367 unsigned char *ivp
= NULL
;
368 unsigned char iv_data
[HASH_MAX_LEN
];
369 int auth_off
= 0, auth_len
= 0, crypt_off
= 0, crypt_len
= 0, icv_off
= 0;
371 dprintk("%s()\n", __FUNCTION__
);
374 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
380 if (crp
->crp_desc
== NULL
|| crp
->crp_buf
== NULL
) {
381 dprintk("%s,%d: EINVAL\n", __FILE__
, __LINE__
);
382 crp
->crp_etype
= EINVAL
;
386 lid
= crp
->crp_sid
& 0xffffffff;
387 if (lid
>= octo_sesnum
|| lid
== 0 || octo_sessions
== NULL
||
388 octo_sessions
[lid
] == NULL
) {
389 crp
->crp_etype
= ENOENT
;
390 dprintk("%s,%d: ENOENT\n", __FILE__
, __LINE__
);
393 od
= octo_sessions
[lid
];
396 * do some error checking outside of the loop for SKB and IOV processing
397 * this leaves us with valid skb or uiop pointers for later
399 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
400 skb
= (struct sk_buff
*) crp
->crp_buf
;
401 if (skb_shinfo(skb
)->nr_frags
>= SCATTERLIST_MAX
) {
402 printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__
, __LINE__
,
403 skb_shinfo(skb
)->nr_frags
);
406 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
407 uiop
= (struct uio
*) crp
->crp_buf
;
408 if (uiop
->uio_iovcnt
> SCATTERLIST_MAX
) {
409 printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__
, __LINE__
,
415 /* point our enccrd and maccrd appropriately */
417 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
418 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
421 if (crd
->crd_alg
== od
->octo_encalg
) enccrd
= crd
;
422 if (crd
->crd_alg
== od
->octo_macalg
) maccrd
= crd
;
426 crp
->crp_etype
= EINVAL
;
427 dprintk("%s,%d: ENOENT - descriptors do not match session\n",
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
);
442 auth_off
= maccrd
->crd_skip
;
443 auth_len
= maccrd
->crd_len
;
444 icv_off
= maccrd
->crd_inject
;
447 crypt_off
= enccrd
->crd_skip
;
448 crypt_len
= enccrd
->crd_len
;
449 } else { /* if (maccrd) */
450 auth_off
= maccrd
->crd_skip
;
451 auth_len
= maccrd
->crd_len
;
452 icv_off
= maccrd
->crd_inject
;
457 * setup the SG list to cover the buffer
459 memset(sg
, 0, sizeof(sg
));
460 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
466 len
= skb_headlen(skb
);
467 sg_set_page(&sg
[sg_num
], virt_to_page(skb
->data
), len
,
468 offset_in_page(skb
->data
));
472 for (i
= 0; i
< skb_shinfo(skb
)->nr_frags
&& sg_num
< SCATTERLIST_MAX
;
474 len
= skb_shinfo(skb
)->frags
[i
].size
;
475 sg_set_page(&sg
[sg_num
], skb_shinfo(skb
)->frags
[i
].page
,
476 len
, skb_shinfo(skb
)->frags
[i
].page_offset
);
480 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
484 for (sg_num
= 0; sg_len
< crp
->crp_ilen
&&
485 sg_num
< uiop
->uio_iovcnt
&&
486 sg_num
< SCATTERLIST_MAX
; sg_num
++) {
487 len
= uiop
->uio_iov
[sg_num
].iov_len
;
488 sg_set_page(&sg
[sg_num
],
489 virt_to_page(uiop
->uio_iov
[sg_num
].iov_base
), len
,
490 offset_in_page(uiop
->uio_iov
[sg_num
].iov_base
));
494 sg_len
= crp
->crp_ilen
;
495 sg_set_page(&sg
[0], virt_to_page(crp
->crp_buf
), sg_len
,
496 offset_in_page(crp
->crp_buf
));
502 * setup a new explicit key
505 if (enccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
506 od
->octo_encklen
= (enccrd
->crd_klen
+ 7) / 8;
507 memcpy(od
->octo_enckey
, enccrd
->crd_key
, od
->octo_encklen
);
511 if (maccrd
->crd_flags
& CRD_F_KEY_EXPLICIT
) {
512 od
->octo_macklen
= (maccrd
->crd_klen
+ 7) / 8;
513 memcpy(od
->octo_mackey
, maccrd
->crd_key
, od
->octo_macklen
);
514 od
->octo_mackey_set
= 0;
516 if (!od
->octo_mackey_set
) {
517 octo_calc_hash(maccrd
->crd_alg
== CRYPTO_MD5_HMAC
? 0 : 1,
518 maccrd
->crd_key
, od
->octo_hminner
, od
->octo_hmouter
);
519 od
->octo_mackey_set
= 1;
524 if (!enccrd
|| (enccrd
->crd_flags
& CRD_F_ENCRYPT
))
525 (*od
->octo_encrypt
)(od
, sg
, sg_len
,
526 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
528 (*od
->octo_decrypt
)(od
, sg
, sg_len
,
529 auth_off
, auth_len
, crypt_off
, crypt_len
, icv_off
, ivp
);
537 cryptocteon_init(void)
539 dprintk("%s(%p)\n", __FUNCTION__
, cryptocteon_init
);
541 softc_device_init(&octo_softc
, "cryptocteon", 0, octo_methods
);
543 octo_id
= crypto_get_driverid(softc_get_device(&octo_softc
),
544 CRYPTOCAP_F_HARDWARE
| CRYPTOCAP_F_SYNC
);
546 printk("Cryptocteon device cannot initialize!");
550 crypto_register(octo_id
, CRYPTO_MD5_HMAC
, 0,0);
551 crypto_register(octo_id
, CRYPTO_SHA1_HMAC
, 0,0);
552 //crypto_register(octo_id, CRYPTO_MD5, 0,0);
553 //crypto_register(octo_id, CRYPTO_SHA1, 0,0);
554 crypto_register(octo_id
, CRYPTO_DES_CBC
, 0,0);
555 crypto_register(octo_id
, CRYPTO_3DES_CBC
, 0,0);
556 crypto_register(octo_id
, CRYPTO_AES_CBC
, 0,0);
562 cryptocteon_exit(void)
564 dprintk("%s()\n", __FUNCTION__
);
565 crypto_unregister_all(octo_id
);
569 module_init(cryptocteon_init
);
570 module_exit(cryptocteon_exit
);
572 MODULE_LICENSE("BSD");
573 MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
574 MODULE_DESCRIPTION("Cryptocteon (OCF module for Cavium OCTEON crypto)");