1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Cryptographic API. |
4 | * |
5 | * s390 implementation of the SHA512 and SHA38 Secure Hash Algorithm. |
6 | * |
7 | * Copyright IBM Corp. 2007 |
8 | * Author(s): Jan Glauber (jang@de.ibm.com) |
9 | */ |
10 | #include <crypto/internal/hash.h> |
11 | #include <crypto/sha2.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/cpufeature.h> |
17 | #include <asm/cpacf.h> |
18 | |
19 | #include "sha.h" |
20 | |
21 | static int sha512_init(struct shash_desc *desc) |
22 | { |
23 | struct s390_sha_ctx *ctx = shash_desc_ctx(desc); |
24 | |
25 | *(__u64 *)&ctx->state[0] = SHA512_H0; |
26 | *(__u64 *)&ctx->state[2] = SHA512_H1; |
27 | *(__u64 *)&ctx->state[4] = SHA512_H2; |
28 | *(__u64 *)&ctx->state[6] = SHA512_H3; |
29 | *(__u64 *)&ctx->state[8] = SHA512_H4; |
30 | *(__u64 *)&ctx->state[10] = SHA512_H5; |
31 | *(__u64 *)&ctx->state[12] = SHA512_H6; |
32 | *(__u64 *)&ctx->state[14] = SHA512_H7; |
33 | ctx->count = 0; |
34 | ctx->func = CPACF_KIMD_SHA_512; |
35 | |
36 | return 0; |
37 | } |
38 | |
39 | static int sha512_export(struct shash_desc *desc, void *out) |
40 | { |
41 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
42 | struct sha512_state *octx = out; |
43 | |
44 | octx->count[0] = sctx->count; |
45 | octx->count[1] = 0; |
46 | memcpy(octx->state, sctx->state, sizeof(octx->state)); |
47 | memcpy(octx->buf, sctx->buf, sizeof(octx->buf)); |
48 | return 0; |
49 | } |
50 | |
51 | static int sha512_import(struct shash_desc *desc, const void *in) |
52 | { |
53 | struct s390_sha_ctx *sctx = shash_desc_ctx(desc); |
54 | const struct sha512_state *ictx = in; |
55 | |
56 | if (unlikely(ictx->count[1])) |
57 | return -ERANGE; |
58 | sctx->count = ictx->count[0]; |
59 | |
60 | memcpy(sctx->state, ictx->state, sizeof(ictx->state)); |
61 | memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); |
62 | sctx->func = CPACF_KIMD_SHA_512; |
63 | return 0; |
64 | } |
65 | |
66 | static struct shash_alg sha512_alg = { |
67 | .digestsize = SHA512_DIGEST_SIZE, |
68 | .init = sha512_init, |
69 | .update = s390_sha_update, |
70 | .final = s390_sha_final, |
71 | .export = sha512_export, |
72 | .import = sha512_import, |
73 | .descsize = sizeof(struct s390_sha_ctx), |
74 | .statesize = sizeof(struct sha512_state), |
75 | .base = { |
76 | .cra_name = "sha512" , |
77 | .cra_driver_name= "sha512-s390" , |
78 | .cra_priority = 300, |
79 | .cra_blocksize = SHA512_BLOCK_SIZE, |
80 | .cra_module = THIS_MODULE, |
81 | } |
82 | }; |
83 | |
84 | MODULE_ALIAS_CRYPTO("sha512" ); |
85 | |
86 | static int sha384_init(struct shash_desc *desc) |
87 | { |
88 | struct s390_sha_ctx *ctx = shash_desc_ctx(desc); |
89 | |
90 | *(__u64 *)&ctx->state[0] = SHA384_H0; |
91 | *(__u64 *)&ctx->state[2] = SHA384_H1; |
92 | *(__u64 *)&ctx->state[4] = SHA384_H2; |
93 | *(__u64 *)&ctx->state[6] = SHA384_H3; |
94 | *(__u64 *)&ctx->state[8] = SHA384_H4; |
95 | *(__u64 *)&ctx->state[10] = SHA384_H5; |
96 | *(__u64 *)&ctx->state[12] = SHA384_H6; |
97 | *(__u64 *)&ctx->state[14] = SHA384_H7; |
98 | ctx->count = 0; |
99 | ctx->func = CPACF_KIMD_SHA_512; |
100 | |
101 | return 0; |
102 | } |
103 | |
104 | static struct shash_alg sha384_alg = { |
105 | .digestsize = SHA384_DIGEST_SIZE, |
106 | .init = sha384_init, |
107 | .update = s390_sha_update, |
108 | .final = s390_sha_final, |
109 | .export = sha512_export, |
110 | .import = sha512_import, |
111 | .descsize = sizeof(struct s390_sha_ctx), |
112 | .statesize = sizeof(struct sha512_state), |
113 | .base = { |
114 | .cra_name = "sha384" , |
115 | .cra_driver_name= "sha384-s390" , |
116 | .cra_priority = 300, |
117 | .cra_blocksize = SHA384_BLOCK_SIZE, |
118 | .cra_ctxsize = sizeof(struct s390_sha_ctx), |
119 | .cra_module = THIS_MODULE, |
120 | } |
121 | }; |
122 | |
123 | MODULE_ALIAS_CRYPTO("sha384" ); |
124 | |
125 | static int __init init(void) |
126 | { |
127 | int ret; |
128 | |
129 | if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_SHA_512)) |
130 | return -ENODEV; |
131 | if ((ret = crypto_register_shash(alg: &sha512_alg)) < 0) |
132 | goto out; |
133 | if ((ret = crypto_register_shash(alg: &sha384_alg)) < 0) |
134 | crypto_unregister_shash(alg: &sha512_alg); |
135 | out: |
136 | return ret; |
137 | } |
138 | |
139 | static void __exit fini(void) |
140 | { |
141 | crypto_unregister_shash(alg: &sha512_alg); |
142 | crypto_unregister_shash(alg: &sha384_alg); |
143 | } |
144 | |
145 | module_cpu_feature_match(S390_CPU_FEATURE_MSA, init); |
146 | module_exit(fini); |
147 | |
148 | MODULE_LICENSE("GPL" ); |
149 | MODULE_DESCRIPTION("SHA512 and SHA-384 Secure Hash Algorithm" ); |
150 | |