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