1 /*
2 * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /************* Include Files ****************/
8
9 #include "cc_pal_mem.h"
10 #include "cc_common_math.h"
11 #include "cc_kdf.h"
12 #include "cc_kdf_error.h"
13 #include "cc_fips_defs.h"
14 #include "cc_general_defs.h"
15 #ifdef USE_MBEDTLS_CRYPTOCELL
16 #include "mbedtls/md.h"
17 #else
18 #include "cc_hash.h"
19 #endif
20 #include "cc_hash_defs.h"
21
22 /************************ Defines *******************************/
23
24 /************************ Enums *********************************/
25
26 /************************ macros ********************************/
27
28
29 /************************ Global Data ******************************/
30
31 /************************ Private Functions ******************************/
32
33 /************************************************************************
34 * The function performs Hash update for data with the size not
35 * aligned to Hash block.
36 *
37 * Note: remBuffSize_ptr - a pointer to the remaining size of the
38 * temp buffer to fill by the data.
39 *
40 ************************************************************************/
41
42 /**
43 * The function performs Hash update for data with the size not
44 * aligned to Hash block.
45 *
46 * Note: remBuffSize_ptr - a pointer to the remaining size of the
47 * temp buffer to fill by the data.
48 *
49 * @author reuvenl (4/3/2013)
50 *
51 * @param hashContext_ptr - HASH context pointer
52 * @param data_ptr - input data pointer
53 * @param dataSize - input data size in bytes
54 * @param buff_ptr - buffer for remaining data accumulation
55 * @param remBuffSize_ptr - size of data on the buffer
56 * @param blockSizeBytes - size of HASH input block in bytes according to mode.
57 *
58 * @return CCError_t
59 */
KdfHashUnalignUpdate(mbedtls_md_context_t * p_hash_ctx,uint8_t * data_ptr,uint32_t dataSize,uint8_t * buff_ptr,uint32_t * remBuffSize_ptr,uint32_t blockSizeBytes)60 static CCError_t KdfHashUnalignUpdate(
61 #ifdef USE_MBEDTLS_CRYPTOCELL
62 mbedtls_md_context_t *p_hash_ctx,
63 #else
64 CCHashUserContext_t *hashContext_ptr,
65 #endif
66 uint8_t *data_ptr, uint32_t dataSize,
67 uint8_t *buff_ptr, uint32_t *remBuffSize_ptr,
68 uint32_t blockSizeBytes)
69 {
70 CCError_t error = CC_OK;
71 uint32_t tmpSize;
72 uint8_t *tmp_ptr;
73
74 /* set buff_ptr to begin of empty part of temp buffer */
75 tmp_ptr = buff_ptr + *remBuffSize_ptr;
76
77 /* if the temp buffer not empty, append it by the data and update Hash on it */
78 if (dataSize >= blockSizeBytes - *remBuffSize_ptr) {
79
80 CC_PalMemCopy(tmp_ptr, data_ptr, blockSizeBytes - *remBuffSize_ptr);
81
82 /* update on the data in temp buffer */
83 #ifdef USE_MBEDTLS_CRYPTOCELL
84 error = mbedtls_md_update(p_hash_ctx, buff_ptr, blockSizeBytes);
85 #else
86 error = CC_HashUpdate( hashContext_ptr, buff_ptr, blockSizeBytes);
87 #endif
88 if (error != CC_OK)
89 return error;
90
91 /* update pointers and sizes */
92 data_ptr += blockSizeBytes - *remBuffSize_ptr;
93 dataSize -= blockSizeBytes - *remBuffSize_ptr;
94 *remBuffSize_ptr = 0;
95 tmp_ptr = buff_ptr;
96 } else {
97 CC_PalMemCopy(tmp_ptr, data_ptr, dataSize);
98 *remBuffSize_ptr += dataSize;
99 return error;
100 }
101
102 /* Update Hash on remaining input data */
103 tmpSize = dataSize % blockSizeBytes;
104 if (tmpSize > 0) {
105 dataSize -= tmpSize;
106 CC_PalMemCopy(tmp_ptr, data_ptr + dataSize, tmpSize);
107 *remBuffSize_ptr += tmpSize;
108 }
109
110 if (dataSize > 0){
111 #ifdef USE_MBEDTLS_CRYPTOCELL
112 error = mbedtls_md_update(p_hash_ctx, data_ptr, dataSize);
113 #else
114 error = CC_HashUpdate( hashContext_ptr, data_ptr, dataSize);
115 #endif
116 }
117
118 return error;
119 }
120
121
122 /**
123 * The function returns CC_HASH defined parameters according to given
124 * KDF Hash mode
125 *
126 */
KdfGetHashParameters(CCKdfHashOpMode_t kdfhashMode,CCHashOperationMode_t * pHashMode,uint32_t * pHashBlockSize,uint32_t * pHashDigestSize)127 static CCError_t KdfGetHashParameters(
128 CCKdfHashOpMode_t kdfhashMode,
129 CCHashOperationMode_t *pHashMode,
130 uint32_t *pHashBlockSize,
131 uint32_t *pHashDigestSize)
132 {
133 switch (kdfhashMode) {
134 case CC_KDF_HASH_SHA1_mode:
135 *pHashMode = CC_HASH_SHA1_mode;
136 *pHashDigestSize = CC_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
137 *pHashBlockSize = CC_HASH_BLOCK_SIZE_IN_BYTES;
138 break;
139 case CC_KDF_HASH_SHA224_mode:
140 *pHashMode = CC_HASH_SHA224_mode;
141 *pHashDigestSize = CC_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
142 *pHashBlockSize = CC_HASH_BLOCK_SIZE_IN_BYTES;
143 break;
144 case CC_KDF_HASH_SHA256_mode:
145 *pHashMode = CC_HASH_SHA256_mode;
146 *pHashDigestSize = CC_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
147 *pHashBlockSize = CC_HASH_BLOCK_SIZE_IN_BYTES;
148 break;
149
150 case CC_KDF_HASH_SHA384_mode:
151 *pHashMode = CC_HASH_SHA384_mode;
152 *pHashDigestSize = CC_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
153 *pHashBlockSize = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
154 break;
155 case CC_KDF_HASH_SHA512_mode:
156 *pHashMode = CC_HASH_SHA512_mode;
157 *pHashDigestSize = CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
158 *pHashBlockSize = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
159 break;
160
161 default:
162 return CC_KDF_INVALID_ARGUMENT_HASH_MODE_ERROR;
163 }
164
165 return CC_OK;
166 }
167
168
169 /************************ Public Functions ******************************/
170
171 /************************ Public Functions ******************************/
172
173
174 /****************************************************************/
175
176
177 /****************************************************************/
178 /*!
179 @brief CC_KdfKeyDerivFunc performs key derivation according to one of the modes defined in standards:
180 ANS X9.42-2001, ANS X9.63, ISO/IEC 18033-2.
181
182 The present implementation of the function allows the following operation modes:
183 <ul><li> CC_KDF_ASN1_DerivMode - mode based on ASN.1 DER encoding; </li>
184 <li> CC_KDF_ConcatDerivMode - mode based on concatenation;</li>
185 <li> CC_KDF_X963_DerivMode = CC_KDF_ConcatDerivMode;</li>
186 <li> CC_KDF_ISO18033_KDF1_DerivMode, CC_KDF_ISO18033_KDF2_DerivMode - specific modes according to
187 ISO/IEC 18033-2 standard.</li></ul>
188
189 The purpose of this function is to derive a keying data from the shared secret value and some
190 other optional shared information, included in OtherInfo (SharedInfo).
191
192 \note All buffers arguments are represented in Big-Endian format.
193
194 @return CC_OK on success.
195 @return A non-zero value on failure as defined cc_kdf_error.h.
196 */
CC_KdfKeyDerivFunc(uint8_t * pZzSecret,size_t zzSecretSize,CCKdfOtherInfo_t * pOtherInfo,CCKdfHashOpMode_t kdfHashMode,CCKdfDerivFuncMode_t derivMode,uint8_t * pKeyingData,size_t keyingDataSize)197 CCError_t CC_KdfKeyDerivFunc(
198 uint8_t *pZzSecret, /*!< [in] A pointer to shared secret value octet string. */
199 size_t zzSecretSize, /*!< [in] The size of the shared secret value in bytes.
200 The maximal size is defined as: ::CC_KDF_MAX_SIZE_OF_SHARED_SECRET_VALUE. */
201 CCKdfOtherInfo_t *pOtherInfo, /*!< [in] A pointer to the structure, containing pointers to the data, shared by
202 two entities of agreement, depending on KDF mode:
203 1. On KDF ASN1 mode OtherInfo includes ASN1 DER encoding of AlgorithmID (mandatory),
204 and some optional data entries as described in part 7.7.1 of the X9.42 standard;
205 2. On both ISO18033-2 KDF1, KDF2 modes this parameter is ignored and may be set to NULL;
206 3. On other modes it is optional and may be set to NULL. */
207 CCKdfHashOpMode_t kdfHashMode, /*!< [in] The KDF identifier of hash function to be used. The hash function output
208 must be at least 160 bits. */
209 CCKdfDerivFuncMode_t derivMode, /*!< [in] The enum value, specifies one of above described derivation modes. */
210 uint8_t *pKeyingData, /*!< [out] A pointer to the buffer for derived keying data. */
211 size_t keyingDataSize /*!< [in] The size in bytes of the keying data to be derived.
212 The maximal size is defined as :: CC_KDF_MAX_SIZE_OF_KEYING_DATA. */
213 )
214
215 {
216
217 /* FUNCTION DECLARATIONS */
218
219 /* The return error identifier */
220 CCError_t error = CC_OK;
221 /* HASH function context structure buffer and parameters */
222 CCHashOperationMode_t hashMode;
223 uint32_t hashOutputSize;
224
225 /*The result buffer for the Hash*/
226 CCHashResultBuf_t hashResultBuff;
227 /* Total count of full HASH blockss for deriving the keying data */
228 uint32_t countOfHashBlocks;
229
230 /* Loop counters */
231 uint32_t i, j;
232 /*counter of Hash blocks (to be hashed with ZZ and OtherInfo) */
233 uint32_t counter;
234 /* Current output buffer position */
235 uint32_t currentOutputBuffPos = 0;
236
237 uint8_t *pTemp;
238 uint32_t remBuffSize, hashBlockSize;
239 uint32_t kdfHashTempBuff[CC_HASH_SHA512_BLOCK_SIZE_IN_WORDS];
240 CCKdfOtherInfoEntries_t fromKdfMode;
241
242 #ifdef USE_MBEDTLS_CRYPTOCELL
243 const mbedtls_md_info_t *md_info=NULL;
244 mbedtls_md_context_t hash_ctx;
245 #else
246 CCHashUserContext_t hashContext;
247 #endif
248
249 CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
250
251 if (pZzSecret == NULL || pKeyingData == NULL) {
252 return CC_KDF_INVALID_ARGUMENT_POINTER_ERROR;
253 }
254
255 if (derivMode >= CC_KDF_DerivFunc_NumOfModes) {
256 return CC_KDF_INVALID_KEY_DERIVATION_MODE_ERROR;
257 }
258
259 if (derivMode == CC_KDF_ASN1_DerivMode &&
260 (pOtherInfo == NULL || pOtherInfo->dataPointers[CC_KDF_ALGORITHM_ID] == 0)) {
261 return CC_KDF_INVALID_ARGUMENT_POINTER_ERROR;
262 }
263
264 /*On KDF1 and KDF2 derivation modes set OtherInfo_ptr = NULL */
265 if (derivMode == CC_KDF_ISO18033_KDF1_DerivMode ||
266 derivMode == CC_KDF_ISO18033_KDF2_DerivMode) {
267 pOtherInfo = NULL;
268 }
269
270 /* Check sizes of the input data to be hashed according to KDF *
271 * limitations */
272 if (zzSecretSize == 0 || zzSecretSize > CC_KDF_MAX_SIZE_OF_SHARED_SECRET_VALUE) {
273 return CC_KDF_INVALID_SHARED_SECRET_VALUE_SIZE_ERROR;
274 }
275
276 /* Check the size of keying data output. Note: because max size is
277 limited in our implementation by CC_KDF_MAX_SIZE_OF_KEYING_DATA
278 bytes */
279 if (keyingDataSize == 0 || keyingDataSize > CC_KDF_MAX_SIZE_OF_KEYING_DATA) {
280 return CC_KDF_INVALID_KEYING_DATA_SIZE_ERROR;
281 }
282
283
284 /* Get HASH parameters according to current operation modes */
285 /*----------------------------------------------------------*/
286 error = KdfGetHashParameters(
287 kdfHashMode,
288 &hashMode,
289 &hashBlockSize,
290 &hashOutputSize);
291 if (error != CC_OK)
292 goto End;
293
294
295 /* Count of HASH blocks and temp buffer pointer and size */
296 countOfHashBlocks = ( keyingDataSize + hashOutputSize - 1 )/ hashOutputSize;
297 pTemp = (uint8_t*)&kdfHashTempBuff[0];
298
299 #ifdef USE_MBEDTLS_CRYPTOCELL
300 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
301 if (NULL == md_info)
302 {
303 error = CC_KDF_INVALID_ARGUMENT_POINTER_ERROR;
304 goto End;
305 }
306 mbedtls_md_init(&hash_ctx);
307 error = mbedtls_md_setup(&hash_ctx, md_info, 0); // 0 = HASH, not HMAC
308 if (error != 0)
309 {
310 goto End;
311 }
312 #endif
313
314 /* ********** Keying data derivation loop ************ */
315
316 for (i = 0; i < countOfHashBlocks; i++) {
317 remBuffSize = 0;
318
319 /*.... HASH Init function .....*/
320 #ifdef USE_MBEDTLS_CRYPTOCELL
321 error = mbedtls_md_starts(&hash_ctx);
322 #else
323 error = CC_HashInit(&hashContext, hashMode);
324 #endif
325 if (error != CC_OK)
326 goto End;
327
328 /*....... Hashing input data by calling HASH_Update function .......*/
329 /*------------------------------------------------------------------*/
330
331 /*.... Hashing of the shared secret value ....*/
332 #ifdef USE_MBEDTLS_CRYPTOCELL
333 error = KdfHashUnalignUpdate(&hash_ctx,
334 pZzSecret,zzSecretSize,
335 pTemp, &remBuffSize, hashBlockSize);
336 #else
337 error = KdfHashUnalignUpdate(&hashContext,
338 pZzSecret,zzSecretSize,
339 pTemp, &remBuffSize, hashBlockSize);
340 #endif
341 if (error != CC_OK)
342 goto End;
343
344 /*.... Hashing of the AlgorithmID (on ASN1 Derivation Mode only) ....*/
345 if (derivMode == CC_KDF_ASN1_DerivMode) {
346 #ifdef USE_MBEDTLS_CRYPTOCELL
347 error = KdfHashUnalignUpdate(&hash_ctx,
348 pOtherInfo->dataPointers[CC_KDF_ALGORITHM_ID],
349 pOtherInfo->dataSizes[CC_KDF_ALGORITHM_ID],
350 pTemp, &remBuffSize, hashBlockSize);
351 #else
352 error = KdfHashUnalignUpdate(&hashContext,
353 pOtherInfo->dataPointers[CC_KDF_ALGORITHM_ID],
354 pOtherInfo->dataSizes[CC_KDF_ALGORITHM_ID],
355 pTemp, &remBuffSize, hashBlockSize);
356 #endif
357 if (error != CC_OK)
358 goto End;
359
360 fromKdfMode = CC_KDF_PARTY_U_INFO;
361 } else {
362 fromKdfMode = CC_KDF_ALGORITHM_ID;
363 }
364
365 /* Set the blocks counter in big endianness mode */
366 if (derivMode == CC_KDF_ISO18033_KDF1_DerivMode)
367 counter = i;
368 else
369 counter = i+1;
370
371 #ifndef BIG__ENDIAN
372 counter = CC_COMMON_REVERSE32(counter);
373 #endif
374
375 /*.... Hashing of the blocks counter ....*/
376 #ifdef USE_MBEDTLS_CRYPTOCELL
377 error = KdfHashUnalignUpdate(&hash_ctx,
378 (uint8_t *)&counter,
379 sizeof(uint32_t),
380 pTemp, &remBuffSize,
381 hashBlockSize);
382 #else
383 error = KdfHashUnalignUpdate(&hashContext,
384 (uint8_t *)&counter,
385 sizeof(uint32_t),
386 pTemp, &remBuffSize,
387 hashBlockSize);
388 #endif
389 if (error != CC_OK)
390 goto End;
391
392 /* ..... Hashing of remaining data of the OtherInfo ..... */
393 if (pOtherInfo != NULL) {
394
395 /* OtherInfo data concatenating and hashing loop */
396 for (j = fromKdfMode; j < CC_KDF_MAX_COUNT_OF_ENTRIES; j++) {
397 /* if entry exists then hash it */
398 if (pOtherInfo->dataPointers[j] != NULL && pOtherInfo->dataSizes[j] != 0) {
399 #ifdef USE_MBEDTLS_CRYPTOCELL
400 error = KdfHashUnalignUpdate(
401 &hash_ctx,
402 pOtherInfo->dataPointers[j]/*pointer to entry data*/,
403 pOtherInfo->dataSizes[j]/*size of entry data*/,
404 pTemp, &remBuffSize, hashBlockSize);
405 #else
406 error = KdfHashUnalignUpdate(
407 &hashContext,
408 pOtherInfo->dataPointers[j]/*pointer to entry data*/,
409 pOtherInfo->dataSizes[j]/*size of entry data*/,
410 pTemp, &remBuffSize, hashBlockSize);
411 #endif
412 if (error != CC_OK)
413 goto End;
414 }
415 }
416 }
417
418 /* last Hash update on remaining data in the temp buffer */
419 if (remBuffSize > 0) {
420 #ifdef USE_MBEDTLS_CRYPTOCELL
421 error = mbedtls_md_update(&hash_ctx, pTemp, remBuffSize);
422 #else
423 error = CC_HashUpdate(&hashContext, pTemp, remBuffSize);
424 #endif
425 if (error != CC_OK)
426 goto End;
427 }
428
429 /* .......... HASH Finish operation ............. */
430 #ifdef USE_MBEDTLS_CRYPTOCELL
431 error = mbedtls_md_finish(&hash_ctx, (unsigned char *)hashResultBuff);
432 #else
433 error = CC_HashFinish(&hashContext, hashResultBuff);
434 #endif
435 if (error != CC_OK)
436 goto End;
437
438 /* Correction of output data size for last block ( if it is not full ) */
439 if (i == (countOfHashBlocks - 1)){
440 hashOutputSize = keyingDataSize - i * hashOutputSize;
441
442 }
443 /* Copying HASH data into output buffer */
444 CC_PalMemCopy(&pKeyingData[currentOutputBuffPos],(uint8_t *)hashResultBuff, hashOutputSize);
445
446 /* Increment the output buffer position */
447 currentOutputBuffPos += hashOutputSize;
448 }
449
450 End:
451 #ifdef USE_MBEDTLS_CRYPTOCELL
452 if(md_info!=NULL){
453 mbedtls_md_free(&hash_ctx);
454 }
455 #endif
456 /* clean temp buffers */
457 CC_PalMemSetZero(&hashResultBuff, sizeof(CCHashResultBuf_t));
458 CC_PalMemSetZero(&kdfHashTempBuff, sizeof(kdfHashTempBuff));
459 #ifdef USE_MBEDTLS_CRYPTOCELL
460 CC_PalMemSetZero(&hash_ctx, sizeof(hash_ctx));
461 #else
462 CC_PalMemSetZero(&hashContext, sizeof(hashContext));
463 #endif
464
465 return error;
466
467 }/* END OF CC_KdfKeyDerivFunc */
468
469
470