iPXE
hkdf.c
Go to the documentation of this file.
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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_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 * The salt and input keying material are allowed to overlap the
54 * buffer that will be filled in with the pseudorandom key.
55 */
56void hkdf_extract ( struct digest_algorithm *digest, const void *salt,
57 size_t salt_len, const void *ikm, size_t ikm_len,
58 void *prk ) {
59 uint8_t ctx[ hmac_ctxsize ( digest ) ];
60 uint8_t zero[ digest->digestsize ];
61
62 /* Use all-zero salt if not specified */
63 if ( ! salt ) {
64 assert ( salt_len == 0 );
65 memset ( zero, 0, sizeof ( zero ) );
66 salt = zero;
67 salt_len = sizeof ( zero );
68 }
69
70 /* Calculate pseudorandom key */
71 hmac_init ( digest, ctx, salt, salt_len );
72 hmac_update ( digest, ctx, ikm, ikm_len );
73 hmac_final ( digest, ctx, prk );
74}
75
76/**
77 * Expand pseudorandom key
78 *
79 * @v digest Digest algorithm
80 * @v prk Pseudorandom key
81 * @v info Additional information (or NULL)
82 * @v info_len Length of additional information
83 * @v out Output keying material
84 * @v len Length of output keying material
85 *
86 * The pseudorandom key and additional information are allowed to
87 * overlap the buffer that will be filled in with the output keying
88 * material, provided that the length of the output keying material is
89 * less than or equal to the length of the pseudorandom key.
90 *
91 * In particular, this allows hkdf_expand() to be used to create a new
92 * generation of pseudorandom key (i.e. to have the output keying
93 * material overwrite the existing pseudorandom key).
94 */
95void hkdf_expand ( struct digest_algorithm *digest, const void *prk,
96 const void *info, size_t info_len, void *out, size_t len ) {
97 size_t digestsize = digest->digestsize;
98 uint8_t ctx[ hmac_ctxsize ( digest ) ];
100 uint8_t index = 0;
101 size_t frag_len;
102
103 while ( len ) {
104
105 /* Calculate T(n) */
106 hmac_init ( digest, ctx, prk, digestsize );
107 if ( index++ )
108 hmac_update ( digest, ctx, hash, digestsize );
109 hmac_update ( digest, ctx, info, info_len );
110 hmac_update ( digest, ctx, &index, sizeof ( index ) );
111 hmac_final ( digest, ctx, hash );
112
113 /* Copy to output buffer */
114 frag_len = len;
115 if ( frag_len > digestsize )
116 frag_len = digestsize;
117 memcpy ( out, hash, frag_len );
118 out += frag_len;
119 len -= frag_len;
120 }
121}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
u32 info
Definition ar9003_mac.h:0
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
long index
Definition bigint.h:30
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
void hkdf_expand(struct digest_algorithm *digest, const void *prk, const void *info, size_t info_len, void *out, size_t len)
Expand pseudorandom key.
Definition hkdf.c:95
void hkdf_extract(struct digest_algorithm *digest, const void *salt, size_t salt_len, const void *ikm, size_t ikm_len, void *prk)
Extract fixed-length pseudorandom key.
Definition hkdf.c:56
HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124
Keyed-Hashing for Message Authentication.
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
uint8_t info_len
Reject information length.
Definition ib_mad.h:7
Cryptographic API.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27