PM / Suspend: Off by one in pm_suspend()
[linux/fpc-iii.git] / crypto / md5.c
blob156b6bcef673afcdfab708dacdb587f66b8b09e3
1 /*
2 * Cryptographic API.
4 * MD5 Message Digest Algorithm (RFC1321).
6 * Derived from cryptoapi implementation, originally based on the
7 * public domain implementation written by Colin Plumb in 1993.
9 * Copyright (c) Cryptoapi developers.
10 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
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.
18 #include <crypto/internal/hash.h>
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/string.h>
22 #include <linux/types.h>
23 #include <linux/cryptohash.h>
24 #include <asm/byteorder.h>
26 #define MD5_DIGEST_SIZE 16
27 #define MD5_HMAC_BLOCK_SIZE 64
28 #define MD5_BLOCK_WORDS 16
29 #define MD5_HASH_WORDS 4
31 struct md5_ctx {
32 u32 hash[MD5_HASH_WORDS];
33 u32 block[MD5_BLOCK_WORDS];
34 u64 byte_count;
37 /* XXX: this stuff can be optimized */
38 static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
40 while (words--) {
41 __le32_to_cpus(buf);
42 buf++;
46 static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
48 while (words--) {
49 __cpu_to_le32s(buf);
50 buf++;
54 static inline void md5_transform_helper(struct md5_ctx *ctx)
56 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
57 md5_transform(ctx->hash, ctx->block);
60 static int md5_init(struct shash_desc *desc)
62 struct md5_ctx *mctx = shash_desc_ctx(desc);
64 mctx->hash[0] = 0x67452301;
65 mctx->hash[1] = 0xefcdab89;
66 mctx->hash[2] = 0x98badcfe;
67 mctx->hash[3] = 0x10325476;
68 mctx->byte_count = 0;
70 return 0;
73 static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len)
75 struct md5_ctx *mctx = shash_desc_ctx(desc);
76 const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
78 mctx->byte_count += len;
80 if (avail > len) {
81 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
82 data, len);
83 return 0;
86 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
87 data, avail);
89 md5_transform_helper(mctx);
90 data += avail;
91 len -= avail;
93 while (len >= sizeof(mctx->block)) {
94 memcpy(mctx->block, data, sizeof(mctx->block));
95 md5_transform_helper(mctx);
96 data += sizeof(mctx->block);
97 len -= sizeof(mctx->block);
100 memcpy(mctx->block, data, len);
102 return 0;
105 static int md5_final(struct shash_desc *desc, u8 *out)
107 struct md5_ctx *mctx = shash_desc_ctx(desc);
108 const unsigned int offset = mctx->byte_count & 0x3f;
109 char *p = (char *)mctx->block + offset;
110 int padding = 56 - (offset + 1);
112 *p++ = 0x80;
113 if (padding < 0) {
114 memset(p, 0x00, padding + sizeof (u64));
115 md5_transform_helper(mctx);
116 p = (char *)mctx->block;
117 padding = 56;
120 memset(p, 0, padding);
121 mctx->block[14] = mctx->byte_count << 3;
122 mctx->block[15] = mctx->byte_count >> 29;
123 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
124 sizeof(u64)) / sizeof(u32));
125 md5_transform(mctx->hash, mctx->block);
126 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
127 memcpy(out, mctx->hash, sizeof(mctx->hash));
128 memset(mctx, 0, sizeof(*mctx));
130 return 0;
133 static struct shash_alg alg = {
134 .digestsize = MD5_DIGEST_SIZE,
135 .init = md5_init,
136 .update = md5_update,
137 .final = md5_final,
138 .descsize = sizeof(struct md5_ctx),
139 .base = {
140 .cra_name = "md5",
141 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
142 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
143 .cra_module = THIS_MODULE,
147 static int __init md5_mod_init(void)
149 return crypto_register_shash(&alg);
152 static void __exit md5_mod_fini(void)
154 crypto_unregister_shash(&alg);
157 module_init(md5_mod_init);
158 module_exit(md5_mod_fini);
160 MODULE_LICENSE("GPL");
161 MODULE_DESCRIPTION("MD5 Message Digest Algorithm");