1*9739f5f9SChristian Marangi // SPDX-License-Identifier: GPL-2.0 2*9739f5f9SChristian Marangi /* 3*9739f5f9SChristian Marangi * Copyright (C) 2019 - 2021 4*9739f5f9SChristian Marangi * 5*9739f5f9SChristian Marangi * Richard van Schagen <vschagen@icloud.com> 6*9739f5f9SChristian Marangi * Christian Marangi <ansuelsmth@gmail.com 7*9739f5f9SChristian Marangi */ 8*9739f5f9SChristian Marangi 9*9739f5f9SChristian Marangi #include <crypto/aes.h> 10*9739f5f9SChristian Marangi #include <crypto/ctr.h> 11*9739f5f9SChristian Marangi #include <crypto/hmac.h> 12*9739f5f9SChristian Marangi #include <crypto/sha1.h> 13*9739f5f9SChristian Marangi #include <crypto/sha2.h> 14*9739f5f9SChristian Marangi #include <linux/kernel.h> 15*9739f5f9SChristian Marangi #include <linux/delay.h> 16*9739f5f9SChristian Marangi #include <linux/dma-mapping.h> 17*9739f5f9SChristian Marangi #include <linux/scatterlist.h> 18*9739f5f9SChristian Marangi 19*9739f5f9SChristian Marangi #include "eip93-cipher.h" 20*9739f5f9SChristian Marangi #include "eip93-hash.h" 21*9739f5f9SChristian Marangi #include "eip93-common.h" 22*9739f5f9SChristian Marangi #include "eip93-main.h" 23*9739f5f9SChristian Marangi #include "eip93-regs.h" 24*9739f5f9SChristian Marangi 25*9739f5f9SChristian Marangi int eip93_parse_ctrl_stat_err(struct eip93_device *eip93, int err) 26*9739f5f9SChristian Marangi { 27*9739f5f9SChristian Marangi u32 ext_err; 28*9739f5f9SChristian Marangi 29*9739f5f9SChristian Marangi if (!err) 30*9739f5f9SChristian Marangi return 0; 31*9739f5f9SChristian Marangi 32*9739f5f9SChristian Marangi switch (err & ~EIP93_PE_CTRL_PE_EXT_ERR_CODE) { 33*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_AUTH_ERR: 34*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_PAD_ERR: 35*9739f5f9SChristian Marangi return -EBADMSG; 36*9739f5f9SChristian Marangi /* let software handle anti-replay errors */ 37*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_SEQNUM_ERR: 38*9739f5f9SChristian Marangi return 0; 39*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR: 40*9739f5f9SChristian Marangi break; 41*9739f5f9SChristian Marangi default: 42*9739f5f9SChristian Marangi dev_err(eip93->dev, "Unhandled error 0x%08x\n", err); 43*9739f5f9SChristian Marangi return -EINVAL; 44*9739f5f9SChristian Marangi } 45*9739f5f9SChristian Marangi 46*9739f5f9SChristian Marangi /* Parse additional ext errors */ 47*9739f5f9SChristian Marangi ext_err = FIELD_GET(EIP93_PE_CTRL_PE_EXT_ERR_CODE, err); 48*9739f5f9SChristian Marangi switch (ext_err) { 49*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_BUS: 50*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_PROCESSING: 51*9739f5f9SChristian Marangi return -EIO; 52*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_DESC_OWNER: 53*9739f5f9SChristian Marangi return -EACCES; 54*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_OP: 55*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_ALGO: 56*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_SPI: 57*9739f5f9SChristian Marangi return -EINVAL; 58*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_ZERO_LENGTH: 59*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_PK_LENGTH: 60*9739f5f9SChristian Marangi case EIP93_PE_CTRL_PE_EXT_ERR_BLOCK_SIZE_ERR: 61*9739f5f9SChristian Marangi return -EBADMSG; 62*9739f5f9SChristian Marangi default: 63*9739f5f9SChristian Marangi dev_err(eip93->dev, "Unhandled ext error 0x%08x\n", ext_err); 64*9739f5f9SChristian Marangi return -EINVAL; 65*9739f5f9SChristian Marangi } 66*9739f5f9SChristian Marangi } 67*9739f5f9SChristian Marangi 68*9739f5f9SChristian Marangi static void *eip93_ring_next_wptr(struct eip93_device *eip93, 69*9739f5f9SChristian Marangi struct eip93_desc_ring *ring) 70*9739f5f9SChristian Marangi { 71*9739f5f9SChristian Marangi void *ptr = ring->write; 72*9739f5f9SChristian Marangi 73*9739f5f9SChristian Marangi if ((ring->write == ring->read - ring->offset) || 74*9739f5f9SChristian Marangi (ring->read == ring->base && ring->write == ring->base_end)) 75*9739f5f9SChristian Marangi return ERR_PTR(-ENOMEM); 76*9739f5f9SChristian Marangi 77*9739f5f9SChristian Marangi if (ring->write == ring->base_end) 78*9739f5f9SChristian Marangi ring->write = ring->base; 79*9739f5f9SChristian Marangi else 80*9739f5f9SChristian Marangi ring->write += ring->offset; 81*9739f5f9SChristian Marangi 82*9739f5f9SChristian Marangi return ptr; 83*9739f5f9SChristian Marangi } 84*9739f5f9SChristian Marangi 85*9739f5f9SChristian Marangi static void *eip93_ring_next_rptr(struct eip93_device *eip93, 86*9739f5f9SChristian Marangi struct eip93_desc_ring *ring) 87*9739f5f9SChristian Marangi { 88*9739f5f9SChristian Marangi void *ptr = ring->read; 89*9739f5f9SChristian Marangi 90*9739f5f9SChristian Marangi if (ring->write == ring->read) 91*9739f5f9SChristian Marangi return ERR_PTR(-ENOENT); 92*9739f5f9SChristian Marangi 93*9739f5f9SChristian Marangi if (ring->read == ring->base_end) 94*9739f5f9SChristian Marangi ring->read = ring->base; 95*9739f5f9SChristian Marangi else 96*9739f5f9SChristian Marangi ring->read += ring->offset; 97*9739f5f9SChristian Marangi 98*9739f5f9SChristian Marangi return ptr; 99*9739f5f9SChristian Marangi } 100*9739f5f9SChristian Marangi 101*9739f5f9SChristian Marangi int eip93_put_descriptor(struct eip93_device *eip93, 102*9739f5f9SChristian Marangi struct eip93_descriptor *desc) 103*9739f5f9SChristian Marangi { 104*9739f5f9SChristian Marangi struct eip93_descriptor *cdesc; 105*9739f5f9SChristian Marangi struct eip93_descriptor *rdesc; 106*9739f5f9SChristian Marangi 107*9739f5f9SChristian Marangi rdesc = eip93_ring_next_wptr(eip93, &eip93->ring->rdr); 108*9739f5f9SChristian Marangi if (IS_ERR(rdesc)) 109*9739f5f9SChristian Marangi return -ENOENT; 110*9739f5f9SChristian Marangi 111*9739f5f9SChristian Marangi cdesc = eip93_ring_next_wptr(eip93, &eip93->ring->cdr); 112*9739f5f9SChristian Marangi if (IS_ERR(cdesc)) 113*9739f5f9SChristian Marangi return -ENOENT; 114*9739f5f9SChristian Marangi 115*9739f5f9SChristian Marangi memset(rdesc, 0, sizeof(struct eip93_descriptor)); 116*9739f5f9SChristian Marangi 117*9739f5f9SChristian Marangi memcpy(cdesc, desc, sizeof(struct eip93_descriptor)); 118*9739f5f9SChristian Marangi 119*9739f5f9SChristian Marangi return 0; 120*9739f5f9SChristian Marangi } 121*9739f5f9SChristian Marangi 122*9739f5f9SChristian Marangi void *eip93_get_descriptor(struct eip93_device *eip93) 123*9739f5f9SChristian Marangi { 124*9739f5f9SChristian Marangi struct eip93_descriptor *cdesc; 125*9739f5f9SChristian Marangi void *ptr; 126*9739f5f9SChristian Marangi 127*9739f5f9SChristian Marangi cdesc = eip93_ring_next_rptr(eip93, &eip93->ring->cdr); 128*9739f5f9SChristian Marangi if (IS_ERR(cdesc)) 129*9739f5f9SChristian Marangi return ERR_PTR(-ENOENT); 130*9739f5f9SChristian Marangi 131*9739f5f9SChristian Marangi memset(cdesc, 0, sizeof(struct eip93_descriptor)); 132*9739f5f9SChristian Marangi 133*9739f5f9SChristian Marangi ptr = eip93_ring_next_rptr(eip93, &eip93->ring->rdr); 134*9739f5f9SChristian Marangi if (IS_ERR(ptr)) 135*9739f5f9SChristian Marangi return ERR_PTR(-ENOENT); 136*9739f5f9SChristian Marangi 137*9739f5f9SChristian Marangi return ptr; 138*9739f5f9SChristian Marangi } 139*9739f5f9SChristian Marangi 140*9739f5f9SChristian Marangi static void eip93_free_sg_copy(const int len, struct scatterlist **sg) 141*9739f5f9SChristian Marangi { 142*9739f5f9SChristian Marangi if (!*sg || !len) 143*9739f5f9SChristian Marangi return; 144*9739f5f9SChristian Marangi 145*9739f5f9SChristian Marangi free_pages((unsigned long)sg_virt(*sg), get_order(len)); 146*9739f5f9SChristian Marangi kfree(*sg); 147*9739f5f9SChristian Marangi *sg = NULL; 148*9739f5f9SChristian Marangi } 149*9739f5f9SChristian Marangi 150*9739f5f9SChristian Marangi static int eip93_make_sg_copy(struct scatterlist *src, struct scatterlist **dst, 151*9739f5f9SChristian Marangi const u32 len, const bool copy) 152*9739f5f9SChristian Marangi { 153*9739f5f9SChristian Marangi void *pages; 154*9739f5f9SChristian Marangi 155*9739f5f9SChristian Marangi *dst = kmalloc(sizeof(**dst), GFP_KERNEL); 156*9739f5f9SChristian Marangi if (!*dst) 157*9739f5f9SChristian Marangi return -ENOMEM; 158*9739f5f9SChristian Marangi 159*9739f5f9SChristian Marangi pages = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, 160*9739f5f9SChristian Marangi get_order(len)); 161*9739f5f9SChristian Marangi if (!pages) { 162*9739f5f9SChristian Marangi kfree(*dst); 163*9739f5f9SChristian Marangi *dst = NULL; 164*9739f5f9SChristian Marangi return -ENOMEM; 165*9739f5f9SChristian Marangi } 166*9739f5f9SChristian Marangi 167*9739f5f9SChristian Marangi sg_init_table(*dst, 1); 168*9739f5f9SChristian Marangi sg_set_buf(*dst, pages, len); 169*9739f5f9SChristian Marangi 170*9739f5f9SChristian Marangi /* copy only as requested */ 171*9739f5f9SChristian Marangi if (copy) 172*9739f5f9SChristian Marangi sg_copy_to_buffer(src, sg_nents(src), pages, len); 173*9739f5f9SChristian Marangi 174*9739f5f9SChristian Marangi return 0; 175*9739f5f9SChristian Marangi } 176*9739f5f9SChristian Marangi 177*9739f5f9SChristian Marangi static bool eip93_is_sg_aligned(struct scatterlist *sg, u32 len, 178*9739f5f9SChristian Marangi const int blksize) 179*9739f5f9SChristian Marangi { 180*9739f5f9SChristian Marangi int nents; 181*9739f5f9SChristian Marangi 182*9739f5f9SChristian Marangi for (nents = 0; sg; sg = sg_next(sg), ++nents) { 183*9739f5f9SChristian Marangi if (!IS_ALIGNED(sg->offset, 4)) 184*9739f5f9SChristian Marangi return false; 185*9739f5f9SChristian Marangi 186*9739f5f9SChristian Marangi if (len <= sg->length) { 187*9739f5f9SChristian Marangi if (!IS_ALIGNED(len, blksize)) 188*9739f5f9SChristian Marangi return false; 189*9739f5f9SChristian Marangi 190*9739f5f9SChristian Marangi return true; 191*9739f5f9SChristian Marangi } 192*9739f5f9SChristian Marangi 193*9739f5f9SChristian Marangi if (!IS_ALIGNED(sg->length, blksize)) 194*9739f5f9SChristian Marangi return false; 195*9739f5f9SChristian Marangi 196*9739f5f9SChristian Marangi len -= sg->length; 197*9739f5f9SChristian Marangi } 198*9739f5f9SChristian Marangi return false; 199*9739f5f9SChristian Marangi } 200*9739f5f9SChristian Marangi 201*9739f5f9SChristian Marangi int check_valid_request(struct eip93_cipher_reqctx *rctx) 202*9739f5f9SChristian Marangi { 203*9739f5f9SChristian Marangi struct scatterlist *src = rctx->sg_src; 204*9739f5f9SChristian Marangi struct scatterlist *dst = rctx->sg_dst; 205*9739f5f9SChristian Marangi u32 src_nents, dst_nents; 206*9739f5f9SChristian Marangi u32 textsize = rctx->textsize; 207*9739f5f9SChristian Marangi u32 authsize = rctx->authsize; 208*9739f5f9SChristian Marangi u32 blksize = rctx->blksize; 209*9739f5f9SChristian Marangi u32 totlen_src = rctx->assoclen + rctx->textsize; 210*9739f5f9SChristian Marangi u32 totlen_dst = rctx->assoclen + rctx->textsize; 211*9739f5f9SChristian Marangi u32 copy_len; 212*9739f5f9SChristian Marangi bool src_align, dst_align; 213*9739f5f9SChristian Marangi int err = -EINVAL; 214*9739f5f9SChristian Marangi 215*9739f5f9SChristian Marangi if (!IS_CTR(rctx->flags)) { 216*9739f5f9SChristian Marangi if (!IS_ALIGNED(textsize, blksize)) 217*9739f5f9SChristian Marangi return err; 218*9739f5f9SChristian Marangi } 219*9739f5f9SChristian Marangi 220*9739f5f9SChristian Marangi if (authsize) { 221*9739f5f9SChristian Marangi if (IS_ENCRYPT(rctx->flags)) 222*9739f5f9SChristian Marangi totlen_dst += authsize; 223*9739f5f9SChristian Marangi else 224*9739f5f9SChristian Marangi totlen_src += authsize; 225*9739f5f9SChristian Marangi } 226*9739f5f9SChristian Marangi 227*9739f5f9SChristian Marangi src_nents = sg_nents_for_len(src, totlen_src); 228*9739f5f9SChristian Marangi dst_nents = sg_nents_for_len(dst, totlen_dst); 229*9739f5f9SChristian Marangi 230*9739f5f9SChristian Marangi if (src == dst) { 231*9739f5f9SChristian Marangi src_nents = max(src_nents, dst_nents); 232*9739f5f9SChristian Marangi dst_nents = src_nents; 233*9739f5f9SChristian Marangi if (unlikely((totlen_src || totlen_dst) && src_nents <= 0)) 234*9739f5f9SChristian Marangi return err; 235*9739f5f9SChristian Marangi 236*9739f5f9SChristian Marangi } else { 237*9739f5f9SChristian Marangi if (unlikely(totlen_src && src_nents <= 0)) 238*9739f5f9SChristian Marangi return err; 239*9739f5f9SChristian Marangi 240*9739f5f9SChristian Marangi if (unlikely(totlen_dst && dst_nents <= 0)) 241*9739f5f9SChristian Marangi return err; 242*9739f5f9SChristian Marangi } 243*9739f5f9SChristian Marangi 244*9739f5f9SChristian Marangi if (authsize) { 245*9739f5f9SChristian Marangi if (dst_nents == 1 && src_nents == 1) { 246*9739f5f9SChristian Marangi src_align = eip93_is_sg_aligned(src, totlen_src, blksize); 247*9739f5f9SChristian Marangi if (src == dst) 248*9739f5f9SChristian Marangi dst_align = src_align; 249*9739f5f9SChristian Marangi else 250*9739f5f9SChristian Marangi dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize); 251*9739f5f9SChristian Marangi } else { 252*9739f5f9SChristian Marangi src_align = false; 253*9739f5f9SChristian Marangi dst_align = false; 254*9739f5f9SChristian Marangi } 255*9739f5f9SChristian Marangi } else { 256*9739f5f9SChristian Marangi src_align = eip93_is_sg_aligned(src, totlen_src, blksize); 257*9739f5f9SChristian Marangi if (src == dst) 258*9739f5f9SChristian Marangi dst_align = src_align; 259*9739f5f9SChristian Marangi else 260*9739f5f9SChristian Marangi dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize); 261*9739f5f9SChristian Marangi } 262*9739f5f9SChristian Marangi 263*9739f5f9SChristian Marangi copy_len = max(totlen_src, totlen_dst); 264*9739f5f9SChristian Marangi if (!src_align) { 265*9739f5f9SChristian Marangi err = eip93_make_sg_copy(src, &rctx->sg_src, copy_len, true); 266*9739f5f9SChristian Marangi if (err) 267*9739f5f9SChristian Marangi return err; 268*9739f5f9SChristian Marangi } 269*9739f5f9SChristian Marangi 270*9739f5f9SChristian Marangi if (!dst_align) { 271*9739f5f9SChristian Marangi err = eip93_make_sg_copy(dst, &rctx->sg_dst, copy_len, false); 272*9739f5f9SChristian Marangi if (err) 273*9739f5f9SChristian Marangi return err; 274*9739f5f9SChristian Marangi } 275*9739f5f9SChristian Marangi 276*9739f5f9SChristian Marangi rctx->src_nents = sg_nents_for_len(rctx->sg_src, totlen_src); 277*9739f5f9SChristian Marangi rctx->dst_nents = sg_nents_for_len(rctx->sg_dst, totlen_dst); 278*9739f5f9SChristian Marangi 279*9739f5f9SChristian Marangi return 0; 280*9739f5f9SChristian Marangi } 281*9739f5f9SChristian Marangi 282*9739f5f9SChristian Marangi /* 283*9739f5f9SChristian Marangi * Set sa_record function: 284*9739f5f9SChristian Marangi * Even sa_record is set to "0", keep " = 0" for readability. 285*9739f5f9SChristian Marangi */ 286*9739f5f9SChristian Marangi void eip93_set_sa_record(struct sa_record *sa_record, const unsigned int keylen, 287*9739f5f9SChristian Marangi const u32 flags) 288*9739f5f9SChristian Marangi { 289*9739f5f9SChristian Marangi /* Reset cmd word */ 290*9739f5f9SChristian Marangi sa_record->sa_cmd0_word = 0; 291*9739f5f9SChristian Marangi sa_record->sa_cmd1_word = 0; 292*9739f5f9SChristian Marangi 293*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_IV_FROM_STATE; 294*9739f5f9SChristian Marangi if (!IS_ECB(flags)) 295*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_SAVE_IV; 296*9739f5f9SChristian Marangi 297*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_OP_BASIC; 298*9739f5f9SChristian Marangi 299*9739f5f9SChristian Marangi switch ((flags & EIP93_ALG_MASK)) { 300*9739f5f9SChristian Marangi case EIP93_ALG_AES: 301*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_AES; 302*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= FIELD_PREP(EIP93_SA_CMD_AES_KEY_LENGTH, 303*9739f5f9SChristian Marangi keylen >> 3); 304*9739f5f9SChristian Marangi break; 305*9739f5f9SChristian Marangi case EIP93_ALG_3DES: 306*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_3DES; 307*9739f5f9SChristian Marangi break; 308*9739f5f9SChristian Marangi case EIP93_ALG_DES: 309*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_DES; 310*9739f5f9SChristian Marangi break; 311*9739f5f9SChristian Marangi default: 312*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_NULL; 313*9739f5f9SChristian Marangi } 314*9739f5f9SChristian Marangi 315*9739f5f9SChristian Marangi switch ((flags & EIP93_HASH_MASK)) { 316*9739f5f9SChristian Marangi case EIP93_HASH_SHA256: 317*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA256; 318*9739f5f9SChristian Marangi break; 319*9739f5f9SChristian Marangi case EIP93_HASH_SHA224: 320*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA224; 321*9739f5f9SChristian Marangi break; 322*9739f5f9SChristian Marangi case EIP93_HASH_SHA1: 323*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA1; 324*9739f5f9SChristian Marangi break; 325*9739f5f9SChristian Marangi case EIP93_HASH_MD5: 326*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_MD5; 327*9739f5f9SChristian Marangi break; 328*9739f5f9SChristian Marangi default: 329*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_NULL; 330*9739f5f9SChristian Marangi } 331*9739f5f9SChristian Marangi 332*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_PAD_ZERO; 333*9739f5f9SChristian Marangi 334*9739f5f9SChristian Marangi switch ((flags & EIP93_MODE_MASK)) { 335*9739f5f9SChristian Marangi case EIP93_MODE_CBC: 336*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CBC; 337*9739f5f9SChristian Marangi break; 338*9739f5f9SChristian Marangi case EIP93_MODE_CTR: 339*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CTR; 340*9739f5f9SChristian Marangi break; 341*9739f5f9SChristian Marangi case EIP93_MODE_ECB: 342*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_ECB; 343*9739f5f9SChristian Marangi break; 344*9739f5f9SChristian Marangi } 345*9739f5f9SChristian Marangi 346*9739f5f9SChristian Marangi sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIGEST_3WORD; 347*9739f5f9SChristian Marangi if (IS_HASH(flags)) { 348*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_PAD; 349*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_DIGEST; 350*9739f5f9SChristian Marangi } 351*9739f5f9SChristian Marangi 352*9739f5f9SChristian Marangi if (IS_HMAC(flags)) { 353*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_HMAC; 354*9739f5f9SChristian Marangi sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_HEADER; 355*9739f5f9SChristian Marangi } 356*9739f5f9SChristian Marangi 357*9739f5f9SChristian Marangi sa_record->sa_spi = 0x0; 358*9739f5f9SChristian Marangi sa_record->sa_seqmum_mask[0] = 0xFFFFFFFF; 359*9739f5f9SChristian Marangi sa_record->sa_seqmum_mask[1] = 0x0; 360*9739f5f9SChristian Marangi } 361*9739f5f9SChristian Marangi 362*9739f5f9SChristian Marangi /* 363*9739f5f9SChristian Marangi * Poor mans Scatter/gather function: 364*9739f5f9SChristian Marangi * Create a Descriptor for every segment to avoid copying buffers. 365*9739f5f9SChristian Marangi * For performance better to wait for hardware to perform multiple DMA 366*9739f5f9SChristian Marangi */ 367*9739f5f9SChristian Marangi static int eip93_scatter_combine(struct eip93_device *eip93, 368*9739f5f9SChristian Marangi struct eip93_cipher_reqctx *rctx, 369*9739f5f9SChristian Marangi u32 datalen, u32 split, int offsetin) 370*9739f5f9SChristian Marangi { 371*9739f5f9SChristian Marangi struct eip93_descriptor *cdesc = rctx->cdesc; 372*9739f5f9SChristian Marangi struct scatterlist *sgsrc = rctx->sg_src; 373*9739f5f9SChristian Marangi struct scatterlist *sgdst = rctx->sg_dst; 374*9739f5f9SChristian Marangi unsigned int remainin = sg_dma_len(sgsrc); 375*9739f5f9SChristian Marangi unsigned int remainout = sg_dma_len(sgdst); 376*9739f5f9SChristian Marangi dma_addr_t saddr = sg_dma_address(sgsrc); 377*9739f5f9SChristian Marangi dma_addr_t daddr = sg_dma_address(sgdst); 378*9739f5f9SChristian Marangi dma_addr_t state_addr; 379*9739f5f9SChristian Marangi u32 src_addr, dst_addr, len, n; 380*9739f5f9SChristian Marangi bool nextin = false; 381*9739f5f9SChristian Marangi bool nextout = false; 382*9739f5f9SChristian Marangi int offsetout = 0; 383*9739f5f9SChristian Marangi int err; 384*9739f5f9SChristian Marangi 385*9739f5f9SChristian Marangi if (IS_ECB(rctx->flags)) 386*9739f5f9SChristian Marangi rctx->sa_state_base = 0; 387*9739f5f9SChristian Marangi 388*9739f5f9SChristian Marangi if (split < datalen) { 389*9739f5f9SChristian Marangi state_addr = rctx->sa_state_ctr_base; 390*9739f5f9SChristian Marangi n = split; 391*9739f5f9SChristian Marangi } else { 392*9739f5f9SChristian Marangi state_addr = rctx->sa_state_base; 393*9739f5f9SChristian Marangi n = datalen; 394*9739f5f9SChristian Marangi } 395*9739f5f9SChristian Marangi 396*9739f5f9SChristian Marangi do { 397*9739f5f9SChristian Marangi if (nextin) { 398*9739f5f9SChristian Marangi sgsrc = sg_next(sgsrc); 399*9739f5f9SChristian Marangi remainin = sg_dma_len(sgsrc); 400*9739f5f9SChristian Marangi if (remainin == 0) 401*9739f5f9SChristian Marangi continue; 402*9739f5f9SChristian Marangi 403*9739f5f9SChristian Marangi saddr = sg_dma_address(sgsrc); 404*9739f5f9SChristian Marangi offsetin = 0; 405*9739f5f9SChristian Marangi nextin = false; 406*9739f5f9SChristian Marangi } 407*9739f5f9SChristian Marangi 408*9739f5f9SChristian Marangi if (nextout) { 409*9739f5f9SChristian Marangi sgdst = sg_next(sgdst); 410*9739f5f9SChristian Marangi remainout = sg_dma_len(sgdst); 411*9739f5f9SChristian Marangi if (remainout == 0) 412*9739f5f9SChristian Marangi continue; 413*9739f5f9SChristian Marangi 414*9739f5f9SChristian Marangi daddr = sg_dma_address(sgdst); 415*9739f5f9SChristian Marangi offsetout = 0; 416*9739f5f9SChristian Marangi nextout = false; 417*9739f5f9SChristian Marangi } 418*9739f5f9SChristian Marangi src_addr = saddr + offsetin; 419*9739f5f9SChristian Marangi dst_addr = daddr + offsetout; 420*9739f5f9SChristian Marangi 421*9739f5f9SChristian Marangi if (remainin == remainout) { 422*9739f5f9SChristian Marangi len = remainin; 423*9739f5f9SChristian Marangi if (len > n) { 424*9739f5f9SChristian Marangi len = n; 425*9739f5f9SChristian Marangi remainin -= n; 426*9739f5f9SChristian Marangi remainout -= n; 427*9739f5f9SChristian Marangi offsetin += n; 428*9739f5f9SChristian Marangi offsetout += n; 429*9739f5f9SChristian Marangi } else { 430*9739f5f9SChristian Marangi nextin = true; 431*9739f5f9SChristian Marangi nextout = true; 432*9739f5f9SChristian Marangi } 433*9739f5f9SChristian Marangi } else if (remainin < remainout) { 434*9739f5f9SChristian Marangi len = remainin; 435*9739f5f9SChristian Marangi if (len > n) { 436*9739f5f9SChristian Marangi len = n; 437*9739f5f9SChristian Marangi remainin -= n; 438*9739f5f9SChristian Marangi remainout -= n; 439*9739f5f9SChristian Marangi offsetin += n; 440*9739f5f9SChristian Marangi offsetout += n; 441*9739f5f9SChristian Marangi } else { 442*9739f5f9SChristian Marangi offsetout += len; 443*9739f5f9SChristian Marangi remainout -= len; 444*9739f5f9SChristian Marangi nextin = true; 445*9739f5f9SChristian Marangi } 446*9739f5f9SChristian Marangi } else { 447*9739f5f9SChristian Marangi len = remainout; 448*9739f5f9SChristian Marangi if (len > n) { 449*9739f5f9SChristian Marangi len = n; 450*9739f5f9SChristian Marangi remainin -= n; 451*9739f5f9SChristian Marangi remainout -= n; 452*9739f5f9SChristian Marangi offsetin += n; 453*9739f5f9SChristian Marangi offsetout += n; 454*9739f5f9SChristian Marangi } else { 455*9739f5f9SChristian Marangi offsetin += len; 456*9739f5f9SChristian Marangi remainin -= len; 457*9739f5f9SChristian Marangi nextout = true; 458*9739f5f9SChristian Marangi } 459*9739f5f9SChristian Marangi } 460*9739f5f9SChristian Marangi n -= len; 461*9739f5f9SChristian Marangi 462*9739f5f9SChristian Marangi cdesc->src_addr = src_addr; 463*9739f5f9SChristian Marangi cdesc->dst_addr = dst_addr; 464*9739f5f9SChristian Marangi cdesc->state_addr = state_addr; 465*9739f5f9SChristian Marangi cdesc->pe_length_word = FIELD_PREP(EIP93_PE_LENGTH_HOST_PE_READY, 466*9739f5f9SChristian Marangi EIP93_PE_LENGTH_HOST_READY); 467*9739f5f9SChristian Marangi cdesc->pe_length_word |= FIELD_PREP(EIP93_PE_LENGTH_LENGTH, len); 468*9739f5f9SChristian Marangi 469*9739f5f9SChristian Marangi if (n == 0) { 470*9739f5f9SChristian Marangi n = datalen - split; 471*9739f5f9SChristian Marangi split = datalen; 472*9739f5f9SChristian Marangi state_addr = rctx->sa_state_base; 473*9739f5f9SChristian Marangi } 474*9739f5f9SChristian Marangi 475*9739f5f9SChristian Marangi if (n == 0) 476*9739f5f9SChristian Marangi cdesc->user_id |= FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, 477*9739f5f9SChristian Marangi EIP93_DESC_LAST); 478*9739f5f9SChristian Marangi 479*9739f5f9SChristian Marangi /* 480*9739f5f9SChristian Marangi * Loop - Delay - No need to rollback 481*9739f5f9SChristian Marangi * Maybe refine by slowing down at EIP93_RING_BUSY 482*9739f5f9SChristian Marangi */ 483*9739f5f9SChristian Marangi again: 484*9739f5f9SChristian Marangi scoped_guard(spinlock_irqsave, &eip93->ring->write_lock) 485*9739f5f9SChristian Marangi err = eip93_put_descriptor(eip93, cdesc); 486*9739f5f9SChristian Marangi if (err) { 487*9739f5f9SChristian Marangi usleep_range(EIP93_RING_BUSY_DELAY, 488*9739f5f9SChristian Marangi EIP93_RING_BUSY_DELAY * 2); 489*9739f5f9SChristian Marangi goto again; 490*9739f5f9SChristian Marangi } 491*9739f5f9SChristian Marangi /* Writing new descriptor count starts DMA action */ 492*9739f5f9SChristian Marangi writel(1, eip93->base + EIP93_REG_PE_CD_COUNT); 493*9739f5f9SChristian Marangi } while (n); 494*9739f5f9SChristian Marangi 495*9739f5f9SChristian Marangi return -EINPROGRESS; 496*9739f5f9SChristian Marangi } 497*9739f5f9SChristian Marangi 498*9739f5f9SChristian Marangi int eip93_send_req(struct crypto_async_request *async, 499*9739f5f9SChristian Marangi const u8 *reqiv, struct eip93_cipher_reqctx *rctx) 500*9739f5f9SChristian Marangi { 501*9739f5f9SChristian Marangi struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); 502*9739f5f9SChristian Marangi struct eip93_device *eip93 = ctx->eip93; 503*9739f5f9SChristian Marangi struct scatterlist *src = rctx->sg_src; 504*9739f5f9SChristian Marangi struct scatterlist *dst = rctx->sg_dst; 505*9739f5f9SChristian Marangi struct sa_state *sa_state; 506*9739f5f9SChristian Marangi struct eip93_descriptor cdesc; 507*9739f5f9SChristian Marangi u32 flags = rctx->flags; 508*9739f5f9SChristian Marangi int offsetin = 0, err; 509*9739f5f9SChristian Marangi u32 datalen = rctx->assoclen + rctx->textsize; 510*9739f5f9SChristian Marangi u32 split = datalen; 511*9739f5f9SChristian Marangi u32 start, end, ctr, blocks; 512*9739f5f9SChristian Marangi u32 iv[AES_BLOCK_SIZE / sizeof(u32)]; 513*9739f5f9SChristian Marangi int crypto_async_idr; 514*9739f5f9SChristian Marangi 515*9739f5f9SChristian Marangi rctx->sa_state_ctr = NULL; 516*9739f5f9SChristian Marangi rctx->sa_state = NULL; 517*9739f5f9SChristian Marangi 518*9739f5f9SChristian Marangi if (IS_ECB(flags)) 519*9739f5f9SChristian Marangi goto skip_iv; 520*9739f5f9SChristian Marangi 521*9739f5f9SChristian Marangi memcpy(iv, reqiv, rctx->ivsize); 522*9739f5f9SChristian Marangi 523*9739f5f9SChristian Marangi rctx->sa_state = kzalloc(sizeof(*rctx->sa_state), GFP_KERNEL); 524*9739f5f9SChristian Marangi if (!rctx->sa_state) 525*9739f5f9SChristian Marangi return -ENOMEM; 526*9739f5f9SChristian Marangi 527*9739f5f9SChristian Marangi sa_state = rctx->sa_state; 528*9739f5f9SChristian Marangi 529*9739f5f9SChristian Marangi memcpy(sa_state->state_iv, iv, rctx->ivsize); 530*9739f5f9SChristian Marangi if (IS_RFC3686(flags)) { 531*9739f5f9SChristian Marangi sa_state->state_iv[0] = ctx->sa_nonce; 532*9739f5f9SChristian Marangi sa_state->state_iv[1] = iv[0]; 533*9739f5f9SChristian Marangi sa_state->state_iv[2] = iv[1]; 534*9739f5f9SChristian Marangi sa_state->state_iv[3] = (u32 __force)cpu_to_be32(0x1); 535*9739f5f9SChristian Marangi } else if (!IS_HMAC(flags) && IS_CTR(flags)) { 536*9739f5f9SChristian Marangi /* Compute data length. */ 537*9739f5f9SChristian Marangi blocks = DIV_ROUND_UP(rctx->textsize, AES_BLOCK_SIZE); 538*9739f5f9SChristian Marangi ctr = be32_to_cpu((__be32 __force)iv[3]); 539*9739f5f9SChristian Marangi /* Check 32bit counter overflow. */ 540*9739f5f9SChristian Marangi start = ctr; 541*9739f5f9SChristian Marangi end = start + blocks - 1; 542*9739f5f9SChristian Marangi if (end < start) { 543*9739f5f9SChristian Marangi split = AES_BLOCK_SIZE * -start; 544*9739f5f9SChristian Marangi /* 545*9739f5f9SChristian Marangi * Increment the counter manually to cope with 546*9739f5f9SChristian Marangi * the hardware counter overflow. 547*9739f5f9SChristian Marangi */ 548*9739f5f9SChristian Marangi iv[3] = 0xffffffff; 549*9739f5f9SChristian Marangi crypto_inc((u8 *)iv, AES_BLOCK_SIZE); 550*9739f5f9SChristian Marangi 551*9739f5f9SChristian Marangi rctx->sa_state_ctr = kzalloc(sizeof(*rctx->sa_state_ctr), 552*9739f5f9SChristian Marangi GFP_KERNEL); 553*9739f5f9SChristian Marangi if (!rctx->sa_state_ctr) { 554*9739f5f9SChristian Marangi err = -ENOMEM; 555*9739f5f9SChristian Marangi goto free_sa_state; 556*9739f5f9SChristian Marangi } 557*9739f5f9SChristian Marangi 558*9739f5f9SChristian Marangi memcpy(rctx->sa_state_ctr->state_iv, reqiv, rctx->ivsize); 559*9739f5f9SChristian Marangi memcpy(sa_state->state_iv, iv, rctx->ivsize); 560*9739f5f9SChristian Marangi 561*9739f5f9SChristian Marangi rctx->sa_state_ctr_base = dma_map_single(eip93->dev, rctx->sa_state_ctr, 562*9739f5f9SChristian Marangi sizeof(*rctx->sa_state_ctr), 563*9739f5f9SChristian Marangi DMA_TO_DEVICE); 564*9739f5f9SChristian Marangi err = dma_mapping_error(eip93->dev, rctx->sa_state_ctr_base); 565*9739f5f9SChristian Marangi if (err) 566*9739f5f9SChristian Marangi goto free_sa_state_ctr; 567*9739f5f9SChristian Marangi } 568*9739f5f9SChristian Marangi } 569*9739f5f9SChristian Marangi 570*9739f5f9SChristian Marangi rctx->sa_state_base = dma_map_single(eip93->dev, rctx->sa_state, 571*9739f5f9SChristian Marangi sizeof(*rctx->sa_state), DMA_TO_DEVICE); 572*9739f5f9SChristian Marangi err = dma_mapping_error(eip93->dev, rctx->sa_state_base); 573*9739f5f9SChristian Marangi if (err) 574*9739f5f9SChristian Marangi goto free_sa_state_ctr_dma; 575*9739f5f9SChristian Marangi 576*9739f5f9SChristian Marangi skip_iv: 577*9739f5f9SChristian Marangi 578*9739f5f9SChristian Marangi cdesc.pe_ctrl_stat_word = FIELD_PREP(EIP93_PE_CTRL_PE_READY_DES_TRING_OWN, 579*9739f5f9SChristian Marangi EIP93_PE_CTRL_HOST_READY); 580*9739f5f9SChristian Marangi cdesc.sa_addr = rctx->sa_record_base; 581*9739f5f9SChristian Marangi cdesc.arc4_addr = 0; 582*9739f5f9SChristian Marangi 583*9739f5f9SChristian Marangi scoped_guard(spinlock_bh, &eip93->ring->idr_lock) 584*9739f5f9SChristian Marangi crypto_async_idr = idr_alloc(&eip93->ring->crypto_async_idr, async, 0, 585*9739f5f9SChristian Marangi EIP93_RING_NUM - 1, GFP_ATOMIC); 586*9739f5f9SChristian Marangi 587*9739f5f9SChristian Marangi cdesc.user_id = FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) | 588*9739f5f9SChristian Marangi FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, rctx->desc_flags); 589*9739f5f9SChristian Marangi 590*9739f5f9SChristian Marangi rctx->cdesc = &cdesc; 591*9739f5f9SChristian Marangi 592*9739f5f9SChristian Marangi /* map DMA_BIDIRECTIONAL to invalidate cache on destination 593*9739f5f9SChristian Marangi * implies __dma_cache_wback_inv 594*9739f5f9SChristian Marangi */ 595*9739f5f9SChristian Marangi if (!dma_map_sg(eip93->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL)) { 596*9739f5f9SChristian Marangi err = -ENOMEM; 597*9739f5f9SChristian Marangi goto free_sa_state_ctr_dma; 598*9739f5f9SChristian Marangi } 599*9739f5f9SChristian Marangi 600*9739f5f9SChristian Marangi if (src != dst && 601*9739f5f9SChristian Marangi !dma_map_sg(eip93->dev, src, rctx->src_nents, DMA_TO_DEVICE)) { 602*9739f5f9SChristian Marangi err = -ENOMEM; 603*9739f5f9SChristian Marangi goto free_sg_dma; 604*9739f5f9SChristian Marangi } 605*9739f5f9SChristian Marangi 606*9739f5f9SChristian Marangi return eip93_scatter_combine(eip93, rctx, datalen, split, offsetin); 607*9739f5f9SChristian Marangi 608*9739f5f9SChristian Marangi free_sg_dma: 609*9739f5f9SChristian Marangi dma_unmap_sg(eip93->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL); 610*9739f5f9SChristian Marangi free_sa_state_ctr_dma: 611*9739f5f9SChristian Marangi if (rctx->sa_state_ctr) 612*9739f5f9SChristian Marangi dma_unmap_single(eip93->dev, rctx->sa_state_ctr_base, 613*9739f5f9SChristian Marangi sizeof(*rctx->sa_state_ctr), 614*9739f5f9SChristian Marangi DMA_TO_DEVICE); 615*9739f5f9SChristian Marangi free_sa_state_ctr: 616*9739f5f9SChristian Marangi kfree(rctx->sa_state_ctr); 617*9739f5f9SChristian Marangi if (rctx->sa_state) 618*9739f5f9SChristian Marangi dma_unmap_single(eip93->dev, rctx->sa_state_base, 619*9739f5f9SChristian Marangi sizeof(*rctx->sa_state), 620*9739f5f9SChristian Marangi DMA_TO_DEVICE); 621*9739f5f9SChristian Marangi free_sa_state: 622*9739f5f9SChristian Marangi kfree(rctx->sa_state); 623*9739f5f9SChristian Marangi 624*9739f5f9SChristian Marangi return err; 625*9739f5f9SChristian Marangi } 626*9739f5f9SChristian Marangi 627*9739f5f9SChristian Marangi void eip93_unmap_dma(struct eip93_device *eip93, struct eip93_cipher_reqctx *rctx, 628*9739f5f9SChristian Marangi struct scatterlist *reqsrc, struct scatterlist *reqdst) 629*9739f5f9SChristian Marangi { 630*9739f5f9SChristian Marangi u32 len = rctx->assoclen + rctx->textsize; 631*9739f5f9SChristian Marangi u32 authsize = rctx->authsize; 632*9739f5f9SChristian Marangi u32 flags = rctx->flags; 633*9739f5f9SChristian Marangi u32 *otag; 634*9739f5f9SChristian Marangi int i; 635*9739f5f9SChristian Marangi 636*9739f5f9SChristian Marangi if (rctx->sg_src == rctx->sg_dst) { 637*9739f5f9SChristian Marangi dma_unmap_sg(eip93->dev, rctx->sg_dst, rctx->dst_nents, 638*9739f5f9SChristian Marangi DMA_BIDIRECTIONAL); 639*9739f5f9SChristian Marangi goto process_tag; 640*9739f5f9SChristian Marangi } 641*9739f5f9SChristian Marangi 642*9739f5f9SChristian Marangi dma_unmap_sg(eip93->dev, rctx->sg_src, rctx->src_nents, 643*9739f5f9SChristian Marangi DMA_TO_DEVICE); 644*9739f5f9SChristian Marangi 645*9739f5f9SChristian Marangi if (rctx->sg_src != reqsrc) 646*9739f5f9SChristian Marangi eip93_free_sg_copy(len + rctx->authsize, &rctx->sg_src); 647*9739f5f9SChristian Marangi 648*9739f5f9SChristian Marangi dma_unmap_sg(eip93->dev, rctx->sg_dst, rctx->dst_nents, 649*9739f5f9SChristian Marangi DMA_BIDIRECTIONAL); 650*9739f5f9SChristian Marangi 651*9739f5f9SChristian Marangi /* SHA tags need conversion from net-to-host */ 652*9739f5f9SChristian Marangi process_tag: 653*9739f5f9SChristian Marangi if (IS_DECRYPT(flags)) 654*9739f5f9SChristian Marangi authsize = 0; 655*9739f5f9SChristian Marangi 656*9739f5f9SChristian Marangi if (authsize) { 657*9739f5f9SChristian Marangi if (!IS_HASH_MD5(flags)) { 658*9739f5f9SChristian Marangi otag = sg_virt(rctx->sg_dst) + len; 659*9739f5f9SChristian Marangi for (i = 0; i < (authsize / 4); i++) 660*9739f5f9SChristian Marangi otag[i] = be32_to_cpu((__be32 __force)otag[i]); 661*9739f5f9SChristian Marangi } 662*9739f5f9SChristian Marangi } 663*9739f5f9SChristian Marangi 664*9739f5f9SChristian Marangi if (rctx->sg_dst != reqdst) { 665*9739f5f9SChristian Marangi sg_copy_from_buffer(reqdst, sg_nents(reqdst), 666*9739f5f9SChristian Marangi sg_virt(rctx->sg_dst), len + authsize); 667*9739f5f9SChristian Marangi eip93_free_sg_copy(len + rctx->authsize, &rctx->sg_dst); 668*9739f5f9SChristian Marangi } 669*9739f5f9SChristian Marangi } 670*9739f5f9SChristian Marangi 671*9739f5f9SChristian Marangi void eip93_handle_result(struct eip93_device *eip93, struct eip93_cipher_reqctx *rctx, 672*9739f5f9SChristian Marangi u8 *reqiv) 673*9739f5f9SChristian Marangi { 674*9739f5f9SChristian Marangi if (rctx->sa_state_ctr) 675*9739f5f9SChristian Marangi dma_unmap_single(eip93->dev, rctx->sa_state_ctr_base, 676*9739f5f9SChristian Marangi sizeof(*rctx->sa_state_ctr), 677*9739f5f9SChristian Marangi DMA_FROM_DEVICE); 678*9739f5f9SChristian Marangi 679*9739f5f9SChristian Marangi if (rctx->sa_state) 680*9739f5f9SChristian Marangi dma_unmap_single(eip93->dev, rctx->sa_state_base, 681*9739f5f9SChristian Marangi sizeof(*rctx->sa_state), 682*9739f5f9SChristian Marangi DMA_FROM_DEVICE); 683*9739f5f9SChristian Marangi 684*9739f5f9SChristian Marangi if (!IS_ECB(rctx->flags)) 685*9739f5f9SChristian Marangi memcpy(reqiv, rctx->sa_state->state_iv, rctx->ivsize); 686*9739f5f9SChristian Marangi 687*9739f5f9SChristian Marangi kfree(rctx->sa_state_ctr); 688*9739f5f9SChristian Marangi kfree(rctx->sa_state); 689*9739f5f9SChristian Marangi } 690*9739f5f9SChristian Marangi 691*9739f5f9SChristian Marangi int eip93_hmac_setkey(u32 ctx_flags, const u8 *key, unsigned int keylen, 692*9739f5f9SChristian Marangi unsigned int hashlen, u8 *dest_ipad, u8 *dest_opad, 693*9739f5f9SChristian Marangi bool skip_ipad) 694*9739f5f9SChristian Marangi { 695*9739f5f9SChristian Marangi u8 ipad[SHA256_BLOCK_SIZE], opad[SHA256_BLOCK_SIZE]; 696*9739f5f9SChristian Marangi struct crypto_ahash *ahash_tfm; 697*9739f5f9SChristian Marangi struct eip93_hash_reqctx *rctx; 698*9739f5f9SChristian Marangi struct ahash_request *req; 699*9739f5f9SChristian Marangi DECLARE_CRYPTO_WAIT(wait); 700*9739f5f9SChristian Marangi struct scatterlist sg[1]; 701*9739f5f9SChristian Marangi const char *alg_name; 702*9739f5f9SChristian Marangi int i, ret; 703*9739f5f9SChristian Marangi 704*9739f5f9SChristian Marangi switch (ctx_flags & EIP93_HASH_MASK) { 705*9739f5f9SChristian Marangi case EIP93_HASH_SHA256: 706*9739f5f9SChristian Marangi alg_name = "sha256-eip93"; 707*9739f5f9SChristian Marangi break; 708*9739f5f9SChristian Marangi case EIP93_HASH_SHA224: 709*9739f5f9SChristian Marangi alg_name = "sha224-eip93"; 710*9739f5f9SChristian Marangi break; 711*9739f5f9SChristian Marangi case EIP93_HASH_SHA1: 712*9739f5f9SChristian Marangi alg_name = "sha1-eip93"; 713*9739f5f9SChristian Marangi break; 714*9739f5f9SChristian Marangi case EIP93_HASH_MD5: 715*9739f5f9SChristian Marangi alg_name = "md5-eip93"; 716*9739f5f9SChristian Marangi break; 717*9739f5f9SChristian Marangi default: /* Impossible */ 718*9739f5f9SChristian Marangi return -EINVAL; 719*9739f5f9SChristian Marangi } 720*9739f5f9SChristian Marangi 721*9739f5f9SChristian Marangi ahash_tfm = crypto_alloc_ahash(alg_name, 0, CRYPTO_ALG_ASYNC); 722*9739f5f9SChristian Marangi if (IS_ERR(ahash_tfm)) 723*9739f5f9SChristian Marangi return PTR_ERR(ahash_tfm); 724*9739f5f9SChristian Marangi 725*9739f5f9SChristian Marangi req = ahash_request_alloc(ahash_tfm, GFP_ATOMIC); 726*9739f5f9SChristian Marangi if (!req) { 727*9739f5f9SChristian Marangi ret = -ENOMEM; 728*9739f5f9SChristian Marangi goto err_ahash; 729*9739f5f9SChristian Marangi } 730*9739f5f9SChristian Marangi 731*9739f5f9SChristian Marangi rctx = ahash_request_ctx_dma(req); 732*9739f5f9SChristian Marangi crypto_init_wait(&wait); 733*9739f5f9SChristian Marangi ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 734*9739f5f9SChristian Marangi crypto_req_done, &wait); 735*9739f5f9SChristian Marangi 736*9739f5f9SChristian Marangi /* Hash the key if > SHA256_BLOCK_SIZE */ 737*9739f5f9SChristian Marangi if (keylen > SHA256_BLOCK_SIZE) { 738*9739f5f9SChristian Marangi sg_init_one(&sg[0], key, keylen); 739*9739f5f9SChristian Marangi 740*9739f5f9SChristian Marangi ahash_request_set_crypt(req, sg, ipad, keylen); 741*9739f5f9SChristian Marangi ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 742*9739f5f9SChristian Marangi if (ret) 743*9739f5f9SChristian Marangi goto err_req; 744*9739f5f9SChristian Marangi 745*9739f5f9SChristian Marangi keylen = hashlen; 746*9739f5f9SChristian Marangi } else { 747*9739f5f9SChristian Marangi memcpy(ipad, key, keylen); 748*9739f5f9SChristian Marangi } 749*9739f5f9SChristian Marangi 750*9739f5f9SChristian Marangi /* Copy to opad */ 751*9739f5f9SChristian Marangi memset(ipad + keylen, 0, SHA256_BLOCK_SIZE - keylen); 752*9739f5f9SChristian Marangi memcpy(opad, ipad, SHA256_BLOCK_SIZE); 753*9739f5f9SChristian Marangi 754*9739f5f9SChristian Marangi /* Pad with HMAC constants */ 755*9739f5f9SChristian Marangi for (i = 0; i < SHA256_BLOCK_SIZE; i++) { 756*9739f5f9SChristian Marangi ipad[i] ^= HMAC_IPAD_VALUE; 757*9739f5f9SChristian Marangi opad[i] ^= HMAC_OPAD_VALUE; 758*9739f5f9SChristian Marangi } 759*9739f5f9SChristian Marangi 760*9739f5f9SChristian Marangi if (skip_ipad) { 761*9739f5f9SChristian Marangi memcpy(dest_ipad, ipad, SHA256_BLOCK_SIZE); 762*9739f5f9SChristian Marangi } else { 763*9739f5f9SChristian Marangi /* Hash ipad */ 764*9739f5f9SChristian Marangi sg_init_one(&sg[0], ipad, SHA256_BLOCK_SIZE); 765*9739f5f9SChristian Marangi ahash_request_set_crypt(req, sg, dest_ipad, SHA256_BLOCK_SIZE); 766*9739f5f9SChristian Marangi ret = crypto_ahash_init(req); 767*9739f5f9SChristian Marangi if (ret) 768*9739f5f9SChristian Marangi goto err_req; 769*9739f5f9SChristian Marangi 770*9739f5f9SChristian Marangi /* Disable HASH_FINALIZE for ipad hash */ 771*9739f5f9SChristian Marangi rctx->partial_hash = true; 772*9739f5f9SChristian Marangi 773*9739f5f9SChristian Marangi ret = crypto_wait_req(crypto_ahash_finup(req), &wait); 774*9739f5f9SChristian Marangi if (ret) 775*9739f5f9SChristian Marangi goto err_req; 776*9739f5f9SChristian Marangi } 777*9739f5f9SChristian Marangi 778*9739f5f9SChristian Marangi /* Hash opad */ 779*9739f5f9SChristian Marangi sg_init_one(&sg[0], opad, SHA256_BLOCK_SIZE); 780*9739f5f9SChristian Marangi ahash_request_set_crypt(req, sg, dest_opad, SHA256_BLOCK_SIZE); 781*9739f5f9SChristian Marangi ret = crypto_ahash_init(req); 782*9739f5f9SChristian Marangi if (ret) 783*9739f5f9SChristian Marangi goto err_req; 784*9739f5f9SChristian Marangi 785*9739f5f9SChristian Marangi /* Disable HASH_FINALIZE for opad hash */ 786*9739f5f9SChristian Marangi rctx->partial_hash = true; 787*9739f5f9SChristian Marangi 788*9739f5f9SChristian Marangi ret = crypto_wait_req(crypto_ahash_finup(req), &wait); 789*9739f5f9SChristian Marangi if (ret) 790*9739f5f9SChristian Marangi goto err_req; 791*9739f5f9SChristian Marangi 792*9739f5f9SChristian Marangi if (!IS_HASH_MD5(ctx_flags)) { 793*9739f5f9SChristian Marangi for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) { 794*9739f5f9SChristian Marangi u32 *ipad_hash = (u32 *)dest_ipad; 795*9739f5f9SChristian Marangi u32 *opad_hash = (u32 *)dest_opad; 796*9739f5f9SChristian Marangi 797*9739f5f9SChristian Marangi if (!skip_ipad) 798*9739f5f9SChristian Marangi ipad_hash[i] = (u32 __force)cpu_to_be32(ipad_hash[i]); 799*9739f5f9SChristian Marangi opad_hash[i] = (u32 __force)cpu_to_be32(opad_hash[i]); 800*9739f5f9SChristian Marangi } 801*9739f5f9SChristian Marangi } 802*9739f5f9SChristian Marangi 803*9739f5f9SChristian Marangi err_req: 804*9739f5f9SChristian Marangi ahash_request_free(req); 805*9739f5f9SChristian Marangi err_ahash: 806*9739f5f9SChristian Marangi crypto_free_ahash(ahash_tfm); 807*9739f5f9SChristian Marangi 808*9739f5f9SChristian Marangi return ret; 809*9739f5f9SChristian Marangi } 810