octeon-sha256.c (6144B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Cryptographic API. 4 * 5 * SHA-224 and SHA-256 Secure Hash Algorithm. 6 * 7 * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>. 8 * 9 * Based on crypto/sha256_generic.c, which is: 10 * 11 * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> 12 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 13 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 14 * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com> 15 */ 16 17#include <linux/mm.h> 18#include <crypto/sha2.h> 19#include <crypto/sha256_base.h> 20#include <linux/init.h> 21#include <linux/types.h> 22#include <linux/module.h> 23#include <asm/byteorder.h> 24#include <asm/octeon/octeon.h> 25#include <crypto/internal/hash.h> 26 27#include "octeon-crypto.h" 28 29/* 30 * We pass everything as 64-bit. OCTEON can handle misaligned data. 31 */ 32 33static void octeon_sha256_store_hash(struct sha256_state *sctx) 34{ 35 u64 *hash = (u64 *)sctx->state; 36 37 write_octeon_64bit_hash_dword(hash[0], 0); 38 write_octeon_64bit_hash_dword(hash[1], 1); 39 write_octeon_64bit_hash_dword(hash[2], 2); 40 write_octeon_64bit_hash_dword(hash[3], 3); 41} 42 43static void octeon_sha256_read_hash(struct sha256_state *sctx) 44{ 45 u64 *hash = (u64 *)sctx->state; 46 47 hash[0] = read_octeon_64bit_hash_dword(0); 48 hash[1] = read_octeon_64bit_hash_dword(1); 49 hash[2] = read_octeon_64bit_hash_dword(2); 50 hash[3] = read_octeon_64bit_hash_dword(3); 51} 52 53static void octeon_sha256_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_sha256_start(block[7]); 65} 66 67static void __octeon_sha256_update(struct sha256_state *sctx, const u8 *data, 68 unsigned int len) 69{ 70 unsigned int partial; 71 unsigned int done; 72 const u8 *src; 73 74 partial = sctx->count % SHA256_BLOCK_SIZE; 75 sctx->count += len; 76 done = 0; 77 src = data; 78 79 if ((partial + len) >= SHA256_BLOCK_SIZE) { 80 if (partial) { 81 done = -partial; 82 memcpy(sctx->buf + partial, data, 83 done + SHA256_BLOCK_SIZE); 84 src = sctx->buf; 85 } 86 87 do { 88 octeon_sha256_transform(src); 89 done += SHA256_BLOCK_SIZE; 90 src = data + done; 91 } while (done + SHA256_BLOCK_SIZE <= len); 92 93 partial = 0; 94 } 95 memcpy(sctx->buf + partial, src, len - done); 96} 97 98static int octeon_sha256_update(struct shash_desc *desc, const u8 *data, 99 unsigned int len) 100{ 101 struct sha256_state *sctx = shash_desc_ctx(desc); 102 struct octeon_cop2_state state; 103 unsigned long flags; 104 105 /* 106 * Small updates never reach the crypto engine, so the generic sha256 is 107 * faster because of the heavyweight octeon_crypto_enable() / 108 * octeon_crypto_disable(). 109 */ 110 if ((sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE) 111 return crypto_sha256_update(desc, data, len); 112 113 flags = octeon_crypto_enable(&state); 114 octeon_sha256_store_hash(sctx); 115 116 __octeon_sha256_update(sctx, data, len); 117 118 octeon_sha256_read_hash(sctx); 119 octeon_crypto_disable(&state, flags); 120 121 return 0; 122} 123 124static int octeon_sha256_final(struct shash_desc *desc, u8 *out) 125{ 126 struct sha256_state *sctx = shash_desc_ctx(desc); 127 static const u8 padding[64] = { 0x80, }; 128 struct octeon_cop2_state state; 129 __be32 *dst = (__be32 *)out; 130 unsigned int pad_len; 131 unsigned long flags; 132 unsigned int index; 133 __be64 bits; 134 int i; 135 136 /* Save number of bits. */ 137 bits = cpu_to_be64(sctx->count << 3); 138 139 /* Pad out to 56 mod 64. */ 140 index = sctx->count & 0x3f; 141 pad_len = (index < 56) ? (56 - index) : ((64+56) - index); 142 143 flags = octeon_crypto_enable(&state); 144 octeon_sha256_store_hash(sctx); 145 146 __octeon_sha256_update(sctx, padding, pad_len); 147 148 /* Append length (before padding). */ 149 __octeon_sha256_update(sctx, (const u8 *)&bits, sizeof(bits)); 150 151 octeon_sha256_read_hash(sctx); 152 octeon_crypto_disable(&state, flags); 153 154 /* Store state in digest */ 155 for (i = 0; i < 8; i++) 156 dst[i] = cpu_to_be32(sctx->state[i]); 157 158 /* Zeroize sensitive information. */ 159 memset(sctx, 0, sizeof(*sctx)); 160 161 return 0; 162} 163 164static int octeon_sha224_final(struct shash_desc *desc, u8 *hash) 165{ 166 u8 D[SHA256_DIGEST_SIZE]; 167 168 octeon_sha256_final(desc, D); 169 170 memcpy(hash, D, SHA224_DIGEST_SIZE); 171 memzero_explicit(D, SHA256_DIGEST_SIZE); 172 173 return 0; 174} 175 176static int octeon_sha256_export(struct shash_desc *desc, void *out) 177{ 178 struct sha256_state *sctx = shash_desc_ctx(desc); 179 180 memcpy(out, sctx, sizeof(*sctx)); 181 return 0; 182} 183 184static int octeon_sha256_import(struct shash_desc *desc, const void *in) 185{ 186 struct sha256_state *sctx = shash_desc_ctx(desc); 187 188 memcpy(sctx, in, sizeof(*sctx)); 189 return 0; 190} 191 192static struct shash_alg octeon_sha256_algs[2] = { { 193 .digestsize = SHA256_DIGEST_SIZE, 194 .init = sha256_base_init, 195 .update = octeon_sha256_update, 196 .final = octeon_sha256_final, 197 .export = octeon_sha256_export, 198 .import = octeon_sha256_import, 199 .descsize = sizeof(struct sha256_state), 200 .statesize = sizeof(struct sha256_state), 201 .base = { 202 .cra_name = "sha256", 203 .cra_driver_name= "octeon-sha256", 204 .cra_priority = OCTEON_CR_OPCODE_PRIORITY, 205 .cra_blocksize = SHA256_BLOCK_SIZE, 206 .cra_module = THIS_MODULE, 207 } 208}, { 209 .digestsize = SHA224_DIGEST_SIZE, 210 .init = sha224_base_init, 211 .update = octeon_sha256_update, 212 .final = octeon_sha224_final, 213 .descsize = sizeof(struct sha256_state), 214 .base = { 215 .cra_name = "sha224", 216 .cra_driver_name= "octeon-sha224", 217 .cra_blocksize = SHA224_BLOCK_SIZE, 218 .cra_module = THIS_MODULE, 219 } 220} }; 221 222static int __init octeon_sha256_mod_init(void) 223{ 224 if (!octeon_has_crypto()) 225 return -ENOTSUPP; 226 return crypto_register_shashes(octeon_sha256_algs, 227 ARRAY_SIZE(octeon_sha256_algs)); 228} 229 230static void __exit octeon_sha256_mod_fini(void) 231{ 232 crypto_unregister_shashes(octeon_sha256_algs, 233 ARRAY_SIZE(octeon_sha256_algs)); 234} 235 236module_init(octeon_sha256_mod_init); 237module_exit(octeon_sha256_mod_fini); 238 239MODULE_LICENSE("GPL"); 240MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm (OCTEON)"); 241MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");