1 /* 2 * Cryptographic API. 3 * 4 * s390 implementation of the SHA1 Secure Hash Algorithm. 5 * 6 * Derived from cryptoapi implementation, adapted for in-place 7 * scatterlist interface. Originally based on the public domain 8 * implementation written by Steve Reid. 9 * 10 * s390 Version: 11 * Copyright IBM Corp. 2003,2007 12 * Author(s): Thomas Spatzier 13 * Jan Glauber (jan.glauber@de.ibm.com) 14 * 15 * Derived from "crypto/sha1.c" 16 * Copyright (c) Alan Smithee. 17 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 18 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 19 * 20 * This program is free software; you can redistribute it and/or modify it 21 * under the terms of the GNU General Public License as published by the Free 22 * Software Foundation; either version 2 of the License, or (at your option) 23 * any later version. 24 * 25 */ 26 #include <linux/init.h> 27 #include <linux/module.h> 28 #include <linux/crypto.h> 29 30 #include "crypt_s390.h" 31 32 #define SHA1_DIGEST_SIZE 20 33 #define SHA1_BLOCK_SIZE 64 34 35 struct s390_sha1_ctx { 36 u64 count; /* message length */ 37 u32 state[5]; 38 u8 buf[2 * SHA1_BLOCK_SIZE]; 39 }; 40 41 static void sha1_init(struct crypto_tfm *tfm) 42 { 43 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 44 45 sctx->state[0] = 0x67452301; 46 sctx->state[1] = 0xEFCDAB89; 47 sctx->state[2] = 0x98BADCFE; 48 sctx->state[3] = 0x10325476; 49 sctx->state[4] = 0xC3D2E1F0; 50 sctx->count = 0; 51 } 52 53 static void sha1_update(struct crypto_tfm *tfm, const u8 *data, 54 unsigned int len) 55 { 56 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 57 unsigned int index; 58 int ret; 59 60 /* how much is already in the buffer? */ 61 index = sctx->count & 0x3f; 62 63 sctx->count += len; 64 65 if (index + len < SHA1_BLOCK_SIZE) 66 goto store; 67 68 /* process one stored block */ 69 if (index) { 70 memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index); 71 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, 72 SHA1_BLOCK_SIZE); 73 BUG_ON(ret != SHA1_BLOCK_SIZE); 74 data += SHA1_BLOCK_SIZE - index; 75 len -= SHA1_BLOCK_SIZE - index; 76 } 77 78 /* process as many blocks as possible */ 79 if (len >= SHA1_BLOCK_SIZE) { 80 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, 81 len & ~(SHA1_BLOCK_SIZE - 1)); 82 BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1))); 83 data += ret; 84 len -= ret; 85 } 86 87 store: 88 /* anything left? */ 89 if (len) 90 memcpy(sctx->buf + index , data, len); 91 } 92 93 /* Add padding and return the message digest. */ 94 static void sha1_final(struct crypto_tfm *tfm, u8 *out) 95 { 96 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 97 u64 bits; 98 unsigned int index, end; 99 int ret; 100 101 /* must perform manual padding */ 102 index = sctx->count & 0x3f; 103 end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE); 104 105 /* start pad with 1 */ 106 sctx->buf[index] = 0x80; 107 108 /* pad with zeros */ 109 index++; 110 memset(sctx->buf + index, 0x00, end - index - 8); 111 112 /* append message length */ 113 bits = sctx->count * 8; 114 memcpy(sctx->buf + end - 8, &bits, sizeof(bits)); 115 116 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end); 117 BUG_ON(ret != end); 118 119 /* copy digest to out */ 120 memcpy(out, sctx->state, SHA1_DIGEST_SIZE); 121 122 /* wipe context */ 123 memset(sctx, 0, sizeof *sctx); 124 } 125 126 static struct crypto_alg alg = { 127 .cra_name = "sha1", 128 .cra_driver_name= "sha1-s390", 129 .cra_priority = CRYPT_S390_PRIORITY, 130 .cra_flags = CRYPTO_ALG_TYPE_DIGEST, 131 .cra_blocksize = SHA1_BLOCK_SIZE, 132 .cra_ctxsize = sizeof(struct s390_sha1_ctx), 133 .cra_module = THIS_MODULE, 134 .cra_list = LIST_HEAD_INIT(alg.cra_list), 135 .cra_u = { .digest = { 136 .dia_digestsize = SHA1_DIGEST_SIZE, 137 .dia_init = sha1_init, 138 .dia_update = sha1_update, 139 .dia_final = sha1_final } } 140 }; 141 142 static int __init init(void) 143 { 144 if (!crypt_s390_func_available(KIMD_SHA_1)) 145 return -EOPNOTSUPP; 146 147 return crypto_register_alg(&alg); 148 } 149 150 static void __exit fini(void) 151 { 152 crypto_unregister_alg(&alg); 153 } 154 155 module_init(init); 156 module_exit(fini); 157 158 MODULE_ALIAS("sha1"); 159 160 MODULE_LICENSE("GPL"); 161 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); 162