Skip to content

Commit 4cbc844

Browse files
author
Eric Biggers
committed
lib/crypto: sha1: Add HMAC support
Add HMAC support to the SHA-1 library, again following what was done for SHA-2. Besides providing the basis for a more streamlined "hmac(sha1)" shash, this will also be useful for multiple in-kernel users such as net/sctp/auth.c, net/ipv6/seg6_hmac.c, and security/keys/trusted-keys/trusted_tpm1.c. Those are currently using crypto_shash, but using the library functions would be much simpler. Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lore.kernel.org/r/20250712232329.818226-5-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
1 parent 90860ae commit 4cbc844

2 files changed

Lines changed: 223 additions & 3 deletions

File tree

include/crypto/sha1.h

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,122 @@ void sha1_final(struct sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE]);
9696
*/
9797
void sha1(const u8 *data, size_t len, u8 out[SHA1_DIGEST_SIZE]);
9898

99+
/**
100+
* struct hmac_sha1_key - Prepared key for HMAC-SHA1
101+
* @istate: private
102+
* @ostate: private
103+
*/
104+
struct hmac_sha1_key {
105+
struct sha1_block_state istate;
106+
struct sha1_block_state ostate;
107+
};
108+
109+
/**
110+
* struct hmac_sha1_ctx - Context for computing HMAC-SHA1 of a message
111+
* @sha_ctx: private
112+
* @ostate: private
113+
*/
114+
struct hmac_sha1_ctx {
115+
struct sha1_ctx sha_ctx;
116+
struct sha1_block_state ostate;
117+
};
118+
119+
/**
120+
* hmac_sha1_preparekey() - Prepare a key for HMAC-SHA1
121+
* @key: (output) the key structure to initialize
122+
* @raw_key: the raw HMAC-SHA1 key
123+
* @raw_key_len: the key length in bytes. All key lengths are supported.
124+
*
125+
* Note: the caller is responsible for zeroizing both the struct hmac_sha1_key
126+
* and the raw key once they are no longer needed.
127+
*
128+
* Context: Any context.
129+
*/
130+
void hmac_sha1_preparekey(struct hmac_sha1_key *key,
131+
const u8 *raw_key, size_t raw_key_len);
132+
133+
/**
134+
* hmac_sha1_init() - Initialize an HMAC-SHA1 context for a new message
135+
* @ctx: (output) the HMAC context to initialize
136+
* @key: the prepared HMAC key
137+
*
138+
* If you don't need incremental computation, consider hmac_sha1() instead.
139+
*
140+
* Context: Any context.
141+
*/
142+
void hmac_sha1_init(struct hmac_sha1_ctx *ctx, const struct hmac_sha1_key *key);
143+
144+
/**
145+
* hmac_sha1_init_usingrawkey() - Initialize an HMAC-SHA1 context for a new
146+
* message, using a raw key
147+
* @ctx: (output) the HMAC context to initialize
148+
* @raw_key: the raw HMAC-SHA1 key
149+
* @raw_key_len: the key length in bytes. All key lengths are supported.
150+
*
151+
* If you don't need incremental computation, consider hmac_sha1_usingrawkey()
152+
* instead.
153+
*
154+
* Context: Any context.
155+
*/
156+
void hmac_sha1_init_usingrawkey(struct hmac_sha1_ctx *ctx,
157+
const u8 *raw_key, size_t raw_key_len);
158+
159+
/**
160+
* hmac_sha1_update() - Update an HMAC-SHA1 context with message data
161+
* @ctx: the HMAC context to update; must have been initialized
162+
* @data: the message data
163+
* @data_len: the data length in bytes
164+
*
165+
* This can be called any number of times.
166+
*
167+
* Context: Any context.
168+
*/
169+
static inline void hmac_sha1_update(struct hmac_sha1_ctx *ctx,
170+
const u8 *data, size_t data_len)
171+
{
172+
sha1_update(&ctx->sha_ctx, data, data_len);
173+
}
174+
175+
/**
176+
* hmac_sha1_final() - Finish computing an HMAC-SHA1 value
177+
* @ctx: the HMAC context to finalize; must have been initialized
178+
* @out: (output) the resulting HMAC-SHA1 value
179+
*
180+
* After finishing, this zeroizes @ctx. So the caller does not need to do it.
181+
*
182+
* Context: Any context.
183+
*/
184+
void hmac_sha1_final(struct hmac_sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE]);
185+
186+
/**
187+
* hmac_sha1() - Compute HMAC-SHA1 in one shot, using a prepared key
188+
* @key: the prepared HMAC key
189+
* @data: the message data
190+
* @data_len: the data length in bytes
191+
* @out: (output) the resulting HMAC-SHA1 value
192+
*
193+
* If you're using the key only once, consider using hmac_sha1_usingrawkey().
194+
*
195+
* Context: Any context.
196+
*/
197+
void hmac_sha1(const struct hmac_sha1_key *key,
198+
const u8 *data, size_t data_len, u8 out[SHA1_DIGEST_SIZE]);
199+
200+
/**
201+
* hmac_sha1_usingrawkey() - Compute HMAC-SHA1 in one shot, using a raw key
202+
* @raw_key: the raw HMAC-SHA1 key
203+
* @raw_key_len: the key length in bytes. All key lengths are supported.
204+
* @data: the message data
205+
* @data_len: the data length in bytes
206+
* @out: (output) the resulting HMAC-SHA1 value
207+
*
208+
* If you're using the key multiple times, prefer to use hmac_sha1_preparekey()
209+
* followed by multiple calls to hmac_sha1() instead.
210+
*
211+
* Context: Any context.
212+
*/
213+
void hmac_sha1_usingrawkey(const u8 *raw_key, size_t raw_key_len,
214+
const u8 *data, size_t data_len,
215+
u8 out[SHA1_DIGEST_SIZE]);
216+
99217
#endif /* _CRYPTO_SHA1_H */

lib/crypto/sha1.c

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/*
3-
* SHA-1 library functions
3+
* SHA-1 and HMAC-SHA1 library functions
44
*/
55

6+
#include <crypto/hmac.h>
67
#include <crypto/sha1.h>
78
#include <linux/bitops.h>
89
#include <linux/export.h>
910
#include <linux/kernel.h>
1011
#include <linux/module.h>
1112
#include <linux/string.h>
1213
#include <linux/unaligned.h>
14+
#include <linux/wordpart.h>
1315

1416
static const struct sha1_block_state sha1_iv = {
1517
.h = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
@@ -197,7 +199,7 @@ void sha1_update(struct sha1_ctx *ctx, const u8 *data, size_t len)
197199
}
198200
EXPORT_SYMBOL_GPL(sha1_update);
199201

200-
void sha1_final(struct sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE])
202+
static void __sha1_final(struct sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE])
201203
{
202204
u64 bitcount = ctx->bytecount << 3;
203205
size_t partial = ctx->bytecount % SHA1_BLOCK_SIZE;
@@ -214,6 +216,11 @@ void sha1_final(struct sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE])
214216

215217
for (size_t i = 0; i < SHA1_DIGEST_SIZE; i += 4)
216218
put_unaligned_be32(ctx->state.h[i / 4], out + i);
219+
}
220+
221+
void sha1_final(struct sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE])
222+
{
223+
__sha1_final(ctx, out);
217224
memzero_explicit(ctx, sizeof(*ctx));
218225
}
219226
EXPORT_SYMBOL_GPL(sha1_final);
@@ -228,6 +235,101 @@ void sha1(const u8 *data, size_t len, u8 out[SHA1_DIGEST_SIZE])
228235
}
229236
EXPORT_SYMBOL_GPL(sha1);
230237

238+
static void __hmac_sha1_preparekey(struct sha1_block_state *istate,
239+
struct sha1_block_state *ostate,
240+
const u8 *raw_key, size_t raw_key_len)
241+
{
242+
union {
243+
u8 b[SHA1_BLOCK_SIZE];
244+
unsigned long w[SHA1_BLOCK_SIZE / sizeof(unsigned long)];
245+
} derived_key = { 0 };
246+
247+
if (unlikely(raw_key_len > SHA1_BLOCK_SIZE))
248+
sha1(raw_key, raw_key_len, derived_key.b);
249+
else
250+
memcpy(derived_key.b, raw_key, raw_key_len);
251+
252+
for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
253+
derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE);
254+
*istate = sha1_iv;
255+
sha1_blocks(istate, derived_key.b, 1);
256+
257+
for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
258+
derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^
259+
HMAC_IPAD_VALUE);
260+
*ostate = sha1_iv;
261+
sha1_blocks(ostate, derived_key.b, 1);
262+
263+
memzero_explicit(&derived_key, sizeof(derived_key));
264+
}
265+
266+
void hmac_sha1_preparekey(struct hmac_sha1_key *key,
267+
const u8 *raw_key, size_t raw_key_len)
268+
{
269+
__hmac_sha1_preparekey(&key->istate, &key->ostate,
270+
raw_key, raw_key_len);
271+
}
272+
EXPORT_SYMBOL_GPL(hmac_sha1_preparekey);
273+
274+
void hmac_sha1_init(struct hmac_sha1_ctx *ctx, const struct hmac_sha1_key *key)
275+
{
276+
ctx->sha_ctx.state = key->istate;
277+
ctx->sha_ctx.bytecount = SHA1_BLOCK_SIZE;
278+
ctx->ostate = key->ostate;
279+
}
280+
EXPORT_SYMBOL_GPL(hmac_sha1_init);
281+
282+
void hmac_sha1_init_usingrawkey(struct hmac_sha1_ctx *ctx,
283+
const u8 *raw_key, size_t raw_key_len)
284+
{
285+
__hmac_sha1_preparekey(&ctx->sha_ctx.state, &ctx->ostate,
286+
raw_key, raw_key_len);
287+
ctx->sha_ctx.bytecount = SHA1_BLOCK_SIZE;
288+
}
289+
EXPORT_SYMBOL_GPL(hmac_sha1_init_usingrawkey);
290+
291+
void hmac_sha1_final(struct hmac_sha1_ctx *ctx, u8 out[SHA1_DIGEST_SIZE])
292+
{
293+
/* Generate the padded input for the outer hash in ctx->sha_ctx.buf. */
294+
__sha1_final(&ctx->sha_ctx, ctx->sha_ctx.buf);
295+
memset(&ctx->sha_ctx.buf[SHA1_DIGEST_SIZE], 0,
296+
SHA1_BLOCK_SIZE - SHA1_DIGEST_SIZE);
297+
ctx->sha_ctx.buf[SHA1_DIGEST_SIZE] = 0x80;
298+
*(__be32 *)&ctx->sha_ctx.buf[SHA1_BLOCK_SIZE - 4] =
299+
cpu_to_be32(8 * (SHA1_BLOCK_SIZE + SHA1_DIGEST_SIZE));
300+
301+
/* Compute the outer hash, which gives the HMAC value. */
302+
sha1_blocks(&ctx->ostate, ctx->sha_ctx.buf, 1);
303+
for (size_t i = 0; i < SHA1_DIGEST_SIZE; i += 4)
304+
put_unaligned_be32(ctx->ostate.h[i / 4], out + i);
305+
306+
memzero_explicit(ctx, sizeof(*ctx));
307+
}
308+
EXPORT_SYMBOL_GPL(hmac_sha1_final);
309+
310+
void hmac_sha1(const struct hmac_sha1_key *key,
311+
const u8 *data, size_t data_len, u8 out[SHA1_DIGEST_SIZE])
312+
{
313+
struct hmac_sha1_ctx ctx;
314+
315+
hmac_sha1_init(&ctx, key);
316+
hmac_sha1_update(&ctx, data, data_len);
317+
hmac_sha1_final(&ctx, out);
318+
}
319+
EXPORT_SYMBOL_GPL(hmac_sha1);
320+
321+
void hmac_sha1_usingrawkey(const u8 *raw_key, size_t raw_key_len,
322+
const u8 *data, size_t data_len,
323+
u8 out[SHA1_DIGEST_SIZE])
324+
{
325+
struct hmac_sha1_ctx ctx;
326+
327+
hmac_sha1_init_usingrawkey(&ctx, raw_key, raw_key_len);
328+
hmac_sha1_update(&ctx, data, data_len);
329+
hmac_sha1_final(&ctx, out);
330+
}
331+
EXPORT_SYMBOL_GPL(hmac_sha1_usingrawkey);
332+
231333
#ifdef sha1_mod_init_arch
232334
static int __init sha1_mod_init(void)
233335
{
@@ -242,5 +344,5 @@ static void __exit sha1_mod_exit(void)
242344
module_exit(sha1_mod_exit);
243345
#endif
244346

245-
MODULE_DESCRIPTION("SHA-1 library functions");
347+
MODULE_DESCRIPTION("SHA-1 and HMAC-SHA1 library functions");
246348
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)