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_sb_ops.h"
22 #include "common_crypto_asym.h"
23 #include "common_util_log.h"
24 #include "common_util_files.h"
25 #include "cc_crypto_defs.h"
26 #include "cc_pka_hw_plat_defs.h"
27
28
29 #define HASH_ON_PLAIN_TEXT 0
30 #define HASH_ON_CIPHER_TEXT 1
31
32
33 /**
34 * @brief The SBU_RSA_Sign generates RSA signature and returns it.
35 *
36 * The function follows the steps:
37 * 1. Read RSA private key structure
38 * 2. Call function according to PKCS version to create RSA signature
39 *
40 * @param[in] pkcsVersion - the version used (according to global definitions of available versions)
41 * @param[in] DataIn_ptr - the data to sign on
42 * @param[in] DataInSize - the data size
43 * @param[in] PemEncryptedFileName_ptr - the private key file
44 * @param[in] pwdFileName - file name of the password
45 * @param[out] Signature_ptr - the RSA signature
46 *
47 */
48 /*********************************************************/
SBU_RSA_Sign(int pkcsVersion,char * DataIn_ptr,unsigned int DataInSize,char * PemEncryptedFileName_ptr,char * pwdFileName,char * Signature_ptr)49 SBUEXPORT_C int SBU_RSA_Sign(int pkcsVersion,
50 char* DataIn_ptr,
51 unsigned int DataInSize,
52 char* PemEncryptedFileName_ptr,
53 char* pwdFileName,
54 char* Signature_ptr)
55 {
56 RSA *pRsaPrivKey = NULL;
57 unsigned char *pwd = NULL;
58 int ret_code;
59
60 OpenSSL_add_all_algorithms ();
61
62 /* parse the passphrase for a given file */
63 if( strlen(pwdFileName) ) {
64 if(CC_CommonGetPassphrase(pwdFileName, &pwd) != 0){
65 printf("Failed to retrieve pwd\n");
66 if (pwd != NULL)
67 free(pwd);
68 return (-1);
69 }
70 }
71 else {
72 pwd = Nullptr;
73 }
74
75 if (CC_CommonGetKeyPair (&pRsaPrivKey, PemEncryptedFileName_ptr, pwd) < 0)
76 {
77 printf ("\nCC_CommonGetKeyPair Cannot read RSA private key\n");
78 return (-1);
79 }
80
81 if (pkcsVersion == RSA_USE_PKCS_15_VERSION) {
82 ret_code = Sign_v15(pRsaPrivKey, DataIn_ptr, DataInSize, Signature_ptr, pwd);
83 } else {
84 ret_code = Sign_v21(pRsaPrivKey, DataIn_ptr, DataInSize, Signature_ptr);
85 }
86
87 return (ret_code);
88 }
89
90
91 /**
92 * @brief The SBU_AES_CTR_Encrypt encrypts (AES CTR) a given data and returns it.
93 * Also, it hash either the plain or the cipher text according to cryptoType.
94 *
95 * @param[in] pFileName - input plain text
96 * @param[in] pOutputFileName - output cipher text
97 * @param[in] Key_ptr - the AES key
98 * @param[in] KeySize - AES key size (must be one of the allowed AES key sizes)
99 * @param[in] IV_ptr - IV (AES IV size is constant)
100 * @param[in] Output_ptr - Output hash buffer
101 * @param[in] imageSize - size of input data
102 * @param[in] cryptoType - 0 - hash the plain text; 1 = hash the cipher text
103 */
104 /*********************************************************/
SBU_AES_CTR_EncryptFile(char * pFileName,char * pOutputFileName,char * Key_ptr,int KeySize,char * IV_ptr,char * Output_ptr,uint32_t * imageSize,int8_t cryptoType)105 SBUEXPORT_C int SBU_AES_CTR_EncryptFile(char *pFileName,
106 char *pOutputFileName,
107 char* Key_ptr, int KeySize,
108 char* IV_ptr,
109 char* Output_ptr,
110 uint32_t *imageSize,
111 int8_t cryptoType)
112 {
113 int rc = 0;
114 FILE *fd = NULL;
115 FILE *encFd = NULL;
116 int actualFileLen = 0;
117 bool encFlag = false;
118 uint32_t totalRead = 0;
119 uint32_t actualRead = 0;
120 unsigned char m_iv[AES_BLOCK_SIZE];
121 unsigned char m_key[AES_BLOCK_SIZE*2];
122 uint8_t origBuff[MAX_IMAGE_CHUNK] = {0};
123 uint8_t encryptedBuff[MAX_IMAGE_CHUNK+AES_BLOCK_SIZE] = {0};
124 uint32_t actualWriten = 0;
125 uint8_t *pBuff2Hash = NULL;
126 uint8_t imageHash[HASH_SHA256_DIGEST_SIZE_IN_BYTES] = {0};
127 EVP_CIPHER_CTX ctrCtx;
128 SHA256_CTX sha256Ctx;
129 uint32_t encryptedBuffSize = 0;
130 uint32_t prevBuffLen = 0;
131
132 if (pFileName == NULL || Output_ptr == NULL || imageSize == NULL){
133 printf("illegal parameters !\n");
134 return 1;
135 }
136 if (IV_ptr != NULL){ /* if there is IV than key is required as well */
137 memcpy (m_iv, IV_ptr, sizeof (m_iv));
138 memcpy (m_key, Key_ptr, KeySize);
139 encFlag = true;
140 }
141
142 /* Open image file for reading */
143 fd = fopen(pFileName, "rb");
144 if (NULL == fd) {
145 printf( "failed to open file %s for reading\n", pFileName);
146 return 1;
147 }
148 /* Get file length */
149 fseek(fd, 0, SEEK_END);
150 actualFileLen=ftell(fd);
151 if (actualFileLen == -1){
152 printf("ftell failed\n");
153 goto END;
154 }
155 fseek(fd, 0, SEEK_SET);
156 // validate size legal and word aligned
157 if ((0 == actualFileLen) ||
158 (actualFileLen % 0x4)) {
159 printf( "ilegal actualFileLen == 0\n");
160 rc = 3;
161 goto END;
162 }
163
164 /* init SHA256 open-ssl context */
165 rc = SHA256_Init(&sha256Ctx);
166 if (rc == 0) {
167 printf( "failed to SHA256_Init 0x%x\n", rc);
168 rc = 1;
169 goto END;
170 }
171
172 /* init variables in case encryption is needed */
173 if (encFlag == true) {
174 /* open encrypted file for writing encrypted image */
175 encFd = fopen(pOutputFileName, "wb");
176 if (NULL == encFd) {
177 printf( "failed to open file %s for writing\n", pOutputFileName);
178 rc = 1;
179 goto END;
180 }
181
182 /* init AES CTR open-ssl context */
183 EVP_CIPHER_CTX_init(&ctrCtx);
184 rc = EVP_EncryptInit(&ctrCtx, EVP_aes_128_ctr(), m_key, m_iv);
185 if (rc == 0) {
186 printf( "failed to EVP_EncryptInit_ex 0x%x\n", rc);
187 rc = 1;
188 goto END;
189 }
190 }
191
192 /* read max 1M bytes from image file,
193 if encryption is required, encrype first and write into pOutputFileName;
194 then perform SHA256. */
195 totalRead = 0;
196 prevBuffLen = 0;
197 encryptedBuffSize = 0;
198
199 while(totalRead < actualFileLen) {
200 /* read file content */
201 actualRead = fread(origBuff, 1, MAX_IMAGE_CHUNK, fd);
202 if (actualRead == 0)
203 {
204 printf( "fread returned 0\n");
205 goto END;
206 }
207 totalRead += actualRead;
208 pBuff2Hash = origBuff;
209 /* handle encryption */
210 if (encFlag == true) {
211 encryptedBuffSize = 0;
212 pBuff2Hash = &encryptedBuff[0];
213 rc = EVP_EncryptUpdate(&ctrCtx, encryptedBuff, &prevBuffLen, origBuff, actualRead);
214 if (rc == 0) {
215 printf( "failed to EVP_EncryptUpdate, rc 0x%x\n", rc);
216 rc = 1;
217 goto END;
218 }
219 /* update total encrypted byte count */
220 encryptedBuffSize += prevBuffLen;
221 if (totalRead >= actualFileLen) {
222 rc = EVP_EncryptFinal_ex(&ctrCtx, encryptedBuff+encryptedBuffSize, &prevBuffLen);
223 if (rc == 0) {
224 printf( "failed to EVP_EncryptFinal_ex, rc 0x%x\n", rc);
225 rc = 1;
226 goto END;
227 }
228 encryptedBuffSize += prevBuffLen;
229 }
230
231 /* write encrypted data to binary file */
232 actualWriten = fwrite(pBuff2Hash, 1, actualRead, encFd);
233 if (actualWriten != actualRead) {
234 printf( "failed to write data to file actual written %d, expected %d\n", actualWriten, actualRead);
235 rc = 1;
236 goto END;
237 }
238 }
239
240 /* calculate SHA256 on plain/cipher image */
241 if (cryptoType == HASH_ON_PLAIN_TEXT) {
242 rc = SHA256_Update(&sha256Ctx, origBuff, actualRead);
243 } else {
244 rc = SHA256_Update(&sha256Ctx, encryptedBuff, actualRead);
245 }
246 if (rc == 0) {
247 printf( "failed to SHA256_Update, rc 0x%x\n", rc);
248 rc = 1;
249 goto END;
250 }
251 if (totalRead >= actualFileLen) {
252 rc = SHA256_Final(imageHash, &sha256Ctx);
253 if (rc == 0) {
254 printf( "failed to SHA256_Final, rc 0x%x\n", rc);
255 rc = 1;
256 goto END;
257 }
258 OPENSSL_cleanse(&sha256Ctx,sizeof(sha256Ctx));
259 }
260
261 }
262 // if we reached here rc is OK
263 rc = 0;
264 // copy the output HASH back to the caller
265 memcpy(Output_ptr , imageHash, HASH_SHA256_DIGEST_SIZE_IN_BYTES);
266 *imageSize = actualFileLen;
267
268 END:
269 if (fd != NULL) {
270 fclose(fd);
271 }
272 if (encFd != NULL) {
273 fclose(encFd);
274 }
275 EVP_cleanup();
276
277 return rc;
278
279 }
280
281
282