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 "cc_hal_plat.h"
10 #include "cc_regs.h"
11 #include "cc_pal_mem.h"
12 #include "cc_pal_mutex.h"
13 #include "cc_pal_abort.h"
14 #include "cc_util_int_defs.h"
15 #include "mbedtls_cc_util_defs.h"
16 #include "cc_util_error.h"
17 #include "cc_aes_defs.h"
18 #include "mbedtls/ccm.h"
19 #include "aes_driver.h"
20 #include "driver_defs.h"
21 #include "cc_util_cmac.h"
22 #include "mbedtls_cc_util_asset_prov.h"
23 #include "cc_util_asset_prov_int.h"
24 
25 
mbedtls_util_asset_pkg_unpack(CCAssetProvKeyType_t keyType,uint32_t assetId,uint32_t * pAssetPkgBuff,size_t assetPackageLen,uint32_t * pAssetData,size_t * pAssetDataLen)26 CCError_t mbedtls_util_asset_pkg_unpack(CCAssetProvKeyType_t        keyType,
27             uint32_t        assetId,
28             uint32_t        *pAssetPkgBuff,
29             size_t          assetPackageLen,
30             uint32_t        *pAssetData,
31             size_t          *pAssetDataLen)
32 {
33     uint32_t  rc = CC_OK;
34     CCUtilAesCmacResult_t         keyProv = { 0 };
35     uint8_t     dataIn[CC_UTIL_MAX_KDF_SIZE_IN_BYTES] = { 0 };
36     size_t    dataInSize = CC_UTIL_MAX_KDF_SIZE_IN_BYTES;
37     uint8_t     provLabel = 'P';
38     CCAssetProvPkg_t   *pAssetPackage = NULL;
39     mbedtls_ccm_context ccmCtx;
40     uint8_t    ccmAddData[CC_ASSET_PROV_ADATA_SIZE] = { 0 };
41     uint8_t    ccmNonceData[CC_ASSET_PROV_NONCE_SIZE] = { 0 };
42     uint32_t    assetDataSize = 0;
43     uint32_t    constPkgSize = CC_ASSET_PROV_ADATA_SIZE+CC_ASSET_PROV_NONCE_SIZE+CC_ASSET_PROV_TAG_SIZE;
44     uint32_t    minPkgSize = constPkgSize+CC_ASSET_PROV_BLOCK_SIZE;
45 
46     /* Validate Inputs */
47     if ((pAssetPkgBuff == NULL) ||
48         (pAssetData == NULL) ||
49         (pAssetDataLen == NULL) ||
50         (assetPackageLen > CC_ASSET_PROV_MAX_ASSET_PKG_SIZE) ||
51         (assetPackageLen < minPkgSize) ||
52         /* Overlapping verification */
53         (((unsigned long)pAssetPkgBuff + assetPackageLen) < (unsigned long)pAssetPkgBuff) ||
54         (assetPackageLen  % CC_32BIT_WORD_SIZE) ||
55         ((keyType != ASSET_PROV_KEY_TYPE_KPICV) && (keyType != ASSET_PROV_KEY_TYPE_KCP))) {
56             CC_PAL_LOG_ERR("Invalid params");
57             return CC_UTIL_ILLEGAL_PARAMS_ERROR;
58     }
59     pAssetPackage = (CCAssetProvPkg_t *)pAssetPkgBuff;
60 
61     /* Validate asset size, must be multiply of 16 bytes */
62     if ((pAssetPackage->assetSize > CC_ASSET_PROV_MAX_ASSET_SIZE) ||
63         (pAssetPackage->assetSize == 0) ||
64         (pAssetPackage->assetSize % CC_ASSET_PROV_BLOCK_SIZE)) {
65             CC_PAL_LOG_ERR("Invalid asset size 0x%x", pAssetPackage->assetSize);
66             return CC_UTIL_ILLEGAL_PARAMS_ERROR;
67     }
68     /* Verify assetDataSize against assetPkgSize */
69     if ((assetPackageLen < (constPkgSize+pAssetPackage->assetSize)) ||
70         (*pAssetDataLen  < pAssetPackage->assetSize)) {
71             CC_PAL_LOG_ERR("Invalid asset size 0x%x", pAssetPackage->assetSize);
72             return CC_UTIL_ILLEGAL_PARAMS_ERROR;
73     }
74     /* Verify package token and version */
75     if ((pAssetPackage->token != CC_ASSET_PROV_TOKEN) ||
76         (pAssetPackage->version != CC_ASSET_PROV_VERSION)) {
77             CC_PAL_LOG_ERR("Invalid token or version");
78             return CC_UTIL_ILLEGAL_PARAMS_ERROR;
79     }
80 
81     /* Generate dataIn buffer for CMAC: iteration || 'P' || 0x00 || asset Id || 0x80
82            since deruved key is 128 bits we have only 1 iteration */
83     rc = UtilCmacBuildDataForDerivation(&provLabel,sizeof(provLabel),
84                                           (uint8_t *)&assetId, sizeof(assetId),
85                                          dataIn, &dataInSize,
86                                          (size_t)CC_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES);
87     if (rc != 0) {
88             CC_PAL_LOG_ERR("Failed UtilCmacBuildDataForDerivation 0x%x", rc);
89             return rc;
90     }
91     dataIn[0] = 1;  // only 1 iteration
92     rc = UtilCmacDeriveKey((keyType == ASSET_PROV_KEY_TYPE_KPICV)?UTIL_KPICV_KEY:UTIL_KCP_KEY,
93                             NULL,
94                             dataIn, dataInSize,
95                             keyProv);
96     if (rc != 0) {
97             CC_PAL_LOG_ERR("Failed UtilCmacDeriveKey 0x%x", rc);
98             return rc;
99     }
100 
101     /* Decrypt and authenticate the BLOB */
102     mbedtls_ccm_init(&ccmCtx);
103 
104     rc = mbedtls_ccm_setkey(&ccmCtx, MBEDTLS_CIPHER_ID_AES, keyProv, CC_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES * CC_BITS_IN_BYTE);
105     if (rc != 0) {
106             CC_PAL_LOG_ERR("Failed to mbedtls_ccm_setkey 0x%x\n", rc);
107             return rc;
108     }
109 
110     assetDataSize = pAssetPackage->assetSize;
111     CC_PalMemCopy(ccmNonceData, pAssetPackage->nonce, CC_ASSET_PROV_NONCE_SIZE);
112     CC_PalMemCopy(ccmAddData, (uint8_t *)pAssetPackage, CC_ASSET_PROV_ADATA_SIZE);
113     rc = mbedtls_ccm_auth_decrypt(&ccmCtx, pAssetPackage->assetSize,
114                                   ccmNonceData, CC_ASSET_PROV_NONCE_SIZE,
115                                   ccmAddData, CC_ASSET_PROV_ADATA_SIZE,
116                                   pAssetPackage->encAsset, (uint8_t *)pAssetData,
117                                   pAssetPackage->encAsset + pAssetPackage->assetSize, CC_ASSET_PROV_TAG_SIZE);
118     if (rc != 0) {
119             CC_PAL_LOG_ERR("Failed to mbedtls_ccm_auth_decrypt 0x%x\n", rc);
120             return rc;
121     }
122 
123     // Set output data
124     *pAssetDataLen = assetDataSize;
125     return CC_OK;
126 }
127 
128