1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Glue code for SHA1 hashing optimized for sparc64 crypto opcodes.
3  *
4  * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
5  *
6  * Copyright (c) Alan Smithee.
7  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
8  * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
9  * Copyright (c) Mathias Krause <minipli@googlemail.com>
10  */
11 
12 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
13 
14 #include <asm/elf.h>
15 #include <asm/opcodes.h>
16 #include <asm/pstate.h>
17 #include <crypto/internal/hash.h>
18 #include <crypto/sha1.h>
19 #include <crypto/sha1_base.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 
23 asmlinkage void sha1_sparc64_transform(struct sha1_state *digest,
24 				       const u8 *data, int rounds);
25 
26 static int sha1_sparc64_update(struct shash_desc *desc, const u8 *data,
27 			       unsigned int len)
28 {
29 	return sha1_base_do_update_blocks(desc, data, len,
30 					  sha1_sparc64_transform);
31 }
32 
33 /* Add padding and return the message digest. */
34 static int sha1_sparc64_finup(struct shash_desc *desc, const u8 *src,
35 			      unsigned int len, u8 *out)
36 {
37 	sha1_base_do_finup(desc, src, len, sha1_sparc64_transform);
38 	return sha1_base_finish(desc, out);
39 }
40 
41 static struct shash_alg alg = {
42 	.digestsize	=	SHA1_DIGEST_SIZE,
43 	.init		=	sha1_base_init,
44 	.update		=	sha1_sparc64_update,
45 	.finup		=	sha1_sparc64_finup,
46 	.descsize	=	SHA1_STATE_SIZE,
47 	.base		=	{
48 		.cra_name	=	"sha1",
49 		.cra_driver_name=	"sha1-sparc64",
50 		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
51 		.cra_flags	=	CRYPTO_AHASH_ALG_BLOCK_ONLY,
52 		.cra_blocksize	=	SHA1_BLOCK_SIZE,
53 		.cra_module	=	THIS_MODULE,
54 	}
55 };
56 
57 static bool __init sparc64_has_sha1_opcode(void)
58 {
59 	unsigned long cfr;
60 
61 	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
62 		return false;
63 
64 	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
65 	if (!(cfr & CFR_SHA1))
66 		return false;
67 
68 	return true;
69 }
70 
71 static int __init sha1_sparc64_mod_init(void)
72 {
73 	if (sparc64_has_sha1_opcode()) {
74 		pr_info("Using sparc64 sha1 opcode optimized SHA-1 implementation\n");
75 		return crypto_register_shash(&alg);
76 	}
77 	pr_info("sparc64 sha1 opcode not available.\n");
78 	return -ENODEV;
79 }
80 
81 static void __exit sha1_sparc64_mod_fini(void)
82 {
83 	crypto_unregister_shash(&alg);
84 }
85 
86 module_init(sha1_sparc64_mod_init);
87 module_exit(sha1_sparc64_mod_fini);
88 
89 MODULE_LICENSE("GPL");
90 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
91 
92 MODULE_ALIAS_CRYPTO("sha1");
93 
94 #include "crop_devid.c"
95