static void crypto_gcm_ghash_update(struct crypto_gcm_ghash_ctx *ctx, const u8 *src, unsigned int srclen) { u8 *dst = ctx->buffer; if (ctx->bytes) { int n = min(srclen, ctx->bytes); u8 *pos = dst + (16 - ctx->bytes); ctx->bytes -= n; srclen -= n; while (n--) *pos++ ^= *src++; if (!ctx->bytes) gf128mul_4k_lle((be128 *)dst, ctx->gf128); } while (srclen >= 16) { crypto_xor(dst, src, 16); gf128mul_4k_lle((be128 *)dst, ctx->gf128); src += 16; srclen -= 16; } if (srclen) { ctx->bytes = 16 - srclen; while (srclen--) *dst++ ^= *src++; } }
static int ghash_update(struct shash_desc *desc, const u8 *src, unsigned int srclen) { struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); u8 *dst = dctx->buffer; if (!ctx->gf128) return -ENOKEY; if (dctx->bytes) { int n = min(srclen, dctx->bytes); u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes); dctx->bytes -= n; srclen -= n; while (n--) *pos++ ^= *src++; if (!dctx->bytes) gf128mul_4k_lle((be128 *)dst, ctx->gf128); } while (srclen >= GHASH_BLOCK_SIZE) { crypto_xor(dst, src, GHASH_BLOCK_SIZE); gf128mul_4k_lle((be128 *)dst, ctx->gf128); src += GHASH_BLOCK_SIZE; srclen -= GHASH_BLOCK_SIZE; } if (srclen) { dctx->bytes = GHASH_BLOCK_SIZE - srclen; while (srclen--) *dst++ ^= *src++; } return 0; }
static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) { u8 *dst = dctx->buffer; if (dctx->bytes) { u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes); while (dctx->bytes--) *tmp++ ^= 0; gf128mul_4k_lle((be128 *)dst, ctx->gf128); } dctx->bytes = 0; }
static void crypto_gcm_ghash_final_xor(struct crypto_gcm_ghash_ctx *ctx, unsigned int authlen, unsigned int cryptlen, u8 *dst) { u8 *buf = ctx->buffer; u128 lengths; lengths.a = cpu_to_be64(authlen * 8); lengths.b = cpu_to_be64(cryptlen * 8); crypto_gcm_ghash_flush(ctx); crypto_xor(buf, (u8 *)&lengths, 16); gf128mul_4k_lle((be128 *)buf, ctx->gf128); crypto_xor(dst, buf, 16); }
static void crypto_gcm_ghash_flush(struct crypto_gcm_ghash_ctx *ctx) { u8 *dst = ctx->buffer; if (ctx->bytes) { u8 *tmp = dst + (16 - ctx->bytes); while (ctx->bytes--) *tmp++ ^= 0; gf128mul_4k_lle((be128 *)dst, ctx->gf128); } ctx->bytes = 0; }