cshake.c
Go to the documentation of this file.
1 /**
2  * @file cshake.c
3  * @brief cSHAKE128 and cSHAKE256 (customizable SHAKE function)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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  * cSHAKE is a customizable variant of the SHAKE function. Refer to
30  * NIST SP 800-185 for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.4
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "xof/cshake.h"
42 
43 //Check crypto library configuration
44 #if (CSHAKE_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Digest a message using cSHAKE128 or cSHAKE256
49  * @param[in] strength Number of bits of security (128 for cSHAKE128 and
50  * 256 for cSHAKE256)
51  * @param[in] input Pointer to the input data (X)
52  * @param[in] inputLen Length of the input data
53  * @param[in] name Function name (N)
54  * @param[in] nameLen Length of the function name
55  * @param[in] custom Customization string (S)
56  * @param[in] customLen Length of the customization string
57  * @param[out] output Pointer to the output data
58  * @param[in] outputLen Expected length of the output data (L)
59  * @return Error code
60  **/
61 
62 error_t cshakeCompute(uint_t strength, const void *input, size_t inputLen,
63  const char_t *name, size_t nameLen, const char_t *custom, size_t customLen,
64  uint8_t *output, size_t outputLen)
65 {
66  error_t error;
67 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
68  CshakeContext *context;
69 #else
70  CshakeContext context[1];
71 #endif
72 
73  //Check parameters
74  if(input == NULL && inputLen != 0)
76 
77  if(output == NULL && outputLen != 0)
79 
80 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
81  //Allocate a memory buffer to hold the cSHAKE context
82  context = cryptoAllocMem(sizeof(CshakeContext));
83  //Failed to allocate memory?
84  if(context == NULL)
85  return ERROR_OUT_OF_MEMORY;
86 #endif
87 
88  //Initialize the cSHAKE context
89  error = cshakeInit(context, strength, name, nameLen, custom, customLen);
90 
91  //Check status code
92  if(!error)
93  {
94  //Absorb input data
95  cshakeAbsorb(context, input, inputLen);
96  //Finish absorbing phase
97  cshakeFinal(context);
98  //Extract data from the squeezing phase
99  cshakeSqueeze(context, output, outputLen);
100  }
101 
102 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
103  //Free previously allocated memory
104  cryptoFreeMem(context);
105 #endif
106 
107  //Return status code
108  return error;
109 }
110 
111 
112 /**
113  * @brief Initialize cSHAKE context
114  * @param[in] context Pointer to the cSHAKE context to initialize
115  * @param[in] strength Number of bits of security (128 for cSHAKE128 and
116  * 256 for cSHAKE256)
117  * @param[in] name Function name (N)
118  * @param[in] nameLen Length of the function name
119  * @param[in] custom Customization string (S)
120  * @param[in] customLen Length of the customization string
121  * @return Error code
122  **/
123 
124 error_t cshakeInit(CshakeContext *context, uint_t strength, const char_t *name,
125  size_t nameLen, const char_t *custom, size_t customLen)
126 {
127  error_t error;
128  size_t i;
129  size_t n;
130  size_t rate;
131  uint8_t buffer[sizeof(size_t) + 1];
132 
133  //Make sure the cSHAKE context is valid
134  if(context == NULL)
136 
137  //cSHAKE128 and cSHAKE256 provides respectively 128 and 256 bits of security
138  if(strength != 128 && strength != 256)
140 
141  //The function name N is optional
142  if(name == NULL && nameLen != 0)
144 
145  //The customization string S is optional
146  if(custom == NULL && customLen != 0)
148 
149  //Save the length of N and S
150  context->nameLen = nameLen;
151  context->customLen = customLen;
152 
153  //Initialize Keccak context
154  error = keccakInit(&context->keccakContext, 2 * strength);
155  //Any error to report?
156  if(error)
157  return error;
158 
159  //The rate of the underlying Keccak sponge function is 168 for cSHAKE128
160  //and 136 for cSHAKE256
161  rate = context->keccakContext.blockSize;
162 
163  //When N and S are both empty strings, cSHAKE is equivalent to SHAKE
164  if(nameLen != 0 || customLen != 0)
165  {
166  //Absorb the string representation of the rate
167  cshakeLeftEncode(rate, buffer, &n);
168  cshakeAbsorb(context, buffer, n);
169  i = n;
170 
171  //Absorb the string representation of N
172  cshakeLeftEncode(nameLen * 8, buffer, &n);
173  cshakeAbsorb(context, buffer, n);
174  cshakeAbsorb(context, name, nameLen);
175  i += n + nameLen;
176 
177  //Absorb the string representation of S
178  cshakeLeftEncode(customLen * 8, buffer, &n);
179  cshakeAbsorb(context, buffer, n);
180  cshakeAbsorb(context, custom, customLen);
181  i += n + customLen;
182 
183  //The padding string consists of bytes set to zero
184  buffer[0] = 0;
185 
186  //Pad the result with zeros until it is a byte string whose length in
187  //bytes is a multiple of the rate
188  while((i % rate) != 0)
189  {
190  //Absorb the padding string
191  cshakeAbsorb(context, buffer, 1);
192  i++;
193  }
194  }
195 
196  //Successful initialization
197  return NO_ERROR;
198 }
199 
200 
201 /**
202  * @brief Absorb data
203  * @param[in] context Pointer to the cSHAKE context
204  * @param[in] input Pointer to the buffer being hashed
205  * @param[in] length Length of the buffer
206  **/
207 
208 void cshakeAbsorb(CshakeContext *context, const void *input, size_t length)
209 {
210  //Absorb the input data
211  keccakAbsorb(&context->keccakContext, input, length);
212 }
213 
214 
215 /**
216  * @brief Finish absorbing phase
217  * @param[in] context Pointer to the cSHAKE context
218  **/
219 
221 {
222  uint8_t pad;
223 
224  //When N and S are both empty strings, cSHAKE is equivalent to SHAKE
225  if(context->nameLen == 0 && context->customLen == 0)
226  {
227  //The padding byte is 0x1F for SHAKE
228  pad = KECCAK_SHAKE_PAD;
229  }
230  else
231  {
232  //The padding byte is 0x04 for cSHAKE
233  pad = KECCAK_CSHAKE_PAD;
234  }
235 
236  //Finish absorbing phase
237  keccakFinal(&context->keccakContext, pad);
238 }
239 
240 
241 /**
242  * @brief Extract data from the squeezing phase
243  * @param[in] context Pointer to the cSHAKE context
244  * @param[out] output Output string
245  * @param[in] length Desired output length, in bytes
246  **/
247 
248 void cshakeSqueeze(CshakeContext *context, uint8_t *output, size_t length)
249 {
250  //Extract data from the squeezing phase
251  keccakSqueeze(&context->keccakContext, output, length);
252 }
253 
254 
255 /**
256  * @brief Encode integer as byte string
257  * @param[in] value Value of the integer to be encoded
258  * @param[out] buffer Buffer where to store the byte string representation
259  * @param[out] length Length of the resulting byte string
260  **/
261 
262 void cshakeLeftEncode(size_t value, uint8_t *buffer, size_t *length)
263 {
264  size_t i;
265  size_t n;
266  size_t temp;
267 
268  //Get the value of the integer to be encoded
269  temp = value;
270 
271  //Let n be the smallest positive integer for which 2^(8*n) > x
272  for(n = 1; n < sizeof(size_t) && (temp >> 8) != 0; n++)
273  {
274  temp >>= 8;
275  }
276 
277  //Encode O(0)
278  buffer[0] = n;
279 
280  //Encode O(1) || ... || O(n)
281  for(i = 1; i <= n; i++)
282  {
283  buffer[i] = value >> ((n - i) * 8);
284  }
285 
286  //Return the length of the byte string representation
287  *length = n + 1;
288 }
289 
290 #endif
#define KECCAK_SHAKE_PAD
Definition: keccak.h:95
error_t cshakeInit(CshakeContext *context, uint_t strength, const char_t *name, size_t nameLen, const char_t *custom, size_t customLen)
Initialize cSHAKE context.
Definition: cshake.c:124
KeccakContext keccakContext
Definition: cshake.h:52
size_t customLen
Definition: cshake.h:51
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
char_t name[]
#define KECCAK_CSHAKE_PAD
Definition: keccak.h:97
void keccakFinal(KeccakContext *context, uint8_t pad)
Finish absorbing phase.
Definition: keccak.c:374
size_t nameLen
Definition: cshake.h:50
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
void cshakeFinal(CshakeContext *context)
Finish absorbing phase.
Definition: cshake.c:220
General definitions for cryptographic algorithms.
cSHAKE128 and cSHAKE256 (customizable SHAKE function)
uint8_t length
Definition: tcp.h:368
void cshakeAbsorb(CshakeContext *context, const void *input, size_t length)
Absorb data.
Definition: cshake.c:208
void cshakeLeftEncode(size_t value, uint8_t *buffer, size_t *length)
Encode integer as byte string.
Definition: cshake.c:262
void keccakSqueeze(KeccakContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: keccak.c:418
char char_t
Definition: compiler_port.h:48
void keccakAbsorb(KeccakContext *context, const void *input, size_t length)
Absorb data.
uint8_t n
uint_t blockSize
Definition: keccak.h:121
#define cryptoFreeMem(p)
Definition: crypto.h:791
uint8_t value[]
Definition: tcp.h:369
error_t cshakeCompute(uint_t strength, const void *input, size_t inputLen, const char_t *name, size_t nameLen, const char_t *custom, size_t customLen, uint8_t *output, size_t outputLen)
Digest a message using cSHAKE128 or cSHAKE256.
Definition: cshake.c:62
#define cryptoAllocMem(size)
Definition: crypto.h:786
error_t keccakInit(KeccakContext *context, uint_t capacity)
Initialize Keccak context.
Definition: keccak.c:285
unsigned int uint_t
Definition: compiler_port.h:50
cSHAKE algorithm context
Definition: cshake.h:49
@ NO_ERROR
Success.
Definition: error.h:44
void cshakeSqueeze(CshakeContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: cshake.c:248