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

lib/crypto: md5: Add MD5 and HMAC-MD5 library functions

Add library functions for MD5, including HMAC support. The MD5
implementation is derived from crypto/md5.c. This closely mirrors the
corresponding SHA-1 and SHA-2 changes.

Like SHA-1 and SHA-2, support for architecture-optimized MD5
implementations is included. I originally proposed dropping those, but
unfortunately there is an AF_ALG user of the PowerPC MD5 code
(https://lore.kernel.org/r/c4191597-341d-4fd7-bc3d-13daf7666c41@csgroup.eu/),
and dropping that code would be viewed as a performance regression. We
don't add new software algorithm implementations purely for AF_ALG, as
escalating to kernel mode merely to do calculations that could be done
in userspace is inefficient and is completely the wrong design. But
since this one already existed, it gets grandfathered in for now. An
objection was also raised to dropping the SPARC64 MD5 code because it
utilizes the CPU's direct support for MD5, although it remains unclear
that anyone is using that. Regardless, we'll keep these around for now.

Note that while MD5 is a legacy algorithm that is vulnerable to
practical collision attacks, it still has various in-kernel users that
implement legacy protocols. Switching to a simple library API, which is
the way the code should have been organized originally, will greatly
simplify their code. For example:

MD5:
drivers/md/dm-crypt.c (for lmk IV generation)
fs/nfsd/nfs4recover.c
fs/ecryptfs/
fs/smb/client/
net/{ipv4,ipv6}/ (for TCP-MD5 signatures)

HMAC-MD5:
fs/smb/client/
fs/smb/server/

(Also net/sctp/ if it continues using HMAC-MD5 for cookie generation.
However, that use case has the flexibility to upgrade to a more modern
algorithm, which I'll be proposing instead.)

As usual, the "md5" and "hmac(md5)" crypto_shash algorithms will also be
reimplemented on top of these library functions. For "hmac(md5)" this
will provide a faster, more streamlined implementation.

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

+522 -1
+180 -1
include/crypto/md5.h
··· 7 7 8 8 #define MD5_DIGEST_SIZE 16 9 9 #define MD5_HMAC_BLOCK_SIZE 64 10 + #define MD5_BLOCK_SIZE 64 10 11 #define MD5_BLOCK_WORDS 16 11 12 #define MD5_HASH_WORDS 4 12 13 #define MD5_STATE_SIZE 24 ··· 28 27 u32 block[MD5_BLOCK_WORDS]; 29 28 }; 30 29 31 - #endif 30 + /* State for the MD5 compression function */ 31 + struct md5_block_state { 32 + u32 h[MD5_HASH_WORDS]; 33 + }; 34 + 35 + /** 36 + * struct md5_ctx - Context for hashing a message with MD5 37 + * @state: the compression function state 38 + * @bytecount: number of bytes processed so far 39 + * @buf: partial block buffer; bytecount % MD5_BLOCK_SIZE bytes are valid 40 + */ 41 + struct md5_ctx { 42 + struct md5_block_state state; 43 + u64 bytecount; 44 + u8 buf[MD5_BLOCK_SIZE] __aligned(__alignof__(__le64)); 45 + }; 46 + 47 + /** 48 + * md5_init() - Initialize an MD5 context for a new message 49 + * @ctx: the context to initialize 50 + * 51 + * If you don't need incremental computation, consider md5() instead. 52 + * 53 + * Context: Any context. 54 + */ 55 + void md5_init(struct md5_ctx *ctx); 56 + 57 + /** 58 + * md5_update() - Update an MD5 context with message data 59 + * @ctx: the context to update; must have been initialized 60 + * @data: the message data 61 + * @len: the data length in bytes 62 + * 63 + * This can be called any number of times. 64 + * 65 + * Context: Any context. 66 + */ 67 + void md5_update(struct md5_ctx *ctx, const u8 *data, size_t len); 68 + 69 + /** 70 + * md5_final() - Finish computing an MD5 message digest 71 + * @ctx: the context to finalize; must have been initialized 72 + * @out: (output) the resulting MD5 message digest 73 + * 74 + * After finishing, this zeroizes @ctx. So the caller does not need to do it. 75 + * 76 + * Context: Any context. 77 + */ 78 + void md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]); 79 + 80 + /** 81 + * md5() - Compute MD5 message digest in one shot 82 + * @data: the message data 83 + * @len: the data length in bytes 84 + * @out: (output) the resulting MD5 message digest 85 + * 86 + * Context: Any context. 87 + */ 88 + void md5(const u8 *data, size_t len, u8 out[MD5_DIGEST_SIZE]); 89 + 90 + /** 91 + * struct hmac_md5_key - Prepared key for HMAC-MD5 92 + * @istate: private 93 + * @ostate: private 94 + */ 95 + struct hmac_md5_key { 96 + struct md5_block_state istate; 97 + struct md5_block_state ostate; 98 + }; 99 + 100 + /** 101 + * struct hmac_md5_ctx - Context for computing HMAC-MD5 of a message 102 + * @hash_ctx: private 103 + * @ostate: private 104 + */ 105 + struct hmac_md5_ctx { 106 + struct md5_ctx hash_ctx; 107 + struct md5_block_state ostate; 108 + }; 109 + 110 + /** 111 + * hmac_md5_preparekey() - Prepare a key for HMAC-MD5 112 + * @key: (output) the key structure to initialize 113 + * @raw_key: the raw HMAC-MD5 key 114 + * @raw_key_len: the key length in bytes. All key lengths are supported. 115 + * 116 + * Note: the caller is responsible for zeroizing both the struct hmac_md5_key 117 + * and the raw key once they are no longer needed. 118 + * 119 + * Context: Any context. 120 + */ 121 + void hmac_md5_preparekey(struct hmac_md5_key *key, 122 + const u8 *raw_key, size_t raw_key_len); 123 + 124 + /** 125 + * hmac_md5_init() - Initialize an HMAC-MD5 context for a new message 126 + * @ctx: (output) the HMAC context to initialize 127 + * @key: the prepared HMAC key 128 + * 129 + * If you don't need incremental computation, consider hmac_md5() instead. 130 + * 131 + * Context: Any context. 132 + */ 133 + void hmac_md5_init(struct hmac_md5_ctx *ctx, const struct hmac_md5_key *key); 134 + 135 + /** 136 + * hmac_md5_init_usingrawkey() - Initialize an HMAC-MD5 context for a new 137 + * message, using a raw key 138 + * @ctx: (output) the HMAC context to initialize 139 + * @raw_key: the raw HMAC-MD5 key 140 + * @raw_key_len: the key length in bytes. All key lengths are supported. 141 + * 142 + * If you don't need incremental computation, consider hmac_md5_usingrawkey() 143 + * instead. 144 + * 145 + * Context: Any context. 146 + */ 147 + void hmac_md5_init_usingrawkey(struct hmac_md5_ctx *ctx, 148 + const u8 *raw_key, size_t raw_key_len); 149 + 150 + /** 151 + * hmac_md5_update() - Update an HMAC-MD5 context with message data 152 + * @ctx: the HMAC context to update; must have been initialized 153 + * @data: the message data 154 + * @data_len: the data length in bytes 155 + * 156 + * This can be called any number of times. 157 + * 158 + * Context: Any context. 159 + */ 160 + static inline void hmac_md5_update(struct hmac_md5_ctx *ctx, 161 + const u8 *data, size_t data_len) 162 + { 163 + md5_update(&ctx->hash_ctx, data, data_len); 164 + } 165 + 166 + /** 167 + * hmac_md5_final() - Finish computing an HMAC-MD5 value 168 + * @ctx: the HMAC context to finalize; must have been initialized 169 + * @out: (output) the resulting HMAC-MD5 value 170 + * 171 + * After finishing, this zeroizes @ctx. So the caller does not need to do it. 172 + * 173 + * Context: Any context. 174 + */ 175 + void hmac_md5_final(struct hmac_md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]); 176 + 177 + /** 178 + * hmac_md5() - Compute HMAC-MD5 in one shot, using a prepared key 179 + * @key: the prepared HMAC key 180 + * @data: the message data 181 + * @data_len: the data length in bytes 182 + * @out: (output) the resulting HMAC-MD5 value 183 + * 184 + * If you're using the key only once, consider using hmac_md5_usingrawkey(). 185 + * 186 + * Context: Any context. 187 + */ 188 + void hmac_md5(const struct hmac_md5_key *key, 189 + const u8 *data, size_t data_len, u8 out[MD5_DIGEST_SIZE]); 190 + 191 + /** 192 + * hmac_md5_usingrawkey() - Compute HMAC-MD5 in one shot, using a raw key 193 + * @raw_key: the raw HMAC-MD5 key 194 + * @raw_key_len: the key length in bytes. All key lengths are supported. 195 + * @data: the message data 196 + * @data_len: the data length in bytes 197 + * @out: (output) the resulting HMAC-MD5 value 198 + * 199 + * If you're using the key multiple times, prefer to use hmac_md5_preparekey() 200 + * followed by multiple calls to hmac_md5() instead. 201 + * 202 + * Context: Any context. 203 + */ 204 + void hmac_md5_usingrawkey(const u8 *raw_key, size_t raw_key_len, 205 + const u8 *data, size_t data_len, 206 + u8 out[MD5_DIGEST_SIZE]); 207 + 208 + #endif /* _CRYPTO_MD5_H */
+10
lib/crypto/Kconfig
··· 101 101 config CRYPTO_LIB_DES 102 102 tristate 103 103 104 + config CRYPTO_LIB_MD5 105 + tristate 106 + help 107 + The MD5 and HMAC-MD5 library functions. Select this if your module 108 + uses any of the functions from <crypto/md5.h>. 109 + 110 + config CRYPTO_LIB_MD5_ARCH 111 + bool 112 + depends on CRYPTO_LIB_MD5 && !UML 113 + 104 114 config CRYPTO_LIB_POLY1305_RSIZE 105 115 int 106 116 default 2 if MIPS
+10
lib/crypto/Makefile
··· 59 59 obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o 60 60 libdes-y := des.o 61 61 62 + ################################################################################ 63 + 64 + obj-$(CONFIG_CRYPTO_LIB_MD5) += libmd5.o 65 + libmd5-y := md5.o 66 + ifeq ($(CONFIG_CRYPTO_LIB_MD5_ARCH),y) 67 + CFLAGS_md5.o += -I$(src)/$(SRCARCH) 68 + endif # CONFIG_CRYPTO_LIB_MD5_ARCH 69 + 70 + ################################################################################ 71 + 62 72 obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o 63 73 libpoly1305-y += poly1305.o 64 74
+322
lib/crypto/md5.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * MD5 and HMAC-MD5 library functions 4 + * 5 + * md5_block_generic() is derived from cryptoapi implementation, originally 6 + * based on the public domain implementation written by Colin Plumb in 1993. 7 + * 8 + * Copyright (c) Cryptoapi developers. 9 + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 10 + * Copyright 2025 Google LLC 11 + */ 12 + 13 + #include <crypto/hmac.h> 14 + #include <crypto/md5.h> 15 + #include <linux/export.h> 16 + #include <linux/kernel.h> 17 + #include <linux/module.h> 18 + #include <linux/string.h> 19 + #include <linux/unaligned.h> 20 + #include <linux/wordpart.h> 21 + 22 + static const struct md5_block_state md5_iv = { 23 + .h = { MD5_H0, MD5_H1, MD5_H2, MD5_H3 }, 24 + }; 25 + 26 + #define F1(x, y, z) (z ^ (x & (y ^ z))) 27 + #define F2(x, y, z) F1(z, x, y) 28 + #define F3(x, y, z) (x ^ y ^ z) 29 + #define F4(x, y, z) (y ^ (x | ~z)) 30 + 31 + #define MD5STEP(f, w, x, y, z, in, s) \ 32 + (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x) 33 + 34 + static void md5_block_generic(struct md5_block_state *state, 35 + const u8 data[MD5_BLOCK_SIZE]) 36 + { 37 + u32 in[MD5_BLOCK_WORDS]; 38 + u32 a, b, c, d; 39 + 40 + memcpy(in, data, MD5_BLOCK_SIZE); 41 + le32_to_cpu_array(in, ARRAY_SIZE(in)); 42 + 43 + a = state->h[0]; 44 + b = state->h[1]; 45 + c = state->h[2]; 46 + d = state->h[3]; 47 + 48 + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 49 + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 50 + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 51 + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 52 + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 53 + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 54 + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 55 + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 56 + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 57 + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 58 + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 59 + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 60 + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 61 + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 62 + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 63 + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 64 + 65 + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 66 + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 67 + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 68 + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 69 + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 70 + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 71 + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 72 + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 73 + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 74 + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 75 + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 76 + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 77 + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 78 + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 79 + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 80 + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 81 + 82 + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 83 + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 84 + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 85 + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 86 + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 87 + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 88 + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 89 + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 90 + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 91 + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 92 + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 93 + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 94 + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 95 + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 96 + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 97 + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 98 + 99 + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 100 + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 101 + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 102 + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 103 + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 104 + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 105 + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 106 + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 107 + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 108 + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 109 + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 110 + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 111 + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 112 + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 113 + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 114 + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 115 + 116 + state->h[0] += a; 117 + state->h[1] += b; 118 + state->h[2] += c; 119 + state->h[3] += d; 120 + } 121 + 122 + static void __maybe_unused md5_blocks_generic(struct md5_block_state *state, 123 + const u8 *data, size_t nblocks) 124 + { 125 + do { 126 + md5_block_generic(state, data); 127 + data += MD5_BLOCK_SIZE; 128 + } while (--nblocks); 129 + } 130 + 131 + #ifdef CONFIG_CRYPTO_LIB_MD5_ARCH 132 + #include "md5.h" /* $(SRCARCH)/md5.h */ 133 + #else 134 + #define md5_blocks md5_blocks_generic 135 + #endif 136 + 137 + void md5_init(struct md5_ctx *ctx) 138 + { 139 + ctx->state = md5_iv; 140 + ctx->bytecount = 0; 141 + } 142 + EXPORT_SYMBOL_GPL(md5_init); 143 + 144 + void md5_update(struct md5_ctx *ctx, const u8 *data, size_t len) 145 + { 146 + size_t partial = ctx->bytecount % MD5_BLOCK_SIZE; 147 + 148 + ctx->bytecount += len; 149 + 150 + if (partial + len >= MD5_BLOCK_SIZE) { 151 + size_t nblocks; 152 + 153 + if (partial) { 154 + size_t l = MD5_BLOCK_SIZE - partial; 155 + 156 + memcpy(&ctx->buf[partial], data, l); 157 + data += l; 158 + len -= l; 159 + 160 + md5_blocks(&ctx->state, ctx->buf, 1); 161 + } 162 + 163 + nblocks = len / MD5_BLOCK_SIZE; 164 + len %= MD5_BLOCK_SIZE; 165 + 166 + if (nblocks) { 167 + md5_blocks(&ctx->state, data, nblocks); 168 + data += nblocks * MD5_BLOCK_SIZE; 169 + } 170 + partial = 0; 171 + } 172 + if (len) 173 + memcpy(&ctx->buf[partial], data, len); 174 + } 175 + EXPORT_SYMBOL_GPL(md5_update); 176 + 177 + static void __md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]) 178 + { 179 + u64 bitcount = ctx->bytecount << 3; 180 + size_t partial = ctx->bytecount % MD5_BLOCK_SIZE; 181 + 182 + ctx->buf[partial++] = 0x80; 183 + if (partial > MD5_BLOCK_SIZE - 8) { 184 + memset(&ctx->buf[partial], 0, MD5_BLOCK_SIZE - partial); 185 + md5_blocks(&ctx->state, ctx->buf, 1); 186 + partial = 0; 187 + } 188 + memset(&ctx->buf[partial], 0, MD5_BLOCK_SIZE - 8 - partial); 189 + *(__le64 *)&ctx->buf[MD5_BLOCK_SIZE - 8] = cpu_to_le64(bitcount); 190 + md5_blocks(&ctx->state, ctx->buf, 1); 191 + 192 + cpu_to_le32_array(ctx->state.h, ARRAY_SIZE(ctx->state.h)); 193 + memcpy(out, ctx->state.h, MD5_DIGEST_SIZE); 194 + } 195 + 196 + void md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]) 197 + { 198 + __md5_final(ctx, out); 199 + memzero_explicit(ctx, sizeof(*ctx)); 200 + } 201 + EXPORT_SYMBOL_GPL(md5_final); 202 + 203 + void md5(const u8 *data, size_t len, u8 out[MD5_DIGEST_SIZE]) 204 + { 205 + struct md5_ctx ctx; 206 + 207 + md5_init(&ctx); 208 + md5_update(&ctx, data, len); 209 + md5_final(&ctx, out); 210 + } 211 + EXPORT_SYMBOL_GPL(md5); 212 + 213 + static void __hmac_md5_preparekey(struct md5_block_state *istate, 214 + struct md5_block_state *ostate, 215 + const u8 *raw_key, size_t raw_key_len) 216 + { 217 + union { 218 + u8 b[MD5_BLOCK_SIZE]; 219 + unsigned long w[MD5_BLOCK_SIZE / sizeof(unsigned long)]; 220 + } derived_key = { 0 }; 221 + 222 + if (unlikely(raw_key_len > MD5_BLOCK_SIZE)) 223 + md5(raw_key, raw_key_len, derived_key.b); 224 + else 225 + memcpy(derived_key.b, raw_key, raw_key_len); 226 + 227 + for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) 228 + derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE); 229 + *istate = md5_iv; 230 + md5_blocks(istate, derived_key.b, 1); 231 + 232 + for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) 233 + derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^ 234 + HMAC_IPAD_VALUE); 235 + *ostate = md5_iv; 236 + md5_blocks(ostate, derived_key.b, 1); 237 + 238 + memzero_explicit(&derived_key, sizeof(derived_key)); 239 + } 240 + 241 + void hmac_md5_preparekey(struct hmac_md5_key *key, 242 + const u8 *raw_key, size_t raw_key_len) 243 + { 244 + __hmac_md5_preparekey(&key->istate, &key->ostate, raw_key, raw_key_len); 245 + } 246 + EXPORT_SYMBOL_GPL(hmac_md5_preparekey); 247 + 248 + void hmac_md5_init(struct hmac_md5_ctx *ctx, const struct hmac_md5_key *key) 249 + { 250 + ctx->hash_ctx.state = key->istate; 251 + ctx->hash_ctx.bytecount = MD5_BLOCK_SIZE; 252 + ctx->ostate = key->ostate; 253 + } 254 + EXPORT_SYMBOL_GPL(hmac_md5_init); 255 + 256 + void hmac_md5_init_usingrawkey(struct hmac_md5_ctx *ctx, 257 + const u8 *raw_key, size_t raw_key_len) 258 + { 259 + __hmac_md5_preparekey(&ctx->hash_ctx.state, &ctx->ostate, 260 + raw_key, raw_key_len); 261 + ctx->hash_ctx.bytecount = MD5_BLOCK_SIZE; 262 + } 263 + EXPORT_SYMBOL_GPL(hmac_md5_init_usingrawkey); 264 + 265 + void hmac_md5_final(struct hmac_md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]) 266 + { 267 + /* Generate the padded input for the outer hash in ctx->hash_ctx.buf. */ 268 + __md5_final(&ctx->hash_ctx, ctx->hash_ctx.buf); 269 + memset(&ctx->hash_ctx.buf[MD5_DIGEST_SIZE], 0, 270 + MD5_BLOCK_SIZE - MD5_DIGEST_SIZE); 271 + ctx->hash_ctx.buf[MD5_DIGEST_SIZE] = 0x80; 272 + *(__le64 *)&ctx->hash_ctx.buf[MD5_BLOCK_SIZE - 8] = 273 + cpu_to_le64(8 * (MD5_BLOCK_SIZE + MD5_DIGEST_SIZE)); 274 + 275 + /* Compute the outer hash, which gives the HMAC value. */ 276 + md5_blocks(&ctx->ostate, ctx->hash_ctx.buf, 1); 277 + cpu_to_le32_array(ctx->ostate.h, ARRAY_SIZE(ctx->ostate.h)); 278 + memcpy(out, ctx->ostate.h, MD5_DIGEST_SIZE); 279 + 280 + memzero_explicit(ctx, sizeof(*ctx)); 281 + } 282 + EXPORT_SYMBOL_GPL(hmac_md5_final); 283 + 284 + void hmac_md5(const struct hmac_md5_key *key, 285 + const u8 *data, size_t data_len, u8 out[MD5_DIGEST_SIZE]) 286 + { 287 + struct hmac_md5_ctx ctx; 288 + 289 + hmac_md5_init(&ctx, key); 290 + hmac_md5_update(&ctx, data, data_len); 291 + hmac_md5_final(&ctx, out); 292 + } 293 + EXPORT_SYMBOL_GPL(hmac_md5); 294 + 295 + void hmac_md5_usingrawkey(const u8 *raw_key, size_t raw_key_len, 296 + const u8 *data, size_t data_len, 297 + u8 out[MD5_DIGEST_SIZE]) 298 + { 299 + struct hmac_md5_ctx ctx; 300 + 301 + hmac_md5_init_usingrawkey(&ctx, raw_key, raw_key_len); 302 + hmac_md5_update(&ctx, data, data_len); 303 + hmac_md5_final(&ctx, out); 304 + } 305 + EXPORT_SYMBOL_GPL(hmac_md5_usingrawkey); 306 + 307 + #ifdef md5_mod_init_arch 308 + static int __init md5_mod_init(void) 309 + { 310 + md5_mod_init_arch(); 311 + return 0; 312 + } 313 + subsys_initcall(md5_mod_init); 314 + 315 + static void __exit md5_mod_exit(void) 316 + { 317 + } 318 + module_exit(md5_mod_exit); 319 + #endif 320 + 321 + MODULE_DESCRIPTION("MD5 and HMAC-MD5 library functions"); 322 + MODULE_LICENSE("GPL");