1 /*
2  * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include "mbedtls/build_info.h"
7 
8 #if defined(MBEDTLS_CHACHAPOLY_C)
9 #include "mbedtls/chachapoly.h"
10 #include "mbedtls/error.h"
11 #include "poly.h"
12 #include "mbedtls/chacha20.h"
13 #include "mbedtls/platform_util.h"
14 #include "chacha_driver.h"
15 #include "cc_pal_abort.h"
16 #include "cc_pal_mem.h"
17 #include "cc_pal_types.h"
18 
19 
20 #if defined(MBEDTLS_SELF_TEST)
21 #if defined(MBEDTLS_PLATFORM_C)
22 #include "mbedtls/platform.h"
23 #else
24 #define mbedtls_printf printf
25 #endif /* MBEDTLS_PLATFORM_C */
26 #endif /* MBEDTLS_SELF_TEST */
27 
28 #if defined(MBEDTLS_CHACHAPOLY_ALT)
29 
mbedtls_chachapoly_init(mbedtls_chachapoly_context * ctx)30 void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
31 {
32     if (NULL == ctx)
33     {
34         CC_PalAbort("ctx cannot be NULL");
35     }
36 
37     mbedtls_platform_zeroize( ctx->key, sizeof( ctx->key ) );
38 
39 }
40 
mbedtls_chachapoly_free(mbedtls_chachapoly_context * ctx)41 void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
42 {
43     if (ctx == NULL) {
44         return;
45     }
46     mbedtls_platform_zeroize( ctx->key, sizeof( ctx->key ) );
47 }
48 
mbedtls_chachapoly_setkey(mbedtls_chachapoly_context * ctx,const unsigned char key[32])49 int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
50                                const unsigned char key[32] )
51 {
52     if ( (ctx == NULL) || (key == NULL)) {
53         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
54     }
55     CC_PalMemCopy(ctx->key, key, MBEDTLS_CHACHA_KEY_SIZE_BYTES);
56     return ( 0 );
57 }
58 
59 /* Cryptocell only supports integrated chachapoly operations  */
mbedtls_chachapoly_starts(mbedtls_chachapoly_context * ctx,const unsigned char nonce[12],mbedtls_chachapoly_mode_t mode)60 int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
61                                const unsigned char nonce[12],
62                                mbedtls_chachapoly_mode_t mode  )
63 {
64     CC_UNUSED_PARAM(ctx);
65     CC_UNUSED_PARAM(nonce);
66     CC_UNUSED_PARAM(mode);
67     return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
68 }
69 /* Cryptocell only supports integrated chachapoly operations  */
mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context * ctx,const unsigned char * aad,size_t aad_len)70 int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
71                                    const unsigned char *aad,
72                                    size_t aad_len )
73 {
74     CC_UNUSED_PARAM(ctx);
75     CC_UNUSED_PARAM(aad);
76     CC_UNUSED_PARAM(aad_len);
77     return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
78 }
79 
80 /* Cryptocell only supports integrated chachapoly operations  */
mbedtls_chachapoly_update(mbedtls_chachapoly_context * ctx,size_t len,const unsigned char * input,unsigned char * output)81 int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
82                                size_t len,
83                                const unsigned char *input,
84                                unsigned char *output )
85 {
86     CC_UNUSED_PARAM(ctx);
87     CC_UNUSED_PARAM(len);
88     CC_UNUSED_PARAM(input);
89     CC_UNUSED_PARAM(output);
90     return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
91 }
92 
93 /* Cryptocell only supports integrated chachapoly operations  */
mbedtls_chachapoly_finish(mbedtls_chachapoly_context * ctx,unsigned char mac[16])94 int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
95                                unsigned char mac[16] )
96 {
97     CC_UNUSED_PARAM(ctx);
98     CC_UNUSED_PARAM(mac);
99     return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
100 }
101 
chachapoly_crypt_and_tag(mbedtls_chachapoly_mode_t mode,size_t length,const unsigned char nonce[12],const unsigned char key[32],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])102 static int chachapoly_crypt_and_tag( mbedtls_chachapoly_mode_t mode,
103                                      size_t length,
104                                      const unsigned char nonce[12],
105                                      const unsigned char key[32],
106                                      const unsigned char *aad,
107                                      size_t aad_len,
108                                      const unsigned char *input,
109                                      unsigned char *output,
110                                      unsigned char tag[16] )
111 {
112     int rc;
113     uint8_t chachaInState[MBEDTLS_CHACHA_BLOCK_SIZE_BYTES] = {0};
114     uint8_t chachaOutState[MBEDTLS_CHACHA_BLOCK_SIZE_BYTES] = {0};
115     mbedtls_poly_key polyKey = {0};
116     mbedtls_poly_mac polyMac = {0};
117     const uint8_t *pCipherData = NULL;
118 
119     if (key == NULL) {
120         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
121     }
122 
123     if (mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
124         pCipherData = output;
125     } else if (mode == MBEDTLS_CHACHAPOLY_DECRYPT) {
126         pCipherData = input;
127     } else {
128         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
129     }
130 
131     // 1. Generate poly key
132     // Calling mbedtls_chacha with data=0 is like performing the chacha block function without the encryption
133     rc = mbedtls_chacha20_crypt( key, nonce, 0, sizeof(chachaInState), chachaInState, chachaOutState );
134     if (rc != 0) {
135         goto end_with_error;
136     }
137     // poly key defined as the first 32 bytes of chacha output.
138     CC_PalMemCopy(polyKey, chachaOutState, sizeof(polyKey));
139 
140     // 2. Encryption pDataIn
141     if (mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
142         rc = mbedtls_chacha20_crypt( key, nonce, 1, length, (uint8_t *)input, (uint8_t *)output );
143         if (rc != 0) {
144             goto end_with_error;
145         }
146     }
147 
148     // 3. Authentication
149     rc = PolyMacCalc(polyKey, aad, aad_len, pCipherData, length, polyMac, true);
150     if (rc != 0) {
151         rc = MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
152         goto end_with_error;
153     }
154 
155     CC_PalMemCopy(tag, polyMac, sizeof(polyMac));
156 
157     if (mode == MBEDTLS_CHACHAPOLY_DECRYPT) {
158         rc = mbedtls_chacha20_crypt( key, nonce, 1, length, (uint8_t *)input, (uint8_t *)output );
159         if (rc != 0) {
160             goto end_with_error;
161         }
162     }
163 
164     return ( 0 );
165 
166     end_with_error:
167     if (output != NULL) {
168         CC_PalMemSetZero(output, length);
169     }
170     return rc;
171 }
172 
mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])173 int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
174                                         size_t length,
175                                         const unsigned char nonce[12],
176                                         const unsigned char *aad,
177                                         size_t aad_len,
178                                         const unsigned char *input,
179                                         unsigned char *output,
180                                         unsigned char tag[16] )
181 {
182 
183     if ( (ctx == NULL) || (nonce == NULL) || (tag == NULL) ) {
184         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
185     }
186 
187     if ( aad_len != 0 && aad == NULL ) {
188         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
189     }
190     if ( length != 0 && input == NULL ) {
191         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
192     }
193     if ( length != 0 && output == NULL ) {
194         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
195     }
196 
197     return( chachapoly_crypt_and_tag( MBEDTLS_CHACHAPOLY_ENCRYPT,
198                                       length, nonce, ctx->key, aad, aad_len,
199                                       input, output, tag ) );
200 }
201 
mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char tag[16],const unsigned char * input,unsigned char * output)202 int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
203                                      size_t length,
204                                      const unsigned char nonce[12],
205                                      const unsigned char *aad,
206                                      size_t aad_len,
207                                      const unsigned char tag[16],
208                                      const unsigned char *input,
209                                      unsigned char *output )
210 {
211     unsigned char check_tag[16];
212     int ret;
213     int diff;
214     size_t i;
215 
216     if ( (nonce == NULL) || (tag == NULL) ) {
217         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
218     }
219 
220     if ( aad_len != 0 && aad == NULL ) {
221         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
222     }
223     if ( length != 0 && input == NULL ) {
224         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
225     }
226     if ( length != 0 && output == NULL ) {
227         return MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA;
228     }
229 
230     if ( (ret = chachapoly_crypt_and_tag( MBEDTLS_CHACHAPOLY_DECRYPT,
231                                       length, nonce, ctx->key, aad, aad_len,
232                                       input, output, check_tag ) ) != 0 ) {
233         return( ret );
234     }
235 
236     /* Check tag in "constant-time" */
237     for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
238         diff |= tag[i] ^ check_tag[i];
239 
240     if( diff != 0 )
241     {
242         mbedtls_platform_zeroize( output, length );
243         return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
244     }
245     return ( 0 );
246 
247 }
248 
249 #endif /* !MBEDTLS_CHACHAPOLY_ALT */
250 
251 #endif /* !MBEDTLS_CHACHAPOLY_C */
252