parallel_hash_xof.c
Go to the documentation of this file.
1 /**
2  * @file parallel_hash_xof.c
3  * @brief ParallelHashXOF (ParallelHash with arbitrary-length output)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
24  * @version 2.6.6
25  **/
26 
27 //Switch to the appropriate trace level
28 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
29 
30 //Dependencies
31 #include "core/crypto.h"
32 #include "xof/parallel_hash_xof.h"
33 
34 //Check crypto library configuration
35 #if (PARALLEL_HASH_XOF_SUPPORT == ENABLED)
36 
37 
38 /**
39  * @brief Digest a message using ParallelHashXOF
40  * @param[in] strength Number of bits of security (128 for ParallelHashXOF128 and
41  * 256 for ParallelHashXOF256)
42  * @param[in] blockSize Block size in bytes for parallel hashing (B)
43  * @param[in] input Pointer to the input string (X)
44  * @param[in] inputLen Length of the input string
45  * @param[in] custom Customization string (S)
46  * @param[in] customLen Length of the customization string
47  * @param[out] output Pointer to the output data
48  * @param[in] outputLen Expected length of the output data (L)
49  * @return Error code
50  **/
51 
52 error_t parallelHashXofCompute(uint_t strength, size_t blockSize,
53  const void *input, size_t inputLen, const char_t *custom, size_t customLen,
54  uint8_t *output, size_t outputLen)
55 {
56  error_t error;
57 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
58  ParallelHashXofContext *context;
59 #else
60  ParallelHashXofContext context[1];
61 #endif
62 
63  //Check parameters
64  if(input == NULL && inputLen != 0)
66 
67  if(output == NULL && outputLen != 0)
69 
70 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
71  //Allocate a memory buffer to hold the ParallelHashXOF context
72  context = cryptoAllocMem(sizeof(ParallelHashXofContext));
73  //Failed to allocate memory?
74  if(context == NULL)
75  return ERROR_OUT_OF_MEMORY;
76 #endif
77 
78  //Initialize the ParallelHashXOF context
79  error = parallelHashXofInit(context, strength, blockSize, custom,
80  customLen);
81 
82  //Check status code
83  if(!error)
84  {
85  //Absorb the input string
86  parallelHashXofAbsorb(context, input, inputLen);
87  //Finish absorbing phase
88  parallelHashXofFinal(context);
89  //Extract data from the squeezing phase
90  parallelHashXofSqueeze(context, output, outputLen);
91  }
92 
93 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
94  //Free previously allocated memory
95  cryptoFreeMem(context);
96 #endif
97 
98  //Return status code
99  return error;
100 }
101 
102 
103 /**
104  * @brief Initialize ParallelHashXOF context
105  * @param[in] context Pointer to the ParallelHashXOF context to initialize
106  * @param[in] strength Number of bits of security (128 for ParallelHashXOF128 and
107  * 256 for ParallelHashXOF256)
108  * @param[in] blockSize Block size in bytes for parallel hashing (B)
109  * @param[in] custom Customization string (S)
110  * @param[in] customLen Length of the customization string
111  * @return Error code
112  **/
113 
115  size_t blockSize, const char_t *custom, size_t customLen)
116 {
117  error_t error;
118  size_t n;
119  uint8_t buffer[sizeof(size_t) + 1];
120 
121  //Make sure the ParallelHash context is valid
122  if(context == NULL)
124 
125  //Check block size
126  if(blockSize == 0)
128 
129  //Initialize parameters
130  context->strength = strength;
131  context->blockSize = blockSize;
132  context->blockPos = 0;
133  context->blockCount = 0;
134 
135  //The length of the hash values depends on the ParallelHashXOF variant
136  context->hLen = (strength == 128) ? 32 : 64;
137 
138  //Initialize the first cSHAKE instance
139  error = cshakeInit(&context->cshakeContext1, strength, "", 0, "", 0);
140 
141  //Check status code
142  if(!error)
143  {
144  //Initialize the second cSHAKE instance
145  error = cshakeInit(&context->cshakeContext2, strength, "ParallelHash",
146  12, custom, customLen);
147  }
148 
149  //Check status code
150  if(!error)
151  {
152  //Absorb the string representation of B
153  cshakeLeftEncode(blockSize, buffer, &n);
154  cshakeAbsorb(&context->cshakeContext2, buffer, n);
155  }
156 
157  //Return status code
158  return error;
159 }
160 
161 
162 /**
163  * @brief Absorb data
164  * @param[in] context Pointer to the ParallelHashXOF context
165  * @param[in] data Pointer to the input string
166  * @param[in] dataLen Length of the string
167  **/
168 
169 void parallelHashXofAbsorb(ParallelHashXofContext *context, const void *input,
170  size_t length)
171 {
172  size_t n;
173  uint8_t h[64];
174 
175  //Process the input string
176  while(length > 0)
177  {
178  //Limit the number of bytes to process at a time
179  n = MIN(context->blockSize - context->blockPos, length);
180 
181  //Absorb the input data
182  cshakeAbsorb(&context->cshakeContext1, input, n);
183  context->blockPos += n;
184 
185  //ParallelHash operates in a block-by-block fashion
186  if(context->blockPos == context->blockSize)
187  {
188  //Compute the hash value for each block separately
189  cshakeFinal(&context->cshakeContext1);
190  cshakeSqueeze(&context->cshakeContext1, h, context->hLen);
191 
192  //The resulting hash values are combined and passed to cSHAKE
193  cshakeAbsorb(&context->cshakeContext2, h, context->hLen);
194 
195  //Re-initialize the cSHAKE context
196  cshakeInit(&context->cshakeContext1, context->strength, "", 0, "", 0);
197 
198  //The block is empty
199  context->blockPos = 0;
200  //Increment the number of blocks
201  context->blockCount++;
202  }
203 
204  //Advance the data pointer
205  input = (uint8_t *) input + n;
206  //Remaining bytes to process
207  length -= n;
208  }
209 }
210 
211 
212 /**
213  * @brief Finish absorbing phase
214  * @param[in] context Pointer to the ParallelHashXOF context
215  **/
216 
218 {
219  size_t n;
220  uint8_t buffer[sizeof(size_t) + 1];
221 
222  //Absorb the string representation of n
223  cshakeRightEncode(context->blockCount, buffer, &n);
224  cshakeAbsorb(&context->cshakeContext2, buffer, n);
225 
226  //When used as a XOF, ParallelHash is computed by setting the encoded output
227  //length to 0
228  cshakeRightEncode(0, buffer, &n);
229  cshakeAbsorb(&context->cshakeContext2, buffer, n);
230 
231  //Finish absorbing phase
232  cshakeFinal(&context->cshakeContext2);
233 }
234 
235 
236 /**
237  * @brief Extract data from the squeezing phase
238  * @param[in] context Pointer to the ParallelHashXOF context
239  * @param[out] output Output string
240  * @param[in] length Desired output length, in bytes
241  **/
242 
243 void parallelHashXofSqueeze(ParallelHashXofContext *context, uint8_t *output,
244  size_t length)
245 {
246  //Extract data from the squeezing phase
247  cshakeSqueeze(&context->cshakeContext2, output, length);
248 }
249 
250 #endif
error_t parallelHashXofInit(ParallelHashXofContext *context, uint_t strength, size_t blockSize, const char_t *custom, size_t customLen)
Initialize ParallelHashXOF context.
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
void parallelHashXofAbsorb(ParallelHashXofContext *context, const void *input, size_t length)
Absorb data.
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void parallelHashXofFinal(ParallelHashXofContext *context)
Finish absorbing phase.
uint8_t h
Definition: ndp.h:302
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
CshakeContext cshakeContext1
error_t
Error codes.
Definition: error.h:43
void cshakeFinal(CshakeContext *context)
Finish absorbing phase.
Definition: cshake.c:220
General definitions for cryptographic algorithms.
ParallelHashXOF algorithm context.
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
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
char char_t
Definition: compiler_port.h:55
CshakeContext cshakeContext2
uint8_t n
#define cryptoFreeMem(p)
Definition: crypto.h:966
void parallelHashXofSqueeze(ParallelHashXofContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
#define cryptoAllocMem(size)
Definition: crypto.h:961
ParallelHashXOF (ParallelHash with arbitrary-length output)
void cshakeRightEncode(size_t value, uint8_t *buffer, size_t *length)
Encode integer as byte string.
Definition: cshake.c:298
unsigned int uint_t
Definition: compiler_port.h:57
error_t parallelHashXofCompute(uint_t strength, size_t blockSize, const void *input, size_t inputLen, const char_t *custom, size_t customLen, uint8_t *output, size_t outputLen)
Digest a message using ParallelHashXOF.
void cshakeSqueeze(CshakeContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: cshake.c:248