From 468a9d82a9e03d85244b5fa212c6ff119d0c5071 Mon Sep 17 00:00:00 2001 From: Theron Spiegl Date: Tue, 24 Nov 2020 17:08:48 -0600 Subject: [PATCH] pull --- crypto_secretstream.js | 373 +++++++++++------------------------------ 1 file changed, 94 insertions(+), 279 deletions(-) diff --git a/crypto_secretstream.js b/crypto_secretstream.js index 4ae3d6b..9d99e17 100644 --- a/crypto_secretstream.js +++ b/crypto_secretstream.js @@ -18,6 +18,7 @@ const crypto_aead_xchacha20poly1305_ietf_ABYTES = 16 const crypto_secretstream_xchacha20poly1305_ABYTES = 1 + crypto_aead_xchacha20poly1305_ietf_ABYTES const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER const crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER +const crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = 0 // #define STATE_COUNTER(STATE) ((STATE)->nonce) // #define STATE_INONCE(STATE) ((STATE)->nonce + \ @@ -33,14 +34,6 @@ class crypto_secretstream_xchacha20poly1305_state { } } -// static inline void -// _crypto_secretstream_xchacha20poly1305_counter_reset -// (crypto_secretstream_xchacha20poly1305_state *state) -// { -// memset(STATE_COUNTER(state), 0, -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES); -// STATE_COUNTER(state)[0] = 1; -// } function _crypto_secretstream_xchacha20poly1305_counter_reset (state) { assert(state instanceof crypto_secretstream_xchacha20poly1305_state, 'state is not an instance of crypto_secretstream_xchacha20poly1305_state') for (let i = 0; i < crypto_secretstream_xchacha20poly1305_COUNTERBYTES; i++) { @@ -49,41 +42,11 @@ function _crypto_secretstream_xchacha20poly1305_counter_reset (state) { state.nonce[0] = 1 } -// void -// crypto_secretstream_xchacha20poly1305_keygen -// (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) -// { -// randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES); -// } function crypto_secretstream_xchacha20poly1305_keygen (k) { assert(k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES) randombytes_buf(k) } -// int -// crypto_secretstream_xchacha20poly1305_init_push -// (crypto_secretstream_xchacha20poly1305_state *state, -// unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES], -// const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) -// { -// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES == -// crypto_core_hchacha20_INPUTBYTES + -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES == -// crypto_aead_xchacha20poly1305_ietf_NPUBBYTES); -// COMPILER_ASSERT(sizeof state->nonce == -// crypto_secretstream_xchacha20poly1305_INONCEBYTES + -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES); - -// randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); -// crypto_core_hchacha20(state->k, out, k, NULL); -// _crypto_secretstream_xchacha20poly1305_counter_reset(state); -// memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// memset(state->_pad, 0, sizeof state->_pad); - -// return 0; -// } function crypto_secretstream_xchacha20poly1305_init_push (state, out, k) { assert(state instanceof crypto_secretstream_xchacha20poly1305_state, 'state not instance of crypto_secretstream_xchacha20poly1305_state') assert(out instanceof Uint8Array && out.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES, 'out not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES') @@ -102,20 +65,6 @@ function crypto_secretstream_xchacha20poly1305_init_push (state, out, k) { return 0 } -// int -// crypto_secretstream_xchacha20poly1305_init_pull -// (crypto_secretstream_xchacha20poly1305_state *state, -// const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES], -// const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) -// { -// crypto_core_hchacha20(state->k, in, k, NULL); -// _crypto_secretstream_xchacha20poly1305_counter_reset(state); -// memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// memset(state->_pad, 0, sizeof state->_pad); - -// return 0; -// } function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, k) { assert(state instanceof crypto_secretstream_xchacha20poly1305_state, 'state not instance of crypto_secretstream_xchacha20poly1305_state') @@ -133,33 +82,6 @@ function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, k) { return 0 } -// void -// crypto_secretstream_xchacha20poly1305_rekey -// (crypto_secretstream_xchacha20poly1305_state *state) -// { -// unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + -// crypto_secretstream_xchacha20poly1305_INONCEBYTES]; -// size_t i; - -// for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { -// new_key_and_inonce[i] = state->k[i]; -// } -// for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { -// new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = -// STATE_INONCE(state)[i]; -// } -// crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, -// sizeof new_key_and_inonce, -// state->nonce, state->k); -// for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { -// state->k[i] = new_key_and_inonce[i]; -// } -// for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { -// STATE_INONCE(state)[i] = -// new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; -// } -// _crypto_secretstream_xchacha20poly1305_counter_reset(state); -// } function crypto_secretstream_xchacha20poly1305_rekey (state) { assert(state instanceof crypto_secretstream_xchacha20poly1305_state, 'state not instance of crypto_secretstream_xchacha20poly1305_state') @@ -184,74 +106,6 @@ function crypto_secretstream_xchacha20poly1305_rekey (state) { _crypto_secretstream_xchacha20poly1305_counter_reset(state) } -// int -// crypto_secretstream_xchacha20poly1305_push -// (crypto_secretstream_xchacha20poly1305_state *state, -// unsigned char *out, unsigned long long *outlen_p, -// const unsigned char *m, unsigned long long mlen, -// const unsigned char *ad, unsigned long long adlen, unsigned char tag) -// { -// crypto_onetimeauth_poly1305_state poly1305_state; -// unsigned char block[64U]; -// unsigned char slen[8U]; -// unsigned char *c; -// unsigned char *mac; - -// if (outlen_p != NULL) { -// *outlen_p = 0U; -// } -// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX -// <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX); -// if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { -// sodium_misuse(); -// } -// crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); -// crypto_onetimeauth_poly1305_init(&poly1305_state, block); -// sodium_memzero(block, sizeof block); - -// crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, -// (0x10 - adlen) & 0xf); -// memset(block, 0, sizeof block); -// block[0] = tag; - -// crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, -// state->nonce, 1U, state->k); -// crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); -// out[0] = block[0]; - -// c = out + (sizeof tag); -// crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); -// crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); -// crypto_onetimeauth_poly1305_update -// (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); -// /* should have been (0x10 - (sizeof block + mlen)) & 0xf to keep input blocks aligned */ - -// STORE64_LE(slen, (uint64_t) adlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); -// STORE64_LE(slen, (sizeof block) + mlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); - -// mac = c + mlen; -// crypto_onetimeauth_poly1305_final(&poly1305_state, mac); -// sodium_memzero(&poly1305_state, sizeof poly1305_state); - -// COMPILER_ASSERT(crypto_onetimeauth_poly1305_BYTES >= -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// XOR_BUF(STATE_INONCE(state), mac, -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// sodium_increment(STATE_COUNTER(state), -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES); -// if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || -// sodium_is_zero(STATE_COUNTER(state), -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { -// crypto_secretstream_xchacha20poly1305_rekey(state); -// } -// if (outlen_p != NULL) { -// *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; -// } -// return 0; -// } function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) { const block = new Uint8Array(64) const slen = new Uint8Array(8) @@ -267,7 +121,7 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) { poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf) block[0] = tag - crypto_stream_chacha20_ietf_xor_ic(block, state.nonce, 1, state.k) + crypto_stream_chacha20_ietf_xor_ic(block, block, state.nonce, 1, state.k) poly.update(block, 0, block.byteLength) out[0] = block[0] @@ -275,7 +129,7 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) { // block is 64 bytes. sizeof tag is 1, as it's a byte, so c is the subarray starting at out[1] // c = out + (sizeof tag); const c = out.subarray(1, out.byteLength) - crypto_stream_chacha20_ietf_xor_ic(c, m, state.nonce, 2, state.key) + crypto_stream_chacha20_ietf_xor_ic(c, m, state.nonce, 2, state.k) poly.update(c, 0, m.byteLength) poly.update(_pad0, (0x10 - block.byteLength + m.byteLength) & 0xf) @@ -303,148 +157,100 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) { return 0 } -// int -// crypto_secretstream_xchacha20poly1305_pull -// (crypto_secretstream_xchacha20poly1305_state *state, -// unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p, -// const unsigned char *in, unsigned long long inlen, -// const unsigned char *ad, unsigned long long adlen) -// { -// crypto_onetimeauth_poly1305_state poly1305_state; -// unsigned char block[64U]; -// unsigned char slen[8U]; -// unsigned char mac[crypto_onetimeauth_poly1305_BYTES]; -// const unsigned char *c; -// const unsigned char *stored_mac; -// unsigned long long mlen; -// unsigned char tag; - -// if (mlen_p != NULL) { -// *mlen_p = 0U; -// } -// if (tag_p != NULL) { -// *tag_p = 0xff; -// } -// if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) { -// return -1; -// } -// mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; -// if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { -// sodium_misuse(); -// } -// crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); -// crypto_onetimeauth_poly1305_init(&poly1305_state, block); -// sodium_memzero(block, sizeof block); - -// crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, -// (0x10 - adlen) & 0xf); - -// memset(block, 0, sizeof block); -// block[0] = in[0]; -// crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, -// state->nonce, 1U, state->k); -// tag = block[0]; -// block[0] = in[0]; -// crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); - -// c = in + (sizeof tag); -// crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); -// crypto_onetimeauth_poly1305_update -// (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); -// /* should have been (0x10 - (sizeof block + mlen)) & 0xf to keep input blocks aligned */ - -// STORE64_LE(slen, (uint64_t) adlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); -// STORE64_LE(slen, (sizeof block) + mlen); -// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); - -// crypto_onetimeauth_poly1305_final(&poly1305_state, mac); -// sodium_memzero(&poly1305_state, sizeof poly1305_state); - -// stored_mac = c + mlen; -// if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { -// sodium_memzero(mac, sizeof mac); -// return -1; -// } - -// crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); -// XOR_BUF(STATE_INONCE(state), mac, -// crypto_secretstream_xchacha20poly1305_INONCEBYTES); -// sodium_increment(STATE_COUNTER(state), -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES); -// if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || -// sodium_is_zero(STATE_COUNTER(state), -// crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { -// crypto_secretstream_xchacha20poly1305_rekey(state); -// } -// if (mlen_p != NULL) { -// *mlen_p = mlen; -// } -// if (tag_p != NULL) { -// *tag_p = tag; -// } -// return 0; -// } -function crypto_secretstream_xchacha20poly1305_pull (state, m, tag, _in, ad) { +function crypto_secretstream_xchacha20poly1305_pull (state, m, _in, ad) { const block = new Uint8Array(64) const slen = new Uint8Array(8) const mac = new Uint8Array(crypto_onetimeauth_poly1305_BYTES) + + if (_in.byteLength < crypto_secretstream_xchacha20poly1305_ABYTES) { + return -1 + } + + const mlen = _in.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES + // if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { + // sodium_misuse() + // } + crypto_stream_chacha20_ietf(block, state.nonce, state.k) + const poly = new Poly1305(block) + block.fill(0) // sodium_memzero(block, sizeof block); + + poly.update(ad, 0, ad.byteLength) + poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf) + + block.fill(0) // memset(block, 0, sizeof block); + block[0] = _in[0] + crypto_stream_chacha20_ietf_xor_ic(block, block, nonce, 1, state.k) + + const tag = block[0] + block[0] = _in[0] + poly.update(block, 0, block.byteLength) + + c = _in.subarray(1, _in.length) + poly.update(c, 0, mlen) + // poly.update(_in, 1, mlen) + poly.update(_pad0, (0x10 - block.byteLength + mlen) & 0xf) + + STORE64_LE(slen, ad.byteLength) + poly.update(slen, slen.byteLength) + STORE64_LE(slen, block.byteLength + m.byteLength) + poly.update(slen, slen.byteLength) + + poly.finish(mac, 0) + const stored_mac = _in.subarray(c + mlen, _in.length) + for (let i = 0; i < mac.length; i++) { + if (mac[i] !== stored_mac[i]) { + mac.fill(0) + return -1 + } + } + + crypto_stream_chacha20_ietf_xor_ic(m, c, state.nonce, 2, state.k) + xor_buf(state.nonce.subarray(crypto_secretstream_xchacha20poly1305_COUNTERBYTES, state.nonce.length), + mac, crypto_secretstream_xchacha20poly1305_INONCEBYTES) + sodium_increment(state.nonce) + + if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || + sodium_is_zero(STATE_COUNTER(state), crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { + crypto_secretstream_xchacha20poly1305_rekey(state) + } + return tag } -// size_t -// crypto_secretstream_xchacha20poly1305_statebytes(void) -// { -// return sizeof(crypto_secretstream_xchacha20poly1305_state); -// } +function crypto_secretstream_xchacha20poly1305_statebytes () { + return crypto_stream_chacha20_ietf_KEYBYTES + crypto_stream_chacha20_ietf_NONCEBYTES + 8 +} -// size_t -// crypto_secretstream_xchacha20poly1305_abytes(void) -// { -// return crypto_secretstream_xchacha20poly1305_ABYTES; -// } +function crypto_secretstream_xchacha20poly1305_abytes() { + return crypto_secretstream_xchacha20poly1305_ABYTES +} -// size_t -// crypto_secretstream_xchacha20poly1305_headerbytes(void) -// { -// return crypto_secretstream_xchacha20poly1305_HEADERBYTES; -// } +function crypto_secretstream_xchacha20poly1305_headerbytes () { + return crypto_secretstream_xchacha20poly1305_HEADERBYTES +} -// size_t -// crypto_secretstream_xchacha20poly1305_keybytes(void) -// { -// return crypto_secretstream_xchacha20poly1305_KEYBYTES; -// } +function crypto_secretstream_xchacha20poly1305_keybytes () { + return crypto_secretstream_xchacha20poly1305_KEYBYTES +} -// size_t -// crypto_secretstream_xchacha20poly1305_messagebytes_max(void) -// { -// return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX; -// } +function crypto_secretstream_xchacha20poly1305_messagebytes_max () { + return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX +} -// unsigned char -// crypto_secretstream_xchacha20poly1305_tag_message(void) -// { -// return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; -// } +function crypto_secretstream_xchacha20poly1305_tag_message () { + return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE +} -// unsigned char -// crypto_secretstream_xchacha20poly1305_tag_push(void) -// { -// return crypto_secretstream_xchacha20poly1305_TAG_PUSH; -// } +function crypto_secretstream_xchacha20poly1305_tag_push () { + return crypto_secretstream_xchacha20poly1305_TAG_PUSH +} -// unsigned char -// crypto_secretstream_xchacha20poly1305_tag_rekey(void) -// { -// return crypto_secretstream_xchacha20poly1305_TAG_REKEY; -// } +function crypto_secretstream_xchacha20poly1305_tag_rekey () { + return crypto_secretstream_xchacha20poly1305_TAG_REKEY +} -// unsigned char -// crypto_secretstream_xchacha20poly1305_tag_final(void) -// { -// return crypto_secretstream_xchacha20poly1305_TAG_FINAL; -// } +function crypto_secretstream_xchacha20poly1305_tag_final () { + return crypto_secretstream_xchacha20poly1305_TAG_FINAL +} function xor_buf (out, _in, n) { for (let i = 0; i < n; i++) { @@ -460,5 +266,14 @@ module.exports = { crypto_secretstream_xchacha20poly1305_init_pull, crypto_secretstream_xchacha20poly1305_rekey, crypto_secretstream_xchacha20poly1305_push, - crypto_secretstream_xchacha20poly1305_pull + crypto_secretstream_xchacha20poly1305_pull, + crypto_secretstream_xchacha20poly1305_statebytes, + crypto_secretstream_xchacha20poly1305_abytes, + crypto_secretstream_xchacha20poly1305_headerbytes, + crypto_secretstream_xchacha20poly1305_keybytes, + crypto_secretstream_xchacha20poly1305_messagebytes_max, + crypto_secretstream_xchacha20poly1305_tag_message, + crypto_secretstream_xchacha20poly1305_tag_push, + crypto_secretstream_xchacha20poly1305_tag_rekey, + crypto_secretstream_xchacha20poly1305_tag_final }