@@ -35,25 +35,56 @@ Public domain.
3535
3636#include <wolfssl/wolfcrypt/settings.h>
3737
38+ #ifdef HAVE_CHACHA
39+ #include <wolfssl/wolfcrypt/chacha.h>
40+ #include <wolfssl/wolfcrypt/error-crypt.h>
41+
42+ #ifdef NO_INLINE
43+ #include <wolfssl/wolfcrypt/misc.h>
44+ #else
45+ #define WOLFSSL_MISC_INCLUDED
46+ #include <wolfcrypt/src/misc.c>
47+ #endif
48+
49+ #ifdef BIG_ENDIAN_ORDER
50+ #define LITTLE32 (x ) ByteReverseWord32(x)
51+ #else
52+ #define LITTLE32 (x ) (x)
53+ #endif
54+
55+ /* Number of rounds */
56+ #define ROUNDS 20
57+
58+ #define U32C (v ) (v##U)
59+ #define U32V (v ) ((word32)(v) & U32C(0xFFFFFFFF))
60+ #define U8TO32_LITTLE (p ) LITTLE32(((word32*)(p))[0])
61+
62+ #define ROTATE (v ,c ) rotlFixed(v, c)
63+ #define XOR (v ,w ) ((v) ^ (w))
64+ #define PLUS (v ,w ) (U32V((v) + (w)))
65+ #define PLUSONE (v ) (PLUS((v),1))
66+
67+ #define QUARTERROUND (a ,b ,c ,d ) \
68+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
69+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
70+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
71+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
72+ #endif /* HAVE_CHACHA */
73+
74+
3875#if defined(WOLFSSL_ARMASM ) && !defined(WOLFSSL_ARMASM_NO_NEON )
3976 /* implementation is located in wolfcrypt/src/port/arm/armv8-chacha.c */
4077
4178#elif defined(WOLFSSL_RISCV_ASM )
4279 /* implementation located in wolfcrypt/src/port/rsicv/riscv-64-chacha.c */
4380
4481#else
82+
83+ /* BEGIN ChaCha C implementation */
4584#if defined(HAVE_CHACHA )
4685
47- #include <wolfssl/wolfcrypt/chacha.h>
48- #include <wolfssl/wolfcrypt/error-crypt.h>
4986#include <wolfssl/wolfcrypt/logging.h>
5087#include <wolfssl/wolfcrypt/cpuid.h>
51- #ifdef NO_INLINE
52- #include <wolfssl/wolfcrypt/misc.h>
53- #else
54- #define WOLFSSL_MISC_INCLUDED
55- #include <wolfcrypt/src/misc.c>
56- #endif
5788
5889#ifdef CHACHA_AEAD_TEST
5990 #include <stdio.h>
@@ -88,31 +119,6 @@ Public domain.
88119 static word32 cpuidFlags = 0 ;
89120#endif
90121
91- #ifdef BIG_ENDIAN_ORDER
92- #define LITTLE32 (x ) ByteReverseWord32(x)
93- #else
94- #define LITTLE32 (x ) (x)
95- #endif
96-
97- /* Number of rounds */
98- #define ROUNDS 20
99-
100- #define U32C (v ) (v##U)
101- #define U32V (v ) ((word32)(v) & U32C(0xFFFFFFFF))
102- #define U8TO32_LITTLE (p ) LITTLE32(((word32*)(p))[0])
103-
104- #define ROTATE (v ,c ) rotlFixed(v, c)
105- #define XOR (v ,w ) ((v) ^ (w))
106- #define PLUS (v ,w ) (U32V((v) + (w)))
107- #define PLUSONE (v ) (PLUS((v),1))
108-
109- #define QUARTERROUND (a ,b ,c ,d ) \
110- x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
111- x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
112- x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
113- x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
114-
115-
116122/**
117123 * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version
118124 * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB.
@@ -238,86 +244,6 @@ static WC_INLINE void wc_Chacha_wordtobyte(word32 x[CHACHA_CHUNK_WORDS],
238244}
239245#endif /* !USE_INTEL_CHACHA_SPEEDUP */
240246
241-
242- #ifdef HAVE_XCHACHA
243-
244- /*
245- * wc_HChacha_block - half a ChaCha block, for XChaCha
246- *
247- * see https://tools.ietf.org/html/draft-arciszewski-xchacha-03
248- */
249- static WC_INLINE void wc_HChacha_block (ChaCha * ctx , word32 stream [CHACHA_CHUNK_WORDS /2 ], word32 nrounds )
250- {
251- word32 x [CHACHA_CHUNK_WORDS ];
252- word32 i ;
253-
254- for (i = 0 ; i < CHACHA_CHUNK_WORDS ; i ++ ) {
255- x [i ] = ctx -> X [i ];
256- }
257-
258- for (i = nrounds ; i > 0 ; i -= 2 ) {
259- QUARTERROUND (0 , 4 , 8 , 12 )
260- QUARTERROUND (1 , 5 , 9 , 13 )
261- QUARTERROUND (2 , 6 , 10 , 14 )
262- QUARTERROUND (3 , 7 , 11 , 15 )
263- QUARTERROUND (0 , 5 , 10 , 15 )
264- QUARTERROUND (1 , 6 , 11 , 12 )
265- QUARTERROUND (2 , 7 , 8 , 13 )
266- QUARTERROUND (3 , 4 , 9 , 14 )
267- }
268-
269- for (i = 0 ; i < CHACHA_CHUNK_WORDS /4 ; ++ i )
270- stream [i ] = x [i ];
271- for (i = CHACHA_CHUNK_WORDS /4 ; i < CHACHA_CHUNK_WORDS /2 ; ++ i )
272- stream [i ] = x [i + CHACHA_CHUNK_WORDS /2 ];
273- }
274-
275- /* XChaCha -- https://tools.ietf.org/html/draft-arciszewski-xchacha-03 */
276- int wc_XChacha_SetKey (ChaCha * ctx ,
277- const byte * key , word32 keySz ,
278- const byte * nonce , word32 nonceSz ,
279- word32 counter ) {
280- word32 k [CHACHA_MAX_KEY_SZ ];
281- byte iv [CHACHA_IV_BYTES ];
282- int ret ;
283-
284- if (nonceSz != XCHACHA_NONCE_BYTES )
285- return BAD_FUNC_ARG ;
286-
287- if ((ret = wc_Chacha_SetKey (ctx , key , keySz )) < 0 )
288- return ret ;
289-
290- /* form a first chacha IV from the first 16 bytes of the nonce.
291- * the first word is supplied in the "counter" arg, and
292- * the result is a full 128 bit nonceful IV for the one-time block
293- * crypto op that follows.
294- */
295- if ((ret = wc_Chacha_SetIV (ctx , nonce + 4 , U8TO32_LITTLE (nonce ))) < 0 )
296- return ret ;
297-
298- wc_HChacha_block (ctx , k , 20 ); /* 20 rounds, but keeping half the output. */
299-
300- /* the HChacha output is used as a 256 bit key for the main cipher. */
301- XMEMCPY (& ctx -> X [4 ], k , 8 * sizeof (word32 ));
302-
303- /* use 8 bytes from the end of the 24 byte nonce, padded up to 12 bytes,
304- * to form the IV for the main cipher.
305- */
306- XMEMSET (iv , 0 , 4 );
307- XMEMCPY (iv + 4 , nonce + 16 , 8 );
308-
309- if ((ret = wc_Chacha_SetIV (ctx , iv , counter )) < 0 )
310- return ret ;
311-
312- ForceZero (k , sizeof k );
313- ForceZero (iv , sizeof iv );
314-
315- return 0 ;
316- }
317-
318- #endif /* HAVE_XCHACHA */
319-
320-
321247#ifdef __cplusplus
322248 extern "C" {
323249#endif
@@ -441,14 +367,94 @@ int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input,
441367#endif
442368}
443369
444- void wc_Chacha_purge_current_block (ChaCha * ctx ) {
370+ #endif /* HAVE_CHACHA */
371+ #endif /* END ChaCha C implementation */
372+
373+ #if defined(HAVE_CHACHA ) && defined(HAVE_XCHACHA )
374+
375+ void wc_Chacha_purge_current_block (ChaCha * ctx )
376+ {
445377 if (ctx -> left > 0 ) {
446378 byte scratch [CHACHA_CHUNK_BYTES ];
447379 XMEMSET (scratch , 0 , sizeof (scratch ));
448380 (void )wc_Chacha_Process (ctx , scratch , scratch , CHACHA_CHUNK_BYTES - ctx -> left );
449381 }
450382}
451383
452- #endif /* HAVE_CHACHA */
384+ /*
385+ * wc_HChacha_block - half a ChaCha block, for XChaCha
386+ *
387+ * see https://tools.ietf.org/html/draft-arciszewski-xchacha-03
388+ */
389+ static WC_INLINE void wc_HChacha_block (ChaCha * ctx ,
390+ word32 stream [CHACHA_CHUNK_WORDS /2 ], word32 nrounds )
391+ {
392+ word32 x [CHACHA_CHUNK_WORDS ];
393+ word32 i ;
394+
395+ for (i = 0 ; i < CHACHA_CHUNK_WORDS ; i ++ ) {
396+ x [i ] = ctx -> X [i ];
397+ }
398+
399+ for (i = nrounds ; i > 0 ; i -= 2 ) {
400+ QUARTERROUND (0 , 4 , 8 , 12 )
401+ QUARTERROUND (1 , 5 , 9 , 13 )
402+ QUARTERROUND (2 , 6 , 10 , 14 )
403+ QUARTERROUND (3 , 7 , 11 , 15 )
404+ QUARTERROUND (0 , 5 , 10 , 15 )
405+ QUARTERROUND (1 , 6 , 11 , 12 )
406+ QUARTERROUND (2 , 7 , 8 , 13 )
407+ QUARTERROUND (3 , 4 , 9 , 14 )
408+ }
409+
410+ for (i = 0 ; i < CHACHA_CHUNK_WORDS /4 ; ++ i )
411+ stream [i ] = x [i ];
412+ for (i = CHACHA_CHUNK_WORDS /4 ; i < CHACHA_CHUNK_WORDS /2 ; ++ i )
413+ stream [i ] = x [i + CHACHA_CHUNK_WORDS /2 ];
414+ }
415+
416+ /* XChaCha -- https://tools.ietf.org/html/draft-arciszewski-xchacha-03 */
417+ int wc_XChacha_SetKey (ChaCha * ctx ,
418+ const byte * key , word32 keySz ,
419+ const byte * nonce , word32 nonceSz ,
420+ word32 counter )
421+ {
422+ int ret ;
423+ word32 k [CHACHA_MAX_KEY_SZ ];
424+ byte iv [CHACHA_IV_BYTES ];
425+
426+ if (nonceSz != XCHACHA_NONCE_BYTES )
427+ return BAD_FUNC_ARG ;
428+
429+ if ((ret = wc_Chacha_SetKey (ctx , key , keySz )) < 0 )
430+ return ret ;
431+
432+ /* form a first chacha IV from the first 16 bytes of the nonce.
433+ * the first word is supplied in the "counter" arg, and
434+ * the result is a full 128 bit nonceful IV for the one-time block
435+ * crypto op that follows.
436+ */
437+ if ((ret = wc_Chacha_SetIV (ctx , nonce + 4 , U8TO32_LITTLE (nonce ))) < 0 )
438+ return ret ;
439+
440+ wc_HChacha_block (ctx , k , 20 ); /* 20 rounds, but keeping half the output. */
441+
442+ /* the HChacha output is used as a 256 bit key for the main cipher. */
443+ XMEMCPY (& ctx -> X [4 ], k , 8 * sizeof (word32 ));
444+
445+ /* use 8 bytes from the end of the 24 byte nonce, padded up to 12 bytes,
446+ * to form the IV for the main cipher.
447+ */
448+ XMEMSET (iv , 0 , 4 );
449+ XMEMCPY (iv + 4 , nonce + 16 , 8 );
450+
451+ if ((ret = wc_Chacha_SetIV (ctx , iv , counter )) < 0 )
452+ return ret ;
453+
454+ ForceZero (k , sizeof k );
455+ ForceZero (iv , sizeof iv );
456+
457+ return 0 ;
458+ }
453459
454- #endif /* WOLFSSL_ARMASM && !WOLFSSL_ARMASM_NO_NEON */
460+ #endif /* HAVE_CHACHA && HAVE_XCHACHA */
0 commit comments