2 * Driver for /dev/crypto device (aka CryptoDev)
4 * Copyright (c) 2004 Michal Ludvig <mludvig@logix.net.nz>, SuSE Labs
5 * Copyright (c) 2009,2010 Nikos Mavrogiannopoulos <nmav@gnutls.org>
7 * This file is part of linux cryptodev.
9 * cryptodev is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * cryptodev is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Device /dev/crypto provides an interface for
25 * accessing kernel CryptoAPI algorithms (ciphers,
26 * hashes) from userspace programs.
28 * /dev/crypto interface was originally introduced in
29 * OpenBSD and this module attempts to keep the API.
33 #include <linux/crypto.h>
35 #include <linux/highmem.h>
36 #include <linux/pagemap.h>
37 #include <linux/random.h>
38 #include "cryptodev.h"
39 #include <asm/uaccess.h>
40 #include <asm/ioctl.h>
41 #include <linux/scatterlist.h>
42 #include "cryptodev_int.h"
45 MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>");
46 MODULE_DESCRIPTION("CryptoDev driver");
47 MODULE_LICENSE("GPL");
49 /* ====== Compile-time config ====== */
51 #define CRYPTODEV_STATS
53 /* ====== Module parameters ====== */
55 int cryptodev_verbosity
= 0;
56 module_param(cryptodev_verbosity
, int, 0644);
57 MODULE_PARM_DESC(cryptodev_verbosity
, "0: normal, 1: verbose, 2: debug");
59 #ifdef CRYPTODEV_STATS
60 static int enable_stats
= 0;
61 module_param(enable_stats
, int, 0644);
62 MODULE_PARM_DESC(enable_stats
, "collect statictics about cryptodev usage");
65 /* ====== CryptoAPI ====== */
67 #define FILL_SG(sg,ptr,len) \
69 (sg)->page = virt_to_page(ptr); \
70 (sg)->offset = offset_in_page(ptr); \
72 (sg)->dma_address = 0; \
76 struct list_head entry
;
78 struct cipher_data cdata
;
79 struct hash_data hdata
;
81 #ifdef CRYPTODEV_STATS
82 #if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2))
83 #error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something!
85 unsigned long long stat
[2];
86 size_t stat_max_size
, stat_count
;
90 struct scatterlist
*sg
;
94 struct list_head list
;
98 /* Prepare session for future use. */
100 crypto_create_session(struct fcrypt
*fcr
, struct session_op
*sop
)
102 struct csession
*ses_new
= NULL
, *ses_ptr
;
104 const char *alg_name
=NULL
;
105 const char *hash_name
=NULL
;
108 /* Does the request make sense? */
109 if (unlikely(!sop
->cipher
&& !sop
->mac
)) {
110 dprintk(1,KERN_DEBUG
,"Both 'cipher' and 'mac' unset.\n");
114 switch (sop
->cipher
) {
118 alg_name
= "cbc(des)";
120 case CRYPTO_3DES_CBC
:
121 alg_name
= "cbc(des3_ede)";
124 alg_name
= "cbc(blowfish)";
127 alg_name
= "cbc(aes)";
129 case CRYPTO_CAMELLIA_CBC
:
130 alg_name
= "cbc(camelia)";
133 alg_name
= "ecb(cipher_null)";
136 dprintk(1,KERN_DEBUG
,"%s: bad cipher: %d\n", __func__
, sop
->cipher
);
143 case CRYPTO_MD5_HMAC
:
144 hash_name
= "hmac(md5)";
146 case CRYPTO_RIPEMD160_HMAC
:
147 hash_name
= "hmac(rmd160)";
149 case CRYPTO_SHA1_HMAC
:
150 hash_name
= "hmac(sha1)";
152 case CRYPTO_SHA2_256_HMAC
:
153 hash_name
= "hmac(sha256)";
155 case CRYPTO_SHA2_384_HMAC
:
156 hash_name
= "hmac(sha384)";
158 case CRYPTO_SHA2_512_HMAC
:
159 hash_name
= "hmac(sha512)";
167 case CRYPTO_RIPEMD160
:
168 hash_name
= "rmd160";
175 case CRYPTO_SHA2_256
:
176 hash_name
= "sha256";
179 case CRYPTO_SHA2_384
:
180 hash_name
= "sha384";
183 case CRYPTO_SHA2_512
:
184 hash_name
= "sha512";
189 dprintk(1,KERN_DEBUG
,"%s: bad mac: %d\n", __func__
, sop
->mac
);
193 /* Create a session and put it to the list. */
194 ses_new
= kzalloc(sizeof(*ses_new
), GFP_KERNEL
);
199 /* Set-up crypto transform. */
201 uint8_t keyp
[CRYPTO_CIPHER_MAX_KEY_LEN
];
203 if (unlikely(sop
->keylen
> CRYPTO_CIPHER_MAX_KEY_LEN
)) {
204 dprintk(1,KERN_DEBUG
,"Setting key failed for %s-%zu.\n",
205 alg_name
, (size_t)sop
->keylen
*8);
210 ret
= copy_from_user(keyp
, sop
->key
, sop
->keylen
);
215 ret
= cryptodev_cipher_init(&ses_new
->cdata
, alg_name
, keyp
, sop
->keylen
);
218 dprintk(1,KERN_DEBUG
,"%s: Failed to load cipher for %s\n", __func__
,
226 uint8_t keyp
[CRYPTO_HMAC_MAX_KEY_LEN
];
228 if (unlikely(sop
->mackeylen
> CRYPTO_HMAC_MAX_KEY_LEN
)) {
229 dprintk(1,KERN_DEBUG
,"Setting key failed for %s-%zu.\n",
230 alg_name
, (size_t)sop
->mackeylen
*8);
235 ret
= copy_from_user(keyp
, sop
->mackey
, sop
->mackeylen
);
240 ret
= cryptodev_hash_init(&ses_new
->hdata
, hash_name
, hmac_mode
, keyp
, sop
->mackeylen
);
242 dprintk(1,KERN_DEBUG
,"%s: Failed to load hash for %s\n", __func__
,
249 ses_new
->array_size
= 16;
250 dprintk(2, KERN_DEBUG
, "%s: preallocating for %d user pages\n",
251 __func__
, ses_new
->array_size
);
252 ses_new
->pages
= kzalloc(ses_new
->array_size
*
253 sizeof(struct page
*), GFP_KERNEL
);
254 ses_new
->sg
= kzalloc(ses_new
->array_size
*
255 sizeof(struct scatterlist
), GFP_KERNEL
);
257 /* put the new session to the list */
258 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
259 init_MUTEX(&ses_new
->sem
);
263 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
264 /* Check for duplicate SID */
265 if (unlikely(ses_new
->sid
== ses_ptr
->sid
)) {
266 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
267 /* Unless we have a broken RNG this
268 shouldn't loop forever... ;-) */
273 list_add(&ses_new
->entry
, &fcr
->list
);
276 /* Fill in some values for the user. */
277 sop
->ses
= ses_new
->sid
;
282 cryptodev_cipher_deinit( &ses_new
->cdata
);
284 if (ses_new
) kfree(ses_new
);
290 /* Everything that needs to be done when remowing a session. */
292 crypto_destroy_session(struct csession
*ses_ptr
)
294 if(down_trylock(&ses_ptr
->sem
)) {
295 dprintk(2, KERN_DEBUG
, "Waiting for semaphore of sid=0x%08X\n",
299 dprintk(2, KERN_DEBUG
, "Removed session 0x%08X\n", ses_ptr
->sid
);
300 #if defined(CRYPTODEV_STATS)
302 dprintk(2, KERN_DEBUG
,
303 "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
304 ses_ptr
->stat
[COP_ENCRYPT
], ses_ptr
->stat
[COP_DECRYPT
],
305 ses_ptr
->stat_max_size
, ses_ptr
->stat_count
> 0
306 ? ((unsigned long)(ses_ptr
->stat
[COP_ENCRYPT
]+
307 ses_ptr
->stat
[COP_DECRYPT
]) /
308 ses_ptr
->stat_count
) : 0,
309 ses_ptr
->stat_count
);
311 cryptodev_cipher_deinit(&ses_ptr
->cdata
);
312 cryptodev_hash_deinit(&ses_ptr
->hdata
);
313 dprintk(2, KERN_DEBUG
, "%s: freeing space for %d user pages\n",
314 __func__
, ses_ptr
->array_size
);
315 kfree(ses_ptr
->pages
);
321 /* Look up a session by ID and remove. */
323 crypto_finish_session(struct fcrypt
*fcr
, uint32_t sid
)
325 struct csession
*tmp
, *ses_ptr
;
326 struct list_head
*head
;
331 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
332 if(ses_ptr
->sid
== sid
) {
333 list_del(&ses_ptr
->entry
);
334 crypto_destroy_session(ses_ptr
);
339 if (unlikely(!ses_ptr
)) {
340 dprintk(1, KERN_ERR
, "Session with sid=0x%08X not found!\n", sid
);
348 /* Remove all sessions when closing the file */
350 crypto_finish_all_sessions(struct fcrypt
*fcr
)
352 struct csession
*tmp
, *ses_ptr
;
353 struct list_head
*head
;
358 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
359 list_del(&ses_ptr
->entry
);
360 crypto_destroy_session(ses_ptr
);
367 /* Look up session by session ID. The returned session is locked. */
368 static struct csession
*
369 crypto_get_session_by_sid(struct fcrypt
*fcr
, uint32_t sid
)
371 struct csession
*ses_ptr
;
374 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
375 if(ses_ptr
->sid
== sid
) {
386 hash_n_crypt(struct csession
*ses_ptr
, struct crypt_op
*cop
,
387 struct scatterlist
*src_sg
, struct scatterlist
*dst_sg
, uint32_t len
)
391 /* Always hash before encryption and after decryption. Maybe
392 * we should introduce a flag to switch... TBD later on.
394 if (cop
->op
== COP_ENCRYPT
) {
395 if (ses_ptr
->hdata
.init
!= 0) {
396 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, src_sg
, len
);
400 if (ses_ptr
->cdata
.init
!= 0) {
401 ret
= cryptodev_cipher_encrypt( &ses_ptr
->cdata
, src_sg
, dst_sg
, len
);
407 if (ses_ptr
->cdata
.init
!= 0) {
408 ret
= cryptodev_cipher_decrypt( &ses_ptr
->cdata
, src_sg
, dst_sg
, len
);
414 if (ses_ptr
->hdata
.init
!= 0) {
415 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, dst_sg
, len
);
422 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
427 /* This is the main crypto function - feed it with plaintext
428 and get a ciphertext (or vice versa :-) */
430 __crypto_run_std(struct csession
*ses_ptr
, struct crypt_op
*cop
)
433 char __user
*src
, __user
*dst
;
434 struct scatterlist sg
;
435 size_t nbytes
, bufsize
;
439 data
= (char*)__get_free_page(GFP_KERNEL
);
441 if (unlikely(!data
)) {
444 bufsize
= PAGE_SIZE
< nbytes
? PAGE_SIZE
: nbytes
;
450 size_t current_len
= nbytes
> bufsize
? bufsize
: nbytes
;
452 ret
= copy_from_user(data
, src
, current_len
);
456 sg_init_one(&sg
, data
, current_len
);
458 ret
= hash_n_crypt(ses_ptr
, cop
, &sg
, &sg
, current_len
);
463 if (ses_ptr
->cdata
.init
!= 0) {
464 ret
= copy_to_user(dst
, data
, current_len
);
470 nbytes
-= current_len
;
474 free_page((unsigned long)data
);
478 #ifndef DISABLE_ZCOPY
480 static void release_user_pages(struct page
**pg
, int pagecount
)
482 while (pagecount
--) {
483 if (!PageReserved(pg
[pagecount
]))
484 SetPageDirty(pg
[pagecount
]);
485 page_cache_release(pg
[pagecount
]);
489 /* last page - first page + 1 */
490 #define PAGECOUNT(buf, buflen) \
491 ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \
492 (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1)
494 /* offset of buf in it's first page */
495 #define PAGEOFFSET(buf) ((unsigned long)buf & ~PAGE_MASK)
497 #define MIN(a, b) ((a > b) ? b : a)
499 /* fetch the pages addr resides in into pg and initialise sg with them */
500 static int __get_userbuf(uint8_t *addr
, uint32_t len
,
501 int pgcount
, struct page
**pg
, struct scatterlist
*sg
)
503 int ret
, pglen
, i
= 0;
504 struct scatterlist
*sgp
;
506 down_write(¤t
->mm
->mmap_sem
);
507 ret
= get_user_pages(current
, current
->mm
,
508 (unsigned long)addr
, pgcount
, 1, 0, pg
, NULL
);
509 up_write(¤t
->mm
->mmap_sem
);
513 sg_init_table(sg
, pgcount
);
515 pglen
= MIN(PAGE_SIZE
- PAGEOFFSET(addr
), len
);
516 sg_set_page(sg
, pg
[i
++], pglen
, PAGEOFFSET(addr
));
519 for (sgp
= sg_next(sg
); len
; sgp
= sg_next(sgp
)) {
520 pglen
= MIN(PAGE_SIZE
, len
);
521 sg_set_page(sgp
, pg
[i
++], pglen
, 0);
524 sg_mark_end(sg_last(sg
, pgcount
));
528 /* make cop->src and cop->dst available in scatterlists */
529 static int get_userbuf(struct csession
*ses
,
530 struct crypt_op
*cop
, struct scatterlist
**src_sg
,
531 struct scatterlist
**dst_sg
, int *tot_pages
)
533 int src_pagecount
, dst_pagecount
= 0, pagecount
;
535 src_pagecount
= PAGECOUNT(cop
->src
, cop
->len
);
536 if (cop
->src
!= cop
->dst
) { /* non-in-situ transformation */
537 dst_pagecount
= PAGECOUNT(cop
->dst
, cop
->len
);
539 (*tot_pages
) = pagecount
= src_pagecount
+ dst_pagecount
;
541 if (pagecount
> ses
->array_size
) {
542 while (ses
->array_size
< pagecount
)
543 ses
->array_size
*= 2;
545 dprintk(2, KERN_DEBUG
, "%s: reallocating to %d elements\n",
546 __func__
, ses
->array_size
);
547 ses
->pages
= krealloc(ses
->pages
, ses
->array_size
*
548 sizeof(struct page
*), GFP_KERNEL
);
549 ses
->sg
= krealloc(ses
->sg
, ses
->array_size
*
550 sizeof(struct scatterlist
), GFP_KERNEL
);
552 if (ses
->sg
== NULL
|| ses
->pages
== NULL
) {
557 if (__get_userbuf(cop
->src
, cop
->len
,
558 src_pagecount
, ses
->pages
, ses
->sg
)) {
559 printk(KERN_ERR
"%s: failed to get user pages\n", __func__
);
562 (*src_sg
) = (*dst_sg
) = ses
->sg
;
565 (*dst_sg
) = ses
->sg
+ src_pagecount
;
567 if (__get_userbuf(cop
->dst
, cop
->len
, dst_pagecount
,
568 ses
->pages
+ src_pagecount
, *dst_sg
)) {
569 printk(KERN_ERR
"%s: failed to get user pages\n", __func__
);
570 release_user_pages(ses
->pages
, src_pagecount
);
577 /* This is the main crypto function - zero-copy edition */
579 __crypto_run_zc(struct csession
*ses_ptr
, struct crypt_op
*cop
)
581 struct scatterlist
*src_sg
, *dst_sg
;
582 int ret
= 0, pagecount
;
584 ret
= get_userbuf(ses_ptr
, cop
, &src_sg
, &dst_sg
, &pagecount
);
586 dprintk(1, KERN_ERR
, "Error getting user pages. Falling back to non zero copy.\n");
587 return __crypto_run_std(ses_ptr
, cop
);
590 ret
= hash_n_crypt(ses_ptr
, cop
, src_sg
, dst_sg
, cop
->len
);
592 release_user_pages(ses_ptr
->pages
, pagecount
);
596 #endif /* DISABLE_ZCOPY */
598 static int crypto_run(struct fcrypt
*fcr
, struct crypt_op
*cop
)
600 struct csession
*ses_ptr
;
601 uint8_t hash_output
[AALG_MAX_RESULT_LEN
];
604 if (unlikely(cop
->op
!= COP_ENCRYPT
&& cop
->op
!= COP_DECRYPT
)) {
605 dprintk(1, KERN_DEBUG
, "invalid operation op=%u\n", cop
->op
);
609 /* this also enters ses_ptr->sem */
610 ses_ptr
= crypto_get_session_by_sid(fcr
, cop
->ses
);
611 if (unlikely(!ses_ptr
)) {
612 dprintk(1, KERN_ERR
, "invalid session ID=0x%08X\n", cop
->ses
);
616 if (ses_ptr
->hdata
.init
!= 0) {
617 ret
= cryptodev_hash_reset(&ses_ptr
->hdata
);
620 "error in cryptodev_hash_reset()\n");
625 if (ses_ptr
->cdata
.init
!= 0) {
626 int blocksize
= ses_ptr
->cdata
.blocksize
;
628 if (unlikely(cop
->len
% blocksize
)) {
630 "data size (%u) isn't a multiple of block size (%u)\n",
631 cop
->len
, blocksize
);
637 uint8_t iv
[EALG_MAX_BLOCK_LEN
];
639 ret
= copy_from_user(iv
, cop
->iv
, min( (int)sizeof(iv
), (ses_ptr
->cdata
.ivsize
)));
641 dprintk(1, KERN_ERR
, "error copying IV (%d bytes)\n", min( (int)sizeof(iv
), (ses_ptr
->cdata
.ivsize
)));
645 cryptodev_cipher_set_iv(&ses_ptr
->cdata
, iv
, ses_ptr
->cdata
.ivsize
);
650 ret
= __crypto_run_std(ses_ptr
, cop
);
652 ret
= __crypto_run_zc(ses_ptr
, cop
);
657 if (ses_ptr
->hdata
.init
!= 0) {
658 ret
= cryptodev_hash_final(&ses_ptr
->hdata
, hash_output
);
660 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
664 if (unlikely(copy_to_user(cop
->mac
, hash_output
, ses_ptr
->hdata
.digestsize
)))
668 #if defined(CRYPTODEV_STATS)
670 /* this is safe - we check cop->op at the function entry */
671 ses_ptr
->stat
[cop
->op
] += cop
->len
;
672 if (ses_ptr
->stat_max_size
< cop
->len
)
673 ses_ptr
->stat_max_size
= cop
->len
;
674 ses_ptr
->stat_count
++;
683 /* ====== /dev/crypto ====== */
686 cryptodev_open(struct inode
*inode
, struct file
*filp
)
690 fcr
= kmalloc(sizeof(*fcr
), GFP_KERNEL
);
694 memset(fcr
, 0, sizeof(*fcr
));
695 init_MUTEX(&fcr
->sem
);
696 INIT_LIST_HEAD(&fcr
->list
);
697 filp
->private_data
= fcr
;
703 cryptodev_release(struct inode
*inode
, struct file
*filp
)
705 struct fcrypt
*fcr
= filp
->private_data
;
708 crypto_finish_all_sessions(fcr
);
710 filp
->private_data
= NULL
;
717 clonefd(struct file
*filp
)
719 struct fdtable
*fdt
= files_fdtable(current
->files
);
721 ret
= get_unused_fd();
724 FD_SET(ret
, fdt
->open_fds
);
725 fd_install(ret
, filp
);
732 cryptodev_ioctl(struct inode
*inode
, struct file
*filp
,
733 unsigned int cmd
, unsigned long arg
)
735 int __user
*p
= (void __user
*)arg
;
736 struct session_op sop
;
738 struct fcrypt
*fcr
= filp
->private_data
;
755 ret
= copy_from_user(&sop
, (void*)arg
, sizeof(sop
));
759 ret
= crypto_create_session(fcr
, &sop
);
762 return copy_to_user((void*)arg
, &sop
, sizeof(sop
));
765 ret
= get_user(ses
, (uint32_t*)arg
);
769 return crypto_finish_session(fcr
, ses
);
772 ret
= copy_from_user(&cop
, (void*)arg
, sizeof(cop
));
776 ret
= crypto_run(fcr
, &cop
);
779 return copy_to_user((void*)arg
, &cop
, sizeof(cop
));
786 /* compatibility code for 32bit userlands */
790 compat_to_session_op(struct compat_session_op
*compat
, struct session_op
*sop
)
792 sop
->cipher
= compat
->cipher
;
793 sop
->mac
= compat
->mac
;
794 sop
->keylen
= compat
->keylen
;
796 sop
->key
= compat_ptr(compat
->key
);
797 sop
->mackeylen
= compat
->mackeylen
;
798 sop
->mackey
= compat_ptr(compat
->mackey
);
799 sop
->ses
= compat
->ses
;
803 session_op_to_compat(struct session_op
*sop
, struct compat_session_op
*compat
)
805 compat
->cipher
= sop
->cipher
;
806 compat
->mac
= sop
->mac
;
807 compat
->keylen
= sop
->keylen
;
809 compat
->key
= ptr_to_compat(sop
->key
);
810 compat
->mackeylen
= sop
->mackeylen
;
811 compat
->mackey
= ptr_to_compat(sop
->mackey
);
812 compat
->ses
= sop
->ses
;
816 compat_to_crypt_op(struct compat_crypt_op
*compat
, struct crypt_op
*cop
)
818 cop
->ses
= compat
->ses
;
819 cop
->op
= compat
->op
;
820 cop
->flags
= compat
->flags
;
821 cop
->len
= compat
->len
;
823 cop
->src
= compat_ptr(compat
->src
);
824 cop
->dst
= compat_ptr(compat
->dst
);
825 cop
->mac
= compat_ptr(compat
->mac
);
826 cop
->iv
= compat_ptr(compat
->iv
);
830 crypt_op_to_compat(struct crypt_op
*cop
, struct compat_crypt_op
*compat
)
832 compat
->ses
= cop
->ses
;
833 compat
->op
= cop
->op
;
834 compat
->flags
= cop
->flags
;
835 compat
->len
= cop
->len
;
837 compat
->src
= ptr_to_compat(cop
->src
);
838 compat
->dst
= ptr_to_compat(cop
->dst
);
839 compat
->mac
= ptr_to_compat(cop
->mac
);
840 compat
->iv
= ptr_to_compat(cop
->iv
);
844 cryptodev_compat_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
846 struct fcrypt
*fcr
= file
->private_data
;
847 struct session_op sop
;
848 struct compat_session_op compat_sop
;
850 struct compat_crypt_op compat_cop
;
860 return cryptodev_ioctl(NULL
, file
, cmd
, arg
);
862 case COMPAT_CIOCGSESSION
:
863 ret
= copy_from_user(&compat_sop
,
864 (void *)arg
, sizeof(compat_sop
));
868 compat_to_session_op(&compat_sop
, &sop
);
870 ret
= crypto_create_session(fcr
, &sop
);
874 session_op_to_compat(&sop
, &compat_sop
);
875 return copy_to_user((void*)arg
,
876 &compat_sop
, sizeof(compat_sop
));
878 case COMPAT_CIOCCRYPT
:
879 ret
= copy_from_user(&compat_cop
,
880 (void*)arg
, sizeof(compat_cop
));
884 compat_to_crypt_op(&compat_cop
, &cop
);
886 ret
= crypto_run(fcr
, &cop
);
890 crypt_op_to_compat(&cop
, &compat_cop
);
891 return copy_to_user((void*)arg
,
892 &compat_cop
, sizeof(compat_cop
));
899 #endif /* CONFIG_COMPAT */
901 struct file_operations cryptodev_fops
= {
902 .owner
= THIS_MODULE
,
903 .open
= cryptodev_open
,
904 .release
= cryptodev_release
,
905 .ioctl
= cryptodev_ioctl
,
907 .compat_ioctl
= cryptodev_compat_ioctl
,
908 #endif /* CONFIG_COMPAT */
911 struct miscdevice cryptodev
= {
912 .minor
= MISC_DYNAMIC_MINOR
,
914 .fops
= &cryptodev_fops
,
918 cryptodev_register(void)
922 rc
= misc_register (&cryptodev
);
924 printk(KERN_ERR PFX
"registeration of /dev/crypto failed\n");
932 cryptodev_deregister(void)
934 misc_deregister(&cryptodev
);
937 /* ====== Module init/exit ====== */
939 int __init
init_cryptodev(void)
943 rc
= cryptodev_register();
947 printk(KERN_INFO PFX
"driver %s loaded.\n", VERSION
);
952 void __exit
exit_cryptodev(void)
954 cryptodev_deregister();
955 printk(KERN_INFO PFX
"driver unloaded.\n");
958 module_init(init_cryptodev
);
959 module_exit(exit_cryptodev
);