Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com>
0003  *
0004  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
0005  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
0006  * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
0007  */
0008 #include <crypto/internal/hash.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/mm.h>
0012 #include <linux/init.h>
0013 #include <linux/crypto.h>
0014 #include <linux/types.h>
0015 #include <crypto/sha2.h>
0016 #include <crypto/sha512_base.h>
0017 #include <linux/percpu.h>
0018 #include <asm/byteorder.h>
0019 #include <asm/unaligned.h>
0020 
0021 const u8 sha384_zero_message_hash[SHA384_DIGEST_SIZE] = {
0022     0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
0023     0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
0024     0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
0025     0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
0026     0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
0027     0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b
0028 };
0029 EXPORT_SYMBOL_GPL(sha384_zero_message_hash);
0030 
0031 const u8 sha512_zero_message_hash[SHA512_DIGEST_SIZE] = {
0032     0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
0033     0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
0034     0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
0035     0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
0036     0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
0037     0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
0038     0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
0039     0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
0040 };
0041 EXPORT_SYMBOL_GPL(sha512_zero_message_hash);
0042 
0043 static inline u64 Ch(u64 x, u64 y, u64 z)
0044 {
0045         return z ^ (x & (y ^ z));
0046 }
0047 
0048 static inline u64 Maj(u64 x, u64 y, u64 z)
0049 {
0050         return (x & y) | (z & (x | y));
0051 }
0052 
0053 static const u64 sha512_K[80] = {
0054         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
0055         0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0056         0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
0057         0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0058         0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
0059         0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0060         0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
0061         0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0062         0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
0063         0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0064         0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
0065         0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0066         0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
0067         0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0068         0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
0069         0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0070         0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
0071         0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0072         0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
0073         0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0074         0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
0075         0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0076         0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
0077         0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0078         0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
0079         0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0080         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
0081 };
0082 
0083 #define e0(x)       (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
0084 #define e1(x)       (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
0085 #define s0(x)       (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
0086 #define s1(x)       (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
0087 
0088 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
0089 {
0090     W[I] = get_unaligned_be64((__u64 *)input + I);
0091 }
0092 
0093 static inline void BLEND_OP(int I, u64 *W)
0094 {
0095     W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
0096 }
0097 
0098 static void
0099 sha512_transform(u64 *state, const u8 *input)
0100 {
0101     u64 a, b, c, d, e, f, g, h, t1, t2;
0102 
0103     int i;
0104     u64 W[16];
0105 
0106     /* load the state into our registers */
0107     a=state[0];   b=state[1];   c=state[2];   d=state[3];
0108     e=state[4];   f=state[5];   g=state[6];   h=state[7];
0109 
0110     /* now iterate */
0111     for (i=0; i<80; i+=8) {
0112         if (!(i & 8)) {
0113             int j;
0114 
0115             if (i < 16) {
0116                 /* load the input */
0117                 for (j = 0; j < 16; j++)
0118                     LOAD_OP(i + j, W, input);
0119             } else {
0120                 for (j = 0; j < 16; j++) {
0121                     BLEND_OP(i + j, W);
0122                 }
0123             }
0124         }
0125 
0126         t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[(i & 15)];
0127         t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
0128         t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
0129         t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
0130         t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
0131         t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
0132         t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
0133         t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
0134         t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
0135         t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
0136         t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
0137         t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
0138         t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
0139         t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
0140         t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
0141         t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
0142     }
0143 
0144     state[0] += a; state[1] += b; state[2] += c; state[3] += d;
0145     state[4] += e; state[5] += f; state[6] += g; state[7] += h;
0146 }
0147 
0148 static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src,
0149                     int blocks)
0150 {
0151     while (blocks--) {
0152         sha512_transform(sst->state, src);
0153         src += SHA512_BLOCK_SIZE;
0154     }
0155 }
0156 
0157 int crypto_sha512_update(struct shash_desc *desc, const u8 *data,
0158             unsigned int len)
0159 {
0160     return sha512_base_do_update(desc, data, len, sha512_generic_block_fn);
0161 }
0162 EXPORT_SYMBOL(crypto_sha512_update);
0163 
0164 static int sha512_final(struct shash_desc *desc, u8 *hash)
0165 {
0166     sha512_base_do_finalize(desc, sha512_generic_block_fn);
0167     return sha512_base_finish(desc, hash);
0168 }
0169 
0170 int crypto_sha512_finup(struct shash_desc *desc, const u8 *data,
0171             unsigned int len, u8 *hash)
0172 {
0173     sha512_base_do_update(desc, data, len, sha512_generic_block_fn);
0174     return sha512_final(desc, hash);
0175 }
0176 EXPORT_SYMBOL(crypto_sha512_finup);
0177 
0178 static struct shash_alg sha512_algs[2] = { {
0179     .digestsize =   SHA512_DIGEST_SIZE,
0180     .init       =   sha512_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   =   "sha512",
0187         .cra_driver_name =  "sha512-generic",
0188         .cra_priority   =   100,
0189         .cra_blocksize  =   SHA512_BLOCK_SIZE,
0190         .cra_module =   THIS_MODULE,
0191     }
0192 }, {
0193     .digestsize =   SHA384_DIGEST_SIZE,
0194     .init       =   sha384_base_init,
0195     .update     =   crypto_sha512_update,
0196     .final      =   sha512_final,
0197     .finup      =   crypto_sha512_finup,
0198     .descsize   =   sizeof(struct sha512_state),
0199     .base       =   {
0200         .cra_name   =   "sha384",
0201         .cra_driver_name =  "sha384-generic",
0202         .cra_priority   =   100,
0203         .cra_blocksize  =   SHA384_BLOCK_SIZE,
0204         .cra_module =   THIS_MODULE,
0205     }
0206 } };
0207 
0208 static int __init sha512_generic_mod_init(void)
0209 {
0210     return crypto_register_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
0211 }
0212 
0213 static void __exit sha512_generic_mod_fini(void)
0214 {
0215     crypto_unregister_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
0216 }
0217 
0218 subsys_initcall(sha512_generic_mod_init);
0219 module_exit(sha512_generic_mod_fini);
0220 
0221 MODULE_LICENSE("GPL");
0222 MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
0223 
0224 MODULE_ALIAS_CRYPTO("sha384");
0225 MODULE_ALIAS_CRYPTO("sha384-generic");
0226 MODULE_ALIAS_CRYPTO("sha512");
0227 MODULE_ALIAS_CRYPTO("sha512-generic");