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_generic.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 #include <crypto/sha.h> 30 31 #include "crypt_s390.h" 32 33 struct s390_sha1_ctx { 34 u64 count; /* message length */ 35 u32 state[5]; 36 u8 buf[2 * SHA1_BLOCK_SIZE]; 37 }; 38 39 static void sha1_init(struct crypto_tfm *tfm) 40 { 41 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 42 43 sctx->state[0] = SHA1_H0; 44 sctx->state[1] = SHA1_H1; 45 sctx->state[2] = SHA1_H2; 46 sctx->state[3] = SHA1_H3; 47 sctx->state[4] = SHA1_H4; 48 sctx->count = 0; 49 } 50 51 static void sha1_update(struct crypto_tfm *tfm, const u8 *data, 52 unsigned int len) 53 { 54 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 55 unsigned int index; 56 int ret; 57 58 /* how much is already in the buffer? */ 59 index = sctx->count & 0x3f; 60 61 sctx->count += len; 62 63 if (index + len < SHA1_BLOCK_SIZE) 64 goto store; 65 66 /* process one stored block */ 67 if (index) { 68 memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index); 69 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, 70 SHA1_BLOCK_SIZE); 71 BUG_ON(ret != SHA1_BLOCK_SIZE); 72 data += SHA1_BLOCK_SIZE - index; 73 len -= SHA1_BLOCK_SIZE - index; 74 } 75 76 /* process as many blocks as possible */ 77 if (len >= SHA1_BLOCK_SIZE) { 78 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, 79 len & ~(SHA1_BLOCK_SIZE - 1)); 80 BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1))); 81 data += ret; 82 len -= ret; 83 } 84 85 store: 86 /* anything left? */ 87 if (len) 88 memcpy(sctx->buf + index , data, len); 89 } 90 91 /* Add padding and return the message digest. */ 92 static void sha1_final(struct crypto_tfm *tfm, u8 *out) 93 { 94 struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); 95 u64 bits; 96 unsigned int index, end; 97 int ret; 98 99 /* must perform manual padding */ 100 index = sctx->count & 0x3f; 101 end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE); 102 103 /* start pad with 1 */ 104 sctx->buf[index] = 0x80; 105 106 /* pad with zeros */ 107 index++; 108 memset(sctx->buf + index, 0x00, end - index - 8); 109 110 /* append message length */ 111 bits = sctx->count * 8; 112 memcpy(sctx->buf + end - 8, &bits, sizeof(bits)); 113 114 ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end); 115 BUG_ON(ret != end); 116 117 /* copy digest to out */ 118 memcpy(out, sctx->state, SHA1_DIGEST_SIZE); 119 120 /* wipe context */ 121 memset(sctx, 0, sizeof *sctx); 122 } 123 124 static struct crypto_alg alg = { 125 .cra_name = "sha1", 126 .cra_driver_name= "sha1-s390", 127 .cra_priority = CRYPT_S390_PRIORITY, 128 .cra_flags = CRYPTO_ALG_TYPE_DIGEST, 129 .cra_blocksize = SHA1_BLOCK_SIZE, 130 .cra_ctxsize = sizeof(struct s390_sha1_ctx), 131 .cra_module = THIS_MODULE, 132 .cra_list = LIST_HEAD_INIT(alg.cra_list), 133 .cra_u = { .digest = { 134 .dia_digestsize = SHA1_DIGEST_SIZE, 135 .dia_init = sha1_init, 136 .dia_update = sha1_update, 137 .dia_final = sha1_final } } 138 }; 139 140 static int __init init(void) 141 { 142 if (!crypt_s390_func_available(KIMD_SHA_1)) 143 return -EOPNOTSUPP; 144 145 return crypto_register_alg(&alg); 146 } 147 148 static void __exit fini(void) 149 { 150 crypto_unregister_alg(&alg); 151 } 152 153 module_init(init); 154 module_exit(fini); 155 156 MODULE_ALIAS("sha1"); 157 158 MODULE_LICENSE("GPL"); 159 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); 160