Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Cryptographic API. | |
3 | * | |
c1e26e1e | 4 | * s390 implementation of the SHA1 Secure Hash Algorithm. |
1da177e4 LT |
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: | |
86aa9fc2 JG |
11 | * Copyright IBM Corp. 2003,2007 |
12 | * Author(s): Thomas Spatzier | |
13 | * Jan Glauber (jan.glauber@de.ibm.com) | |
1da177e4 LT |
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/mm.h> | |
29 | #include <linux/crypto.h> | |
30 | #include <asm/scatterlist.h> | |
31 | #include <asm/byteorder.h> | |
c1e26e1e | 32 | #include "crypt_s390.h" |
1da177e4 LT |
33 | |
34 | #define SHA1_DIGEST_SIZE 20 | |
35 | #define SHA1_BLOCK_SIZE 64 | |
36 | ||
c1e26e1e JG |
37 | struct crypt_s390_sha1_ctx { |
38 | u64 count; | |
39 | u32 state[5]; | |
1da177e4 | 40 | u32 buf_len; |
c1e26e1e | 41 | u8 buffer[2 * SHA1_BLOCK_SIZE]; |
1da177e4 LT |
42 | }; |
43 | ||
6c2bb98b | 44 | static void sha1_init(struct crypto_tfm *tfm) |
1da177e4 | 45 | { |
6c2bb98b | 46 | struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm); |
86aa9fc2 JG |
47 | |
48 | ctx->state[0] = 0x67452301; | |
49 | ctx->state[1] = 0xEFCDAB89; | |
50 | ctx->state[2] = 0x98BADCFE; | |
51 | ctx->state[3] = 0x10325476; | |
52 | ctx->state[4] = 0xC3D2E1F0; | |
43600106 HX |
53 | |
54 | ctx->count = 0; | |
43600106 | 55 | ctx->buf_len = 0; |
1da177e4 LT |
56 | } |
57 | ||
6c2bb98b HX |
58 | static void sha1_update(struct crypto_tfm *tfm, const u8 *data, |
59 | unsigned int len) | |
1da177e4 | 60 | { |
c1e26e1e | 61 | struct crypt_s390_sha1_ctx *sctx; |
1da177e4 LT |
62 | long imd_len; |
63 | ||
6c2bb98b | 64 | sctx = crypto_tfm_ctx(tfm); |
86aa9fc2 | 65 | sctx->count += len * 8; /* message bit length */ |
1da177e4 | 66 | |
86aa9fc2 | 67 | /* anything in buffer yet? -> must be completed */ |
1da177e4 | 68 | if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { |
86aa9fc2 | 69 | /* complete full block and hash */ |
1da177e4 | 70 | memcpy(sctx->buffer + sctx->buf_len, data, |
86aa9fc2 | 71 | SHA1_BLOCK_SIZE - sctx->buf_len); |
c1e26e1e | 72 | crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, |
1da177e4 LT |
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 | ||
86aa9fc2 | 79 | /* rest of data contains full blocks? */ |
1da177e4 | 80 | imd_len = len & ~0x3ful; |
86aa9fc2 | 81 | if (imd_len) { |
c1e26e1e | 82 | crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); |
1da177e4 LT |
83 | data += imd_len; |
84 | len -= imd_len; | |
85 | } | |
86aa9fc2 JG |
86 | /* anything left? store in buffer */ |
87 | if (len) { | |
1da177e4 LT |
88 | memcpy(sctx->buffer + sctx->buf_len , data, len); |
89 | sctx->buf_len += len; | |
90 | } | |
91 | } | |
92 | ||
93 | ||
86aa9fc2 | 94 | static void pad_message(struct crypt_s390_sha1_ctx* sctx) |
1da177e4 LT |
95 | { |
96 | int index; | |
97 | ||
98 | index = sctx->buf_len; | |
86aa9fc2 JG |
99 | sctx->buf_len = (sctx->buf_len < 56) ? |
100 | SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; | |
101 | /* start pad with 1 */ | |
1da177e4 | 102 | sctx->buffer[index] = 0x80; |
86aa9fc2 | 103 | /* pad with zeros */ |
1da177e4 LT |
104 | index++; |
105 | memset(sctx->buffer + index, 0x00, sctx->buf_len - index); | |
86aa9fc2 | 106 | /* append length */ |
1da177e4 | 107 | memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, |
86aa9fc2 | 108 | sizeof sctx->count); |
1da177e4 LT |
109 | } |
110 | ||
111 | /* Add padding and return the message digest. */ | |
6c2bb98b | 112 | static void sha1_final(struct crypto_tfm *tfm, u8 *out) |
1da177e4 | 113 | { |
6c2bb98b | 114 | struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); |
1da177e4 | 115 | |
86aa9fc2 | 116 | /* must perform manual padding */ |
1da177e4 | 117 | pad_message(sctx); |
c1e26e1e | 118 | crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); |
86aa9fc2 | 119 | /* copy digest to out */ |
1da177e4 | 120 | memcpy(out, sctx->state, SHA1_DIGEST_SIZE); |
86aa9fc2 | 121 | /* wipe context */ |
1da177e4 LT |
122 | memset(sctx, 0, sizeof *sctx); |
123 | } | |
124 | ||
125 | static struct crypto_alg alg = { | |
126 | .cra_name = "sha1", | |
86aa9fc2 | 127 | .cra_driver_name= "sha1-s390", |
65b75c36 | 128 | .cra_priority = CRYPT_S390_PRIORITY, |
1da177e4 LT |
129 | .cra_flags = CRYPTO_ALG_TYPE_DIGEST, |
130 | .cra_blocksize = SHA1_BLOCK_SIZE, | |
c1e26e1e | 131 | .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), |
1da177e4 | 132 | .cra_module = THIS_MODULE, |
86aa9fc2 | 133 | .cra_list = LIST_HEAD_INIT(alg.cra_list), |
1da177e4 LT |
134 | .cra_u = { .digest = { |
135 | .dia_digestsize = SHA1_DIGEST_SIZE, | |
86aa9fc2 JG |
136 | .dia_init = sha1_init, |
137 | .dia_update = sha1_update, | |
138 | .dia_final = sha1_final } } | |
1da177e4 LT |
139 | }; |
140 | ||
86aa9fc2 | 141 | static int __init init(void) |
1da177e4 | 142 | { |
86aa9fc2 JG |
143 | if (!crypt_s390_func_available(KIMD_SHA_1)) |
144 | return -EOPNOTSUPP; | |
1da177e4 | 145 | |
86aa9fc2 | 146 | return crypto_register_alg(&alg); |
1da177e4 LT |
147 | } |
148 | ||
86aa9fc2 | 149 | static void __exit fini(void) |
1da177e4 LT |
150 | { |
151 | crypto_unregister_alg(&alg); | |
152 | } | |
153 | ||
154 | module_init(init); | |
155 | module_exit(fini); | |
156 | ||
157 | MODULE_ALIAS("sha1"); | |
158 | ||
159 | MODULE_LICENSE("GPL"); | |
160 | MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); |