Merge tag 'for-4.19/post-20180822' of git://git.kernel.dk/linux-block
[sfrench/cifs-2.6.git] / arch / mips / cavium-octeon / crypto / octeon-sha512.c
1 /*
2  * Cryptographic API.
3  *
4  * SHA-512 and SHA-384 Secure Hash Algorithm.
5  *
6  * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
7  *
8  * Based on crypto/sha512_generic.c, which is:
9  *
10  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
11  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
12  * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
13  *
14  * This program is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by the
16  * Free Software Foundation; either version 2, or (at your option) any
17  * later version.
18  */
19
20 #include <linux/mm.h>
21 #include <crypto/sha.h>
22 #include <linux/init.h>
23 #include <linux/types.h>
24 #include <linux/module.h>
25 #include <asm/byteorder.h>
26 #include <asm/octeon/octeon.h>
27 #include <crypto/internal/hash.h>
28
29 #include "octeon-crypto.h"
30
31 /*
32  * We pass everything as 64-bit. OCTEON can handle misaligned data.
33  */
34
35 static void octeon_sha512_store_hash(struct sha512_state *sctx)
36 {
37         write_octeon_64bit_hash_sha512(sctx->state[0], 0);
38         write_octeon_64bit_hash_sha512(sctx->state[1], 1);
39         write_octeon_64bit_hash_sha512(sctx->state[2], 2);
40         write_octeon_64bit_hash_sha512(sctx->state[3], 3);
41         write_octeon_64bit_hash_sha512(sctx->state[4], 4);
42         write_octeon_64bit_hash_sha512(sctx->state[5], 5);
43         write_octeon_64bit_hash_sha512(sctx->state[6], 6);
44         write_octeon_64bit_hash_sha512(sctx->state[7], 7);
45 }
46
47 static void octeon_sha512_read_hash(struct sha512_state *sctx)
48 {
49         sctx->state[0] = read_octeon_64bit_hash_sha512(0);
50         sctx->state[1] = read_octeon_64bit_hash_sha512(1);
51         sctx->state[2] = read_octeon_64bit_hash_sha512(2);
52         sctx->state[3] = read_octeon_64bit_hash_sha512(3);
53         sctx->state[4] = read_octeon_64bit_hash_sha512(4);
54         sctx->state[5] = read_octeon_64bit_hash_sha512(5);
55         sctx->state[6] = read_octeon_64bit_hash_sha512(6);
56         sctx->state[7] = read_octeon_64bit_hash_sha512(7);
57 }
58
59 static void octeon_sha512_transform(const void *_block)
60 {
61         const u64 *block = _block;
62
63         write_octeon_64bit_block_sha512(block[0], 0);
64         write_octeon_64bit_block_sha512(block[1], 1);
65         write_octeon_64bit_block_sha512(block[2], 2);
66         write_octeon_64bit_block_sha512(block[3], 3);
67         write_octeon_64bit_block_sha512(block[4], 4);
68         write_octeon_64bit_block_sha512(block[5], 5);
69         write_octeon_64bit_block_sha512(block[6], 6);
70         write_octeon_64bit_block_sha512(block[7], 7);
71         write_octeon_64bit_block_sha512(block[8], 8);
72         write_octeon_64bit_block_sha512(block[9], 9);
73         write_octeon_64bit_block_sha512(block[10], 10);
74         write_octeon_64bit_block_sha512(block[11], 11);
75         write_octeon_64bit_block_sha512(block[12], 12);
76         write_octeon_64bit_block_sha512(block[13], 13);
77         write_octeon_64bit_block_sha512(block[14], 14);
78         octeon_sha512_start(block[15]);
79 }
80
81 static int octeon_sha512_init(struct shash_desc *desc)
82 {
83         struct sha512_state *sctx = shash_desc_ctx(desc);
84
85         sctx->state[0] = SHA512_H0;
86         sctx->state[1] = SHA512_H1;
87         sctx->state[2] = SHA512_H2;
88         sctx->state[3] = SHA512_H3;
89         sctx->state[4] = SHA512_H4;
90         sctx->state[5] = SHA512_H5;
91         sctx->state[6] = SHA512_H6;
92         sctx->state[7] = SHA512_H7;
93         sctx->count[0] = sctx->count[1] = 0;
94
95         return 0;
96 }
97
98 static int octeon_sha384_init(struct shash_desc *desc)
99 {
100         struct sha512_state *sctx = shash_desc_ctx(desc);
101
102         sctx->state[0] = SHA384_H0;
103         sctx->state[1] = SHA384_H1;
104         sctx->state[2] = SHA384_H2;
105         sctx->state[3] = SHA384_H3;
106         sctx->state[4] = SHA384_H4;
107         sctx->state[5] = SHA384_H5;
108         sctx->state[6] = SHA384_H6;
109         sctx->state[7] = SHA384_H7;
110         sctx->count[0] = sctx->count[1] = 0;
111
112         return 0;
113 }
114
115 static void __octeon_sha512_update(struct sha512_state *sctx, const u8 *data,
116                                    unsigned int len)
117 {
118         unsigned int part_len;
119         unsigned int index;
120         unsigned int i;
121
122         /* Compute number of bytes mod 128. */
123         index = sctx->count[0] % SHA512_BLOCK_SIZE;
124
125         /* Update number of bytes. */
126         if ((sctx->count[0] += len) < len)
127                 sctx->count[1]++;
128
129         part_len = SHA512_BLOCK_SIZE - index;
130
131         /* Transform as many times as possible. */
132         if (len >= part_len) {
133                 memcpy(&sctx->buf[index], data, part_len);
134                 octeon_sha512_transform(sctx->buf);
135
136                 for (i = part_len; i + SHA512_BLOCK_SIZE <= len;
137                         i += SHA512_BLOCK_SIZE)
138                         octeon_sha512_transform(&data[i]);
139
140                 index = 0;
141         } else {
142                 i = 0;
143         }
144
145         /* Buffer remaining input. */
146         memcpy(&sctx->buf[index], &data[i], len - i);
147 }
148
149 static int octeon_sha512_update(struct shash_desc *desc, const u8 *data,
150                                 unsigned int len)
151 {
152         struct sha512_state *sctx = shash_desc_ctx(desc);
153         struct octeon_cop2_state state;
154         unsigned long flags;
155
156         /*
157          * Small updates never reach the crypto engine, so the generic sha512 is
158          * faster because of the heavyweight octeon_crypto_enable() /
159          * octeon_crypto_disable().
160          */
161         if ((sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE)
162                 return crypto_sha512_update(desc, data, len);
163
164         flags = octeon_crypto_enable(&state);
165         octeon_sha512_store_hash(sctx);
166
167         __octeon_sha512_update(sctx, data, len);
168
169         octeon_sha512_read_hash(sctx);
170         octeon_crypto_disable(&state, flags);
171
172         return 0;
173 }
174
175 static int octeon_sha512_final(struct shash_desc *desc, u8 *hash)
176 {
177         struct sha512_state *sctx = shash_desc_ctx(desc);
178         static u8 padding[128] = { 0x80, };
179         struct octeon_cop2_state state;
180         __be64 *dst = (__be64 *)hash;
181         unsigned int pad_len;
182         unsigned long flags;
183         unsigned int index;
184         __be64 bits[2];
185         int i;
186
187         /* Save number of bits. */
188         bits[1] = cpu_to_be64(sctx->count[0] << 3);
189         bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
190
191         /* Pad out to 112 mod 128. */
192         index = sctx->count[0] & 0x7f;
193         pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
194
195         flags = octeon_crypto_enable(&state);
196         octeon_sha512_store_hash(sctx);
197
198         __octeon_sha512_update(sctx, padding, pad_len);
199
200         /* Append length (before padding). */
201         __octeon_sha512_update(sctx, (const u8 *)bits, sizeof(bits));
202
203         octeon_sha512_read_hash(sctx);
204         octeon_crypto_disable(&state, flags);
205
206         /* Store state in digest. */
207         for (i = 0; i < 8; i++)
208                 dst[i] = cpu_to_be64(sctx->state[i]);
209
210         /* Zeroize sensitive information. */
211         memset(sctx, 0, sizeof(struct sha512_state));
212
213         return 0;
214 }
215
216 static int octeon_sha384_final(struct shash_desc *desc, u8 *hash)
217 {
218         u8 D[64];
219
220         octeon_sha512_final(desc, D);
221
222         memcpy(hash, D, 48);
223         memzero_explicit(D, 64);
224
225         return 0;
226 }
227
228 static struct shash_alg octeon_sha512_algs[2] = { {
229         .digestsize     =       SHA512_DIGEST_SIZE,
230         .init           =       octeon_sha512_init,
231         .update         =       octeon_sha512_update,
232         .final          =       octeon_sha512_final,
233         .descsize       =       sizeof(struct sha512_state),
234         .base           =       {
235                 .cra_name       =       "sha512",
236                 .cra_driver_name=       "octeon-sha512",
237                 .cra_priority   =       OCTEON_CR_OPCODE_PRIORITY,
238                 .cra_blocksize  =       SHA512_BLOCK_SIZE,
239                 .cra_module     =       THIS_MODULE,
240         }
241 }, {
242         .digestsize     =       SHA384_DIGEST_SIZE,
243         .init           =       octeon_sha384_init,
244         .update         =       octeon_sha512_update,
245         .final          =       octeon_sha384_final,
246         .descsize       =       sizeof(struct sha512_state),
247         .base           =       {
248                 .cra_name       =       "sha384",
249                 .cra_driver_name=       "octeon-sha384",
250                 .cra_priority   =       OCTEON_CR_OPCODE_PRIORITY,
251                 .cra_blocksize  =       SHA384_BLOCK_SIZE,
252                 .cra_module     =       THIS_MODULE,
253         }
254 } };
255
256 static int __init octeon_sha512_mod_init(void)
257 {
258         if (!octeon_has_crypto())
259                 return -ENOTSUPP;
260         return crypto_register_shashes(octeon_sha512_algs,
261                                        ARRAY_SIZE(octeon_sha512_algs));
262 }
263
264 static void __exit octeon_sha512_mod_fini(void)
265 {
266         crypto_unregister_shashes(octeon_sha512_algs,
267                                   ARRAY_SIZE(octeon_sha512_algs));
268 }
269
270 module_init(octeon_sha512_mod_init);
271 module_exit(octeon_sha512_mod_fini);
272
273 MODULE_LICENSE("GPL");
274 MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms (OCTEON)");
275 MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");