1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _CRYPTO_MD5_H
3 #define _CRYPTO_MD5_H
4
5 #include <crypto/hash.h>
6 #include <linux/types.h>
7
8 #define MD5_DIGEST_SIZE 16
9 #define MD5_HMAC_BLOCK_SIZE 64
10 #define MD5_BLOCK_SIZE 64
11 #define MD5_BLOCK_WORDS 16
12 #define MD5_HASH_WORDS 4
13 #define MD5_STATE_SIZE 24
14
15 #define MD5_H0 0x67452301UL
16 #define MD5_H1 0xefcdab89UL
17 #define MD5_H2 0x98badcfeUL
18 #define MD5_H3 0x10325476UL
19
20 #define CRYPTO_MD5_STATESIZE \
21 CRYPTO_HASH_STATESIZE(MD5_STATE_SIZE, MD5_HMAC_BLOCK_SIZE)
22
23 extern const u8 md5_zero_message_hash[MD5_DIGEST_SIZE];
24
25 struct md5_state {
26 u32 hash[MD5_HASH_WORDS];
27 u64 byte_count;
28 u32 block[MD5_BLOCK_WORDS];
29 };
30
31 /* State for the MD5 compression function */
32 struct md5_block_state {
33 u32 h[MD5_HASH_WORDS];
34 };
35
36 /**
37 * struct md5_ctx - Context for hashing a message with MD5
38 * @state: the compression function state
39 * @bytecount: number of bytes processed so far
40 * @buf: partial block buffer; bytecount % MD5_BLOCK_SIZE bytes are valid
41 */
42 struct md5_ctx {
43 struct md5_block_state state;
44 u64 bytecount;
45 u8 buf[MD5_BLOCK_SIZE] __aligned(__alignof__(__le64));
46 };
47
48 /**
49 * md5_init() - Initialize an MD5 context for a new message
50 * @ctx: the context to initialize
51 *
52 * If you don't need incremental computation, consider md5() instead.
53 *
54 * Context: Any context.
55 */
56 void md5_init(struct md5_ctx *ctx);
57
58 /**
59 * md5_update() - Update an MD5 context with message data
60 * @ctx: the context to update; must have been initialized
61 * @data: the message data
62 * @len: the data length in bytes
63 *
64 * This can be called any number of times.
65 *
66 * Context: Any context.
67 */
68 void md5_update(struct md5_ctx *ctx, const u8 *data, size_t len);
69
70 /**
71 * md5_final() - Finish computing an MD5 message digest
72 * @ctx: the context to finalize; must have been initialized
73 * @out: (output) the resulting MD5 message digest
74 *
75 * After finishing, this zeroizes @ctx. So the caller does not need to do it.
76 *
77 * Context: Any context.
78 */
79 void md5_final(struct md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]);
80
81 /**
82 * md5() - Compute MD5 message digest in one shot
83 * @data: the message data
84 * @len: the data length in bytes
85 * @out: (output) the resulting MD5 message digest
86 *
87 * Context: Any context.
88 */
89 void md5(const u8 *data, size_t len, u8 out[MD5_DIGEST_SIZE]);
90
91 /**
92 * struct hmac_md5_key - Prepared key for HMAC-MD5
93 * @istate: private
94 * @ostate: private
95 */
96 struct hmac_md5_key {
97 struct md5_block_state istate;
98 struct md5_block_state ostate;
99 };
100
101 /**
102 * struct hmac_md5_ctx - Context for computing HMAC-MD5 of a message
103 * @hash_ctx: private
104 * @ostate: private
105 */
106 struct hmac_md5_ctx {
107 struct md5_ctx hash_ctx;
108 struct md5_block_state ostate;
109 };
110
111 /**
112 * hmac_md5_preparekey() - Prepare a key for HMAC-MD5
113 * @key: (output) the key structure to initialize
114 * @raw_key: the raw HMAC-MD5 key
115 * @raw_key_len: the key length in bytes. All key lengths are supported.
116 *
117 * Note: the caller is responsible for zeroizing both the struct hmac_md5_key
118 * and the raw key once they are no longer needed.
119 *
120 * Context: Any context.
121 */
122 void hmac_md5_preparekey(struct hmac_md5_key *key,
123 const u8 *raw_key, size_t raw_key_len);
124
125 /**
126 * hmac_md5_init() - Initialize an HMAC-MD5 context for a new message
127 * @ctx: (output) the HMAC context to initialize
128 * @key: the prepared HMAC key
129 *
130 * If you don't need incremental computation, consider hmac_md5() instead.
131 *
132 * Context: Any context.
133 */
134 void hmac_md5_init(struct hmac_md5_ctx *ctx, const struct hmac_md5_key *key);
135
136 /**
137 * hmac_md5_init_usingrawkey() - Initialize an HMAC-MD5 context for a new
138 * message, using a raw key
139 * @ctx: (output) the HMAC context to initialize
140 * @raw_key: the raw HMAC-MD5 key
141 * @raw_key_len: the key length in bytes. All key lengths are supported.
142 *
143 * If you don't need incremental computation, consider hmac_md5_usingrawkey()
144 * instead.
145 *
146 * Context: Any context.
147 */
148 void hmac_md5_init_usingrawkey(struct hmac_md5_ctx *ctx,
149 const u8 *raw_key, size_t raw_key_len);
150
151 /**
152 * hmac_md5_update() - Update an HMAC-MD5 context with message data
153 * @ctx: the HMAC context to update; must have been initialized
154 * @data: the message data
155 * @data_len: the data length in bytes
156 *
157 * This can be called any number of times.
158 *
159 * Context: Any context.
160 */
hmac_md5_update(struct hmac_md5_ctx * ctx,const u8 * data,size_t data_len)161 static inline void hmac_md5_update(struct hmac_md5_ctx *ctx,
162 const u8 *data, size_t data_len)
163 {
164 md5_update(&ctx->hash_ctx, data, data_len);
165 }
166
167 /**
168 * hmac_md5_final() - Finish computing an HMAC-MD5 value
169 * @ctx: the HMAC context to finalize; must have been initialized
170 * @out: (output) the resulting HMAC-MD5 value
171 *
172 * After finishing, this zeroizes @ctx. So the caller does not need to do it.
173 *
174 * Context: Any context.
175 */
176 void hmac_md5_final(struct hmac_md5_ctx *ctx, u8 out[MD5_DIGEST_SIZE]);
177
178 /**
179 * hmac_md5() - Compute HMAC-MD5 in one shot, using a prepared key
180 * @key: the prepared HMAC key
181 * @data: the message data
182 * @data_len: the data length in bytes
183 * @out: (output) the resulting HMAC-MD5 value
184 *
185 * If you're using the key only once, consider using hmac_md5_usingrawkey().
186 *
187 * Context: Any context.
188 */
189 void hmac_md5(const struct hmac_md5_key *key,
190 const u8 *data, size_t data_len, u8 out[MD5_DIGEST_SIZE]);
191
192 /**
193 * hmac_md5_usingrawkey() - Compute HMAC-MD5 in one shot, using a raw key
194 * @raw_key: the raw HMAC-MD5 key
195 * @raw_key_len: the key length in bytes. All key lengths are supported.
196 * @data: the message data
197 * @data_len: the data length in bytes
198 * @out: (output) the resulting HMAC-MD5 value
199 *
200 * If you're using the key multiple times, prefer to use hmac_md5_preparekey()
201 * followed by multiple calls to hmac_md5() instead.
202 *
203 * Context: Any context.
204 */
205 void hmac_md5_usingrawkey(const u8 *raw_key, size_t raw_key_len,
206 const u8 *data, size_t data_len,
207 u8 out[MD5_DIGEST_SIZE]);
208
209 #endif /* _CRYPTO_MD5_H */
210