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/random.h>
37 #include "cryptodev.h"
38 #include <asm/uaccess.h>
39 #include <asm/ioctl.h>
40 #include <linux/scatterlist.h>
41 #include "cryptodev_int.h"
44 MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>");
45 MODULE_DESCRIPTION("CryptoDev driver");
46 MODULE_LICENSE("GPL");
48 /* ====== Compile-time config ====== */
50 #define CRYPTODEV_STATS
52 /* ====== Module parameters ====== */
54 int cryptodev_verbosity
= 0;
55 module_param(cryptodev_verbosity
, int, 0644);
56 MODULE_PARM_DESC(cryptodev_verbosity
, "0: normal, 1: verbose, 2: debug");
58 #ifdef CRYPTODEV_STATS
59 static int enable_stats
= 0;
60 module_param(enable_stats
, int, 0644);
61 MODULE_PARM_DESC(enable_stats
, "collect statictics about cryptodev usage");
64 /* ====== CryptoAPI ====== */
66 #define FILL_SG(sg,ptr,len) \
68 (sg)->page = virt_to_page(ptr); \
69 (sg)->offset = offset_in_page(ptr); \
71 (sg)->dma_address = 0; \
75 struct list_head entry
;
77 struct cipher_data cdata
;
78 struct hash_data hdata
;
80 #ifdef CRYPTODEV_STATS
81 #if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2))
82 #error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something!
84 unsigned long long stat
[2];
85 size_t stat_max_size
, stat_count
;
90 struct list_head list
;
94 /* Prepare session for future use. */
96 crypto_create_session(struct fcrypt
*fcr
, struct session_op
*sop
)
98 struct csession
*ses_new
= NULL
, *ses_ptr
;
100 const char *alg_name
=NULL
;
101 const char *hash_name
=NULL
;
104 /* Does the request make sense? */
105 if (unlikely(!sop
->cipher
&& !sop
->mac
)) {
106 dprintk(1,KERN_DEBUG
,"Both 'cipher' and 'mac' unset.\n");
110 switch (sop
->cipher
) {
114 alg_name
= "cbc(des)";
116 case CRYPTO_3DES_CBC
:
117 alg_name
= "cbc(des3_ede)";
120 alg_name
= "cbc(blowfish)";
123 alg_name
= "cbc(aes)";
125 case CRYPTO_CAMELLIA_CBC
:
126 alg_name
= "cbc(camelia)";
129 dprintk(1,KERN_DEBUG
,"%s: bad cipher: %d\n", __func__
, sop
->cipher
);
136 case CRYPTO_MD5_HMAC
:
137 hash_name
= "hmac(md5)";
139 case CRYPTO_RIPEMD160_HMAC
:
140 hash_name
= "hmac(rmd160)";
142 case CRYPTO_SHA1_HMAC
:
143 hash_name
= "hmac(sha1)";
145 case CRYPTO_SHA2_256_HMAC
:
146 hash_name
= "hmac(sha256)";
148 case CRYPTO_SHA2_384_HMAC
:
149 hash_name
= "hmac(sha384)";
151 case CRYPTO_SHA2_512_HMAC
:
152 hash_name
= "hmac(sha512)";
160 case CRYPTO_RIPEMD160
:
161 hash_name
= "rmd160";
168 case CRYPTO_SHA2_256
:
169 hash_name
= "sha256";
172 case CRYPTO_SHA2_384
:
173 hash_name
= "sha384";
176 case CRYPTO_SHA2_512
:
177 hash_name
= "sha512";
182 dprintk(1,KERN_DEBUG
,"%s: bad mac: %d\n", __func__
, sop
->mac
);
186 /* Create a session and put it to the list. */
187 ses_new
= kmalloc(sizeof(*ses_new
), GFP_KERNEL
);
192 memset(ses_new
, 0, sizeof(*ses_new
));
194 /* Set-up crypto transform. */
196 ret
= cryptodev_cipher_init(&ses_new
->cdata
, alg_name
, sop
->key
, sop
->keylen
);
198 dprintk(1,KERN_DEBUG
,"%s: Failed to load cipher for %s\n", __func__
,
206 ret
= cryptodev_hash_init(&ses_new
->hdata
, hash_name
, hmac_mode
, sop
->mackey
, sop
->mackeylen
);
208 dprintk(1,KERN_DEBUG
,"%s: Failed to load hash for %s\n", __func__
,
215 /* put the new session to the list */
216 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
217 init_MUTEX(&ses_new
->sem
);
221 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
222 /* Check for duplicate SID */
223 if (unlikely(ses_new
->sid
== ses_ptr
->sid
)) {
224 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
225 /* Unless we have a broken RNG this
226 shouldn't loop forever... ;-) */
231 list_add(&ses_new
->entry
, &fcr
->list
);
234 /* Fill in some values for the user. */
235 sop
->ses
= ses_new
->sid
;
240 cryptodev_cipher_deinit( &ses_new
->cdata
);
242 if (ses_new
) kfree(ses_new
);
248 /* Everything that needs to be done when remowing a session. */
250 crypto_destroy_session(struct csession
*ses_ptr
)
252 if(down_trylock(&ses_ptr
->sem
)) {
253 dprintk(2, KERN_DEBUG
, "Waiting for semaphore of sid=0x%08X\n",
257 dprintk(2, KERN_DEBUG
, "Removed session 0x%08X\n", ses_ptr
->sid
);
258 #if defined(CRYPTODEV_STATS)
260 dprintk(2, KERN_DEBUG
,
261 "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
262 ses_ptr
->stat
[COP_ENCRYPT
], ses_ptr
->stat
[COP_DECRYPT
],
263 ses_ptr
->stat_max_size
, ses_ptr
->stat_count
> 0
264 ? ((unsigned long)(ses_ptr
->stat
[COP_ENCRYPT
]+
265 ses_ptr
->stat
[COP_DECRYPT
]) /
266 ses_ptr
->stat_count
) : 0,
267 ses_ptr
->stat_count
);
269 cryptodev_cipher_deinit(&ses_ptr
->cdata
);
270 cryptodev_hash_deinit(&ses_ptr
->hdata
);
275 /* Look up a session by ID and remove. */
277 crypto_finish_session(struct fcrypt
*fcr
, uint32_t sid
)
279 struct csession
*tmp
, *ses_ptr
;
280 struct list_head
*head
;
285 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
286 if(ses_ptr
->sid
== sid
) {
287 list_del(&ses_ptr
->entry
);
288 crypto_destroy_session(ses_ptr
);
293 if (unlikely(!ses_ptr
)) {
294 dprintk(1, KERN_ERR
, "Session with sid=0x%08X not found!\n", sid
);
302 /* Remove all sessions when closing the file */
304 crypto_finish_all_sessions(struct fcrypt
*fcr
)
306 struct csession
*tmp
, *ses_ptr
;
307 struct list_head
*head
;
312 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
313 list_del(&ses_ptr
->entry
);
314 crypto_destroy_session(ses_ptr
);
321 /* Look up session by session ID. The returned session is locked. */
322 static struct csession
*
323 crypto_get_session_by_sid(struct fcrypt
*fcr
, uint32_t sid
)
325 struct csession
*ses_ptr
;
328 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
329 if(ses_ptr
->sid
== sid
) {
339 /* This is the main crypto function - feed it with plaintext
340 and get a ciphertext (or vice versa :-) */
342 crypto_run(struct fcrypt
*fcr
, struct crypt_op
*cop
)
345 char __user
*src
, __user
*dst
;
346 struct scatterlist sg
;
347 struct csession
*ses_ptr
;
348 unsigned int ivsize
=0;
349 size_t nbytes
, bufsize
;
351 uint8_t hash_output
[AALG_MAX_RESULT_LEN
];
353 if (unlikely(cop
->op
!= COP_ENCRYPT
&& cop
->op
!= COP_DECRYPT
)) {
354 dprintk(1, KERN_DEBUG
, "invalid operation op=%u\n", cop
->op
);
358 ses_ptr
= crypto_get_session_by_sid(fcr
, cop
->ses
);
359 if (unlikely(!ses_ptr
)) {
360 dprintk(1, KERN_ERR
, "invalid session ID=0x%08X\n", cop
->ses
);
365 data
= (char*)__get_free_page(GFP_KERNEL
);
367 if (unlikely(!data
)) {
371 bufsize
= PAGE_SIZE
< nbytes
? PAGE_SIZE
: nbytes
;
375 if (ses_ptr
->hdata
.init
!= 0) {
376 ret
= cryptodev_hash_reset(&ses_ptr
->hdata
);
379 "error in cryptodev_hash_reset()\n");
384 if (ses_ptr
->cdata
.init
!= 0) {
385 int blocksize
= ses_ptr
->cdata
.blocksize
;
387 if (unlikely(nbytes
% blocksize
)) {
389 "data size (%zu) isn't a multiple of block size (%u)\n",
395 ivsize
= ses_ptr
->cdata
.ivsize
;
398 cryptodev_cipher_set_iv(&ses_ptr
->cdata
, cop
->iv
, ivsize
);
407 size_t current_len
= nbytes
> bufsize
? bufsize
: nbytes
;
409 ret
= copy_from_user(data
, src
, current_len
);
413 sg_init_one(&sg
, data
, current_len
);
415 /* Always hash before encryption and after decryption. Maybe
416 * we should introduce a flag to switch... TBD later on.
418 if (cop
->op
== COP_ENCRYPT
) {
419 if (ses_ptr
->hdata
.init
!= 0) {
420 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
422 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
426 if (ses_ptr
->cdata
.init
!= 0) {
427 ret
= cryptodev_cipher_encrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
430 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
433 if (unlikely(copy_to_user(dst
, data
, current_len
)))
438 if (ses_ptr
->cdata
.init
!= 0) {
439 ret
= cryptodev_cipher_decrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
442 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
445 if (unlikely(copy_to_user(dst
, data
, current_len
)))
451 if (ses_ptr
->hdata
.init
!= 0) {
452 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
454 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
460 nbytes
-= current_len
;
464 if (ses_ptr
->hdata
.init
!= 0) {
465 ret
= cryptodev_hash_final(&ses_ptr
->hdata
, hash_output
);
467 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
471 if (unlikely(copy_to_user(cop
->mac
, hash_output
, ses_ptr
->hdata
.digestsize
)))
475 #if defined(CRYPTODEV_STATS)
477 /* this is safe - we check cop->op at the function entry */
478 ses_ptr
->stat
[cop
->op
] += cop
->len
;
479 if (ses_ptr
->stat_max_size
< cop
->len
)
480 ses_ptr
->stat_max_size
= cop
->len
;
481 ses_ptr
->stat_count
++;
486 free_page((unsigned long)data
);
494 /* ====== /dev/crypto ====== */
497 cryptodev_open(struct inode
*inode
, struct file
*filp
)
501 fcr
= kmalloc(sizeof(*fcr
), GFP_KERNEL
);
505 memset(fcr
, 0, sizeof(*fcr
));
506 init_MUTEX(&fcr
->sem
);
507 INIT_LIST_HEAD(&fcr
->list
);
508 filp
->private_data
= fcr
;
514 cryptodev_release(struct inode
*inode
, struct file
*filp
)
516 struct fcrypt
*fcr
= filp
->private_data
;
519 crypto_finish_all_sessions(fcr
);
521 filp
->private_data
= NULL
;
528 clonefd(struct file
*filp
)
530 struct fdtable
*fdt
= files_fdtable(current
->files
);
532 ret
= get_unused_fd();
535 FD_SET(ret
, fdt
->open_fds
);
536 fd_install(ret
, filp
);
543 cryptodev_ioctl(struct inode
*inode
, struct file
*filp
,
544 unsigned int cmd
, unsigned long arg
)
546 int __user
*p
= (void __user
*)arg
;
547 struct session_op sop
;
549 struct fcrypt
*fcr
= filp
->private_data
;
566 ret
= copy_from_user(&sop
, (void*)arg
, sizeof(sop
));
570 ret
= crypto_create_session(fcr
, &sop
);
573 return copy_to_user((void*)arg
, &sop
, sizeof(sop
));
576 get_user(ses
, (uint32_t*)arg
);
577 ret
= crypto_finish_session(fcr
, ses
);
581 ret
= copy_from_user(&cop
, (void*)arg
, sizeof(cop
));
585 ret
= crypto_run(fcr
, &cop
);
588 return copy_to_user((void*)arg
, &cop
, sizeof(cop
));
595 /* compatibility code for 32bit userlands */
599 compat_to_session_op(struct compat_session_op
*compat
, struct session_op
*sop
)
601 sop
->cipher
= compat
->cipher
;
602 sop
->mac
= compat
->mac
;
603 sop
->keylen
= compat
->keylen
;
605 sop
->key
= compat_ptr(compat
->key
);
606 sop
->mackeylen
= compat
->mackeylen
;
607 sop
->mackey
= compat_ptr(compat
->mackey
);
608 sop
->ses
= compat
->ses
;
612 session_op_to_compat(struct session_op
*sop
, struct compat_session_op
*compat
)
614 compat
->cipher
= sop
->cipher
;
615 compat
->mac
= sop
->mac
;
616 compat
->keylen
= sop
->keylen
;
618 compat
->key
= ptr_to_compat(sop
->key
);
619 compat
->mackeylen
= sop
->mackeylen
;
620 compat
->mackey
= ptr_to_compat(sop
->mackey
);
621 compat
->ses
= sop
->ses
;
625 compat_to_crypt_op(struct compat_crypt_op
*compat
, struct crypt_op
*cop
)
627 cop
->ses
= compat
->ses
;
628 cop
->op
= compat
->op
;
629 cop
->flags
= compat
->flags
;
630 cop
->len
= compat
->len
;
632 cop
->src
= compat_ptr(compat
->src
);
633 cop
->dst
= compat_ptr(compat
->dst
);
634 cop
->mac
= compat_ptr(compat
->mac
);
635 cop
->iv
= compat_ptr(compat
->iv
);
639 crypt_op_to_compat(struct crypt_op
*cop
, struct compat_crypt_op
*compat
)
641 compat
->ses
= cop
->ses
;
642 compat
->op
= cop
->op
;
643 compat
->flags
= cop
->flags
;
644 compat
->len
= cop
->len
;
646 compat
->src
= ptr_to_compat(cop
->src
);
647 compat
->dst
= ptr_to_compat(cop
->dst
);
648 compat
->mac
= ptr_to_compat(cop
->mac
);
649 compat
->iv
= ptr_to_compat(cop
->iv
);
653 cryptodev_compat_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
655 struct fcrypt
*fcr
= file
->private_data
;
656 struct session_op sop
;
657 struct compat_session_op compat_sop
;
659 struct compat_crypt_op compat_cop
;
669 return cryptodev_ioctl(NULL
, file
, cmd
, arg
);
671 case COMPAT_CIOCGSESSION
:
672 ret
= copy_from_user(&compat_sop
,
673 (void *)arg
, sizeof(compat_sop
));
677 compat_to_session_op(&compat_sop
, &sop
);
679 ret
= crypto_create_session(fcr
, &sop
);
683 session_op_to_compat(&sop
, &compat_sop
);
684 return copy_to_user((void*)arg
,
685 &compat_sop
, sizeof(compat_sop
));
687 case COMPAT_CIOCCRYPT
:
688 ret
= copy_from_user(&compat_cop
,
689 (void*)arg
, sizeof(compat_cop
));
693 compat_to_crypt_op(&compat_cop
, &cop
);
695 ret
= crypto_run(fcr
, &cop
);
699 crypt_op_to_compat(&cop
, &compat_cop
);
700 return copy_to_user((void*)arg
,
701 &compat_cop
, sizeof(compat_cop
));
708 #endif /* CONFIG_COMPAT */
710 struct file_operations cryptodev_fops
= {
711 .owner
= THIS_MODULE
,
712 .open
= cryptodev_open
,
713 .release
= cryptodev_release
,
714 .ioctl
= cryptodev_ioctl
,
716 .compat_ioctl
= cryptodev_compat_ioctl
,
717 #endif /* CONFIG_COMPAT */
720 struct miscdevice cryptodev
= {
721 .minor
= MISC_DYNAMIC_MINOR
,
723 .fops
= &cryptodev_fops
,
727 cryptodev_register(void)
731 rc
= misc_register (&cryptodev
);
733 printk(KERN_ERR PFX
"registeration of /dev/crypto failed\n");
741 cryptodev_deregister(void)
743 misc_deregister(&cryptodev
);
746 /* ====== Module init/exit ====== */
748 int __init
init_cryptodev(void)
752 rc
= cryptodev_register();
756 printk(KERN_INFO PFX
"driver %s loaded.\n", VERSION
);
761 void __exit
exit_cryptodev(void)
763 cryptodev_deregister();
764 printk(KERN_INFO PFX
"driver unloaded.\n");
767 module_init(init_cryptodev
);
768 module_exit(exit_cryptodev
);