forked from wolfSSL/wolfssl
set chacha20 similar to aes-ctr when handling leftover stream and add test case
This commit is contained in:
committed by
Jacob Barthelmeh
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()");
|
printf(testingFmt, "wc_Chacha_Process()");
|
||||||
|
|
||||||
ret = wc_Chacha_SetKey(&enc, key, keySz);
|
ret = wc_Chacha_SetKey(&enc, key, keySz);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = wc_Chacha_SetKey(&dec, key, keySz);
|
ret = wc_Chacha_SetKey(&dec, key, keySz);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = wc_Chacha_SetIV(&enc, cipher, 0);
|
ret = wc_Chacha_SetIV(&enc, cipher, 0);
|
||||||
}
|
AssertIntEQ(ret, 0);
|
||||||
if (ret == 0) {
|
ret = wc_Chacha_SetIV(&dec, cipher, 0);
|
||||||
ret = wc_Chacha_SetIV(&dec, cipher, 0);
|
AssertIntEQ(ret, 0);
|
||||||
}
|
|
||||||
}
|
ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen);
|
ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen);
|
ret = XMEMCMP(input, plain, (int)inlen);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = XMEMCMP(input, plain, (int)inlen);
|
|
||||||
}
|
/* 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. */
|
/* Test bad args. */
|
||||||
if (ret == 0) {
|
ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen);
|
||||||
ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen);
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
if (ret == BAD_FUNC_ARG) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
|
||||||
ret = WOLFSSL_FATAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(resultFmt, ret == 0 ? passed : failed);
|
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,
|
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext,
|
||||||
sizeof(plaintext), generatedCiphertext, generatedAuthTag);
|
sizeof(plaintext), generatedCiphertext, generatedAuthTag);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte));
|
ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte));
|
||||||
}
|
AssertIntEQ(ret, 0);
|
||||||
|
|
||||||
/* Test bad args. */
|
/* 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);
|
sizeof(plaintext), generatedCiphertext, generatedAuthTag);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad),
|
ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad),
|
||||||
plaintext, sizeof(plaintext),
|
plaintext, sizeof(plaintext),
|
||||||
generatedCiphertext, generatedAuthTag);
|
generatedCiphertext, generatedAuthTag);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL,
|
||||||
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL,
|
|
||||||
sizeof(plaintext), generatedCiphertext, generatedAuthTag);
|
sizeof(plaintext), generatedCiphertext, generatedAuthTag);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
||||||
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
|
||||||
plaintext, 0, generatedCiphertext, generatedAuthTag);
|
plaintext, 0, generatedCiphertext, generatedAuthTag);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
||||||
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
|
||||||
plaintext, sizeof(plaintext), NULL, generatedAuthTag);
|
plaintext, sizeof(plaintext), NULL, generatedAuthTag);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
||||||
ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad),
|
|
||||||
plaintext, sizeof(plaintext), generatedCiphertext, NULL);
|
plaintext, sizeof(plaintext), generatedCiphertext, NULL);
|
||||||
}
|
if (ret == BAD_FUNC_ARG) {
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = 0;
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
ret = WOLFSSL_FATAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printf(resultFmt, ret == 0 ? passed : failed);
|
printf(resultFmt, ret == 0 ? passed : failed);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -10127,39 +10132,32 @@ static int test_wc_ChaCha20Poly1305_aead (void)
|
|||||||
printf(testingFmt, "wc_ChaCha20Poly1305_Decrypt()");
|
printf(testingFmt, "wc_ChaCha20Poly1305_Decrypt()");
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
||||||
sizeof(cipher), authTag, generatedPlaintext);
|
sizeof(cipher), authTag, generatedPlaintext);
|
||||||
if (ret == 0) {
|
AssertIntEQ(ret, 0);
|
||||||
ret = XMEMCMP(generatedPlaintext, plaintext,
|
ret = XMEMCMP(generatedPlaintext, plaintext,
|
||||||
sizeof(plaintext)/sizeof(byte));
|
sizeof(plaintext)/sizeof(byte));
|
||||||
}
|
AssertIntEQ(ret, 0);
|
||||||
|
|
||||||
/* Test bad args. */
|
/* 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);
|
sizeof(cipher), authTag, generatedPlaintext);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad),
|
ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad),
|
||||||
cipher, sizeof(cipher), authTag, generatedPlaintext);
|
cipher, sizeof(cipher), authTag, generatedPlaintext);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL,
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL,
|
|
||||||
sizeof(cipher), authTag, generatedPlaintext);
|
sizeof(cipher), authTag, generatedPlaintext);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
|
||||||
sizeof(cipher), NULL, generatedPlaintext);
|
sizeof(cipher), NULL, generatedPlaintext);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
|
||||||
sizeof(cipher), authTag, NULL);
|
sizeof(cipher), authTag, NULL);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
||||||
ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher,
|
|
||||||
0, authTag, generatedPlaintext);
|
0, authTag, generatedPlaintext);
|
||||||
}
|
AssertIntEQ(ret, BAD_FUNC_ARG);
|
||||||
if (ret == BAD_FUNC_ARG) {
|
if (ret == BAD_FUNC_ARG) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
|
||||||
ret = WOLFSSL_FATAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(resultFmt, ret == 0 ? passed : failed);
|
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);
|
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+0] = counter; /* block counter */
|
||||||
ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */
|
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 */
|
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[ 1] = constants[1];
|
||||||
ctx->X[ 2] = constants[2];
|
ctx->X[ 2] = constants[2];
|
||||||
ctx->X[ 3] = constants[3];
|
ctx->X[ 3] = constants[3];
|
||||||
|
ctx->left = 0; /* resets state */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -260,18 +262,30 @@ static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c,
|
|||||||
word32 bytes)
|
word32 bytes)
|
||||||
{
|
{
|
||||||
byte* output;
|
byte* output;
|
||||||
word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
|
|
||||||
word32 i;
|
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;) {
|
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]);
|
ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]);
|
||||||
if (bytes <= CHACHA_CHUNK_BYTES) {
|
if (bytes <= CHACHA_CHUNK_BYTES) {
|
||||||
for (i = 0; i < bytes; ++i) {
|
for (i = 0; i < bytes; ++i) {
|
||||||
c[i] = m[i] ^ output[i];
|
c[i] = m[i] ^ output[i];
|
||||||
}
|
}
|
||||||
|
ctx->left = CHACHA_CHUNK_BYTES - i;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) {
|
for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) {
|
||||||
|
@ -163,6 +163,12 @@ int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead,
|
|||||||
CHACHA20_POLY1305_AEAD_KEYSIZE);
|
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) {
|
if (ret == 0) {
|
||||||
aead->state = CHACHA20_POLY1305_STATE_READY;
|
aead->state = CHACHA20_POLY1305_STATE_READY;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,8 @@ enum {
|
|||||||
|
|
||||||
typedef struct ChaCha {
|
typedef struct ChaCha {
|
||||||
word32 X[CHACHA_CHUNK_WORDS]; /* state of cipher */
|
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
|
#ifdef HAVE_INTEL_AVX1
|
||||||
/* vpshufd reads 16 bytes but we only use bottom 4. */
|
/* vpshufd reads 16 bytes but we only use bottom 4. */
|
||||||
byte extra[12];
|
byte extra[12];
|
||||||
|
Reference in New Issue
Block a user