[PATCH 18/19] [CRYPTO] gcm: Add givcrypt operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[CRYPTO] gcm: Add givcrypt operations
    
This patch implements the givcrypt functions for gcm.  It simply calls
the givcrypt operations on the underlying cipher instead of encrypt or
decrypt.
    
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
---

 crypto/gcm.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/crypto/gcm.c b/crypto/gcm.c
index 1fdefe5..7775ea0 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -8,6 +8,7 @@
  * by the Free Software Foundation.
  */
 
+#include <crypto/aead.h>
 #include <crypto/ctr.h>
 #include <crypto/gf128mul.h>
 #include <crypto/internal/skcipher.h>
@@ -41,7 +42,7 @@ struct crypto_gcm_req_priv_ctx {
 	u8 auth_tag[16];
 	u8 iauth_tag[16];
 	struct crypto_gcm_ghash_ctx ghash;
-	struct ablkcipher_request abreq;
+	struct skcipher_givcrypt_request greq;
 };
 
 static void crypto_gcm_ghash_init(struct crypto_gcm_ghash_ctx *ctx, u32 flags,
@@ -271,15 +272,21 @@ static void crypto_gcm_encrypt_done(struct crypto_async_request *areq, int err)
 	aead_request_complete(req, err);
 }
 
+static void crypto_gcm_init_encrypt(struct ablkcipher_request *abreq,
+				    struct aead_request *req)
+{
+	crypto_gcm_init_crypt(abreq, req, req->cryptlen);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					crypto_gcm_encrypt_done, req);
+}
+
 static int crypto_gcm_encrypt(struct aead_request *req)
 {
 	struct crypto_gcm_req_priv_ctx *pctx = aead_request_ctx(req);
-	struct ablkcipher_request *abreq = &pctx->abreq;
+	struct ablkcipher_request *abreq = &pctx->greq.creq;
 	int err;
 
-	crypto_gcm_init_crypt(abreq, req, req->cryptlen);
-	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-					crypto_gcm_encrypt_done, req);
+	crypto_gcm_init_encrypt(abreq, req);
 
 	err = crypto_ablkcipher_encrypt(abreq);
 	if (err)
@@ -288,6 +295,24 @@ static int crypto_gcm_encrypt(struct aead_request *req)
 	return crypto_gcm_hash(req);
 }
 
+static int crypto_gcm_givencrypt(struct aead_givcrypt_request *req)
+{
+	struct aead_request *areq = &req->areq;
+	struct crypto_gcm_req_priv_ctx *pctx = aead_request_ctx(areq);
+	struct skcipher_givcrypt_request *greq = &pctx->greq;
+	struct ablkcipher_request *abreq = &greq->creq;
+	int err;
+
+	crypto_gcm_init_encrypt(abreq, areq);
+	skcipher_givcrypt_set_giv(greq, req->giv, req->seq);
+
+	err = crypto_skcipher_givencrypt(greq);
+	if (err)
+		return err;
+
+	return crypto_gcm_hash(areq);
+}
+
 static int crypto_gcm_verify(struct aead_request *req)
 {
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
@@ -315,15 +340,14 @@ static void crypto_gcm_decrypt_done(struct crypto_async_request *areq, int err)
 	aead_request_complete(req, err);
 }
 
-static int crypto_gcm_decrypt(struct aead_request *req)
+static int crypto_gcm_init_decrypt(struct ablkcipher_request *abreq,
+				   struct aead_request *req)
 {
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct crypto_gcm_req_priv_ctx *pctx = aead_request_ctx(req);
-	struct ablkcipher_request *abreq = &pctx->abreq;
 	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
 	unsigned int cryptlen = req->cryptlen;
 	unsigned int authsize = crypto_aead_authsize(aead);
-	int err;
 
 	if (cryptlen < authsize)
 		return -EINVAL;
@@ -334,6 +358,18 @@ static int crypto_gcm_decrypt(struct aead_request *req)
 					crypto_gcm_decrypt_done, req);
 
 	crypto_gcm_ghash_update_sg(ghash, req->src, cryptlen);
+	return 0;
+}
+
+static int crypto_gcm_decrypt(struct aead_request *req)
+{
+	struct crypto_gcm_req_priv_ctx *pctx = aead_request_ctx(req);
+	struct ablkcipher_request *abreq = &pctx->greq.creq;
+	int err;
+
+	err = crypto_gcm_init_decrypt(abreq, req);
+	if (err)
+		return err;
 
 	err = crypto_ablkcipher_decrypt(abreq);
 	if (err)
@@ -342,6 +378,27 @@ static int crypto_gcm_decrypt(struct aead_request *req)
 	return crypto_gcm_verify(req);
 }
 
+static int crypto_gcm_givdecrypt(struct aead_givcrypt_request *req)
+{
+	struct aead_request *areq = &req->areq;
+	struct crypto_gcm_req_priv_ctx *pctx = aead_request_ctx(areq);
+	struct skcipher_givcrypt_request *greq = &pctx->greq;
+	struct ablkcipher_request *abreq = &greq->creq;
+	int err;
+
+	err = crypto_gcm_init_decrypt(abreq, areq);
+	if (err)
+		return err;
+
+	skcipher_givcrypt_set_giv(greq, req->giv, req->seq);
+
+	err = crypto_skcipher_givdecrypt(greq);
+	if (err)
+		return err;
+
+	return crypto_gcm_verify(areq);
+}
+
 static int crypto_gcm_init_tfm(struct crypto_tfm *tfm)
 {
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
@@ -440,6 +497,8 @@ static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
 	inst->alg.cra_aead.setkey = crypto_gcm_setkey;
 	inst->alg.cra_aead.encrypt = crypto_gcm_encrypt;
 	inst->alg.cra_aead.decrypt = crypto_gcm_decrypt;
+	inst->alg.cra_aead.givencrypt = crypto_gcm_givencrypt;
+	inst->alg.cra_aead.givdecrypt = crypto_gcm_givdecrypt;
 
 out:
 	return inst;
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux