Blame view

crypto/sha512_generic.c 9.15 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
  struct sha512_ctx {
  	u64 state[8];
  	u32 count[4];
  	u8 buf[128];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  };
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
28
  static DEFINE_PER_CPU(u64[80], msg_schedule);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  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));
  }
  
  static inline u64 RORu64(u64 x, u64 y)
  {
          return (x >> y) | (x << (64 - y));
  }
  
  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,
  };
  
  #define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
  #define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
  #define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
  #define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
86
87
88
  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)
  {
  	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
  }
  
  static void
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
89
  sha512_transform(u64 *state, const u8 *input)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
  {
  	u64 a, b, c, d, e, f, g, h, t1, t2;
  
  	int i;
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
94
  	u64 *W = get_cpu_var(msg_schedule);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
102
103
104
  
  	/* load the input */
          for (i = 0; i < 16; i++)
                  LOAD_OP(i, W, input);
  
          for (i = 16; i < 80; i++) {
                  BLEND_OP(i, W);
          }
  
  	/* load the state into our registers */
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
105
106
  	a=state[0];   b=state[1];   c=state[2];   d=state[3];
  	e=state[4];   f=state[5];   g=state[6];   h=state[7];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	/* now iterate */
  	for (i=0; i<80; i+=8) {
  		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
  		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+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+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+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+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+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+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+7];
  		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
  	}
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
126
127
128
  
  	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
129
130
131
  
  	/* erase our data */
  	a = b = c = d = e = f = g = h = t1 = t2 = 0;
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
132
133
  	memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
  	put_cpu_var(msg_schedule);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
135
136
  static int
  sha512_init(struct shash_desc *desc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
138
  	struct sha512_ctx *sctx = shash_desc_ctx(desc);
5265eeb2b   Jan Glauber   [CRYPTO] sha: Add...
139
140
141
142
143
144
145
146
  	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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
148
149
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
151
152
  static int
  sha384_init(struct shash_desc *desc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
154
  	struct sha512_ctx *sctx = shash_desc_ctx(desc);
5265eeb2b   Jan Glauber   [CRYPTO] sha: Add...
155
156
157
158
159
160
161
162
  	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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
          sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
164
165
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
167
168
  static int
  sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
170
  	struct sha512_ctx *sctx = shash_desc_ctx(desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
  
  	unsigned int i, index, part_len;
  
  	/* Compute number of bytes mod 128 */
  	index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
176

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
182
183
  	/* Update number of bits */
  	if ((sctx->count[0] += (len << 3)) < (len << 3)) {
  		if ((sctx->count[1] += 1) < 1)
  			if ((sctx->count[2] += 1) < 1)
  				sctx->count[3]++;
  		sctx->count[1] += (len >> 29);
  	}
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
184

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  	/* Transform as many times as possible. */
  	if (len >= part_len) {
  		memcpy(&sctx->buf[index], data, part_len);
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
190
  		sha512_transform(sctx->state, sctx->buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  
  		for (i = part_len; i + 127 < len; i+=128)
f9e2bca6c   Adrian-Ken Rueegsegger   crypto: sha512 - ...
193
  			sha512_transform(sctx->state, &data[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
  
  		index = 0;
  	} else {
  		i = 0;
  	}
  
  	/* Buffer remaining input */
  	memcpy(&sctx->buf[index], &data[i], len - i);
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
202
203
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
205
206
  static int
  sha512_final(struct shash_desc *desc, u8 *hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
208
  	struct sha512_ctx *sctx = shash_desc_ctx(desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
          static u8 padding[128] = { 0x80, };
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
210
211
  	__be64 *dst = (__be64 *)hash;
  	__be32 bits[4];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	unsigned int index, pad_len;
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
213
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  
  	/* Save number of bits */
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
216
217
218
219
  	bits[3] = cpu_to_be32(sctx->count[0]);
  	bits[2] = cpu_to_be32(sctx->count[1]);
  	bits[1] = cpu_to_be32(sctx->count[2]);
  	bits[0] = cpu_to_be32(sctx->count[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
222
223
  
  	/* Pad out to 112 mod 128. */
  	index = (sctx->count[0] >> 3) & 0x7f;
  	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
224
  	sha512_update(desc, padding, pad_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
  
  	/* Append length (before padding) */
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
227
  	sha512_update(desc, (const u8 *)bits, sizeof(bits));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
  
  	/* Store state in digest */
06ace7a9b   Herbert Xu   [CRYPTO] Use stan...
230
231
  	for (i = 0; i < 8; i++)
  		dst[i] = cpu_to_be64(sctx->state[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  	/* Zeroize sensitive information. */
  	memset(sctx, 0, sizeof(struct sha512_ctx));
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
234
235
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
237
  static int sha384_final(struct shash_desc *desc, u8 *hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
239
  	u8 D[64];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240

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

bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
243
244
245
246
  	memcpy(hash, D, 48);
  	memset(D, 0, 64);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  }
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
248
249
250
251
252
253
254
255
256
257
258
259
  static struct shash_alg sha512 = {
  	.digestsize	=	SHA512_DIGEST_SIZE,
  	.init		=	sha512_init,
  	.update		=	sha512_update,
  	.final		=	sha512_final,
  	.descsize	=	sizeof(struct sha512_ctx),
  	.base		=	{
  		.cra_name	=	"sha512",
  		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
  		.cra_blocksize	=	SHA512_BLOCK_SIZE,
  		.cra_module	=	THIS_MODULE,
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  };
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
261
262
263
264
265
266
267
268
269
270
271
272
  static struct shash_alg sha384 = {
  	.digestsize	=	SHA384_DIGEST_SIZE,
  	.init		=	sha384_init,
  	.update		=	sha512_update,
  	.final		=	sha384_final,
  	.descsize	=	sizeof(struct sha512_ctx),
  	.base		=	{
  		.cra_name	=	"sha384",
  		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
  		.cra_blocksize	=	SHA384_BLOCK_SIZE,
  		.cra_module	=	THIS_MODULE,
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  };
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
274
  static int __init sha512_generic_mod_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
  {
          int ret = 0;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
277
          if ((ret = crypto_register_shash(&sha384)) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
                  goto out;
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
279
280
          if ((ret = crypto_register_shash(&sha512)) < 0)
                  crypto_unregister_shash(&sha384);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
  out:
          return ret;
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
284
  static void __exit sha512_generic_mod_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  {
bd9d20dba   Adrian-Ken Rueegsegger   crypto: sha512 - ...
286
287
          crypto_unregister_shash(&sha384);
          crypto_unregister_shash(&sha512);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
289
290
  module_init(sha512_generic_mod_init);
  module_exit(sha512_generic_mod_fini);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
78f8b3a24   Jan Glauber   [CRYPTO] sha512: ...
294
295
296
  
  MODULE_ALIAS("sha384");
  MODULE_ALIAS("sha512");