1 /*
2  * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 /************* Include Files ****************/
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include "cc_pal_log.h"
13 #include "cc_prod_error.h"
14 #include "prod_hw_defs.h"
15 #include "cc_regs.h"
16 #include "dx_host.h"
17 #include "dx_crys_kernel.h"
18 #include "prod_crypto_driver.h"
19 #include "cc_pal_mem.h"
20 #include "aes_driver.h"
21 #include "driver_defs.h"
22 #include "cc_production_asset.h"
23 #include "cc_aes_defs.h"
24 #include "mbedtls/ccm.h"
25 
26 /**
27  * This function is used to perform AES  operation.
28  *
29  * @param[in] pInternalKey  - a pointer to internal key
30  * @param[in] pDataIn       - a pointer to input buffer - address must be 32bit aligned
31  * @param[in] dataInSize    - size of data in bytes
32  * @param[in] pOutbuff      - a pointer to output buffer- address must be 32bit aligned
33  * @param[in] outbuffSize   - size of data out bytes
34  *
35  */
36 
CC_PROD_AesCcmDecrypt(uint8_t * pKey,uint32_t keySizeInBytes,uint8_t * pNonce,uint32_t nonceSizeInBytes,uint8_t * pAddData,uint32_t addDataSizeInBytes,uint8_t * pCipherData,uint32_t dataSize,uint8_t * pPlainBuff,uint32_t tagSize,uint8_t * pTagBuff,unsigned long workspaceAddr,uint32_t workspaceSize)37 uint32_t CC_PROD_AesCcmDecrypt(uint8_t *pKey,
38                                uint32_t  keySizeInBytes,
39                                uint8_t *pNonce,
40                                uint32_t  nonceSizeInBytes,
41                                uint8_t *pAddData,
42                                uint32_t  addDataSizeInBytes,
43                                uint8_t *pCipherData,
44                                uint32_t  dataSize,
45                                uint8_t *pPlainBuff,
46                                uint32_t  tagSize,
47                                uint8_t *pTagBuff,
48                                unsigned long workspaceAddr,
49                             uint32_t     workspaceSize)
50 {
51 
52         uint32_t rc = 0;
53         mbedtls_ccm_context *pCtx;
54 
55         if (workspaceSize < sizeof(mbedtls_ccm_context) || (workspaceAddr % CC_32BIT_WORD_SIZE)) {
56                 CC_PAL_LOG_ERR("invalid workspace\n");
57                 return CC_PROD_INVALID_PARAM_ERR;
58         }
59         pCtx = (mbedtls_ccm_context *)workspaceAddr;
60 
61         mbedtls_ccm_init(pCtx);
62 
63         rc = mbedtls_ccm_setkey(pCtx, MBEDTLS_CIPHER_ID_AES, pKey, keySizeInBytes * CC_BITS_IN_BYTE);
64         if (rc != 0) {
65                 CC_PAL_LOG_ERR("Failed to mbedtls_ccm_setkey 0x%x\n", rc);
66                 return rc;
67         }
68 
69         rc = mbedtls_ccm_auth_decrypt(pCtx, dataSize,
70                                       pNonce, nonceSizeInBytes,
71                                       pAddData, addDataSizeInBytes,
72                                       pCipherData, pPlainBuff,
73                                       pTagBuff, tagSize);
74         if (rc != 0) {
75                 CC_PAL_LOG_ERR("Failed to mbedtls_ccm_auth_decrypt 0x%x\n", rc);
76         }
77 
78         return rc;
79 }
80 
81 
82 /**
83  * This function is used to perform AES  operation.
84  *
85  * @param[in] pInternalKey  - a pointer to internal key
86  * @param[in] pDataIn       - a pointer to input buffer - address must be 32bit aligned
87  * @param[in] dataInSize    - size of data in bytes
88  * @param[in] pOutbuff      - a pointer to output buffer- address must be 32bit aligned
89  * @param[in] outbuffSize   - size of data out bytes
90  *
91  */
CC_PROD_Aes(aesMode_t cipherMode,cryptoDirection_t encDecDir,cryptoKeyType_t keyType,uint8_t * pKey,uint32_t keySizeInBytes,uint8_t * pIv,uint32_t ivSizeInBytes,uint32_t * pDataIn,uint32_t dataInSize,uint32_t * pOutbuff)92 uint32_t CC_PROD_Aes(aesMode_t cipherMode,
93                      cryptoDirection_t encDecDir,
94                      cryptoKeyType_t keyType,
95                      uint8_t *pKey,
96                      uint32_t  keySizeInBytes,
97                      uint8_t *pIv,
98                      uint32_t  ivSizeInBytes,
99                      uint32_t *pDataIn,
100                      uint32_t  dataInSize,
101                      uint32_t *pOutbuff)
102 {
103         uint32_t error;
104         AesContext_t aesCtx;
105 
106         error = CC_PROD_AesInit(&aesCtx,
107                                 cipherMode,
108                                 encDecDir,
109                                 keyType, pKey, keySizeInBytes,
110                                 pIv, ivSizeInBytes);
111         if (error != CC_OK) {
112                 return error;
113         }
114         error = CC_PROD_AesProcess(&aesCtx,
115                                    pDataIn,  dataInSize,
116                                    pOutbuff);
117         if (error != CC_OK) {
118                 return error;
119         }
120         if ((cipherMode == CIPHER_CBC_MAC) && (pOutbuff != NULL)){
121             CC_PalMemCopy((uint8_t *)pOutbuff, (uint8_t *)aesCtx.ivBuf, CC_AES_BLOCK_SIZE_IN_BYTES);
122         }
123         return CC_OK;
124 }
125 
126 /**
127  * This function is used to perform AES CBC MAC operation.
128  *
129  * @param[in] pKey  - a pointer to internal key
130  * @param[in] pDataIn       - a pointer to input buffer
131  * @param[in] blockSize     - size of data in bytes
132  * @param[in] pCmacResult   - a pointer to output buffer
133  *
134  */
CC_PROD_AesInit(AesContext_t * pAesCtx,aesMode_t cipherMode,cryptoDirection_t encDecDir,cryptoKeyType_t keyType,uint8_t * pKey,uint32_t keySizeInBytes,uint8_t * pIv,uint32_t ivSizeInBytes)135 uint32_t CC_PROD_AesInit(AesContext_t *pAesCtx,
136                          aesMode_t cipherMode,
137                          cryptoDirection_t encDecDir,
138                          cryptoKeyType_t keyType,
139                          uint8_t *pKey,
140                          uint32_t keySizeInBytes,
141                          uint8_t *pIv,
142                          uint32_t ivSizeInBytes)
143 {
144         switch (keySizeInBytes) {
145         case 16:
146                 pAesCtx->keySizeId = KEY_SIZE_128_BIT;
147                 break;
148         case 24:
149                 pAesCtx->keySizeId = KEY_SIZE_192_BIT;
150                 break;
151         case 32:
152                 pAesCtx->keySizeId = KEY_SIZE_256_BIT;
153                 break;
154         default:
155                 CC_PAL_LOG_ERR("NOT OK\n");
156                 return 1;
157         }
158         pAesCtx->mode = cipherMode;
159         pAesCtx->dir = encDecDir;
160         pAesCtx->cryptoKey = keyType;
161         pAesCtx->padType = CRYPTO_PADDING_NONE;
162         pAesCtx->dataBlockType = FIRST_BLOCK;
163         pAesCtx->inputDataAddrType = DLLI_ADDR;
164         pAesCtx->outputDataAddrType = DLLI_ADDR;
165         CC_PalMemCopy((uint8_t *)pAesCtx->ivBuf, pIv, ivSizeInBytes);
166         if (keyType == USER_KEY) {
167                 CC_PalMemCopy((uint8_t *)pAesCtx->keyBuf, pKey, keySizeInBytes);
168         }
169 
170         return CC_OK;
171 }
172 
173 
174 /**
175  * This function is used to perform AES CBC MAC operation.
176  *
177  * @param[in] cipherMode    - the aes mode
178  * @param[in] pDataIn       - a pointer to input buffer - address must be 32bit aligned
179  * @param[in] dataInSize    - size of data in bytes
180  * @param[out] pOutbuff     - a pointer to output buffer - address must be 32bit aligned
181  * @param[in] outbuffSize   -  the expectedsize of output buffer in bytes
182  *
183  */
CC_PROD_AesProcess(AesContext_t * pAesCtx,uint32_t * pDataIn,uint32_t dataInSize,uint32_t * pOutbuff)184 uint32_t CC_PROD_AesProcess(AesContext_t *pAesCtx,
185                             uint32_t *pDataIn,
186                             uint32_t  dataInSize,
187                      uint32_t *pOutbuff)
188 {
189     uint32_t error;
190     CCBuffInfo_t inBuffInfo;
191     CCBuffInfo_t outBuffInfo;
192 
193     /* set data buffers structures */
194     error = SetDataBuffersInfo((uint8_t*)pDataIn, dataInSize, &inBuffInfo,
195                                (uint8_t*)pOutbuff, dataInSize, &outBuffInfo);
196     if (error != 0) {
197          CC_PAL_LOG_ERR("illegal data buffers\n");
198          return error;
199     }
200 
201     return ProcessAesDrv(pAesCtx, &inBuffInfo, &outBuffInfo, dataInSize);
202 }
203 
204 
205 
CC_PROD_KeyDerivation(cryptoKeyType_t keyType,uint8_t * pUserKey,const uint8_t * pLabel,size_t labelSize,const uint8_t * pContextData,size_t contextSize,uint8_t * pDerivedKey)206 uint32_t  CC_PROD_KeyDerivation(cryptoKeyType_t keyType,
207                                 uint8_t *pUserKey,
208                                 const uint8_t               *pLabel,
209                                 size_t                      labelSize,
210                                 const uint8_t               *pContextData,
211                                 size_t                      contextSize,
212                                 uint8_t                     *pDerivedKey)
213 {
214         uint32_t                dataInSize = 0;
215         drvError_t      drvRc;
216         AesContext_t    aesCtx;
217         uint8_t         dataIn[PROD_KEY_TMP_LABEL_SIZE + PROD_KEY_TMP_CONTEXT_SIZE + 3] = { 0 };
218         CCBuffInfo_t inBuffInfo;
219         CCBuffInfo_t outBuffInfo;
220 
221         /* Check inputs */
222         if (((keyType != USER_KEY) && (keyType != RTL_KEY)) ||
223             ((keyType == USER_KEY) && (pUserKey == NULL)) ||
224             (labelSize > PROD_KEY_TMP_LABEL_SIZE) ||
225             (pLabel == NULL) ||
226             (contextSize > PROD_KEY_TMP_CONTEXT_SIZE) ||
227             (pContextData == NULL) ||
228             (pDerivedKey == NULL)) {
229                 return CC_PROD_INVALID_PARAM_ERR;
230         }
231 
232         /* Generate dataIn buffer for CMAC: iteration || Label || 0x00 || context || length
233                since deruved key is 128 bits we have only 1 iteration */
234         dataInSize = 0;
235         dataIn[dataInSize++] = 1;
236         CC_PalMemCopy((uint8_t *)&dataIn[dataInSize], pLabel, labelSize);
237         dataInSize += labelSize;
238 
239         dataIn[dataInSize++] = 0x00;
240         CC_PalMemCopy((uint8_t *)&dataIn[dataInSize], pContextData, contextSize);
241         dataInSize += contextSize;
242         dataIn[dataInSize++] =  CC_AES_BLOCK_SIZE_IN_BYTES * CC_BITS_IN_BYTE;  // all derived keys are 128 bits
243 
244         aesCtx.cryptoKey = keyType;
245         aesCtx.keySizeId = KEY_SIZE_128_BIT;
246         if (keyType == USER_KEY) {
247                 CC_PalMemCopy(aesCtx.keyBuf, pUserKey, CC_AES_BLOCK_SIZE_IN_BYTES);
248         }
249 
250         aesCtx.mode               = CIPHER_CMAC;
251         aesCtx.dir                = CRYPTO_DIRECTION_ENCRYPT;
252         aesCtx.dataBlockType      = FIRST_BLOCK;
253         aesCtx.inputDataAddrType  = DLLI_ADDR;
254         aesCtx.outputDataAddrType = DLLI_ADDR;
255         CC_PalMemSetZero(aesCtx.ivBuf, AES_IV_SIZE);
256 
257         /* set data buffers structures */
258         drvRc = SetDataBuffersInfo((uint8_t*)dataIn, dataInSize, &inBuffInfo,
259                                    NULL, 0, &outBuffInfo);
260         if (drvRc != 0) {
261              CC_PAL_LOG_ERR("illegal data buffers\n");
262              return drvRc;
263         }
264         drvRc = FinishAesDrv(&aesCtx, &inBuffInfo, &outBuffInfo, dataInSize);
265         if (drvRc != 0) {
266                 return drvRc;
267         }
268         CC_PalMemCopy(pDerivedKey, aesCtx.ivBuf, CC_AES_BLOCK_SIZE_IN_BYTES);
269         return CC_OK;
270 }
271 
272 
273