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"
43 MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>");
44 MODULE_DESCRIPTION("CryptoDev driver");
45 MODULE_LICENSE("GPL");
47 /* ====== Compile-time config ====== */
49 #define CRYPTODEV_STATS
51 /* ====== Module parameters ====== */
53 int cryptodev_verbosity
= 0;
54 module_param(cryptodev_verbosity
, int, 0644);
55 MODULE_PARM_DESC(cryptodev_verbosity
, "0: normal, 1: verbose, 2: debug");
57 #ifdef CRYPTODEV_STATS
58 static int enable_stats
= 0;
59 module_param(enable_stats
, int, 0644);
60 MODULE_PARM_DESC(enable_stats
, "collect statictics about cryptodev usage");
63 /* ====== CryptoAPI ====== */
65 #define FILL_SG(sg,ptr,len) \
67 (sg)->page = virt_to_page(ptr); \
68 (sg)->offset = offset_in_page(ptr); \
70 (sg)->dma_address = 0; \
74 struct list_head entry
;
76 struct cipher_data cdata
;
77 struct hash_data hdata
;
79 #ifdef CRYPTODEV_STATS
80 #if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2))
81 #error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something!
83 unsigned long long stat
[2];
84 size_t stat_max_size
, stat_count
;
89 struct list_head list
;
93 /* Prepare session for future use. */
95 crypto_create_session(struct fcrypt
*fcr
, struct session_op
*sop
)
97 struct csession
*ses_new
, *ses_ptr
;
99 const char *alg_name
=NULL
;
100 const char *hash_name
=NULL
;
103 /* Does the request make sense? */
104 if (unlikely(!sop
->cipher
&& !sop
->mac
)) {
105 dprintk(1,KERN_DEBUG
,"Both 'cipher' and 'mac' unset.\n");
109 switch (sop
->cipher
) {
113 alg_name
= "cbc(des)";
115 case CRYPTO_3DES_CBC
:
116 alg_name
= "cbc(des3_ede)";
119 alg_name
= "cbc(blowfish)";
122 alg_name
= "cbc(aes)";
124 case CRYPTO_CAMELLIA_CBC
:
125 alg_name
= "cbc(camelia)";
128 dprintk(1,KERN_DEBUG
,"%s: bad cipher: %d\n", __func__
, sop
->cipher
);
135 case CRYPTO_MD5_HMAC
:
136 hash_name
= "hmac(md5)";
138 case CRYPTO_RIPEMD160_HMAC
:
139 hash_name
= "hmac(rmd160)";
141 case CRYPTO_SHA1_HMAC
:
142 hash_name
= "hmac(sha1)";
144 case CRYPTO_SHA2_256_HMAC
:
145 hash_name
= "hmac(sha256)";
147 case CRYPTO_SHA2_384_HMAC
:
148 hash_name
= "hmac(sha384)";
150 case CRYPTO_SHA2_512_HMAC
:
151 hash_name
= "hmac(sha512)";
159 case CRYPTO_RIPEMD160
:
160 hash_name
= "rmd160";
167 case CRYPTO_SHA2_256
:
168 hash_name
= "sha256";
171 case CRYPTO_SHA2_384
:
172 hash_name
= "sha384";
175 case CRYPTO_SHA2_512
:
176 hash_name
= "sha512";
181 dprintk(1,KERN_DEBUG
,"%s: bad mac: %d\n", __func__
, sop
->mac
);
185 /* Create a session and put it to the list. */
186 ses_new
= kmalloc(sizeof(*ses_new
), GFP_KERNEL
);
192 memset(ses_new
, 0, sizeof(*ses_new
));
194 /* Set-up crypto transform. */
197 ret
= cryptodev_cipher_init(&ses_new
->cdata
, alg_name
, sop
->key
, sop
->keylen
);
204 ret
= cryptodev_hash_init(&ses_new
->hdata
, hash_name
, hmac_mode
, sop
->mackey
, sop
->mackeylen
);
206 dprintk(1,KERN_DEBUG
,"%s: Failed to load transform for %s\n", __func__
,
212 /* put the new session to the list */
213 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
214 init_MUTEX(&ses_new
->sem
);
218 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
219 /* Check for duplicate SID */
220 if (unlikely(ses_new
->sid
== ses_ptr
->sid
)) {
221 get_random_bytes(&ses_new
->sid
, sizeof(ses_new
->sid
));
222 /* Unless we have a broken RNG this
223 shouldn't loop forever... ;-) */
228 list_add(&ses_new
->entry
, &fcr
->list
);
231 /* Fill in some values for the user. */
232 sop
->ses
= ses_new
->sid
;
237 cryptodev_cipher_deinit( &ses_new
->cdata
);
238 cryptodev_hash_deinit( &ses_new
->hdata
);
244 /* Everything that needs to be done when remowing a session. */
246 crypto_destroy_session(struct csession
*ses_ptr
)
248 if(down_trylock(&ses_ptr
->sem
)) {
249 dprintk(2, KERN_DEBUG
, "Waiting for semaphore of sid=0x%08X\n",
253 dprintk(2, KERN_DEBUG
, "Removed session 0x%08X\n", ses_ptr
->sid
);
254 #if defined(CRYPTODEV_STATS)
256 dprintk(2, KERN_DEBUG
,
257 "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
258 ses_ptr
->stat
[COP_ENCRYPT
], ses_ptr
->stat
[COP_DECRYPT
],
259 ses_ptr
->stat_max_size
, ses_ptr
->stat_count
> 0
260 ? ((unsigned long)(ses_ptr
->stat
[COP_ENCRYPT
]+
261 ses_ptr
->stat
[COP_DECRYPT
]) /
262 ses_ptr
->stat_count
) : 0,
263 ses_ptr
->stat_count
);
265 cryptodev_cipher_deinit(&ses_ptr
->cdata
);
266 cryptodev_hash_deinit(&ses_ptr
->hdata
);
271 /* Look up a session by ID and remove. */
273 crypto_finish_session(struct fcrypt
*fcr
, uint32_t sid
)
275 struct csession
*tmp
, *ses_ptr
;
276 struct list_head
*head
;
281 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
282 if(ses_ptr
->sid
== sid
) {
283 list_del(&ses_ptr
->entry
);
284 crypto_destroy_session(ses_ptr
);
289 if (unlikely(!ses_ptr
)) {
290 dprintk(1, KERN_ERR
, "Session with sid=0x%08X not found!\n", sid
);
298 /* Remove all sessions when closing the file */
300 crypto_finish_all_sessions(struct fcrypt
*fcr
)
302 struct csession
*tmp
, *ses_ptr
;
303 struct list_head
*head
;
308 list_for_each_entry_safe(ses_ptr
, tmp
, head
, entry
) {
309 list_del(&ses_ptr
->entry
);
310 crypto_destroy_session(ses_ptr
);
317 /* Look up session by session ID. The returned session is locked. */
318 static struct csession
*
319 crypto_get_session_by_sid(struct fcrypt
*fcr
, uint32_t sid
)
321 struct csession
*ses_ptr
;
324 list_for_each_entry(ses_ptr
, &fcr
->list
, entry
) {
325 if(ses_ptr
->sid
== sid
) {
335 /* This is the main crypto function - feed it with plaintext
336 and get a ciphertext (or vice versa :-) */
338 crypto_run(struct fcrypt
*fcr
, struct crypt_op
*cop
)
341 char __user
*src
, __user
*dst
;
342 struct scatterlist sg
;
343 struct csession
*ses_ptr
;
344 unsigned int ivsize
=0;
345 size_t nbytes
, bufsize
;
347 uint8_t hash_output
[AALG_MAX_RESULT_LEN
];
349 if (unlikely(cop
->op
!= COP_ENCRYPT
&& cop
->op
!= COP_DECRYPT
)) {
350 dprintk(1, KERN_DEBUG
, "invalid operation op=%u\n", cop
->op
);
354 ses_ptr
= crypto_get_session_by_sid(fcr
, cop
->ses
);
355 if (unlikely(!ses_ptr
)) {
356 dprintk(1, KERN_ERR
, "invalid session ID=0x%08X\n", cop
->ses
);
361 data
= (char*)__get_free_page(GFP_KERNEL
);
363 if (unlikely(!data
)) {
367 bufsize
= PAGE_SIZE
< nbytes
? PAGE_SIZE
: nbytes
;
371 if (ses_ptr
->hdata
.init
!= 0) {
372 ret
= cryptodev_hash_reset(&ses_ptr
->hdata
);
375 "error in cryptodev_hash_reset()\n");
380 if (ses_ptr
->cdata
.init
!= 0) {
381 int blocksize
= ses_ptr
->cdata
.blocksize
;
383 if (unlikely(nbytes
% blocksize
)) {
385 "data size (%zu) isn't a multiple of block size (%u)\n",
391 ivsize
= ses_ptr
->cdata
.ivsize
;
394 cryptodev_cipher_set_iv(&ses_ptr
->cdata
, cop
->iv
, ivsize
);
403 size_t current_len
= nbytes
> bufsize
? bufsize
: nbytes
;
405 copy_from_user(data
, src
, current_len
);
407 sg_init_one(&sg
, data
, current_len
);
409 /* Always hash before encryption and after decryption. Maybe
410 * we should introduce a flag to switch... TBD later on.
412 if (cop
->op
== COP_ENCRYPT
) {
413 if (ses_ptr
->hdata
.init
!= 0) {
414 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
416 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
420 if (ses_ptr
->cdata
.init
!= 0) {
421 ret
= cryptodev_cipher_encrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
424 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
427 copy_to_user(dst
, data
, current_len
);
431 if (ses_ptr
->cdata
.init
!= 0) {
432 ret
= cryptodev_cipher_decrypt( &ses_ptr
->cdata
, &sg
, &sg
, current_len
);
435 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
438 copy_to_user(dst
, data
, current_len
);
443 if (ses_ptr
->hdata
.init
!= 0) {
444 ret
= cryptodev_hash_update(&ses_ptr
->hdata
, &sg
, current_len
);
446 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
452 nbytes
-= current_len
;
456 if (ses_ptr
->hdata
.init
!= 0) {
457 ret
= cryptodev_hash_final(&ses_ptr
->hdata
, hash_output
);
459 dprintk(0, KERN_ERR
, "CryptoAPI failure: %d\n",ret
);
463 copy_to_user(cop
->mac
, hash_output
, ses_ptr
->hdata
.digestsize
);
466 #if defined(CRYPTODEV_STATS)
468 /* this is safe - we check cop->op at the function entry */
469 ses_ptr
->stat
[cop
->op
] += cop
->len
;
470 if (ses_ptr
->stat_max_size
< cop
->len
)
471 ses_ptr
->stat_max_size
= cop
->len
;
472 ses_ptr
->stat_count
++;
477 free_page((unsigned long)data
);
485 /* ====== /dev/crypto ====== */
488 cryptodev_open(struct inode
*inode
, struct file
*filp
)
492 fcr
= kmalloc(sizeof(*fcr
), GFP_KERNEL
);
496 memset(fcr
, 0, sizeof(*fcr
));
497 init_MUTEX(&fcr
->sem
);
498 INIT_LIST_HEAD(&fcr
->list
);
499 filp
->private_data
= fcr
;
505 cryptodev_release(struct inode
*inode
, struct file
*filp
)
507 struct fcrypt
*fcr
= filp
->private_data
;
510 crypto_finish_all_sessions(fcr
);
512 filp
->private_data
= NULL
;
519 clonefd(struct file
*filp
)
521 struct fdtable
*fdt
= files_fdtable(current
->files
);
523 ret
= get_unused_fd();
526 FD_SET(ret
, fdt
->open_fds
);
527 fd_install(ret
, filp
);
534 cryptodev_ioctl(struct inode
*inode
, struct file
*filp
,
535 unsigned int cmd
, unsigned long arg
)
537 int __user
*p
= (void __user
*)arg
;
538 struct session_op sop
;
540 struct fcrypt
*fcr
= filp
->private_data
;
557 copy_from_user(&sop
, (void*)arg
, sizeof(sop
));
558 ret
= crypto_create_session(fcr
, &sop
);
561 copy_to_user((void*)arg
, &sop
, sizeof(sop
));
565 get_user(ses
, (uint32_t*)arg
);
566 ret
= crypto_finish_session(fcr
, ses
);
570 copy_from_user(&cop
, (void*)arg
, sizeof(cop
));
571 ret
= crypto_run(fcr
, &cop
);
574 copy_to_user((void*)arg
, &cop
, sizeof(cop
));
582 struct file_operations cryptodev_fops
= {
583 .owner
= THIS_MODULE
,
584 .open
= cryptodev_open
,
585 .release
= cryptodev_release
,
586 .ioctl
= cryptodev_ioctl
,
589 struct miscdevice cryptodev
= {
590 .minor
= MISC_DYNAMIC_MINOR
,
592 .fops
= &cryptodev_fops
,
596 cryptodev_register(void)
600 rc
= misc_register (&cryptodev
);
602 printk(KERN_ERR PFX
"registeration of /dev/crypto failed\n");
610 cryptodev_deregister(void)
612 misc_deregister(&cryptodev
);
615 /* ====== Module init/exit ====== */
617 int __init
init_cryptodev(void)
621 rc
= cryptodev_register();
625 printk(KERN_INFO PFX
"driver loaded.\n");
630 void __exit
exit_cryptodev(void)
632 cryptodev_deregister();
633 printk(KERN_INFO PFX
"driver unloaded.\n");
636 module_init(init_cryptodev
);
637 module_exit(exit_cryptodev
);