| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com> | 
 | 2 |  * | 
 | 3 |  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> | 
 | 4 |  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> | 
 | 5 |  * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> | 
 | 6 |  * | 
 | 7 |  * This program is free software; you can redistribute it and/or modify it | 
 | 8 |  * under the terms of the GNU General Public License as published by the | 
 | 9 |  * Free Software Foundation; either version 2, or (at your option) any | 
 | 10 |  * later version. | 
 | 11 |  * | 
 | 12 |  */ | 
 | 13 |  | 
 | 14 | #include <linux/kernel.h> | 
 | 15 | #include <linux/module.h> | 
 | 16 |  | 
 | 17 | #include <linux/mm.h> | 
 | 18 | #include <linux/init.h> | 
 | 19 | #include <linux/crypto.h> | 
| Herbert Xu | 06ace7a | 2005-10-30 21:25:15 +1100 | [diff] [blame] | 20 | #include <linux/types.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
 | 22 | #include <asm/scatterlist.h> | 
 | 23 | #include <asm/byteorder.h> | 
 | 24 |  | 
 | 25 | #define SHA384_DIGEST_SIZE 48 | 
 | 26 | #define SHA512_DIGEST_SIZE 64 | 
| Herbert Xu | 686106f | 2006-12-08 13:59:52 +1100 | [diff] [blame] | 27 | #define SHA384_HMAC_BLOCK_SIZE 128 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 | #define SHA512_HMAC_BLOCK_SIZE 128 | 
 | 29 |  | 
 | 30 | struct sha512_ctx { | 
 | 31 | 	u64 state[8]; | 
 | 32 | 	u32 count[4]; | 
 | 33 | 	u8 buf[128]; | 
 | 34 | 	u64 W[80]; | 
 | 35 | }; | 
 | 36 |  | 
 | 37 | static inline u64 Ch(u64 x, u64 y, u64 z) | 
 | 38 | { | 
 | 39 |         return z ^ (x & (y ^ z)); | 
 | 40 | } | 
 | 41 |  | 
 | 42 | static inline u64 Maj(u64 x, u64 y, u64 z) | 
 | 43 | { | 
 | 44 |         return (x & y) | (z & (x | y)); | 
 | 45 | } | 
 | 46 |  | 
 | 47 | static inline u64 RORu64(u64 x, u64 y) | 
 | 48 | { | 
 | 49 |         return (x >> y) | (x << (64 - y)); | 
 | 50 | } | 
 | 51 |  | 
 | 52 | static const u64 sha512_K[80] = { | 
 | 53 |         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, | 
 | 54 |         0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, | 
 | 55 |         0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, | 
 | 56 |         0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, | 
 | 57 |         0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, | 
 | 58 |         0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, | 
 | 59 |         0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, | 
 | 60 |         0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, | 
 | 61 |         0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, | 
 | 62 |         0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, | 
 | 63 |         0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, | 
 | 64 |         0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, | 
 | 65 |         0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, | 
 | 66 |         0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, | 
 | 67 |         0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, | 
 | 68 |         0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, | 
 | 69 |         0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, | 
 | 70 |         0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, | 
 | 71 |         0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, | 
 | 72 |         0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, | 
 | 73 |         0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, | 
 | 74 |         0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, | 
 | 75 |         0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, | 
 | 76 |         0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, | 
 | 77 |         0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, | 
 | 78 |         0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, | 
 | 79 |         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, | 
 | 80 | }; | 
 | 81 |  | 
 | 82 | #define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) | 
 | 83 | #define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) | 
 | 84 | #define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) | 
 | 85 | #define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) | 
 | 86 |  | 
 | 87 | /* H* initial state for SHA-512 */ | 
 | 88 | #define H0         0x6a09e667f3bcc908ULL | 
 | 89 | #define H1         0xbb67ae8584caa73bULL | 
 | 90 | #define H2         0x3c6ef372fe94f82bULL | 
 | 91 | #define H3         0xa54ff53a5f1d36f1ULL | 
 | 92 | #define H4         0x510e527fade682d1ULL | 
 | 93 | #define H5         0x9b05688c2b3e6c1fULL | 
 | 94 | #define H6         0x1f83d9abfb41bd6bULL | 
 | 95 | #define H7         0x5be0cd19137e2179ULL | 
 | 96 |  | 
 | 97 | /* H'* initial state for SHA-384 */ | 
 | 98 | #define HP0 0xcbbb9d5dc1059ed8ULL | 
 | 99 | #define HP1 0x629a292a367cd507ULL | 
 | 100 | #define HP2 0x9159015a3070dd17ULL | 
 | 101 | #define HP3 0x152fecd8f70e5939ULL | 
 | 102 | #define HP4 0x67332667ffc00b31ULL | 
 | 103 | #define HP5 0x8eb44a8768581511ULL | 
 | 104 | #define HP6 0xdb0c2e0d64f98fa7ULL | 
 | 105 | #define HP7 0x47b5481dbefa4fa4ULL | 
 | 106 |  | 
 | 107 | static inline void LOAD_OP(int I, u64 *W, const u8 *input) | 
 | 108 | { | 
 | 109 | 	W[I] = __be64_to_cpu( ((__be64*)(input))[I] ); | 
 | 110 | } | 
 | 111 |  | 
 | 112 | static inline void BLEND_OP(int I, u64 *W) | 
 | 113 | { | 
 | 114 | 	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; | 
 | 115 | } | 
 | 116 |  | 
 | 117 | static void | 
 | 118 | sha512_transform(u64 *state, u64 *W, const u8 *input) | 
 | 119 | { | 
 | 120 | 	u64 a, b, c, d, e, f, g, h, t1, t2; | 
 | 121 |  | 
 | 122 | 	int i; | 
 | 123 |  | 
 | 124 | 	/* load the input */ | 
 | 125 |         for (i = 0; i < 16; i++) | 
 | 126 |                 LOAD_OP(i, W, input); | 
 | 127 |  | 
 | 128 |         for (i = 16; i < 80; i++) { | 
 | 129 |                 BLEND_OP(i, W); | 
 | 130 |         } | 
 | 131 |  | 
 | 132 | 	/* load the state into our registers */ | 
 | 133 | 	a=state[0];   b=state[1];   c=state[2];   d=state[3];   | 
 | 134 | 	e=state[4];   f=state[5];   g=state[6];   h=state[7];   | 
 | 135 |    | 
 | 136 | 	/* now iterate */ | 
 | 137 | 	for (i=0; i<80; i+=8) { | 
 | 138 | 		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ]; | 
 | 139 | 		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2; | 
 | 140 | 		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; | 
 | 141 | 		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2; | 
 | 142 | 		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; | 
 | 143 | 		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2; | 
 | 144 | 		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; | 
 | 145 | 		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2; | 
 | 146 | 		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; | 
 | 147 | 		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2; | 
 | 148 | 		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; | 
 | 149 | 		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2; | 
 | 150 | 		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; | 
 | 151 | 		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2; | 
 | 152 | 		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; | 
 | 153 | 		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2; | 
 | 154 | 	} | 
 | 155 |    | 
 | 156 | 	state[0] += a; state[1] += b; state[2] += c; state[3] += d;   | 
 | 157 | 	state[4] += e; state[5] += f; state[6] += g; state[7] += h;   | 
 | 158 |  | 
 | 159 | 	/* erase our data */ | 
 | 160 | 	a = b = c = d = e = f = g = h = t1 = t2 = 0; | 
 | 161 | } | 
 | 162 |  | 
 | 163 | static void | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 164 | sha512_init(struct crypto_tfm *tfm) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 166 | 	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 167 | 	sctx->state[0] = H0; | 
 | 168 | 	sctx->state[1] = H1; | 
 | 169 | 	sctx->state[2] = H2; | 
 | 170 | 	sctx->state[3] = H3; | 
 | 171 | 	sctx->state[4] = H4; | 
 | 172 | 	sctx->state[5] = H5; | 
 | 173 | 	sctx->state[6] = H6; | 
 | 174 | 	sctx->state[7] = H7; | 
 | 175 | 	sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 176 | } | 
 | 177 |  | 
 | 178 | static void | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 179 | sha384_init(struct crypto_tfm *tfm) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 181 | 	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 182 |         sctx->state[0] = HP0; | 
 | 183 |         sctx->state[1] = HP1; | 
 | 184 |         sctx->state[2] = HP2; | 
 | 185 |         sctx->state[3] = HP3; | 
 | 186 |         sctx->state[4] = HP4; | 
 | 187 |         sctx->state[5] = HP5; | 
 | 188 |         sctx->state[6] = HP6; | 
 | 189 |         sctx->state[7] = HP7; | 
 | 190 |         sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 191 | } | 
 | 192 |  | 
 | 193 | static void | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 194 | sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 196 | 	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 |  | 
 | 198 | 	unsigned int i, index, part_len; | 
 | 199 |  | 
 | 200 | 	/* Compute number of bytes mod 128 */ | 
 | 201 | 	index = (unsigned int)((sctx->count[0] >> 3) & 0x7F); | 
 | 202 | 	 | 
 | 203 | 	/* Update number of bits */ | 
 | 204 | 	if ((sctx->count[0] += (len << 3)) < (len << 3)) { | 
 | 205 | 		if ((sctx->count[1] += 1) < 1) | 
 | 206 | 			if ((sctx->count[2] += 1) < 1) | 
 | 207 | 				sctx->count[3]++; | 
 | 208 | 		sctx->count[1] += (len >> 29); | 
 | 209 | 	} | 
 | 210 | 	 | 
 | 211 |         part_len = 128 - index; | 
 | 212 | 	 | 
 | 213 | 	/* Transform as many times as possible. */ | 
 | 214 | 	if (len >= part_len) { | 
 | 215 | 		memcpy(&sctx->buf[index], data, part_len); | 
 | 216 | 		sha512_transform(sctx->state, sctx->W, sctx->buf); | 
 | 217 |  | 
 | 218 | 		for (i = part_len; i + 127 < len; i+=128) | 
 | 219 | 			sha512_transform(sctx->state, sctx->W, &data[i]); | 
 | 220 |  | 
 | 221 | 		index = 0; | 
 | 222 | 	} else { | 
 | 223 | 		i = 0; | 
 | 224 | 	} | 
 | 225 |  | 
 | 226 | 	/* Buffer remaining input */ | 
 | 227 | 	memcpy(&sctx->buf[index], &data[i], len - i); | 
 | 228 |  | 
 | 229 | 	/* erase our data */ | 
 | 230 | 	memset(sctx->W, 0, sizeof(sctx->W)); | 
 | 231 | } | 
 | 232 |  | 
 | 233 | static void | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 234 | sha512_final(struct crypto_tfm *tfm, u8 *hash) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 236 | 	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 237 |         static u8 padding[128] = { 0x80, }; | 
| Herbert Xu | 06ace7a | 2005-10-30 21:25:15 +1100 | [diff] [blame] | 238 | 	__be64 *dst = (__be64 *)hash; | 
 | 239 | 	__be32 bits[4]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 240 | 	unsigned int index, pad_len; | 
| Herbert Xu | 06ace7a | 2005-10-30 21:25:15 +1100 | [diff] [blame] | 241 | 	int i; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 242 |  | 
 | 243 | 	/* Save number of bits */ | 
| Herbert Xu | 06ace7a | 2005-10-30 21:25:15 +1100 | [diff] [blame] | 244 | 	bits[3] = cpu_to_be32(sctx->count[0]); | 
 | 245 | 	bits[2] = cpu_to_be32(sctx->count[1]); | 
 | 246 | 	bits[1] = cpu_to_be32(sctx->count[2]); | 
 | 247 | 	bits[0] = cpu_to_be32(sctx->count[3]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 248 |  | 
 | 249 | 	/* Pad out to 112 mod 128. */ | 
 | 250 | 	index = (sctx->count[0] >> 3) & 0x7f; | 
 | 251 | 	pad_len = (index < 112) ? (112 - index) : ((128+112) - index); | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 252 | 	sha512_update(tfm, padding, pad_len); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 253 |  | 
 | 254 | 	/* Append length (before padding) */ | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 255 | 	sha512_update(tfm, (const u8 *)bits, sizeof(bits)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 256 |  | 
 | 257 | 	/* Store state in digest */ | 
| Herbert Xu | 06ace7a | 2005-10-30 21:25:15 +1100 | [diff] [blame] | 258 | 	for (i = 0; i < 8; i++) | 
 | 259 | 		dst[i] = cpu_to_be64(sctx->state[i]); | 
 | 260 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 | 	/* Zeroize sensitive information. */ | 
 | 262 | 	memset(sctx, 0, sizeof(struct sha512_ctx)); | 
 | 263 | } | 
 | 264 |  | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 265 | static void sha384_final(struct crypto_tfm *tfm, u8 *hash) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 266 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 267 |         u8 D[64]; | 
 | 268 |  | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 269 | 	sha512_final(tfm, D); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 270 |  | 
 | 271 |         memcpy(hash, D, 48); | 
 | 272 |         memset(D, 0, 64); | 
 | 273 | } | 
 | 274 |  | 
 | 275 | static struct crypto_alg sha512 = { | 
 | 276 |         .cra_name       = "sha512", | 
 | 277 |         .cra_flags      = CRYPTO_ALG_TYPE_DIGEST, | 
 | 278 |         .cra_blocksize  = SHA512_HMAC_BLOCK_SIZE, | 
 | 279 |         .cra_ctxsize    = sizeof(struct sha512_ctx), | 
 | 280 |         .cra_module     = THIS_MODULE, | 
| Atsushi Nemoto | e1147d8 | 2006-04-10 08:42:35 +1000 | [diff] [blame] | 281 | 	.cra_alignmask	= 3, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 282 |         .cra_list       = LIST_HEAD_INIT(sha512.cra_list), | 
 | 283 |         .cra_u          = { .digest = { | 
 | 284 |                                 .dia_digestsize = SHA512_DIGEST_SIZE, | 
 | 285 |                                 .dia_init       = sha512_init, | 
 | 286 |                                 .dia_update     = sha512_update, | 
 | 287 |                                 .dia_final      = sha512_final } | 
 | 288 |         } | 
 | 289 | }; | 
 | 290 |  | 
 | 291 | static struct crypto_alg sha384 = { | 
 | 292 |         .cra_name       = "sha384", | 
 | 293 |         .cra_flags      = CRYPTO_ALG_TYPE_DIGEST, | 
 | 294 |         .cra_blocksize  = SHA384_HMAC_BLOCK_SIZE, | 
 | 295 |         .cra_ctxsize    = sizeof(struct sha512_ctx), | 
| Atsushi Nemoto | e1147d8 | 2006-04-10 08:42:35 +1000 | [diff] [blame] | 296 | 	.cra_alignmask	= 3, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 297 |         .cra_module     = THIS_MODULE, | 
 | 298 |         .cra_list       = LIST_HEAD_INIT(sha384.cra_list), | 
 | 299 |         .cra_u          = { .digest = { | 
 | 300 |                                 .dia_digestsize = SHA384_DIGEST_SIZE, | 
 | 301 |                                 .dia_init       = sha384_init, | 
 | 302 |                                 .dia_update     = sha512_update, | 
 | 303 |                                 .dia_final      = sha384_final } | 
 | 304 |         } | 
 | 305 | }; | 
 | 306 |  | 
 | 307 | MODULE_ALIAS("sha384"); | 
 | 308 |  | 
 | 309 | static int __init init(void) | 
 | 310 | { | 
 | 311 |         int ret = 0; | 
 | 312 |  | 
 | 313 |         if ((ret = crypto_register_alg(&sha384)) < 0) | 
 | 314 |                 goto out; | 
 | 315 |         if ((ret = crypto_register_alg(&sha512)) < 0) | 
 | 316 |                 crypto_unregister_alg(&sha384); | 
 | 317 | out: | 
 | 318 |         return ret; | 
 | 319 | } | 
 | 320 |  | 
 | 321 | static void __exit fini(void) | 
 | 322 | { | 
 | 323 |         crypto_unregister_alg(&sha384); | 
 | 324 |         crypto_unregister_alg(&sha512); | 
 | 325 | } | 
 | 326 |  | 
 | 327 | module_init(init); | 
 | 328 | module_exit(fini); | 
 | 329 |  | 
 | 330 | MODULE_LICENSE("GPL"); | 
 | 331 | MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); |