/src/nss-nspr/nss/lib/freebl/chacha20poly1305.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifdef FREEBL_NO_DEPEND |
6 | | #include "stubs.h" |
7 | | #endif |
8 | | |
9 | | #include <string.h> |
10 | | #include <stdio.h> |
11 | | |
12 | | #include "seccomon.h" |
13 | | #include "secerr.h" |
14 | | #include "blapit.h" |
15 | | #include "blapii.h" |
16 | | #include "chacha20poly1305.h" |
17 | | |
18 | | // There are three implementations of ChaCha20Poly1305: |
19 | | // 1) 128-bit with AVX hardware acceleration used on x64 |
20 | | // 2) 256-bit with AVX2 hardware acceleration used on x64 |
21 | | // 3) 32-bit used on all other platforms |
22 | | |
23 | | // On x64 when AVX2 and other necessary registers are available, |
24 | | // the 256bit-verctorized version will be used. When AVX2 features |
25 | | // are unavailable or disabled but AVX registers are available, the |
26 | | // 128bit-vectorized version will be used. In all other cases the |
27 | | // scalar version of the HACL* code will be used. |
28 | | |
29 | | // Instead of including the headers (they bring other things we don't want), |
30 | | // we declare the functions here. |
31 | | // Usage is guarded by runtime checks of required hardware features. |
32 | | |
33 | | // Forward declaration from Hacl_Chacha20_Vec128.h and Hacl_Chacha20Poly1305_128.h. |
34 | | extern void Hacl_Chacha20_Vec128_chacha20_encrypt_128(uint32_t len, uint8_t *out, |
35 | | uint8_t *text, uint8_t *key, |
36 | | uint8_t *n1, uint32_t ctr); |
37 | | extern void |
38 | | Hacl_Chacha20Poly1305_128_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
39 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
40 | | uint8_t *cipher, uint8_t *mac); |
41 | | extern uint32_t |
42 | | Hacl_Chacha20Poly1305_128_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
43 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
44 | | uint8_t *cipher, uint8_t *mac); |
45 | | |
46 | | // Forward declaration from Hacl_Chacha20_Vec256.h and Hacl_Chacha20Poly1305_256.h. |
47 | | extern void Hacl_Chacha20_Vec256_chacha20_encrypt_256(uint32_t len, uint8_t *out, |
48 | | uint8_t *text, uint8_t *key, |
49 | | uint8_t *n1, uint32_t ctr); |
50 | | extern void |
51 | | Hacl_Chacha20Poly1305_256_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
52 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
53 | | uint8_t *cipher, uint8_t *mac); |
54 | | extern uint32_t |
55 | | Hacl_Chacha20Poly1305_256_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
56 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
57 | | uint8_t *cipher, uint8_t *mac); |
58 | | |
59 | | // Forward declaration from Hacl_Chacha20.h and Hacl_Chacha20Poly1305_32.h. |
60 | | extern void Hacl_Chacha20_chacha20_encrypt(uint32_t len, uint8_t *out, |
61 | | uint8_t *text, uint8_t *key, |
62 | | uint8_t *n1, uint32_t ctr); |
63 | | extern void |
64 | | Hacl_Chacha20Poly1305_32_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
65 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
66 | | uint8_t *cipher, uint8_t *mac); |
67 | | extern uint32_t |
68 | | Hacl_Chacha20Poly1305_32_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
69 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
70 | | uint8_t *cipher, uint8_t *mac); |
71 | | |
72 | | // Forward declaration from chacha20-ppc64le.S |
73 | | void chacha20vsx(uint32_t len, uint8_t *output, uint8_t *block, uint8_t *k, |
74 | | uint8_t *nonce, uint32_t ctr); |
75 | | |
76 | | // Forward declaration from chacha20poly1305-ppc.c |
77 | | extern void |
78 | | Chacha20Poly1305_vsx_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
79 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
80 | | uint8_t *cipher, uint8_t *mac); |
81 | | extern uint32_t |
82 | | Chacha20Poly1305_vsx_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, |
83 | | uint8_t *aad, uint32_t mlen, uint8_t *m, |
84 | | uint8_t *cipher, uint8_t *mac); |
85 | | |
86 | | SECStatus |
87 | | ChaCha20_InitContext(ChaCha20Context *ctx, const unsigned char *key, |
88 | | unsigned int keyLen, const unsigned char *nonce, |
89 | | unsigned int nonceLen, PRUint32 ctr) |
90 | 0 | { |
91 | | #ifdef NSS_DISABLE_CHACHAPOLY |
92 | | return SECFailure; |
93 | | #else |
94 | 0 | if (keyLen != 32) { |
95 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
96 | 0 | return SECFailure; |
97 | 0 | } |
98 | 0 | if (nonceLen != 12) { |
99 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
100 | 0 | return SECFailure; |
101 | 0 | } |
102 | | |
103 | 0 | ctx->counter = ctr; |
104 | 0 | PORT_Memcpy(ctx->key, key, sizeof(ctx->key)); |
105 | 0 | PORT_Memcpy(ctx->nonce, nonce, sizeof(ctx->nonce)); |
106 | |
|
107 | 0 | NSS_CLASSIFY(ctx->nonce, sizeof(ctx->nonce)); |
108 | 0 | NSS_CLASSIFY(ctx->key, sizeof(ctx->key)); |
109 | |
|
110 | 0 | return SECSuccess; |
111 | 0 | #endif |
112 | 0 | } |
113 | | |
114 | | ChaCha20Context * |
115 | | ChaCha20_CreateContext(const unsigned char *key, unsigned int keyLen, |
116 | | const unsigned char *nonce, unsigned int nonceLen, |
117 | | PRUint32 ctr) |
118 | 0 | { |
119 | | #ifdef NSS_DISABLE_CHACHAPOLY |
120 | | return NULL; |
121 | | #else |
122 | 0 | ChaCha20Context *ctx; |
123 | |
|
124 | 0 | ctx = PORT_New(ChaCha20Context); |
125 | 0 | if (ctx == NULL) { |
126 | 0 | return NULL; |
127 | 0 | } |
128 | | |
129 | 0 | if (ChaCha20_InitContext(ctx, key, keyLen, nonce, nonceLen, ctr) != SECSuccess) { |
130 | 0 | PORT_Free(ctx); |
131 | 0 | ctx = NULL; |
132 | 0 | } |
133 | |
|
134 | 0 | return ctx; |
135 | 0 | #endif |
136 | 0 | } |
137 | | |
138 | | void |
139 | | ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit) |
140 | 0 | { |
141 | 0 | #ifndef NSS_DISABLE_CHACHAPOLY |
142 | 0 | PORT_Memset(ctx, 0, sizeof(*ctx)); |
143 | 0 | if (freeit) { |
144 | 0 | PORT_Free(ctx); |
145 | 0 | } |
146 | 0 | #endif |
147 | 0 | } |
148 | | |
149 | | SECStatus |
150 | | ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx, |
151 | | const unsigned char *key, unsigned int keyLen, |
152 | | unsigned int tagLen) |
153 | 164 | { |
154 | | #ifdef NSS_DISABLE_CHACHAPOLY |
155 | | return SECFailure; |
156 | | #else |
157 | 164 | if (keyLen != 32) { |
158 | 1 | PORT_SetError(SEC_ERROR_BAD_KEY); |
159 | 1 | return SECFailure; |
160 | 1 | } |
161 | 163 | if (tagLen != 16) { |
162 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
163 | 0 | return SECFailure; |
164 | 0 | } |
165 | | |
166 | 163 | PORT_Memcpy(ctx->key, key, sizeof(ctx->key)); |
167 | 163 | ctx->tagLen = tagLen; |
168 | | |
169 | 163 | NSS_CLASSIFY(ctx->key, sizeof(ctx->key)); |
170 | | |
171 | 163 | return SECSuccess; |
172 | 163 | #endif |
173 | 163 | } |
174 | | |
175 | | ChaCha20Poly1305Context * |
176 | | ChaCha20Poly1305_CreateContext(const unsigned char *key, unsigned int keyLen, |
177 | | unsigned int tagLen) |
178 | 156 | { |
179 | | #ifdef NSS_DISABLE_CHACHAPOLY |
180 | | return NULL; |
181 | | #else |
182 | 156 | ChaCha20Poly1305Context *ctx; |
183 | | |
184 | 156 | ctx = PORT_New(ChaCha20Poly1305Context); |
185 | 156 | if (ctx == NULL) { |
186 | 0 | return NULL; |
187 | 0 | } |
188 | | |
189 | 156 | if (ChaCha20Poly1305_InitContext(ctx, key, keyLen, tagLen) != SECSuccess) { |
190 | 0 | PORT_Free(ctx); |
191 | 0 | ctx = NULL; |
192 | 0 | } |
193 | | |
194 | 156 | return ctx; |
195 | 156 | #endif |
196 | 156 | } |
197 | | |
198 | | void |
199 | | ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit) |
200 | 163 | { |
201 | 163 | #ifndef NSS_DISABLE_CHACHAPOLY |
202 | 163 | PORT_Memset(ctx, 0, sizeof(*ctx)); |
203 | 163 | if (freeit) { |
204 | 156 | PORT_Free(ctx); |
205 | 156 | } |
206 | 163 | #endif |
207 | 163 | } |
208 | | |
209 | | #ifndef NSS_DISABLE_CHACHAPOLY |
210 | | void |
211 | | ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k, |
212 | | uint8_t *nonce, uint32_t ctr) |
213 | 0 | { |
214 | 0 | #ifdef NSS_X64 |
215 | 0 | #ifndef NSS_DISABLE_AVX2 |
216 | 0 | if (avx2_support()) { |
217 | 0 | Hacl_Chacha20_Vec256_chacha20_encrypt_256(len, output, block, k, nonce, ctr); |
218 | 0 | return; |
219 | 0 | } |
220 | 0 | #endif |
221 | | |
222 | 0 | #ifndef NSS_DISABLE_SSE3 |
223 | 0 | if (ssse3_support() && sse4_1_support() && avx_support()) { |
224 | 0 | Hacl_Chacha20_Vec128_chacha20_encrypt_128(len, output, block, k, nonce, ctr); |
225 | 0 | return; |
226 | 0 | } |
227 | 0 | #endif |
228 | | |
229 | | #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \ |
230 | | !defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX) |
231 | | if (ppc_crypto_support()) { |
232 | | chacha20vsx(len, output, block, k, nonce, ctr); |
233 | | return; |
234 | | } |
235 | | #endif |
236 | 0 | { |
237 | 0 | Hacl_Chacha20_chacha20_encrypt(len, output, block, k, nonce, ctr); |
238 | 0 | return; |
239 | 0 | } |
240 | 0 | } |
241 | | #endif /* NSS_DISABLE_CHACHAPOLY */ |
242 | | |
243 | | SECStatus |
244 | | ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len, |
245 | | const unsigned char *k, const unsigned char *nonce, PRUint32 ctr) |
246 | 0 | { |
247 | | #ifdef NSS_DISABLE_CHACHAPOLY |
248 | | return SECFailure; |
249 | | #else |
250 | | // ChaCha has a 64 octet block, with a 32-bit block counter. |
251 | 0 | if (sizeof(len) > 4) { |
252 | 0 | unsigned long long len_ull = len; |
253 | 0 | if (len_ull >= (1ULL << (6 + 32))) { |
254 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
255 | 0 | return SECFailure; |
256 | 0 | } |
257 | 0 | } |
258 | 0 | ChaCha20Xor(output, (uint8_t *)block, len, (uint8_t *)k, |
259 | 0 | (uint8_t *)nonce, ctr); |
260 | 0 | return SECSuccess; |
261 | 0 | #endif |
262 | 0 | } |
263 | | |
264 | | SECStatus |
265 | | ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, |
266 | | unsigned int *outputLen, unsigned int maxOutputLen, |
267 | | const unsigned char *input, unsigned int inputLen, |
268 | | const unsigned char *nonce, unsigned int nonceLen, |
269 | | const unsigned char *ad, unsigned int adLen) |
270 | 0 | { |
271 | | #ifdef NSS_DISABLE_CHACHAPOLY |
272 | | return SECFailure; |
273 | | #else |
274 | |
|
275 | 0 | if (nonceLen != 12) { |
276 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
277 | 0 | return SECFailure; |
278 | 0 | } |
279 | | // ChaCha has a 64 octet block, with a 32-bit block counter. |
280 | 0 | if (sizeof(inputLen) > 4) { |
281 | 0 | unsigned long long inputLen_ull = inputLen; |
282 | 0 | if (inputLen_ull >= (1ULL << (6 + 32))) { |
283 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
284 | 0 | return SECFailure; |
285 | 0 | } |
286 | 0 | } |
287 | 0 | if (maxOutputLen < inputLen + ctx->tagLen) { |
288 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
289 | 0 | return SECFailure; |
290 | 0 | } |
291 | | |
292 | 0 | #ifdef NSS_X64 |
293 | 0 | #ifndef NSS_DISABLE_AVX2 |
294 | 0 | if (avx2_support()) { |
295 | 0 | Hacl_Chacha20Poly1305_256_aead_encrypt( |
296 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
297 | 0 | (uint8_t *)input, output, output + inputLen); |
298 | 0 | goto finish; |
299 | 0 | } |
300 | 0 | #endif |
301 | | |
302 | 0 | #ifndef NSS_DISABLE_SSE3 |
303 | 0 | if (ssse3_support() && sse4_1_support() && avx_support()) { |
304 | 0 | Hacl_Chacha20Poly1305_128_aead_encrypt( |
305 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
306 | 0 | (uint8_t *)input, output, output + inputLen); |
307 | 0 | goto finish; |
308 | 0 | } |
309 | 0 | #endif |
310 | | |
311 | | #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \ |
312 | | !defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX) |
313 | | if (ppc_crypto_support()) { |
314 | | Chacha20Poly1305_vsx_aead_encrypt( |
315 | | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
316 | | (uint8_t *)input, output, output + inputLen); |
317 | | goto finish; |
318 | | } |
319 | | #endif |
320 | 0 | { |
321 | 0 | Hacl_Chacha20Poly1305_32_aead_encrypt( |
322 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
323 | 0 | (uint8_t *)input, output, output + inputLen); |
324 | 0 | goto finish; |
325 | 0 | } |
326 | | |
327 | 0 | finish: |
328 | 0 | *outputLen = inputLen + ctx->tagLen; |
329 | 0 | return SECSuccess; |
330 | 0 | #endif |
331 | 0 | } |
332 | | |
333 | | SECStatus |
334 | | ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output, |
335 | | unsigned int *outputLen, unsigned int maxOutputLen, |
336 | | const unsigned char *input, unsigned int inputLen, |
337 | | const unsigned char *nonce, unsigned int nonceLen, |
338 | | const unsigned char *ad, unsigned int adLen) |
339 | 7 | { |
340 | | #ifdef NSS_DISABLE_CHACHAPOLY |
341 | | return SECFailure; |
342 | | #else |
343 | 7 | unsigned int ciphertextLen; |
344 | | |
345 | 7 | if (nonceLen != 12) { |
346 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
347 | 0 | return SECFailure; |
348 | 0 | } |
349 | 7 | if (inputLen < ctx->tagLen) { |
350 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
351 | 0 | return SECFailure; |
352 | 0 | } |
353 | 7 | ciphertextLen = inputLen - ctx->tagLen; |
354 | 7 | if (maxOutputLen < ciphertextLen) { |
355 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
356 | 0 | return SECFailure; |
357 | 0 | } |
358 | | // ChaCha has a 64 octet block, with a 32-bit block counter. |
359 | 7 | if (inputLen >= (1ULL << (6 + 32)) + ctx->tagLen) { |
360 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
361 | 0 | return SECFailure; |
362 | 0 | } |
363 | | |
364 | 7 | uint32_t res = 1; |
365 | 7 | #ifdef NSS_X64 |
366 | 7 | #ifndef NSS_DISABLE_AVX2 |
367 | 7 | if (avx2_support()) { |
368 | 7 | res = Hacl_Chacha20Poly1305_256_aead_decrypt( |
369 | 7 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
370 | 7 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen); |
371 | 7 | goto finish; |
372 | 7 | } |
373 | 0 | #endif |
374 | | |
375 | 0 | #ifndef NSS_DISABLE_SSE3 |
376 | 0 | if (ssse3_support() && sse4_1_support() && avx_support()) { |
377 | 0 | res = Hacl_Chacha20Poly1305_128_aead_decrypt( |
378 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
379 | 0 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen); |
380 | 0 | goto finish; |
381 | 0 | } |
382 | 0 | #endif |
383 | | |
384 | | #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \ |
385 | | !defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX) |
386 | | if (ppc_crypto_support()) { |
387 | | res = Chacha20Poly1305_vsx_aead_decrypt( |
388 | | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
389 | | (uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen); |
390 | | goto finish; |
391 | | } |
392 | | #endif |
393 | 0 | { |
394 | 0 | res = Hacl_Chacha20Poly1305_32_aead_decrypt( |
395 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
396 | 0 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen); |
397 | 0 | goto finish; |
398 | 0 | } |
399 | | |
400 | 7 | finish: |
401 | 7 | if (res) { |
402 | 7 | PORT_SetError(SEC_ERROR_BAD_DATA); |
403 | 7 | return SECFailure; |
404 | 7 | } |
405 | | |
406 | 0 | *outputLen = ciphertextLen; |
407 | 0 | return SECSuccess; |
408 | 7 | #endif |
409 | 7 | } |
410 | | |
411 | | SECStatus |
412 | | ChaCha20Poly1305_Encrypt(const ChaCha20Poly1305Context *ctx, |
413 | | unsigned char *output, unsigned int *outputLen, |
414 | | unsigned int maxOutputLen, const unsigned char *input, |
415 | | unsigned int inputLen, const unsigned char *nonce, |
416 | | unsigned int nonceLen, const unsigned char *ad, |
417 | | unsigned int adLen, unsigned char *outTag) |
418 | 0 | { |
419 | | #ifdef NSS_DISABLE_CHACHAPOLY |
420 | | return SECFailure; |
421 | | #else |
422 | |
|
423 | 0 | if (nonceLen != 12) { |
424 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
425 | 0 | return SECFailure; |
426 | 0 | } |
427 | | // ChaCha has a 64 octet block, with a 32-bit block counter. |
428 | 0 | if (sizeof(inputLen) > 4) { |
429 | 0 | unsigned long long inputLen_ull = inputLen; |
430 | 0 | if (inputLen_ull >= (1ULL << (6 + 32))) { |
431 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
432 | 0 | return SECFailure; |
433 | 0 | } |
434 | 0 | } |
435 | 0 | if (maxOutputLen < inputLen) { |
436 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
437 | 0 | return SECFailure; |
438 | 0 | } |
439 | | |
440 | 0 | #ifdef NSS_X64 |
441 | 0 | #ifndef NSS_DISABLE_AVX2 |
442 | 0 | if (avx2_support()) { |
443 | 0 | Hacl_Chacha20Poly1305_256_aead_encrypt( |
444 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
445 | 0 | (uint8_t *)input, output, outTag); |
446 | 0 | goto finish; |
447 | 0 | } |
448 | 0 | #endif |
449 | | |
450 | 0 | #ifndef NSS_DISABLE_SSE3 |
451 | 0 | if (ssse3_support() && sse4_1_support() && avx_support()) { |
452 | 0 | Hacl_Chacha20Poly1305_128_aead_encrypt( |
453 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
454 | 0 | (uint8_t *)input, output, outTag); |
455 | 0 | goto finish; |
456 | 0 | } |
457 | 0 | #endif |
458 | | #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \ |
459 | | !defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX) |
460 | | if (ppc_crypto_support()) { |
461 | | Chacha20Poly1305_vsx_aead_encrypt( |
462 | | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
463 | | (uint8_t *)input, output, outTag); |
464 | | goto finish; |
465 | | } |
466 | | #endif |
467 | 0 | { |
468 | 0 | Hacl_Chacha20Poly1305_32_aead_encrypt( |
469 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen, |
470 | 0 | (uint8_t *)input, output, outTag); |
471 | 0 | goto finish; |
472 | 0 | } |
473 | | |
474 | 0 | finish: |
475 | 0 | *outputLen = inputLen; |
476 | 0 | return SECSuccess; |
477 | 0 | #endif |
478 | 0 | } |
479 | | |
480 | | SECStatus |
481 | | ChaCha20Poly1305_Decrypt(const ChaCha20Poly1305Context *ctx, |
482 | | unsigned char *output, unsigned int *outputLen, |
483 | | unsigned int maxOutputLen, const unsigned char *input, |
484 | | unsigned int inputLen, const unsigned char *nonce, |
485 | | unsigned int nonceLen, const unsigned char *ad, |
486 | | unsigned int adLen, /* const */ unsigned char *tagIn) |
487 | 0 | { |
488 | | #ifdef NSS_DISABLE_CHACHAPOLY |
489 | | return SECFailure; |
490 | | #else |
491 | 0 | unsigned int ciphertextLen; |
492 | |
|
493 | 0 | if (nonceLen != 12) { |
494 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
495 | 0 | return SECFailure; |
496 | 0 | } |
497 | 0 | ciphertextLen = inputLen; |
498 | 0 | if (maxOutputLen < ciphertextLen) { |
499 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
500 | 0 | return SECFailure; |
501 | 0 | } |
502 | | // ChaCha has a 64 octet block, with a 32-bit block counter. |
503 | 0 | if (sizeof(inputLen) > 4) { |
504 | 0 | unsigned long long inputLen_ull = inputLen; |
505 | 0 | if (inputLen_ull >= (1ULL << (6 + 32))) { |
506 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
507 | 0 | return SECFailure; |
508 | 0 | } |
509 | 0 | } |
510 | | |
511 | 0 | uint32_t res = 1; |
512 | 0 | #ifdef NSS_X64 |
513 | 0 | #ifndef NSS_DISABLE_AVX2 |
514 | 0 | if (avx2_support()) { |
515 | 0 | res = Hacl_Chacha20Poly1305_256_aead_decrypt( |
516 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
517 | 0 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn); |
518 | 0 | goto finish; |
519 | 0 | } |
520 | 0 | #endif |
521 | | |
522 | 0 | #ifndef NSS_DISABLE_SSE3 |
523 | 0 | if (ssse3_support() && sse4_1_support() && avx_support()) { |
524 | 0 | res = Hacl_Chacha20Poly1305_128_aead_decrypt( |
525 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
526 | 0 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn); |
527 | 0 | goto finish; |
528 | 0 | } |
529 | 0 | #endif |
530 | | |
531 | | #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \ |
532 | | !defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX) |
533 | | if (ppc_crypto_support()) { |
534 | | res = Chacha20Poly1305_vsx_aead_decrypt( |
535 | | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
536 | | (uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn); |
537 | | goto finish; |
538 | | } |
539 | | #endif |
540 | 0 | { |
541 | 0 | res = Hacl_Chacha20Poly1305_32_aead_decrypt( |
542 | 0 | (uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen, |
543 | 0 | (uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn); |
544 | 0 | goto finish; |
545 | 0 | } |
546 | | |
547 | 0 | finish: |
548 | 0 | if (res) { |
549 | 0 | PORT_SetError(SEC_ERROR_BAD_DATA); |
550 | 0 | return SECFailure; |
551 | 0 | } |
552 | | |
553 | 0 | *outputLen = ciphertextLen; |
554 | 0 | return SECSuccess; |
555 | 0 | #endif |
556 | 0 | } |