1 // SPDX-License-Identifier: GPL-2.0-or-later !! 1 // SPDX-License-Identifier: GPL-2.0-only 2 /* !! 2 /* Glue code for SHA1 hashing optimized for sparc64 crypto opcodes. 3 * Cryptographic API. << 4 * Glue code for the SHA1 Secure Hash Algorith << 5 * 3 * 6 * This file is based on sha1_generic.c and sh !! 4 * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c 7 * 5 * 8 * Copyright (c) Alan Smithee. 6 * Copyright (c) Alan Smithee. 9 * Copyright (c) Andrew McDonald <andrew@mcdon 7 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 10 * Copyright (c) Jean-Francois Dive <jef@linux 8 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 11 * Copyright (c) Mathias Krause <minipli@googl 9 * Copyright (c) Mathias Krause <minipli@googlemail.com> 12 */ 10 */ 13 11 >> 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt >> 13 14 #include <crypto/internal/hash.h> 14 #include <crypto/internal/hash.h> 15 #include <linux/init.h> 15 #include <linux/init.h> 16 #include <linux/module.h> 16 #include <linux/module.h> >> 17 #include <linux/mm.h> 17 #include <linux/types.h> 18 #include <linux/types.h> 18 #include <crypto/sha1.h> 19 #include <crypto/sha1.h> 19 #include <crypto/sha1_base.h> 20 #include <crypto/sha1_base.h> 20 #include <asm/byteorder.h> << 21 21 22 #include "sha1.h" !! 22 #include <asm/pstate.h> >> 23 #include <asm/elf.h> >> 24 >> 25 #include "opcodes.h" >> 26 >> 27 asmlinkage void sha1_sparc64_transform(u32 *digest, const char *data, >> 28 unsigned int rounds); >> 29 >> 30 static void __sha1_sparc64_update(struct sha1_state *sctx, const u8 *data, >> 31 unsigned int len, unsigned int partial) >> 32 { >> 33 unsigned int done = 0; >> 34 >> 35 sctx->count += len; >> 36 if (partial) { >> 37 done = SHA1_BLOCK_SIZE - partial; >> 38 memcpy(sctx->buffer + partial, data, done); >> 39 sha1_sparc64_transform(sctx->state, sctx->buffer, 1); >> 40 } >> 41 if (len - done >= SHA1_BLOCK_SIZE) { >> 42 const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE; >> 43 >> 44 sha1_sparc64_transform(sctx->state, data + done, rounds); >> 45 done += rounds * SHA1_BLOCK_SIZE; >> 46 } >> 47 >> 48 memcpy(sctx->buffer, data + done, len - done); >> 49 } >> 50 >> 51 static int sha1_sparc64_update(struct shash_desc *desc, const u8 *data, >> 52 unsigned int len) >> 53 { >> 54 struct sha1_state *sctx = shash_desc_ctx(desc); >> 55 unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; >> 56 >> 57 /* Handle the fast case right here */ >> 58 if (partial + len < SHA1_BLOCK_SIZE) { >> 59 sctx->count += len; >> 60 memcpy(sctx->buffer + partial, data, len); >> 61 } else >> 62 __sha1_sparc64_update(sctx, data, len, partial); 23 63 24 asmlinkage void sha1_block_data_order(struct s !! 64 return 0; 25 const u8 *data, int rounds); !! 65 } 26 66 27 int sha1_update_arm(struct shash_desc *desc, c !! 67 /* Add padding and return the message digest. */ 28 unsigned int len) !! 68 static int sha1_sparc64_final(struct shash_desc *desc, u8 *out) 29 { 69 { 30 /* make sure signature matches sha1_bl !! 70 struct sha1_state *sctx = shash_desc_ctx(desc); 31 BUILD_BUG_ON(offsetof(struct sha1_stat !! 71 unsigned int i, index, padlen; >> 72 __be32 *dst = (__be32 *)out; >> 73 __be64 bits; >> 74 static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; >> 75 >> 76 bits = cpu_to_be64(sctx->count << 3); >> 77 >> 78 /* Pad out to 56 mod 64 and append length */ >> 79 index = sctx->count % SHA1_BLOCK_SIZE; >> 80 padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index); >> 81 >> 82 /* We need to fill a whole block for __sha1_sparc64_update() */ >> 83 if (padlen <= 56) { >> 84 sctx->count += padlen; >> 85 memcpy(sctx->buffer + index, padding, padlen); >> 86 } else { >> 87 __sha1_sparc64_update(sctx, padding, padlen, index); >> 88 } >> 89 __sha1_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56); 32 90 33 return sha1_base_do_update(desc, data, !! 91 /* Store state in digest */ >> 92 for (i = 0; i < 5; i++) >> 93 dst[i] = cpu_to_be32(sctx->state[i]); >> 94 >> 95 /* Wipe context */ >> 96 memset(sctx, 0, sizeof(*sctx)); >> 97 >> 98 return 0; 34 } 99 } 35 EXPORT_SYMBOL_GPL(sha1_update_arm); << 36 100 37 static int sha1_final(struct shash_desc *desc, !! 101 static int sha1_sparc64_export(struct shash_desc *desc, void *out) 38 { 102 { 39 sha1_base_do_finalize(desc, sha1_block !! 103 struct sha1_state *sctx = shash_desc_ctx(desc); 40 return sha1_base_finish(desc, out); !! 104 >> 105 memcpy(out, sctx, sizeof(*sctx)); >> 106 >> 107 return 0; 41 } 108 } 42 109 43 int sha1_finup_arm(struct shash_desc *desc, co !! 110 static int sha1_sparc64_import(struct shash_desc *desc, const void *in) 44 unsigned int len, u8 *out) << 45 { 111 { 46 sha1_base_do_update(desc, data, len, s !! 112 struct sha1_state *sctx = shash_desc_ctx(desc); 47 return sha1_final(desc, out); !! 113 >> 114 memcpy(sctx, in, sizeof(*sctx)); >> 115 >> 116 return 0; 48 } 117 } 49 EXPORT_SYMBOL_GPL(sha1_finup_arm); << 50 118 51 static struct shash_alg alg = { 119 static struct shash_alg alg = { 52 .digestsize = SHA1_DIGEST_SI 120 .digestsize = SHA1_DIGEST_SIZE, 53 .init = sha1_base_init 121 .init = sha1_base_init, 54 .update = sha1_update_ar !! 122 .update = sha1_sparc64_update, 55 .final = sha1_final, !! 123 .final = sha1_sparc64_final, 56 .finup = sha1_finup_arm !! 124 .export = sha1_sparc64_export, >> 125 .import = sha1_sparc64_import, 57 .descsize = sizeof(struct 126 .descsize = sizeof(struct sha1_state), >> 127 .statesize = sizeof(struct sha1_state), 58 .base = { 128 .base = { 59 .cra_name = "sha1" 129 .cra_name = "sha1", 60 .cra_driver_name= "sha1- !! 130 .cra_driver_name= "sha1-sparc64", 61 .cra_priority = 150, !! 131 .cra_priority = SPARC_CR_OPCODE_PRIORITY, 62 .cra_blocksize = SHA1_B 132 .cra_blocksize = SHA1_BLOCK_SIZE, 63 .cra_module = THIS_M 133 .cra_module = THIS_MODULE, 64 } 134 } 65 }; 135 }; 66 136 67 !! 137 static bool __init sparc64_has_sha1_opcode(void) 68 static int __init sha1_mod_init(void) << 69 { 138 { 70 return crypto_register_shash(&alg); !! 139 unsigned long cfr; >> 140 >> 141 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) >> 142 return false; >> 143 >> 144 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); >> 145 if (!(cfr & CFR_SHA1)) >> 146 return false; >> 147 >> 148 return true; 71 } 149 } 72 150 >> 151 static int __init sha1_sparc64_mod_init(void) >> 152 { >> 153 if (sparc64_has_sha1_opcode()) { >> 154 pr_info("Using sparc64 sha1 opcode optimized SHA-1 implementation\n"); >> 155 return crypto_register_shash(&alg); >> 156 } >> 157 pr_info("sparc64 sha1 opcode not available.\n"); >> 158 return -ENODEV; >> 159 } 73 160 74 static void __exit sha1_mod_fini(void) !! 161 static void __exit sha1_sparc64_mod_fini(void) 75 { 162 { 76 crypto_unregister_shash(&alg); 163 crypto_unregister_shash(&alg); 77 } 164 } 78 165 79 !! 166 module_init(sha1_sparc64_mod_init); 80 module_init(sha1_mod_init); !! 167 module_exit(sha1_sparc64_mod_fini); 81 module_exit(sha1_mod_fini); << 82 168 83 MODULE_LICENSE("GPL"); 169 MODULE_LICENSE("GPL"); 84 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm !! 170 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated"); >> 171 85 MODULE_ALIAS_CRYPTO("sha1"); 172 MODULE_ALIAS_CRYPTO("sha1"); 86 MODULE_AUTHOR("David McCullough <ucdevel@gmail !! 173 >> 174 #include "crop_devid.c" 87 175
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.