Index: nss/lib/freebl/chacha20poly1305.c |
diff --git a/nss/lib/freebl/chacha20poly1305.c b/nss/lib/freebl/chacha20poly1305.c |
index 6fa5c4b53d220c782fe5e6628f98ff248865d7bd..cd265e1ff0c7af79f6b29bb23cea08560528352f 100644 |
--- a/nss/lib/freebl/chacha20poly1305.c |
+++ b/nss/lib/freebl/chacha20poly1305.c |
@@ -12,158 +12,187 @@ |
#include "seccomon.h" |
#include "secerr.h" |
#include "blapit.h" |
-#include "poly1305/poly1305.h" |
-#include "chacha20/chacha20.h" |
+ |
+#ifndef NSS_DISABLE_CHACHAPOLY |
+#include "poly1305.h" |
+#include "chacha20.h" |
#include "chacha20poly1305.h" |
+#endif |
/* Poly1305Do writes the Poly1305 authenticator of the given additional data |
* and ciphertext to |out|. */ |
+#ifndef NSS_DISABLE_CHACHAPOLY |
static void |
-Poly1305Do(unsigned char *out, |
- const unsigned char *ad, unsigned int adLen, |
- const unsigned char *ciphertext, unsigned int ciphertextLen, |
- const unsigned char key[32]) |
+Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, |
+ const unsigned char *ciphertext, unsigned int ciphertextLen, |
+ const unsigned char key[32]) |
{ |
poly1305_state state; |
unsigned int j; |
unsigned char lengthBytes[8]; |
+ static const unsigned char zeros[15]; |
unsigned int i; |
Poly1305Init(&state, key); |
+ Poly1305Update(&state, ad, adLen); |
+ if (adLen % 16 > 0) { |
+ Poly1305Update(&state, zeros, 16 - adLen % 16); |
+ } |
+ Poly1305Update(&state, ciphertext, ciphertextLen); |
+ if (ciphertextLen % 16 > 0) { |
+ Poly1305Update(&state, zeros, 16 - ciphertextLen % 16); |
+ } |
j = adLen; |
for (i = 0; i < sizeof(lengthBytes); i++) { |
- lengthBytes[i] = j; |
- j >>= 8; |
+ lengthBytes[i] = j; |
+ j >>= 8; |
} |
- Poly1305Update(&state, ad, adLen); |
Poly1305Update(&state, lengthBytes, sizeof(lengthBytes)); |
j = ciphertextLen; |
for (i = 0; i < sizeof(lengthBytes); i++) { |
- lengthBytes[i] = j; |
- j >>= 8; |
+ lengthBytes[i] = j; |
+ j >>= 8; |
} |
- Poly1305Update(&state, ciphertext, ciphertextLen); |
Poly1305Update(&state, lengthBytes, sizeof(lengthBytes)); |
Poly1305Finish(&state, out); |
} |
+#endif |
SECStatus |
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx, |
- const unsigned char *key, unsigned int keyLen, |
- unsigned int tagLen) |
+ const unsigned char *key, unsigned int keyLen, |
+ unsigned int tagLen) |
{ |
+#ifdef NSS_DISABLE_CHACHAPOLY |
+ return SECFailure; |
+#else |
if (keyLen != 32) { |
- PORT_SetError(SEC_ERROR_BAD_KEY); |
- return SECFailure; |
+ PORT_SetError(SEC_ERROR_BAD_KEY); |
+ return SECFailure; |
} |
if (tagLen == 0 || tagLen > 16) { |
- PORT_SetError(SEC_ERROR_INPUT_LEN); |
- return SECFailure; |
+ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return SECFailure; |
} |
- memcpy(ctx->key, key, sizeof(ctx->key)); |
+ PORT_Memcpy(ctx->key, key, sizeof(ctx->key)); |
ctx->tagLen = tagLen; |
return SECSuccess; |
+#endif |
} |
ChaCha20Poly1305Context * |
ChaCha20Poly1305_CreateContext(const unsigned char *key, unsigned int keyLen, |
- unsigned int tagLen) |
+ unsigned int tagLen) |
{ |
+#ifdef NSS_DISABLE_CHACHAPOLY |
+ return NULL; |
+#else |
ChaCha20Poly1305Context *ctx; |
ctx = PORT_New(ChaCha20Poly1305Context); |
if (ctx == NULL) { |
- return NULL; |
+ return NULL; |
} |
if (ChaCha20Poly1305_InitContext(ctx, key, keyLen, tagLen) != SECSuccess) { |
- PORT_Free(ctx); |
- ctx = NULL; |
+ PORT_Free(ctx); |
+ ctx = NULL; |
} |
return ctx; |
+#endif |
} |
void |
ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit) |
{ |
- memset(ctx, 0, sizeof(*ctx)); |
+#ifndef NSS_DISABLE_CHACHAPOLY |
+ PORT_Memset(ctx, 0, sizeof(*ctx)); |
if (freeit) { |
- PORT_Free(ctx); |
+ PORT_Free(ctx); |
} |
+#endif |
} |
SECStatus |
-ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, |
- unsigned char *output, unsigned int *outputLen, |
- unsigned int maxOutputLen, |
- const unsigned char *input, unsigned int inputLen, |
- const unsigned char *nonce, unsigned int nonceLen, |
- const unsigned char *ad, unsigned int adLen) |
+ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, |
+ unsigned int *outputLen, unsigned int maxOutputLen, |
+ const unsigned char *input, unsigned int inputLen, |
+ const unsigned char *nonce, unsigned int nonceLen, |
+ const unsigned char *ad, unsigned int adLen) |
{ |
+#ifdef NSS_DISABLE_CHACHAPOLY |
+ return SECFailure; |
+#else |
unsigned char block[64]; |
unsigned char tag[16]; |
- if (nonceLen != 8) { |
- PORT_SetError(SEC_ERROR_INPUT_LEN); |
- return SECFailure; |
+ if (nonceLen != 12) { |
+ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return SECFailure; |
} |
*outputLen = inputLen + ctx->tagLen; |
if (maxOutputLen < *outputLen) { |
- PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
- return SECFailure; |
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
+ return SECFailure; |
} |
- memset(block, 0, sizeof(block)); |
+ PORT_Memset(block, 0, sizeof(block)); |
// Generate a block of keystream. The first 32 bytes will be the poly1305 |
// key. The remainder of the block is discarded. |
ChaCha20XOR(block, block, sizeof(block), ctx->key, nonce, 0); |
ChaCha20XOR(output, input, inputLen, ctx->key, nonce, 1); |
Poly1305Do(tag, ad, adLen, output, inputLen, block); |
- memcpy(output + inputLen, tag, ctx->tagLen); |
+ PORT_Memcpy(output + inputLen, tag, ctx->tagLen); |
return SECSuccess; |
+#endif |
} |
SECStatus |
-ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, |
- unsigned char *output, unsigned int *outputLen, |
- unsigned int maxOutputLen, |
- const unsigned char *input, unsigned int inputLen, |
- const unsigned char *nonce, unsigned int nonceLen, |
- const unsigned char *ad, unsigned int adLen) |
+ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output, |
+ unsigned int *outputLen, unsigned int maxOutputLen, |
+ const unsigned char *input, unsigned int inputLen, |
+ const unsigned char *nonce, unsigned int nonceLen, |
+ const unsigned char *ad, unsigned int adLen) |
{ |
+#ifdef NSS_DISABLE_CHACHAPOLY |
+ return SECFailure; |
+#else |
unsigned char block[64]; |
unsigned char tag[16]; |
+ unsigned int ciphertextLen; |
- if (nonceLen != 8) { |
- PORT_SetError(SEC_ERROR_INPUT_LEN); |
- return SECFailure; |
+ if (nonceLen != 12) { |
+ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return SECFailure; |
} |
if (inputLen < ctx->tagLen) { |
- PORT_SetError(SEC_ERROR_INPUT_LEN); |
- return SECFailure; |
+ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return SECFailure; |
} |
- *outputLen = inputLen - ctx->tagLen; |
+ ciphertextLen = inputLen - ctx->tagLen; |
+ *outputLen = ciphertextLen; |
if (maxOutputLen < *outputLen) { |
- PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
- return SECFailure; |
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
+ return SECFailure; |
} |
- memset(block, 0, sizeof(block)); |
+ PORT_Memset(block, 0, sizeof(block)); |
// Generate a block of keystream. The first 32 bytes will be the poly1305 |
// key. The remainder of the block is discarded. |
ChaCha20XOR(block, block, sizeof(block), ctx->key, nonce, 0); |
- Poly1305Do(tag, ad, adLen, input, inputLen - ctx->tagLen, block); |
- if (NSS_SecureMemcmp(tag, &input[inputLen - ctx->tagLen], ctx->tagLen) != 0) { |
- PORT_SetError(SEC_ERROR_BAD_DATA); |
- return SECFailure; |
+ Poly1305Do(tag, ad, adLen, input, ciphertextLen, block); |
+ if (NSS_SecureMemcmp(tag, &input[ciphertextLen], ctx->tagLen) != 0) { |
+ PORT_SetError(SEC_ERROR_BAD_DATA); |
+ return SECFailure; |
} |
- ChaCha20XOR(output, input, inputLen - ctx->tagLen, ctx->key, nonce, 1); |
+ ChaCha20XOR(output, input, ciphertextLen, ctx->key, nonce, 1); |
return SECSuccess; |
+#endif |
} |