2 * Driver for /dev/crypto device (aka CryptoDev)
4 * Copyright (c) 2010 Nikos Mavrogiannopoulos <nmav@gnutls.org>
5 * Portions Copyright (c) 2010 Michael Weiser
6 * Portions Copyright (c) 2010 Phil Sutter
8 * This file is part of linux cryptodev.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <linux/crypto.h>
28 #include <linux/highmem.h>
29 #include <linux/ioctl.h>
30 #include <linux/random.h>
31 #include <linux/scatterlist.h>
32 #include <linux/uaccess.h>
33 #include <crypto/algapi.h>
34 #include <crypto/hash.h>
35 #include "cryptodev.h"
36 #include "cryptodev_int.h"
39 struct cryptodev_result
{
40 struct completion completion
;
44 static void cryptodev_complete(struct crypto_async_request
*req
, int err
)
46 struct cryptodev_result
*res
= req
->data
;
48 if (err
== -EINPROGRESS
)
52 complete(&res
->completion
);
55 int cryptodev_cipher_init(struct cipher_data
*out
, const char *alg_name
,
56 uint8_t *keyp
, size_t keylen
)
58 struct ablkcipher_alg
*alg
;
61 memset(out
, 0, sizeof(*out
));
63 out
->async
.s
= crypto_alloc_ablkcipher(alg_name
, 0, 0);
64 if (unlikely(IS_ERR(out
->async
.s
))) {
65 dprintk(1, KERN_DEBUG
, "%s: Failed to load cipher %s\n",
70 alg
= crypto_ablkcipher_alg(out
->async
.s
);
73 /* Was correct key length supplied? */
74 if (alg
->max_keysize
> 0 &&
75 unlikely((keylen
< alg
->min_keysize
) ||
76 (keylen
> alg
->max_keysize
))) {
77 dprintk(1, KERN_DEBUG
,
78 "Wrong keylen '%zu' for algorithm '%s'. \
80 keylen
, alg_name
, alg
->min_keysize
,
87 ret
= crypto_ablkcipher_setkey(out
->async
.s
, keyp
, keylen
);
89 dprintk(1, KERN_DEBUG
, "Setting key failed for %s-%zu.\n",
95 out
->blocksize
= crypto_ablkcipher_blocksize(out
->async
.s
);
96 out
->ivsize
= crypto_ablkcipher_ivsize(out
->async
.s
);
98 out
->async
.result
= kmalloc(sizeof(*out
->async
.result
), GFP_KERNEL
);
99 if (unlikely(!out
->async
.result
)) {
104 memset(out
->async
.result
, 0, sizeof(*out
->async
.result
));
105 init_completion(&out
->async
.result
->completion
);
107 out
->async
.request
= ablkcipher_request_alloc(out
->async
.s
, GFP_KERNEL
);
108 if (unlikely(!out
->async
.request
)) {
109 dprintk(1, KERN_ERR
, "error allocating async crypto request\n");
114 ablkcipher_request_set_callback(out
->async
.request
,
115 CRYPTO_TFM_REQ_MAY_BACKLOG
,
116 cryptodev_complete
, out
->async
.result
);
121 if (out
->async
.request
)
122 ablkcipher_request_free(out
->async
.request
);
123 kfree(out
->async
.result
);
125 crypto_free_ablkcipher(out
->async
.s
);
130 void cryptodev_cipher_deinit(struct cipher_data
*cdata
)
133 if (cdata
->async
.request
)
134 ablkcipher_request_free(cdata
->async
.request
);
135 kfree(cdata
->async
.result
);
137 crypto_free_ablkcipher(cdata
->async
.s
);
143 void cryptodev_cipher_set_iv(struct cipher_data
*cdata
,
144 void *iv
, size_t iv_size
)
146 memcpy(cdata
->async
.iv
, iv
, min(iv_size
, sizeof(cdata
->async
.iv
)));
149 static inline int waitfor(struct cryptodev_result
*cr
, ssize_t ret
)
156 wait_for_completion(&cr
->completion
);
157 /* At this point we known for sure the request has finished,
158 * because wait_for_completion above was not interruptible.
159 * This is important because otherwise hardware or driver
160 * might try to access memory which will be freed or reused for
161 * another request. */
163 if (unlikely(cr
->err
)) {
164 dprintk(0, KERN_ERR
, "error from async request: %d\n",
177 ssize_t
cryptodev_cipher_encrypt(struct cipher_data
*cdata
,
178 const struct scatterlist
*sg1
, struct scatterlist
*sg2
,
183 INIT_COMPLETION(cdata
->async
.result
->completion
);
184 ablkcipher_request_set_crypt(cdata
->async
.request
,
185 (struct scatterlist
*)sg1
, sg2
,
186 len
, cdata
->async
.iv
);
187 ret
= crypto_ablkcipher_encrypt(cdata
->async
.request
);
189 return waitfor(cdata
->async
.result
, ret
);
192 ssize_t
cryptodev_cipher_decrypt(struct cipher_data
*cdata
,
193 const struct scatterlist
*sg1
, struct scatterlist
*sg2
,
198 INIT_COMPLETION(cdata
->async
.result
->completion
);
199 ablkcipher_request_set_crypt(cdata
->async
.request
,
200 (struct scatterlist
*)sg1
, sg2
,
201 len
, cdata
->async
.iv
);
202 ret
= crypto_ablkcipher_decrypt(cdata
->async
.request
);
204 return waitfor(cdata
->async
.result
, ret
);
209 int cryptodev_hash_init(struct hash_data
*hdata
, const char *alg_name
,
210 int hmac_mode
, void *mackey
, size_t mackeylen
)
214 hdata
->async
.s
= crypto_alloc_ahash(alg_name
, 0, 0);
215 if (unlikely(IS_ERR(hdata
->async
.s
))) {
216 dprintk(1, KERN_DEBUG
, "%s: Failed to load transform for %s\n",
221 /* Copy the key from user and set to TFM. */
222 if (hmac_mode
!= 0) {
223 ret
= crypto_ahash_setkey(hdata
->async
.s
, mackey
, mackeylen
);
225 dprintk(1, KERN_DEBUG
,
226 "Setting hmac key failed for %s-%zu.\n",
227 alg_name
, mackeylen
*8);
233 hdata
->digestsize
= crypto_ahash_digestsize(hdata
->async
.s
);
235 hdata
->async
.result
= kmalloc(sizeof(*hdata
->async
.result
), GFP_KERNEL
);
236 if (unlikely(!hdata
->async
.result
)) {
241 memset(hdata
->async
.result
, 0, sizeof(*hdata
->async
.result
));
242 init_completion(&hdata
->async
.result
->completion
);
244 hdata
->async
.request
= ahash_request_alloc(hdata
->async
.s
, GFP_KERNEL
);
245 if (unlikely(!hdata
->async
.request
)) {
246 dprintk(0, KERN_ERR
, "error allocating async crypto request\n");
251 ahash_request_set_callback(hdata
->async
.request
,
252 CRYPTO_TFM_REQ_MAY_BACKLOG
,
253 cryptodev_complete
, hdata
->async
.result
);
255 ret
= crypto_ahash_init(hdata
->async
.request
);
257 dprintk(0, KERN_ERR
, "error in crypto_hash_init()\n");
265 ahash_request_free(hdata
->async
.request
);
267 kfree(hdata
->async
.result
);
268 crypto_free_ahash(hdata
->async
.s
);
272 void cryptodev_hash_deinit(struct hash_data
*hdata
)
275 if (hdata
->async
.request
)
276 ahash_request_free(hdata
->async
.request
);
277 kfree(hdata
->async
.result
);
279 crypto_free_ahash(hdata
->async
.s
);
284 int cryptodev_hash_reset(struct hash_data
*hdata
)
288 ret
= crypto_ahash_init(hdata
->async
.request
);
290 dprintk(0, KERN_ERR
, "error in crypto_hash_init()\n");
298 ssize_t
cryptodev_hash_update(struct hash_data
*hdata
,
299 struct scatterlist
*sg
, size_t len
)
303 INIT_COMPLETION(hdata
->async
.result
->completion
);
304 ahash_request_set_crypt(hdata
->async
.request
, sg
, NULL
, len
);
306 ret
= crypto_ahash_update(hdata
->async
.request
);
308 return waitfor(hdata
->async
.result
, ret
);
311 int cryptodev_hash_final(struct hash_data
*hdata
, void* output
)
315 INIT_COMPLETION(hdata
->async
.result
->completion
);
316 ahash_request_set_crypt(hdata
->async
.request
, NULL
, output
, 0);
318 ret
= crypto_ahash_final(hdata
->async
.request
);
320 return waitfor(hdata
->async
.result
, ret
);