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