mirror of https://github.com/wolfSSL/wolfssl.git
set chacha20 similar to aes-ctr when handling leftover stream and add test case
parent
f3b2815e1f
commit
0ec7b311d8
148
tests/api.c
148
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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue