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