diff --git a/tests/api.c b/tests/api.c index f59e0e9ae..a14ae4a2c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -9976,32 +9976,45 @@ static int test_wc_Chacha_Process (void) printf(testingFmt, "wc_Chacha_Process()"); ret = wc_Chacha_SetKey(&enc, key, keySz); - if (ret == 0) { - ret = wc_Chacha_SetKey(&dec, key, keySz); - if (ret == 0) { - ret = wc_Chacha_SetIV(&enc, cipher, 0); - } - if (ret == 0) { - ret = wc_Chacha_SetIV(&dec, cipher, 0); - } - } - if (ret == 0) { - ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen); - if (ret == 0) { - ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen); - if (ret == 0) { - ret = XMEMCMP(input, plain, (int)inlen); - } - } - } + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetKey(&dec, key, keySz); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&enc, cipher, 0); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&dec, cipher, 0); + AssertIntEQ(ret, 0); + + ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen); + AssertIntEQ(ret, 0); + ret = XMEMCMP(input, plain, (int)inlen); + AssertIntEQ(ret, 0); + + /* test checking and using leftovers */ + ret = wc_Chacha_SetIV(&enc, cipher, 0); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&dec, cipher, 0); + AssertIntEQ(ret, 0); + + ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen - 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&enc, cipher + (inlen - 2), + (byte*)input + (inlen - 2), 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, plain, (byte*)cipher, (word32)inlen - 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, cipher + (inlen - 2), + (byte*)input + (inlen - 2), 2); + AssertIntEQ(ret, 0); + ret = XMEMCMP(input, plain, (int)inlen); + AssertIntEQ(ret, 0); + /* Test bad args. */ - if (ret == 0) { - ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen); - if (ret == BAD_FUNC_ARG) { - ret = 0; - } else { - ret = WOLFSSL_FATAL_ERROR; - } + ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen); + AssertIntEQ(ret, BAD_FUNC_ARG); + if (ret == BAD_FUNC_ARG) { + ret = 0; } printf(resultFmt, ret == 0 ? passed : failed); @@ -10085,39 +10098,31 @@ static int test_wc_ChaCha20Poly1305_aead (void) ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, sizeof(plaintext), generatedCiphertext, generatedAuthTag); - if (ret == 0) { - ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte)); - } + AssertIntEQ(ret, 0); + ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte)); + AssertIntEQ(ret, 0); + /* Test bad args. */ - if (ret == 0) { - ret = wc_ChaCha20Poly1305_Encrypt(NULL, iv, aad, sizeof(aad), plaintext, + ret = wc_ChaCha20Poly1305_Encrypt(NULL, iv, aad, sizeof(aad), plaintext, sizeof(plaintext), generatedCiphertext, generatedAuthTag); - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad), + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad), plaintext, sizeof(plaintext), generatedCiphertext, generatedAuthTag); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL, + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL, sizeof(plaintext), generatedCiphertext, generatedAuthTag); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, 0, generatedCiphertext, generatedAuthTag); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, sizeof(plaintext), NULL, generatedAuthTag); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, sizeof(plaintext), generatedCiphertext, NULL); - } - if (ret == BAD_FUNC_ARG) { - ret = 0; - } else { - ret = WOLFSSL_FATAL_ERROR; - } + if (ret == BAD_FUNC_ARG) { + ret = 0; } printf(resultFmt, ret == 0 ? passed : failed); if (ret != 0) { @@ -10127,39 +10132,32 @@ static int test_wc_ChaCha20Poly1305_aead (void) printf(testingFmt, "wc_ChaCha20Poly1305_Decrypt()"); ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, sizeof(cipher), authTag, generatedPlaintext); - if (ret == 0) { - ret = XMEMCMP(generatedPlaintext, plaintext, + AssertIntEQ(ret, 0); + ret = XMEMCMP(generatedPlaintext, plaintext, sizeof(plaintext)/sizeof(byte)); - } + AssertIntEQ(ret, 0); + /* Test bad args. */ - if (ret == 0) { - ret = wc_ChaCha20Poly1305_Decrypt(NULL, iv, aad, sizeof(aad), cipher, + ret = wc_ChaCha20Poly1305_Decrypt(NULL, iv, aad, sizeof(aad), cipher, sizeof(cipher), authTag, generatedPlaintext); - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad), + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad), cipher, sizeof(cipher), authTag, generatedPlaintext); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL, + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL, sizeof(cipher), authTag, generatedPlaintext); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, sizeof(cipher), NULL, generatedPlaintext); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, sizeof(cipher), authTag, NULL); - } - if (ret == BAD_FUNC_ARG) { - ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, 0, authTag, generatedPlaintext); - } - if (ret == BAD_FUNC_ARG) { - ret = 0; - } else { - ret = WOLFSSL_FATAL_ERROR; - } + AssertIntEQ(ret, BAD_FUNC_ARG); + if (ret == BAD_FUNC_ARG) { + ret = 0; } printf(resultFmt, ret == 0 ? passed : failed); diff --git a/wolfcrypt/src/chacha.c b/wolfcrypt/src/chacha.c index 6b47e4266..427056c79 100644 --- a/wolfcrypt/src/chacha.c +++ b/wolfcrypt/src/chacha.c @@ -126,6 +126,7 @@ int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) XMEMCPY(temp, inIv, CHACHA_IV_BYTES); + ctx->left = 0; /* resets state */ ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */ ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */ ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */ @@ -200,6 +201,7 @@ int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) ctx->X[ 1] = constants[1]; ctx->X[ 2] = constants[2]; ctx->X[ 3] = constants[3]; + ctx->left = 0; /* resets state */ return 0; } @@ -260,18 +262,30 @@ static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, word32 bytes) { byte* output; - word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ word32 i; - output = (byte*)temp; + /* handle left overs */ + if (ctx->left > 0) { + output = (byte*)ctx->tmp + CHACHA_CHUNK_BYTES - ctx->left; + for (i = 0; i < bytes && i < ctx->left; i++) { + c[i] = m[i] ^ output[i]; + } + ctx->left = ctx->left - i; + bytes = bytes - i; + c += i; + m += i; + } + + output = (byte*)ctx->tmp; for (; bytes > 0;) { - wc_Chacha_wordtobyte(temp, ctx->X); + wc_Chacha_wordtobyte(ctx->tmp, ctx->X); ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); if (bytes <= CHACHA_CHUNK_BYTES) { for (i = 0; i < bytes; ++i) { c[i] = m[i] ^ output[i]; } + ctx->left = CHACHA_CHUNK_BYTES - i; return; } for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) { diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index e048c3067..64bc4c199 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -163,6 +163,12 @@ int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, CHACHA20_POLY1305_AEAD_KEYSIZE); } + /* advance counter by 1 after creating Poly1305 key */ + if (ret == 0) { + ret = wc_Chacha_SetIV(&aead->chacha, inIV, + CHACHA20_POLY1305_AEAD_INITIAL_COUNTER + 1); + } + if (ret == 0) { aead->state = CHACHA20_POLY1305_STATE_READY; } diff --git a/wolfssl/wolfcrypt/chacha.h b/wolfssl/wolfcrypt/chacha.h index 3cfd73106..1aa2b91a2 100644 --- a/wolfssl/wolfcrypt/chacha.h +++ b/wolfssl/wolfcrypt/chacha.h @@ -57,6 +57,8 @@ enum { typedef struct ChaCha { word32 X[CHACHA_CHUNK_WORDS]; /* state of cipher */ + word32 tmp[CHACHA_CHUNK_WORDS]; /* left over stream */ + word32 left; /* number of bytes leftover */ #ifdef HAVE_INTEL_AVX1 /* vpshufd reads 16 bytes but we only use bottom 4. */ byte extra[12];