Back to home page

LXR

 
 

    


0001 /* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com>
0002  *
0003  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
0004  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
0005  * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
0006  *
0007  * This program is free software; you can redistribute it and/or modify it
0008  * under the terms of the GNU General Public License as published by the
0009  * Free Software Foundation; either version 2, or (at your option) any
0010  * later version.
0011  *
0012  */
0013 #include <crypto/internal/hash.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/mm.h>
0017 #include <linux/init.h>
0018 #include <linux/crypto.h>
0019 #include <linux/types.h>
0020 #include <crypto/sha.h>
0021 #include <crypto/sha512_base.h>
0022 #include <linux/percpu.h>
0023 #include <asm/byteorder.h>
0024 #include <asm/unaligned.h>
0025 
0026 static inline u64 Ch(u64 x, u64 y, u64 z)
0027 {
0028         return z ^ (x & (y ^ z));
0029 }
0030 
0031 static inline u64 Maj(u64 x, u64 y, u64 z)
0032 {
0033         return (x & y) | (z & (x | y));
0034 }
0035 
0036 static const u64 sha512_K[80] = {
0037         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
0038         0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0039         0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
0040         0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0041         0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
0042         0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0043         0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
0044         0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0045         0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
0046         0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0047         0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
0048         0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0049         0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
0050         0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0051         0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
0052         0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0053         0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
0054         0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0055         0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
0056         0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0057         0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
0058         0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0059         0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
0060         0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0061         0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
0062         0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0063         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
0064 };
0065 
0066 #define e0(x)       (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
0067 #define e1(x)       (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
0068 #define s0(x)       (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
0069 #define s1(x)       (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
0070 
0071 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
0072 {
0073     W[I] = get_unaligned_be64((__u64 *)input + I);
0074 }
0075 
0076 static inline void BLEND_OP(int I, u64 *W)
0077 {
0078     W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
0079 }
0080 
0081 static void
0082 sha512_transform(u64 *state, const u8 *input)
0083 {
0084     u64 a, b, c, d, e, f, g, h, t1, t2;
0085 
0086     int i;
0087     u64 W[16];
0088 
0089     /* load the state into our registers */
0090     a=state[0];   b=state[1];   c=state[2];   d=state[3];
0091     e=state[4];   f=state[5];   g=state[6];   h=state[7];
0092 
0093     /* now iterate */
0094     for (i=0; i<80; i+=8) {
0095         if (!(i & 8)) {
0096             int j;
0097 
0098             if (i < 16) {
0099                 /* load the input */
0100                 for (j = 0; j < 16; j++)
0101                     LOAD_OP(i + j, W, input);
0102             } else {
0103                 for (j = 0; j < 16; j++) {
0104                     BLEND_OP(i + j, W);
0105                 }
0106             }
0107         }
0108 
0109         t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[(i & 15)];
0110         t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
0111         t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
0112         t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
0113         t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
0114         t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
0115         t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
0116         t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
0117         t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
0118         t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
0119         t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
0120         t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
0121         t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
0122         t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
0123         t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
0124         t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
0125     }
0126 
0127     state[0] += a; state[1] += b; state[2] += c; state[3] += d;
0128     state[4] += e; state[5] += f; state[6] += g; state[7] += h;
0129 
0130     /* erase our data */
0131     a = b = c = d = e = f = g = h = t1 = t2 = 0;
0132 }
0133 
0134 static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src,
0135                     int blocks)
0136 {
0137     while (blocks--) {
0138         sha512_transform(sst->state, src);
0139         src += SHA512_BLOCK_SIZE;
0140     }
0141 }
0142 
0143 int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
0144             unsigned int len)
0145 {
0146     return sha512_base_do_update(desc, data, len, sha512_generic_block_fn);
0147 }
0148 EXPORT_SYMBOL(crypto_sha512_update);
0149 
0150 static int sha512_final(struct shash_desc *desc, u8 *hash)
0151 {
0152     sha512_base_do_finalize(desc, sha512_generic_block_fn);
0153     return sha512_base_finish(desc, hash);
0154 }
0155 
0156 int crypto_sha512_finup(struct shash_desc *desc, const u8 *data,
0157             unsigned int len, u8 *hash)
0158 {
0159     sha512_base_do_update(desc, data, len, sha512_generic_block_fn);
0160     return sha512_final(desc, hash);
0161 }
0162 EXPORT_SYMBOL(crypto_sha512_finup);
0163 
0164 static struct shash_alg sha512_algs[2] = { {
0165     .digestsize =   SHA512_DIGEST_SIZE,
0166     .init       =   sha512_base_init,
0167     .update     =   crypto_sha512_update,
0168     .final      =   sha512_final,
0169     .finup      =   crypto_sha512_finup,
0170     .descsize   =   sizeof(struct sha512_state),
0171     .base       =   {
0172         .cra_name   =   "sha512",
0173         .cra_driver_name =  "sha512-generic",
0174         .cra_flags  =   CRYPTO_ALG_TYPE_SHASH,
0175         .cra_blocksize  =   SHA512_BLOCK_SIZE,
0176         .cra_module =   THIS_MODULE,
0177     }
0178 }, {
0179     .digestsize =   SHA384_DIGEST_SIZE,
0180     .init       =   sha384_base_init,
0181     .update     =   crypto_sha512_update,
0182     .final      =   sha512_final,
0183     .finup      =   crypto_sha512_finup,
0184     .descsize   =   sizeof(struct sha512_state),
0185     .base       =   {
0186         .cra_name   =   "sha384",
0187         .cra_driver_name =  "sha384-generic",
0188         .cra_flags  =   CRYPTO_ALG_TYPE_SHASH,
0189         .cra_blocksize  =   SHA384_BLOCK_SIZE,
0190         .cra_module =   THIS_MODULE,
0191     }
0192 } };
0193 
0194 static int __init sha512_generic_mod_init(void)
0195 {
0196     return crypto_register_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
0197 }
0198 
0199 static void __exit sha512_generic_mod_fini(void)
0200 {
0201     crypto_unregister_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
0202 }
0203 
0204 module_init(sha512_generic_mod_init);
0205 module_exit(sha512_generic_mod_fini);
0206 
0207 MODULE_LICENSE("GPL");
0208 MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
0209 
0210 MODULE_ALIAS_CRYPTO("sha384");
0211 MODULE_ALIAS_CRYPTO("sha384-generic");
0212 MODULE_ALIAS_CRYPTO("sha512");
0213 MODULE_ALIAS_CRYPTO("sha512-generic");