]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
crypto: ccp - Add support for valid authsize values less than 16
authorGary R Hook <gary.hook@amd.com>
Tue, 30 Jul 2019 16:05:24 +0000 (16:05 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Aug 2019 08:10:51 +0000 (10:10 +0200)
commit 9f00baf74e4b6f79a3a3dfab44fb7bb2e797b551 upstream.

AES GCM encryption allows for authsize values of 4, 8, and 12-16 bytes.
Validate the requested authsize, and retain it to save in the request
context.

Fixes: 36cf515b9bbe2 ("crypto: ccp - Enable support for AES GCM on v5 CCPs")
Cc: <stable@vger.kernel.org>
Signed-off-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/crypto/ccp/ccp-crypto-aes-galois.c
drivers/crypto/ccp/ccp-ops.c
include/linux/ccp.h

index f9fec2ddf56aef0e3ec72039395bc6044403f8f9..94c1ad7eeddf7ca84d11f685b90756c2edefcf2f 100644 (file)
@@ -58,6 +58,19 @@ static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
 static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
                                   unsigned int authsize)
 {
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -104,6 +117,7 @@ static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
        memset(&rctx->cmd, 0, sizeof(rctx->cmd));
        INIT_LIST_HEAD(&rctx->cmd.entry);
        rctx->cmd.engine = CCP_ENGINE_AES;
+       rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);
        rctx->cmd.u.aes.type = ctx->u.aes.type;
        rctx->cmd.u.aes.mode = ctx->u.aes.mode;
        rctx->cmd.u.aes.action = encrypt;
index 3f30ed2f7f4efd7f7f840a0939729fd0abca9091..1a24021c7f5b0e6179c71d892e4ede4c694f536a 100644 (file)
@@ -622,6 +622,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        unsigned long long *final;
        unsigned int dm_offset;
+       unsigned int authsize;
        unsigned int jobid;
        unsigned int ilen;
        bool in_place = true; /* Default value */
@@ -643,6 +644,21 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
        if (!aes->key) /* Gotta have a key SGL */
                return -EINVAL;
 
+       /* Zero defaults to 16 bytes, the maximum size */
+       authsize = aes->authsize ? aes->authsize : AES_BLOCK_SIZE;
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* First, decompose the source buffer into AAD & PT,
         * and the destination buffer into AAD, CT & tag, or
         * the input into CT & tag.
@@ -657,7 +673,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
                p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen);
        } else {
                /* Input length for decryption includes tag */
-               ilen = aes->src_len - AES_BLOCK_SIZE;
+               ilen = aes->src_len - authsize;
                p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen);
        }
 
@@ -839,19 +855,19 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        if (aes->action == CCP_AES_ACTION_ENCRYPT) {
                /* Put the ciphered tag after the ciphertext. */
-               ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ccp_get_dm_area(&final_wa, 0, p_tag, 0, authsize);
        } else {
                /* Does this ciphered tag match the input? */
-               ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE,
+               ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
                                           DMA_BIDIRECTIONAL);
                if (ret)
                        goto e_tag;
-               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
                if (ret)
                        goto e_tag;
 
                ret = crypto_memneq(tag.address, final_wa.address,
-                                   AES_BLOCK_SIZE) ? -EBADMSG : 0;
+                                   authsize) ? -EBADMSG : 0;
                ccp_dm_free(&tag);
        }
 
index 55cb455cfcb067f2ccdbdc84d6d2ba9c78deaaf8..a5dfbaf2470d7cbf31f8b339b469f0c85fbaea9d 100644 (file)
@@ -170,6 +170,8 @@ struct ccp_aes_engine {
        enum ccp_aes_mode mode;
        enum ccp_aes_action action;
 
+       u32 authsize;
+
        struct scatterlist *key;
        u32 key_len;            /* In bytes */