cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

octeon-md5.c (5041B)


      1/*
      2 * Cryptographic API.
      3 *
      4 * MD5 Message Digest Algorithm (RFC1321).
      5 *
      6 * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
      7 *
      8 * Based on crypto/md5.c, which is:
      9 *
     10 * Derived from cryptoapi implementation, originally based on the
     11 * public domain implementation written by Colin Plumb in 1993.
     12 *
     13 * Copyright (c) Cryptoapi developers.
     14 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
     15 *
     16 * This program is free software; you can redistribute it and/or modify it
     17 * under the terms of the GNU General Public License as published by the Free
     18 * Software Foundation; either version 2 of the License, or (at your option)
     19 * any later version.
     20 */
     21
     22#include <crypto/md5.h>
     23#include <linux/init.h>
     24#include <linux/types.h>
     25#include <linux/module.h>
     26#include <linux/string.h>
     27#include <asm/byteorder.h>
     28#include <asm/octeon/octeon.h>
     29#include <crypto/internal/hash.h>
     30
     31#include "octeon-crypto.h"
     32
     33/*
     34 * We pass everything as 64-bit. OCTEON can handle misaligned data.
     35 */
     36
     37static void octeon_md5_store_hash(struct md5_state *ctx)
     38{
     39	u64 *hash = (u64 *)ctx->hash;
     40
     41	write_octeon_64bit_hash_dword(hash[0], 0);
     42	write_octeon_64bit_hash_dword(hash[1], 1);
     43}
     44
     45static void octeon_md5_read_hash(struct md5_state *ctx)
     46{
     47	u64 *hash = (u64 *)ctx->hash;
     48
     49	hash[0] = read_octeon_64bit_hash_dword(0);
     50	hash[1] = read_octeon_64bit_hash_dword(1);
     51}
     52
     53static void octeon_md5_transform(const void *_block)
     54{
     55	const u64 *block = _block;
     56
     57	write_octeon_64bit_block_dword(block[0], 0);
     58	write_octeon_64bit_block_dword(block[1], 1);
     59	write_octeon_64bit_block_dword(block[2], 2);
     60	write_octeon_64bit_block_dword(block[3], 3);
     61	write_octeon_64bit_block_dword(block[4], 4);
     62	write_octeon_64bit_block_dword(block[5], 5);
     63	write_octeon_64bit_block_dword(block[6], 6);
     64	octeon_md5_start(block[7]);
     65}
     66
     67static int octeon_md5_init(struct shash_desc *desc)
     68{
     69	struct md5_state *mctx = shash_desc_ctx(desc);
     70
     71	mctx->hash[0] = MD5_H0;
     72	mctx->hash[1] = MD5_H1;
     73	mctx->hash[2] = MD5_H2;
     74	mctx->hash[3] = MD5_H3;
     75	cpu_to_le32_array(mctx->hash, 4);
     76	mctx->byte_count = 0;
     77
     78	return 0;
     79}
     80
     81static int octeon_md5_update(struct shash_desc *desc, const u8 *data,
     82			     unsigned int len)
     83{
     84	struct md5_state *mctx = shash_desc_ctx(desc);
     85	const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
     86	struct octeon_cop2_state state;
     87	unsigned long flags;
     88
     89	mctx->byte_count += len;
     90
     91	if (avail > len) {
     92		memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
     93		       data, len);
     94		return 0;
     95	}
     96
     97	memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data,
     98	       avail);
     99
    100	flags = octeon_crypto_enable(&state);
    101	octeon_md5_store_hash(mctx);
    102
    103	octeon_md5_transform(mctx->block);
    104	data += avail;
    105	len -= avail;
    106
    107	while (len >= sizeof(mctx->block)) {
    108		octeon_md5_transform(data);
    109		data += sizeof(mctx->block);
    110		len -= sizeof(mctx->block);
    111	}
    112
    113	octeon_md5_read_hash(mctx);
    114	octeon_crypto_disable(&state, flags);
    115
    116	memcpy(mctx->block, data, len);
    117
    118	return 0;
    119}
    120
    121static int octeon_md5_final(struct shash_desc *desc, u8 *out)
    122{
    123	struct md5_state *mctx = shash_desc_ctx(desc);
    124	const unsigned int offset = mctx->byte_count & 0x3f;
    125	char *p = (char *)mctx->block + offset;
    126	int padding = 56 - (offset + 1);
    127	struct octeon_cop2_state state;
    128	unsigned long flags;
    129
    130	*p++ = 0x80;
    131
    132	flags = octeon_crypto_enable(&state);
    133	octeon_md5_store_hash(mctx);
    134
    135	if (padding < 0) {
    136		memset(p, 0x00, padding + sizeof(u64));
    137		octeon_md5_transform(mctx->block);
    138		p = (char *)mctx->block;
    139		padding = 56;
    140	}
    141
    142	memset(p, 0, padding);
    143	mctx->block[14] = mctx->byte_count << 3;
    144	mctx->block[15] = mctx->byte_count >> 29;
    145	cpu_to_le32_array(mctx->block + 14, 2);
    146	octeon_md5_transform(mctx->block);
    147
    148	octeon_md5_read_hash(mctx);
    149	octeon_crypto_disable(&state, flags);
    150
    151	memcpy(out, mctx->hash, sizeof(mctx->hash));
    152	memset(mctx, 0, sizeof(*mctx));
    153
    154	return 0;
    155}
    156
    157static int octeon_md5_export(struct shash_desc *desc, void *out)
    158{
    159	struct md5_state *ctx = shash_desc_ctx(desc);
    160
    161	memcpy(out, ctx, sizeof(*ctx));
    162	return 0;
    163}
    164
    165static int octeon_md5_import(struct shash_desc *desc, const void *in)
    166{
    167	struct md5_state *ctx = shash_desc_ctx(desc);
    168
    169	memcpy(ctx, in, sizeof(*ctx));
    170	return 0;
    171}
    172
    173static struct shash_alg alg = {
    174	.digestsize	=	MD5_DIGEST_SIZE,
    175	.init		=	octeon_md5_init,
    176	.update		=	octeon_md5_update,
    177	.final		=	octeon_md5_final,
    178	.export		=	octeon_md5_export,
    179	.import		=	octeon_md5_import,
    180	.descsize	=	sizeof(struct md5_state),
    181	.statesize	=	sizeof(struct md5_state),
    182	.base		=	{
    183		.cra_name	=	"md5",
    184		.cra_driver_name=	"octeon-md5",
    185		.cra_priority	=	OCTEON_CR_OPCODE_PRIORITY,
    186		.cra_blocksize	=	MD5_HMAC_BLOCK_SIZE,
    187		.cra_module	=	THIS_MODULE,
    188	}
    189};
    190
    191static int __init md5_mod_init(void)
    192{
    193	if (!octeon_has_crypto())
    194		return -ENOTSUPP;
    195	return crypto_register_shash(&alg);
    196}
    197
    198static void __exit md5_mod_fini(void)
    199{
    200	crypto_unregister_shash(&alg);
    201}
    202
    203module_init(md5_mod_init);
    204module_exit(md5_mod_fini);
    205
    206MODULE_LICENSE("GPL");
    207MODULE_DESCRIPTION("MD5 Message Digest Algorithm (OCTEON)");
    208MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");