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