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