Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/x86/crypto/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  polyval-clmulni_glue.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Glue code for POLYVAL using PCMULQDQ-NI
 *
 * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
 * Copyright (c) 2009 Intel Corp.
 *   Author: Huang Ying <ying.huang@intel.com>
 * Copyright 2021 Google LLC
 */


/*
 * Glue code based on ghash-clmulni-intel_glue.c.
 *
 * This implementation of POLYVAL uses montgomery multiplication
 * accelerated by PCLMULQDQ-NI to implement the finite field
 * operations.
 */


#include <asm/cpu_device_id.h>
#include <asm/fpu/api.h>
#include <crypto/internal/hash.h>
#include <crypto/polyval.h>
#include <crypto/utils.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>

#define POLYVAL_ALIGN 16
#define POLYVAL_ALIGN_ATTR __aligned(POLYVAL_ALIGN)
#define POLYVAL_ALIGN_EXTRA ((POLYVAL_ALIGN - 1) & ~(CRYPTO_MINALIGN - 1))
#define POLYVAL_CTX_SIZE (sizeof(struct polyval_tfm_ctx) + POLYVAL_ALIGN_EXTRA)
#define NUM_KEY_POWERS 8

struct polyval_tfm_ctx {
 /*
 * These powers must be in the order h^8, ..., h^1.
 */

 u8 key_powers[NUM_KEY_POWERS][POLYVAL_BLOCK_SIZE] POLYVAL_ALIGN_ATTR;
};

struct polyval_desc_ctx {
 u8 buffer[POLYVAL_BLOCK_SIZE];
};

asmlinkage void clmul_polyval_update(const struct polyval_tfm_ctx *keys,
 const u8 *in, size_t nblocks, u8 *accumulator);
asmlinkage void clmul_polyval_mul(u8 *op1, const u8 *op2);

static inline struct polyval_tfm_ctx *polyval_tfm_ctx(struct crypto_shash *tfm)
{
 return PTR_ALIGN(crypto_shash_ctx(tfm), POLYVAL_ALIGN);
}

static void internal_polyval_update(const struct polyval_tfm_ctx *keys,
 const u8 *in, size_t nblocks, u8 *accumulator)
{
 kernel_fpu_begin();
 clmul_polyval_update(keys, in, nblocks, accumulator);
 kernel_fpu_end();
}

static void internal_polyval_mul(u8 *op1, const u8 *op2)
{
 kernel_fpu_begin();
 clmul_polyval_mul(op1, op2);
 kernel_fpu_end();
}

static int polyval_x86_setkey(struct crypto_shash *tfm,
   const u8 *key, unsigned int keylen)
{
 struct polyval_tfm_ctx *tctx = polyval_tfm_ctx(tfm);
 int i;

 if (keylen != POLYVAL_BLOCK_SIZE)
  return -EINVAL;

 memcpy(tctx->key_powers[NUM_KEY_POWERS-1], key, POLYVAL_BLOCK_SIZE);

 for (i = NUM_KEY_POWERS-2; i >= 0; i--) {
  memcpy(tctx->key_powers[i], key, POLYVAL_BLOCK_SIZE);
  internal_polyval_mul(tctx->key_powers[i],
         tctx->key_powers[i+1]);
 }

 return 0;
}

static int polyval_x86_init(struct shash_desc *desc)
{
 struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);

 memset(dctx, 0, sizeof(*dctx));

 return 0;
}

static int polyval_x86_update(struct shash_desc *desc,
    const u8 *src, unsigned int srclen)
{
 struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
 const struct polyval_tfm_ctx *tctx = polyval_tfm_ctx(desc->tfm);
 unsigned int nblocks;

 do {
  /* Allow rescheduling every 4K bytes. */
  nblocks = min(srclen, 4096U) / POLYVAL_BLOCK_SIZE;
  internal_polyval_update(tctx, src, nblocks, dctx->buffer);
  srclen -= nblocks * POLYVAL_BLOCK_SIZE;
  src += nblocks * POLYVAL_BLOCK_SIZE;
 } while (srclen >= POLYVAL_BLOCK_SIZE);

 return srclen;
}

static int polyval_x86_finup(struct shash_desc *desc, const u8 *src,
        unsigned int len, u8 *dst)
{
 struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
 const struct polyval_tfm_ctx *tctx = polyval_tfm_ctx(desc->tfm);

 if (len) {
  crypto_xor(dctx->buffer, src, len);
  internal_polyval_mul(dctx->buffer,
         tctx->key_powers[NUM_KEY_POWERS-1]);
 }

 memcpy(dst, dctx->buffer, POLYVAL_BLOCK_SIZE);

 return 0;
}

static struct shash_alg polyval_alg = {
 .digestsize = POLYVAL_DIGEST_SIZE,
 .init  = polyval_x86_init,
 .update  = polyval_x86_update,
 .finup  = polyval_x86_finup,
 .setkey  = polyval_x86_setkey,
 .descsize = sizeof(struct polyval_desc_ctx),
 .base  = {
  .cra_name  = "polyval",
  .cra_driver_name = "polyval-clmulni",
  .cra_priority  = 200,
  .cra_flags  = CRYPTO_AHASH_ALG_BLOCK_ONLY,
  .cra_blocksize  = POLYVAL_BLOCK_SIZE,
  .cra_ctxsize  = POLYVAL_CTX_SIZE,
  .cra_module  = THIS_MODULE,
 },
};

__maybe_unused static const struct x86_cpu_id pcmul_cpu_id[] = {
 X86_MATCH_FEATURE(X86_FEATURE_PCLMULQDQ, NULL),
 {}
};
MODULE_DEVICE_TABLE(x86cpu, pcmul_cpu_id);

static int __init polyval_clmulni_mod_init(void)
{
 if (!x86_match_cpu(pcmul_cpu_id))
  return -ENODEV;

 if (!boot_cpu_has(X86_FEATURE_AVX))
  return -ENODEV;

 return crypto_register_shash(&polyval_alg);
}

static void __exit polyval_clmulni_mod_exit(void)
{
 crypto_unregister_shash(&polyval_alg);
}

module_init(polyval_clmulni_mod_init);
module_exit(polyval_clmulni_mod_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("POLYVAL hash function accelerated by PCLMULQDQ-NI");
MODULE_ALIAS_CRYPTO("polyval");
MODULE_ALIAS_CRYPTO("polyval-clmulni");

Messung V0.5
C=97 H=94 G=95

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.