summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto/aead.c58
-rw-r--r--include/crypto/aead.h35
2 files changed, 85 insertions, 8 deletions
diff --git a/crypto/aead.c b/crypto/aead.c
index 717b2f6ec9bb..c2bf3b313354 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -13,6 +13,7 @@
*/
#include <crypto/internal/aead.h>
+#include <crypto/scatterwalk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -85,6 +86,59 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
}
EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
+struct aead_old_request {
+ struct scatterlist srcbuf[2];
+ struct scatterlist dstbuf[2];
+ struct aead_request subreq;
+};
+
+unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
+{
+ return tfm->reqsize + sizeof(struct aead_old_request);
+}
+EXPORT_SYMBOL_GPL(crypto_aead_reqsize);
+
+static int old_crypt(struct aead_request *req,
+ int (*crypt)(struct aead_request *req))
+{
+ struct aead_old_request *nreq = aead_request_ctx(req);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct scatterlist *src, *dst;
+
+ if (req->old)
+ return crypt(req);
+
+ src = scatterwalk_ffwd(nreq->srcbuf, req->src,
+ req->assoclen + req->cryptoff);
+ dst = scatterwalk_ffwd(nreq->dstbuf, req->dst,
+ req->assoclen + req->cryptoff);
+
+ aead_request_set_tfm(&nreq->subreq, aead);
+ aead_request_set_callback(&nreq->subreq, aead_request_flags(req),
+ req->base.complete, req->base.data);
+ aead_request_set_crypt(&nreq->subreq, src, dst, req->cryptlen,
+ req->iv);
+ aead_request_set_assoc(&nreq->subreq, req->src, req->assoclen);
+
+ return crypt(&nreq->subreq);
+}
+
+static int old_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct aead_alg *alg = crypto_aead_alg(aead);
+
+ return old_crypt(req, alg->encrypt);
+}
+
+static int old_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct aead_alg *alg = crypto_aead_alg(aead);
+
+ return old_crypt(req, alg->decrypt);
+}
+
static int no_givcrypt(struct aead_givcrypt_request *req)
{
return -ENOSYS;
@@ -98,8 +152,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
return -EINVAL;
- crt->encrypt = alg->encrypt;
- crt->decrypt = alg->decrypt;
+ crt->encrypt = old_encrypt;
+ crt->decrypt = old_decrypt;
if (alg->ivsize) {
crt->givencrypt = alg->givencrypt ?: no_givcrypt;
crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
index dbcad08f4891..e2d2c3c62e68 100644
--- a/include/crypto/aead.h
+++ b/include/crypto/aead.h
@@ -52,6 +52,7 @@
* @base: Common attributes for async crypto requests
* @assoclen: Length in bytes of associated data for authentication
* @cryptlen: Length of data to be encrypted or decrypted
+ * @cryptoff: Bytes to skip after AD before plain/cipher text
* @iv: Initialisation vector
* @assoc: Associated data
* @src: Source data
@@ -61,8 +62,11 @@
struct aead_request {
struct crypto_async_request base;
+ bool old;
+
unsigned int assoclen;
unsigned int cryptlen;
+ unsigned int cryptoff;
u8 *iv;
@@ -314,10 +318,7 @@ static inline int crypto_aead_decrypt(struct aead_request *req)
*
* Return: number of bytes
*/
-static inline unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
-{
- return tfm->reqsize;
-}
+unsigned int crypto_aead_reqsize(struct crypto_aead *tfm);
/**
* aead_request_set_tfm() - update cipher handle reference in request
@@ -417,6 +418,9 @@ static inline void aead_request_set_callback(struct aead_request *req,
* destination is the ciphertext. For a decryption operation, the use is
* reversed - the source is the ciphertext and the destination is the plaintext.
*
+ * For both src/dst the layout is associated data, skipped data,
+ * plain/cipher text, authentication tag.
+ *
* IMPORTANT NOTE AEAD requires an authentication tag (MAC). For decryption,
* the caller must concatenate the ciphertext followed by the
* authentication tag and provide the entire data stream to the
@@ -449,8 +453,7 @@ static inline void aead_request_set_crypt(struct aead_request *req,
* @assoc: associated data scatter / gather list
* @assoclen: number of bytes to process from @assoc
*
- * For encryption, the memory is filled with the associated data. For
- * decryption, the memory must point to the associated data.
+ * Obsolete, do not use.
*/
static inline void aead_request_set_assoc(struct aead_request *req,
struct scatterlist *assoc,
@@ -458,6 +461,26 @@ static inline void aead_request_set_assoc(struct aead_request *req,
{
req->assoc = assoc;
req->assoclen = assoclen;
+ req->old = true;
+}
+
+/**
+ * aead_request_set_ad - set associated data information
+ * @req: request handle
+ * @assoclen: number of bytes in associated data
+ * @cryptoff: Number of bytes to skip after AD before plain/cipher text
+ *
+ * Setting the AD information. This function sets the length of
+ * the associated data and the number of bytes to skip after it to
+ * access the plain/cipher text.
+ */
+static inline void aead_request_set_ad(struct aead_request *req,
+ unsigned int assoclen,
+ unsigned int cryptoff)
+{
+ req->assoclen = assoclen;
+ req->cryptoff = cryptoff;
+ req->old = false;
}
static inline struct crypto_aead *aead_givcrypt_reqtfm(