1 From 8cabaedb69acc5b44c7a9cf058045908130a6af7 Mon Sep 17 00:00:00 2001
2 From: Cristian Stoica <cristian.stoica@freescale.com>
3 Date: Wed, 23 Oct 2013 16:57:22 +0300
4 Subject: [[Patch][fsl 03/16] Add support for aead keys for composite
7 Upstream-status: Pending
9 Composite aead algorithms (e.g. AES-CBC + HMAC-SHA1) need two keys to
10 operate. The two keys are wrapped in a single buffer in the form
11 used also by crypto/authenc.c
12 Blockcipher and non-composite aead algorithms (e.g. AES-GCM) use a
13 single key which is simply copied from user-space.
15 Signed-off-by: Cristian Stoica <cristian.stoica@freescale.com>
16 Tested-by: Horia Ioan Geanta Neag <horia.geanta@freescale.com>
18 cryptlib.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 ioctl.c | 24 ++++++++++++++----------
21 3 files changed, 76 insertions(+), 10 deletions(-)
23 diff --git a/cryptlib.c b/cryptlib.c
24 index a7fbff4..2986d09 100644
28 #include <crypto/hash.h>
29 #include <crypto/cryptodev.h>
30 #include <crypto/aead.h>
31 +#include <linux/rtnetlink.h>
32 +#include <crypto/authenc.h>
33 #include "cryptodev_int.h"
36 @@ -53,6 +55,63 @@ static void cryptodev_complete(struct crypto_async_request *req, int err)
37 complete(&res->completion);
40 +int cryptodev_get_cipher_keylen(unsigned int *keylen, struct session_op *sop,
43 + unsigned int klen = sop->keylen;
45 + if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN))
48 + if (aead && sop->mackeylen) {
49 + if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN))
51 + klen += sop->mackeylen;
52 + klen += RTA_SPACE(sizeof(struct crypto_authenc_key_param));
59 +int cryptodev_get_cipher_key(uint8_t *key, struct session_op *sop, int aead)
61 + /* Get algorithm key from user-space. For composite aead algorithms,
62 + * the key representation is in the format used by linux kernel in
65 + struct crypto_authenc_key_param *param;
69 + if (aead && sop->mackeylen) {
70 + /* the key header type and header length */
72 + rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
73 + rta->rta_len = RTA_LENGTH(sizeof(*param));
75 + /* the key parameter is the length of the encryption key */
76 + param = RTA_DATA(rta);
77 + param->enckeylen = cpu_to_be32(sop->keylen);
79 + /* copy the hash key */
80 + key += RTA_SPACE(sizeof(*param));
81 + if (unlikely(copy_from_user(key, sop->mackey, sop->mackeylen))) {
85 + /* get the pointer ready for the encryption key */
86 + key += sop->mackeylen;
88 + /* blockcipher algorithms have the key ready to use */
89 + if (unlikely(copy_from_user(key, sop->key, sop->keylen)))
97 int cryptodev_cipher_init(struct cipher_data *out, const char *alg_name,
98 uint8_t *keyp, size_t keylen, int stream, int aead)
100 diff --git a/cryptlib.h b/cryptlib.h
101 index 0744284..a0a8a63 100644
104 @@ -25,6 +25,9 @@ struct cipher_data {
105 int cryptodev_cipher_init(struct cipher_data *out, const char *alg_name,
106 uint8_t *key, size_t keylen, int stream, int aead);
107 void cryptodev_cipher_deinit(struct cipher_data *cdata);
108 +int cryptodev_get_cipher_key(uint8_t *key, struct session_op *sop, int aead);
109 +int cryptodev_get_cipher_keylen(unsigned int *keylen, struct session_op *sop,
111 ssize_t cryptodev_cipher_decrypt(struct cipher_data *cdata,
112 const struct scatterlist *sg1,
113 struct scatterlist *sg2, size_t len);
114 diff --git a/ioctl.c b/ioctl.c
115 index c614373..3baf195 100644
118 @@ -109,7 +109,8 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
119 const char *alg_name = NULL;
120 const char *hash_name = NULL;
121 int hmac_mode = 1, stream = 0, aead = 0;
122 - uint8_t enckey[CRYPTO_CIPHER_MAX_KEY_LEN];
123 + uint8_t *key = NULL;
124 + unsigned int keylen;
125 uint8_t mackey[CRYPTO_HMAC_MAX_KEY_LEN];
127 /* Does the request make sense? */
128 @@ -229,20 +230,22 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
130 /* Set-up crypto transform. */
132 - if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN)) {
133 - ddebug(1, "Setting key failed for %s-%zu.",
134 - alg_name, (size_t)sop->keylen*8);
136 + ret = cryptodev_get_cipher_keylen(&keylen, sop, aead);
137 + if (unlikely(ret < 0))
141 - if (unlikely(copy_from_user(enckey, sop->key, sop->keylen))) {
143 + key = kmalloc(keylen, GFP_KERNEL);
144 + if (unlikely(!key)) {
149 - ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, enckey,
150 - sop->keylen, stream, aead);
151 + ret = cryptodev_get_cipher_key(key, sop, aead);
152 + if (unlikely(ret < 0))
155 + ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, key, keylen,
158 ddebug(1, "Failed to load cipher for %s", alg_name);
160 @@ -318,6 +321,7 @@ error_hash:
162 kfree(ses_new->pages);