Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Cryptographic API.
0004  *
0005  * SHA1 Secure Hash Algorithm.
0006  *
0007  * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
0008  *
0009  * Based on crypto/sha1_generic.c, which is:
0010  *
0011  * Copyright (c) Alan Smithee.
0012  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
0013  * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
0014  */
0015 
0016 #include <linux/mm.h>
0017 #include <crypto/sha1.h>
0018 #include <crypto/sha1_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_sha1_store_hash(struct sha1_state *sctx)
0033 {
0034     u64 *hash = (u64 *)sctx->state;
0035     union {
0036         u32 word[2];
0037         u64 dword;
0038     } hash_tail = { { sctx->state[4], } };
0039 
0040     write_octeon_64bit_hash_dword(hash[0], 0);
0041     write_octeon_64bit_hash_dword(hash[1], 1);
0042     write_octeon_64bit_hash_dword(hash_tail.dword, 2);
0043     memzero_explicit(&hash_tail.word[0], sizeof(hash_tail.word[0]));
0044 }
0045 
0046 static void octeon_sha1_read_hash(struct sha1_state *sctx)
0047 {
0048     u64 *hash = (u64 *)sctx->state;
0049     union {
0050         u32 word[2];
0051         u64 dword;
0052     } hash_tail;
0053 
0054     hash[0]     = read_octeon_64bit_hash_dword(0);
0055     hash[1]     = read_octeon_64bit_hash_dword(1);
0056     hash_tail.dword = read_octeon_64bit_hash_dword(2);
0057     sctx->state[4]  = hash_tail.word[0];
0058     memzero_explicit(&hash_tail.dword, sizeof(hash_tail.dword));
0059 }
0060 
0061 static void octeon_sha1_transform(const void *_block)
0062 {
0063     const u64 *block = _block;
0064 
0065     write_octeon_64bit_block_dword(block[0], 0);
0066     write_octeon_64bit_block_dword(block[1], 1);
0067     write_octeon_64bit_block_dword(block[2], 2);
0068     write_octeon_64bit_block_dword(block[3], 3);
0069     write_octeon_64bit_block_dword(block[4], 4);
0070     write_octeon_64bit_block_dword(block[5], 5);
0071     write_octeon_64bit_block_dword(block[6], 6);
0072     octeon_sha1_start(block[7]);
0073 }
0074 
0075 static void __octeon_sha1_update(struct sha1_state *sctx, const u8 *data,
0076                  unsigned int len)
0077 {
0078     unsigned int partial;
0079     unsigned int done;
0080     const u8 *src;
0081 
0082     partial = sctx->count % SHA1_BLOCK_SIZE;
0083     sctx->count += len;
0084     done = 0;
0085     src = data;
0086 
0087     if ((partial + len) >= SHA1_BLOCK_SIZE) {
0088         if (partial) {
0089             done = -partial;
0090             memcpy(sctx->buffer + partial, data,
0091                    done + SHA1_BLOCK_SIZE);
0092             src = sctx->buffer;
0093         }
0094 
0095         do {
0096             octeon_sha1_transform(src);
0097             done += SHA1_BLOCK_SIZE;
0098             src = data + done;
0099         } while (done + SHA1_BLOCK_SIZE <= len);
0100 
0101         partial = 0;
0102     }
0103     memcpy(sctx->buffer + partial, src, len - done);
0104 }
0105 
0106 static int octeon_sha1_update(struct shash_desc *desc, const u8 *data,
0107             unsigned int len)
0108 {
0109     struct sha1_state *sctx = shash_desc_ctx(desc);
0110     struct octeon_cop2_state state;
0111     unsigned long flags;
0112 
0113     /*
0114      * Small updates never reach the crypto engine, so the generic sha1 is
0115      * faster because of the heavyweight octeon_crypto_enable() /
0116      * octeon_crypto_disable().
0117      */
0118     if ((sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
0119         return crypto_sha1_update(desc, data, len);
0120 
0121     flags = octeon_crypto_enable(&state);
0122     octeon_sha1_store_hash(sctx);
0123 
0124     __octeon_sha1_update(sctx, data, len);
0125 
0126     octeon_sha1_read_hash(sctx);
0127     octeon_crypto_disable(&state, flags);
0128 
0129     return 0;
0130 }
0131 
0132 static int octeon_sha1_final(struct shash_desc *desc, u8 *out)
0133 {
0134     struct sha1_state *sctx = shash_desc_ctx(desc);
0135     static const u8 padding[64] = { 0x80, };
0136     struct octeon_cop2_state state;
0137     __be32 *dst = (__be32 *)out;
0138     unsigned int pad_len;
0139     unsigned long flags;
0140     unsigned int index;
0141     __be64 bits;
0142     int i;
0143 
0144     /* Save number of bits. */
0145     bits = cpu_to_be64(sctx->count << 3);
0146 
0147     /* Pad out to 56 mod 64. */
0148     index = sctx->count & 0x3f;
0149     pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
0150 
0151     flags = octeon_crypto_enable(&state);
0152     octeon_sha1_store_hash(sctx);
0153 
0154     __octeon_sha1_update(sctx, padding, pad_len);
0155 
0156     /* Append length (before padding). */
0157     __octeon_sha1_update(sctx, (const u8 *)&bits, sizeof(bits));
0158 
0159     octeon_sha1_read_hash(sctx);
0160     octeon_crypto_disable(&state, flags);
0161 
0162     /* Store state in digest */
0163     for (i = 0; i < 5; i++)
0164         dst[i] = cpu_to_be32(sctx->state[i]);
0165 
0166     /* Zeroize sensitive information. */
0167     memset(sctx, 0, sizeof(*sctx));
0168 
0169     return 0;
0170 }
0171 
0172 static int octeon_sha1_export(struct shash_desc *desc, void *out)
0173 {
0174     struct sha1_state *sctx = shash_desc_ctx(desc);
0175 
0176     memcpy(out, sctx, sizeof(*sctx));
0177     return 0;
0178 }
0179 
0180 static int octeon_sha1_import(struct shash_desc *desc, const void *in)
0181 {
0182     struct sha1_state *sctx = shash_desc_ctx(desc);
0183 
0184     memcpy(sctx, in, sizeof(*sctx));
0185     return 0;
0186 }
0187 
0188 static struct shash_alg octeon_sha1_alg = {
0189     .digestsize =   SHA1_DIGEST_SIZE,
0190     .init       =   sha1_base_init,
0191     .update     =   octeon_sha1_update,
0192     .final      =   octeon_sha1_final,
0193     .export     =   octeon_sha1_export,
0194     .import     =   octeon_sha1_import,
0195     .descsize   =   sizeof(struct sha1_state),
0196     .statesize  =   sizeof(struct sha1_state),
0197     .base       =   {
0198         .cra_name   =   "sha1",
0199         .cra_driver_name=   "octeon-sha1",
0200         .cra_priority   =   OCTEON_CR_OPCODE_PRIORITY,
0201         .cra_blocksize  =   SHA1_BLOCK_SIZE,
0202         .cra_module =   THIS_MODULE,
0203     }
0204 };
0205 
0206 static int __init octeon_sha1_mod_init(void)
0207 {
0208     if (!octeon_has_crypto())
0209         return -ENOTSUPP;
0210     return crypto_register_shash(&octeon_sha1_alg);
0211 }
0212 
0213 static void __exit octeon_sha1_mod_fini(void)
0214 {
0215     crypto_unregister_shash(&octeon_sha1_alg);
0216 }
0217 
0218 module_init(octeon_sha1_mod_init);
0219 module_exit(octeon_sha1_mod_fini);
0220 
0221 MODULE_LICENSE("GPL");
0222 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (OCTEON)");
0223 MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");