Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Cryptographic API. | |
3 | * | |
4 | * MD5 Message Digest Algorithm (RFC1321). | |
5 | * | |
6 | * Derived from cryptoapi implementation, originally based on the | |
7 | * public domain implementation written by Colin Plumb in 1993. | |
8 | * | |
9 | * Copyright (c) Cryptoapi developers. | |
10 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | |
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 | */ | |
14b75ba7 | 18 | #include <crypto/internal/hash.h> |
7d6f75eb | 19 | #include <crypto/md5.h> |
1da177e4 LT |
20 | #include <linux/init.h> |
21 | #include <linux/module.h> | |
22 | #include <linux/string.h> | |
06ace7a9 | 23 | #include <linux/types.h> |
bc0b96b5 | 24 | #include <linux/cryptohash.h> |
1da177e4 LT |
25 | #include <asm/byteorder.h> |
26 | ||
0c4c78de LC |
27 | const u8 md5_zero_message_hash[MD5_DIGEST_SIZE] = { |
28 | 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, | |
29 | 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e, | |
30 | }; | |
31 | EXPORT_SYMBOL_GPL(md5_zero_message_hash); | |
32 | ||
1da177e4 LT |
33 | /* XXX: this stuff can be optimized */ |
34 | static inline void le32_to_cpu_array(u32 *buf, unsigned int words) | |
35 | { | |
36 | while (words--) { | |
37 | __le32_to_cpus(buf); | |
38 | buf++; | |
39 | } | |
40 | } | |
41 | ||
42 | static inline void cpu_to_le32_array(u32 *buf, unsigned int words) | |
43 | { | |
44 | while (words--) { | |
45 | __cpu_to_le32s(buf); | |
46 | buf++; | |
47 | } | |
48 | } | |
49 | ||
7d6f75eb | 50 | static inline void md5_transform_helper(struct md5_state *ctx) |
1da177e4 LT |
51 | { |
52 | le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); | |
53 | md5_transform(ctx->hash, ctx->block); | |
54 | } | |
55 | ||
14b75ba7 | 56 | static int md5_init(struct shash_desc *desc) |
1da177e4 | 57 | { |
7d6f75eb | 58 | struct md5_state *mctx = shash_desc_ctx(desc); |
1da177e4 | 59 | |
6a185016 LC |
60 | mctx->hash[0] = MD5_H0; |
61 | mctx->hash[1] = MD5_H1; | |
62 | mctx->hash[2] = MD5_H2; | |
63 | mctx->hash[3] = MD5_H3; | |
1da177e4 | 64 | mctx->byte_count = 0; |
14b75ba7 AKR |
65 | |
66 | return 0; | |
1da177e4 LT |
67 | } |
68 | ||
14b75ba7 | 69 | static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len) |
1da177e4 | 70 | { |
7d6f75eb | 71 | struct md5_state *mctx = shash_desc_ctx(desc); |
1da177e4 LT |
72 | const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); |
73 | ||
74 | mctx->byte_count += len; | |
75 | ||
76 | if (avail > len) { | |
77 | memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), | |
78 | data, len); | |
14b75ba7 | 79 | return 0; |
1da177e4 LT |
80 | } |
81 | ||
82 | memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), | |
83 | data, avail); | |
84 | ||
85 | md5_transform_helper(mctx); | |
86 | data += avail; | |
87 | len -= avail; | |
88 | ||
89 | while (len >= sizeof(mctx->block)) { | |
90 | memcpy(mctx->block, data, sizeof(mctx->block)); | |
91 | md5_transform_helper(mctx); | |
92 | data += sizeof(mctx->block); | |
93 | len -= sizeof(mctx->block); | |
94 | } | |
95 | ||
96 | memcpy(mctx->block, data, len); | |
14b75ba7 AKR |
97 | |
98 | return 0; | |
1da177e4 LT |
99 | } |
100 | ||
14b75ba7 | 101 | static int md5_final(struct shash_desc *desc, u8 *out) |
1da177e4 | 102 | { |
7d6f75eb | 103 | struct md5_state *mctx = shash_desc_ctx(desc); |
1da177e4 LT |
104 | const unsigned int offset = mctx->byte_count & 0x3f; |
105 | char *p = (char *)mctx->block + offset; | |
106 | int padding = 56 - (offset + 1); | |
107 | ||
108 | *p++ = 0x80; | |
109 | if (padding < 0) { | |
110 | memset(p, 0x00, padding + sizeof (u64)); | |
111 | md5_transform_helper(mctx); | |
112 | p = (char *)mctx->block; | |
113 | padding = 56; | |
114 | } | |
115 | ||
116 | memset(p, 0, padding); | |
117 | mctx->block[14] = mctx->byte_count << 3; | |
118 | mctx->block[15] = mctx->byte_count >> 29; | |
119 | le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - | |
120 | sizeof(u64)) / sizeof(u32)); | |
121 | md5_transform(mctx->hash, mctx->block); | |
122 | cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); | |
123 | memcpy(out, mctx->hash, sizeof(mctx->hash)); | |
124 | memset(mctx, 0, sizeof(*mctx)); | |
14b75ba7 AKR |
125 | |
126 | return 0; | |
1da177e4 LT |
127 | } |
128 | ||
7d6f75eb MV |
129 | static int md5_export(struct shash_desc *desc, void *out) |
130 | { | |
131 | struct md5_state *ctx = shash_desc_ctx(desc); | |
132 | ||
133 | memcpy(out, ctx, sizeof(*ctx)); | |
134 | return 0; | |
135 | } | |
136 | ||
137 | static int md5_import(struct shash_desc *desc, const void *in) | |
138 | { | |
139 | struct md5_state *ctx = shash_desc_ctx(desc); | |
140 | ||
141 | memcpy(ctx, in, sizeof(*ctx)); | |
142 | return 0; | |
143 | } | |
144 | ||
14b75ba7 AKR |
145 | static struct shash_alg alg = { |
146 | .digestsize = MD5_DIGEST_SIZE, | |
147 | .init = md5_init, | |
148 | .update = md5_update, | |
149 | .final = md5_final, | |
7d6f75eb MV |
150 | .export = md5_export, |
151 | .import = md5_import, | |
152 | .descsize = sizeof(struct md5_state), | |
eebb111f | 153 | .statesize = sizeof(struct md5_state), |
14b75ba7 AKR |
154 | .base = { |
155 | .cra_name = "md5", | |
156 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | |
157 | .cra_blocksize = MD5_HMAC_BLOCK_SIZE, | |
158 | .cra_module = THIS_MODULE, | |
159 | } | |
1da177e4 LT |
160 | }; |
161 | ||
3af5b90b | 162 | static int __init md5_mod_init(void) |
1da177e4 | 163 | { |
14b75ba7 | 164 | return crypto_register_shash(&alg); |
1da177e4 LT |
165 | } |
166 | ||
3af5b90b | 167 | static void __exit md5_mod_fini(void) |
1da177e4 | 168 | { |
14b75ba7 | 169 | crypto_unregister_shash(&alg); |
1da177e4 LT |
170 | } |
171 | ||
3af5b90b KB |
172 | module_init(md5_mod_init); |
173 | module_exit(md5_mod_fini); | |
1da177e4 LT |
174 | |
175 | MODULE_LICENSE("GPL"); | |
176 | MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); | |
5d26a105 | 177 | MODULE_ALIAS_CRYPTO("md5"); |