Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: md5 - Wrap library and add HMAC support

Reimplement crypto/md5.c on top of the new MD5 library functions. Also
add support for HMAC-MD5, again just wrapping the library functions.

This closely mirrors crypto/sha1.c.

Link: https://lore.kernel.org/r/20250805222855.10362-7-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+171 -194
+2 -1
crypto/Kconfig
··· 938 938 config CRYPTO_MD5 939 939 tristate "MD5" 940 940 select CRYPTO_HASH 941 + select CRYPTO_LIB_MD5 941 942 help 942 - MD5 message digest algorithm (RFC1321) 943 + MD5 message digest algorithm (RFC1321), including HMAC support. 943 944 944 945 config CRYPTO_MICHAEL_MIC 945 946 tristate "Michael MIC"
+165 -192
crypto/md5.c
··· 1 - /* 2 - * Cryptographic API. 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Crypto API support for MD5 and HMAC-MD5 3 4 * 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 - * 5 + * Copyright 2025 Google LLC 17 6 */ 18 7 #include <crypto/internal/hash.h> 19 8 #include <crypto/md5.h> 20 9 #include <linux/kernel.h> 21 10 #include <linux/module.h> 22 - #include <linux/string.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 + } 23 48 24 49 const u8 md5_zero_message_hash[MD5_DIGEST_SIZE] = { 25 50 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, ··· 52 27 }; 53 28 EXPORT_SYMBOL_GPL(md5_zero_message_hash); 54 29 55 - #define F1(x, y, z) (z ^ (x & (y ^ z))) 56 - #define F2(x, y, z) F1(z, x, y) 57 - #define F3(x, y, z) (x ^ y ^ z) 58 - #define F4(x, y, z) (y ^ (x | ~z)) 30 + #define MD5_CTX(desc) ((struct md5_ctx *)shash_desc_ctx(desc)) 59 31 60 - #define MD5STEP(f, w, x, y, z, in, s) \ 61 - (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x) 62 - 63 - static void md5_transform(__u32 *hash, __u32 const *in) 32 + static int crypto_md5_init(struct shash_desc *desc) 64 33 { 65 - u32 a, b, c, d; 66 - 67 - a = hash[0]; 68 - b = hash[1]; 69 - c = hash[2]; 70 - d = hash[3]; 71 - 72 - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 73 - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 74 - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 75 - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 76 - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 77 - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 78 - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 79 - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 80 - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 81 - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 82 - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 83 - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 84 - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 85 - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 86 - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 87 - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 88 - 89 - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 90 - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 91 - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 92 - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 93 - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 94 - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 95 - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 96 - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 97 - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 98 - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 99 - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 100 - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 101 - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 102 - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 103 - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 104 - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 105 - 106 - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 107 - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 108 - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 109 - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 110 - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 111 - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 112 - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 113 - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 114 - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 115 - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 116 - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 117 - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 118 - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 119 - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 120 - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 121 - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 122 - 123 - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 124 - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 125 - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 126 - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 127 - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 128 - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 129 - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 130 - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 131 - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 132 - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 133 - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 134 - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 135 - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 136 - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 137 - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 138 - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 139 - 140 - hash[0] += a; 141 - hash[1] += b; 142 - hash[2] += c; 143 - hash[3] += d; 144 - } 145 - 146 - static inline void md5_transform_helper(struct md5_state *ctx, 147 - u32 block[MD5_BLOCK_WORDS]) 148 - { 149 - le32_to_cpu_array(block, MD5_BLOCK_WORDS); 150 - md5_transform(ctx->hash, block); 151 - } 152 - 153 - static int md5_init(struct shash_desc *desc) 154 - { 155 - struct md5_state *mctx = shash_desc_ctx(desc); 156 - 157 - mctx->hash[0] = MD5_H0; 158 - mctx->hash[1] = MD5_H1; 159 - mctx->hash[2] = MD5_H2; 160 - mctx->hash[3] = MD5_H3; 161 - mctx->byte_count = 0; 162 - 34 + md5_init(MD5_CTX(desc)); 163 35 return 0; 164 36 } 165 37 166 - static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len) 38 + static int crypto_md5_update(struct shash_desc *desc, 39 + const u8 *data, unsigned int len) 167 40 { 168 - struct md5_state *mctx = shash_desc_ctx(desc); 169 - u32 block[MD5_BLOCK_WORDS]; 170 - 171 - mctx->byte_count += len; 172 - do { 173 - memcpy(block, data, sizeof(block)); 174 - md5_transform_helper(mctx, block); 175 - data += sizeof(block); 176 - len -= sizeof(block); 177 - } while (len >= sizeof(block)); 178 - memzero_explicit(block, sizeof(block)); 179 - mctx->byte_count -= len; 180 - return len; 181 - } 182 - 183 - static int md5_finup(struct shash_desc *desc, const u8 *data, unsigned int len, 184 - u8 *out) 185 - { 186 - struct md5_state *mctx = shash_desc_ctx(desc); 187 - u32 block[MD5_BLOCK_WORDS]; 188 - unsigned int offset; 189 - int padding; 190 - char *p; 191 - 192 - memcpy(block, data, len); 193 - 194 - offset = len; 195 - p = (char *)block + offset; 196 - padding = 56 - (offset + 1); 197 - 198 - *p++ = 0x80; 199 - if (padding < 0) { 200 - memset(p, 0x00, padding + sizeof (u64)); 201 - md5_transform_helper(mctx, block); 202 - p = (char *)block; 203 - padding = 56; 204 - } 205 - 206 - memset(p, 0, padding); 207 - mctx->byte_count += len; 208 - block[14] = mctx->byte_count << 3; 209 - block[15] = mctx->byte_count >> 29; 210 - le32_to_cpu_array(block, (sizeof(block) - sizeof(u64)) / sizeof(u32)); 211 - md5_transform(mctx->hash, block); 212 - memzero_explicit(block, sizeof(block)); 213 - cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); 214 - memcpy(out, mctx->hash, sizeof(mctx->hash)); 215 - 41 + md5_update(MD5_CTX(desc), data, len); 216 42 return 0; 217 43 } 218 44 219 - static struct shash_alg alg = { 220 - .digestsize = MD5_DIGEST_SIZE, 221 - .init = md5_init, 222 - .update = md5_update, 223 - .finup = md5_finup, 224 - .descsize = MD5_STATE_SIZE, 225 - .base = { 226 - .cra_name = "md5", 227 - .cra_driver_name = "md5-generic", 228 - .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 229 - .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 230 - .cra_module = THIS_MODULE, 231 - } 45 + static int crypto_md5_final(struct shash_desc *desc, u8 *out) 46 + { 47 + md5_final(MD5_CTX(desc), out); 48 + return 0; 49 + } 50 + 51 + static int crypto_md5_digest(struct shash_desc *desc, 52 + const u8 *data, unsigned int len, u8 *out) 53 + { 54 + md5(data, len, out); 55 + return 0; 56 + } 57 + 58 + static int crypto_md5_export(struct shash_desc *desc, void *out) 59 + { 60 + return __crypto_md5_export(MD5_CTX(desc), out); 61 + } 62 + 63 + static int crypto_md5_import(struct shash_desc *desc, const void *in) 64 + { 65 + return __crypto_md5_import(MD5_CTX(desc), in); 66 + } 67 + 68 + #define HMAC_MD5_KEY(tfm) ((struct hmac_md5_key *)crypto_shash_ctx(tfm)) 69 + #define HMAC_MD5_CTX(desc) ((struct hmac_md5_ctx *)shash_desc_ctx(desc)) 70 + 71 + static int crypto_hmac_md5_setkey(struct crypto_shash *tfm, 72 + const u8 *raw_key, unsigned int keylen) 73 + { 74 + hmac_md5_preparekey(HMAC_MD5_KEY(tfm), raw_key, keylen); 75 + return 0; 76 + } 77 + 78 + static int crypto_hmac_md5_init(struct shash_desc *desc) 79 + { 80 + hmac_md5_init(HMAC_MD5_CTX(desc), HMAC_MD5_KEY(desc->tfm)); 81 + return 0; 82 + } 83 + 84 + static int crypto_hmac_md5_update(struct shash_desc *desc, 85 + const u8 *data, unsigned int len) 86 + { 87 + hmac_md5_update(HMAC_MD5_CTX(desc), data, len); 88 + return 0; 89 + } 90 + 91 + static int crypto_hmac_md5_final(struct shash_desc *desc, u8 *out) 92 + { 93 + hmac_md5_final(HMAC_MD5_CTX(desc), out); 94 + return 0; 95 + } 96 + 97 + static int crypto_hmac_md5_digest(struct shash_desc *desc, 98 + const u8 *data, unsigned int len, u8 *out) 99 + { 100 + hmac_md5(HMAC_MD5_KEY(desc->tfm), data, len, out); 101 + return 0; 102 + } 103 + 104 + static int crypto_hmac_md5_export(struct shash_desc *desc, void *out) 105 + { 106 + return __crypto_md5_export(&HMAC_MD5_CTX(desc)->hash_ctx, out); 107 + } 108 + 109 + static int crypto_hmac_md5_import(struct shash_desc *desc, const void *in) 110 + { 111 + struct hmac_md5_ctx *ctx = HMAC_MD5_CTX(desc); 112 + 113 + ctx->ostate = HMAC_MD5_KEY(desc->tfm)->ostate; 114 + return __crypto_md5_import(&ctx->hash_ctx, in); 115 + } 116 + 117 + static struct shash_alg algs[] = { 118 + { 119 + .base.cra_name = "md5", 120 + .base.cra_driver_name = "md5-lib", 121 + .base.cra_priority = 300, 122 + .base.cra_blocksize = MD5_BLOCK_SIZE, 123 + .base.cra_module = THIS_MODULE, 124 + .digestsize = MD5_DIGEST_SIZE, 125 + .init = crypto_md5_init, 126 + .update = crypto_md5_update, 127 + .final = crypto_md5_final, 128 + .digest = crypto_md5_digest, 129 + .export = crypto_md5_export, 130 + .import = crypto_md5_import, 131 + .descsize = sizeof(struct md5_ctx), 132 + .statesize = MD5_SHASH_STATE_SIZE, 133 + }, 134 + { 135 + .base.cra_name = "hmac(md5)", 136 + .base.cra_driver_name = "hmac-md5-lib", 137 + .base.cra_priority = 300, 138 + .base.cra_blocksize = MD5_BLOCK_SIZE, 139 + .base.cra_ctxsize = sizeof(struct hmac_md5_key), 140 + .base.cra_module = THIS_MODULE, 141 + .digestsize = MD5_DIGEST_SIZE, 142 + .setkey = crypto_hmac_md5_setkey, 143 + .init = crypto_hmac_md5_init, 144 + .update = crypto_hmac_md5_update, 145 + .final = crypto_hmac_md5_final, 146 + .digest = crypto_hmac_md5_digest, 147 + .export = crypto_hmac_md5_export, 148 + .import = crypto_hmac_md5_import, 149 + .descsize = sizeof(struct hmac_md5_ctx), 150 + .statesize = MD5_SHASH_STATE_SIZE, 151 + }, 232 152 }; 233 153 234 - static int __init md5_mod_init(void) 154 + static int __init crypto_md5_mod_init(void) 235 155 { 236 - return crypto_register_shash(&alg); 156 + return crypto_register_shashes(algs, ARRAY_SIZE(algs)); 237 157 } 158 + module_init(crypto_md5_mod_init); 238 159 239 - static void __exit md5_mod_fini(void) 160 + static void __exit crypto_md5_mod_exit(void) 240 161 { 241 - crypto_unregister_shash(&alg); 162 + crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); 242 163 } 243 - 244 - module_init(md5_mod_init); 245 - module_exit(md5_mod_fini); 164 + module_exit(crypto_md5_mod_exit); 246 165 247 166 MODULE_LICENSE("GPL"); 248 - MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); 167 + MODULE_DESCRIPTION("Crypto API support for MD5 and HMAC-MD5"); 168 + 249 169 MODULE_ALIAS_CRYPTO("md5"); 170 + MODULE_ALIAS_CRYPTO("md5-lib"); 171 + MODULE_ALIAS_CRYPTO("hmac(md5)"); 172 + MODULE_ALIAS_CRYPTO("hmac-md5-lib");
+3
crypto/testmgr.c
··· 4178 4178 } 4179 4179 }, { 4180 4180 .alg = "authenc(hmac(md5),ecb(cipher_null))", 4181 + .generic_driver = "authenc(hmac-md5-lib,ecb-cipher_null)", 4181 4182 .test = alg_test_aead, 4182 4183 .suite = { 4183 4184 .aead = __VECS(hmac_md5_ecb_cipher_null_tv_template) ··· 5065 5064 } 5066 5065 }, { 5067 5066 .alg = "hmac(md5)", 5067 + .generic_driver = "hmac-md5-lib", 5068 5068 .test = alg_test_hash, 5069 5069 .suite = { 5070 5070 .hash = __VECS(hmac_md5_tv_template) ··· 5252 5250 } 5253 5251 }, { 5254 5252 .alg = "md5", 5253 + .generic_driver = "md5-lib", 5255 5254 .test = alg_test_hash, 5256 5255 .suite = { 5257 5256 .hash = __VECS(md5_tv_template)
+1 -1
drivers/crypto/img-hash.c
··· 700 700 701 701 static int img_hash_cra_md5_init(struct crypto_tfm *tfm) 702 702 { 703 - return img_hash_cra_init(tfm, "md5-generic"); 703 + return img_hash_cra_init(tfm, "md5-lib"); 704 704 } 705 705 706 706 static int img_hash_cra_sha1_init(struct crypto_tfm *tfm)