set chacha20 similar to aes-ctr when handling leftover stream and add test case

pull/2709/head
JacobBarthelmeh 2020-01-01 19:49:28 -08:00 committed by Jacob Barthelmeh
parent f3b2815e1f
commit 0ec7b311d8
4 changed files with 98 additions and 78 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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];