shake.c
Go to the documentation of this file.
1 /**
2  * @file shake.c
3  * @brief SHAKE128 and SHAKE256 extendable-output functions
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * SHAKE is a function on binary data in which the output can be extended to any
30  * desired length. SHAKE128 supports 128 bits of security strength. SHAKE256
31  * supports 256 bits of security strength. Refer to FIPS 202 for more details
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 2.5.4
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
39 
40 //Dependencies
41 #include "core/crypto.h"
42 #include "xof/shake.h"
43 
44 //Check crypto library configuration
45 #if (SHAKE_SUPPORT == ENABLED)
46 
47 //SHAKE128 object identifier (2.16.840.1.101.3.4.2.11)
48 const uint8_t SHAKE128_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0B};
49 //SHAKE256 object identifier (2.16.840.1.101.3.4.2.12)
50 const uint8_t SHAKE256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0C};
51 
52 //Common interface for XOF algorithms (SHAKE128)
54 {
55  "SHAKE128",
57  sizeof(SHAKE128_OID),
58  sizeof(ShakeContext),
64 };
65 
66 //Common interface for XOF algorithms (SHAKE256)
68 {
69  "SHAKE256",
71  sizeof(SHAKE256_OID),
72  sizeof(ShakeContext),
78 };
79 
80 
81 /**
82  * @brief Digest a message using SHAKE128 or SHAKE256
83  * @param[in] strength Number of bits of security (128 for SHAKE128 and
84  * 256 for SHAKE256)
85  * @param[in] input Pointer to the input data
86  * @param[in] inputLen Length of the input data
87  * @param[out] output Pointer to the output data
88  * @param[in] outputLen Expected length of the output data
89  * @return Error code
90  **/
91 
92 error_t shakeCompute(uint_t strength, const void *input, size_t inputLen,
93  uint8_t *output, size_t outputLen)
94 {
95  error_t error;
96 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
97  ShakeContext *context;
98 #else
99  ShakeContext context[1];
100 #endif
101 
102  //Check parameters
103  if(input == NULL && inputLen != 0)
105 
106  if(output == NULL && outputLen != 0)
108 
109 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
110  //Allocate a memory buffer to hold the SHAKE context
111  context = cryptoAllocMem(sizeof(ShakeContext));
112  //Failed to allocate memory?
113  if(context == NULL)
114  return ERROR_OUT_OF_MEMORY;
115 #endif
116 
117  //Initialize the SHAKE context
118  error = shakeInit(context, strength);
119 
120  //Check status code
121  if(!error)
122  {
123  //Absorb input data
124  shakeAbsorb(context, input, inputLen);
125  //Finish absorbing phase
126  shakeFinal(context);
127  //Extract data from the squeezing phase
128  shakeSqueeze(context, output, outputLen);
129  }
130 
131 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
132  //Free previously allocated memory
133  cryptoFreeMem(context);
134 #endif
135 
136  //Return status code
137  return error;
138 }
139 
140 
141 /**
142  * @brief Digest a message using SHAKE128
143  * @param[in] input Pointer to the input data
144  * @param[in] inputLen Length of the input data
145  * @param[out] output Pointer to the output data
146  * @param[in] outputLen Expected length of the output data
147  * @return Error code
148  **/
149 
150 error_t shake128Compute(const void *input, size_t inputLen, uint8_t *output,
151  size_t outputLen)
152 {
153  //Digest the message using SHAKE128
154  return shakeCompute(128, input, inputLen, output, outputLen);
155 }
156 
157 
158 /**
159  * @brief Digest a message using SHAKE256
160  * @param[in] input Pointer to the input data
161  * @param[in] inputLen Length of the input data
162  * @param[out] output Pointer to the output data
163  * @param[in] outputLen Expected length of the output data
164  * @return Error code
165  **/
166 
167 error_t shake256Compute(const void *input, size_t inputLen, uint8_t *output,
168  size_t outputLen)
169 {
170  //Digest the message using SHAKE256
171  return shakeCompute(256, input, inputLen, output, outputLen);
172 }
173 
174 
175 /**
176  * @brief Initialize SHAKE context
177  * @param[in] context Pointer to the SHAKE context to initialize
178  * @param[in] strength Number of bits of security (128 for SHAKE128 and
179  * 256 for SHAKE256)
180  * @return Error code
181  **/
182 
184 {
185  error_t error;
186 
187  //SHAKE128 and SHAKE256 provides respectively 128 and 256 bits of security
188  if(strength == 128 || strength == 256)
189  {
190  //Initialize Keccak context
191  error = keccakInit(&context->keccakContext, 2 * strength);
192  }
193  else
194  {
195  //Report an error
196  error = ERROR_INVALID_PARAMETER;
197  }
198 
199  //Return status code
200  return error;
201 }
202 
203 
204 /**
205  * @brief Initialize SHAKE128 context
206  * @param[in] context Pointer to the SHAKE context to initialize
207  * @return Error code
208  **/
209 
211 {
212  //Initialize SHAKE128 context
213  return shakeInit(context, 128);
214 }
215 
216 
217 /**
218  * @brief Initialize SHAKE256 context
219  * @param[in] context Pointer to the SHAKE context to initialize
220  * @return Error code
221  **/
222 
224 {
225  //Initialize SHAKE256 context
226  return shakeInit(context, 256);
227 }
228 
229 
230 /**
231  * @brief Absorb data
232  * @param[in] context Pointer to the SHAKE context
233  * @param[in] input Pointer to the buffer being hashed
234  * @param[in] length Length of the buffer
235  **/
236 
237 void shakeAbsorb(ShakeContext *context, const void *input, size_t length)
238 {
239  //Absorb the input data
240  keccakAbsorb(&context->keccakContext, input, length);
241 }
242 
243 
244 /**
245  * @brief Finish absorbing phase
246  * @param[in] context Pointer to the SHAKE context
247  **/
248 
249 void shakeFinal(ShakeContext *context)
250 {
251  //Finish absorbing phase (padding byte is 0x1F for XOFs)
253 }
254 
255 
256 /**
257  * @brief Extract data from the squeezing phase
258  * @param[in] context Pointer to the SHAKE context
259  * @param[out] output Output string
260  * @param[in] length Desired output length, in bytes
261  **/
262 
263 void shakeSqueeze(ShakeContext *context, uint8_t *output, size_t length)
264 {
265  //Extract data from the squeezing phase
266  keccakSqueeze(&context->keccakContext, output, length);
267 }
268 
269 #endif
#define KECCAK_SHAKE_PAD
Definition: keccak.h:101
SHAKE128 and SHAKE256 extendable-output functions.
void(* XofAlgoAbsorb)(void *context, const void *input, size_t length)
Definition: crypto.h:1072
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void keccakFinal(KeccakContext *context, uint8_t pad)
Finish absorbing phase.
Definition: keccak.c:373
const XofAlgo shake256XofAlgo
Definition: shake.c:67
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
error_t shakeInit(ShakeContext *context, uint_t strength)
Initialize SHAKE context.
Definition: shake.c:183
const uint8_t SHAKE256_OID[9]
Definition: shake.c:50
void shakeAbsorb(ShakeContext *context, const void *input, size_t length)
Absorb data.
Definition: shake.c:237
General definitions for cryptographic algorithms.
void shakeSqueeze(ShakeContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: shake.c:263
SHAKE algorithm context.
Definition: shake.h:53
error_t shake256Init(ShakeContext *context)
Initialize SHAKE256 context.
Definition: shake.c:223
uint8_t length
Definition: tcp.h:375
KeccakContext keccakContext
Definition: shake.h:54
void keccakSqueeze(KeccakContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: keccak.c:417
const XofAlgo shake128XofAlgo
Definition: shake.c:53
error_t(* XofAlgoCompute)(const void *input, size_t inputLen, uint8_t *output, size_t outputLen)
Definition: crypto.h:1068
Common interface for XOF algorithms.
Definition: crypto.h:1146
void keccakAbsorb(KeccakContext *context, const void *input, size_t length)
Absorb data.
#define cryptoFreeMem(p)
Definition: crypto.h:861
error_t shake128Compute(const void *input, size_t inputLen, uint8_t *output, size_t outputLen)
Digest a message using SHAKE128.
Definition: shake.c:150
#define cryptoAllocMem(size)
Definition: crypto.h:856
void(* XofAlgoInit)(void *context)
Definition: crypto.h:1071
error_t keccakInit(KeccakContext *context, uint_t capacity)
Initialize Keccak context.
Definition: keccak.c:285
void shakeFinal(ShakeContext *context)
Finish absorbing phase.
Definition: shake.c:249
error_t shake256Compute(const void *input, size_t inputLen, uint8_t *output, size_t outputLen)
Digest a message using SHAKE256.
Definition: shake.c:167
void(* XofAlgoSqueeze)(void *context, uint8_t *output, size_t length)
Definition: crypto.h:1074
unsigned int uint_t
Definition: compiler_port.h:57
error_t shake128Init(ShakeContext *context)
Initialize SHAKE128 context.
Definition: shake.c:210
error_t shakeCompute(uint_t strength, const void *input, size_t inputLen, uint8_t *output, size_t outputLen)
Digest a message using SHAKE128 or SHAKE256.
Definition: shake.c:92
void(* XofAlgoFinal)(void *context)
Definition: crypto.h:1073
const uint8_t SHAKE128_OID[9]
Definition: shake.c:48