xref: /linux/crypto/md5.c (revision d6b6aac0cdb4b4f81cccc531ed76211d56c17444)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Crypto API support for MD5 and HMAC-MD5
4  *
5  * Copyright 2025 Google LLC
6  */
7 #include <crypto/internal/hash.h>
8 #include <crypto/md5.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 
12 /*
13  * Export and import functions.  crypto_shash wants a particular format that
14  * matches that used by some legacy drivers.  It currently is the same as the
15  * library MD5 context, except the value in bytecount must be block-aligned and
16  * the remainder must be stored in an extra u8 appended to the struct.
17  */
18 
19 #define MD5_SHASH_STATE_SIZE (sizeof(struct md5_ctx) + 1)
20 static_assert(sizeof(struct md5_ctx) == sizeof(struct md5_state));
21 static_assert(offsetof(struct md5_ctx, state) == offsetof(struct md5_state, hash));
22 static_assert(offsetof(struct md5_ctx, bytecount) == offsetof(struct md5_state, byte_count));
23 static_assert(offsetof(struct md5_ctx, buf) == offsetof(struct md5_state, block));
24 
25 static int __crypto_md5_export(const struct md5_ctx *ctx0, void *out)
26 {
27 	struct md5_ctx ctx = *ctx0;
28 	unsigned int partial;
29 	u8 *p = out;
30 
31 	partial = ctx.bytecount % MD5_BLOCK_SIZE;
32 	ctx.bytecount -= partial;
33 	memcpy(p, &ctx, sizeof(ctx));
34 	p += sizeof(ctx);
35 	*p = partial;
36 	return 0;
37 }
38 
39 static int __crypto_md5_import(struct md5_ctx *ctx, const void *in)
40 {
41 	const u8 *p = in;
42 
43 	memcpy(ctx, p, sizeof(*ctx));
44 	p += sizeof(*ctx);
45 	ctx->bytecount += *p;
46 	return 0;
47 }
48 
49 const u8 md5_zero_message_hash[MD5_DIGEST_SIZE] = {
50 	0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
51 	0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
52 };
53 EXPORT_SYMBOL_GPL(md5_zero_message_hash);
54 
55 #define MD5_CTX(desc) ((struct md5_ctx *)shash_desc_ctx(desc))
56 
57 static int crypto_md5_init(struct shash_desc *desc)
58 {
59 	md5_init(MD5_CTX(desc));
60 	return 0;
61 }
62 
63 static int crypto_md5_update(struct shash_desc *desc,
64 			     const u8 *data, unsigned int len)
65 {
66 	md5_update(MD5_CTX(desc), data, len);
67 	return 0;
68 }
69 
70 static int crypto_md5_final(struct shash_desc *desc, u8 *out)
71 {
72 	md5_final(MD5_CTX(desc), out);
73 	return 0;
74 }
75 
76 static int crypto_md5_digest(struct shash_desc *desc,
77 			     const u8 *data, unsigned int len, u8 *out)
78 {
79 	md5(data, len, out);
80 	return 0;
81 }
82 
83 static int crypto_md5_export(struct shash_desc *desc, void *out)
84 {
85 	return __crypto_md5_export(MD5_CTX(desc), out);
86 }
87 
88 static int crypto_md5_import(struct shash_desc *desc, const void *in)
89 {
90 	return __crypto_md5_import(MD5_CTX(desc), in);
91 }
92 
93 #define HMAC_MD5_KEY(tfm) ((struct hmac_md5_key *)crypto_shash_ctx(tfm))
94 #define HMAC_MD5_CTX(desc) ((struct hmac_md5_ctx *)shash_desc_ctx(desc))
95 
96 static int crypto_hmac_md5_setkey(struct crypto_shash *tfm,
97 				  const u8 *raw_key, unsigned int keylen)
98 {
99 	hmac_md5_preparekey(HMAC_MD5_KEY(tfm), raw_key, keylen);
100 	return 0;
101 }
102 
103 static int crypto_hmac_md5_init(struct shash_desc *desc)
104 {
105 	hmac_md5_init(HMAC_MD5_CTX(desc), HMAC_MD5_KEY(desc->tfm));
106 	return 0;
107 }
108 
109 static int crypto_hmac_md5_update(struct shash_desc *desc,
110 				  const u8 *data, unsigned int len)
111 {
112 	hmac_md5_update(HMAC_MD5_CTX(desc), data, len);
113 	return 0;
114 }
115 
116 static int crypto_hmac_md5_final(struct shash_desc *desc, u8 *out)
117 {
118 	hmac_md5_final(HMAC_MD5_CTX(desc), out);
119 	return 0;
120 }
121 
122 static int crypto_hmac_md5_digest(struct shash_desc *desc,
123 				  const u8 *data, unsigned int len, u8 *out)
124 {
125 	hmac_md5(HMAC_MD5_KEY(desc->tfm), data, len, out);
126 	return 0;
127 }
128 
129 static int crypto_hmac_md5_export(struct shash_desc *desc, void *out)
130 {
131 	return __crypto_md5_export(&HMAC_MD5_CTX(desc)->hash_ctx, out);
132 }
133 
134 static int crypto_hmac_md5_import(struct shash_desc *desc, const void *in)
135 {
136 	struct hmac_md5_ctx *ctx = HMAC_MD5_CTX(desc);
137 
138 	ctx->ostate = HMAC_MD5_KEY(desc->tfm)->ostate;
139 	return __crypto_md5_import(&ctx->hash_ctx, in);
140 }
141 
142 static struct shash_alg algs[] = {
143 	{
144 		.base.cra_name		= "md5",
145 		.base.cra_driver_name	= "md5-lib",
146 		.base.cra_priority	= 300,
147 		.base.cra_blocksize	= MD5_BLOCK_SIZE,
148 		.base.cra_module	= THIS_MODULE,
149 		.digestsize		= MD5_DIGEST_SIZE,
150 		.init			= crypto_md5_init,
151 		.update			= crypto_md5_update,
152 		.final			= crypto_md5_final,
153 		.digest			= crypto_md5_digest,
154 		.export			= crypto_md5_export,
155 		.import			= crypto_md5_import,
156 		.descsize		= sizeof(struct md5_ctx),
157 		.statesize		= MD5_SHASH_STATE_SIZE,
158 	},
159 	{
160 		.base.cra_name		= "hmac(md5)",
161 		.base.cra_driver_name	= "hmac-md5-lib",
162 		.base.cra_priority	= 300,
163 		.base.cra_blocksize	= MD5_BLOCK_SIZE,
164 		.base.cra_ctxsize	= sizeof(struct hmac_md5_key),
165 		.base.cra_module	= THIS_MODULE,
166 		.digestsize		= MD5_DIGEST_SIZE,
167 		.setkey			= crypto_hmac_md5_setkey,
168 		.init			= crypto_hmac_md5_init,
169 		.update			= crypto_hmac_md5_update,
170 		.final			= crypto_hmac_md5_final,
171 		.digest			= crypto_hmac_md5_digest,
172 		.export			= crypto_hmac_md5_export,
173 		.import			= crypto_hmac_md5_import,
174 		.descsize		= sizeof(struct hmac_md5_ctx),
175 		.statesize		= MD5_SHASH_STATE_SIZE,
176 	},
177 };
178 
179 static int __init crypto_md5_mod_init(void)
180 {
181 	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
182 }
183 module_init(crypto_md5_mod_init);
184 
185 static void __exit crypto_md5_mod_exit(void)
186 {
187 	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
188 }
189 module_exit(crypto_md5_mod_exit);
190 
191 MODULE_LICENSE("GPL");
192 MODULE_DESCRIPTION("Crypto API support for MD5 and HMAC-MD5");
193 
194 MODULE_ALIAS_CRYPTO("md5");
195 MODULE_ALIAS_CRYPTO("md5-lib");
196 MODULE_ALIAS_CRYPTO("hmac(md5)");
197 MODULE_ALIAS_CRYPTO("hmac-md5-lib");
198