wp/wp-includes/sodium_compat/src/Crypto32.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
--- a/wp/wp-includes/sodium_compat/src/Crypto32.php	Tue Oct 22 16:11:46 2019 +0200
+++ b/wp/wp-includes/sodium_compat/src/Crypto32.php	Tue Dec 15 13:49:49 2020 +0100
@@ -777,6 +777,53 @@
     }
 
     /**
+     * Initialize a hashing context for BLAKE2b.
+     *
+     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
+     *
+     * @param string $key
+     * @param int $outputLength
+     * @param string $salt
+     * @param string $personal
+     * @return string
+     * @throws RangeException
+     * @throws SodiumException
+     * @throws TypeError
+     */
+    public static function generichash_init_salt_personal(
+        $key = '',
+        $outputLength = 32,
+        $salt = '',
+        $personal = ''
+    ) {
+        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
+        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();
+
+        $k = null;
+        if (!empty($key)) {
+            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
+            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
+                throw new RangeException('Invalid key size');
+            }
+        }
+        if (!empty($salt)) {
+            $s = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt);
+        } else {
+            $s = null;
+        }
+        if (!empty($salt)) {
+            $p = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal);
+        } else {
+            $p = null;
+        }
+
+        /** @var SplFixedArray $ctx */
+        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s, $p);
+
+        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
+    }
+
+    /**
      * Update a hashing context for BLAKE2b with $message
      *
      * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
@@ -1185,6 +1232,362 @@
     }
 
     /**
+     * @param string $key
+     * @return array<int, string> Returns a state and a header.
+     * @throws Exception
+     * @throws SodiumException
+     */
+    public static function secretstream_xchacha20poly1305_init_push($key)
+    {
+        # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
+        $out = random_bytes(24);
+
+        # crypto_core_hchacha20(state->k, out, k, NULL);
+        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key);
+        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
+            $subkey,
+            ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) . str_repeat("\0", 4)
+        );
+
+        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
+        $state->counterReset();
+
+        # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
+        #        crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+        # memset(state->_pad, 0, sizeof state->_pad);
+        return array(
+            $state->toString(),
+            $out
+        );
+    }
+
+    /**
+     * @param string $key
+     * @param string $header
+     * @return string Returns a state.
+     * @throws Exception
+     */
+    public static function secretstream_xchacha20poly1305_init_pull($key, $header)
+    {
+        # crypto_core_hchacha20(state->k, in, k, NULL);
+        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
+            ParagonIE_Sodium_Core32_Util::substr($header, 0, 16),
+            $key
+        );
+        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
+            $subkey,
+            ParagonIE_Sodium_Core32_Util::substr($header, 16)
+        );
+        $state->counterReset();
+        # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
+        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+        # memset(state->_pad, 0, sizeof state->_pad);
+        # return 0;
+        return $state->toString();
+    }
+
+    /**
+     * @param string $state
+     * @param string $msg
+     * @param string $aad
+     * @param int $tag
+     * @return string
+     * @throws SodiumException
+     */
+    public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0)
+    {
+        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
+        # crypto_onetimeauth_poly1305_state poly1305_state;
+        # unsigned char                     block[64U];
+        # unsigned char                     slen[8U];
+        # unsigned char                    *c;
+        # unsigned char                    *mac;
+
+        $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg);
+        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);
+
+        if ((($msglen + 63) >> 6) > 0xfffffffe) {
+            throw new SodiumException(
+                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
+            );
+        }
+
+        # if (outlen_p != NULL) {
+        #     *outlen_p = 0U;
+        # }
+        # 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);
+        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
+            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
+        );
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+        $auth->update($aad);
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+        #     (0x10 - adlen) & 0xf);
+        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));
+
+        # memset(block, 0, sizeof block);
+        # block[0] = tag;
+        # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
+        #                                    state->nonce, 1U, state->k);
+        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
+            ParagonIE_Sodium_Core32_Util::intToChr($tag) . str_repeat("\0", 63),
+            $st->getCombinedNonce(),
+            $st->getKey(),
+            ParagonIE_Sodium_Core32_Util::store64_le(1)
+        );
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+        $auth->update($block);
+
+        # out[0] = block[0];
+        $out = $block[0];
+        # c = out + (sizeof tag);
+        # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
+        $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
+            $msg,
+            $st->getCombinedNonce(),
+            $st->getKey(),
+            ParagonIE_Sodium_Core32_Util::store64_le(2)
+        );
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+        $auth->update($cipher);
+
+        $out .= $cipher;
+        unset($cipher);
+
+        # crypto_onetimeauth_poly1305_update
+        # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
+
+        # STORE64_LE(slen, (uint64_t) adlen);
+        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+        $auth->update($slen);
+
+        # STORE64_LE(slen, (sizeof block) + mlen);
+        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);
+
+        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+        $auth->update($slen);
+
+        # mac = c + mlen;
+        # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+        $mac = $auth->finish();
+        $out .= $mac;
+
+        # sodium_memzero(&poly1305_state, sizeof poly1305_state);
+        unset($auth);
+
+
+        # XOR_BUF(STATE_INONCE(state), mac,
+        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+        $st->xorNonce($mac);
+
+        # sodium_increment(STATE_COUNTER(state),
+        #     crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+        $st->incrementCounter();
+        // Overwrite by reference:
+        $state = $st->toString();
+
+        /** @var bool $rekey */
+        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
+        # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+        #     sodium_is_zero(STATE_COUNTER(state),
+        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+        #     crypto_secretstream_xchacha20poly1305_rekey(state);
+        # }
+        if ($rekey || $st->needsRekey()) {
+            // DO REKEY
+            self::secretstream_xchacha20poly1305_rekey($state);
+        }
+        # if (outlen_p != NULL) {
+        #     *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
+        # }
+        return $out;
+    }
+
+    /**
+     * @param string $state
+     * @param string $cipher
+     * @param string $aad
+     * @return bool|array{0: string, 1: int}
+     * @throws SodiumException
+     */
+    public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '')
+    {
+        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
+
+        $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher);
+        #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
+        $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
+        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);
+
+        #     if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
+        #         sodium_misuse();
+        #     }
+        if ((($msglen + 63) >> 6) > 0xfffffffe) {
+            throw new SodiumException(
+                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
+            );
+        }
+
+        #     crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
+        #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);
+        #     sodium_memzero(block, sizeof block);
+        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
+            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
+        );
+
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+        $auth->update($aad);
+
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+        #         (0x10 - adlen) & 0xf);
+        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 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);
+        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
+            $cipher[0] . str_repeat("\0", 63),
+            $st->getCombinedNonce(),
+            $st->getKey(),
+            ParagonIE_Sodium_Core32_Util::store64_le(1)
+        );
+        #     tag = block[0];
+        #     block[0] = in[0];
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+        $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]);
+        $block[0] = $cipher[0];
+        $auth->update($block);
+
+
+        #     c = in + (sizeof tag);
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+        $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen));
+
+        #     crypto_onetimeauth_poly1305_update
+        #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));
+
+        #     STORE64_LE(slen, (uint64_t) adlen);
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);
+        $auth->update($slen);
+
+        #     STORE64_LE(slen, (sizeof block) + mlen);
+        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);
+        $auth->update($slen);
+
+        #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+        #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
+        $mac = $auth->finish();
+
+        #     stored_mac = c + mlen;
+        #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
+        #     sodium_memzero(mac, sizeof mac);
+        #         return -1;
+        #     }
+
+        $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16);
+        if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) {
+            return false;
+        }
+
+        #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
+        $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
+            ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen),
+            $st->getCombinedNonce(),
+            $st->getKey(),
+            ParagonIE_Sodium_Core32_Util::store64_le(2)
+        );
+
+        #     XOR_BUF(STATE_INONCE(state), mac,
+        #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+        $st->xorNonce($mac);
+
+        #     sodium_increment(STATE_COUNTER(state),
+        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+        $st->incrementCounter();
+
+        #     if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+        #         sodium_is_zero(STATE_COUNTER(state),
+        #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+        #         crypto_secretstream_xchacha20poly1305_rekey(state);
+        #     }
+
+        // Overwrite by reference:
+        $state = $st->toString();
+
+        /** @var bool $rekey */
+        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
+        if ($rekey || $st->needsRekey()) {
+            // DO REKEY
+            self::secretstream_xchacha20poly1305_rekey($state);
+        }
+        return array($out, $tag);
+    }
+
+    /**
+     * @param string $state
+     * @return void
+     * @throws SodiumException
+     */
+    public static function secretstream_xchacha20poly1305_rekey(&$state)
+    {
+        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($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];
+        # }
+        $new_key_and_inonce = $st->getKey();
+
+        # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
+        #     new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
+        #         STATE_INONCE(state)[i];
+        # }
+        $new_key_and_inonce .= ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8);
+
+        # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
+        #                                 sizeof new_key_and_inonce,
+        #                                 state->nonce, state->k);
+
+        $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
+            $new_key_and_inonce,
+            $st->getCombinedNonce(),
+            $st->getKey(),
+            ParagonIE_Sodium_Core32_Util::store64_le(0)
+        ));
+
+        # 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);
+        $st->counterReset();
+
+        $state = $st->toString();
+    }
+
+    /**
      * Detached Ed25519 signature.
      *
      * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.