lkml.org 
[lkml]   [2021]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 272/340] crypto: sun4i-ss - IV register does not work on A10 and A13
    Date
    From: Corentin Labbe <clabbe@baylibre.com>

    commit b756f1c8fc9d84e3f546d7ffe056c5352f4aab05 upstream.

    Allwinner A10 and A13 SoC have a version of the SS which produce
    invalid IV in IVx register.

    Instead of adding a variant for those, let's convert SS to produce IV
    directly from data.
    Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 34 ++++++++++++++++++++++++------
    1 file changed, 28 insertions(+), 6 deletions(-)

    --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
    +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
    @@ -20,6 +20,7 @@ static int noinline_for_stack sun4i_ss_o
    unsigned int ivsize = crypto_skcipher_ivsize(tfm);
    struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
    u32 mode = ctx->mode;
    + void *backup_iv = NULL;
    /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
    u32 rx_cnt = SS_RX_DEFAULT;
    u32 tx_cnt = 0;
    @@ -44,6 +45,13 @@ static int noinline_for_stack sun4i_ss_o
    return -EINVAL;
    }

    + if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
    + backup_iv = kzalloc(ivsize, GFP_KERNEL);
    + if (!backup_iv)
    + return -ENOMEM;
    + scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
    + }
    +
    spin_lock_irqsave(&ss->slock, flags);

    for (i = 0; i < op->keylen; i += 4)
    @@ -117,9 +125,12 @@ static int noinline_for_stack sun4i_ss_o
    } while (oleft);

    if (areq->iv) {
    - for (i = 0; i < 4 && i < ivsize / 4; i++) {
    - v = readl(ss->base + SS_IV0 + i * 4);
    - *(u32 *)(areq->iv + i * 4) = v;
    + if (mode & SS_DECRYPTION) {
    + memcpy(areq->iv, backup_iv, ivsize);
    + kfree_sensitive(backup_iv);
    + } else {
    + scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
    + ivsize, 0);
    }
    }

    @@ -176,6 +187,7 @@ static int sun4i_ss_cipher_poll(struct s
    unsigned int ileft = areq->cryptlen;
    unsigned int oleft = areq->cryptlen;
    unsigned int todo;
    + void *backup_iv = NULL;
    struct sg_mapping_iter mi, mo;
    unsigned long pi = 0, po = 0; /* progress for in and out */
    bool miter_err;
    @@ -219,6 +231,13 @@ static int sun4i_ss_cipher_poll(struct s
    if (need_fallback)
    return sun4i_ss_cipher_poll_fallback(areq);

    + if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
    + backup_iv = kzalloc(ivsize, GFP_KERNEL);
    + if (!backup_iv)
    + return -ENOMEM;
    + scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
    + }
    +
    spin_lock_irqsave(&ss->slock, flags);

    for (i = 0; i < op->keylen; i += 4)
    @@ -347,9 +366,12 @@ static int sun4i_ss_cipher_poll(struct s
    sg_miter_stop(&mo);
    }
    if (areq->iv) {
    - for (i = 0; i < 4 && i < ivsize / 4; i++) {
    - v = readl(ss->base + SS_IV0 + i * 4);
    - *(u32 *)(areq->iv + i * 4) = v;
    + if (mode & SS_DECRYPTION) {
    + memcpy(areq->iv, backup_iv, ivsize);
    + kfree_sensitive(backup_iv);
    + } else {
    + scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
    + ivsize, 0);
    }
    }


    \
     
     \ /
      Last update: 2021-03-02 00:10    [W:4.137 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site