Leancrypto 0.12.0
Post-Quantum Cryptographic Library
Loading...
Searching...
No Matches
lc_hkdf.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 - 2024, Stephan Mueller <smueller@chronox.de>
3 *
4 * License: see LICENSE file in root directory
5 *
6 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
7 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
9 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
10 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
11 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
12 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
13 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
16 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 */
19
20#ifndef LC_HKDF_H
21#define LC_HKDF_H
22
23#include "ext_headers.h"
24#include "lc_hmac.h"
25#include "lc_rng.h"
26#include "lc_memset_secure.h"
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
33struct lc_hkdf_ctx {
34 uint8_t partial[LC_SHA_MAX_SIZE_DIGEST];
35 size_t partial_ptr;
36 uint8_t ctr;
37 uint8_t rng_initialized : 1;
38 struct lc_hmac_ctx hmac_ctx;
39};
40
41#define LC_HKDF_STATE_SIZE(hashname) (LC_HMAC_CTX_SIZE(hashname))
42#define LC_HKDF_CTX_SIZE(hashname) \
43 (sizeof(struct lc_hkdf_ctx) + LC_HKDF_STATE_SIZE(hashname))
44
45#define _LC_HKDF_SET_CTX(name, hashname, ctx, offset) \
46 _LC_HMAC_SET_CTX((&(name)->hmac_ctx), hashname, ctx, offset)
47
48#define LC_HKDF_SET_CTX(name, hashname) \
49 _LC_HKDF_SET_CTX(name, hashname, name, sizeof(struct lc_hkdf_ctx))
51
73int lc_hkdf_extract(struct lc_hkdf_ctx *hkdf_ctx, const uint8_t *ikm,
74 size_t ikmlen, const uint8_t *salt, size_t saltlen);
75
92int lc_hkdf_expand(struct lc_hkdf_ctx *hkdf_ctx, const uint8_t *info,
93 size_t infolen, uint8_t *dst, size_t dlen);
94
102static inline void lc_hkdf_zero(struct lc_hkdf_ctx *hkdf_ctx)
103{
104 /*
105 * The use of this function implies that ->hmac_ctx is followed
106 * immediately by the state buffer!
107 */
108 lc_hmac_zero(&hkdf_ctx->hmac_ctx);
109 lc_memset_secure(hkdf_ctx->partial, 0, LC_SHA_MAX_SIZE_DIGEST);
110 hkdf_ctx->ctr = 0x01;
111 hkdf_ctx->rng_initialized = 0;
112 hkdf_ctx->partial_ptr = LC_SHA_MAX_SIZE_DIGEST;
113}
114
125int lc_hkdf_alloc(const struct lc_hash *hash, struct lc_hkdf_ctx **hkdf_ctx);
126
133void lc_hkdf_zero_free(struct lc_hkdf_ctx *hkdf_ctx);
134
142#define LC_HKDF_CTX_ON_STACK(name, hashname) \
143 _Pragma("GCC diagnostic push") \
144 _Pragma("GCC diagnostic ignored \"-Wvla\"") _Pragma( \
145 "GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
146 LC_ALIGNED_BUFFER(name##_ctx_buf, \
147 LC_HKDF_CTX_SIZE(hashname), \
148 LC_HASH_COMMON_ALIGNMENT); \
149 struct lc_hkdf_ctx *name = (struct lc_hkdf_ctx *)name##_ctx_buf; \
150 LC_HKDF_SET_CTX(name, hashname); \
151 lc_hkdf_zero(name); \
152 _Pragma("GCC diagnostic pop")
153
173static inline int lc_hkdf(const struct lc_hash *hash, const uint8_t *ikm,
174 size_t ikmlen, const uint8_t *salt, size_t saltlen,
175 const uint8_t *info, size_t infolen, uint8_t *dst,
176 size_t dlen)
177{
178 int ret;
179 LC_HKDF_CTX_ON_STACK(hkdf, hash);
180
181 ret = lc_hkdf_extract(hkdf, ikm, ikmlen, salt, saltlen);
182 if (ret < 0)
183 goto out;
184 ret = lc_hkdf_expand(hkdf, info, infolen, dst, dlen);
185
186out:
187 lc_hkdf_zero(hkdf);
188 return ret;
189}
190
191/******************************** HKDF as RNG *********************************/
192
202/* HKDF DRNG implementation */
203extern const struct lc_rng *lc_hkdf_rng;
204
205#define LC_HKDF_DRNG_CTX_SIZE(hashname) \
206 (sizeof(struct lc_rng_ctx) + LC_HKDF_CTX_SIZE(hashname))
207
208#define LC_HKDF_DRNG_SET_CTX(name, hashname) LC_HKDF_SET_CTX(name, hashname)
209
210#define LC_HKDF_RNG_CTX(name, hashname) \
211 LC_RNG_CTX(name, lc_hkdf_rng); \
212 LC_HKDF_DRNG_SET_CTX(((struct lc_hkdf_ctx *)(name->rng_state)), \
213 hashname); \
214 lc_rng_zero(name)
215
225#define LC_HKDF_DRNG_CTX_ON_STACK(name, hashname) \
226 _Pragma("GCC diagnostic push") \
227 _Pragma("GCC diagnostic ignored \"-Wvla\"") _Pragma( \
228 "GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
229 LC_ALIGNED_BUFFER(name##_ctx_buf, \
230 LC_HKDF_DRNG_CTX_SIZE(hashname), \
231 LC_HASH_COMMON_ALIGNMENT); \
232 struct lc_rng_ctx *name = (struct lc_rng_ctx *)name##_ctx_buf; \
233 LC_HKDF_RNG_CTX(name, hashname); \
234 _Pragma("GCC diagnostic pop")
235
251int lc_hkdf_rng_alloc(struct lc_rng_ctx **state, const struct lc_hash *hash);
252
253#ifdef __cplusplus
254}
255#endif
256
257#endif /* LC_HKDF_H */
static void lc_hmac_zero(struct lc_hmac_ctx *hmac_ctx)
Zeroize HMAC context allocated with either HMAC_CTX_ON_STACK or hmac_alloc.
Definition lc_hmac.h:148
void lc_hash(const struct lc_hash *hash, const uint8_t *in, size_t inlen, uint8_t *digest)
Calculate message digest - one-shot.
int lc_hkdf_expand(struct lc_hkdf_ctx *hkdf_ctx, const uint8_t *info, size_t infolen, uint8_t *dst, size_t dlen)
HMAC-based Extract-and-Expand Key Derivation Function (HKDF) - RFC5869 Expand phase.
#define LC_HKDF_CTX_ON_STACK(name, hashname)
Allocate stack memory for the HKDF context.
Definition lc_hkdf.h:142
static int lc_hkdf(const struct lc_hash *hash, const uint8_t *ikm, size_t ikmlen, const uint8_t *salt, size_t saltlen, const uint8_t *info, size_t infolen, uint8_t *dst, size_t dlen)
HMAC-based Extract-and-Expand Key Derivation Function (HKDF) - RFC5869 Complete implementation.
Definition lc_hkdf.h:173
void lc_hkdf_zero_free(struct lc_hkdf_ctx *hkdf_ctx)
Zeroize and free HKDF context.
static void lc_hkdf_zero(struct lc_hkdf_ctx *hkdf_ctx)
Zeroize HKDF context allocated with either LC_HKDF_CTX_ON_STACK or hkdf_alloc.
Definition lc_hkdf.h:102
int lc_hkdf_alloc(const struct lc_hash *hash, struct lc_hkdf_ctx **hkdf_ctx)
Allocate HKDF context on heap.
int lc_hkdf_extract(struct lc_hkdf_ctx *hkdf_ctx, const uint8_t *ikm, size_t ikmlen, const uint8_t *salt, size_t saltlen)
HMAC-based Extract-and-Expand Key Derivation Function (HKDF) - RFC5869 Extract phase.
int lc_hkdf_rng_alloc(struct lc_rng_ctx **state, const struct lc_hash *hash)
Allocation of a HKDF DRNG context.
const struct lc_rng * lc_hkdf_rng
static void lc_memset_secure(void *s, int c, size_t n)