1 /* 2 * Cryptographic API. 3 * Glue code for the SHA1 Secure Hash Algorithm assembler implementation 4 * 5 * This file is based on sha1_generic.c and sha1_ssse3_glue.c 6 * 7 * Copyright (c) Alan Smithee. 8 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 9 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 10 * Copyright (c) Mathias Krause <minipli@googlemail.com> 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the Free 14 * Software Foundation; either version 2 of the License, or (at your option) 15 * any later version. 16 * 17 */ 18 19 #include <crypto/internal/hash.h> 20 #include <linux/init.h> 21 #include <linux/module.h> 22 #include <linux/cryptohash.h> 23 #include <linux/types.h> 24 #include <crypto/sha.h> 25 #include <asm/byteorder.h> 26 27 struct SHA1_CTX { 28 uint32_t h0,h1,h2,h3,h4; 29 u64 count; 30 u8 data[SHA1_BLOCK_SIZE]; 31 }; 32 33 asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest, 34 const unsigned char *data, unsigned int rounds); 35 36 37 static int sha1_init(struct shash_desc *desc) 38 { 39 struct SHA1_CTX *sctx = shash_desc_ctx(desc); 40 memset(sctx, 0, sizeof(*sctx)); 41 sctx->h0 = SHA1_H0; 42 sctx->h1 = SHA1_H1; 43 sctx->h2 = SHA1_H2; 44 sctx->h3 = SHA1_H3; 45 sctx->h4 = SHA1_H4; 46 return 0; 47 } 48 49 50 static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data, 51 unsigned int len, unsigned int partial) 52 { 53 unsigned int done = 0; 54 55 sctx->count += len; 56 57 if (partial) { 58 done = SHA1_BLOCK_SIZE - partial; 59 memcpy(sctx->data + partial, data, done); 60 sha1_block_data_order(sctx, sctx->data, 1); 61 } 62 63 if (len - done >= SHA1_BLOCK_SIZE) { 64 const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE; 65 sha1_block_data_order(sctx, data + done, rounds); 66 done += rounds * SHA1_BLOCK_SIZE; 67 } 68 69 memcpy(sctx->data, data + done, len - done); 70 return 0; 71 } 72 73 74 static int sha1_update(struct shash_desc *desc, const u8 *data, 75 unsigned int len) 76 { 77 struct SHA1_CTX *sctx = shash_desc_ctx(desc); 78 unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; 79 int res; 80 81 /* Handle the fast case right here */ 82 if (partial + len < SHA1_BLOCK_SIZE) { 83 sctx->count += len; 84 memcpy(sctx->data + partial, data, len); 85 return 0; 86 } 87 res = __sha1_update(sctx, data, len, partial); 88 return res; 89 } 90 91 92 /* Add padding and return the message digest. */ 93 static int sha1_final(struct shash_desc *desc, u8 *out) 94 { 95 struct SHA1_CTX *sctx = shash_desc_ctx(desc); 96 unsigned int i, index, padlen; 97 __be32 *dst = (__be32 *)out; 98 __be64 bits; 99 static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; 100 101 bits = cpu_to_be64(sctx->count << 3); 102 103 /* Pad out to 56 mod 64 and append length */ 104 index = sctx->count % SHA1_BLOCK_SIZE; 105 padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index); 106 /* We need to fill a whole block for __sha1_update() */ 107 if (padlen <= 56) { 108 sctx->count += padlen; 109 memcpy(sctx->data + index, padding, padlen); 110 } else { 111 __sha1_update(sctx, padding, padlen, index); 112 } 113 __sha1_update(sctx, (const u8 *)&bits, sizeof(bits), 56); 114 115 /* Store state in digest */ 116 for (i = 0; i < 5; i++) 117 dst[i] = cpu_to_be32(((u32 *)sctx)[i]); 118 119 /* Wipe context */ 120 memset(sctx, 0, sizeof(*sctx)); 121 return 0; 122 } 123 124 125 static int sha1_export(struct shash_desc *desc, void *out) 126 { 127 struct SHA1_CTX *sctx = shash_desc_ctx(desc); 128 memcpy(out, sctx, sizeof(*sctx)); 129 return 0; 130 } 131 132 133 static int sha1_import(struct shash_desc *desc, const void *in) 134 { 135 struct SHA1_CTX *sctx = shash_desc_ctx(desc); 136 memcpy(sctx, in, sizeof(*sctx)); 137 return 0; 138 } 139 140 141 static struct shash_alg alg = { 142 .digestsize = SHA1_DIGEST_SIZE, 143 .init = sha1_init, 144 .update = sha1_update, 145 .final = sha1_final, 146 .export = sha1_export, 147 .import = sha1_import, 148 .descsize = sizeof(struct SHA1_CTX), 149 .statesize = sizeof(struct SHA1_CTX), 150 .base = { 151 .cra_name = "sha1", 152 .cra_driver_name= "sha1-asm", 153 .cra_priority = 150, 154 .cra_flags = CRYPTO_ALG_TYPE_SHASH, 155 .cra_blocksize = SHA1_BLOCK_SIZE, 156 .cra_module = THIS_MODULE, 157 } 158 }; 159 160 161 static int __init sha1_mod_init(void) 162 { 163 return crypto_register_shash(&alg); 164 } 165 166 167 static void __exit sha1_mod_fini(void) 168 { 169 crypto_unregister_shash(&alg); 170 } 171 172 173 module_init(sha1_mod_init); 174 module_exit(sha1_mod_fini); 175 176 MODULE_LICENSE("GPL"); 177 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); 178 MODULE_ALIAS("sha1"); 179 MODULE_AUTHOR("David McCullough <ucdevel@gmail.com>"); 180