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