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
23extern const u8 md5_zero_message_hash[MD5_DIGEST_SIZE];
24
25struct 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 */
32struct 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 */
42struct 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 */
56void 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 */
68void 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 */
79void 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 */
89void 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 */
96struct 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 */
106struct 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 */
122void 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 */
134void 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 */
148void 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 */
161static inline void hmac_md5_update(struct hmac_md5_ctx *ctx,
162 const u8 *data, size_t data_len)
163{
164 md5_update(ctx: &ctx->hash_ctx, data, len: 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 */
176void 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 */
189void 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 */
205void 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