linux/crypto/ghash-generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * GHASH: hash function for GCM (Galois/Counter Mode).
   4 *
   5 * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
   6 * Copyright (c) 2009 Intel Corp.
   7 *   Author: Huang Ying <ying.huang@intel.com>
   8 */
   9
  10/*
  11 * GHASH is a keyed hash function used in GCM authentication tag generation.
  12 *
  13 * The original GCM paper [1] presents GHASH as a function GHASH(H, A, C) which
  14 * takes a 16-byte hash key H, additional authenticated data A, and a ciphertext
  15 * C.  It formats A and C into a single byte string X, interprets X as a
  16 * polynomial over GF(2^128), and evaluates this polynomial at the point H.
  17 *
  18 * However, the NIST standard for GCM [2] presents GHASH as GHASH(H, X) where X
  19 * is the already-formatted byte string containing both A and C.
  20 *
  21 * "ghash" in the Linux crypto API uses the 'X' (pre-formatted) convention,
  22 * since the API supports only a single data stream per hash.  Thus, the
  23 * formatting of 'A' and 'C' is done in the "gcm" template, not in "ghash".
  24 *
  25 * The reason "ghash" is separate from "gcm" is to allow "gcm" to use an
  26 * accelerated "ghash" when a standalone accelerated "gcm(aes)" is unavailable.
  27 * It is generally inappropriate to use "ghash" for other purposes, since it is
  28 * an "ε-almost-XOR-universal hash function", not a cryptographic hash function.
  29 * It can only be used securely in crypto modes specially designed to use it.
  30 *
  31 * [1] The Galois/Counter Mode of Operation (GCM)
  32 *     (http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.694.695&rep=rep1&type=pdf)
  33 * [2] Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC
  34 *     (https://csrc.nist.gov/publications/detail/sp/800-38d/final)
  35 */
  36
  37#include <crypto/algapi.h>
  38#include <crypto/gf128mul.h>
  39#include <crypto/ghash.h>
  40#include <crypto/internal/hash.h>
  41#include <linux/crypto.h>
  42#include <linux/init.h>
  43#include <linux/kernel.h>
  44#include <linux/module.h>
  45
  46static int ghash_init(struct shash_desc *desc)
  47{
  48        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  49
  50        memset(dctx, 0, sizeof(*dctx));
  51
  52        return 0;
  53}
  54
  55static int ghash_setkey(struct crypto_shash *tfm,
  56                        const u8 *key, unsigned int keylen)
  57{
  58        struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
  59        be128 k;
  60
  61        if (keylen != GHASH_BLOCK_SIZE) {
  62                crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  63                return -EINVAL;
  64        }
  65
  66        if (ctx->gf128)
  67                gf128mul_free_4k(ctx->gf128);
  68
  69        BUILD_BUG_ON(sizeof(k) != GHASH_BLOCK_SIZE);
  70        memcpy(&k, key, GHASH_BLOCK_SIZE); /* avoid violating alignment rules */
  71        ctx->gf128 = gf128mul_init_4k_lle(&k);
  72        memzero_explicit(&k, GHASH_BLOCK_SIZE);
  73
  74        if (!ctx->gf128)
  75                return -ENOMEM;
  76
  77        return 0;
  78}
  79
  80static int ghash_update(struct shash_desc *desc,
  81                         const u8 *src, unsigned int srclen)
  82{
  83        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  84        struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
  85        u8 *dst = dctx->buffer;
  86
  87        if (dctx->bytes) {
  88                int n = min(srclen, dctx->bytes);
  89                u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
  90
  91                dctx->bytes -= n;
  92                srclen -= n;
  93
  94                while (n--)
  95                        *pos++ ^= *src++;
  96
  97                if (!dctx->bytes)
  98                        gf128mul_4k_lle((be128 *)dst, ctx->gf128);
  99        }
 100
 101        while (srclen >= GHASH_BLOCK_SIZE) {
 102                crypto_xor(dst, src, GHASH_BLOCK_SIZE);
 103                gf128mul_4k_lle((be128 *)dst, ctx->gf128);
 104                src += GHASH_BLOCK_SIZE;
 105                srclen -= GHASH_BLOCK_SIZE;
 106        }
 107
 108        if (srclen) {
 109                dctx->bytes = GHASH_BLOCK_SIZE - srclen;
 110                while (srclen--)
 111                        *dst++ ^= *src++;
 112        }
 113
 114        return 0;
 115}
 116
 117static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 118{
 119        u8 *dst = dctx->buffer;
 120
 121        if (dctx->bytes) {
 122                u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
 123
 124                while (dctx->bytes--)
 125                        *tmp++ ^= 0;
 126
 127                gf128mul_4k_lle((be128 *)dst, ctx->gf128);
 128        }
 129
 130        dctx->bytes = 0;
 131}
 132
 133static int ghash_final(struct shash_desc *desc, u8 *dst)
 134{
 135        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 136        struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 137        u8 *buf = dctx->buffer;
 138
 139        ghash_flush(ctx, dctx);
 140        memcpy(dst, buf, GHASH_BLOCK_SIZE);
 141
 142        return 0;
 143}
 144
 145static void ghash_exit_tfm(struct crypto_tfm *tfm)
 146{
 147        struct ghash_ctx *ctx = crypto_tfm_ctx(tfm);
 148        if (ctx->gf128)
 149                gf128mul_free_4k(ctx->gf128);
 150}
 151
 152static struct shash_alg ghash_alg = {
 153        .digestsize     = GHASH_DIGEST_SIZE,
 154        .init           = ghash_init,
 155        .update         = ghash_update,
 156        .final          = ghash_final,
 157        .setkey         = ghash_setkey,
 158        .descsize       = sizeof(struct ghash_desc_ctx),
 159        .base           = {
 160                .cra_name               = "ghash",
 161                .cra_driver_name        = "ghash-generic",
 162                .cra_priority           = 100,
 163                .cra_blocksize          = GHASH_BLOCK_SIZE,
 164                .cra_ctxsize            = sizeof(struct ghash_ctx),
 165                .cra_module             = THIS_MODULE,
 166                .cra_exit               = ghash_exit_tfm,
 167        },
 168};
 169
 170static int __init ghash_mod_init(void)
 171{
 172        return crypto_register_shash(&ghash_alg);
 173}
 174
 175static void __exit ghash_mod_exit(void)
 176{
 177        crypto_unregister_shash(&ghash_alg);
 178}
 179
 180subsys_initcall(ghash_mod_init);
 181module_exit(ghash_mod_exit);
 182
 183MODULE_LICENSE("GPL");
 184MODULE_DESCRIPTION("GHASH hash function");
 185MODULE_ALIAS_CRYPTO("ghash");
 186MODULE_ALIAS_CRYPTO("ghash-generic");
 187