Skip to content

Commit 8d2ebbf

Browse files
committed
[crypto] Add support for HKDF key derivation
Add support for the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as used in TLS version 1.3 and defined in RFC 5869. Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent a42daf6 commit 8d2ebbf

4 files changed

Lines changed: 450 additions & 0 deletions

File tree

src/crypto/hkdf.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation; either version 2 of the
7+
* License, or any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17+
* 02110-1301, USA.
18+
*
19+
* You can also choose to distribute this program under the terms of
20+
* the Unmodified Binary Distribution Licence (as given in the file
21+
* COPYING.UBDL), provided that you have satisfied its requirements.
22+
*/
23+
24+
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25+
FILE_SECBOOT ( PERMITTED );
26+
27+
/** @file
28+
*
29+
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
30+
*
31+
* The algorithm is defined in RFC 5869, with its usage by TLS 1.3
32+
* documented in RFC 8446 section 7.1.
33+
*
34+
*/
35+
36+
#include <stdint.h>
37+
#include <string.h>
38+
#include <assert.h>
39+
#include <ipxe/crypto.h>
40+
#include <ipxe/hmac.h>
41+
#include <ipxe/hkdf.h>
42+
43+
/**
44+
* Extract fixed-length pseudorandom key
45+
*
46+
* @v digest Digest algorithm
47+
* @v salt Salt value (or NULL)
48+
* @v salt_len Length of salt value
49+
* @v ikm Input keying material
50+
* @v ikm_len Length of input keying material
51+
* @v prk Pseudorandom key to fill in
52+
*/
53+
void hkdf_extract ( struct digest_algorithm *digest, const void *salt,
54+
size_t salt_len, const void *ikm, size_t ikm_len,
55+
void *prk ) {
56+
uint8_t ctx[ hmac_ctxsize ( digest ) ];
57+
58+
/* Use all-zero salt if not specified */
59+
if ( ! salt ) {
60+
assert ( salt_len == 0 );
61+
salt_len = digest->digestsize;
62+
memset ( prk, 0, salt_len );
63+
salt = prk;
64+
}
65+
66+
/* Calculate pseudorandom key */
67+
hmac_init ( digest, ctx, salt, salt_len );
68+
hmac_update ( digest, ctx, ikm, ikm_len );
69+
hmac_final ( digest, ctx, prk );
70+
}
71+
72+
/**
73+
* Expand pseudorandom key
74+
*
75+
* @v digest Digest algorithm
76+
* @v prk Pseudorandom key
77+
* @v info Additional information (or NULL)
78+
* @v info_len Length of additional information
79+
* @v out Output keying material
80+
* @v len Length of output keying material
81+
*/
82+
void hkdf_expand ( struct digest_algorithm *digest, const void *prk,
83+
const void *info, size_t info_len, void *out, size_t len ) {
84+
size_t digestsize = digest->digestsize;
85+
uint8_t ctx[ hmac_ctxsize ( digest ) ];
86+
uint8_t hash[digestsize];
87+
uint8_t index = 0;
88+
size_t frag_len;
89+
90+
while ( len ) {
91+
92+
/* Calculate T(n) */
93+
hmac_init ( digest, ctx, prk, digestsize );
94+
if ( index++ )
95+
hmac_update ( digest, ctx, hash, digestsize );
96+
hmac_update ( digest, ctx, info, info_len );
97+
hmac_update ( digest, ctx, &index, sizeof ( index ) );
98+
hmac_final ( digest, ctx, hash );
99+
100+
/* Copy to output buffer */
101+
frag_len = len;
102+
if ( frag_len > digestsize )
103+
frag_len = digestsize;
104+
memcpy ( out, hash, frag_len );
105+
out += frag_len;
106+
len -= frag_len;
107+
}
108+
}

src/include/ipxe/hkdf.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef _IPXE_HKDF_H
2+
#define _IPXE_HKDF_H
3+
4+
/** @file
5+
*
6+
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
7+
*
8+
*/
9+
10+
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11+
FILE_SECBOOT ( PERMITTED );
12+
13+
#include <ipxe/crypto.h>
14+
15+
extern void hkdf_extract ( struct digest_algorithm *digest, const void *salt,
16+
size_t salt_len, const void *ikm, size_t ikm_len,
17+
void *prk );
18+
extern void hkdf_expand ( struct digest_algorithm *digest, const void *prk,
19+
const void *info, size_t info_len, void *out,
20+
size_t len );
21+
22+
#endif /* _IPXE_HKDF_H */

0 commit comments

Comments
 (0)