Blame view

crypto/sha512_generic.c 8.65 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com>
   *
   * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
   * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
   * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
   * Free Software Foundation; either version 2, or (at your option) any
   * later version.
   *
   */
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
13
  #include <crypto/internal/hash.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/kernel.h>
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
  #include <linux/mm.h>
  #include <linux/init.h>
  #include <linux/crypto.h>
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
19
  #include <linux/types.h>
5265eeb2b   Jan Glauber   [CRYPTO] sha: Add...
20
  #include <crypto/sha.h>
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
21
  #include <linux/percpu.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/byteorder.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
30
31
  static inline u64 Ch(u64 x, u64 y, u64 z)
  {
          return z ^ (x & (y ^ z));
  }
  
  static inline u64 Maj(u64 x, u64 y, u64 z)
  {
          return (x & y) | (z & (x | y));
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  static const u64 sha512_K[80] = {
          0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
          0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
          0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
          0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
          0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
          0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
          0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
          0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
          0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
          0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
          0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
          0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
          0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
          0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
          0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
          0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
          0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
          0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
          0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
          0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
          0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
          0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
          0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
          0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
          0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
          0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
          0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
  };
f2ea0f5f0   Alexey Dobriyan   crypto: sha512 - ...
61
62
63
64
  #define e0(x)       (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
  #define e1(x)       (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
  #define s0(x)       (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
  #define s1(x)       (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
  static inline void LOAD_OP(int I, u64 *W, const u8 *input)
  {
  	W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
  }
  
  static inline void BLEND_OP(int I, u64 *W)
  {
58d7d18b5   Herbert Xu   crypto: sha512 - ...
73
  	W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  }
  
  static void
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
77
  sha512_transform(u64 *state, const u8 *input)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
  {
  	u64 a, b, c, d, e, f, g, h, t1, t2;
  
  	int i;
51fc6dc8f   Alexey Dobriyan   crypto: sha512 - ...
82
  	u64 W[16];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	/* load the state into our registers */
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
85
86
  	a=state[0];   b=state[1];   c=state[2];   d=state[3];
  	e=state[4];   f=state[5];   g=state[6];   h=state[7];
3a92d687c   Herbert Xu   crypto: sha512 - ...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  	/* now iterate */
  	for (i=0; i<80; i+=8) {
  		if (!(i & 8)) {
  			int j;
  
  			if (i < 16) {
  				/* load the input */
  				for (j = 0; j < 16; j++)
  					LOAD_OP(i + j, W, input);
  			} else {
  				for (j = 0; j < 16; j++) {
  					BLEND_OP(i + j, W);
  				}
  			}
  		}
  
  		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[(i & 15)];
  		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
  		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
  		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
  		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
  		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
  		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
  		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
  		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
  		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
  		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
  		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
  		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
  		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
  		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
  		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  	}
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
120
121
122
  
  	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
  	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
  
  	/* erase our data */
  	a = b = c = d = e = f = g = h = t1 = t2 = 0;
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
127
128
  static int
  sha512_init(struct shash_desc *desc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
1f38ad838   Herbert Xu   crypto: sha512 - ...
130
  	struct sha512_state *sctx = shash_desc_ctx(desc);
5265eeb2b   Jan Glauber   [CRYPTO] sha: Add...
131
132
133
134
135
136
137
138
  	sctx->state[0] = SHA512_H0;
  	sctx->state[1] = SHA512_H1;
  	sctx->state[2] = SHA512_H2;
  	sctx->state[3] = SHA512_H3;
  	sctx->state[4] = SHA512_H4;
  	sctx->state[5] = SHA512_H5;
  	sctx->state[6] = SHA512_H6;
  	sctx->state[7] = SHA512_H7;
13887ed68   Herbert Xu   crypto: sha512_ge...
139
  	sctx->count[0] = sctx->count[1] = 0;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
140
141
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
143
144
  static int
  sha384_init(struct shash_desc *desc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  {
1f38ad838   Herbert Xu   crypto: sha512 - ...
146
  	struct sha512_state *sctx = shash_desc_ctx(desc);
5265eeb2b   Jan Glauber   [CRYPTO] sha: Add...
147
148
149
150
151
152
153
154
  	sctx->state[0] = SHA384_H0;
  	sctx->state[1] = SHA384_H1;
  	sctx->state[2] = SHA384_H2;
  	sctx->state[3] = SHA384_H3;
  	sctx->state[4] = SHA384_H4;
  	sctx->state[5] = SHA384_H5;
  	sctx->state[6] = SHA384_H6;
  	sctx->state[7] = SHA384_H7;
13887ed68   Herbert Xu   crypto: sha512_ge...
155
  	sctx->count[0] = sctx->count[1] = 0;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
156
157
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  }
bf70fa9d9   Tim Chen   crypto: sha512 - ...
159
160
  int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
  			unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  {
1f38ad838   Herbert Xu   crypto: sha512 - ...
162
  	struct sha512_state *sctx = shash_desc_ctx(desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
  
  	unsigned int i, index, part_len;
  
  	/* Compute number of bytes mod 128 */
13887ed68   Herbert Xu   crypto: sha512_ge...
167
168
169
  	index = sctx->count[0] & 0x7f;
  
  	/* Update number of bytes */
25c3d30c9   Kent Yoder   crypto: sha512 - ...
170
  	if ((sctx->count[0] += len) < len)
13887ed68   Herbert Xu   crypto: sha512_ge...
171
  		sctx->count[1]++;
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
172

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
          part_len = 128 - index;
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
174

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  	/* Transform as many times as possible. */
  	if (len >= part_len) {
  		memcpy(&sctx->buf[index], data, part_len);
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
178
  		sha512_transform(sctx->state, sctx->buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  
  		for (i = part_len; i + 127 < len; i+=128)
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
181
  			sha512_transform(sctx->state, &data[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
186
187
188
189
  
  		index = 0;
  	} else {
  		i = 0;
  	}
  
  	/* Buffer remaining input */
  	memcpy(&sctx->buf[index], &data[i], len - i);
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
190
191
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  }
bf70fa9d9   Tim Chen   crypto: sha512 - ...
193
  EXPORT_SYMBOL(crypto_sha512_update);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
195
196
  static int
  sha512_final(struct shash_desc *desc, u8 *hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  {
1f38ad838   Herbert Xu   crypto: sha512 - ...
198
  	struct sha512_state *sctx = shash_desc_ctx(desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
          static u8 padding[128] = { 0x80, };
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
200
  	__be64 *dst = (__be64 *)hash;
13887ed68   Herbert Xu   crypto: sha512_ge...
201
  	__be64 bits[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	unsigned int index, pad_len;
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
203
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
  
  	/* Save number of bits */
13887ed68   Herbert Xu   crypto: sha512_ge...
206
207
  	bits[1] = cpu_to_be64(sctx->count[0] << 3);
  	bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  
  	/* Pad out to 112 mod 128. */
13887ed68   Herbert Xu   crypto: sha512_ge...
210
  	index = sctx->count[0] & 0x7f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
bf70fa9d9   Tim Chen   crypto: sha512 - ...
212
  	crypto_sha512_update(desc, padding, pad_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  
  	/* Append length (before padding) */
bf70fa9d9   Tim Chen   crypto: sha512 - ...
215
  	crypto_sha512_update(desc, (const u8 *)bits, sizeof(bits));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
  
  	/* Store state in digest */
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
218
219
  	for (i = 0; i < 8; i++)
  		dst[i] = cpu_to_be64(sctx->state[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	/* Zeroize sensitive information. */
1f38ad838   Herbert Xu   crypto: sha512 - ...
221
  	memset(sctx, 0, sizeof(struct sha512_state));
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
222
223
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
225
  static int sha384_final(struct shash_desc *desc, u8 *hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
227
  	u8 D[64];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
229
  	sha512_final(desc, D);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230

bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
231
232
233
234
  	memcpy(hash, D, 48);
  	memset(D, 0, 64);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  }
648b2a102   Jussi Kivilinna   crypto: sha512 - ...
236
  static struct shash_alg sha512_algs[2] = { {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
237
238
  	.digestsize	=	SHA512_DIGEST_SIZE,
  	.init		=	sha512_init,
bf70fa9d9   Tim Chen   crypto: sha512 - ...
239
  	.update		=	crypto_sha512_update,
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
240
  	.final		=	sha512_final,
1f38ad838   Herbert Xu   crypto: sha512 - ...
241
  	.descsize	=	sizeof(struct sha512_state),
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
242
243
  	.base		=	{
  		.cra_name	=	"sha512",
d32958149   Jussi Kivilinna   crypto: sha512_ge...
244
  		.cra_driver_name =	"sha512-generic",
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
245
246
247
248
  		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
  		.cra_blocksize	=	SHA512_BLOCK_SIZE,
  		.cra_module	=	THIS_MODULE,
  	}
648b2a102   Jussi Kivilinna   crypto: sha512 - ...
249
  }, {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
250
251
  	.digestsize	=	SHA384_DIGEST_SIZE,
  	.init		=	sha384_init,
bf70fa9d9   Tim Chen   crypto: sha512 - ...
252
  	.update		=	crypto_sha512_update,
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
253
  	.final		=	sha384_final,
1f38ad838   Herbert Xu   crypto: sha512 - ...
254
  	.descsize	=	sizeof(struct sha512_state),
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
255
256
  	.base		=	{
  		.cra_name	=	"sha384",
d32958149   Jussi Kivilinna   crypto: sha512_ge...
257
  		.cra_driver_name =	"sha384-generic",
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
258
259
260
261
  		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
  		.cra_blocksize	=	SHA384_BLOCK_SIZE,
  		.cra_module	=	THIS_MODULE,
  	}
648b2a102   Jussi Kivilinna   crypto: sha512 - ...
262
  } };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
264
  static int __init sha512_generic_mod_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  {
648b2a102   Jussi Kivilinna   crypto: sha512 - ...
266
  	return crypto_register_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
268
  static void __exit sha512_generic_mod_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  {
648b2a102   Jussi Kivilinna   crypto: sha512 - ...
270
  	crypto_unregister_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
272
273
  module_init(sha512_generic_mod_init);
  module_exit(sha512_generic_mod_fini);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
276
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
277
278
279
  
  MODULE_ALIAS("sha384");
  MODULE_ALIAS("sha512");