Leancrypto 0.12.0
Post-Quantum Cryptographic Library
Loading...
Searching...
No Matches
lc_hash.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 - 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_HASH_H
21#define LC_HASH_H
22
23#include "ext_headers.h"
24#include "lc_memset_secure.h"
25#include "lc_memory_support.h"
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
32struct lc_hash {
33 /* SHA3 / SHAKE interface */
34 void (*init)(void *state);
35 void (*update)(void *state, const uint8_t *in, size_t inlen);
36 void (*final)(void *state, uint8_t *digest);
37 void (*set_digestsize)(void *state, size_t digestsize);
38 size_t (*get_digestsize)(void *state);
39
40 /* Sponge interface */
41 void (*sponge_permutation)(void *state, unsigned int rounds);
42 void (*sponge_add_bytes)(void *state, const uint8_t *data,
43 size_t offset, size_t length);
44 void (*sponge_extract_bytes)(const void *state, uint8_t *data,
45 size_t offset, size_t length);
46 void (*sponge_newstate)(void *state, const uint8_t *newstate,
47 size_t offset, size_t length);
48
49 uint8_t sponge_rate;
50 unsigned short statesize;
51};
52
53struct lc_hash_ctx {
54 const struct lc_hash *hash;
55 void *hash_state;
56};
57
58/*
59 * Align the hash_state pointer to 8 bytes boundary irrespective where
60 * it is embedded into. This is achieved by adding 7 more bytes than necessary
61 * to LC_ALIGNED_BUFFER and then adjusting the pointer offset in that range
62 * accordingly.
63 *
64 * It is permissible to set the alignment requirement with compile-time
65 * arguments.
66 */
67#ifndef LC_HASH_COMMON_ALIGNMENT
68/* Macro set during leancrypto compile time for target platform */
69#define LC_HASH_COMMON_ALIGNMENT 64
70#endif
71
72#define LC_ALIGN_HASH_MASK(p) \
73 LC_ALIGN_PTR_64(p, LC_ALIGNMENT_MASK(LC_HASH_COMMON_ALIGNMENT))
74
75#define LC_SHA_MAX_SIZE_DIGEST 64
76
77/*
78 * This is the source of the compiler warning of using Variable-Length-Arrays
79 * (VLA). It is considered to be harmless to have this VLA here. If you do not
80 * want it, you have the following options:
81 *
82 * 1. Define a hard-coded value here, e.g. sizeof(struct lc_sha3_224_state)
83 * as the SHA3-224 has the largest structure.
84 * 2. Only use the SHA-specific stack allocation functions
85 * (e.g. LC_SHA3_256_CTX_ON_STACK) instead of the generic
86 * LC_HASH_CTX_ON_STACK call.
87 * 3. Do not use stack-allocation function.
88 * 4. Ignore the warning by using
89 * #pragma GCC diagnostic ignored "-Wvla"
90 * #pragma GCC diagnostic push
91 * LC_HASH_CTX_ON_STACK()
92 * #pragma pop
93 */
94#define LC_HASH_STATE_SIZE_NONALIGNED(x) ((unsigned long)(x->statesize))
95#define LC_HASH_STATE_SIZE(x) \
96 (LC_HASH_STATE_SIZE_NONALIGNED(x) + LC_HASH_COMMON_ALIGNMENT)
97#define LC_HASH_CTX_SIZE(x) (sizeof(struct lc_hash_ctx) + LC_HASH_STATE_SIZE(x))
98
99#define _LC_HASH_SET_CTX(name, hashname, ctx, offset) \
100 name->hash_state = LC_ALIGN_HASH_MASK(((uint8_t *)(ctx)) + (offset)); \
101 name->hash = hashname
102
103#define LC_HASH_SET_CTX(name, hashname) \
104 _LC_HASH_SET_CTX(name, hashname, name, sizeof(struct lc_hash_ctx))
106
130static inline void lc_hash_init(struct lc_hash_ctx *hash_ctx)
131{
132 const struct lc_hash *hash;
133
134 if (!hash_ctx)
135 return;
136
137 hash = hash_ctx->hash;
138 hash->init(hash_ctx->hash_state);
139}
140
150static inline void lc_hash_update(struct lc_hash_ctx *hash_ctx,
151 const uint8_t *in, size_t inlen)
152{
153 const struct lc_hash *hash;
154
155 if (!hash_ctx)
156 return;
157
158 hash = hash_ctx->hash;
159 hash->update(hash_ctx->hash_state, in, inlen);
160}
161
192static inline void lc_hash_final(struct lc_hash_ctx *hash_ctx, uint8_t *digest)
193{
194 const struct lc_hash *hash;
195
196 if (!hash_ctx || !digest)
197 return;
198
199 hash = hash_ctx->hash;
200 hash->final(hash_ctx->hash_state, digest);
201}
202
211static inline void lc_hash_set_digestsize(struct lc_hash_ctx *hash_ctx,
212 size_t digestsize)
213{
214 const struct lc_hash *hash;
215
216 if (!hash_ctx)
217 return;
218
219 hash = hash_ctx->hash;
220 if (hash->set_digestsize)
221 hash->set_digestsize(hash_ctx->hash_state, digestsize);
222}
223
231static inline size_t lc_hash_digestsize(struct lc_hash_ctx *hash_ctx)
232{
233 const struct lc_hash *hash;
234
235 if (!hash_ctx)
236 return 0;
237
238 hash = hash_ctx->hash;
239 return hash->get_digestsize(hash_ctx->hash_state);
240}
241
250static inline unsigned int lc_hash_blocksize(struct lc_hash_ctx *hash_ctx)
251{
252 const struct lc_hash *hash;
253
254 if (!hash_ctx)
255 return 0;
256
257 hash = hash_ctx->hash;
258 return hash->sponge_rate;
259}
260
268static inline unsigned int lc_hash_ctxsize(struct lc_hash_ctx *hash_ctx)
269{
270 const struct lc_hash *hash;
271
272 if (!hash_ctx)
273 return 0;
274
275 hash = hash_ctx->hash;
276 return hash->statesize;
277}
278
286static inline void lc_hash_zero(struct lc_hash_ctx *hash_ctx)
287{
288 const struct lc_hash *hash;
289
290 if (!hash_ctx)
291 return;
292
293 hash = hash_ctx->hash;
294 lc_memset_secure((uint8_t *)hash_ctx + sizeof(struct lc_hash_ctx), 0,
295 hash->statesize);
296}
297
307#define LC_HASH_CTX_ON_STACK(name, hashname) \
308 _Pragma("GCC diagnostic push") \
309 _Pragma("GCC diagnostic ignored \"-Wvla\"") _Pragma( \
310 "GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
311 LC_ALIGNED_BUFFER(name##_ctx_buf, \
312 LC_HASH_CTX_SIZE(hashname), \
313 LC_HASH_COMMON_ALIGNMENT); \
314 struct lc_hash_ctx *name = (struct lc_hash_ctx *)name##_ctx_buf; \
315 LC_HASH_SET_CTX(name, hashname); \
316 lc_hash_zero(name); \
317 _Pragma("GCC diagnostic pop")
318
330int lc_hash_alloc(const struct lc_hash *hash, struct lc_hash_ctx **hash_ctx);
331
338void lc_hash_zero_free(struct lc_hash_ctx *hash_ctx);
339
353void lc_hash(const struct lc_hash *hash, const uint8_t *in, size_t inlen,
354 uint8_t *digest);
355
369void lc_xof(const struct lc_hash *xof, const uint8_t *in, size_t inlen,
370 uint8_t *digest, size_t digestlen);
371
390static inline int lc_sponge(const struct lc_hash *hash, void *state,
391 unsigned int rounds)
392{
393 if (!state || !hash || !hash->sponge_permutation)
394 return -EOPNOTSUPP;
395
396 hash->sponge_permutation(state, rounds);
397
398 return 0;
399}
400
425static inline int lc_sponge_add_bytes(const struct lc_hash *hash, void *state,
426 const uint8_t *data, size_t offset,
427 size_t length)
428{
429 if (!state || !hash || !hash->sponge_add_bytes)
430 return -EOPNOTSUPP;
431
432 hash->sponge_add_bytes(state, data, offset, length);
433
434 return 0;
435}
436
459static inline int lc_sponge_extract_bytes(const struct lc_hash *hash,
460 const void *state, uint8_t *data,
461 size_t offset, size_t length)
462{
463 if (!state || !hash || !hash->sponge_extract_bytes)
464 return -EOPNOTSUPP;
465
466 hash->sponge_extract_bytes(state, data, offset, length);
467
468 return 0;
469}
470
488static inline int lc_sponge_newstate(const struct lc_hash *hash, void *state,
489 const uint8_t *data, size_t offset,
490 size_t length)
491{
492 if (!state || !hash || !hash->sponge_newstate)
493 return -EOPNOTSUPP;
494
495 hash->sponge_newstate(state, data, offset, length);
496
497 return 0;
498}
499
500#ifdef __cplusplus
501}
502#endif
503
504#endif /* LC_HASH_H */
static int lc_sponge_add_bytes(const struct lc_hash *hash, void *state, const uint8_t *data, size_t offset, size_t length)
Function to add (in GF(2), using bitwise exclusive-or) data given as bytes into the sponge state.
Definition lc_hash.h:425
static size_t lc_hash_digestsize(struct lc_hash_ctx *hash_ctx)
Get the size of the message digest.
Definition lc_hash.h:231
static 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.
Definition lc_hash.h:211
static int lc_sponge(const struct lc_hash *hash, void *state, unsigned int rounds)
Perform Sponge permutation on buffer.
Definition lc_hash.h:390
static int lc_sponge_extract_bytes(const struct lc_hash *hash, const void *state, uint8_t *data, size_t offset, size_t length)
Function to retrieve data from the state. The bit positions that are retrieved by this function are f...
Definition lc_hash.h:459
int lc_hash_alloc(const struct lc_hash *hash, struct lc_hash_ctx **hash_ctx)
Allocate Hash context on heap.
void lc_hash(const struct lc_hash *hash, const uint8_t *in, size_t inlen, uint8_t *digest)
Calculate message digest - one-shot.
void lc_xof(const struct lc_hash *xof, const uint8_t *in, size_t inlen, uint8_t *digest, size_t digestlen)
Calculate message digest for an XOF - one-shot.
static unsigned int lc_hash_ctxsize(struct lc_hash_ctx *hash_ctx)
Get the context size of the message digest implementation.
Definition lc_hash.h:268
static unsigned int lc_hash_blocksize(struct lc_hash_ctx *hash_ctx)
Get the block size of the message digest (or the "rate" in terms of Sponge-based algorithms)
Definition lc_hash.h:250
static void lc_hash_zero(struct lc_hash_ctx *hash_ctx)
Zeroize Hash context allocated with either LC_HASH_CTX_ON_STACK or lc_hmac_alloc.
Definition lc_hash.h:286
static void lc_hash_final(struct lc_hash_ctx *hash_ctx, uint8_t *digest)
Calculate message digest.
Definition lc_hash.h:192
static void lc_hash_update(struct lc_hash_ctx *hash_ctx, const uint8_t *in, size_t inlen)
Update hash.
Definition lc_hash.h:150
void lc_hash_zero_free(struct lc_hash_ctx *hash_ctx)
Zeroize and free hash context.
static void lc_hash_init(struct lc_hash_ctx *hash_ctx)
Initialize hash context.
Definition lc_hash.h:130
static int lc_sponge_newstate(const struct lc_hash *hash, void *state, const uint8_t *data, size_t offset, size_t length)
Function to insert a complete new sponge state.
Definition lc_hash.h:488
static void lc_memset_secure(void *s, int c, size_t n)