Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Cryptographic API.
0004  *
0005  * SHA-512 and SHA-384 Secure Hash Algorithm.
0006  *
0007  * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
0008  *
0009  * Based on crypto/sha512_generic.c, which is:
0010  *
0011  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
0012  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
0013  * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
0014  */
0015 
0016 #include <linux/mm.h>
0017 #include <crypto/sha2.h>
0018 #include <crypto/sha512_base.h>
0019 #include <linux/init.h>
0020 #include <linux/types.h>
0021 #include <linux/module.h>
0022 #include <asm/byteorder.h>
0023 #include <asm/octeon/octeon.h>
0024 #include <crypto/internal/hash.h>
0025 
0026 #include "octeon-crypto.h"
0027 
0028 /*
0029  * We pass everything as 64-bit. OCTEON can handle misaligned data.
0030  */
0031 
0032 static void octeon_sha512_store_hash(struct sha512_state *sctx)
0033 {
0034     write_octeon_64bit_hash_sha512(sctx->state[0], 0);
0035     write_octeon_64bit_hash_sha512(sctx->state[1], 1);
0036     write_octeon_64bit_hash_sha512(sctx->state[2], 2);
0037     write_octeon_64bit_hash_sha512(sctx->state[3], 3);
0038     write_octeon_64bit_hash_sha512(sctx->state[4], 4);
0039     write_octeon_64bit_hash_sha512(sctx->state[5], 5);
0040     write_octeon_64bit_hash_sha512(sctx->state[6], 6);
0041     write_octeon_64bit_hash_sha512(sctx->state[7], 7);
0042 }
0043 
0044 static void octeon_sha512_read_hash(struct sha512_state *sctx)
0045 {
0046     sctx->state[0] = read_octeon_64bit_hash_sha512(0);
0047     sctx->state[1] = read_octeon_64bit_hash_sha512(1);
0048     sctx->state[2] = read_octeon_64bit_hash_sha512(2);
0049     sctx->state[3] = read_octeon_64bit_hash_sha512(3);
0050     sctx->state[4] = read_octeon_64bit_hash_sha512(4);
0051     sctx->state[5] = read_octeon_64bit_hash_sha512(5);
0052     sctx->state[6] = read_octeon_64bit_hash_sha512(6);
0053     sctx->state[7] = read_octeon_64bit_hash_sha512(7);
0054 }
0055 
0056 static void octeon_sha512_transform(const void *_block)
0057 {
0058     const u64 *block = _block;
0059 
0060     write_octeon_64bit_block_sha512(block[0], 0);
0061     write_octeon_64bit_block_sha512(block[1], 1);
0062     write_octeon_64bit_block_sha512(block[2], 2);
0063     write_octeon_64bit_block_sha512(block[3], 3);
0064     write_octeon_64bit_block_sha512(block[4], 4);
0065     write_octeon_64bit_block_sha512(block[5], 5);
0066     write_octeon_64bit_block_sha512(block[6], 6);
0067     write_octeon_64bit_block_sha512(block[7], 7);
0068     write_octeon_64bit_block_sha512(block[8], 8);
0069     write_octeon_64bit_block_sha512(block[9], 9);
0070     write_octeon_64bit_block_sha512(block[10], 10);
0071     write_octeon_64bit_block_sha512(block[11], 11);
0072     write_octeon_64bit_block_sha512(block[12], 12);
0073     write_octeon_64bit_block_sha512(block[13], 13);
0074     write_octeon_64bit_block_sha512(block[14], 14);
0075     octeon_sha512_start(block[15]);
0076 }
0077 
0078 static void __octeon_sha512_update(struct sha512_state *sctx, const u8 *data,
0079                    unsigned int len)
0080 {
0081     unsigned int part_len;
0082     unsigned int index;
0083     unsigned int i;
0084 
0085     /* Compute number of bytes mod 128. */
0086     index = sctx->count[0] % SHA512_BLOCK_SIZE;
0087 
0088     /* Update number of bytes. */
0089     if ((sctx->count[0] += len) < len)
0090         sctx->count[1]++;
0091 
0092     part_len = SHA512_BLOCK_SIZE - index;
0093 
0094     /* Transform as many times as possible. */
0095     if (len >= part_len) {
0096         memcpy(&sctx->buf[index], data, part_len);
0097         octeon_sha512_transform(sctx->buf);
0098 
0099         for (i = part_len; i + SHA512_BLOCK_SIZE <= len;
0100             i += SHA512_BLOCK_SIZE)
0101             octeon_sha512_transform(&data[i]);
0102 
0103         index = 0;
0104     } else {
0105         i = 0;
0106     }
0107 
0108     /* Buffer remaining input. */
0109     memcpy(&sctx->buf[index], &data[i], len - i);
0110 }
0111 
0112 static int octeon_sha512_update(struct shash_desc *desc, const u8 *data,
0113                 unsigned int len)
0114 {
0115     struct sha512_state *sctx = shash_desc_ctx(desc);
0116     struct octeon_cop2_state state;
0117     unsigned long flags;
0118 
0119     /*
0120      * Small updates never reach the crypto engine, so the generic sha512 is
0121      * faster because of the heavyweight octeon_crypto_enable() /
0122      * octeon_crypto_disable().
0123      */
0124     if ((sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE)
0125         return crypto_sha512_update(desc, data, len);
0126 
0127     flags = octeon_crypto_enable(&state);
0128     octeon_sha512_store_hash(sctx);
0129 
0130     __octeon_sha512_update(sctx, data, len);
0131 
0132     octeon_sha512_read_hash(sctx);
0133     octeon_crypto_disable(&state, flags);
0134 
0135     return 0;
0136 }
0137 
0138 static int octeon_sha512_final(struct shash_desc *desc, u8 *hash)
0139 {
0140     struct sha512_state *sctx = shash_desc_ctx(desc);
0141     static u8 padding[128] = { 0x80, };
0142     struct octeon_cop2_state state;
0143     __be64 *dst = (__be64 *)hash;
0144     unsigned int pad_len;
0145     unsigned long flags;
0146     unsigned int index;
0147     __be64 bits[2];
0148     int i;
0149 
0150     /* Save number of bits. */
0151     bits[1] = cpu_to_be64(sctx->count[0] << 3);
0152     bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
0153 
0154     /* Pad out to 112 mod 128. */
0155     index = sctx->count[0] & 0x7f;
0156     pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
0157 
0158     flags = octeon_crypto_enable(&state);
0159     octeon_sha512_store_hash(sctx);
0160 
0161     __octeon_sha512_update(sctx, padding, pad_len);
0162 
0163     /* Append length (before padding). */
0164     __octeon_sha512_update(sctx, (const u8 *)bits, sizeof(bits));
0165 
0166     octeon_sha512_read_hash(sctx);
0167     octeon_crypto_disable(&state, flags);
0168 
0169     /* Store state in digest. */
0170     for (i = 0; i < 8; i++)
0171         dst[i] = cpu_to_be64(sctx->state[i]);
0172 
0173     /* Zeroize sensitive information. */
0174     memset(sctx, 0, sizeof(struct sha512_state));
0175 
0176     return 0;
0177 }
0178 
0179 static int octeon_sha384_final(struct shash_desc *desc, u8 *hash)
0180 {
0181     u8 D[64];
0182 
0183     octeon_sha512_final(desc, D);
0184 
0185     memcpy(hash, D, 48);
0186     memzero_explicit(D, 64);
0187 
0188     return 0;
0189 }
0190 
0191 static struct shash_alg octeon_sha512_algs[2] = { {
0192     .digestsize =   SHA512_DIGEST_SIZE,
0193     .init       =   sha512_base_init,
0194     .update     =   octeon_sha512_update,
0195     .final      =   octeon_sha512_final,
0196     .descsize   =   sizeof(struct sha512_state),
0197     .base       =   {
0198         .cra_name   =   "sha512",
0199         .cra_driver_name=   "octeon-sha512",
0200         .cra_priority   =   OCTEON_CR_OPCODE_PRIORITY,
0201         .cra_blocksize  =   SHA512_BLOCK_SIZE,
0202         .cra_module =   THIS_MODULE,
0203     }
0204 }, {
0205     .digestsize =   SHA384_DIGEST_SIZE,
0206     .init       =   sha384_base_init,
0207     .update     =   octeon_sha512_update,
0208     .final      =   octeon_sha384_final,
0209     .descsize   =   sizeof(struct sha512_state),
0210     .base       =   {
0211         .cra_name   =   "sha384",
0212         .cra_driver_name=   "octeon-sha384",
0213         .cra_priority   =   OCTEON_CR_OPCODE_PRIORITY,
0214         .cra_blocksize  =   SHA384_BLOCK_SIZE,
0215         .cra_module =   THIS_MODULE,
0216     }
0217 } };
0218 
0219 static int __init octeon_sha512_mod_init(void)
0220 {
0221     if (!octeon_has_crypto())
0222         return -ENOTSUPP;
0223     return crypto_register_shashes(octeon_sha512_algs,
0224                        ARRAY_SIZE(octeon_sha512_algs));
0225 }
0226 
0227 static void __exit octeon_sha512_mod_fini(void)
0228 {
0229     crypto_unregister_shashes(octeon_sha512_algs,
0230                   ARRAY_SIZE(octeon_sha512_algs));
0231 }
0232 
0233 module_init(octeon_sha512_mod_init);
0234 module_exit(octeon_sha512_mod_fini);
0235 
0236 MODULE_LICENSE("GPL");
0237 MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms (OCTEON)");
0238 MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");