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 
12 #include <openssl/objects.h>
13 #include <openssl/evp.h>
14 #include <openssl/aes.h>
15 #include <openssl/err.h>
16 #include <openssl/cmac.h>
17 #include <openssl/sha.h>
18 #include "common_crypto_sym.h"
19 #include "common_util_log.h"
20 #include "common_util_files.h"
21 
22 /**
23 * @brief Encrypts (AES CTR) a given data and returns it.
24 *
25 * @param[in] pDataIn - the data to encrypt
26 * @param[in] dataInSize - the data size
27 * @param[in] pKey - the AES key
28 * @param[in] keySize - AES key size (must be one of the allowed AES key sizes)
29 * @param[in] pIV - IV (AES IV size is constant)
30 * @param[out] pEncBuff - the encrypted buffer
31 */
32 /*********************************************************/
CC_CommonAesCtrEncrypt(int8_t * pDataIn,int32_t dataInSize,int8_t * pKey,int32_t keySize,int8_t * pIV,int8_t * pEncBuff)33 int32_t CC_CommonAesCtrEncrypt(int8_t  *pDataIn,
34                   int32_t    dataInSize,
35                   int8_t   *pKey,
36                   int32_t    keySize,
37                   int8_t   *pIV,
38                   int8_t   *pEncBuff)
39 {
40     AES_KEY key;
41     uint8_t m_iv[AES_BLOCK_SIZE];
42     uint8_t m_ecount_buf[AES_BLOCK_SIZE];
43     uint32_t m_num = 0;
44     int32_t ret = (-1);
45 
46     if ((NULL == pDataIn) ||
47         (NULL == pKey) ||
48         (NULL == pIV) ||
49         (NULL == pEncBuff)) {
50         UTIL_LOG_ERR("ilegal input\n");
51         return -1;
52     }
53     memcpy (m_iv, pIV, sizeof (m_iv));
54     memset (m_ecount_buf, 0, sizeof (m_ecount_buf));
55 
56     /* Initialize an AES_KEY from raw key bytes */
57     ret = AES_set_encrypt_key (pKey, keySize * 8, &key);
58     if (ret != 0) {
59         UTIL_LOG_ERR("\n AES_set_encrypt_key failed");
60         return -1;
61     }
62     /* Encrypting data and sending it to the destination */
63     AES_ctr128_encrypt (pDataIn, pEncBuff, dataInSize, &key, m_iv, m_ecount_buf, &m_num);
64 
65     return 0;
66 }
67 
68 
69 /**
70 * @brief The CC_CommonAesCbcDecrypt decrypts (AES CBC) a given data
71 *               and returns the decrypted buffer. data was encrypted using:
72 *   "openssl enc -e -nosalt -aes-128-cbc -in <in_file,bin> -out <out_file.bin> -pass file:<pwd_file.txt>"
73 * @param[in] pwdFileName - file name for passsword to generate key and IV from
74 * @param[in] pEncBuff - the encrypted buffer- input buffer
75 * @param[in] encBuffSize - the encrypted buffer size
76 * @param[out] pDecBuff -the decrypted buffer.
77 *
78 * NOTE: pDecBuff - alocated size must be multiple of 16 bytes. same as encBuffSize
79 */
80 /*********************************************************/
CC_CommonAesCbcDecrypt(int8_t * pwdFileName,int8_t * pEncBuff,int32_t encBuffSize,int8_t * pDecBuff)81 int32_t CC_CommonAesCbcDecrypt(int8_t *pwdFileName,
82                   int8_t *pEncBuff,
83                   int32_t   encBuffSize,
84                   int8_t *pDecBuff)
85 {
86     uint8_t *pwdBuff = NULL;
87     int32_t pwdBuffLen = 0;
88     const EVP_CIPHER *cipher = NULL;
89     const EVP_MD *dgst = NULL;
90     int8_t keyBuff[EVP_MAX_KEY_LENGTH] = {0x0};
91     int8_t ivBuff[EVP_MAX_KEY_LENGTH] = {0x0};
92     AES_KEY aesKey;
93     int32_t status = 1;
94 
95     if ((NULL == pEncBuff) ||
96         (NULL == pDecBuff)) {
97         UTIL_LOG_ERR("ilegal input\n");
98         return 1;
99     }
100 
101     /* parse the passphrase for a given file */
102     if ((NULL != pwdFileName)) {
103         if (CC_CommonGetPassphrase(pwdFileName, &pwdBuff)) {
104         UTIL_LOG_ERR("Failed to retrieve pwd\n");
105         status = 1;
106         goto END;
107     }
108         pwdBuffLen = strlen(pwdBuff);
109     }
110 
111     /* get the IV and key from pwd */
112     cipher = EVP_get_cipherbyname("aes-128-cbc");
113     if (NULL == cipher) {
114         UTIL_LOG_ERR("EVP_get_cipherbyname failed\n");
115         status = 1;
116         goto END;
117     }
118 
119     dgst = EVP_get_digestbyname("md5");
120     if (NULL == dgst) {
121         UTIL_LOG_ERR("EVP_get_digestbyname failed\n");
122         status = 1;
123         goto END;
124     }
125 
126     UTIL_LOG_BYTE_BUFF("pwdBuff", pwdBuff, strlen(pwdBuff));
127     status = EVP_BytesToKey(cipher, dgst, NULL, (uint8_t *) pwdBuff, pwdBuffLen, 1, keyBuff, ivBuff);
128     if (0 == status) {
129         UTIL_LOG_ERR("EVP_BytesToKey failed\n");
130         status = 1;
131         goto END;
132     }
133 
134     UTIL_LOG_BYTE_BUFF("keyBuff", keyBuff, sizeof(keyBuff));
135     UTIL_LOG_BYTE_BUFF("ivBuff", ivBuff, sizeof(ivBuff));
136 
137     /* key and IV are ready, start decryption */
138     memset (pDecBuff, 0, encBuffSize);  /* encBuffSize is multiple of 16 bytes */
139 
140     /* Initialize an AES_KEY from raw key bytes */
141     status = AES_set_decrypt_key (keyBuff, 128, &aesKey);
142     if (status != 0) {
143         UTIL_LOG_ERR("\n AES_set_encrypt_key failed");
144         status = 1;
145         goto END;
146     }
147     /* Encrypting data and sending it to the destination */
148     AES_cbc_encrypt(pEncBuff, pDecBuff, encBuffSize, &aesKey, ivBuff, AES_DECRYPT);
149 
150     status = 0;
151     END:
152     if (pwdBuff != NULL) {
153         free(pwdBuff);
154     }
155     return status;
156 }
157 
158 /**
159 * @brief Encrypts AES CBC-MAC a given data
160 *               and returns the encrypted buffer.
161 *
162 * @param[in] pKey - key buffer
163 * @param[in] pIv - iv buffer
164 * @param[in] pBuff - the plaintext buffer
165 * @param[in] encBuffSize - the plaintext buffer size
166 * @param[in] pEncMacBuff -the encrypted - ciphertext buffer.
167 * @param[out] pEncMacBuff -the encrypted - ciphertext buffer.
168 *
169 */
170 /*********************************************************/
CC_CommonAesCbcMacEncrypt(int8_t * pKey,int8_t * pIv,int8_t * pBuff,uint32_t buffSize,uint32_t macSize,int8_t * pEncMacBuff)171 int32_t CC_CommonAesCbcMacEncrypt(int8_t *pKey,
172                   int8_t *pIv,
173                   int8_t *pBuff,
174                   uint32_t   buffSize,
175                   uint32_t   macSize,
176                   int8_t *pEncMacBuff)
177 {
178     AES_KEY aesKey;
179     int32_t status = 1;
180     uint8_t *pOutBuff = NULL;
181 
182     if ((NULL == pKey) ||
183         (NULL == pIv) ||
184         (NULL == pBuff) ||
185         (NULL == pEncMacBuff) ||
186         (0 == buffSize)) {
187         UTIL_LOG_ERR("ilegal input\n");
188         return 1;
189     }
190 
191     memset (pEncMacBuff, 0, macSize);  /* buffSize is multiple of 16 bytes */
192 
193     pOutBuff = malloc(buffSize);
194     if (NULL == pOutBuff) {
195         UTIL_LOG_ERR("malloc failed\n");
196         return 1;
197     }
198 
199     /* Initialize an AES_KEY from raw key bytes */
200     status = AES_set_encrypt_key(pKey, 128, &aesKey);
201     if (status != 0) {
202         UTIL_LOG_ERR("\n AES_set_encrypt_key failed");
203         status = 1;
204         goto END;
205     }
206     /* Encrypting data and sending it to the destination */
207     AES_cbc_encrypt(pBuff, pOutBuff, buffSize, &aesKey, pIv, AES_ENCRYPT);
208     memcpy(pEncMacBuff, pOutBuff, macSize);
209 
210     status = 0;
211     END:
212     if (pOutBuff != NULL) {
213         free(pOutBuff);
214     }
215     return status;
216 }
217 
218 
219 /**
220 * @brief Encrypts (AES CCM) a given data and returns it.
221 *
222 * @param[in] pDataIn - the data to encrypt
223 * @param[in] dataInSize - the data size
224 * @param[in] pKey - the AES key
225 * @param[in] keySize - AES key size (must be one of the allowed AES key sizes)
226 * @param[out] pOutput - Output buffer
227 */
228 /*********************************************************/
CC_CommonAesCcmEncrypt(uint8_t * keyBuf,uint8_t * nonce,uint32_t nonceLen,uint8_t * aData,uint32_t aDatalen,uint8_t * plainTxt,uint32_t plainTxtLen,uint8_t * enBuff,uint32_t * enBuffLen,uint8_t * tagBuff,uint32_t tagBuffLen)229 int32_t CC_CommonAesCcmEncrypt(uint8_t *keyBuf,
230                   uint8_t *nonce,
231                   uint32_t  nonceLen,
232                   uint8_t *aData,
233                   uint32_t  aDatalen,
234                   uint8_t *plainTxt,
235                   uint32_t  plainTxtLen,
236                   uint8_t *enBuff,
237                   uint32_t  *enBuffLen,
238                   uint8_t *tagBuff,
239                   uint32_t  tagBuffLen)
240 {
241     EVP_CIPHER_CTX ccm_ctx;
242     int32_t outlen = 0;
243     int32_t rc  = 0;
244 
245     if ((NULL == keyBuf) ||
246         (NULL == nonce) ||
247         (NULL == plainTxt) ||
248         (NULL == enBuff) ||
249         (NULL == enBuffLen) ||
250         (NULL == tagBuff)) {
251         UTIL_LOG_ERR( "invalid input pointers\n");
252         return 1;
253     }
254     /* check legth validity*/
255     memset(enBuff, 0, plainTxtLen);
256     memset(tagBuff, 0, tagBuffLen);
257 
258 
259     EVP_CIPHER_CTX_init(&ccm_ctx);
260 
261     /* Set cipher type and mode */
262     rc  = EVP_EncryptInit_ex(&ccm_ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
263     if (rc != 1) {
264         UTIL_LOG_ERR( "failed to EVP_EncryptInit_ex() for CCM cipher\n");
265         rc = 1;
266         goto ccmEnd;
267     }
268     /* Set nonce length if default 96 bits is not appropriate */
269     rc  = EVP_CIPHER_CTX_ctrl(&ccm_ctx, EVP_CTRL_CCM_SET_IVLEN, nonceLen, NULL);
270     if (rc != 1) {
271         UTIL_LOG_ERR( "failed to EVP_CIPHER_CTX_ctrl() for nonce length\n");
272         rc = 1;
273         goto ccmEnd;
274     }
275     /* Set tag length */
276     rc  = EVP_CIPHER_CTX_ctrl(&ccm_ctx, EVP_CTRL_CCM_SET_TAG, tagBuffLen, NULL);
277     if (rc != 1) {
278         UTIL_LOG_ERR( "failed to EVP_CIPHER_CTX_ctrl() for tag length\n");
279         rc = 1;
280         goto ccmEnd;
281     }
282     /* Initialise key and IV */
283     UTIL_LOG_BYTE_BUFF("nonce", nonce, nonceLen);
284     UTIL_LOG_BYTE_BUFF("keyBuf", keyBuf, 16);
285     rc  = EVP_EncryptInit_ex(&ccm_ctx, NULL, NULL, keyBuf, nonce);
286     if (rc != 1) {
287         UTIL_LOG_ERR( "failed to EVP_EncryptInit_ex() for key and IV\n");
288         rc = 1;
289         goto ccmEnd;
290     }
291     if ((aDatalen>0) && (aData != NULL)) {
292         /* Set plaintext length: only needed if AAD is used */
293         rc  = EVP_EncryptUpdate(&ccm_ctx, NULL, &outlen, NULL, plainTxtLen);
294         if (rc != 1) {
295             UTIL_LOG_ERR( "failed to EVP_EncryptUpdate() for plaintext length\n");
296             rc = 1;
297             goto ccmEnd;
298         }
299         /* Zero or one call to specify any AAD */
300         UTIL_LOG_BYTE_BUFF("aData", aData, aDatalen);
301         rc  = EVP_EncryptUpdate(&ccm_ctx, NULL, &outlen, aData, aDatalen);
302         if (rc != 1) {
303             UTIL_LOG_ERR( "failed to EVP_EncryptUpdate() for AAD\n");
304             rc = 1;
305             goto ccmEnd;
306         }
307     }
308 
309     /* Encrypt plaintext: can only be called once */
310     UTIL_LOG_BYTE_BUFF("plainTxt", plainTxt, plainTxtLen);
311     rc  = EVP_EncryptUpdate(&ccm_ctx, enBuff, &outlen, plainTxt, plainTxtLen);
312     if (rc != 1) {
313         UTIL_LOG_ERR( "failed to EVP_EncryptUpdate() for plaintext\n");
314         rc = 1;
315         goto ccmEnd;
316     }
317     if (outlen != plainTxtLen) {
318         UTIL_LOG_ERR( "ccm encrypt size(%d) != palin text size(%d)\n", outlen, plainTxtLen);
319         rc = 1;
320         goto ccmEnd;
321     }
322     UTIL_LOG_BYTE_BUFF("enBuff", enBuff, outlen);
323     /* Finalise: note get no output for CCM */
324     rc  = EVP_EncryptFinal_ex(&ccm_ctx, &enBuff[outlen], &outlen);
325     if (rc != 1) {
326         UTIL_LOG_ERR( "failed to EVP_EncryptFinal_ex()\n");
327         rc = 1;
328         goto ccmEnd;
329     }
330     /* Get tag */
331     rc  = EVP_CIPHER_CTX_ctrl(&ccm_ctx, EVP_CTRL_CCM_GET_TAG, tagBuffLen, tagBuff);
332     if (rc != 1) {
333         UTIL_LOG_ERR( "failed to EVP_CIPHER_CTX_ctrl() to get the tag\n");
334         rc = 1;
335         goto ccmEnd;
336     }
337     UTIL_LOG_BYTE_BUFF("tagBuff", tagBuff, tagBuffLen);
338     rc = 0;
339 
340     ccmEnd:
341 
342     EVP_CIPHER_CTX_cleanup(&ccm_ctx);
343     return rc;
344 }
345 
346 
347 
348 /**
349 * @brief Encrypts (AES CMAC) a given data and returns it.
350 *
351 * @param[in] pDataIn - the data to encrypt
352 * @param[in] dataInSize - the data size
353 * @param[in] pKey - the AES key
354 * @param[in] keySize - the key size in bytes
355 * @param[in] pOutput - Output buffer
356 */
357 /*********************************************************/
CC_CommonAesCmacEncrypt(int8_t * pDataIn,int32_t dataInSize,int8_t * pKey,int32_t keySize,int8_t * pOutput)358 int32_t CC_CommonAesCmacEncrypt(int8_t *pDataIn,
359                    int32_t  dataInSize,
360                    int8_t *pKey,
361                    int32_t  keySize,
362                    int8_t *pOutput)
363 {
364     CMAC_CTX *cmac_ctx = NULL;
365     int32_t rc = 0;
366     size_t tempOutSize = 0;
367 
368     if ((NULL == pKey) ||
369         (NULL == pDataIn) ||
370         (NULL == pOutput) ||
371         ((keySize != AES_BLOCK_SIZE) && (keySize != (AES_BLOCK_SIZE*2)))) {
372         UTIL_LOG_ERR( "Ilegal parameters\n");
373         return 1;
374     }
375     cmac_ctx = CMAC_CTX_new();
376     if (NULL == cmac_ctx) {
377         UTIL_LOG_ERR( "failed to CMAC_CTX_new\n");
378         return 1;
379     }
380     memset(pOutput, 0, AES_BLOCK_SIZE);
381     if (AES_BLOCK_SIZE == keySize) {
382         rc = CMAC_Init(cmac_ctx, pKey, AES_BLOCK_SIZE, EVP_aes_128_cbc(), 0);
383     } else {
384         rc = CMAC_Init(cmac_ctx, pKey, AES_BLOCK_SIZE*2, EVP_aes_256_cbc(), 0);
385     }
386     if (rc != 1) {
387         UTIL_LOG_ERR( "failed to CMAC_Init\n");
388         rc = 2;
389         goto cmacEnd;
390     }
391     rc = CMAC_Update(cmac_ctx, pDataIn, dataInSize);
392     if (rc != 1) {
393         UTIL_LOG_ERR( "failed to CMAC_Update\n");
394         rc = 3;
395         goto cmacEnd;
396     }
397     rc = CMAC_Final(cmac_ctx, pOutput, &tempOutSize);
398     if (rc != 1) {
399         UTIL_LOG_ERR( "failed to CMAC_Final\n");
400         rc = 4;
401         goto cmacEnd;
402     }
403     rc = 0;
404     cmacEnd:
405     if (cmac_ctx != NULL) {
406         CMAC_CTX_free(cmac_ctx);
407     }
408     return rc;
409 }
410 
411 
412 /**
413  * @brief Calculates HASH on a given buffer, and returns the digest
414  *
415  * @param[in] pPemDecryted - the decrypted public key (input data for HASH)
416  * @param[out] pHash - the HASH SHA 256 calculated on the data
417  *
418  */
419 /*********************************************************/
CC_CommonCalcHash(uint8_t * pPemDecryted,int32_t pemDecryptedSize,uint8_t * pHash,int32_t hashSize)420 int32_t CC_CommonCalcHash(uint8_t *pPemDecryted,
421                int32_t            pemDecryptedSize,
422                uint8_t *pHash,
423                int32_t           hashSize)
424 {
425 
426     uint8_t hash[HASH_SHA256_DIGEST_SIZE_IN_BYTES];
427     int32_t i;
428 
429     /* Verify no NULL pointers */
430     if ((pPemDecryted == NULL) ||
431         (pHash == NULL)) {
432         UTIL_LOG_ERR("Illegal parameters \n");
433         return -1;
434     }
435 
436     /* verify the size is correct */
437     if ((hashSize != HASH_SHA256_DIGEST_SIZE_IN_BYTES) && (hashSize != HASH_SHA256_DIGEST_SIZE_IN_BYTES/2)) {
438         UTIL_LOG_ERR("The digest size is incorrect it can either be %d or %d, given digest size is %d\n", HASH_SHA256_DIGEST_SIZE_IN_BYTES, HASH_SHA256_DIGEST_SIZE_IN_BYTES/2, hashSize);
439         return -1;
440     }
441 
442     /* Calculate the hash */
443     SHA256(pPemDecryted, pemDecryptedSize,hash);
444 
445     /* copy the hash according to requested size */
446     memcpy(pHash, hash, hashSize);
447     return 0;
448 
449 }
450 
451 
452 /**
453  * @brief Calculates HASH on a given buffer, and returns the digest
454  *
455  * @param[in] pPemDecryted - the decrypted public key (input data for HASH)
456  * @param[out] pHash - the HASH SHA 256 calculated on the data
457  *
458  */
459 /*********************************************************/
CC_CommonCalcSha1(uint8_t * pDataIn,int32_t dataInSize,uint8_t * pHash)460 int32_t CC_CommonCalcSha1(uint8_t *pDataIn,
461                int32_t            dataInSize,
462                uint8_t *pHash)
463 {
464     uint8_t hash[HASH_SHA1_DIGEST_SIZE_IN_BYTES];
465     int32_t i;
466 
467     /* Verify no NULL pointers */
468     if ((pDataIn == NULL) ||
469         (pHash == NULL)) {
470         UTIL_LOG_ERR("Illegal parameters \n");
471         return -1;
472     }
473 
474     /* Calculate the hash */
475     SHA1(pDataIn, dataInSize, hash);
476 
477     /* copy the hash according to requested size */
478     memcpy(pHash, hash, HASH_SHA1_DIGEST_SIZE_IN_BYTES);
479     return 0;
480 
481 }
482 
483 
484 /**
485 * @brief Encrypts (AES ECB) a given data and returns it.
486 *
487 * @param[in] pDataIn - the data to encrypt
488 * @param[in] dataInSize - the data size
489 * @param[in] pKey - the AES key
490 * @param[in] keySize - AES key size (must be one of the allowed AES key sizes)
491 * @param[out] pEncBuff - the encrypted buffer
492 */
493 /*********************************************************/
CC_CommonAesEcbEncrypt(uint8_t * pDataIn,uint32_t dataInSize,uint8_t * pKey,uint32_t keySize,uint8_t * pEncBuff)494 int32_t CC_CommonAesEcbEncrypt(uint8_t  *pDataIn,
495                   uint32_t    dataInSize,
496                   uint8_t   *pKey,
497                   uint32_t    keySize,
498                   uint8_t   *pEncBuff)
499 {
500     #define BITS_WITHIN_BYTE 8
501 
502     int rc = 0;
503     AES_KEY encKey;
504 
505     if ((NULL == pDataIn) ||
506         (NULL == pKey) ||
507         (NULL == pEncBuff)) {
508         UTIL_LOG_ERR("ilegal input\n");
509         return 1;
510     }
511 
512     UTIL_LOG_ERR("About to AES_set_encrypt_key\n");
513     rc = AES_set_encrypt_key(pKey, (keySize*BITS_WITHIN_BYTE), &encKey);
514     if (rc != 0) {
515         UTIL_LOG_ERR("Failed AES_set_encrypt_key\n");
516         return 1;
517     }
518 
519     /* Encrypting data and sending it to the destination */
520     UTIL_LOG_ERR("About to AES_ecb_encrypt byteCount\n");
521     AES_ecb_encrypt(pDataIn, pEncBuff, &encKey, AES_ENCRYPT);
522 
523     return 0;
524 }
525 
526 
527 
528 
529