1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 /************* Include Files ****************/
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "cc_util_int_defs.h"
12 #include "cc_sym_error.h"
13 #include "cc_aes_defs.h"
14 #include "mbedtls_cc_util_defs.h"
15 #include "cc_util_error.h"
16 #include "mbedtls_cc_util_key_derivation.h"
17 #include "cc_hal_plat.h"
18 #include "cc_regs.h"
19 #include "cc_pal_mutex.h"
20 #include "cc_pal_abort.h"
21 #include "cc_util_cmac.h"
22 #include "cc_fips_defs.h"
23 #include "cc_hash_defs.h"
24 #include "cc_general_defs.h"
25 #include "mbedtls/md.h"
26 
mbedtls_util_key_derivation(mbedtls_util_keytype_t keyType,mbedtls_util_keydata * pUserKey,mbedtls_util_prftype_t prfType,CCHashOperationMode_t hashMode,const uint8_t * pLabel,size_t labelSize,const uint8_t * pContextData,size_t contextSize,uint8_t * pDerivedKey,size_t derivedKeySize)27 CCUtilError_t mbedtls_util_key_derivation( mbedtls_util_keytype_t             keyType,
28                       mbedtls_util_keydata             *pUserKey,
29                     mbedtls_util_prftype_t             prfType,
30                                     CCHashOperationMode_t       hashMode,
31                                     const uint8_t               *pLabel,
32                                     size_t                      labelSize,
33                                     const uint8_t               *pContextData,
34                                     size_t                      contextSize,
35                                     uint8_t                     *pDerivedKey,
36                                     size_t                      derivedKeySize)
37 {
38         uint32_t                rc = 0;
39         uint32_t                dataSize, i, iterationNum, numIteration, bytesToCopy;
40         uint8_t                 dataIn[CC_UTIL_MAX_KDF_SIZE_IN_BYTES] = {0};
41         uint8_t                 tmp[CC_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES];
42         CCHashResultBuf_t       hmacResultBuff;
43         size_t                  length, lengthReverse, prfUpperLimit;
44         UtilKeyType_t           utilKeyType;
45         uint8_t*                srcToCopy;
46         size_t origDerivedKeySize;
47 
48         const mbedtls_md_info_t *mdInfo = NULL;
49 
50         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
51 
52         /* Check input */
53         if(pDerivedKey == NULL)
54                 return CC_UTIL_ILLEGAL_PARAMS_ERROR;
55 
56         /* Check PRF type */
57         if ((CC_UTIL_PRF_CMAC != prfType) && (CC_UTIL_PRF_HMAC != prfType)) {
58                 return CC_UTIL_INVALID_PRF_TYPE;
59         }
60 
61         if ((CC_UTIL_PRF_HMAC == prfType) && (hashMode >= CC_HASH_MD5_mode)){
62                 return CC_UTIL_INVALID_HASH_MODE;
63         }
64         origDerivedKeySize = derivedKeySize;
65         /* Check key type */
66         switch (keyType) {
67         case CC_UTIL_ROOT_KEY:
68                 if (CC_UTIL_PRF_HMAC == prfType) {
69                         return CC_UTIL_INVALID_PRF_TYPE;
70                 }
71 
72                 utilKeyType = UTIL_ROOT_KEY;
73                 break;
74         case CC_UTIL_USER_KEY:
75                 if (!pUserKey) {
76                         return CC_UTIL_INVALID_KEY_TYPE;
77                 }
78                 if (!pUserKey->pKey) {
79                         return CC_UTIL_INVALID_KEY_TYPE;
80                 }
81 
82                 utilKeyType = UTIL_USER_KEY;
83                 break;
84         default:
85                 return CC_UTIL_INVALID_KEY_TYPE;
86         }
87 
88         /* Check Label, Context, DerivedKey sizes */
89         if (derivedKeySize > CC_UTIL_MAX_DERIVED_KEY_SIZE_IN_BYTES)
90                 return CC_UTIL_ILLEGAL_PARAMS_ERROR;
91 
92         if ( ((labelSize != 0) && (pLabel == NULL)) ||
93              (labelSize == 0) ||
94              (labelSize > CC_UTIL_MAX_LABEL_LENGTH_IN_BYTES) ) {
95                 return CC_UTIL_ILLEGAL_PARAMS_ERROR;
96         }
97 
98         if ( ((contextSize != 0) && (pContextData == NULL)) ||
99              (contextSize == 0) ||
100              (contextSize > CC_UTIL_MAX_CONTEXT_LENGTH_IN_BYTES) ) {
101                 return CC_UTIL_ILLEGAL_PARAMS_ERROR;
102         }
103 
104         /* Generate dataIn buffer for CMAC: iteration || Label || 0x00 || context || length */
105 
106         if(CC_UTIL_PRF_CMAC == prfType) {
107                 prfUpperLimit = CC_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES;
108         } else { /* CC_UTIL_PRF_HMAC */
109                 if (CC_TRUE == HmacSupportedHashModes_t[hashMode]) {
110             mdInfo = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
111             if( mdInfo == NULL ){
112                 return CC_UTIL_INVALID_HASH_MODE;
113             }
114                         prfUpperLimit = HmacHashInfo_t[hashMode].hashResultSize;
115                 } else {
116                         return CC_UTIL_UNSUPPORTED_HASH_MODE;
117                 }
118         }
119 
120         i = 1;
121         numIteration = (derivedKeySize + prfUpperLimit - 1) / prfUpperLimit;
122         length = derivedKeySize*8;
123         if (length > 0xFF){
124                 dataSize = CC_UTIL_FIX_DATA_MAX_SIZE_IN_BYTES;
125         } else {
126                 dataSize = CC_UTIL_FIX_DATA_MIN_SIZE_IN_BYTES;
127         }
128 
129         dataSize += labelSize+contextSize;
130 
131         if (labelSize!=0) {
132                 CC_PalMemCopy((uint8_t*)&dataIn[i], pLabel, labelSize);
133                 i+=labelSize;
134         }
135 
136         dataIn[i++] = 0x00;
137 
138         if (contextSize!=0) {
139                 CC_PalMemCopy((uint8_t*)&dataIn[i], pContextData, contextSize);
140                 i+=contextSize;
141         }
142 
143         if (length > 0xFF) {
144                 /* Reverse words order and bytes in each word */
145                 lengthReverse = ((length & 0xFF00)>>8) | ((length & 0xFF)<<8);
146                 CC_PalMemCopy((uint8_t*)&dataIn[i], (uint8_t*)&lengthReverse, 2);
147         } else {
148                 CC_PalMemCopy((uint8_t*)&dataIn[i], (uint8_t*)&length, 1);
149         }
150 
151         srcToCopy = ((CC_UTIL_PRF_CMAC == prfType) ? tmp : (uint8_t*)&hmacResultBuff);
152         for (iterationNum = 0; iterationNum < numIteration; iterationNum++) {
153                 dataIn[0] = iterationNum+1;
154                 if(CC_UTIL_PRF_CMAC == prfType) {
155                         rc = UtilCmacDeriveKey(utilKeyType, (CCAesUserKeyData_t*)pUserKey, dataIn, dataSize, tmp);
156                 }
157                 else { /* CC_UTIL_PRF_HMAC */
158             rc = mbedtls_md_hmac( mdInfo,
159                           pUserKey->pKey,
160                           pUserKey->keySize,
161                           dataIn,
162                           dataSize,
163                           (unsigned char*)hmacResultBuff );
164                 }
165 
166                 if (rc != CC_SUCCESS){
167                         return rc;
168                 }
169 
170                 /* concatenate the latest PRF result */
171                 /* copy only number of bits that required... */
172                 if (derivedKeySize > prfUpperLimit) {
173                         bytesToCopy = prfUpperLimit;
174                         derivedKeySize -= prfUpperLimit;
175                 } else{
176                     bytesToCopy = derivedKeySize;
177                 }
178 
179                 if(bytesToCopy<=(origDerivedKeySize-iterationNum*prfUpperLimit) /*to avoid memory corruption*/&&
180                         ( bytesToCopy<=CC_HASH_RESULT_SIZE_IN_WORDS*sizeof(uint32_t) ) /*to remove static analyzer warnings*/)
181                 {
182                     CC_PalMemCopy((uint8_t*)&pDerivedKey[iterationNum*prfUpperLimit], srcToCopy, bytesToCopy);
183                 }else{
184                     return CC_UTIL_DATA_OUT_SIZE_INVALID_ERROR;
185                 }
186         }
187 
188         return rc;
189 }
190 
191