Leancrypto 1.6.0
Post-Quantum Cryptographic Library
Loading...
Searching...
No Matches
lc_cshake.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 - 2025, 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_CSHAKE_H
21#define LC_CSHAKE_H
22
23#include "lc_hash.h"
24#include "lc_sha3.h"
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
62int lc_cshake_init(struct lc_hash_ctx *ctx, const uint8_t *n, size_t nlen,
63 const uint8_t *s, size_t slen);
64
76static inline void lc_cshake_final(struct lc_hash_ctx *ctx, uint8_t *out,
77 size_t outlen)
78{
79 lc_hash_set_digestsize(ctx, outlen);
80 lc_hash_final(ctx, out);
81}
82
83/*
84 * Separate cSHAKE API with re-initialization support
85 *
86 * Re-initialization means that any state created by the init operation can be
87 * re-established during re-init.
88 */
90struct lc_cshake_ctx {
91 uint8_t *shadow_ctx;
92 struct lc_hash_ctx hash_ctx;
93};
94
95#define LC_CSHAKE_STATE_SIZE(x) (LC_HASH_STATE_SIZE(x))
96#define LC_CSHAKE_STATE_SIZE_REINIT(x) (2 * LC_HASH_STATE_SIZE(x))
97#define LC_CSHAKE_CTX_SIZE(x) \
98 (LC_CSHAKE_STATE_SIZE(x) + sizeof(struct lc_cshake_ctx))
99#define LC_CSHAKE_CTX_SIZE_REINIT(x) \
100 (LC_CSHAKE_STATE_SIZE_REINIT(x) + sizeof(struct lc_cshake_ctx))
101
102#define _LC_CSHAKE_SET_CTX(name, hashname, ctx, offset) \
103 _LC_HASH_SET_CTX((&name->hash_ctx), hashname, ctx, offset); \
104 name->shadow_ctx = NULL
105
106#define LC_CSHAKE_SET_CTX(name, hashname) \
107 _LC_CSHAKE_SET_CTX(name, hashname, name, sizeof(struct lc_cshake_ctx))
108
109#define _LC_CSHAKE_SET_CTX_REINIT(name, hashname, ctx, offset) \
110 _LC_HASH_SET_CTX((&name->hash_ctx), hashname, ctx, offset); \
111 name->shadow_ctx = (uint8_t *)((uint8_t *)ctx + offset + \
112 LC_HASH_STATE_SIZE(hashname))
113
114#define LC_CSHAKE_SET_CTX_REINIT(name, hashname) \
115 _LC_CSHAKE_SET_CTX_REINIT(name, hashname, name, \
116 sizeof(struct lc_cshake_ctx))
118
135int lc_cshake_ctx_init(struct lc_cshake_ctx *cshake_ctx, const uint8_t *n,
136 size_t nlen, const uint8_t *s, size_t slen);
137
147void lc_cshake_ctx_reinit(struct lc_cshake_ctx *cshake_ctx);
148
157void lc_cshake_ctx_update(struct lc_cshake_ctx *cshake_ctx, const uint8_t *in,
158 size_t inlen);
159
171void lc_cshake_ctx_final(struct lc_cshake_ctx *cshake_ctx, uint8_t *out,
172 size_t outlen);
173
186int lc_cshake_ctx_alloc(const struct lc_hash *hash,
187 struct lc_cshake_ctx **cshake_ctx, uint32_t flags);
188
189/*
190 * Support re-initialization of state. You set a key during cshake_init,
191 * perform a full CSHAKE operation. After a cshake_final, the re-initialization
192 * support allows you to call cshake_reinit and reuse the state for a new
193 * operation without providing the keys again. If in doubt, initialize
194 * the context with re-init support. The difference is that more memory is
195 * allocated to retain the initialized state.
196 */
197#define LC_CSHAKE_FLAGS_SUPPORT_REINIT (1 << 0)
198
204void lc_cshake_ctx_zero_free(struct lc_cshake_ctx *cshake_ctx);
205
212static inline void lc_cshake_ctx_zero(struct lc_cshake_ctx *cshake_ctx)
213{
214 struct lc_hash_ctx *hash_ctx;
215 const struct lc_hash *hash;
216
217 if (!cshake_ctx)
218 return;
219 hash_ctx = &cshake_ctx->hash_ctx;
220 hash = hash_ctx->hash;
221
222 lc_memset_secure((uint8_t *)cshake_ctx + sizeof(struct lc_cshake_ctx),
223 0,
224 cshake_ctx->shadow_ctx ?
225 LC_CSHAKE_STATE_SIZE_REINIT(hash) :
226 LC_CSHAKE_STATE_SIZE(hash));
227}
228
239#define LC_CSHAKE_CTX_ON_STACK(name, hashname) \
240 _Pragma("GCC diagnostic push") \
241 _Pragma("GCC diagnostic ignored \"-Wvla\"") _Pragma( \
242 "GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
243 LC_ALIGNED_BUFFER(name##_ctx_buf, \
244 LC_CSHAKE_CTX_SIZE(hashname), \
245 LC_HASH_COMMON_ALIGNMENT); \
246 struct lc_cshake_ctx *name = (struct lc_cshake_ctx *)name##_ctx_buf; \
247 LC_CSHAKE_SET_CTX(name, hashname); \
248 lc_cshake_ctx_zero(name); \
249 _Pragma("GCC diagnostic pop")
250
262#define LC_CSHAKE_CTX_ON_STACK_REINIT(name, hashname) \
263 _Pragma("GCC diagnostic push") \
264 _Pragma("GCC diagnostic ignored \"-Wvla\"") _Pragma( \
265 "GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
266 LC_ALIGNED_BUFFER(name##_ctx_buf, \
267 LC_CSHAKE_CTX_SIZE_REINIT(hashname), \
268 LC_HASH_COMMON_ALIGNMENT); \
269 struct lc_cshake_ctx *name = (struct lc_cshake_ctx *)name##_ctx_buf; \
270 LC_CSHAKE_SET_CTX_REINIT(name, hashname); \
271 lc_cshake_ctx_zero(name); \
272 _Pragma("GCC diagnostic pop")
273
274#ifdef __cplusplus
275}
276#endif
277
278#endif /* LC_CSHAKE_H */
void lc_hash_set_digestsize(struct lc_hash_ctx *hash_ctx, size_t digestsize)
Set the size of the message digest - this call is intended for SHAKE.
int lc_hash(const struct lc_hash *hash, const uint8_t *in, size_t inlen, uint8_t *digest)
Calculate message digest - one-shot.
void lc_hash_final(struct lc_hash_ctx *hash_ctx, uint8_t *digest)
Calculate message digest.
int lc_cshake_ctx_init(struct lc_cshake_ctx *cshake_ctx, const uint8_t *n, size_t nlen, const uint8_t *s, size_t slen)
Initialize the hash state with re-init support following the cSHAKE specification.
void lc_cshake_ctx_update(struct lc_cshake_ctx *cshake_ctx, const uint8_t *in, size_t inlen)
Update CSHAKE.
int lc_cshake_ctx_alloc(const struct lc_hash *hash, struct lc_cshake_ctx **cshake_ctx, uint32_t flags)
Allocate CSHAKE context on heap.
int lc_cshake_init(struct lc_hash_ctx *ctx, const uint8_t *n, size_t nlen, const uint8_t *s, size_t slen)
Initialize the hash state following the cSHAKE specification.
void lc_cshake_ctx_final(struct lc_cshake_ctx *cshake_ctx, uint8_t *out, size_t outlen)
Generate a cSHAKE message digest from a given state.
void lc_cshake_ctx_zero_free(struct lc_cshake_ctx *cshake_ctx)
Zeroize and free CSHAKE context.
static void lc_cshake_ctx_zero(struct lc_cshake_ctx *cshake_ctx)
Zeroize CSHAKE context allocated with either LC_CSHAKE_CTX_ON_STACK or lc_cshake_alloc.
Definition lc_cshake.h:212
void lc_cshake_ctx_reinit(struct lc_cshake_ctx *cshake_ctx)
Re-initialize CSHAKE context after a cshake_final operation.
static void lc_cshake_final(struct lc_hash_ctx *ctx, uint8_t *out, size_t outlen)
Generate a cSHAKE message digest from a given state.
Definition lc_cshake.h:76
static void lc_memset_secure(void *s, int c, size_t n)