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,
30 * although a bit extended.
34 #include <linux/crypto.h>
36 #include <linux/highmem.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"
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
, *ses_ptr
;
100 const char *alg_name
=NULL
;
101 const char *hash_name
=NULL
;
104 /* Does the request make sense? */
105 if (!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
);
193 memset(ses_new
, 0, sizeof(*ses_new
));
195 /* Set-up crypto transform. */
198 ret
= cryptodev_cipher_init(&ses_new
->cdata
, alg_name
, sop
->key
, sop
->keylen
);
205 ret
= cryptodev_hash_init(&ses_new
->hdata
, hash_name
, hmac_mode
, sop
->mackey
, sop
->mackeylen
);
207 dprintk(1,KERN_DEBUG
,"%s: Failed to load transform for %s\n", __func__
,
213 /* put the new session to the list */
214 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
215 init_MUTEX(&ses_new
->sem
);
219 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
220 /* Check for duplicate SID */
221 if (unlikely(ses_new
->sid
== ses_ptr
->sid
)) {
222 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
223 /* Unless we have a broken RNG this
224 shouldn't loop forever... ;-) */
229 list_add(&ses_new
->entry
, &fcr
->list
);
232 /* Fill in some values for the user. */
233 sop
->ses
= ses_new
->sid
;
238 cryptodev_cipher_deinit( &ses_new
->cdata
);
239 cryptodev_hash_deinit( &ses_new
->hdata
);
245 /* Everything that needs to be done when remowing a session. */
247 crypto_destroy_session(struct csession
*ses_ptr
)
249 if(down_trylock(&ses_ptr
->sem
)) {
250 dprintk(2, KERN_DEBUG
, "Waiting for semaphore of sid=0x%08X\n",
254 dprintk(2, KERN_DEBUG
, "Removed session 0x%08X\n", ses_ptr
->sid
);
255 #if defined(CRYPTODEV_STATS)
257 dprintk(2, KERN_DEBUG
,
258 "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
259 ses_ptr
->stat
[COP_ENCRYPT
], ses_ptr
->stat
[COP_DECRYPT
],
260 ses_ptr
->stat_max_size
, ses_ptr
->stat_count
> 0
261 ? ((unsigned long)(ses_ptr
->stat
[COP_ENCRYPT
]+
262 ses_ptr
->stat
[COP_DECRYPT
]) /
263 ses_ptr
->stat_count
) : 0,
264 ses_ptr
->stat_count
);
266 cryptodev_cipher_deinit(&ses_ptr
->cdata
);
267 cryptodev_hash_deinit(&ses_ptr
->hdata
);
272 /* Look up a session by ID and remove. */
274 crypto_finish_session(struct fcrypt
*fcr
, uint32_t sid
)
276 struct csession
*tmp
, *ses_ptr
;
277 struct list_head
*head
;
282 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
283 if(ses_ptr
->sid
== sid
) {
284 list_del(&ses_ptr
->entry
);
285 crypto_destroy_session(ses_ptr
);
291 dprintk(1, KERN_ERR
, "Session with sid=0x%08X not found!\n", sid
);
299 /* Remove all sessions when closing the file */
301 crypto_finish_all_sessions(struct fcrypt
*fcr
)
303 struct csession
*tmp
, *ses_ptr
;
304 struct list_head
*head
;
309 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
310 list_del(&ses_ptr
->entry
);
311 crypto_destroy_session(ses_ptr
);
318 /* Look up session by session ID. The returned session is locked. */
319 static struct csession
*
320 crypto_get_session_by_sid(struct fcrypt
*fcr
, uint32_t sid
)
322 struct csession
*ses_ptr
;
325 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
326 if(ses_ptr
->sid
== sid
) {
336 /* This is the main crypto function - feed it with plaintext
337 and get a ciphertext (or vice versa :-) */
339 crypto_run(struct fcrypt
*fcr
, struct crypt_op
*cop
)
342 char __user
*src
, __user
*dst
;
343 struct scatterlist sg
;
344 struct csession
*ses_ptr
;
345 unsigned int ivsize
=0;
346 size_t nbytes
, bufsize
;
348 uint8_t hash_output
[AALG_MAX_RESULT_LEN
];
350 if (unlikely(cop
->op
!= COP_ENCRYPT
&& cop
->op
!= COP_DECRYPT
)) {
351 dprintk(1, KERN_DEBUG
, "invalid operation op=%u\n", cop
->op
);
355 ses_ptr
= crypto_get_session_by_sid(fcr
, cop
->ses
);
357 dprintk(1, KERN_ERR
, "invalid session ID=0x%08X\n", cop
->ses
);
362 data
= (char*)__get_free_page(GFP_KERNEL
);
364 if (unlikely(!data
)) {
368 bufsize
= PAGE_SIZE
< nbytes
? PAGE_SIZE
: nbytes
;
372 if (ses_ptr
->hdata
.init
!= 0) {
373 ret
= cryptodev_hash_reset(&ses_ptr
->hdata
);
376 "error in cryptodev_hash_reset()\n");
381 if (ses_ptr
->cdata
.init
!= 0) {
382 int blocksize
= ses_ptr
->cdata
.blocksize
;
384 if (unlikely(nbytes
% blocksize
)) {
386 "data size (%zu) isn't a multiple of block size (%u)\n",
392 ivsize
= ses_ptr
->cdata
.ivsize
;
395 cryptodev_cipher_set_iv(&ses_ptr
->cdata
, cop
->iv
, ivsize
);
404 size_t current_len
= nbytes
> bufsize
? bufsize
: nbytes
;
406 copy_from_user(data
, src
, current_len
);
408 sg_init_one(&sg
, data
, current_len
);
410 /* Always hash before encryption and after decryption. Maybe
411 * we should introduce a flag to switch... TBD later on.
413 if (cop
->op
== COP_ENCRYPT
) {
414 if (ses_ptr
->hdata
.init
!= 0) {
415 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
417 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
421 if (ses_ptr
->cdata
.init
!= 0) {
422 ret
= cryptodev_cipher_encrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
425 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
428 copy_to_user(dst
, data
, current_len
);
432 if (ses_ptr
->cdata
.init
!= 0) {
433 ret
= cryptodev_cipher_decrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
436 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
439 copy_to_user(dst
, data
, current_len
);
444 if (ses_ptr
->hdata
.init
!= 0) {
445 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
447 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
453 nbytes
-= current_len
;
457 if (ses_ptr
->hdata
.init
!= 0) {
458 ret
= cryptodev_hash_final(&ses_ptr
->hdata
, hash_output
);
460 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
464 copy_to_user(cop
->mac
, hash_output
, ses_ptr
->hdata
.digestsize
);
467 #if defined(CRYPTODEV_STATS)
469 /* this is safe - we check cop->op at the function entry */
470 ses_ptr
->stat
[cop
->op
] += cop
->len
;
471 if (ses_ptr
->stat_max_size
< cop
->len
)
472 ses_ptr
->stat_max_size
= cop
->len
;
473 ses_ptr
->stat_count
++;
478 free_page((unsigned long)data
);
486 /* ====== /dev/crypto ====== */
489 cryptodev_open(struct inode
*inode
, struct file
*filp
)
493 fcr
= kmalloc(sizeof(*fcr
), GFP_KERNEL
);
497 memset(fcr
, 0, sizeof(*fcr
));
498 init_MUTEX(&fcr
->sem
);
499 INIT_LIST_HEAD(&fcr
->list
);
500 filp
->private_data
= fcr
;
506 cryptodev_release(struct inode
*inode
, struct file
*filp
)
508 struct fcrypt
*fcr
= filp
->private_data
;
511 crypto_finish_all_sessions(fcr
);
513 filp
->private_data
= NULL
;
520 clonefd(struct file
*filp
)
522 struct fdtable
*fdt
= files_fdtable(current
->files
);
524 ret
= get_unused_fd();
527 FD_SET(ret
, fdt
->open_fds
);
528 fd_install(ret
, filp
);
535 cryptodev_ioctl(struct inode
*inode
, struct file
*filp
,
536 unsigned int cmd
, unsigned long arg
)
538 int __user
*p
= (void __user
*)arg
;
539 struct session_op sop
;
541 struct fcrypt
*fcr
= filp
->private_data
;
558 copy_from_user(&sop
, (void*)arg
, sizeof(sop
));
559 ret
= crypto_create_session(fcr
, &sop
);
562 copy_to_user((void*)arg
, &sop
, sizeof(sop
));
566 get_user(ses
, (uint32_t*)arg
);
567 ret
= crypto_finish_session(fcr
, ses
);
571 copy_from_user(&cop
, (void*)arg
, sizeof(cop
));
572 ret
= crypto_run(fcr
, &cop
);
573 copy_to_user((void*)arg
, &cop
, sizeof(cop
));
581 struct file_operations cryptodev_fops
= {
582 .owner
= THIS_MODULE
,
583 .open
= cryptodev_open
,
584 .release
= cryptodev_release
,
585 .ioctl
= cryptodev_ioctl
,
588 struct miscdevice cryptodev
= {
589 .minor
= MISC_DYNAMIC_MINOR
,
591 .fops
= &cryptodev_fops
,
595 cryptodev_register(void)
599 rc
= misc_register (&cryptodev
);
601 printk(KERN_ERR PFX
"registeration of /dev/crypto failed\n");
609 cryptodev_deregister(void)
611 misc_deregister(&cryptodev
);
614 /* ====== Module init/exit ====== */
616 int __init
init_cryptodev(void)
620 rc
= cryptodev_register();
624 printk(KERN_INFO PFX
"driver loaded.\n");
629 void __exit
exit_cryptodev(void)
631 cryptodev_deregister();
632 printk(KERN_INFO PFX
"driver unloaded.\n");
635 module_init(init_cryptodev
);
636 module_exit(exit_cryptodev
);