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 <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdint.h>
12 #include <stdbool.h>
13
14 #include <openssl/objects.h>
15 #include <openssl/pem.h>
16 #include <openssl/evp.h>
17 #include <openssl/rand.h>
18 #include <openssl/bn.h>
19 #include <openssl/aes.h>
20 #include <openssl/err.h>
21 #include "common_util_log.h"
22 #include "common_crypto_asym.h"
23 #include "common_crypto_sym.h"
24 #include "common_rsa_keypair_util.h"
25 #include "common_util_files.h"
26 #include "cc_util_asset_prov_int.h"
27
28 static uint8_t isLibOpened = 0;
29
30 #define KPICV_KEY_SIZE 16
31 #define KPROV_KEY_SIZE 16
32 #define KPROV_DATA_IN_SIZE 8
33
34
35 /**
36 * @brief initialize openSSL library
37 *
38 * @param[in] None
39 * @param[out] None
40 *
41 */
42 /*********************************************************/
InitOpenSsl(void)43 static void InitOpenSsl(void)
44 {
45 if (0 == isLibOpened) {
46 OpenSSL_add_all_algorithms();
47 }
48 isLibOpened++;
49 }
50
51
52 /**
53 * @brief terminates and cleanup openSSL library
54 *
55 * @param[in] None
56 * @param[out] None
57 *
58 */
59 /*********************************************************/
CloseOpenSsl(void)60 static void CloseOpenSsl(void)
61 {
62 isLibOpened--;
63 if (0 == isLibOpened) {
64 EVP_cleanup();
65 //CYPTO_cleanup_all_ex_data(); /* cleanup application specific data to avoid memory leaks.*/
66 }
67 }
68
69
70 /**
71 * @brief performs CMAC key derivation for Kprov using openSSL library
72 *
73 * @param[in] pKey & keySize - Kpicv key and its size
74 * lable & pContext & contextSize used to build the dataIn for derivation
75 * @param[out] pOutKey - Kprov
76 *
77 */
78 /*********************************************************/
AesCmacKeyDerivation(char * pKey,uint32_t keySize,char lable,uint8_t * pContext,uint32_t contextSize,char * pOutKey,uint32_t outKeySize)79 static int AesCmacKeyDerivation(char *pKey, uint32_t keySize,
80 char lable,
81 uint8_t *pContext, uint32_t contextSize,
82 char *pOutKey, uint32_t outKeySize)
83 {
84 int rc = 0;
85 int i = 0;
86 int8_t dataIn[KPROV_DATA_IN_SIZE] = {0x0};
87
88 /* Create the input to the CMAC derivation */
89 dataIn[i++] = 0x1;
90 dataIn[i++] = lable;
91 dataIn[i++] = 0x0;
92 memcpy(&dataIn[i], pContext, contextSize);
93 i += contextSize;
94 dataIn[i] = outKeySize*CC_BITS_IN_BYTE; // size of the key in bits
95
96 UTIL_LOG_BYTE_BUFF("dataIn", dataIn, sizeof(dataIn));
97 UTIL_LOG_BYTE_BUFF("pKey", pKey, keySize);
98 rc = CC_CommonAesCmacEncrypt(dataIn, sizeof(dataIn),
99 pKey, keySize, pOutKey);
100 if (rc != 0) {
101 UTIL_LOG_ERR( "failed to CC_CommonAesCmacEncrypt(), rc %d\n", rc);
102 return (-1);
103 }
104 UTIL_LOG_BYTE_BUFF("pOutKey", pOutKey, outKeySize);
105 return rc;
106 }
107
108
109 /**
110 * @brief Build the ICV asset BLOB using openSSL library
111 *
112 * @param[in] encKeyBuff & encKeyBuffSize & pKeyPwdFileName - the encryptes Kpicv key
113 * assetId - Asset ID, used for Kprov derivation
114 * asset & assetSize - The Asset to generate the BLOB for
115 * pBlobFileName - OUT - the asset BLOB binary file name
116 * @param[out] None
117 *
118 */
119 /*********************************************************/
build_asset_blob(char * encKeyBuff,uint32_t encKeyBuffSize,char * pKeyPwdFileName,uint32_t assetId,uint8_t * asset,uint32_t assetSize,char * pBlobFileName)120 int build_asset_blob(char *encKeyBuff, uint32_t encKeyBuffSize,
121 char *pKeyPwdFileName,
122 uint32_t assetId,
123 uint8_t *asset, uint32_t assetSize,
124 char *pBlobFileName)
125 {
126 int rc = 0;
127 uint8_t keyPicv[(KPICV_KEY_SIZE + CC_ASSET_PROV_BLOCK_SIZE)] = {0};
128 uint8_t keyProv[KPROV_KEY_SIZE] = {0};
129 uint8_t i = 0;
130 CCAssetProvPkg_t assetBlob = {0};
131 uint32_t assetBlobSize;
132
133 // Verify Inputs
134 UTIL_LOG_ERR( "encKeyBuffSize %d\n", encKeyBuffSize);
135 if ((encKeyBuff == NULL) ||
136 (encKeyBuffSize != (KPICV_KEY_SIZE + CC_ASSET_PROV_BLOCK_SIZE)) ||
137 (asset == NULL) ||
138 (assetSize > CC_ASSET_PROV_MAX_ASSET_SIZE) || (assetSize % CC_ASSET_PROV_BLOCK_SIZE) ||
139 (pBlobFileName == NULL)) {
140 UTIL_LOG_ERR( "Invalid inputs\n");
141 return (-1);
142 }
143 assetBlobSize = CC_ASSET_PROV_ADATA_SIZE + CC_ASSET_PROV_NONCE_SIZE + assetSize + CC_ASSET_PROV_TAG_SIZE;
144
145 InitOpenSsl();
146
147 // Build the BLOB header
148 assetBlob.token = CC_ASSET_PROV_TOKEN;
149 assetBlob.version = CC_ASSET_PROV_VERSION;
150 assetBlob.assetSize = assetSize;
151 assetBlob.reserved[0] = 0;
152 assetBlob.reserved[1] = 0; // reserved
153 rc = CC_CommonRandBytes(CC_ASSET_PROV_NONCE_SIZE, (uint8_t *)assetBlob.nonce);
154 if (rc != 0) {
155 UTIL_LOG_ERR( "failed to CC_CommonRandBytes() for nonce, rc %d\n", rc);
156 rc = (-1);
157 goto end_func;
158 }
159
160
161 // Decrypt Kpicv
162 UTIL_LOG_ERR( "calling CC_CommonAesCbcDecrypt() pKeyPwdFileName %s\n", pKeyPwdFileName);
163 rc = CC_CommonAesCbcDecrypt(pKeyPwdFileName, encKeyBuff, encKeyBuffSize, keyPicv);
164 if (rc != 0) {
165 UTIL_LOG_ERR( "failed to CC_CommonAesCbcDecrypt() for Kpicv, rc %d\n", rc);
166 rc = (-1);
167 goto end_func;
168 }
169
170
171 // Calculate Kprov = cmac(Kpicv, 0x01 || 0x50 || 0x00 || asset id || 0x80)
172 UTIL_LOG_ERR( "calling AesCmacKeyDerivation\n");
173 rc = AesCmacKeyDerivation(keyPicv, KPICV_KEY_SIZE,
174 'P',
175 (uint8_t *)&assetId, sizeof(assetId),
176 keyProv, sizeof(keyProv));
177 if (rc != 0) {
178 UTIL_LOG_ERR( "failed to AesCmacKeyDerivation() for Kprov, rc %d\n", rc);
179 rc = (-1);
180 goto end_func;
181 }
182
183 // Encrypt and authenticate the asset
184 UTIL_LOG_ERR( "calling CC_CommonAesCcmEncrypt\n");
185 rc = CC_CommonAesCcmEncrypt(keyProv,
186 (uint8_t *)assetBlob.nonce, CC_ASSET_PROV_NONCE_SIZE,
187 (uint8_t *)&assetBlob, CC_ASSET_PROV_ADATA_SIZE,
188 asset, assetSize,
189 (uint8_t *)assetBlob.encAsset, &assetSize,
190 ((uint8_t *)assetBlob.encAsset)+assetSize, CC_ASSET_PROV_TAG_SIZE);
191 if (rc != 0) {
192 UTIL_LOG_ERR( "failed to CC_CommonAesCmacEncrypt() for Kprov, rc %d\n", rc);
193 rc = (-1);
194 goto end_func;
195 }
196
197 UTIL_LOG_BYTE_BUFF("assetBlob", (uint8_t *)&assetBlob, assetBlobSize);
198 // Writing the asset BLOB into bin file
199 rc = CC_CommonUtilCopyBuffToBinFile(pBlobFileName, (uint8_t *)&assetBlob, assetBlobSize);
200 if (rc != 0) {
201 UTIL_LOG_ERR( "failed to CC_CommonUtilCopyBuffToBinFile(), rc %d\n", rc);
202 rc = (-1);
203 goto end_func;
204 }
205 rc = 0;
206 end_func:
207 CloseOpenSsl();
208 UTIL_LOG_ERR( "End rc %d\n", rc);
209 return rc;
210 }
211