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 (C) 2003 IBM Deutschland GmbH, IBM Corporation 12 * Author(s): Thomas Spatzier (tspat@de.ibm.com) 13 * 14 * Derived from "crypto/sha1.c" 15 * Copyright (c) Alan Smithee. 16 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 17 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 18 * 19 * This program is free software; you can redistribute it and/or modify it 20 * under the terms of the GNU General Public License as published by the Free 21 * Software Foundation; either version 2 of the License, or (at your option) 22 * any later version. 23 * 24 */ 25 #include <linux/init.h> 26 #include <linux/module.h> 27 #include <linux/mm.h> 28 #include <linux/crypto.h> 29 #include <asm/scatterlist.h> 30 #include <asm/byteorder.h> 31 #include "crypt_s390.h" 32 33 #define SHA1_DIGEST_SIZE 20 34 #define SHA1_BLOCK_SIZE 64 35 36 struct crypt_s390_sha1_ctx { 37 u64 count; 38 u32 state[5]; 39 u32 buf_len; 40 u8 buffer[2 * SHA1_BLOCK_SIZE]; 41 }; 42 43 static void 44 sha1_init(void *ctx) 45 { 46 static const struct crypt_s390_sha1_ctx initstate = { 47 .state = { 48 0x67452301, 49 0xEFCDAB89, 50 0x98BADCFE, 51 0x10325476, 52 0xC3D2E1F0 53 }, 54 }; 55 memcpy(ctx, &initstate, sizeof(initstate)); 56 } 57 58 static void 59 sha1_update(void *ctx, const u8 *data, unsigned int len) 60 { 61 struct crypt_s390_sha1_ctx *sctx; 62 long imd_len; 63 64 sctx = ctx; 65 sctx->count += len * 8; //message bit length 66 67 //anything in buffer yet? -> must be completed 68 if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { 69 //complete full block and hash 70 memcpy(sctx->buffer + sctx->buf_len, data, 71 SHA1_BLOCK_SIZE - sctx->buf_len); 72 crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, 73 SHA1_BLOCK_SIZE); 74 data += SHA1_BLOCK_SIZE - sctx->buf_len; 75 len -= SHA1_BLOCK_SIZE - sctx->buf_len; 76 sctx->buf_len = 0; 77 } 78 79 //rest of data contains full blocks? 80 imd_len = len & ~0x3ful; 81 if (imd_len){ 82 crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); 83 data += imd_len; 84 len -= imd_len; 85 } 86 //anything left? store in buffer 87 if (len){ 88 memcpy(sctx->buffer + sctx->buf_len , data, len); 89 sctx->buf_len += len; 90 } 91 } 92 93 94 static void 95 pad_message(struct crypt_s390_sha1_ctx* sctx) 96 { 97 int index; 98 99 index = sctx->buf_len; 100 sctx->buf_len = (sctx->buf_len < 56)? 101 SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; 102 //start pad with 1 103 sctx->buffer[index] = 0x80; 104 //pad with zeros 105 index++; 106 memset(sctx->buffer + index, 0x00, sctx->buf_len - index); 107 //append length 108 memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, 109 sizeof sctx->count); 110 } 111 112 /* Add padding and return the message digest. */ 113 static void 114 sha1_final(void* ctx, u8 *out) 115 { 116 struct crypt_s390_sha1_ctx *sctx = ctx; 117 118 //must perform manual padding 119 pad_message(sctx); 120 crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); 121 //copy digest to out 122 memcpy(out, sctx->state, SHA1_DIGEST_SIZE); 123 /* Wipe context */ 124 memset(sctx, 0, sizeof *sctx); 125 } 126 127 static struct crypto_alg alg = { 128 .cra_name = "sha1", 129 .cra_flags = CRYPTO_ALG_TYPE_DIGEST, 130 .cra_blocksize = SHA1_BLOCK_SIZE, 131 .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), 132 .cra_module = THIS_MODULE, 133 .cra_list = LIST_HEAD_INIT(alg.cra_list), 134 .cra_u = { .digest = { 135 .dia_digestsize = SHA1_DIGEST_SIZE, 136 .dia_init = sha1_init, 137 .dia_update = sha1_update, 138 .dia_final = sha1_final } } 139 }; 140 141 static int 142 init(void) 143 { 144 int ret = -ENOSYS; 145 146 if (crypt_s390_func_available(KIMD_SHA_1)){ 147 ret = crypto_register_alg(&alg); 148 if (ret == 0){ 149 printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n"); 150 } 151 } 152 return ret; 153 } 154 155 static void __exit 156 fini(void) 157 { 158 crypto_unregister_alg(&alg); 159 } 160 161 module_init(init); 162 module_exit(fini); 163 164 MODULE_ALIAS("sha1"); 165 166 MODULE_LICENSE("GPL"); 167 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); 168