1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Cryptographic API. |
4 | * |
5 | * s390 implementation of the SHA512 and SHA384 Secure Hash Algorithm. |
6 | * |
7 | * Copyright IBM Corp. 2019 |
8 | * Author(s): Joerg Schmidbauer (jschmidb@de.ibm.com) |
9 | */ |
10 | #include <crypto/internal/hash.h> |
11 | #include <linux/init.h> |
12 | #include <linux/module.h> |
13 | #include <linux/cpufeature.h> |
14 | #include <crypto/sha3.h> |
15 | #include <asm/cpacf.h> |
16 | |
17 | #include "sha.h" |
18 | |
19 | static int sha3_512_init(struct shash_desc *desc) |
20 | { |
21 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
22 | |
23 | memset(sctx->state, 0, sizeof(sctx->state)); |
24 | sctx->count = 0; |
25 | sctx->func = CPACF_KIMD_SHA3_512; |
26 | |
27 | return 0; |
28 | } |
29 | |
30 | static int sha3_512_export(struct shash_desc *desc, void *out) |
31 | { |
32 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
33 | struct sha3_state *octx = out; |
34 | |
35 | octx->rsiz = sctx->count; |
36 | octx->rsizw = sctx->count >> 32; |
37 | |
38 | memcpy(octx->st, sctx->state, sizeof(octx->st)); |
39 | memcpy(octx->buf, sctx->buf, sizeof(octx->buf)); |
40 | |
41 | return 0; |
42 | } |
43 | |
44 | static int sha3_512_import(struct shash_desc *desc, const void *in) |
45 | { |
46 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
47 | const struct sha3_state *ictx = in; |
48 | |
49 | if (unlikely(ictx->rsizw)) |
50 | return -ERANGE; |
51 | sctx->count = ictx->rsiz; |
52 | |
53 | memcpy(sctx->state, ictx->st, sizeof(ictx->st)); |
54 | memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); |
55 | sctx->func = CPACF_KIMD_SHA3_512; |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | static int sha3_384_import(struct shash_desc *desc, const void *in) |
61 | { |
62 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
63 | const struct sha3_state *ictx = in; |
64 | |
65 | if (unlikely(ictx->rsizw)) |
66 | return -ERANGE; |
67 | sctx->count = ictx->rsiz; |
68 | |
69 | memcpy(sctx->state, ictx->st, sizeof(ictx->st)); |
70 | memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); |
71 | sctx->func = CPACF_KIMD_SHA3_384; |
72 | |
73 | return 0; |
74 | } |
75 | |
76 | static struct shash_alg sha3_512_alg = { |
77 | .digestsize = SHA3_512_DIGEST_SIZE, |
78 | .init = sha3_512_init, |
79 | .update = s390_sha_update, |
80 | .final = s390_sha_final, |
81 | .export = sha3_512_export, |
82 | .import = sha3_512_import, |
83 | .descsize = sizeof(struct s390_sha_ctx), |
84 | .statesize = sizeof(struct sha3_state), |
85 | .base = { |
86 | .cra_name = "sha3-512" , |
87 | .cra_driver_name = "sha3-512-s390" , |
88 | .cra_priority = 300, |
89 | .cra_blocksize = SHA3_512_BLOCK_SIZE, |
90 | .cra_module = THIS_MODULE, |
91 | } |
92 | }; |
93 | |
94 | MODULE_ALIAS_CRYPTO("sha3-512" ); |
95 | |
96 | static int sha3_384_init(struct shash_desc *desc) |
97 | { |
98 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
99 | |
100 | memset(sctx->state, 0, sizeof(sctx->state)); |
101 | sctx->count = 0; |
102 | sctx->func = CPACF_KIMD_SHA3_384; |
103 | |
104 | return 0; |
105 | } |
106 | |
107 | static struct shash_alg sha3_384_alg = { |
108 | .digestsize = SHA3_384_DIGEST_SIZE, |
109 | .init = sha3_384_init, |
110 | .update = s390_sha_update, |
111 | .final = s390_sha_final, |
112 | .export = sha3_512_export, /* same as for 512 */ |
113 | .import = sha3_384_import, /* function code different! */ |
114 | .descsize = sizeof(struct s390_sha_ctx), |
115 | .statesize = sizeof(struct sha3_state), |
116 | .base = { |
117 | .cra_name = "sha3-384" , |
118 | .cra_driver_name = "sha3-384-s390" , |
119 | .cra_priority = 300, |
120 | .cra_blocksize = SHA3_384_BLOCK_SIZE, |
121 | .cra_ctxsize = sizeof(struct s390_sha_ctx), |
122 | .cra_module = THIS_MODULE, |
123 | } |
124 | }; |
125 | |
126 | MODULE_ALIAS_CRYPTO("sha3-384" ); |
127 | |
128 | static int __init init(void) |
129 | { |
130 | int ret; |
131 | |
132 | if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_SHA3_512)) |
133 | return -ENODEV; |
134 | ret = crypto_register_shash(alg: &sha3_512_alg); |
135 | if (ret < 0) |
136 | goto out; |
137 | ret = crypto_register_shash(alg: &sha3_384_alg); |
138 | if (ret < 0) |
139 | crypto_unregister_shash(alg: &sha3_512_alg); |
140 | out: |
141 | return ret; |
142 | } |
143 | |
144 | static void __exit fini(void) |
145 | { |
146 | crypto_unregister_shash(alg: &sha3_512_alg); |
147 | crypto_unregister_shash(alg: &sha3_384_alg); |
148 | } |
149 | |
150 | module_cpu_feature_match(S390_CPU_FEATURE_MSA, init); |
151 | module_exit(fini); |
152 | |
153 | MODULE_LICENSE("GPL" ); |
154 | MODULE_DESCRIPTION("SHA3-512 and SHA3-384 Secure Hash Algorithm" ); |
155 | |