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