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