2 * Driver for /dev/crypto device (aka CryptoDev)
4 * Copyright (c) 2004 Michal Ludvig <mludvig@logix.net.nz>, SuSE Labs
5 * Copyright (c) 2009 Nikos Mavrogiannopoulos <nmav@gennetsa.com>, Gennet S.A.
7 * Device /dev/crypto provides an interface for
8 * accessing kernel CryptoAPI algorithms (ciphers,
9 * hashes) from userspace programs.
11 * /dev/crypto interface was originally introduced in
12 * OpenBSD and this module attempts to keep the API,
13 * although a bit extended.
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/init.h>
20 #include <linux/sched.h>
22 #include <linux/file.h>
23 #include <linux/fdtable.h>
24 #include <linux/miscdevice.h>
25 #include <linux/crypto.h>
27 #include <linux/highmem.h>
28 #include <linux/random.h>
29 #include "cryptodev.h"
30 #include <asm/uaccess.h>
31 #include <asm/ioctl.h>
32 #include <linux/scatterlist.h>
34 MODULE_AUTHOR("Michal Ludvig <mludvig@logix.net.nz>");
35 MODULE_DESCRIPTION("CryptoDev driver");
36 MODULE_LICENSE("Dual BSD/GPL");
38 /* ====== Compile-time config ====== */
40 #define CRYPTODEV_STATS
42 /* ====== Module parameters ====== */
44 static int verbosity
= 0;
45 module_param(verbosity
, int, 0644);
46 MODULE_PARM_DESC(verbosity
, "0: normal, 1: verbose, 2: debug");
48 #ifdef CRYPTODEV_STATS
49 static int enable_stats
= 0;
50 module_param(enable_stats
, int, 0644);
51 MODULE_PARM_DESC(enable_stats
, "collect statictics about cryptodev usage");
54 /* ====== Debug helpers ====== */
56 #define PFX "cryptodev: "
57 #define dprintk(level,severity,format,a...) \
59 if (level <= verbosity) \
60 printk(severity PFX "%s[%u]: " format, \
61 current->comm, current->pid, \
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 crypto_blkcipher
*tfm
;
79 struct crypto_hash
*hash_tfm
;
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
;
91 struct list_head list
;
95 /* Prepare session for future use. */
97 crypto_create_session(struct fcrypt
*fcr
, struct session_op
*sop
)
99 struct csession
*ses_new
, *ses_ptr
;
100 struct crypto_blkcipher
*blk_tfm
=NULL
;
101 struct crypto_hash
*hash_tfm
=NULL
;
103 const char *alg_name
=NULL
;
104 const char *hash_name
=NULL
;
105 struct blkcipher_alg
* blkalg
;
108 /* Does the request make sense? */
109 if (!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(3des_ede)";
124 alg_name
= "cbc(blowfish)";
127 alg_name
= "cbc(aes)";
129 case CRYPTO_CAMELLIA_CBC
:
130 alg_name
= "cbc(camelia)";
133 dprintk(1,KERN_DEBUG
,"%s: bad cipher: %d\n", __func__
, sop
->cipher
);
140 case CRYPTO_MD5_HMAC
:
141 hash_name
= "hmac(md5)";
143 case CRYPTO_RIPEMD160_HMAC
:
144 hash_name
= "hmac(rmd160)";
146 case CRYPTO_SHA1_HMAC
:
147 hash_name
= "hmac(sha1)";
149 case CRYPTO_SHA2_256_HMAC
:
150 hash_name
= "hmac(sha256)";
152 case CRYPTO_SHA2_384_HMAC
:
153 hash_name
= "hmac(sha384)";
155 case CRYPTO_SHA2_512_HMAC
:
156 hash_name
= "hmac(sha512)";
164 case CRYPTO_RIPEMD160
:
165 hash_name
= "rmd160";
172 case CRYPTO_SHA2_256
:
173 hash_name
= "sha256";
176 case CRYPTO_SHA2_384
:
177 hash_name
= "sha384";
180 case CRYPTO_SHA2_512
:
181 hash_name
= "sha512";
186 dprintk(1,KERN_DEBUG
,"%s: bad mac: %d\n", __func__
, sop
->mac
);
190 /* Set-up crypto transform. */
192 uint8_t keyp
[CRYPTO_CIPHER_MAX_KEY_LEN
];
194 blk_tfm
= crypto_alloc_blkcipher(alg_name
, 0, CRYPTO_ALG_ASYNC
);
195 if (IS_ERR(blk_tfm
)) {
196 dprintk(1,KERN_DEBUG
,"%s: Failed to load transform for %s\n", __func__
,
201 blkalg
= crypto_blkcipher_alg(blk_tfm
);
202 if (blkalg
!= NULL
) {
203 /* Was correct key length supplied? */
204 if ((sop
->keylen
< blkalg
->min_keysize
) ||
205 (sop
->keylen
> blkalg
->max_keysize
)) {
206 dprintk(0,KERN_DEBUG
,"Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.\n",
207 sop
->keylen
, alg_name
, blkalg
->min_keysize
,
208 blkalg
->max_keysize
);
214 if (sop
->keylen
> CRYPTO_CIPHER_MAX_KEY_LEN
) {
215 dprintk(0,KERN_DEBUG
,"Setting key failed for %s-%zu.\n",
216 alg_name
, sop
->keylen
*8);
221 /* Copy the key from user and set to TFM. */
222 copy_from_user(keyp
, sop
->key
, sop
->keylen
);
223 ret
= crypto_blkcipher_setkey(blk_tfm
, keyp
, sop
->keylen
);
225 dprintk(0,KERN_DEBUG
,"Setting key failed for %s-%zu.\n",
226 alg_name
, sop
->keylen
*8);
234 hash_tfm
= crypto_alloc_hash(hash_name
, 0, CRYPTO_ALG_ASYNC
);
235 if (IS_ERR(hash_tfm
)) {
236 dprintk(1,KERN_DEBUG
,"%s: Failed to load transform for %s\n", __func__
,
241 /* Copy the key from user and set to TFM. */
242 if (hmac_mode
!= 0) {
243 uint8_t hkeyp
[CRYPTO_HMAC_MAX_KEY_LEN
];
245 if (sop
->mackeylen
> CRYPTO_HMAC_MAX_KEY_LEN
) {
246 dprintk(0,KERN_DEBUG
,"Setting hmac key failed for %s-%zu.\n",
247 hash_name
, sop
->mackeylen
*8);
252 copy_from_user(hkeyp
, sop
->mackey
, sop
->mackeylen
);
253 ret
= crypto_hash_setkey(hash_tfm
, hkeyp
, sop
->mackeylen
);
255 dprintk(0,KERN_DEBUG
,"Setting hmac key failed for %s-%zu.\n",
256 hash_name
, sop
->mackeylen
*8);
264 /* Create a session and put it to the list. */
265 ses_new
= kmalloc(sizeof(*ses_new
), GFP_KERNEL
);
271 memset(ses_new
, 0, sizeof(*ses_new
));
272 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
273 ses_new
->tfm
= blk_tfm
;
274 ses_new
->hash_tfm
= hash_tfm
;
275 init_MUTEX(&ses_new
->sem
);
279 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
280 /* Check for duplicate SID */
281 if (unlikely(ses_new
->sid
== ses_ptr
->sid
)) {
282 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
283 /* Unless we have a broken RNG this
284 shouldn't loop forever... ;-) */
289 list_add(&ses_new
->entry
, &fcr
->list
);
292 /* Fill in some values for the user. */
293 sop
->ses
= ses_new
->sid
;
299 crypto_free_blkcipher(blk_tfm
);
301 crypto_free_hash(hash_tfm
);
307 /* Everything that needs to be done when remowing a session. */
309 crypto_destroy_session(struct csession
*ses_ptr
)
311 if(down_trylock(&ses_ptr
->sem
)) {
312 dprintk(2, KERN_DEBUG
, "Waiting for semaphore of sid=0x%08X\n",
316 dprintk(2, KERN_DEBUG
, "Removed session 0x%08X\n", ses_ptr
->sid
);
317 #if defined(CRYPTODEV_STATS)
319 dprintk(2, KERN_DEBUG
,
320 "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
321 ses_ptr
->stat
[COP_ENCRYPT
], ses_ptr
->stat
[COP_DECRYPT
],
322 ses_ptr
->stat_max_size
, ses_ptr
->stat_count
> 0
323 ? ((unsigned long)(ses_ptr
->stat
[COP_ENCRYPT
]+
324 ses_ptr
->stat
[COP_DECRYPT
]) /
325 ses_ptr
->stat_count
) : 0,
326 ses_ptr
->stat_count
);
329 crypto_free_blkcipher(ses_ptr
->tfm
);
332 if (ses_ptr
->hash_tfm
) {
333 crypto_free_hash(ses_ptr
->hash_tfm
);
334 ses_ptr
->hash_tfm
= NULL
;
340 /* Look up a session by ID and remove. */
342 crypto_finish_session(struct fcrypt
*fcr
, uint32_t sid
)
344 struct csession
*tmp
, *ses_ptr
;
345 struct list_head
*head
;
350 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
351 if(ses_ptr
->sid
== sid
) {
352 list_del(&ses_ptr
->entry
);
353 crypto_destroy_session(ses_ptr
);
359 dprintk(1, KERN_ERR
, "Session with sid=0x%08X not found!\n", sid
);
367 /* Remove all sessions when closing the file */
369 crypto_finish_all_sessions(struct fcrypt
*fcr
)
371 struct csession
*tmp
, *ses_ptr
;
372 struct list_head
*head
;
377 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
378 list_del(&ses_ptr
->entry
);
379 crypto_destroy_session(ses_ptr
);
386 /* Look up session by session ID. The returned session is locked. */
387 static struct csession
*
388 crypto_get_session_by_sid(struct fcrypt
*fcr
, uint32_t sid
)
390 struct csession
*ses_ptr
;
393 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
394 if(ses_ptr
->sid
== sid
) {
404 /* This is the main crypto function - feed it with plaintext
405 and get a ciphertext (or vice versa :-) */
407 crypto_run(struct fcrypt
*fcr
, struct crypt_op
*cop
)
409 char *data
, ivp
[EALG_MAX_BLOCK_LEN
];
410 char __user
*src
, __user
*dst
;
411 struct scatterlist sg
;
412 struct csession
*ses_ptr
;
413 unsigned int ivsize
=0;
414 size_t nbytes
, bufsize
;
416 uint8_t hash_output
[HASH_MAX_LEN
];
417 struct blkcipher_desc bdesc
= {
418 .flags
= CRYPTO_TFM_REQ_MAY_SLEEP
,
420 struct hash_desc hdesc
= {
421 .flags
= CRYPTO_TFM_REQ_MAY_SLEEP
,
425 if (unlikely(cop
->op
!= COP_ENCRYPT
&& cop
->op
!= COP_DECRYPT
)) {
426 dprintk(1, KERN_DEBUG
, "invalid operation op=%u\n", cop
->op
);
430 ses_ptr
= crypto_get_session_by_sid(fcr
, cop
->ses
);
432 dprintk(1, KERN_ERR
, "invalid session ID=0x%08X\n", cop
->ses
);
437 data
= (char*)__get_free_page(GFP_KERNEL
);
439 if (unlikely(!data
)) {
443 bufsize
= PAGE_SIZE
< nbytes
? PAGE_SIZE
: nbytes
;
446 bdesc
.tfm
= ses_ptr
->tfm
;
447 hdesc
.tfm
= ses_ptr
->hash_tfm
;
449 ret
= crypto_hash_init(&hdesc
);
452 "error in crypto_hash_init()\n");
458 if (nbytes
% crypto_blkcipher_blocksize(ses_ptr
->tfm
)) {
460 "data size (%zu) isn't a multiple of block size (%u)\n",
461 nbytes
, crypto_blkcipher_blocksize(ses_ptr
->tfm
));
466 ivsize
= crypto_blkcipher_ivsize(ses_ptr
->tfm
);
469 copy_from_user(ivp
, cop
->iv
, ivsize
);
470 crypto_blkcipher_set_iv(ses_ptr
->tfm
, ivp
, ivsize
);
479 size_t current_len
= nbytes
> bufsize
? bufsize
: nbytes
;
481 copy_from_user(data
, src
, current_len
);
483 sg_set_buf(&sg
, data
, current_len
);
485 /* Always hash before encryption and after decryption. Maybe
486 * we should introduce a flag to switch... TBD later on.
488 if (cop
->op
== COP_ENCRYPT
) {
490 ret
= crypto_hash_update(&hdesc
, &sg
, current_len
);
492 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
497 ret
= crypto_blkcipher_encrypt(&bdesc
, &sg
, &sg
, current_len
);
500 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
503 copy_to_user(dst
, data
, current_len
);
508 ret
= crypto_blkcipher_decrypt(&bdesc
, &sg
, &sg
, current_len
);
511 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
514 copy_to_user(dst
, data
, current_len
);
520 ret
= crypto_hash_update(&hdesc
, &sg
, current_len
);
522 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
528 nbytes
-= current_len
;
533 ret
= crypto_hash_final(&hdesc
, hash_output
);
535 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
539 copy_to_user(cop
->mac
, hash_output
, crypto_hash_digestsize(ses_ptr
->hash_tfm
));
542 #if defined(CRYPTODEV_STATS)
544 /* this is safe - we check cop->op at the function entry */
545 ses_ptr
->stat
[cop
->op
] += cop
->len
;
546 if (ses_ptr
->stat_max_size
< cop
->len
)
547 ses_ptr
->stat_max_size
= cop
->len
;
548 ses_ptr
->stat_count
++;
553 free_page((unsigned long)data
);
561 /* ====== /dev/crypto ====== */
564 cryptodev_open(struct inode
*inode
, struct file
*filp
)
568 fcr
= kmalloc(sizeof(*fcr
), GFP_KERNEL
);
572 memset(fcr
, 0, sizeof(*fcr
));
573 init_MUTEX(&fcr
->sem
);
574 INIT_LIST_HEAD(&fcr
->list
);
575 filp
->private_data
= fcr
;
581 cryptodev_release(struct inode
*inode
, struct file
*filp
)
583 struct fcrypt
*fcr
= filp
->private_data
;
586 crypto_finish_all_sessions(fcr
);
588 filp
->private_data
= NULL
;
595 clonefd(struct file
*filp
)
597 struct fdtable
*fdt
= files_fdtable(current
->files
);
599 ret
= get_unused_fd();
602 FD_SET(ret
, fdt
->open_fds
);
603 fd_install(ret
, filp
);
610 cryptodev_ioctl(struct inode
*inode
, struct file
*filp
,
611 unsigned int cmd
, unsigned long arg
)
613 int __user
*p
= (void __user
*)arg
;
614 struct session_op sop
;
616 struct fcrypt
*fcr
= filp
->private_data
;
633 copy_from_user(&sop
, (void*)arg
, sizeof(sop
));
634 ret
= crypto_create_session(fcr
, &sop
);
637 copy_to_user((void*)arg
, &sop
, sizeof(sop
));
641 get_user(ses
, (uint32_t*)arg
);
642 ret
= crypto_finish_session(fcr
, ses
);
646 copy_from_user(&cop
, (void*)arg
, sizeof(cop
));
647 ret
= crypto_run(fcr
, &cop
);
648 copy_to_user((void*)arg
, &cop
, sizeof(cop
));
656 struct file_operations cryptodev_fops
= {
657 .owner
= THIS_MODULE
,
658 .open
= cryptodev_open
,
659 .release
= cryptodev_release
,
660 .ioctl
= cryptodev_ioctl
,
663 struct miscdevice cryptodev
= {
664 .minor
= CRYPTODEV_MINOR
,
666 .fops
= &cryptodev_fops
,
670 cryptodev_register(void)
674 rc
= misc_register (&cryptodev
);
676 printk(KERN_ERR PFX
"registeration of /dev/crypto failed\n");
684 cryptodev_deregister(void)
686 misc_deregister(&cryptodev
);
689 /* ====== Module init/exit ====== */
691 int __init
init_cryptodev(void)
695 rc
= cryptodev_register();
699 printk(KERN_INFO PFX
"driver loaded.\n");
704 void __exit
exit_cryptodev(void)
706 cryptodev_deregister();
707 printk(KERN_INFO PFX
"driver unloaded.\n");
710 module_init(init_cryptodev
);
711 module_exit(exit_cryptodev
);