1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_CC_API
8 
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "mbedtls_cc_chacha.h"
12 #include "mbedtls_cc_poly.h"
13 #include "poly.h"
14 #include "mbedtls_cc_chacha_poly_error.h"
15 
16 
mbedtls_chacha_poly(mbedtls_chacha_nonce pNonce,mbedtls_chacha_key pKey,mbedtls_chacha_encrypt_mode_t encryptDecryptFlag,uint8_t * pAddData,size_t addDataSize,uint8_t * pDataIn,size_t dataInSize,uint8_t * pDataOut,mbedtls_poly_mac macRes)17 CIMPORT_C CCError_t  mbedtls_chacha_poly(
18         mbedtls_chacha_nonce         pNonce,
19         mbedtls_chacha_key            pKey,
20         mbedtls_chacha_encrypt_mode_t    encryptDecryptFlag,
21         uint8_t          *pAddData,
22         size_t           addDataSize,
23         uint8_t                     *pDataIn,
24         size_t                       dataInSize,
25         uint8_t                     *pDataOut,
26         mbedtls_poly_mac         macRes)
27 
28 {
29     CCError_t rc;
30     uint8_t chachaInState[CC_CHACHA_BLOCK_SIZE_IN_BYTES] = {0};
31     uint8_t chachaOutState[CC_CHACHA_BLOCK_SIZE_IN_BYTES] = {0};
32     mbedtls_poly_key polyKey = {0};
33     mbedtls_poly_mac polyMac = {0};
34     uint8_t *pCipherData = NULL;
35 
36 
37     // Verify inputs
38     if ((pAddData == NULL) ^ (addDataSize == 0)) {
39         return CC_CHACHA_POLY_ADATA_INVALID_ERROR;
40     }
41     if ((pDataIn == NULL) ^ (dataInSize == 0)) {
42         return CC_CHACHA_POLY_DATA_INVALID_ERROR;
43     }
44     if (((pDataOut == NULL) ^ (pDataIn == NULL))||
45         (macRes == NULL) ||
46         (pNonce == NULL) ||
47         (pKey == NULL) ||
48         (dataInSize > CC_MAX_UINT32_VAL) ||
49         (addDataSize > CC_MAX_UINT32_VAL))
50         return CC_CHACHA_POLY_DATA_INVALID_ERROR;
51 
52 
53     if (encryptDecryptFlag == CC_CHACHA_Encrypt) {
54         pCipherData = pDataOut;
55     } else if (encryptDecryptFlag == CC_CHACHA_Decrypt) {
56         pCipherData = pDataIn;
57     } else {
58         return CC_CHACHA_POLY_ENC_MODE_INVALID_ERROR;
59     }
60 
61     // 1. Generate poly key
62     // Calling mbedtls_chacha with data=0 is like performing the chacha block function without the encryption
63     rc = mbedtls_chacha(pNonce, CC_CHACHA_Nonce96BitSize, pKey, 0, CC_CHACHA_Encrypt, chachaInState, sizeof(chachaInState), chachaOutState);
64     if (rc != CC_OK) {
65         rc = CC_CHACHA_POLY_GEN_KEY_ERROR;
66         goto end_with_error;
67     }
68     // poly key defined as the first 32 bytes of chacha output.
69     CC_PalMemCopy(polyKey, chachaOutState, sizeof(polyKey));
70 
71     // 2. Encryption pDataIn
72     if (encryptDecryptFlag == CC_CHACHA_Encrypt) {
73         rc = mbedtls_chacha(pNonce, CC_CHACHA_Nonce96BitSize, pKey, 1, encryptDecryptFlag, (uint8_t *)pDataIn,  dataInSize, (uint8_t *)pDataOut);
74         if (rc != CC_OK) {
75             rc = CC_CHACHA_POLY_ENCRYPTION_ERROR;
76             goto end_with_error;
77         }
78     }
79 
80     // 3. Authentication
81     rc = PolyMacCalc(polyKey, pAddData, addDataSize, pCipherData, dataInSize, polyMac, true);
82     if (rc != CC_OK) {
83         rc = CC_CHACHA_POLY_AUTH_ERROR;
84         goto end_with_error;
85     }
86     // 3.1. If encrypt, Calculate mac
87     if (encryptDecryptFlag == CC_CHACHA_Encrypt) {
88         CC_PalMemCopy(macRes, polyMac, sizeof(polyMac));
89         return CC_OK;
90     }
91 
92     // 3.2. If decrypt, first Verify the expected macRes with polyMac, than decrypt the msg
93     if (CC_PalMemCmp(macRes, polyMac, sizeof(polyMac)) != 0) {
94         rc = CC_CHACHA_POLY_MAC_ERROR;
95         goto end_with_error;
96     }
97     rc = mbedtls_chacha(pNonce, CC_CHACHA_Nonce96BitSize, pKey, 1, encryptDecryptFlag, (uint8_t *)pDataIn,  dataInSize, (uint8_t *)pDataOut);
98     if (rc != CC_OK) {
99         rc = CC_CHACHA_POLY_ENCRYPTION_ERROR;
100         goto end_with_error;
101     }
102     return CC_OK;
103 
104     end_with_error:
105     if (pDataOut != NULL) {
106         CC_PalMemSetZero(pDataOut, dataInSize);
107     }
108     return rc;
109 
110 }
111 
112