1 /**
2  * @file decaf/shake.h
3  * @copyright
4  *   Based on CC0 code by David Leon Gil, 2015 \n
5  *   Copyright (c) 2015 Cryptography Research, Inc.  \n
6  *   Released under the MIT License.  See LICENSE.txt for license information.
7  * @author Mike Hamburg
8  * @brief SHA-3-n and DECAF_SHAKE-n instances.
9  */
10 
11 #ifndef __DECAF_SHAKE_H__
12 #define __DECAF_SHAKE_H__
13 
14 #include <stdint.h>
15 #include <sys/types.h>
16 #include <stdlib.h> /* for NULL */
17 
18 #include <decaf/common.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #ifndef INTERNAL_SPONGE_STRUCT
25     /** Sponge container object for the various primitives. */
26     typedef struct decaf_keccak_sponge_s {
27         /** @cond internal */
28         uint64_t opaque[26];
29         /** @endcond */
30     } decaf_keccak_sponge_s;
31 
32     /** Convenience GMP-style one-element array version */
33     typedef struct decaf_keccak_sponge_s decaf_keccak_sponge_t[1];
34 
35     /** Parameters for sponge construction, distinguishing DECAF_SHA3 and
36      * DECAF_SHAKE instances.
37      */
38     struct decaf_kparams_s;
39 #endif
40 
41 /**
42  * @brief Initialize a sponge context object.
43  * @param [out] sponge The object to initialize.
44  * @param [in] params The sponge's parameter description.
45  */
46 void DECAF_API_VIS decaf_sha3_init (
47     decaf_keccak_sponge_t sponge,
48     const struct decaf_kparams_s *params
49 );
50 
51 /**
52  * @brief Absorb data into a DECAF_SHA3 or DECAF_SHAKE hash context.
53  * @param [inout] sponge The context.
54  * @param [in] in The input data.
55  * @param [in] len The input data's length in bytes.
56  * @return DECAF_FAILURE if the sponge has already been used for output.
57  * @return DECAF_SUCCESS otherwise.
58  */
59 decaf_error_t DECAF_API_VIS decaf_sha3_update (
60     struct decaf_keccak_sponge_s * __restrict__ sponge,
61     const uint8_t *in,
62     size_t len
63 );
64 
65 /**
66  * @brief Squeeze output data from a DECAF_SHA3 or DECAF_SHAKE hash context.
67  * This does not destroy or re-initialize the hash context, and
68  * decaf_sha3 output can be called more times.
69  *
70  * @param [inout] sponge The context.
71  * @param [out] out The output data.
72  * @param [in] len The requested output data length in bytes.
73  * @return DECAF_FAILURE if the sponge has exhausted its output capacity.
74  * @return DECAF_SUCCESS otherwise.
75  */
76 decaf_error_t DECAF_API_VIS decaf_sha3_output (
77     decaf_keccak_sponge_t sponge,
78     uint8_t * __restrict__ out,
79     size_t len
80 );
81 
82 /**
83  * @brief Squeeze output data from a DECAF_SHA3 or DECAF_SHAKE hash context.
84  * This re-initializes the context to its starting parameters.
85  *
86  * @param [inout] sponge The context.
87  * @param [out] out The output data.
88  * @param [in] len The requested output data length in bytes.
89  */
90 decaf_error_t DECAF_API_VIS decaf_sha3_final (
91     decaf_keccak_sponge_t sponge,
92     uint8_t * __restrict__ out,
93     size_t len
94 );
95 
96 /**
97  * @brief Reset the sponge to the empty string.
98  *
99  * @param [inout] sponge The context.
100  */
101 void DECAF_API_VIS decaf_sha3_reset (
102     decaf_keccak_sponge_t sponge
103 );
104 
105 /**
106  * @brief Return the default output length of the sponge construction,
107  * for the purpose of C++ default operators.
108  *
109  * Returns n/8 for DECAF_SHA3-n and 2n/8 for DECAF_SHAKE-n.
110  */
111 size_t DECAF_API_VIS decaf_sha3_default_output_bytes (
112     const decaf_keccak_sponge_t sponge /**< [inout] The context. */
113 );
114 
115 /**
116  * @brief Return the default output length of the sponge construction,
117  * for the purpose of C++ default operators.
118  *
119  * Returns n/8 for DECAF_SHA3-n and SIZE_MAX for DECAF_SHAKE-n.
120  */
121 size_t DECAF_API_VIS decaf_sha3_max_output_bytes (
122     const decaf_keccak_sponge_t sponge /**< [inout] The context. */
123 );
124 
125 /**
126  * @brief Destroy a DECAF_SHA3 or DECAF_SHAKE sponge context by overwriting it with 0.
127  * @param [out] sponge The context.
128  */
129 void DECAF_API_VIS decaf_sha3_destroy (
130     decaf_keccak_sponge_t sponge
131 );
132 
133 /**
134  * @brief Hash (in) to (out)
135  * @param [in] in The input data.
136  * @param [in] inlen The length of the input data.
137  * @param [out] out A buffer for the output data.
138  * @param [in] outlen The length of the output data.
139  * @param [in] params The parameters of the sponge hash.
140  */
141 decaf_error_t DECAF_API_VIS decaf_sha3_hash (
142     uint8_t *out,
143     size_t outlen,
144     const uint8_t *in,
145     size_t inlen,
146     const struct decaf_kparams_s *params
147 );
148 
149 /* FUTURE: expand/doxygenate individual DECAF_SHAKE/DECAF_SHA3 instances? */
150 
151 #if defined _MSC_VER
152 
153 /** @cond internal */
154 #define DECAF_DEC_SHAKE(n) \
155     extern const struct DECAF_API_VIS decaf_kparams_s DECAF_SHAKE##n##_params_s; \
156     typedef struct decaf_shake##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_shake##n##_ctx_t[1]; \
157     static inline void DECAF_NONNULL decaf_shake##n##_init(decaf_shake##n##_ctx_t sponge) { \
158         decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \
159     } \
160     static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \
161         decaf_sha3_init(sponge, &DECAF_SHAKE##n##_params_s); \
162     } \
163     static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \
164         return decaf_sha3_update(sponge->s, in, inlen); \
165     } \
166     static inline void  DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
167         decaf_sha3_output(sponge->s, out, outlen); \
168         decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \
169     } \
170     static inline void  DECAF_NONNULL decaf_shake##n##_output(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
171         decaf_sha3_output(sponge->s, out, outlen); \
172     } \
173     static inline void  DECAF_NONNULL decaf_shake##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \
174         decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHAKE##n##_params_s); \
175     } \
176     static inline void  DECAF_NONNULL decaf_shake##n##_destroy( decaf_shake##n##_ctx_t sponge ) { \
177         decaf_sha3_destroy(sponge->s); \
178     }
179 
180 #define DECAF_DEC_SHA3(n) \
181     extern const struct DECAF_API_VIS decaf_kparams_s DECAF_SHA3_##n##_params_s; \
182     typedef struct decaf_sha3_##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_sha3_##n##_ctx_t[1]; \
183     static inline void DECAF_NONNULL decaf_sha3_##n##_init(decaf_sha3_##n##_ctx_t sponge) { \
184         decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \
185     } \
186     static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \
187         decaf_sha3_init(sponge, &DECAF_SHA3_##n##_params_s); \
188     } \
189     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \
190         return decaf_sha3_update(sponge->s, in, inlen); \
191     } \
192     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
193         decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \
194         decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \
195         return ret; \
196     } \
197     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_output(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
198         return decaf_sha3_output(sponge->s, out, outlen); \
199     } \
200     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \
201         return decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHA3_##n##_params_s); \
202     } \
203     static inline void DECAF_NONNULL decaf_sha3_##n##_destroy(decaf_sha3_##n##_ctx_t sponge) { \
204         decaf_sha3_destroy(sponge->s); \
205     }
206 /** @endcond */
207 
208 #else // _MSC_VER
209 
210 /** @cond internal */
211 #define DECAF_DEC_SHAKE(n) \
212     DECAF_API_VIS extern const struct decaf_kparams_s DECAF_SHAKE##n##_params_s; \
213     typedef struct decaf_shake##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_shake##n##_ctx_t[1]; \
214     static inline void DECAF_NONNULL decaf_shake##n##_init(decaf_shake##n##_ctx_t sponge) { \
215         decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \
216     } \
217     static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \
218         decaf_sha3_init(sponge, &DECAF_SHAKE##n##_params_s); \
219     } \
220     static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \
221         return decaf_sha3_update(sponge->s, in, inlen); \
222     } \
223     static inline void  DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
224         decaf_sha3_output(sponge->s, out, outlen); \
225         decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \
226     } \
227     static inline void  DECAF_NONNULL decaf_shake##n##_output(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
228         decaf_sha3_output(sponge->s, out, outlen); \
229     } \
230     static inline void  DECAF_NONNULL decaf_shake##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \
231         decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHAKE##n##_params_s); \
232     } \
233     static inline void  DECAF_NONNULL decaf_shake##n##_destroy( decaf_shake##n##_ctx_t sponge ) { \
234         decaf_sha3_destroy(sponge->s); \
235     }
236 
237 #define DECAF_DEC_SHA3(n) \
238     DECAF_API_VIS extern const struct decaf_kparams_s DECAF_SHA3_##n##_params_s; \
239     typedef struct decaf_sha3_##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_sha3_##n##_ctx_t[1]; \
240     static inline void DECAF_NONNULL decaf_sha3_##n##_init(decaf_sha3_##n##_ctx_t sponge) { \
241         decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \
242     } \
243     static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \
244         decaf_sha3_init(sponge, &DECAF_SHA3_##n##_params_s); \
245     } \
246     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \
247         return decaf_sha3_update(sponge->s, in, inlen); \
248     } \
249     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
250         decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \
251         decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \
252         return ret; \
253     } \
254     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_output(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \
255         return decaf_sha3_output(sponge->s, out, outlen); \
256     } \
257     static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \
258         return decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHA3_##n##_params_s); \
259     } \
260     static inline void DECAF_NONNULL decaf_sha3_##n##_destroy(decaf_sha3_##n##_ctx_t sponge) { \
261         decaf_sha3_destroy(sponge->s); \
262     }
263 /** @endcond */
264 
265 #endif // _MSC_VER
266 
267 
268 
269 DECAF_DEC_SHAKE(128)
270 DECAF_DEC_SHAKE(256)
271 DECAF_DEC_SHA3(224)
272 DECAF_DEC_SHA3(256)
273 DECAF_DEC_SHA3(384)
274 DECAF_DEC_SHA3(512)
275 #undef DECAF_DEC_SHAKE
276 #undef DECAF_DEC_SHA3
277 
278 #ifdef __cplusplus
279 } /* extern "C" */
280 #endif
281 
282 #endif /* __DECAF_SHAKE_H__ */
283