From a90fc6ab46e660e3c97a99e8f9a2a77707dacaa2 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 2 Jul 2024 14:11:55 -0700 Subject: [PATCH 01/36] Add anonymous-credentials lib/cxx for Web Discovery --- .../anonymous_credentials/rs/.gitignore | 3 + .../anonymous_credentials/rs/cxx/BUILD.gn | 21 + .../anonymous_credentials/rs/cxx/Cargo.toml | 13 + .../anonymous_credentials/rs/cxx/src/lib.rs | 117 ++ .../anonymous_credentials/rs/lib/BUILD.gn | 29 + .../anonymous_credentials/rs/lib/Cargo.toml | 19 + .../anonymous_credentials/rs/lib/README.md | 11 + .../anonymous_credentials/rs/lib/src/data.rs | 256 +++ .../anonymous_credentials/rs/lib/src/join.rs | 182 ++ .../anonymous_credentials/rs/lib/src/lib.rs | 243 +++ .../anonymous_credentials/rs/lib/src/sign.rs | 66 + .../anonymous_credentials/rs/lib/src/util.rs | 90 + script/brave_license_helper.py | 3 + .../v0_1/README.chromium | 8 + .../v0_1/README.chromium | 8 + third_party/rust/brave_miracl/v0_1/BUILD.gn | 67 + .../rust/brave_miracl/v0_1/README.chromium | 9 + .../rust/chromium_crates_io/Cargo.lock | 24 + .../rust/chromium_crates_io/Cargo.toml | 9 + .../brave-miracl-0.1.3/.cargo-checksum.json | 1 + .../brave-miracl-0.1.3/.cargo_vcs_info.json | 6 + .../vendor/brave-miracl-0.1.3/.gitignore | 2 + .../vendor/brave-miracl-0.1.3/.gitmodules | 3 + .../vendor/brave-miracl-0.1.3/Cargo.toml | 34 + .../vendor/brave-miracl-0.1.3/Cargo.toml.orig | 18 + .../vendor/brave-miracl-0.1.3/LICENSE | 202 ++ .../vendor/brave-miracl-0.1.3/README.md | 15 + .../vendor/brave-miracl-0.1.3/src/aes.rs | 888 ++++++++ .../vendor/brave-miracl-0.1.3/src/arch.rs | 22 + .../brave-miracl-0.1.3/src/bn254/big.rs | 1062 ++++++++++ .../brave-miracl-0.1.3/src/bn254/bls.rs | 181 ++ .../brave-miracl-0.1.3/src/bn254/dbig.rs | 314 +++ .../brave-miracl-0.1.3/src/bn254/ecdh.rs | 432 ++++ .../brave-miracl-0.1.3/src/bn254/ecp.rs | 1824 +++++++++++++++++ .../brave-miracl-0.1.3/src/bn254/ecp2.rs | 999 +++++++++ .../brave-miracl-0.1.3/src/bn254/eddsa.rs | 455 ++++ .../vendor/brave-miracl-0.1.3/src/bn254/fp.rs | 825 ++++++++ .../brave-miracl-0.1.3/src/bn254/fp12.rs | 1111 ++++++++++ .../brave-miracl-0.1.3/src/bn254/fp2.rs | 516 +++++ .../brave-miracl-0.1.3/src/bn254/fp4.rs | 784 +++++++ .../brave-miracl-0.1.3/src/bn254/hpke.rs | 386 ++++ .../brave-miracl-0.1.3/src/bn254/mod.rs | 30 + .../brave-miracl-0.1.3/src/bn254/mpin.rs | 228 +++ .../brave-miracl-0.1.3/src/bn254/pair.rs | 1038 ++++++++++ .../brave-miracl-0.1.3/src/bn254/rom.rs | 192 ++ .../brave-miracl-0.1.3/src/dilithium.rs | 1248 +++++++++++ .../vendor/brave-miracl-0.1.3/src/gcm.rs | 505 +++++ .../vendor/brave-miracl-0.1.3/src/hash256.rs | 312 +++ .../vendor/brave-miracl-0.1.3/src/hash384.rs | 431 ++++ .../vendor/brave-miracl-0.1.3/src/hash512.rs | 431 ++++ .../vendor/brave-miracl-0.1.3/src/hmac.rs | 943 +++++++++ .../vendor/brave-miracl-0.1.3/src/kyber.rs | 728 +++++++ .../vendor/brave-miracl-0.1.3/src/lib.rs | 40 + .../vendor/brave-miracl-0.1.3/src/main.rs | 3 + .../vendor/brave-miracl-0.1.3/src/nhs.rs | 709 +++++++ .../vendor/brave-miracl-0.1.3/src/rand.rs | 181 ++ .../vendor/brave-miracl-0.1.3/src/sha3.rs | 345 ++++ .../vendor/brave-miracl-0.1.3/src/share.rs | 165 ++ .../vendor/brave-miracl-0.1.3/src/x509.rs | 1311 ++++++++++++ 59 files changed, 20098 insertions(+) create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/.gitignore create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/cxx/BUILD.gn create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/BUILD.gn create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/Cargo.toml create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/README.md create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/src/join.rs create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/src/lib.rs create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/src/sign.rs create mode 100644 components/web_discovery/browser/anonymous_credentials/rs/lib/src/util.rs create mode 100644 third_party/rust/anonymous_credentials/v0_1/README.chromium create mode 100644 third_party/rust/anonymous_credentials_cxx/v0_1/README.chromium create mode 100644 third_party/rust/brave_miracl/v0_1/BUILD.gn create mode 100644 third_party/rust/brave_miracl/v0_1/README.chromium create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo-checksum.json create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo_vcs_info.json create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitignore create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitmodules create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml.orig create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/LICENSE create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/README.md create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/aes.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/arch.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/big.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/bls.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/dbig.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecdh.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp2.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/eddsa.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp12.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp2.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp4.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/hpke.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mod.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mpin.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/pair.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/rom.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/dilithium.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/gcm.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash256.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash384.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash512.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hmac.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/kyber.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/main.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/nhs.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/rand.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/sha3.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/share.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/x509.rs diff --git a/components/web_discovery/browser/anonymous_credentials/rs/.gitignore b/components/web_discovery/browser/anonymous_credentials/rs/.gitignore new file mode 100644 index 000000000000..d9510d9f6795 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/.gitignore @@ -0,0 +1,3 @@ +target +example/main +Cargo.lock diff --git a/components/web_discovery/browser/anonymous_credentials/rs/cxx/BUILD.gn b/components/web_discovery/browser/anonymous_credentials/rs/cxx/BUILD.gn new file mode 100644 index 000000000000..03dbf10acfda --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//build/rust/rust_static_library.gni") + +rust_static_library("rust_lib") { + crate_name = "anonymous_credentials_cxx" + crate_root = "src/lib.rs" + allow_unsafe = true + + edition = "2021" + sources = [ "src/lib.rs" ] + + visibility = [ "//brave/components/web_discovery/browser:*" ] + + cxx_bindings = [ "src/lib.rs" ] + + deps = [ "//brave/components/web_discovery/browser/anonymous_credentials/rs/lib:rust_lib" ] +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml new file mode 100644 index 000000000000..2d8d350f2594 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "anonymous-credentials-cxx" +version = "0.1.0" +edition = "2021" +license = "MPL-2.0" + +[dependencies] +anonymous-credentials = "0.1" +cxx = "1" + +[lib] +name = "anonymous_credentials_cxx" +crate-type = ["rlib"] diff --git a/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs new file mode 100644 index 000000000000..a474f63f0816 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs @@ -0,0 +1,117 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use anonymous_credentials::{ + CredentialBIG, CredentialManager as InternalCredentialManager, GroupPublicKey, JoinResponse, + Result, UserCredentials, +}; + +#[allow(unsafe_op_in_unsafe_fn)] +#[cxx::bridge(namespace = "anonymous_credentials")] +mod ffi { + struct StartJoinResult { + gsk: Vec, + join_request: Vec, + } + struct VecU8Result { + data: Vec, + error_message: String, + } + struct EmptyResult { + error_message: String, + } + extern "Rust" { + type CredentialManager; + fn new_credential_manager() -> Box; + fn new_credential_manager_with_fixed_seed() -> Box; + fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult; + fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result; + fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult; + fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result; + } +} + +use ffi::*; + +#[allow(dead_code)] +struct CredentialManager(InternalCredentialManager); + +fn new_credential_manager() -> Box { + Box::new(CredentialManager(InternalCredentialManager::new())) +} + +fn new_credential_manager_with_fixed_seed() -> Box { + Box::new(CredentialManager(InternalCredentialManager::new_with_seed( + &[0u8; 1], + ))) +} + +impl CredentialManager { + fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { + let result = self.0.start_join(challenge); + StartJoinResult { + gsk: result.gsk.to_bytes().to_vec(), + join_request: result.join_msg.to_bytes().to_vec(), + } + } + + /// Processes response and returns user credentials + fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result { + || -> Result> { + let public_key = GroupPublicKey::try_from(public_key)?; + let gsk = CredentialBIG::try_from(gsk)?; + let join_resp = JoinResponse::try_from(join_resp)?; + self.0 + .finish_join(&public_key, &gsk, join_resp) + .map(|creds| creds.to_bytes().to_vec()) + }() + .into() + } + + fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult { + || -> Result<()> { + let gsk = CredentialBIG::try_from(gsk)?; + let credentials = UserCredentials::try_from(credentials)?; + self.0.set_gsk_and_credentials(gsk, credentials); + Ok(()) + }() + .into() + } + + fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result { + self.0 + .sign(msg, basename) + .map(|sig| sig.to_bytes().to_vec()) + .into() + } +} + +impl From>> for VecU8Result { + fn from(value: Result>) -> Self { + match value { + Ok(data) => VecU8Result { + data, + error_message: String::new(), + }, + Err(e) => VecU8Result { + data: Vec::new(), + error_message: e.to_string(), + }, + } + } +} + +impl From> for EmptyResult { + fn from(value: Result<()>) -> Self { + match value { + Ok(()) => EmptyResult { + error_message: String::new(), + }, + Err(e) => EmptyResult { + error_message: e.to_string(), + }, + } + } +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/BUILD.gn b/components/web_discovery/browser/anonymous_credentials/rs/lib/BUILD.gn new file mode 100644 index 000000000000..03e10c4e4a16 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//build/rust/rust_static_library.gni") + +rust_static_library("rust_lib") { + crate_name = "anonymous_credentials" + crate_root = "src/lib.rs" + sources = [ + "src/data.rs", + "src/join.rs", + "src/lib.rs", + "src/sign.rs", + "src/util.rs", + ] + + visibility = [ + "//brave/components/web_discovery/browser/anonymous_credentials/rs/cxx:*", + ] + + deps = [ + "//brave/third_party/rust/brave_miracl/v0_1:lib", + "//brave/third_party/rust/lazy_static/v1:lib", + "//brave/third_party/rust/rand/v0_8:lib", + "//brave/third_party/rust/thiserror/v1:lib", + ] +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/lib/Cargo.toml new file mode 100644 index 000000000000..1efc85f2de2f --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "anonymous-credentials" +version = "0.1.4" +edition = "2021" +authors = ["Darnell Andries "] +description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" +license = "MPL-2.0" +repository = "https://github.com/brave-experiments/anonymous-credentials-rs" +keywords = ["daa", "credentials", "bn254"] +categories = ["cryptography"] + +[dependencies] +lazy_static = "1.4" +rand = "0.8" +brave-miracl = { version = "0.1", features = ["std"] } +thiserror = "1.0" + +[dev-dependencies] +hex = "0.4" diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/README.md b/components/web_discovery/browser/anonymous_credentials/rs/lib/README.md new file mode 100644 index 000000000000..da0fa655154f --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/README.md @@ -0,0 +1,11 @@ +# anonymous-credentials + +[![Crates.io](https://img.shields.io/crates/v/anonymous-credentials?style=for-the-badge)](https://crates.io/crates/anonymous-credentials) + +Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). + +bn254 is the only supported curve for this library. + +## License + +This project is licensed under the terms of the [Mozilla Public License 2.0](LICENSE). diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs new file mode 100644 index 000000000000..9581d02a78de --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs @@ -0,0 +1,256 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +use brave_miracl::bn254::{ + big::{self, BIG}, + ecp::ECP, + ecp2::ECP2, + fp2::FP2, +}; + +use super::CredentialError; + +pub const BIG_SIZE: usize = big::MODBYTES; +pub const ECP_SIZE: usize = BIG_SIZE * 2 + 1; +pub const ECP2_COMPAT_SIZE: usize = BIG_SIZE * 4; + +pub const ECP_PROOF_SIZE: usize = BIG_SIZE * 2; +pub const JOIN_REQUEST_SIZE: usize = ECP_SIZE + ECP_PROOF_SIZE; +pub const USER_CREDENTIALS_SIZE: usize = ECP_SIZE * 4; +pub const JOIN_RESPONSE_SIZE: usize = USER_CREDENTIALS_SIZE + ECP_PROOF_SIZE; +pub const GROUP_PUBLIC_KEY_SIZE: usize = ECP2_COMPAT_SIZE * 2 + BIG_SIZE * 4; +pub const SIGNATURE_SIZE: usize = ECP_SIZE * 5 + ECP_PROOF_SIZE; + +/// A "join" request to be sent to the issuer. +pub struct JoinRequest { + pub(crate) q: ECP, // G1 ** gsk + + pub(crate) proof: ECPProof, +} + +/// A "join" response from the issuer, to be used +/// to generate DAA credentials. +pub struct JoinResponse { + pub(crate) cred: UserCredentials, + pub(crate) proof: ECPProof, +} + +/// DAA credentials to be used for signing messages. +pub struct UserCredentials { + pub(crate) a: ECP, + pub(crate) b: ECP, + pub(crate) c: ECP, + pub(crate) d: ECP, +} + +/// A DAA signature to be sent to the verifier. +pub struct Signature { + pub(crate) a: ECP, + pub(crate) b: ECP, + pub(crate) c: ECP, + pub(crate) d: ECP, + pub(crate) nym: ECP, + + pub(crate) proof: ECPProof, +} + +/// A group public key published by the issuer. +/// This is required to finish the "join" process +/// and acquire credentials. +pub struct GroupPublicKey { + pub(crate) x: ECP2, // G2 ** x + pub(crate) y: ECP2, // G2 ** y + + // ZK of discrete-log knowledge for X and Y + pub(crate) cx: BIG, + pub(crate) sx: BIG, + pub(crate) cy: BIG, + pub(crate) sy: BIG, +} + +pub(crate) struct ECPProof { + pub c: BIG, + pub s: BIG, +} + +/// Wrapper for a big number. +pub struct CredentialBIG(pub(crate) BIG); + +/// A result of starting the "join" process to acquire credentials. +pub struct StartJoinResult { + /// Private key which should be persisted for finishing the "join" + /// process and future signing requests. + pub gsk: CredentialBIG, + /// The join request to be sent to the issuer. + pub join_msg: JoinRequest, +} + +pub(crate) fn ecp_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != ECP_SIZE { + return Err(CredentialError::BadECP); + } + Ok(ECP::frombytes(bytes)) +} + +pub(crate) fn ecp2_from_compat_bytes(bytes: &[u8]) -> Result { + if bytes.len() != ECP2_COMPAT_SIZE { + return Err(CredentialError::BadECP2); + } + let x = FP2::new_bigs( + &big_from_bytes(&bytes[..BIG_SIZE])?, + &big_from_bytes(&bytes[BIG_SIZE..BIG_SIZE * 2])?, + ); + let y = FP2::new_bigs( + &big_from_bytes(&bytes[BIG_SIZE * 2..BIG_SIZE * 3])?, + &big_from_bytes(&bytes[BIG_SIZE * 3..BIG_SIZE * 4])?, + ); + Ok(ECP2::new_fp2s(&x, &y)) +} + +pub(crate) fn ecp2_to_compat_bytes(point: &ECP2) -> [u8; ECP2_COMPAT_SIZE] { + let mut result = [0u8; ECP2_COMPAT_SIZE]; + + let mut x = point.getx(); + let mut y = point.gety(); + + x.geta().tobytes(&mut result[..BIG_SIZE]); + x.getb().tobytes(&mut result[BIG_SIZE..BIG_SIZE * 2]); + y.geta().tobytes(&mut result[BIG_SIZE * 2..BIG_SIZE * 3]); + y.getb().tobytes(&mut result[BIG_SIZE * 3..]); + + result +} + +pub(crate) fn big_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != BIG_SIZE { + return Err(CredentialError::BadBIG); + } + Ok(BIG::frombytes(bytes)) +} + +impl TryFrom<&[u8]> for JoinResponse { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != JOIN_RESPONSE_SIZE { + return Err(CredentialError::BadJoinResponse); + } + + Ok(JoinResponse { + cred: bytes[..USER_CREDENTIALS_SIZE].try_into()?, + proof: bytes[USER_CREDENTIALS_SIZE..].try_into()?, + }) + } +} + +impl TryFrom<&[u8]> for UserCredentials { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != USER_CREDENTIALS_SIZE { + return Err(CredentialError::BadUserCredentials); + } + Ok(UserCredentials { + a: ecp_from_bytes(&bytes[..ECP_SIZE])?, + b: ecp_from_bytes(&bytes[ECP_SIZE..ECP_SIZE * 2])?, + c: ecp_from_bytes(&bytes[ECP_SIZE * 2..ECP_SIZE * 3])?, + d: ecp_from_bytes(&bytes[ECP_SIZE * 3..ECP_SIZE * 4])?, + }) + } +} + +impl TryFrom<&[u8]> for GroupPublicKey { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != GROUP_PUBLIC_KEY_SIZE { + return Err(CredentialError::GroupPublicKeyLength); + } + + let big_start = ECP2_COMPAT_SIZE * 2; + + Ok(GroupPublicKey { + x: ecp2_from_compat_bytes(&bytes[..ECP2_COMPAT_SIZE])?, + y: ecp2_from_compat_bytes(&bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2])?, + cx: big_from_bytes(&bytes[big_start..big_start + BIG_SIZE])?, + sx: big_from_bytes(&bytes[big_start + BIG_SIZE..big_start + BIG_SIZE * 2])?, + cy: big_from_bytes(&bytes[big_start + BIG_SIZE * 2..big_start + BIG_SIZE * 3])?, + sy: big_from_bytes(&bytes[big_start + BIG_SIZE * 3..big_start + BIG_SIZE * 4])?, + }) + } +} + +impl CredentialBIG { + pub fn to_bytes(&self) -> [u8; BIG_SIZE] { + let mut bytes = [0u8; BIG_SIZE]; + self.0.tobytes(&mut bytes); + bytes + } +} + +impl TryFrom<&[u8]> for CredentialBIG { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + Ok(Self(big_from_bytes(bytes)?)) + } +} + +impl JoinRequest { + pub fn to_bytes(&self) -> [u8; JOIN_REQUEST_SIZE] { + let mut result = [0u8; JOIN_REQUEST_SIZE]; + self.q.tobytes(&mut result, false); + result[ECP_SIZE..].copy_from_slice(&self.proof.to_bytes()); + result + } +} + +impl UserCredentials { + pub fn to_bytes(&self) -> [u8; USER_CREDENTIALS_SIZE] { + let mut result = [0u8; USER_CREDENTIALS_SIZE]; + self.a.tobytes(&mut result[..ECP_SIZE], false); + self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); + self.c.tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); + self.d.tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); + result + } +} + +impl ECPProof { + pub fn to_bytes(&self) -> [u8; ECP_PROOF_SIZE] { + let mut result = [0u8; ECP_PROOF_SIZE]; + self.c.tobytes(&mut result[..BIG_SIZE]); + self.s.tobytes(&mut result[BIG_SIZE..]); + result + } +} + +impl TryFrom<&[u8]> for ECPProof { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != ECP_PROOF_SIZE { + return Err(CredentialError::BadECPProof); + } + + Ok(ECPProof { + c: big_from_bytes(&bytes[0..BIG_SIZE])?, + s: big_from_bytes(&bytes[BIG_SIZE..])?, + }) + } +} + +impl Signature { + pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] { + let mut result = [0u8; SIGNATURE_SIZE]; + self.a.tobytes(&mut result[..ECP_SIZE], false); + self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); + self.c.tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); + self.d.tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); + self.nym.tobytes(&mut result[ECP_SIZE * 4..ECP_SIZE * 5], false); + result[ECP_SIZE * 5..].copy_from_slice(&self.proof.to_bytes()); + result + } +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/join.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/join.rs new file mode 100644 index 000000000000..96ceb816c63f --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/join.rs @@ -0,0 +1,182 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +use brave_miracl::{ + bn254::{ + big::BIG, + ecp::ECP, + ecp2::ECP2, + fp12::FP12, + pair::{g1mul, g2mul}, + }, + rand::RAND, +}; + +use super::data::{ + ecp2_to_compat_bytes, CredentialBIG, ECPProof, GroupPublicKey, JoinRequest, JoinResponse, + StartJoinResult, UserCredentials, BIG_SIZE, ECP2_COMPAT_SIZE, ECP_SIZE, +}; +use super::util::{ + ecp_challenge_equals, hash256, pair_normalized_triple_ate, random_mod_curve_order, + CURVE_ORDER_BIG, G1_ECP, G2_ECP, +}; +use super::{CredentialError, Result}; + +fn ecp_challenge(message: &[u8; BIG_SIZE], y: &ECP, g: &ECP, gr: &ECP) -> BIG { + let mut all_bytes = [0u8; ECP_SIZE * 3 + BIG_SIZE]; + + all_bytes[..BIG_SIZE].copy_from_slice(message); + + y.tobytes(&mut all_bytes[BIG_SIZE..], false); + g.tobytes(&mut all_bytes[ECP_SIZE + BIG_SIZE..], false); + gr.tobytes(&mut all_bytes[ECP_SIZE * 2 + BIG_SIZE..], false); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} + +fn make_ecp_proof(rng: &mut RAND, y: &ECP, x: &BIG, message: &[u8; BIG_SIZE]) -> ECPProof { + let r = random_mod_curve_order(rng); + + let g = G1_ECP.clone(); + let gr = g1mul(&g, &r); + let c = ecp_challenge(message, y, &g, &gr); + let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); + s.add(&r); + s.rmod(&CURVE_ORDER_BIG); + ECPProof { c, s } +} + +fn verify_ecp_proof_equals(a: &ECP, b: &ECP, y: &ECP, z: &ECP, proof: &ECPProof) -> bool { + let cn = BIG::modneg(&proof.c, &CURVE_ORDER_BIG); + + let mut r#as = g1mul(a, &proof.s); + let yc = g1mul(y, &cn); + let mut bs = g1mul(b, &proof.s); + let zc = g1mul(z, &cn); + + r#as.add(&yc); + bs.add(&zc); + + let cc = ecp_challenge_equals(None, &y, &z, &a, &b, &r#as, &bs); + + BIG::comp(&proof.c, &cc) == 0 +} + +fn verify_aux_fast(a: &ECP, b: &ECP, c: &ECP, d: &ECP, x: &ECP2, y: &ECP2, rng: &mut RAND) -> bool { + if a.is_infinity() { + return false; + } + + let e1 = random_mod_curve_order(rng); + let e2 = random_mod_curve_order(rng); + let ne1 = BIG::modneg(&e1, &CURVE_ORDER_BIG); + let ne2 = BIG::modneg(&e2, &CURVE_ORDER_BIG); + + // AA = e1 * A + let aa = g1mul(a, &e1); + + // BB = -e1 * B + let mut bb = g1mul(b, &ne1); + + // CC = -e2 * C + let mut cc = g1mul(c, &ne2); + + // BB = (-e1 * B) + (-e2 * C) + bb.add(&cc); + + // CC = e2 * (A + D) + cc.copy(a); + cc.add(d); + cc = g1mul(&cc, &e2); + + // w = e(e1·A, Y)·e((-e1·B) + (-e2·C), G2)·e(e2·(A + D), X) + let w = pair_normalized_triple_ate(y, &aa, &G2_ECP, &bb, x, &cc); + + let mut fp12_one = FP12::new(); + fp12_one.one(); + + w.equals(&fp12_one) +} + +pub fn start_join(rng: &mut RAND, challenge: &[u8]) -> StartJoinResult { + let gsk = random_mod_curve_order(rng); + let q = g1mul(&G1_ECP, &gsk); + + let challenge_hash = hash256(challenge); + + let proof = make_ecp_proof(rng, &q, &gsk, &challenge_hash); + + StartJoinResult { gsk: CredentialBIG(gsk), join_msg: JoinRequest { q, proof } } +} + +pub fn finish_join( + pub_key: &GroupPublicKey, + gsk: &CredentialBIG, + resp: JoinResponse, +) -> Result { + verify_group_public_key(pub_key)?; + + let q = g1mul(&G1_ECP, &gsk.0); + + let mut rng = RAND::new(); + rng.seed(BIG_SIZE, &gsk.to_bytes()); + + if !verify_ecp_proof_equals(&G1_ECP, &q, &resp.cred.b, &resp.cred.d, &resp.proof) { + return Err(CredentialError::JoinResponseValidation); + } + + if !verify_aux_fast( + &resp.cred.a, + &resp.cred.b, + &resp.cred.c, + &resp.cred.d, + &pub_key.x, + &pub_key.y, + &mut rng, + ) { + return Err(CredentialError::JoinResponseValidation); + } + + Ok(resp.cred) +} + +fn ecp2_challenge(y: &ECP2, g: &ECP2, gr: &ECP2) -> BIG { + let mut all_bytes = [0u8; ECP2_COMPAT_SIZE * 3]; + + all_bytes[..ECP2_COMPAT_SIZE].copy_from_slice(&ecp2_to_compat_bytes(y)); + all_bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2].copy_from_slice(&ecp2_to_compat_bytes(g)); + all_bytes[ECP2_COMPAT_SIZE * 2..].copy_from_slice(&ecp2_to_compat_bytes(gr)); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} + +fn verify_ecp2_proof(y: &ECP2, c: &BIG, s: &BIG) -> bool { + let cn = BIG::modneg(c, &CURVE_ORDER_BIG); + + let mut gs = g2mul(&G2_ECP, s); + let yc = g2mul(y, &cn); + + gs.add(&yc); + + let cc = ecp2_challenge(y, &G2_ECP, &gs); + + BIG::comp(c, &cc) == 0 +} + +fn verify_group_public_key(key: &GroupPublicKey) -> Result<()> { + match verify_ecp2_proof(&key.x, &key.cx, &key.sx) && verify_ecp2_proof(&key.y, &key.cy, &key.sy) + { + true => Ok(()), + false => Err(CredentialError::BadGroupPublicKey), + } +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/lib.rs new file mode 100644 index 000000000000..15effca276dd --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/lib.rs @@ -0,0 +1,243 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. +//! Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). +//! +//! bn254 is the only supported curve for this library. + +mod data; +mod join; +mod sign; +mod util; + +use brave_miracl::rand::RAND; +use rand::{rngs::OsRng, RngCore}; +use thiserror::Error; + +pub use self::data::*; +use self::join::{finish_join, start_join}; +use self::sign::sign; + +#[derive(Error, Debug)] +pub enum CredentialError { + #[error("ECP should be {0} bytes", ECP_SIZE)] + BadECP, + #[error("ECP2 should be {0} bytes", ECP2_COMPAT_SIZE)] + BadECP2, + #[error("BIG should be {0} bytes", BIG_SIZE)] + BadBIG, + #[error("ECP proof should be {0} bytes", ECP_PROOF_SIZE)] + BadECPProof, + #[error("User credentials should be {0} bytes", USER_CREDENTIALS_SIZE)] + BadUserCredentials, + #[error("Join response should be {0} bytes", JOIN_RESPONSE_SIZE)] + BadJoinResponse, + #[error("Group public key should be {0} bytes", GROUP_PUBLIC_KEY_SIZE)] + GroupPublicKeyLength, + #[error("Join response validation failed")] + JoinResponseValidation, + #[error("Private key and/or credentials not set")] + CredentialsNotSet, + #[error("Group public key verification failed")] + BadGroupPublicKey, +} + +pub type Result = std::result::Result; + +/// Creates and manages Direct Anonymous Attestation credentials +/// using the bn254 curve. +pub struct CredentialManager { + rng: RAND, + gsk_and_credentials: Option<(CredentialBIG, UserCredentials)>, +} + +impl CredentialManager { + /// Creates new manager with random seed. + pub fn new() -> Self { + let mut entropy = [0u8; 128]; + OsRng::default().fill_bytes(&mut entropy); + Self::new_with_seed(&entropy) + } + + /// Creates new manager with fixed seed. Should only be used for testing. + pub fn new_with_seed(entropy: &[u8]) -> Self { + let mut rng = RAND::new(); + + rng.seed(entropy.len(), entropy); + + Self { rng, gsk_and_credentials: None } + } + + /// Creates a "join" requests to be sent to the credential issuer, + /// for a given challenge. + pub fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { + start_join(&mut self.rng, challenge) + } + + /// Processes a "join" response from the issuer, and returns anonymous + /// credentials. + pub fn finish_join( + &mut self, + public_key: &GroupPublicKey, + gsk: &CredentialBIG, + join_resp: JoinResponse, + ) -> Result { + finish_join(public_key, gsk, join_resp) + } + + /// Sets the key and credentials to be used for signing requests. + pub fn set_gsk_and_credentials(&mut self, gsk: CredentialBIG, credentials: UserCredentials) { + self.gsk_and_credentials = Some((gsk, credentials)); + } + + /// Signs a message using the pre-set credentials and a given basename. + /// Returns a signature to be sent to the verifier. + pub fn sign(&mut self, msg: &[u8], basename: &[u8]) -> Result { + match &self.gsk_and_credentials { + Some((gsk, credentials)) => Ok(sign(&mut self.rng, gsk, credentials, msg, basename)), + None => Err(CredentialError::CredentialsNotSet), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use lazy_static::lazy_static; + + lazy_static! { + static ref EXPECTED_GSK: Vec = + hex::decode("0198c86f99ede0ca2ed30b8e4ae6cac831c9b398445422a41d95abb4d3f03499") + .unwrap(); + static ref GROUP_PUB_KEY: Vec = hex::decode( + "0477ce930400ab04a6e1caa46601dbd1b1ba5d24f0577834a960285a0512e7ed\ + 0174121707ea5d80e083d2e992236864608998a4d08cb3a41dde1fc6b7eaad5b2\ + 125310b44ca712bf63f62c39cb44917de0772fefd876e170729428142c21d4f17\ + 9f72fcdc1c1ff5f13e272449ac9ff01a74e95bb011045b12bdac942b46168d051\ + 1ecbb4651d9ddd6491437a8d6b6e6e6877038ea4317a5de863e237ff6472014d2\ + 2c88863b6d8de3eb1b73bb46ab12553c2765bcde905487c518936887ba831dc42\ + ca4862bf60b7cccf08ae579f14699fcff5ec8366af5562a2117095dc066105c17\ + 714dadae0b2110b91d0f19f062e9ab410f59e4515cb027e268435502cf12d4a2d\ + de1c5b711619507485e54e6e6bb1b279e7f42067c47b124e7b1e044de0345f28c\ + ea642eef79e0da60dad085b9bec8b73c61a4eee59ec4f024fc83366e1efc63762\ + b2c1c214ad151dd01f1a5f16d5a238187f1afdab361dfea2e0956be24b1bcdba7\ + c9a6a5e0296377bd1cf1b722bc4d375ae8aa4761b7aac5a50e9871" + ) + .unwrap(); + static ref EXPECTED_CREDENTIALS: Vec = hex::decode( + "04246220e5a9d48d359178c9e0994cc10f7288b50\ + cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ + bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ + 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ + 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ + 9939ec717f4f39e114337878f03c9066afc2250332\ + 76f162b4904248822cb548ccb8167480e23f019813\ + 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ + dd7c9f0006eab2576635a36af81e0f781437c4ee35\ + b8672511089830401074ad73c4e9e9aed541bdc5a2\ + df2ee815a3ac4f6297b73da35db2a646e19720475c\ + fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ + bd494be6a551768c8", + ) + .unwrap(); + } + + const CHALLENGE: &[u8] = b"challenge"; + + fn manager_with_fixed_seed() -> CredentialManager { + let entropy = [0u8; 1]; + CredentialManager::new_with_seed(&entropy) + } + + #[test] + fn test_gsk_and_join_msg() { + let mut cm = manager_with_fixed_seed(); + let result = cm.start_join(CHALLENGE); + + let expected_join_msg = hex::decode( + "04185d9e3a0f0e590928568a951a70749c5f3e\ + 969b3c335f109f0e95f4c0cbabe70ddd27e6751\ + df37fa70b906d3d246b388a2a9fb67c3972ea1b\ + 822dc80653454e0de86a209418b4953191caa980\ + 462463ec21b07da451e7becc2d7917ef34f5150c\ + 1c0a4187182af0a43a28868c7b17b2c73704bc26\ + 8071b414d99f48999014b2", + ) + .unwrap(); + + assert_eq!(result.gsk.to_bytes().as_slice(), EXPECTED_GSK.as_slice()); + assert_eq!(result.join_msg.to_bytes().as_slice(), &expected_join_msg); + } + + #[test] + fn test_finish_join_credentials() { + let mut cm = manager_with_fixed_seed(); + + let group_pub_key: GroupPublicKey = GROUP_PUB_KEY.as_slice().try_into().unwrap(); + let gsk: CredentialBIG = EXPECTED_GSK.as_slice().try_into().unwrap(); + let join_response: JoinResponse = hex::decode( + "04246220e5a9d48d359178c9e0994cc10f7288b50\ + cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ + bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ + 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ + 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ + 9939ec717f4f39e114337878f03c9066afc2250332\ + 76f162b4904248822cb548ccb8167480e23f019813\ + 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ + dd7c9f0006eab2576635a36af81e0f781437c4ee35\ + b8672511089830401074ad73c4e9e9aed541bdc5a2\ + df2ee815a3ac4f6297b73da35db2a646e19720475c\ + fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ + bd494be6a551768c81677932196184249f179d319f\ + eba43b32da42501daa355d3cde30615a08ac687188\ + a8c6e3b8a330f76c233e900acd6ef31c50796b9192\ + 9cfc16b4fcad40b5309", + ) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + + let credentials = cm.finish_join(&group_pub_key, &gsk, join_response).unwrap().to_bytes(); + + assert_eq!(credentials.as_slice(), EXPECTED_CREDENTIALS.as_slice()); + } + + #[test] + fn test_signature() { + let mut cm = manager_with_fixed_seed(); + + let gsk = EXPECTED_GSK.as_slice().try_into().unwrap(); + let credentials = EXPECTED_CREDENTIALS.as_slice().try_into().unwrap(); + cm.set_gsk_and_credentials(gsk, credentials); + + let expected_signature = hex::decode( + "0406cb022fcc3dcaef1e4c62dad349bfd263581126c\ + f17b293d1a41e4d96f840da00ad85e4a97aad1247a19\ + a425da6f96978fdac180136f0f486bad0fce0a9ada20\ + 401074ad73c4e9e9aed541bdc5a2df2ee815a3ac4f62\ + 97b73da35db2a646e19720475cfe50eb2465833b5075\ + 8f6c8f09fdf645643a4b3ef5bd494be6a551768c8042\ + 4a006154937bcd3b8f94f12a4672d9a9411928846adc\ + 9132737600089a65915121160cbd4e417435e4acfe66\ + 57840c50584bc8dca420544879fe7fe9c03bc0f0418e\ + e65a71c262c5301d782b20e7f3f252e938282b98a2f8\ + 6a7447e2aa424005819835a0a954d4f6dc53ae4c8bad\ + 2d192a70fcb8883403f69989e43ff66caad0104208cd\ + 8eb5e25486eb754e44f4e2f3b6f5153f5aa73d7eab8c\ + 2f5c867a157276b0463ced7f409f86ef91a4548cf4bb\ + 519392cd657505475e585a3ea0348b6266b1fd3d4ab1\ + 253392386bf2f08afe36072abe575e07865272c3014a\ + b067f5051181fe574571f34d278e2c9359294ca44aa3\ + 3568c546082e4e8d921541e5ccc6c81", + ) + .unwrap(); + + let signature_bytes = cm.sign(b"message", b"basename").unwrap().to_bytes(); + + assert_eq!(signature_bytes, expected_signature.as_slice()); + } +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/sign.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/sign.rs new file mode 100644 index 000000000000..4012347312e7 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/sign.rs @@ -0,0 +1,66 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +use brave_miracl::{ + bn254::{big::BIG, ecp::ECP, pair::g1mul}, + rand::RAND, +}; + +use super::{ + data::{CredentialBIG, ECPProof, Signature, UserCredentials, BIG_SIZE}, + util::{ecp_challenge_equals, hash256, random_mod_curve_order, CURVE_ORDER_BIG}, +}; + +fn make_ecp_proof_equals( + rng: &mut RAND, + message: &[u8; BIG_SIZE], + a: &ECP, + b: &ECP, + y: &ECP, + z: &ECP, + x: &BIG, +) -> ECPProof { + let r = random_mod_curve_order(rng); + + let ar = g1mul(&a, &r); + let br = g1mul(&b, &r); + + let c = ecp_challenge_equals(Some(message), y, z, a, b, &ar, &br); + let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); + s.add(&r); + s.rmod(&CURVE_ORDER_BIG); + + ECPProof { c, s } +} + +pub fn sign( + rng: &mut RAND, + gsk: &CredentialBIG, + credentials: &UserCredentials, + msg: &[u8], + bsn: &[u8], +) -> Signature { + // Randomize credentials for signature + let r = random_mod_curve_order(rng); + + let a = g1mul(&credentials.a, &r); + let b = g1mul(&credentials.b, &r); + let c = g1mul(&credentials.c, &r); + let d = g1mul(&credentials.d, &r); + + // Map basename to point in G1 + let bsn_hash = hash256(bsn); + let bsn_point = ECP::mapit(&bsn_hash); + let nym = g1mul(&bsn_point, &gsk.0); + + // Compute H(H(msg) || H(bsn)) to be used in proof of equality + let mut msg_bsn_hash_data = [0u8; BIG_SIZE * 2]; + msg_bsn_hash_data[..BIG_SIZE].copy_from_slice(&hash256(msg)); + msg_bsn_hash_data[BIG_SIZE..].copy_from_slice(&hash256(bsn)); + let msg_bsn_hash = hash256(&msg_bsn_hash_data); + + let proof = make_ecp_proof_equals(rng, &msg_bsn_hash, &b, &bsn_point, &d, &nym, &gsk.0); + Signature { a, b, c, d, nym, proof } +} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/util.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/util.rs new file mode 100644 index 000000000000..a249020edd0e --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/util.rs @@ -0,0 +1,90 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +use brave_miracl::{ + bn254::{ + big::BIG, + ecp::ECP, + ecp2::ECP2, + fp12::FP12, + fp2::FP2, + pair::{another, fexp, initmp, miller}, + rom::{CURVE_GX, CURVE_GY, CURVE_ORDER, CURVE_PXA, CURVE_PXB, CURVE_PYA, CURVE_PYB}, + }, + hash256::HASH256, + rand::RAND, +}; +use lazy_static::lazy_static; + +use super::data::{BIG_SIZE, ECP_SIZE}; + +lazy_static! { + pub static ref G1_ECP: ECP = { + let gx = BIG::new_ints(&CURVE_GX); + let gy = BIG::new_ints(&CURVE_GY); + ECP::new_bigs(&gx, &gy) + }; + pub static ref G2_ECP: ECP2 = { + let pxa = BIG::new_ints(&CURVE_PXA); + let pxb = BIG::new_ints(&CURVE_PXB); + let pya = BIG::new_ints(&CURVE_PYA); + let pyb = BIG::new_ints(&CURVE_PYB); + let wx = FP2::new_bigs(&pxa, &pxb); + let wy = FP2::new_bigs(&pya, &pyb); + ECP2::new_fp2s(&wx, &wy) + }; + pub static ref CURVE_ORDER_BIG: BIG = BIG::new_ints(&CURVE_ORDER); +} + +pub fn random_mod_curve_order(rng: &mut RAND) -> BIG { + BIG::randomnum(&CURVE_ORDER_BIG, rng) +} + +pub fn hash256(data: &[u8]) -> [u8; 32] { + let mut hash = HASH256::new(); + hash.process_array(data); + hash.hash() +} + +pub fn pair_normalized_triple_ate(p: &ECP2, q: &ECP, r: &ECP2, s: &ECP, t: &ECP2, u: &ECP) -> FP12 { + let mut rr = initmp(); + another(&mut rr, p, q); + another(&mut rr, r, s); + another(&mut rr, t, u); + let r = miller(&mut rr); + fexp(&r) +} + +pub fn ecp_challenge_equals( + message: Option<&[u8; BIG_SIZE]>, + y: &ECP, + z: &ECP, + a: &ECP, + b: &ECP, + ar: &ECP, + br: &ECP, +) -> BIG { + let (mut all_bytes, msg_len) = match message { + Some(message) => { + let mut all_bytes = vec![0u8; ECP_SIZE * 6 + BIG_SIZE]; + all_bytes[..BIG_SIZE].copy_from_slice(message); + (all_bytes, message.len()) + } + None => (vec![0u8; ECP_SIZE * 6], 0), + }; + + y.tobytes(&mut all_bytes[msg_len..], false); + z.tobytes(&mut all_bytes[msg_len + ECP_SIZE..], false); + a.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 2..], false); + b.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 3..], false); + ar.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 4..], false); + br.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 5..], false); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} diff --git a/script/brave_license_helper.py b/script/brave_license_helper.py index 214d86d3d2d3..312ec5cfce7e 100644 --- a/script/brave_license_helper.py +++ b/script/brave_license_helper.py @@ -42,6 +42,9 @@ def AddBraveCredits(root, prune_paths, special_cases, prune_dirs, # Rust code written by Brave and under the same license as the browser. os.path.join('brave', 'third_party', 'rust', 'adblock_cxx'), + os.path.join('brave', 'third_party', 'rust', 'anonymous_credentials'), + os.path.join('brave', 'third_party', 'rust', + 'anonymous_credentials_cxx'), os.path.join('brave', 'third_party', 'rust', 'brave_news_cxx'), os.path.join('brave', 'third_party', 'rust', 'brave_wallet'), os.path.join('brave', 'third_party', 'rust', diff --git a/third_party/rust/anonymous_credentials/v0_1/README.chromium b/third_party/rust/anonymous_credentials/v0_1/README.chromium new file mode 100644 index 000000000000..27bae2a94df4 --- /dev/null +++ b/third_party/rust/anonymous_credentials/v0_1/README.chromium @@ -0,0 +1,8 @@ +Name: anonymous-credentials +URL: https://crates.io/crates/anonymous-credentials +Description: Implementation of Direct Anonymous Attestation for the Web Discovery Project +Version: 0.1.4 +Security Critical: yes +Shipped: yes +License: Mozilla Public License 2.0 +License File: diff --git a/third_party/rust/anonymous_credentials_cxx/v0_1/README.chromium b/third_party/rust/anonymous_credentials_cxx/v0_1/README.chromium new file mode 100644 index 000000000000..f20c1192a5fe --- /dev/null +++ b/third_party/rust/anonymous_credentials_cxx/v0_1/README.chromium @@ -0,0 +1,8 @@ +Name: anonymous-credentials-cxx +URL: https://crates.io/crates/anonymous-credentials-cxx +Description: +Version: 0.1.0 +Security Critical: yes +Shipped: yes +License: Mozilla Public License 2.0 +License File: diff --git a/third_party/rust/brave_miracl/v0_1/BUILD.gn b/third_party/rust/brave_miracl/v0_1/BUILD.gn new file mode 100644 index 000000000000..28a360c7d608 --- /dev/null +++ b/third_party/rust/brave_miracl/v0_1/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by +# tools/crates/gnrt. +# Do not edit! + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "brave_miracl" + epoch = "0.1" + crate_type = "rlib" + crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs" + sources = [ + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/aes.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/arch.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/big.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/bls.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/dbig.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecdh.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp2.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/eddsa.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp12.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp2.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp4.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/hpke.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mod.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mpin.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/pair.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/rom.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/dilithium.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/gcm.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash256.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash384.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash512.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hmac.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/kyber.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/main.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/nhs.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/rand.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/sha3.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/share.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/x509.rs", + ] + inputs = [] + + build_native_rust_unit_tests = false + edition = "2021" + cargo_pkg_version = "0.1.3" + cargo_pkg_authors = "Mike Scott " + cargo_pkg_name = "brave-miracl" + cargo_pkg_description = + "Subset of the MIRACL Core library that includes the bn254 elliptic curve" + library_configs -= [ "//build/config/compiler:chromium_code" ] + library_configs += [ "//build/config/compiler:no_chromium_code" ] + executable_configs -= [ "//build/config/compiler:chromium_code" ] + executable_configs += [ "//build/config/compiler:no_chromium_code" ] + proc_macro_configs -= [ "//build/config/compiler:chromium_code" ] + proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] + features = [ "std" ] +} diff --git a/third_party/rust/brave_miracl/v0_1/README.chromium b/third_party/rust/brave_miracl/v0_1/README.chromium new file mode 100644 index 000000000000..2220ddbaabca --- /dev/null +++ b/third_party/rust/brave_miracl/v0_1/README.chromium @@ -0,0 +1,9 @@ +Name: brave-miracl +URL: https://crates.io/crates/brave-miracl +Description: Subset of the MIRACL Core library that includes the bn254 elliptic curve +Version: 0.1.3 +Security Critical: yes +Shipped: yes +License: Apache 2.0 +License File: //brave/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/LICENSE +Revision: fb447a11105dae466ddd7f9eb666a30cbceff539 diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock index 281d8105b706..f34713c7d7fe 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock @@ -100,6 +100,24 @@ dependencies = [ "libc", ] +[[package]] +name = "anonymous-credentials" +version = "0.1.4" +dependencies = [ + "brave-miracl", + "lazy_static", + "rand 0.8.5", + "thiserror", +] + +[[package]] +name = "anonymous-credentials-cxx" +version = "0.1.0" +dependencies = [ + "anonymous-credentials", + "cxx", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -251,6 +269,11 @@ dependencies = [ "subtle", ] +[[package]] +name = "brave-miracl" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "brave-news-cxx" version = "1.0.0" @@ -373,6 +396,7 @@ name = "chromium" version = "0.1.0" dependencies = [ "adblock-cxx", + "anonymous-credentials-cxx", "brave-news-cxx", "brave_wallet", "challenge-bypass-ristretto-cxx", diff --git a/third_party/rust/chromium_crates_io/Cargo.toml b/third_party/rust/chromium_crates_io/Cargo.toml index ea92188a663d..3b4dbd844f62 100644 --- a/third_party/rust/chromium_crates_io/Cargo.toml +++ b/third_party/rust/chromium_crates_io/Cargo.toml @@ -26,6 +26,7 @@ adblock-cxx = { version = "1" } constellation-cxx = "0.1" challenge-bypass-ristretto-cxx = "1" zcash = "1" +anonymous-credentials-cxx = "0.1" [patch.crates-io.futures-retry_v0_5] path = "../futures_retry/v0_5/crate" @@ -79,6 +80,14 @@ package = "constellation-cxx" path = "../../../components/challenge_bypass_ristretto/rust/cxx" package = "challenge-bypass-ristretto-cxx" +[patch.crates-io.anonymous-credentials_v0_1] +path = "../../../components/web_discovery/browser/anonymous_credentials/rs/lib" +package = "anonymous-credentials" + +[patch.crates-io.anonymous-credentials-cxx_v0_1] +path = "../../../components/web_discovery/browser/anonymous_credentials/rs/cxx" +package = "anonymous-credentials-cxx" + [patch.crates-io.aho_corasick_v1] path = "../../../../third_party/rust/chromium_crates_io/vendor/aho-corasick-1.1.3" package = "aho-corasick" diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo-checksum.json new file mode 100644 index 000000000000..697c9ce2fbb4 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{}} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo_vcs_info.json new file mode 100644 index 000000000000..e273ed2a6c61 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "fb447a11105dae466ddd7f9eb666a30cbceff539" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitignore b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitignore new file mode 100644 index 000000000000..96ef6c0b944e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitmodules b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitmodules new file mode 100644 index 000000000000..987edd9563d6 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/.gitmodules @@ -0,0 +1,3 @@ +[submodule "miracl-core"] + path = miracl-core + url = https://github.com/miracl/core diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml new file mode 100644 index 000000000000..e0d3f4510d19 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml @@ -0,0 +1,34 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "brave-miracl" +version = "0.1.3" +authors = ["Mike Scott "] +exclude = [ + "/miracl-core", + "generate.sh", + "renovate.json", +] +description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" +homepage = "https://github.com/miracl/core" +readme = "README.md" +keywords = ["bn254"] +categories = ["cryptography"] +license = "Apache-2.0" +repository = "https://github.com/brave-experiments/miracl-rs" + +[dependencies] + +[features] +default = ["std"] +std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml.orig new file mode 100644 index 000000000000..13ebaef9e368 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/Cargo.toml.orig @@ -0,0 +1,18 @@ +[package] +name = "brave-miracl" +version = "0.1.3" +edition = "2021" +authors = ["Mike Scott "] +description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" +license = "Apache-2.0" +homepage = "https://github.com/miracl/core" +repository = "https://github.com/brave-experiments/miracl-rs" +keywords = ["bn254"] +categories = ["cryptography"] +exclude = ["/miracl-core", "generate.sh", "renovate.json"] + +[dependencies] + +[features] +default = ["std"] +std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/LICENSE b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/LICENSE new file mode 100644 index 000000000000..3c8565d62f17 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Miracl Technologies Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/README.md b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/README.md new file mode 100644 index 000000000000..67423ec88b3f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/README.md @@ -0,0 +1,15 @@ +# brave-miracl + +[![Crates.io](https://img.shields.io/crates/v/brave-miracl?style=for-the-badge)](https://crates.io/crates/brave-miracl) + +A subset of the [MIRACL Core](https://github.com/miracl/core) library that includes the bn254 elliptic curve. + +## Updating the library code + +MIRACL Core is embedded in this repository as a git submodule. + +The library code can be updated and regenerated by executing `./generate.sh`. + +## License + +MIRACL Core is licensed under the [Apache 2.0 License](LICENSE). diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/aes.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/aes.rs new file mode 100644 index 000000000000..1242e351b807 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/aes.rs @@ -0,0 +1,888 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub const ECB: usize = 0; +pub const CBC: usize = 1; +pub const CFB1: usize = 2; +pub const CFB2: usize = 3; +pub const CFB4: usize = 5; +pub const OFB1: usize = 14; +pub const OFB2: usize = 15; +pub const OFB4: usize = 17; +pub const OFB8: usize = 21; +pub const OFB16: usize = 29; +pub const CTR1: usize = 30; +pub const CTR2: usize = 31; +pub const CTR4: usize = 33; +pub const CTR8: usize = 37; +pub const CTR16: usize = 45; + +const INCO: [u8; 4] = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */ + +const PTAB: [u8; 256] = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, + 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, + 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, + 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, + 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, + 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, + 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, + 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, + 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, + 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +]; + +const LTAB: [u8; 256] = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, + 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, + 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, + 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, + 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, + 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, + 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, + 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, + 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, + 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, + 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, + 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, + 24, 13, 99, 140, 128, 192, 247, 112, 7, +]; + +const FBSUB: [u8; 256] = [ + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, + 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, + 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, + 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, + 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, + 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, + 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, + 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, + 153, 45, 15, 176, 84, 187, 22, +]; + +const RBSUB: [u8; 256] = [ + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, + 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, + 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, + 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, + 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, + 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, + 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, + 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, + 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, + 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, + 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, + 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, + 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, +]; + +const RCO: [u8; 16] = [ + 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, +]; + +const FTABLE: [u32; 256] = [ + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, + 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, +]; + +const RTABLE: [u32; 256] = [ + 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, + 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, + 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, + 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, + 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, + 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, + 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, + 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, + 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, + 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, + 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, + 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, + 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, + 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, + 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, + 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, + 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, + 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, + 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, + 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, + 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, + 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, + 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, + 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, + 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, + 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, + 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, + 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, +]; + +pub struct AES { + // nk: usize, + nr: usize, + mode: usize, + fkey: [u32; 60], + rkey: [u32; 60], + pub f: [u8; 16], +} + +fn rotl8(x: u32) -> u32 { + ((x) << 8) | ((x) >> 24) +} + +fn rotl16(x: u32) -> u32 { + ((x) << 16) | ((x) >> 16) +} + +fn rotl24(x: u32) -> u32 { + ((x) << 24) | ((x) >> 8) +} + +fn pack(b: [u8; 4]) -> u32 { + /* pack bytes into a 32-bit Word */ + ((b[3] as u32) << 24) | ((b[2] as u32) << 16) | ((b[1] as u32) << 8) | (b[0] as u32) +} + +fn unpack(a: u32) -> [u8; 4] { + /* unpack bytes from a word */ + [ + (a & 0xff) as u8, + ((a >> 8) & 0xff) as u8, + ((a >> 16) & 0xff) as u8, + ((a >> 24) & 0xff) as u8, + ] +} + +fn bmul(x: u8, y: u8) -> u8 { + /* x.y= AntiLog(Log(x) + Log(y)) */ + let ix = (x as usize) & 0xff; + let iy = (y as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + let ly = (LTAB[iy] as usize) & 0xff; + + if x != 0 && y != 0 { + PTAB[(lx + ly) % 255] + } else { + 0 + } +} + +fn subbyte(a: u32) -> u32 { + let mut b = unpack(a); + b[0] = FBSUB[b[0] as usize]; + b[1] = FBSUB[b[1] as usize]; + b[2] = FBSUB[b[2] as usize]; + b[3] = FBSUB[b[3] as usize]; + pack(b) +} + +fn product(x: u32, y: u32) -> u8 { + /* dot product of two 4-byte arrays */ + let xb = unpack(x); + let yb = unpack(y); + + bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]) +} + +fn invmixcol(x: u32) -> u32 { + /* matrix Multiplication */ + let mut b: [u8; 4] = [0; 4]; + let mut m = pack(INCO); + b[3] = product(m, x); + m = rotl24(m); + b[2] = product(m, x); + m = rotl24(m); + b[1] = product(m, x); + m = rotl24(m); + b[0] = product(m, x); + pack(b) +} + +fn increment(f: &mut [u8; 16]) { + for i in 0..16 { + f[i] += 1; + if f[i] != 0 { + break; + } + } +} + +impl AES { + pub fn new() -> AES { + AES { + // nk: 0, + nr: 0, + mode: 0, + fkey: [0; 60], + rkey: [0; 60], + f: [0; 16], + } + } + + /* reset cipher */ + pub fn reset(&mut self, m: usize, iv: Option<[u8; 16]>) { + /* reset mode, or reset iv */ + self.mode = m; + for i in 0..16 { + self.f[i] = 0 + } + if self.mode != ECB { + if let Some(x) = iv { + for i in 0..16 { + self.f[i] = x[i] + } + } + } + } + + pub fn init(&mut self, m: usize, nkey: usize, key: &[u8], iv: Option<[u8; 16]>) -> bool { + /* Key Scheduler. Create expanded encryption key */ + let mut cipherkey: [u32; 8] = [0; 8]; + let mut b: [u8; 4] = [0; 4]; + let nk = nkey / 4; + if nk != 4 && nk != 6 && nk != 8 { + return false; + } + let nr = 6 + nk; + //self.nk = nk; + self.nr = nr; + self.reset(m, iv); + let n = 4 * (nr + 1); + + let mut j = 0; + for i in 0..nk { + for k in 0..4 { + b[k] = key[j + k] + } + cipherkey[i] = pack(b); + j += 4; + } + + for i in 0..nk { + self.fkey[i] = cipherkey[i] + } + + j = nk; + let mut k = 0; + while j < n { + self.fkey[j] = self.fkey[j - nk] ^ subbyte(rotl24(self.fkey[j - 1])) ^ (RCO[k] as u32); + if nk <= 6 { + for i in 1..nk { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + } else { + for i in 1..4 { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + + if (j + 4) < n { + self.fkey[j + 4] = self.fkey[j + 4 - nk] ^ subbyte(self.fkey[j + 3]); + } + for i in 5..nk { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + } + j += nk; + k += 1; + } + + /* now for the expanded decrypt key in reverse order */ + + for j in 0..4 { + self.rkey[j + n - 4] = self.fkey[j] + } + let mut i = 4; + while i < n - 4 { + let k = n - 4 - i; + for j in 0..4 { + self.rkey[k + j] = invmixcol(self.fkey[i + j]) + } + i += 4; + } + for j in n - 4..n { + self.rkey[j + 4 - n] = self.fkey[j] + } + true + } + + pub fn getreg(&mut self) -> [u8; 16] { + let mut ir: [u8; 16] = [0; 16]; + for i in 0..16 { + ir[i] = self.f[i] + } + ir + } + + /* Encrypt a single block */ + pub fn ecb_encrypt(&mut self, buff: &mut [u8; 16]) { + let mut b: [u8; 4] = [0; 4]; + let mut p: [u32; 4] = [0; 4]; + let mut q: [u32; 4] = [0; 4]; + + let mut j = 0; + for i in 0..4 { + for k in 0..4 { + b[k] = buff[j + k] + } + p[i] = pack(b); + p[i] ^= self.fkey[i]; + j += 4; + } + + let mut k = 4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + q[0] = self.fkey[k] + ^ FTABLE[(p[0] & 0xff) as usize] + ^ rotl8(FTABLE[((p[1] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[2] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[3] >> 24) & 0xff) as usize]); + + q[1] = self.fkey[k + 1] + ^ FTABLE[(p[1] & 0xff) as usize] + ^ rotl8(FTABLE[((p[2] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[3] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[0] >> 24) & 0xff) as usize]); + + q[2] = self.fkey[k + 2] + ^ FTABLE[(p[2] & 0xff) as usize] + ^ rotl8(FTABLE[((p[3] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[0] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[1] >> 24) & 0xff) as usize]); + + q[3] = self.fkey[k + 3] + ^ FTABLE[(p[3] & 0xff) as usize] + ^ rotl8(FTABLE[((p[0] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[1] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[2] >> 24) & 0xff) as usize]); + + k += 4; + for j in 0..4 { + core::mem::swap(&mut p[j], &mut q[j]); + } + } + + /* Last Round */ + + q[0] = self.fkey[k] + ^ (FBSUB[(p[0] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); + + q[1] = self.fkey[k + 1] + ^ (FBSUB[(p[1] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); + + q[2] = self.fkey[k + 2] + ^ (FBSUB[(p[2] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); + + q[3] = self.fkey[k + 3] + ^ (FBSUB[(p[3] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); + + j = 0; + for i in 0..4 { + b = unpack(q[i]); + for k in 0..4 { + buff[j + k] = b[k] + } + j += 4; + } + } + + /* Decrypt a single block */ + pub fn ecb_decrypt(&mut self, buff: &mut [u8; 16]) { + let mut b: [u8; 4] = [0; 4]; + let mut p: [u32; 4] = [0; 4]; + let mut q: [u32; 4] = [0; 4]; + + let mut j = 0; + for i in 0..4 { + for k in 0..4 { + b[k] = buff[j + k] + } + p[i] = pack(b); + p[i] ^= self.rkey[i]; + j += 4; + } + + let mut k = 4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + q[0] = self.rkey[k] + ^ RTABLE[(p[0] & 0xff) as usize] + ^ rotl8(RTABLE[((p[3] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[2] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[1] >> 24) & 0xff) as usize]); + + q[1] = self.rkey[k + 1] + ^ RTABLE[(p[1] & 0xff) as usize] + ^ rotl8(RTABLE[((p[0] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[3] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[2] >> 24) & 0xff) as usize]); + + q[2] = self.rkey[k + 2] + ^ RTABLE[(p[2] & 0xff) as usize] + ^ rotl8(RTABLE[((p[1] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[0] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[3] >> 24) & 0xff) as usize]); + + q[3] = self.rkey[k + 3] + ^ RTABLE[(p[3] & 0xff) as usize] + ^ rotl8(RTABLE[((p[2] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[1] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[0] >> 24) & 0xff) as usize]); + + k += 4; + for j in 0..4 { + core::mem::swap(&mut p[j], &mut q[j]); + } + } + + /* Last Round */ + + q[0] = self.rkey[k] + ^ (RBSUB[(p[0] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); + + q[1] = self.rkey[k + 1] + ^ (RBSUB[(p[1] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); + + q[2] = self.rkey[k + 2] + ^ (RBSUB[(p[2] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); + + q[3] = self.rkey[k + 3] + ^ (RBSUB[((p[3]) & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); + + j = 0; + for i in 0..4 { + b = unpack(q[i]); + for k in 0..4 { + buff[j + k] = b[k] + } + j += 4; + } + } + + /* Encrypt using selected mode of operation */ + pub fn encrypt(&mut self, buff: &mut [u8; 16]) -> u32 { + let mut st: [u8; 16] = [0; 16]; + + // Supported Modes of Operation + + let mut fell_off: u32 = 0; + + match self.mode { + ECB => { + self.ecb_encrypt(buff); + 0 + } + CBC => { + for j in 0..16 { + buff[j] ^= self.f[j] + } + self.ecb_encrypt(buff); + for j in 0..16 { + self.f[j] = buff[j] + } + 0 + } + + CFB1 | CFB2 | CFB4 => { + let bytes = self.mode - CFB1 + 1; + for j in 0..bytes { + fell_off = (fell_off << 8) | (self.f[j] as u32) + } + for j in 0..16 { + st[j] = self.f[j] + } + for j in bytes..16 { + self.f[j - bytes] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j]; + self.f[16 - bytes + j] = buff[j]; + } + fell_off + } + + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes = self.mode - OFB1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + for j in 0..16 { + self.f[j] = st[j] + } + + //self.ecb_encrypt(&mut (self.f)); + //for j in 0..bytes {buff[j]^=self.f[j]} + 0 + } + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes = self.mode - CTR1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + increment(&mut (self.f)); + 0 + } + + _ => 0, + } + } + + /* Decrypt using selected mode of operation */ + pub fn decrypt(&mut self, buff: &mut [u8; 16]) -> u32 { + let mut st: [u8; 16] = [0; 16]; + + // Supported Modes of Operation + + let mut fell_off: u32 = 0; + + match self.mode { + ECB => { + self.ecb_decrypt(buff); + 0 + } + CBC => { + for j in 0..16 { + st[j] = self.f[j]; + self.f[j] = buff[j]; + } + self.ecb_decrypt(buff); + for j in 0..16 { + buff[j] ^= st[j]; + st[j] = 0; + } + 0 + } + CFB1 | CFB2 | CFB4 => { + let bytes = self.mode - CFB1 + 1; + for j in 0..bytes { + fell_off = (fell_off << 8) | (self.f[j] as u32) + } + for j in 0..16 { + st[j] = self.f[j] + } + for j in bytes..16 { + self.f[j - bytes] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + self.f[16 - bytes + j] = buff[j]; + buff[j] ^= st[j]; + } + fell_off + } + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes = self.mode - OFB1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + for j in 0..16 { + self.f[j] = st[j] + } + // self.ecb_encrypt(A.f[:]); + // for j in 0..bytes {buff[j]^=self.f[j]} + 0 + } + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes = self.mode - CTR1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + increment(&mut (self.f)); + 0 + } + + _ => 0, + } + } + + /* Clean up and delete left-overs */ + pub fn end(&mut self) { + // clean up + for i in 0..4 * (self.nr + 1) { + self.fkey[i] = 0; + self.rkey[i] = 0 + } + for i in 0..16 { + self.f[i] = 0 + } + } +} + +/* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */ +pub fn cbc_iv0_encrypt(k: &[u8], m: &[u8], c: &mut [u8]) -> usize { + /* AES CBC encryption, with Null IV and key K */ + /* Input is from an octet string m, output is to an octet string c */ + /* Input is padded as necessary to make up a full final block */ + let mut a = AES::new(); + let mut fin = false; + + let mut buff: [u8; 16] = [0; 16]; + + a.init(CBC, k.len(), k, None); + + let mut ipt = 0; + let mut opt = 0; + let mut i; + loop { + i = 0; + while i < 16 { + if ipt < m.len() { + buff[i] = m[ipt]; + i += 1; + ipt += 1; + } else { + fin = true; + break; + } + } + if fin { + break; + } + a.encrypt(&mut buff); + for j in 0..16 { + if opt < c.len() { + c[opt] = buff[j]; + opt += 1; + } + } + } + + /* last block, filled up to i-th index */ + + let padlen = 16 - i; + for j in i..16 { + buff[j] = padlen as u8 + } + + a.encrypt(&mut buff); + + for j in 0..16 { + if opt < c.len() { + c[opt] = buff[j]; + opt += 1; + } + } + a.end(); + opt +} + +/* returns plaintext if all consistent, else returns null string */ +pub fn cbc_iv0_decrypt(k: &[u8], c: &[u8], m: &mut [u8]) -> usize { + /* padding is removed */ + let mut a = AES::new(); + let mut fin = false; + + let mut buff: [u8; 16] = [0; 16]; + + a.init(CBC, k.len(), k, None); + + let mut ipt = 0; + let mut opt = 0; + let mut i; + + if c.is_empty() { + return 0; + } + let mut ch = c[ipt]; + ipt += 1; + + loop { + i = 0; + while i < 16 { + buff[i] = ch; + if ipt >= c.len() { + fin = true; + break; + } else { + ch = c[ipt]; + ipt += 1 + } + i += 1; + } + a.decrypt(&mut buff); + if fin { + break; + } + for j in 0..16 { + if opt < m.len() { + m[opt] = buff[j]; + opt += 1; + } + } + } + + a.end(); + let mut bad = false; + let padlen = buff[15] as usize; + if i != 15 || padlen < 1 || padlen > 16 { + bad = true + } + if padlen >= 2 && padlen <= 16 { + for j in 16 - padlen..16 { + if buff[j] != padlen as u8 { + bad = true + } + } + } + + if !bad { + for i in 0..16 - padlen { + if opt < m.len() { + m[opt] = buff[i]; + opt += 1; + } + } + } + + if bad { + 0 + } else { + opt + } +} + +/* +fn main() +{ + let mut key:[u8;32]=[0;32]; + let mut block:[u8;16]=[0;16]; + let mut iv: [u8;16] = [0;16]; + + for i in 0..32 {key[i]=0} + key[0]=1; + for i in 0..16 {iv[i]=i as u8} + for i in 0..16 {block[i]=i as u8} + + let mut aes=AES::new(); + aes.init(CTR16,32,&key,Some(iv)); + + println!("Plain= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.encrypt(&mut block); + + println!("Encrypt= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.reset(CTR16,Some(iv)); + aes.decrypt(&mut block); + + println!("Decrypt= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.end(); +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/arch.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/arch.rs new file mode 100644 index 000000000000..dce3c15fb6fd --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/arch.rs @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub type Chunk = i64; +pub type DChunk = i128; +pub const CHUNK: usize = 64; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/big.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/big.rs new file mode 100644 index 000000000000..3105c65a9d1d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/big.rs @@ -0,0 +1,1062 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::arch; +use crate::arch::Chunk; + +use crate::arch::DChunk; + +use crate::rand::RAND; +use crate::bn254::dbig::DBIG; + +pub const MODBYTES: usize = 32; +pub const BASEBITS: usize = 56; + +pub const NLEN: usize = 1 + ((8 * MODBYTES - 1) / BASEBITS); +pub const DNLEN: usize = 2 * NLEN; +pub const BMASK: Chunk = (1 << BASEBITS) - 1; +pub const HBITS: usize = BASEBITS / 2; +pub const HMASK: Chunk = (1 << HBITS) - 1; +pub const NEXCESS: isize = 1 << ((arch::CHUNK) - BASEBITS - 1); +pub const BIGBITS: usize = MODBYTES * 8; + +#[derive(Copy)] +pub struct BIG { + pub w: [Chunk; NLEN], +} + +impl Clone for BIG { + fn clone(&self) -> BIG { + *self + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for BIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for BIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl BIG { + pub const fn new() -> BIG { + BIG { w: [0; NLEN] } + } + + pub fn new_int(x: isize) -> BIG { + let mut s = BIG::new(); + s.w[0] = x as Chunk; + s + } + + pub fn new_ints(a: &[Chunk]) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = a[i] + } + s + } + + pub fn new_copy(y: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_big(y: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_dcopy(y: &DBIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn get(&self, i: usize) -> Chunk { + self.w[i] + } + + pub fn set(&mut self, i: usize, x: Chunk) { + self.w[i] = x; + } + + pub fn xortop(&mut self, x: Chunk) { + self.w[NLEN - 1] ^= x; + } + + pub fn ortop(&mut self, x: Chunk) { + self.w[NLEN - 1] |= x; + } + + /* test for zero */ + pub fn iszilch(&self) -> bool { + let mut d = 0 as Chunk; + for i in 0..NLEN { + d |= self.w[i]; + } + (1 & ((d-1)>>BASEBITS)) != 0 + } + + /* set to zero */ + pub fn zero(&mut self) { + for i in 0..NLEN { + self.w[i] = 0 + } + } + + /* Test for equal to one */ + pub fn isunity(&self) -> bool { + let mut d = 0 as Chunk; + for i in 1..NLEN { + d |= self.w[i]; + } + (1 & ((d-1)>>BASEBITS) & (((self.w[0]^1)-1)>>BASEBITS)) != 0 + } + + /* set to one */ + pub fn one(&mut self) { + self.w[0] = 1; + for i in 1..NLEN { + self.w[i] = 0; + } + } + + /* Copy from another BIG */ + pub fn copy(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] + } + } + + pub fn dcopy(&mut self, x: &DBIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] + } + } + + /* Get top and bottom half of =x*y+c+r */ + pub fn muladd(a: Chunk, b: Chunk, c: Chunk, r: Chunk) -> (Chunk, Chunk) { + let prod: DChunk = (a as DChunk) * (b as DChunk) + (c as DChunk) + (r as DChunk); + let bot = (prod & (BMASK as DChunk)) as Chunk; + let top = (prod >> BASEBITS) as Chunk; + (top, bot) + } + + /* normalise BIG - force all digits < 2^BASEBITS */ + pub fn norm(&mut self) -> Chunk { + let mut carry = self.w[0]>>BASEBITS; + self.w[0] &= BMASK; + for i in 1..NLEN - 1 { + let d = self.w[i] + carry; + self.w[i] = d & BMASK; + carry = d >> BASEBITS; + } + self.w[NLEN - 1] += carry; + (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as Chunk + } + + /* Conditional swap of two bigs depending on d using XOR - no branches */ + pub fn cswap(&mut self, b: &mut BIG, d: isize) -> Chunk { + let c = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^b.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..NLEN { + let mut t = c & (self.w[i] ^ b.w[i]); + t^=r; + let mut e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + e=b.w[i]^t; w^=e; + b.w[i]=e^ra; + } + return w; + } + + pub fn cmove(&mut self, g: &BIG, d: isize) -> Chunk { + let b = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^g.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..NLEN { + let mut t = b & (self.w[i] ^ g.w[i]); + t^=r; + let e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + } + return w; + } + + /* Shift right by less than a word */ + pub fn fshr(&mut self, k: usize) -> isize { + let n = k; + let w = self.w[0] & ((1 << n) - 1); /* shifted out part */ + for i in 0..NLEN - 1 { + self.w[i] = (self.w[i] >> k) | ((self.w[i + 1] << (BASEBITS - n)) & BMASK); + } + self.w[NLEN - 1] >>= k; + w as isize + } + + /* general shift right */ + pub fn shr(&mut self, k: usize) { + let n = k % BASEBITS; + let m = k / BASEBITS; + for i in 0..NLEN - m - 1 { + self.w[i] = (self.w[m + i] >> n) | ((self.w[m + i + 1] << (BASEBITS - n)) & BMASK) + } + self.w[NLEN - m - 1] = self.w[NLEN - 1] >> n; + for i in NLEN - m..NLEN { + self.w[i] = 0 + } + } + + /* Shift right by less than a word */ + pub fn fshl(&mut self, k: usize) -> isize { + let n = k; + self.w[NLEN - 1] = (self.w[NLEN - 1] << n) | (self.w[NLEN - 2] >> (BASEBITS - n)); + for i in (1..NLEN - 1).rev() { + self.w[i] = ((self.w[i] << k) & BMASK) | (self.w[i - 1] >> (BASEBITS - n)); + } + self.w[0] = (self.w[0] << n) & BMASK; + (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as isize /* return excess - only used in ff.c */ + } + + /* general shift left */ + pub fn shl(&mut self, k: usize) { + let n = k % BASEBITS; + let m = k / BASEBITS; + + self.w[NLEN - 1] = self.w[NLEN - 1 - m] << n; + if NLEN >= m + 2 { + self.w[NLEN - 1] |= self.w[NLEN - m - 2] >> (BASEBITS - n) + } + for i in (m + 1..NLEN - 1).rev() { + self.w[i] = ((self.w[i - m] << n) & BMASK) | (self.w[i - m - 1] >> (BASEBITS - n)); + } + self.w[m] = (self.w[0] << n) & BMASK; + for i in 0..m { + self.w[i] = 0 + } + } + + /* return number of bits */ + pub fn nbits(&self) -> usize { + let mut k = NLEN - 1; + let mut s = BIG::new_copy(&self); + s.norm(); + while (k as isize) >= 0 && s.w[k] == 0 { + k = k.wrapping_sub(1) + } + if (k as isize) < 0 { + return 0; + } + let mut bts = BASEBITS * k; + let mut c = s.w[k]; + while c != 0 { + c /= 2; + bts += 1; + } + bts + } + + /* Convert to Hex String */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut s = String::new(); + let mut len = self.nbits(); + + if len % 4 == 0 { + len /= 4; + } else { + len /= 4; + len += 1; + } + let mb = (MODBYTES * 2) as usize; + if len < mb { + len = mb + } + + for i in (0..len).rev() { + let mut b = BIG::new_copy(&self); + b.shr(i * 4); + s = s + &format!("{:X}", b.w[0] & 15); + } + s + } + + #[cfg(feature = "std")] + pub fn fromstring(val: String) -> BIG { + let mut res = BIG::new(); + let len = val.len(); + let op = &val[0..1]; + let n = u8::from_str_radix(op, 16).unwrap(); + res.w[0] += n as Chunk; + for i in 1..len { + res.shl(4); + let op = &val[i..i+1]; + let n = u8::from_str_radix(op, 16).unwrap(); + res.w[0] += n as Chunk; + } + res + } + + pub fn add(&mut self, r: &BIG) { + for i in 0..NLEN { + self.w[i] += r.w[i] + } + } + + pub fn or(&mut self, r: &BIG) { + for i in 0..NLEN { + self.w[i] |= r.w[i] + } + } + + pub fn dbl(&mut self) { + for i in 0..NLEN { + self.w[i] += self.w[i] + } + } + + /* return this+x */ + pub fn plus(&self, x: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = self.w[i] + x.w[i]; + } + s.norm(); + s + } + + pub fn inc(&mut self, x: isize) { + self.norm(); + self.w[0] += x as Chunk; + } + + /* return self-x */ + pub fn minus(&self, x: &BIG) -> BIG { + let mut d = BIG::new(); + for i in 0..NLEN { + d.w[i] = self.w[i] - x.w[i]; + } + d + } + + /* self-=x */ + pub fn sub(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] -= x.w[i]; + } + } + + /* reverse subtract this=x-this */ + + pub fn rsub(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] - self.w[i] + } + } + + /* self-=x, where x is int */ + pub fn dec(&mut self, x: isize) { + self.norm(); + self.w[0] -= x as Chunk; + } + + /* self*=x, where x is small int BIG { + let mut m = BIG::new(); + for i in 0..(MODBYTES as usize) { + m.fshl(8); + m.w[0] += b[i + n] as Chunk; + } + m + } + + pub fn tobytes(&self, b: &mut [u8]) { + self.tobytearray(b, 0) + } + + pub fn frombytes(b: &[u8]) -> BIG { + BIG::frombytearray(b, 0) + } + + /* self*=x, where x is >NEXCESS */ + pub fn pmul(&mut self, c: isize) -> Chunk { + let mut carry = 0 as Chunk; + for i in 0..NLEN { + let ak = self.w[i]; + let tuple = BIG::muladd(ak, c as Chunk, carry, 0 as Chunk); + carry = tuple.0; + self.w[i] = tuple.1; + } + carry + } + + /* self*=c and catch overflow in DBIG */ + pub fn pxmul(&mut self, c: isize) -> DBIG { + let mut m = DBIG::new(); + let mut carry = 0 as Chunk; + for j in 0..NLEN { + let tuple = BIG::muladd(self.w[j], c as Chunk, carry, m.w[j]); + carry = tuple.0; + m.w[j] = tuple.1; + } + m.w[NLEN] = carry; + m + } + + /* divide by 3 */ + pub fn div3(&mut self) -> Chunk { + let mut carry = 0 as Chunk; + self.norm(); + let base = 1 << BASEBITS; + for i in (0..NLEN).rev() { + let ak = carry * base + self.w[i]; + self.w[i] = ak / 3; + carry = ak % 3; + } + carry + } + + /* return a*b where result fits in a BIG */ + pub fn smul(a: &BIG, b: &BIG) -> BIG { + let mut c = BIG::new(); + for i in 0..NLEN { + let mut carry = 0 as Chunk; + for j in 0..NLEN { + if i + j < NLEN { + let tuple = BIG::muladd(a.w[i], b.w[j], carry, c.w[i + j]); + carry = tuple.0; + c.w[i + j] = tuple.1; + } + } + } + c + } + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + pub fn comp(a: &BIG, b: &BIG) -> isize { + let mut gt = 0 as Chunk; + let mut eq = 1 as Chunk; + for i in (0..NLEN).rev() { + gt |= ((b.w[i]-a.w[i]) >> BASEBITS) & eq; + eq &= ((b.w[i]^a.w[i])-1) >> BASEBITS; + } + (gt+gt+eq-1) as isize + } + + /* set x = x mod 2^m */ + pub fn mod2m(&mut self, m: usize) { + let wd = m / BASEBITS; + let bt = m % BASEBITS; + let msk = (1 << bt) - 1; + self.w[wd] &= msk; + for i in wd + 1..NLEN { + self.w[i] = 0 + } + } + + /* Arazi and Qi inversion mod 256 */ + pub fn invmod256(a: isize) -> isize { + let mut t1: isize = 0; + let mut c = (a >> 1) & 1; + t1 += c; + t1 &= 1; + t1 = 2 - t1; + t1 <<= 1; + let mut u = t1 + 1; + + // i=2 + let mut b = a & 3; + t1 = u * b; + t1 >>= 2; + c = (a >> 2) & 3; + let mut t2 = (u * c) & 3; + t1 += t2; + t1 *= u; + t1 &= 3; + t1 = 4 - t1; + t1 <<= 2; + u += t1; + + // i=4 + b = a & 15; + t1 = u * b; + t1 >>= 4; + c = (a >> 4) & 15; + t2 = (u * c) & 15; + t1 += t2; + t1 *= u; + t1 &= 15; + t1 = 16 - t1; + t1 <<= 4; + u += t1; + + u + } + + /* return parity */ + pub fn parity(&self) -> isize { + (self.w[0] % 2) as isize + } + + /* return n-th bit */ + pub fn bit(&self, n: usize) -> isize { + return ((self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) >> (n%BASEBITS)) as isize; + + + // if (self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) > 0 { +// 1 +// } else { +// 0 +// } + } + + /* return n last bits */ + pub fn lastbits(&mut self, n: usize) -> isize { + let msk = ((1 << n) - 1) as Chunk; + self.norm(); + (self.w[0] & msk) as isize + } + + /* a=1/a mod 2^256. This is very fast! */ + pub fn invmod2m(&mut self) { + let mut u = BIG::new(); + let mut b = BIG::new(); + let mut c = BIG::new(); + + u.inc(BIG::invmod256(self.lastbits(8))); + + let mut i = 8; + while i < BIGBITS { + u.norm(); + b.copy(self); + b.mod2m(i); + let mut t1 = BIG::smul(&u, &b); + t1.shr(i); + c.copy(self); + c.shr(i); + c.mod2m(i); + + let mut t2 = BIG::smul(&u, &c); + t2.mod2m(i); + t1.add(&t2); + t1.norm(); + b = BIG::smul(&t1, &u); + t1.copy(&b); + t1.mod2m(i); + + t2.one(); + t2.shl(i); + t1.rsub(&t2); + t1.norm(); + t1.shl(i); + u.add(&t1); + i <<= 1; + } + u.mod2m(BIGBITS); + self.copy(&u); + self.norm(); + } + +// Set self=self mod m in constant time (if bd is known at compile time) +// bd is Max number of bits in b - Actual number of bits in m + pub fn ctmod(&mut self,m:&BIG,bd:usize) { + let mut k=bd; + let mut r=BIG::new(); + let mut c=BIG::new_copy(m); + self.norm(); + + c.shl(k); + loop { + r.copy(self); + r.sub(&c); + r.norm(); + self.cmove(&r,(1 - ((r.w[NLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); + if k==0 {break;} + c.fshr(1); + k -= 1; + } + } + + /* reduce self mod m */ + pub fn rmod(&mut self, m: &BIG) { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss> (arch::CHUNK - 1)) & 1)) as isize; + a.cmove(&r, d); + r.copy(self); + r.add(&e); + r.norm(); + self.cmove(&r, d); + if k==0 {break;} + k -= 1; + c.fshr(1); + e.fshr(1); + } + } + + /* divide self by m */ + pub fn div(&mut self, m: &BIG) { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss BIG { + let mut m = BIG::new(); + let mut j = 0; + let mut r: u8 = 0; + /* generate random BIG */ + + for _ in 0..8 * (MODBYTES as usize) { + if j == 0 { + r = rng.getbyte() + } else { + r >>= 1 + } + + let b = (r as Chunk) & 1; + m.shl(1); + m.w[0] += b; + j += 1; + j &= 7; + } + m + } + + /* Create random BIG in portable way, one bit at a time */ + pub fn randomnum(q: &BIG, rng: &mut RAND) -> BIG { + let mut d = DBIG::new(); + let mut j = 0; + let mut r: u8 = 0; + let t = BIG::new_copy(q); + for _ in 0..2 * t.nbits() { + if j == 0 { + r = rng.getbyte(); + } else { + r >>= 1 + } + + let b = (r as Chunk) & 1; + d.shl(1); + d.w[0] += b; + j += 1; + j &= 7; + } + d.dmod(q) + } + +/* create randum BIG less than r and less than trunc bits */ + pub fn randtrunc(q: &BIG, trunc: usize, rng: &mut RAND) -> BIG { + let mut m=BIG::randomnum(q,rng); + if q.nbits() > trunc { + m.mod2m(trunc); + } + m + } + + /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ + pub fn jacobi(&mut self, p: &BIG) -> isize { + let mut m: usize = 0; + let mut t = BIG::new(); + let mut x = BIG::new(); + let mut n = BIG::new(); + let zilch = BIG::new(); + let one = BIG::new_int(1); + if p.parity() == 0 || BIG::comp(self, &zilch) == 0 || BIG::comp(p, &one) <= 0 { + return 0; + } + self.norm(); + + x.copy(self); + n.copy(p); + x.rmod(p); + + while BIG::comp(&n, &one) > 0 { + if BIG::comp(&x, &zilch) == 0 { + return 0; + } + let n8 = n.lastbits(3) as usize; + let mut k = 0; + while x.parity() == 0 { + k += 1; + x.shr(1); + } + if k % 2 == 1 { + m += (n8 * n8 - 1) / 8 + } + m += (n8 - 1) * ((x.lastbits(2) as usize) - 1) / 4; + t.copy(&n); + t.rmod(&x); + n.copy(&x); + x.copy(&t); + m %= 2; + } + if m == 0 { + 1 + } else { + -1 + } + } + +// Set self=1/self mod p. Binary method +// NOTE: This function is NOT side-channel safe +// If a is a secret then ALWAYS calculate 1/a = m*(1/am) mod p +// where m is a random masking value + pub fn invmodp(&mut self, p: &BIG) { + self.rmod(p); + if self.iszilch() {return;} + let mut u = BIG::new_copy(self); + let mut v = BIG::new_copy(p); + let mut x1 = BIG::new_int(1); + let mut x2 = BIG::new(); + let mut t = BIG::new(); + let one = BIG::new_int(1); + + while (BIG::comp(&u, &one) != 0) && (BIG::comp(&v, &one) != 0) { + while u.parity() == 0 { + u.fshr(1); + t.copy(&x1); + t.add(p); + x1.cmove(&t,x1.parity()); + x1.norm(); + x1.fshr(1); + } + while v.parity() == 0 { + v.fshr(1); + t.copy(&x2); + t.add(p); + x2.cmove(&t,x2.parity()); + x2.norm(); + x2.fshr(1); + } + if BIG::comp(&u, &v) >= 0 { + u.sub(&v); + u.norm(); + t.copy(&x1); + t.add(p); + x1.cmove(&t,(BIG::comp(&x1,&x2)>>1)&1); + x1.sub(&x2); + x1.norm(); + } else { + v.sub(&u); + v.norm(); + t.copy(&x2); + t.add(p); + x2.cmove(&t,(BIG::comp(&x2,&x1)>>1)&1); + x2.sub(&x1); + x2.norm(); + } + } + self.copy(&x1); + self.cmove(&x2,BIG::comp(&u,&one)&1); + } + + /* return a*b as DBIG - Simple Karatsuba */ + pub fn mul(a: &BIG, b: &BIG) -> DBIG { + let mut c = DBIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut d: [DChunk; DNLEN] = [0; DNLEN]; + for i in 0..NLEN { + d[i] = (a.w[i] as DChunk) * (b.w[i] as DChunk); + } + let mut s = d[0]; + let mut t = s; + c.w[0] = (t & rm) as Chunk; + t >>= rb; + for k in 1..NLEN { + s += d[k]; + t += s; + for i in 1 + k / 2..k + 1 { + t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk) + } + c.w[k] = (t & rm) as Chunk; + t >>= rb; + } + for k in NLEN..2 * NLEN - 1 { + s -= d[k - NLEN]; + t += s; + let mut i = 1 + k / 2; + while i < NLEN { + t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk); + i += 1; + } + + c.w[k] = (t & rm) as Chunk; + t >>= rb; + } + c.w[2 * NLEN - 1] = t as Chunk; + c + } + + /* return a^2 as DBIG */ + pub fn sqr(a: &BIG) -> DBIG { + let mut c = DBIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut t = (a.w[0] as DChunk) * (a.w[0] as DChunk); + c.w[0] = (t & rm) as Chunk; + let mut co = t >> rb; + + let mut j = 1; + while j < NLEN - 1 { + t = (a.w[j] as DChunk) * (a.w[0] as DChunk); + for i in 1..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + t = (a.w[j] as DChunk) * (a.w[0] as DChunk); + for i in 1..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + } + + j = NLEN + (NLEN % 2) - 1; + while j < DNLEN - 3 { + t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); + for i in j + 2 - NLEN..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); + for i in j + 2 - NLEN..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + } + + t = (a.w[NLEN - 2] as DChunk) * (a.w[NLEN - 1] as DChunk); + t += t; + t += co; + c.w[DNLEN - 3] = (t & rm) as Chunk; + co = t >> rb; + + t = (a.w[NLEN - 1] as DChunk) * (a.w[NLEN - 1] as DChunk) + co; + c.w[DNLEN - 2] = (t & rm) as Chunk; + co = t >> rb; + c.w[DNLEN - 1] = co as Chunk; + + c + } + + /* Montgomery reduction */ + pub fn monty(md: &BIG, mc: Chunk, d: &mut DBIG) -> BIG { + let mut b = BIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut dd: [DChunk; NLEN] = [0; NLEN]; + let mut v: [Chunk; NLEN] = [0; NLEN]; + + b.zero(); + + let mut t = d.w[0] as DChunk; + v[0] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; + t += (v[0] as DChunk) * (md.w[0] as DChunk); + t = (d.w[1] as DChunk) + (t >> rb); + let mut s: DChunk = 0; + for k in 1..NLEN { + t = t + s + (v[0] as DChunk) * (md.w[k] as DChunk); + let mut i = 1 + k / 2; + while i < k { + t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); + i += 1; + } + v[k] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; + t += (v[k] as DChunk) * (md.w[0] as DChunk); + t = (d.w[k + 1] as DChunk) + (t >> rb); + dd[k] = (v[k] as DChunk) * (md.w[k] as DChunk); + s += dd[k]; + } + + for k in NLEN..2 * NLEN - 1 { + t += s; + let mut i = 1 + k / 2; + while i < NLEN { + t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); + i += 1; + } + b.w[k - NLEN] = (t & rm) as Chunk; + t = (d.w[k + 1] as DChunk) + (t >> rb); + s -= dd[k + 1 - NLEN]; + } + b.w[NLEN - 1] = (t & rm) as Chunk; + b + } + + /* Fast combined shift, subtract and norm. Return sign of result */ + pub fn ssn(r: &mut BIG, a: &BIG, m: &mut BIG) -> isize { + let n = NLEN - 1; + m.w[0] = (m.w[0] >> 1) | ((m.w[1] << (BASEBITS - 1)) & BMASK); + r.w[0] = a.w[0] - m.w[0]; + let mut carry = r.w[0] >> BASEBITS; + r.w[0] &= BMASK; + for i in 1..n { + m.w[i] = (m.w[i] >> 1) | ((m.w[i + 1] << (BASEBITS - 1)) & BMASK); + r.w[i] = a.w[i] - m.w[i] + carry; + carry = r.w[i] >> BASEBITS; + r.w[i] &= BMASK; + } + m.w[n] >>= 1; + r.w[n] = a.w[n] - m.w[n] + carry; + ((r.w[n] >> (arch::CHUNK - 1)) & 1) as isize + } + + /* return a*b mod m */ + pub fn modmul(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + let mut b = BIG::new_copy(b1); + a.rmod(m); + b.rmod(m); + let mut d = BIG::mul(&a, &b); + d.ctdmod(m,m.nbits()) + } + + /* return a^2 mod m */ + pub fn modsqr(a1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + a.rmod(m); + let mut d = BIG::sqr(&a); + d.ctdmod(m,m.nbits()) + } + + /* return -a mod m */ + pub fn modneg(a1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + a.rmod(m); + a.rsub(m); + a.norm(); + a + } + + /* return a+b mod m */ + pub fn modadd(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + let mut b = BIG::new_copy(b1); + a.rmod(m); + b.rmod(m); + a.add(&b); a.norm(); + a.ctmod(m,1); + a + } + + /* return this^e mod m */ + pub fn powmod(&mut self, e1: &BIG, m: &BIG) -> BIG { + self.norm(); + let mut e = BIG::new_copy(e1); + e.norm(); + let mut a = BIG::new_int(1); + let mut z = BIG::new_copy(&e); + let mut s = BIG::new_copy(self); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + a = BIG::modmul(&a, &s, m) + } + if z.iszilch() { + break; + } + s = BIG::modsqr(&s, m); + } + a + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/bls.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/bls.rs new file mode 100644 index 000000000000..dddbae94bf2d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/bls.rs @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp::FP; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::dbig::DBIG; +use crate::bn254::ecp2::ECP2; +//use crate::bn254::fp4::FP4; +use crate::bn254::pair; +use crate::bn254::rom; +use crate::hmac; + +/* Boneh-Lynn-Shacham signature 128-bit API Functions */ + +/* Loosely (for now) following https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-02 */ + +// Minimal-signature-size variant + +pub const BFS: usize = big::MODBYTES as usize; +pub const BGS: usize = big::MODBYTES as usize; +pub const BLS_OK: isize = 0; +pub const BLS_FAIL: isize = -1; + +// NOTE this must be accessed in unsafe mode. +// But it is just written to once at start-up, so actually safe. + +// Best not to use precomp if stack memory limited - i.e. embedded use +// Uncomment to use precomp - Note this example code may no longer work when Rust 2024 appears in version 1.82, and may need restructuring +// static mut G2_TAB: [FP4; ecp::G2_TABLE] = [FP4::new(); ecp::G2_TABLE]; + +fn ceil(a: usize,b: usize) -> usize { + (a-1)/b+1 +} + +/* output u \in F_p */ +fn hash_to_field(hash: usize,hlen: usize ,u: &mut [FP], dst: &[u8],m: &[u8],ctr: usize) { + let q = BIG::new_ints(&rom::MODULUS); + let nbq=q.nbits(); + let el = ceil(nbq+ecp::AESKEY*8,8); + + let mut okm: [u8;256]=[0;256]; + let mut fd: [u8;128]=[0;128]; + + hmac::xmd_expand(hash,hlen,&mut okm,el*ctr,&dst,&m); + for i in 0..ctr { + for j in 0..el { + fd[j]=okm[el*i+j]; + } + u[i]=FP::new_big(&DBIG::frombytes(&fd[0 .. el]).ctdmod(&q,8*el-nbq)); + } +} + +/* hash a message to an ECP point, using SHA2, random oracle method */ +#[allow(non_snake_case)] +pub fn bls_hash_to_point(m: &[u8]) -> ECP { + let dst= "BLS_SIG_BN254G1_XMD:SHA-256_SVDW_RO_NUL_"; + + let mut u: [FP; 2] = [ + FP::new(), + FP::new(), + ]; + hash_to_field(hmac::MC_SHA2,ecp::HASH_TYPE,&mut u,dst.as_bytes(),m,2); + + let mut P=ECP::map2point(&u[0]); + let P1=ECP::map2point(&u[1]); + + P.add(&P1); + P.cfp(); + P.affine(); + P +} + +pub fn init() -> isize { +// Uncomment to use precomp +// let g = ECP2::generator(); +// if g.is_infinity() { +// return BLS_FAIL; +// } +// unsafe { +// pair::precomp(&mut G2_TAB, &g); +// } + BLS_OK +} + +/* generate key pair, private key s, public key w */ +pub fn key_pair_generate(ikm: &[u8], s: &mut [u8], w: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let nbr=r.nbits(); + let el = ceil(3*ceil(nbr,8),2); + let g = ECP2::generator(); + let mut len: [u8; 2] = [0; 2]; + hmac::inttobytes(el,&mut len); + + let salt="BLS-SIG-KEYGEN-SALT-"; + + let mut prk: [u8;64]=[0;64]; + let mut okm: [u8;128]=[0;128]; + let mut aikm: [u8;65]=[0;65]; + let likm=ikm.len(); + for i in 0..likm { + aikm[i]=ikm[i]; + } + aikm[likm]=0; + + let hlen=ecp::HASH_TYPE; + + hmac::hkdf_extract(hmac::MC_SHA2,hlen,&mut prk,Some(&salt.as_bytes()),&aikm[0 .. likm+1]); + hmac::hkdf_expand(hmac::MC_SHA2,hlen,&mut okm,el,&prk[0 .. hlen],&len); + + let mut dx = DBIG::frombytes(&okm[0 .. el]); + let sc = dx.ctdmod(&r,8*el-nbr); + sc.tobytes(s); +// SkToPk + pair::g2mul(&g, &sc).tobytes(w,true); // true for public key compression + BLS_OK +} + +/* Sign message m using private key s to produce signature sig */ + +pub fn core_sign(sig: &mut [u8], m: &[u8], s: &[u8]) -> isize { + let d = bls_hash_to_point(m); + let sc = BIG::frombytes(&s); + pair::g1mul(&d, &sc).tobytes(sig, true); + BLS_OK +} + +/* Verify signature given message m, the signature sig, and the public key w */ + +pub fn core_verify(sig: &[u8], m: &[u8], w: &[u8]) -> isize { + let hm = bls_hash_to_point(m); + let mut d = ECP::frombytes(&sig); + + if !pair::g1member(&d) { + return BLS_FAIL; + } + d.neg(); + + let pk = ECP2::frombytes(&w); + if !pair::g2member(&pk) { + return BLS_FAIL; + } + +// Uncomment to use precomp + // Use new multi-pairing mechanism + //let mut r = pair::initmp(); + // pair::another(&mut r,&g,&d); + + //unsafe { + // pair::another_pc(&mut r, &G2_TAB, &d); + //} + //pair::another(&mut r, &pk, &hm); + //let mut v = pair::miller(&mut r); + + //.. or else do not use precomp! + let g = ECP2::generator(); + let mut v = pair::ate2(&g, &d, &pk, &hm); + + v = pair::fexp(&v); + if v.isunity() { + return BLS_OK; + } + BLS_FAIL +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/dbig.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/dbig.rs new file mode 100644 index 000000000000..5f2de894baed --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/dbig.rs @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::arch; +use crate::arch::Chunk; +use crate::bn254::big; +use crate::bn254::big::BIG; + +pub struct DBIG { + pub w: [Chunk; big::DNLEN], +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for DBIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for DBIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl DBIG { + pub fn new() -> DBIG { + DBIG { + w: [0; big::DNLEN as usize], + } + } + + pub fn new_copy(y: &DBIG) -> DBIG { + let mut s = DBIG::new(); + for i in 0..big::DNLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_scopy(x: &BIG) -> DBIG { + let mut b = DBIG::new(); + for i in 0..big::NLEN { + b.w[i] = x.w[i]; + } + b.w[big::NLEN - 1] = x.get(big::NLEN - 1) & big::BMASK; /* top word normalized */ + b.w[big::NLEN] = x.get(big::NLEN - 1) >> big::BASEBITS; + + for i in big::NLEN + 1..big::DNLEN { + b.w[i] = 0 + } + b + } + + /* split DBIG at position n, return higher half, keep lower half */ + pub fn split(&mut self, n: usize) -> BIG { + let mut t = BIG::new(); + let m = n % big::BASEBITS; + let mut carry = self.w[big::DNLEN - 1] << (big::BASEBITS - m); + + for i in (big::NLEN - 1..big::DNLEN - 1).rev() { + let nw = (self.w[i] >> m) | carry; + carry = (self.w[i] << (big::BASEBITS - m)) & big::BMASK; + t.set(i + 1 - big::NLEN, nw); + } + self.w[big::NLEN - 1] &= ((1 as Chunk) << m) - 1; + t + } + + /* general shift left */ + pub fn shl(&mut self, k: usize) { + let n = k % big::BASEBITS; + let m = k / big::BASEBITS; + self.w[big::DNLEN - 1] = + (self.w[big::DNLEN - 1 - m] << n) | (self.w[big::DNLEN - m - 2] >> (big::BASEBITS - n)); + for i in (m + 1..big::DNLEN - 1).rev() { + self.w[i] = + ((self.w[i - m] << n) & big::BMASK) | (self.w[i - m - 1] >> (big::BASEBITS - n)); + } + + self.w[m] = (self.w[0] << n) & big::BMASK; + for i in 0..m { + self.w[i] = 0 + } + } + + /* general shift right */ + pub fn shr(&mut self, k: usize) { + let n = k % big::BASEBITS; + let m = k / big::BASEBITS; + for i in 0..big::DNLEN - m - 1 { + self.w[i] = + (self.w[m + i] >> n) | ((self.w[m + i + 1] << (big::BASEBITS - n)) & big::BMASK); + } + self.w[big::DNLEN - m - 1] = self.w[big::DNLEN - 1] >> n; + for i in big::DNLEN - m..big::DNLEN { + self.w[i] = 0 + } + } + + /* Copy from another DBIG */ + pub fn copy(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] = x.w[i]; + } + } + + pub fn ucopy(&mut self, x: &BIG) { + for i in 0..big::NLEN { + self.w[i] = 0; + } + for i in big::NLEN..big::DNLEN { + self.w[i] = x.w[i - big::NLEN]; + } + } + + pub fn cmove(&mut self, g: &DBIG, d: isize) -> Chunk { + let b = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^g.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..big::DNLEN { + let mut t = b & (self.w[i] ^ g.w[i]); + t^=r; + let e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + } + return w; + } + + /* self+=x */ + pub fn add(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] += x.w[i]; + } + } + + /* self-=x */ + pub fn sub(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] -= x.w[i]; + } + } + + /* self=x-self */ + pub fn rsub(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] = x.w[i] - self.w[i]; + } + } + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + pub fn comp(a: &DBIG, b: &DBIG) -> isize { + let mut gt = 0 as Chunk; + let mut eq = 1 as Chunk; + for i in (0..big::DNLEN).rev() { + gt |= ((b.w[i]-a.w[i]) >> big::BASEBITS) & eq; + eq &= ((b.w[i]^a.w[i])-1) >> big::BASEBITS; + } + (gt+gt+eq-1) as isize + } + + /* convert from byte array to BIG */ + pub fn frombytes(b: &[u8]) -> DBIG { + let mut m = DBIG::new(); + for i in 0..(b.len()) { + m.shl(8); + m.w[0] += b[i] as Chunk; + } + m + } + + /* normalise BIG - force all digits < 2^big::BASEBITS */ + pub fn norm(&mut self) { + let mut carry = self.w[0]>>big::BASEBITS; + self.w[0] &= big::BMASK; + for i in 1..big::DNLEN - 1 { + let d = self.w[i] + carry; + self.w[i] = d & big::BMASK; + carry = d >> big::BASEBITS; + } + self.w[big::DNLEN - 1] += carry + } + +// Set self=self mod m in constant time (if bd is known at compile time) +// bd is Max number of bits in b - Actual number of bits in m + pub fn ctdmod(&mut self, m: &BIG, bd: usize) -> BIG { + let mut k=bd; + self.norm(); + let mut c = DBIG::new_scopy(m); + let mut dr = DBIG::new(); + + c.shl(k); + + loop { + dr.copy(self); + dr.sub(&c); + dr.norm(); + self.cmove(&dr,(1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); + if k==0 {break;} + c.shr(1); + k -= 1; + } + BIG::new_dcopy(self) + } + + /* reduces self DBIG mod a BIG, and returns the BIG */ + pub fn dmod(&mut self, m: &BIG) -> BIG { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss BIG { + let mut k=bd; + let mut c = DBIG::new_scopy(m); + let mut a = BIG::new(); + let mut e = BIG::new_int(1); + let mut dr = DBIG::new(); + let mut r = BIG::new(); + self.norm(); + + c.shl(k); + e.shl(k); + + loop { + dr.copy(self); + dr.sub(&c); + dr.norm(); + let d = (1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize; + self.cmove(&dr, d); + r.copy(&a); + r.add(&e); + r.norm(); + a.cmove(&r, d); + if k==0 {break;} + k -= 1; + c.shr(1); + e.shr(1); + } + a + } + + /* return this/c */ + pub fn div(&mut self, m: &BIG) -> BIG { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss usize { + let mut k = big::DNLEN - 1; + let mut s = DBIG::new_copy(&self); + s.norm(); + while (k as isize) >= 0 && s.w[k] == 0 { + k = k.wrapping_sub(1) + } + if (k as isize) < 0 { + return 0; + } + let mut bts = (big::BASEBITS as usize) * k; + let mut c = s.w[k]; + while c != 0 { + c /= 2; + bts += 1; + } + bts + } + + /* Convert to Hex String */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut s = String::new(); + let mut len = self.nbits(); + + if len % 4 == 0 { + len /= 4; + } else { + len /= 4; + len += 1; + } + + for i in (0..len).rev() { + let mut b = DBIG::new_copy(&self); + b.shr(i * 4); + s = s + &format!("{:X}", b.w[0] & 15); + } + s + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecdh.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecdh.rs new file mode 100644 index 000000000000..96ceadf4f311 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecdh.rs @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ECDH/ECIES/ECDSA API Functions */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::rom; + +use crate::aes; +use crate::hmac; +use crate::rand::RAND; + +pub const INVALID_PUBLIC_KEY: isize = -2; +pub const ERROR: isize = -3; +//pub const INVALID: isize = -4; +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; + +pub fn rfc7748(r: &mut BIG) { + let mut lg=0; + let mut t=BIG::new_int(1); + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let n=(8*EGS-lg+1) as usize; + r.mod2m(n); + t.shl(n); + r.add(&t); + c=r.lastbits(lg as usize); + r.dec(c); +} + +#[allow(non_snake_case)] +pub fn in_range(s: &[u8]) -> bool { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sc = BIG::frombytes(&s); + if sc.iszilch() { + return false; + } + if BIG::comp(&sc, &r) >= 0 { + return false; + } + true +} + +/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), + * where s is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in s + * otherwise it is generated randomly internally */ +#[allow(non_snake_case)] +pub fn key_pair_generate(rng: Option<&mut RAND>, s: &mut [u8], w: &mut [u8]) -> isize { + let res = 0; + let mut sc: BIG; + let G = ECP::generator(); + let r = BIG::new_ints(&rom::CURVE_ORDER); + + if let Some(x) = rng { + if ecp::CURVETYPE != ecp::WEIERSTRASS { + sc = BIG::random(x); // from random bytes + } else { + sc = BIG::randomnum(&r, x); // Removes biases + } + } else { + sc = BIG::frombytes(&s); + } + + if ecp::CURVETYPE != ecp::WEIERSTRASS { + rfc7748(&mut sc); // For Montgomery or Edwards, apply RFC7748 transformation + } + sc.tobytes(s); + let WP = G.clmul(&sc,&r); + WP.tobytes(w, false); // To use point compression on public keys, change to true + + res +} + +/* validate public key */ +#[allow(non_snake_case)] +pub fn public_key_validate(w: &[u8]) -> isize { + let mut WP = ECP::frombytes(w); + let mut res = 0; + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + if WP.is_infinity() { + res = INVALID_PUBLIC_KEY + } + if res == 0 { + let q = BIG::new_ints(&rom::MODULUS); + let nb = q.nbits(); + let mut k = BIG::new(); + k.one(); + k.shl((nb + 4) / 2); + k.add(&q); + k.div(&r); + + while k.parity() == 0 { + k.shr(1); + WP.dbl(); + } + + if !k.isunity() { + WP = WP.mul(&mut k) + } + if WP.is_infinity() { + res = INVALID_PUBLIC_KEY + } + } + res +} + +/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ +#[allow(non_snake_case)] +pub fn ecpsvdp_dh(s: &[u8], wd: &[u8], z: &mut [u8], typ: isize) -> isize { + let mut res = 0; + + let sc = BIG::frombytes(&s); + + let mut W = ECP::frombytes(&wd); + if W.is_infinity() { + res = ERROR + } + + if res == 0 { + let r = BIG::new_ints(&rom::CURVE_ORDER); + W = W.clmul(&sc,&r); + if W.is_infinity() { + res = ERROR; + } else { + if ecp::CURVETYPE != ecp::MONTGOMERY { + if typ>0 { + if typ==1 { + W.tobytes(z,true); + } else { + W.tobytes(z,false); + } + } else { + W.getx().tobytes(z); + } + return res; + } else { + W.getx().tobytes(z); + } + } + } + res +} + +/* IEEE ECDSA Signature, C and D are signature on F using private key S */ +#[allow(non_snake_case)] +pub fn ecpsp_dsa( + sha: usize, + rng: &mut RAND, + s: &[u8], + f: &[u8], + c: &mut [u8], + d: &mut [u8], +) -> isize { + let mut t: [u8; EGS] = [0; EGS]; + let mut b: [u8; EGS] = [0; EGS]; + + hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS,0,Some(f), -1, None); + + let G = ECP::generator(); + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + let sc = BIG::frombytes(s); /* s or &s? */ + let fb = BIG::frombytes(&b); + + let mut cb = BIG::new(); + let mut db = BIG::new(); + let mut tb = BIG::new(); + let mut V = ECP::new(); + + while db.iszilch() { + let mut u = BIG::randomnum(&r, rng); + let w = BIG::randomnum(&r, rng); /* IMPORTANT - side channel masking to protect invmodp() */ + + V.copy(&G); + V = V.clmul(&u,&r); + let vx = V.getx(); + cb.copy(&vx); + cb.rmod(&r); + if cb.iszilch() { + continue; + } + + tb.copy(&BIG::modmul(&u, &w, &r)); + u.copy(&tb); + + u.invmodp(&r); + db.copy(&BIG::modmul(&sc, &cb, &r)); + db.copy(&BIG::modadd(&db, &fb, &r)); + tb.copy(&BIG::modmul(&db, &w, &r)); + db.copy(&tb); + + tb.copy(&BIG::modmul(&u, &db, &r)); + db.copy(&tb); + } + + cb.tobytes(&mut t); + for i in 0..EGS { + c[i] = t[i] + } + db.tobytes(&mut t); + for i in 0..EGS { + d[i] = t[i] + } + 0 +} + +/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ +#[allow(non_snake_case)] +pub fn ecpvp_dsa(sha: usize, w: &[u8], f: &[u8], c: &[u8], d: &[u8]) -> isize { + let mut res = 0; + + let mut b: [u8; EGS] = [0; EGS]; + + hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS, 0,Some(f), -1, None); + + let mut G = ECP::generator(); + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + let mut cb = BIG::frombytes(c); /* c or &c ? */ + let mut db = BIG::frombytes(d); /* d or &d ? */ + let mut fb = BIG::frombytes(&b); + let mut tb = BIG::new(); + + if cb.iszilch() || BIG::comp(&cb, &r) >= 0 || db.iszilch() || BIG::comp(&db, &r) >= 0 { + res = ERROR; + } + + if res == 0 { + db.invmodp(&r); + tb.copy(&BIG::modmul(&mut fb, &mut db, &r)); + fb.copy(&tb); + let h2 = BIG::modmul(&mut cb, &mut db, &r); + + let WP = ECP::frombytes(&w); + if WP.is_infinity() { + res = ERROR; + } else { + let mut P = ECP::new(); + P.copy(&WP); + + P = P.mul2(&h2, &mut G, &fb); + + if P.is_infinity() { + res = ERROR; + } else { + db = P.getx(); + db.rmod(&r); + + if BIG::comp(&db, &cb) != 0 { + res = ERROR + } + } + } + } + + res +} + +/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ +// returns length of ciphertext +#[allow(non_snake_case)] +pub fn ecies_encrypt( + sha: usize, + p1: &[u8], + p2: &[u8], + rng: &mut RAND, + w: &[u8], + m: &[u8], + v: &mut [u8], + c: &mut [u8], + t: &mut [u8], +) -> usize { + let mut z: [u8; EFS] = [0; EFS]; + let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut u: [u8; EGS] = [0; EGS]; + let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; + let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; + + if key_pair_generate(Some(rng), &mut u, v) != 0 { + return 0; + } + if ecpsvdp_dh(&u, &w, &mut z, 0) != 0 { + return 0; + } + + for i in 0..2 * EFS + 1 { + vz[i] = v[i] + } + for i in 0..EFS { + vz[2 * EFS + 1 + i] = z[i] + } + + hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); + + for i in 0..ecp::AESKEY { + k1[i] = k[i]; + k2[i] = k[ecp::AESKEY + i] + } + + let clen = aes::cbc_iv0_encrypt(&k1, m, c); + + let mut l2: [u8; 8] = [0; 8]; + let p2l = p2.len(); + + hmac::inttobytes(p2l, &mut l2); + + let mut opt=clen; + for i in 0..p2l { + c[opt]=p2[i]; opt+=1; + } + for i in 0..8 { + c[opt]=l2[i]; opt+=1; + } + + hmac::hmac1(hmac::MC_SHA2, sha, t, t.len(), &k2, &c[0..opt]); + + clen +} + +/* constant time n-byte compare */ +fn ncomp(t1: &[u8], t2: &[u8], n: usize) -> bool { + let mut res = 0; + for i in 0..n { + res |= (t1[i] ^ t2[i]) as isize; + } + if res == 0 { + return true; + } + false +} + +/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ +// returns length of plaintext +#[allow(non_snake_case)] +pub fn ecies_decrypt( + sha: usize, + p1: &[u8], + p2: &[u8], + v: &[u8], + c: &mut [u8], + clen: usize, + t: &[u8], + u: &[u8], + m: &mut [u8], +) -> usize { + let mut z: [u8; EFS] = [0; EFS]; + let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; + let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; + let mut tag: [u8; 32] = [0; 32]; /* 32 is max length of tag */ + + for i in 0..t.len() { + tag[i] = t[i] + } + + if ecpsvdp_dh(&u, &v, &mut z, 0) != 0 { + return 0; + } + + for i in 0..2 * EFS + 1 { + vz[i] = v[i] + } + for i in 0..EFS { + vz[2 * EFS + 1 + i] = z[i] + } + + hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); + + for i in 0..ecp::AESKEY { + k1[i] = k[i]; + k2[i] = k[ecp::AESKEY + i] + } + + let mlen = aes::cbc_iv0_decrypt(&k1, &c[0..clen], m); + + if mlen == 0 { + return 0; + } + + let mut l2: [u8; 8] = [0; 8]; + let p2l = p2.len(); + + hmac::inttobytes(p2l, &mut l2); + let mut opt=clen; + + for i in 0..p2l { + c[opt]=p2[i]; opt+=1; + } + for i in 0..8 { + c[opt]=l2[i]; opt+=1; + } + + let tl=tag.len(); + hmac::hmac1(hmac::MC_SHA2, sha, &mut tag, tl, &k2, &c[0..opt]); + + if !ncomp(&t, &tag, t.len()) { + return 0; + } + + mlen +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp.rs new file mode 100644 index 000000000000..23a6b7adf915 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp.rs @@ -0,0 +1,1824 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::fp::FP; +use crate::bn254::fp; +use crate::bn254::rom; + +#[derive(Clone)] +pub struct ECP { + x: FP, + y: FP, + z: FP, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for ECP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for ECP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +pub const WEIERSTRASS: usize = 0; +pub const EDWARDS: usize = 1; +pub const MONTGOMERY: usize = 2; +pub const NOT: usize = 0; +pub const BN: usize = 1; +pub const BLS12: usize = 2; +pub const BLS24: usize = 3; +pub const BLS48: usize = 4; +pub const D_TYPE: usize = 0; +pub const M_TYPE: usize = 1; +pub const POSITIVEX: usize = 0; +pub const NEGATIVEX: usize = 1; + +pub const CURVETYPE:usize=WEIERSTRASS; +pub const CURVE_A:isize=0; +pub const CURVE_PAIRING_TYPE:usize=BN; +pub const SEXTIC_TWIST:usize=D_TYPE; +pub const SIGN_OF_X:usize=NEGATIVEX; +pub const ATE_BITS:usize=66; +pub const G2_TABLE:usize=71; +pub const HTC_ISO:usize=0; +pub const HTC_ISO_G2:usize=0; + +pub const ALLOW_ALT_COMPRESS:bool=false; +pub const HASH_TYPE:usize=32; +pub const AESKEY:usize=16; + +#[allow(non_snake_case)] +impl ECP { + pub fn pnew() -> ECP { + ECP { + x: FP::new(), + y: FP::new_int(1), + z: FP::new(), + } + } + + pub fn new() -> ECP { + let mut E = ECP::pnew(); + if CURVETYPE == EDWARDS { + E.z.one(); + } + E + } + + /* set (x,y) from two BIGs */ + pub fn new_bigs(ix: &BIG, iy: &BIG) -> ECP { + let mut E = ECP::new(); + E.x.bcopy(ix); + E.y.bcopy(iy); + E.z.one(); + E.x.norm(); + let rhs = ECP::rhs(&E.x); + if CURVETYPE == MONTGOMERY { + if rhs.qr(None) != 1 { + E.inf(); + } + } else { + let mut y2 = FP::new_copy(&E.y); + y2.sqr(); + if !y2.equals(&rhs) { + E.inf(); + } + } + E + } + + /* set (x,y) from BIG and a bit */ + pub fn new_bigint(ix: &BIG, s: isize) -> ECP { + let mut E = ECP::new(); + let mut hint = FP::new(); + E.x.bcopy(ix); + E.x.norm(); + E.z.one(); + + let rhs = ECP::rhs(&E.x); + + if rhs.qr(Some(&mut hint)) == 1 { + let mut ny = rhs.sqrt(Some(&hint)); + if ny.sign() != s { + ny.neg(); ny.norm() + } + E.y.copy(&ny); + } else { + E.inf() + } + E + } + + #[allow(non_snake_case)] + /* set from x - calculate y from curve equation */ + pub fn new_big(ix: &BIG) -> ECP { + let mut E = ECP::new(); + let mut hint = FP::new(); + E.x.bcopy(ix); + E.x.norm(); + E.z.one(); + let rhs = ECP::rhs(&E.x); + if rhs.qr(Some(&mut hint)) == 1 { + if CURVETYPE != MONTGOMERY { + E.y.copy(&rhs.sqrt(Some(&hint))) + } + } else { + E.inf(); + } + E + } + + /* set this=O */ + pub fn inf(&mut self) { + self.x.zero(); + if CURVETYPE != MONTGOMERY { + self.y.one(); + } + if CURVETYPE != EDWARDS { + self.z.zero(); + } else { + self.z.one() + } + } + + /* Calculate RHS of curve equation */ + fn rhs(x: &FP) -> FP { + let mut r = FP::new_copy(x); + r.sqr(); + + if CURVETYPE == WEIERSTRASS { + // x^3+Ax+B + let b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + r.mul(x); + if CURVE_A == -3 { + let mut cx = FP::new_copy(x); + cx.imul(3); + cx.neg(); + cx.norm(); + r.add(&cx); + } + r.add(&b); + } + if CURVETYPE == EDWARDS { + // (Ax^2-1)/(Bx^2-1) + let mut b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let one = FP::new_int(1); + b.mul(&r); + b.sub(&one); + b.norm(); + if CURVE_A == -1 { + r.neg() + } + r.sub(&one); + r.norm(); + b.inverse(None); + r.mul(&b); + } + if CURVETYPE == MONTGOMERY { + // x^3+Ax^2+x + let mut x3 = FP::new(); + x3.copy(&r); + x3.mul(x); + r.imul(CURVE_A); + r.add(&x3); + r.add(&x); + } + r.reduce(); + r + } + + /* test for O point-at-infinity */ + pub fn is_infinity(&self) -> bool { + if CURVETYPE == EDWARDS { + return self.x.iszilch() && self.y.equals(&self.z); + } + if CURVETYPE == WEIERSTRASS { + return self.x.iszilch() && self.z.iszilch(); + } + if CURVETYPE == MONTGOMERY { + return self.z.iszilch(); + } + true + } + + /* Conditional swap of P and Q dependant on d */ + pub fn cswap(&mut self, Q: &mut ECP, d: isize) { + self.x.cswap(&mut Q.x, d); + if CURVETYPE != MONTGOMERY { + self.y.cswap(&mut Q.y, d) + } + self.z.cswap(&mut Q.z, d); + } + + /* Conditional move of Q to P dependant on d */ + pub fn cmove(&mut self, Q: &ECP, d: isize) { + self.x.cmove(&Q.x, d); + if CURVETYPE != MONTGOMERY { + self.y.cmove(&Q.y, d) + } + self.z.cmove(&Q.z, d); + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* this=P */ + pub fn copy(&mut self, P: &ECP) { + self.x.copy(&P.x); + if CURVETYPE != MONTGOMERY { + self.y.copy(&P.y) + } + self.z.copy(&P.z); + } + + /* this=-this */ + pub fn neg(&mut self) { + if CURVETYPE == WEIERSTRASS { + self.y.neg(); + self.y.norm(); + } + if CURVETYPE == EDWARDS { + self.x.neg(); + self.x.norm(); + } + } + /* multiply x coordinate */ + pub fn mulx(&mut self, c: &mut FP) { + self.x.mul(c); + } + + /* Constant time select from pre-computed table */ + fn selector(&mut self, W: &[ECP], b: i32) { + // unsure about &[& syntax. An array of pointers I hope.. + let mut MP = ECP::new(); + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&W[0], ECP::teq(babs, 0)); // conditional move + self.cmove(&W[1], ECP::teq(babs, 1)); + self.cmove(&W[2], ECP::teq(babs, 2)); + self.cmove(&W[3], ECP::teq(babs, 3)); + self.cmove(&W[4], ECP::teq(babs, 4)); + self.cmove(&W[5], ECP::teq(babs, 5)); + self.cmove(&W[6], ECP::teq(babs, 6)); + self.cmove(&W[7], ECP::teq(babs, 7)); + + MP.copy(self); + MP.neg(); + self.cmove(&MP, (m & 1) as isize); + } + + /* Test P == Q */ + pub fn equals(&self, Q: &ECP) -> bool { + let mut a = FP::new(); + let mut b = FP::new(); + a.copy(&self.x); + a.mul(&Q.z); + b.copy(&Q.x); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + if CURVETYPE != MONTGOMERY { + a.copy(&self.y); + a.mul(&Q.z); + b.copy(&Q.y); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + } + true + } + + /* set to affine - from (x,y,z) to (x,y) */ + pub fn affine(&mut self) { + if self.is_infinity() { + return; + } + let one = FP::new_int(1); + if self.z.equals(&one) { + return; + } + self.z.inverse(None); + + self.x.mul(&self.z); + self.x.reduce(); + if CURVETYPE != MONTGOMERY { + self.y.mul(&self.z); + self.y.reduce(); + } + self.z.copy(&one); + } + + /* extract x as a BIG */ + pub fn getx(&self) -> BIG { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.x.redc() + } + + /* extract y as a BIG */ + pub fn gety(&self) -> BIG { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.y.redc() + } + + /* get sign of Y */ + pub fn gets(&self) -> isize { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.y.sign() + } + + /* extract x as an FP */ + pub fn getpx(&self) -> FP { + FP::new_copy(&self.x) + } + /* extract y as an FP */ + pub fn getpy(&self) -> FP { + FP::new_copy(&self.y) + } + + /* extract z as an FP */ + pub fn getpz(&self) -> FP { + FP::new_copy(&self.z) + } + + /* convert to byte array */ + pub fn tobytes(&self, b: &mut [u8], compress: bool) { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.x.redc().tobytes(&mut t); + + if CURVETYPE == MONTGOMERY { + for i in 0..MB { + b[i] = t[i] + } + return; + } + + if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + b[i]=t[i]; + } + if compress { + b[0]|=0x80; + if W.y.islarger()==1 { + b[0]|=0x20; + } + } else { + W.y.redc().tobytes(&mut t); + for i in 0..MB { + b[i+MB]=t[i]; + } + } + } else { + for i in 0..MB { + b[i + 1] = t[i]; + } + if compress { + b[0] = 0x02; + if W.y.sign() == 1 { + b[0] = 0x03; + } + return; + } + b[0] = 0x04; + W.y.redc().tobytes(&mut t); + for i in 0..MB { + b[i + MB + 1] = t[i]; + } + } + } + + /* convert from byte array to point */ + pub fn frombytes(b: &[u8]) -> ECP { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let p = BIG::new_ints(&rom::MODULUS); + + if CURVETYPE == MONTGOMERY { + for i in 0..MB { + t[i] = b[i]; + } + let px = BIG::frombytes(&t); + if BIG::comp(&px, &p) >= 0 { + return ECP::new(); + } + return ECP::new_big(&px); + } + + if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + t[i]=b[i]; + } + t[0]&=0x1f; + let px=BIG::frombytes(&t); + if (b[0]&0x80)==0 { + for i in 0 ..MB { + t[i]=b[i+MB]; + } + let py=BIG::frombytes(&t); + return ECP::new_bigs(&px, &py); + } else { + let sgn=(b[0]&0x20)>>5; + let mut P=ECP::new_bigint(&px,0); + let cmp=P.y.islarger(); + if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { + P.neg(); + } + return P; + } + } else { + for i in 0..MB { + t[i] = b[i + 1]; + } + let px = BIG::frombytes(&t); + if BIG::comp(&px, &p) >= 0 { + return ECP::new(); + } + if b[0] == 0x04 { + for i in 0..MB { + t[i] = b[i + MB + 1]; + } + let py = BIG::frombytes(&t); + if BIG::comp(&py, &p) >= 0 { + return ECP::new(); + } + return ECP::new_bigs(&px, &py); + } + if b[0] == 0x02 || b[0] == 0x03 { + return ECP::new_bigint(&px, (b[0] & 1) as isize); + } + } + + ECP::new() + } + + /* convert to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + if W.is_infinity() { + return String::from("infinity"); + } + if CURVETYPE == MONTGOMERY { + return format!("({})", W.x.redc().tostring()); + } else { + return format!("({},{})", W.x.redc().tostring(), W.y.redc().tostring()); + }; + } + + /* this*=2 */ + pub fn dbl(&mut self) { + if CURVETYPE == WEIERSTRASS { + if CURVE_A == 0 { + let mut t0 = FP::new_copy(&self.y); + t0.sqr(); + let mut t1 = FP::new_copy(&self.y); + t1.mul(&self.z); + let mut t2 = FP::new_copy(&self.z); + t2.sqr(); + + self.z.copy(&t0); + self.z.add(&t0); + self.z.norm(); + self.z.dbl(); + self.z.dbl(); + self.z.norm(); + t2.imul(3 * rom::CURVE_B_I); + + let mut x3 = FP::new_copy(&t2); + x3.mul(&self.z); + + let mut y3 = FP::new_copy(&t0); + y3.add(&t2); + y3.norm(); + self.z.mul(&t1); + t1.copy(&t2); + t1.add(&t2); + t2.add(&t1); + t0.sub(&t2); + t0.norm(); + y3.mul(&t0); + y3.add(&x3); + t1.copy(&self.x); + t1.mul(&self.y); + self.x.copy(&t0); + self.x.norm(); + self.x.mul(&t1); + self.x.dbl(); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + } else { + let mut t0 = FP::new_copy(&self.x); + let mut t1 = FP::new_copy(&self.y); + let mut t2 = FP::new_copy(&self.z); + let mut t3 = FP::new_copy(&self.x); + let mut z3 = FP::new_copy(&self.z); + let mut y3 = FP::new(); + let mut x3 = FP::new(); + let mut b = FP::new(); + + if rom::CURVE_B_I == 0 { + b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + + t0.sqr(); //1 x^2 + t1.sqr(); //2 y^2 + t2.sqr(); //3 + + t3.mul(&self.y); //4 + t3.dbl(); + t3.norm(); //5 + z3.mul(&self.x); //6 + z3.dbl(); + z3.norm(); //7 + y3.copy(&t2); + + if rom::CURVE_B_I == 0 { + y3.mul(&b); //8 + } else { + y3.imul(rom::CURVE_B_I); + } + + y3.sub(&z3); //9 *** + x3.copy(&y3); + x3.add(&y3); + x3.norm(); //10 + + y3.add(&x3); //11 + x3.copy(&t1); + x3.sub(&y3); + x3.norm(); //12 + y3.add(&t1); + y3.norm(); //13 + y3.mul(&x3); //14 + x3.mul(&t3); //15 + t3.copy(&t2); + t3.add(&t2); //16 + t2.add(&t3); //17 + + if rom::CURVE_B_I == 0 { + z3.mul(&b); //18 + } else { + z3.imul(rom::CURVE_B_I); + } + + z3.sub(&t2); //19 + z3.sub(&t0); + z3.norm(); //20 *** + t3.copy(&z3); + t3.add(&z3); //21 + + z3.add(&t3); + z3.norm(); //22 + t3.copy(&t0); + t3.add(&t0); //23 + t0.add(&t3); //24 + t0.sub(&t2); + t0.norm(); //25 + + t0.mul(&z3); //26 + y3.add(&t0); //27 + t0.copy(&self.y); + t0.mul(&self.z); //28 + t0.dbl(); + t0.norm(); //29 + z3.mul(&t0); //30 + x3.sub(&z3); //31 + t0.dbl(); + t0.norm(); //32 + t1.dbl(); + t1.norm(); //33 + z3.copy(&t0); + z3.mul(&t1); //34 + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } + } + if CURVETYPE == EDWARDS { + let mut c = FP::new_copy(&self.x); + let mut d = FP::new_copy(&self.y); + let mut h = FP::new_copy(&self.z); + let mut j = FP::new(); + + self.x.mul(&self.y); + self.x.dbl(); + self.x.norm(); + c.sqr(); + d.sqr(); + if CURVE_A == -1 { + c.neg() + } + self.y.copy(&c); + self.y.add(&d); + self.y.norm(); + h.sqr(); + h.dbl(); + self.z.copy(&self.y); + j.copy(&self.y); + j.sub(&h); + j.norm(); + self.x.mul(&j); + c.sub(&d); + c.norm(); + self.y.mul(&c); + self.z.mul(&j); + } + if CURVETYPE == MONTGOMERY { + let mut a = FP::new_copy(&self.x); + let mut b = FP::new_copy(&self.x); + let mut aa = FP::new(); + let mut bb = FP::new(); + let mut c = FP::new(); + + a.add(&self.z); + a.norm(); + aa.copy(&a); + aa.sqr(); + b.sub(&self.z); + b.norm(); + bb.copy(&b); + bb.sqr(); + c.copy(&aa); + c.sub(&bb); + c.norm(); + + self.x.copy(&aa); + self.x.mul(&bb); + + a.copy(&c); + a.imul((CURVE_A + 2) / 4); + + bb.add(&a); + bb.norm(); + self.z.copy(&bb); + self.z.mul(&c); + } + } + + /* self+=Q */ + pub fn add(&mut self, Q: &ECP) { + if CURVETYPE == WEIERSTRASS { + if CURVE_A == 0 { + let b = 3 * rom::CURVE_B_I; + let mut t0 = FP::new_copy(&self.x); + t0.mul(&Q.x); + let mut t1 = FP::new_copy(&self.y); + t1.mul(&Q.y); + let mut t2 = FP::new_copy(&self.z); + t2.mul(&Q.z); + let mut t3 = FP::new_copy(&self.x); + t3.add(&self.y); + t3.norm(); + let mut t4 = FP::new_copy(&Q.x); + t4.add(&Q.y); + t4.norm(); + t3.mul(&t4); + t4.copy(&t0); + t4.add(&t1); + + t3.sub(&t4); + t3.norm(); + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); + let mut x3 = FP::new_copy(&Q.y); + x3.add(&Q.z); + x3.norm(); + + t4.mul(&x3); + x3.copy(&t1); + x3.add(&t2); + + t4.sub(&x3); + t4.norm(); + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); + let mut y3 = FP::new_copy(&Q.x); + y3.add(&Q.z); + y3.norm(); + x3.mul(&y3); + y3.copy(&t0); + y3.add(&t2); + y3.rsub(&x3); + y3.norm(); + x3.copy(&t0); + x3.add(&t0); + t0.add(&x3); + t0.norm(); + t2.imul(b); + + let mut z3 = FP::new_copy(&t1); + z3.add(&t2); + z3.norm(); + t1.sub(&t2); + t1.norm(); + y3.imul(b); + + x3.copy(&y3); + x3.mul(&t4); + t2.copy(&t3); + t2.mul(&t1); + x3.rsub(&t2); + y3.mul(&t0); + t1.mul(&z3); + y3.add(&t1); + t0.mul(&t3); + z3.mul(&t4); + z3.add(&t0); + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } else { + let mut t0 = FP::new_copy(&self.x); + let mut t1 = FP::new_copy(&self.y); + let mut t2 = FP::new_copy(&self.z); + let mut t3 = FP::new_copy(&self.x); + let mut t4 = FP::new_copy(&Q.x); + let mut z3 = FP::new(); + let mut y3 = FP::new_copy(&Q.x); + let mut x3 = FP::new_copy(&Q.y); + let mut b = FP::new(); + + if rom::CURVE_B_I == 0 { + b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + + t0.mul(&Q.x); //1 + t1.mul(&Q.y); //2 + t2.mul(&Q.z); //3 + + t3.add(&self.y); + t3.norm(); //4 + t4.add(&Q.y); + t4.norm(); //5 + t3.mul(&t4); //6 + t4.copy(&t0); + t4.add(&t1); //7 + t3.sub(&t4); + t3.norm(); //8 + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); //9 + x3.add(&Q.z); + x3.norm(); //10 + t4.mul(&x3); //11 + x3.copy(&t1); + x3.add(&t2); //12 + + t4.sub(&x3); + t4.norm(); //13 + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); //14 + y3.add(&Q.z); + y3.norm(); //15 + + x3.mul(&y3); //16 + y3.copy(&t0); + y3.add(&t2); //17 + + y3.rsub(&x3); + y3.norm(); //18 + z3.copy(&t2); + + if rom::CURVE_B_I == 0 { + z3.mul(&b); //18 + } else { + z3.imul(rom::CURVE_B_I); + } + + x3.copy(&y3); + x3.sub(&z3); + x3.norm(); //20 + z3.copy(&x3); + z3.add(&x3); //21 + + x3.add(&z3); //22 + z3.copy(&t1); + z3.sub(&x3); + z3.norm(); //23 + x3.add(&t1); + x3.norm(); //24 + + if rom::CURVE_B_I == 0 { + y3.mul(&b); //18 + } else { + y3.imul(rom::CURVE_B_I); + } + + t1.copy(&t2); + t1.add(&t2); //t1.norm();//26 + t2.add(&t1); //27 + + y3.sub(&t2); //28 + + y3.sub(&t0); + y3.norm(); //29 + t1.copy(&y3); + t1.add(&y3); //30 + y3.add(&t1); + y3.norm(); //31 + + t1.copy(&t0); + t1.add(&t0); //32 + t0.add(&t1); //33 + t0.sub(&t2); + t0.norm(); //34 + t1.copy(&t4); + t1.mul(&y3); //35 + t2.copy(&t0); + t2.mul(&y3); //36 + y3.copy(&x3); + y3.mul(&z3); //37 + y3.add(&t2); //y3.norm();//38 + x3.mul(&t3); //39 + x3.sub(&t1); //40 + z3.mul(&t4); //41 + t1.copy(&t3); + t1.mul(&t0); //42 + z3.add(&t1); + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } + } + if CURVETYPE == EDWARDS { + let bb = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let mut a = FP::new_copy(&self.z); + let mut b = FP::new(); + let mut c = FP::new_copy(&self.x); + let mut d = FP::new_copy(&self.y); + let mut e = FP::new(); + let mut f = FP::new(); + let mut g = FP::new(); + + a.mul(&Q.z); + b.copy(&a); + b.sqr(); + c.mul(&Q.x); + d.mul(&Q.y); + + e.copy(&c); + e.mul(&d); + e.mul(&bb); + f.copy(&b); + f.sub(&e); + g.copy(&b); + g.add(&e); + + if CURVE_A == 1 { + e.copy(&d); + e.sub(&c); + } + c.add(&d); + + b.copy(&self.x); + b.add(&self.y); + d.copy(&Q.x); + d.add(&Q.y); + b.norm(); + d.norm(); + b.mul(&d); + b.sub(&c); + b.norm(); + f.norm(); + b.mul(&f); + self.x.copy(&a); + self.x.mul(&b); + g.norm(); + if CURVE_A == 1 { + e.norm(); + c.copy(&e); + c.mul(&g); + } + if CURVE_A == -1 { + c.norm(); + c.mul(&g); + } + self.y.copy(&a); + self.y.mul(&c); + self.z.copy(&f); + self.z.mul(&g); + } + } + + /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ + pub fn dadd(&mut self, Q: &ECP, W: &ECP) { + let mut a = FP::new_copy(&self.x); + let mut b = FP::new_copy(&self.x); + let mut c = FP::new_copy(&Q.x); + let mut d = FP::new_copy(&Q.x); + let mut da = FP::new(); + let mut cb = FP::new(); + + a.add(&self.z); + b.sub(&self.z); + + c.add(&Q.z); + d.sub(&Q.z); + + a.norm(); + d.norm(); + + da.copy(&d); + da.mul(&a); + + c.norm(); + b.norm(); + + cb.copy(&c); + cb.mul(&b); + + a.copy(&da); + a.add(&cb); + a.norm(); + a.sqr(); + b.copy(&da); + b.sub(&cb); + b.norm(); + b.sqr(); + + self.x.copy(&a); + self.z.copy(&W.x); + self.z.mul(&b); + } + + /* self-=Q */ + pub fn sub(&mut self, Q: &ECP) { + let mut NQ = ECP::new(); + NQ.copy(Q); + NQ.neg(); + self.add(&NQ); + } + + /* constant time multiply by small integer of length bts - use ladder */ + pub fn pinmul(&self, e: i32, bts: i32) -> ECP { + if CURVETYPE == MONTGOMERY { + self.mul(&BIG::new_int(e as isize)) + } else { + let mut P = ECP::new(); + let mut R0 = ECP::new(); + let mut R1 = ECP::new(); + R1.copy(&self); + + for i in (0..bts).rev() { + let b = ((e >> i) & 1) as isize; + P.copy(&R1); + P.add(&R0); + R0.cswap(&mut R1, b); + R1.copy(&P); + R0.dbl(); + R0.cswap(&mut R1, b); + } + P.copy(&R0); + P + } + } + +// Point multiplication, multiplies a point P by a scalar e +// This code has no inherent awareness of the order of the curve, or the order of the point. +// The order of the curve will be h.r, where h is a cofactor, and r is a large prime +// Typically P will be of order r (but not always), and typically e will be less than r (but not always) +// A problem can arise if a secret e is a few bits less than r, as the leading zeros in e will leak via a timing attack +// The secret e may however be greater than r (see RFC7748 which combines elimination of a small cofactor h with the point multiplication, using an e>r) +// Our solution is to use as a multiplier an e, whose length in bits is that of the logical OR of e and r, hence allowing e>r while forcing inclusion of leading zeros if e ECP { + return self.clmul(e,e); + } + +// .. but this one does not (typically set maxe=r) +// Set P=e*P + pub fn clmul(&self, e: &BIG, maxe: &BIG) -> ECP { + if e.iszilch() || self.is_infinity() { + return ECP::new(); + } + let mut P = ECP::new(); + let mut cm = BIG::new_copy(e); cm.or(maxe); + let max=cm.nbits(); + + if CURVETYPE == MONTGOMERY { + /* use Ladder */ + let mut D = ECP::new(); + let mut R0 = ECP::new(); + R0.copy(&self); + let mut R1 = ECP::new(); + R1.copy(&self); + R1.dbl(); + D.copy(&self); D.affine(); + let nb = max; + + for i in (0..nb - 1).rev() { + let b = e.bit(i); + P.copy(&R1); + P.dadd(&R0, &D); + R0.cswap(&mut R1, b); + R1.copy(&P); + R0.dbl(); + R0.cswap(&mut R1, b); + } + P.copy(&R0) + } else { + // fixed size windows + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut Q = ECP::new(); + let mut C = ECP::new(); + + let mut W: [ECP; 8] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + Q.copy(&self); + Q.dbl(); + + W[0].copy(&self); + + for i in 1..8 { + C.copy(&W[i - 1]); + W[i].copy(&C); + W[i].add(&Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(&e); + let s = t.parity(); + t.inc(1); + t.norm(); + let ns = t.parity(); + mt.copy(&t); + mt.inc(1); + mt.norm(); + t.cmove(&mt, s); + Q.cmove(&self, ns); + C.copy(&Q); + + let nb = 1 + (max + 3) / 4; + + // convert exponent to signed 4-bit window + for i in 0..nb { + w[i] = (t.lastbits(5) - 16) as i8; + t.dec(w[i] as isize); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5) as i8; + + //P.copy(&W[((w[nb] as usize) - 1) / 2]); + + P.selector(&W, w[nb] as i32); + for i in (0..nb).rev() { + Q.selector(&W, w[i] as i32); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(&Q); + } + P.sub(&C); /* apply correction */ + } + P + } + +// Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i + pub fn muln(n: usize, X: &[ECP], e: &[BIG]) -> ECP { + let mut B: [ECP; 16] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut P = ECP::new(); + let mut S = ECP::new(); + let mut R = ECP::new(); + + mt.copy(&e[0]); mt.norm(); + for i in 1..n { // find biggest + t.copy(&e[i]); t.norm(); + let k=BIG::comp(&t,&mt); + mt.cmove(&t,(k+1)/2); + } + let nb=(mt.nbits()+3)/4; + for i in (0..nb).rev() { // Pippenger's algorithm + for j in 0..16 { + B[j].inf(); + } + for j in 0..n { + mt.copy(&e[j]); mt.norm(); + mt.shr((i*4) as usize); + let k=mt.lastbits(4) as usize; + B[k].add(&X[j]); + } + R.inf(); S.inf(); + for j in (1..16).rev() { + R.add(&B[j]); + S.add(&R); + } + for _ in 0..4 { + P.dbl(); + } + P.add(&S); + } + P + } + + /* Return e.this+f.Q */ + + pub fn mul2(&self, e: &BIG, Q: &ECP, f: &BIG) -> ECP { + let mut te = BIG::new(); + let mut tf = BIG::new(); + let mut mt = BIG::new(); + let mut S = ECP::new(); + let mut T = ECP::new(); + let mut C = ECP::new(); + + let mut W: [ECP; 8] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 1) / 2; + let mut w: [i8; CT] = [0; CT]; + + te.copy(e); + tf.copy(f); + + // precompute table + + W[1].copy(&self); + W[1].sub(Q); + W[2].copy(&self); + W[2].add(Q); + S.copy(&Q); + S.dbl(); + C.copy(&W[1]); + W[0].copy(&C); + W[0].sub(&S); // copy to C is stupid Rust thing.. + C.copy(&W[2]); + W[3].copy(&C); + W[3].add(&S); + T.copy(&self); + T.dbl(); + C.copy(&W[1]); + W[5].copy(&C); + W[5].add(&T); + C.copy(&W[2]); + W[6].copy(&C); + W[6].add(&T); + C.copy(&W[5]); + W[4].copy(&C); + W[4].sub(&S); + C.copy(&W[6]); + W[7].copy(&C); + W[7].add(&S); + + // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction + + let mut s = te.parity(); + te.inc(1); + te.norm(); + let mut ns = te.parity(); + mt.copy(&te); + mt.inc(1); + mt.norm(); + te.cmove(&mt, s); + T.cmove(&self, ns); + C.copy(&T); + + s = tf.parity(); + tf.inc(1); + tf.norm(); + ns = tf.parity(); + mt.copy(&tf); + mt.inc(1); + mt.norm(); + tf.cmove(&mt, s); + S.cmove(&Q, ns); + C.add(&S); + + mt.copy(&te); + mt.add(&tf); + mt.norm(); + let nb = 1 + (mt.nbits() + 1) / 2; + + // convert exponent to signed 2-bit window + for i in 0..nb { + let a = te.lastbits(3) - 4; + te.dec(a); + te.norm(); + te.fshr(2); + let b = tf.lastbits(3) - 4; + tf.dec(b); + tf.norm(); + tf.fshr(2); + w[i] = (4 * a + b) as i8; + } + w[nb] = (4 * te.lastbits(3) + tf.lastbits(3)) as i8; + //S.copy(&W[((w[nb] as usize) - 1) / 2]); + S.selector(&W, w[nb] as i32); + + for i in (0..nb).rev() { + T.selector(&W, w[i] as i32); + S.dbl(); + S.dbl(); + S.add(&T); + } + S.sub(&C); /* apply correction */ + S + } + + pub fn cfp(&mut self) { + let cf = rom::CURVE_COF_I; + if cf == 1 { + return; + } + if cf == 4 { + self.dbl(); + self.dbl(); + return; + } + if cf == 8 { + self.dbl(); + self.dbl(); + self.dbl(); + return; + } + let c = BIG::new_ints(&rom::CURVE_COF); + let P = self.mul(&c); + self.copy(&P); + } + +/* Hunt and Peck a BIG to a curve point */ + #[allow(non_snake_case)] + pub fn hap2point(h: &BIG) -> ECP { + let mut P: ECP; + let mut x =BIG::new_copy(&h); + loop { + if CURVETYPE != MONTGOMERY { + P = ECP::new_bigint(&x, 0); + } else { + P = ECP::new_big(&x); + } + x.inc(1); + x.norm(); + if !P.is_infinity() { + break; + } + } + P + } + +/* Constant time Map to Point */ + #[allow(non_snake_case)] + pub fn map2point(h: &FP) -> ECP { + let mut P = ECP::new(); + + if CURVETYPE == MONTGOMERY { + // Elligator 2 + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut t =FP::new_copy(h); + let mut w =FP::new(); + let one=FP::new_int(1); + let A=FP::new_int(CURVE_A); + let mut N =FP::new(); + let mut D =FP::new(); + let mut hint =FP::new(); + + t.sqr(); // t^2 + + if fp::PM1D2 == 2 { + t.dbl(); // 2t^2 + } + if fp::PM1D2 == 1 { + t.neg(); // -t^2 + } + if fp::PM1D2 > 2 { + t.imul(fp::QNRI as isize); // precomputed QNR + } + + t.norm(); + D.copy(&t); D.add(&one); D.norm(); // Denominator D=1+z.t^2 + + X1.copy(&A); + X1.neg(); X1.norm(); // X1=-A/D + X2.copy(&X1); + X2.mul(&t); // X2=-At/D + + w.copy(&X1); w.sqr(); N.copy(&w); N.mul(&X1); + w.mul(&A); w.mul(&D); N.add(&w); + t.copy(&D); t.sqr(); + t.mul(&X1); + N.add(&t); N.norm(); // Numerator=x^3+ADx^2+D^2x + + t.copy(&N); t.mul(&D); // N*D + let qres=t.qr(Some(&mut hint)); // only exp + w.copy(&t); w.inverse(Some(&hint)); + D.copy(&w); D.mul(&N); // 1/D + X1.mul(&D); // get X1 + X2.mul(&D); // get X2 + X1.cmove(&X2,1-qres); + + let a=X1.redc(); + P.copy(&ECP::new_big(&a)); + + } + if CURVETYPE == EDWARDS { +// Elligator 2 - map to Montgomery, place point, map back + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut t=FP::new_copy(h); + let mut w=FP::new(); + let one=FP::new_int(1); + let mut A=FP::new(); + let mut w1=FP::new(); + let mut w2=FP::new(); + let mut B = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let mut Y=FP::new(); + let mut K=FP::new(); + let mut D=FP::new(); + let mut hint=FP::new(); + //let mut Y3=FP::new(); + let rfc: isize; + + if fp::MODTYPE != fp::GENERALISED_MERSENNE { + A.copy(&B); + if CURVE_A==1 { + A.add(&one); // A=B+1 + B.sub(&one); // B=B-1 + } else { + A.sub(&one); // A=B-1 + B.add(&one); // B=B+1 + } + A.norm(); B.norm(); + + A.div2(); // (A+B)/2 = J/K + B.div2(); // (B-A)/2 + B.div2(); // (B-A)/4 = -1/K + + K.copy(&B); + K.neg(); K.norm(); + + K.invsqrt(&mut w2,&mut w1); // return K, sqrt(1/K) - could be precalculated! + K.copy(&w2); + rfc=fp::RIADZ; + if rfc==1 { + A.mul(&K); + K.mul(&w1); + } else { + B.sqr(); + } + } else { + rfc=1; + A.copy(&FP::new_int(156326)); + } +// Map to this Montgomery curve X^2=X^3+AX^2+BX + t.sqr(); // t^2 + let mut qnr=0; + if fp::PM1D2 == 2 { + t.dbl(); + qnr=2; + } + if fp::PM1D2 == 1 { + t.neg(); + qnr = -1; + } + if fp::PM1D2 > 2 { + t.imul(fp::QNRI as isize); // precomputed QNR + qnr=fp::QNRI as isize; + } + t.norm(); + + D.copy(&t); D.add(&one); D.norm(); // Denominator=(1+z.u^2) + X1.copy(&A); + X1.neg(); X1.norm(); // X1=-(J/K).inv(1+z.u^2) + X2.copy(&X1); X2.mul(&t); // X2=X1*z*u^2 + +// Figure out RHS of Montgomery curve in rational form gx1/d^3 + + w.copy(&X1); w.sqr(); w1.copy(&w); w1.mul(&X1); + w.mul(&A); w.mul(&D); w1.add(&w); + w2.copy(&D); w2.sqr(); + + if rfc==0 { + w.copy(&X1); w.mul(&B); + w2.mul(&w); + w1.add(&w2); // w1=X1^3+ADX1^2+BD^2X1 + } else { + w2.mul(&X1); + w1.add(&w2); // w1=X1^3+ADX1^2+D^2X1 + } + w1.norm(); + + B.copy(&w1); B.mul(&D); // gx1=num/den^3 - is_qr num*den (same as num/den, same as num/den^3) + let qres=B.qr(Some(&mut hint)); // Exponentiation + w.copy(&B); w.inverse(Some(&hint)); + D.copy(&w); D.mul(&w1); // 1/D + X1.mul(&D); // get X1 + X2.mul(&D); // get X2 + D.sqr(); + + w1.copy(&B); w1.imul(qnr); + w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + w.mul(&hint); + w2.copy(&D); w2.mul(&h); + + X1.cmove(&X2,1-qres); + B.cmove(&w1,1-qres); + hint.cmove(&w,1-qres); + D.cmove(&w2,1-qres); + + Y.copy(&B.sqrt(Some(&hint))); + Y.mul(&D); +/* + Y.copy(&B.sqrt(Some(&hint))); // sqrt(num*den) + Y.mul(&D); // sqrt(num/den^3) + + B.imul(qnr); // now for gx2 = Z.u^2.gx1 + w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); // qnr^C3 + hint.mul(&w); // modify hint for gx2 + + Y3.copy(&B.sqrt(Some(&hint))); // second candidate + D.mul(&h); + Y3.mul(&D); + + X1.cmove(&X2,1-qres); // pick correct one + Y.cmove(&Y3,1-qres); +*/ +// correct sign of Y + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,qres^Y.sign()); + + if rfc==0 { + X1.mul(&K); + Y.mul(&K); + } + + if fp::MODTYPE == fp::GENERALISED_MERSENNE { + // GOLDILOCKS isogeny + t.copy(&X1); t.sqr(); + w.copy(&t); w.add(&one); w.norm(); + t.sub(&one); t.norm(); + w1.copy(&t); w1.mul(&Y); + w1.dbl(); X2.copy(&w1); X2.add(&w1); X2.norm(); + t.sqr(); + Y.sqr(); Y.dbl(); Y.dbl(); Y.norm(); + B.copy(&t); B.add(&Y); B.norm(); + + w2.copy(&Y); w2.sub(&t); w2.norm(); + w2.mul(&X1); + t.mul(&X1); + Y.div2(); + w1.copy(&Y); w1.mul(&w); + w1.rsub(&t); w1.norm(); + + t.copy(&X2); t.mul(&w1); // output in projective to avoid inversion + P.x.copy(&t); + t.copy(&w2); t.mul(&B); + P.y.copy(&t); + t.copy(&w1); t.mul(&B); + P.z.copy(&t); + + return P; + } else { + w1.copy(&X1); w1.add(&one); w1.norm(); // s+1 + w2.copy(&X1); w2.sub(&one); w2.norm(); // s-1 + t.copy(&w1); t.mul(&Y); + X1.mul(&w1); + + if rfc==1 { + X1.mul(&K); + } + Y.mul(&w2); // output in projective to avoid inversion + P.x.copy(&X1); + P.y.copy(&Y); + P.z.copy(&t); + + return P + } + } + if CURVETYPE==WEIERSTRASS { + // SSWU or SVDW method + let mut A=FP::new(); + let mut B=FP::new(); + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut X3=FP::new(); + let one=FP::new_int(1); + let mut Y=FP::new(); + let mut D=FP::new(); + let mut t=FP::new_copy(h); + let mut w=FP::new(); + let mut D2=FP::new(); + let mut hint=FP::new(); + let mut GX1=FP::new(); + //let mut Y3=FP::new(); + + let sgn=t.sign(); + + if CURVE_A != 0 || HTC_ISO != 0 + { // Map to point on isogenous curve + if HTC_ISO != 0 { +/* CAHCZS + A.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_AD))); + B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_BD))); +CAHCZF */ + } else { + A.copy(&FP::new_int(CURVE_A)); + B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + // SSWU Method + t.sqr(); + t.imul(fp::RIADZ); // Z from hash-to-point draft standard + w.copy(&t); w.add(&one); w.norm(); + + w.mul(&t); D.copy(&A); + D.mul(&w); + + w.add(&one); w.norm(); + w.mul(&B); + w.neg(); w.norm(); + + X2.copy(&w); + X3.copy(&t); X3.mul(&X2); + +// x^3+Ad^2x+Bd^3 + GX1.copy(&X2); GX1.sqr(); D2.copy(&D); + D2.sqr(); w.copy(&A); w.mul(&D2); GX1.add(&w); GX1.norm(); GX1.mul(&X2); D2.mul(&D); w.copy(&B); w.mul(&D2); GX1.add(&w); GX1.norm(); + + w.copy(&GX1); w.mul(&D); + let qr=w.qr(Some(&mut hint)); + D.copy(&w); D.inverse(Some(&hint)); + D.mul(&GX1); + X2.mul(&D); + X3.mul(&D); + t.mul(h); + D2.copy(&D); D2.sqr(); + + D.copy(&D2); D.mul(&t); + t.copy(&w); t.imul(fp::RIADZ); + X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + X1.mul(&hint); + + X2.cmove(&X3,1-qr); + D2.cmove(&D,1-qr); + w.cmove(&t,1-qr); + hint.cmove(&X1,1-qr); + + Y.copy(&w.sqrt(Some(&hint))); + Y.mul(&D2); +/* + Y.copy(&w.sqrt(Some(&hint))); + Y.mul(&D2); + + D2.mul(&t); + w.imul(fp::RIADZ); + + X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + hint.mul(&X1); + + Y3.copy(&w.sqrt(Some(&hint))); + Y3.mul(&D2); + + X2.cmove(&X3,1-qr); + Y.cmove(&Y3,1-qr); +*/ + let ne=Y.sign()^sgn; + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,ne); + + if HTC_ISO != 0 { + +/* CAHCZS + let mut k=0; + let isox=HTC_ISO; + let isoy=3*(isox-1)/2; + // xnum + let mut xnum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; + for _ in 0..isox { + xnum.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xnum.add(&w); xnum.norm(); + } + // xden + let mut xden=FP::new_copy(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xden.add(&w); xden.norm(); + for _ in 0..isox-2 { + xden.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xden.add(&w); xden.norm(); + } + // ynum + let mut ynum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; + for _ in 0..isoy { + ynum.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + ynum.add(&w); ynum.norm(); + } + // yden + let mut yden=FP::new_copy(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + yden.add(&w); yden.norm(); + for _ in 0..isoy-1 { + yden.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + yden.add(&w); yden.norm(); + } + ynum.mul(&Y); + w.copy(&xnum); w.mul(&yden); + P.x.copy(&w); + w.copy(&ynum); w.mul(&xden); + P.y.copy(&w); + w.copy(&xden); w.mul(&yden); + P.z.copy(&w); + return P; +CAHCZF */ + } else { + let x=X2.redc(); + let y=Y.redc(); + P.copy(&ECP::new_bigs(&x,&y)); + return P; + } + } else { +// Shallue and van de Woestijne +// SQRTM3 not available, so preprocess this out +/* */ + let Z=fp::RIADZ; + X1.copy(&FP::new_int(Z)); + X3.copy(&X1); + A.copy(&ECP::rhs(&X1)); + B.copy(&FP::new_big(&BIG::new_ints(&rom::SQRTM3))); + B.imul(Z); + + t.sqr(); + Y.copy(&A); Y.mul(&t); + t.copy(&one); t.add(&Y); t.norm(); + Y.rsub(&one); Y.norm(); + D.copy(&t); D.mul(&Y); + D.mul(&B); + + w.copy(&A); + FP::tpo(&mut D,&mut w); + + w.mul(&B); + if w.sign()==1 { + w.neg(); + w.norm(); + } + w.mul(&B); + w.mul(&h); w.mul(&Y); w.mul(&D); + + X1.neg(); X1.norm(); X1.div2(); + X2.copy(&X1); + X1.sub(&w); X1.norm(); + X2.add(&w); X2.norm(); + A.dbl(); A.dbl(); A.norm(); + t.sqr(); t.mul(&D); t.sqr(); + A.mul(&t); + X3.add(&A); X3.norm(); + + let mut rhs=ECP::rhs(&X2); + X3.cmove(&X2,rhs.qr(None)); + rhs.copy(&ECP::rhs(&X1)); + X3.cmove(&X1,rhs.qr(None)); + rhs.copy(&ECP::rhs(&X3)); + Y.copy(&rhs.sqrt(None)); + + let ne=Y.sign()^sgn; + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,ne); + + let x=X3.redc(); + let y=Y.redc(); + P.copy(&ECP::new_bigs(&x,&y)); + return P; +/* */ + } + } + P + } + +/* Map byte string to curve point */ + #[allow(non_snake_case)] + pub fn mapit(h: &[u8]) -> ECP { + let q = BIG::new_ints(&rom::MODULUS); + let mut dx = DBIG::frombytes(h); + let x=dx.dmod(&q); + let mut P=ECP::hap2point(&x); + P.cfp(); + P + } + + pub fn generator() -> ECP { + let G: ECP; + let gx = BIG::new_ints(&rom::CURVE_GX); + if CURVETYPE != MONTGOMERY { + let gy = BIG::new_ints(&rom::CURVE_GY); + G = ECP::new_bigs(&gx, &gy); + } else { + G = ECP::new_big(&gx); + } + G + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp2.rs new file mode 100644 index 000000000000..09c66c6bcd9a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/ecp2.rs @@ -0,0 +1,999 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::fp2::FP2; +use crate::bn254::rom; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; + +#[derive(Clone)] +pub struct ECP2 { + x: FP2, + y: FP2, + z: FP2, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for ECP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for ECP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[allow(non_snake_case)] +impl ECP2 { + pub fn new() -> ECP2 { + ECP2 { + x: FP2::new(), + y: FP2::new_int(1), + z: FP2::new(), + } + } + #[allow(non_snake_case)] + /* construct this from (x,y) - but set to O if not on curve */ + pub fn new_fp2s(ix: &FP2, iy: &FP2) -> ECP2 { + let mut E = ECP2::new(); + E.x.copy(&ix); + E.y.copy(&iy); + E.z.one(); + E.x.norm(); + + let rhs = ECP2::rhs(&E.x); + let mut y2 = FP2::new_copy(&E.y); + y2.sqr(); + if !y2.equals(&rhs) { + E.inf(); + } + E + } + + /* construct this from x - but set to O if not on curve */ + pub fn new_fp2(ix: &FP2, s:isize) -> ECP2 { + let mut E = ECP2::new(); + let mut h = FP::new(); + E.x.copy(&ix); + E.y.one(); + E.z.one(); + E.x.norm(); + let mut rhs = ECP2::rhs(&E.x); + if rhs.qr(Some(&mut h)) == 1 { + rhs.sqrt(Some(&h)); + if rhs.sign() != s { + rhs.neg(); + } + rhs.reduce(); + E.y.copy(&rhs); + } else { + E.inf(); + } + E + } + + /* Test this=O? */ + pub fn is_infinity(&self) -> bool { + self.x.iszilch() && self.z.iszilch() + } + + /* copy self=P */ + pub fn copy(&mut self, P: &ECP2) { + self.x.copy(&P.x); + self.y.copy(&P.y); + self.z.copy(&P.z); + } + + /* set self=O */ + pub fn inf(&mut self) { + self.x.zero(); + self.y.one(); + self.z.zero(); + } + + /* set self=-self */ + pub fn neg(&mut self) { + self.y.norm(); + self.y.neg(); + self.y.norm(); + } + + /* Conditional move of Q to self dependant on d */ + pub fn cmove(&mut self, Q: &ECP2, d: isize) { + self.x.cmove(&Q.x, d); + self.y.cmove(&Q.y, d); + self.z.cmove(&Q.z, d); + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* Constant time select from pre-computed table */ + pub fn selector(&mut self, W: &[ECP2], b: i32) { + let mut MP = ECP2::new(); + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&W[0], ECP2::teq(babs, 0)); // conditional move + self.cmove(&W[1], ECP2::teq(babs, 1)); + self.cmove(&W[2], ECP2::teq(babs, 2)); + self.cmove(&W[3], ECP2::teq(babs, 3)); + self.cmove(&W[4], ECP2::teq(babs, 4)); + self.cmove(&W[5], ECP2::teq(babs, 5)); + self.cmove(&W[6], ECP2::teq(babs, 6)); + self.cmove(&W[7], ECP2::teq(babs, 7)); + + MP.copy(self); + MP.neg(); + self.cmove(&MP, (m & 1) as isize); + } + + /* Test if P == Q */ + pub fn equals(&self, Q: &ECP2) -> bool { + let mut a = FP2::new_copy(&self.x); + let mut b = FP2::new_copy(&Q.x); + + a.mul(&Q.z); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + a.copy(&self.y); + a.mul(&Q.z); + b.copy(&Q.y); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + + true + } + + /* set to Affine - (x,y,z) to (x,y) */ + pub fn affine(&mut self) { + if self.is_infinity() { + return; + } + let one = FP2::new_int(1); + if self.z.equals(&one) { + return; + } + self.z.inverse(None); + + self.x.mul(&self.z); + self.x.reduce(); + self.y.mul(&self.z); + self.y.reduce(); + self.z.copy(&one); + } + + /* extract affine x as FP2 */ + pub fn getx(&self) -> FP2 { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + FP2::new_copy(&W.x) + } + + /* extract affine y as FP2 */ + pub fn gety(&self) -> FP2 { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + FP2::new_copy(&W.y) + } + + /* extract projective x */ + pub fn getpx(&self) -> FP2 { + FP2::new_copy(&self.x) + } + /* extract projective y */ + pub fn getpy(&self) -> FP2 { + FP2::new_copy(&self.y) + } + /* extract projective z */ + pub fn getpz(&self) -> FP2 { + FP2::new_copy(&self.z) + } + + /* convert to byte array */ + pub fn tobytes(&self, b: &mut [u8], compress: bool) { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + W.x.tobytes(&mut t); + + if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { + alt=true; + } + if alt { + for i in 0..MB { + b[i]=t[i] + } + if !compress { + W.y.tobytes(&mut t); + for i in 0..MB { + b[i+MB]=t[i]; + } + } else { + b[0]|=0x80; + if W.y.islarger()==1 { + b[0]|=0x20; + } + } + + } else { + for i in 0..MB { + b[i+1]=t[i]; + } + if !compress { + b[0]=0x04; + W.y.tobytes(&mut t); + for i in 0..MB { + b[i+MB+1]=t[i]; + } + } else { + b[0]=0x02; + if W.y.sign() == 1 { + b[0]=0x03; + } + } + } + } + + /* convert from byte array to point */ + pub fn frombytes(b: &[u8]) -> ECP2 { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + let typ=b[0] as isize; + let mut alt=false; + + if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + t[i]=b[i]; + } + t[0]&=0x1f; + let rx=FP2::frombytes(&t); + if (b[0]&0x80)==0 { + for i in 0..MB { + t[i]=b[i+MB]; + } + let ry=FP2::frombytes(&t); + ECP2::new_fp2s(&rx,&ry) + } else { + let sgn=(b[0]&0x20)>>5; + let mut P=ECP2::new_fp2(&rx,0); + let cmp=P.y.islarger(); + if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { + P.neg(); + } + P + } + } else { + for i in 0..MB { + t[i]=b[i+1]; + } + let rx=FP2::frombytes(&t); + if typ == 0x04 { + for i in 0..MB { + t[i]=b[i+MB+1]; + } + let ry=FP2::frombytes(&t); + ECP2::new_fp2s(&rx,&ry) + } else { + ECP2::new_fp2(&rx,typ&1) + } + } + } + + /* convert this to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + if W.is_infinity() { + String::from("infinity") + } else { + format!("({},{})", W.x.tostring(), W.y.tostring()) + } + } + + /* Calculate RHS of twisted curve equation x^3+B/i */ + pub fn rhs(x: &FP2) -> FP2 { + let mut r = FP2::new_copy(x); + r.sqr(); + let mut b = FP2::new_big(&BIG::new_ints(&rom::CURVE_B)); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.div_ip(); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + b.norm(); + b.mul_ip(); + b.norm(); + } + + r.mul(x); + r.add(&b); + + r.reduce(); + r + } + + /* self+=self */ + pub fn dbl(&mut self) -> isize { + let mut iy = FP2::new_copy(&self.y); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + iy.mul_ip(); + iy.norm(); + } + + let mut t0 = FP2::new_copy(&self.y); //***** Change + t0.sqr(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t0.mul_ip(); + } + let mut t1 = FP2::new_copy(&iy); + t1.mul(&self.z); + let mut t2 = FP2::new_copy(&self.z); + t2.sqr(); + + self.z.copy(&t0); + self.z.add(&t0); + self.z.norm(); + self.z.dbl(); + self.z.dbl(); + self.z.norm(); + + t2.imul(3 * rom::CURVE_B_I); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + t2.mul_ip(); + t2.norm(); + } + let mut x3 = FP2::new_copy(&t2); + x3.mul(&self.z); + + let mut y3 = FP2::new_copy(&t0); + + y3.add(&t2); + y3.norm(); + self.z.mul(&t1); + t1.copy(&t2); + t1.add(&t2); + t2.add(&t1); + t2.norm(); + t0.sub(&t2); + t0.norm(); //y^2-9bz^2 + y3.mul(&t0); + y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 + t1.copy(&self.x); + t1.mul(&iy); // + self.x.copy(&t0); + self.x.norm(); + self.x.mul(&t1); + self.x.dbl(); //(y^2-9bz^2)xy2 + + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + + 1 + } + + /* self+=Q - return 0 for add, 1 for double, -1 for O */ + pub fn add(&mut self, Q: &ECP2) -> isize { + let b = 3 * rom::CURVE_B_I; + let mut t0 = FP2::new_copy(&self.x); + t0.mul(&Q.x); // x.Q.x + let mut t1 = FP2::new_copy(&self.y); + t1.mul(&Q.y); // y.Q.y + + let mut t2 = FP2::new_copy(&self.z); + t2.mul(&Q.z); + let mut t3 = FP2::new_copy(&self.x); + t3.add(&self.y); + t3.norm(); //t3=X1+Y1 + let mut t4 = FP2::new_copy(&Q.x); + t4.add(&Q.y); + t4.norm(); //t4=X2+Y2 + t3.mul(&t4); //t3=(X1+Y1)(X2+Y2) + t4.copy(&t0); + t4.add(&t1); //t4=X1.X2+Y1.Y2 + + t3.sub(&t4); + t3.norm(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t3.mul_ip(); + t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 + } + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); //t4=Y1+Z1 + let mut x3 = FP2::new_copy(&Q.y); + x3.add(&Q.z); + x3.norm(); //x3=Y2+Z2 + + t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2) + x3.copy(&t1); // + x3.add(&t2); //X3=Y1.Y2+Z1.Z2 + + t4.sub(&x3); + t4.norm(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t4.mul_ip(); + t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 + } + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); // x3=X1+Z1 + let mut y3 = FP2::new_copy(&Q.x); + y3.add(&Q.z); + y3.norm(); // y3=X2+Z2 + x3.mul(&y3); // x3=(X1+Z1)(X2+Z2) + y3.copy(&t0); + y3.add(&t2); // y3=X1.X2+Z1+Z2 + y3.rsub(&x3); + y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 + + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t0.mul_ip(); + t0.norm(); // x.Q.x + t1.mul_ip(); + t1.norm(); // y.Q.y + } + x3.copy(&t0); + x3.add(&t0); + t0.add(&x3); + t0.norm(); + t2.imul(b); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + t2.mul_ip(); + t2.norm(); + } + let mut z3 = FP2::new_copy(&t1); + z3.add(&t2); + z3.norm(); + t1.sub(&t2); + t1.norm(); + y3.imul(b); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + y3.mul_ip(); + y3.norm(); + } + x3.copy(&y3); + x3.mul(&t4); + t2.copy(&t3); + t2.mul(&t1); + x3.rsub(&t2); + y3.mul(&t0); + t1.mul(&z3); + y3.add(&t1); + t0.mul(&t3); + z3.mul(&t4); + z3.add(&t0); + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + + 0 + } + + /* set this-=Q */ + pub fn sub(&mut self, Q: &ECP2) -> isize { + let mut NQ = ECP2::new(); + NQ.copy(Q); + NQ.neg(); + self.add(&NQ) + } + + /* set this*=q, where q is Modulus, using Frobenius */ + pub fn frob(&mut self, x: &FP2) { + let mut x2 = FP2::new_copy(x); + x2.sqr(); + self.x.conj(); + self.y.conj(); + self.z.conj(); + self.z.reduce(); + self.x.mul(&x2); + self.y.mul(&x2); + self.y.mul(x); + } + + /* self*=e */ + pub fn mul(&self, e: &BIG) -> ECP2 { + /* fixed size windows */ + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut P = ECP2::new(); + let mut Q = ECP2::new(); + let mut C = ECP2::new(); + + if self.is_infinity() { + return P; + } + + let mut W: [ECP2; 8] = [ + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + /* precompute table */ + Q.copy(&self); + Q.dbl(); + + W[0].copy(&self); + + for i in 1..8 { + C.copy(&W[i - 1]); + W[i].copy(&C); + W[i].add(&Q); + } + + /* make exponent odd - add 2P if even, P if odd */ + t.copy(&e); + let s = t.parity(); + t.inc(1); + t.norm(); + let ns = t.parity(); + mt.copy(&t); + mt.inc(1); + mt.norm(); + t.cmove(&mt, s); + Q.cmove(&self, ns); + C.copy(&Q); + + let nb = 1 + (t.nbits() + 3) / 4; + + /* convert exponent to signed 4-bit window */ + for i in 0..nb { + w[i] = (t.lastbits(5) - 16) as i8; + t.dec(w[i] as isize); + t.norm(); + t.fshr(4); + } + w[nb] = (t.lastbits(5)) as i8; + + //P.copy(&W[((w[nb] as usize) - 1) / 2]); + + P.selector(&W, w[nb] as i32); + for i in (0..nb).rev() { + Q.selector(&W, w[i] as i32); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(&Q); + } + P.sub(&C); + P + } + + #[allow(non_snake_case)] + pub fn cfp(&mut self) { + let mut X = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + X.inverse(None); + X.norm(); + } + let x = BIG::new_ints(&rom::CURVE_BNX); + // Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez + // Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))). + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + let mut T = self.mul(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + T.neg(); + } + let mut K = ECP2::new(); + K.copy(&T); + K.dbl(); + K.add(&T); + + K.frob(&X); + self.frob(&X); + self.frob(&X); + self.frob(&X); + self.add(&T); + self.add(&K); + T.frob(&X); + T.frob(&X); + self.add(&T); + } + // Efficient hash maps to G2 on BLS curves - Budroni, Pintore + // Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) + if ecp::CURVE_PAIRING_TYPE > ecp::BN { + let mut xQ = self.mul(&x); + let mut x2Q = xQ.mul(&x); + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + xQ.neg(); + } + x2Q.sub(&xQ); + x2Q.sub(&self); + + xQ.sub(&self); + xQ.frob(&X); + + self.dbl(); + self.frob(&X); + self.frob(&X); + + self.add(&x2Q); + self.add(&xQ); + } + } + + + /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + + pub fn mul4(Q: &[ECP2], u: &[BIG]) -> ECP2 { + let mut W = ECP2::new(); + let mut P = ECP2::new(); + + let mut T: [ECP2; 8] = [ + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ]; + + let mut mt = BIG::new(); + + let mut t: [BIG; 4] = [ + BIG::new_copy(&u[0]), + BIG::new_copy(&u[1]), + BIG::new_copy(&u[2]), + BIG::new_copy(&u[3]), + ]; + + const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); + let mut w: [i8; CT] = [0; CT]; + let mut s: [i8; CT] = [0; CT]; + + for i in 0..4 { + t[i].norm(); + } + + T[0].copy(&Q[0]); + W.copy(&T[0]); + T[1].copy(&W); + T[1].add(&Q[1]); // Q[0]+Q[1] + T[2].copy(&W); + T[2].add(&Q[2]); + W.copy(&T[1]); // Q[0]+Q[2] + T[3].copy(&W); + T[3].add(&Q[2]); + W.copy(&T[0]); // Q[0]+Q[1]+Q[2] + T[4].copy(&W); + T[4].add(&Q[3]); + W.copy(&T[1]); // Q[0]+Q[3] + T[5].copy(&W); + T[5].add(&Q[3]); + W.copy(&T[2]); // Q[0]+Q[1]+Q[3] + T[6].copy(&W); + T[6].add(&Q[3]); + W.copy(&T[3]); // Q[0]+Q[2]+Q[3] + T[7].copy(&W); + T[7].add(&Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] + + // Make it odd + let pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for i in 0..4 { + mt.or(&t[i]); + } + + let nb = 1 + mt.nbits(); + + // Sign pivot + + s[nb - 1] = 1; + for i in 0..nb - 1 { + t[0].fshr(1); + s[i] = (2 * t[0].parity() - 1) as i8; + } + + // Recoded exponent + for i in 0..nb { + w[i] = 0; + let mut k = 1; + for j in 1..4 { + let bt = s[i] * (t[j].parity() as i8); + t[j].fshr(1); + t[j].dec((bt >> 1) as isize); + t[j].norm(); + w[i] += bt * (k as i8); + k *= 2; + } + } + + // Main loop + P.selector(&T, (2 * w[nb - 1] + 1) as i32); + for i in (0..nb - 1).rev() { + P.dbl(); + W.selector(&T, (2 * w[i] + s[i]) as i32); + P.add(&W); + } + + // apply correction + W.copy(&P); + W.sub(&Q[0]); + P.cmove(&W, pb); + + P + } + +/* Hunt and Peck a BIG to a curve point */ + #[allow(non_snake_case)] + pub fn hap2point(h: &BIG) -> ECP2 { + let mut Q: ECP2; + let one = BIG::new_int(1); + let mut x =BIG::new_copy(&h); + loop { + let X = FP2::new_bigs(&one, &x); + Q = ECP2::new_fp2(&X,0); + if !Q.is_infinity() { + break; + } + x.inc(1); + x.norm(); + } + Q + } + +/* Constant time Map to Point */ + #[allow(unreachable_code)] + #[allow(non_snake_case)] + pub fn map2point(H: &FP2) -> ECP2 { + let mut T=FP2::new_copy(H); /**/ + let sgn=T.sign(); /**/ + if ecp::HTC_ISO_G2 == 0 { + // Shallue and van de Woestijne +/* */ + let mut NY=FP2::new_int(1); + let mut Z=FP::new_int(fp::RIADZG2A); + let mut X1=FP2::new_fp(&Z); + let mut X3=FP2::new_copy(&X1); + let mut A=ECP2::rhs(&X1); + let mut W=FP2::new_copy(&A); + + if fp::RIADZG2A==-1 && fp::RIADZG2B==0 && ecp::SEXTIC_TWIST == ecp::M_TYPE && rom::CURVE_B_I==4 { + W.copy(&FP2::new_ints(2,1)); + } else { + W.sqrt(None); + } + let s = FP::new_big(&BIG::new_ints(&rom::SQRTM3)); + Z.mul(&s); + + T.sqr(); + let mut Y=FP2::new_copy(&A); Y.mul(&T); + T.copy(&NY); T.add(&Y); T.norm(); + Y.rsub(&NY); Y.norm(); + NY.copy(&T); NY.mul(&Y); + + NY.pmul(&Z); + NY.inverse(None); + + W.pmul(&Z); + if W.sign()==1 { + W.neg(); + W.norm(); + } + W.pmul(&Z); + W.mul(&H); W.mul(&Y); W.mul(&NY); + + X1.neg(); X1.norm(); X1.div2(); + let mut X2=FP2::new_copy(&X1); + X1.sub(&W); X1.norm(); + X2.add(&W); X2.norm(); + A.dbl(); A.dbl(); A.norm(); + T.sqr(); T.mul(&NY); T.sqr(); + A.mul(&T); + X3.add(&A); X3.norm(); + + Y.copy(&ECP2::rhs(&X2)); + X3.cmove(&X2,Y.qr(None)); + Y.copy(&ECP2::rhs(&X1)); + X3.cmove(&X1,Y.qr(None)); + Y.copy(&ECP2::rhs(&X3)); + Y.sqrt(None); + + let ne=Y.sign()^sgn; + W.copy(&Y); W.neg(); W.norm(); + Y.cmove(&W,ne); + + return ECP2::new_fp2s(&X3,&Y); +/* */ + } else { +/* CAHCZS + let NY=FP2::new_int(1); + let Ad=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_ADR),&BIG::new_ints(&rom::CURVE_ADI)); + let Bd=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_BDR),&BIG::new_ints(&rom::CURVE_BDI)); + let ZZ=FP2::new_ints(fp::RIADZG2A,fp::RIADZG2B); + let mut hint=FP::new(); + + T.sqr(); + T.mul(&ZZ); + let mut W=FP2::new_copy(&T); + W.add(&NY); W.norm(); + + W.mul(&T); + let mut D=FP2::new_copy(&Ad); + D.mul(&W); + + W.add(&NY); W.norm(); + W.mul(&Bd); + W.neg(); W.norm(); + + let mut X2=FP2::new_copy(&W); + let mut X3=FP2::new_copy(&T); + X3.mul(&X2); + + let mut GX1=FP2::new_copy(&X2); GX1.sqr(); + let mut D2=FP2::new_copy(&D); D2.sqr(); + + W.copy(&Ad); W.mul(&D2); GX1.add(&W); GX1.norm(); GX1.mul(&X2); D2.mul(&D); W.copy(&Bd); W.mul(&D2); GX1.add(&W); GX1.norm(); // x^3+Ax+b + + W.copy(&GX1); W.mul(&D); + let qr=W.qr(Some(&mut hint)); + D.copy(&W); D.inverse(Some(&hint)); + D.mul(&GX1); + X2.mul(&D); + X3.mul(&D); + T.mul(&H); + D2.copy(&D); D2.sqr(); + + D.copy(&D2); D.mul(&T); + T.copy(&W); T.mul(&ZZ); + + let mut s=FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC2)); + s.mul(&hint); + + X2.cmove(&X3,1-qr); + W.cmove(&T,1-qr); + D2.cmove(&D,1-qr); + hint.cmove(&s,1-qr); + + let mut Y=FP2::new_copy(&W); Y.sqrt(Some(&hint)); + Y.mul(&D2); + + let ne=Y.sign()^sgn; + W.copy(&Y); W.neg(); W.norm(); + Y.cmove(&W,ne); + + let mut k=0; + let isox=ecp::HTC_ISO_G2; + let isoy=3*(isox-1)/2; + + // xnum + let mut xnum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; + for _ in 0..isox { + xnum.mul(&X2); + xnum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xnum.norm(); + } + //xden + let mut xden=FP2::new_copy(&X2); + xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xden.norm(); + for _ in 0..isox-2 { + xden.mul(&X2); + xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xden.norm(); + } + //ynum + let mut ynum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; + for _ in 0..isoy { + ynum.mul(&X2); + ynum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + ynum.norm(); + } + //yden + let mut yden=FP2::new_copy(&X2); + yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + yden.norm(); + for _ in 0..isoy-1 { + yden.mul(&X2); + yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + yden.norm(); + } + ynum.mul(&Y); + + let mut Q=ECP2::new(); + T.copy(&xnum); T.mul(&yden); + Q.x.copy(&T); + T.copy(&ynum); T.mul(&xden); + Q.y.copy(&T); + T.copy(&xden); T.mul(&yden); + Q.z.copy(&T); + return Q; +CAHCZF */ + + } + ECP2::new() + } + +/* Map byte string to curve point */ + #[allow(non_snake_case)] + pub fn mapit(h: &[u8]) -> ECP2 { + let q = BIG::new_ints(&rom::MODULUS); + let mut dx = DBIG::frombytes(h); + let x=dx.dmod(&q); + let mut P=ECP2::hap2point(&x); + P.cfp(); + P + } + + pub fn generator() -> ECP2 { + ECP2::new_fp2s( + &FP2::new_bigs( + &BIG::new_ints(&rom::CURVE_PXA), + &BIG::new_ints(&rom::CURVE_PXB), + ), + &FP2::new_bigs( + &BIG::new_ints(&rom::CURVE_PYA), + &BIG::new_ints(&rom::CURVE_PYB), + ), + ) + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/eddsa.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/eddsa.rs new file mode 100644 index 000000000000..202c88672ebc --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/eddsa.rs @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ECDH/ECIES/ECDSA API Functions */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::rom; +use crate::rand::RAND; +use crate::hash512::HASH512; +use crate::sha3; +use crate::sha3::SHA3; + +pub const INVALID_PUBLIC_KEY: isize = -2; +pub const ERROR: isize = -3; +//pub const INVALID: isize = -4; +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; + +fn rfc7748(r: &mut BIG) { + let mut lg=0; + let mut t=BIG::new_int(1); + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let n=(8*EGS-lg+1) as usize; + r.mod2m(n); + t.shl(n); + r.add(&t); + c=r.lastbits(lg as usize); + r.dec(c); +} + +// reverse first n bytes of buff - for little endian +fn reverse(n: usize,buff: &mut [u8]) { + for i in 0..n/2 { + let ch = buff[i]; + buff[i] = buff[n - i - 1]; + buff[n - i - 1] = ch; + } +} + +// dom - domain function +fn dom(ds: &str,ph: bool,cl: usize,domain: &mut [u8]) -> usize { + let dsb = ds.as_bytes(); + let n=dsb.len(); + for i in 0..n { + domain[i]=dsb[i]; + } + if ph { + domain[n]=1; + } else { + domain[n]=0; + } + domain[n+1]=cl as u8; + return n+2; +} + +fn h(s: &[u8],digest: &mut [u8]) -> usize { + if ecp::AESKEY<=16 { // for ed25519? + let mut sh=HASH512::new(); + for i in 0..s.len() { + sh.process(s[i]); + } + let hs = sh.hash(); + for i in 0..64 { + digest[i]=hs[i]; + } + return 64; + } else { // for ed448? + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..s.len() { + sh.process(s[i]); + } + sh.shake(digest,2*s.len()); + return 2*s.len(); + } +} + +fn h2(ph: bool,ctx: Option<&[u8]>,r: &[u8],q: &[u8],m: &[u8]) -> DBIG { + let b=q.len(); + let mut cl=0; + if let Some(sctx) = ctx { + cl=sctx.len(); + } + let mut domain: [u8; 64] = [0; 64]; + if ecp::AESKEY<=16 { // Ed25519?? + let mut sh=HASH512::new(); + if ph || cl>0 { // if not prehash and no context, omit dom2() + let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + } + for i in 0..b { + sh.process(r[i]); + } + for i in 0..b { + sh.process(q[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + let mut h=sh.hash(); + reverse(64,&mut h); + return DBIG::frombytes(&h); + } else { // for ed448? + let dl=dom("Sigbn254",ph,cl,&mut domain); + let mut h: [u8; 128] = [0; 128]; + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + for i in 0..b { + sh.process(r[i]); + } + for i in 0..b { + sh.process(q[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + + sh.shake(&mut h,2*b); + reverse(2*b,&mut h[0..2*b]); + return DBIG::frombytes(&h[0..2*b]); + } +} + +fn getr(ph: bool,b: usize,digest: &[u8],ctx: Option<&[u8]>,m: &[u8]) -> DBIG { + let mut cl=0; + if let Some(sctx) = ctx { + cl=sctx.len(); + } + let mut domain: [u8; 64] = [0; 64]; + + if ecp::AESKEY<=16 { // Ed25519?? + let mut sh=HASH512::new(); + if ph || cl>0 { // if not prehash and no context, omit dom2() + let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + } + for i in b..2*b { + sh.process(digest[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + let mut h=sh.hash(); + reverse(64,&mut h); + return DBIG::frombytes(&h); + } else { // for ed448? + let dl=dom("Sigbn254",ph,cl,&mut domain); + let mut h: [u8; 128] = [0; 128]; + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + for i in b..2*b { + sh.process(digest[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + sh.shake(&mut h,2*b); + reverse(2*b,&mut h[0..2*b]); + return DBIG::frombytes(&h[0..2*b]); + } +} + +// encode integer (little endian) +fn encode_int(x: &BIG,w: &mut [u8]) -> usize { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + w[0]=0; + x.tobytearray(w,index); + reverse(b,w); + return b; +} + +// encode point + #[allow(non_snake_case)] +fn encode(P: &ECP,w: &mut [u8]) { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let x=P.getx(); + let y=P.gety(); + encode_int(&y,w); + w[b-1]|=(x.parity()<<7) as u8; +} + +// get sign +fn getsign(x: &[u8]) -> isize{ + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + if (x[b-1]&0x80)!=0 { + return 1; + } else { + return 0; + } +} + +// decode integer (little endian) +fn decode_int(strip_sign: bool,ei: &[u8]) -> BIG { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let mut r: [u8; EFS+1] = [0; EFS+1]; + + for i in 0..b { + r[i]=ei[i]; + } + reverse(b,&mut r); + + if strip_sign { + r[0]&=0x7f; + } + return BIG::frombytearray(&r,index); +} + +// decode compressed point +fn decode(w: &[u8]) -> ECP { + let sign=getsign(w); // lsb of x + let y=decode_int(true,w); + let one = FP::new_int(1); + let mut hint=FP::new(); + let mut x=FP::new_big(&y); x.sqr(); + let mut d=FP::new_copy(&x); + x.sub(&one); + x.norm(); + let mut t = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + d.mul(&t); + if ecp::CURVE_A==1 { + d.sub(&one); + } + if ecp::CURVE_A==-1 { + d.add(&one); + } + d.norm(); +// inverse square root trick for sqrt(x/d) + t.copy(&x); + t.sqr(); + x.mul(&t); + x.mul(&d); + if x.qr(Some(&mut hint))!=1 { + return ECP::new(); + } + d.copy(&x.sqrt(Some(&hint))); + x.inverse(Some(&hint)); + x.mul(&d); + x.mul(&t); + x.reduce(); + if x.redc().parity()!=sign { + x.neg(); + } + x.norm(); + return ECP::new_bigs(&x.redc(),&y); +} + +#[allow(non_snake_case)] +fn key_pair_regenerate(d: &[u8], q: &mut [u8]) { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let mut G=ECP::generator(); + + let mut digest: [u8; 128] = [0; 128]; + h(d,&mut digest); + +// reverse bytes for little endian + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + G.copy(&G.mul(&s)); + encode(&G,q); +} + +/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), + * where s is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in s + * otherwise it is generated randomly internally */ +#[allow(non_snake_case)] +pub fn key_pair_generate(rng: Option<&mut RAND>, d: &mut [u8], q: &mut [u8]) -> isize { + let res = 0; + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let mut G=ECP::generator(); + + if let Some(srng) = rng { + for i in 0..b { + d[i]=srng.getbyte(); + } + } + let mut digest: [u8; 128] = [0; 128]; + h(d,&mut digest); + +// reverse bytes for little endian + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + G.copy(&G.mul(&s)); + encode(&G,q); + return res; +} + +// Generate a signature using key pair (d,q) on message m +// Set ph=true if message has already been pre-hashed +// if ph=false, then context should be NULL for ed25519. However RFC8032 mode ed25519ctx is supported by supplying a non-NULL or non-empty context +#[allow(non_snake_case)] +pub fn signature(ph: bool,d: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &mut [u8]) ->isize { + let mut digest: [u8; 128] = [0; 128]; + let mut q: [u8; EFS+1] = [0; EFS+1]; // public key + h(d,&mut digest); // hash of private key + let mut res = 0; + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let r = BIG::new_ints(&rom::CURVE_ORDER); + + key_pair_regenerate(d,&mut q); + let qs=&q[0..b]; + + if d.len()!=qs.len() || d.len()!=b { + res=INVALID_PUBLIC_KEY; + } + if res==0 { + let mut dr=getr(ph,b,&digest,ctx,m); + let sr=dr.dmod(&r); + let R=ECP::generator().mul(&sr); + encode(&R,&mut sig[0..b]); + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + dr=h2(ph,ctx,sig,&qs,m); + let sd=dr.dmod(&r); + encode_int(&BIG::modadd(&sr,&BIG::modmul(&s,&sd,&r),&r),&mut sig[b..2*b]); + } + return res; +} + +// verify a signature using public key q +// same context (if any) as used for signature +#[allow(non_snake_case)] +pub fn verify(ph: bool, q: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &[u8]) ->bool { + + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let mut lg=0; + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let r = BIG::new_ints(&rom::CURVE_ORDER); + let mut R=decode(&sig[0..b]); + + if R.is_infinity() { + return false; + } + + let t=decode_int(false,&sig[b..2*b]); + + if BIG::comp(&t,&r)>=0 { + return false; + } + let mut du=h2(ph,ctx,&sig,q,m); + let su=du.dmod(&r); + + let mut G=ECP::generator(); + let mut QD=decode(&q); + if QD.is_infinity() { + return false; + } + QD.neg(); + for _ in 0..lg { // use cofactor 2^c + G.dbl(); QD.dbl(); R.dbl(); + } + + if !G.mul2(&t,&QD,&su).equals(&R) { + return false; + } + return true; +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp.rs new file mode 100644 index 000000000000..17caff2ed023 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp.rs @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::arch; +use crate::arch::Chunk; +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::rom; + +use crate::rand::RAND; + +#[derive(Copy, Clone)] +pub struct FP { + pub x: BIG, + pub xes: i32, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +pub const NOT_SPECIAL: usize = 0; +pub const PSEUDO_MERSENNE: usize = 1; +pub const MONTGOMERY_FRIENDLY: usize = 2; +pub const GENERALISED_MERSENNE: usize = 3; + +pub const NEGATOWER: usize = 0; +pub const POSITOWER: usize = 1; + +pub const MODBITS:usize = 254; /* Number of bits in Modulus */ +pub const PM1D2: usize = 1; /* Modulus mod 8 */ +pub const RIADZ: isize = -1; /* Z for hash-to-point */ +pub const RIADZG2A: isize = -1; /* G2 Z for hash-to-point */ +pub const RIADZG2B: isize = 0; /* G2 Z for hash-to-point */ +pub const MODTYPE:usize=NOT_SPECIAL; +pub const QNRI:usize=0; /* Fp2 QNR 2^i+sqrt(-1) */ +pub const TOWER:usize=NEGATOWER; /* Tower type */ + +pub const FEXCESS:i32 = ((1 as i32)<<26)-1; +pub const OMASK: Chunk = (-1) << (MODBITS % big::BASEBITS); +pub const TBITS: usize = MODBITS % big::BASEBITS; // Number of active bits in top word +pub const TMASK: Chunk = (1 << TBITS) - 1; + +pub const BIG_ENDIAN_SIGN: bool = false; + +impl FP { + /* Constructors */ + pub const fn new() -> FP { + FP { + x: BIG::new(), + xes: 1, + } + } + + pub fn new_int(a: isize) -> FP { + let mut f = FP::new(); + if a<0 { + let mut m = BIG::new_ints(&rom::MODULUS); + m.inc(a); m.norm(); + f.x.copy(&m); + } else { + f.x.inc(a); + } + f.nres(); + f + } + + pub fn new_copy(y: &FP) -> FP { + let mut f = FP::new(); + f.x.copy(&(y.x)); + f.xes = y.xes; + f + } + + pub fn new_big(y: &BIG) -> FP { + let mut f = FP::new(); + f.x.copy(y); + f.nres(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP { + let m = BIG::new_ints(&rom::MODULUS); + let w = BIG::randomnum(&m,rng); + FP::new_big(&w) + } + + pub fn nres(&mut self) { + if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { + let r = BIG::new_ints(&rom::R2MODP); + let mut d = BIG::mul(&(self.x), &r); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2; + } else { + let m = BIG::new_ints(&rom::MODULUS); + self.x.rmod(&m); + self.xes = 1; + } + } + + /* convert back to regular form */ + pub fn redc(&self) -> BIG { + if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { + let mut d = DBIG::new_scopy(&(self.x)); + FP::modulo(&mut d) + } else { + BIG::new_copy(&(self.x)) + } + } + + /* reduce a DBIG to a BIG using the appropriate form of the modulus */ + /* dd */ + pub fn modulo(d: &mut DBIG) -> BIG { + if MODTYPE == PSEUDO_MERSENNE { + let mut b = BIG::new(); + let mut t = d.split(MODBITS); + b.dcopy(&d); + let v = t.pmul(rom::MCONST as isize); + + t.add(&b); + t.norm(); + + let tw = t.w[big::NLEN - 1]; + t.w[big::NLEN - 1] &= TMASK; + t.w[0] += rom::MCONST * ((tw >> TBITS) + (v << (big::BASEBITS - TBITS))); + t.norm(); + return t; + } + + if MODTYPE == MONTGOMERY_FRIENDLY { + let mut b = BIG::new(); + for i in 0..big::NLEN { + let x = d.w[i]; + + let tuple = BIG::muladd(x, rom::MCONST - 1, x, d.w[big::NLEN + i - 1]); + d.w[big::NLEN + i] += tuple.0; + d.w[big::NLEN + i - 1] = tuple.1; + } + + b.zero(); + + for i in 0..big::NLEN { + b.w[i] = d.w[big::NLEN + i]; + } + b.norm(); + return b; + } + + if MODTYPE == GENERALISED_MERSENNE { + // GoldiLocks Only + let mut b = BIG::new(); + let t = d.split(MODBITS); + let rm2 = (MODBITS / 2) as usize; + b.dcopy(&d); + b.add(&t); + let mut dd = DBIG::new_scopy(&t); + dd.shl(rm2); + + let mut tt = dd.split(MODBITS); + let lo = BIG::new_dcopy(&dd); + b.add(&tt); + b.add(&lo); + b.norm(); + tt.shl(rm2); + b.add(&tt); + + let carry = b.w[big::NLEN - 1] >> TBITS; + b.w[big::NLEN - 1] &= TMASK; + b.w[0] += carry; + + let ix=(224 / big::BASEBITS) as usize; + b.w[ix] += carry << (224 % big::BASEBITS); + b.norm(); + return b; + } + + if MODTYPE == NOT_SPECIAL { + let m = BIG::new_ints(&rom::MODULUS); + return BIG::monty(&m, rom::MCONST, d); + } + BIG::new() + } + + /* convert to string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + self.redc().tostring() + } + + /* reduce this mod Modulus */ + pub fn reduce(&mut self) { + let mut m = BIG::new_ints(&rom::MODULUS); + let mut r = BIG::new_copy(&m); + let mut sb: usize; + self.x.norm(); + if self.xes > 16 { + let q = FP::quo(&self.x, &m); + let carry = r.pmul(q); + r.w[big::NLEN - 1] += carry << big::BASEBITS; // correction - put any carry out back in again + self.x.sub(&r); + self.x.norm(); + sb = 2; + } else { + sb = FP::logb2((self.xes - 1) as u32); + } + m.fshl(sb); + + while sb > 0 { + let sr = BIG::ssn(&mut r, &self.x, &mut m); + self.x.cmove(&r, 1 - sr); + sb -= 1; + } + + self.xes = 1; + } + + /* test this=0? */ + pub fn iszilch(&self) -> bool { + let mut a = FP::new_copy(self); + a.reduce(); + a.x.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + return 0; + } + let mut sx = BIG::new_ints(&rom::MODULUS); + let fx=self.redc(); + sx.sub(&fx); sx.norm(); + BIG::comp(&fx,&sx) + } + + pub fn tobytes(&self,b: &mut [u8]) { + self.redc().tobytes(b) + } + + pub fn frombytes(b: &[u8]) -> FP { + let t=BIG::frombytes(b); + FP::new_big(&t) + } + + /* test this=0? */ + pub fn isunity(&self) -> bool { + let mut a = FP::new_copy(self); + a.reduce(); + a.redc().isunity() + } + + pub fn sign(&self) -> isize { + if BIG_ENDIAN_SIGN { + let mut m = BIG::new_ints(&rom::MODULUS); + m.dec(1); + m.fshr(1); + let mut n = FP::new_copy(self); + n.reduce(); + let w=n.redc(); + let cp=BIG::comp(&w,&m); + ((cp+1)&2)>>1 + } else { + let mut a = FP::new_copy(self); + a.reduce(); + a.redc().parity() + } + } + + /* copy from FP b */ + pub fn copy(&mut self, b: &FP) { + self.x.copy(&(b.x)); + self.xes = b.xes; + } + + /* copy from BIG b */ + pub fn bcopy(&mut self, b: &BIG) { + self.x.copy(&b); + self.nres(); + } + + /* set this=0 */ + pub fn zero(&mut self) { + self.x.zero(); + self.xes = 1; + } + + /* set this=1 */ + pub fn one(&mut self) { + self.x.one(); + self.nres() + } + + /* normalise this */ + pub fn norm(&mut self) { + self.x.norm(); + } + + /* swap FPs depending on d */ + pub fn cswap(&mut self, b: &mut FP, d: isize) { + self.x.cswap(&mut (b.x), d); + let mut c = d as i32; + c = !(c - 1); + let t = c & (self.xes ^ b.xes); + self.xes ^= t; + b.xes ^= t; + } + + /* copy FPs depending on d */ + pub fn cmove(&mut self, b: &FP, d: isize) { + self.x.cmove(&(b.x), d); + let c = d as i32; + self.xes ^= (self.xes ^ b.xes) & (-c); + } + + /* this*=b mod Modulus */ + pub fn mul(&mut self, b: &FP) { + if (self.xes as i64) * (b.xes as i64) > FEXCESS as i64 { + self.reduce() + } + + let mut d = BIG::mul(&(self.x), &(b.x)); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2; + } + + fn logb2(w: u32) -> usize { + let mut v = w; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + ((((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize + } + + // find appoximation to quotient of a/m + // Out by at most 2. + // Note that MAXXES is bounded to be 2-bits less than half a word + fn quo(n: &BIG, m: &BIG) -> isize { + let hb = arch::CHUNK / 2; + + if TBITS < hb { + let sh = hb - TBITS; + let num = (n.w[big::NLEN - 1] << sh) | (n.w[big::NLEN - 2] >> (big::BASEBITS - sh)); + let den = (m.w[big::NLEN - 1] << sh) | (m.w[big::NLEN - 2] >> (big::BASEBITS - sh)); + (num / (den + 1)) as isize + } else { + let num = n.w[big::NLEN - 1]; + let den = m.w[big::NLEN - 1]; + (num / (den + 1)) as isize + } + } + + /* this = -this mod Modulus */ + pub fn neg(&mut self) { + let mut p = BIG::new_ints(&rom::MODULUS); + let sb = FP::logb2((self.xes - 1) as u32); + + p.fshl(sb); + self.x.rsub(&p); + self.xes = 1 << ((sb as i32) + 1); + if self.xes > FEXCESS { + self.reduce() + } + } + + /* this*=c mod Modulus, where c is a small int */ + pub fn imul(&mut self, c: isize) { + let mut cc = c; + let mut s = false; + if cc < 0 { + cc = -cc; + s = true; + } + + if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { + let mut d = self.x.pxmul(cc); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2 + } else if self.xes * (cc as i32) <= FEXCESS { + self.x.pmul(cc); + self.xes *= cc as i32; + } else { + let n = FP::new_int(cc); + self.mul(&n); + } + + if s { + self.neg(); + self.norm(); + } + } + + /* self*=self mod Modulus */ + pub fn sqr(&mut self) { + if (self.xes as i64) * (self.xes as i64) > FEXCESS as i64 { + self.reduce() + } + + let mut d = BIG::sqr(&(self.x)); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2 + } + + /* self+=b */ + pub fn add(&mut self, b: &FP) { + self.x.add(&(b.x)); + self.xes += b.xes; + if self.xes > FEXCESS { + self.reduce() + } + } + + /* self+=self */ + pub fn dbl(&mut self) { + self.x.dbl(); + self.xes += self.xes; + if self.xes > FEXCESS { + self.reduce() + } + } + + /* self-=b */ + pub fn sub(&mut self, b: &FP) { + let mut n = FP::new_copy(b); + n.neg(); + self.add(&n); + } + + /* self=b-self */ + pub fn rsub(&mut self, b: &FP) { + self.neg(); + self.add(&b); + } + + /* self/=2 mod Modulus */ + pub fn div2(&mut self) { + let p = BIG::new_ints(&rom::MODULUS); + let pr = self.x.parity(); + let mut w = BIG::new_copy(&self.x); + self.x.fshr(1); + w.add(&p); w.norm(); + w.fshr(1); + self.x.cmove(&w,pr); + } + /* return jacobi symbol (this/Modulus) */ + pub fn jacobi(&mut self) -> isize { + let p = BIG::new_ints(&rom::MODULUS); + let mut w = self.redc(); + w.jacobi(&p) + } + /* return TRUE if self==a */ + pub fn equals(&self, a: &FP) -> bool { + let mut f = FP::new_copy(self); + let mut s = FP::new_copy(a); + f.reduce(); + s.reduce(); + BIG::comp(&(f.x), &(s.x)) == 0 + } + + /* return self^e mod Modulus */ + // Could leak size of e + // but not used here with secret exponent e + pub fn pow(&self, e: &BIG) -> FP { + let mut tb: [FP; 16] = [ + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + ]; + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + let mut s = FP::new_copy(&self); + s.norm(); + let mut t = BIG::new_copy(e); + t.norm(); + let nb = 1 + (t.nbits() + 3) / 4; + + for i in 0..nb { + let lsbs = t.lastbits(4); + t.dec(lsbs); + t.norm(); + w[i] = lsbs as i8; + t.fshr(4); + } + tb[0].one(); + tb[1].copy(&s); + + let mut c = FP::new(); + for i in 2..16 { + c.copy(&tb[i - 1]); + tb[i].copy(&c); + tb[i].mul(&s); + } + let mut r = FP::new_copy(&tb[w[nb - 1] as usize]); + for i in (0..nb - 1).rev() { + r.sqr(); + r.sqr(); + r.sqr(); + r.sqr(); + r.mul(&tb[w[i] as usize]) + } + r.reduce(); + r + } + + // See eprint paper https://eprint.iacr.org/2018/1038 + // return this^(p-3)/4 or this^(p-5)/8 + pub fn fpow(&self) -> FP { + let ac: [isize; 11] = [1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255]; + let mut xp: [FP; 11] = [ + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + ]; + // phase 1 + let mut t = FP::new(); + xp[0].copy(&self); // 1 + xp[1].copy(&self); + xp[1].sqr(); // 2 + t.copy(&xp[1]); + xp[2].copy(&t); + xp[2].mul(&self); // 3 + t.copy(&xp[2]); + xp[3].copy(&t); + xp[3].sqr(); // 6 + t.copy(&xp[3]); + xp[4].copy(&t); + xp[4].sqr(); // 12 + t.copy(&xp[4]); + t.mul(&xp[2]); + xp[5].copy(&t); // 15 + t.copy(&xp[5]); + xp[6].copy(&t); + xp[6].sqr(); // 30 + t.copy(&xp[6]); + xp[7].copy(&t); + xp[7].sqr(); // 60 + t.copy(&xp[7]); + xp[8].copy(&t); + xp[8].sqr(); // 120 + t.copy(&xp[8]); + xp[9].copy(&t); + xp[9].sqr(); // 240 + t.copy(&xp[9]); + t.mul(&xp[5]); + xp[10].copy(&t); // 255 + + let mut n = MODBITS as isize; + let mut c: isize; + + if MODTYPE == GENERALISED_MERSENNE { + // Goldilocks ONLY + n /= 2; + } + + let e = PM1D2 as isize; + + n-=e+1; + c=((rom::MCONST as isize)+(1< k { + i -= 1; + } + key.copy(&xp[i]); + k -= ac[i]; + } + while k != 0 { + i -= 1; + if ac[i] > k { + continue; + } + key.mul(&xp[i]); + k -= ac[i]; + } + // phase 2 + t.copy(&xp[2]); + xp[1].copy(&t); + t.copy(&xp[5]); + xp[2].copy(&t); + t.copy(&xp[10]); + xp[3].copy(&t); + + let mut j = 3; + let mut m = 8; + let nw = n - bw; + let mut r = FP::new(); + + while 2 * m < nw { + t.copy(&xp[j]); + j += 1; + for _ in 0..m { + t.sqr(); + } + r.copy(&xp[j - 1]); + r.mul(&t); + xp[j].copy(&r); + m *= 2; + } + let mut lo = nw - m; + r.copy(&xp[j]); + + while lo != 0 { + m /= 2; + j -= 1; + if lo < m { + continue; + } + lo -= m; + t.copy(&r); + for _ in 0..m { + t.sqr(); + } + r.copy(&t); + r.mul(&xp[j]); + } + // phase 3 + if bw != 0 { + for _ in 0..bw { + r.sqr(); + } + r.mul(&key); + } + if MODTYPE == GENERALISED_MERSENNE { + // Goldilocks ONLY + key.copy(&r); + r.sqr(); + r.mul(&self); + for _ in 0..n + 1 { + r.sqr(); + } + r.mul(&key); + } + while nd>0 { + r.sqr(); + nd-=1; + } + r + } + + /* Pseudo_inverse square root */ + pub fn progen(&mut self) { + if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { + self.copy(&self.fpow()); + return; + } + let e=PM1D2 as usize; + let mut m = BIG::new_ints(&rom::MODULUS); + m.dec(1); + m.shr(e); + m.dec(1); + m.fshr(1); + + self.copy(&self.pow(&m)); + } + + /* self=1/self mod Modulus */ + pub fn inverse(&mut self,take_hint: Option<&FP>) { + let e=PM1D2 as isize; + self.norm(); + let mut s=FP::new_copy(self); + for _ in 0..e-1 { + s.sqr(); + s.mul(self); + } + if let Some(hint) = take_hint { + self.copy(&hint); + } else { + self.progen(); + } + for _ in 0..=e { + self.sqr(); + } + self.mul(&s); + self.reduce(); + } + + /* Test for Quadratic Residue */ + pub fn qr(&self,give_hint: Option<&mut FP>) -> isize { + let e=PM1D2 as isize; + let mut r=FP::new_copy(self); + r.progen(); + if let Some(hint) = give_hint { + hint.copy(&r); + } + + r.sqr(); + r.mul(self); + for _ in 0..e-1 { + r.sqr(); + } + + r.isunity() as isize + } + + pub fn invsqrt(&self,i: &mut FP,s: &mut FP) -> isize { + let mut h=FP::new(); + let qr=self.qr(Some(&mut h)); + s.copy(&self.sqrt(Some(&h))); + i.copy(self); + i.inverse(Some(&h)); + qr + } + +// Two for the price of One - See Hamburg https://eprint.iacr.org/2012/309.pdf +// Calculate inverse of i and square root of s, return QR + pub fn tpo(mut i: &mut FP,mut s: &mut FP) -> isize { + let mut w = FP::new_copy(s); + let mut t = FP::new_copy(i); + w.mul(&i); + t.mul(&w); + let qr=t.invsqrt(&mut i,&mut s); + i.mul(&w); + s.mul(&i); + qr + } + + /* return sqrt(this) mod Modulus */ + pub fn sqrt(&self,take_hint: Option<&FP>) -> FP { + let e=PM1D2 as isize; + let mut g=FP::new_copy(self); + + if let Some(hint) = take_hint { + g.copy(&hint); + } else { + g.progen(); + } + let m = BIG::new_ints(&rom::ROI); + let mut v=FP::new_big(&m); + let mut t=FP::new_copy(&g); + t.sqr(); + t.mul(self); + + let mut r=FP::new_copy(self); + r.mul(&g); + let mut b=FP::new_copy(&t); + + for k in (2..=e).rev() //(int k=e;k>1;k--) + { + for _ in 1..k-1 { + b.sqr(); + } + let u=!b.isunity() as isize; + g.copy(&r); g.mul(&v); + r.cmove(&g,u); + v.sqr(); + g.copy(&t); g.mul(&v); + t.cmove(&g,u); + b.copy(&t); + } + let sgn=r.sign(); + let mut nr=FP::new_copy(&r); + nr.neg(); nr.norm(); + r.cmove(&nr,sgn); + r + } + +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp12.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp12.rs new file mode 100644 index 000000000000..04df83d8b8a7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp12.rs @@ -0,0 +1,1111 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::fp::FP; +use crate::bn254::fp2::FP2; +use crate::bn254::fp4::FP4; +use crate::bn254::rom; + +pub const ZERO: usize = 0; +pub const ONE: usize = 1; +pub const SPARSEST: usize = 2; +pub const SPARSER: usize = 3; +pub const SPARSE: usize = 4; +pub const DENSE: usize = 5; + +#[derive(Copy, Clone)] +pub struct FP12 { + a: FP4, + b: FP4, + c: FP4, + stype: usize, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP12 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP12 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP12 { + pub fn new() -> FP12 { + FP12 { + a: FP4::new(), + b: FP4::new(), + c: FP4::new(), + stype: ZERO, + } + } + + pub fn settype(&mut self, t: usize) { + self.stype = t; + } + + pub fn gettype(&self) -> usize { + self.stype + } + + pub fn new_int(a: isize) -> FP12 { + let mut f = FP12::new(); + f.a.copy(&FP4::new_int(a)); + f.b.zero(); + f.c.zero(); + if a == 1 { + f.stype = ONE; + } else { + f.stype = SPARSEST; + } + f + } + + pub fn new_copy(x: &FP12) -> FP12 { + let mut f = FP12::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f.c.copy(&x.c); + f.stype = x.stype; + f + } + + pub fn new_fp4s(d: &FP4, e: &FP4, f: &FP4) -> FP12 { + let mut g = FP12::new(); + g.a.copy(d); + g.b.copy(e); + g.c.copy(f); + g.stype = DENSE; + g + } + + pub fn new_fp4(d: &FP4) -> FP12 { + let mut g = FP12::new(); + g.a.copy(d); + g.b.zero(); + g.c.zero(); + g.stype = SPARSEST; + g + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + self.c.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + self.c.norm(); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + //self.reduce(); + self.a.iszilch() && self.b.iszilch() && self.c.iszilch() + } + + /* Conditional move of g to self dependant on d */ + pub fn cmove(&mut self, g: &FP12, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + self.c.cmove(&g.c, d); + let mut u = d as usize; + u = !(u.wrapping_sub(1)); + self.stype ^= (self.stype ^ g.stype) & u; + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* Constant time select from pre-computed table */ + pub fn selector(&mut self, g: &[FP12], b: i32) { + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&g[0], FP12::teq(babs, 0)); // conditional move + self.cmove(&g[1], FP12::teq(babs, 1)); + self.cmove(&g[2], FP12::teq(babs, 2)); + self.cmove(&g[3], FP12::teq(babs, 3)); + self.cmove(&g[4], FP12::teq(babs, 4)); + self.cmove(&g[5], FP12::teq(babs, 5)); + self.cmove(&g[6], FP12::teq(babs, 6)); + self.cmove(&g[7], FP12::teq(babs, 7)); + + let mut invf = FP12::new_copy(self); + invf.conj(); + self.cmove(&invf, (m & 1) as isize); + } + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP4::new_int(1); + self.a.equals(&one) && self.b.iszilch() && self.c.iszilch() + } + + /* test self=x */ + pub fn equals(&self, x: &FP12) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c) + } + + pub fn geta(&mut self) -> FP4 { + self.a + // let f = FP4::new_copy(&self.a); + // return f; + } + + pub fn getb(&mut self) -> FP4 { + self.b + // let f = FP4::new_copy(&self.b); + // return f; + } + + pub fn getc(&mut self) -> FP4 { + self.c + // let f = FP4::new_copy(&self.c); + // return f; + } + + /* copy self=x */ + pub fn copy(&mut self, x: &FP12) { + self.a.copy(&x.a); + self.b.copy(&x.b); + self.c.copy(&x.c); + self.stype = x.stype; + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + self.c.zero(); + self.stype = ONE; + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + self.c.zero(); + self.stype = ZERO; + } + + /* this=conj(this) */ + pub fn conj(&mut self) { + self.a.conj(); + self.b.nconj(); + self.c.conj(); + } + + /* Granger-Scott Unitary Squaring */ + pub fn usqr(&mut self) { + let mut a = FP4::new_copy(&self.a); + let mut b = FP4::new_copy(&self.c); + let mut c = FP4::new_copy(&self.b); + let mut d = FP4::new(); + + self.a.sqr(); + d.copy(&self.a); + d.add(&self.a); + self.a.add(&d); + + self.a.norm(); + a.nconj(); + + a.dbl(); + self.a.add(&a); + b.sqr(); + b.times_i(); + + d.copy(&b); + d.add(&b); + b.add(&d); + b.norm(); + + c.sqr(); + d.copy(&c); + d.add(&c); + c.add(&d); + c.norm(); + + self.b.conj(); + self.b.dbl(); + self.c.nconj(); + + self.c.dbl(); + self.b.add(&b); + self.c.add(&c); + self.stype = DENSE; + self.reduce(); + } + + /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ + pub fn sqr(&mut self) { + if self.stype == ONE { + return; + } + + let mut a = FP4::new_copy(&self.a); + let mut b = FP4::new_copy(&self.b); + let mut c = FP4::new_copy(&self.c); + let mut d = FP4::new_copy(&self.a); + + a.sqr(); + b.mul(&self.c); + b.dbl(); + b.norm(); + c.sqr(); + d.mul(&self.b); + d.dbl(); + + self.c.add(&self.a); + self.c.add(&self.b); + self.c.norm(); + self.c.sqr(); + + self.a.copy(&a); + a.add(&b); + a.norm(); + a.add(&c); + a.add(&d); + a.norm(); + + a.neg(); + b.times_i(); + c.times_i(); + + self.a.add(&b); + + self.b.copy(&c); + self.b.add(&d); + self.c.add(&a); + if self.stype == SPARSER || self.stype == SPARSEST { + self.stype = SPARSE; + } else { + self.stype = DENSE; + } + self.norm(); + } + + /* FP12 full multiplication self=self*y */ + pub fn mul(&mut self, y: &FP12) { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new_copy(&self.b); + let mut z3 = FP4::new(); + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new_copy(&y.a); + + z0.mul(&y.a); + z2.mul(&y.b); + + t0.add(&self.b); + t1.add(&y.b); + + t0.norm(); + t1.norm(); + + z1.copy(&t0); + z1.mul(&t1); + t0.copy(&self.b); + t0.add(&self.c); + t1.copy(&y.b); + t1.add(&y.c); + + t0.norm(); + t1.norm(); + + z3.copy(&t0); + z3.mul(&t1); + + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + z1.add(&t0); + self.b.copy(&z1); + self.b.add(&t1); + + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + t0.mul(&t1); + z2.add(&t0); + + t0.copy(&self.c); + t0.mul(&y.c); + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + self.stype = DENSE; + self.norm(); + } + + /* FP12 full multiplication w=w*y */ + /* Supports sparse multiplicands */ + /* Usually w is denser than y */ + pub fn ssmul(&mut self, y: &FP12) { + if self.stype == ONE { + self.copy(&y); + return; + } + if y.stype == ONE { + return; + } + if y.stype >= SPARSE { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new(); + let mut z3 = FP4::new(); + z0.mul(&y.a); + + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + if y.stype == SPARSE || self.stype == SPARSE { + let mut ga = FP2::new(); + let mut gb = FP2::new(); + + gb.copy(&self.b.getb()); + gb.mul(&y.b.getb()); + ga.zero(); + if y.stype != SPARSE { + ga.copy(&self.b.getb()); + ga.mul(&y.b.geta()); + } + if self.stype != SPARSE { + ga.copy(&self.b.geta()); + ga.mul(&y.b.getb()); + } + z2.set_fp2s(&ga, &gb); + z2.times_i(); + } else { + z2.copy(&self.b); + z2.mul(&y.b); + } + } else { + z2.copy(&self.b); + z2.mul(&y.b); + } + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new_copy(&y.a); + t0.add(&self.b); + t0.norm(); + t1.add(&y.b); + t1.norm(); + + z1.copy(&t0); + z1.mul(&t1); + t0.copy(&self.b); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.b); + t1.add(&y.c); + t1.norm(); + + z3.copy(&t0); + z3.mul(&t1); + + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + z1.add(&t0); + self.b.copy(&z1); + self.b.add(&t1); + + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + + t0.mul(&t1); + z2.add(&t0); + + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + if y.stype == SPARSE || self.stype == SPARSE { + let mut ga = FP2::new(); + let mut gb = FP2::new(); + + ga.copy(&self.c.geta()); + ga.mul(&y.c.geta()); + gb.zero(); + if y.stype != SPARSE { + gb.copy(&self.c.geta()); + gb.mul(&y.c.getb()); + } + if self.stype != SPARSE { + gb.copy(&self.c.getb()); + gb.mul(&y.c.geta()); + } + t0.set_fp2s(&ga, &gb); + } else { + t0.copy(&self.c); + t0.mul(&y.c); + } + } else { + t0.copy(&self.c); + t0.mul(&y.c); + } + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } else { + if self.stype == SPARSER || self.stype == SPARSEST { + self.smul(&y); + return; + } + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + // dense by sparser - 13m + let mut z0 = FP4::new_copy(&self.a); + let mut z2 = FP4::new_copy(&self.b); + let mut z3 = FP4::new_copy(&self.b); + let mut t0 = FP4::new(); + let mut t1 = FP4::new_copy(&y.a); + + z0.mul(&y.a); + if y.stype == SPARSEST { + z2.qmul(&y.b.geta().getA()); + } else { + z2.pmul(&y.b.geta()); + } + self.b.add(&self.a); + t1.padd(&y.b.geta()); + + t1.norm(); + self.b.norm(); + self.b.mul(&t1); + z3.add(&self.c); + z3.norm(); + + if y.stype == SPARSEST { + z3.qmul(&y.b.geta().getA()); + } else { + z3.pmul(&y.b.geta()); + } + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + self.b.add(&t0); + + self.b.add(&t1); + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + z3.norm(); + t0.mul(&y.a); + self.c.copy(&z2); + self.c.add(&t0); + + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new(); + let mut z3 = FP4::new(); + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new(); + + z0.mul(&y.a); + t0.add(&self.b); + t0.norm(); + + z1.copy(&t0); + z1.mul(&y.a); + t0.copy(&self.b); + t0.add(&self.c); + t0.norm(); + + z3.copy(&t0); + if y.stype == SPARSEST { + z3.qmul(&y.c.getb().getA()); + } else { + z3.pmul(&y.c.getb()); + } + z3.times_i(); + + t0.copy(&z0); + t0.neg(); + z1.add(&t0); + self.b.copy(&z1); + z2.copy(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + + t0.mul(&t1); + z2.add(&t0); + t0.copy(&self.c); + + if y.stype == SPARSEST { + t0.qmul(&y.c.getb().getA()); + } else { + t0.pmul(&y.c.getb()); + } + t0.times_i(); + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } + } + self.stype = DENSE; + self.norm(); + } + + /* Special case of multiplication arises from special form of ATE pairing line function */ + pub fn smul(&mut self, y: &FP12) { + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + let mut w1 = FP2::new_copy(&self.a.geta()); + let mut w2 = FP2::new_copy(&self.a.getb()); + //let mut w3=FP2::new_copy(&self.b.geta()); + + let mut w3: FP2; + + w1.mul(&y.a.geta()); + w2.mul(&y.a.getb()); + + if y.stype == SPARSEST || self.stype == SPARSEST { + if y.stype == SPARSEST && self.stype == SPARSEST { + let mut t = FP::new_copy(&self.b.geta().getA()); + t.mul(&y.b.geta().getA()); + w3 = FP2::new_fp(&t); + } else if y.stype != SPARSEST { + w3 = FP2::new_copy(&y.b.geta()); + w3.pmul(&self.b.geta().getA()); + } else { + w3 = FP2::new_copy(&self.b.geta()); + w3.pmul(&y.b.geta().getA()); + } + } else { + w3 = FP2::new_copy(&self.b.geta()); + w3.mul(&y.b.geta()); + } + let mut ta = FP2::new_copy(&self.a.geta()); + let mut tb = FP2::new_copy(&y.a.geta()); + ta.add(&self.a.getb()); + ta.norm(); + tb.add(&y.a.getb()); + tb.norm(); + let mut tc = FP2::new_copy(&ta); + tc.mul(&tb); + let mut t = FP2::new_copy(&w1); + t.add(&w2); + t.neg(); + tc.add(&t); + + ta.copy(&self.a.geta()); + ta.add(&self.b.geta()); + ta.norm(); + tb.copy(&y.a.geta()); + tb.add(&y.b.geta()); + tb.norm(); + let mut td = FP2::new_copy(&ta); + td.mul(&tb); + t.copy(&w1); + t.add(&w3); + t.neg(); + td.add(&t); + + ta.copy(&self.a.getb()); + ta.add(&self.b.geta()); + ta.norm(); + tb.copy(&y.a.getb()); + tb.add(&y.b.geta()); + tb.norm(); + let mut te = FP2::new_copy(&ta); + te.mul(&tb); + t.copy(&w2); + t.add(&w3); + t.neg(); + te.add(&t); + + w2.mul_ip(); + w1.add(&w2); + + self.a.set_fp2s(&w1, &tc); + self.b.set_fp2s(&td, &te); + self.c.set_fp2(&w3); + + self.a.norm(); + self.b.norm(); + } else { + let mut w1 = FP2::new_copy(&self.a.geta()); + let mut w2 = FP2::new_copy(&self.a.getb()); + // let mut w3=FP2::new_copy(&self.c.getb()); + let mut w3: FP2; + + w1.mul(&y.a.geta()); + w2.mul(&y.a.getb()); + + if y.stype == SPARSEST || self.stype == SPARSEST { + if y.stype == SPARSEST && self.stype == SPARSEST { + let mut t = FP::new_copy(&self.c.getb().getA()); + t.mul(&y.c.getb().getA()); + w3 = FP2::new_fp(&t); + } else if y.stype != SPARSEST { + w3 = FP2::new_copy(&y.c.getb()); + w3.pmul(&self.c.getb().getA()); + } else { + w3 = FP2::new_copy(&self.c.getb()); + w3.pmul(&y.c.getb().getA()); + } + } else { + w3 = FP2::new_copy(&self.c.getb()); + w3.mul(&y.c.getb()); + } + let mut ta = FP2::new_copy(&self.a.geta()); + let mut tb = FP2::new_copy(&y.a.geta()); + ta.add(&self.a.getb()); + ta.norm(); + tb.add(&y.a.getb()); + tb.norm(); + let mut tc = FP2::new_copy(&ta); + tc.mul(&tb); + let mut t = FP2::new_copy(&w1); + t.add(&w2); + t.neg(); + tc.add(&t); + + ta.copy(&self.a.geta()); + ta.add(&self.c.getb()); + ta.norm(); + tb.copy(&y.a.geta()); + tb.add(&y.c.getb()); + tb.norm(); + let mut td = FP2::new_copy(&ta); + td.mul(&tb); + t.copy(&w1); + t.add(&w3); + t.neg(); + td.add(&t); + + ta.copy(&self.a.getb()); + ta.add(&self.c.getb()); + ta.norm(); + tb.copy(&y.a.getb()); + tb.add(&y.c.getb()); + tb.norm(); + let mut te = FP2::new_copy(&ta); + te.mul(&tb); + t.copy(&w2); + t.add(&w3); + t.neg(); + te.add(&t); + + w2.mul_ip(); + w1.add(&w2); + self.a.set_fp2s(&w1, &tc); + + w3.mul_ip(); + w3.norm(); + self.b.set_fp2h(&w3); + + te.norm(); + te.mul_ip(); + self.c.set_fp2s(&te, &td); + + self.a.norm(); + self.c.norm(); + } + self.stype = SPARSE; + } + + /* self=1/self */ + pub fn inverse(&mut self) { + let mut f0 = FP4::new_copy(&self.a); + let mut f1 = FP4::new_copy(&self.b); + let mut f2 = FP4::new_copy(&self.a); + let mut f3 = FP4::new(); + + self.norm(); + f0.sqr(); + f1.mul(&self.c); + f1.times_i(); + f0.sub(&f1); + f0.norm(); + + f1.copy(&self.c); + f1.sqr(); + f1.times_i(); + f2.mul(&self.b); + f1.sub(&f2); + f1.norm(); + + f2.copy(&self.b); + f2.sqr(); + f3.copy(&self.a); + f3.mul(&self.c); + f2.sub(&f3); + f2.norm(); + + f3.copy(&self.b); + f3.mul(&f2); + f3.times_i(); + self.a.mul(&f0); + f3.add(&self.a); + self.c.mul(&f1); + self.c.times_i(); + + f3.add(&self.c); + f3.norm(); + f3.inverse(None); + self.a.copy(&f0); + self.a.mul(&f3); + self.b.copy(&f1); + self.b.mul(&f3); + self.c.copy(&f2); + self.c.mul(&f3); + self.stype = DENSE; + } + + /* self=self^p using Frobenius */ + pub fn frob(&mut self, f: &FP2) { + let mut f2 = FP2::new_copy(f); + let mut f3 = FP2::new_copy(f); + + f2.sqr(); + f3.mul(&f2); + + self.a.frob(&f3); + self.b.frob(&f3); + self.c.frob(&f3); + + self.b.pmul(f); + self.c.pmul(&f2); + self.stype = DENSE; + } + + /* trace function */ + pub fn trace(&mut self) -> FP4 { + let mut t = FP4::new(); + t.copy(&self.a); + t.imul(3); + t.reduce(); + t + } + + /* convert from byte array to FP12 */ + pub fn frombytes(w: &[u8]) -> FP12 { + const MB:usize = 4*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=w[i]; + } + let c=FP4::frombytes(&t); + for i in 0..MB { + t[i]=w[i+MB]; + } + let b=FP4::frombytes(&t); + for i in 0..MB { + t[i]=w[i+2*MB]; + } + let a=FP4::frombytes(&t); + FP12::new_fp4s(&a,&b,&c) + } + + /* convert this to byte array */ + pub fn tobytes(&mut self, w: &mut [u8]) { + const MB:usize = 4*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + + self.c.tobytes(&mut t); + for i in 0..MB { + w[i]=t[i]; + } + self.b.tobytes(&mut t); + for i in 0..MB { + w[i+MB]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + w[i+2*MB]=t[i]; + } + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!( + "[{},{},{}]", + self.a.tostring(), + self.b.tostring(), + self.c.tostring() + ) + } + +/* Note this is simple square and multiply, so not side-channel safe */ +/* But fast for final exponentiation where exponent is not a secret */ +/* return this^e */ + pub fn pow(&self, e: &BIG) -> FP12 { + let mut r = FP12::new_copy(self); + r.norm(); + let mut e1 = BIG::new_copy(e); + e1.norm(); + let mut e3 = BIG::new_copy(&e1); + e3.pmul(3); + e3.norm(); + let mut w = FP12::new_copy(&r); + if e3.iszilch() { + w.one(); + return w; + } + + let nb = e3.nbits(); + for i in (1..nb - 1).rev() { + w.usqr(); + let bt = e3.bit(i) - e1.bit(i); + if bt == 1 { + w.mul(&r); + } + if bt == -1 { + r.conj(); + w.mul(&r); + r.conj(); + } + } + + w.reduce(); + w + } + + /* constant time powering by small integer of max length bts */ + pub fn pinpow(&mut self, e: i32, bts: i32) { + let mut r: [FP12; 2] = [FP12::new_int(1), FP12::new_copy(self)]; + let mut t = FP12::new(); + + for i in (0..bts).rev() { + let b: usize = ((e >> i) & 1) as usize; + t.copy(&r[b]); + r[1 - b].mul(&t); + r[b].usqr(); + } + self.copy(&r[0]); + } + + pub fn compow(&mut self, e: &BIG, r: &BIG) -> FP4 { + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let q = BIG::new_ints(&rom::MODULUS); + + let mut g1 = FP12::new_copy(self); + let mut g2 = FP12::new_copy(self); + + let mut m = BIG::new_copy(&q); + m.rmod(&r); + + let mut a = BIG::new_copy(&e); + a.rmod(&m); + + let mut b = BIG::new_copy(&e); + b.div(&m); + + let mut c = g1.trace(); + + if b.iszilch() { + c = c.xtr_pow(&a); + return c; + } + + g2.frob(&f); + let cp = g2.trace(); + g1.conj(); + g2.mul(&g1); + let cpm1 = g2.trace(); + g2.mul(&g1); + let cpm2 = g2.trace(); + + c.xtr_pow2(&cp, &cpm1, &cpm2, &a, &b) + } + + /* p=q0^u0.q1^u1.q2^u2.q3^u3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + pub fn pow4(q: &[FP12], u: &[BIG]) -> FP12 { + let mut g: [FP12; 8] = [ + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + ]; + + let mut r = FP12::new(); + let mut p = FP12::new(); + const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); + let mut w: [i8; CT] = [0; CT]; + let mut s: [i8; CT] = [0; CT]; + + let mut mt = BIG::new(); + let mut t: [BIG; 4] = [ + BIG::new_copy(&u[0]), + BIG::new_copy(&u[1]), + BIG::new_copy(&u[2]), + BIG::new_copy(&u[3]), + ]; + + for i in 0..4 { + t[i].norm(); + } + + // precomputation + g[0].copy(&q[0]); + r.copy(&g[0]); + g[1].copy(&r); + g[1].mul(&q[1]); // q[0].q[1] + g[2].copy(&r); + g[2].mul(&q[2]); + r.copy(&g[1]); // q[0].q[2] + g[3].copy(&r); + g[3].mul(&q[2]); + r.copy(&g[0]); // q[0].q[1].q[2] + g[4].copy(&r); + g[4].mul(&q[3]); + r.copy(&g[1]); // q[0].q[3] + g[5].copy(&r); + g[5].mul(&q[3]); + r.copy(&g[2]); // q[0].q[1].q[3] + g[6].copy(&r); + g[6].mul(&q[3]); + r.copy(&g[3]); // q[0].q[2].q[3] + g[7].copy(&r); + g[7].mul(&q[3]); // q[0].q[1].q[2].q[3] + + // Make it odd + let pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for i in 0..4 { + mt.or(&t[i]); + } + + let nb = 1 + mt.nbits(); + + // Sign pivot + s[nb - 1] = 1; + for i in 0..nb - 1 { + t[0].fshr(1); + s[i] = (2 * t[0].parity() - 1) as i8; + //println!("s={}",s[i]); + } + + // Recoded exponent + for i in 0..nb { + w[i] = 0; + let mut k = 1; + for j in 1..4 { + let bt = s[i] * (t[j].parity() as i8); + t[j].fshr(1); + t[j].dec((bt >> 1) as isize); + t[j].norm(); + w[i] += bt * (k as i8); + k *= 2; + } + } + + // Main loop + p.selector(&g, (2 * w[nb - 1] + 1) as i32); + for i in (0..nb - 1).rev() { + p.usqr(); + r.selector(&g, (2 * w[i] + s[i]) as i32); + p.mul(&r); + } + + // apply correction + r.copy(&q[0]); + r.conj(); + r.mul(&p); + p.cmove(&r, pb); + p.reduce(); + p + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp2.rs new file mode 100644 index 000000000000..72eb05861457 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp2.rs @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::rom; + +use crate::rand::RAND; + +#[derive(Copy, Clone)] +pub struct FP2 { + a: FP, + b: FP, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP2 { + pub const fn new() -> FP2 { + FP2 { + a: FP::new(), + b: FP::new(), + } + } + + pub fn new_int(a: isize) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_int(a)); + f.b.zero(); + f + } + + pub fn new_ints(a: isize, b: isize) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_int(a)); + f.b.copy(&FP::new_int(b)); + f + } + + pub fn new_copy(x: &FP2) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f + } + + pub fn new_fps(c: &FP, d: &FP) -> FP2 { + let mut f = FP2::new(); + f.a.copy(c); + f.b.copy(d); + f + } + + pub fn new_bigs(c: &BIG, d: &BIG) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_big(c)); + f.b.copy(&FP::new_big(d)); + f + } + + pub fn new_fp(c: &FP) -> FP2 { + let mut f = FP2::new(); + f.a.copy(c); + f.b.zero(); + f + } + + pub fn new_big(c: &BIG) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_big(c)); + f.b.zero(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP2 { + FP2::new_fps(&FP::new_rand(rng),&FP::new_rand(rng)) + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + self.a.iszilch() && self.b.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + return 0; + } + let cmp=self.b.islarger(); + if cmp!=0 { + return cmp; + } + self.a.islarger() + } + + pub fn tobytes(&self,bf: &mut [u8]) { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + self.b.tobytes(&mut t); + for i in 0..MB { + bf[i]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + bf[i+MB]=t[i]; + } + } + + pub fn frombytes(bf: &[u8]) -> FP2 { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=bf[i]; + } + let tb=FP::frombytes(&t); + for i in 0..MB { + t[i]=bf[i+MB]; + } + let ta=FP::frombytes(&t); + FP2::new_fps(&ta,&tb) + } + + pub fn cmove(&mut self, g: &FP2, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + } + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP::new_int(1); + self.a.equals(&one) && self.b.iszilch() + } + + /* test self=x */ + pub fn equals(&self, x: &FP2) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) + } + + /* extract a */ + #[allow(non_snake_case)] + pub fn getA(&mut self) -> FP { + self.a + } + + /* extract b */ + #[allow(non_snake_case)] + pub fn getB(&mut self) -> FP { + self.b + } + + /* extract a */ + pub fn geta(&mut self) -> BIG { + self.a.redc() + } + + /* extract b */ + pub fn getb(&mut self) -> BIG { + self.b.redc() + } + + /* copy self=x */ + pub fn copy(&mut self, x: &FP2) { + self.a.copy(&x.a); + self.b.copy(&x.b); + } + + pub fn set_fp(&mut self, x: &FP) { + self.a.copy(x); + self.b.zero(); + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + } + + pub fn sign(&self) -> isize { + let mut p1=self.a.sign(); + let mut p2=self.b.sign(); + if fp::BIG_ENDIAN_SIGN { + let u=self.b.iszilch() as isize; + p2^=(p1^p2)&u; + p2 + } else { + let u=self.a.iszilch() as isize; + p1^=(p1^p2)&u; + p1 + } + } + + /* negate self mod Modulus */ + pub fn neg(&mut self) { + let mut m = FP::new_copy(&self.a); + let mut t = FP::new(); + + m.add(&self.b); + m.neg(); + t.copy(&m); + t.add(&self.b); + self.b.copy(&m); + self.b.add(&self.a); + self.a.copy(&t); + } + + /* set to a-ib */ + pub fn conj(&mut self) { + self.b.neg(); + self.b.norm(); + } + + /* self+=a */ + pub fn add(&mut self, x: &FP2) { + self.a.add(&x.a); + self.b.add(&x.b); + } + + pub fn dbl(&mut self) { + self.a.dbl(); + self.b.dbl(); + } + + /* self-=a */ + pub fn sub(&mut self, x: &FP2) { + let mut m = FP2::new_copy(x); + m.neg(); + self.add(&m); + } + + /* self=a-self */ + pub fn rsub(&mut self, x: &FP2) { + self.neg(); + self.add(x); + } + + /* self*=s, where s is an FP */ + pub fn pmul(&mut self, s: &FP) { + self.a.mul(s); + self.b.mul(s); + } + + /* self*=i, where i is an int */ + pub fn imul(&mut self, c: isize) { + self.a.imul(c); + self.b.imul(c); + } + + /* self*=self */ + pub fn sqr(&mut self) { + let mut w1 = FP::new_copy(&self.a); + let mut w3 = FP::new_copy(&self.a); + let mut mb = FP::new_copy(&self.b); + + w1.add(&self.b); + + w3.add(&self.a); + w3.norm(); + self.b.mul(&w3); + + mb.neg(); + self.a.add(&mb); + + w1.norm(); + self.a.norm(); + + self.a.mul(&w1); + } + + /* this*=y */ + pub fn mul(&mut self, y: &FP2) { + if ((self.a.xes + self.b.xes) as i64) * ((y.a.xes + y.b.xes) as i64) > fp::FEXCESS as i64 { + if self.a.xes > 1 { + self.a.reduce() + } + if self.b.xes > 1 { + self.b.reduce() + } + } + + let p = BIG::new_ints(&rom::MODULUS); + let mut pr = DBIG::new(); + + pr.ucopy(&p); + + let mut c = BIG::new_copy(&(self.a.x)); + let mut d = BIG::new_copy(&(y.a.x)); + + let mut a = BIG::mul(&self.a.x, &y.a.x); + let mut b = BIG::mul(&self.b.x, &y.b.x); + + c.add(&self.b.x); + c.norm(); + d.add(&y.b.x); + d.norm(); + + let mut e = BIG::mul(&c, &d); + let mut f = DBIG::new_copy(&a); + f.add(&b); + b.rsub(&pr); + + a.add(&b); + a.norm(); + e.sub(&f); + e.norm(); + + self.a.x.copy(&FP::modulo(&mut a)); + self.a.xes = 3; + self.b.x.copy(&FP::modulo(&mut e)); + self.b.xes = 2; + } +/* + pub fn pow(&mut self, e: &BIG) { + let mut w = FP2::new_copy(self); + let mut z = BIG::new_copy(&e); + let mut r = FP2::new_int(1); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + self.copy(&r); + }*/ + + pub fn qr(&mut self,h:Option<&mut FP>) -> isize { + let mut c=FP2::new_copy(self); + c.conj(); + c.mul(self); + c.getA().qr(h) + } + + /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ + pub fn sqrt(&mut self,h:Option<&FP>) { + if self.iszilch() { + return; + } + let mut w1 = FP::new_copy(&self.b); + let mut w2 = FP::new_copy(&self.a); + let mut w3 = FP::new_copy(&self.a); + let mut w4 = FP::new(); + let mut hint = FP::new(); + + w1.sqr(); + w2.sqr(); + w1.add(&w2); w1.norm(); + + w2.copy(&w1.sqrt(h)); + w1.copy(&w2); + + w2.copy(&self.a); + w2.add(&w1); + w2.norm(); + w2.div2(); + + w1.copy(&self.b); w1.div2(); + let qr=w2.qr(Some(&mut hint)); + +// tweak hint + w3.copy(&hint); w3.neg(); w3.norm(); + w4.copy(&w2); w4.neg(); w4.norm(); + + w2.cmove(&w4,1-qr); + hint.cmove(&w3,1-qr); + + self.a.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&self.a); + self.b.copy(&w3); self.b.mul(&w1); + w4.copy(&self.a); + + self.a.cmove(&self.b,1-qr); + self.b.cmove(&w4,1-qr); + +/* + self.a.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&self.a); + self.b.copy(&w3); self.b.mul(&w1); + + hint.neg(); hint.norm(); + w2.neg(); w2.norm(); + + w4.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&w4); + w3.mul(&w1); + + self.a.cmove(&w3,1-qr); + self.b.cmove(&w4,1-qr); +*/ + let sgn=self.sign(); + let mut nr=FP2::new_copy(&self); + nr.neg(); nr.norm(); + self.cmove(&nr,sgn); + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!("[{},{}]", self.a.tostring(), self.b.tostring()) + } + + /* self=1/self */ + pub fn inverse(&mut self,h:Option<&FP>) { + self.norm(); + let mut w1 = FP::new_copy(&self.a); + let mut w2 = FP::new_copy(&self.b); + + w1.sqr(); + w2.sqr(); + w1.add(&w2); + w1.inverse(h); + self.a.mul(&w1); + w1.neg(); + w1.norm(); + self.b.mul(&w1); + } + + /* self/=2 */ + pub fn div2(&mut self) { + self.a.div2(); + self.b.div2(); + } + + /* self*=sqrt(-1) */ + pub fn times_i(&mut self) { + let z = FP::new_copy(&self.a); + self.a.copy(&self.b); + self.a.neg(); + self.b.copy(&z); + } + + /* w*=(1+sqrt(-1)) */ + /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ + pub fn mul_ip(&mut self) { + let mut t = FP2::new_copy(self); + let mut i = fp::QNRI; + self.times_i(); + while i > 0 { + t.dbl(); + t.norm(); + i -= 1; + } + self.add(&t); + if fp::TOWER == fp::POSITOWER { + self.norm(); + self.neg(); + } + } + + /* w/=(1+sqrt(-1)) */ + pub fn div_ip(&mut self) { + let mut z = FP2::new_ints(1 << fp::QNRI, 1); + z.inverse(None); + self.norm(); + self.mul(&z); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp4.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp4.rs new file mode 100644 index 000000000000..1f36040c7c20 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/fp4.rs @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::fp2::FP2; +use crate::rand::RAND; +#[allow(unused_imports)] +use crate::bn254::rom; + +#[derive(Copy, Clone)] +pub struct FP4 { + a: FP2, + b: FP2, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP4 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP4 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP4 { + pub const fn new() -> FP4 { + FP4 { + a: FP2::new(), + b: FP2::new(), + } + } + + pub fn new_int(a: isize) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&FP2::new_int(a)); + f.b.zero(); + f + } + + pub fn new_ints(a: isize,b: isize) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&FP2::new_int(a)); + f.b.copy(&FP2::new_int(b)); + f + } + + pub fn new_copy(x: &FP4) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f + } + + pub fn new_fp2s(c: &FP2, d: &FP2) -> FP4 { + let mut f = FP4::new(); + f.a.copy(c); + f.b.copy(d); + f + } + + pub fn new_fp2(c: &FP2) -> FP4 { + let mut f = FP4::new(); + f.a.copy(c); + f.b.zero(); + f + } + + pub fn new_fp(c: &FP) -> FP4 { + let mut f = FP4::new(); + f.a.set_fp(c); + f.b.zero(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP4 { + FP4::new_fp2s(&FP2::new_rand(rng),&FP2::new_rand(rng)) + } + + pub fn set_fp2s(&mut self, c: &FP2, d: &FP2) { + self.a.copy(&c); + self.b.copy(&d); + } + + pub fn set_fp(&mut self, c: &FP) { + self.a.set_fp(&c); + self.b.zero(); + } + + pub fn set_fp2(&mut self, c: &FP2) { + self.a.copy(&c); + self.b.zero(); + } + + pub fn set_fp2h(&mut self, c: &FP2) { + self.b.copy(&c); + self.a.zero(); + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + } + + pub fn cmove(&mut self, g: &FP4, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + self.a.iszilch() && self.b.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + 0 + } else { + let cmp=self.b.islarger(); + if cmp!=0 { + cmp + } else { + self.a.islarger() + } + } + } + + pub fn tobytes(&self,bf: &mut [u8]) { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + self.b.tobytes(&mut t); + for i in 0..MB { + bf[i]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + bf[i+MB]=t[i]; + } + } + + pub fn frombytes(bf: &[u8]) -> FP4 { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=bf[i]; + } + let tb=FP2::frombytes(&t); + for i in 0..MB { + t[i]=bf[i+MB]; + } + let ta=FP2::frombytes(&t); + FP4::new_fp2s(&ta,&tb) + } + + + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP2::new_int(1); + self.a.equals(&one) && self.b.iszilch() + } + + /* test is w real? That is in a+ib test b is zero */ + pub fn isreal(&mut self) -> bool { + self.b.iszilch() + } + /* extract real part a */ + pub fn real(&self) -> FP2 { + FP2::new_copy(&self.a) + } + + pub fn geta(&self) -> FP2 { + FP2::new_copy(&self.a) + } + /* extract imaginary part b */ + pub fn getb(&self) -> FP2 { + FP2::new_copy(&self.b) + } + + /* test self=x */ + pub fn equals(&self, x: &FP4) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) + } + /* copy self=x */ + pub fn copy(&mut self, x: &FP4) { + self.a.copy(&x.a); + self.b.copy(&x.b); + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + } + + pub fn sign(&self) -> isize { + let mut p1=self.a.sign(); + let mut p2=self.b.sign(); + if fp::BIG_ENDIAN_SIGN { + let u=self.b.iszilch() as isize; + p2^=(p1^p2)&u; + p2 + } else { + let u=self.a.iszilch() as isize; + p1^=(p1^p2)&u; + p1 + } + } + + /* negate self mod Modulus */ + pub fn neg(&mut self) { + self.norm(); + let mut m = FP2::new_copy(&self.a); + let mut t = FP2::new(); + + m.add(&self.b); + m.neg(); + t.copy(&m); + t.add(&self.b); + self.b.copy(&m); + self.b.add(&self.a); + self.a.copy(&t); + self.norm(); + } + + /* set to a-ib */ + pub fn conj(&mut self) { + self.b.neg(); + self.norm(); + } + + /* self=-conjugate(self) */ + pub fn nconj(&mut self) { + self.a.neg(); + self.norm(); + } + + /* self+=a */ + pub fn add(&mut self, x: &FP4) { + self.a.add(&x.a); + self.b.add(&x.b); + } + + pub fn padd(&mut self, x: &FP2) { + self.a.add(x); + } + + pub fn dbl(&mut self) { + self.a.dbl(); + self.b.dbl(); + } + + /* self-=a */ + pub fn sub(&mut self, x: &FP4) { + let mut m = FP4::new_copy(x); + m.neg(); + self.add(&m); + } + + /* self-=a */ + pub fn rsub(&mut self, x: &FP4) { + self.neg(); + self.add(x); + } + + /* self*=s, where s is an FP2 */ + pub fn pmul(&mut self, s: &FP2) { + self.a.mul(s); + self.b.mul(s); + } + + /* self*=s, where s is an FP */ + pub fn qmul(&mut self, s: &FP) { + self.a.pmul(s); + self.b.pmul(s); + } + + /* self*=i, where i is an int */ + pub fn imul(&mut self, c: isize) { + self.a.imul(c); + self.b.imul(c); + } + + /* self*=self */ + + pub fn sqr(&mut self) { + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + let mut t3 = FP2::new_copy(&self.a); + + t3.mul(&self.b); + t1.add(&self.b); + t2.mul_ip(); + + t2.add(&self.a); + + t1.norm(); + t2.norm(); + + self.a.copy(&t1); + + self.a.mul(&t2); + + t2.copy(&t3); + t2.mul_ip(); + t2.add(&t3); + t2.norm(); + t2.neg(); + self.a.add(&t2); + + t3.dbl(); + self.b.copy(&t3); + + self.norm(); + } + + /* self*=y */ + pub fn mul(&mut self, y: &FP4) { + //self.norm(); + + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + let mut t3 = FP2::new(); + let mut t4 = FP2::new_copy(&self.b); + + t1.mul(&y.a); + t2.mul(&y.b); + t3.copy(&y.b); + t3.add(&y.a); + t4.add(&self.a); + + t3.norm(); + t4.norm(); + + t4.mul(&t3); + + t3.copy(&t1); + t3.neg(); + t4.add(&t3); + t4.norm(); + + t3.copy(&t2); + t3.neg(); + self.b.copy(&t4); + self.b.add(&t3); + + t2.mul_ip(); + self.a.copy(&t2); + self.a.add(&t1); + + self.norm(); + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!("[{},{}]", self.a.tostring(), self.b.tostring()) + } + + /* self=1/self */ + pub fn inverse(&mut self,h:Option<&FP>) { + //self.norm(); + + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + + t1.sqr(); + t2.sqr(); + t2.mul_ip(); + t2.norm(); + t1.sub(&t2); + t1.inverse(h); + self.a.mul(&t1); + t1.neg(); + t1.norm(); + self.b.mul(&t1); + } + + /* self*=i where i = sqrt(-1+sqrt(-1)) */ + pub fn times_i(&mut self) { + let mut t = FP2::new_copy(&self.b); + self.b.copy(&self.a); + t.mul_ip(); + self.a.copy(&t); + self.norm(); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } + + /* self=self^p using Frobenius */ + pub fn frob(&mut self, f: &FP2) { + self.a.conj(); + self.b.conj(); + self.b.mul(f); + } + + /* return this^e */ +/* + pub fn pow(&self, e: &BIG) -> FP4 { + let mut w = FP4::new_copy(self); + w.norm(); + let mut z = BIG::new_copy(&e); + let mut r = FP4::new_int(1); + z.norm(); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + r + } +*/ + /* XTR xtr_a function */ + pub fn xtr_a(&mut self, w: &FP4, y: &FP4, z: &FP4) { + let mut r = FP4::new_copy(w); + let mut t = FP4::new_copy(w); + r.sub(y); + r.norm(); + r.pmul(&self.a); + t.add(y); + t.norm(); + t.pmul(&self.b); + t.times_i(); + + self.copy(&r); + self.add(&t); + self.add(z); + + self.norm(); + } + + /* XTR xtr_d function */ + pub fn xtr_d(&mut self) { + let mut w = FP4::new_copy(self); + self.sqr(); + w.conj(); + w.dbl(); + w.norm(); + self.sub(&w); + self.reduce(); + } + + /* r=x^n using XTR method on traces of FP12s */ + pub fn xtr_pow(&self, n: &BIG) -> FP4 { + let mut sf = FP4::new_copy(self); + sf.norm(); + let mut a = FP4::new_int(3); + let mut b = FP4::new_copy(&sf); + let mut c = FP4::new_copy(&b); + c.xtr_d(); + let mut t = FP4::new(); + let mut r = FP4::new(); + + let par = n.parity(); + let mut v = BIG::new_copy(n); + v.norm(); + v.fshr(1); + if par == 0 { + v.dec(1); + v.norm(); + } + + let nb = v.nbits(); + for i in (0..nb).rev() { + if v.bit(i) != 1 { + t.copy(&b); + sf.conj(); + c.conj(); + b.xtr_a(&a, &sf, &c); + sf.conj(); + c.copy(&t); + c.xtr_d(); + a.xtr_d(); + } else { + t.copy(&a); + t.conj(); + a.copy(&b); + a.xtr_d(); + b.xtr_a(&c, &sf, &t); + c.xtr_d(); + } + } + if par == 0 { + r.copy(&c) + } else { + r.copy(&b) + } + r.reduce(); + r + } + + /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ + pub fn xtr_pow2(&mut self, ck: &FP4, ckml: &FP4, ckm2l: &FP4, a: &BIG, b: &BIG) -> FP4 { + let mut e = BIG::new_copy(a); + let mut d = BIG::new_copy(b); + let mut w = BIG::new(); + e.norm(); + d.norm(); + + let mut cu = FP4::new_copy(ck); // can probably be passed in w/o copying + let mut cv = FP4::new_copy(self); + let mut cumv = FP4::new_copy(ckml); + let mut cum2v = FP4::new_copy(ckm2l); + let mut r = FP4::new(); + let mut t = FP4::new(); + + let mut f2: usize = 0; + while d.parity() == 0 && e.parity() == 0 { + d.fshr(1); + e.fshr(1); + f2 += 1; + } + + while BIG::comp(&d, &e) != 0 { + if BIG::comp(&d, &e) > 0 { + w.copy(&e); + w.imul(4); + w.norm(); + if BIG::comp(&d, &w) <= 0 { + w.copy(&d); + d.copy(&e); + e.rsub(&w); + e.norm(); + + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cum2v.copy(&cumv); + cum2v.conj(); + cumv.copy(&cv); + cv.copy(&cu); + cu.copy(&t); + } else if d.parity() == 0 { + d.fshr(1); + r.copy(&cum2v); + r.conj(); + t.copy(&cumv); + t.xtr_a(&cu, &cv, &r); + cum2v.copy(&cumv); + cum2v.xtr_d(); + cumv.copy(&t); + cu.xtr_d(); + } else if e.parity() == 1 { + d.sub(&e); + d.norm(); + d.fshr(1); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cu.xtr_d(); + cum2v.copy(&cv); + cum2v.xtr_d(); + cum2v.conj(); + cv.copy(&t); + } else { + w.copy(&d); + d.copy(&e); + d.fshr(1); + e.copy(&w); + t.copy(&cumv); + t.xtr_d(); + cumv.copy(&cum2v); + cumv.conj(); + cum2v.copy(&t); + cum2v.conj(); + t.copy(&cv); + t.xtr_d(); + cv.copy(&cu); + cu.copy(&t); + } + } + if BIG::comp(&d, &e) < 0 { + w.copy(&d); + w.imul(4); + w.norm(); + if BIG::comp(&e, &w) <= 0 { + e.sub(&d); + e.norm(); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cum2v.copy(&cumv); + cumv.copy(&cu); + cu.copy(&t); + } else if e.parity() == 0 { + w.copy(&d); + d.copy(&e); + d.fshr(1); + e.copy(&w); + t.copy(&cumv); + t.xtr_d(); + cumv.copy(&cum2v); + cumv.conj(); + cum2v.copy(&t); + cum2v.conj(); + t.copy(&cv); + t.xtr_d(); + cv.copy(&cu); + cu.copy(&t); + } else if d.parity() == 1 { + w.copy(&e); + e.copy(&d); + w.sub(&d); + w.norm(); + d.copy(&w); + d.fshr(1); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cumv.conj(); + cum2v.copy(&cu); + cum2v.xtr_d(); + cum2v.conj(); + cu.copy(&cv); + cu.xtr_d(); + cv.copy(&t); + } else { + d.fshr(1); + r.copy(&cum2v); + r.conj(); + t.copy(&cumv); + t.xtr_a(&cu, &cv, &r); + cum2v.copy(&cumv); + cum2v.xtr_d(); + cumv.copy(&t); + cu.xtr_d(); + } + } + } + r.copy(&cv); + r.xtr_a(&cu, &cumv, &cum2v); + for _ in 0..f2 { + r.xtr_d() + } + r = r.xtr_pow(&d); + r + } + + /* this/=2 */ + pub fn div2(&mut self) { + self.a.div2(); + self.b.div2(); + } + + pub fn div_i(&mut self) { + let mut u = FP2::new_copy(&self.a); + let v = FP2::new_copy(&self.b); + u.div_ip(); + self.a.copy(&v); + self.b.copy(&u); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } +/* + pub fn pow(&mut self, e: &BIG) { + let mut w = FP4::new_copy(self); + let mut z = BIG::new_copy(&e); + let mut r = FP4::new_int(1); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + self.copy(&r); + } +*/ + +/* PFGE24S + + pub fn qr(&mut self,h:Option<&mut FP>) -> isize { + let mut c=FP4::new_copy(self); + c.conj(); + c.mul(self); + c.geta().qr(h) + } + + // sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) + // returns true if this is QR + pub fn sqrt(&mut self,h:Option<&FP>) { + if self.iszilch() { + return; + } + + let mut a = FP2::new_copy(&self.a); + let mut b = FP2::new_copy(&self.a); + let mut s = FP2::new_copy(&self.b); + let mut t = FP2::new_copy(&self.a); + let mut hint = FP::new(); + + s.sqr(); + a.sqr(); + s.mul_ip(); + s.norm(); + a.sub(&s); + + s.copy(&a); s.norm(); + + s.sqrt(h); + + a.copy(&t); + a.add(&s); + a.norm(); + a.div2(); + + + b.copy(&self.b); b.div2(); + let qr=a.qr(Some(&mut hint)); + + +// tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial + s.copy(&a); + let mut twk = FP::new_big(&BIG::new_ints(&rom::TWK)); + twk.mul(&hint); + s.div_ip(); s.norm(); + + a.cmove(&s,1-qr); + hint.cmove(&twk,1-qr); + + self.a.copy(&a); self.a.sqrt(Some(&hint)); + s.copy(&a); s.inverse(Some(&hint)); + s.mul(&self.a); + self.b.copy(&s); self.b.mul(&b); + t.copy(&self.a); + + self.a.cmove(&self.b,1-qr); + self.b.cmove(&t,1-qr); + + let sgn=self.sign(); + let mut nr=FP4::new_copy(&self); + nr.neg(); nr.norm(); + self.cmove(&nr,sgn); + } +PFGE24F */ +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/hpke.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/hpke.rs new file mode 100644 index 000000000000..6aa0b7ce0f19 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/hpke.rs @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::ecp; +use crate::bn254::ecdh; + +use crate::hmac; +use crate::rand::RAND; + +const GROUP: usize = ecdh::EGS; +const POINT: usize = 2*ecdh::EFS+1; + +const MAX_LABEL: usize = 20; // may need adjustment + +#[allow(non_snake_case)] +fn reverse (x: &mut [u8]) { + let lx=x.len(); + for i in 0..lx/2 { + let ch=x[i]; + x[i]=x[lx-i-1]; + x[lx-i-1]=ch; + } +} +/* +fn printbinary(array: &[u8]) { + for i in 0..array.len() { + print!("{:02X}", array[i]) + } + println!("") +} +*/ + +#[allow(non_snake_case)] +fn labeledExtract(prk: &mut [u8],salt: Option<&[u8]>,suite_id: &[u8],label: &str,ikm: Option<&[u8]>) { + let rfc="HPKE-v1"; + let prefix1=rfc.as_bytes(); + let prefix2=label.as_bytes(); + let mut likm: [u8; 18+MAX_LABEL+2*POINT] = [0; 18+MAX_LABEL+2*POINT]; + let mut k=0; + for i in 0..prefix1.len() { + likm[k]=prefix1[i]; + k+=1; + } + for i in 0..suite_id.len() { + likm[k]=suite_id[i]; + k+=1; + } + for i in 0..prefix2.len() { + likm[k]=prefix2[i]; + k+=1; + } + if let Some(sikm) = ikm { + for i in 0..sikm.len() { + likm[k]=sikm[i]; + k+=1; + } + } + hmac::hkdf_extract(hmac::MC_SHA2,ecp::HASH_TYPE,prk,salt,&likm[0..k]); +} + +#[allow(non_snake_case)] +fn labeledExpand(okm: &mut [u8],prk: &[u8],suite_id: &[u8],label: &str,info: Option<&[u8]>,el: usize) { + let mut ar: [u8; 2] = [0; 2]; + let rfc="HPKE-v1"; + let prefix1=rfc.as_bytes(); + let prefix2=label.as_bytes(); + hmac::inttobytes(el,&mut ar); + let mut linfo: [u8; 20+MAX_LABEL+3*POINT] = [0; 20+MAX_LABEL+3*POINT]; + linfo[0]=ar[0]; + linfo[1]=ar[1]; + let mut k=2; + for i in 0..prefix1.len() { + linfo[k]=prefix1[i]; + k+=1; + } + for i in 0..suite_id.len() { + linfo[k]=suite_id[i]; + k+=1; + } + for i in 0..prefix2.len() { + linfo[k]=prefix2[i]; + k+=1; + } + if let Some(sinfo) = info { + for i in 0..sinfo.len() { + linfo[k]=sinfo[i]; + k+=1; + } + } + hmac:: hkdf_expand(hmac::MC_SHA2,ecp::HASH_TYPE,okm,el,prk,&linfo[0..k]); +} + +#[allow(non_snake_case)] +fn extractAndExpand(config_id: usize,okm: &mut [u8],dh: &[u8],context: &[u8]) { + let kem = config_id&255; + let txt="KEM"; + let mut suite_id: [u8;5] = [0;5]; + let mut kem_id: [u8; 2] = [0; 2]; + let ckem=txt.as_bytes(); + hmac::inttobytes(kem,&mut kem_id); + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + suite_id[k]=kem_id[0]; k+=1; + suite_id[k]=kem_id[1]; + + let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; + labeledExtract(&mut prk,None,&suite_id,"eae_prk",Some(dh)); + labeledExpand(okm,&prk,&suite_id,"shared_secret",Some(&context),ecp::HASH_TYPE); +} + +#[allow(non_snake_case)] +pub fn deriveKeyPair(config_id: usize,mut sk: &mut [u8],mut pk: &mut [u8],seed: &[u8]) -> bool { + let mut counter=0; + let kem = config_id&255; + let txt="KEM"; + let mut suite_id: [u8;5] = [0;5]; + let mut kem_id: [u8; 2] = [0; 2]; + let ckem=txt.as_bytes(); + hmac::inttobytes(kem,&mut kem_id); + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + suite_id[k]=kem_id[0]; k+=1; + suite_id[k]=kem_id[1]; + + let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; + labeledExtract(&mut prk,None,&suite_id,"dkp_prk",Some(&seed)); + + //println!("prk= {:02X?}",prk); + + if kem==32 || kem==33 { // RFC7748 + labeledExpand(&mut sk,&prk,&suite_id,"sk",None,GROUP); + reverse(&mut sk); + if kem==32 { + sk[GROUP-1]&=248; + sk[0]&=127; + sk[0]|=64; + } else { + sk[GROUP-1]&=252; + sk[0]|=128; + } + } else { + let mut bit_mask=0xff; + if kem==18 { + bit_mask=1; + } + for i in 0..GROUP { + sk[i]=0; + } + while !ecdh::in_range(&sk) && counter<256 { + let mut info: [u8;1]=[0;1]; + info[0]=counter as u8; + labeledExpand(sk,&prk,&suite_id,"candidate",Some(&info),GROUP); + sk[0] &= bit_mask as u8; + counter += 1; + } + } + //for i in 0..sk.len() { +// print!({} +// println!("SK= {:02X?}",sk); + // println!("kem= {}",kem); + //println!("counter= {}",counter); + ecdh::key_pair_generate(None::<&mut RAND>, &mut sk, &mut pk); + if kem==32 || kem==33 { + reverse(&mut pk); + } + counter<256 +} + +#[allow(non_snake_case)] +pub fn encap(config_id: usize,skE: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { + let pklen=pkE.len(); + let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; + let kem = config_id&255; + let mut rev: [u8; POINT]=[0; POINT]; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkR[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); + reverse(&mut dh[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); + } + let mut k=0; + for i in 0..pklen { + kemcontext[k]=pkE[i]; + k+=1; + } + for i in 0..pklen { + kemcontext[k]=pkR[i]; + k+=1; + } +//print!("e dh= "); printbinary(&dh[0..pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); +} + +#[allow(non_snake_case)] +pub fn decap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { + let pklen=pkE.len(); + let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; + let mut rev: [u8; POINT]=[0; POINT]; + let kem = config_id&255; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkE[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); + reverse(&mut dh[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); + } + + let mut k=0; + for i in 0..pklen { + kemcontext[k]=pkE[i]; + k+=1; + } + for i in 0..pklen { // not a mistake + kemcontext[k]=pkR[i]; + k+=1; + } +//print!("d dh= "); printbinary(&dh[0..pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); +} + +#[allow(non_snake_case)] +pub fn authencap(config_id: usize,skE: &[u8],skS: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { + let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; + let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; + + let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; + let kem = config_id&255; + let pklen=pkE.len(); + let mut rev: [u8; POINT]=[0; POINT]; + + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkR[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); + ecdh::ecpsvdp_dh(&skS, &rev[0..pklen], &mut dh1, 0); + reverse(&mut dh[0..pklen]); + reverse(&mut dh1[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); + ecdh::ecpsvdp_dh(&skS, &pkR, &mut dh1, 0); + } + + for i in 0..ecdh::EFS { + dh[i+ecdh::EFS] = dh1[i]; + } + + for i in 0..pklen { + kemcontext[i]=pkE[i]; + kemcontext[pklen+i]= pkR[i]; + kemcontext[2*pklen+i]= pkS[i]; + } +//print!("e dh= "); printbinary(&dh[0..pklen]); +//print!("e kemcontext= "); printbinary(&kemcontext[0..3*pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); +} + +#[allow(non_snake_case)] +pub fn authdecap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { + let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; + let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; + let kem = config_id&255; + let pklen=pkE.len(); + let mut rev: [u8; POINT]=[0; POINT]; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkE[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); + for i in 0..pklen { + rev[i]=pkS[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh1, 0); + reverse(&mut dh[0..pklen]); + reverse(&mut dh1[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); + ecdh::ecpsvdp_dh(&skR, &pkS, &mut dh1, 0); + } + + for i in 0..ecdh::EFS { + dh[i+ecdh::EFS] = dh1[i]; + } + + for i in 0..pklen { + kemcontext[i]=pkE[i]; + kemcontext[pklen+i]= pkR[i]; + kemcontext[2*pklen+i]= pkS[i]; + } +//print!("d dh= "); printbinary(&dh[0..pklen]); +//print!("d kemcontext= "); printbinary(&kemcontext[0..3*pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); +} + +#[allow(non_snake_case)] +pub fn keyschedule(config_id: usize,key: &mut [u8],nonce: &mut [u8],exp_secret: &mut [u8],mode: usize,z: &mut [u8],info: &[u8],psk: Option<&[u8]>,pskID: Option<&[u8]>) { + + let mut context: [u8; 1+2*ecp::HASH_TYPE] = [0; 1+2*ecp::HASH_TYPE]; + let kem=config_id&255; + let kdf=(config_id>>8)&3; + let aead=(config_id>>10)&3; + + let txt="HPKE"; + let ckem=txt.as_bytes(); + let mut suite_id: [u8;10] = [0;10]; + let mut num: [u8; 2] = [0; 2]; + + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + hmac::inttobytes(kem,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; k+=1; + hmac::inttobytes(kdf,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; k+=1; + hmac::inttobytes(aead,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; + + let mut k=0; + let mut h: [u8; 64] = [0; 64]; + let mut secret: [u8; 64] = [0; 64]; + + context[k]=mode as u8; k+=1; + + labeledExtract(&mut h,None,&suite_id,"psk_id_hash",pskID); + for i in 0..ecp::HASH_TYPE { + context[k] = h[i]; k+=1; + } + labeledExtract(&mut h,None,&suite_id,"info_hash",Some(&info)); + for i in 0..ecp::HASH_TYPE { + context[k] = h[i]; k+=1; + } + + //labeledExtract(&mut h,None,&suite_id,"psk_hash",psk); + + //labeledExtract(&mut secret,Some(&h),&suite_id,"secret",Some(z)); + + labeledExtract(&mut secret,Some(z),&suite_id,"secret",psk); + + labeledExpand(key,&secret,&suite_id,"key",Some(&context[0..k]),ecp::AESKEY); + labeledExpand(nonce,&secret,&suite_id,"base_nonce",Some(&context[0..k]),12); + labeledExpand(exp_secret,&secret,&suite_id,"exp",Some(&context[0..k]),ecp::HASH_TYPE); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mod.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mod.rs new file mode 100644 index 000000000000..89eca15de70e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mod.rs @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pub mod big; +pub mod bls; +pub mod dbig; +pub mod ecp; +pub mod ecp2; +pub mod fp; +pub mod fp12; +pub mod fp2; +pub mod fp4; +pub mod mpin; +pub mod pair; +pub mod rom; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mpin.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mpin.rs new file mode 100644 index 000000000000..3b3121e5dda5 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/mpin.rs @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::ecp2::ECP2; +use crate::bn254::fp12::FP12; +use crate::bn254::pair; +use crate::bn254::rom; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; + +use crate::hmac; +use crate::rand::RAND; + +/* MPIN 128-bit API Functions */ + +/* Configure mode of operation */ + +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; +pub const BAD_PARAMS: isize = -11; +pub const INVALID_POINT: isize = -14; +pub const WRONG_ORDER: isize = -18; +pub const BAD_PIN: isize = -19; +pub const SHA256: usize = 32; +pub const SHA384: usize = 48; +pub const SHA512: usize = 64; + +/* Configure your PIN here */ + +pub const MAXPIN: i32 = 10000; /* PIN less than this */ +pub const PBLEN: i32 = 14; /* Number of bits in PIN */ + +fn ceil(a: usize,b: usize) -> usize { + (a-1)/b+1 +} + +#[allow(non_snake_case)] +pub fn encode_to_curve(dst: &[u8],id: &[u8],hcid: &mut [u8]) { + let q = BIG::new_ints(&rom::MODULUS); + let k=q.nbits(); + let r = BIG::new_ints(&rom::CURVE_ORDER); + let m=r.nbits(); + let el=ceil(k+ceil(m,2),8); + let mut okm: [u8;512]=[0;512]; + hmac::xmd_expand(hmac::MC_SHA2,ecp::HASH_TYPE,&mut okm,el,&dst,&id); + let mut fd: [u8;256]=[0;256]; + for j in 0..el { + fd[j]=okm[j]; + } + let mut dx=DBIG::frombytes(&fd[0..el]); + let u=FP::new_big(&dx.dmod(&q)); + let mut P=ECP::map2point(&u); + P.cfp(); + P.affine(); + P.tobytes(hcid,false); +} + +/* create random secret S */ +pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sc = BIG::randtrunc(&r, 16 * ecp::AESKEY, rng); + sc.tobytes(s); + 0 +} + +/* Extract PIN from TOKEN for identity CID */ +#[allow(non_snake_case)] +pub fn extract_pin(cid: &[u8], pin: i32, token: &mut [u8]) -> isize { + let mut P = ECP::frombytes(&token); + if P.is_infinity() { + return INVALID_POINT; + } + let mut R = ECP::frombytes(&cid); + if R.is_infinity() { + return INVALID_POINT; + } + + R = R.pinmul(pin%MAXPIN, PBLEN); + P.sub(&R); + P.tobytes(token, false); + 0 +} + +/* Implement step 2 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_2(x: &[u8], y: &[u8], sec: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let mut P = ECP::frombytes(sec); + if P.is_infinity() { + return INVALID_POINT; + } + + let mut px = BIG::frombytes(x); + let py = BIG::frombytes(y); + px.add(&py); + px.rmod(&r); + + P = pair::g1mul(&P, &px); + P.neg(); + P.tobytes(sec, false); + 0 +} + +/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ +#[allow(non_snake_case)] +pub fn get_client_secret(s: &mut [u8], idhtc: &[u8], cst: &mut [u8]) -> isize { + let sx=BIG::frombytes(s); + let P=ECP::frombytes(idhtc); + if P.is_infinity() { + return INVALID_POINT; + } + pair::g1mul(&P, &sx).tobytes(cst, false); + 0 +} + +/* Implement step 1 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_1( + cid: &[u8], + rng: Option<&mut RAND>, + x: &mut [u8], + pin: usize, + token: &[u8], + sec: &mut [u8], + xid: &mut [u8] +) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sx: BIG; + + if let Some(rd) = rng { + sx = BIG::randtrunc(&r, 16 * ecp::AESKEY, rd); + sx.tobytes(x); + } else { + sx = BIG::frombytes(x); + } + let mut P=ECP::frombytes(cid); + if P.is_infinity() { + return INVALID_POINT; + } + + let mut T = ECP::frombytes(&token); + if T.is_infinity() { + return INVALID_POINT; + } + + let W = P.pinmul((pin as i32) % MAXPIN, PBLEN); + T.add(&W); + + P = pair::g1mul(&P, &sx); + P.tobytes(xid, false); + + T.tobytes(sec, false); + 0 +} + + +/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ +#[allow(non_snake_case)] +pub fn get_server_secret(s: &[u8], sst: &mut [u8]) -> isize { + let mut Q = ECP2::generator(); + let sc = BIG::frombytes(s); + Q = pair::g2mul(&Q, &sc); + Q.tobytes(sst,false); + 0 +} + +/* Implement step 2 of MPin protocol on server side */ +#[allow(non_snake_case)] +pub fn server( + hid: &[u8], + y: &[u8], + sst: &[u8], + xid: &[u8], + msec: &[u8], +) -> isize { + let Q = ECP2::generator(); + let sQ = ECP2::frombytes(&sst); + if sQ.is_infinity() { + return INVALID_POINT; + } + let mut R = ECP::frombytes(&xid); + if R.is_infinity() { + return INVALID_POINT; + } + + let sy = BIG::frombytes(&y); + let mut P = ECP::frombytes(&hid); + if P.is_infinity() { + return INVALID_POINT; + } + + P = pair::g1mul(&P, &sy); + P.add(&R); + R = ECP::frombytes(&msec); + if R.is_infinity() { + return INVALID_POINT; + } + + let mut g: FP12; + g = pair::ate2(&Q, &R, &sQ, &P); + g = pair::fexp(&g); + + if !g.isunity() { + return BAD_PIN; + } + 0 +} + diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/pair.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/pair.rs new file mode 100644 index 000000000000..360fe0fcd07a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/pair.rs @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::ecp2::ECP2; +use crate::bn254::fp::FP; +use crate::bn254::fp12; +use crate::bn254::fp12::FP12; +use crate::bn254::fp2::FP2; +use crate::bn254::fp4::FP4; +use crate::bn254::rom; + +#[allow(unused_imports)] +use crate::bn254::dbig::DBIG; + +#[allow(non_snake_case)] +fn dbl(A: &mut ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { + cc.copy(&A.getpx()); //X + let mut yy = FP2::new_copy(&A.getpy()); //Y + bb.copy(&A.getpz()); //Z + + aa.copy(&yy); //Y + aa.mul(&bb); //YZ + cc.sqr(); //X^2 + yy.sqr(); //Y^2 + bb.sqr(); //Z^2 + + aa.dbl(); + aa.neg(); aa.norm(); + aa.mul_ip(); + aa.norm(); + + let sb = 3 * rom::CURVE_B_I; + bb.imul(sb); + cc.imul(3); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + yy.mul_ip(); + yy.norm(); + cc.mul_ip(); + cc.norm(); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + bb.mul_ip(); + bb.norm(); + } + bb.sub(&yy); + bb.norm(); + A.dbl(); +} + +#[allow(non_snake_case)] +fn add(A: &mut ECP2, B: &ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { + + aa.copy(&A.getpx()); // X1 + cc.copy(&A.getpy()); // Y1 + let mut t1 = FP2::new_copy(&A.getpz()); // Z1 + bb.copy(&A.getpz()); // Z1 + + t1.mul(&B.getpy()); // T1=Z1.Y2 + bb.mul(&B.getpx()); // T2=Z1.X2 + + aa.sub(&bb); + aa.norm(); // X1=X1-Z1.X2 + cc.sub(&t1); + cc.norm(); // Y1=Y1-Z1.Y2 + + t1.copy(&aa); // T1=X1-Z1.X2 + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + aa.mul_ip(); + aa.norm(); + } + + t1.mul(&B.getpy()); // T1=(X1-Z1.X2).Y2 + + bb.copy(&cc); // T2=Y1-Z1.Y2 + bb.mul(&B.getpx()); // T2=(Y1-Z1.Y2).X2 + bb.sub(&t1); + bb.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 + + cc.neg(); + cc.norm(); // Y1=-(Y1-Z1.Y2).Xs + + A.add(B); +} + +#[allow(non_snake_case)] +fn linedbl(A: &mut ECP2, qx: &FP, qy: &FP) -> FP12 { + let mut a = FP4::new(); + let mut b = FP4::new(); + let mut c = FP4::new(); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + dbl(A,&mut aa,&mut bb,&mut cc); + + cc.pmul(qx); + aa.pmul(qy); + + a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + c.copy(&FP4::new_fp2(&cc)); + c.times_i(); + } + let mut res= FP12::new_fp4s(&a, &b, &c); + res.settype(fp12::SPARSER); + res +} + +#[allow(non_snake_case)] +fn lineadd(A: &mut ECP2, B: &ECP2, qx: &FP, qy: &FP) -> FP12 { + let mut a = FP4::new(); + let mut b = FP4::new(); + let mut c = FP4::new(); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + add(A,B,&mut aa,&mut bb,&mut cc); + + cc.pmul(qx); + aa.pmul(qy); + + a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + c.copy(&FP4::new_fp2(&cc)); + c.times_i(); + } + let mut res= FP12::new_fp4s(&a, &b, &c); + res.settype(fp12::SPARSER); + res +} + +/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ +#[allow(non_snake_case)] +fn lbits(n3: &mut BIG,n: &mut BIG) -> usize { + n.copy(&BIG::new_ints(&rom::CURVE_BNX)); + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + n.pmul(6); + if ecp::SIGN_OF_X==ecp::POSITIVEX { + n.inc(2); + } else { + n.dec(2); + } + } + n.norm(); + n3.copy(&n); + n3.pmul(3); + n3.norm(); + n3.nbits() +} + +/* prepare for multi-pairing */ +pub fn initmp() -> [FP12; ecp::ATE_BITS] { + [FP12::new_int(1); ecp::ATE_BITS] +} + +/* basic Miller loop */ +pub fn miller(r:&mut [FP12]) -> FP12 { + let mut res=FP12::new_int(1); + for i in (1..ecp::ATE_BITS).rev() { + res.sqr(); + res.ssmul(&r[i]); + r[i].zero(); + } + + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + res.conj(); + } + res.ssmul(&r[0]); + r[0].zero(); + res +} + +fn pack(aa: &FP2,bb: &FP2,cc: &FP2) -> FP4 { + let mut i=FP2::new_copy(cc); + i.inverse(None); + let mut a=FP2::new_copy(aa); + let mut b=FP2::new_copy(bb); + a.mul(&i); + b.mul(&i); + FP4::new_fp2s(&a,&b) +} + +fn unpack(t: &FP4, qx: &FP, qy: &FP) -> FP12 { + let b:FP4; + let mut c:FP4; + let w=FP2::new_fp(qx); + + let mut aa=t.geta(); + let bb=t.getb(); + aa.pmul(qy); + let a=FP4::new_fp2s(&aa,&bb); + + if ecp::SEXTIC_TWIST==ecp::D_TYPE { + b=FP4::new_fp2(&w); + c=FP4::new(); + } else { + b=FP4::new(); + c=FP4::new_fp2(&w); c.times_i(); + } + let mut v=FP12::new_fp4s(&a,&b,&c); + v.settype(fp12::SPARSEST); + v +} + +#[allow(non_snake_case)] +pub fn precomp(T: &mut [FP4],GV: &ECP2) { + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let nb=lbits(&mut n3,&mut n); + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + let mut P=ECP2::new(); P.copy(GV); + + if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let mut A = ECP2::new(); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + let mut j=0; + + for i in (1..nb-1).rev() { + dbl(&mut A,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + add(&mut A,&P,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + } + if bt==-1 { + add(&mut A,&NP,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + } + } +/* R-ate fixup required for BN curves */ + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + A.neg(); + } + let mut K = ECP2::new(); + K.copy(&P); + K.frob(&f); + add(&mut A,&K,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + K.frob(&f); + K.neg(); + add(&mut A,&K,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); + } +} + +/* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ +#[allow(non_snake_case)] +pub fn another_pc(r:&mut [FP12],T: &[FP4],QV: &ECP) { + let mut n = BIG::new(); + let mut n3 = BIG::new(); + + if QV.is_infinity() { + return; + } + + let nb=lbits(&mut n3,&mut n); + + let mut Q = ECP::new(); + Q.copy(QV); + Q.affine(); + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let mut j=0; + for i in (1..nb-1).rev() { + let mut lv=unpack(&T[j],&qx,&qy); j+=1; + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + let lv2=unpack(&T[j],&qx,&qy); j+=1; + lv.smul(&lv2); + } + if bt==-1 { + let lv2=unpack(&T[j],&qx,&qy); j+=1; + lv.smul(&lv2); + } + r[i].ssmul(&lv); + } + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + let mut lv=unpack(&T[j],&qx,&qy); j+=1; + let lv2=unpack(&T[j],&qx,&qy); + lv.smul(&lv2); + r[0].ssmul(&lv); + } +} + +/* Accumulate another set of line functions for n-pairing */ +#[allow(non_snake_case)] +pub fn another(r:&mut [FP12],P1: &ECP2,Q1: &ECP) { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return; + } +// P is needed in affine form for line function, Q for (Qx,Qy) extraction + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + + if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + let mut A = ECP2::new(); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb-1).rev() { + let mut lv=linedbl(&mut A,&qx,&qy); + + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + let lv2=lineadd(&mut A,&P,&qx,&qy); + lv.smul(&lv2); + } + if bt==-1 { + let lv2=lineadd(&mut A,&NP,&qx,&qy); + lv.smul(&lv2); + } + r[i].ssmul(&lv); + } + +/* R-ate fixup required for BN curves */ + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + A.neg(); + } + K.copy(&P); + K.frob(&f); + let mut lv=lineadd(&mut A,&K,&qx,&qy); + K.frob(&f); + K.neg(); + let lv2=lineadd(&mut A,&K,&qx,&qy); + lv.smul(&lv2); + r[0].ssmul(&lv); + } +} + +#[allow(non_snake_case)] +/* Optimal R-ate pairing */ +pub fn ate(P1: &ECP2, Q1: &ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return FP12::new_int(1); + } + + if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let mut A = ECP2::new(); + let mut r = FP12::new_int(1); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb - 1).rev() { + r.sqr(); + let mut lv = linedbl(&mut A, &qx, &qy); + let bt = n3.bit(i) - n.bit(i); + if bt == 1 { + let lv2 = lineadd(&mut A, &P, &qx, &qy); + lv.smul(&lv2); + } + if bt == -1 { + let lv2 = lineadd(&mut A, &NP, &qx, &qy); + lv.smul(&lv2); + } + r.ssmul(&lv); + } + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + r.conj(); + } + + /* R-ate fixup required for BN curves */ + + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + A.neg(); + } + + K.copy(&P); + K.frob(&f); + + let mut lv = lineadd(&mut A, &K, &qx, &qy); + K.frob(&f); + K.neg(); + let lv2 = lineadd(&mut A, &K, &qx, &qy); + lv.smul(&lv2); + r.ssmul(&lv); + } + + r +} + +#[allow(non_snake_case)] +/* Optimal R-ate double pairing e(P,Q).e(R,S) */ +pub fn ate2(P1: &ECP2, Q1: &ECP, R1: &ECP2, S1: &ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return ate(R1,S1); + } + if S1.is_infinity() { + return ate(P1,Q1); + } + + if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + let mut R = ECP2::new(); + R.copy(R1); + R.affine(); + let mut S = ECP::new(); + S.copy(S1); + S.affine(); + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let sx = FP::new_copy(&S.getpx()); + let sy = FP::new_copy(&S.getpy()); + + let mut A = ECP2::new(); + let mut B = ECP2::new(); + let mut r = FP12::new_int(1); + + A.copy(&P); + B.copy(&R); + + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + let mut NR = ECP2::new(); + NR.copy(&R); + NR.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb - 1).rev() { + r.sqr(); + let mut lv = linedbl(&mut A, &qx, &qy); + let lv2 = linedbl(&mut B, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + let bt = n3.bit(i) - n.bit(i); + if bt == 1 { + lv = lineadd(&mut A, &P, &qx, &qy); + let lv2 = lineadd(&mut B, &R, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + } + if bt == -1 { + lv = lineadd(&mut A, &NP, &qx, &qy); + let lv2 = lineadd(&mut B, &NR, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + } + } + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + r.conj(); + } + + /* R-ate fixup */ + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + A.neg(); + B.neg(); + } + K.copy(&P); + K.frob(&f); + + let mut lv = lineadd(&mut A, &K, &qx, &qy); + K.frob(&f); + K.neg(); + let mut lv2 = lineadd(&mut A, &K, &qx, &qy); + lv.smul(&lv2); + r.ssmul(&lv); + + K.copy(&R); + K.frob(&f); + + lv = lineadd(&mut B, &K, &sx, &sy); + K.frob(&f); + K.neg(); + lv2 = lineadd(&mut B, &K, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + + } + + r +} + +/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ +pub fn fexp(m: &FP12) -> FP12 { + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut r = FP12::new_copy(m); + + /* Easy part of final exp */ + let mut lv = FP12::new_copy(&r); + lv.inverse(); + r.conj(); + + r.mul(&lv); + lv.copy(&r); + r.frob(&f); + r.frob(&f); + r.mul(&lv); + + /* Hard part of final exp */ + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + lv.copy(&r); + lv.frob(&f); + let mut x0 = FP12::new_copy(&lv); + x0.frob(&f); + lv.mul(&r); + x0.mul(&lv); + x0.frob(&f); + let mut x1 = FP12::new_copy(&r); + x1.conj(); + let mut x4 = r.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + x4.conj(); + } + + let mut x3 = FP12::new_copy(&x4); + x3.frob(&f); + + let mut x2 = x4.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + x2.conj(); + } + let mut x5 = FP12::new_copy(&x2); + x5.conj(); + lv = x2.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + lv.conj(); + } + x2.frob(&f); + r.copy(&x2); + r.conj(); + + x4.mul(&r); + x2.frob(&f); + + r.copy(&lv); + r.frob(&f); + lv.mul(&r); + + lv.usqr(); + lv.mul(&x4); + lv.mul(&x5); + r.copy(&x3); + r.mul(&x5); + r.mul(&lv); + lv.mul(&x2); + r.usqr(); + r.mul(&lv); + r.usqr(); + lv.copy(&r); + lv.mul(&x1); + r.mul(&x0); + lv.usqr(); + r.mul(&lv); + r.reduce(); + } else { + +// See https://eprint.iacr.org/2020/875.pdf + let mut y1 = FP12::new_copy(&r); + y1.usqr(); + y1.mul(&r); // y1=r^3 + + let mut y0 = FP12::new_copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + let mut t0 = FP12::new_copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + + y0.copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + t0.copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + +// ^(x+p) + y0.copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + t0.copy(&r); + t0.frob(&f); + r.copy(&y0); + r.mul(&t0); + +// ^(x^2+p^2-1) + y0.copy(&r.pow(&x)); + y0.copy(&y0.pow(&x)); + t0.copy(&r); + t0.frob(&f); t0.frob(&f); + y0.mul(&t0); + t0.copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + + r.mul(&y1); + r.reduce(); + } + r +} + +#[allow(non_snake_case)] +/* GLV method */ +fn glv(ee: &BIG) -> [BIG; 2] { + let mut u: [BIG; 2] = [BIG::new(), BIG::new()]; + let q = BIG::new_ints(&rom::CURVE_ORDER); + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +/* */ + let mut t = BIG::new(); + let mut v: [BIG; 2] = [BIG::new(), BIG::new()]; + + for i in 0..2 { + t.copy(&BIG::new_ints(&rom::CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); + let mut d: DBIG = BIG::mul(&t, &ee); + v[i].copy(&d.ctdiv(&q,t.nbits())); + } + u[0].copy(&ee); + for i in 0..2 { + for j in 0..2 { + t = BIG::new_ints(&rom::CURVE_SB[j][i]); + t = BIG::modmul(&mut v[j], &mut t, &q); + u[i].add(&q); + u[i].sub(&t); + u[i].ctmod(&q,1); + } + } +/* */ + } else { + let x = BIG::new_ints(&rom::CURVE_BNX); + let x2 = BIG::smul(&x, &x); + let bd=q.nbits()-x2.nbits(); + u[0].copy(&ee); + u[0].ctmod(&x2,bd); + u[1].copy(&ee); + u[1].ctdiv(&x2,bd); + u[1].rsub(&q); + } + u +} + +#[allow(non_snake_case)] +/* Galbraith & Scott Method */ +pub fn gs(ee: &BIG) -> [BIG; 4] { + let mut u: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; + let q = BIG::new_ints(&rom::CURVE_ORDER); + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +/* */ + let mut t = BIG::new(); + + let mut v: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; + for i in 0..4 { + t.copy(&BIG::new_ints(&rom::CURVE_WB[i])); + let mut d: DBIG = BIG::mul(&t, &ee); + v[i].copy(&d.ctdiv(&q,t.nbits())); + } + u[0].copy(&ee); + for i in 0..4 { + for j in 0..4 { + t = BIG::new_ints(&rom::CURVE_BB[j][i]); + t = BIG::modmul(&mut v[j], &mut t, &q); + u[i].add(&q); + u[i].sub(&t); + u[i].ctmod(&q,1); + } + } +/* */ + } else { + let x = BIG::new_ints(&rom::CURVE_BNX); + let bd=q.nbits()-x.nbits(); // fixed + + let mut w = BIG::new_copy(&ee); + for i in 0..3 { + u[i].copy(&w); + u[i].ctmod(&x,bd); + w.ctdiv(&x,bd); + } + u[3].copy(&w); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + let mut t = BIG::new(); + t.copy(&BIG::modneg(&u[1], &q)); + u[1].copy(&t); + t.copy(&BIG::modneg(&u[3], &q)); + u[3].copy(&t); + } + } + u +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G1 */ +pub fn g1mul(P: &ECP, e: &BIG) -> ECP { + let mut R = ECP::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GLV { + R.copy(P); + let mut Q = ECP::new(); + Q.copy(P); + Q.affine(); + + let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); + let mut u = glv(&ee); + Q.mulx(&mut cru); + + let mut np = u[0].nbits(); + let mut t: BIG = BIG::modneg(&u[0], &q); + let mut nn = t.nbits(); + if nn < np { + u[0].copy(&t); + R.neg(); + } + + np = u[1].nbits(); + t = BIG::modneg(&u[1], &q); + nn = t.nbits(); + if nn < np { + u[1].copy(&t); + Q.neg(); + } + u[0].norm(); + u[1].norm(); + R = R.mul2(&u[0], &Q, &u[1]); + } else { + R = P.clmul(&ee,&q); + } + R +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G2 */ +pub fn g2mul(P: &ECP2, e: &BIG) -> ECP2 { + let mut R = ECP2::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GS_G2 { + let mut Q: [ECP2; 4] = [ECP2::new(), ECP2::new(), ECP2::new(), ECP2::new()]; + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + + let mut u = gs(&ee); + let mut T = ECP2::new(); + + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + f.inverse(None); + f.norm(); + } + + let mut t = BIG::new(); + Q[0].copy(&P); + for i in 1..4 { + T.copy(&Q[i - 1]); + Q[i].copy(&T); + Q[i].frob(&f); + } + for i in 0..4 { + let np = u[i].nbits(); + t.copy(&BIG::modneg(&u[i], &q)); + let nn = t.nbits(); + if nn < np { + u[i].copy(&t); + Q[i].neg(); + } + u[i].norm(); + } + + R.copy(&ECP2::mul4(&Q, &u)); + } else { + R.copy(&P.mul(&ee)); + } + R +} + +/* f=f^e */ +/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ +pub fn gtpow(d: &FP12, e: &BIG) -> FP12 { + let mut r = FP12::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GS_GT { + let mut g: [FP12; 4] = [FP12::new(), FP12::new(), FP12::new(), FP12::new()]; + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + + let mut t = BIG::new(); + let mut u = gs(&ee); + let mut w = FP12::new(); + + g[0].copy(&d); + for i in 1..4 { + w.copy(&g[i - 1]); + g[i].copy(&w); + g[i].frob(&f); + } + for i in 0..4 { + let np = u[i].nbits(); + t.copy(&BIG::modneg(&u[i], &q)); + let nn = t.nbits(); + if nn < np { + u[i].copy(&t); + g[i].conj(); + } + u[i].norm(); + } + r.copy(&FP12::pow4(&g, &u)); + } else { + r.copy(&d.pow(&ee)); + } + r +} + +/* test G1 group membership */ +#[allow(non_snake_case)] +pub fn g1member(P: &ECP) -> bool { + //let q = BIG::new_ints(&rom::CURVE_ORDER); + if P.is_infinity() { + return false; + } + if ecp::CURVE_PAIRING_TYPE != ecp::BN { + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); + let mut W=ECP::new(); W.copy(P); W.mulx(&mut cru); + let mut T=P.mul(&x); + if P.equals(&T) {return false;} // P is of low order + + T=T.mul(&x); T.neg(); + if !W.equals(&T) { + return false; + } + +// Not needed +// W.add(P); T.mulx(&mut cru); W.add(&T); +// if !W.is_infinity() { +// return false; +// } +/* + let W=P.mul(&q); + if !W.is_infinity() { + return false; + } */ + } + true +} + +/* test G2 group membership */ +#[allow(non_snake_case)] +pub fn g2member(P: &ECP2) -> bool { + if P.is_infinity() { + return false; + } + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + f.inverse(None); + f.norm(); + } + let x = BIG::new_ints(&rom::CURVE_BNX); + + let mut W=ECP2::new(); + let mut T=P.mul(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + T.neg(); + } + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +//https://eprint.iacr.org/2022/348.pdf + W.copy(&T); + W.frob(&f); + T.add(P); + T.add(&W); + W.frob(&f); + T.add(&W); + W.frob(&f); + W.dbl(); + } else { +//https://eprint.iacr.org/2021/1130 + W.copy(P); W.frob(&f); + } + + if !W.equals(&T) { + return false; + } + true +} + +/* Check that m is in cyclotomic sub-group */ +/* Check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ +pub fn gtcyclotomic(m: &FP12) -> bool { + if m.isunity() { + return false; + } + let mut r = FP12::new_copy(&m); + r.conj(); + r.mul(&m); + if !r.isunity() { + return false; + } + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + r.copy(&m); r.frob(&f); r.frob(&f); + let mut w = FP12::new_copy(&r); w.frob(&f); w.frob(&f); + w.mul(&m); + if !w.equals(&r) { + return false; + } + return true; +} + +/* test for full GT group membership */ +pub fn gtmember(m: &FP12) -> bool { + if !gtcyclotomic(m) { + return false; + } + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + + let mut r=FP12::new(); + let mut t=m.pow(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + t.conj(); + } + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +//https://eprint.iacr.org/2022/348.pdf + r.copy(&t); + r.frob(&f); + t.mul(m); + t.mul(&r); + r.frob(&f); + t.mul(&r); + r.frob(&f); + r.usqr(); + } else { +//https://eprint.iacr.org/2021/1130 + r.copy(m); r.frob(&f); + } + + if !r.equals(&t) { + return false; + } + + true +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/rom.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/rom.rs new file mode 100644 index 000000000000..b53157c96674 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/bn254/rom.rs @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use crate::arch::Chunk; +use crate::bn254::big::NLEN; + +// BN254 Modulus +// Base Bits= 56 +pub const MODULUS: [Chunk; NLEN] = [0x13, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const ROI: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const R2MODP: [Chunk; NLEN] = [ + 0x2F2A96FF5E7E39, + 0x64E8642B96F13C, + 0x9926F7B00C7146, + 0x8321E7B4DACD24, + 0x1D127A2E, +]; +pub const MCONST: Chunk = 0x435E50D79435E5; +pub const SQRTM3:[Chunk;NLEN]=[0x4,0x60C,0x3CF0F,0x4000000126CD89,0x25236482]; +pub const FRA: [Chunk; NLEN] = [ + 0x7DE6C06F2A6DE9, + 0x74924D3F77C2E1, + 0x50A846953F8509, + 0x212E7C8CB6499B, + 0x1B377619, +]; +pub const FRB: [Chunk; NLEN] = [ + 0x82193F90D5922A, + 0x8B6DB2C08850C5, + 0x2F57B96AC8DC17, + 0x1ED1837503EAB2, + 0x9EBEE69, +]; + +pub const CURVE_COF_I: isize = 1; +pub const CURVE_B_I: isize = 2; +pub const CURVE_B: [Chunk; NLEN] = [0x2, 0x0, 0x0, 0x0, 0x0]; +pub const CURVE_ORDER: [Chunk; NLEN] = [ + 0xD, + 0x800000000010A1, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, +]; +pub const CURVE_GX: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const CURVE_GY: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; +pub const CURVE_HTPC:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0]; +pub const CURVE_BNX: [Chunk; NLEN] = [0x80000000000001, 0x40, 0x0, 0x0, 0x0]; +pub const CURVE_COF: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; +pub const CRU: [Chunk; NLEN] = [0x80000000000007, 0x6CD, 0x40000000024909, 0x49B362, 0x0]; +pub const CURVE_PXA: [Chunk; NLEN] = [ + 0xEE4224C803FB2B, + 0x8BBB4898BF0D91, + 0x7E8C61EDB6A464, + 0x519EB62FEB8D8C, + 0x61A10BB, +]; +pub const CURVE_PXB: [Chunk; NLEN] = [ + 0x8C34C1E7D54CF3, + 0x746BAE3784B70D, + 0x8C5982AA5B1F4D, + 0xBA737833310AA7, + 0x516AAF9, +]; +pub const CURVE_PYA: [Chunk; NLEN] = [ + 0xF0E07891CD2B9A, + 0xAE6BDBE09BD19, + 0x96698C822329BD, + 0x6BAF93439A90E0, + 0x21897A0, +]; +pub const CURVE_PYB: [Chunk; NLEN] = [ + 0x2D1AEC6B3ACE9B, + 0x6FFD739C9578A, + 0x56F5F38D37B090, + 0x7C8B15268F6D44, + 0xEBB2B0E, +]; +pub const CURVE_W: [[Chunk; NLEN]; 2] = [ + [0x3, 0x80000000000204, 0x6181, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], +]; +pub const CURVE_SB: [[[Chunk; NLEN]; 2]; 2] = [ + [ + [0x4, 0x80000000000285, 0x6181, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x81, 0x0, 0x0, 0x0], + [0xA, 0xE9D, 0x80000000079E1E, 0x40000001BA344D, 0x25236482], + ], +]; +pub const CURVE_WB: [[Chunk; NLEN]; 4] = [ + [0x80000000000000, 0x80000000000040, 0x2080, 0x0, 0x0], + [0x80000000000005, 0x54A, 0x8000000001C707, 0x312241, 0x0], + [ + 0x80000000000003, + 0x800000000002C5, + 0xC000000000E383, + 0x189120, + 0x0, + ], + [0x80000000000001, 0x800000000000C1, 0x2080, 0x0, 0x0], +]; +pub const CURVE_BB: [[[Chunk; NLEN]; 4]; 4] = [ + [ + [ + 0x8000000000000D, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [0x2, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x81, 0x0, 0x0, 0x0], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000D, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + ], + [ + [0x2, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x80000000000002, 0x40, 0x0, 0x0, 0x0], + [0x2, 0x102, 0x0, 0x0, 0x0], + [ + 0xA, + 0x80000000001020, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [0x80000000000002, 0x40, 0x0, 0x0, 0x0], + ], +]; + +pub const USE_GLV: bool = true; +pub const USE_GS_G2: bool = true; +pub const USE_GS_GT: bool = true; +pub const GT_STRONG: bool = false; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/dilithium.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/dilithium.rs new file mode 100644 index 000000000000..8f5b186b640e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/dilithium.rs @@ -0,0 +1,1248 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Dilithium API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. + +Note that the Matrix A is calculated on-the-fly to keep memory requirement minimal +But this makes all stages much slower +Note that +1. Matrix A can just be generated randomly for Key generation (without using SHA3 which is very slow) +2. A precalculated A can be included in the public key, for use by signature and verification (which blows up public key size) +3. Precalculating A for signature calculation means that the A does not have to re-calculated for each attempt to find a good signature + +Might be simpler to wait for hardware support for SHA3! + + M.Scott 30/09/2021 +*/ + +use crate::sha3; +use crate::sha3::SHA3; + +//q= 8380417 +const LGN: usize = 8; +const DEGREE: usize = 1 << LGN; +const PRIME: i32 = 0x7fe001; +const D: usize = 13; +const TD: usize = 23 - D; + +const ONE: i32 = 0x3FFE00; // R mod Q +const COMBO: i32 = 0xA3FA; // ONE*inv mod Q +const ND: u32 = 0xFC7FDFFF; // 1/(R-Q) mod R +const R2MODP: u64 = 0x2419FF; // R^2 mod Q + +const MAXLG: usize = 19; +const MAXK: usize = 8; // could reduce these if not using highest security +const MAXL: usize = 7; +const YBYTES: usize = ((MAXLG + 1) * DEGREE) / 8; + +pub const SK_SIZE_2: usize = 32 * 3 + DEGREE * (4 * 13 + 4 * 3 + 4 * 3) / 8; +pub const PK_SIZE_2: usize = (4 * DEGREE * TD) / 8 + 32; +pub const SIG_SIZE_2: usize = (DEGREE * 4 * (17 + 1)) / 8 + 80 + 4 + 32; + +pub const SK_SIZE_3: usize = 32 * 3 + DEGREE * (6 * 13 + 5 * 4 + 6 * 4) / 8; +pub const PK_SIZE_3: usize = (6 * DEGREE * TD) / 8 + 32; +pub const SIG_SIZE_3: usize = (DEGREE * 5 * (19 + 1)) / 8 + 55 + 6 + 32; + +pub const SK_SIZE_5: usize = 32 * 3 + DEGREE * (8 * 13 + 7 * 3 + 8 * 3) / 8; +pub const PK_SIZE_5: usize = (8 * DEGREE * TD) / 8 + 32; +pub const SIG_SIZE_5: usize = (DEGREE * 7 * (19 + 1)) / 8 + 75 + 8 + 32; + +// parameters for each security level +// tau,gamma1,gamma2,K,L,eta,lg(2*eta+1),omega +const PARAMS_2: [usize; 8] = [39, 17, 88, 4, 4, 2, 3, 80]; +const PARAMS_3: [usize; 8] = [49, 19, 32, 6, 5, 4, 4, 55]; +const PARAMS_5: [usize; 8] = [60, 19, 32, 8, 7, 2, 3, 75]; + +const ROOTS: [i32; 256] = [ + 0x3ffe00, 0x64f7, 0x581103, 0x77f504, 0x39e44, 0x740119, 0x728129, 0x71e24, 0x1bde2b, 0x23e92b, + 0x7a64ae, 0x5ff480, 0x2f9a75, 0x53db0a, 0x2f7a49, 0x28e527, 0x299658, 0xfa070, 0x6f65a5, + 0x36b788, 0x777d91, 0x6ecaa1, 0x27f968, 0x5fb37c, 0x5f8dd7, 0x44fae8, 0x6a84f8, 0x4ddc99, + 0x1ad035, 0x7f9423, 0x3d3201, 0x445c5, 0x294a67, 0x17620, 0x2ef4cd, 0x35dec5, 0x668504, + 0x49102d, 0x5927d5, 0x3bbeaf, 0x44f586, 0x516e7d, 0x368a96, 0x541e42, 0x360400, 0x7b4a4e, + 0x23d69c, 0x77a55e, 0x65f23e, 0x66cad7, 0x357e1e, 0x458f5a, 0x35843f, 0x5f3618, 0x67745d, + 0x38738c, 0xc63a8, 0x81b9a, 0xe8f76, 0x3b3853, 0x3b8534, 0x58dc31, 0x1f9d54, 0x552f2e, + 0x43e6e6, 0x688c82, 0x47c1d0, 0x51781a, 0x69b65e, 0x3509ee, 0x2135c7, 0x67afbc, 0x6caf76, + 0x1d9772, 0x419073, 0x709cf7, 0x4f3281, 0x4fb2af, 0x4870e1, 0x1efca, 0x3410f2, 0x70de86, + 0x20c638, 0x296e9f, 0x5297a4, 0x47844c, 0x799a6e, 0x5a140a, 0x75a283, 0x6d2114, 0x7f863c, + 0x6be9f8, 0x7a0bde, 0x1495d4, 0x1c4563, 0x6a0c63, 0x4cdbea, 0x40af0, 0x7c417, 0x2f4588, 0xad00, + 0x6f16bf, 0xdcd44, 0x3c675a, 0x470bcb, 0x7fbe7f, 0x193948, 0x4e49c1, 0x24756c, 0x7ca7e0, + 0xb98a1, 0x6bc809, 0x2e46c, 0x49a809, 0x3036c2, 0x639ff7, 0x5b1c94, 0x7d2ae1, 0x141305, + 0x147792, 0x139e25, 0x67b0e1, 0x737945, 0x69e803, 0x51cea3, 0x44a79d, 0x488058, 0x3a97d9, + 0x1fea93, 0x33ff5a, 0x2358d4, 0x3a41f8, 0x4cdf73, 0x223dfb, 0x5a8ba0, 0x498423, 0x412f5, + 0x252587, 0x6d04f1, 0x359b5d, 0x4a28a1, 0x4682fd, 0x6d9b57, 0x4f25df, 0xdbe5e, 0x1c5e1a, + 0xde0e6, 0xc7f5a, 0x78f83, 0x67428b, 0x7f3705, 0x77e6fd, 0x75e022, 0x503af7, 0x1f0084, + 0x30ef86, 0x49997e, 0x77dcd7, 0x742593, 0x4901c3, 0x53919, 0x4610c, 0x5aad42, 0x3eb01b, + 0x3472e7, 0x4ce03c, 0x1a7cc7, 0x31924, 0x2b5ee5, 0x291199, 0x585a3b, 0x134d71, 0x3de11c, + 0x130984, 0x25f051, 0x185a46, 0x466519, 0x1314be, 0x283891, 0x49bb91, 0x52308a, 0x1c853f, + 0x1d0b4b, 0x6fd6a7, 0x6b88bf, 0x12e11b, 0x4d3e3f, 0x6a0d30, 0x78fde5, 0x1406c7, 0x327283, + 0x61ed6f, 0x6c5954, 0x1d4099, 0x590579, 0x6ae5ae, 0x16e405, 0xbdbe7, 0x221de8, 0x33f8cf, + 0x779935, 0x54aa0d, 0x665ff9, 0x63b158, 0x58711c, 0x470c13, 0x910d8, 0x463e20, 0x612659, + 0x251d8b, 0x2573b7, 0x7d5c90, 0x1ddd98, 0x336898, 0x2d4bb, 0x6d73a8, 0x4f4cbf, 0x27c1c, + 0x18aa08, 0x2dfd71, 0xc5ca5, 0x19379a, 0x478168, 0x646c3e, 0x51813d, 0x35c539, 0x3b0115, + 0x41dc0, 0x21c4f7, 0x70fbf5, 0x1a35e7, 0x7340e, 0x795d46, 0x1a4cd0, 0x645caf, 0x1d2668, + 0x666e99, 0x6f0634, 0x7be5db, 0x455fdc, 0x530765, 0x5dc1b0, 0x7973de, 0x5cfd0a, 0x2cc93, + 0x70f806, 0x189c2a, 0x49c5aa, 0x776a51, 0x3bcf2c, 0x7f234f, 0x6b16e0, 0x3c15ca, 0x155e68, + 0x72f6b7, 0x1e29ce, +]; +const IROOTS: [i32; 256] = [ + 0x3ffe00, 0x7f7b0a, 0x7eafd, 0x27cefe, 0x78c1dd, 0xd5ed8, 0xbdee8, 0x7c41bd, 0x56fada, + 0x5065b8, 0x2c04f7, 0x50458c, 0x1feb81, 0x57b53, 0x5bf6d6, 0x6401d6, 0x7b9a3c, 0x42ae00, + 0x4bde, 0x650fcc, 0x320368, 0x155b09, 0x3ae519, 0x20522a, 0x202c85, 0x57e699, 0x111560, + 0x86270, 0x492879, 0x107a5c, 0x703f91, 0x5649a9, 0x2ab0d3, 0x6042ad, 0x2703d0, 0x445acd, + 0x44a7ae, 0x71508b, 0x77c467, 0x737c59, 0x476c75, 0x186ba4, 0x20a9e9, 0x4a5bc2, 0x3a50a7, + 0x4a61e3, 0x19152a, 0x19edc3, 0x83aa3, 0x5c0965, 0x495b3, 0x49dc01, 0x2bc1bf, 0x49556b, + 0x2e7184, 0x3aea7b, 0x442152, 0x26b82c, 0x36cfd4, 0x195afd, 0x4a013c, 0x50eb34, 0x7e69e1, + 0x56959a, 0x454828, 0x375fa9, 0x3b3864, 0x2e115e, 0x15f7fe, 0xc66bc, 0x182f20, 0x6c41dc, + 0x6b686f, 0x6bccfc, 0x2b520, 0x24c36d, 0x1c400a, 0x4fa93f, 0x3637f8, 0x7cfb95, 0x1417f8, + 0x744760, 0x33821, 0x5b6a95, 0x319640, 0x66a6b9, 0x2182, 0x38d436, 0x4378a7, 0x7212bd, + 0x10c942, 0x7f3301, 0x509a79, 0x781bea, 0x7bd511, 0x330417, 0x15d39e, 0x639a9e, 0x6b4a2d, + 0x5d423, 0x13f609, 0x59c5, 0x12beed, 0xa3d7e, 0x25cbf7, 0x64593, 0x385bb5, 0x2d485d, 0x567162, + 0x5f19c9, 0xf017b, 0x4bcf0f, 0x7df037, 0x376f20, 0x302d52, 0x30ad80, 0xf430a, 0x3e4f8e, + 0x62488f, 0x13308b, 0x183045, 0x5eaa3a, 0x4ad613, 0x1629a3, 0x2e67e7, 0x381e31, 0x17537f, + 0x3bf91b, 0x61b633, 0xce94a, 0x6a8199, 0x43ca37, 0x14c921, 0xbcb2, 0x4410d5, 0x875b0, 0x361a57, + 0x6743d7, 0xee7fb, 0x7d136e, 0x22e2f7, 0x66c23, 0x221e51, 0x2cd89c, 0x3a8025, 0x3fa26, + 0x10d9cd, 0x197168, 0x62b999, 0x1b8352, 0x659331, 0x682bb, 0x78abf3, 0x65aa1a, 0xee40c, + 0x5e1b0a, 0x7bc241, 0x44deec, 0x4a1ac8, 0x2e5ec4, 0x1b73c3, 0x385e99, 0x66a867, 0x73835c, + 0x51e290, 0x6735f9, 0x7d63e5, 0x309342, 0x126c59, 0x7d0b46, 0x4c7769, 0x620269, 0x28371, + 0x5a6c4a, 0x5ac276, 0x1eb9a8, 0x39a1e1, 0x76cf29, 0x38d3ee, 0x276ee5, 0x1c2ea9, 0x198008, + 0x2b35f4, 0x846cc, 0x4be732, 0x5dc219, 0x74041a, 0x68fbfc, 0x14fa53, 0x26da88, 0x629f68, + 0x1386ad, 0x1df292, 0x4d6d7e, 0x6bd93a, 0x6e21c, 0x15d2d1, 0x32a1c2, 0x6cfee6, 0x145742, + 0x10095a, 0x62d4b6, 0x635ac2, 0x2daf77, 0x362470, 0x57a770, 0x6ccb43, 0x397ae8, 0x6785bb, + 0x59efb0, 0x6cd67d, 0x41fee5, 0x6c9290, 0x2785c6, 0x56ce68, 0x54811c, 0x7cc6dd, 0x65633a, + 0x32ffc5, 0x4b6d1a, 0x412fe6, 0x2532bf, 0x7b7ef5, 0x7aa6e8, 0x36de3e, 0xbba6e, 0x8032a, + 0x364683, 0x4ef07b, 0x60df7d, 0x2fa50a, 0x9ffdf, 0x7f904, 0xa8fc, 0x189d76, 0x78507e, 0x7360a7, + 0x71ff1b, 0x6381e7, 0x7221a3, 0x30ba22, 0x1244aa, 0x395d04, 0x35b760, 0x4a44a4, 0x12db10, + 0x5aba7a, 0x7bcd0c, 0x365bde, 0x255461, 0x5da206, 0x33008e, 0x459e09, 0x5c872d, 0x4be0a7, + 0x5ff56e, +]; + +/* Montgomery stuff */ + +fn redc(t: u64) -> i32 { + let m = (t as u32).wrapping_mul(ND); + (((m as u64) * (PRIME as u64) + t) >> 32) as i32 +} + +fn nres(x: i32) -> i32 { + redc((x as u64) * R2MODP) +} + +fn modmul(a: i32, b: i32) -> i32 { + redc((a as u64) * (b as u64)) +} + +fn poly_pos(p: &mut [i32]) { + for j in 0..DEGREE { + p[j] += (p[j] >> 31) & PRIME; + } +} +// NTT code + +// Important! +// nres(x); ntt(x) +// nres(y); ntt(y) +// z=x*y +// intt(z); +// redc(z); + +// is equivalent to (note that nres() and redc() cancel out) + +// ntt(x); +// nres(y); ntt(y); +// z=x*y +// intt(z) + +// is equivalent to + +// ntt(x) +// ntt(y) +// z=x*y +// intt(z) +// nres(z) + +// In all cases z ends up in normal (non-Montgomery) form! +// So the conversion to Montgomery form can be "pushed" through the calculation. + +// Here intt(z) <- intt(z);nres(z); +// Combining is more efficient +// note that ntt() and intt() are not mutually inverse + +/* Cooley-Tukey NTT */ +/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ +fn ntt(x: &mut [i32]) { + let mut t = DEGREE / 2; + let q = PRIME; + + /* Make positive */ + poly_pos(x); + + let mut m = 1; + while m < DEGREE { + let mut k = 0; + for i in 0..m { + let s = ROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = modmul(x[j + t], s); + x[j] = u + v; + x[j + t] = u + 2 * q - v; + } + k += 2 * t; + } + t /= 2; + m *= 2; + } +} + +/* Gentleman-Sande INTT */ +/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ +/* Output fully reduced */ + +const NTTL: usize = 2; // maybe could be 1? + +fn intt(x: &mut [i32]) { + let mut t = 1; + let q = PRIME; + let mut m = DEGREE / 2; + let mut n = LGN; + while m >= 1 { + let lim = NTTL >> n; + n -= 1; + let mut k = 0; + for i in 0..m { + let s = IROOTS[m + i]; + for j in k..k + t { + let u: i32; + let v: i32; + if m < NTTL && j < k + lim { + u = modmul(x[j], ONE); + v = modmul(x[j + t], ONE); + } else { + u = x[j]; + v = x[j + t]; + } + x[j] = u + v; + let w = u + ((DEGREE / NTTL) as i32) * q - v; + x[j + t] = modmul(w, s); + } + k += 2 * t; + } + t *= 2; + m /= 2; + } + + // fully reduce, nres combined with 1/DEGREE + for j in 0..DEGREE { + x[j] = modmul(x[j], COMBO); + x[j] -= q; + x[j] += (x[j] >> 31) & q; + } +} + +fn nres_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = nres(p[i]); + } +} + +fn redc_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = redc(p[i] as u64); + } +} + +fn poly_copy(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = p3[i]; + } +} + +fn poly_scopy(p1: &mut [i32], p3: &[i8]) { + for i in 0..DEGREE { + p1[i] = p3[i] as i32; + } +} + +fn poly_mcopy(p1: &mut [i32], p3: &[i16]) { + for i in 0..DEGREE { + p1[i] = p3[i] as i32; + } +} + +fn poly_zero(p1: &mut [i32]) { + for i in 0..DEGREE { + p1[i] = 0; + } +} + +fn poly_negate(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = PRIME - p3[i]; + } +} + +fn poly_mul(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = modmul(p1[i], p3[i]); + } +} + +fn poly_add(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += p3[i]; + } +} + +fn poly_sub(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += PRIME - p3[i]; + } +} + +/* reduces inputs < 2q */ +fn poly_soft_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let e = poly[i] - PRIME; + poly[i] = e + ((e >> 31) & PRIME); + } +} + +/* fully reduces modulo q */ +fn poly_hard_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let mut e = modmul(poly[i], ONE); + e -= PRIME; + poly[i] = e + ((e >> 31) & PRIME); + } +} + +// Generate a[i][j] from rho +fn expandaij(rho: &[u8], aij: &mut [i32], i: usize, j: usize) { + let mut buff: [u8; 4 * DEGREE] = [0; 4 * DEGREE]; + let mut sh = SHA3::new(sha3::SHAKE128); + for m in 0..32 { + sh.process(rho[m]) + } + sh.process(j as u8); + sh.process(i as u8); + sh.shake(&mut buff, 4 * DEGREE); + let mut m = 0; + let mut n = 0; + while m < DEGREE { + let b0 = buff[n] as u32; + let b1 = buff[n + 1] as u32; + let b2 = buff[n + 2] as u32; + let cf = (((b2 & 0x7f) << 16) + (b1 << 8) + b0) as i32; + n += 3; + if cf >= PRIME { + continue; + } + aij[m] = cf; + m += 1; + } +} + +// array t has ab active bits per word +// extract bytes from array of words +// if mx!=0 then -mx<=t[i]<=+mx +fn nextbyte32(ab: usize, mx: usize, t: &[i32], ptr: &mut usize, bts: &mut usize) -> u8 { + let mut left = ab - *bts; + let mut w = t[*ptr]; + let mxm = mx as i32; + if mxm != 0 { + w = mxm - w; + } + let mut r = w >> *bts; + let mut i = 0; + while left < 8 { + i += 1; + w = t[(*ptr) + i]; + if mxm != 0 { + w = mxm - w; + } + r |= w << left; + left += ab; + } + *bts += 8; + while *bts >= ab { + *bts -= ab; + *ptr += 1; + } + r as u8 +} + +fn nextbyte16(ab: usize, mx: usize, t: &[i16], ptr: &mut usize, bts: &mut usize) -> u8 { + let mut left = ab - *bts; + let mut w = t[*ptr]; + let mxm = mx as i16; + if mxm != 0 { + w = mxm - w; + } + let mut r = w >> *bts; + let mut i = 0; + while left < 8 { + i += 1; + w = t[(*ptr) + i]; + if mxm != 0 { + w = mxm - w; + } + r |= w << left; + left += ab; + } + *bts += 8; + while *bts >= ab { + *bts -= ab; + *ptr += 1; + } + r as u8 +} + +fn nextbyte8(ab: usize, mx: usize, t: &[i8], ptr: &mut usize, bts: &mut usize) -> u8 { + let mut left = ab - *bts; + let mut w = t[*ptr]; + let mxm = mx as i8; + if mxm != 0 { + w = mxm - w; + } + let mut r = w >> *bts; + let mut i = 0; + while left < 8 { + i += 1; + w = t[(*ptr) + i]; + if mxm != 0 { + w = mxm - w; + } + r |= w << left; + left += ab; + } + *bts += 8; + while *bts >= ab { + *bts -= ab; + *ptr += 1; + } + r as u8 +} + +fn nextword(ab: usize, mx: usize, t: &[u8], ptr: &mut usize, bts: &mut usize) -> i32 { + let mut r = (t[*ptr] >> *bts) as i32; + let mxm = mx as i32; + let mask = (1 << ab) - 1; + let mut w: i32; + let mut i = 0; + let mut gotbits = 8 - *bts; + while gotbits < ab { + i += 1; + w = t[(*ptr) + i] as i32; + r |= w << gotbits; + gotbits += 8; + } + *bts += ab; + while *bts >= 8 { + *bts -= 8; + *ptr += 1; + } + w = r & mask; + if mxm != 0 { + w = mxm - w; + } + w +} + +fn pack_pk(params: &[usize], pk: &mut [u8], rho: &[u8], t1: &[i16]) { + let ck = params[3]; + for i in 0..32 { + pk[i] = rho[i]; + } + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + let mut n = 32; + for _ in 0..(ck * DEGREE * TD) / 8 { + pk[n] = nextbyte16(TD, 0, t1, &mut ptr, &mut bts); + n += 1; + } +} + +fn unpack_pk(params: &[usize], rho: &mut [u8], t1: &mut [i16], pk: &[u8]) { + let ck = params[3]; + for i in 0..32 { + rho[i] = pk[i]; + } + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + for i in 0..ck * DEGREE { + t1[i] = nextword(TD, 0, &pk[32..], &mut ptr, &mut bts) as i16; + } +} + +fn pack_sk( + params: &[usize], + sk: &mut [u8], + rho: &[u8], + bk: &[u8], + tr: &[u8], + s1: &[i8], + s2: &[i8], + t0: &[i16], +) { + let ck = params[3]; + let el = params[4]; + let eta = params[5]; + let lg2eta1 = params[6]; + + for i in 0..32 { + sk[i] = rho[i]; + } + let mut n = 32; + for i in 0..32 { + sk[n] = bk[i]; + n += 1; + } + for i in 0..32 { + sk[n] = tr[i]; + n += 1; + } + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for _ in 0..(el * DEGREE * lg2eta1) / 8 { + sk[n] = nextbyte8(lg2eta1, eta, s1, &mut ptr, &mut bts); + n += 1; + } + ptr = 0; + bts = 0; + for _ in 0..(ck * DEGREE * lg2eta1) / 8 { + sk[n] = nextbyte8(lg2eta1, eta, s2, &mut ptr, &mut bts); + n += 1; + } + ptr = 0; + bts = 0; + for _ in 0..(ck * DEGREE * D) / 8 { + sk[n] = nextbyte16(D, 1 << (D - 1), t0, &mut ptr, &mut bts); + n += 1; + } +} + +fn unpack_sk( + params: &[usize], + rho: &mut [u8], + bk: &mut [u8], + tr: &mut [u8], + s1: &mut [i8], + s2: &mut [i8], + t0: &mut [i16], + sk: &[u8], +) { + let ck = params[3]; + let el = params[4]; + let eta = params[5]; + let lg2eta1 = params[6]; + + for i in 0..32 { + rho[i] = sk[i]; + } + let mut n = 32; + for i in 0..32 { + bk[i] = sk[n]; + n += 1; + } + for i in 0..32 { + tr[i] = sk[n]; + n += 1; + } + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for i in 0..el * DEGREE { + s1[i] = nextword(lg2eta1, eta, &sk[n..], &mut ptr, &mut bts) as i8; + } + n += ptr; + ptr = 0; + bts = 0; + for i in 0..ck * DEGREE { + s2[i] = nextword(lg2eta1, eta, &sk[n..], &mut ptr, &mut bts) as i8; + } + n += ptr; + ptr = 0; + bts = 0; + for i in 0..ck * DEGREE { + t0[i] = nextword(D, 1 << (D - 1), &sk[n..], &mut ptr, &mut bts) as i16; + } +} + +// pack signature - changes z +fn pack_sig(params: &[usize], sig: &mut [u8], z: &mut [i32], ct: &[u8], h: &[u8]) { + let lg = params[1]; + let gamma1 = 1 << lg; + let ck = params[3]; + let el = params[4]; + let omega = params[7]; + + for i in 0..32 { + sig[i] = ct[i]; + } + let mut n = 32; + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for i in 0..el { + let row = DEGREE * i; + for m in 0..DEGREE { + let mut t = z[row + m]; + if t > PRIME / 2 { + t -= PRIME; + } + t = gamma1 - t; + z[row + m] = t; + } + } + for _ in 0..(el * DEGREE * (lg + 1)) / 8 { + sig[n] = nextbyte32(lg + 1, 0, z, &mut ptr, &mut bts); + n += 1; + } + for i in 0..omega + ck { + sig[n] = h[i]; + n += 1; + } +} + +fn unpack_sig(params: &[usize], z: &mut [i32], ct: &mut [u8], h: &mut [u8], sig: &[u8]) { + let lg = params[1]; + let gamma1 = 1 << lg; + let ck = params[3]; + let el = params[4]; + let omega = params[7]; + + for i in 0..32 { + ct[i] = sig[i]; + } + + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for i in 0..el * DEGREE { + let mut t = nextword(lg + 1, 0, &sig[32..], &mut ptr, &mut bts); + t = gamma1 - t; + if t < 0 { + t += PRIME; + } + z[i] = t; + } + let mut m = 32 + (el * DEGREE * (lg + 1)) / 8; + for i in 0..omega + ck { + h[i] = sig[m]; + m += 1; + } +} + +fn sample_sn(params: &[usize], rhod: &[u8], s: &mut [i8], n: usize) { + let mut buff: [u8; 272] = [0; 272]; + let mut sh = SHA3::new(sha3::SHAKE256); + for m in 0..64 { + sh.process(rhod[m]); + } + sh.process((n & 0xff) as u8); + sh.process(((n >> 8) & 0xff) as u8); + sh.shake(&mut buff, 272); + + let eta = params[5]; + let lg2eta1 = params[6]; + + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + for m in 0..DEGREE { + loop { + s[m] = nextword(lg2eta1, 0, &buff, &mut ptr, &mut bts) as i8; + if s[m] <= 2 * (eta as i8) { + break; + } + } + s[m] = (eta as i8) - s[m]; + } +} + +fn sample_y(params: &[usize], k: usize, rhod: &[u8], y: &mut [i32]) { + let lg = params[1]; + let gamma1 = 1 << lg; + let el = params[4]; + let mut buff: [u8; YBYTES] = [0; YBYTES]; + for i in 0..el { + let row = DEGREE * i; + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..64 { + sh.process(rhod[j]); + } + let ki = k + i; + sh.process((ki & 0xff) as u8); + sh.process((ki >> 8) as u8); + sh.shake(&mut buff, ((lg + 1) * DEGREE) / 8); + + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for m in 0..DEGREE { + let mut w = nextword(lg + 1, 0, &buff, &mut ptr, &mut bts); + w = gamma1 - w; + let t = w >> 31; + y[row + m] = w + (PRIME & t); + } + } +} + +fn crh1(params: &[usize], h: &mut [u8], rho: &[u8], t1: &[i16]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(rho[j]); + } + let ck = params[3]; + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for _ in 0..(ck * DEGREE * TD) / 8 { + sh.process(nextbyte16(TD, 0, t1, &mut ptr, &mut bts)); + } + sh.shake(h, 32); +} + +fn crh2(h: &mut [u8], tr: &[u8], mess: &[u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(tr[j]); + } + for j in 0..mess.len() { + sh.process(mess[j]); + } + sh.shake(h, 64); +} + +fn crh3(h: &mut [u8], bk: &[u8], mu: &[u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(bk[j]); + } + for j in 0..64 { + sh.process(mu[j]); + } + sh.shake(h, 64); +} + +fn h4(params: &[usize], ct: &mut [u8], mu: &[u8], w1: &[i8]) { + let ck = params[3]; + let dv = params[2]; + let mut w1b = 4; + if dv == 88 { + w1b = 6; + } + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..64 { + sh.process(mu[j]); + } + + let mut ptr = 0 as usize; + let mut bts = 0 as usize; + + for _ in 0..(ck * DEGREE * w1b) / 8 { + sh.process(nextbyte8(w1b, 0, w1, &mut ptr, &mut bts)); + } + sh.shake(ct, 32); +} + +fn sampleinball(params: &[usize], ct: &[u8], c: &mut [i32]) { + let tau = params[0]; + let mut buff: [u8; 136] = [0; 136]; + let mut signs: [u8; 8] = [0; 8]; + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(ct[j]); + } + sh.shake(&mut buff, 136); + for i in 0..8 { + signs[i] = buff[i]; + } + let mut k = 8; + let mut b = 0; + poly_zero(c); + let mut j: usize; + let mut n = 1; + let mut sn = signs[0]; + for i in DEGREE - tau..DEGREE { + loop { + j = buff[k] as usize; + k += 1; + if j <= i { + break; + } + } + c[i] = c[j]; + c[j] = 1 - 2 * ((sn as i32) & 1); + sn >>= 1; + b += 1; + if b == 8 { + sn = signs[n]; + n += 1; + b = 0; + } + } +} + +fn p2r(r0: &mut i32) -> i16 { + let d = (1 << D) as i32; + let r1 = (*r0 + d / 2 - 1) >> D; + *r0 -= r1 << D; + r1 as i16 +} + +fn power2round(t: &[i32], t0: &mut [i16], t1: &mut [i16]) { + for m in 0..DEGREE { + let mut w = t[m]; + t1[m] = p2r(&mut w); + t0[m] = w as i16; + } +} + +fn decompose_lo(params: &[usize], a: i32) -> i32 { + let dv = params[2]; + let mut a1 = (a + 127) >> 7; + let gamma2: i32; + if dv == 32 { + a1 = (a1 * 1025 + (1 << 21)) >> 22; + a1 &= 15; + gamma2 = (PRIME - 1) / 32; + } else { + // 88 + a1 = (a1 * 11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; + gamma2 = (PRIME - 1) / 88; + } + + let mut a0 = a - a1 * 2 * gamma2; + a0 -= (((PRIME - 1) / 2 - a0) >> 31) & PRIME; + a0 += (a0 >> 31) & PRIME; + a0 +} + +fn decompose_hi(params: &[usize], a: i32) -> i8 { + let dv = params[2]; + + let mut a1 = (a + 127) >> 7; + if dv == 32 { + a1 = (a1 * 1025 + (1 << 21)) >> 22; + a1 &= 15; + } else { + // 88 + a1 = (a1 * 11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; + } + a1 as i8 +} + +fn lobits(params: &[usize], r0: &mut [i32], r: &[i32]) { + for m in 0..DEGREE { + r0[m] = decompose_lo(params, r[m]); + } +} + +fn hibits(params: &[usize], r1: &mut [i8], r: &[i32]) { + for m in 0..DEGREE { + r1[m] = decompose_hi(params, r[m]); + } +} + +fn makepartialhint(params: &[usize], h: &mut [u8], hptr: usize, z: &[i32], r: &[i32]) -> usize { + let mut ptr = hptr; + let omega = params[7]; + for m in 0..DEGREE { + let a0 = decompose_hi(params, r[m]); + let mut rz = r[m] + z[m]; + rz -= PRIME; + rz = rz + ((rz >> 31) & PRIME); + let a1 = decompose_hi(params, rz); + if a0 != a1 { + if ptr >= omega { + return omega + 1; + } + h[ptr] = (m & 0xff) as u8; + ptr += 1; + } + } + ptr +} + +fn usepartialhint( + params: &[usize], + r: &mut [i8], + h: &[u8], + hptr: usize, + i: usize, + w: &[i32], +) -> usize { + let mut ptr = hptr; + let dv = params[2] as i32; + let omega = params[7]; + let md = (dv / 2) as i8; + + for m in 0..DEGREE { + let mut a1 = decompose_hi(params, w[m]); + if m == h[ptr] as usize && ptr < h[omega + i] as usize { + ptr += 1; + let a0 = decompose_lo(params, w[m]); + if a0 <= PRIME / 2 { + a1 += 1; + if a1 >= md { + a1 -= md; + } + } else { + a1 -= 1; + if a1 < 0 { + a1 += md; + } + } + } + r[m] = a1; + } + ptr +} + +fn infinity_norm(w: &[i32]) -> i32 { + let mut n = 0 as i32; + for m in 0..DEGREE { + let mut az = w[m]; + if az > PRIME / 2 { + az = PRIME - az; + } + if az > n { + n = az; + } + } + n +} + +fn keypair(params: &[usize], tau: &[u8], sk: &mut [u8], pk: &mut [u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + let mut buff: [u8; 128] = [0; 128]; + let mut rho: [u8; 32] = [0; 32]; + let mut rhod: [u8; 64] = [0; 64]; + let mut bk: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut s1: [i8; MAXL * DEGREE] = [0; MAXL * DEGREE]; + let mut s2: [i8; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut t0: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut t1: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let ck = params[3]; + let el = params[4]; + + for i in 0..32 { + sh.process(tau[i]); + } + sh.shake(&mut buff, 128); + for i in 0..32 { + rho[i] = buff[i]; + bk[i] = buff[i + 96]; + } + for i in 0..64 { + rhod[i] = buff[i + 32]; + } + + for i in 0..el { + let row = DEGREE * i; + sample_sn(params, &rhod, &mut s1[row..], i); + } + + for i in 0..ck { + let row = DEGREE * i; + sample_sn(params, &rhod, &mut s2[row..], el + i); + poly_zero(&mut r); + for j in 0..el { + poly_scopy(&mut w, &s1[j * DEGREE..]); + ntt(&mut w); + expandaij(&rho, &mut aij, i, j); + poly_mul(&mut w, &aij); + poly_add(&mut r, &w); + } + poly_hard_reduce(&mut r); + intt(&mut r); + poly_scopy(&mut w, &s2[row..]); + poly_pos(&mut w); + poly_add(&mut r, &w); + poly_soft_reduce(&mut r); + power2round(&r, &mut t0[row..], &mut t1[row..]); + } + crh1(params, &mut tr, &rho, &t1); + pack_pk(params, pk, &rho, &t1); + pack_sk(params, sk, &rho, &bk, &tr, &s1, &s2, &t0); +} + +fn signature(params: &[usize], sk: &[u8], m: &[u8], sig: &mut [u8]) -> usize { + let mut rho: [u8; 32] = [0; 32]; + let mut bk: [u8; 32] = [0; 32]; + let mut ct: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut mu: [u8; 64] = [0; 64]; + let mut rhod: [u8; 64] = [0; 64]; + let mut hint: [u8; 100] = [0; 100]; + + //let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut s1: [i8; MAXL * DEGREE] = [0; MAXL * DEGREE]; + let mut s2: [i8; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut t0: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let mut y: [i32; MAXL * DEGREE] = [0; MAXL * DEGREE]; + let mut ay: [i32; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let mut w1: [i8; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let tau = params[0]; + let lg = params[1]; + let gamma1 = (1 << lg) as i32; + let dv = params[2] as i32; + let gamma2 = (PRIME - 1) / dv; + let ck = params[3]; + let el = params[4]; + let eta = params[5]; + let beta = (tau * eta) as i32; + let omega = params[7]; + + unpack_sk( + params, &mut rho, &mut bk, &mut tr, &mut s1, &mut s2, &mut t0, &sk, + ); + + // signature + crh2(&mut mu, &tr, m); + crh3(&mut rhod, &bk, &mu); + let mut k = 0; + + loop { + let fk = k * el; + k += 1; + sample_y(params, fk, &rhod, &mut y); + // NTT y + for i in 0..el { + let row = DEGREE * i; + ntt(&mut y[row..]); + } + // Calculate ay + for i in 0..ck { + let row = DEGREE * i; + poly_zero(&mut r); + for j in 0..el { + poly_copy(&mut w, &y[j * DEGREE..]); + expandaij(&rho, &mut c, i, j); + poly_mul(&mut w, &c); + poly_add(&mut r, &w); + } + poly_hard_reduce(&mut r); + intt(&mut r); + poly_copy(&mut ay[row..], &r); + // Calculate w1 + hibits(params, &mut w1[row..], &ay[row..]); + } + // Calculate c + h4(params, &mut ct, &mu, &w1); + sampleinball(params, &ct, &mut c); + let mut badone = false; + // Calculate z=y+c.s1 + ntt(&mut c); + for i in 0..el { + let row = DEGREE * i; + poly_scopy(&mut w, &s1[row..]); + ntt(&mut w); + poly_mul(&mut w, &c); + + nres_it(&mut w); + poly_add(&mut y[row..], &w); // re-use y for z + redc_it(&mut y[row..]); // unNTT y + intt(&mut y[row..]); + + poly_soft_reduce(&mut y[row..]); + if infinity_norm(&y[row..]) >= gamma1 - beta { + badone = true; + break; + } + } + if badone { + continue; + } + // Calculate ay=w-c.s2 and r0=lobits(w-c.s2) + let mut nh = 0; + for i in 0..omega + ck { + hint[i] = 0; + } + for i in 0..ck { + let row = DEGREE * i; + poly_scopy(&mut w, &s2[row..]); + ntt(&mut w); + poly_mul(&mut w, &c); + intt(&mut w); + poly_sub(&mut ay[row..], &w); + poly_soft_reduce(&mut ay[row..]); + lobits(params, &mut w, &ay[row..]); + if infinity_norm(&w) >= gamma2 - beta { + badone = true; + break; + } + poly_mcopy(&mut w, &t0[row..]); + ntt(&mut w); + poly_mul(&mut w, &c); + intt(&mut w); + poly_negate(&mut r, &w); + if infinity_norm(&r) >= gamma2 { + badone = true; + break; + } + poly_sub(&mut ay[row..], &r); + poly_soft_reduce(&mut ay[row..]); + nh = makepartialhint(params, &mut hint, nh, &r, &ay[row..]); + if nh > omega { + badone = true; + break; + } + hint[omega + i] = nh as u8; + } + if badone { + continue; + } + break; + } + pack_sig(params, sig, &mut y, &ct, &hint); + k +} + +fn verify(params: &[usize], pk: &[u8], m: &[u8], sig: &[u8]) -> bool { + let mut rho: [u8; 32] = [0; 32]; + let mut ct: [u8; 32] = [0; 32]; + let mut cct: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut mu: [u8; 64] = [0; 64]; + let mut hint: [u8; 100] = [0; 100]; + + let mut z: [i32; MAXL * DEGREE] = [0; MAXL * DEGREE]; + let mut t1: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut w1d: [i8; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let tau = params[0]; + let lg = params[1]; + let gamma1 = (1 << lg) as i32; + let ck = params[3]; + let el = params[4]; + let eta = params[5]; + let beta = (tau * eta) as i32; + let omega = params[7]; + + unpack_pk(params, &mut rho, &mut t1, pk); + unpack_sig(params, &mut z, &mut ct, &mut hint, sig); + + for i in 0..el { + let row = DEGREE * i; + if infinity_norm(&z[row..]) >= gamma1 - beta { + return false; + } + ntt(&mut z[row..]); + } + crh1(params, &mut tr, &rho, &t1); + crh2(&mut mu, &tr, m); + + sampleinball(params, &ct, &mut c); + ntt(&mut c); + + // Calculate az + let mut hints = 0; + for i in 0..ck { + let row = DEGREE * i; + poly_zero(&mut r); + for j in 0..el { + poly_copy(&mut w, &z[j * DEGREE..]); + expandaij(&rho, &mut aij, i, j); + poly_mul(&mut w, &aij); + poly_add(&mut r, &w); + } + poly_hard_reduce(&mut r); + + // Calculate Az-ct1.2^d + for m in 0..DEGREE { + w[m] = ((t1[row + m]) as i32) << D; + } + ntt(&mut w); + poly_mul(&mut w, &c); + poly_sub(&mut r, &w); + intt(&mut r); + + hints = usepartialhint(params, &mut w1d[row..], &mut hint, hints, i, &r); + if hints > omega { + return false; + } + } + + h4(params, &mut cct, &mu, &w1d); + + for i in 0..32 { + if ct[i] != cct[i] { + return false; + } + } + true +} + +// Dilithium API + +pub fn keypair_2(tau: &[u8], sk: &mut [u8], pk: &mut [u8]) { + keypair(&PARAMS_2, tau, sk, pk); +} + +pub fn signature_2(sk: &[u8], m: &[u8], sig: &mut [u8]) -> usize { + signature(&PARAMS_2, sk, m, sig) +} + +pub fn verify_2(pk: &[u8], m: &[u8], sig: &[u8]) -> bool { + verify(&PARAMS_2, pk, m, sig) +} + +pub fn keypair_3(tau: &[u8], sk: &mut [u8], pk: &mut [u8]) { + keypair(&PARAMS_3, tau, sk, pk); +} + +pub fn signature_3(sk: &[u8], m: &[u8], sig: &mut [u8]) -> usize { + signature(&PARAMS_3, sk, m, sig) +} + +pub fn verify_3(pk: &[u8], m: &[u8], sig: &[u8]) -> bool { + verify(&PARAMS_3, pk, m, sig) +} + +pub fn keypair_5(tau: &[u8], sk: &mut [u8], pk: &mut [u8]) { + keypair(&PARAMS_5, tau, sk, pk); +} + +pub fn signature_5(sk: &[u8], m: &[u8], sig: &mut [u8]) -> usize { + signature(&PARAMS_5, sk, m, sig) +} + +pub fn verify_5(pk: &[u8], m: &[u8], sig: &[u8]) -> bool { + verify(&PARAMS_5, pk, m, sig) +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/gcm.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/gcm.rs new file mode 100644 index 000000000000..27c20d0c0581 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/gcm.rs @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const GCM_NB: usize = 4; +const GCM_ACCEPTING_HEADER: usize = 0; +const GCM_ACCEPTING_CIPHER: usize = 1; +const GCM_NOT_ACCEPTING_MORE: usize = 2; +const GCM_FINISHED: usize = 3; +//const GCM_ENCRYPTING: usize = 0; +//const GCM_DECRYPTING: usize = 1; + +use crate::aes; +use crate::aes::AES; + +pub struct GCM { + table: [[u32; 4]; 128], + statex: [u8; 16], + y_0: [u8; 16], + // counter: usize, + lena: [u32; 2], + lenc: [u32; 2], + status: usize, + a: AES, +} + +impl GCM { + fn pack(b: [u8; 4]) -> u32 { + /* pack bytes into a 32-bit Word */ + ((b[0] as u32) << 24) | ((b[1] as u32) << 16) | ((b[2] as u32) << 8) | (b[3] as u32) + } + + fn unpack(a: u32) -> [u8; 4] { + /* unpack bytes from a word */ + [ + ((a >> 24) & 0xff) as u8, + ((a >> 16) & 0xff) as u8, + ((a >> 8) & 0xff) as u8, + (a & 0xff) as u8, + ] + } + + fn precompute(&mut self, h: &[u8]) { + let mut b: [u8; 4] = [0; 4]; + let mut j = 0; + for i in 0..GCM_NB { + b[0] = h[j]; + b[1] = h[j + 1]; + b[2] = h[j + 2]; + b[3] = h[j + 3]; + self.table[0][i] = GCM::pack(b); + j += 4; + } + for i in 1..128 { + let mut c: u32 = 0; + for j in 0..GCM_NB { + self.table[i][j] = c | (self.table[i - 1][j]) >> 1; + c = self.table[i - 1][j] << 31; + } + if c != 0 { + self.table[i][0] ^= 0xE1000000 + } /* irreducible polynomial */ + } + } + + fn gf2mul(&mut self) { + /* gf2m mul - Z=H*X mod 2^128 */ + let mut p: [u32; 4] = [0; 4]; + + for i in 0..4 { + p[i] = 0 + } + let mut j: usize = 8; + let mut m = 0; + for i in 0..128 { + j -= 1; + let mut c = ((self.statex[m] >> j) & 1) as u32; + c = (!c).wrapping_add(1); // + 1; + for k in 0..GCM_NB { + p[k] ^= self.table[i][k] & c + } + if j == 0 { + j = 8; + m += 1; + if m == 16 { + break; + } + } + } + j = 0; + for i in 0..GCM_NB { + let b = GCM::unpack(p[i]); + self.statex[j] = b[0]; + self.statex[j + 1] = b[1]; + self.statex[j + 2] = b[2]; + self.statex[j + 3] = b[3]; + j += 4; + } + } + + fn wrap(&mut self) { + /* Finish off GHASH */ + let mut f: [u32; 4] = [0; 4]; + let mut el: [u8; 16] = [0; 16]; + + /* convert lengths from bytes to bits */ + f[0] = (self.lena[0] << 3) | (self.lena[1] & 0xE0000000) >> 29; + f[1] = self.lena[1] << 3; + f[2] = (self.lenc[0] << 3) | (self.lenc[1] & 0xE0000000) >> 29; + f[3] = self.lenc[1] << 3; + let mut j = 0; + for i in 0..GCM_NB { + let b = GCM::unpack(f[i]); + el[j] = b[0]; + el[j + 1] = b[1]; + el[j + 2] = b[2]; + el[j + 3] = b[3]; + j += 4; + } + for i in 0..16 { + self.statex[i] ^= el[i] + } + self.gf2mul(); + } + + fn ghash(&mut self, plain: &[u8], len: usize) -> bool { + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + for i in 0..16 { + if j >= len { + break; + } + self.statex[i] ^= plain[j]; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul(); + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Initialize GCM mode */ + pub fn init(&mut self, nk: usize, key: &[u8], niv: usize, iv: &[u8]) { + /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ + let mut h: [u8; 16] = [0; 16]; + + for i in 0..16 { + h[i] = 0; + self.statex[i] = 0 + } + + self.a = AES::new(); + + self.a.init(aes::ECB, nk, key, None); + self.a.ecb_encrypt(&mut h); /* E(K,0) */ + self.precompute(&h); + + self.lena[0] = 0; + self.lenc[0] = 0; + self.lena[1] = 0; + self.lenc[1] = 0; + if niv == 12 { + for i in 0..12 { + self.a.f[i] = iv[i] + } + let b = GCM::unpack(1); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* initialise IV */ + for i in 0..16 { + self.y_0[i] = self.a.f[i] + } + } else { + self.status = GCM_ACCEPTING_CIPHER; + self.ghash(iv, niv); /* GHASH(H,0,IV) */ + self.wrap(); + for i in 0..16 { + self.a.f[i] = self.statex[i]; + self.y_0[i] = self.a.f[i]; + self.statex[i] = 0 + } + self.lena[0] = 0; + self.lenc[0] = 0; + self.lena[1] = 0; + self.lenc[1] = 0; + } + self.status = GCM_ACCEPTING_HEADER; + } + + pub fn new() -> GCM { + GCM { + table: [[0; 4]; 128], + statex: [0; 16], + y_0: [0; 16], + //counter:0, + lena: [0; 2], + lenc: [0; 2], + status: 0, + a: AES::new(), + } + } + + /* Add Header data - included but not encrypted */ + pub fn add_header(&mut self, header: &[u8], len: usize) -> bool { + /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ + if self.status != GCM_ACCEPTING_HEADER { + return false; + } + let mut j = 0; + while j < len { + for i in 0..16 { + if j >= len { + break; + } + self.statex[i] ^= header[j]; + j += 1; + self.lena[1] += 1; + if self.lena[1] == 0 { + self.lena[0] += 1 + } + } + self.gf2mul(); + } + if len % 16 != 0 { + self.status = GCM_ACCEPTING_CIPHER + } + true + } + + /* Add Plaintext - included and encrypted */ + /* if plain is None - encrypts cipher in place */ + pub fn add_plain(&mut self, cipher: &mut [u8], plain: Option<&[u8]>, len: usize) -> bool { + let mut cb: [u8; 16] = [0; 16]; + let mut b: [u8; 4] = [0; 4]; + + let mut counter: u32; + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + b[0] = self.a.f[12]; + b[1] = self.a.f[13]; + b[2] = self.a.f[14]; + b[3] = self.a.f[15]; + counter = GCM::pack(b); + counter += 1; + b = GCM::unpack(counter); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* increment counter */ + for i in 0..16 { + cb[i] = self.a.f[i] + } + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + + for i in 0..16 { + if j >= len { + break; + } + + if let Some(sp) = plain { + cipher[j] = sp[j] ^ cb[i]; + } else { + cipher[j] ^= cb[i]; + } + + self.statex[i] ^= cipher[j]; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul() + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Add Ciphertext - decrypts to plaintext */ + /* if cipher is None - decrypts plain in place */ + pub fn add_cipher(&mut self, plain: &mut [u8], cipher: Option<&[u8]>, len: usize) -> bool { + let mut cb: [u8; 16] = [0; 16]; + let mut b: [u8; 4] = [0; 4]; + + let mut counter: u32; + + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + b[0] = self.a.f[12]; + b[1] = self.a.f[13]; + b[2] = self.a.f[14]; + b[3] = self.a.f[15]; + counter = GCM::pack(b); + counter += 1; + b = GCM::unpack(counter); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* increment counter */ + for i in 0..16 { + cb[i] = self.a.f[i] + } + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + for i in 0..16 { + if j >= len { + break; + } + let oc: u8; + if let Some(sc) = cipher { + oc = sc[j]; + } else { + oc = plain[j]; + } + + plain[j] = oc ^ cb[i]; + self.statex[i] ^= oc; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul() + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Finish and extract Tag */ + pub fn finish(&mut self, tag: &mut [u8], extract: bool) { + /* Finish off GHASH and extract tag (MAC) */ + self.wrap(); + /* extract tag */ + if extract { + self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ + for i in 0..16 { + self.y_0[i] ^= self.statex[i] + } + for i in 0..16 { + tag[i] = self.y_0[i]; + self.y_0[i] = 0; + self.statex[i] = 0 + } + } + self.status = GCM_FINISHED; + self.a.end(); + } + + pub fn hex2bytes(hex: &[u8], bin: &mut [u8]) { + let len = hex.len(); + + for i in 0..len / 2 { + let mut v: u8; + let mut c = hex[2 * i]; + if c >= b'0' && c <= b'9' { + v = c - b'0'; + } else if c >= b'A' && c <= b'F' { + v = c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v = c - b'a' + 10; + } else { + v = 0; + } + v <<= 4; + c = hex[2 * i + 1]; + if c >= b'0' && c <= b'9' { + v += c - b'0'; + } else if c >= b'A' && c <= b'F' { + v += c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v += c - b'a' + 10; + } else { + v = 0; + } + bin[i] = v; + } + } +} + +pub fn encrypt(c: &mut [u8], t: &mut [u8], k: &[u8], iv: &[u8], h: &[u8], p: &[u8]) { + let mut g = GCM::new(); + g.init(k.len(), k, iv.len(), iv); + g.add_header(h, h.len()); + g.add_plain(c, Some(p), p.len()); + g.finish(t, true) +} + +pub fn decrypt(p: &mut [u8], t: &mut [u8], k: &[u8], iv: &[u8], h: &[u8], c: &[u8]) { + let mut g = GCM::new(); + g.init(k.len(), k, iv.len(), iv); + g.add_header(h, h.len()); + g.add_cipher(p, Some(c), c.len()); + g.finish(t, true); +} + +/* +fn main() +{ + let kt=b"feffe9928665731c6d6a8f9467308308"; + let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; + let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; + let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; +// Tag should be 619cc5aefffe0bfa462af43c1699d050 + + let mut gcm=GCM::new(); + + let len=mt.len()/2; + let lenh=ht.len()/2; + let lenk=kt.len()/2; + let leniv=nt.len()/2; + + //let mut t:[u8;16]=[0;16]; // Tag + let mut k:[u8;16]=[0;16]; // AES Key + let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted + let mut n:[u8;100]=[0;100]; // IV - Initialisation vector + let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated + let mut c:[u8;100]=[0;100]; // Ciphertext + let mut p:[u8;100]=[0;100]; // Recovered Plaintext + + GCM::hex2bytes(mt,&mut m); + GCM::hex2bytes(ht,&mut h); + GCM::hex2bytes(kt,&mut k); + GCM::hex2bytes(nt,&mut n); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",m[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_plain(&mut c,&m,len); + let mut t=gcm.finish(true); + + println!("Ciphertext="); + for i in 0..len {print!("{:02x}",c[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_cipher(&mut p,&c,len); + t=gcm.finish(true); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",p[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash256.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash256.rs new file mode 100644 index 000000000000..9c23f9b54121 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash256.rs @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH256_H0: u32 = 0x6A09E667; +const HASH256_H1: u32 = 0xBB67AE85; +const HASH256_H2: u32 = 0x3C6EF372; +const HASH256_H3: u32 = 0xA54FF53A; +const HASH256_H4: u32 = 0x510E527F; +const HASH256_H5: u32 = 0x9B05688C; +const HASH256_H6: u32 = 0x1F83D9AB; +const HASH256_H7: u32 = 0x5BE0CD19; + +const HASH256_K: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; + +pub struct HASH256 { + length: [u32; 2], + h: [u32; 8], + w: [u32; 64], +} + +impl HASH256 { + fn s(n: u32, x: u32) -> u32 { + ((x) >> n) | ((x) << (32 - n)) + } + fn r(n: u32, x: u32) -> u32 { + (x) >> n + } + + fn ch(x: u32, y: u32, z: u32) -> u32 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u32, y: u32, z: u32) -> u32 { + (x & y) ^ (x & z) ^ (y & z) + } + fn sig0(x: u32) -> u32 { + HASH256::s(2, x) ^ HASH256::s(13, x) ^ HASH256::s(22, x) + } + + fn sig1(x: u32) -> u32 { + HASH256::s(6, x) ^ HASH256::s(11, x) ^ HASH256::s(25, x) + } + + fn theta0(x: u32) -> u32 { + HASH256::s(7, x) ^ HASH256::s(18, x) ^ HASH256::r(3, x) + } + + fn theta1(x: u32) -> u32 { + HASH256::s(17, x) ^ HASH256::s(19, x) ^ HASH256::r(10, x) + } + + pub fn as_bytes(&self, array: &mut [u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = self.length[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..8 { + let mut t = self.h[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..64 { + let mut t = self.w[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + } + + pub fn from_bytes(&mut self, array: &[u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = array[ptr + 3] as u32; + t = 256 * t + (array[ptr + 2] as u32); + t = 256 * t + (array[ptr + 1] as u32); + t = 256 * t + (array[ptr] as u32); + self.length[i] = t; + ptr += 4; + } + for i in 0..8 { + let mut t = array[ptr + 3] as u32; + t = 256 * t + (array[ptr + 2] as u32); + t = 256 * t + (array[ptr + 1] as u32); + t = 256 * t + (array[ptr] as u32); + self.h[i] = t; + ptr += 4; + } + for i in 0..64 { + let mut t = array[ptr + 3] as u32; + t = 256 * t + (array[ptr + 2] as u32); + t = 256 * t + (array[ptr + 1] as u32); + t = 256 * t + (array[ptr] as u32); + self.w[i] = t; + ptr += 4; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..64 { + self.w[j] = HASH256::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH256::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..64 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH256::sig1(e)) + .wrapping_add(HASH256::ch(e, f, g)) + .wrapping_add(HASH256_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH256::sig0(a).wrapping_add(HASH256::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH256_H0; + self.h[1] = HASH256_H1; + self.h[2] = HASH256_H2; + self.h[3] = HASH256_H3; + self.h[4] = HASH256_H4; + self.h[5] = HASH256_H5; + self.h[6] = HASH256_H6; + self.h[7] = HASH256_H7; + } + + pub fn new() -> HASH256 { + let mut nh = HASH256 { + length: [0; 2], + h: [0; 8], + w: [0; 64], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH256) -> HASH256 { + let mut nh = HASH256 { + length: [0; 2], + h: [0; 8], + w: [0; 64], + }; + nh.length[0] = hh.length[0]; + nh.length[1] = hh.length[1]; + for i in 0..64 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 32) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u32; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 512) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 32] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 32] = [0; 32]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 512) != 448 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..32 { + /* convert to bytes */ + digest[i] = ((self.h[i / 4] >> (8 * (3 - i % 4))) & 0xff) as u8; + } + self.init(); + digest + } + + pub fn continuing_hash(&self) -> [u8; 32] { + let mut sh = HASH256::new_copy(self); + sh.hash() + } +} + +//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 +/* +fn main() { + let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + let test = s.into_bytes(); + let mut sh=HASH256::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..32 {print!("{:02x}",digest[i])} +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash384.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash384.rs new file mode 100644 index 000000000000..4c0b8e2d72f3 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash384.rs @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH384_H0: u64 = 0xcbbb9d5dc1059ed8; +const HASH384_H1: u64 = 0x629a292a367cd507; +const HASH384_H2: u64 = 0x9159015a3070dd17; +const HASH384_H3: u64 = 0x152fecd8f70e5939; +const HASH384_H4: u64 = 0x67332667ffc00b31; +const HASH384_H5: u64 = 0x8eb44a8768581511; +const HASH384_H6: u64 = 0xdb0c2e0d64f98fa7; +const HASH384_H7: u64 = 0x47b5481dbefa4fa4; + +const HASH384_K: [u64; 80] = [ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +]; + +pub struct HASH384 { + length: [u64; 2], + h: [u64; 8], + w: [u64; 80], +} + +impl HASH384 { + fn s(n: u64, x: u64) -> u64 { + ((x) >> n) | ((x) << (64 - n)) + } + fn r(n: u64, x: u64) -> u64 { + (x) >> n + } + + fn ch(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (x & z) ^ (y & z) + } + + fn sig0(x: u64) -> u64 { + HASH384::s(28, x) ^ HASH384::s(34, x) ^ HASH384::s(39, x) + } + + fn sig1(x: u64) -> u64 { + HASH384::s(14, x) ^ HASH384::s(18, x) ^ HASH384::s(41, x) + } + + fn theta0(x: u64) -> u64 { + HASH384::s(1, x) ^ HASH384::s(8, x) ^ HASH384::r(7, x) + } + + fn theta1(x: u64) -> u64 { + HASH384::s(19, x) ^ HASH384::s(61, x) ^ HASH384::r(6, x) + } + + pub fn as_bytes(&self, array: &mut [u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = self.length[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..8 { + let mut t = self.h[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..80 { + let mut t = self.w[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + } + + pub fn from_bytes(&mut self, array: &[u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.length[i] = t; + ptr += 8; + } + for i in 0..8 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.h[i] = t; + ptr += 8; + } + for i in 0..80 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.w[i] = t; + ptr += 8; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..80 { + self.w[j] = HASH384::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH384::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..80 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH384::sig1(e)) + .wrapping_add(HASH384::ch(e, f, g)) + .wrapping_add(HASH384_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH384::sig0(a).wrapping_add(HASH384::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH384_H0; + self.h[1] = HASH384_H1; + self.h[2] = HASH384_H2; + self.h[3] = HASH384_H3; + self.h[4] = HASH384_H4; + self.h[5] = HASH384_H5; + self.h[6] = HASH384_H6; + self.h[7] = HASH384_H7; + } + + pub fn new() -> HASH384 { + let mut nh = HASH384 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH384) -> HASH384 { + let mut nh = HASH384 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.length[0] = hh.length[0]; + nh.length[1] = hh.length[1]; + for i in 0..80 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 64) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u64; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 1024) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 48] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 48] = [0; 48]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 1024) != 896 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..48 { + /* convert to bytes */ + digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; + } + self.init(); + digest + } + pub fn continuing_hash(&self) -> [u8; 48] { + let mut sh = HASH384::new_copy(self); + sh.hash() + } +} + +//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH384::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..48 {print!("{:02x}",digest[i])} +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash512.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash512.rs new file mode 100644 index 000000000000..206f9762549d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hash512.rs @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH512_H0: u64 = 0x6a09e667f3bcc908; +const HASH512_H1: u64 = 0xbb67ae8584caa73b; +const HASH512_H2: u64 = 0x3c6ef372fe94f82b; +const HASH512_H3: u64 = 0xa54ff53a5f1d36f1; +const HASH512_H4: u64 = 0x510e527fade682d1; +const HASH512_H5: u64 = 0x9b05688c2b3e6c1f; +const HASH512_H6: u64 = 0x1f83d9abfb41bd6b; +const HASH512_H7: u64 = 0x5be0cd19137e2179; + +const HASH512_K: [u64; 80] = [ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +]; + +pub struct HASH512 { + length: [u64; 2], + h: [u64; 8], + w: [u64; 80], +} + +impl HASH512 { + fn s(n: u64, x: u64) -> u64 { + ((x) >> n) | ((x) << (64 - n)) + } + fn r(n: u64, x: u64) -> u64 { + (x) >> n + } + + fn ch(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (x & z) ^ (y & z) + } + + fn sig0(x: u64) -> u64 { + HASH512::s(28, x) ^ HASH512::s(34, x) ^ HASH512::s(39, x) + } + + fn sig1(x: u64) -> u64 { + HASH512::s(14, x) ^ HASH512::s(18, x) ^ HASH512::s(41, x) + } + + fn theta0(x: u64) -> u64 { + HASH512::s(1, x) ^ HASH512::s(8, x) ^ HASH512::r(7, x) + } + + fn theta1(x: u64) -> u64 { + HASH512::s(19, x) ^ HASH512::s(61, x) ^ HASH512::r(6, x) + } + + pub fn as_bytes(&self, array: &mut [u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = self.length[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..8 { + let mut t = self.h[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + for i in 0..80 { + let mut t = self.w[i]; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = (t % 256) as u8; + t /= 256; + ptr += 1; + array[ptr] = t as u8; + ptr += 1; + } + } + + pub fn from_bytes(&mut self, array: &[u8]) { + let mut ptr = 0; + for i in 0..2 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.length[i] = t; + ptr += 8; + } + for i in 0..8 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.h[i] = t; + ptr += 8; + } + for i in 0..80 { + let mut t = array[ptr + 7] as u64; + t = 256 * t + (array[ptr + 6] as u64); + t = 256 * t + (array[ptr + 5] as u64); + t = 256 * t + (array[ptr + 4] as u64); + t = 256 * t + (array[ptr + 3] as u64); + t = 256 * t + (array[ptr + 2] as u64); + t = 256 * t + (array[ptr + 1] as u64); + t = 256 * t + (array[ptr] as u64); + self.w[i] = t; + ptr += 8; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..80 { + self.w[j] = HASH512::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH512::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..80 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH512::sig1(e)) + .wrapping_add(HASH512::ch(e, f, g)) + .wrapping_add(HASH512_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH512::sig0(a).wrapping_add(HASH512::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH512_H0; + self.h[1] = HASH512_H1; + self.h[2] = HASH512_H2; + self.h[3] = HASH512_H3; + self.h[4] = HASH512_H4; + self.h[5] = HASH512_H5; + self.h[6] = HASH512_H6; + self.h[7] = HASH512_H7; + } + + pub fn new() -> HASH512 { + let mut nh = HASH512 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH512) -> HASH512 { + let mut nh = HASH512 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.length[0] = hh.length[0]; + nh.length[1] = hh.length[1]; + for i in 0..80 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 64) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u64; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 1024) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 64] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 64] = [0; 64]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 1024) != 896 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..64 { + /* convert to bytes */ + digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; + } + self.init(); + digest + } + pub fn continuing_hash(&self) -> [u8; 64] { + let mut sh = HASH512::new_copy(self); + sh.hash() + } +} + +//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH512::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..64 {print!("{:02x}",digest[i])} +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hmac.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hmac.rs new file mode 100644 index 000000000000..1b2f3e894e8a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/hmac.rs @@ -0,0 +1,943 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::hash256::HASH256; +use crate::hash384::HASH384; +use crate::hash512::HASH512; +use crate::rand::RAND; +use crate::sha3::SHA3; + +pub const MC_SHA2: usize = 2; +pub const MC_SHA3: usize = 3; +pub const SHA256: usize = 32; +pub const SHA384: usize = 48; +pub const SHA512: usize = 64; + +#[allow(non_snake_case)] +/* General Purpose Hash function */ +#[allow(clippy::too_many_arguments)] +pub fn GPhashit( + hash: usize, + sha: usize, + w: &mut [u8], + pad: usize, + zpad: usize, + a: Option<&[u8]>, + n: isize, + b: Option<&[u8]>, +) { + let mut r: [u8; 64] = [0; 64]; + + if hash == MC_SHA2 { + if sha == SHA256 { + let mut h = HASH256::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + if sha == SHA384 { + let mut h = HASH384::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + if sha == SHA512 { + let mut h = HASH512::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + } + if hash == MC_SHA3 { + let mut h = SHA3::new(sha); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + h.hash(&mut r); + } + + if pad == 0 { + for i in 0..sha { + w[i] = r[i] + } + } else if pad <= sha { + for i in 0..pad { + w[i] = r[i] + } + } else { + for i in 0..sha { + w[i + pad - sha] = r[i] + } + for i in 0..(pad - sha) { + w[i] = 0 + } + } +} + +#[allow(non_snake_case)] +pub fn SPhashit(hash: usize, sha: usize, w: &mut [u8], a: Option<&[u8]>) { + GPhashit(hash, sha, w, 0, 0, a, -1, None); +} + +pub fn inttobytes(n: usize, b: &mut [u8]) { + let mut i = b.len(); + let mut m = n; + while m > 0 && i > 0 { + i -= 1; + b[i] = (m & 0xff) as u8; + m /= 256; + } +} + +pub fn kdf2(hash: usize, sha: usize, z: &[u8], p: Option<&[u8]>, olen: usize, k: &mut [u8]) { + /* NOTE: the parameter olen is the length of the output K in bytes */ + let hlen = sha; + let mut lk = 0; + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + + for counter in 1..cthreshold + 1 { + let mut b: [u8; 64] = [0; 64]; + GPhashit(hash, sha, &mut b, 0, 0, Some(z), counter as isize, p); + if lk + hlen > olen { + for i in 0..(olen % hlen) { + k[lk] = b[i]; + lk += 1 + } + } else { + for i in 0..hlen { + k[lk] = b[i]; + lk += 1 + } + } + } +} + +/* Password based Key Derivation Function */ +/* Input password p, salt s, and repeat count */ +/* Output key of length olen */ +pub fn pbkdf2( + hash: usize, + sha: usize, + pass: &[u8], + salt: &[u8], + rep: usize, + olen: usize, + k: &mut [u8], +) { + let mut d = olen / sha; + if olen % sha != 0 { + d += 1 + } + let mut f: [u8; 64] = [0; 64]; + let mut u: [u8; 64] = [0; 64]; + let mut ku: [u8; 64] = [0; 64]; + let mut s: [u8; 36] = [0; 36]; // Maximum salt of 32 bytes + 4 + let mut n: [u8; 4] = [0; 4]; + + let sl = salt.len(); + let mut kp = 0; + for i in 0..d { + for j in 0..sl { + s[j] = salt[j] + } + inttobytes(i + 1, &mut n); + for j in 0..4 { + s[sl + j] = n[j] + } + + hmac1(hash, sha, &mut f, sha, &s[0..sl + 4], pass); + + for j in 0..sha { + u[j] = f[j] + } + + for _ in 1..rep { + hmac1(hash, sha, &mut ku, sha, &u, pass); + for m in 0..sha { + u[m] = ku[m]; + f[m] ^= u[m] + } + } + for j in 0..sha { + if kp < olen { + k[kp] = f[j] + } + kp += 1 + } + } +} + +fn blksize(hash: usize, sha: usize) -> usize { + let mut lb = 0; + if hash == MC_SHA2 { + lb = 64; + if sha > 32 { + lb = 128; + } + } + if hash == MC_SHA3 { + lb = 200 - 2 * sha; + } + lb +} + +/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */ +pub fn hmac1(hash: usize, sha: usize, tag: &mut [u8], olen: usize, k: &[u8], m: &[u8]) -> bool { + /* Input is from an octet m * + * olen is requested output length in bytes. k is the key * + * The output is the calculated tag */ + let mut b: [u8; 64] = [0; 64]; /* Not good */ + let mut k0: [u8; 128] = [0; 128]; + + let lb = blksize(hash, sha); + if lb == 0 { + return false; + } + + for i in 0..lb { + k0[i] = 0 + } + + if k.len() > lb { + SPhashit(hash, sha, &mut b, Some(k)); + //GPhashit(hash, sha, &mut b,0,0,k, 0, None); + for i in 0..sha { + k0[i] = b[i] + } + } else { + for i in 0..k.len() { + k0[i] = k[i] + } + } + + for i in 0..lb { + k0[i] ^= 0x36 + } + + GPhashit(hash, sha, &mut b, 0, 0, Some(&k0[0..lb]), -1, Some(m)); + + for i in 0..lb { + k0[i] ^= 0x6a + } + GPhashit( + hash, + sha, + tag, + olen, + 0, + Some(&k0[0..lb]), + -1, + Some(&b[0..sha]), + ); + + true +} + +pub fn hkdf_extract(hash: usize, hlen: usize, prk: &mut [u8], salt: Option<&[u8]>, ikm: &[u8]) { + if let Some(x) = salt { + hmac1(hash, hlen, prk, hlen, x, ikm); + } else { + let h: [u8; 64] = [0; 64]; + hmac1(hash, hlen, prk, hlen, &h[0..hlen], ikm); + } +} + +pub fn hkdf_expand(hash: usize, hlen: usize, okm: &mut [u8], olen: usize, prk: &[u8], info: &[u8]) { + let n = olen / hlen; + let flen = olen % hlen; + + let mut t: [u8; 1024] = [0; 1024]; // >= info.length+hlen+1 + let mut k: [u8; 64] = [0; 64]; + + let mut l = 0; + let mut m = 0; + for i in 1..=n { + for j in 0..info.len() { + t[l] = info[j]; + l += 1; + } + t[l] = i as u8; + l += 1; + hmac1(hash, hlen, &mut k, hlen, prk, &t[0..l]); + l = 0; + for j in 0..hlen { + okm[m] = k[j]; + m += 1; + t[l] = k[j]; + l += 1; + } + } + if flen > 0 { + for j in 0..info.len() { + t[l] = info[j]; + l += 1; + } + t[l] = (n + 1) as u8; + l += 1; + hmac1(hash, hlen, &mut k, flen, prk, &t[0..l]); + for j in 0..flen { + okm[m] = k[j]; + m += 1; + } + } +} + +fn ceil(a: usize, b: usize) -> usize { + (a - 1) / b + 1 +} + +pub fn xof_expand(hlen: usize, okm: &mut [u8], olen: usize, dst: &[u8], msg: &[u8]) { + let mut h = SHA3::new(hlen); + for i in 0..msg.len() { + h.process(msg[i]); + } + h.process(((olen >> 8) & 0xff) as u8); + h.process((olen & 0xff) as u8); + + for i in 0..dst.len() { + h.process(dst[i]); + } + h.process((dst.len() & 0xff) as u8); + + h.shake(okm, olen); +} + +pub fn xmd_expand(hash: usize, hlen: usize, okm: &mut [u8], olen: usize, dst: &[u8], msg: &[u8]) { + let mut w: [u8; 64] = [0; 64]; + if dst.len() >= 256 { + GPhashit( + hash, + hlen, + &mut w, + 0, + 0, + Some(b"H2C-OVERSIZE-DST-"), + -1, + Some(&dst), + ); + xmd_expand_short_dst(hash, hlen, okm, olen, &w[0..hlen], msg); + } else { + xmd_expand_short_dst(hash, hlen, okm, olen, dst, msg); + } +} + +// Assumes dst.len() < 256. +fn xmd_expand_short_dst( + hash: usize, + hlen: usize, + okm: &mut [u8], + olen: usize, + dst: &[u8], + msg: &[u8], +) { + let mut tmp: [u8; 260] = [0; 260]; + let mut h0: [u8; 64] = [0; 64]; + let mut h1: [u8; 64] = [0; 64]; + let mut h2: [u8; 64] = [0; 64]; + + let ell = ceil(olen, hlen); + let blk = blksize(hash, hlen); + tmp[0] = ((olen >> 8) & 0xff) as u8; + tmp[1] = (olen & 0xff) as u8; + tmp[2] = 0; + + for j in 0..dst.len() { + tmp[3 + j] = dst[j]; + } + tmp[3 + dst.len()] = (dst.len() & 0xff) as u8; + + GPhashit( + hash, + hlen, + &mut h0, + 0, + blk, + Some(msg), + -1, + Some(&tmp[0..dst.len() + 4]), + ); + + let mut k = 0; + for i in 1..=ell { + for j in 0..hlen { + h1[j] ^= h0[j]; + h2[j] = h1[j]; + } + tmp[0] = i as u8; + + for j in 0..dst.len() { + tmp[1 + j] = dst[j]; + } + tmp[1 + dst.len()] = (dst.len() & 0xff) as u8; + + GPhashit( + hash, + hlen, + &mut h1, + 0, + 0, + Some(&h2[0..hlen]), + -1, + Some(&tmp[0..dst.len() + 2]), + ); + for j in 0..hlen { + okm[k] = h1[j]; + k += 1; + if k == olen { + break; + } + } + } +} + +/* Mask Generation Function */ + +pub fn mgf1(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { + let hlen = sha; + + let mut j = 0; + for i in 0..k.len() { + k[i] = 0 + } + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + for counter in 0..cthreshold { + let mut b: [u8; 64] = [0; 64]; + GPhashit(MC_SHA2, sha, &mut b, 0, 0, Some(z), counter as isize, None); + //hashit(sha, Some(z), counter as isize, &mut b); + + if j + hlen > olen { + for i in 0..(olen % hlen) { + k[j] = b[i]; + j += 1 + } + } else { + for i in 0..hlen { + k[j] = b[i]; + j += 1 + } + } + } +} + +pub fn mgf1xor(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { + let hlen = sha; + let mut j = 0; + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + for counter in 0..cthreshold { + let mut b: [u8; 64] = [0; 64]; + GPhashit(MC_SHA2, sha, &mut b, 0, 0, Some(z), counter as isize, None); + + if j + hlen > olen { + for i in 0..(olen % hlen) { + k[j] ^= b[i]; + j += 1 + } + } else { + for i in 0..hlen { + k[j] ^= b[i]; + j += 1 + } + } + } +} + +// PKCS 1.5 +/* SHAXXX identifier strings */ +const SHA256ID: [u8; 19] = [ + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20, +]; +const SHA384ID: [u8; 19] = [ + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30, +]; +const SHA512ID: [u8; 19] = [ + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40, +]; + +pub fn pkcs15(sha: usize, m: &[u8], w: &mut [u8], rfs: usize) -> bool { + let olen = rfs; + let hlen = sha; + let idlen = 19; + let mut b: [u8; 64] = [0; 64]; /* Not good */ + + if olen < idlen + hlen + 10 { + return false; + } + SPhashit(MC_SHA2, sha, &mut b, Some(m)); + + for i in 0..w.len() { + w[i] = 0 + } + let mut i = 0; + w[i] = 0; + i += 1; + w[i] = 1; + i += 1; + for _ in 0..olen - idlen - hlen - 3 { + w[i] = 0xff; + i += 1 + } + w[i] = 0; + i += 1; + if hlen == SHA256 { + for j in 0..idlen { + w[i] = SHA256ID[j]; + i += 1 + } + } + if hlen == SHA384 { + for j in 0..idlen { + w[i] = SHA384ID[j]; + i += 1 + } + } + if hlen == SHA512 { + for j in 0..idlen { + w[i] = SHA512ID[j]; + i += 1 + } + } + for j in 0..hlen { + w[i] = b[j]; + i += 1 + } + true +} + +// Alternate PKCS 1.5 +/* SHAXXX identifier strings */ +const SHA256IDB: [u8; 17] = [ + 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, + 0x20, +]; +const SHA384IDB: [u8; 17] = [ + 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, + 0x30, +]; +const SHA512IDB: [u8; 17] = [ + 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, + 0x40, +]; + +pub fn pkcs15b(sha: usize, m: &[u8], w: &mut [u8], rfs: usize) -> bool { + let olen = rfs; + let hlen = sha; + let idlen = 17; + let mut b: [u8; 64] = [0; 64]; /* Not good */ + + if olen < idlen + hlen + 10 { + return false; + } + SPhashit(MC_SHA2, sha, &mut b, Some(m)); + for i in 0..w.len() { + w[i] = 0 + } + let mut i = 0; + w[i] = 0; + i += 1; + w[i] = 1; + i += 1; + for _ in 0..olen - idlen - hlen - 3 { + w[i] = 0xff; + i += 1 + } + w[i] = 0; + i += 1; + if hlen == SHA256 { + for j in 0..idlen { + w[i] = SHA256IDB[j]; + i += 1 + } + } + if hlen == SHA384 { + for j in 0..idlen { + w[i] = SHA384IDB[j]; + i += 1 + } + } + if hlen == SHA512 { + for j in 0..idlen { + w[i] = SHA512IDB[j]; + i += 1 + } + } + for j in 0..hlen { + w[i] = b[j]; + i += 1 + } + true +} + +pub fn pss_encode(sha: usize, m: &[u8], rng: &mut RAND, f: &mut [u8], rfs: usize) -> bool { + let emlen = rfs; + let embits = 8 * emlen - 1; + let hlen = sha; + let mut h: [u8; 64] = [0; 64]; + let mut salt: [u8; 64] = [0; 64]; + let mut md: [u8; 136] = [0; 136]; + for i in 0..hlen { + salt[i] = rng.getbyte() + } + let mask = (0xff as u8) >> (8 * emlen - embits); + SPhashit(MC_SHA2, sha, &mut h, Some(m)); + if emlen < hlen + hlen + 2 { + return false; + } + for i in 0..8 { + md[i] = 0; + } + for i in 0..hlen { + md[8 + i] = h[i]; + } + for i in 0..hlen { + md[8 + hlen + i] = salt[i]; + } + SPhashit(MC_SHA2, sha, &mut h, Some(&md[0..8 + hlen + hlen])); + for i in 0..emlen - hlen - hlen - 2 { + f[i] = 0; + } + f[emlen - hlen - hlen - 2] = 0x01; + for i in 0..hlen { + f[emlen + i - hlen - hlen - 1] = salt[i]; + } + mgf1xor(sha, &h[0..hlen], emlen - hlen - 1, f); + f[0] &= mask; + for i in 0..hlen { + f[emlen + i - hlen - 1] = h[i]; + } + f[emlen - 1] = 0xbc as u8; + true +} + +pub fn pss_verify(sha: usize, m: &[u8], f: &[u8]) -> bool { + let emlen = f.len(); + let embits = 8 * emlen - 1; + let hlen = sha; + let mut db: [u8; 512] = [0; 512]; + let mut hmask: [u8; 64] = [0; 64]; + let mut h: [u8; 64] = [0; 64]; + let mut salt: [u8; 64] = [0; 64]; + let mut md: [u8; 136] = [0; 136]; + let mask = (0xff as u8) >> (8 * emlen - embits); + + SPhashit(MC_SHA2, sha, &mut hmask, Some(m)); + if emlen < hlen + hlen + 2 { + return false; + } + if f[emlen - 1] != 0xbc as u8 { + return false; + } + if (f[0] & (!mask)) != 0 { + return false; + } + for i in 0..emlen - hlen - 1 { + db[i] = f[i] + } + for i in 0..hlen { + h[i] = f[emlen + i - hlen - 1] + } + mgf1xor(sha, &h[0..hlen], emlen - hlen - 1, &mut db); + db[0] &= mask; + + let mut k = 0 as u8; + for i in 0..emlen - hlen - hlen - 2 { + k |= db[i] + } + if k != 0 { + return false; + } + if db[emlen - hlen - hlen - 2] != 0x01 { + return false; + } + for i in 0..hlen { + salt[i] = db[emlen + i - hlen - hlen - 1] + } + for i in 0..8 { + md[i] = 0 + } + for i in 0..hlen { + md[8 + i] = hmask[i] + } + for i in 0..hlen { + md[8 + hlen + i] = salt[i] + } + SPhashit(MC_SHA2, sha, &mut hmask, Some(&md[0..8 + hlen + hlen])); + k = 0; + for i in 0..hlen { + k |= h[i] - hmask[i]; + } + if k != 0 { + return false; + } + true +} + +/* OAEP Message Encoding for Encryption */ +pub fn oaep_encode( + sha: usize, + m: &[u8], + rng: &mut RAND, + p: Option<&[u8]>, + f: &mut [u8], + rfs: usize, +) -> bool { + let olen = rfs - 1; + let mlen = m.len(); + + let hlen = sha; + + let mut seed: [u8; 64] = [0; 64]; + + let seedlen = hlen; + if mlen > olen - hlen - seedlen - 1 { + return false; + } + + let mut dbmask: [u8; 512] = [0; 512]; + + SPhashit(MC_SHA2, sha, f, p); + //hashit(sha, p, -1, f); + let slen = olen - mlen - hlen - seedlen - 1; + + for i in 0..slen { + f[hlen + i] = 0 + } + f[hlen + slen] = 1; + for i in 0..mlen { + f[hlen + slen + 1 + i] = m[i] + } + + for i in 0..seedlen { + seed[i] = rng.getbyte() + } + + mgf1(sha, &seed[0..seedlen], olen - seedlen, &mut dbmask); + + for i in 0..olen - seedlen { + dbmask[i] ^= f[i] + } + + mgf1(sha, &dbmask[0..olen - seedlen], seedlen, f); + + for i in 0..seedlen { + f[i] ^= seed[i] + } + + for i in 0..olen - seedlen { + f[i + seedlen] = dbmask[i] + } + + /* pad to length rfs */ + let d = 1; + for i in (d..rfs).rev() { + f[i] = f[i - d]; + } + for i in (0..d).rev() { + f[i] = 0; + } + true +} + +/* OAEP Message Decoding for Decryption */ +pub fn oaep_decode(sha: usize, p: Option<&[u8]>, f: &mut [u8], rfs: usize) -> usize { + let olen = rfs - 1; + + let hlen = sha; + let mut seed: [u8; 64] = [0; 64]; + let seedlen = hlen; + let mut chash: [u8; 64] = [0; 64]; + + if olen < seedlen + hlen + 1 { + return 0; + } + let mut dbmask: [u8; 512] = [0; 512]; + + if f.len() < rfs { + let d = rfs - f.len(); + for i in (d..rfs).rev() { + f[i] = f[i - d]; + } + for i in (0..d).rev() { + f[i] = 0; + } + } + SPhashit(MC_SHA2, sha, &mut chash, p); + //hashit(sha, p, -1, &mut chash); + + let x = f[0]; + + for i in seedlen..olen { + dbmask[i - seedlen] = f[i + 1]; + } + + mgf1(sha, &dbmask[0..olen - seedlen], seedlen, &mut seed); + for i in 0..seedlen { + seed[i] ^= f[i + 1] + } + mgf1(sha, &seed[0..seedlen], olen - seedlen, f); + for i in 0..olen - seedlen { + dbmask[i] ^= f[i] + } + + let mut comp = 0; + for i in 0..hlen { + comp |= (chash[i] ^ dbmask[i]) as usize; + } + + for i in 0..olen - seedlen - hlen { + dbmask[i] = dbmask[i + hlen] + } + + for i in 0..hlen { + seed[i] = 0; + chash[i] = 0 + } + + // find first non-zero t in array + let mut k = 0; + let mut t = 0; + let m = olen - seedlen - hlen; + for i in 0..m { + if t == 0 && dbmask[i] != 0 { + k = i; + t = dbmask[i]; + } + } + + if comp != 0 || x != 0 || t != 0x01 { + for i in 0..olen - seedlen { + dbmask[i] = 0 + } + return 0; + } + + for i in 0..m - k - 1 { + f[i] = dbmask[i + k + 1]; + } + + for i in 0..olen - seedlen { + dbmask[i] = 0 + } + + m - k - 1 +} + +/* + +use core::sha3; +use core::hmac; + + + + let mut okm: [u8;100]=[0;100]; + let msg: &[u8] = b"abc"; + let dst: &[u8] = b"P256_XMD:SHA-256_SSWU_RO_TESTGEN"; + hmac::xof_expand(sha3::SHAKE128,&mut okm,48,&dst,&msg); + print!("okm= "); printbinary(&okm[0..48]); + hmac::xmd_expand(hmac::MC_SHA2,32,&mut okm,48,&dst,&msg); + print!("okm= "); printbinary(&okm[0..48]); + + + let mut ikm: [u8;22]=[0;22]; + let mut salt: [u8;13]=[0;13]; + let mut info: [u8;10]=[0;10]; + let mut prk: [u8;32]=[0;32]; + let mut okm: [u8;42]=[0;42]; + + for i in 0..22 {ikm[i]=0x0b;} + for i in 0..13 {salt[i]=i as u8;} + for i in 0..10 {info[i]=(0xf0+i) as u8;} + + hmac::hkdf_extract(hmac::MC_SHA2,32,&mut prk,Some(&salt),&ikm); + + print!("PRK= "); + for i in 0..32 { + print!("{:02X}",prk[i]); + } + + hmac::hkdf_expand(hmac::MC_SHA2,32,&mut okm,42,&prk,&info); + print!("OKM= "); + for i in 0..42 { + print!("{:02X}",okm[i]); + } + + +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/kyber.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/kyber.rs new file mode 100644 index 000000000000..e7a8ef762170 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/kyber.rs @@ -0,0 +1,728 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Kyber API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. + + M.Scott 06/07/2022 +*/ + +use crate::sha3; +use crate::sha3::SHA3; + +const LGN: usize = 8; +const DEGREE: usize = 1 << LGN; +const PRIME: i16 = 0xD01; + +const ONE: i16 = 0x549; // r mod q +const QINV: i32 = -3327; // -1/q mod 2^16 + //const TWO26: i32 = 1<<26; // 2^26 +const TWO25: i32 = 1 << 25; // 2^25 +const BARC: i32 = 20159; // ((TWO26 + PRIME/2)/PRIME) + +pub const SECRET_CPA_SIZE_512: usize = 2 * (DEGREE * 3) / 2; +pub const PUBLIC_SIZE_512: usize = 32 + 2 * (DEGREE * 3) / 2; +pub const CIPHERTEXT_SIZE_512: usize = (10 * 2 + 4) * DEGREE / 8; +pub const SECRET_CCA_SIZE_512: usize = SECRET_CPA_SIZE_512 + PUBLIC_SIZE_512 + 64; +pub const SHARED_SECRET_512: usize = 32; + +pub const SECRET_CPA_SIZE_768: usize = 3 * (DEGREE * 3) / 2; +pub const PUBLIC_SIZE_768: usize = 32 + 3 * (DEGREE * 3) / 2; +pub const CIPHERTEXT_SIZE_768: usize = (10 * 3 + 4) * DEGREE / 8; +pub const SECRET_CCA_SIZE_768: usize = SECRET_CPA_SIZE_768 + PUBLIC_SIZE_768 + 64; +pub const SHARED_SECRET_768: usize = 32; + +pub const SECRET_CPA_SIZE_1024: usize = 4 * (DEGREE * 3) / 2; +pub const PUBLIC_SIZE_1024: usize = 32 + 4 * (DEGREE * 3) / 2; +pub const CIPHERTEXT_SIZE_1024: usize = (11 * 4 + 5) * DEGREE / 8; +pub const SECRET_CCA_SIZE_1024: usize = SECRET_CPA_SIZE_1024 + PUBLIC_SIZE_1024 + 64; +pub const SHARED_SECRET_1024: usize = 32; + +pub const MAXK: usize = 4; + +// parameters for each security level +// K,eta1,eta2,du,dv,shared secret +const PARAMS_512: [usize; 6] = [2, 3, 2, 10, 4, 32]; +const PARAMS_768: [usize; 6] = [3, 2, 2, 10, 4, 32]; +const PARAMS_1024: [usize; 6] = [4, 2, 2, 11, 5, 32]; + +/* Start of public domain reference implementation code - translated from https://github.com/pq-crystals/kyber */ + +const ZETAS: [i16; 128] = [ + -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, + 573, -1325, 264, 383, -829, 1458, -1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, + 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, + -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, + -1103, 430, 555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, 1574, 1653, -246, + 778, 1159, -147, -777, 1483, -602, 1119, -1590, 644, -872, 349, 418, 329, -156, -75, 817, 1097, + 603, 610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, -1659, -1185, + -1530, -1278, 794, -1510, -854, -870, 478, -108, -308, 996, 991, 958, -1460, 1522, 1628, +]; +/* +fn printbinary(array: &[u8]) { + for i in 0..array.len() { + print!("{:02X}", array[i]) + } + println!("") +} +*/ +/* Montgomery stuff */ + +fn montgomery_reduce(a: i32) -> i16 { + let dp = PRIME as i32; + let dt = (((a & 0xffff) * QINV) & 0xffff) as i16; + let t = ((a - ((dt as i32) * dp)) >> 16) as i16; + t +} + +fn barrett_reduce(a: i16) -> i16 { + let da = a as i32; + let mut t = ((BARC * da + TWO25) >> 26) as i16; + t *= PRIME; + a - t +} + +fn fqmul(a: i16, b: i16) -> i16 { + montgomery_reduce((a as i32) * (b as i32)) +} + +fn ntt(r: &mut [i16]) { + let mut k = 1; + let mut len = 128; + while len >= 2 { + let mut start = 0; + while start < 256 { + let zeta = ZETAS[k]; + k += 1; + let mut j = start; + while j < start + len { + let t = fqmul(zeta, r[j + len]); + r[j + len] = r[j] - t; + r[j] += t; + j += 1; + } + start = j + len + } + len >>= 1; + } +} + +fn invntt(r: &mut [i16]) { + let f = 1441 as i16; + let mut k = 127; + let mut len = 2; + while len <= 128 { + let mut start = 0; + while start < 256 { + let zeta = ZETAS[k]; + k -= 1; + let mut j = start; + while j < start + len { + let t = r[j]; + r[j] = barrett_reduce(t + r[j + len]); // problem here + r[j + len] -= t; + r[j + len] = fqmul(zeta, r[j + len]); + j += 1; + } + start = j + len; + } + len <<= 1; + } + for j in 0..256 { + r[j] = fqmul(r[j], f); + } +} + +fn basemul(r: &mut [i16], a: &[i16], b: &[i16], zeta: i16) { + r[0] = fqmul(a[1], b[1]); + r[0] = fqmul(r[0], zeta); + r[0] += fqmul(a[0], b[0]); + r[1] = fqmul(a[0], b[1]); + r[1] += fqmul(a[1], b[0]); +} + +fn poly_reduce(r: &mut [i16]) { + for i in 0..DEGREE { + r[i] = barrett_reduce(r[i]); + } +} + +fn poly_ntt(r: &mut [i16]) { + ntt(r); + poly_reduce(r); +} + +fn poly_invntt(r: &mut [i16]) { + invntt(r); +} + +// Note r must be distinct from a and b +fn poly_mul(r: &mut [i16], a: &[i16], b: &[i16]) { + for i in 0..DEGREE / 4 { + let x = 4 * i; + let y = x + 2; + let z = x + 4; + basemul(&mut r[x..y], &a[x..y], &b[x..y], ZETAS[64 + i]); + basemul(&mut r[y..z], &a[y..z], &b[y..z], -ZETAS[64 + i]); + } +} + +fn poly_tomont(r: &mut [i16]) { + for i in 0..DEGREE { + r[i] = montgomery_reduce((r[i] as i32) * (ONE as i32)); + } +} + +/* End of public domain reference code use */ + +fn poly_add(p1: &mut [i16], p2: &[i16], p3: &[i16]) { + for i in 0..DEGREE { + p1[i] = p2[i] + p3[i]; + } +} + +fn poly_acc(p1: &mut [i16], p3: &[i16]) { + for i in 0..DEGREE { + p1[i] += p3[i]; + } +} + +fn poly_dec(p1: &mut [i16], p3: &[i16]) { + for i in 0..DEGREE { + p1[i] -= p3[i]; + } +} + +// Generate a[i][j] from rho +fn expandaij(rho: &[u8], aij: &mut [i16], i: usize, j: usize) { + let mut buff: [u8; 3 * DEGREE] = [0; 3 * DEGREE]; + let mut sh = SHA3::new(sha3::SHAKE128); + for m in 0..32 { + sh.process(rho[m]) + } + sh.process(j as u8); + sh.process(i as u8); + sh.shake(&mut buff, 3 * DEGREE); + let mut m = 0; + let mut n = 0; + let dp = PRIME as u32; + while n < DEGREE { + let d1 = (buff[m] as u32) + 256 * ((buff[m + 1] & 0x0f) as u32); + let d2 = ((buff[m + 1] / 16) as u32) + 16 * (buff[m + 2] as u32); + if d1 < dp { + aij[n] = d1 as i16; + n += 1; + } + if d2 < dp && n < DEGREE { + aij[n] = d2 as i16; + n += 1; + } + m += 3; + } +} + +fn getbit(b: &[u8], n: usize) -> i16 { + let wd = n / 8; + let bt = n % 8; + ((b[wd] >> bt) & 1) as i16 +} + +fn cbd(bts: &[u8], eta: usize, f: &mut [i16]) { + for i in 0..DEGREE { + let mut a = 0 as i16; + let mut b = 0 as i16; + for j in 0..eta { + a += getbit(bts, 2 * i * eta + j); + b += getbit(bts, 2 * i * eta + eta + j); + } + f[i] = a - b; + } +} + +// extract ab bits into word from dense byte stream +fn nextword(ab: usize, t: &[u8], ptr: &mut usize, bts: &mut usize) -> i16 { + let mut r = (t[*ptr] >> (*bts)) as i16; + let mask = ((1 << ab) - 1) as i16; + let mut i = 0; + let mut gotbits = 8 - (*bts); // bits left in current byte + while gotbits < ab { + i += 1; + let w = t[(*ptr) + i] as i16; + r |= w << gotbits; + gotbits += 8; + } + *bts += ab; + while *bts >= 8 { + *bts -= 8; + *ptr += 1; + } + r & mask +} + +fn nextbyte16(ab: usize, t: &[i16], ptr: &mut usize, bts: &mut usize) -> u8 { + let mut left = ab - (*bts); + let mut i = 0; + let mut w = t[*ptr]; + w += (w >> 15) & PRIME; + let mut r = w >> (*bts); + while left < 8 { + i += 1; + w = t[(*ptr) + i]; + w += (w >> 15) & PRIME; + r |= w << left; + left += ab; + } + *bts += 8; + while *bts >= ab { + *bts -= ab; + *ptr += 1; + } + (r & 0xff) as u8 +} + +fn encode(t: &[i16], len: usize, l: usize, pack: &mut [u8]) { + let mut ptr = 0; + let mut bts = 0; + for n in 0..len * (DEGREE * l) / 8 { + pack[n] = nextbyte16(l, t, &mut ptr, &mut bts); + } +} + +// return 0 if encoding is unchanged +fn chk_encode(t: &[i16], len: usize, l: usize, pack: &[u8]) -> u8 { + let mut ptr = 0; + let mut bts = 0; + let mut diff = 0 as u8; + for n in 0..len * (DEGREE * l) / 8 { + let m = nextbyte16(l, t, &mut ptr, &mut bts); + diff |= m ^ pack[n]; + } + diff +} + +fn decode(pack: &[u8], l: usize, t: &mut [i16], len: usize) { + let mut ptr = 0; + let mut bts = 0; + for i in 0..len * DEGREE { + t[i] = nextword(l, pack, &mut ptr, &mut bts); + } +} + +// Bernsteins safe division by 0xD01 +fn safediv(xx: i32) -> i32 { + let mut x = xx; + let mut q = 0 as i32; + + let mut qpart = (((x as i64) * 645083) >> 31) as i32; + x -= qpart * 0xD01; + q += qpart; + + qpart = ((((x as i64) * 645083) >> 31) as i32) + 1; + x -= qpart * 0xD01; + q += qpart + (x >> 31); + + q +} + +fn compress(t: &mut [i16], len: usize, d: usize) { + let twod = (1 << d) as i32; + let dp = PRIME as i32; + for i in 0..len * DEGREE { + t[i] += (t[i] >> 15) & PRIME; + t[i] = (safediv(twod * (t[i] as i32) + dp / 2) & (twod - 1)) as i16; + } +} +fn decompress(t: &mut [i16], len: usize, d: usize) { + let twod1 = (1 << (d - 1)) as i32; + let dp = PRIME as i32; + for i in 0..len * DEGREE { + t[i] = ((dp * (t[i] as i32) + twod1) >> d) as i16; + } +} + +fn cpa_keypair(params: &[usize], tau: &[u8], sk: &mut [u8], pk: &mut [u8]) { + let mut rho: [u8; 32] = [0; 32]; + let mut sigma: [u8; 33] = [0; 33]; + let mut buff: [u8; 256] = [0; 256]; + + let mut r: [i16; DEGREE] = [0; DEGREE]; + let mut w: [i16; DEGREE] = [0; DEGREE]; + let mut aij: [i16; DEGREE] = [0; DEGREE]; + let mut s: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut e: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut p: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let mut sh = SHA3::new(sha3::HASH512); + + let ck = params[0]; + let eta1 = params[1]; + let public_key_size = 32 + ck * (DEGREE * 3) / 2; + + for i in 0..32 { + sh.process(tau[i]); + } + sh.hash(&mut buff); + for i in 0..32 { + rho[i] = buff[i]; + sigma[i] = buff[i + 32]; + } + sigma[32] = 0; + + // create s + for i in 0..ck { + sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff, 64 * eta1); + cbd(&buff, eta1, &mut s[i * DEGREE..]); + sigma[32] += 1; + } + + // create e + for i in 0..ck { + sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff, 64 * eta1); + cbd(&buff, eta1, &mut e[i * DEGREE..]); + sigma[32] += 1; + } + + for k in 0..ck { + let row = k * DEGREE; + poly_ntt(&mut s[row..]); + poly_ntt(&mut e[row..]); + } + + for i in 0..ck { + let row = i * DEGREE; + expandaij(&rho, &mut aij, i, 0); + poly_mul(&mut r, &aij, &s); + for j in 1..ck { + expandaij(&rho, &mut aij, i, j); + poly_mul(&mut w, &s[j * DEGREE..], &aij); + poly_acc(&mut r, &w); + } + poly_reduce(&mut r); + poly_tomont(&mut r); + poly_add(&mut p[row..], &r, &e[row..]); + poly_reduce(&mut p[row..]); + } + + encode(&s, ck, 12, sk); + encode(&p, ck, 12, pk); + for i in 0..32 { + pk[public_key_size - 32 + i] = rho[i]; + } +} + +fn cpa_base_encrypt( + params: &[usize], + coins: &[u8], + pk: &[u8], + ss: &[u8], + u: &mut [i16], + v: &mut [i16], +) { + let mut rho: [u8; 32] = [0; 32]; + let mut sigma: [u8; 33] = [0; 33]; + let mut buff: [u8; 256] = [0; 256]; + + let mut r: [i16; DEGREE] = [0; DEGREE]; + let mut w: [i16; DEGREE] = [0; DEGREE]; + let mut aij: [i16; DEGREE] = [0; DEGREE]; + let mut q: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut p: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let ck = params[0]; + let eta1 = params[1]; + let eta2 = params[2]; + let du = params[3]; + let dv = params[4]; + let public_key_size = 32 + ck * (DEGREE * 3) / 2; + + for i in 0..32 { + sigma[i] = coins[i]; + } + sigma[32] = 0; + for i in 0..32 { + rho[i] = pk[i + public_key_size - 32]; + } + // create q + for i in 0..ck { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff, 64 * eta1); + cbd(&buff, eta1, &mut q[i * DEGREE..]); + sigma[32] += 1; + } + // create e1 + for i in 0..ck { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff, 64 * eta2); + cbd(&buff, eta1, &mut u[i * DEGREE..]); + sigma[32] += 1; + } + for i in 0..ck { + let row = DEGREE * i; + poly_ntt(&mut q[row..]); + } + + for i in 0..ck { + let row = i * DEGREE; + expandaij(&rho, &mut aij, 0, i); + poly_mul(&mut r, &aij, &q); + for j in 1..ck { + expandaij(&rho, &mut aij, j, i); + poly_mul(&mut w, &q[j * DEGREE..], &aij); + poly_acc(&mut r, &w); + } + poly_reduce(&mut r); + poly_invntt(&mut r); + poly_acc(&mut u[row..], &r); + poly_reduce(&mut u[row..]); + } + + decode(&pk, 12, &mut p, ck); + + poly_mul(v, &p, &q); + for i in 1..ck { + let row = DEGREE * i; + poly_mul(&mut r, &p[row..], &q[row..]); + poly_acc(v, &r); + } + poly_invntt(v); + + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff, 64 * eta2); + cbd(&buff, eta1, &mut w); // e2 + + poly_acc(v, &w); + + decode(&ss, 1, &mut r, 1); + decompress(&mut r, 1, 1); + poly_acc(v, &r); + poly_reduce(v); + compress(u, ck, du); + compress(v, 1, dv); +} + +fn cpa_encrypt(params: &[usize], coins: &[u8], pk: &[u8], ss: &[u8], ct: &mut [u8]) { + let mut v: [i16; DEGREE] = [0; DEGREE]; + let mut u: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let ck = params[0]; + let du = params[3]; + let dv = params[4]; + let ciphertext_size = (du * ck + dv) * DEGREE / 8; + cpa_base_encrypt(params, coins, pk, ss, &mut u, &mut v); + encode(&u, ck, du, ct); + encode(&v, 1, dv, &mut ct[ciphertext_size - (dv * DEGREE / 8)..]); +} + +// Re-encrypt and check that ct is OK (if so return is zero) +fn cpa_check_encrypt(params: &[usize], coins: &[u8], pk: &[u8], ss: &[u8], ct: &[u8]) -> u8 { + let mut v: [i16; DEGREE] = [0; DEGREE]; + let mut u: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let ck = params[0]; + let du = params[3]; + let dv = params[4]; + let ciphertext_size = (du * ck + dv) * DEGREE / 8; + cpa_base_encrypt(params, coins, pk, ss, &mut u, &mut v); + let d1 = chk_encode(&u, ck, du, ct); + let d2 = chk_encode(&v, 1, dv, &ct[ciphertext_size - (dv * DEGREE / 8)..]); + if (d1 | d2) == 0 { + 0 + } else { + 0xff + } +} + +fn cpa_decrypt(params: &[usize], sk: &[u8], ct: &[u8], ss: &mut [u8]) { + let mut w: [i16; DEGREE] = [0; DEGREE]; + let mut v: [i16; DEGREE] = [0; DEGREE]; + let mut r: [i16; DEGREE] = [0; DEGREE]; + let mut u: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + let mut s: [i16; MAXK * DEGREE] = [0; MAXK * DEGREE]; + + let ck = params[0]; + let du = params[3]; + let dv = params[4]; + + decode(ct, du, &mut u, ck); + decode(&ct[(du * ck * DEGREE) / 8..], dv, &mut v, 1); + decompress(&mut u, ck, du); + decompress(&mut v, 1, dv); + decode(sk, 12, &mut s, ck); + + poly_ntt(&mut u); + poly_mul(&mut w, &u, &s); + for i in 1..ck { + let row = DEGREE * i; + poly_ntt(&mut u[row..]); + poly_mul(&mut r, &u[row..], &s[row..]); + poly_acc(&mut w, &r); + } + poly_reduce(&mut w); + poly_invntt(&mut w); + poly_dec(&mut v, &w); + compress(&mut v, 1, 1); + encode(&v, 1, 1, ss); +} + +fn cca_keypair(params: &[usize], randbytes64: &[u8], sk: &mut [u8], pk: &mut [u8]) { + let ck = params[0]; + let secret_cpa_key_size = ck * (DEGREE * 3) / 2; + let public_key_size = 32 + ck * (DEGREE * 3) / 2; + + cpa_keypair(params, randbytes64, sk, pk); + for i in 0..public_key_size { + sk[i + secret_cpa_key_size] = pk[i]; + } + let mut sh = SHA3::new(sha3::HASH256); + for i in 0..public_key_size { + sh.process(pk[i]); + } + sh.hash(&mut sk[secret_cpa_key_size + public_key_size..]); + for i in 0..32 { + sk[i + secret_cpa_key_size + public_key_size + 32] = randbytes64[i + 32]; + } +} + +fn cca_encrypt(params: &[usize], randbytes32: &[u8], pk: &[u8], ss: &mut [u8], ct: &mut [u8]) { + let mut hm: [u8; 32] = [0; 32]; + let mut h: [u8; 32] = [0; 32]; + let mut g: [u8; 64] = [0; 64]; + let ck = params[0]; + let du = params[3]; + let dv = params[4]; + let public_key_size = 32 + ck * (DEGREE * 3) / 2; + let ciphertext_size = (du * ck + dv) * DEGREE / 8; + let shared_secret_size = params[5]; + + let mut sh = SHA3::new(sha3::HASH256); + for i in 0..32 { + sh.process(randbytes32[i]); + } + sh.hash(&mut hm); + + sh = SHA3::new(sha3::HASH256); + for i in 0..public_key_size { + sh.process(pk[i]); + } + sh.hash(&mut h); + + sh = SHA3::new(sha3::HASH512); + sh.process_array(&hm); + sh.process_array(&h); + sh.hash(&mut g); + cpa_encrypt(params, &g[32..], &pk, &hm, ct); + + sh = SHA3::new(sha3::HASH256); + for i in 0..ciphertext_size { + sh.process(ct[i]); + } + sh.hash(&mut h); + sh = SHA3::new(sha3::SHAKE256); + sh.process_array(&g[0..32]); + sh.process_array(&h); + sh.shake(ss, shared_secret_size); +} + +fn cca_decrypt(params: &[usize], sk: &[u8], ct: &[u8], ss: &mut [u8]) { + let mut m: [u8; 32] = [0; 32]; + let mut g: [u8; 64] = [0; 64]; + let ck = params[0]; + let secret_cpa_key_size = ck * (DEGREE * 3) / 2; + let public_key_size = 32 + ck * (DEGREE * 3) / 2; + let shared_secret_size = params[5]; + + let pk = &sk[secret_cpa_key_size..secret_cpa_key_size + public_key_size]; + let h = &sk[secret_cpa_key_size + public_key_size..secret_cpa_key_size + public_key_size + 32]; + let z = + &sk[secret_cpa_key_size + public_key_size + 32..secret_cpa_key_size + public_key_size + 64]; + + cpa_decrypt(params, sk, ct, &mut m); + + let mut sh = SHA3::new(sha3::HASH512); + sh.process_array(&m); + sh.process_array(h); + sh.hash(&mut g); + + let mask = cpa_check_encrypt(params, &g[32..], pk, &m, ct); // FO check ct is correct + + for i in 0..32 { + g[i] ^= (g[i] ^ z[i]) & mask; + } + + sh = SHA3::new(sha3::HASH256); + sh.process_array(&ct); + sh.hash(&mut m); + + sh = SHA3::new(sha3::SHAKE256); + sh.process_array(&g[0..32]); + sh.process_array(&m); + sh.shake(ss, shared_secret_size); +} + +// ********************* Kyber API ****************************** + +pub fn keypair_512(randbytes64: &[u8], sk: &mut [u8], pk: &mut [u8]) { + cca_keypair(&PARAMS_512, randbytes64, sk, pk); +} + +pub fn keypair_768(randbytes64: &[u8], sk: &mut [u8], pk: &mut [u8]) { + cca_keypair(&PARAMS_768, randbytes64, sk, pk); +} + +pub fn keypair_1024(randbytes64: &[u8], sk: &mut [u8], pk: &mut [u8]) { + cca_keypair(&PARAMS_1024, randbytes64, sk, pk); +} + +pub fn encrypt_512(randbytes32: &[u8], pk: &[u8], ss: &mut [u8], ct: &mut [u8]) { + cca_encrypt(&PARAMS_512, randbytes32, pk, ss, ct); +} + +pub fn encrypt_768(randbytes32: &[u8], pk: &[u8], ss: &mut [u8], ct: &mut [u8]) { + cca_encrypt(&PARAMS_768, randbytes32, pk, ss, ct); +} + +pub fn encrypt_1024(randbytes32: &[u8], pk: &[u8], ss: &mut [u8], ct: &mut [u8]) { + cca_encrypt(&PARAMS_1024, randbytes32, pk, ss, ct); +} + +pub fn decrypt_512(sk: &[u8], ct: &[u8], ss: &mut [u8]) { + cca_decrypt(&PARAMS_512, sk, ct, ss); +} + +pub fn decrypt_768(sk: &[u8], ct: &[u8], ss: &mut [u8]) { + cca_decrypt(&PARAMS_768, sk, ct, ss); +} + +pub fn decrypt_1024(sk: &[u8], ct: &[u8], ss: &mut [u8]) { + cca_decrypt(&PARAMS_1024, sk, ct, ss); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs new file mode 100644 index 000000000000..e1b2139f8ad8 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/lib.rs @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// comment out if debugging with print macros !!! +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::many_single_char_names)] +#![allow(clippy::needless_range_loop)] +#![allow(clippy::manual_memcpy)] +#![allow(clippy::new_without_default)] +pub mod aes; +pub mod arch; +pub mod dilithium; +pub mod gcm; +pub mod hash256; +pub mod hash384; +pub mod hash512; +pub mod hmac; +pub mod kyber; +pub mod nhs; +pub mod rand; +pub mod sha3; +pub mod share; +pub mod x509; +pub mod bn254; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/main.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/main.rs new file mode 100644 index 000000000000..e7a11a969c03 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/nhs.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/nhs.rs new file mode 100644 index 000000000000..8fc70fb1c3d7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/nhs.rs @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* NewHope Simple API high-level functions */ + +use crate::rand::RAND; +use crate::sha3; +use crate::sha3::SHA3; + +const PRIME: i32 = 0x3001; // q in Hex +const LGN: usize = 10; // Degree n=2^LGN +const ND: u32 = 0xF7002FFF; // 1/(R-q) mod R +const ONE: i32 = 0x2AC8; // R mod q +const R2MODP: u64 = 0x1620; // R^2 mod q + +const DEGREE: usize = 1 << LGN; +const WL: usize = 32; + +const INV: i32 = 0xeab; +const INVPR: i32 = 0x2c2a; + +const ROOTS: [i32; 1024] = [ + 0x2ac8, 0x2baf, 0x299b, 0x685, 0x2f04, 0x158d, 0x2d49, 0x24b5, 0x1edc, 0xab3, 0x2a95, 0x24d, + 0x3cb, 0x6a8, 0x12f9, 0x15ba, 0x1861, 0x2a89, 0x1c5c, 0xbe6, 0xc1e, 0x2024, 0x207, 0x19ce, + 0x2710, 0x1744, 0x18bc, 0x2cd7, 0x396, 0x18d5, 0x1c45, 0xc4, 0x21a6, 0xe03, 0x2b3c, 0x2d91, + 0xc5d, 0x432, 0x1fbc, 0xcae, 0x2512, 0x2979, 0x3b2, 0x714, 0xb2e, 0x1a97, 0x1a03, 0x1bcd, + 0x2216, 0x2701, 0xa, 0x263c, 0x1179, 0x200c, 0x2d08, 0x1c34, 0x291, 0x2c99, 0x2a5a, 0x723, + 0xb1d, 0x1ccc, 0x1fb6, 0x2f58, 0x2bfe, 0x1cda, 0x2a0, 0x5f1, 0x2de, 0x1fc7, 0x1ea8, 0x1719, + 0x2fa7, 0x27ec, 0x20ff, 0x12c0, 0x1ac1, 0x2232, 0x2f9b, 0xd3e, 0x2aed, 0x15f0, 0x11e8, 0xed0, + 0x26a, 0x1de5, 0xa3f, 0xf43, 0xebf, 0x204e, 0xac7, 0x2d9c, 0x5ea, 0x25d1, 0xb6, 0x49c, 0x995, + 0x2555, 0x26e2, 0x100, 0x1878, 0x5aa, 0x2e10, 0x271c, 0xcb, 0x1b4c, 0x2fb8, 0x25b7, 0x1543, + 0x2c7b, 0x241a, 0x2223, 0x20ca, 0x24ed, 0x137, 0x1b65, 0x1dc2, 0x7c7, 0x2ec3, 0xd0c, 0x1169, + 0x1c7a, 0x1ea1, 0xf89, 0x2199, 0x291d, 0x1088, 0x2046, 0x256d, 0x2bc7, 0x2e9b, 0x41f, 0x1b55, + 0x2b38, 0xd0, 0x2e6a, 0x1755, 0x6bc, 0x2724, 0x3ba, 0x222e, 0x2c5c, 0x2da5, 0x213c, 0x10fe, + 0x169a, 0x1552, 0x5d3, 0x300, 0x1b5d, 0x1342, 0x2004, 0x256f, 0x2039, 0x667, 0x23b5, 0x1123, + 0xdb, 0x2da0, 0xe1e, 0x2f54, 0x2767, 0x154a, 0x40a, 0x11d3, 0x2821, 0xc09, 0x974, 0x694, 0xfbf, + 0x27ba, 0x132, 0x83f, 0x2d06, 0x10e, 0x183f, 0x29ae, 0x28c3, 0x2dc9, 0x1144, 0x2c70, 0x2a4a, + 0xf3c, 0x1e32, 0x1171, 0x1e43, 0xdd4, 0x2ddf, 0x28d2, 0xfac, 0x3c4, 0x2f19, 0x10a6, 0x2f7, + 0xe1d, 0x828, 0x138f, 0x1332, 0xfab, 0xcf6, 0x13f8, 0x24a0, 0x112d, 0x2717, 0x6e7, 0x1044, + 0x36e, 0xfe8, 0x6a, 0xba7, 0x1d69, 0x29ec, 0x23b2, 0xaee, 0x16df, 0x1068, 0x1a7e, 0x253f, + 0x24c, 0xb33, 0x2683, 0x15ce, 0x1ad3, 0x1a36, 0xc96, 0xaea, 0x260a, 0xce, 0x28b1, 0xe4f, + 0x2b11, 0x5f8, 0x1fc4, 0xe77, 0x2366, 0x11f9, 0x153c, 0x24eb, 0x20cd, 0x1398, 0x22, 0x2b97, + 0x249b, 0x8eb, 0x12b2, 0x2fe3, 0x29c1, 0x1b00, 0x2663, 0xeaa, 0x2e06, 0xe0, 0x1569, 0x10f5, + 0x284e, 0xa38, 0x201d, 0x1c53, 0x1681, 0x1f6f, 0x2f95, 0x2fe8, 0xacb, 0x1680, 0x17fd, 0x2c39, + 0x165a, 0x10bb, 0x29d8, 0x2622, 0x1196, 0x884, 0x2a79, 0x140e, 0x2d80, 0x6fa, 0x11b2, 0x26c4, + 0x355, 0x1054, 0x29e9, 0x23ed, 0xbe3, 0x24fa, 0x1fb3, 0x10ac, 0x2919, 0x2584, 0x10a4, 0xe85, + 0x650, 0x1893, 0x1dc1, 0xd8e, 0x12dc, 0x2d42, 0x284d, 0xfff, 0x250f, 0xacd, 0x13c3, 0x6cc, + 0x1a79, 0x1221, 0x2614, 0x270a, 0x1ea, 0x155, 0x2818, 0x222c, 0x2e5b, 0x25d8, 0x1dbf, 0x191c, + 0xb0f, 0xdac, 0x1082, 0x12ef, 0x11b6, 0xfa8, 0x2b72, 0x159d, 0x209e, 0x31b, 0x2c7c, 0x14f7, + 0xe09, 0x1bb2, 0x1ec7, 0x2404, 0x20ae, 0x6ad, 0xed6, 0x2b70, 0x1c7b, 0x18d1, 0x2732, 0x12da, + 0xd56, 0x5c1, 0x1648, 0x18b7, 0x1605, 0x1bc4, 0x280, 0x2ece, 0xc, 0x1aae, 0x1c4, 0x1cdb, + 0x22d6, 0x21d8, 0x257c, 0x51f, 0x211b, 0xff, 0x2ee0, 0x2585, 0xe1, 0x2c35, 0x26db, 0x2971, + 0x2208, 0x17e1, 0x21be, 0x135e, 0x28d6, 0x2891, 0x1689, 0x2138, 0xb86, 0x2e3a, 0x1204, 0x2d10, + 0x2324, 0xf3f, 0x2508, 0x33d, 0xcb2, 0x292a, 0xe27, 0x2e64, 0x29f8, 0x2d46, 0x9b7, 0x20eb, + 0x1b7c, 0x9eb, 0x2b2a, 0x58c, 0x27d0, 0x121b, 0x272e, 0x29f6, 0x2dbd, 0x2697, 0x2aac, 0xd6f, + 0x1c67, 0x2c5b, 0x108d, 0x363, 0x249d, 0x2d5e, 0x2fd, 0x2cb2, 0x1f8f, 0x20a4, 0xa19, 0x2ac9, + 0x19b1, 0x1581, 0x17a2, 0x29eb, 0x1b72, 0x13b0, 0xee4, 0xa8f, 0x2315, 0x5e6, 0x951, 0x2e29, + 0xdad, 0x1f2b, 0x224e, 0x37f, 0x1a72, 0xa91, 0x1407, 0x2df9, 0x3ad, 0x23f7, 0x1a24, 0x1d2a, + 0x234b, 0x1df3, 0x1143, 0x7ff, 0x1a6d, 0x2774, 0x2690, 0x2ab5, 0x586, 0x2781, 0x2009, 0x2fdd, + 0x2881, 0x399, 0x2fb6, 0x144, 0x137f, 0xfa0, 0x2e4c, 0x1c7f, 0x2fac, 0xb09, 0x1264, 0x127b, + 0x198c, 0x2b40, 0x230, 0x1cf4, 0x180b, 0xb58, 0x144a, 0x2aec, 0xfb, 0x2602, 0x14ee, 0x783, + 0x1098, 0x23d8, 0x203, 0xe9, 0x108a, 0x14b8, 0xeec, 0xc58, 0x1248, 0x243c, 0x28aa, 0x6bf, + 0x27c4, 0x276e, 0x19b8, 0x1d11, 0x2e16, 0x472, 0x1464, 0x24b9, 0x662, 0x1097, 0x2067, 0x20d6, + 0x171c, 0x4, 0x682, 0x17bb, 0x1186, 0x4f2, 0x3ff, 0x2a43, 0x1dc7, 0x1ae5, 0x8cc, 0x2e7c, + 0x2ef8, 0x2ae0, 0x2904, 0xed4, 0x6c5, 0x14ae, 0xb72, 0x11c3, 0x337, 0x2da3, 0x2916, 0x6d8, + 0x1cf9, 0x10ee, 0x1800, 0x1ae4, 0xa0d, 0x101b, 0x1a8d, 0x2e98, 0x24cd, 0x813, 0x1aa4, 0x9b9, + 0x680, 0x2349, 0x24d1, 0x20f8, 0xe31, 0x249f, 0x216b, 0x12d9, 0x1d21, 0x19db, 0x191a, 0x1dd0, + 0x5df, 0x55c, 0x2b86, 0x213, 0xe9e, 0x1ef1, 0x268a, 0x1d5e, 0x1e20, 0x28c1, 0x1379, 0x249, + 0x19de, 0x18b, 0x1e41, 0x2a1e, 0x2612, 0x297, 0x2e96, 0x2102, 0x46, 0x1b9f, 0x1a4d, 0x2050, + 0x1b32, 0x568, 0x11f7, 0x1829, 0x870, 0x1f4, 0x1dca, 0x990, 0x1df6, 0x2b62, 0x13ec, 0x9f2, + 0x1260, 0x2997, 0x1412, 0x1e6d, 0x1694, 0x11ac, 0x2d8b, 0x276f, 0x26f5, 0x233e, 0x2b44, 0x2f5a, + 0x2d37, 0x2cb1, 0xc75, 0x98d, 0x1d56, 0x7ae, 0x10e6, 0x113f, 0x17b8, 0xad3, 0x737, 0x221e, + 0x1b70, 0x1f3e, 0x2966, 0x18b2, 0x4fa, 0x2044, 0x1312, 0x154e, 0x2029, 0x700, 0x1b45, 0x27a6, + 0x226a, 0x21bf, 0x58d, 0x2f11, 0x2e02, 0x17fc, 0x4d2, 0x1757, 0xcb1, 0x2ef1, 0x2582, 0x1276, + 0x881, 0x2fc0, 0x104a, 0x670, 0x274f, 0x2b53, 0x19dd, 0x752, 0x1663, 0xcbd, 0x2b2b, 0x2fc6, + 0x13b6, 0x21e6, 0x15f6, 0x126b, 0x2637, 0x1cd9, 0x2f50, 0xe82, 0x5b0, 0x24e0, 0x1350, 0x2f24, + 0x21f7, 0x1a16, 0x2f3e, 0x167e, 0x1f7d, 0x28a0, 0x16f0, 0xe33, 0x53b, 0x28c5, 0x1500, 0x2f88, + 0x26cc, 0x2018, 0x1604, 0x218b, 0x2cd1, 0x9ee, 0x17f3, 0x5fd, 0x1f5a, 0x2d0, 0x2b46, 0x23cc, + 0x503, 0x1c46, 0x1cc3, 0x28e2, 0x243e, 0x122b, 0x2e0c, 0xe37, 0x2611, 0x85e, 0x9b8, 0x1b24, + 0x762, 0x19b6, 0x3bc, 0x2d50, 0x2079, 0x18da, 0x170a, 0x800, 0xaa2, 0x135a, 0x1a15, 0x13d1, + 0xca, 0x2113, 0x2db9, 0xdb2, 0x1a5c, 0x29a9, 0x1488, 0x14c1, 0x2c9, 0x917, 0x28e7, 0x265c, + 0xdab, 0x2ab9, 0x2bc6, 0x105b, 0x1839, 0x219c, 0x50, 0x11da, 0x1802, 0xf56, 0x2e6, 0x2190, + 0xddb, 0x56e, 0x9d9, 0x1c81, 0x1016, 0x12d6, 0x296f, 0x14b4, 0x1014, 0x1e64, 0x1d90, 0x89f, + 0x2bc2, 0x2777, 0x2819, 0x1c65, 0x1a41, 0x5a2, 0x2cd2, 0x427, 0xd71, 0x29c8, 0x1e58, 0x53f, + 0x7c5, 0x1dcd, 0x4a1, 0x1268, 0x2597, 0x2926, 0xee, 0x111b, 0x1038, 0xe6c, 0x22dc, 0x2f2f, + 0x441, 0x2cfd, 0x1cb0, 0x6a4, 0x2224, 0x620, 0x5dc, 0x16b1, 0x2a1d, 0x1787, 0x20c7, 0x641, + 0xd84, 0x1c05, 0x2d0d, 0x2f52, 0x1b8c, 0xd7d, 0x17e8, 0x1589, 0xc73, 0x151b, 0x4e2, 0x1ae9, + 0x1b18, 0xb9b, 0x949, 0x2c60, 0x1e7a, 0xd5, 0x1bdc, 0x1f57, 0x1753, 0x124a, 0x559, 0xb76, + 0x2334, 0x12d1, 0x1de1, 0x14b2, 0x2faa, 0x1697, 0x147a, 0x5a1, 0x2c30, 0x1c02, 0x1043, 0x2ee1, + 0x2402, 0x1cc8, 0x2a16, 0xff7, 0x1364, 0x1b9a, 0x2a53, 0x2f94, 0x294c, 0x1ee5, 0x1a87, 0x2141, + 0xd66, 0x953, 0x28a3, 0x2f30, 0x2477, 0x18e3, 0x1035, 0x1fc1, 0x1d68, 0x2fb3, 0x138c, 0x2487, + 0x1bf8, 0xd96, 0x1018, 0x748, 0x244e, 0x15bd, 0x175e, 0x2be, 0x23d, 0x1da, 0x176d, 0xc17, + 0x24be, 0x2ebb, 0x7d8, 0x100a, 0x759, 0x1db4, 0x2259, 0x23f4, 0x2d59, 0x2847, 0xbf5, 0x1cfe, + 0xa20, 0x258, 0x1180, 0x279c, 0x54, 0x2abf, 0xc5c, 0x9f9, 0x3d5, 0x2ce4, 0x165f, 0x23d9, + 0x27b9, 0x6f9, 0x281a, 0x169e, 0x627, 0x156d, 0x1ff8, 0x211, 0x2e34, 0x1724, 0x2c2e, 0x2790, + 0x2dd5, 0x2bf2, 0xdbc, 0x2884, 0x20a9, 0x2390, 0x1e1a, 0x1b6a, 0x5f7, 0xab7, 0x1333, 0x16ab, + 0x28dd, 0x20, 0x30f, 0x24b6, 0x5c2, 0x1ce4, 0x1400, 0x2669, 0x60, 0x156c, 0xe20, 0x26d4, + 0x26ab, 0x1ebb, 0x223d, 0x5b4, 0x2025, 0x1e1c, 0xaae, 0x2e08, 0x6cd, 0x1677, 0x13d9, 0x17b5, + 0x1046, 0x1d8c, 0x14eb, 0x18d8, 0x1ce5, 0x2478, 0x16ae, 0xb79, 0x23d4, 0x684, 0x156b, 0x567, + 0x1a, 0x29ce, 0x83a, 0x19e8, 0x58e, 0x294a, 0x1136, 0x2319, 0x2fba, 0x1a29, 0x1d, 0x1879, + 0x291b, 0x19f6, 0x2c2f, 0x21c9, 0x19bb, 0xbbc, 0x26f9, 0xc22, 0x708, 0x11a1, 0x18d3, 0x7f8, + 0x28f8, 0x2427, 0x1deb, 0xaed, 0x26aa, 0x2482, 0x203b, 0x2f05, 0x2b82, 0x192f, 0x2df4, 0x8dc, + 0x2877, 0xd5e, 0x240e, 0x775, 0x2dae, 0x1d3e, 0x20ba, 0x215b, 0x22d1, 0xeba, 0xf50, 0xaa8, + 0x184a, 0x1f67, 0x2e04, 0xc6e, 0x6dd, 0x1a09, 0x27f, 0x494, 0x1426, 0xae3, 0xe15, 0x65f, + 0x13c4, 0x105, 0x872, 0x2667, 0x1ff6, 0xd9f, 0x2ca1, 0x2f39, 0x2657, 0x23fd, 0x2405, 0xb73, + 0x2294, 0x1f1e, 0x2eba, 0x110a, 0x2cae, 0x141f, 0x22cd, 0x25d6, 0x11c1, 0x1c, 0x2d8e, 0x161a, + 0x1aa8, 0x229e, 0x1bf9, 0x7cf, 0x106d, 0x2c40, 0xd93, 0x255e, 0x28c2, 0xc1a, 0x2f17, 0x7ca, + 0x2f63, 0xbf, +]; +const IROOTS: [i32; 1024] = [ + 0x2ac8, 0x452, 0x297c, 0x666, 0xb4c, 0x2b8, 0x1a74, 0xfd, 0x1a47, 0x1d08, 0x2959, 0x2c36, + 0x2db4, 0x56c, 0x254e, 0x1125, 0x2f3d, 0x13bc, 0x172c, 0x2c6b, 0x32a, 0x1745, 0x18bd, 0x8f1, + 0x1633, 0x2dfa, 0xfdd, 0x23e3, 0x241b, 0x13a5, 0x578, 0x17a0, 0xa9, 0x104b, 0x1335, 0x24e4, + 0x28de, 0x5a7, 0x368, 0x2d70, 0x13cd, 0x2f9, 0xff5, 0x1e88, 0x9c5, 0x2ff7, 0x900, 0xdeb, + 0x1434, 0x15fe, 0x156a, 0x24d3, 0x28ed, 0x2c4f, 0x688, 0xaef, 0x2353, 0x1045, 0x2bcf, 0x23a4, + 0x270, 0x4c5, 0x21fe, 0xe5b, 0xfbb, 0x1f79, 0x6e4, 0xe68, 0x2078, 0x1160, 0x1387, 0x1e98, + 0x22f5, 0x13e, 0x283a, 0x123f, 0x149c, 0x2eca, 0xb14, 0xf37, 0xdde, 0xbe7, 0x386, 0x1abe, + 0xa4a, 0x49, 0x14b5, 0x2f36, 0x8e5, 0x1f1, 0x2a57, 0x1789, 0x2f01, 0x91f, 0xaac, 0x266c, + 0x2b65, 0x2f4b, 0xa30, 0x2a17, 0x265, 0x253a, 0xfb3, 0x2142, 0x20be, 0x25c2, 0x121c, 0x2d97, + 0x2131, 0x1e19, 0x1a11, 0x514, 0x22c3, 0x66, 0xdcf, 0x1540, 0x1d41, 0xf02, 0x815, 0x5a, 0x18e8, + 0x1159, 0x103a, 0x2d23, 0x2a10, 0x2d61, 0x1327, 0x403, 0x25c9, 0x7b3, 0x1f0c, 0x1a98, 0x2f21, + 0x1fb, 0x2157, 0x99e, 0x1501, 0x640, 0x1e, 0x1d4f, 0x2716, 0xb66, 0x46a, 0x2fdf, 0x1c69, 0xf34, + 0xb16, 0x1ac5, 0x1e08, 0xc9b, 0x218a, 0x103d, 0x2a09, 0x4f0, 0x21b2, 0x750, 0x2f33, 0x9f7, + 0x2517, 0x236b, 0x15cb, 0x152e, 0x1a33, 0x97e, 0x24ce, 0x2db5, 0xac2, 0x1583, 0x1f99, 0x1922, + 0x2513, 0xc4f, 0x615, 0x1298, 0x245a, 0x2f97, 0x2019, 0x2c93, 0x1fbd, 0x291a, 0x8ea, 0x1ed4, + 0xb61, 0x1c09, 0x230b, 0x2056, 0x1ccf, 0x1c72, 0x27d9, 0x21e4, 0x2d0a, 0x1f5b, 0xe8, 0x2c3d, + 0x2055, 0x72f, 0x222, 0x222d, 0x11be, 0x1e90, 0x11cf, 0x20c5, 0x5b7, 0x391, 0x1ebd, 0x238, + 0x73e, 0x653, 0x17c2, 0x2ef3, 0x2fb, 0x27c2, 0x2ecf, 0x847, 0x2042, 0x296d, 0x268d, 0x23f8, + 0x7e0, 0x1e2e, 0x2bf7, 0x1ab7, 0x89a, 0xad, 0x21e3, 0x261, 0x2f26, 0x1ede, 0xc4c, 0x299a, + 0xfc8, 0xa92, 0xffd, 0x1cbf, 0x14a4, 0x2d01, 0x2a2e, 0x1aaf, 0x1967, 0x1f03, 0xec5, 0x25c, + 0x3a5, 0xdd3, 0x2c47, 0x8dd, 0x2945, 0x18ac, 0x197, 0x2f31, 0x4c9, 0x14ac, 0x2be2, 0x166, + 0x43a, 0xa94, 0x1b53, 0x293c, 0x212d, 0x6fd, 0x521, 0x109, 0x185, 0x2735, 0x151c, 0x123a, + 0x5be, 0x2c02, 0x2b0f, 0x1e7b, 0x1846, 0x297f, 0x2ffd, 0x18e5, 0xf2b, 0xf9a, 0x1f6a, 0x299f, + 0xb48, 0x1b9d, 0x2b8f, 0x1eb, 0x12f0, 0x1649, 0x893, 0x83d, 0x2942, 0x757, 0xbc5, 0x1db9, + 0x23a9, 0x2115, 0x1b49, 0x1f77, 0x2f18, 0x2dfe, 0xc29, 0x1f69, 0x287e, 0x1b13, 0x9ff, 0x2f06, + 0x515, 0x1bb7, 0x24a9, 0x17f6, 0x130d, 0x2dd1, 0x4c1, 0x1675, 0x1d86, 0x1d9d, 0x24f8, 0x55, + 0x1382, 0x1b5, 0x2061, 0x1c82, 0x2ebd, 0x4b, 0x2c68, 0x780, 0x24, 0xff8, 0x880, 0x2a7b, 0x54c, + 0x971, 0x88d, 0x1594, 0x2802, 0x1ebe, 0x120e, 0xcb6, 0x12d7, 0x15dd, 0xc0a, 0x2c54, 0x208, + 0x1bfa, 0x2570, 0x158f, 0x2c82, 0xdb3, 0x10d6, 0x2254, 0x1d8, 0x26b0, 0x2a1b, 0xcec, 0x2572, + 0x211d, 0x1c51, 0x148f, 0x616, 0x185f, 0x1a80, 0x1650, 0x538, 0x25e8, 0xf5d, 0x1072, 0x34f, + 0x2d04, 0x2a3, 0xb64, 0x2c9e, 0x1f74, 0x3a6, 0x139a, 0x2292, 0x555, 0x96a, 0x244, 0x60b, 0x8d3, + 0x1de6, 0x831, 0x2a75, 0x4d7, 0x2616, 0x1485, 0xf16, 0x264a, 0x2bb, 0x609, 0x19d, 0x21da, + 0x6d7, 0x234f, 0x2cc4, 0xaf9, 0x20c2, 0xcdd, 0x2f1, 0x1dfd, 0x1c7, 0x247b, 0xec9, 0x1978, + 0x770, 0x72b, 0x1ca3, 0xe43, 0x1820, 0xdf9, 0x690, 0x926, 0x3cc, 0x2f20, 0xa7c, 0x121, 0x2f02, + 0xee6, 0x2ae2, 0xa85, 0xe29, 0xd2b, 0x1326, 0x2e3d, 0x1553, 0x2ff5, 0x133, 0x2d81, 0x143d, + 0x19fc, 0x174a, 0x19b9, 0x2a40, 0x22ab, 0x1d27, 0x8cf, 0x1730, 0x1386, 0x491, 0x212b, 0x2954, + 0xf53, 0xbfd, 0x113a, 0x144f, 0x21f8, 0x1b0a, 0x385, 0x2ce6, 0xf63, 0x1a64, 0x48f, 0x2059, + 0x1e4b, 0x1d12, 0x1f7f, 0x2255, 0x24f2, 0x16e5, 0x1242, 0xa29, 0x1a6, 0xdd5, 0x7e9, 0x2eac, + 0x2e17, 0x8f7, 0x9ed, 0x1de0, 0x1588, 0x2935, 0x1c3e, 0x2534, 0xaf2, 0x2002, 0x7b4, 0x2bf, + 0x1d25, 0x2273, 0x1240, 0x176e, 0x29b1, 0x217c, 0x1f5d, 0xa7d, 0x6e8, 0x1f55, 0x104e, 0xb07, + 0x241e, 0xc14, 0x618, 0x1fad, 0x2cac, 0x93d, 0x1e4f, 0x2907, 0x281, 0x1bf3, 0x588, 0x277d, + 0x1e6b, 0x9df, 0x629, 0x1f46, 0x19a7, 0x3c8, 0x1804, 0x1981, 0x2536, 0x19, 0x6c, 0x1092, + 0x1980, 0x13ae, 0xfe4, 0x2f42, 0x9e, 0x2837, 0xea, 0x23e7, 0x73f, 0xaa3, 0x226e, 0x3c1, 0x1f94, + 0x2832, 0x1408, 0xd63, 0x1559, 0x19e7, 0x273, 0x2fe5, 0x1e40, 0xa2b, 0xd34, 0x1be2, 0x353, + 0x1ef7, 0x147, 0x10e3, 0xd6d, 0x248e, 0xbfc, 0xc04, 0x9aa, 0xc8, 0x360, 0x2262, 0x100b, 0x99a, + 0x278f, 0x2efc, 0x1c3d, 0x29a2, 0x21ec, 0x251e, 0x1bdb, 0x2b6d, 0x2d82, 0x15f8, 0x2924, 0x2393, + 0x1fd, 0x109a, 0x17b7, 0x2559, 0x20b1, 0x2147, 0xd30, 0xea6, 0xf47, 0x12c3, 0x253, 0x288c, + 0xbf3, 0x22a3, 0x78a, 0x2725, 0x20d, 0x16d2, 0x47f, 0xfc, 0xfc6, 0xb7f, 0x957, 0x2514, 0x1216, + 0xbda, 0x709, 0x2809, 0x172e, 0x1e60, 0x28f9, 0x23df, 0x908, 0x2445, 0x1646, 0xe38, 0x3d2, + 0x160b, 0x6e6, 0x1788, 0x2fe4, 0x15d8, 0x47, 0xce8, 0x1ecb, 0x6b7, 0x2a73, 0x1619, 0x27c7, + 0x633, 0x2fe7, 0x2a9a, 0x1a96, 0x297d, 0xc2d, 0x2488, 0x1953, 0xb89, 0x131c, 0x1729, 0x1b16, + 0x1275, 0x1fbb, 0x184c, 0x1c28, 0x198a, 0x2934, 0x1f9, 0x2553, 0x11e5, 0xfdc, 0x2a4d, 0xdc4, + 0x1146, 0x956, 0x92d, 0x21e1, 0x1a95, 0x2fa1, 0x998, 0x1c01, 0x131d, 0x2a3f, 0xb4b, 0x2cf2, + 0x2fe1, 0x724, 0x1956, 0x1cce, 0x254a, 0x2a0a, 0x1497, 0x11e7, 0xc71, 0xf58, 0x77d, 0x2245, + 0x40f, 0x22c, 0x871, 0x3d3, 0x18dd, 0x1cd, 0x2df0, 0x1009, 0x1a94, 0x29da, 0x1963, 0x7e7, + 0x2908, 0x848, 0xc28, 0x19a2, 0x31d, 0x2c2c, 0x2608, 0x23a5, 0x542, 0x2fad, 0x865, 0x1e81, + 0x2da9, 0x25e1, 0x1303, 0x240c, 0x7ba, 0x2a8, 0xc0d, 0xda8, 0x124d, 0x28a8, 0x1ff7, 0x2829, + 0x146, 0xb43, 0x23ea, 0x1894, 0x2e27, 0x2dc4, 0x2d43, 0x18a3, 0x1a44, 0xbb3, 0x28b9, 0x1fe9, + 0x226b, 0x1409, 0xb7a, 0x1c75, 0x4e, 0x1299, 0x1040, 0x1fcc, 0x171e, 0xb8a, 0xd1, 0x75e, + 0x26ae, 0x229b, 0xec0, 0x157a, 0x111c, 0x6b5, 0x6d, 0x5ae, 0x1467, 0x1c9d, 0x200a, 0x5eb, + 0x1339, 0xbff, 0x120, 0x1fbe, 0x13ff, 0x3d1, 0x2a60, 0x1b87, 0x196a, 0x57, 0x1b4f, 0x1220, + 0x1d30, 0xccd, 0x248b, 0x2aa8, 0x1db7, 0x18ae, 0x10aa, 0x1425, 0x2f2c, 0x1187, 0x3a1, 0x26b8, + 0x2466, 0x14e9, 0x1518, 0x2b1f, 0x1ae6, 0x238e, 0x1a78, 0x1819, 0x2284, 0x1475, 0xaf, 0x2f4, + 0x13fc, 0x227d, 0x29c0, 0xf3a, 0x187a, 0x5e4, 0x1950, 0x2a25, 0x29e1, 0xddd, 0x295d, 0x1351, + 0x304, 0x2bc0, 0xd2, 0xd25, 0x2195, 0x1fc9, 0x1ee6, 0x2f13, 0x6db, 0xa6a, 0x1d99, 0x2b60, + 0x1234, 0x283c, 0x2ac2, 0x11a9, 0x639, 0x2290, 0x2bda, 0x32f, 0x2a5f, 0x15c0, 0x139c, 0x7e8, + 0x88a, 0x43f, 0x2762, 0x1271, 0x119d, 0x1fed, 0x1b4d, 0x692, 0x1d2b, 0x1feb, 0x1380, 0x2628, + 0x2a93, 0x2226, 0xe71, 0x2d1b, 0x20ab, 0x17ff, 0x1e27, 0x2fb1, 0xe65, 0x17c8, 0x1fa6, 0x43b, + 0x548, 0x2256, 0x9a5, 0x71a, 0x26ea, 0x2d38, 0x1b40, 0x1b79, 0x658, 0x15a5, 0x224f, 0x248, + 0xeee, 0x2f37, 0x1c30, 0x15ec, 0x1ca7, 0x255f, 0x2801, 0x18f7, 0x1727, 0xf88, 0x2b1, 0x2c45, + 0x164b, 0x289f, 0x14dd, 0x2649, 0x27a3, 0x9f0, 0x21ca, 0x1f5, 0x1dd6, 0xbc3, 0x71f, 0x133e, + 0x13bb, 0x2afe, 0xc35, 0x4bb, 0x2d31, 0x10a7, 0x2a04, 0x180e, 0x2613, 0x330, 0xe76, 0x19fd, + 0xfe9, 0x935, 0x79, 0x1b01, 0x73c, 0x2ac6, 0x21ce, 0x1911, 0x761, 0x1084, 0x1983, 0xc3, 0x15eb, + 0xe0a, 0xdd, 0x1cb1, 0xb21, 0x2a51, 0x217f, 0xb1, 0x1328, 0x9ca, 0x1d96, 0x1a0b, 0xe1b, 0x1c4b, + 0x3b, 0x4d6, 0x2344, 0x199e, 0x28af, 0x1624, 0x4ae, 0x8b2, 0x2991, 0x1fb7, 0x41, 0x2780, + 0x1d8b, 0xa7f, 0x110, 0x2350, 0x18aa, 0x2b2f, 0x1805, 0x1ff, 0xf0, 0x2a74, 0xe42, 0xd97, 0x85b, + 0x14bc, 0x2901, 0xfd8, 0x1ab3, 0x1cef, 0xfbd, 0x2b07, 0x174f, 0x69b, 0x10c3, 0x1491, 0xde3, + 0x28ca, 0x252e, 0x1849, 0x1ec2, 0x1f1b, 0x2853, 0x12ab, 0x2674, 0x238c, 0x350, 0x2ca, 0xa7, + 0x4bd, 0xcc3, 0x90c, 0x892, 0x276, 0x1e55, 0x196d, 0x1194, 0x1bef, 0x66a, 0x1da1, 0x260f, + 0x1c15, 0x49f, 0x120b, 0x2671, 0x1237, 0x2e0d, 0x2791, 0x17d8, 0x1e0a, 0x2a99, 0x14cf, 0xfb1, + 0x15b4, 0x1462, 0x2fbb, 0xeff, 0x16b, 0x2d6a, 0x9ef, 0x5e3, 0x11c0, 0x2e76, 0x1623, 0x2db8, + 0x1c88, 0x740, 0x11e1, 0x12a3, 0x977, 0x1110, 0x2163, 0x2dee, 0x47b, 0x2aa5, 0x2a22, 0x1231, + 0x16e7, 0x1626, 0x12e0, 0x1d28, 0xe96, 0xb62, 0x21d0, 0xf09, 0xb30, 0xcb8, 0x2981, 0x2648, + 0x155d, 0x27ee, 0xb34, 0x169, 0x1574, 0x1fe6, 0x25f4, 0x151d, 0x1801, 0x1f13, 0x1308, 0x2929, + 0x6eb, 0x25e, 0x2cca, 0x1e3e, 0x248f, +]; + +fn round(a: i32, b: i32) -> i32 { + (a + b / 2) / b +} + +/* Constant time absolute value */ +fn nabs(x: i32) -> i32 { + let mask = x >> 31; + (x + mask) ^ mask +} + +/* Montgomery stuff */ + +fn redc(t: u64) -> i32 { + let m = (t as u32).wrapping_mul(ND); + (((m as u64) * (PRIME as u64) + t) >> WL) as i32 +} + +fn nres(x: i32) -> i32 { + redc((x as u64) * R2MODP) +} + +fn modmul(a: i32, b: i32) -> i32 { + redc((a as u64) * (b as u64)) +} + +/* Cooley-Tukey NTT */ +fn ntt(x: &mut [i32]) { + let mut t = DEGREE / 2; + let q = PRIME; + + /* Convert to Montgomery form */ + for j in 0..DEGREE { + x[j] = nres(x[j]) + } + let mut m = 1; + while m < DEGREE { + let mut k = 0; + for i in 0..m { + let s = ROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = modmul(x[j + t], s); + x[j] = u + v; + x[j + t] = u + 2 * q - v; + } + k += 2 * t; + } + t /= 2; + m *= 2; + } +} + +/* Gentleman-Sande INTT */ + +fn intt(x: &mut [i32]) { + let mut t = 1; + let q = PRIME; + let mut m = DEGREE / 2; + while m > 1 { + let mut k = 0; + for i in 0..m { + let s = IROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = x[j + t]; + x[j] = u + v; + let w = u + (DEGREE as i32) * q - v; + x[j + t] = modmul(w, s); + } + k += 2 * t; + } + t *= 2; + m /= 2; + } + + /* Last iteration merged with n^-1 */ + t = DEGREE / 2; + for j in 0..t { + let u = x[j]; + let v = x[j + t]; + let w = u + (DEGREE as i32) * q - v; + x[j + t] = modmul(w, INVPR); + x[j] = modmul(u + v, INV); + } + /* convert back from Montgomery to "normal" form */ + for j in 0..DEGREE { + x[j] = redc(x[j] as u64); + x[j] -= q; + x[j] += (x[j] >> (WL - 1)) & q; + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +fn encode(key: &[u8], poly: &mut [i32]) { + let q2 = PRIME / 2; + let mut j = 0; + let mut i = 0; + while i < 256 { + let mut kj = key[j]; + j += 1; + for _ in 0..8 { + let b = (kj & 1) as i32; + poly[i] = b * q2; + poly[i + 256] = b * q2; + poly[i + 512] = b * q2; + poly[i + 768] = b * q2; + kj >>= 1; + i += 1; + } + } +} + +fn decode(poly: &[i32], key: &mut [u8]) { + let q2 = PRIME / 2; + for i in 0..32 { + key[i] = 0; + } + + let mut i = 0; + let mut j = 0; + while i < 256 { + for _ in 0..8 { + let t = nabs(poly[i] - q2) + + nabs(poly[i + 256] - q2) + + nabs(poly[i + 512] - q2) + + nabs(poly[i + 768] - q2); + let mut b = t - PRIME; + b = (b >> 31) & 1; + key[j] = (key[j] >> 1) + ((b << 7) as u8); + i += 1; + } + j += 1; + } +} + +/* convert 32-byte seed to random polynomial */ + +fn parse(seed: &[u8], poly: &mut [i32]) { + let mut hash: [u8; 4 * DEGREE] = [0; 4 * DEGREE]; + let mut sh = SHA3::new(sha3::SHAKE128); + for i in 0..32 { + sh.process(seed[i]) + } + sh.shake(&mut hash, 4 * DEGREE); + + let mut j = 0; + for i in 0..DEGREE { + let mut n = (hash[j] & 0x7f) as i32; + n <<= 8; + n += (hash[j + 1]) as i32; + n <<= 8; + n += (hash[j + 2]) as i32; + n <<= 8; + n += (hash[j + 3]) as i32; + j += 4; + poly[i] = nres(n); + //poly[i]=modmul(n,ONE); // reduce 31-bit random number mod q + } +} + +/* Compress 14 bits polynomial coefficients into byte array */ +/* 7 bytes is 3x14 */ + +fn nhs_pack(poly: &[i32], array: &mut [u8]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let a = poly[i]; + let b = poly[i + 1]; + let c = poly[i + 2]; + let d = poly[i + 3]; + i += 4; + array[j] = (a & 0xff) as u8; + array[j + 1] = (((a >> 8) | (b << 6)) & 0xff) as u8; + array[j + 2] = ((b >> 2) & 0xff) as u8; + array[j + 3] = (((b >> 10) | (c << 4)) & 0xff) as u8; + array[j + 4] = ((c >> 4) & 0xff) as u8; + array[j + 5] = (((c >> 12) | (d << 2)) & 0xff) as u8; + array[j + 6] = (d >> 6) as u8; + j += 7; + } +} + +fn nhs_unpack(array: &[u8], poly: &mut [i32]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let a = array[j] as i32; + let b = array[j + 1] as i32; + let c = array[j + 2] as i32; + let d = array[j + 3] as i32; + let e = array[j + 4] as i32; + let f = array[j + 5] as i32; + let g = array[j + 6] as i32; + j += 7; + poly[i] = a | ((b & 0x3f) << 8); + poly[i + 1] = (b >> 6) | (c << 2) | ((d & 0xf) << 10); + poly[i + 2] = (d >> 4) | (e << 4) | ((f & 3) << 12); + poly[i + 3] = (f >> 2) | (g << 6); + i += 4; + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +fn compress(poly: &[i32], array: &mut [u8]) { + let mut col = 0 as i32; + let mut j = 0; + let mut i = 0; + while i < DEGREE { + for _ in 0..8 { + let b = round(poly[i] * 8, PRIME) & 7; + col = (col << 3) + b; + i += 1; + } + array[j] = (col & 0xff) as u8; + array[j + 1] = ((col >> 8) & 0xff) as u8; + array[j + 2] = ((col >> 16) & 0xff) as u8; + j += 3; + col = 0; + } +} + +fn decompress(array: &[u8], poly: &mut [i32]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let mut col = (array[j + 2] as i32) & 0xff; + col = (col << 8) + ((array[j + 1] as i32) & 0xff); + col = (col << 8) + ((array[j] as i32) & 0xff); + j += 3; + for _ in 0..8 { + let b = (col & 0xe00000) >> 21; + col <<= 3; + poly[i] = round(b * PRIME, 8); + i += 1; + } + } +} + +/* generate centered binomial distribution */ + +fn error(rng: &mut RAND, poly: &mut [i32]) { + for i in 0..DEGREE { + let mut n1 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); + let mut n2 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); + let mut r = 0 as i32; + for _ in 0..16 { + r += (n1 & 1) - (n2 & 1); + n1 >>= 1; + n2 >>= 1; + } + poly[i] = r + PRIME; + } +} + +fn redc_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = redc(p[i] as u64); + } +} + +fn nres_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = nres(p[i]); + } +} + +fn poly_mul(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = modmul(p1[i], p3[i]); + } +} + +fn poly_add(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += p3[i]; + } +} + +fn poly_rsub(p1: &mut [i32], p2: &[i32]) { + for i in 0..DEGREE { + p1[i] = p2[i] + PRIME - p1[i]; + } +} + +/* reduces inputs < 2q */ +fn poly_soft_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let e = poly[i] - PRIME; + poly[i] = e + ((e >> (WL - 1)) & PRIME); + } +} + +/* fully reduces modulo q */ +fn poly_hard_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let mut e = modmul(poly[i], ONE); + e -= PRIME; + poly[i] = e + ((e >> (WL - 1)) & PRIME); + } +} + +/* API functions. See https://eprint.iacr.org/2016/1157.pdf Protocol 1 */ +// ss is secret key key, sb is seed|public key to be sent to client +pub fn server_1(rng: &mut RAND, sb: &mut [u8], ss: &mut [u8]) { + let mut seed: [u8; 32] = [0; 32]; + let mut array: [u8; 1792] = [0; 1792]; + let mut s: [i32; DEGREE] = [0; DEGREE]; + let mut e: [i32; DEGREE] = [0; DEGREE]; + let mut b: [i32; DEGREE] = [0; DEGREE]; + + for i in 0..32 { + seed[i] = rng.getbyte(); + } + + parse(&seed, &mut b); + + error(rng, &mut e); + error(rng, &mut s); + + ntt(&mut s); + ntt(&mut e); + poly_mul(&mut b, &s); + poly_add(&mut b, &e); + poly_hard_reduce(&mut b); + + redc_it(&mut b); + nhs_pack(&b, &mut array); + + for i in 0..32 { + sb[i] = seed[i]; + } + + for i in 0..1792 { + sb[i + 32] = array[i]; + } + + poly_hard_reduce(&mut s); + nhs_pack(&s, &mut array); + + for i in 0..1792 { + ss[i] = array[i]; + } +} + +// optimized to reduce memory +// uc is U|cbar to be returned to server +// okey is shared key +pub fn client(rng: &mut RAND, sb: &[u8], uc: &mut [u8], okey: &mut [u8]) { + let mut sh = SHA3::new(sha3::HASH256); + + let mut seed: [u8; 32] = [0; 32]; + let mut array: [u8; 1792] = [0; 1792]; + let mut key: [u8; 32] = [0; 32]; + let mut cc: [u8; 384] = [0; 384]; + + let mut sd: [i32; DEGREE] = [0; DEGREE]; + let mut ed: [i32; DEGREE] = [0; DEGREE]; + let mut u: [i32; DEGREE] = [0; DEGREE]; + let mut k: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + + error(rng, &mut sd); + error(rng, &mut ed); + + ntt(&mut sd); + ntt(&mut ed); + + for i in 0..32 { + seed[i] = sb[i]; + } + + for i in 0..1792 { + array[i] = sb[i + 32]; + } + + parse(&seed, &mut u); + + poly_mul(&mut u, &sd); + poly_add(&mut u, &ed); + poly_hard_reduce(&mut u); + + for i in 0..32 { + key[i] = rng.getbyte(); + } + + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + encode(&key, &mut k); + + nhs_unpack(&array, &mut c); + nres_it(&mut c); + + poly_mul(&mut c, &sd); + intt(&mut c); + error(rng, &mut ed); + poly_add(&mut c, &ed); + poly_add(&mut c, &k); + + compress(&c, &mut cc); + + sh = SHA3::new(sha3::HASH256); + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + for i in 0..32 { + okey[i] = key[i]; + } + + redc_it(&mut u); + nhs_pack(&u, &mut array); + + for i in 0..1792 { + uc[i] = array[i]; + } + + for i in 0..384 { + uc[i + 1792] = cc[i]; + } +} + +// calculate shared okey from uc and secret key ss +pub fn server_2(ss: &[u8], uc: &[u8], okey: &mut [u8]) { + let mut sh = SHA3::new(sha3::HASH256); + + let mut s: [i32; DEGREE] = [0; DEGREE]; + let mut k: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + + let mut array: [u8; 1792] = [0; 1792]; + let mut key: [u8; 32] = [0; 32]; + let mut cc: [u8; 384] = [0; 384]; + + for i in 0..1792 { + array[i] = uc[i]; + } + + nhs_unpack(&array, &mut k); + nres_it(&mut k); + + for i in 0..384 { + cc[i] = uc[i + 1792]; + } + + decompress(&cc, &mut c); + + for i in 0..1792 { + array[i] = ss[i]; + } + + nhs_unpack(&array, &mut s); + + poly_mul(&mut k, &s); + intt(&mut k); + poly_rsub(&mut k, &c); + poly_soft_reduce(&mut k); + + decode(&k, &mut key); + + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + for i in 0..32 { + okey[i] = key[i]; + } +} + +/* +fn main() { + let x=3; + let y=redc(x as u64); + let z=redc((y as u64)*(R2MODP)); + println!("{:02x}",z); + + let mut a:[i32;1024]=[0;1024]; + for i in 0..1024 {a[i]=i as i32} + + ntt(&mut a); + + for i in 0..1024 {a[i]=modmul(a[i],ONE)} + + intt(&mut a); + + println!("{:02x}",a[7]); + +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/rand.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/rand.rs new file mode 100644 index 000000000000..73ea088cfbc6 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/rand.rs @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//extern crate mcore; + +use crate::hash256::HASH256; + +pub const RAND_NK: usize = 21; +const RAND_NJ: usize = 6; +const RAND_NV: usize = 8; + +// Marsaglia-Zaman random generator (https://projecteuclid.org/euclid.aoap/1177005878) +// Analysis: https://ieeexplore.ieee.org/document/669305 +#[allow(non_camel_case_types)] +pub struct RAND { + pub ira: [u32; RAND_NK], /* random number... */ + pub rndptr: usize, + pub borrow: u32, + pub pool_ptr: usize, + pub pool: [u8; 32], +} + +impl RAND { + pub fn new() -> RAND { + RAND { + ira: [0; RAND_NK], + rndptr: 0, + borrow: 0, + pool_ptr: 0, + pool: [0; 32], + } + } + + #[allow(dead_code)] + pub fn clean(&mut self) { + self.pool_ptr = 0; + self.rndptr = 0; + for i in 0..32 { + self.pool[i] = 0 + } + for i in 0..RAND_NK { + self.ira[i] = 0 + } + self.borrow = 0; + } + + fn sbrand(&mut self) -> u32 { + /* Marsaglia & Zaman random number generator */ + self.rndptr += 1; + if self.rndptr < RAND_NK { + return self.ira[self.rndptr]; + } + self.rndptr = 0; + let mut k = RAND_NK - RAND_NJ; + for i in 0..RAND_NK { + /* calculate next NK values */ + if k == RAND_NK { + k = 0 + } + let t = self.ira[k]; + let pdiff = t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow); + if pdiff < t { + self.borrow = 0 + } + if pdiff > t { + self.borrow = 1 + } + self.ira[i] = pdiff; + k += 1; + } + self.ira[0] + } + + fn sirand(&mut self, seed: u32) { + let mut m: u32 = 1; + let mut sd = seed; + self.borrow = 0; + self.rndptr = 0; + self.ira[0] ^= sd; + for i in 1..RAND_NK { + /* fill initialisation vector */ + let inn = (RAND_NV * i) % RAND_NK; + self.ira[inn] ^= m; /* note XOR */ + let t = m; + m = sd.wrapping_sub(m); + sd = t; + } + for _ in 0..10000 { + self.sbrand(); + } /* "warm-up" & stir the generator */ + } + + fn fill_pool(&mut self) { + let mut sh = HASH256::new(); + for _ in 0..128 { + sh.process((self.sbrand() & 0xff) as u8) + } + let w = sh.hash(); + for i in 0..32 { + self.pool[i] = w[i] + } + self.pool_ptr = 0; + } + + fn pack(b: [u8; 4]) -> u32 { + /* pack 4 bytes into a 32-bit Word */ + (((b[3] as u32) & 0xff) << 24) + | (((b[2] as u32) & 0xff) << 16) + | (((b[1] as u32) & 0xff) << 8) + | ((b[0] as u32) & 0xff) + } + + pub fn seed(&mut self, rawlen: usize, raw: &[u8]) { + /* initialise from at least 128 byte string of raw random entropy */ + let mut b: [u8; 4] = [0; 4]; + let mut sh = HASH256::new(); + self.pool_ptr = 0; + + for i in 0..RAND_NK { + self.ira[i] = 0 + } + if rawlen > 0 { + for i in 0..rawlen { + sh.process(raw[i]); + } + let digest = sh.hash(); + + /* initialise PRNG from distilled randomness */ + + for i in 0..8 { + b[0] = digest[4 * i]; + b[1] = digest[4 * i + 1]; + b[2] = digest[4 * i + 2]; + b[3] = digest[4 * i + 3]; + self.sirand(RAND::pack(b)); + } + } + self.fill_pool(); + } + + pub fn getbyte(&mut self) -> u8 { + let r = self.pool[self.pool_ptr]; + self.pool_ptr += 1; + if self.pool_ptr >= 32 { + self.fill_pool() + } + r + } +} + +/* test main program + +fn main() { + let mut raw : [u8;100]=[0;100]; + let mut rng=RAND::new(); + + rng.clean(); + for i in 0..100 {raw[i]=i as u8} + + rng.seed(100,&raw); + + for _ in 0..1000 { + print!("{:03} ",rng.getbyte()); + } +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/sha3.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/sha3.rs new file mode 100644 index 000000000000..d3bd6d6cc98b --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/sha3.rs @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub const HASH224: usize = 28; +pub const HASH256: usize = 32; +pub const HASH384: usize = 48; +pub const HASH512: usize = 64; +pub const SHAKE128: usize = 16; +pub const SHAKE256: usize = 32; + +const ROUNDS: usize = 24; + +const RC: [u64; 24] = [ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +]; + +pub struct SHA3 { + length: usize, + rate: usize, + len: usize, + //s: [[u64; 5]; 5], + s: [u64; 25], +} + +impl SHA3 { + fn rotl(x: u64, n: u64) -> u64 { + ((x) << n) | ((x) >> (64 - n)) + } + + fn transform(&mut self) { + for k in 0..ROUNDS { + let c0 = self.s[0] ^ self.s[5] ^ self.s[10] ^ self.s[15] ^ self.s[20]; + let c1 = self.s[1] ^ self.s[6] ^ self.s[11] ^ self.s[16] ^ self.s[21]; + let c2 = self.s[2] ^ self.s[7] ^ self.s[12] ^ self.s[17] ^ self.s[22]; + let c3 = self.s[3] ^ self.s[8] ^ self.s[13] ^ self.s[18] ^ self.s[23]; + let c4 = self.s[4] ^ self.s[9] ^ self.s[14] ^ self.s[19] ^ self.s[24]; + + let d0 = c4 ^ SHA3::rotl(c1, 1); + let d1 = c0 ^ SHA3::rotl(c2, 1); + let d2 = c1 ^ SHA3::rotl(c3, 1); + let d3 = c2 ^ SHA3::rotl(c4, 1); + let d4 = c3 ^ SHA3::rotl(c0, 1); + + let b00 = self.s[0] ^ d0; + let b02 = SHA3::rotl(self.s[1] ^ d1, 1); + let b04 = SHA3::rotl(self.s[2] ^ d2, 62); + let b01 = SHA3::rotl(self.s[3] ^ d3, 28); + let b03 = SHA3::rotl(self.s[4] ^ d4, 27); + + let b13 = SHA3::rotl(self.s[5] ^ d0, 36); + let b10 = SHA3::rotl(self.s[6] ^ d1, 44); + let b12 = SHA3::rotl(self.s[7] ^ d2, 6); + let b14 = SHA3::rotl(self.s[8] ^ d3, 55); + let b11 = SHA3::rotl(self.s[9] ^ d4, 20); + + let b21 = SHA3::rotl(self.s[10] ^ d0, 3); + let b23 = SHA3::rotl(self.s[11] ^ d1, 10); + let b20 = SHA3::rotl(self.s[12] ^ d2, 43); + let b22 = SHA3::rotl(self.s[13] ^ d3, 25); + let b24 = SHA3::rotl(self.s[14] ^ d4, 39); + + let b34 = SHA3::rotl(self.s[15] ^ d0, 41); + let b31 = SHA3::rotl(self.s[16] ^ d1, 45); + let b33 = SHA3::rotl(self.s[17] ^ d2, 15); + let b30 = SHA3::rotl(self.s[18] ^ d3, 21); + let b32 = SHA3::rotl(self.s[19] ^ d4, 8); + + let b42 = SHA3::rotl(self.s[20] ^ d0, 18); + let b44 = SHA3::rotl(self.s[21] ^ d1, 2); + let b41 = SHA3::rotl(self.s[22] ^ d2, 61); + let b43 = SHA3::rotl(self.s[23] ^ d3, 56); + let b40 = SHA3::rotl(self.s[24] ^ d4, 14); + + self.s[0] = b00 ^ (!b10 & b20); + self.s[1] = b10 ^ (!b20 & b30); + self.s[2] = b20 ^ (!b30 & b40); + self.s[3] = b30 ^ (!b40 & b00); + self.s[4] = b40 ^ (!b00 & b10); + + self.s[5] = b01 ^ (!b11 & b21); + self.s[6] = b11 ^ (!b21 & b31); + self.s[7] = b21 ^ (!b31 & b41); + self.s[8] = b31 ^ (!b41 & b01); + self.s[9] = b41 ^ (!b01 & b11); + + self.s[10] = b02 ^ (!b12 & b22); + self.s[11] = b12 ^ (!b22 & b32); + self.s[12] = b22 ^ (!b32 & b42); + self.s[13] = b32 ^ (!b42 & b02); + self.s[14] = b42 ^ (!b02 & b12); + + self.s[15] = b03 ^ (!b13 & b23); + self.s[16] = b13 ^ (!b23 & b33); + self.s[17] = b23 ^ (!b33 & b43); + self.s[18] = b33 ^ (!b43 & b03); + self.s[19] = b43 ^ (!b03 & b13); + + self.s[20] = b04 ^ (!b14 & b24); + self.s[21] = b14 ^ (!b24 & b34); + self.s[22] = b24 ^ (!b34 & b44); + self.s[23] = b34 ^ (!b44 & b04); + self.s[24] = b44 ^ (!b04 & b14); + + self.s[0] ^= RC[k]; + } + } + + /* Initialise Hash function */ + pub fn init(&mut self, olen: usize) { + /* initialise */ + for i in 0..25 { + self.s[i] = 0; + } + self.length = 0; + self.len = olen; + self.rate = 200 - 2 * olen; + } + + pub fn new(olen: usize) -> SHA3 { + let mut nh = SHA3 { + length: 0, + rate: 0, + len: 0, + s: [0; 25], + }; + nh.init(olen); + nh + } + + pub fn new_copy(hh: &SHA3) -> SHA3 { + let mut nh = SHA3 { + length: 0, + rate: 0, + len: 0, + s: [0; 25], + }; + nh.length = hh.length; + nh.len = hh.len; + nh.rate = hh.rate; + for i in 0..25 { + nh.s[i] = hh.s[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = self.length as usize; + let b = cnt % 8; + let ind = cnt / 8; + self.s[ind] ^= (byt as u64) << (8 * b); + self.length += 1; + if self.length == self.rate { + self.length = 0; + self.transform(); + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + pub fn squeeze(&mut self, buff: &mut [u8], olen: usize) { + let mut m = 0; + let nb = olen / self.rate; + + for _ in 0..nb { + for i in 0..self.rate / 8 { + let mut el = self.s[i]; + for _ in 0..8 { + buff[m] = (el & 0xff) as u8; + m += 1; + el >>= 8; + } + } + self.transform(); + } + + let mut i = 0; + while m < olen { + let mut el = self.s[i]; + i += 1; + for _ in 0..8 { + buff[m] = (el & 0xff) as u8; + m += 1; + if m >= olen { + break; + } + el >>= 8; + } + } + + /* + loop { + for i in 0..25 { + let mut el = self.s[i]; + for _ in 0..8 { + buff[m] = (el & 0xff) as u8; + m += 1; + if m >= olen || (m % self.rate) == 0 { + done = true; + break; + } + el >>= 8; + } + if done { + break; + } + } + if m >= olen { + break; + } + done = false; + self.transform(); + } */ + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self, digest: &mut [u8]) { + /* pad message and finish - supply digest */ + let q = self.rate - self.length; + if q == 1 { + self.process(0x86); + } else { + self.process(0x06); + while self.length != self.rate - 1 { + self.process(0x00) + } + self.process(0x80); + } + let hlen = self.len as usize; + self.squeeze(digest, hlen); + } + + pub fn continuing_hash(&mut self, digest: &mut [u8]) { + let mut sh = SHA3::new_copy(self); + sh.hash(digest) + } + + pub fn shake(&mut self, digest: &mut [u8], olen: usize) { + let q = self.rate - self.length; + if q == 1 { + self.process(0x9f); + } else { + self.process(0x1f); + while self.length != self.rate - 1 { + self.process(0x00) + } + self.process(0x80); + } + self.squeeze(digest, olen); + } + + pub fn continuing_shake(&mut self, digest: &mut [u8], olen: usize) { + let mut sh = SHA3::new_copy(self); + sh.shake(digest, olen); + } +} + +//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 +//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 +//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let mut digest: [u8;100]=[0;100]; + let test = s.into_bytes(); + + let mut sh=SHA3::new(HASH256); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.hash(&mut digest); + for i in 0..32 {print!("{:02x}",digest[i])} + println!(""); + + sh=SHA3::new(HASH512); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.hash(&mut digest); + for i in 0..64 {print!("{:02x}",digest[i])} + println!(""); + + sh=SHA3::new(SHAKE256); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.shake(&mut digest,72); + for i in 0..72 {print!("{:02x}",digest[i])} + println!(""); + +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/share.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/share.rs new file mode 100644 index 000000000000..a48f91b17316 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/share.rs @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Shamir threshold secret sharing module */ +/* Split any byte array into number of shares < 256 */ +/* Specify number of shares required for recovery - nsr */ + +/* See TestMPIN.rs for an example of use */ + +use crate::rand::RAND; + +const PTAB: [u8; 256] = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, + 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, + 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, + 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, + 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, + 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, + 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, + 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, + 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, + 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +]; + +const LTAB: [u8; 256] = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, + 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, + 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, + 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, + 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, + 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, + 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, + 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, + 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, + 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, + 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, + 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, + 24, 13, 99, 140, 128, 192, 247, 112, 7, +]; + +pub struct SHARE<'a> { + id: u8, + nsr: u8, + b: &'a [u8], +} + +fn mul(x: u8, y: u8) -> u8 { + /* x.y= AntiLog(Log(x) + Log(y)) */ + let ix = (x as usize) & 0xff; + let iy = (y as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + let ly = (LTAB[iy] as usize) & 0xff; + + if x != 0 && y != 0 { + PTAB[(lx + ly) % 255] + } else { + 0 + } +} + +fn add(x: u8, y: u8) -> u8 { + x ^ y +} + +fn inv(x: u8) -> u8 { + let ix = (x as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + PTAB[255 - lx] +} + +/* Lagrange interpolation */ +fn interpolate(n: usize, x: &[u8], y: &[u8]) -> u8 { + let mut yp = 0 as u8; + for i in 0..n { + let mut p = 1 as u8; + for j in 0..n { + if i != j { + p = mul(p, mul(x[j], inv(add(x[i], x[j])))); + } + } + yp = add(yp, mul(p, y[i])); + } + yp +} + +impl<'a> SHARE<'a> { + /* Return a share of M */ + /* input id - Unique share ID */ + /* input nsr - Number of shares required for recovery */ + /* input Message M to be shared */ + /* input Random number generator rng to be used */ + /* return share structure */ + // must bind lifetime of the byte array stored by structure, to lifetime of s + pub fn new( + ident: usize, + numshare: usize, + s: &'a mut [u8], + m: &[u8], + rng: &mut RAND, + ) -> SHARE<'a> { + if ident < 1 || ident >= 256 || numshare < 2 || numshare >= 256 { + return SHARE { + id: 0, + nsr: 0, + b: s, + }; + } + let len = m.len(); + for j in 0..len { + let mut x = ident as u8; + s[j] = m[j]; + for _ in 1..numshare { + s[j] = add(s[j], mul(rng.getbyte(), x)); + x = mul(x, ident as u8); + } + } + SHARE { + id: ident as u8, + nsr: numshare as u8, + b: s, + } + } + /* recover M from shares */ + pub fn recover(m: &mut [u8], s: &[SHARE]) { + let len = s[0].b.len(); + let nsr = s[0].nsr as usize; + if nsr != s.len() { + return; + } + for i in 1..nsr { + if s[i].nsr as usize != nsr || s[i].b.len() != len { + return; + } + } + let mut x: [u8; 256] = [0; 256]; + let mut y: [u8; 256] = [0; 256]; + + for j in 0..len { + for i in 0..nsr { + x[i] = s[i].id; + y[i] = s[i].b[j]; + } + m[j] = interpolate(nsr, &x, &y); + } + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/x509.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/x509.rs new file mode 100644 index 000000000000..0602946c6ef7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.3/src/x509.rs @@ -0,0 +1,1311 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE X.509 Functions */ + +pub struct PKTYPE { + pub kind: usize, + pub hash: usize, + pub curve: usize, + pub len: usize, +} + +pub struct FDTYPE { + pub index: usize, + pub length: usize, +} + +// Supported Encryption/Signature Methods + +pub const ECC: usize = 1; +pub const RSA: usize = 2; +pub const ECD: usize = 3; // for Ed25519 and Ed448 +pub const PQ: usize = 4; + +// Supported Hash functions + +pub const H256: usize = 2; +pub const H384: usize = 3; +pub const H512: usize = 4; +pub const SHAKE256: usize = 5; + +// Supported Curves + +pub const USE_NIST256: usize = 4; +/**< For the NIST 256-bit standard curve - WEIERSTRASS only */ +pub const USE_ED25519: usize = 1; +/**< Bernstein's Modulus 2^255-19 - EDWARDS only */ +pub const USE_ED448: usize = 5; +//const USE_BRAINPOOL:usize = 2; /**< For Brainpool 256-bit curve - WEIERSTRASS only */ +//const USE_ANSSI:usize = 3; /**< For French 256-bit standard curve - WEIERSTRASS only */ +pub const USE_NIST384: usize = 10; +/**< For the NIST 384-bit standard curve - WEIERSTRASS only */ +pub const USE_NIST521: usize = 12; +/**< For the NIST 521-bit standard curve - WEIERSTRASS only */ + +const ANY: u8 = 0x00; +const SEQ: u8 = 0x30; +const OID: u8 = 0x006; +const INT: u8 = 0x02; +const NUL: u8 = 0x05; +//const ZER: u8 = 0x00; +//const UTF: u8 = 0x0C; +const UTC: u8 = 0x17; +const GTM: u8 = 0x18; +//const LOG: u8 = 0x01; +const BIT: u8 = 0x03; +const OCT: u8 = 0x04; +//const STR: u8 = 0x13; +const SET: u8 = 0x31; +//const IA5: u8 = 0x16; +const EXT: u8 = 0xA3; +const DNS: u8 = 0x82; + +// Define some OIDs +// Elliptic Curve with SHA256 + +const ECCSHA256: [u8; 8] = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02]; +const ECCSHA384: [u8; 8] = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03]; +const ECCSHA512: [u8; 8] = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04]; +const ECPK: [u8; 7] = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01]; +const EDPK25519: [u8; 3] = [0x2b, 0x65, 0x70]; +const EDPK448: [u8; 3] = [0x2b, 0x65, 0x71]; +const PRIME25519: [u8; 9] = [0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01]; +const PRIME256V1: [u8; 8] = [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]; +const SECP384R1: [u8; 5] = [0x2B, 0x81, 0x04, 0x00, 0x22]; +const SECP521R1: [u8; 5] = [0x2B, 0x81, 0x04, 0x00, 0x23]; +const RSAPK: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]; +const RSASHA256: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b]; +const RSASHA384: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0]; +const RSASHA512: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d]; +const DILITHIUM3: [u8; 11] = [ + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, 0x06, 0x05, +]; +// Cert details + +pub const CN: [u8; 3] = [0x55, 0x04, 0x06]; // countryName +pub const SN: [u8; 3] = [0x55, 0x04, 0x08]; // stateName +pub const LN: [u8; 3] = [0x55, 0x04, 0x07]; // localName +pub const ON: [u8; 3] = [0x55, 0x04, 0x0A]; // orgName +pub const UN: [u8; 3] = [0x55, 0x04, 0x0B]; // unitName +pub const MN: [u8; 3] = [0x55, 0x04, 0x03]; // myName +pub const EN: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01]; // emailName + +// Extensions +pub const AN: [u8; 3] = [0x55, 0x1D, 0x11]; // altName +pub const KU: [u8; 3] = [0x55, 0x1D, 0x0F]; // keyUsage +pub const BC: [u8; 3] = [0x55, 0x1D, 0x13]; // basicConstraints + +fn getalen(tag: u8, b: &[u8], j: usize) -> usize { + let mut k = j; + let mut len: usize; + if tag != 0 && b[k] != tag { + return 0; + } + k += 1; + if b[k] == 0x81 { + k += 1; + len = b[k] as usize; + } else if b[k] == 0x82 { + k += 1; + len = 256 * (b[k] as usize); + k += 1; + len += b[k] as usize; + } else { + len = b[k] as usize; + if len > 127 { + return 0; + } + } + len +} + +fn skip(len: usize) -> usize { + if len < 128 { + return 2; + } + if len < 256 { + return 3; + } + 4 +} + +fn bround(len: usize) -> usize { + if len % 8 == 0 { + return len; + } + len + (8 - len % 8) +} + +impl PKTYPE { + pub fn new() -> PKTYPE { + PKTYPE { + kind: 0, + hash: 0, + curve: 0, + len: 0, + } + } +} + +impl FDTYPE { + pub fn new() -> FDTYPE { + FDTYPE { + index: 0, + length: 0, + } + } +} + +// Input private key in PKCS#8 format +// e.g. openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 +// e.g. openssl req -x509 -nodes -days 3650 -newkey ec:<(openssl ecparam -name prime256v1) -keyout key.pem -out ecdsacert.pem +// extract private key from uncompressed key.pem into octet +// For RSA octet = p|q|dp|dq|c where pk->len is multiple of 5 +// For ECC octet = k +pub fn extract_private_key(c: &[u8], pk: &mut [u8]) -> PKTYPE { + let mut soid: [u8; 12] = [0; 12]; + let mut ret = PKTYPE::new(); + let mut j = 0 as usize; + let pklen = pk.len(); + + let mut len = getalen(SEQ, c, j); // Check for expected SEQ clause, and get length + if len == 0 { + // if not a SEQ clause, there is a problem, exit + return ret; + } + j += skip(len); // skip over length to clause contents. + if len + j != c.len() { + return ret; + } + len = getalen(INT, c, j); + if len == 0 { + // if not a SEQ clause, there is a problem, exit + return ret; + } + j += skip(len) + len; + len = getalen(SEQ, c, j); + if len == 0 { + // if not a SEQ clause, there is a problem, exit + return ret; + } + j += skip(len); + // extract OID + len = getalen(OID, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + let mut fin = j + len; + if len > soid.len() { + return ret; + } + let mut slen = 0; + while j < fin { + soid[slen] = c[j]; + slen += 1; + j += 1; + } + j = fin; + if EDPK25519 == soid[0..slen] { + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + let rlen = 32; + if rlen > pklen { + return ret; + } + ret.len = rlen; + for i in 0..rlen - len { + pk[i] = 0; + } + for i in rlen - len..rlen { + pk[i] = c[j]; + j += 1; + } + ret.kind = ECD; + ret.curve = USE_ED25519; + } + if EDPK448 == soid[0..slen] { + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + let rlen = 57; + if rlen > pklen { + return ret; + } + ret.len = rlen; + for i in 0..rlen - len { + pk[i] = 0; + } + for i in rlen - len..rlen { + pk[i] = c[j]; + j += 1; + } + ret.kind = ECD; + ret.curve = USE_ED448; + } + if DILITHIUM3 == soid[0..slen] { + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + let mut tlen = len; + if tlen > pk.len() { + tlen = pk.len(); + } + + for i in 0..tlen { + pk[i] = c[j]; + j += 1; + } + ret.len = tlen; + ret.kind = PQ; + ret.curve = 8 * tlen; + } + if ECPK == soid[0..slen] { + len = getalen(OID, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + fin = j + len; + if len > soid.len() { + return ret; + } + slen = 0; + while j < fin { + soid[slen] = c[j]; + slen += 1; + j += 1; + } + j = fin; + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over version + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + ret.kind = ECC; + let mut rlen = 0; + if PRIME256V1 == soid[0..slen] { + ret.curve = USE_NIST256; + rlen = 32; + } + if SECP384R1 == soid[0..slen] { + ret.curve = USE_NIST384; + rlen = 48; + } + if SECP521R1 == soid[0..slen] { + ret.curve = USE_NIST521; + rlen = 66; + } + if rlen > pklen { + ret.curve = 0; + ret.len = 0; + return ret; + } + ret.len = rlen; + for i in 0..rlen - len { + pk[i] = 0; + } + for i in rlen - len..rlen { + pk[i] = c[j]; + j += 1; + } + } + if RSAPK == soid[0..slen] { + len = getalen(NUL, c, j); + if len != 0 { + return ret; + } + j += skip(len); + + len = getalen(OCT, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over version + + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over n + + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over e + + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over d + + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len); // get p + + if c[j] == 0 { + j += 1; + len -= 1; + } + let mut rlen = bround(len); + + if 5 * rlen > pklen { + return ret; + } + + for i in 0..rlen - len { + pk[i] = 0; + } + for i in rlen - len..rlen { + pk[i] = c[j]; + j += 1; + } + + let flen = rlen; // should be same length for all + for k in 1..5 { + len = getalen(INT, c, j); + if len == 0 { + return ret; + } + j += skip(len); // get q,dp,dq,c + if c[j] == 0 { + j += 1; + len -= 1; + } + rlen = bround(len); + if rlen != flen { + return ret; + } + for i in 0..rlen - len { + pk[i] = 0; + } + for i in rlen - len..rlen { + pk[k * flen + i] = c[j]; + j += 1; + } + } + ret.len = 5 * flen; + ret.kind = RSA; + ret.curve = 16 * flen; + } + ret +} + +// Input signed cert as octet, and extract signature +// Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature +// Note that signature type is not provided here - its the type of the public key that +// is used to verify it that matters, and which determines for example the curve to be used! +pub fn extract_cert_sig(sc: &[u8], sig: &mut [u8]) -> PKTYPE { + let mut soid: [u8; 12] = [0; 12]; + let mut ret = PKTYPE::new(); + let mut j = 0 as usize; + let mut len = getalen(SEQ, sc, j); // Check for expected SEQ clause, and get length + let siglen = sig.len(); + + if len == 0 { + // if not a SEQ clause, there is a problem, exit + return ret; + } + j += skip(len); // skip over length to clause contents. Add len to skip clause + if len + j != sc.len() { + return ret; + } + len = getalen(SEQ, sc, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over cert to signature OID + len = getalen(SEQ, sc, j); + if len == 0 { + return ret; + } + j += skip(len); + let sj = j + len; // Needed to jump over signature OID + + // dive in to extract OID + len = getalen(OID, sc, j); + if len == 0 { + return ret; + } + j += skip(len); + let mut fin = j + len; + if len > soid.len() { + return ret; + } + + let mut slen = 0; + while j < fin { + soid[slen] = sc[j]; + slen += 1; + j += 1; + } + if EDPK25519 == soid[0..slen] { + ret.kind = ECD; + ret.hash = H512; + } + if EDPK448 == soid[0..slen] { + ret.kind = ECD; + ret.hash = SHAKE256; + } + if ECCSHA256 == soid[0..slen] { + ret.kind = ECC; + ret.hash = H256; + } + if ECCSHA384 == soid[0..slen] { + ret.kind = ECC; + ret.hash = H384; + } + if ECCSHA512 == soid[0..slen] { + ret.kind = ECC; + ret.hash = H512; + } + if RSASHA256 == soid[0..slen] { + ret.kind = RSA; + ret.hash = H256; + } + if RSASHA384 == soid[0..slen] { + ret.kind = RSA; + ret.hash = H384; + } + if RSASHA512 == soid[0..slen] { + ret.kind = RSA; + ret.hash = H512; + } + if DILITHIUM3 == soid[0..slen] { + ret.kind = PQ; + ret.hash = 0; // hash type is implicit + } + if ret.kind == 0 { + return ret; // unsupported type + } + + j = sj; + len = getalen(BIT, sc, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + j += 1; + len -= 1; // skip bit shift (hopefully 0!) + + if ret.kind == ECD { + if len > siglen { + ret.kind = 0; + return ret; + } + ret.len = len; + slen = 0; + fin = j + len; + while j < fin { + sig[slen] = sc[j]; + j += 1; + slen += 1; + } + if ret.hash == H512 { + ret.curve = USE_ED25519; + } + if ret.hash == SHAKE256 { + ret.curve = USE_ED448; + } + } + + if ret.kind == ECC { + len = getalen(SEQ, sc, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + + // pick up r part of signature + len = getalen(INT, sc, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + if sc[j] == 0 { + // skip leading zero + j += 1; + len -= 1; + } + let mut rlen = bround(len); + let mut ex = rlen - len; + + if 2 * rlen > siglen { + ret.kind = 0; + return ret; + } + ret.len = 2 * rlen; + + slen = 0; + for _ in 0..ex { + sig[slen] = 0; + slen += 1; + } + fin = j + len; + while j < fin { + sig[slen] = sc[j]; + j += 1; + slen += 1; + } + // pick up s part of signature + len = getalen(INT, sc, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + if sc[j] == 0 { + // skip leading zero + j += 1; + len -= 1; + } + rlen = bround(len); + ex = rlen - len; + for _ in 0..ex { + sig[slen] = 0; + slen += 1; + } + fin = j + len; + while j < fin { + sig[slen] = sc[j]; + j += 1; + slen += 1; + } + if ret.hash == H256 { + ret.curve = USE_NIST256; + } + if ret.hash == H384 { + ret.curve = USE_NIST384; + } + if ret.hash == H512 { + ret.curve = USE_NIST521; + } + } + if ret.kind == RSA { + let rlen = bround(len); + let ex = rlen - len; + if rlen > siglen { + ret.kind = 0; + ret.curve = 0; + return ret; + } + ret.len = rlen; + slen = 0; + for _ in 0..ex { + sig[slen] = 0; + slen += 1; + } + fin = j + len; + while j < fin { + sig[slen] = sc[j]; + j += 1; + slen += 1; + } + ret.curve = 8 * rlen; + } + if ret.kind == PQ { + if len > siglen { + ret.kind = 0; + ret.curve = 0; + return ret; + } + ret.len = len; + slen = 0; + fin = j + len; + while j < fin { + sig[slen] = sc[j]; + j += 1; + slen += 1; + } + ret.curve = 8 * len; + } + ret +} + +// Extract pointer to cert inside signed cert, and return its length; +// let cert=&sc[ptr..ptr+len] +pub fn find_cert(sc: &[u8], ptr: &mut usize) -> usize { + let mut j: usize = 0; + + let mut len = getalen(SEQ, sc, j); + if len == 0 { + return 0; + } + j += skip(len); + + let k = j; + len = getalen(SEQ, sc, j); + if len == 0 { + return 0; + } + j += skip(len); + let fin = j + len; + *ptr = k; + fin - k +} + +// Extract certificate from signed cert +pub fn extract_cert(sc: &[u8], cert: &mut [u8]) -> usize { + let mut ptr = 0; + let n = find_cert(sc, &mut ptr); + let k = ptr; + let fin = n + k; + if fin - k > cert.len() { + return 0; + } + for i in k..fin { + cert[i - k] = sc[i]; + } + n +} + +// extract pointer to ASN.1 raw public Key inside certificate, and return its length; +// let public_key=&c[ptr..ptr+len] +pub fn find_public_key(c: &[u8], ptr: &mut usize) -> usize { + let mut j: usize = 0; + let mut len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len); + + if len + j != c.len() { + return 0; + } + + len = getalen(ANY, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; //jump over version clause + + len = getalen(INT, c, j); + if len > 0 { + j += skip(len) + len; // jump over serial number clause (if there is one) + } + + len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; // jump over signature algorithm + + len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; // skip issuer + + len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; // skip validity + + len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; // skip subject + + let k = j; + len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len); // + + let fin = j + len; + *ptr = k; + fin - k +} + +// get Public details from ASN.1 description +pub fn get_public_key(c: &[u8], key: &mut [u8]) -> PKTYPE { + let mut koid: [u8; 12] = [0; 12]; + let mut ret = PKTYPE::new(); + let mut j = 0; + let keylen = key.len(); + + let mut len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); // + + len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); // + + // ** Maybe dive in and check Public Key OIDs here? + // ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC + // rsapublicKey for RSA + + let sj = j + len; + + len = getalen(OID, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + let mut fin = j + len; + if len > koid.len() { + return ret; + } + let mut slen = 0; + while j < fin { + koid[slen] = c[j]; + slen += 1; + j += 1; + } + ret.kind = 0; + if ECPK == koid[0..slen] { + ret.kind = ECC; + } + if EDPK25519 == koid[0..slen] { + ret.kind = ECD; + ret.curve = USE_ED25519 + } + if EDPK448 == koid[0..slen] { + ret.kind = ECD; + ret.curve = USE_ED448 + } + if RSAPK == koid[0..slen] { + ret.kind = RSA; + } + if DILITHIUM3 == koid[0..slen] { + ret.kind = PQ; + } + + if ret.kind == 0 { + return ret; + } + if ret.kind == ECC { + len = getalen(OID, c, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + + fin = j + len; + if len > koid.len() { + ret.kind = 0; + return ret; + } + slen = 0; + while j < fin { + koid[slen] = c[j]; + slen += 1; + j += 1; + } + if PRIME25519 == koid[0..slen] { + ret.curve = USE_ED25519; + } + if PRIME256V1 == koid[0..slen] { + ret.curve = USE_NIST256; + } + if SECP384R1 == koid[0..slen] { + ret.curve = USE_NIST384; + } + if SECP521R1 == koid[0..slen] { + ret.curve = USE_NIST521; + } + } + j = sj; + + len = getalen(BIT, c, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + j += 1; + len -= 1; // skip bit shift (hopefully 0!) + + if ret.kind == ECC || ret.kind == ECD || ret.kind == PQ { + if len > keylen { + ret.kind = 0; + return ret; + } + ret.len = len; + fin = j + len; + slen = 0; + while j < fin { + key[slen] = c[j]; + slen += 1; + j += 1; + } + } + if ret.kind == PQ { + ret.curve = 8 * len; + } + if ret.kind == RSA { + // Key is (modulus,exponent) - assume exponent is 65537 + len = getalen(SEQ, c, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + + len = getalen(INT, c, j); + if len == 0 { + ret.kind = 0; + return ret; + } + j += skip(len); + if c[j] == 0 { + j += 1; + len -= 1; + } + if len > keylen { + ret.kind = 0; + return ret; + } + ret.len = len; + fin = j + len; + slen = 0; + while j < fin { + key[slen] = c[j]; + slen += 1; + j += 1; + } + ret.curve = 8 * len; + } + ret +} + +// Extract Public Key from inside Certificate +pub fn extract_public_key(c: &[u8], key: &mut [u8]) -> PKTYPE { + let mut ptr = 0; + let pklen = find_public_key(c, &mut ptr); // ptr is pointer into certificate, at start of ASN.1 raw public key + let cc = &c[ptr..ptr + pklen]; + get_public_key(&cc, key) +} + +pub fn find_issuer(c: &[u8]) -> FDTYPE { + let mut j: usize = 0; + let mut ret = FDTYPE::new(); + let mut len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); + + if len + j != c.len() { + return ret; + } + + len = getalen(ANY, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over version clause + + len = getalen(INT, c, j); + if len > 0 { + j += skip(len) + len; // jump over serial number clause (if there is one) + } + + len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // jump over signature algorithm + + len = getalen(SEQ, c, j); + ret.index = j; + ret.length = len + skip(len); + + ret +} + +pub fn find_validity(c: &[u8]) -> usize { + let pos = find_issuer(c); + let j = pos.index + pos.length; // skip issuer + + //let mut j=find_issuer(c); + //let len=getalen(SEQ,c,j); + //if len==0 { + // return 0; + //} + //j+=skip(len)+len; // skip issuer + j +} + +pub fn find_subject(c: &[u8]) -> FDTYPE { + let mut j = find_validity(c); + let mut ret = FDTYPE::new(); + let mut len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len) + len; // skip validity + + len = getalen(SEQ, c, j); + ret.index = j; + ret.length = len + skip(len); + + ret +} + +pub fn self_signed(c: &[u8]) -> bool { + let ksub = find_subject(c); + let kiss = find_issuer(c); + + if ksub.length != kiss.length { + return false; + } + + // let sublen=getalen(SEQ,c,ksub); + // let isslen=getalen(SEQ,c,kiss); + // if sublen != isslen { + // return false; + // } + // ksub+=skip(sublen); + // kiss+=skip(isslen); + let mut m: u8 = 0; + for i in 0..ksub.length { + m |= c[i + ksub.index] - c[i + kiss.index]; + } + if m != 0 { + return false; + } + true +} + +// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length +// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy +// cert information into it. + +// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field + +pub fn find_entity_property(c: &[u8], soid: &[u8], start: usize) -> FDTYPE { + let mut ret = FDTYPE::new(); + let mut foid: [u8; 32] = [0; 32]; + let mut j = start; + let tlen = getalen(SEQ, c, j); + if tlen == 0 { + return ret; + } + j += skip(tlen); + let k = j; + while j < k + tlen { + let mut len = getalen(SET, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); + len = getalen(OID, c, j); + if len == 0 { + return ret; + } + j += skip(len); + let fin = j + len; + if len > foid.len() { + return ret; + } + let mut flen: usize = 0; + while j < fin { + foid[flen] = c[j]; + flen += 1; + j += 1; + } + len = getalen(ANY, c, j); // get text, could be any type + if len == 0 { + return ret; + } + j += skip(len); + if foid[0..flen] == *soid { + ret.index = j; // if its the right one.. + ret.length = len; + return ret; + } + j += len; // skip over it + } + ret +} + +pub fn find_start_date(c: &[u8], start: usize) -> usize { + let mut j = start; + let mut len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len); + + len = getalen(UTC, c, j); + if len == 0 { + // could be generalised time + len = getalen(GTM, c, j); + if len == 0 { + return 0; + } + j += skip(len); + j += 2; // skip century + } else { + j += skip(len); + } + + j +} + +pub fn find_expiry_date(c: &[u8], start: usize) -> usize { + let mut j = start; + let mut len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len); + + len = getalen(UTC, c, j); + if len == 0 { + len = getalen(GTM, c, j); + if len == 0 { + return 0; + } + } + j += skip(len) + len; + + len = getalen(UTC, c, j); + if len == 0 { + // could be generalised time + len = getalen(GTM, c, j); + if len == 0 { + return 0; + } + j += skip(len); + j += 2; // skip century + } else { + j += skip(len); + } + + j +} + +pub fn find_extensions(c: &[u8]) -> usize { + let pos = find_subject(c); + let mut j = pos.index + pos.length; + + // let mut len=getalen(SEQ,c,j); + // if len==0 { + // return 0; + // } + // j+=skip(len)+len; // skip subject + + let len = getalen(SEQ, c, j); + if len == 0 { + return 0; + } + j += skip(len) + len; // skip public key + + if j >= c.len() { + return 0; + } + + j +} + +pub fn find_extension(c: &[u8], soid: &[u8], start: usize) -> FDTYPE { + let mut ret = FDTYPE::new(); + let mut foid: [u8; 32] = [0; 32]; + + let mut j = start; + let tlen = getalen(EXT, c, j); + if tlen == 0 { + return ret; + } + j += skip(tlen); + + let tlen = getalen(SEQ, c, j); + if tlen == 0 { + return ret; + } + j += skip(tlen); + + let k = j; + while j < k + tlen { + let mut len = getalen(SEQ, c, j); + if len == 0 { + return ret; + } + j += skip(len); + let nj = j + len; + len = getalen(OID, c, j); + j += skip(len); + let fin = j + len; + if len > foid.len() { + return ret; + } + let mut flen: usize = 0; + while j < fin { + foid[flen] = c[j]; + flen += 1; + j += 1; + } + if foid[0..flen] == *soid { + ret.index = j; // if its the right one.. + ret.length = nj - j; + return ret; + } + j = nj; // skip over this extension + } + + ret +} + +// return 1 if name found, else 0, where name is URL +// input cert, and pointer to SAN extension +// Takes wild-card into consideration + +pub fn find_alt_name(c: &[u8], start: usize, name: &[u8]) -> bool { + if start == 0 { + return false; + } + let mut j = start; + let mut tlen = getalen(OCT, c, j); + if tlen == 0 { + return false; + } + j += skip(tlen); + + tlen = getalen(SEQ, c, j); + if tlen == 0 { + return false; + } + j += skip(tlen); + let k = j; + while j < k + tlen { + let tag = c[j]; + let mut len = getalen(ANY, c, j); + if len == 0 { + return false; + } + j += skip(len); // ?? If its not dns, skip over it j+=len + if tag != DNS { + // only interested in URLs + j += len; + continue; + } + let mut cmp = true; + let mut m = 0; + let nlen = name.len(); + if c[j] == b'*' { + j += 1; + len -= 1; // skip over * + while m < nlen { + // advance to first . + if name[m] == b'.' { + break; + } + m += 1; + } + } + for _ in 0..len { + if m == nlen { + // name has ended before comparison completed + cmp = false; + j += 1; + continue; + } + if c[j] != name[m] { + cmp = false; + } + m += 1; + j += 1; + } + if m != nlen { + cmp = false; + } + if cmp { + return true; + } + } + + false +} From 64aec0573ccbd410e123c2b3cda168ff948ce2a2 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 3 Jul 2024 19:24:41 -0700 Subject: [PATCH 02/36] Accept opaque types in anonymous-credentials functions --- .../anonymous_credentials/rs/cxx/Cargo.toml | 2 +- .../anonymous_credentials/rs/cxx/src/lib.rs | 147 ++++++++++++------ .../anonymous_credentials/rs/lib/src/data.rs | 37 +++++ 3 files changed, 136 insertions(+), 50 deletions(-) diff --git a/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml index 2d8d350f2594..83a371436ccd 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MPL-2.0" [dependencies] -anonymous-credentials = "0.1" +anonymous-credentials = { version = "0.1", path = "../lib" } cxx = "1" [lib] diff --git a/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs index a474f63f0816..27ee45a287f0 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs @@ -4,11 +4,11 @@ * You can obtain one at https://mozilla.org/MPL/2.0/. */ use anonymous_credentials::{ - CredentialBIG, CredentialManager as InternalCredentialManager, GroupPublicKey, JoinResponse, - Result, UserCredentials, + CredentialBIG as InternalCredentialBIG, CredentialManager as InternalCredentialManager, + GroupPublicKey as InternalGroupPublicKey, JoinResponse as InternalJoinResponse, Result, + UserCredentials as InternalUserCredentials, }; -#[allow(unsafe_op_in_unsafe_fn)] #[cxx::bridge(namespace = "anonymous_credentials")] mod ffi { struct StartJoinResult { @@ -19,22 +19,95 @@ mod ffi { data: Vec, error_message: String, } - struct EmptyResult { + struct GroupPublicKeyResult { + value: Box, error_message: String, } + struct CredentialBIGResult { + value: Box, + error_message: String, + } + struct JoinResponseResult { + value: Box, + error_message: String, + } + struct UserCredentialsResult { + value: Box, + error_message: String, + } + extern "Rust" { type CredentialManager; + type GroupPublicKey; + type CredentialBIG; + type JoinResponse; + type UserCredentials; + + fn load_group_public_key(data: &[u8]) -> GroupPublicKeyResult; + fn load_credential_big(data: &[u8]) -> CredentialBIGResult; + fn load_join_response(data: &[u8]) -> JoinResponseResult; + fn load_user_credentials(data: &[u8]) -> UserCredentialsResult; + fn new_credential_manager() -> Box; fn new_credential_manager_with_fixed_seed() -> Box; - fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult; - fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result; - fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult; - fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result; + fn start_join(self: &mut CredentialManager, challenge: &[u8]) -> StartJoinResult; + fn finish_join( + self: &mut CredentialManager, + public_key: &GroupPublicKey, + gsk: &CredentialBIG, + join_resp: Box, + ) -> VecU8Result; + fn set_gsk_and_credentials( + self: &mut CredentialManager, + gsk: Box, + credentials: Box, + ); + fn sign(self: &mut CredentialManager, msg: &[u8], basename: &[u8]) -> VecU8Result; } } use ffi::*; +macro_rules! wrapper_with_loader { + ($internal_type:ident, $wrapped_type:ident, $result_type:ident, $loader_func_name:ident) => { + #[derive(Default)] + struct $wrapped_type($internal_type); + + fn $loader_func_name(data: &[u8]) -> $result_type { + match $internal_type::try_from(data) { + Ok(value) => $result_type { + value: Box::new($wrapped_type(value)), + error_message: String::new(), + }, + Err(e) => $result_type { + value: Box::new(Default::default()), + error_message: e.to_string(), + }, + } + } + }; +} + +wrapper_with_loader!( + InternalGroupPublicKey, + GroupPublicKey, + GroupPublicKeyResult, + load_group_public_key +); +wrapper_with_loader!( + InternalCredentialBIG, + CredentialBIG, + CredentialBIGResult, + load_credential_big +); +wrapper_with_loader!(InternalJoinResponse, JoinResponse, JoinResponseResult, load_join_response); +wrapper_with_loader!( + InternalUserCredentials, + UserCredentials, + UserCredentialsResult, + load_user_credentials +); + #[allow(dead_code)] struct CredentialManager(InternalCredentialManager); @@ -43,9 +116,7 @@ fn new_credential_manager() -> Box { } fn new_credential_manager_with_fixed_seed() -> Box { - Box::new(CredentialManager(InternalCredentialManager::new_with_seed( - &[0u8; 1], - ))) + Box::new(CredentialManager(InternalCredentialManager::new_with_seed(&[0u8; 1]))) } impl CredentialManager { @@ -58,60 +129,38 @@ impl CredentialManager { } /// Processes response and returns user credentials - fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result { + fn finish_join( + &mut self, + public_key: &GroupPublicKey, + gsk: &CredentialBIG, + join_resp: Box, + ) -> VecU8Result { || -> Result> { - let public_key = GroupPublicKey::try_from(public_key)?; - let gsk = CredentialBIG::try_from(gsk)?; - let join_resp = JoinResponse::try_from(join_resp)?; self.0 - .finish_join(&public_key, &gsk, join_resp) + .finish_join(&public_key.0, &gsk.0, join_resp.0) .map(|creds| creds.to_bytes().to_vec()) }() .into() } - fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult { - || -> Result<()> { - let gsk = CredentialBIG::try_from(gsk)?; - let credentials = UserCredentials::try_from(credentials)?; - self.0.set_gsk_and_credentials(gsk, credentials); - Ok(()) - }() - .into() + fn set_gsk_and_credentials( + &mut self, + gsk: Box, + credentials: Box, + ) { + self.0.set_gsk_and_credentials(gsk.0, credentials.0); } fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result { - self.0 - .sign(msg, basename) - .map(|sig| sig.to_bytes().to_vec()) - .into() + self.0.sign(msg, basename).map(|sig| sig.to_bytes().to_vec()).into() } } impl From>> for VecU8Result { fn from(value: Result>) -> Self { match value { - Ok(data) => VecU8Result { - data, - error_message: String::new(), - }, - Err(e) => VecU8Result { - data: Vec::new(), - error_message: e.to_string(), - }, - } - } -} - -impl From> for EmptyResult { - fn from(value: Result<()>) -> Self { - match value { - Ok(()) => EmptyResult { - error_message: String::new(), - }, - Err(e) => EmptyResult { - error_message: e.to_string(), - }, + Ok(data) => VecU8Result { data, error_message: String::new() }, + Err(e) => VecU8Result { data: Vec::new(), error_message: e.to_string() }, } } } diff --git a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs index 9581d02a78de..fd87748c6249 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs @@ -254,3 +254,40 @@ impl Signature { result } } + +impl Default for CredentialBIG { + fn default() -> Self { + Self(BIG::new()) + } +} + +impl Default for ECPProof { + fn default() -> Self { + Self { c: BIG::new(), s: BIG::new() } + } +} + +impl Default for JoinResponse { + fn default() -> Self { + Self { cred: UserCredentials::default(), proof: ECPProof::default() } + } +} + +impl Default for UserCredentials { + fn default() -> Self { + UserCredentials { a: ECP::new(), b: ECP::new(), c: ECP::new(), d: ECP::new() } + } +} + +impl Default for GroupPublicKey { + fn default() -> Self { + GroupPublicKey { + x: ECP2::new(), + y: ECP2::new(), + cx: BIG::new(), + sx: BIG::new(), + cy: BIG::new(), + sy: BIG::new(), + } + } +} From f13dbca79183c919a69953a4bd29451eee6960b3 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 24 Apr 2024 12:27:17 -0700 Subject: [PATCH 03/36] Add anonymous-credentials crate and cxx binding --- browser/sources.gni | 1 + .../web_discovery_project/browser/BUILD.gn | 10 + .../browser/anonymous_credentials/rs/BUILD.gn | 23 + .../anonymous_credentials/rs/Cargo.lock | 199 ++ .../anonymous_credentials/rs/Cargo.toml | 13 + .../anonymous_credentials/rs/src/lib.rs | 110 + .../rust/anonymous_credentials/v0_1/BUILD.gn | 44 + .../.cargo-checksum.json | 1 + .../.cargo_vcs_info.json | 6 + .../anonymous-credentials-0.1.2/.gitignore | 2 + .../anonymous-credentials-0.1.2/Cargo.toml | 42 + .../Cargo.toml.orig | 19 + .../anonymous-credentials-0.1.2/LICENSE | 373 ++++ .../anonymous-credentials-0.1.2/README.md | 11 + .../anonymous-credentials-0.1.2/src/data.rs | 243 +++ .../anonymous-credentials-0.1.2/src/join.rs | 180 ++ .../anonymous-credentials-0.1.2/src/lib.rs | 228 +++ .../anonymous-credentials-0.1.2/src/sign.rs | 68 + .../anonymous-credentials-0.1.2/src/util.rs | 85 + .../brave-miracl-0.1.2/.cargo-checksum.json | 1 + .../brave-miracl-0.1.2/.cargo_vcs_info.json | 6 + .../vendor/brave-miracl-0.1.2/.gitignore | 2 + .../vendor/brave-miracl-0.1.2/.gitmodules | 3 + .../vendor/brave-miracl-0.1.2/Cargo.toml | 34 + .../vendor/brave-miracl-0.1.2/Cargo.toml.orig | 18 + .../vendor/brave-miracl-0.1.2/LICENSE | 202 ++ .../vendor/brave-miracl-0.1.2/README.md | 15 + .../vendor/brave-miracl-0.1.2/src/aes.rs | 901 ++++++++ .../vendor/brave-miracl-0.1.2/src/arch.rs | 22 + .../brave-miracl-0.1.2/src/bn254/big.rs | 1062 ++++++++++ .../brave-miracl-0.1.2/src/bn254/bls.rs | 181 ++ .../brave-miracl-0.1.2/src/bn254/dbig.rs | 314 +++ .../brave-miracl-0.1.2/src/bn254/ecdh.rs | 432 ++++ .../brave-miracl-0.1.2/src/bn254/ecp.rs | 1824 +++++++++++++++++ .../brave-miracl-0.1.2/src/bn254/ecp2.rs | 999 +++++++++ .../brave-miracl-0.1.2/src/bn254/eddsa.rs | 455 ++++ .../vendor/brave-miracl-0.1.2/src/bn254/fp.rs | 825 ++++++++ .../brave-miracl-0.1.2/src/bn254/fp12.rs | 1111 ++++++++++ .../brave-miracl-0.1.2/src/bn254/fp2.rs | 516 +++++ .../brave-miracl-0.1.2/src/bn254/fp4.rs | 784 +++++++ .../brave-miracl-0.1.2/src/bn254/hpke.rs | 386 ++++ .../brave-miracl-0.1.2/src/bn254/mod.rs | 30 + .../brave-miracl-0.1.2/src/bn254/mpin.rs | 228 +++ .../brave-miracl-0.1.2/src/bn254/pair.rs | 1038 ++++++++++ .../brave-miracl-0.1.2/src/bn254/rom.rs | 192 ++ .../brave-miracl-0.1.2/src/dilithium.rs | 1199 +++++++++++ .../vendor/brave-miracl-0.1.2/src/gcm.rs | 508 +++++ .../vendor/brave-miracl-0.1.2/src/hash256.rs | 288 +++ .../vendor/brave-miracl-0.1.2/src/hash384.rs | 383 ++++ .../vendor/brave-miracl-0.1.2/src/hash512.rs | 383 ++++ .../vendor/brave-miracl-0.1.2/src/hmac.rs | 870 ++++++++ .../vendor/brave-miracl-0.1.2/src/kyber.rs | 719 +++++++ .../vendor/brave-miracl-0.1.2/src/lib.rs | 41 + .../vendor/brave-miracl-0.1.2/src/main.rs | 3 + .../vendor/brave-miracl-0.1.2/src/nhs.rs | 709 +++++++ .../vendor/brave-miracl-0.1.2/src/rand.rs | 183 ++ .../vendor/brave-miracl-0.1.2/src/sha3.rs | 344 ++++ .../vendor/brave-miracl-0.1.2/src/share.rs | 154 ++ .../vendor/brave-miracl-0.1.2/src/x509.rs | 1285 ++++++++++++ 59 files changed, 20308 insertions(+) create mode 100644 components/web_discovery_project/browser/BUILD.gn create mode 100644 components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn create mode 100644 components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock create mode 100644 components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml create mode 100644 components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs create mode 100644 third_party/rust/anonymous_credentials/v0_1/BUILD.gn create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/arch.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/big.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs create mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs diff --git a/browser/sources.gni b/browser/sources.gni index 06565def9695..885ce2b23587 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -204,6 +204,7 @@ brave_chrome_browser_deps = [ "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/version_info", + "//brave/components/web_discovery_project/browser", "//brave/components/webcompat:core", "//brave/services/network/public/cpp", "//brave/third_party/blink/renderer", diff --git a/components/web_discovery_project/browser/BUILD.gn b/components/web_discovery_project/browser/BUILD.gn new file mode 100644 index 000000000000..eb59e4c02ea3 --- /dev/null +++ b/components/web_discovery_project/browser/BUILD.gn @@ -0,0 +1,10 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +static_library("browser") { + deps = [ + "anonymous_credentials/rs:rust_lib" + ] +} diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn b/components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn new file mode 100644 index 000000000000..6c2f9e6f564b --- /dev/null +++ b/components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//build/rust/rust_static_library.gni") + +rust_static_library("rust_lib") { + crate_name = "anonymous_credentials_cxx" + crate_root = "src/lib.rs" + allow_unsafe = true + + edition = "2021" + sources = [ "src/lib.rs" ] + + visibility = [ + "//brave/components/web_discovery_project/browser:*", + ] + + cxx_bindings = [ "src/lib.rs" ] + + deps = [ "//brave/third_party/rust/anonymous_credentials/v0_1:lib" ] +} diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock b/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock new file mode 100644 index 000000000000..f3866ed78a68 --- /dev/null +++ b/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock @@ -0,0 +1,199 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anonymous-credentials" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f25d3a6796aee3f2a4c4bd1fe2473908faa815d54ca693bc8d7c063e7d77f23" +dependencies = [ + "brave-miracl", + "lazy_static", + "rand", + "thiserror", +] + +[[package]] +name = "anonymous-credentials-cxx" +version = "0.1.0" +dependencies = [ + "anonymous-credentials", + "cxx", +] + +[[package]] +name = "brave-miracl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22bc3fa88a8cf37713577f7123a18636092c7ef2b6651eee2409fb0f9569f3b3" + +[[package]] +name = "cc" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cxx" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21db378d04296a84d8b7d047c36bb3954f0b46529db725d7e62fb02f9ba53ccc" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8dcadd2e2fb4a501e1d9e93d6e88e6ea494306d8272069c92d5a9edf8855c0" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad08a837629ad949b73d032c637653d069e909cffe4ee7870b02301939ce39cc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml b/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml new file mode 100644 index 000000000000..c0cbc7f34835 --- /dev/null +++ b/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "anonymous-credentials-cxx" +version = "0.1.0" +edition = "2021" +license = "MPL-2.0" + +[dependencies] +anonymous-credentials = "0.1.2" +cxx = "1" + +[lib] +name = "anonymous_credentials_cxx" +crate-type = ["rlib"] diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs b/components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs new file mode 100644 index 000000000000..4f6bc14caad8 --- /dev/null +++ b/components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs @@ -0,0 +1,110 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use anonymous_credentials::{ + CredentialBIG, CredentialManager as InternalCredentialManager, GroupPublicKey, JoinResponse, + Result, UserCredentials, +}; + +#[allow(unsafe_op_in_unsafe_fn)] +#[cxx::bridge(namespace = "anonymous_credentials")] +mod ffi { + struct StartJoinResult { + gsk: Vec, + join_request: Vec, + } + struct VecU8Result { + data: Vec, + error_message: String, + } + struct EmptyResult { + error_message: String, + } + extern "Rust" { + type CredentialManager; + fn new_credential_manager() -> Box; + fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult; + fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result; + fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult; + fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result; + } +} + +use ffi::*; + +#[allow(dead_code)] +struct CredentialManager(InternalCredentialManager); + +fn new_credential_manager() -> Box { + Box::new(CredentialManager(InternalCredentialManager::new())) +} + +impl CredentialManager { + fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { + let result = self.0.start_join(challenge); + StartJoinResult { + gsk: result.gsk.to_bytes().to_vec(), + join_request: result.join_msg.to_bytes().to_vec(), + } + } + + /// Processes response and returns user credentials + fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result { + || -> Result> { + let public_key = GroupPublicKey::try_from(public_key)?; + let gsk = CredentialBIG::try_from(gsk)?; + let join_resp = JoinResponse::try_from(join_resp)?; + self.0 + .finish_join(&public_key, &gsk, join_resp) + .map(|creds| creds.to_bytes().to_vec()) + }() + .into() + } + + fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult { + || -> Result<()> { + let gsk = CredentialBIG::try_from(gsk)?; + let credentials = UserCredentials::try_from(credentials)?; + self.0.set_gsk_and_credentials(gsk, credentials); + Ok(()) + }() + .into() + } + + fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result { + self.0 + .sign(msg, basename) + .map(|sig| sig.to_bytes().to_vec()) + .into() + } +} + +impl From>> for VecU8Result { + fn from(value: Result>) -> Self { + match value { + Ok(data) => VecU8Result { + data, + error_message: String::new(), + }, + Err(e) => VecU8Result { + data: Vec::new(), + error_message: e.to_string(), + }, + } + } +} + +impl From> for EmptyResult { + fn from(value: Result<()>) -> Self { + match value { + Ok(()) => EmptyResult { + error_message: String::new(), + }, + Err(e) => EmptyResult { + error_message: e.to_string(), + }, + } + } +} diff --git a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn new file mode 100644 index 000000000000..54e91148a236 --- /dev/null +++ b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn @@ -0,0 +1,44 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by +# tools/crates/gnrt. +# Do not edit! + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "anonymous_credentials" + epoch = "0.1" + crate_type = "rlib" + crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs" + sources = [ + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs", + ] + inputs = [] + + build_native_rust_unit_tests = false + edition = "2021" + cargo_pkg_version = "0.1.2" + cargo_pkg_authors = "Darnell Andries " + cargo_pkg_name = "anonymous-credentials" + cargo_pkg_description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" + library_configs -= [ "//build/config/compiler:chromium_code" ] + library_configs += [ "//build/config/compiler:no_chromium_code" ] + executable_configs -= [ "//build/config/compiler:chromium_code" ] + executable_configs += [ "//build/config/compiler:no_chromium_code" ] + proc_macro_configs -= [ "//build/config/compiler:chromium_code" ] + proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] + deps = [ + "//brave/third_party/rust/brave_miracl/v0_1:lib", + "//brave/third_party/rust/lazy_static/v1:lib", + "//brave/third_party/rust/rand/v0_8:lib", + "//brave/third_party/rust/thiserror/v1:lib", + ] +} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json new file mode 100644 index 000000000000..697c9ce2fbb4 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{}} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json new file mode 100644 index 000000000000..90abaf468340 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "33e360909c77f1dd485db47668b410fc2b2532d5" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore new file mode 100644 index 000000000000..96ef6c0b944e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml new file mode 100644 index 000000000000..1d6385e3d791 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml @@ -0,0 +1,42 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "anonymous-credentials" +version = "0.1.2" +authors = ["Darnell Andries "] +description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" +readme = "README.md" +keywords = [ + "daa", + "credentials", + "bn254", +] +categories = ["cryptography"] +license = "MPL-2.0" +repository = "https://github.com/brave-experiments/anonymous-credentials-rs" + +[dependencies.brave-miracl] +version = "0.1" +features = ["std"] + +[dependencies.lazy_static] +version = "1.4" + +[dependencies.rand] +version = "0.8" + +[dependencies.thiserror] +version = "1.0" + +[dev-dependencies.hex] +version = "0.4" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig new file mode 100644 index 000000000000..a33afba07d5a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig @@ -0,0 +1,19 @@ +[package] +name = "anonymous-credentials" +version = "0.1.2" +edition = "2021" +authors = ["Darnell Andries "] +description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" +license = "MPL-2.0" +repository = "https://github.com/brave-experiments/anonymous-credentials-rs" +keywords = ["daa", "credentials", "bn254"] +categories = ["cryptography"] + +[dependencies] +lazy_static = "1.4" +rand = "0.8" +brave-miracl = { version = "0.1", features = ["std"] } +thiserror = "1.0" + +[dev-dependencies] +hex = "0.4" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE new file mode 100644 index 000000000000..d0a1fa1482ee --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md new file mode 100644 index 000000000000..da0fa655154f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md @@ -0,0 +1,11 @@ +# anonymous-credentials + +[![Crates.io](https://img.shields.io/crates/v/anonymous-credentials?style=for-the-badge)](https://crates.io/crates/anonymous-credentials) + +Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). + +bn254 is the only supported curve for this library. + +## License + +This project is licensed under the terms of the [Mozilla Public License 2.0](LICENSE). diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs new file mode 100644 index 000000000000..91fb515e1cff --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs @@ -0,0 +1,243 @@ +use brave_miracl::bn254::{ + big::{self, BIG}, + ecp::ECP, + ecp2::ECP2, + fp2::FP2, +}; + +use super::CredentialError; + +pub const BIG_SIZE: usize = big::MODBYTES; +pub const ECP_SIZE: usize = BIG_SIZE * 2 + 1; +pub const ECP2_COMPAT_SIZE: usize = BIG_SIZE * 4; + +pub const ECP_PROOF_SIZE: usize = BIG_SIZE * 2; +pub const JOIN_REQUEST_SIZE: usize = ECP_SIZE + ECP_PROOF_SIZE; +pub const USER_CREDENTIALS_SIZE: usize = ECP_SIZE * 4; +pub const JOIN_RESPONSE_SIZE: usize = USER_CREDENTIALS_SIZE + ECP_PROOF_SIZE; +pub const GROUP_PUBLIC_KEY_SIZE: usize = ECP2_COMPAT_SIZE * 2 + BIG_SIZE * 4; +pub const SIGNATURE_SIZE: usize = ECP_SIZE * 5 + ECP_PROOF_SIZE; + +pub struct JoinRequest { + pub(crate) q: ECP, // G1 ** gsk + + pub(crate) proof: ECPProof, +} + +pub struct JoinResponse { + pub(crate) cred: UserCredentials, + pub(crate) proof: ECPProof, +} + +pub struct UserCredentials { + pub(crate) a: ECP, + pub(crate) b: ECP, + pub(crate) c: ECP, + pub(crate) d: ECP, +} + +pub struct Signature { + pub(crate) a: ECP, + pub(crate) b: ECP, + pub(crate) c: ECP, + pub(crate) d: ECP, + pub(crate) nym: ECP, + + pub(crate) proof: ECPProof, +} + +pub struct GroupPublicKey { + pub(crate) x: ECP2, // G2 ** x + pub(crate) y: ECP2, // G2 ** y + + // ZK of discrete-log knowledge for X and Y + pub(crate) cx: BIG, + pub(crate) sx: BIG, + pub(crate) cy: BIG, + pub(crate) sy: BIG, +} + +pub struct ECPProof { + pub(crate) c: BIG, + pub(crate) s: BIG, +} + +pub struct CredentialBIG(pub(crate) BIG); + +pub struct StartJoinResult { + pub gsk: CredentialBIG, + pub join_msg: JoinRequest, +} + +pub(crate) fn ecp_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != ECP_SIZE { + return Err(CredentialError::BadECP); + } + Ok(ECP::frombytes(bytes)) +} + +pub(crate) fn ecp2_from_compat_bytes(bytes: &[u8]) -> Result { + if bytes.len() != ECP2_COMPAT_SIZE { + return Err(CredentialError::BadECP2); + } + let x = FP2::new_bigs( + &big_from_bytes(&bytes[..BIG_SIZE])?, + &big_from_bytes(&bytes[BIG_SIZE..BIG_SIZE * 2])?, + ); + let y = FP2::new_bigs( + &big_from_bytes(&bytes[BIG_SIZE * 2..BIG_SIZE * 3])?, + &big_from_bytes(&bytes[BIG_SIZE * 3..BIG_SIZE * 4])?, + ); + Ok(ECP2::new_fp2s(&x, &y)) +} + +pub(crate) fn ecp2_to_compat_bytes(point: &ECP2) -> [u8; ECP2_COMPAT_SIZE] { + let mut result = [0u8; ECP2_COMPAT_SIZE]; + + let mut x = point.getx(); + let mut y = point.gety(); + + x.geta().tobytes(&mut result[..BIG_SIZE]); + x.getb().tobytes(&mut result[BIG_SIZE..BIG_SIZE * 2]); + y.geta().tobytes(&mut result[BIG_SIZE * 2..BIG_SIZE * 3]); + y.getb().tobytes(&mut result[BIG_SIZE * 3..]); + + result +} + +pub(crate) fn big_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != BIG_SIZE { + return Err(CredentialError::BadBIG); + } + Ok(BIG::frombytes(bytes)) +} + +impl TryFrom<&[u8]> for JoinResponse { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != JOIN_RESPONSE_SIZE { + return Err(CredentialError::BadJoinResponse); + } + + Ok(JoinResponse { + cred: bytes[..USER_CREDENTIALS_SIZE].try_into()?, + proof: bytes[USER_CREDENTIALS_SIZE..].try_into()?, + }) + } +} + +impl TryFrom<&[u8]> for UserCredentials { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != USER_CREDENTIALS_SIZE { + return Err(CredentialError::BadUserCredentials); + } + Ok(UserCredentials { + a: ecp_from_bytes(&bytes[..ECP_SIZE])?, + b: ecp_from_bytes(&bytes[ECP_SIZE..ECP_SIZE * 2])?, + c: ecp_from_bytes(&bytes[ECP_SIZE * 2..ECP_SIZE * 3])?, + d: ecp_from_bytes(&bytes[ECP_SIZE * 3..ECP_SIZE * 4])?, + }) + } +} + +impl TryFrom<&[u8]> for GroupPublicKey { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != GROUP_PUBLIC_KEY_SIZE { + return Err(CredentialError::GroupPublicKeyLength); + } + + let big_start = ECP2_COMPAT_SIZE * 2; + + Ok(GroupPublicKey { + x: ecp2_from_compat_bytes(&bytes[..ECP2_COMPAT_SIZE])?, + y: ecp2_from_compat_bytes(&bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2])?, + cx: big_from_bytes(&bytes[big_start..big_start + BIG_SIZE])?, + sx: big_from_bytes(&bytes[big_start + BIG_SIZE..big_start + BIG_SIZE * 2])?, + cy: big_from_bytes(&bytes[big_start + BIG_SIZE * 2..big_start + BIG_SIZE * 3])?, + sy: big_from_bytes(&bytes[big_start + BIG_SIZE * 3..big_start + BIG_SIZE * 4])?, + }) + } +} + +impl CredentialBIG { + pub fn to_bytes(&self) -> [u8; BIG_SIZE] { + let mut bytes = [0u8; BIG_SIZE]; + self.0.tobytes(&mut bytes); + bytes + } +} + +impl TryFrom<&[u8]> for CredentialBIG { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + Ok(Self(big_from_bytes(bytes)?)) + } +} + +impl JoinRequest { + pub fn to_bytes(&self) -> [u8; JOIN_REQUEST_SIZE] { + let mut result = [0u8; JOIN_REQUEST_SIZE]; + self.q.tobytes(&mut result, false); + result[ECP_SIZE..].copy_from_slice(&self.proof.to_bytes()); + result + } +} + +impl UserCredentials { + pub fn to_bytes(&self) -> [u8; USER_CREDENTIALS_SIZE] { + let mut result = [0u8; USER_CREDENTIALS_SIZE]; + self.a.tobytes(&mut result[..ECP_SIZE], false); + self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); + self.c + .tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); + self.d + .tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); + result + } +} + +impl ECPProof { + pub fn to_bytes(&self) -> [u8; ECP_PROOF_SIZE] { + let mut result = [0u8; ECP_PROOF_SIZE]; + self.c.tobytes(&mut result[..BIG_SIZE]); + self.s.tobytes(&mut result[BIG_SIZE..]); + result + } +} + +impl TryFrom<&[u8]> for ECPProof { + type Error = CredentialError; + + fn try_from(bytes: &[u8]) -> Result { + if bytes.len() != ECP_PROOF_SIZE { + return Err(CredentialError::BadECPProof); + } + + Ok(ECPProof { + c: big_from_bytes(&bytes[0..BIG_SIZE])?, + s: big_from_bytes(&bytes[BIG_SIZE..])?, + }) + } +} + +impl Signature { + pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] { + let mut result = [0u8; SIGNATURE_SIZE]; + self.a.tobytes(&mut result[..ECP_SIZE], false); + self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); + self.c + .tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); + self.d + .tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); + self.nym + .tobytes(&mut result[ECP_SIZE * 4..ECP_SIZE * 5], false); + result[ECP_SIZE * 5..].copy_from_slice(&self.proof.to_bytes()); + result + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs new file mode 100644 index 000000000000..a6eeee031d26 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs @@ -0,0 +1,180 @@ +use brave_miracl::{ + bn254::{ + big::BIG, + ecp::ECP, + ecp2::ECP2, + fp12::FP12, + pair::{g1mul, g2mul}, + }, + rand::RAND, +}; + +use super::data::{ + ecp2_to_compat_bytes, CredentialBIG, ECPProof, GroupPublicKey, JoinRequest, JoinResponse, + StartJoinResult, UserCredentials, BIG_SIZE, ECP2_COMPAT_SIZE, ECP_SIZE, +}; +use super::util::{ + ecp_challenge_equals, hash256, pair_normalized_triple_ate, random_mod_curve_order, + CURVE_ORDER_BIG, G1_ECP, G2_ECP, +}; +use super::{CredentialError, Result}; + +fn ecp_challenge(message: &[u8; BIG_SIZE], y: &ECP, g: &ECP, gr: &ECP) -> BIG { + let mut all_bytes = [0u8; ECP_SIZE * 3 + BIG_SIZE]; + + all_bytes[..BIG_SIZE].copy_from_slice(message); + + y.tobytes(&mut all_bytes[BIG_SIZE..], false); + g.tobytes(&mut all_bytes[ECP_SIZE + BIG_SIZE..], false); + gr.tobytes(&mut all_bytes[ECP_SIZE * 2 + BIG_SIZE..], false); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} + +fn make_ecp_proof(rng: &mut RAND, y: &ECP, x: &BIG, message: &[u8; BIG_SIZE]) -> ECPProof { + let r = random_mod_curve_order(rng); + + let g = G1_ECP.clone(); + let gr = g1mul(&g, &r); + let c = ecp_challenge(message, y, &g, &gr); + let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); + s.add(&r); + s.rmod(&CURVE_ORDER_BIG); + ECPProof { c, s } +} + +fn verify_ecp_proof_equals(a: &ECP, b: &ECP, y: &ECP, z: &ECP, proof: &ECPProof) -> bool { + let cn = BIG::modneg(&proof.c, &CURVE_ORDER_BIG); + + let mut r#as = g1mul(a, &proof.s); + let yc = g1mul(y, &cn); + let mut bs = g1mul(b, &proof.s); + let zc = g1mul(z, &cn); + + r#as.add(&yc); + bs.add(&zc); + + let cc = ecp_challenge_equals(None, &y, &z, &a, &b, &r#as, &bs); + + BIG::comp(&proof.c, &cc) == 0 +} + +fn verify_aux_fast(a: &ECP, b: &ECP, c: &ECP, d: &ECP, x: &ECP2, y: &ECP2, rng: &mut RAND) -> bool { + if a.is_infinity() { + return false; + } + + let e1 = random_mod_curve_order(rng); + let e2 = random_mod_curve_order(rng); + let ne1 = BIG::modneg(&e1, &CURVE_ORDER_BIG); + let ne2 = BIG::modneg(&e2, &CURVE_ORDER_BIG); + + // AA = e1 * A + let aa = g1mul(a, &e1); + + // BB = -e1 * B + let mut bb = g1mul(b, &ne1); + + // CC = -e2 * C + let mut cc = g1mul(c, &ne2); + + // BB = (-e1 * B) + (-e2 * C) + bb.add(&cc); + + // CC = e2 * (A + D) + cc.copy(a); + cc.add(d); + cc = g1mul(&cc, &e2); + + // w = e(e1·A, Y)·e((-e1·B) + (-e2·C), G2)·e(e2·(A + D), X) + let w = pair_normalized_triple_ate(y, &aa, &G2_ECP, &bb, x, &cc); + + let mut fp12_one = FP12::new(); + fp12_one.one(); + + w.equals(&fp12_one) +} + +pub fn start_join(rng: &mut RAND, challenge: &[u8]) -> StartJoinResult { + let gsk = random_mod_curve_order(rng); + let q = g1mul(&G1_ECP, &gsk); + + let challenge_hash = hash256(challenge); + + let proof = make_ecp_proof(rng, &q, &gsk, &challenge_hash); + + StartJoinResult { + gsk: CredentialBIG(gsk), + join_msg: JoinRequest { q, proof }, + } +} + +pub fn finish_join( + pub_key: &GroupPublicKey, + gsk: &CredentialBIG, + resp: JoinResponse, +) -> Result { + verify_group_public_key(pub_key)?; + + let q = g1mul(&G1_ECP, &gsk.0); + + let mut rng = RAND::new(); + rng.seed(BIG_SIZE, &gsk.to_bytes()); + + if !verify_ecp_proof_equals(&G1_ECP, &q, &resp.cred.b, &resp.cred.d, &resp.proof) { + return Err(CredentialError::JoinResponseValidation); + } + + if !verify_aux_fast( + &resp.cred.a, + &resp.cred.b, + &resp.cred.c, + &resp.cred.d, + &pub_key.x, + &pub_key.y, + &mut rng, + ) { + return Err(CredentialError::JoinResponseValidation); + } + + Ok(resp.cred) +} + +fn ecp2_challenge(y: &ECP2, g: &ECP2, gr: &ECP2) -> BIG { + let mut all_bytes = [0u8; ECP2_COMPAT_SIZE * 3]; + + all_bytes[..ECP2_COMPAT_SIZE].copy_from_slice(&ecp2_to_compat_bytes(y)); + all_bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2].copy_from_slice(&ecp2_to_compat_bytes(g)); + all_bytes[ECP2_COMPAT_SIZE * 2..].copy_from_slice(&ecp2_to_compat_bytes(gr)); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} + +fn verify_ecp2_proof(y: &ECP2, c: &BIG, s: &BIG) -> bool { + let cn = BIG::modneg(c, &CURVE_ORDER_BIG); + + let mut gs = g2mul(&G2_ECP, s); + let yc = g2mul(y, &cn); + + gs.add(&yc); + + let cc = ecp2_challenge(y, &G2_ECP, &gs); + + BIG::comp(c, &cc) == 0 +} + +fn verify_group_public_key(key: &GroupPublicKey) -> Result<()> { + match verify_ecp2_proof(&key.x, &key.cx, &key.sx) && verify_ecp2_proof(&key.y, &key.cy, &key.sy) + { + true => Ok(()), + false => Err(CredentialError::BadGroupPublicKey), + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs new file mode 100644 index 000000000000..088720f48a35 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs @@ -0,0 +1,228 @@ +mod data; +mod join; +mod sign; +mod util; + +use brave_miracl::rand::RAND; +use rand::{rngs::OsRng, RngCore}; +use thiserror::Error; + +pub use self::data::*; +use self::join::{finish_join, start_join}; +use self::sign::sign; + +#[derive(Error, Debug)] +pub enum CredentialError { + #[error("ECP should be {0} bytes", ECP_SIZE)] + BadECP, + #[error("ECP2 should be {0} bytes", ECP2_COMPAT_SIZE)] + BadECP2, + #[error("BIG should be {0} bytes", BIG_SIZE)] + BadBIG, + #[error("ECP proof should be {0} bytes", ECP_PROOF_SIZE)] + BadECPProof, + #[error("User credentials should be {0} bytes", USER_CREDENTIALS_SIZE)] + BadUserCredentials, + #[error("Join response should be {0} bytes", JOIN_RESPONSE_SIZE)] + BadJoinResponse, + #[error("Group public key should be {0} bytes", GROUP_PUBLIC_KEY_SIZE)] + GroupPublicKeyLength, + #[error("Join response validation failed")] + JoinResponseValidation, + #[error("Private key and/or credentials not set")] + CredentialsNotSet, + #[error("Group public key verification failed")] + BadGroupPublicKey, +} + +pub type Result = std::result::Result; + +pub struct CredentialManager { + rng: RAND, + gsk_and_credentials: Option<(CredentialBIG, UserCredentials)>, +} + +impl CredentialManager { + pub fn new() -> Self { + let mut entropy = [0u8; 128]; + OsRng::default().fill_bytes(&mut entropy); + Self::new_with_seed(&entropy) + } + + fn new_with_seed(entropy: &[u8]) -> Self { + let mut rng = RAND::new(); + + rng.seed(entropy.len(), entropy); + + Self { + rng, + gsk_and_credentials: None, + } + } + + pub fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { + start_join(&mut self.rng, challenge) + } + + pub fn finish_join( + &mut self, + public_key: &GroupPublicKey, + gsk: &CredentialBIG, + join_resp: JoinResponse, + ) -> Result { + finish_join(public_key, gsk, join_resp) + } + + pub fn set_gsk_and_credentials(&mut self, gsk: CredentialBIG, credentials: UserCredentials) { + self.gsk_and_credentials = Some((gsk, credentials)); + } + + pub fn sign(&mut self, msg: &[u8], basename: &[u8]) -> Result { + match &self.gsk_and_credentials { + Some((gsk, credentials)) => Ok(sign(&mut self.rng, gsk, credentials, msg, basename)), + None => Err(CredentialError::CredentialsNotSet), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use lazy_static::lazy_static; + + lazy_static! { + static ref EXPECTED_GSK: Vec = + hex::decode("0198c86f99ede0ca2ed30b8e4ae6cac831c9b398445422a41d95abb4d3f03499") + .unwrap(); + static ref GROUP_PUB_KEY: Vec = hex::decode( + "0477ce930400ab04a6e1caa46601dbd1b1ba5d24f0577834a960285a0512e7ed\ + 0174121707ea5d80e083d2e992236864608998a4d08cb3a41dde1fc6b7eaad5b2\ + 125310b44ca712bf63f62c39cb44917de0772fefd876e170729428142c21d4f17\ + 9f72fcdc1c1ff5f13e272449ac9ff01a74e95bb011045b12bdac942b46168d051\ + 1ecbb4651d9ddd6491437a8d6b6e6e6877038ea4317a5de863e237ff6472014d2\ + 2c88863b6d8de3eb1b73bb46ab12553c2765bcde905487c518936887ba831dc42\ + ca4862bf60b7cccf08ae579f14699fcff5ec8366af5562a2117095dc066105c17\ + 714dadae0b2110b91d0f19f062e9ab410f59e4515cb027e268435502cf12d4a2d\ + de1c5b711619507485e54e6e6bb1b279e7f42067c47b124e7b1e044de0345f28c\ + ea642eef79e0da60dad085b9bec8b73c61a4eee59ec4f024fc83366e1efc63762\ + b2c1c214ad151dd01f1a5f16d5a238187f1afdab361dfea2e0956be24b1bcdba7\ + c9a6a5e0296377bd1cf1b722bc4d375ae8aa4761b7aac5a50e9871" + ) + .unwrap(); + static ref EXPECTED_CREDENTIALS: Vec = hex::decode( + "04246220e5a9d48d359178c9e0994cc10f7288b50\ + cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ + bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ + 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ + 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ + 9939ec717f4f39e114337878f03c9066afc2250332\ + 76f162b4904248822cb548ccb8167480e23f019813\ + 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ + dd7c9f0006eab2576635a36af81e0f781437c4ee35\ + b8672511089830401074ad73c4e9e9aed541bdc5a2\ + df2ee815a3ac4f6297b73da35db2a646e19720475c\ + fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ + bd494be6a551768c8", + ) + .unwrap(); + } + + const CHALLENGE: &[u8] = b"challenge"; + + fn manager_with_fixed_seed() -> CredentialManager { + let entropy = [0u8; 1]; + CredentialManager::new_with_seed(&entropy) + } + + #[test] + fn test_gsk_and_join_msg() { + let mut cm = manager_with_fixed_seed(); + let result = cm.start_join(CHALLENGE); + + let expected_join_msg = hex::decode( + "04185d9e3a0f0e590928568a951a70749c5f3e\ + 969b3c335f109f0e95f4c0cbabe70ddd27e6751\ + df37fa70b906d3d246b388a2a9fb67c3972ea1b\ + 822dc80653454e0de86a209418b4953191caa980\ + 462463ec21b07da451e7becc2d7917ef34f5150c\ + 1c0a4187182af0a43a28868c7b17b2c73704bc26\ + 8071b414d99f48999014b2", + ) + .unwrap(); + + assert_eq!(result.gsk.to_bytes().as_slice(), EXPECTED_GSK.as_slice()); + assert_eq!(result.join_msg.to_bytes().as_slice(), &expected_join_msg); + } + + #[test] + fn test_finish_join_credentials() { + let mut cm = manager_with_fixed_seed(); + + let group_pub_key: GroupPublicKey = GROUP_PUB_KEY.as_slice().try_into().unwrap(); + let gsk: CredentialBIG = EXPECTED_GSK.as_slice().try_into().unwrap(); + let join_response: JoinResponse = hex::decode( + "04246220e5a9d48d359178c9e0994cc10f7288b50\ + cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ + bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ + 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ + 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ + 9939ec717f4f39e114337878f03c9066afc2250332\ + 76f162b4904248822cb548ccb8167480e23f019813\ + 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ + dd7c9f0006eab2576635a36af81e0f781437c4ee35\ + b8672511089830401074ad73c4e9e9aed541bdc5a2\ + df2ee815a3ac4f6297b73da35db2a646e19720475c\ + fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ + bd494be6a551768c81677932196184249f179d319f\ + eba43b32da42501daa355d3cde30615a08ac687188\ + a8c6e3b8a330f76c233e900acd6ef31c50796b9192\ + 9cfc16b4fcad40b5309", + ) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + + let credentials = cm + .finish_join(&group_pub_key, &gsk, join_response) + .unwrap() + .to_bytes(); + + assert_eq!(credentials.as_slice(), EXPECTED_CREDENTIALS.as_slice()); + } + + #[test] + fn test_signature() { + let mut cm = manager_with_fixed_seed(); + + let gsk = EXPECTED_GSK.as_slice().try_into().unwrap(); + let credentials = EXPECTED_CREDENTIALS.as_slice().try_into().unwrap(); + cm.set_gsk_and_credentials(gsk, credentials); + + let expected_signature = hex::decode( + "0406cb022fcc3dcaef1e4c62dad349bfd263581126c\ + f17b293d1a41e4d96f840da00ad85e4a97aad1247a19\ + a425da6f96978fdac180136f0f486bad0fce0a9ada20\ + 401074ad73c4e9e9aed541bdc5a2df2ee815a3ac4f62\ + 97b73da35db2a646e19720475cfe50eb2465833b5075\ + 8f6c8f09fdf645643a4b3ef5bd494be6a551768c8042\ + 4a006154937bcd3b8f94f12a4672d9a9411928846adc\ + 9132737600089a65915121160cbd4e417435e4acfe66\ + 57840c50584bc8dca420544879fe7fe9c03bc0f0418e\ + e65a71c262c5301d782b20e7f3f252e938282b98a2f8\ + 6a7447e2aa424005819835a0a954d4f6dc53ae4c8bad\ + 2d192a70fcb8883403f69989e43ff66caad0104208cd\ + 8eb5e25486eb754e44f4e2f3b6f5153f5aa73d7eab8c\ + 2f5c867a157276b0463ced7f409f86ef91a4548cf4bb\ + 519392cd657505475e585a3ea0348b6266b1fd3d4ab1\ + 253392386bf2f08afe36072abe575e07865272c3014a\ + b067f5051181fe574571f34d278e2c9359294ca44aa3\ + 3568c546082e4e8d921541e5ccc6c81", + ) + .unwrap(); + + let signature_bytes = cm.sign(b"message", b"basename").unwrap().to_bytes(); + + assert_eq!(signature_bytes, expected_signature.as_slice()); + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs new file mode 100644 index 000000000000..1ee21cf091cc --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs @@ -0,0 +1,68 @@ +use brave_miracl::{ + bn254::{big::BIG, ecp::ECP, pair::g1mul}, + rand::RAND, +}; + +use super::{ + data::{CredentialBIG, ECPProof, Signature, UserCredentials, BIG_SIZE}, + util::{ecp_challenge_equals, hash256, random_mod_curve_order, CURVE_ORDER_BIG}, +}; + +fn make_ecp_proof_equals( + rng: &mut RAND, + message: &[u8; BIG_SIZE], + a: &ECP, + b: &ECP, + y: &ECP, + z: &ECP, + x: &BIG, +) -> ECPProof { + let r = random_mod_curve_order(rng); + + let ar = g1mul(&a, &r); + let br = g1mul(&b, &r); + + let c = ecp_challenge_equals(Some(message), y, z, a, b, &ar, &br); + let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); + s.add(&r); + s.rmod(&CURVE_ORDER_BIG); + + ECPProof { c, s } +} + +pub fn sign( + rng: &mut RAND, + gsk: &CredentialBIG, + credentials: &UserCredentials, + msg: &[u8], + bsn: &[u8], +) -> Signature { + // Randomize credentials for signature + let r = random_mod_curve_order(rng); + + let a = g1mul(&credentials.a, &r); + let b = g1mul(&credentials.b, &r); + let c = g1mul(&credentials.c, &r); + let d = g1mul(&credentials.d, &r); + + // Map basename to point in G1 + let bsn_hash = hash256(bsn); + let bsn_point = ECP::mapit(&bsn_hash); + let nym = g1mul(&bsn_point, &gsk.0); + + // Compute H(H(msg) || H(bsn)) to be used in proof of equality + let mut msg_bsn_hash_data = [0u8; BIG_SIZE * 2]; + msg_bsn_hash_data[..BIG_SIZE].copy_from_slice(&hash256(msg)); + msg_bsn_hash_data[BIG_SIZE..].copy_from_slice(&hash256(bsn)); + let msg_bsn_hash = hash256(&msg_bsn_hash_data); + + let proof = make_ecp_proof_equals(rng, &msg_bsn_hash, &b, &bsn_point, &d, &nym, &gsk.0); + Signature { + a, + b, + c, + d, + nym, + proof, + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs new file mode 100644 index 000000000000..6a68c682edee --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs @@ -0,0 +1,85 @@ +use brave_miracl::{ + bn254::{ + big::BIG, + ecp::ECP, + ecp2::ECP2, + fp12::FP12, + fp2::FP2, + pair::{another, fexp, initmp, miller}, + rom::{CURVE_GX, CURVE_GY, CURVE_ORDER, CURVE_PXA, CURVE_PXB, CURVE_PYA, CURVE_PYB}, + }, + hash256::HASH256, + rand::RAND, +}; +use lazy_static::lazy_static; + +use super::data::{BIG_SIZE, ECP_SIZE}; + +lazy_static! { + pub static ref G1_ECP: ECP = { + let gx = BIG::new_ints(&CURVE_GX); + let gy = BIG::new_ints(&CURVE_GY); + ECP::new_bigs(&gx, &gy) + }; + pub static ref G2_ECP: ECP2 = { + let pxa = BIG::new_ints(&CURVE_PXA); + let pxb = BIG::new_ints(&CURVE_PXB); + let pya = BIG::new_ints(&CURVE_PYA); + let pyb = BIG::new_ints(&CURVE_PYB); + let wx = FP2::new_bigs(&pxa, &pxb); + let wy = FP2::new_bigs(&pya, &pyb); + ECP2::new_fp2s(&wx, &wy) + }; + pub static ref CURVE_ORDER_BIG: BIG = BIG::new_ints(&CURVE_ORDER); +} + +pub fn random_mod_curve_order(rng: &mut RAND) -> BIG { + BIG::randomnum(&CURVE_ORDER_BIG, rng) +} + +pub fn hash256(data: &[u8]) -> [u8; 32] { + let mut hash = HASH256::new(); + hash.process_array(data); + hash.hash() +} + +pub fn pair_normalized_triple_ate(p: &ECP2, q: &ECP, r: &ECP2, s: &ECP, t: &ECP2, u: &ECP) -> FP12 { + let mut rr = initmp(); + another(&mut rr, p, q); + another(&mut rr, r, s); + another(&mut rr, t, u); + let r = miller(&mut rr); + fexp(&r) +} + +pub fn ecp_challenge_equals( + message: Option<&[u8; BIG_SIZE]>, + y: &ECP, + z: &ECP, + a: &ECP, + b: &ECP, + ar: &ECP, + br: &ECP, +) -> BIG { + let (mut all_bytes, msg_len) = match message { + Some(message) => { + let mut all_bytes = vec![0u8; ECP_SIZE * 6 + BIG_SIZE]; + all_bytes[..BIG_SIZE].copy_from_slice(message); + (all_bytes, message.len()) + } + None => (vec![0u8; ECP_SIZE * 6], 0), + }; + + y.tobytes(&mut all_bytes[msg_len..], false); + z.tobytes(&mut all_bytes[msg_len + ECP_SIZE..], false); + a.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 2..], false); + b.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 3..], false); + ar.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 4..], false); + br.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 5..], false); + + let hash = hash256(&all_bytes); + + let mut c = BIG::frombytes(&hash); + c.rmod(&CURVE_ORDER_BIG); + c +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json new file mode 100644 index 000000000000..697c9ce2fbb4 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{}} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json new file mode 100644 index 000000000000..a2ca3d221cd8 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4294e2675ef3016ec941d2011b93226832fb8431" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore new file mode 100644 index 000000000000..96ef6c0b944e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules new file mode 100644 index 000000000000..987edd9563d6 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules @@ -0,0 +1,3 @@ +[submodule "miracl-core"] + path = miracl-core + url = https://github.com/miracl/core diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml new file mode 100644 index 000000000000..f891260784f5 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml @@ -0,0 +1,34 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "brave-miracl" +version = "0.1.2" +authors = ["Mike Scott "] +exclude = [ + "/miracl-core", + "generate.sh", + "renovate.json", +] +description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" +homepage = "https://github.com/miracl/core" +readme = "README.md" +keywords = ["bn254"] +categories = ["cryptography"] +license = "Apache-2.0" +repository = "https://github.com/brave-experiments/miracl-rs" + +[dependencies] + +[features] +default = ["std"] +std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig new file mode 100644 index 000000000000..92fbebeec901 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig @@ -0,0 +1,18 @@ +[package] +name = "brave-miracl" +version = "0.1.2" +edition = "2021" +authors = ["Mike Scott "] +description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" +license = "Apache-2.0" +homepage = "https://github.com/miracl/core" +repository = "https://github.com/brave-experiments/miracl-rs" +keywords = ["bn254"] +categories = ["cryptography"] +exclude = ["/miracl-core", "generate.sh", "renovate.json"] + +[dependencies] + +[features] +default = ["std"] +std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE new file mode 100644 index 000000000000..3c8565d62f17 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Miracl Technologies Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md new file mode 100644 index 000000000000..67423ec88b3f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md @@ -0,0 +1,15 @@ +# brave-miracl + +[![Crates.io](https://img.shields.io/crates/v/brave-miracl?style=for-the-badge)](https://crates.io/crates/brave-miracl) + +A subset of the [MIRACL Core](https://github.com/miracl/core) library that includes the bn254 elliptic curve. + +## Updating the library code + +MIRACL Core is embedded in this repository as a git submodule. + +The library code can be updated and regenerated by executing `./generate.sh`. + +## License + +MIRACL Core is licensed under the [Apache 2.0 License](LICENSE). diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs new file mode 100644 index 000000000000..65b0fa41d320 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs @@ -0,0 +1,901 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub const ECB: usize = 0; +pub const CBC: usize = 1; +pub const CFB1: usize = 2; +pub const CFB2: usize = 3; +pub const CFB4: usize = 5; +pub const OFB1: usize = 14; +pub const OFB2: usize = 15; +pub const OFB4: usize = 17; +pub const OFB8: usize = 21; +pub const OFB16: usize = 29; +pub const CTR1: usize = 30; +pub const CTR2: usize = 31; +pub const CTR4: usize = 33; +pub const CTR8: usize = 37; +pub const CTR16: usize = 45; + +const INCO: [u8; 4] = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */ + +const PTAB: [u8; 256] = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, + 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, + 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, + 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, + 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, + 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, + 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, + 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, + 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, + 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +]; + +const LTAB: [u8; 256] = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, + 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, + 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, + 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, + 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, + 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, + 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, + 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, + 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, + 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, + 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, + 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, + 24, 13, 99, 140, 128, 192, 247, 112, 7, +]; + +const FBSUB: [u8; 256] = [ + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, + 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, + 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, + 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, + 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, + 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, + 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, + 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, + 153, 45, 15, 176, 84, 187, 22, +]; + +const RBSUB: [u8; 256] = [ + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, + 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, + 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, + 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, + 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, + 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, + 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, + 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, + 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, + 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, + 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, + 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, + 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, +]; + +const RCO: [u8; 16] = [ + 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, +]; + +const FTABLE: [u32; 256] = [ + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, + 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, +]; + +const RTABLE: [u32; 256] = [ + 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, + 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, + 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, + 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, + 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, + 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, + 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, + 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, + 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, + 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, + 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, + 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, + 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, + 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, + 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, + 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, + 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, + 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, + 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, + 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, + 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, + 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, + 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, + 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, + 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, + 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, + 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, + 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, +]; + +pub struct AES { +// nk: usize, + nr: usize, + mode: usize, + fkey: [u32; 60], + rkey: [u32; 60], + pub f: [u8; 16], +} + + +fn rotl8(x: u32) -> u32 { + ((x) << 8) | ((x) >> 24) +} + +fn rotl16(x: u32) -> u32 { + ((x) << 16) | ((x) >> 16) +} + +fn rotl24(x: u32) -> u32 { + ((x) << 24) | ((x) >> 8) +} + +fn pack(b: [u8; 4]) -> u32 { + /* pack bytes into a 32-bit Word */ + ((b[3] as u32) << 24) + | ((b[2] as u32) << 16) + | ((b[1] as u32) << 8) + | (b[0] as u32) +} + +fn unpack(a: u32) -> [u8; 4] { + /* unpack bytes from a word */ + [ + (a & 0xff) as u8, + ((a >> 8) & 0xff) as u8, + ((a >> 16) & 0xff) as u8, + ((a >> 24) & 0xff) as u8, + ] +} + +fn bmul(x: u8, y: u8) -> u8 { + /* x.y= AntiLog(Log(x) + Log(y)) */ + let ix = (x as usize) & 0xff; + let iy = (y as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + let ly = (LTAB[iy] as usize) & 0xff; + + if x != 0 && y != 0 { + PTAB[(lx + ly) % 255] + } else { + 0 + } +} + +fn subbyte(a: u32) -> u32 { + let mut b = unpack(a); + b[0] = FBSUB[b[0] as usize]; + b[1] = FBSUB[b[1] as usize]; + b[2] = FBSUB[b[2] as usize]; + b[3] = FBSUB[b[3] as usize]; + pack(b) +} + +fn product(x: u32, y: u32) -> u8 { + /* dot product of two 4-byte arrays */ + let xb = unpack(x); + let yb = unpack(y); + + bmul(xb[0], yb[0]) + ^ bmul(xb[1], yb[1]) + ^ bmul(xb[2], yb[2]) + ^ bmul(xb[3], yb[3]) +} + +fn invmixcol(x: u32) -> u32 { + /* matrix Multiplication */ + let mut b: [u8; 4] = [0; 4]; + let mut m = pack(INCO); + b[3] = product(m, x); + m = rotl24(m); + b[2] = product(m, x); + m = rotl24(m); + b[1] = product(m, x); + m = rotl24(m); + b[0] = product(m, x); + pack(b) +} + +fn increment(f: &mut [u8; 16]) { + for i in 0..16 { + f[i] += 1; + if f[i] != 0 { + break; + } + } +} + +impl AES { + + pub fn new() -> AES { + AES { +// nk: 0, + nr: 0, + mode: 0, + fkey: [0; 60], + rkey: [0; 60], + f: [0; 16], + } + } + + /* reset cipher */ + pub fn reset(&mut self, m: usize, iv: Option<[u8; 16]>) { + /* reset mode, or reset iv */ + self.mode = m; + for i in 0..16 { + self.f[i] = 0 + } + if self.mode != ECB { + if let Some(x) = iv { + for i in 0..16 { + self.f[i] = x[i] + } + } + } + } + + pub fn init(&mut self, m: usize, nkey: usize, key: &[u8], iv: Option<[u8; 16]>) -> bool { + /* Key Scheduler. Create expanded encryption key */ + let mut cipherkey: [u32; 8] = [0; 8]; + let mut b: [u8; 4] = [0; 4]; + let nk = nkey / 4; + if nk != 4 && nk != 6 && nk != 8 { + return false; + } + let nr = 6 + nk; + //self.nk = nk; + self.nr = nr; + self.reset(m, iv); + let n = 4 * (nr + 1); + + let mut j = 0; + for i in 0..nk { + for k in 0..4 { + b[k] = key[j + k] + } + cipherkey[i] = pack(b); + j += 4; + } + + for i in 0..nk { + self.fkey[i] = cipherkey[i] + } + + j = nk; + let mut k = 0; + while j < n { + self.fkey[j] = + self.fkey[j - nk] ^ subbyte(rotl24(self.fkey[j - 1])) ^ (RCO[k] as u32); + if nk<=6 { + for i in 1..nk { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + } else { + for i in 1..4 { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + + if (j + 4) < n { + self.fkey[j + 4] = self.fkey[j + 4 - nk] ^ subbyte(self.fkey[j + 3]); + } + for i in 5..nk { + if (i + j) >= n { + break; + } + self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; + } + } + j += nk; + k += 1; + } + + /* now for the expanded decrypt key in reverse order */ + + for j in 0..4 { + self.rkey[j + n - 4] = self.fkey[j] + } + let mut i = 4; + while i < n - 4 { + let k = n - 4 - i; + for j in 0..4 { + self.rkey[k + j] = invmixcol(self.fkey[i + j]) + } + i += 4; + } + for j in n - 4..n { + self.rkey[j + 4 - n] = self.fkey[j] + } + true + } + + pub fn getreg(&mut self) -> [u8; 16] { + let mut ir: [u8; 16] = [0; 16]; + for i in 0..16 { + ir[i] = self.f[i] + } + ir + } + + /* Encrypt a single block */ + pub fn ecb_encrypt(&mut self, buff: &mut [u8; 16]) { + let mut b: [u8; 4] = [0; 4]; + let mut p: [u32; 4] = [0; 4]; + let mut q: [u32; 4] = [0; 4]; + + let mut j = 0; + for i in 0..4 { + for k in 0..4 { + b[k] = buff[j + k] + } + p[i] = pack(b); + p[i] ^= self.fkey[i]; + j += 4; + } + + let mut k = 4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + q[0] = self.fkey[k] + ^ FTABLE[(p[0] & 0xff) as usize] + ^ rotl8(FTABLE[((p[1] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[2] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[3] >> 24) & 0xff) as usize]); + + q[1] = self.fkey[k + 1] + ^ FTABLE[(p[1] & 0xff) as usize] + ^ rotl8(FTABLE[((p[2] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[3] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[0] >> 24) & 0xff) as usize]); + + q[2] = self.fkey[k + 2] + ^ FTABLE[(p[2] & 0xff) as usize] + ^ rotl8(FTABLE[((p[3] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[0] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[1] >> 24) & 0xff) as usize]); + + q[3] = self.fkey[k + 3] + ^ FTABLE[(p[3] & 0xff) as usize] + ^ rotl8(FTABLE[((p[0] >> 8) & 0xff) as usize]) + ^ rotl16(FTABLE[((p[1] >> 16) & 0xff) as usize]) + ^ rotl24(FTABLE[((p[2] >> 24) & 0xff) as usize]); + + k += 4; + for j in 0..4 { + let t = p[j]; + p[j] = q[j]; + q[j] = t; + } + } + + /* Last Round */ + + q[0] = self.fkey[k] + ^ (FBSUB[(p[0] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); + + q[1] = self.fkey[k + 1] + ^ (FBSUB[(p[1] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); + + q[2] = self.fkey[k + 2] + ^ (FBSUB[(p[2] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); + + q[3] = self.fkey[k + 3] + ^ (FBSUB[(p[3] & 0xff) as usize] as u32) + ^ rotl8((FBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((FBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((FBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); + + j = 0; + for i in 0..4 { + b = unpack(q[i]); + for k in 0..4 { + buff[j + k] = b[k] + } + j += 4; + } + } + + /* Decrypt a single block */ + pub fn ecb_decrypt(&mut self, buff: &mut [u8; 16]) { + let mut b: [u8; 4] = [0; 4]; + let mut p: [u32; 4] = [0; 4]; + let mut q: [u32; 4] = [0; 4]; + + let mut j = 0; + for i in 0..4 { + for k in 0..4 { + b[k] = buff[j + k] + } + p[i] = pack(b); + p[i] ^= self.rkey[i]; + j += 4; + } + + let mut k = 4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + q[0] = self.rkey[k] + ^ RTABLE[(p[0] & 0xff) as usize] + ^ rotl8(RTABLE[((p[3] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[2] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[1] >> 24) & 0xff) as usize]); + + q[1] = self.rkey[k + 1] + ^ RTABLE[(p[1] & 0xff) as usize] + ^ rotl8(RTABLE[((p[0] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[3] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[2] >> 24) & 0xff) as usize]); + + q[2] = self.rkey[k + 2] + ^ RTABLE[(p[2] & 0xff) as usize] + ^ rotl8(RTABLE[((p[1] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[0] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[3] >> 24) & 0xff) as usize]); + + q[3] = self.rkey[k + 3] + ^ RTABLE[(p[3] & 0xff) as usize] + ^ rotl8(RTABLE[((p[2] >> 8) & 0xff) as usize]) + ^ rotl16(RTABLE[((p[1] >> 16) & 0xff) as usize]) + ^ rotl24(RTABLE[((p[0] >> 24) & 0xff) as usize]); + + k += 4; + for j in 0..4 { + let t = p[j]; + p[j] = q[j]; + q[j] = t; + } + } + + /* Last Round */ + + q[0] = self.rkey[k] + ^ (RBSUB[(p[0] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); + + q[1] = self.rkey[k + 1] + ^ (RBSUB[(p[1] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); + + q[2] = self.rkey[k + 2] + ^ (RBSUB[(p[2] & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); + + q[3] = self.rkey[k + 3] + ^ (RBSUB[((p[3]) & 0xff) as usize] as u32) + ^ rotl8((RBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) + ^ rotl16((RBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) + ^ rotl24((RBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); + + j = 0; + for i in 0..4 { + b = unpack(q[i]); + for k in 0..4 { + buff[j + k] = b[k] + } + j += 4; + } + } + + /* Encrypt using selected mode of operation */ + pub fn encrypt(&mut self, buff: &mut [u8; 16]) -> u32 { + let mut st: [u8; 16] = [0; 16]; + + // Supported Modes of Operation + + let mut fell_off: u32 = 0; + + match self.mode { + ECB => { + self.ecb_encrypt(buff); + 0 + } + CBC => { + for j in 0..16 { + buff[j] ^= self.f[j] + } + self.ecb_encrypt(buff); + for j in 0..16 { + self.f[j] = buff[j] + } + 0 + } + + CFB1 | CFB2 | CFB4 => { + let bytes = self.mode - CFB1 + 1; + for j in 0..bytes { + fell_off = (fell_off << 8) | (self.f[j] as u32) + } + for j in 0..16 { + st[j] = self.f[j] + } + for j in bytes..16 { + self.f[j - bytes] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j]; + self.f[16 - bytes + j] = buff[j]; + } + fell_off + } + + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes = self.mode - OFB1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + for j in 0..16 { + self.f[j] = st[j] + } + + //self.ecb_encrypt(&mut (self.f)); + //for j in 0..bytes {buff[j]^=self.f[j]} + 0 + } + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes = self.mode - CTR1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + increment(&mut (self.f)); + 0 + } + + _ => { + 0 + } + } + } + + /* Decrypt using selected mode of operation */ + pub fn decrypt(&mut self, buff: &mut [u8; 16]) -> u32 { + let mut st: [u8; 16] = [0; 16]; + + // Supported Modes of Operation + + let mut fell_off: u32 = 0; + + match self.mode { + ECB => { + self.ecb_decrypt(buff); + 0 + } + CBC => { + for j in 0..16 { + st[j] = self.f[j]; + self.f[j] = buff[j]; + } + self.ecb_decrypt(buff); + for j in 0..16 { + buff[j] ^= st[j]; + st[j] = 0; + } + 0 + } + CFB1 | CFB2 | CFB4 => { + let bytes = self.mode - CFB1 + 1; + for j in 0..bytes { + fell_off = (fell_off << 8) | (self.f[j] as u32) + } + for j in 0..16 { + st[j] = self.f[j] + } + for j in bytes..16 { + self.f[j - bytes] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + self.f[16 - bytes + j] = buff[j]; + buff[j] ^= st[j]; + } + fell_off + } + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes = self.mode - OFB1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + for j in 0..16 { + self.f[j] = st[j] + } + // self.ecb_encrypt(A.f[:]); + // for j in 0..bytes {buff[j]^=self.f[j]} + 0 + } + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes = self.mode - CTR1 + 1; + for j in 0..16 { + st[j] = self.f[j] + } + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j] ^= st[j] + } + increment(&mut (self.f)); + 0 + } + + _ => { + 0 + } + } + } + + /* Clean up and delete left-overs */ + pub fn end(&mut self) { + // clean up + for i in 0..4 * (self.nr + 1) { + self.fkey[i] = 0; + self.rkey[i] = 0 + } + for i in 0..16 { + self.f[i] = 0 + } + } +} + +/* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */ +pub fn cbc_iv0_encrypt(k: &[u8], m: &[u8],c: &mut [u8]) -> usize { + /* AES CBC encryption, with Null IV and key K */ + /* Input is from an octet string m, output is to an octet string c */ + /* Input is padded as necessary to make up a full final block */ + let mut a = AES::new(); + let mut fin = false; + + let mut buff: [u8; 16] = [0; 16]; + + a.init(CBC, k.len(), k, None); + + let mut ipt = 0; + let mut opt = 0; + let mut i; + loop { + i = 0; + while i < 16 { + if ipt < m.len() { + buff[i] = m[ipt]; + i += 1; + ipt += 1; + } else { + fin = true; + break; + } + } + if fin { + break; + } + a.encrypt(&mut buff); + for j in 0..16 { + if opt < c.len() { + c[opt]=buff[j]; opt+=1; + } + } + } + + /* last block, filled up to i-th index */ + + let padlen = 16 - i; + for j in i..16 { + buff[j] = padlen as u8 + } + + a.encrypt(&mut buff); + + for j in 0..16 { + if opt usize { + /* padding is removed */ + let mut a = AES::new(); + let mut fin = false; + + let mut buff: [u8; 16] = [0; 16]; + + a.init(CBC, k.len(), k, None); + + let mut ipt = 0; + let mut opt = 0; + let mut i; + + if c.is_empty() { + return 0; + } + let mut ch = c[ipt]; + ipt += 1; + + loop { + i = 0; + while i < 16 { + buff[i] = ch; + if ipt >= c.len() { + fin = true; + break; + } else { + ch = c[ipt]; + ipt += 1 + } + i += 1; + } + a.decrypt(&mut buff); + if fin { + break; + } + for j in 0..16 { + if opt 16 { + bad = true + } + if padlen >= 2 && padlen <= 16 { + for j in 16 - padlen..16 { + if buff[j] != padlen as u8 { + bad = true + } + } + } + + if !bad { + for i in 0..16 - padlen { + if opt BIG { + *self + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for BIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for BIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl BIG { + pub const fn new() -> BIG { + BIG { w: [0; NLEN] } + } + + pub fn new_int(x: isize) -> BIG { + let mut s = BIG::new(); + s.w[0] = x as Chunk; + s + } + + pub fn new_ints(a: &[Chunk]) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = a[i] + } + s + } + + pub fn new_copy(y: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_big(y: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_dcopy(y: &DBIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn get(&self, i: usize) -> Chunk { + self.w[i] + } + + pub fn set(&mut self, i: usize, x: Chunk) { + self.w[i] = x; + } + + pub fn xortop(&mut self, x: Chunk) { + self.w[NLEN - 1] ^= x; + } + + pub fn ortop(&mut self, x: Chunk) { + self.w[NLEN - 1] |= x; + } + + /* test for zero */ + pub fn iszilch(&self) -> bool { + let mut d = 0 as Chunk; + for i in 0..NLEN { + d |= self.w[i]; + } + (1 & ((d-1)>>BASEBITS)) != 0 + } + + /* set to zero */ + pub fn zero(&mut self) { + for i in 0..NLEN { + self.w[i] = 0 + } + } + + /* Test for equal to one */ + pub fn isunity(&self) -> bool { + let mut d = 0 as Chunk; + for i in 1..NLEN { + d |= self.w[i]; + } + (1 & ((d-1)>>BASEBITS) & (((self.w[0]^1)-1)>>BASEBITS)) != 0 + } + + /* set to one */ + pub fn one(&mut self) { + self.w[0] = 1; + for i in 1..NLEN { + self.w[i] = 0; + } + } + + /* Copy from another BIG */ + pub fn copy(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] + } + } + + pub fn dcopy(&mut self, x: &DBIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] + } + } + + /* Get top and bottom half of =x*y+c+r */ + pub fn muladd(a: Chunk, b: Chunk, c: Chunk, r: Chunk) -> (Chunk, Chunk) { + let prod: DChunk = (a as DChunk) * (b as DChunk) + (c as DChunk) + (r as DChunk); + let bot = (prod & (BMASK as DChunk)) as Chunk; + let top = (prod >> BASEBITS) as Chunk; + (top, bot) + } + + /* normalise BIG - force all digits < 2^BASEBITS */ + pub fn norm(&mut self) -> Chunk { + let mut carry = self.w[0]>>BASEBITS; + self.w[0] &= BMASK; + for i in 1..NLEN - 1 { + let d = self.w[i] + carry; + self.w[i] = d & BMASK; + carry = d >> BASEBITS; + } + self.w[NLEN - 1] += carry; + (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as Chunk + } + + /* Conditional swap of two bigs depending on d using XOR - no branches */ + pub fn cswap(&mut self, b: &mut BIG, d: isize) -> Chunk { + let c = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^b.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..NLEN { + let mut t = c & (self.w[i] ^ b.w[i]); + t^=r; + let mut e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + e=b.w[i]^t; w^=e; + b.w[i]=e^ra; + } + return w; + } + + pub fn cmove(&mut self, g: &BIG, d: isize) -> Chunk { + let b = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^g.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..NLEN { + let mut t = b & (self.w[i] ^ g.w[i]); + t^=r; + let e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + } + return w; + } + + /* Shift right by less than a word */ + pub fn fshr(&mut self, k: usize) -> isize { + let n = k; + let w = self.w[0] & ((1 << n) - 1); /* shifted out part */ + for i in 0..NLEN - 1 { + self.w[i] = (self.w[i] >> k) | ((self.w[i + 1] << (BASEBITS - n)) & BMASK); + } + self.w[NLEN - 1] >>= k; + w as isize + } + + /* general shift right */ + pub fn shr(&mut self, k: usize) { + let n = k % BASEBITS; + let m = k / BASEBITS; + for i in 0..NLEN - m - 1 { + self.w[i] = (self.w[m + i] >> n) | ((self.w[m + i + 1] << (BASEBITS - n)) & BMASK) + } + self.w[NLEN - m - 1] = self.w[NLEN - 1] >> n; + for i in NLEN - m..NLEN { + self.w[i] = 0 + } + } + + /* Shift right by less than a word */ + pub fn fshl(&mut self, k: usize) -> isize { + let n = k; + self.w[NLEN - 1] = (self.w[NLEN - 1] << n) | (self.w[NLEN - 2] >> (BASEBITS - n)); + for i in (1..NLEN - 1).rev() { + self.w[i] = ((self.w[i] << k) & BMASK) | (self.w[i - 1] >> (BASEBITS - n)); + } + self.w[0] = (self.w[0] << n) & BMASK; + (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as isize /* return excess - only used in ff.c */ + } + + /* general shift left */ + pub fn shl(&mut self, k: usize) { + let n = k % BASEBITS; + let m = k / BASEBITS; + + self.w[NLEN - 1] = self.w[NLEN - 1 - m] << n; + if NLEN >= m + 2 { + self.w[NLEN - 1] |= self.w[NLEN - m - 2] >> (BASEBITS - n) + } + for i in (m + 1..NLEN - 1).rev() { + self.w[i] = ((self.w[i - m] << n) & BMASK) | (self.w[i - m - 1] >> (BASEBITS - n)); + } + self.w[m] = (self.w[0] << n) & BMASK; + for i in 0..m { + self.w[i] = 0 + } + } + + /* return number of bits */ + pub fn nbits(&self) -> usize { + let mut k = NLEN - 1; + let mut s = BIG::new_copy(&self); + s.norm(); + while (k as isize) >= 0 && s.w[k] == 0 { + k = k.wrapping_sub(1) + } + if (k as isize) < 0 { + return 0; + } + let mut bts = BASEBITS * k; + let mut c = s.w[k]; + while c != 0 { + c /= 2; + bts += 1; + } + bts + } + + /* Convert to Hex String */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut s = String::new(); + let mut len = self.nbits(); + + if len % 4 == 0 { + len /= 4; + } else { + len /= 4; + len += 1; + } + let mb = (MODBYTES * 2) as usize; + if len < mb { + len = mb + } + + for i in (0..len).rev() { + let mut b = BIG::new_copy(&self); + b.shr(i * 4); + s = s + &format!("{:X}", b.w[0] & 15); + } + s + } + + #[cfg(feature = "std")] + pub fn fromstring(val: String) -> BIG { + let mut res = BIG::new(); + let len = val.len(); + let op = &val[0..1]; + let n = u8::from_str_radix(op, 16).unwrap(); + res.w[0] += n as Chunk; + for i in 1..len { + res.shl(4); + let op = &val[i..i+1]; + let n = u8::from_str_radix(op, 16).unwrap(); + res.w[0] += n as Chunk; + } + res + } + + pub fn add(&mut self, r: &BIG) { + for i in 0..NLEN { + self.w[i] += r.w[i] + } + } + + pub fn or(&mut self, r: &BIG) { + for i in 0..NLEN { + self.w[i] |= r.w[i] + } + } + + pub fn dbl(&mut self) { + for i in 0..NLEN { + self.w[i] += self.w[i] + } + } + + /* return this+x */ + pub fn plus(&self, x: &BIG) -> BIG { + let mut s = BIG::new(); + for i in 0..NLEN { + s.w[i] = self.w[i] + x.w[i]; + } + s.norm(); + s + } + + pub fn inc(&mut self, x: isize) { + self.norm(); + self.w[0] += x as Chunk; + } + + /* return self-x */ + pub fn minus(&self, x: &BIG) -> BIG { + let mut d = BIG::new(); + for i in 0..NLEN { + d.w[i] = self.w[i] - x.w[i]; + } + d + } + + /* self-=x */ + pub fn sub(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] -= x.w[i]; + } + } + + /* reverse subtract this=x-this */ + + pub fn rsub(&mut self, x: &BIG) { + for i in 0..NLEN { + self.w[i] = x.w[i] - self.w[i] + } + } + + /* self-=x, where x is int */ + pub fn dec(&mut self, x: isize) { + self.norm(); + self.w[0] -= x as Chunk; + } + + /* self*=x, where x is small int BIG { + let mut m = BIG::new(); + for i in 0..(MODBYTES as usize) { + m.fshl(8); + m.w[0] += b[i + n] as Chunk; + } + m + } + + pub fn tobytes(&self, b: &mut [u8]) { + self.tobytearray(b, 0) + } + + pub fn frombytes(b: &[u8]) -> BIG { + BIG::frombytearray(b, 0) + } + + /* self*=x, where x is >NEXCESS */ + pub fn pmul(&mut self, c: isize) -> Chunk { + let mut carry = 0 as Chunk; + for i in 0..NLEN { + let ak = self.w[i]; + let tuple = BIG::muladd(ak, c as Chunk, carry, 0 as Chunk); + carry = tuple.0; + self.w[i] = tuple.1; + } + carry + } + + /* self*=c and catch overflow in DBIG */ + pub fn pxmul(&mut self, c: isize) -> DBIG { + let mut m = DBIG::new(); + let mut carry = 0 as Chunk; + for j in 0..NLEN { + let tuple = BIG::muladd(self.w[j], c as Chunk, carry, m.w[j]); + carry = tuple.0; + m.w[j] = tuple.1; + } + m.w[NLEN] = carry; + m + } + + /* divide by 3 */ + pub fn div3(&mut self) -> Chunk { + let mut carry = 0 as Chunk; + self.norm(); + let base = 1 << BASEBITS; + for i in (0..NLEN).rev() { + let ak = carry * base + self.w[i]; + self.w[i] = ak / 3; + carry = ak % 3; + } + carry + } + + /* return a*b where result fits in a BIG */ + pub fn smul(a: &BIG, b: &BIG) -> BIG { + let mut c = BIG::new(); + for i in 0..NLEN { + let mut carry = 0 as Chunk; + for j in 0..NLEN { + if i + j < NLEN { + let tuple = BIG::muladd(a.w[i], b.w[j], carry, c.w[i + j]); + carry = tuple.0; + c.w[i + j] = tuple.1; + } + } + } + c + } + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + pub fn comp(a: &BIG, b: &BIG) -> isize { + let mut gt = 0 as Chunk; + let mut eq = 1 as Chunk; + for i in (0..NLEN).rev() { + gt |= ((b.w[i]-a.w[i]) >> BASEBITS) & eq; + eq &= ((b.w[i]^a.w[i])-1) >> BASEBITS; + } + (gt+gt+eq-1) as isize + } + + /* set x = x mod 2^m */ + pub fn mod2m(&mut self, m: usize) { + let wd = m / BASEBITS; + let bt = m % BASEBITS; + let msk = (1 << bt) - 1; + self.w[wd] &= msk; + for i in wd + 1..NLEN { + self.w[i] = 0 + } + } + + /* Arazi and Qi inversion mod 256 */ + pub fn invmod256(a: isize) -> isize { + let mut t1: isize = 0; + let mut c = (a >> 1) & 1; + t1 += c; + t1 &= 1; + t1 = 2 - t1; + t1 <<= 1; + let mut u = t1 + 1; + + // i=2 + let mut b = a & 3; + t1 = u * b; + t1 >>= 2; + c = (a >> 2) & 3; + let mut t2 = (u * c) & 3; + t1 += t2; + t1 *= u; + t1 &= 3; + t1 = 4 - t1; + t1 <<= 2; + u += t1; + + // i=4 + b = a & 15; + t1 = u * b; + t1 >>= 4; + c = (a >> 4) & 15; + t2 = (u * c) & 15; + t1 += t2; + t1 *= u; + t1 &= 15; + t1 = 16 - t1; + t1 <<= 4; + u += t1; + + u + } + + /* return parity */ + pub fn parity(&self) -> isize { + (self.w[0] % 2) as isize + } + + /* return n-th bit */ + pub fn bit(&self, n: usize) -> isize { + return ((self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) >> (n%BASEBITS)) as isize; + + + // if (self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) > 0 { +// 1 +// } else { +// 0 +// } + } + + /* return n last bits */ + pub fn lastbits(&mut self, n: usize) -> isize { + let msk = ((1 << n) - 1) as Chunk; + self.norm(); + (self.w[0] & msk) as isize + } + + /* a=1/a mod 2^256. This is very fast! */ + pub fn invmod2m(&mut self) { + let mut u = BIG::new(); + let mut b = BIG::new(); + let mut c = BIG::new(); + + u.inc(BIG::invmod256(self.lastbits(8))); + + let mut i = 8; + while i < BIGBITS { + u.norm(); + b.copy(self); + b.mod2m(i); + let mut t1 = BIG::smul(&u, &b); + t1.shr(i); + c.copy(self); + c.shr(i); + c.mod2m(i); + + let mut t2 = BIG::smul(&u, &c); + t2.mod2m(i); + t1.add(&t2); + t1.norm(); + b = BIG::smul(&t1, &u); + t1.copy(&b); + t1.mod2m(i); + + t2.one(); + t2.shl(i); + t1.rsub(&t2); + t1.norm(); + t1.shl(i); + u.add(&t1); + i <<= 1; + } + u.mod2m(BIGBITS); + self.copy(&u); + self.norm(); + } + +// Set self=self mod m in constant time (if bd is known at compile time) +// bd is Max number of bits in b - Actual number of bits in m + pub fn ctmod(&mut self,m:&BIG,bd:usize) { + let mut k=bd; + let mut r=BIG::new(); + let mut c=BIG::new_copy(m); + self.norm(); + + c.shl(k); + loop { + r.copy(self); + r.sub(&c); + r.norm(); + self.cmove(&r,(1 - ((r.w[NLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); + if k==0 {break;} + c.fshr(1); + k -= 1; + } + } + + /* reduce self mod m */ + pub fn rmod(&mut self, m: &BIG) { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss> (arch::CHUNK - 1)) & 1)) as isize; + a.cmove(&r, d); + r.copy(self); + r.add(&e); + r.norm(); + self.cmove(&r, d); + if k==0 {break;} + k -= 1; + c.fshr(1); + e.fshr(1); + } + } + + /* divide self by m */ + pub fn div(&mut self, m: &BIG) { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss BIG { + let mut m = BIG::new(); + let mut j = 0; + let mut r: u8 = 0; + /* generate random BIG */ + + for _ in 0..8 * (MODBYTES as usize) { + if j == 0 { + r = rng.getbyte() + } else { + r >>= 1 + } + + let b = (r as Chunk) & 1; + m.shl(1); + m.w[0] += b; + j += 1; + j &= 7; + } + m + } + + /* Create random BIG in portable way, one bit at a time */ + pub fn randomnum(q: &BIG, rng: &mut RAND) -> BIG { + let mut d = DBIG::new(); + let mut j = 0; + let mut r: u8 = 0; + let t = BIG::new_copy(q); + for _ in 0..2 * t.nbits() { + if j == 0 { + r = rng.getbyte(); + } else { + r >>= 1 + } + + let b = (r as Chunk) & 1; + d.shl(1); + d.w[0] += b; + j += 1; + j &= 7; + } + d.dmod(q) + } + +/* create randum BIG less than r and less than trunc bits */ + pub fn randtrunc(q: &BIG, trunc: usize, rng: &mut RAND) -> BIG { + let mut m=BIG::randomnum(q,rng); + if q.nbits() > trunc { + m.mod2m(trunc); + } + m + } + + /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ + pub fn jacobi(&mut self, p: &BIG) -> isize { + let mut m: usize = 0; + let mut t = BIG::new(); + let mut x = BIG::new(); + let mut n = BIG::new(); + let zilch = BIG::new(); + let one = BIG::new_int(1); + if p.parity() == 0 || BIG::comp(self, &zilch) == 0 || BIG::comp(p, &one) <= 0 { + return 0; + } + self.norm(); + + x.copy(self); + n.copy(p); + x.rmod(p); + + while BIG::comp(&n, &one) > 0 { + if BIG::comp(&x, &zilch) == 0 { + return 0; + } + let n8 = n.lastbits(3) as usize; + let mut k = 0; + while x.parity() == 0 { + k += 1; + x.shr(1); + } + if k % 2 == 1 { + m += (n8 * n8 - 1) / 8 + } + m += (n8 - 1) * ((x.lastbits(2) as usize) - 1) / 4; + t.copy(&n); + t.rmod(&x); + n.copy(&x); + x.copy(&t); + m %= 2; + } + if m == 0 { + 1 + } else { + -1 + } + } + +// Set self=1/self mod p. Binary method +// NOTE: This function is NOT side-channel safe +// If a is a secret then ALWAYS calculate 1/a = m*(1/am) mod p +// where m is a random masking value + pub fn invmodp(&mut self, p: &BIG) { + self.rmod(p); + if self.iszilch() {return;} + let mut u = BIG::new_copy(self); + let mut v = BIG::new_copy(p); + let mut x1 = BIG::new_int(1); + let mut x2 = BIG::new(); + let mut t = BIG::new(); + let one = BIG::new_int(1); + + while (BIG::comp(&u, &one) != 0) && (BIG::comp(&v, &one) != 0) { + while u.parity() == 0 { + u.fshr(1); + t.copy(&x1); + t.add(p); + x1.cmove(&t,x1.parity()); + x1.norm(); + x1.fshr(1); + } + while v.parity() == 0 { + v.fshr(1); + t.copy(&x2); + t.add(p); + x2.cmove(&t,x2.parity()); + x2.norm(); + x2.fshr(1); + } + if BIG::comp(&u, &v) >= 0 { + u.sub(&v); + u.norm(); + t.copy(&x1); + t.add(p); + x1.cmove(&t,(BIG::comp(&x1,&x2)>>1)&1); + x1.sub(&x2); + x1.norm(); + } else { + v.sub(&u); + v.norm(); + t.copy(&x2); + t.add(p); + x2.cmove(&t,(BIG::comp(&x2,&x1)>>1)&1); + x2.sub(&x1); + x2.norm(); + } + } + self.copy(&x1); + self.cmove(&x2,BIG::comp(&u,&one)&1); + } + + /* return a*b as DBIG - Simple Karatsuba */ + pub fn mul(a: &BIG, b: &BIG) -> DBIG { + let mut c = DBIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut d: [DChunk; DNLEN] = [0; DNLEN]; + for i in 0..NLEN { + d[i] = (a.w[i] as DChunk) * (b.w[i] as DChunk); + } + let mut s = d[0]; + let mut t = s; + c.w[0] = (t & rm) as Chunk; + t >>= rb; + for k in 1..NLEN { + s += d[k]; + t += s; + for i in 1 + k / 2..k + 1 { + t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk) + } + c.w[k] = (t & rm) as Chunk; + t >>= rb; + } + for k in NLEN..2 * NLEN - 1 { + s -= d[k - NLEN]; + t += s; + let mut i = 1 + k / 2; + while i < NLEN { + t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk); + i += 1; + } + + c.w[k] = (t & rm) as Chunk; + t >>= rb; + } + c.w[2 * NLEN - 1] = t as Chunk; + c + } + + /* return a^2 as DBIG */ + pub fn sqr(a: &BIG) -> DBIG { + let mut c = DBIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut t = (a.w[0] as DChunk) * (a.w[0] as DChunk); + c.w[0] = (t & rm) as Chunk; + let mut co = t >> rb; + + let mut j = 1; + while j < NLEN - 1 { + t = (a.w[j] as DChunk) * (a.w[0] as DChunk); + for i in 1..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + t = (a.w[j] as DChunk) * (a.w[0] as DChunk); + for i in 1..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + } + + j = NLEN + (NLEN % 2) - 1; + while j < DNLEN - 3 { + t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); + for i in j + 2 - NLEN..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); + for i in j + 2 - NLEN..(j + 1) / 2 { + t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); + } + t += t; + t += co; + t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); + c.w[j] = (t & rm) as Chunk; + co = t >> rb; + j += 1; + } + + t = (a.w[NLEN - 2] as DChunk) * (a.w[NLEN - 1] as DChunk); + t += t; + t += co; + c.w[DNLEN - 3] = (t & rm) as Chunk; + co = t >> rb; + + t = (a.w[NLEN - 1] as DChunk) * (a.w[NLEN - 1] as DChunk) + co; + c.w[DNLEN - 2] = (t & rm) as Chunk; + co = t >> rb; + c.w[DNLEN - 1] = co as Chunk; + + c + } + + /* Montgomery reduction */ + pub fn monty(md: &BIG, mc: Chunk, d: &mut DBIG) -> BIG { + let mut b = BIG::new(); + let rm = BMASK as DChunk; + let rb = BASEBITS; + + let mut dd: [DChunk; NLEN] = [0; NLEN]; + let mut v: [Chunk; NLEN] = [0; NLEN]; + + b.zero(); + + let mut t = d.w[0] as DChunk; + v[0] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; + t += (v[0] as DChunk) * (md.w[0] as DChunk); + t = (d.w[1] as DChunk) + (t >> rb); + let mut s: DChunk = 0; + for k in 1..NLEN { + t = t + s + (v[0] as DChunk) * (md.w[k] as DChunk); + let mut i = 1 + k / 2; + while i < k { + t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); + i += 1; + } + v[k] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; + t += (v[k] as DChunk) * (md.w[0] as DChunk); + t = (d.w[k + 1] as DChunk) + (t >> rb); + dd[k] = (v[k] as DChunk) * (md.w[k] as DChunk); + s += dd[k]; + } + + for k in NLEN..2 * NLEN - 1 { + t += s; + let mut i = 1 + k / 2; + while i < NLEN { + t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); + i += 1; + } + b.w[k - NLEN] = (t & rm) as Chunk; + t = (d.w[k + 1] as DChunk) + (t >> rb); + s -= dd[k + 1 - NLEN]; + } + b.w[NLEN - 1] = (t & rm) as Chunk; + b + } + + /* Fast combined shift, subtract and norm. Return sign of result */ + pub fn ssn(r: &mut BIG, a: &BIG, m: &mut BIG) -> isize { + let n = NLEN - 1; + m.w[0] = (m.w[0] >> 1) | ((m.w[1] << (BASEBITS - 1)) & BMASK); + r.w[0] = a.w[0] - m.w[0]; + let mut carry = r.w[0] >> BASEBITS; + r.w[0] &= BMASK; + for i in 1..n { + m.w[i] = (m.w[i] >> 1) | ((m.w[i + 1] << (BASEBITS - 1)) & BMASK); + r.w[i] = a.w[i] - m.w[i] + carry; + carry = r.w[i] >> BASEBITS; + r.w[i] &= BMASK; + } + m.w[n] >>= 1; + r.w[n] = a.w[n] - m.w[n] + carry; + ((r.w[n] >> (arch::CHUNK - 1)) & 1) as isize + } + + /* return a*b mod m */ + pub fn modmul(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + let mut b = BIG::new_copy(b1); + a.rmod(m); + b.rmod(m); + let mut d = BIG::mul(&a, &b); + d.ctdmod(m,m.nbits()) + } + + /* return a^2 mod m */ + pub fn modsqr(a1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + a.rmod(m); + let mut d = BIG::sqr(&a); + d.ctdmod(m,m.nbits()) + } + + /* return -a mod m */ + pub fn modneg(a1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + a.rmod(m); + a.rsub(m); + a.norm(); + a + } + + /* return a+b mod m */ + pub fn modadd(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { + let mut a = BIG::new_copy(a1); + let mut b = BIG::new_copy(b1); + a.rmod(m); + b.rmod(m); + a.add(&b); a.norm(); + a.ctmod(m,1); + a + } + + /* return this^e mod m */ + pub fn powmod(&mut self, e1: &BIG, m: &BIG) -> BIG { + self.norm(); + let mut e = BIG::new_copy(e1); + e.norm(); + let mut a = BIG::new_int(1); + let mut z = BIG::new_copy(&e); + let mut s = BIG::new_copy(self); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + a = BIG::modmul(&a, &s, m) + } + if z.iszilch() { + break; + } + s = BIG::modsqr(&s, m); + } + a + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs new file mode 100644 index 000000000000..507ce760e626 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp::FP; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::dbig::DBIG; +use crate::bn254::ecp2::ECP2; +//use crate::bn254::fp4::FP4; +use crate::bn254::pair; +use crate::bn254::rom; +use crate::hmac; + +/* Boneh-Lynn-Shacham signature 128-bit API Functions */ + +/* Loosely (for now) following https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-02 */ + +// Minimal-signature-size variant + +pub const BFS: usize = big::MODBYTES as usize; +pub const BGS: usize = big::MODBYTES as usize; +pub const BLS_OK: isize = 0; +pub const BLS_FAIL: isize = -1; + +// NOTE this must be accessed in unsafe mode. +// But it is just written to once at start-up, so actually safe. + +// Best not to use precomp if stack memory limited - i.e. embedded use +// Uncomment to use precomp +// static mut G2_TAB: [FP4; ecp::G2_TABLE] = [FP4::new(); ecp::G2_TABLE]; + +fn ceil(a: usize,b: usize) -> usize { + (a-1)/b+1 +} + +/* output u \in F_p */ +fn hash_to_field(hash: usize,hlen: usize ,u: &mut [FP], dst: &[u8],m: &[u8],ctr: usize) { + let q = BIG::new_ints(&rom::MODULUS); + let nbq=q.nbits(); + let el = ceil(nbq+ecp::AESKEY*8,8); + + let mut okm: [u8;256]=[0;256]; + let mut fd: [u8;128]=[0;128]; + + hmac::xmd_expand(hash,hlen,&mut okm,el*ctr,&dst,&m); + for i in 0..ctr { + for j in 0..el { + fd[j]=okm[el*i+j]; + } + u[i]=FP::new_big(&DBIG::frombytes(&fd[0 .. el]).ctdmod(&q,8*el-nbq)); + } +} + +/* hash a message to an ECP point, using SHA2, random oracle method */ +#[allow(non_snake_case)] +pub fn bls_hash_to_point(m: &[u8]) -> ECP { + let dst= "BLS_SIG_BN254G1_XMD:SHA-256_SVDW_RO_NUL_"; + + let mut u: [FP; 2] = [ + FP::new(), + FP::new(), + ]; + hash_to_field(hmac::MC_SHA2,ecp::HASH_TYPE,&mut u,dst.as_bytes(),m,2); + + let mut P=ECP::map2point(&u[0]); + let P1=ECP::map2point(&u[1]); + + P.add(&P1); + P.cfp(); + P.affine(); + P +} + +pub fn init() -> isize { +// Uncomment to use precomp +// let g = ECP2::generator(); +// if g.is_infinity() { +// return BLS_FAIL; +// } +// unsafe { +// pair::precomp(&mut G2_TAB, &g); +// } + BLS_OK +} + +/* generate key pair, private key s, public key w */ +pub fn key_pair_generate(ikm: &[u8], s: &mut [u8], w: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let nbr=r.nbits(); + let el = ceil(3*ceil(nbr,8),2); + let g = ECP2::generator(); + let mut len: [u8; 2] = [0; 2]; + hmac::inttobytes(el,&mut len); + + let salt="BLS-SIG-KEYGEN-SALT-"; + + let mut prk: [u8;64]=[0;64]; + let mut okm: [u8;128]=[0;128]; + let mut aikm: [u8;65]=[0;65]; + let likm=ikm.len(); + for i in 0..likm { + aikm[i]=ikm[i]; + } + aikm[likm]=0; + + let hlen=ecp::HASH_TYPE; + + hmac::hkdf_extract(hmac::MC_SHA2,hlen,&mut prk,Some(&salt.as_bytes()),&aikm[0 .. likm+1]); + hmac::hkdf_expand(hmac::MC_SHA2,hlen,&mut okm,el,&prk[0 .. hlen],&len); + + let mut dx = DBIG::frombytes(&okm[0 .. el]); + let sc = dx.ctdmod(&r,8*el-nbr); + sc.tobytes(s); +// SkToPk + pair::g2mul(&g, &sc).tobytes(w,true); // true for public key compression + BLS_OK +} + +/* Sign message m using private key s to produce signature sig */ + +pub fn core_sign(sig: &mut [u8], m: &[u8], s: &[u8]) -> isize { + let d = bls_hash_to_point(m); + let sc = BIG::frombytes(&s); + pair::g1mul(&d, &sc).tobytes(sig, true); + BLS_OK +} + +/* Verify signature given message m, the signature sig, and the public key w */ + +pub fn core_verify(sig: &[u8], m: &[u8], w: &[u8]) -> isize { + let hm = bls_hash_to_point(m); + let mut d = ECP::frombytes(&sig); + + if !pair::g1member(&d) { + return BLS_FAIL; + } + d.neg(); + + let pk = ECP2::frombytes(&w); + if !pair::g2member(&pk) { + return BLS_FAIL; + } + +// Uncomment to use precomp + // Use new multi-pairing mechanism + //let mut r = pair::initmp(); + // pair::another(&mut r,&g,&d); + + //unsafe { + // pair::another_pc(&mut r, &G2_TAB, &d); + //} + //pair::another(&mut r, &pk, &hm); + //let mut v = pair::miller(&mut r); + + //.. or else do not use precomp! + let g = ECP2::generator(); + let mut v = pair::ate2(&g, &d, &pk, &hm); + + v = pair::fexp(&v); + if v.isunity() { + return BLS_OK; + } + BLS_FAIL +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs new file mode 100644 index 000000000000..5f2de894baed --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::arch; +use crate::arch::Chunk; +use crate::bn254::big; +use crate::bn254::big::BIG; + +pub struct DBIG { + pub w: [Chunk; big::DNLEN], +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for DBIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for DBIG { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl DBIG { + pub fn new() -> DBIG { + DBIG { + w: [0; big::DNLEN as usize], + } + } + + pub fn new_copy(y: &DBIG) -> DBIG { + let mut s = DBIG::new(); + for i in 0..big::DNLEN { + s.w[i] = y.w[i] + } + s + } + + pub fn new_scopy(x: &BIG) -> DBIG { + let mut b = DBIG::new(); + for i in 0..big::NLEN { + b.w[i] = x.w[i]; + } + b.w[big::NLEN - 1] = x.get(big::NLEN - 1) & big::BMASK; /* top word normalized */ + b.w[big::NLEN] = x.get(big::NLEN - 1) >> big::BASEBITS; + + for i in big::NLEN + 1..big::DNLEN { + b.w[i] = 0 + } + b + } + + /* split DBIG at position n, return higher half, keep lower half */ + pub fn split(&mut self, n: usize) -> BIG { + let mut t = BIG::new(); + let m = n % big::BASEBITS; + let mut carry = self.w[big::DNLEN - 1] << (big::BASEBITS - m); + + for i in (big::NLEN - 1..big::DNLEN - 1).rev() { + let nw = (self.w[i] >> m) | carry; + carry = (self.w[i] << (big::BASEBITS - m)) & big::BMASK; + t.set(i + 1 - big::NLEN, nw); + } + self.w[big::NLEN - 1] &= ((1 as Chunk) << m) - 1; + t + } + + /* general shift left */ + pub fn shl(&mut self, k: usize) { + let n = k % big::BASEBITS; + let m = k / big::BASEBITS; + self.w[big::DNLEN - 1] = + (self.w[big::DNLEN - 1 - m] << n) | (self.w[big::DNLEN - m - 2] >> (big::BASEBITS - n)); + for i in (m + 1..big::DNLEN - 1).rev() { + self.w[i] = + ((self.w[i - m] << n) & big::BMASK) | (self.w[i - m - 1] >> (big::BASEBITS - n)); + } + + self.w[m] = (self.w[0] << n) & big::BMASK; + for i in 0..m { + self.w[i] = 0 + } + } + + /* general shift right */ + pub fn shr(&mut self, k: usize) { + let n = k % big::BASEBITS; + let m = k / big::BASEBITS; + for i in 0..big::DNLEN - m - 1 { + self.w[i] = + (self.w[m + i] >> n) | ((self.w[m + i + 1] << (big::BASEBITS - n)) & big::BMASK); + } + self.w[big::DNLEN - m - 1] = self.w[big::DNLEN - 1] >> n; + for i in big::DNLEN - m..big::DNLEN { + self.w[i] = 0 + } + } + + /* Copy from another DBIG */ + pub fn copy(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] = x.w[i]; + } + } + + pub fn ucopy(&mut self, x: &BIG) { + for i in 0..big::NLEN { + self.w[i] = 0; + } + for i in big::NLEN..big::DNLEN { + self.w[i] = x.w[i - big::NLEN]; + } + } + + pub fn cmove(&mut self, g: &DBIG, d: isize) -> Chunk { + let b = -d as Chunk; + let mut w=0 as Chunk; + let r=self.w[0]^g.w[1]; + let mut ra=r.wrapping_add(r); ra >>= 1; + for i in 0..big::DNLEN { + let mut t = b & (self.w[i] ^ g.w[i]); + t^=r; + let e=self.w[i]^t; w^=e; + self.w[i]=e^ra; + } + return w; + } + + /* self+=x */ + pub fn add(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] += x.w[i]; + } + } + + /* self-=x */ + pub fn sub(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] -= x.w[i]; + } + } + + /* self=x-self */ + pub fn rsub(&mut self, x: &DBIG) { + for i in 0..big::DNLEN { + self.w[i] = x.w[i] - self.w[i]; + } + } + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + pub fn comp(a: &DBIG, b: &DBIG) -> isize { + let mut gt = 0 as Chunk; + let mut eq = 1 as Chunk; + for i in (0..big::DNLEN).rev() { + gt |= ((b.w[i]-a.w[i]) >> big::BASEBITS) & eq; + eq &= ((b.w[i]^a.w[i])-1) >> big::BASEBITS; + } + (gt+gt+eq-1) as isize + } + + /* convert from byte array to BIG */ + pub fn frombytes(b: &[u8]) -> DBIG { + let mut m = DBIG::new(); + for i in 0..(b.len()) { + m.shl(8); + m.w[0] += b[i] as Chunk; + } + m + } + + /* normalise BIG - force all digits < 2^big::BASEBITS */ + pub fn norm(&mut self) { + let mut carry = self.w[0]>>big::BASEBITS; + self.w[0] &= big::BMASK; + for i in 1..big::DNLEN - 1 { + let d = self.w[i] + carry; + self.w[i] = d & big::BMASK; + carry = d >> big::BASEBITS; + } + self.w[big::DNLEN - 1] += carry + } + +// Set self=self mod m in constant time (if bd is known at compile time) +// bd is Max number of bits in b - Actual number of bits in m + pub fn ctdmod(&mut self, m: &BIG, bd: usize) -> BIG { + let mut k=bd; + self.norm(); + let mut c = DBIG::new_scopy(m); + let mut dr = DBIG::new(); + + c.shl(k); + + loop { + dr.copy(self); + dr.sub(&c); + dr.norm(); + self.cmove(&dr,(1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); + if k==0 {break;} + c.shr(1); + k -= 1; + } + BIG::new_dcopy(self) + } + + /* reduces self DBIG mod a BIG, and returns the BIG */ + pub fn dmod(&mut self, m: &BIG) -> BIG { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss BIG { + let mut k=bd; + let mut c = DBIG::new_scopy(m); + let mut a = BIG::new(); + let mut e = BIG::new_int(1); + let mut dr = DBIG::new(); + let mut r = BIG::new(); + self.norm(); + + c.shl(k); + e.shl(k); + + loop { + dr.copy(self); + dr.sub(&c); + dr.norm(); + let d = (1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize; + self.cmove(&dr, d); + r.copy(&a); + r.add(&e); + r.norm(); + a.cmove(&r, d); + if k==0 {break;} + k -= 1; + c.shr(1); + e.shr(1); + } + a + } + + /* return this/c */ + pub fn div(&mut self, m: &BIG) -> BIG { + let ss=self.nbits() as isize; + let ms=m.nbits() as isize; + let mut k=(ss-ms) as usize; + if ss usize { + let mut k = big::DNLEN - 1; + let mut s = DBIG::new_copy(&self); + s.norm(); + while (k as isize) >= 0 && s.w[k] == 0 { + k = k.wrapping_sub(1) + } + if (k as isize) < 0 { + return 0; + } + let mut bts = (big::BASEBITS as usize) * k; + let mut c = s.w[k]; + while c != 0 { + c /= 2; + bts += 1; + } + bts + } + + /* Convert to Hex String */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut s = String::new(); + let mut len = self.nbits(); + + if len % 4 == 0 { + len /= 4; + } else { + len /= 4; + len += 1; + } + + for i in (0..len).rev() { + let mut b = DBIG::new_copy(&self); + b.shr(i * 4); + s = s + &format!("{:X}", b.w[0] & 15); + } + s + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs new file mode 100644 index 000000000000..96ceadf4f311 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ECDH/ECIES/ECDSA API Functions */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::rom; + +use crate::aes; +use crate::hmac; +use crate::rand::RAND; + +pub const INVALID_PUBLIC_KEY: isize = -2; +pub const ERROR: isize = -3; +//pub const INVALID: isize = -4; +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; + +pub fn rfc7748(r: &mut BIG) { + let mut lg=0; + let mut t=BIG::new_int(1); + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let n=(8*EGS-lg+1) as usize; + r.mod2m(n); + t.shl(n); + r.add(&t); + c=r.lastbits(lg as usize); + r.dec(c); +} + +#[allow(non_snake_case)] +pub fn in_range(s: &[u8]) -> bool { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sc = BIG::frombytes(&s); + if sc.iszilch() { + return false; + } + if BIG::comp(&sc, &r) >= 0 { + return false; + } + true +} + +/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), + * where s is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in s + * otherwise it is generated randomly internally */ +#[allow(non_snake_case)] +pub fn key_pair_generate(rng: Option<&mut RAND>, s: &mut [u8], w: &mut [u8]) -> isize { + let res = 0; + let mut sc: BIG; + let G = ECP::generator(); + let r = BIG::new_ints(&rom::CURVE_ORDER); + + if let Some(x) = rng { + if ecp::CURVETYPE != ecp::WEIERSTRASS { + sc = BIG::random(x); // from random bytes + } else { + sc = BIG::randomnum(&r, x); // Removes biases + } + } else { + sc = BIG::frombytes(&s); + } + + if ecp::CURVETYPE != ecp::WEIERSTRASS { + rfc7748(&mut sc); // For Montgomery or Edwards, apply RFC7748 transformation + } + sc.tobytes(s); + let WP = G.clmul(&sc,&r); + WP.tobytes(w, false); // To use point compression on public keys, change to true + + res +} + +/* validate public key */ +#[allow(non_snake_case)] +pub fn public_key_validate(w: &[u8]) -> isize { + let mut WP = ECP::frombytes(w); + let mut res = 0; + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + if WP.is_infinity() { + res = INVALID_PUBLIC_KEY + } + if res == 0 { + let q = BIG::new_ints(&rom::MODULUS); + let nb = q.nbits(); + let mut k = BIG::new(); + k.one(); + k.shl((nb + 4) / 2); + k.add(&q); + k.div(&r); + + while k.parity() == 0 { + k.shr(1); + WP.dbl(); + } + + if !k.isunity() { + WP = WP.mul(&mut k) + } + if WP.is_infinity() { + res = INVALID_PUBLIC_KEY + } + } + res +} + +/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ +#[allow(non_snake_case)] +pub fn ecpsvdp_dh(s: &[u8], wd: &[u8], z: &mut [u8], typ: isize) -> isize { + let mut res = 0; + + let sc = BIG::frombytes(&s); + + let mut W = ECP::frombytes(&wd); + if W.is_infinity() { + res = ERROR + } + + if res == 0 { + let r = BIG::new_ints(&rom::CURVE_ORDER); + W = W.clmul(&sc,&r); + if W.is_infinity() { + res = ERROR; + } else { + if ecp::CURVETYPE != ecp::MONTGOMERY { + if typ>0 { + if typ==1 { + W.tobytes(z,true); + } else { + W.tobytes(z,false); + } + } else { + W.getx().tobytes(z); + } + return res; + } else { + W.getx().tobytes(z); + } + } + } + res +} + +/* IEEE ECDSA Signature, C and D are signature on F using private key S */ +#[allow(non_snake_case)] +pub fn ecpsp_dsa( + sha: usize, + rng: &mut RAND, + s: &[u8], + f: &[u8], + c: &mut [u8], + d: &mut [u8], +) -> isize { + let mut t: [u8; EGS] = [0; EGS]; + let mut b: [u8; EGS] = [0; EGS]; + + hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS,0,Some(f), -1, None); + + let G = ECP::generator(); + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + let sc = BIG::frombytes(s); /* s or &s? */ + let fb = BIG::frombytes(&b); + + let mut cb = BIG::new(); + let mut db = BIG::new(); + let mut tb = BIG::new(); + let mut V = ECP::new(); + + while db.iszilch() { + let mut u = BIG::randomnum(&r, rng); + let w = BIG::randomnum(&r, rng); /* IMPORTANT - side channel masking to protect invmodp() */ + + V.copy(&G); + V = V.clmul(&u,&r); + let vx = V.getx(); + cb.copy(&vx); + cb.rmod(&r); + if cb.iszilch() { + continue; + } + + tb.copy(&BIG::modmul(&u, &w, &r)); + u.copy(&tb); + + u.invmodp(&r); + db.copy(&BIG::modmul(&sc, &cb, &r)); + db.copy(&BIG::modadd(&db, &fb, &r)); + tb.copy(&BIG::modmul(&db, &w, &r)); + db.copy(&tb); + + tb.copy(&BIG::modmul(&u, &db, &r)); + db.copy(&tb); + } + + cb.tobytes(&mut t); + for i in 0..EGS { + c[i] = t[i] + } + db.tobytes(&mut t); + for i in 0..EGS { + d[i] = t[i] + } + 0 +} + +/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ +#[allow(non_snake_case)] +pub fn ecpvp_dsa(sha: usize, w: &[u8], f: &[u8], c: &[u8], d: &[u8]) -> isize { + let mut res = 0; + + let mut b: [u8; EGS] = [0; EGS]; + + hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS, 0,Some(f), -1, None); + + let mut G = ECP::generator(); + + let r = BIG::new_ints(&rom::CURVE_ORDER); + + let mut cb = BIG::frombytes(c); /* c or &c ? */ + let mut db = BIG::frombytes(d); /* d or &d ? */ + let mut fb = BIG::frombytes(&b); + let mut tb = BIG::new(); + + if cb.iszilch() || BIG::comp(&cb, &r) >= 0 || db.iszilch() || BIG::comp(&db, &r) >= 0 { + res = ERROR; + } + + if res == 0 { + db.invmodp(&r); + tb.copy(&BIG::modmul(&mut fb, &mut db, &r)); + fb.copy(&tb); + let h2 = BIG::modmul(&mut cb, &mut db, &r); + + let WP = ECP::frombytes(&w); + if WP.is_infinity() { + res = ERROR; + } else { + let mut P = ECP::new(); + P.copy(&WP); + + P = P.mul2(&h2, &mut G, &fb); + + if P.is_infinity() { + res = ERROR; + } else { + db = P.getx(); + db.rmod(&r); + + if BIG::comp(&db, &cb) != 0 { + res = ERROR + } + } + } + } + + res +} + +/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ +// returns length of ciphertext +#[allow(non_snake_case)] +pub fn ecies_encrypt( + sha: usize, + p1: &[u8], + p2: &[u8], + rng: &mut RAND, + w: &[u8], + m: &[u8], + v: &mut [u8], + c: &mut [u8], + t: &mut [u8], +) -> usize { + let mut z: [u8; EFS] = [0; EFS]; + let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut u: [u8; EGS] = [0; EGS]; + let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; + let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; + + if key_pair_generate(Some(rng), &mut u, v) != 0 { + return 0; + } + if ecpsvdp_dh(&u, &w, &mut z, 0) != 0 { + return 0; + } + + for i in 0..2 * EFS + 1 { + vz[i] = v[i] + } + for i in 0..EFS { + vz[2 * EFS + 1 + i] = z[i] + } + + hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); + + for i in 0..ecp::AESKEY { + k1[i] = k[i]; + k2[i] = k[ecp::AESKEY + i] + } + + let clen = aes::cbc_iv0_encrypt(&k1, m, c); + + let mut l2: [u8; 8] = [0; 8]; + let p2l = p2.len(); + + hmac::inttobytes(p2l, &mut l2); + + let mut opt=clen; + for i in 0..p2l { + c[opt]=p2[i]; opt+=1; + } + for i in 0..8 { + c[opt]=l2[i]; opt+=1; + } + + hmac::hmac1(hmac::MC_SHA2, sha, t, t.len(), &k2, &c[0..opt]); + + clen +} + +/* constant time n-byte compare */ +fn ncomp(t1: &[u8], t2: &[u8], n: usize) -> bool { + let mut res = 0; + for i in 0..n { + res |= (t1[i] ^ t2[i]) as isize; + } + if res == 0 { + return true; + } + false +} + +/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ +// returns length of plaintext +#[allow(non_snake_case)] +pub fn ecies_decrypt( + sha: usize, + p1: &[u8], + p2: &[u8], + v: &[u8], + c: &mut [u8], + clen: usize, + t: &[u8], + u: &[u8], + m: &mut [u8], +) -> usize { + let mut z: [u8; EFS] = [0; EFS]; + let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; + let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; + let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; + let mut tag: [u8; 32] = [0; 32]; /* 32 is max length of tag */ + + for i in 0..t.len() { + tag[i] = t[i] + } + + if ecpsvdp_dh(&u, &v, &mut z, 0) != 0 { + return 0; + } + + for i in 0..2 * EFS + 1 { + vz[i] = v[i] + } + for i in 0..EFS { + vz[2 * EFS + 1 + i] = z[i] + } + + hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); + + for i in 0..ecp::AESKEY { + k1[i] = k[i]; + k2[i] = k[ecp::AESKEY + i] + } + + let mlen = aes::cbc_iv0_decrypt(&k1, &c[0..clen], m); + + if mlen == 0 { + return 0; + } + + let mut l2: [u8; 8] = [0; 8]; + let p2l = p2.len(); + + hmac::inttobytes(p2l, &mut l2); + let mut opt=clen; + + for i in 0..p2l { + c[opt]=p2[i]; opt+=1; + } + for i in 0..8 { + c[opt]=l2[i]; opt+=1; + } + + let tl=tag.len(); + hmac::hmac1(hmac::MC_SHA2, sha, &mut tag, tl, &k2, &c[0..opt]); + + if !ncomp(&t, &tag, t.len()) { + return 0; + } + + mlen +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs new file mode 100644 index 000000000000..23a6b7adf915 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs @@ -0,0 +1,1824 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::fp::FP; +use crate::bn254::fp; +use crate::bn254::rom; + +#[derive(Clone)] +pub struct ECP { + x: FP, + y: FP, + z: FP, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for ECP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for ECP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +pub const WEIERSTRASS: usize = 0; +pub const EDWARDS: usize = 1; +pub const MONTGOMERY: usize = 2; +pub const NOT: usize = 0; +pub const BN: usize = 1; +pub const BLS12: usize = 2; +pub const BLS24: usize = 3; +pub const BLS48: usize = 4; +pub const D_TYPE: usize = 0; +pub const M_TYPE: usize = 1; +pub const POSITIVEX: usize = 0; +pub const NEGATIVEX: usize = 1; + +pub const CURVETYPE:usize=WEIERSTRASS; +pub const CURVE_A:isize=0; +pub const CURVE_PAIRING_TYPE:usize=BN; +pub const SEXTIC_TWIST:usize=D_TYPE; +pub const SIGN_OF_X:usize=NEGATIVEX; +pub const ATE_BITS:usize=66; +pub const G2_TABLE:usize=71; +pub const HTC_ISO:usize=0; +pub const HTC_ISO_G2:usize=0; + +pub const ALLOW_ALT_COMPRESS:bool=false; +pub const HASH_TYPE:usize=32; +pub const AESKEY:usize=16; + +#[allow(non_snake_case)] +impl ECP { + pub fn pnew() -> ECP { + ECP { + x: FP::new(), + y: FP::new_int(1), + z: FP::new(), + } + } + + pub fn new() -> ECP { + let mut E = ECP::pnew(); + if CURVETYPE == EDWARDS { + E.z.one(); + } + E + } + + /* set (x,y) from two BIGs */ + pub fn new_bigs(ix: &BIG, iy: &BIG) -> ECP { + let mut E = ECP::new(); + E.x.bcopy(ix); + E.y.bcopy(iy); + E.z.one(); + E.x.norm(); + let rhs = ECP::rhs(&E.x); + if CURVETYPE == MONTGOMERY { + if rhs.qr(None) != 1 { + E.inf(); + } + } else { + let mut y2 = FP::new_copy(&E.y); + y2.sqr(); + if !y2.equals(&rhs) { + E.inf(); + } + } + E + } + + /* set (x,y) from BIG and a bit */ + pub fn new_bigint(ix: &BIG, s: isize) -> ECP { + let mut E = ECP::new(); + let mut hint = FP::new(); + E.x.bcopy(ix); + E.x.norm(); + E.z.one(); + + let rhs = ECP::rhs(&E.x); + + if rhs.qr(Some(&mut hint)) == 1 { + let mut ny = rhs.sqrt(Some(&hint)); + if ny.sign() != s { + ny.neg(); ny.norm() + } + E.y.copy(&ny); + } else { + E.inf() + } + E + } + + #[allow(non_snake_case)] + /* set from x - calculate y from curve equation */ + pub fn new_big(ix: &BIG) -> ECP { + let mut E = ECP::new(); + let mut hint = FP::new(); + E.x.bcopy(ix); + E.x.norm(); + E.z.one(); + let rhs = ECP::rhs(&E.x); + if rhs.qr(Some(&mut hint)) == 1 { + if CURVETYPE != MONTGOMERY { + E.y.copy(&rhs.sqrt(Some(&hint))) + } + } else { + E.inf(); + } + E + } + + /* set this=O */ + pub fn inf(&mut self) { + self.x.zero(); + if CURVETYPE != MONTGOMERY { + self.y.one(); + } + if CURVETYPE != EDWARDS { + self.z.zero(); + } else { + self.z.one() + } + } + + /* Calculate RHS of curve equation */ + fn rhs(x: &FP) -> FP { + let mut r = FP::new_copy(x); + r.sqr(); + + if CURVETYPE == WEIERSTRASS { + // x^3+Ax+B + let b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + r.mul(x); + if CURVE_A == -3 { + let mut cx = FP::new_copy(x); + cx.imul(3); + cx.neg(); + cx.norm(); + r.add(&cx); + } + r.add(&b); + } + if CURVETYPE == EDWARDS { + // (Ax^2-1)/(Bx^2-1) + let mut b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let one = FP::new_int(1); + b.mul(&r); + b.sub(&one); + b.norm(); + if CURVE_A == -1 { + r.neg() + } + r.sub(&one); + r.norm(); + b.inverse(None); + r.mul(&b); + } + if CURVETYPE == MONTGOMERY { + // x^3+Ax^2+x + let mut x3 = FP::new(); + x3.copy(&r); + x3.mul(x); + r.imul(CURVE_A); + r.add(&x3); + r.add(&x); + } + r.reduce(); + r + } + + /* test for O point-at-infinity */ + pub fn is_infinity(&self) -> bool { + if CURVETYPE == EDWARDS { + return self.x.iszilch() && self.y.equals(&self.z); + } + if CURVETYPE == WEIERSTRASS { + return self.x.iszilch() && self.z.iszilch(); + } + if CURVETYPE == MONTGOMERY { + return self.z.iszilch(); + } + true + } + + /* Conditional swap of P and Q dependant on d */ + pub fn cswap(&mut self, Q: &mut ECP, d: isize) { + self.x.cswap(&mut Q.x, d); + if CURVETYPE != MONTGOMERY { + self.y.cswap(&mut Q.y, d) + } + self.z.cswap(&mut Q.z, d); + } + + /* Conditional move of Q to P dependant on d */ + pub fn cmove(&mut self, Q: &ECP, d: isize) { + self.x.cmove(&Q.x, d); + if CURVETYPE != MONTGOMERY { + self.y.cmove(&Q.y, d) + } + self.z.cmove(&Q.z, d); + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* this=P */ + pub fn copy(&mut self, P: &ECP) { + self.x.copy(&P.x); + if CURVETYPE != MONTGOMERY { + self.y.copy(&P.y) + } + self.z.copy(&P.z); + } + + /* this=-this */ + pub fn neg(&mut self) { + if CURVETYPE == WEIERSTRASS { + self.y.neg(); + self.y.norm(); + } + if CURVETYPE == EDWARDS { + self.x.neg(); + self.x.norm(); + } + } + /* multiply x coordinate */ + pub fn mulx(&mut self, c: &mut FP) { + self.x.mul(c); + } + + /* Constant time select from pre-computed table */ + fn selector(&mut self, W: &[ECP], b: i32) { + // unsure about &[& syntax. An array of pointers I hope.. + let mut MP = ECP::new(); + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&W[0], ECP::teq(babs, 0)); // conditional move + self.cmove(&W[1], ECP::teq(babs, 1)); + self.cmove(&W[2], ECP::teq(babs, 2)); + self.cmove(&W[3], ECP::teq(babs, 3)); + self.cmove(&W[4], ECP::teq(babs, 4)); + self.cmove(&W[5], ECP::teq(babs, 5)); + self.cmove(&W[6], ECP::teq(babs, 6)); + self.cmove(&W[7], ECP::teq(babs, 7)); + + MP.copy(self); + MP.neg(); + self.cmove(&MP, (m & 1) as isize); + } + + /* Test P == Q */ + pub fn equals(&self, Q: &ECP) -> bool { + let mut a = FP::new(); + let mut b = FP::new(); + a.copy(&self.x); + a.mul(&Q.z); + b.copy(&Q.x); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + if CURVETYPE != MONTGOMERY { + a.copy(&self.y); + a.mul(&Q.z); + b.copy(&Q.y); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + } + true + } + + /* set to affine - from (x,y,z) to (x,y) */ + pub fn affine(&mut self) { + if self.is_infinity() { + return; + } + let one = FP::new_int(1); + if self.z.equals(&one) { + return; + } + self.z.inverse(None); + + self.x.mul(&self.z); + self.x.reduce(); + if CURVETYPE != MONTGOMERY { + self.y.mul(&self.z); + self.y.reduce(); + } + self.z.copy(&one); + } + + /* extract x as a BIG */ + pub fn getx(&self) -> BIG { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.x.redc() + } + + /* extract y as a BIG */ + pub fn gety(&self) -> BIG { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.y.redc() + } + + /* get sign of Y */ + pub fn gets(&self) -> isize { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.y.sign() + } + + /* extract x as an FP */ + pub fn getpx(&self) -> FP { + FP::new_copy(&self.x) + } + /* extract y as an FP */ + pub fn getpy(&self) -> FP { + FP::new_copy(&self.y) + } + + /* extract z as an FP */ + pub fn getpz(&self) -> FP { + FP::new_copy(&self.z) + } + + /* convert to byte array */ + pub fn tobytes(&self, b: &mut [u8], compress: bool) { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let mut W = ECP::new(); + W.copy(self); + W.affine(); + W.x.redc().tobytes(&mut t); + + if CURVETYPE == MONTGOMERY { + for i in 0..MB { + b[i] = t[i] + } + return; + } + + if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + b[i]=t[i]; + } + if compress { + b[0]|=0x80; + if W.y.islarger()==1 { + b[0]|=0x20; + } + } else { + W.y.redc().tobytes(&mut t); + for i in 0..MB { + b[i+MB]=t[i]; + } + } + } else { + for i in 0..MB { + b[i + 1] = t[i]; + } + if compress { + b[0] = 0x02; + if W.y.sign() == 1 { + b[0] = 0x03; + } + return; + } + b[0] = 0x04; + W.y.redc().tobytes(&mut t); + for i in 0..MB { + b[i + MB + 1] = t[i]; + } + } + } + + /* convert from byte array to point */ + pub fn frombytes(b: &[u8]) -> ECP { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let p = BIG::new_ints(&rom::MODULUS); + + if CURVETYPE == MONTGOMERY { + for i in 0..MB { + t[i] = b[i]; + } + let px = BIG::frombytes(&t); + if BIG::comp(&px, &p) >= 0 { + return ECP::new(); + } + return ECP::new_big(&px); + } + + if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + t[i]=b[i]; + } + t[0]&=0x1f; + let px=BIG::frombytes(&t); + if (b[0]&0x80)==0 { + for i in 0 ..MB { + t[i]=b[i+MB]; + } + let py=BIG::frombytes(&t); + return ECP::new_bigs(&px, &py); + } else { + let sgn=(b[0]&0x20)>>5; + let mut P=ECP::new_bigint(&px,0); + let cmp=P.y.islarger(); + if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { + P.neg(); + } + return P; + } + } else { + for i in 0..MB { + t[i] = b[i + 1]; + } + let px = BIG::frombytes(&t); + if BIG::comp(&px, &p) >= 0 { + return ECP::new(); + } + if b[0] == 0x04 { + for i in 0..MB { + t[i] = b[i + MB + 1]; + } + let py = BIG::frombytes(&t); + if BIG::comp(&py, &p) >= 0 { + return ECP::new(); + } + return ECP::new_bigs(&px, &py); + } + if b[0] == 0x02 || b[0] == 0x03 { + return ECP::new_bigint(&px, (b[0] & 1) as isize); + } + } + + ECP::new() + } + + /* convert to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut W = ECP::new(); + W.copy(self); + W.affine(); + if W.is_infinity() { + return String::from("infinity"); + } + if CURVETYPE == MONTGOMERY { + return format!("({})", W.x.redc().tostring()); + } else { + return format!("({},{})", W.x.redc().tostring(), W.y.redc().tostring()); + }; + } + + /* this*=2 */ + pub fn dbl(&mut self) { + if CURVETYPE == WEIERSTRASS { + if CURVE_A == 0 { + let mut t0 = FP::new_copy(&self.y); + t0.sqr(); + let mut t1 = FP::new_copy(&self.y); + t1.mul(&self.z); + let mut t2 = FP::new_copy(&self.z); + t2.sqr(); + + self.z.copy(&t0); + self.z.add(&t0); + self.z.norm(); + self.z.dbl(); + self.z.dbl(); + self.z.norm(); + t2.imul(3 * rom::CURVE_B_I); + + let mut x3 = FP::new_copy(&t2); + x3.mul(&self.z); + + let mut y3 = FP::new_copy(&t0); + y3.add(&t2); + y3.norm(); + self.z.mul(&t1); + t1.copy(&t2); + t1.add(&t2); + t2.add(&t1); + t0.sub(&t2); + t0.norm(); + y3.mul(&t0); + y3.add(&x3); + t1.copy(&self.x); + t1.mul(&self.y); + self.x.copy(&t0); + self.x.norm(); + self.x.mul(&t1); + self.x.dbl(); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + } else { + let mut t0 = FP::new_copy(&self.x); + let mut t1 = FP::new_copy(&self.y); + let mut t2 = FP::new_copy(&self.z); + let mut t3 = FP::new_copy(&self.x); + let mut z3 = FP::new_copy(&self.z); + let mut y3 = FP::new(); + let mut x3 = FP::new(); + let mut b = FP::new(); + + if rom::CURVE_B_I == 0 { + b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + + t0.sqr(); //1 x^2 + t1.sqr(); //2 y^2 + t2.sqr(); //3 + + t3.mul(&self.y); //4 + t3.dbl(); + t3.norm(); //5 + z3.mul(&self.x); //6 + z3.dbl(); + z3.norm(); //7 + y3.copy(&t2); + + if rom::CURVE_B_I == 0 { + y3.mul(&b); //8 + } else { + y3.imul(rom::CURVE_B_I); + } + + y3.sub(&z3); //9 *** + x3.copy(&y3); + x3.add(&y3); + x3.norm(); //10 + + y3.add(&x3); //11 + x3.copy(&t1); + x3.sub(&y3); + x3.norm(); //12 + y3.add(&t1); + y3.norm(); //13 + y3.mul(&x3); //14 + x3.mul(&t3); //15 + t3.copy(&t2); + t3.add(&t2); //16 + t2.add(&t3); //17 + + if rom::CURVE_B_I == 0 { + z3.mul(&b); //18 + } else { + z3.imul(rom::CURVE_B_I); + } + + z3.sub(&t2); //19 + z3.sub(&t0); + z3.norm(); //20 *** + t3.copy(&z3); + t3.add(&z3); //21 + + z3.add(&t3); + z3.norm(); //22 + t3.copy(&t0); + t3.add(&t0); //23 + t0.add(&t3); //24 + t0.sub(&t2); + t0.norm(); //25 + + t0.mul(&z3); //26 + y3.add(&t0); //27 + t0.copy(&self.y); + t0.mul(&self.z); //28 + t0.dbl(); + t0.norm(); //29 + z3.mul(&t0); //30 + x3.sub(&z3); //31 + t0.dbl(); + t0.norm(); //32 + t1.dbl(); + t1.norm(); //33 + z3.copy(&t0); + z3.mul(&t1); //34 + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } + } + if CURVETYPE == EDWARDS { + let mut c = FP::new_copy(&self.x); + let mut d = FP::new_copy(&self.y); + let mut h = FP::new_copy(&self.z); + let mut j = FP::new(); + + self.x.mul(&self.y); + self.x.dbl(); + self.x.norm(); + c.sqr(); + d.sqr(); + if CURVE_A == -1 { + c.neg() + } + self.y.copy(&c); + self.y.add(&d); + self.y.norm(); + h.sqr(); + h.dbl(); + self.z.copy(&self.y); + j.copy(&self.y); + j.sub(&h); + j.norm(); + self.x.mul(&j); + c.sub(&d); + c.norm(); + self.y.mul(&c); + self.z.mul(&j); + } + if CURVETYPE == MONTGOMERY { + let mut a = FP::new_copy(&self.x); + let mut b = FP::new_copy(&self.x); + let mut aa = FP::new(); + let mut bb = FP::new(); + let mut c = FP::new(); + + a.add(&self.z); + a.norm(); + aa.copy(&a); + aa.sqr(); + b.sub(&self.z); + b.norm(); + bb.copy(&b); + bb.sqr(); + c.copy(&aa); + c.sub(&bb); + c.norm(); + + self.x.copy(&aa); + self.x.mul(&bb); + + a.copy(&c); + a.imul((CURVE_A + 2) / 4); + + bb.add(&a); + bb.norm(); + self.z.copy(&bb); + self.z.mul(&c); + } + } + + /* self+=Q */ + pub fn add(&mut self, Q: &ECP) { + if CURVETYPE == WEIERSTRASS { + if CURVE_A == 0 { + let b = 3 * rom::CURVE_B_I; + let mut t0 = FP::new_copy(&self.x); + t0.mul(&Q.x); + let mut t1 = FP::new_copy(&self.y); + t1.mul(&Q.y); + let mut t2 = FP::new_copy(&self.z); + t2.mul(&Q.z); + let mut t3 = FP::new_copy(&self.x); + t3.add(&self.y); + t3.norm(); + let mut t4 = FP::new_copy(&Q.x); + t4.add(&Q.y); + t4.norm(); + t3.mul(&t4); + t4.copy(&t0); + t4.add(&t1); + + t3.sub(&t4); + t3.norm(); + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); + let mut x3 = FP::new_copy(&Q.y); + x3.add(&Q.z); + x3.norm(); + + t4.mul(&x3); + x3.copy(&t1); + x3.add(&t2); + + t4.sub(&x3); + t4.norm(); + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); + let mut y3 = FP::new_copy(&Q.x); + y3.add(&Q.z); + y3.norm(); + x3.mul(&y3); + y3.copy(&t0); + y3.add(&t2); + y3.rsub(&x3); + y3.norm(); + x3.copy(&t0); + x3.add(&t0); + t0.add(&x3); + t0.norm(); + t2.imul(b); + + let mut z3 = FP::new_copy(&t1); + z3.add(&t2); + z3.norm(); + t1.sub(&t2); + t1.norm(); + y3.imul(b); + + x3.copy(&y3); + x3.mul(&t4); + t2.copy(&t3); + t2.mul(&t1); + x3.rsub(&t2); + y3.mul(&t0); + t1.mul(&z3); + y3.add(&t1); + t0.mul(&t3); + z3.mul(&t4); + z3.add(&t0); + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } else { + let mut t0 = FP::new_copy(&self.x); + let mut t1 = FP::new_copy(&self.y); + let mut t2 = FP::new_copy(&self.z); + let mut t3 = FP::new_copy(&self.x); + let mut t4 = FP::new_copy(&Q.x); + let mut z3 = FP::new(); + let mut y3 = FP::new_copy(&Q.x); + let mut x3 = FP::new_copy(&Q.y); + let mut b = FP::new(); + + if rom::CURVE_B_I == 0 { + b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + + t0.mul(&Q.x); //1 + t1.mul(&Q.y); //2 + t2.mul(&Q.z); //3 + + t3.add(&self.y); + t3.norm(); //4 + t4.add(&Q.y); + t4.norm(); //5 + t3.mul(&t4); //6 + t4.copy(&t0); + t4.add(&t1); //7 + t3.sub(&t4); + t3.norm(); //8 + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); //9 + x3.add(&Q.z); + x3.norm(); //10 + t4.mul(&x3); //11 + x3.copy(&t1); + x3.add(&t2); //12 + + t4.sub(&x3); + t4.norm(); //13 + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); //14 + y3.add(&Q.z); + y3.norm(); //15 + + x3.mul(&y3); //16 + y3.copy(&t0); + y3.add(&t2); //17 + + y3.rsub(&x3); + y3.norm(); //18 + z3.copy(&t2); + + if rom::CURVE_B_I == 0 { + z3.mul(&b); //18 + } else { + z3.imul(rom::CURVE_B_I); + } + + x3.copy(&y3); + x3.sub(&z3); + x3.norm(); //20 + z3.copy(&x3); + z3.add(&x3); //21 + + x3.add(&z3); //22 + z3.copy(&t1); + z3.sub(&x3); + z3.norm(); //23 + x3.add(&t1); + x3.norm(); //24 + + if rom::CURVE_B_I == 0 { + y3.mul(&b); //18 + } else { + y3.imul(rom::CURVE_B_I); + } + + t1.copy(&t2); + t1.add(&t2); //t1.norm();//26 + t2.add(&t1); //27 + + y3.sub(&t2); //28 + + y3.sub(&t0); + y3.norm(); //29 + t1.copy(&y3); + t1.add(&y3); //30 + y3.add(&t1); + y3.norm(); //31 + + t1.copy(&t0); + t1.add(&t0); //32 + t0.add(&t1); //33 + t0.sub(&t2); + t0.norm(); //34 + t1.copy(&t4); + t1.mul(&y3); //35 + t2.copy(&t0); + t2.mul(&y3); //36 + y3.copy(&x3); + y3.mul(&z3); //37 + y3.add(&t2); //y3.norm();//38 + x3.mul(&t3); //39 + x3.sub(&t1); //40 + z3.mul(&t4); //41 + t1.copy(&t3); + t1.mul(&t0); //42 + z3.add(&t1); + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + } + } + if CURVETYPE == EDWARDS { + let bb = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let mut a = FP::new_copy(&self.z); + let mut b = FP::new(); + let mut c = FP::new_copy(&self.x); + let mut d = FP::new_copy(&self.y); + let mut e = FP::new(); + let mut f = FP::new(); + let mut g = FP::new(); + + a.mul(&Q.z); + b.copy(&a); + b.sqr(); + c.mul(&Q.x); + d.mul(&Q.y); + + e.copy(&c); + e.mul(&d); + e.mul(&bb); + f.copy(&b); + f.sub(&e); + g.copy(&b); + g.add(&e); + + if CURVE_A == 1 { + e.copy(&d); + e.sub(&c); + } + c.add(&d); + + b.copy(&self.x); + b.add(&self.y); + d.copy(&Q.x); + d.add(&Q.y); + b.norm(); + d.norm(); + b.mul(&d); + b.sub(&c); + b.norm(); + f.norm(); + b.mul(&f); + self.x.copy(&a); + self.x.mul(&b); + g.norm(); + if CURVE_A == 1 { + e.norm(); + c.copy(&e); + c.mul(&g); + } + if CURVE_A == -1 { + c.norm(); + c.mul(&g); + } + self.y.copy(&a); + self.y.mul(&c); + self.z.copy(&f); + self.z.mul(&g); + } + } + + /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ + pub fn dadd(&mut self, Q: &ECP, W: &ECP) { + let mut a = FP::new_copy(&self.x); + let mut b = FP::new_copy(&self.x); + let mut c = FP::new_copy(&Q.x); + let mut d = FP::new_copy(&Q.x); + let mut da = FP::new(); + let mut cb = FP::new(); + + a.add(&self.z); + b.sub(&self.z); + + c.add(&Q.z); + d.sub(&Q.z); + + a.norm(); + d.norm(); + + da.copy(&d); + da.mul(&a); + + c.norm(); + b.norm(); + + cb.copy(&c); + cb.mul(&b); + + a.copy(&da); + a.add(&cb); + a.norm(); + a.sqr(); + b.copy(&da); + b.sub(&cb); + b.norm(); + b.sqr(); + + self.x.copy(&a); + self.z.copy(&W.x); + self.z.mul(&b); + } + + /* self-=Q */ + pub fn sub(&mut self, Q: &ECP) { + let mut NQ = ECP::new(); + NQ.copy(Q); + NQ.neg(); + self.add(&NQ); + } + + /* constant time multiply by small integer of length bts - use ladder */ + pub fn pinmul(&self, e: i32, bts: i32) -> ECP { + if CURVETYPE == MONTGOMERY { + self.mul(&BIG::new_int(e as isize)) + } else { + let mut P = ECP::new(); + let mut R0 = ECP::new(); + let mut R1 = ECP::new(); + R1.copy(&self); + + for i in (0..bts).rev() { + let b = ((e >> i) & 1) as isize; + P.copy(&R1); + P.add(&R0); + R0.cswap(&mut R1, b); + R1.copy(&P); + R0.dbl(); + R0.cswap(&mut R1, b); + } + P.copy(&R0); + P + } + } + +// Point multiplication, multiplies a point P by a scalar e +// This code has no inherent awareness of the order of the curve, or the order of the point. +// The order of the curve will be h.r, where h is a cofactor, and r is a large prime +// Typically P will be of order r (but not always), and typically e will be less than r (but not always) +// A problem can arise if a secret e is a few bits less than r, as the leading zeros in e will leak via a timing attack +// The secret e may however be greater than r (see RFC7748 which combines elimination of a small cofactor h with the point multiplication, using an e>r) +// Our solution is to use as a multiplier an e, whose length in bits is that of the logical OR of e and r, hence allowing e>r while forcing inclusion of leading zeros if e ECP { + return self.clmul(e,e); + } + +// .. but this one does not (typically set maxe=r) +// Set P=e*P + pub fn clmul(&self, e: &BIG, maxe: &BIG) -> ECP { + if e.iszilch() || self.is_infinity() { + return ECP::new(); + } + let mut P = ECP::new(); + let mut cm = BIG::new_copy(e); cm.or(maxe); + let max=cm.nbits(); + + if CURVETYPE == MONTGOMERY { + /* use Ladder */ + let mut D = ECP::new(); + let mut R0 = ECP::new(); + R0.copy(&self); + let mut R1 = ECP::new(); + R1.copy(&self); + R1.dbl(); + D.copy(&self); D.affine(); + let nb = max; + + for i in (0..nb - 1).rev() { + let b = e.bit(i); + P.copy(&R1); + P.dadd(&R0, &D); + R0.cswap(&mut R1, b); + R1.copy(&P); + R0.dbl(); + R0.cswap(&mut R1, b); + } + P.copy(&R0) + } else { + // fixed size windows + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut Q = ECP::new(); + let mut C = ECP::new(); + + let mut W: [ECP; 8] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + Q.copy(&self); + Q.dbl(); + + W[0].copy(&self); + + for i in 1..8 { + C.copy(&W[i - 1]); + W[i].copy(&C); + W[i].add(&Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(&e); + let s = t.parity(); + t.inc(1); + t.norm(); + let ns = t.parity(); + mt.copy(&t); + mt.inc(1); + mt.norm(); + t.cmove(&mt, s); + Q.cmove(&self, ns); + C.copy(&Q); + + let nb = 1 + (max + 3) / 4; + + // convert exponent to signed 4-bit window + for i in 0..nb { + w[i] = (t.lastbits(5) - 16) as i8; + t.dec(w[i] as isize); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5) as i8; + + //P.copy(&W[((w[nb] as usize) - 1) / 2]); + + P.selector(&W, w[nb] as i32); + for i in (0..nb).rev() { + Q.selector(&W, w[i] as i32); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(&Q); + } + P.sub(&C); /* apply correction */ + } + P + } + +// Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i + pub fn muln(n: usize, X: &[ECP], e: &[BIG]) -> ECP { + let mut B: [ECP; 16] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut P = ECP::new(); + let mut S = ECP::new(); + let mut R = ECP::new(); + + mt.copy(&e[0]); mt.norm(); + for i in 1..n { // find biggest + t.copy(&e[i]); t.norm(); + let k=BIG::comp(&t,&mt); + mt.cmove(&t,(k+1)/2); + } + let nb=(mt.nbits()+3)/4; + for i in (0..nb).rev() { // Pippenger's algorithm + for j in 0..16 { + B[j].inf(); + } + for j in 0..n { + mt.copy(&e[j]); mt.norm(); + mt.shr((i*4) as usize); + let k=mt.lastbits(4) as usize; + B[k].add(&X[j]); + } + R.inf(); S.inf(); + for j in (1..16).rev() { + R.add(&B[j]); + S.add(&R); + } + for _ in 0..4 { + P.dbl(); + } + P.add(&S); + } + P + } + + /* Return e.this+f.Q */ + + pub fn mul2(&self, e: &BIG, Q: &ECP, f: &BIG) -> ECP { + let mut te = BIG::new(); + let mut tf = BIG::new(); + let mut mt = BIG::new(); + let mut S = ECP::new(); + let mut T = ECP::new(); + let mut C = ECP::new(); + + let mut W: [ECP; 8] = [ + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ECP::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 1) / 2; + let mut w: [i8; CT] = [0; CT]; + + te.copy(e); + tf.copy(f); + + // precompute table + + W[1].copy(&self); + W[1].sub(Q); + W[2].copy(&self); + W[2].add(Q); + S.copy(&Q); + S.dbl(); + C.copy(&W[1]); + W[0].copy(&C); + W[0].sub(&S); // copy to C is stupid Rust thing.. + C.copy(&W[2]); + W[3].copy(&C); + W[3].add(&S); + T.copy(&self); + T.dbl(); + C.copy(&W[1]); + W[5].copy(&C); + W[5].add(&T); + C.copy(&W[2]); + W[6].copy(&C); + W[6].add(&T); + C.copy(&W[5]); + W[4].copy(&C); + W[4].sub(&S); + C.copy(&W[6]); + W[7].copy(&C); + W[7].add(&S); + + // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction + + let mut s = te.parity(); + te.inc(1); + te.norm(); + let mut ns = te.parity(); + mt.copy(&te); + mt.inc(1); + mt.norm(); + te.cmove(&mt, s); + T.cmove(&self, ns); + C.copy(&T); + + s = tf.parity(); + tf.inc(1); + tf.norm(); + ns = tf.parity(); + mt.copy(&tf); + mt.inc(1); + mt.norm(); + tf.cmove(&mt, s); + S.cmove(&Q, ns); + C.add(&S); + + mt.copy(&te); + mt.add(&tf); + mt.norm(); + let nb = 1 + (mt.nbits() + 1) / 2; + + // convert exponent to signed 2-bit window + for i in 0..nb { + let a = te.lastbits(3) - 4; + te.dec(a); + te.norm(); + te.fshr(2); + let b = tf.lastbits(3) - 4; + tf.dec(b); + tf.norm(); + tf.fshr(2); + w[i] = (4 * a + b) as i8; + } + w[nb] = (4 * te.lastbits(3) + tf.lastbits(3)) as i8; + //S.copy(&W[((w[nb] as usize) - 1) / 2]); + S.selector(&W, w[nb] as i32); + + for i in (0..nb).rev() { + T.selector(&W, w[i] as i32); + S.dbl(); + S.dbl(); + S.add(&T); + } + S.sub(&C); /* apply correction */ + S + } + + pub fn cfp(&mut self) { + let cf = rom::CURVE_COF_I; + if cf == 1 { + return; + } + if cf == 4 { + self.dbl(); + self.dbl(); + return; + } + if cf == 8 { + self.dbl(); + self.dbl(); + self.dbl(); + return; + } + let c = BIG::new_ints(&rom::CURVE_COF); + let P = self.mul(&c); + self.copy(&P); + } + +/* Hunt and Peck a BIG to a curve point */ + #[allow(non_snake_case)] + pub fn hap2point(h: &BIG) -> ECP { + let mut P: ECP; + let mut x =BIG::new_copy(&h); + loop { + if CURVETYPE != MONTGOMERY { + P = ECP::new_bigint(&x, 0); + } else { + P = ECP::new_big(&x); + } + x.inc(1); + x.norm(); + if !P.is_infinity() { + break; + } + } + P + } + +/* Constant time Map to Point */ + #[allow(non_snake_case)] + pub fn map2point(h: &FP) -> ECP { + let mut P = ECP::new(); + + if CURVETYPE == MONTGOMERY { + // Elligator 2 + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut t =FP::new_copy(h); + let mut w =FP::new(); + let one=FP::new_int(1); + let A=FP::new_int(CURVE_A); + let mut N =FP::new(); + let mut D =FP::new(); + let mut hint =FP::new(); + + t.sqr(); // t^2 + + if fp::PM1D2 == 2 { + t.dbl(); // 2t^2 + } + if fp::PM1D2 == 1 { + t.neg(); // -t^2 + } + if fp::PM1D2 > 2 { + t.imul(fp::QNRI as isize); // precomputed QNR + } + + t.norm(); + D.copy(&t); D.add(&one); D.norm(); // Denominator D=1+z.t^2 + + X1.copy(&A); + X1.neg(); X1.norm(); // X1=-A/D + X2.copy(&X1); + X2.mul(&t); // X2=-At/D + + w.copy(&X1); w.sqr(); N.copy(&w); N.mul(&X1); + w.mul(&A); w.mul(&D); N.add(&w); + t.copy(&D); t.sqr(); + t.mul(&X1); + N.add(&t); N.norm(); // Numerator=x^3+ADx^2+D^2x + + t.copy(&N); t.mul(&D); // N*D + let qres=t.qr(Some(&mut hint)); // only exp + w.copy(&t); w.inverse(Some(&hint)); + D.copy(&w); D.mul(&N); // 1/D + X1.mul(&D); // get X1 + X2.mul(&D); // get X2 + X1.cmove(&X2,1-qres); + + let a=X1.redc(); + P.copy(&ECP::new_big(&a)); + + } + if CURVETYPE == EDWARDS { +// Elligator 2 - map to Montgomery, place point, map back + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut t=FP::new_copy(h); + let mut w=FP::new(); + let one=FP::new_int(1); + let mut A=FP::new(); + let mut w1=FP::new(); + let mut w2=FP::new(); + let mut B = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + let mut Y=FP::new(); + let mut K=FP::new(); + let mut D=FP::new(); + let mut hint=FP::new(); + //let mut Y3=FP::new(); + let rfc: isize; + + if fp::MODTYPE != fp::GENERALISED_MERSENNE { + A.copy(&B); + if CURVE_A==1 { + A.add(&one); // A=B+1 + B.sub(&one); // B=B-1 + } else { + A.sub(&one); // A=B-1 + B.add(&one); // B=B+1 + } + A.norm(); B.norm(); + + A.div2(); // (A+B)/2 = J/K + B.div2(); // (B-A)/2 + B.div2(); // (B-A)/4 = -1/K + + K.copy(&B); + K.neg(); K.norm(); + + K.invsqrt(&mut w2,&mut w1); // return K, sqrt(1/K) - could be precalculated! + K.copy(&w2); + rfc=fp::RIADZ; + if rfc==1 { + A.mul(&K); + K.mul(&w1); + } else { + B.sqr(); + } + } else { + rfc=1; + A.copy(&FP::new_int(156326)); + } +// Map to this Montgomery curve X^2=X^3+AX^2+BX + t.sqr(); // t^2 + let mut qnr=0; + if fp::PM1D2 == 2 { + t.dbl(); + qnr=2; + } + if fp::PM1D2 == 1 { + t.neg(); + qnr = -1; + } + if fp::PM1D2 > 2 { + t.imul(fp::QNRI as isize); // precomputed QNR + qnr=fp::QNRI as isize; + } + t.norm(); + + D.copy(&t); D.add(&one); D.norm(); // Denominator=(1+z.u^2) + X1.copy(&A); + X1.neg(); X1.norm(); // X1=-(J/K).inv(1+z.u^2) + X2.copy(&X1); X2.mul(&t); // X2=X1*z*u^2 + +// Figure out RHS of Montgomery curve in rational form gx1/d^3 + + w.copy(&X1); w.sqr(); w1.copy(&w); w1.mul(&X1); + w.mul(&A); w.mul(&D); w1.add(&w); + w2.copy(&D); w2.sqr(); + + if rfc==0 { + w.copy(&X1); w.mul(&B); + w2.mul(&w); + w1.add(&w2); // w1=X1^3+ADX1^2+BD^2X1 + } else { + w2.mul(&X1); + w1.add(&w2); // w1=X1^3+ADX1^2+D^2X1 + } + w1.norm(); + + B.copy(&w1); B.mul(&D); // gx1=num/den^3 - is_qr num*den (same as num/den, same as num/den^3) + let qres=B.qr(Some(&mut hint)); // Exponentiation + w.copy(&B); w.inverse(Some(&hint)); + D.copy(&w); D.mul(&w1); // 1/D + X1.mul(&D); // get X1 + X2.mul(&D); // get X2 + D.sqr(); + + w1.copy(&B); w1.imul(qnr); + w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + w.mul(&hint); + w2.copy(&D); w2.mul(&h); + + X1.cmove(&X2,1-qres); + B.cmove(&w1,1-qres); + hint.cmove(&w,1-qres); + D.cmove(&w2,1-qres); + + Y.copy(&B.sqrt(Some(&hint))); + Y.mul(&D); +/* + Y.copy(&B.sqrt(Some(&hint))); // sqrt(num*den) + Y.mul(&D); // sqrt(num/den^3) + + B.imul(qnr); // now for gx2 = Z.u^2.gx1 + w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); // qnr^C3 + hint.mul(&w); // modify hint for gx2 + + Y3.copy(&B.sqrt(Some(&hint))); // second candidate + D.mul(&h); + Y3.mul(&D); + + X1.cmove(&X2,1-qres); // pick correct one + Y.cmove(&Y3,1-qres); +*/ +// correct sign of Y + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,qres^Y.sign()); + + if rfc==0 { + X1.mul(&K); + Y.mul(&K); + } + + if fp::MODTYPE == fp::GENERALISED_MERSENNE { + // GOLDILOCKS isogeny + t.copy(&X1); t.sqr(); + w.copy(&t); w.add(&one); w.norm(); + t.sub(&one); t.norm(); + w1.copy(&t); w1.mul(&Y); + w1.dbl(); X2.copy(&w1); X2.add(&w1); X2.norm(); + t.sqr(); + Y.sqr(); Y.dbl(); Y.dbl(); Y.norm(); + B.copy(&t); B.add(&Y); B.norm(); + + w2.copy(&Y); w2.sub(&t); w2.norm(); + w2.mul(&X1); + t.mul(&X1); + Y.div2(); + w1.copy(&Y); w1.mul(&w); + w1.rsub(&t); w1.norm(); + + t.copy(&X2); t.mul(&w1); // output in projective to avoid inversion + P.x.copy(&t); + t.copy(&w2); t.mul(&B); + P.y.copy(&t); + t.copy(&w1); t.mul(&B); + P.z.copy(&t); + + return P; + } else { + w1.copy(&X1); w1.add(&one); w1.norm(); // s+1 + w2.copy(&X1); w2.sub(&one); w2.norm(); // s-1 + t.copy(&w1); t.mul(&Y); + X1.mul(&w1); + + if rfc==1 { + X1.mul(&K); + } + Y.mul(&w2); // output in projective to avoid inversion + P.x.copy(&X1); + P.y.copy(&Y); + P.z.copy(&t); + + return P + } + } + if CURVETYPE==WEIERSTRASS { + // SSWU or SVDW method + let mut A=FP::new(); + let mut B=FP::new(); + let mut X1=FP::new(); + let mut X2=FP::new(); + let mut X3=FP::new(); + let one=FP::new_int(1); + let mut Y=FP::new(); + let mut D=FP::new(); + let mut t=FP::new_copy(h); + let mut w=FP::new(); + let mut D2=FP::new(); + let mut hint=FP::new(); + let mut GX1=FP::new(); + //let mut Y3=FP::new(); + + let sgn=t.sign(); + + if CURVE_A != 0 || HTC_ISO != 0 + { // Map to point on isogenous curve + if HTC_ISO != 0 { +/* CAHCZS + A.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_AD))); + B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_BD))); +CAHCZF */ + } else { + A.copy(&FP::new_int(CURVE_A)); + B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); + } + // SSWU Method + t.sqr(); + t.imul(fp::RIADZ); // Z from hash-to-point draft standard + w.copy(&t); w.add(&one); w.norm(); + + w.mul(&t); D.copy(&A); + D.mul(&w); + + w.add(&one); w.norm(); + w.mul(&B); + w.neg(); w.norm(); + + X2.copy(&w); + X3.copy(&t); X3.mul(&X2); + +// x^3+Ad^2x+Bd^3 + GX1.copy(&X2); GX1.sqr(); D2.copy(&D); + D2.sqr(); w.copy(&A); w.mul(&D2); GX1.add(&w); GX1.norm(); GX1.mul(&X2); D2.mul(&D); w.copy(&B); w.mul(&D2); GX1.add(&w); GX1.norm(); + + w.copy(&GX1); w.mul(&D); + let qr=w.qr(Some(&mut hint)); + D.copy(&w); D.inverse(Some(&hint)); + D.mul(&GX1); + X2.mul(&D); + X3.mul(&D); + t.mul(h); + D2.copy(&D); D2.sqr(); + + D.copy(&D2); D.mul(&t); + t.copy(&w); t.imul(fp::RIADZ); + X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + X1.mul(&hint); + + X2.cmove(&X3,1-qr); + D2.cmove(&D,1-qr); + w.cmove(&t,1-qr); + hint.cmove(&X1,1-qr); + + Y.copy(&w.sqrt(Some(&hint))); + Y.mul(&D2); +/* + Y.copy(&w.sqrt(Some(&hint))); + Y.mul(&D2); + + D2.mul(&t); + w.imul(fp::RIADZ); + + X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); + hint.mul(&X1); + + Y3.copy(&w.sqrt(Some(&hint))); + Y3.mul(&D2); + + X2.cmove(&X3,1-qr); + Y.cmove(&Y3,1-qr); +*/ + let ne=Y.sign()^sgn; + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,ne); + + if HTC_ISO != 0 { + +/* CAHCZS + let mut k=0; + let isox=HTC_ISO; + let isoy=3*(isox-1)/2; + // xnum + let mut xnum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; + for _ in 0..isox { + xnum.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xnum.add(&w); xnum.norm(); + } + // xden + let mut xden=FP::new_copy(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xden.add(&w); xden.norm(); + for _ in 0..isox-2 { + xden.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + xden.add(&w); xden.norm(); + } + // ynum + let mut ynum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; + for _ in 0..isoy { + ynum.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + ynum.add(&w); ynum.norm(); + } + // yden + let mut yden=FP::new_copy(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + yden.add(&w); yden.norm(); + for _ in 0..isoy-1 { + yden.mul(&X2); + w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; + yden.add(&w); yden.norm(); + } + ynum.mul(&Y); + w.copy(&xnum); w.mul(&yden); + P.x.copy(&w); + w.copy(&ynum); w.mul(&xden); + P.y.copy(&w); + w.copy(&xden); w.mul(&yden); + P.z.copy(&w); + return P; +CAHCZF */ + } else { + let x=X2.redc(); + let y=Y.redc(); + P.copy(&ECP::new_bigs(&x,&y)); + return P; + } + } else { +// Shallue and van de Woestijne +// SQRTM3 not available, so preprocess this out +/* */ + let Z=fp::RIADZ; + X1.copy(&FP::new_int(Z)); + X3.copy(&X1); + A.copy(&ECP::rhs(&X1)); + B.copy(&FP::new_big(&BIG::new_ints(&rom::SQRTM3))); + B.imul(Z); + + t.sqr(); + Y.copy(&A); Y.mul(&t); + t.copy(&one); t.add(&Y); t.norm(); + Y.rsub(&one); Y.norm(); + D.copy(&t); D.mul(&Y); + D.mul(&B); + + w.copy(&A); + FP::tpo(&mut D,&mut w); + + w.mul(&B); + if w.sign()==1 { + w.neg(); + w.norm(); + } + w.mul(&B); + w.mul(&h); w.mul(&Y); w.mul(&D); + + X1.neg(); X1.norm(); X1.div2(); + X2.copy(&X1); + X1.sub(&w); X1.norm(); + X2.add(&w); X2.norm(); + A.dbl(); A.dbl(); A.norm(); + t.sqr(); t.mul(&D); t.sqr(); + A.mul(&t); + X3.add(&A); X3.norm(); + + let mut rhs=ECP::rhs(&X2); + X3.cmove(&X2,rhs.qr(None)); + rhs.copy(&ECP::rhs(&X1)); + X3.cmove(&X1,rhs.qr(None)); + rhs.copy(&ECP::rhs(&X3)); + Y.copy(&rhs.sqrt(None)); + + let ne=Y.sign()^sgn; + w.copy(&Y); w.neg(); w.norm(); + Y.cmove(&w,ne); + + let x=X3.redc(); + let y=Y.redc(); + P.copy(&ECP::new_bigs(&x,&y)); + return P; +/* */ + } + } + P + } + +/* Map byte string to curve point */ + #[allow(non_snake_case)] + pub fn mapit(h: &[u8]) -> ECP { + let q = BIG::new_ints(&rom::MODULUS); + let mut dx = DBIG::frombytes(h); + let x=dx.dmod(&q); + let mut P=ECP::hap2point(&x); + P.cfp(); + P + } + + pub fn generator() -> ECP { + let G: ECP; + let gx = BIG::new_ints(&rom::CURVE_GX); + if CURVETYPE != MONTGOMERY { + let gy = BIG::new_ints(&rom::CURVE_GY); + G = ECP::new_bigs(&gx, &gy); + } else { + G = ECP::new_big(&gx); + } + G + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs new file mode 100644 index 000000000000..09c66c6bcd9a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs @@ -0,0 +1,999 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::fp2::FP2; +use crate::bn254::rom; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; + +#[derive(Clone)] +pub struct ECP2 { + x: FP2, + y: FP2, + z: FP2, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for ECP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for ECP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[allow(non_snake_case)] +impl ECP2 { + pub fn new() -> ECP2 { + ECP2 { + x: FP2::new(), + y: FP2::new_int(1), + z: FP2::new(), + } + } + #[allow(non_snake_case)] + /* construct this from (x,y) - but set to O if not on curve */ + pub fn new_fp2s(ix: &FP2, iy: &FP2) -> ECP2 { + let mut E = ECP2::new(); + E.x.copy(&ix); + E.y.copy(&iy); + E.z.one(); + E.x.norm(); + + let rhs = ECP2::rhs(&E.x); + let mut y2 = FP2::new_copy(&E.y); + y2.sqr(); + if !y2.equals(&rhs) { + E.inf(); + } + E + } + + /* construct this from x - but set to O if not on curve */ + pub fn new_fp2(ix: &FP2, s:isize) -> ECP2 { + let mut E = ECP2::new(); + let mut h = FP::new(); + E.x.copy(&ix); + E.y.one(); + E.z.one(); + E.x.norm(); + let mut rhs = ECP2::rhs(&E.x); + if rhs.qr(Some(&mut h)) == 1 { + rhs.sqrt(Some(&h)); + if rhs.sign() != s { + rhs.neg(); + } + rhs.reduce(); + E.y.copy(&rhs); + } else { + E.inf(); + } + E + } + + /* Test this=O? */ + pub fn is_infinity(&self) -> bool { + self.x.iszilch() && self.z.iszilch() + } + + /* copy self=P */ + pub fn copy(&mut self, P: &ECP2) { + self.x.copy(&P.x); + self.y.copy(&P.y); + self.z.copy(&P.z); + } + + /* set self=O */ + pub fn inf(&mut self) { + self.x.zero(); + self.y.one(); + self.z.zero(); + } + + /* set self=-self */ + pub fn neg(&mut self) { + self.y.norm(); + self.y.neg(); + self.y.norm(); + } + + /* Conditional move of Q to self dependant on d */ + pub fn cmove(&mut self, Q: &ECP2, d: isize) { + self.x.cmove(&Q.x, d); + self.y.cmove(&Q.y, d); + self.z.cmove(&Q.z, d); + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* Constant time select from pre-computed table */ + pub fn selector(&mut self, W: &[ECP2], b: i32) { + let mut MP = ECP2::new(); + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&W[0], ECP2::teq(babs, 0)); // conditional move + self.cmove(&W[1], ECP2::teq(babs, 1)); + self.cmove(&W[2], ECP2::teq(babs, 2)); + self.cmove(&W[3], ECP2::teq(babs, 3)); + self.cmove(&W[4], ECP2::teq(babs, 4)); + self.cmove(&W[5], ECP2::teq(babs, 5)); + self.cmove(&W[6], ECP2::teq(babs, 6)); + self.cmove(&W[7], ECP2::teq(babs, 7)); + + MP.copy(self); + MP.neg(); + self.cmove(&MP, (m & 1) as isize); + } + + /* Test if P == Q */ + pub fn equals(&self, Q: &ECP2) -> bool { + let mut a = FP2::new_copy(&self.x); + let mut b = FP2::new_copy(&Q.x); + + a.mul(&Q.z); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + a.copy(&self.y); + a.mul(&Q.z); + b.copy(&Q.y); + b.mul(&self.z); + if !a.equals(&b) { + return false; + } + + true + } + + /* set to Affine - (x,y,z) to (x,y) */ + pub fn affine(&mut self) { + if self.is_infinity() { + return; + } + let one = FP2::new_int(1); + if self.z.equals(&one) { + return; + } + self.z.inverse(None); + + self.x.mul(&self.z); + self.x.reduce(); + self.y.mul(&self.z); + self.y.reduce(); + self.z.copy(&one); + } + + /* extract affine x as FP2 */ + pub fn getx(&self) -> FP2 { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + FP2::new_copy(&W.x) + } + + /* extract affine y as FP2 */ + pub fn gety(&self) -> FP2 { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + FP2::new_copy(&W.y) + } + + /* extract projective x */ + pub fn getpx(&self) -> FP2 { + FP2::new_copy(&self.x) + } + /* extract projective y */ + pub fn getpy(&self) -> FP2 { + FP2::new_copy(&self.y) + } + /* extract projective z */ + pub fn getpz(&self) -> FP2 { + FP2::new_copy(&self.z) + } + + /* convert to byte array */ + pub fn tobytes(&self, b: &mut [u8], compress: bool) { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + let mut alt=false; + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + W.x.tobytes(&mut t); + + if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { + alt=true; + } + if alt { + for i in 0..MB { + b[i]=t[i] + } + if !compress { + W.y.tobytes(&mut t); + for i in 0..MB { + b[i+MB]=t[i]; + } + } else { + b[0]|=0x80; + if W.y.islarger()==1 { + b[0]|=0x20; + } + } + + } else { + for i in 0..MB { + b[i+1]=t[i]; + } + if !compress { + b[0]=0x04; + W.y.tobytes(&mut t); + for i in 0..MB { + b[i+MB+1]=t[i]; + } + } else { + b[0]=0x02; + if W.y.sign() == 1 { + b[0]=0x03; + } + } + } + } + + /* convert from byte array to point */ + pub fn frombytes(b: &[u8]) -> ECP2 { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + let typ=b[0] as isize; + let mut alt=false; + + if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { + alt=true; + } + + if alt { + for i in 0..MB { + t[i]=b[i]; + } + t[0]&=0x1f; + let rx=FP2::frombytes(&t); + if (b[0]&0x80)==0 { + for i in 0..MB { + t[i]=b[i+MB]; + } + let ry=FP2::frombytes(&t); + ECP2::new_fp2s(&rx,&ry) + } else { + let sgn=(b[0]&0x20)>>5; + let mut P=ECP2::new_fp2(&rx,0); + let cmp=P.y.islarger(); + if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { + P.neg(); + } + P + } + } else { + for i in 0..MB { + t[i]=b[i+1]; + } + let rx=FP2::frombytes(&t); + if typ == 0x04 { + for i in 0..MB { + t[i]=b[i+MB+1]; + } + let ry=FP2::frombytes(&t); + ECP2::new_fp2s(&rx,&ry) + } else { + ECP2::new_fp2(&rx,typ&1) + } + } + } + + /* convert this to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + let mut W = ECP2::new(); + W.copy(self); + W.affine(); + if W.is_infinity() { + String::from("infinity") + } else { + format!("({},{})", W.x.tostring(), W.y.tostring()) + } + } + + /* Calculate RHS of twisted curve equation x^3+B/i */ + pub fn rhs(x: &FP2) -> FP2 { + let mut r = FP2::new_copy(x); + r.sqr(); + let mut b = FP2::new_big(&BIG::new_ints(&rom::CURVE_B)); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.div_ip(); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + b.norm(); + b.mul_ip(); + b.norm(); + } + + r.mul(x); + r.add(&b); + + r.reduce(); + r + } + + /* self+=self */ + pub fn dbl(&mut self) -> isize { + let mut iy = FP2::new_copy(&self.y); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + iy.mul_ip(); + iy.norm(); + } + + let mut t0 = FP2::new_copy(&self.y); //***** Change + t0.sqr(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t0.mul_ip(); + } + let mut t1 = FP2::new_copy(&iy); + t1.mul(&self.z); + let mut t2 = FP2::new_copy(&self.z); + t2.sqr(); + + self.z.copy(&t0); + self.z.add(&t0); + self.z.norm(); + self.z.dbl(); + self.z.dbl(); + self.z.norm(); + + t2.imul(3 * rom::CURVE_B_I); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + t2.mul_ip(); + t2.norm(); + } + let mut x3 = FP2::new_copy(&t2); + x3.mul(&self.z); + + let mut y3 = FP2::new_copy(&t0); + + y3.add(&t2); + y3.norm(); + self.z.mul(&t1); + t1.copy(&t2); + t1.add(&t2); + t2.add(&t1); + t2.norm(); + t0.sub(&t2); + t0.norm(); //y^2-9bz^2 + y3.mul(&t0); + y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 + t1.copy(&self.x); + t1.mul(&iy); // + self.x.copy(&t0); + self.x.norm(); + self.x.mul(&t1); + self.x.dbl(); //(y^2-9bz^2)xy2 + + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + + 1 + } + + /* self+=Q - return 0 for add, 1 for double, -1 for O */ + pub fn add(&mut self, Q: &ECP2) -> isize { + let b = 3 * rom::CURVE_B_I; + let mut t0 = FP2::new_copy(&self.x); + t0.mul(&Q.x); // x.Q.x + let mut t1 = FP2::new_copy(&self.y); + t1.mul(&Q.y); // y.Q.y + + let mut t2 = FP2::new_copy(&self.z); + t2.mul(&Q.z); + let mut t3 = FP2::new_copy(&self.x); + t3.add(&self.y); + t3.norm(); //t3=X1+Y1 + let mut t4 = FP2::new_copy(&Q.x); + t4.add(&Q.y); + t4.norm(); //t4=X2+Y2 + t3.mul(&t4); //t3=(X1+Y1)(X2+Y2) + t4.copy(&t0); + t4.add(&t1); //t4=X1.X2+Y1.Y2 + + t3.sub(&t4); + t3.norm(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t3.mul_ip(); + t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 + } + t4.copy(&self.y); + t4.add(&self.z); + t4.norm(); //t4=Y1+Z1 + let mut x3 = FP2::new_copy(&Q.y); + x3.add(&Q.z); + x3.norm(); //x3=Y2+Z2 + + t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2) + x3.copy(&t1); // + x3.add(&t2); //X3=Y1.Y2+Z1.Z2 + + t4.sub(&x3); + t4.norm(); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t4.mul_ip(); + t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 + } + x3.copy(&self.x); + x3.add(&self.z); + x3.norm(); // x3=X1+Z1 + let mut y3 = FP2::new_copy(&Q.x); + y3.add(&Q.z); + y3.norm(); // y3=X2+Z2 + x3.mul(&y3); // x3=(X1+Z1)(X2+Z2) + y3.copy(&t0); + y3.add(&t2); // y3=X1.X2+Z1+Z2 + y3.rsub(&x3); + y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 + + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + t0.mul_ip(); + t0.norm(); // x.Q.x + t1.mul_ip(); + t1.norm(); // y.Q.y + } + x3.copy(&t0); + x3.add(&t0); + t0.add(&x3); + t0.norm(); + t2.imul(b); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + t2.mul_ip(); + t2.norm(); + } + let mut z3 = FP2::new_copy(&t1); + z3.add(&t2); + z3.norm(); + t1.sub(&t2); + t1.norm(); + y3.imul(b); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + y3.mul_ip(); + y3.norm(); + } + x3.copy(&y3); + x3.mul(&t4); + t2.copy(&t3); + t2.mul(&t1); + x3.rsub(&t2); + y3.mul(&t0); + t1.mul(&z3); + y3.add(&t1); + t0.mul(&t3); + z3.mul(&t4); + z3.add(&t0); + + self.x.copy(&x3); + self.x.norm(); + self.y.copy(&y3); + self.y.norm(); + self.z.copy(&z3); + self.z.norm(); + + 0 + } + + /* set this-=Q */ + pub fn sub(&mut self, Q: &ECP2) -> isize { + let mut NQ = ECP2::new(); + NQ.copy(Q); + NQ.neg(); + self.add(&NQ) + } + + /* set this*=q, where q is Modulus, using Frobenius */ + pub fn frob(&mut self, x: &FP2) { + let mut x2 = FP2::new_copy(x); + x2.sqr(); + self.x.conj(); + self.y.conj(); + self.z.conj(); + self.z.reduce(); + self.x.mul(&x2); + self.y.mul(&x2); + self.y.mul(x); + } + + /* self*=e */ + pub fn mul(&self, e: &BIG) -> ECP2 { + /* fixed size windows */ + let mut mt = BIG::new(); + let mut t = BIG::new(); + let mut P = ECP2::new(); + let mut Q = ECP2::new(); + let mut C = ECP2::new(); + + if self.is_infinity() { + return P; + } + + let mut W: [ECP2; 8] = [ + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ]; + + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + /* precompute table */ + Q.copy(&self); + Q.dbl(); + + W[0].copy(&self); + + for i in 1..8 { + C.copy(&W[i - 1]); + W[i].copy(&C); + W[i].add(&Q); + } + + /* make exponent odd - add 2P if even, P if odd */ + t.copy(&e); + let s = t.parity(); + t.inc(1); + t.norm(); + let ns = t.parity(); + mt.copy(&t); + mt.inc(1); + mt.norm(); + t.cmove(&mt, s); + Q.cmove(&self, ns); + C.copy(&Q); + + let nb = 1 + (t.nbits() + 3) / 4; + + /* convert exponent to signed 4-bit window */ + for i in 0..nb { + w[i] = (t.lastbits(5) - 16) as i8; + t.dec(w[i] as isize); + t.norm(); + t.fshr(4); + } + w[nb] = (t.lastbits(5)) as i8; + + //P.copy(&W[((w[nb] as usize) - 1) / 2]); + + P.selector(&W, w[nb] as i32); + for i in (0..nb).rev() { + Q.selector(&W, w[i] as i32); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(&Q); + } + P.sub(&C); + P + } + + #[allow(non_snake_case)] + pub fn cfp(&mut self) { + let mut X = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + X.inverse(None); + X.norm(); + } + let x = BIG::new_ints(&rom::CURVE_BNX); + // Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez + // Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))). + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + let mut T = self.mul(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + T.neg(); + } + let mut K = ECP2::new(); + K.copy(&T); + K.dbl(); + K.add(&T); + + K.frob(&X); + self.frob(&X); + self.frob(&X); + self.frob(&X); + self.add(&T); + self.add(&K); + T.frob(&X); + T.frob(&X); + self.add(&T); + } + // Efficient hash maps to G2 on BLS curves - Budroni, Pintore + // Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) + if ecp::CURVE_PAIRING_TYPE > ecp::BN { + let mut xQ = self.mul(&x); + let mut x2Q = xQ.mul(&x); + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + xQ.neg(); + } + x2Q.sub(&xQ); + x2Q.sub(&self); + + xQ.sub(&self); + xQ.frob(&X); + + self.dbl(); + self.frob(&X); + self.frob(&X); + + self.add(&x2Q); + self.add(&xQ); + } + } + + + /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + + pub fn mul4(Q: &[ECP2], u: &[BIG]) -> ECP2 { + let mut W = ECP2::new(); + let mut P = ECP2::new(); + + let mut T: [ECP2; 8] = [ + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ECP2::new(), + ]; + + let mut mt = BIG::new(); + + let mut t: [BIG; 4] = [ + BIG::new_copy(&u[0]), + BIG::new_copy(&u[1]), + BIG::new_copy(&u[2]), + BIG::new_copy(&u[3]), + ]; + + const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); + let mut w: [i8; CT] = [0; CT]; + let mut s: [i8; CT] = [0; CT]; + + for i in 0..4 { + t[i].norm(); + } + + T[0].copy(&Q[0]); + W.copy(&T[0]); + T[1].copy(&W); + T[1].add(&Q[1]); // Q[0]+Q[1] + T[2].copy(&W); + T[2].add(&Q[2]); + W.copy(&T[1]); // Q[0]+Q[2] + T[3].copy(&W); + T[3].add(&Q[2]); + W.copy(&T[0]); // Q[0]+Q[1]+Q[2] + T[4].copy(&W); + T[4].add(&Q[3]); + W.copy(&T[1]); // Q[0]+Q[3] + T[5].copy(&W); + T[5].add(&Q[3]); + W.copy(&T[2]); // Q[0]+Q[1]+Q[3] + T[6].copy(&W); + T[6].add(&Q[3]); + W.copy(&T[3]); // Q[0]+Q[2]+Q[3] + T[7].copy(&W); + T[7].add(&Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] + + // Make it odd + let pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for i in 0..4 { + mt.or(&t[i]); + } + + let nb = 1 + mt.nbits(); + + // Sign pivot + + s[nb - 1] = 1; + for i in 0..nb - 1 { + t[0].fshr(1); + s[i] = (2 * t[0].parity() - 1) as i8; + } + + // Recoded exponent + for i in 0..nb { + w[i] = 0; + let mut k = 1; + for j in 1..4 { + let bt = s[i] * (t[j].parity() as i8); + t[j].fshr(1); + t[j].dec((bt >> 1) as isize); + t[j].norm(); + w[i] += bt * (k as i8); + k *= 2; + } + } + + // Main loop + P.selector(&T, (2 * w[nb - 1] + 1) as i32); + for i in (0..nb - 1).rev() { + P.dbl(); + W.selector(&T, (2 * w[i] + s[i]) as i32); + P.add(&W); + } + + // apply correction + W.copy(&P); + W.sub(&Q[0]); + P.cmove(&W, pb); + + P + } + +/* Hunt and Peck a BIG to a curve point */ + #[allow(non_snake_case)] + pub fn hap2point(h: &BIG) -> ECP2 { + let mut Q: ECP2; + let one = BIG::new_int(1); + let mut x =BIG::new_copy(&h); + loop { + let X = FP2::new_bigs(&one, &x); + Q = ECP2::new_fp2(&X,0); + if !Q.is_infinity() { + break; + } + x.inc(1); + x.norm(); + } + Q + } + +/* Constant time Map to Point */ + #[allow(unreachable_code)] + #[allow(non_snake_case)] + pub fn map2point(H: &FP2) -> ECP2 { + let mut T=FP2::new_copy(H); /**/ + let sgn=T.sign(); /**/ + if ecp::HTC_ISO_G2 == 0 { + // Shallue and van de Woestijne +/* */ + let mut NY=FP2::new_int(1); + let mut Z=FP::new_int(fp::RIADZG2A); + let mut X1=FP2::new_fp(&Z); + let mut X3=FP2::new_copy(&X1); + let mut A=ECP2::rhs(&X1); + let mut W=FP2::new_copy(&A); + + if fp::RIADZG2A==-1 && fp::RIADZG2B==0 && ecp::SEXTIC_TWIST == ecp::M_TYPE && rom::CURVE_B_I==4 { + W.copy(&FP2::new_ints(2,1)); + } else { + W.sqrt(None); + } + let s = FP::new_big(&BIG::new_ints(&rom::SQRTM3)); + Z.mul(&s); + + T.sqr(); + let mut Y=FP2::new_copy(&A); Y.mul(&T); + T.copy(&NY); T.add(&Y); T.norm(); + Y.rsub(&NY); Y.norm(); + NY.copy(&T); NY.mul(&Y); + + NY.pmul(&Z); + NY.inverse(None); + + W.pmul(&Z); + if W.sign()==1 { + W.neg(); + W.norm(); + } + W.pmul(&Z); + W.mul(&H); W.mul(&Y); W.mul(&NY); + + X1.neg(); X1.norm(); X1.div2(); + let mut X2=FP2::new_copy(&X1); + X1.sub(&W); X1.norm(); + X2.add(&W); X2.norm(); + A.dbl(); A.dbl(); A.norm(); + T.sqr(); T.mul(&NY); T.sqr(); + A.mul(&T); + X3.add(&A); X3.norm(); + + Y.copy(&ECP2::rhs(&X2)); + X3.cmove(&X2,Y.qr(None)); + Y.copy(&ECP2::rhs(&X1)); + X3.cmove(&X1,Y.qr(None)); + Y.copy(&ECP2::rhs(&X3)); + Y.sqrt(None); + + let ne=Y.sign()^sgn; + W.copy(&Y); W.neg(); W.norm(); + Y.cmove(&W,ne); + + return ECP2::new_fp2s(&X3,&Y); +/* */ + } else { +/* CAHCZS + let NY=FP2::new_int(1); + let Ad=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_ADR),&BIG::new_ints(&rom::CURVE_ADI)); + let Bd=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_BDR),&BIG::new_ints(&rom::CURVE_BDI)); + let ZZ=FP2::new_ints(fp::RIADZG2A,fp::RIADZG2B); + let mut hint=FP::new(); + + T.sqr(); + T.mul(&ZZ); + let mut W=FP2::new_copy(&T); + W.add(&NY); W.norm(); + + W.mul(&T); + let mut D=FP2::new_copy(&Ad); + D.mul(&W); + + W.add(&NY); W.norm(); + W.mul(&Bd); + W.neg(); W.norm(); + + let mut X2=FP2::new_copy(&W); + let mut X3=FP2::new_copy(&T); + X3.mul(&X2); + + let mut GX1=FP2::new_copy(&X2); GX1.sqr(); + let mut D2=FP2::new_copy(&D); D2.sqr(); + + W.copy(&Ad); W.mul(&D2); GX1.add(&W); GX1.norm(); GX1.mul(&X2); D2.mul(&D); W.copy(&Bd); W.mul(&D2); GX1.add(&W); GX1.norm(); // x^3+Ax+b + + W.copy(&GX1); W.mul(&D); + let qr=W.qr(Some(&mut hint)); + D.copy(&W); D.inverse(Some(&hint)); + D.mul(&GX1); + X2.mul(&D); + X3.mul(&D); + T.mul(&H); + D2.copy(&D); D2.sqr(); + + D.copy(&D2); D.mul(&T); + T.copy(&W); T.mul(&ZZ); + + let mut s=FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC2)); + s.mul(&hint); + + X2.cmove(&X3,1-qr); + W.cmove(&T,1-qr); + D2.cmove(&D,1-qr); + hint.cmove(&s,1-qr); + + let mut Y=FP2::new_copy(&W); Y.sqrt(Some(&hint)); + Y.mul(&D2); + + let ne=Y.sign()^sgn; + W.copy(&Y); W.neg(); W.norm(); + Y.cmove(&W,ne); + + let mut k=0; + let isox=ecp::HTC_ISO_G2; + let isoy=3*(isox-1)/2; + + // xnum + let mut xnum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; + for _ in 0..isox { + xnum.mul(&X2); + xnum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xnum.norm(); + } + //xden + let mut xden=FP2::new_copy(&X2); + xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xden.norm(); + for _ in 0..isox-2 { + xden.mul(&X2); + xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + xden.norm(); + } + //ynum + let mut ynum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; + for _ in 0..isoy { + ynum.mul(&X2); + ynum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + ynum.norm(); + } + //yden + let mut yden=FP2::new_copy(&X2); + yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + yden.norm(); + for _ in 0..isoy-1 { + yden.mul(&X2); + yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; + yden.norm(); + } + ynum.mul(&Y); + + let mut Q=ECP2::new(); + T.copy(&xnum); T.mul(&yden); + Q.x.copy(&T); + T.copy(&ynum); T.mul(&xden); + Q.y.copy(&T); + T.copy(&xden); T.mul(&yden); + Q.z.copy(&T); + return Q; +CAHCZF */ + + } + ECP2::new() + } + +/* Map byte string to curve point */ + #[allow(non_snake_case)] + pub fn mapit(h: &[u8]) -> ECP2 { + let q = BIG::new_ints(&rom::MODULUS); + let mut dx = DBIG::frombytes(h); + let x=dx.dmod(&q); + let mut P=ECP2::hap2point(&x); + P.cfp(); + P + } + + pub fn generator() -> ECP2 { + ECP2::new_fp2s( + &FP2::new_bigs( + &BIG::new_ints(&rom::CURVE_PXA), + &BIG::new_ints(&rom::CURVE_PXB), + ), + &FP2::new_bigs( + &BIG::new_ints(&rom::CURVE_PYA), + &BIG::new_ints(&rom::CURVE_PYB), + ), + ) + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs new file mode 100644 index 000000000000..202c88672ebc --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ECDH/ECIES/ECDSA API Functions */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::rom; +use crate::rand::RAND; +use crate::hash512::HASH512; +use crate::sha3; +use crate::sha3::SHA3; + +pub const INVALID_PUBLIC_KEY: isize = -2; +pub const ERROR: isize = -3; +//pub const INVALID: isize = -4; +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; + +fn rfc7748(r: &mut BIG) { + let mut lg=0; + let mut t=BIG::new_int(1); + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let n=(8*EGS-lg+1) as usize; + r.mod2m(n); + t.shl(n); + r.add(&t); + c=r.lastbits(lg as usize); + r.dec(c); +} + +// reverse first n bytes of buff - for little endian +fn reverse(n: usize,buff: &mut [u8]) { + for i in 0..n/2 { + let ch = buff[i]; + buff[i] = buff[n - i - 1]; + buff[n - i - 1] = ch; + } +} + +// dom - domain function +fn dom(ds: &str,ph: bool,cl: usize,domain: &mut [u8]) -> usize { + let dsb = ds.as_bytes(); + let n=dsb.len(); + for i in 0..n { + domain[i]=dsb[i]; + } + if ph { + domain[n]=1; + } else { + domain[n]=0; + } + domain[n+1]=cl as u8; + return n+2; +} + +fn h(s: &[u8],digest: &mut [u8]) -> usize { + if ecp::AESKEY<=16 { // for ed25519? + let mut sh=HASH512::new(); + for i in 0..s.len() { + sh.process(s[i]); + } + let hs = sh.hash(); + for i in 0..64 { + digest[i]=hs[i]; + } + return 64; + } else { // for ed448? + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..s.len() { + sh.process(s[i]); + } + sh.shake(digest,2*s.len()); + return 2*s.len(); + } +} + +fn h2(ph: bool,ctx: Option<&[u8]>,r: &[u8],q: &[u8],m: &[u8]) -> DBIG { + let b=q.len(); + let mut cl=0; + if let Some(sctx) = ctx { + cl=sctx.len(); + } + let mut domain: [u8; 64] = [0; 64]; + if ecp::AESKEY<=16 { // Ed25519?? + let mut sh=HASH512::new(); + if ph || cl>0 { // if not prehash and no context, omit dom2() + let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + } + for i in 0..b { + sh.process(r[i]); + } + for i in 0..b { + sh.process(q[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + let mut h=sh.hash(); + reverse(64,&mut h); + return DBIG::frombytes(&h); + } else { // for ed448? + let dl=dom("Sigbn254",ph,cl,&mut domain); + let mut h: [u8; 128] = [0; 128]; + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + for i in 0..b { + sh.process(r[i]); + } + for i in 0..b { + sh.process(q[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + + sh.shake(&mut h,2*b); + reverse(2*b,&mut h[0..2*b]); + return DBIG::frombytes(&h[0..2*b]); + } +} + +fn getr(ph: bool,b: usize,digest: &[u8],ctx: Option<&[u8]>,m: &[u8]) -> DBIG { + let mut cl=0; + if let Some(sctx) = ctx { + cl=sctx.len(); + } + let mut domain: [u8; 64] = [0; 64]; + + if ecp::AESKEY<=16 { // Ed25519?? + let mut sh=HASH512::new(); + if ph || cl>0 { // if not prehash and no context, omit dom2() + let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + } + for i in b..2*b { + sh.process(digest[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + let mut h=sh.hash(); + reverse(64,&mut h); + return DBIG::frombytes(&h); + } else { // for ed448? + let dl=dom("Sigbn254",ph,cl,&mut domain); + let mut h: [u8; 128] = [0; 128]; + let mut sh=SHA3::new(sha3::SHAKE256); + for i in 0..dl { + sh.process(domain[i]); + } + if let Some(sctx) = ctx { + for i in 0..cl { + sh.process(sctx[i]); + } + } + for i in b..2*b { + sh.process(digest[i]); + } + for i in 0..m.len() { + sh.process(m[i]); + } + sh.shake(&mut h,2*b); + reverse(2*b,&mut h[0..2*b]); + return DBIG::frombytes(&h[0..2*b]); + } +} + +// encode integer (little endian) +fn encode_int(x: &BIG,w: &mut [u8]) -> usize { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + w[0]=0; + x.tobytearray(w,index); + reverse(b,w); + return b; +} + +// encode point + #[allow(non_snake_case)] +fn encode(P: &ECP,w: &mut [u8]) { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let x=P.getx(); + let y=P.gety(); + encode_int(&y,w); + w[b-1]|=(x.parity()<<7) as u8; +} + +// get sign +fn getsign(x: &[u8]) -> isize{ + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + if (x[b-1]&0x80)!=0 { + return 1; + } else { + return 0; + } +} + +// decode integer (little endian) +fn decode_int(strip_sign: bool,ei: &[u8]) -> BIG { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let mut r: [u8; EFS+1] = [0; EFS+1]; + + for i in 0..b { + r[i]=ei[i]; + } + reverse(b,&mut r); + + if strip_sign { + r[0]&=0x7f; + } + return BIG::frombytearray(&r,index); +} + +// decode compressed point +fn decode(w: &[u8]) -> ECP { + let sign=getsign(w); // lsb of x + let y=decode_int(true,w); + let one = FP::new_int(1); + let mut hint=FP::new(); + let mut x=FP::new_big(&y); x.sqr(); + let mut d=FP::new_copy(&x); + x.sub(&one); + x.norm(); + let mut t = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); + d.mul(&t); + if ecp::CURVE_A==1 { + d.sub(&one); + } + if ecp::CURVE_A==-1 { + d.add(&one); + } + d.norm(); +// inverse square root trick for sqrt(x/d) + t.copy(&x); + t.sqr(); + x.mul(&t); + x.mul(&d); + if x.qr(Some(&mut hint))!=1 { + return ECP::new(); + } + d.copy(&x.sqrt(Some(&hint))); + x.inverse(Some(&hint)); + x.mul(&d); + x.mul(&t); + x.reduce(); + if x.redc().parity()!=sign { + x.neg(); + } + x.norm(); + return ECP::new_bigs(&x.redc(),&y); +} + +#[allow(non_snake_case)] +fn key_pair_regenerate(d: &[u8], q: &mut [u8]) { + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let mut G=ECP::generator(); + + let mut digest: [u8; 128] = [0; 128]; + h(d,&mut digest); + +// reverse bytes for little endian + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + G.copy(&G.mul(&s)); + encode(&G,q); +} + +/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), + * where s is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in s + * otherwise it is generated randomly internally */ +#[allow(non_snake_case)] +pub fn key_pair_generate(rng: Option<&mut RAND>, d: &mut [u8], q: &mut [u8]) -> isize { + let res = 0; + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let mut G=ECP::generator(); + + if let Some(srng) = rng { + for i in 0..b { + d[i]=srng.getbyte(); + } + } + let mut digest: [u8; 128] = [0; 128]; + h(d,&mut digest); + +// reverse bytes for little endian + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + G.copy(&G.mul(&s)); + encode(&G,q); + return res; +} + +// Generate a signature using key pair (d,q) on message m +// Set ph=true if message has already been pre-hashed +// if ph=false, then context should be NULL for ed25519. However RFC8032 mode ed25519ctx is supported by supplying a non-NULL or non-empty context +#[allow(non_snake_case)] +pub fn signature(ph: bool,d: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &mut [u8]) ->isize { + let mut digest: [u8; 128] = [0; 128]; + let mut q: [u8; EFS+1] = [0; EFS+1]; // public key + h(d,&mut digest); // hash of private key + let mut res = 0; + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + let r = BIG::new_ints(&rom::CURVE_ORDER); + + key_pair_regenerate(d,&mut q); + let qs=&q[0..b]; + + if d.len()!=qs.len() || d.len()!=b { + res=INVALID_PUBLIC_KEY; + } + if res==0 { + let mut dr=getr(ph,b,&digest,ctx,m); + let sr=dr.dmod(&r); + let R=ECP::generator().mul(&sr); + encode(&R,&mut sig[0..b]); + reverse(b,&mut digest); + let mut s=BIG::frombytearray(&digest,index); + rfc7748(&mut s); + dr=h2(ph,ctx,sig,&qs,m); + let sd=dr.dmod(&r); + encode_int(&BIG::modadd(&sr,&BIG::modmul(&s,&sd,&r),&r),&mut sig[b..2*b]); + } + return res; +} + +// verify a signature using public key q +// same context (if any) as used for signature +#[allow(non_snake_case)] +pub fn verify(ph: bool, q: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &[u8]) ->bool { + + let mut index=0; + if 8*EFS==fp::MODBITS { + index=1; // extra byte needed for compression + } + let b=EFS+index; + + let mut lg=0; + let mut c=rom::CURVE_COF_I; + while c!=1 { + lg+=1; + c/=2; + } + let r = BIG::new_ints(&rom::CURVE_ORDER); + let mut R=decode(&sig[0..b]); + + if R.is_infinity() { + return false; + } + + let t=decode_int(false,&sig[b..2*b]); + + if BIG::comp(&t,&r)>=0 { + return false; + } + let mut du=h2(ph,ctx,&sig,q,m); + let su=du.dmod(&r); + + let mut G=ECP::generator(); + let mut QD=decode(&q); + if QD.is_infinity() { + return false; + } + QD.neg(); + for _ in 0..lg { // use cofactor 2^c + G.dbl(); QD.dbl(); R.dbl(); + } + + if !G.mul2(&t,&QD,&su).equals(&R) { + return false; + } + return true; +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs new file mode 100644 index 000000000000..17caff2ed023 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::arch; +use crate::arch::Chunk; +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::rom; + +use crate::rand::RAND; + +#[derive(Copy, Clone)] +pub struct FP { + pub x: BIG, + pub xes: i32, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +pub const NOT_SPECIAL: usize = 0; +pub const PSEUDO_MERSENNE: usize = 1; +pub const MONTGOMERY_FRIENDLY: usize = 2; +pub const GENERALISED_MERSENNE: usize = 3; + +pub const NEGATOWER: usize = 0; +pub const POSITOWER: usize = 1; + +pub const MODBITS:usize = 254; /* Number of bits in Modulus */ +pub const PM1D2: usize = 1; /* Modulus mod 8 */ +pub const RIADZ: isize = -1; /* Z for hash-to-point */ +pub const RIADZG2A: isize = -1; /* G2 Z for hash-to-point */ +pub const RIADZG2B: isize = 0; /* G2 Z for hash-to-point */ +pub const MODTYPE:usize=NOT_SPECIAL; +pub const QNRI:usize=0; /* Fp2 QNR 2^i+sqrt(-1) */ +pub const TOWER:usize=NEGATOWER; /* Tower type */ + +pub const FEXCESS:i32 = ((1 as i32)<<26)-1; +pub const OMASK: Chunk = (-1) << (MODBITS % big::BASEBITS); +pub const TBITS: usize = MODBITS % big::BASEBITS; // Number of active bits in top word +pub const TMASK: Chunk = (1 << TBITS) - 1; + +pub const BIG_ENDIAN_SIGN: bool = false; + +impl FP { + /* Constructors */ + pub const fn new() -> FP { + FP { + x: BIG::new(), + xes: 1, + } + } + + pub fn new_int(a: isize) -> FP { + let mut f = FP::new(); + if a<0 { + let mut m = BIG::new_ints(&rom::MODULUS); + m.inc(a); m.norm(); + f.x.copy(&m); + } else { + f.x.inc(a); + } + f.nres(); + f + } + + pub fn new_copy(y: &FP) -> FP { + let mut f = FP::new(); + f.x.copy(&(y.x)); + f.xes = y.xes; + f + } + + pub fn new_big(y: &BIG) -> FP { + let mut f = FP::new(); + f.x.copy(y); + f.nres(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP { + let m = BIG::new_ints(&rom::MODULUS); + let w = BIG::randomnum(&m,rng); + FP::new_big(&w) + } + + pub fn nres(&mut self) { + if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { + let r = BIG::new_ints(&rom::R2MODP); + let mut d = BIG::mul(&(self.x), &r); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2; + } else { + let m = BIG::new_ints(&rom::MODULUS); + self.x.rmod(&m); + self.xes = 1; + } + } + + /* convert back to regular form */ + pub fn redc(&self) -> BIG { + if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { + let mut d = DBIG::new_scopy(&(self.x)); + FP::modulo(&mut d) + } else { + BIG::new_copy(&(self.x)) + } + } + + /* reduce a DBIG to a BIG using the appropriate form of the modulus */ + /* dd */ + pub fn modulo(d: &mut DBIG) -> BIG { + if MODTYPE == PSEUDO_MERSENNE { + let mut b = BIG::new(); + let mut t = d.split(MODBITS); + b.dcopy(&d); + let v = t.pmul(rom::MCONST as isize); + + t.add(&b); + t.norm(); + + let tw = t.w[big::NLEN - 1]; + t.w[big::NLEN - 1] &= TMASK; + t.w[0] += rom::MCONST * ((tw >> TBITS) + (v << (big::BASEBITS - TBITS))); + t.norm(); + return t; + } + + if MODTYPE == MONTGOMERY_FRIENDLY { + let mut b = BIG::new(); + for i in 0..big::NLEN { + let x = d.w[i]; + + let tuple = BIG::muladd(x, rom::MCONST - 1, x, d.w[big::NLEN + i - 1]); + d.w[big::NLEN + i] += tuple.0; + d.w[big::NLEN + i - 1] = tuple.1; + } + + b.zero(); + + for i in 0..big::NLEN { + b.w[i] = d.w[big::NLEN + i]; + } + b.norm(); + return b; + } + + if MODTYPE == GENERALISED_MERSENNE { + // GoldiLocks Only + let mut b = BIG::new(); + let t = d.split(MODBITS); + let rm2 = (MODBITS / 2) as usize; + b.dcopy(&d); + b.add(&t); + let mut dd = DBIG::new_scopy(&t); + dd.shl(rm2); + + let mut tt = dd.split(MODBITS); + let lo = BIG::new_dcopy(&dd); + b.add(&tt); + b.add(&lo); + b.norm(); + tt.shl(rm2); + b.add(&tt); + + let carry = b.w[big::NLEN - 1] >> TBITS; + b.w[big::NLEN - 1] &= TMASK; + b.w[0] += carry; + + let ix=(224 / big::BASEBITS) as usize; + b.w[ix] += carry << (224 % big::BASEBITS); + b.norm(); + return b; + } + + if MODTYPE == NOT_SPECIAL { + let m = BIG::new_ints(&rom::MODULUS); + return BIG::monty(&m, rom::MCONST, d); + } + BIG::new() + } + + /* convert to string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + self.redc().tostring() + } + + /* reduce this mod Modulus */ + pub fn reduce(&mut self) { + let mut m = BIG::new_ints(&rom::MODULUS); + let mut r = BIG::new_copy(&m); + let mut sb: usize; + self.x.norm(); + if self.xes > 16 { + let q = FP::quo(&self.x, &m); + let carry = r.pmul(q); + r.w[big::NLEN - 1] += carry << big::BASEBITS; // correction - put any carry out back in again + self.x.sub(&r); + self.x.norm(); + sb = 2; + } else { + sb = FP::logb2((self.xes - 1) as u32); + } + m.fshl(sb); + + while sb > 0 { + let sr = BIG::ssn(&mut r, &self.x, &mut m); + self.x.cmove(&r, 1 - sr); + sb -= 1; + } + + self.xes = 1; + } + + /* test this=0? */ + pub fn iszilch(&self) -> bool { + let mut a = FP::new_copy(self); + a.reduce(); + a.x.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + return 0; + } + let mut sx = BIG::new_ints(&rom::MODULUS); + let fx=self.redc(); + sx.sub(&fx); sx.norm(); + BIG::comp(&fx,&sx) + } + + pub fn tobytes(&self,b: &mut [u8]) { + self.redc().tobytes(b) + } + + pub fn frombytes(b: &[u8]) -> FP { + let t=BIG::frombytes(b); + FP::new_big(&t) + } + + /* test this=0? */ + pub fn isunity(&self) -> bool { + let mut a = FP::new_copy(self); + a.reduce(); + a.redc().isunity() + } + + pub fn sign(&self) -> isize { + if BIG_ENDIAN_SIGN { + let mut m = BIG::new_ints(&rom::MODULUS); + m.dec(1); + m.fshr(1); + let mut n = FP::new_copy(self); + n.reduce(); + let w=n.redc(); + let cp=BIG::comp(&w,&m); + ((cp+1)&2)>>1 + } else { + let mut a = FP::new_copy(self); + a.reduce(); + a.redc().parity() + } + } + + /* copy from FP b */ + pub fn copy(&mut self, b: &FP) { + self.x.copy(&(b.x)); + self.xes = b.xes; + } + + /* copy from BIG b */ + pub fn bcopy(&mut self, b: &BIG) { + self.x.copy(&b); + self.nres(); + } + + /* set this=0 */ + pub fn zero(&mut self) { + self.x.zero(); + self.xes = 1; + } + + /* set this=1 */ + pub fn one(&mut self) { + self.x.one(); + self.nres() + } + + /* normalise this */ + pub fn norm(&mut self) { + self.x.norm(); + } + + /* swap FPs depending on d */ + pub fn cswap(&mut self, b: &mut FP, d: isize) { + self.x.cswap(&mut (b.x), d); + let mut c = d as i32; + c = !(c - 1); + let t = c & (self.xes ^ b.xes); + self.xes ^= t; + b.xes ^= t; + } + + /* copy FPs depending on d */ + pub fn cmove(&mut self, b: &FP, d: isize) { + self.x.cmove(&(b.x), d); + let c = d as i32; + self.xes ^= (self.xes ^ b.xes) & (-c); + } + + /* this*=b mod Modulus */ + pub fn mul(&mut self, b: &FP) { + if (self.xes as i64) * (b.xes as i64) > FEXCESS as i64 { + self.reduce() + } + + let mut d = BIG::mul(&(self.x), &(b.x)); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2; + } + + fn logb2(w: u32) -> usize { + let mut v = w; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + ((((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize + } + + // find appoximation to quotient of a/m + // Out by at most 2. + // Note that MAXXES is bounded to be 2-bits less than half a word + fn quo(n: &BIG, m: &BIG) -> isize { + let hb = arch::CHUNK / 2; + + if TBITS < hb { + let sh = hb - TBITS; + let num = (n.w[big::NLEN - 1] << sh) | (n.w[big::NLEN - 2] >> (big::BASEBITS - sh)); + let den = (m.w[big::NLEN - 1] << sh) | (m.w[big::NLEN - 2] >> (big::BASEBITS - sh)); + (num / (den + 1)) as isize + } else { + let num = n.w[big::NLEN - 1]; + let den = m.w[big::NLEN - 1]; + (num / (den + 1)) as isize + } + } + + /* this = -this mod Modulus */ + pub fn neg(&mut self) { + let mut p = BIG::new_ints(&rom::MODULUS); + let sb = FP::logb2((self.xes - 1) as u32); + + p.fshl(sb); + self.x.rsub(&p); + self.xes = 1 << ((sb as i32) + 1); + if self.xes > FEXCESS { + self.reduce() + } + } + + /* this*=c mod Modulus, where c is a small int */ + pub fn imul(&mut self, c: isize) { + let mut cc = c; + let mut s = false; + if cc < 0 { + cc = -cc; + s = true; + } + + if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { + let mut d = self.x.pxmul(cc); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2 + } else if self.xes * (cc as i32) <= FEXCESS { + self.x.pmul(cc); + self.xes *= cc as i32; + } else { + let n = FP::new_int(cc); + self.mul(&n); + } + + if s { + self.neg(); + self.norm(); + } + } + + /* self*=self mod Modulus */ + pub fn sqr(&mut self) { + if (self.xes as i64) * (self.xes as i64) > FEXCESS as i64 { + self.reduce() + } + + let mut d = BIG::sqr(&(self.x)); + self.x.copy(&FP::modulo(&mut d)); + self.xes = 2 + } + + /* self+=b */ + pub fn add(&mut self, b: &FP) { + self.x.add(&(b.x)); + self.xes += b.xes; + if self.xes > FEXCESS { + self.reduce() + } + } + + /* self+=self */ + pub fn dbl(&mut self) { + self.x.dbl(); + self.xes += self.xes; + if self.xes > FEXCESS { + self.reduce() + } + } + + /* self-=b */ + pub fn sub(&mut self, b: &FP) { + let mut n = FP::new_copy(b); + n.neg(); + self.add(&n); + } + + /* self=b-self */ + pub fn rsub(&mut self, b: &FP) { + self.neg(); + self.add(&b); + } + + /* self/=2 mod Modulus */ + pub fn div2(&mut self) { + let p = BIG::new_ints(&rom::MODULUS); + let pr = self.x.parity(); + let mut w = BIG::new_copy(&self.x); + self.x.fshr(1); + w.add(&p); w.norm(); + w.fshr(1); + self.x.cmove(&w,pr); + } + /* return jacobi symbol (this/Modulus) */ + pub fn jacobi(&mut self) -> isize { + let p = BIG::new_ints(&rom::MODULUS); + let mut w = self.redc(); + w.jacobi(&p) + } + /* return TRUE if self==a */ + pub fn equals(&self, a: &FP) -> bool { + let mut f = FP::new_copy(self); + let mut s = FP::new_copy(a); + f.reduce(); + s.reduce(); + BIG::comp(&(f.x), &(s.x)) == 0 + } + + /* return self^e mod Modulus */ + // Could leak size of e + // but not used here with secret exponent e + pub fn pow(&self, e: &BIG) -> FP { + let mut tb: [FP; 16] = [ + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + ]; + const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; + let mut w: [i8; CT] = [0; CT]; + + let mut s = FP::new_copy(&self); + s.norm(); + let mut t = BIG::new_copy(e); + t.norm(); + let nb = 1 + (t.nbits() + 3) / 4; + + for i in 0..nb { + let lsbs = t.lastbits(4); + t.dec(lsbs); + t.norm(); + w[i] = lsbs as i8; + t.fshr(4); + } + tb[0].one(); + tb[1].copy(&s); + + let mut c = FP::new(); + for i in 2..16 { + c.copy(&tb[i - 1]); + tb[i].copy(&c); + tb[i].mul(&s); + } + let mut r = FP::new_copy(&tb[w[nb - 1] as usize]); + for i in (0..nb - 1).rev() { + r.sqr(); + r.sqr(); + r.sqr(); + r.sqr(); + r.mul(&tb[w[i] as usize]) + } + r.reduce(); + r + } + + // See eprint paper https://eprint.iacr.org/2018/1038 + // return this^(p-3)/4 or this^(p-5)/8 + pub fn fpow(&self) -> FP { + let ac: [isize; 11] = [1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255]; + let mut xp: [FP; 11] = [ + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + FP::new(), + ]; + // phase 1 + let mut t = FP::new(); + xp[0].copy(&self); // 1 + xp[1].copy(&self); + xp[1].sqr(); // 2 + t.copy(&xp[1]); + xp[2].copy(&t); + xp[2].mul(&self); // 3 + t.copy(&xp[2]); + xp[3].copy(&t); + xp[3].sqr(); // 6 + t.copy(&xp[3]); + xp[4].copy(&t); + xp[4].sqr(); // 12 + t.copy(&xp[4]); + t.mul(&xp[2]); + xp[5].copy(&t); // 15 + t.copy(&xp[5]); + xp[6].copy(&t); + xp[6].sqr(); // 30 + t.copy(&xp[6]); + xp[7].copy(&t); + xp[7].sqr(); // 60 + t.copy(&xp[7]); + xp[8].copy(&t); + xp[8].sqr(); // 120 + t.copy(&xp[8]); + xp[9].copy(&t); + xp[9].sqr(); // 240 + t.copy(&xp[9]); + t.mul(&xp[5]); + xp[10].copy(&t); // 255 + + let mut n = MODBITS as isize; + let mut c: isize; + + if MODTYPE == GENERALISED_MERSENNE { + // Goldilocks ONLY + n /= 2; + } + + let e = PM1D2 as isize; + + n-=e+1; + c=((rom::MCONST as isize)+(1< k { + i -= 1; + } + key.copy(&xp[i]); + k -= ac[i]; + } + while k != 0 { + i -= 1; + if ac[i] > k { + continue; + } + key.mul(&xp[i]); + k -= ac[i]; + } + // phase 2 + t.copy(&xp[2]); + xp[1].copy(&t); + t.copy(&xp[5]); + xp[2].copy(&t); + t.copy(&xp[10]); + xp[3].copy(&t); + + let mut j = 3; + let mut m = 8; + let nw = n - bw; + let mut r = FP::new(); + + while 2 * m < nw { + t.copy(&xp[j]); + j += 1; + for _ in 0..m { + t.sqr(); + } + r.copy(&xp[j - 1]); + r.mul(&t); + xp[j].copy(&r); + m *= 2; + } + let mut lo = nw - m; + r.copy(&xp[j]); + + while lo != 0 { + m /= 2; + j -= 1; + if lo < m { + continue; + } + lo -= m; + t.copy(&r); + for _ in 0..m { + t.sqr(); + } + r.copy(&t); + r.mul(&xp[j]); + } + // phase 3 + if bw != 0 { + for _ in 0..bw { + r.sqr(); + } + r.mul(&key); + } + if MODTYPE == GENERALISED_MERSENNE { + // Goldilocks ONLY + key.copy(&r); + r.sqr(); + r.mul(&self); + for _ in 0..n + 1 { + r.sqr(); + } + r.mul(&key); + } + while nd>0 { + r.sqr(); + nd-=1; + } + r + } + + /* Pseudo_inverse square root */ + pub fn progen(&mut self) { + if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { + self.copy(&self.fpow()); + return; + } + let e=PM1D2 as usize; + let mut m = BIG::new_ints(&rom::MODULUS); + m.dec(1); + m.shr(e); + m.dec(1); + m.fshr(1); + + self.copy(&self.pow(&m)); + } + + /* self=1/self mod Modulus */ + pub fn inverse(&mut self,take_hint: Option<&FP>) { + let e=PM1D2 as isize; + self.norm(); + let mut s=FP::new_copy(self); + for _ in 0..e-1 { + s.sqr(); + s.mul(self); + } + if let Some(hint) = take_hint { + self.copy(&hint); + } else { + self.progen(); + } + for _ in 0..=e { + self.sqr(); + } + self.mul(&s); + self.reduce(); + } + + /* Test for Quadratic Residue */ + pub fn qr(&self,give_hint: Option<&mut FP>) -> isize { + let e=PM1D2 as isize; + let mut r=FP::new_copy(self); + r.progen(); + if let Some(hint) = give_hint { + hint.copy(&r); + } + + r.sqr(); + r.mul(self); + for _ in 0..e-1 { + r.sqr(); + } + + r.isunity() as isize + } + + pub fn invsqrt(&self,i: &mut FP,s: &mut FP) -> isize { + let mut h=FP::new(); + let qr=self.qr(Some(&mut h)); + s.copy(&self.sqrt(Some(&h))); + i.copy(self); + i.inverse(Some(&h)); + qr + } + +// Two for the price of One - See Hamburg https://eprint.iacr.org/2012/309.pdf +// Calculate inverse of i and square root of s, return QR + pub fn tpo(mut i: &mut FP,mut s: &mut FP) -> isize { + let mut w = FP::new_copy(s); + let mut t = FP::new_copy(i); + w.mul(&i); + t.mul(&w); + let qr=t.invsqrt(&mut i,&mut s); + i.mul(&w); + s.mul(&i); + qr + } + + /* return sqrt(this) mod Modulus */ + pub fn sqrt(&self,take_hint: Option<&FP>) -> FP { + let e=PM1D2 as isize; + let mut g=FP::new_copy(self); + + if let Some(hint) = take_hint { + g.copy(&hint); + } else { + g.progen(); + } + let m = BIG::new_ints(&rom::ROI); + let mut v=FP::new_big(&m); + let mut t=FP::new_copy(&g); + t.sqr(); + t.mul(self); + + let mut r=FP::new_copy(self); + r.mul(&g); + let mut b=FP::new_copy(&t); + + for k in (2..=e).rev() //(int k=e;k>1;k--) + { + for _ in 1..k-1 { + b.sqr(); + } + let u=!b.isunity() as isize; + g.copy(&r); g.mul(&v); + r.cmove(&g,u); + v.sqr(); + g.copy(&t); g.mul(&v); + t.cmove(&g,u); + b.copy(&t); + } + let sgn=r.sign(); + let mut nr=FP::new_copy(&r); + nr.neg(); nr.norm(); + r.cmove(&nr,sgn); + r + } + +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs new file mode 100644 index 000000000000..04df83d8b8a7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs @@ -0,0 +1,1111 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::fp::FP; +use crate::bn254::fp2::FP2; +use crate::bn254::fp4::FP4; +use crate::bn254::rom; + +pub const ZERO: usize = 0; +pub const ONE: usize = 1; +pub const SPARSEST: usize = 2; +pub const SPARSER: usize = 3; +pub const SPARSE: usize = 4; +pub const DENSE: usize = 5; + +#[derive(Copy, Clone)] +pub struct FP12 { + a: FP4, + b: FP4, + c: FP4, + stype: usize, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP12 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP12 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP12 { + pub fn new() -> FP12 { + FP12 { + a: FP4::new(), + b: FP4::new(), + c: FP4::new(), + stype: ZERO, + } + } + + pub fn settype(&mut self, t: usize) { + self.stype = t; + } + + pub fn gettype(&self) -> usize { + self.stype + } + + pub fn new_int(a: isize) -> FP12 { + let mut f = FP12::new(); + f.a.copy(&FP4::new_int(a)); + f.b.zero(); + f.c.zero(); + if a == 1 { + f.stype = ONE; + } else { + f.stype = SPARSEST; + } + f + } + + pub fn new_copy(x: &FP12) -> FP12 { + let mut f = FP12::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f.c.copy(&x.c); + f.stype = x.stype; + f + } + + pub fn new_fp4s(d: &FP4, e: &FP4, f: &FP4) -> FP12 { + let mut g = FP12::new(); + g.a.copy(d); + g.b.copy(e); + g.c.copy(f); + g.stype = DENSE; + g + } + + pub fn new_fp4(d: &FP4) -> FP12 { + let mut g = FP12::new(); + g.a.copy(d); + g.b.zero(); + g.c.zero(); + g.stype = SPARSEST; + g + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + self.c.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + self.c.norm(); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + //self.reduce(); + self.a.iszilch() && self.b.iszilch() && self.c.iszilch() + } + + /* Conditional move of g to self dependant on d */ + pub fn cmove(&mut self, g: &FP12, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + self.c.cmove(&g.c, d); + let mut u = d as usize; + u = !(u.wrapping_sub(1)); + self.stype ^= (self.stype ^ g.stype) & u; + } + + /* return 1 if b==c, no branching */ + fn teq(b: i32, c: i32) -> isize { + let mut x = b ^ c; + x -= 1; // if x=0, x now -1 + ((x >> 31) & 1) as isize + } + + /* Constant time select from pre-computed table */ + pub fn selector(&mut self, g: &[FP12], b: i32) { + let m = b >> 31; + let mut babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + self.cmove(&g[0], FP12::teq(babs, 0)); // conditional move + self.cmove(&g[1], FP12::teq(babs, 1)); + self.cmove(&g[2], FP12::teq(babs, 2)); + self.cmove(&g[3], FP12::teq(babs, 3)); + self.cmove(&g[4], FP12::teq(babs, 4)); + self.cmove(&g[5], FP12::teq(babs, 5)); + self.cmove(&g[6], FP12::teq(babs, 6)); + self.cmove(&g[7], FP12::teq(babs, 7)); + + let mut invf = FP12::new_copy(self); + invf.conj(); + self.cmove(&invf, (m & 1) as isize); + } + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP4::new_int(1); + self.a.equals(&one) && self.b.iszilch() && self.c.iszilch() + } + + /* test self=x */ + pub fn equals(&self, x: &FP12) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c) + } + + pub fn geta(&mut self) -> FP4 { + self.a + // let f = FP4::new_copy(&self.a); + // return f; + } + + pub fn getb(&mut self) -> FP4 { + self.b + // let f = FP4::new_copy(&self.b); + // return f; + } + + pub fn getc(&mut self) -> FP4 { + self.c + // let f = FP4::new_copy(&self.c); + // return f; + } + + /* copy self=x */ + pub fn copy(&mut self, x: &FP12) { + self.a.copy(&x.a); + self.b.copy(&x.b); + self.c.copy(&x.c); + self.stype = x.stype; + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + self.c.zero(); + self.stype = ONE; + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + self.c.zero(); + self.stype = ZERO; + } + + /* this=conj(this) */ + pub fn conj(&mut self) { + self.a.conj(); + self.b.nconj(); + self.c.conj(); + } + + /* Granger-Scott Unitary Squaring */ + pub fn usqr(&mut self) { + let mut a = FP4::new_copy(&self.a); + let mut b = FP4::new_copy(&self.c); + let mut c = FP4::new_copy(&self.b); + let mut d = FP4::new(); + + self.a.sqr(); + d.copy(&self.a); + d.add(&self.a); + self.a.add(&d); + + self.a.norm(); + a.nconj(); + + a.dbl(); + self.a.add(&a); + b.sqr(); + b.times_i(); + + d.copy(&b); + d.add(&b); + b.add(&d); + b.norm(); + + c.sqr(); + d.copy(&c); + d.add(&c); + c.add(&d); + c.norm(); + + self.b.conj(); + self.b.dbl(); + self.c.nconj(); + + self.c.dbl(); + self.b.add(&b); + self.c.add(&c); + self.stype = DENSE; + self.reduce(); + } + + /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ + pub fn sqr(&mut self) { + if self.stype == ONE { + return; + } + + let mut a = FP4::new_copy(&self.a); + let mut b = FP4::new_copy(&self.b); + let mut c = FP4::new_copy(&self.c); + let mut d = FP4::new_copy(&self.a); + + a.sqr(); + b.mul(&self.c); + b.dbl(); + b.norm(); + c.sqr(); + d.mul(&self.b); + d.dbl(); + + self.c.add(&self.a); + self.c.add(&self.b); + self.c.norm(); + self.c.sqr(); + + self.a.copy(&a); + a.add(&b); + a.norm(); + a.add(&c); + a.add(&d); + a.norm(); + + a.neg(); + b.times_i(); + c.times_i(); + + self.a.add(&b); + + self.b.copy(&c); + self.b.add(&d); + self.c.add(&a); + if self.stype == SPARSER || self.stype == SPARSEST { + self.stype = SPARSE; + } else { + self.stype = DENSE; + } + self.norm(); + } + + /* FP12 full multiplication self=self*y */ + pub fn mul(&mut self, y: &FP12) { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new_copy(&self.b); + let mut z3 = FP4::new(); + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new_copy(&y.a); + + z0.mul(&y.a); + z2.mul(&y.b); + + t0.add(&self.b); + t1.add(&y.b); + + t0.norm(); + t1.norm(); + + z1.copy(&t0); + z1.mul(&t1); + t0.copy(&self.b); + t0.add(&self.c); + t1.copy(&y.b); + t1.add(&y.c); + + t0.norm(); + t1.norm(); + + z3.copy(&t0); + z3.mul(&t1); + + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + z1.add(&t0); + self.b.copy(&z1); + self.b.add(&t1); + + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + t0.mul(&t1); + z2.add(&t0); + + t0.copy(&self.c); + t0.mul(&y.c); + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + self.stype = DENSE; + self.norm(); + } + + /* FP12 full multiplication w=w*y */ + /* Supports sparse multiplicands */ + /* Usually w is denser than y */ + pub fn ssmul(&mut self, y: &FP12) { + if self.stype == ONE { + self.copy(&y); + return; + } + if y.stype == ONE { + return; + } + if y.stype >= SPARSE { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new(); + let mut z3 = FP4::new(); + z0.mul(&y.a); + + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + if y.stype == SPARSE || self.stype == SPARSE { + let mut ga = FP2::new(); + let mut gb = FP2::new(); + + gb.copy(&self.b.getb()); + gb.mul(&y.b.getb()); + ga.zero(); + if y.stype != SPARSE { + ga.copy(&self.b.getb()); + ga.mul(&y.b.geta()); + } + if self.stype != SPARSE { + ga.copy(&self.b.geta()); + ga.mul(&y.b.getb()); + } + z2.set_fp2s(&ga, &gb); + z2.times_i(); + } else { + z2.copy(&self.b); + z2.mul(&y.b); + } + } else { + z2.copy(&self.b); + z2.mul(&y.b); + } + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new_copy(&y.a); + t0.add(&self.b); + t0.norm(); + t1.add(&y.b); + t1.norm(); + + z1.copy(&t0); + z1.mul(&t1); + t0.copy(&self.b); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.b); + t1.add(&y.c); + t1.norm(); + + z3.copy(&t0); + z3.mul(&t1); + + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + z1.add(&t0); + self.b.copy(&z1); + self.b.add(&t1); + + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + + t0.mul(&t1); + z2.add(&t0); + + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + if y.stype == SPARSE || self.stype == SPARSE { + let mut ga = FP2::new(); + let mut gb = FP2::new(); + + ga.copy(&self.c.geta()); + ga.mul(&y.c.geta()); + gb.zero(); + if y.stype != SPARSE { + gb.copy(&self.c.geta()); + gb.mul(&y.c.getb()); + } + if self.stype != SPARSE { + gb.copy(&self.c.getb()); + gb.mul(&y.c.geta()); + } + t0.set_fp2s(&ga, &gb); + } else { + t0.copy(&self.c); + t0.mul(&y.c); + } + } else { + t0.copy(&self.c); + t0.mul(&y.c); + } + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } else { + if self.stype == SPARSER || self.stype == SPARSEST { + self.smul(&y); + return; + } + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + // dense by sparser - 13m + let mut z0 = FP4::new_copy(&self.a); + let mut z2 = FP4::new_copy(&self.b); + let mut z3 = FP4::new_copy(&self.b); + let mut t0 = FP4::new(); + let mut t1 = FP4::new_copy(&y.a); + + z0.mul(&y.a); + if y.stype == SPARSEST { + z2.qmul(&y.b.geta().getA()); + } else { + z2.pmul(&y.b.geta()); + } + self.b.add(&self.a); + t1.padd(&y.b.geta()); + + t1.norm(); + self.b.norm(); + self.b.mul(&t1); + z3.add(&self.c); + z3.norm(); + + if y.stype == SPARSEST { + z3.qmul(&y.b.geta().getA()); + } else { + z3.pmul(&y.b.geta()); + } + t0.copy(&z0); + t0.neg(); + t1.copy(&z2); + t1.neg(); + + self.b.add(&t0); + + self.b.add(&t1); + z3.add(&t1); + z2.add(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + z3.norm(); + t0.mul(&y.a); + self.c.copy(&z2); + self.c.add(&t0); + + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + let mut z0 = FP4::new_copy(&self.a); + let mut z1 = FP4::new(); + let mut z2 = FP4::new(); + let mut z3 = FP4::new(); + let mut t0 = FP4::new_copy(&self.a); + let mut t1 = FP4::new(); + + z0.mul(&y.a); + t0.add(&self.b); + t0.norm(); + + z1.copy(&t0); + z1.mul(&y.a); + t0.copy(&self.b); + t0.add(&self.c); + t0.norm(); + + z3.copy(&t0); + if y.stype == SPARSEST { + z3.qmul(&y.c.getb().getA()); + } else { + z3.pmul(&y.c.getb()); + } + z3.times_i(); + + t0.copy(&z0); + t0.neg(); + z1.add(&t0); + self.b.copy(&z1); + z2.copy(&t0); + + t0.copy(&self.a); + t0.add(&self.c); + t0.norm(); + t1.copy(&y.a); + t1.add(&y.c); + t1.norm(); + + t0.mul(&t1); + z2.add(&t0); + t0.copy(&self.c); + + if y.stype == SPARSEST { + t0.qmul(&y.c.getb().getA()); + } else { + t0.pmul(&y.c.getb()); + } + t0.times_i(); + t1.copy(&t0); + t1.neg(); + + self.c.copy(&z2); + self.c.add(&t1); + z3.add(&t1); + t0.times_i(); + self.b.add(&t0); + z3.norm(); + z3.times_i(); + self.a.copy(&z0); + self.a.add(&z3); + } + } + self.stype = DENSE; + self.norm(); + } + + /* Special case of multiplication arises from special form of ATE pairing line function */ + pub fn smul(&mut self, y: &FP12) { + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + let mut w1 = FP2::new_copy(&self.a.geta()); + let mut w2 = FP2::new_copy(&self.a.getb()); + //let mut w3=FP2::new_copy(&self.b.geta()); + + let mut w3: FP2; + + w1.mul(&y.a.geta()); + w2.mul(&y.a.getb()); + + if y.stype == SPARSEST || self.stype == SPARSEST { + if y.stype == SPARSEST && self.stype == SPARSEST { + let mut t = FP::new_copy(&self.b.geta().getA()); + t.mul(&y.b.geta().getA()); + w3 = FP2::new_fp(&t); + } else if y.stype != SPARSEST { + w3 = FP2::new_copy(&y.b.geta()); + w3.pmul(&self.b.geta().getA()); + } else { + w3 = FP2::new_copy(&self.b.geta()); + w3.pmul(&y.b.geta().getA()); + } + } else { + w3 = FP2::new_copy(&self.b.geta()); + w3.mul(&y.b.geta()); + } + let mut ta = FP2::new_copy(&self.a.geta()); + let mut tb = FP2::new_copy(&y.a.geta()); + ta.add(&self.a.getb()); + ta.norm(); + tb.add(&y.a.getb()); + tb.norm(); + let mut tc = FP2::new_copy(&ta); + tc.mul(&tb); + let mut t = FP2::new_copy(&w1); + t.add(&w2); + t.neg(); + tc.add(&t); + + ta.copy(&self.a.geta()); + ta.add(&self.b.geta()); + ta.norm(); + tb.copy(&y.a.geta()); + tb.add(&y.b.geta()); + tb.norm(); + let mut td = FP2::new_copy(&ta); + td.mul(&tb); + t.copy(&w1); + t.add(&w3); + t.neg(); + td.add(&t); + + ta.copy(&self.a.getb()); + ta.add(&self.b.geta()); + ta.norm(); + tb.copy(&y.a.getb()); + tb.add(&y.b.geta()); + tb.norm(); + let mut te = FP2::new_copy(&ta); + te.mul(&tb); + t.copy(&w2); + t.add(&w3); + t.neg(); + te.add(&t); + + w2.mul_ip(); + w1.add(&w2); + + self.a.set_fp2s(&w1, &tc); + self.b.set_fp2s(&td, &te); + self.c.set_fp2(&w3); + + self.a.norm(); + self.b.norm(); + } else { + let mut w1 = FP2::new_copy(&self.a.geta()); + let mut w2 = FP2::new_copy(&self.a.getb()); + // let mut w3=FP2::new_copy(&self.c.getb()); + let mut w3: FP2; + + w1.mul(&y.a.geta()); + w2.mul(&y.a.getb()); + + if y.stype == SPARSEST || self.stype == SPARSEST { + if y.stype == SPARSEST && self.stype == SPARSEST { + let mut t = FP::new_copy(&self.c.getb().getA()); + t.mul(&y.c.getb().getA()); + w3 = FP2::new_fp(&t); + } else if y.stype != SPARSEST { + w3 = FP2::new_copy(&y.c.getb()); + w3.pmul(&self.c.getb().getA()); + } else { + w3 = FP2::new_copy(&self.c.getb()); + w3.pmul(&y.c.getb().getA()); + } + } else { + w3 = FP2::new_copy(&self.c.getb()); + w3.mul(&y.c.getb()); + } + let mut ta = FP2::new_copy(&self.a.geta()); + let mut tb = FP2::new_copy(&y.a.geta()); + ta.add(&self.a.getb()); + ta.norm(); + tb.add(&y.a.getb()); + tb.norm(); + let mut tc = FP2::new_copy(&ta); + tc.mul(&tb); + let mut t = FP2::new_copy(&w1); + t.add(&w2); + t.neg(); + tc.add(&t); + + ta.copy(&self.a.geta()); + ta.add(&self.c.getb()); + ta.norm(); + tb.copy(&y.a.geta()); + tb.add(&y.c.getb()); + tb.norm(); + let mut td = FP2::new_copy(&ta); + td.mul(&tb); + t.copy(&w1); + t.add(&w3); + t.neg(); + td.add(&t); + + ta.copy(&self.a.getb()); + ta.add(&self.c.getb()); + ta.norm(); + tb.copy(&y.a.getb()); + tb.add(&y.c.getb()); + tb.norm(); + let mut te = FP2::new_copy(&ta); + te.mul(&tb); + t.copy(&w2); + t.add(&w3); + t.neg(); + te.add(&t); + + w2.mul_ip(); + w1.add(&w2); + self.a.set_fp2s(&w1, &tc); + + w3.mul_ip(); + w3.norm(); + self.b.set_fp2h(&w3); + + te.norm(); + te.mul_ip(); + self.c.set_fp2s(&te, &td); + + self.a.norm(); + self.c.norm(); + } + self.stype = SPARSE; + } + + /* self=1/self */ + pub fn inverse(&mut self) { + let mut f0 = FP4::new_copy(&self.a); + let mut f1 = FP4::new_copy(&self.b); + let mut f2 = FP4::new_copy(&self.a); + let mut f3 = FP4::new(); + + self.norm(); + f0.sqr(); + f1.mul(&self.c); + f1.times_i(); + f0.sub(&f1); + f0.norm(); + + f1.copy(&self.c); + f1.sqr(); + f1.times_i(); + f2.mul(&self.b); + f1.sub(&f2); + f1.norm(); + + f2.copy(&self.b); + f2.sqr(); + f3.copy(&self.a); + f3.mul(&self.c); + f2.sub(&f3); + f2.norm(); + + f3.copy(&self.b); + f3.mul(&f2); + f3.times_i(); + self.a.mul(&f0); + f3.add(&self.a); + self.c.mul(&f1); + self.c.times_i(); + + f3.add(&self.c); + f3.norm(); + f3.inverse(None); + self.a.copy(&f0); + self.a.mul(&f3); + self.b.copy(&f1); + self.b.mul(&f3); + self.c.copy(&f2); + self.c.mul(&f3); + self.stype = DENSE; + } + + /* self=self^p using Frobenius */ + pub fn frob(&mut self, f: &FP2) { + let mut f2 = FP2::new_copy(f); + let mut f3 = FP2::new_copy(f); + + f2.sqr(); + f3.mul(&f2); + + self.a.frob(&f3); + self.b.frob(&f3); + self.c.frob(&f3); + + self.b.pmul(f); + self.c.pmul(&f2); + self.stype = DENSE; + } + + /* trace function */ + pub fn trace(&mut self) -> FP4 { + let mut t = FP4::new(); + t.copy(&self.a); + t.imul(3); + t.reduce(); + t + } + + /* convert from byte array to FP12 */ + pub fn frombytes(w: &[u8]) -> FP12 { + const MB:usize = 4*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=w[i]; + } + let c=FP4::frombytes(&t); + for i in 0..MB { + t[i]=w[i+MB]; + } + let b=FP4::frombytes(&t); + for i in 0..MB { + t[i]=w[i+2*MB]; + } + let a=FP4::frombytes(&t); + FP12::new_fp4s(&a,&b,&c) + } + + /* convert this to byte array */ + pub fn tobytes(&mut self, w: &mut [u8]) { + const MB:usize = 4*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + + self.c.tobytes(&mut t); + for i in 0..MB { + w[i]=t[i]; + } + self.b.tobytes(&mut t); + for i in 0..MB { + w[i+MB]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + w[i+2*MB]=t[i]; + } + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!( + "[{},{},{}]", + self.a.tostring(), + self.b.tostring(), + self.c.tostring() + ) + } + +/* Note this is simple square and multiply, so not side-channel safe */ +/* But fast for final exponentiation where exponent is not a secret */ +/* return this^e */ + pub fn pow(&self, e: &BIG) -> FP12 { + let mut r = FP12::new_copy(self); + r.norm(); + let mut e1 = BIG::new_copy(e); + e1.norm(); + let mut e3 = BIG::new_copy(&e1); + e3.pmul(3); + e3.norm(); + let mut w = FP12::new_copy(&r); + if e3.iszilch() { + w.one(); + return w; + } + + let nb = e3.nbits(); + for i in (1..nb - 1).rev() { + w.usqr(); + let bt = e3.bit(i) - e1.bit(i); + if bt == 1 { + w.mul(&r); + } + if bt == -1 { + r.conj(); + w.mul(&r); + r.conj(); + } + } + + w.reduce(); + w + } + + /* constant time powering by small integer of max length bts */ + pub fn pinpow(&mut self, e: i32, bts: i32) { + let mut r: [FP12; 2] = [FP12::new_int(1), FP12::new_copy(self)]; + let mut t = FP12::new(); + + for i in (0..bts).rev() { + let b: usize = ((e >> i) & 1) as usize; + t.copy(&r[b]); + r[1 - b].mul(&t); + r[b].usqr(); + } + self.copy(&r[0]); + } + + pub fn compow(&mut self, e: &BIG, r: &BIG) -> FP4 { + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let q = BIG::new_ints(&rom::MODULUS); + + let mut g1 = FP12::new_copy(self); + let mut g2 = FP12::new_copy(self); + + let mut m = BIG::new_copy(&q); + m.rmod(&r); + + let mut a = BIG::new_copy(&e); + a.rmod(&m); + + let mut b = BIG::new_copy(&e); + b.div(&m); + + let mut c = g1.trace(); + + if b.iszilch() { + c = c.xtr_pow(&a); + return c; + } + + g2.frob(&f); + let cp = g2.trace(); + g1.conj(); + g2.mul(&g1); + let cpm1 = g2.trace(); + g2.mul(&g1); + let cpm2 = g2.trace(); + + c.xtr_pow2(&cp, &cpm1, &cpm2, &a, &b) + } + + /* p=q0^u0.q1^u1.q2^u2.q3^u3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + pub fn pow4(q: &[FP12], u: &[BIG]) -> FP12 { + let mut g: [FP12; 8] = [ + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + FP12::new(), + ]; + + let mut r = FP12::new(); + let mut p = FP12::new(); + const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); + let mut w: [i8; CT] = [0; CT]; + let mut s: [i8; CT] = [0; CT]; + + let mut mt = BIG::new(); + let mut t: [BIG; 4] = [ + BIG::new_copy(&u[0]), + BIG::new_copy(&u[1]), + BIG::new_copy(&u[2]), + BIG::new_copy(&u[3]), + ]; + + for i in 0..4 { + t[i].norm(); + } + + // precomputation + g[0].copy(&q[0]); + r.copy(&g[0]); + g[1].copy(&r); + g[1].mul(&q[1]); // q[0].q[1] + g[2].copy(&r); + g[2].mul(&q[2]); + r.copy(&g[1]); // q[0].q[2] + g[3].copy(&r); + g[3].mul(&q[2]); + r.copy(&g[0]); // q[0].q[1].q[2] + g[4].copy(&r); + g[4].mul(&q[3]); + r.copy(&g[1]); // q[0].q[3] + g[5].copy(&r); + g[5].mul(&q[3]); + r.copy(&g[2]); // q[0].q[1].q[3] + g[6].copy(&r); + g[6].mul(&q[3]); + r.copy(&g[3]); // q[0].q[2].q[3] + g[7].copy(&r); + g[7].mul(&q[3]); // q[0].q[1].q[2].q[3] + + // Make it odd + let pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for i in 0..4 { + mt.or(&t[i]); + } + + let nb = 1 + mt.nbits(); + + // Sign pivot + s[nb - 1] = 1; + for i in 0..nb - 1 { + t[0].fshr(1); + s[i] = (2 * t[0].parity() - 1) as i8; + //println!("s={}",s[i]); + } + + // Recoded exponent + for i in 0..nb { + w[i] = 0; + let mut k = 1; + for j in 1..4 { + let bt = s[i] * (t[j].parity() as i8); + t[j].fshr(1); + t[j].dec((bt >> 1) as isize); + t[j].norm(); + w[i] += bt * (k as i8); + k *= 2; + } + } + + // Main loop + p.selector(&g, (2 * w[nb - 1] + 1) as i32); + for i in (0..nb - 1).rev() { + p.usqr(); + r.selector(&g, (2 * w[i] + s[i]) as i32); + p.mul(&r); + } + + // apply correction + r.copy(&q[0]); + r.conj(); + r.mul(&p); + p.cmove(&r, pb); + p.reduce(); + p + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs new file mode 100644 index 000000000000..72eb05861457 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::dbig::DBIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::rom; + +use crate::rand::RAND; + +#[derive(Copy, Clone)] +pub struct FP2 { + a: FP, + b: FP, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP2 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP2 { + pub const fn new() -> FP2 { + FP2 { + a: FP::new(), + b: FP::new(), + } + } + + pub fn new_int(a: isize) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_int(a)); + f.b.zero(); + f + } + + pub fn new_ints(a: isize, b: isize) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_int(a)); + f.b.copy(&FP::new_int(b)); + f + } + + pub fn new_copy(x: &FP2) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f + } + + pub fn new_fps(c: &FP, d: &FP) -> FP2 { + let mut f = FP2::new(); + f.a.copy(c); + f.b.copy(d); + f + } + + pub fn new_bigs(c: &BIG, d: &BIG) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_big(c)); + f.b.copy(&FP::new_big(d)); + f + } + + pub fn new_fp(c: &FP) -> FP2 { + let mut f = FP2::new(); + f.a.copy(c); + f.b.zero(); + f + } + + pub fn new_big(c: &BIG) -> FP2 { + let mut f = FP2::new(); + f.a.copy(&FP::new_big(c)); + f.b.zero(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP2 { + FP2::new_fps(&FP::new_rand(rng),&FP::new_rand(rng)) + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + self.a.iszilch() && self.b.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + return 0; + } + let cmp=self.b.islarger(); + if cmp!=0 { + return cmp; + } + self.a.islarger() + } + + pub fn tobytes(&self,bf: &mut [u8]) { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + self.b.tobytes(&mut t); + for i in 0..MB { + bf[i]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + bf[i+MB]=t[i]; + } + } + + pub fn frombytes(bf: &[u8]) -> FP2 { + const MB:usize = big::MODBYTES as usize; + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=bf[i]; + } + let tb=FP::frombytes(&t); + for i in 0..MB { + t[i]=bf[i+MB]; + } + let ta=FP::frombytes(&t); + FP2::new_fps(&ta,&tb) + } + + pub fn cmove(&mut self, g: &FP2, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + } + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP::new_int(1); + self.a.equals(&one) && self.b.iszilch() + } + + /* test self=x */ + pub fn equals(&self, x: &FP2) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) + } + + /* extract a */ + #[allow(non_snake_case)] + pub fn getA(&mut self) -> FP { + self.a + } + + /* extract b */ + #[allow(non_snake_case)] + pub fn getB(&mut self) -> FP { + self.b + } + + /* extract a */ + pub fn geta(&mut self) -> BIG { + self.a.redc() + } + + /* extract b */ + pub fn getb(&mut self) -> BIG { + self.b.redc() + } + + /* copy self=x */ + pub fn copy(&mut self, x: &FP2) { + self.a.copy(&x.a); + self.b.copy(&x.b); + } + + pub fn set_fp(&mut self, x: &FP) { + self.a.copy(x); + self.b.zero(); + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + } + + pub fn sign(&self) -> isize { + let mut p1=self.a.sign(); + let mut p2=self.b.sign(); + if fp::BIG_ENDIAN_SIGN { + let u=self.b.iszilch() as isize; + p2^=(p1^p2)&u; + p2 + } else { + let u=self.a.iszilch() as isize; + p1^=(p1^p2)&u; + p1 + } + } + + /* negate self mod Modulus */ + pub fn neg(&mut self) { + let mut m = FP::new_copy(&self.a); + let mut t = FP::new(); + + m.add(&self.b); + m.neg(); + t.copy(&m); + t.add(&self.b); + self.b.copy(&m); + self.b.add(&self.a); + self.a.copy(&t); + } + + /* set to a-ib */ + pub fn conj(&mut self) { + self.b.neg(); + self.b.norm(); + } + + /* self+=a */ + pub fn add(&mut self, x: &FP2) { + self.a.add(&x.a); + self.b.add(&x.b); + } + + pub fn dbl(&mut self) { + self.a.dbl(); + self.b.dbl(); + } + + /* self-=a */ + pub fn sub(&mut self, x: &FP2) { + let mut m = FP2::new_copy(x); + m.neg(); + self.add(&m); + } + + /* self=a-self */ + pub fn rsub(&mut self, x: &FP2) { + self.neg(); + self.add(x); + } + + /* self*=s, where s is an FP */ + pub fn pmul(&mut self, s: &FP) { + self.a.mul(s); + self.b.mul(s); + } + + /* self*=i, where i is an int */ + pub fn imul(&mut self, c: isize) { + self.a.imul(c); + self.b.imul(c); + } + + /* self*=self */ + pub fn sqr(&mut self) { + let mut w1 = FP::new_copy(&self.a); + let mut w3 = FP::new_copy(&self.a); + let mut mb = FP::new_copy(&self.b); + + w1.add(&self.b); + + w3.add(&self.a); + w3.norm(); + self.b.mul(&w3); + + mb.neg(); + self.a.add(&mb); + + w1.norm(); + self.a.norm(); + + self.a.mul(&w1); + } + + /* this*=y */ + pub fn mul(&mut self, y: &FP2) { + if ((self.a.xes + self.b.xes) as i64) * ((y.a.xes + y.b.xes) as i64) > fp::FEXCESS as i64 { + if self.a.xes > 1 { + self.a.reduce() + } + if self.b.xes > 1 { + self.b.reduce() + } + } + + let p = BIG::new_ints(&rom::MODULUS); + let mut pr = DBIG::new(); + + pr.ucopy(&p); + + let mut c = BIG::new_copy(&(self.a.x)); + let mut d = BIG::new_copy(&(y.a.x)); + + let mut a = BIG::mul(&self.a.x, &y.a.x); + let mut b = BIG::mul(&self.b.x, &y.b.x); + + c.add(&self.b.x); + c.norm(); + d.add(&y.b.x); + d.norm(); + + let mut e = BIG::mul(&c, &d); + let mut f = DBIG::new_copy(&a); + f.add(&b); + b.rsub(&pr); + + a.add(&b); + a.norm(); + e.sub(&f); + e.norm(); + + self.a.x.copy(&FP::modulo(&mut a)); + self.a.xes = 3; + self.b.x.copy(&FP::modulo(&mut e)); + self.b.xes = 2; + } +/* + pub fn pow(&mut self, e: &BIG) { + let mut w = FP2::new_copy(self); + let mut z = BIG::new_copy(&e); + let mut r = FP2::new_int(1); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + self.copy(&r); + }*/ + + pub fn qr(&mut self,h:Option<&mut FP>) -> isize { + let mut c=FP2::new_copy(self); + c.conj(); + c.mul(self); + c.getA().qr(h) + } + + /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ + pub fn sqrt(&mut self,h:Option<&FP>) { + if self.iszilch() { + return; + } + let mut w1 = FP::new_copy(&self.b); + let mut w2 = FP::new_copy(&self.a); + let mut w3 = FP::new_copy(&self.a); + let mut w4 = FP::new(); + let mut hint = FP::new(); + + w1.sqr(); + w2.sqr(); + w1.add(&w2); w1.norm(); + + w2.copy(&w1.sqrt(h)); + w1.copy(&w2); + + w2.copy(&self.a); + w2.add(&w1); + w2.norm(); + w2.div2(); + + w1.copy(&self.b); w1.div2(); + let qr=w2.qr(Some(&mut hint)); + +// tweak hint + w3.copy(&hint); w3.neg(); w3.norm(); + w4.copy(&w2); w4.neg(); w4.norm(); + + w2.cmove(&w4,1-qr); + hint.cmove(&w3,1-qr); + + self.a.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&self.a); + self.b.copy(&w3); self.b.mul(&w1); + w4.copy(&self.a); + + self.a.cmove(&self.b,1-qr); + self.b.cmove(&w4,1-qr); + +/* + self.a.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&self.a); + self.b.copy(&w3); self.b.mul(&w1); + + hint.neg(); hint.norm(); + w2.neg(); w2.norm(); + + w4.copy(&w2.sqrt(Some(&hint))); + w3.copy(&w2); w3.inverse(Some(&hint)); + w3.mul(&w4); + w3.mul(&w1); + + self.a.cmove(&w3,1-qr); + self.b.cmove(&w4,1-qr); +*/ + let sgn=self.sign(); + let mut nr=FP2::new_copy(&self); + nr.neg(); nr.norm(); + self.cmove(&nr,sgn); + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!("[{},{}]", self.a.tostring(), self.b.tostring()) + } + + /* self=1/self */ + pub fn inverse(&mut self,h:Option<&FP>) { + self.norm(); + let mut w1 = FP::new_copy(&self.a); + let mut w2 = FP::new_copy(&self.b); + + w1.sqr(); + w2.sqr(); + w1.add(&w2); + w1.inverse(h); + self.a.mul(&w1); + w1.neg(); + w1.norm(); + self.b.mul(&w1); + } + + /* self/=2 */ + pub fn div2(&mut self) { + self.a.div2(); + self.b.div2(); + } + + /* self*=sqrt(-1) */ + pub fn times_i(&mut self) { + let z = FP::new_copy(&self.a); + self.a.copy(&self.b); + self.a.neg(); + self.b.copy(&z); + } + + /* w*=(1+sqrt(-1)) */ + /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ + pub fn mul_ip(&mut self) { + let mut t = FP2::new_copy(self); + let mut i = fp::QNRI; + self.times_i(); + while i > 0 { + t.dbl(); + t.norm(); + i -= 1; + } + self.add(&t); + if fp::TOWER == fp::POSITOWER { + self.norm(); + self.neg(); + } + } + + /* w/=(1+sqrt(-1)) */ + pub fn div_ip(&mut self) { + let mut z = FP2::new_ints(1 << fp::QNRI, 1); + z.inverse(None); + self.norm(); + self.mul(&z); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs new file mode 100644 index 000000000000..1f36040c7c20 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::fp; +use crate::bn254::fp::FP; +use crate::bn254::fp2::FP2; +use crate::rand::RAND; +#[allow(unused_imports)] +use crate::bn254::rom; + +#[derive(Copy, Clone)] +pub struct FP4 { + a: FP2, + b: FP2, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for FP4 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for FP4 { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "{}", self.tostring()) + } +} + +impl FP4 { + pub const fn new() -> FP4 { + FP4 { + a: FP2::new(), + b: FP2::new(), + } + } + + pub fn new_int(a: isize) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&FP2::new_int(a)); + f.b.zero(); + f + } + + pub fn new_ints(a: isize,b: isize) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&FP2::new_int(a)); + f.b.copy(&FP2::new_int(b)); + f + } + + pub fn new_copy(x: &FP4) -> FP4 { + let mut f = FP4::new(); + f.a.copy(&x.a); + f.b.copy(&x.b); + f + } + + pub fn new_fp2s(c: &FP2, d: &FP2) -> FP4 { + let mut f = FP4::new(); + f.a.copy(c); + f.b.copy(d); + f + } + + pub fn new_fp2(c: &FP2) -> FP4 { + let mut f = FP4::new(); + f.a.copy(c); + f.b.zero(); + f + } + + pub fn new_fp(c: &FP) -> FP4 { + let mut f = FP4::new(); + f.a.set_fp(c); + f.b.zero(); + f + } + + pub fn new_rand(rng: &mut RAND) -> FP4 { + FP4::new_fp2s(&FP2::new_rand(rng),&FP2::new_rand(rng)) + } + + pub fn set_fp2s(&mut self, c: &FP2, d: &FP2) { + self.a.copy(&c); + self.b.copy(&d); + } + + pub fn set_fp(&mut self, c: &FP) { + self.a.set_fp(&c); + self.b.zero(); + } + + pub fn set_fp2(&mut self, c: &FP2) { + self.a.copy(&c); + self.b.zero(); + } + + pub fn set_fp2h(&mut self, c: &FP2) { + self.b.copy(&c); + self.a.zero(); + } + + /* reduce components mod Modulus */ + pub fn reduce(&mut self) { + self.a.reduce(); + self.b.reduce(); + } + + /* normalise components of w */ + pub fn norm(&mut self) { + self.a.norm(); + self.b.norm(); + } + + pub fn cmove(&mut self, g: &FP4, d: isize) { + self.a.cmove(&g.a, d); + self.b.cmove(&g.b, d); + } + + /* test self=0 ? */ + pub fn iszilch(&self) -> bool { + self.a.iszilch() && self.b.iszilch() + } + + pub fn islarger(&self) -> isize { + if self.iszilch() { + 0 + } else { + let cmp=self.b.islarger(); + if cmp!=0 { + cmp + } else { + self.a.islarger() + } + } + } + + pub fn tobytes(&self,bf: &mut [u8]) { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + self.b.tobytes(&mut t); + for i in 0..MB { + bf[i]=t[i]; + } + self.a.tobytes(&mut t); + for i in 0..MB { + bf[i+MB]=t[i]; + } + } + + pub fn frombytes(bf: &[u8]) -> FP4 { + const MB:usize = 2*(big::MODBYTES as usize); + let mut t: [u8; MB] = [0; MB]; + for i in 0..MB { + t[i]=bf[i]; + } + let tb=FP2::frombytes(&t); + for i in 0..MB { + t[i]=bf[i+MB]; + } + let ta=FP2::frombytes(&t); + FP4::new_fp2s(&ta,&tb) + } + + + + /* test self=1 ? */ + pub fn isunity(&self) -> bool { + let one = FP2::new_int(1); + self.a.equals(&one) && self.b.iszilch() + } + + /* test is w real? That is in a+ib test b is zero */ + pub fn isreal(&mut self) -> bool { + self.b.iszilch() + } + /* extract real part a */ + pub fn real(&self) -> FP2 { + FP2::new_copy(&self.a) + } + + pub fn geta(&self) -> FP2 { + FP2::new_copy(&self.a) + } + /* extract imaginary part b */ + pub fn getb(&self) -> FP2 { + FP2::new_copy(&self.b) + } + + /* test self=x */ + pub fn equals(&self, x: &FP4) -> bool { + self.a.equals(&x.a) && self.b.equals(&x.b) + } + /* copy self=x */ + pub fn copy(&mut self, x: &FP4) { + self.a.copy(&x.a); + self.b.copy(&x.b); + } + + /* set self=0 */ + pub fn zero(&mut self) { + self.a.zero(); + self.b.zero(); + } + + /* set self=1 */ + pub fn one(&mut self) { + self.a.one(); + self.b.zero(); + } + + pub fn sign(&self) -> isize { + let mut p1=self.a.sign(); + let mut p2=self.b.sign(); + if fp::BIG_ENDIAN_SIGN { + let u=self.b.iszilch() as isize; + p2^=(p1^p2)&u; + p2 + } else { + let u=self.a.iszilch() as isize; + p1^=(p1^p2)&u; + p1 + } + } + + /* negate self mod Modulus */ + pub fn neg(&mut self) { + self.norm(); + let mut m = FP2::new_copy(&self.a); + let mut t = FP2::new(); + + m.add(&self.b); + m.neg(); + t.copy(&m); + t.add(&self.b); + self.b.copy(&m); + self.b.add(&self.a); + self.a.copy(&t); + self.norm(); + } + + /* set to a-ib */ + pub fn conj(&mut self) { + self.b.neg(); + self.norm(); + } + + /* self=-conjugate(self) */ + pub fn nconj(&mut self) { + self.a.neg(); + self.norm(); + } + + /* self+=a */ + pub fn add(&mut self, x: &FP4) { + self.a.add(&x.a); + self.b.add(&x.b); + } + + pub fn padd(&mut self, x: &FP2) { + self.a.add(x); + } + + pub fn dbl(&mut self) { + self.a.dbl(); + self.b.dbl(); + } + + /* self-=a */ + pub fn sub(&mut self, x: &FP4) { + let mut m = FP4::new_copy(x); + m.neg(); + self.add(&m); + } + + /* self-=a */ + pub fn rsub(&mut self, x: &FP4) { + self.neg(); + self.add(x); + } + + /* self*=s, where s is an FP2 */ + pub fn pmul(&mut self, s: &FP2) { + self.a.mul(s); + self.b.mul(s); + } + + /* self*=s, where s is an FP */ + pub fn qmul(&mut self, s: &FP) { + self.a.pmul(s); + self.b.pmul(s); + } + + /* self*=i, where i is an int */ + pub fn imul(&mut self, c: isize) { + self.a.imul(c); + self.b.imul(c); + } + + /* self*=self */ + + pub fn sqr(&mut self) { + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + let mut t3 = FP2::new_copy(&self.a); + + t3.mul(&self.b); + t1.add(&self.b); + t2.mul_ip(); + + t2.add(&self.a); + + t1.norm(); + t2.norm(); + + self.a.copy(&t1); + + self.a.mul(&t2); + + t2.copy(&t3); + t2.mul_ip(); + t2.add(&t3); + t2.norm(); + t2.neg(); + self.a.add(&t2); + + t3.dbl(); + self.b.copy(&t3); + + self.norm(); + } + + /* self*=y */ + pub fn mul(&mut self, y: &FP4) { + //self.norm(); + + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + let mut t3 = FP2::new(); + let mut t4 = FP2::new_copy(&self.b); + + t1.mul(&y.a); + t2.mul(&y.b); + t3.copy(&y.b); + t3.add(&y.a); + t4.add(&self.a); + + t3.norm(); + t4.norm(); + + t4.mul(&t3); + + t3.copy(&t1); + t3.neg(); + t4.add(&t3); + t4.norm(); + + t3.copy(&t2); + t3.neg(); + self.b.copy(&t4); + self.b.add(&t3); + + t2.mul_ip(); + self.a.copy(&t2); + self.a.add(&t1); + + self.norm(); + } + + /* output to hex string */ + #[cfg(feature = "std")] + pub fn tostring(&self) -> String { + format!("[{},{}]", self.a.tostring(), self.b.tostring()) + } + + /* self=1/self */ + pub fn inverse(&mut self,h:Option<&FP>) { + //self.norm(); + + let mut t1 = FP2::new_copy(&self.a); + let mut t2 = FP2::new_copy(&self.b); + + t1.sqr(); + t2.sqr(); + t2.mul_ip(); + t2.norm(); + t1.sub(&t2); + t1.inverse(h); + self.a.mul(&t1); + t1.neg(); + t1.norm(); + self.b.mul(&t1); + } + + /* self*=i where i = sqrt(-1+sqrt(-1)) */ + pub fn times_i(&mut self) { + let mut t = FP2::new_copy(&self.b); + self.b.copy(&self.a); + t.mul_ip(); + self.a.copy(&t); + self.norm(); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } + + /* self=self^p using Frobenius */ + pub fn frob(&mut self, f: &FP2) { + self.a.conj(); + self.b.conj(); + self.b.mul(f); + } + + /* return this^e */ +/* + pub fn pow(&self, e: &BIG) -> FP4 { + let mut w = FP4::new_copy(self); + w.norm(); + let mut z = BIG::new_copy(&e); + let mut r = FP4::new_int(1); + z.norm(); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + r + } +*/ + /* XTR xtr_a function */ + pub fn xtr_a(&mut self, w: &FP4, y: &FP4, z: &FP4) { + let mut r = FP4::new_copy(w); + let mut t = FP4::new_copy(w); + r.sub(y); + r.norm(); + r.pmul(&self.a); + t.add(y); + t.norm(); + t.pmul(&self.b); + t.times_i(); + + self.copy(&r); + self.add(&t); + self.add(z); + + self.norm(); + } + + /* XTR xtr_d function */ + pub fn xtr_d(&mut self) { + let mut w = FP4::new_copy(self); + self.sqr(); + w.conj(); + w.dbl(); + w.norm(); + self.sub(&w); + self.reduce(); + } + + /* r=x^n using XTR method on traces of FP12s */ + pub fn xtr_pow(&self, n: &BIG) -> FP4 { + let mut sf = FP4::new_copy(self); + sf.norm(); + let mut a = FP4::new_int(3); + let mut b = FP4::new_copy(&sf); + let mut c = FP4::new_copy(&b); + c.xtr_d(); + let mut t = FP4::new(); + let mut r = FP4::new(); + + let par = n.parity(); + let mut v = BIG::new_copy(n); + v.norm(); + v.fshr(1); + if par == 0 { + v.dec(1); + v.norm(); + } + + let nb = v.nbits(); + for i in (0..nb).rev() { + if v.bit(i) != 1 { + t.copy(&b); + sf.conj(); + c.conj(); + b.xtr_a(&a, &sf, &c); + sf.conj(); + c.copy(&t); + c.xtr_d(); + a.xtr_d(); + } else { + t.copy(&a); + t.conj(); + a.copy(&b); + a.xtr_d(); + b.xtr_a(&c, &sf, &t); + c.xtr_d(); + } + } + if par == 0 { + r.copy(&c) + } else { + r.copy(&b) + } + r.reduce(); + r + } + + /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ + pub fn xtr_pow2(&mut self, ck: &FP4, ckml: &FP4, ckm2l: &FP4, a: &BIG, b: &BIG) -> FP4 { + let mut e = BIG::new_copy(a); + let mut d = BIG::new_copy(b); + let mut w = BIG::new(); + e.norm(); + d.norm(); + + let mut cu = FP4::new_copy(ck); // can probably be passed in w/o copying + let mut cv = FP4::new_copy(self); + let mut cumv = FP4::new_copy(ckml); + let mut cum2v = FP4::new_copy(ckm2l); + let mut r = FP4::new(); + let mut t = FP4::new(); + + let mut f2: usize = 0; + while d.parity() == 0 && e.parity() == 0 { + d.fshr(1); + e.fshr(1); + f2 += 1; + } + + while BIG::comp(&d, &e) != 0 { + if BIG::comp(&d, &e) > 0 { + w.copy(&e); + w.imul(4); + w.norm(); + if BIG::comp(&d, &w) <= 0 { + w.copy(&d); + d.copy(&e); + e.rsub(&w); + e.norm(); + + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cum2v.copy(&cumv); + cum2v.conj(); + cumv.copy(&cv); + cv.copy(&cu); + cu.copy(&t); + } else if d.parity() == 0 { + d.fshr(1); + r.copy(&cum2v); + r.conj(); + t.copy(&cumv); + t.xtr_a(&cu, &cv, &r); + cum2v.copy(&cumv); + cum2v.xtr_d(); + cumv.copy(&t); + cu.xtr_d(); + } else if e.parity() == 1 { + d.sub(&e); + d.norm(); + d.fshr(1); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cu.xtr_d(); + cum2v.copy(&cv); + cum2v.xtr_d(); + cum2v.conj(); + cv.copy(&t); + } else { + w.copy(&d); + d.copy(&e); + d.fshr(1); + e.copy(&w); + t.copy(&cumv); + t.xtr_d(); + cumv.copy(&cum2v); + cumv.conj(); + cum2v.copy(&t); + cum2v.conj(); + t.copy(&cv); + t.xtr_d(); + cv.copy(&cu); + cu.copy(&t); + } + } + if BIG::comp(&d, &e) < 0 { + w.copy(&d); + w.imul(4); + w.norm(); + if BIG::comp(&e, &w) <= 0 { + e.sub(&d); + e.norm(); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cum2v.copy(&cumv); + cumv.copy(&cu); + cu.copy(&t); + } else if e.parity() == 0 { + w.copy(&d); + d.copy(&e); + d.fshr(1); + e.copy(&w); + t.copy(&cumv); + t.xtr_d(); + cumv.copy(&cum2v); + cumv.conj(); + cum2v.copy(&t); + cum2v.conj(); + t.copy(&cv); + t.xtr_d(); + cv.copy(&cu); + cu.copy(&t); + } else if d.parity() == 1 { + w.copy(&e); + e.copy(&d); + w.sub(&d); + w.norm(); + d.copy(&w); + d.fshr(1); + t.copy(&cv); + t.xtr_a(&cu, &cumv, &cum2v); + cumv.conj(); + cum2v.copy(&cu); + cum2v.xtr_d(); + cum2v.conj(); + cu.copy(&cv); + cu.xtr_d(); + cv.copy(&t); + } else { + d.fshr(1); + r.copy(&cum2v); + r.conj(); + t.copy(&cumv); + t.xtr_a(&cu, &cv, &r); + cum2v.copy(&cumv); + cum2v.xtr_d(); + cumv.copy(&t); + cu.xtr_d(); + } + } + } + r.copy(&cv); + r.xtr_a(&cu, &cumv, &cum2v); + for _ in 0..f2 { + r.xtr_d() + } + r = r.xtr_pow(&d); + r + } + + /* this/=2 */ + pub fn div2(&mut self) { + self.a.div2(); + self.b.div2(); + } + + pub fn div_i(&mut self) { + let mut u = FP2::new_copy(&self.a); + let v = FP2::new_copy(&self.b); + u.div_ip(); + self.a.copy(&v); + self.b.copy(&u); + if fp::TOWER == fp::POSITOWER { + self.neg(); + self.norm(); + } + } +/* + pub fn pow(&mut self, e: &BIG) { + let mut w = FP4::new_copy(self); + let mut z = BIG::new_copy(&e); + let mut r = FP4::new_int(1); + loop { + let bt = z.parity(); + z.fshr(1); + if bt == 1 { + r.mul(&mut w) + }; + if z.iszilch() { + break; + } + w.sqr(); + } + r.reduce(); + self.copy(&r); + } +*/ + +/* PFGE24S + + pub fn qr(&mut self,h:Option<&mut FP>) -> isize { + let mut c=FP4::new_copy(self); + c.conj(); + c.mul(self); + c.geta().qr(h) + } + + // sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) + // returns true if this is QR + pub fn sqrt(&mut self,h:Option<&FP>) { + if self.iszilch() { + return; + } + + let mut a = FP2::new_copy(&self.a); + let mut b = FP2::new_copy(&self.a); + let mut s = FP2::new_copy(&self.b); + let mut t = FP2::new_copy(&self.a); + let mut hint = FP::new(); + + s.sqr(); + a.sqr(); + s.mul_ip(); + s.norm(); + a.sub(&s); + + s.copy(&a); s.norm(); + + s.sqrt(h); + + a.copy(&t); + a.add(&s); + a.norm(); + a.div2(); + + + b.copy(&self.b); b.div2(); + let qr=a.qr(Some(&mut hint)); + + +// tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial + s.copy(&a); + let mut twk = FP::new_big(&BIG::new_ints(&rom::TWK)); + twk.mul(&hint); + s.div_ip(); s.norm(); + + a.cmove(&s,1-qr); + hint.cmove(&twk,1-qr); + + self.a.copy(&a); self.a.sqrt(Some(&hint)); + s.copy(&a); s.inverse(Some(&hint)); + s.mul(&self.a); + self.b.copy(&s); self.b.mul(&b); + t.copy(&self.a); + + self.a.cmove(&self.b,1-qr); + self.b.cmove(&t,1-qr); + + let sgn=self.sign(); + let mut nr=FP4::new_copy(&self); + nr.neg(); nr.norm(); + self.cmove(&nr,sgn); + } +PFGE24F */ +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs new file mode 100644 index 000000000000..6aa0b7ce0f19 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::ecp; +use crate::bn254::ecdh; + +use crate::hmac; +use crate::rand::RAND; + +const GROUP: usize = ecdh::EGS; +const POINT: usize = 2*ecdh::EFS+1; + +const MAX_LABEL: usize = 20; // may need adjustment + +#[allow(non_snake_case)] +fn reverse (x: &mut [u8]) { + let lx=x.len(); + for i in 0..lx/2 { + let ch=x[i]; + x[i]=x[lx-i-1]; + x[lx-i-1]=ch; + } +} +/* +fn printbinary(array: &[u8]) { + for i in 0..array.len() { + print!("{:02X}", array[i]) + } + println!("") +} +*/ + +#[allow(non_snake_case)] +fn labeledExtract(prk: &mut [u8],salt: Option<&[u8]>,suite_id: &[u8],label: &str,ikm: Option<&[u8]>) { + let rfc="HPKE-v1"; + let prefix1=rfc.as_bytes(); + let prefix2=label.as_bytes(); + let mut likm: [u8; 18+MAX_LABEL+2*POINT] = [0; 18+MAX_LABEL+2*POINT]; + let mut k=0; + for i in 0..prefix1.len() { + likm[k]=prefix1[i]; + k+=1; + } + for i in 0..suite_id.len() { + likm[k]=suite_id[i]; + k+=1; + } + for i in 0..prefix2.len() { + likm[k]=prefix2[i]; + k+=1; + } + if let Some(sikm) = ikm { + for i in 0..sikm.len() { + likm[k]=sikm[i]; + k+=1; + } + } + hmac::hkdf_extract(hmac::MC_SHA2,ecp::HASH_TYPE,prk,salt,&likm[0..k]); +} + +#[allow(non_snake_case)] +fn labeledExpand(okm: &mut [u8],prk: &[u8],suite_id: &[u8],label: &str,info: Option<&[u8]>,el: usize) { + let mut ar: [u8; 2] = [0; 2]; + let rfc="HPKE-v1"; + let prefix1=rfc.as_bytes(); + let prefix2=label.as_bytes(); + hmac::inttobytes(el,&mut ar); + let mut linfo: [u8; 20+MAX_LABEL+3*POINT] = [0; 20+MAX_LABEL+3*POINT]; + linfo[0]=ar[0]; + linfo[1]=ar[1]; + let mut k=2; + for i in 0..prefix1.len() { + linfo[k]=prefix1[i]; + k+=1; + } + for i in 0..suite_id.len() { + linfo[k]=suite_id[i]; + k+=1; + } + for i in 0..prefix2.len() { + linfo[k]=prefix2[i]; + k+=1; + } + if let Some(sinfo) = info { + for i in 0..sinfo.len() { + linfo[k]=sinfo[i]; + k+=1; + } + } + hmac:: hkdf_expand(hmac::MC_SHA2,ecp::HASH_TYPE,okm,el,prk,&linfo[0..k]); +} + +#[allow(non_snake_case)] +fn extractAndExpand(config_id: usize,okm: &mut [u8],dh: &[u8],context: &[u8]) { + let kem = config_id&255; + let txt="KEM"; + let mut suite_id: [u8;5] = [0;5]; + let mut kem_id: [u8; 2] = [0; 2]; + let ckem=txt.as_bytes(); + hmac::inttobytes(kem,&mut kem_id); + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + suite_id[k]=kem_id[0]; k+=1; + suite_id[k]=kem_id[1]; + + let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; + labeledExtract(&mut prk,None,&suite_id,"eae_prk",Some(dh)); + labeledExpand(okm,&prk,&suite_id,"shared_secret",Some(&context),ecp::HASH_TYPE); +} + +#[allow(non_snake_case)] +pub fn deriveKeyPair(config_id: usize,mut sk: &mut [u8],mut pk: &mut [u8],seed: &[u8]) -> bool { + let mut counter=0; + let kem = config_id&255; + let txt="KEM"; + let mut suite_id: [u8;5] = [0;5]; + let mut kem_id: [u8; 2] = [0; 2]; + let ckem=txt.as_bytes(); + hmac::inttobytes(kem,&mut kem_id); + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + suite_id[k]=kem_id[0]; k+=1; + suite_id[k]=kem_id[1]; + + let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; + labeledExtract(&mut prk,None,&suite_id,"dkp_prk",Some(&seed)); + + //println!("prk= {:02X?}",prk); + + if kem==32 || kem==33 { // RFC7748 + labeledExpand(&mut sk,&prk,&suite_id,"sk",None,GROUP); + reverse(&mut sk); + if kem==32 { + sk[GROUP-1]&=248; + sk[0]&=127; + sk[0]|=64; + } else { + sk[GROUP-1]&=252; + sk[0]|=128; + } + } else { + let mut bit_mask=0xff; + if kem==18 { + bit_mask=1; + } + for i in 0..GROUP { + sk[i]=0; + } + while !ecdh::in_range(&sk) && counter<256 { + let mut info: [u8;1]=[0;1]; + info[0]=counter as u8; + labeledExpand(sk,&prk,&suite_id,"candidate",Some(&info),GROUP); + sk[0] &= bit_mask as u8; + counter += 1; + } + } + //for i in 0..sk.len() { +// print!({} +// println!("SK= {:02X?}",sk); + // println!("kem= {}",kem); + //println!("counter= {}",counter); + ecdh::key_pair_generate(None::<&mut RAND>, &mut sk, &mut pk); + if kem==32 || kem==33 { + reverse(&mut pk); + } + counter<256 +} + +#[allow(non_snake_case)] +pub fn encap(config_id: usize,skE: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { + let pklen=pkE.len(); + let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; + let kem = config_id&255; + let mut rev: [u8; POINT]=[0; POINT]; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkR[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); + reverse(&mut dh[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); + } + let mut k=0; + for i in 0..pklen { + kemcontext[k]=pkE[i]; + k+=1; + } + for i in 0..pklen { + kemcontext[k]=pkR[i]; + k+=1; + } +//print!("e dh= "); printbinary(&dh[0..pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); +} + +#[allow(non_snake_case)] +pub fn decap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { + let pklen=pkE.len(); + let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; + let mut rev: [u8; POINT]=[0; POINT]; + let kem = config_id&255; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkE[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); + reverse(&mut dh[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); + } + + let mut k=0; + for i in 0..pklen { + kemcontext[k]=pkE[i]; + k+=1; + } + for i in 0..pklen { // not a mistake + kemcontext[k]=pkR[i]; + k+=1; + } +//print!("d dh= "); printbinary(&dh[0..pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); +} + +#[allow(non_snake_case)] +pub fn authencap(config_id: usize,skE: &[u8],skS: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { + let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; + let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; + + let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; + let kem = config_id&255; + let pklen=pkE.len(); + let mut rev: [u8; POINT]=[0; POINT]; + + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkR[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); + ecdh::ecpsvdp_dh(&skS, &rev[0..pklen], &mut dh1, 0); + reverse(&mut dh[0..pklen]); + reverse(&mut dh1[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); + ecdh::ecpsvdp_dh(&skS, &pkR, &mut dh1, 0); + } + + for i in 0..ecdh::EFS { + dh[i+ecdh::EFS] = dh1[i]; + } + + for i in 0..pklen { + kemcontext[i]=pkE[i]; + kemcontext[pklen+i]= pkR[i]; + kemcontext[2*pklen+i]= pkS[i]; + } +//print!("e dh= "); printbinary(&dh[0..pklen]); +//print!("e kemcontext= "); printbinary(&kemcontext[0..3*pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); +} + +#[allow(non_snake_case)] +pub fn authdecap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { + let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; + let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; + let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; + let kem = config_id&255; + let pklen=pkE.len(); + let mut rev: [u8; POINT]=[0; POINT]; + + if kem==32 || kem==33 { + for i in 0..pklen { + rev[i]=pkE[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); + for i in 0..pklen { + rev[i]=pkS[i]; + } + reverse(&mut rev[0..pklen]); + ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh1, 0); + reverse(&mut dh[0..pklen]); + reverse(&mut dh1[0..pklen]); + } else { + ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); + ecdh::ecpsvdp_dh(&skR, &pkS, &mut dh1, 0); + } + + for i in 0..ecdh::EFS { + dh[i+ecdh::EFS] = dh1[i]; + } + + for i in 0..pklen { + kemcontext[i]=pkE[i]; + kemcontext[pklen+i]= pkR[i]; + kemcontext[2*pklen+i]= pkS[i]; + } +//print!("d dh= "); printbinary(&dh[0..pklen]); +//print!("d kemcontext= "); printbinary(&kemcontext[0..3*pklen]); + extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); +} + +#[allow(non_snake_case)] +pub fn keyschedule(config_id: usize,key: &mut [u8],nonce: &mut [u8],exp_secret: &mut [u8],mode: usize,z: &mut [u8],info: &[u8],psk: Option<&[u8]>,pskID: Option<&[u8]>) { + + let mut context: [u8; 1+2*ecp::HASH_TYPE] = [0; 1+2*ecp::HASH_TYPE]; + let kem=config_id&255; + let kdf=(config_id>>8)&3; + let aead=(config_id>>10)&3; + + let txt="HPKE"; + let ckem=txt.as_bytes(); + let mut suite_id: [u8;10] = [0;10]; + let mut num: [u8; 2] = [0; 2]; + + let mut k=0; + for i in 0..ckem.len() { + suite_id[k]=ckem[i]; + k+=1; + } + hmac::inttobytes(kem,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; k+=1; + hmac::inttobytes(kdf,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; k+=1; + hmac::inttobytes(aead,&mut num); + suite_id[k]=num[0]; k+=1; + suite_id[k]=num[1]; + + let mut k=0; + let mut h: [u8; 64] = [0; 64]; + let mut secret: [u8; 64] = [0; 64]; + + context[k]=mode as u8; k+=1; + + labeledExtract(&mut h,None,&suite_id,"psk_id_hash",pskID); + for i in 0..ecp::HASH_TYPE { + context[k] = h[i]; k+=1; + } + labeledExtract(&mut h,None,&suite_id,"info_hash",Some(&info)); + for i in 0..ecp::HASH_TYPE { + context[k] = h[i]; k+=1; + } + + //labeledExtract(&mut h,None,&suite_id,"psk_hash",psk); + + //labeledExtract(&mut secret,Some(&h),&suite_id,"secret",Some(z)); + + labeledExtract(&mut secret,Some(z),&suite_id,"secret",psk); + + labeledExpand(key,&secret,&suite_id,"key",Some(&context[0..k]),ecp::AESKEY); + labeledExpand(nonce,&secret,&suite_id,"base_nonce",Some(&context[0..k]),12); + labeledExpand(exp_secret,&secret,&suite_id,"exp",Some(&context[0..k]),ecp::HASH_TYPE); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs new file mode 100644 index 000000000000..89eca15de70e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pub mod big; +pub mod bls; +pub mod dbig; +pub mod ecp; +pub mod ecp2; +pub mod fp; +pub mod fp12; +pub mod fp2; +pub mod fp4; +pub mod mpin; +pub mod pair; +pub mod rom; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs new file mode 100644 index 000000000000..3b3121e5dda5 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big; +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::ecp2::ECP2; +use crate::bn254::fp12::FP12; +use crate::bn254::pair; +use crate::bn254::rom; +use crate::bn254::fp::FP; +use crate::bn254::dbig::DBIG; + +use crate::hmac; +use crate::rand::RAND; + +/* MPIN 128-bit API Functions */ + +/* Configure mode of operation */ + +pub const EFS: usize = big::MODBYTES as usize; +pub const EGS: usize = big::MODBYTES as usize; +pub const BAD_PARAMS: isize = -11; +pub const INVALID_POINT: isize = -14; +pub const WRONG_ORDER: isize = -18; +pub const BAD_PIN: isize = -19; +pub const SHA256: usize = 32; +pub const SHA384: usize = 48; +pub const SHA512: usize = 64; + +/* Configure your PIN here */ + +pub const MAXPIN: i32 = 10000; /* PIN less than this */ +pub const PBLEN: i32 = 14; /* Number of bits in PIN */ + +fn ceil(a: usize,b: usize) -> usize { + (a-1)/b+1 +} + +#[allow(non_snake_case)] +pub fn encode_to_curve(dst: &[u8],id: &[u8],hcid: &mut [u8]) { + let q = BIG::new_ints(&rom::MODULUS); + let k=q.nbits(); + let r = BIG::new_ints(&rom::CURVE_ORDER); + let m=r.nbits(); + let el=ceil(k+ceil(m,2),8); + let mut okm: [u8;512]=[0;512]; + hmac::xmd_expand(hmac::MC_SHA2,ecp::HASH_TYPE,&mut okm,el,&dst,&id); + let mut fd: [u8;256]=[0;256]; + for j in 0..el { + fd[j]=okm[j]; + } + let mut dx=DBIG::frombytes(&fd[0..el]); + let u=FP::new_big(&dx.dmod(&q)); + let mut P=ECP::map2point(&u); + P.cfp(); + P.affine(); + P.tobytes(hcid,false); +} + +/* create random secret S */ +pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sc = BIG::randtrunc(&r, 16 * ecp::AESKEY, rng); + sc.tobytes(s); + 0 +} + +/* Extract PIN from TOKEN for identity CID */ +#[allow(non_snake_case)] +pub fn extract_pin(cid: &[u8], pin: i32, token: &mut [u8]) -> isize { + let mut P = ECP::frombytes(&token); + if P.is_infinity() { + return INVALID_POINT; + } + let mut R = ECP::frombytes(&cid); + if R.is_infinity() { + return INVALID_POINT; + } + + R = R.pinmul(pin%MAXPIN, PBLEN); + P.sub(&R); + P.tobytes(token, false); + 0 +} + +/* Implement step 2 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_2(x: &[u8], y: &[u8], sec: &mut [u8]) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let mut P = ECP::frombytes(sec); + if P.is_infinity() { + return INVALID_POINT; + } + + let mut px = BIG::frombytes(x); + let py = BIG::frombytes(y); + px.add(&py); + px.rmod(&r); + + P = pair::g1mul(&P, &px); + P.neg(); + P.tobytes(sec, false); + 0 +} + +/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ +#[allow(non_snake_case)] +pub fn get_client_secret(s: &mut [u8], idhtc: &[u8], cst: &mut [u8]) -> isize { + let sx=BIG::frombytes(s); + let P=ECP::frombytes(idhtc); + if P.is_infinity() { + return INVALID_POINT; + } + pair::g1mul(&P, &sx).tobytes(cst, false); + 0 +} + +/* Implement step 1 on client side of MPin protocol */ +#[allow(non_snake_case)] +pub fn client_1( + cid: &[u8], + rng: Option<&mut RAND>, + x: &mut [u8], + pin: usize, + token: &[u8], + sec: &mut [u8], + xid: &mut [u8] +) -> isize { + let r = BIG::new_ints(&rom::CURVE_ORDER); + let sx: BIG; + + if let Some(rd) = rng { + sx = BIG::randtrunc(&r, 16 * ecp::AESKEY, rd); + sx.tobytes(x); + } else { + sx = BIG::frombytes(x); + } + let mut P=ECP::frombytes(cid); + if P.is_infinity() { + return INVALID_POINT; + } + + let mut T = ECP::frombytes(&token); + if T.is_infinity() { + return INVALID_POINT; + } + + let W = P.pinmul((pin as i32) % MAXPIN, PBLEN); + T.add(&W); + + P = pair::g1mul(&P, &sx); + P.tobytes(xid, false); + + T.tobytes(sec, false); + 0 +} + + +/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ +#[allow(non_snake_case)] +pub fn get_server_secret(s: &[u8], sst: &mut [u8]) -> isize { + let mut Q = ECP2::generator(); + let sc = BIG::frombytes(s); + Q = pair::g2mul(&Q, &sc); + Q.tobytes(sst,false); + 0 +} + +/* Implement step 2 of MPin protocol on server side */ +#[allow(non_snake_case)] +pub fn server( + hid: &[u8], + y: &[u8], + sst: &[u8], + xid: &[u8], + msec: &[u8], +) -> isize { + let Q = ECP2::generator(); + let sQ = ECP2::frombytes(&sst); + if sQ.is_infinity() { + return INVALID_POINT; + } + let mut R = ECP::frombytes(&xid); + if R.is_infinity() { + return INVALID_POINT; + } + + let sy = BIG::frombytes(&y); + let mut P = ECP::frombytes(&hid); + if P.is_infinity() { + return INVALID_POINT; + } + + P = pair::g1mul(&P, &sy); + P.add(&R); + R = ECP::frombytes(&msec); + if R.is_infinity() { + return INVALID_POINT; + } + + let mut g: FP12; + g = pair::ate2(&Q, &R, &sQ, &P); + g = pair::fexp(&g); + + if !g.isunity() { + return BAD_PIN; + } + 0 +} + diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs new file mode 100644 index 000000000000..360fe0fcd07a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs @@ -0,0 +1,1038 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::bn254::big::BIG; +use crate::bn254::ecp; +use crate::bn254::ecp::ECP; +use crate::bn254::ecp2::ECP2; +use crate::bn254::fp::FP; +use crate::bn254::fp12; +use crate::bn254::fp12::FP12; +use crate::bn254::fp2::FP2; +use crate::bn254::fp4::FP4; +use crate::bn254::rom; + +#[allow(unused_imports)] +use crate::bn254::dbig::DBIG; + +#[allow(non_snake_case)] +fn dbl(A: &mut ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { + cc.copy(&A.getpx()); //X + let mut yy = FP2::new_copy(&A.getpy()); //Y + bb.copy(&A.getpz()); //Z + + aa.copy(&yy); //Y + aa.mul(&bb); //YZ + cc.sqr(); //X^2 + yy.sqr(); //Y^2 + bb.sqr(); //Z^2 + + aa.dbl(); + aa.neg(); aa.norm(); + aa.mul_ip(); + aa.norm(); + + let sb = 3 * rom::CURVE_B_I; + bb.imul(sb); + cc.imul(3); + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + yy.mul_ip(); + yy.norm(); + cc.mul_ip(); + cc.norm(); + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + bb.mul_ip(); + bb.norm(); + } + bb.sub(&yy); + bb.norm(); + A.dbl(); +} + +#[allow(non_snake_case)] +fn add(A: &mut ECP2, B: &ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { + + aa.copy(&A.getpx()); // X1 + cc.copy(&A.getpy()); // Y1 + let mut t1 = FP2::new_copy(&A.getpz()); // Z1 + bb.copy(&A.getpz()); // Z1 + + t1.mul(&B.getpy()); // T1=Z1.Y2 + bb.mul(&B.getpx()); // T2=Z1.X2 + + aa.sub(&bb); + aa.norm(); // X1=X1-Z1.X2 + cc.sub(&t1); + cc.norm(); // Y1=Y1-Z1.Y2 + + t1.copy(&aa); // T1=X1-Z1.X2 + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + aa.mul_ip(); + aa.norm(); + } + + t1.mul(&B.getpy()); // T1=(X1-Z1.X2).Y2 + + bb.copy(&cc); // T2=Y1-Z1.Y2 + bb.mul(&B.getpx()); // T2=(Y1-Z1.Y2).X2 + bb.sub(&t1); + bb.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 + + cc.neg(); + cc.norm(); // Y1=-(Y1-Z1.Y2).Xs + + A.add(B); +} + +#[allow(non_snake_case)] +fn linedbl(A: &mut ECP2, qx: &FP, qy: &FP) -> FP12 { + let mut a = FP4::new(); + let mut b = FP4::new(); + let mut c = FP4::new(); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + dbl(A,&mut aa,&mut bb,&mut cc); + + cc.pmul(qx); + aa.pmul(qy); + + a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + c.copy(&FP4::new_fp2(&cc)); + c.times_i(); + } + let mut res= FP12::new_fp4s(&a, &b, &c); + res.settype(fp12::SPARSER); + res +} + +#[allow(non_snake_case)] +fn lineadd(A: &mut ECP2, B: &ECP2, qx: &FP, qy: &FP) -> FP12 { + let mut a = FP4::new(); + let mut b = FP4::new(); + let mut c = FP4::new(); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + add(A,B,&mut aa,&mut bb,&mut cc); + + cc.pmul(qx); + aa.pmul(qy); + + a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs + if ecp::SEXTIC_TWIST == ecp::D_TYPE { + b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) + } + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + c.copy(&FP4::new_fp2(&cc)); + c.times_i(); + } + let mut res= FP12::new_fp4s(&a, &b, &c); + res.settype(fp12::SPARSER); + res +} + +/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ +#[allow(non_snake_case)] +fn lbits(n3: &mut BIG,n: &mut BIG) -> usize { + n.copy(&BIG::new_ints(&rom::CURVE_BNX)); + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + n.pmul(6); + if ecp::SIGN_OF_X==ecp::POSITIVEX { + n.inc(2); + } else { + n.dec(2); + } + } + n.norm(); + n3.copy(&n); + n3.pmul(3); + n3.norm(); + n3.nbits() +} + +/* prepare for multi-pairing */ +pub fn initmp() -> [FP12; ecp::ATE_BITS] { + [FP12::new_int(1); ecp::ATE_BITS] +} + +/* basic Miller loop */ +pub fn miller(r:&mut [FP12]) -> FP12 { + let mut res=FP12::new_int(1); + for i in (1..ecp::ATE_BITS).rev() { + res.sqr(); + res.ssmul(&r[i]); + r[i].zero(); + } + + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + res.conj(); + } + res.ssmul(&r[0]); + r[0].zero(); + res +} + +fn pack(aa: &FP2,bb: &FP2,cc: &FP2) -> FP4 { + let mut i=FP2::new_copy(cc); + i.inverse(None); + let mut a=FP2::new_copy(aa); + let mut b=FP2::new_copy(bb); + a.mul(&i); + b.mul(&i); + FP4::new_fp2s(&a,&b) +} + +fn unpack(t: &FP4, qx: &FP, qy: &FP) -> FP12 { + let b:FP4; + let mut c:FP4; + let w=FP2::new_fp(qx); + + let mut aa=t.geta(); + let bb=t.getb(); + aa.pmul(qy); + let a=FP4::new_fp2s(&aa,&bb); + + if ecp::SEXTIC_TWIST==ecp::D_TYPE { + b=FP4::new_fp2(&w); + c=FP4::new(); + } else { + b=FP4::new(); + c=FP4::new_fp2(&w); c.times_i(); + } + let mut v=FP12::new_fp4s(&a,&b,&c); + v.settype(fp12::SPARSEST); + v +} + +#[allow(non_snake_case)] +pub fn precomp(T: &mut [FP4],GV: &ECP2) { + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let nb=lbits(&mut n3,&mut n); + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut aa = FP2::new(); + let mut bb = FP2::new(); + let mut cc = FP2::new(); + + let mut P=ECP2::new(); P.copy(GV); + + if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let mut A = ECP2::new(); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + let mut j=0; + + for i in (1..nb-1).rev() { + dbl(&mut A,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + add(&mut A,&P,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + } + if bt==-1 { + add(&mut A,&NP,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + } + } +/* R-ate fixup required for BN curves */ + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + A.neg(); + } + let mut K = ECP2::new(); + K.copy(&P); + K.frob(&f); + add(&mut A,&K,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); j+=1; + K.frob(&f); + K.neg(); + add(&mut A,&K,&mut aa,&mut bb,&mut cc); + T[j].copy(&pack(&aa,&bb,&cc)); + } +} + +/* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ +#[allow(non_snake_case)] +pub fn another_pc(r:&mut [FP12],T: &[FP4],QV: &ECP) { + let mut n = BIG::new(); + let mut n3 = BIG::new(); + + if QV.is_infinity() { + return; + } + + let nb=lbits(&mut n3,&mut n); + + let mut Q = ECP::new(); + Q.copy(QV); + Q.affine(); + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let mut j=0; + for i in (1..nb-1).rev() { + let mut lv=unpack(&T[j],&qx,&qy); j+=1; + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + let lv2=unpack(&T[j],&qx,&qy); j+=1; + lv.smul(&lv2); + } + if bt==-1 { + let lv2=unpack(&T[j],&qx,&qy); j+=1; + lv.smul(&lv2); + } + r[i].ssmul(&lv); + } + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + let mut lv=unpack(&T[j],&qx,&qy); j+=1; + let lv2=unpack(&T[j],&qx,&qy); + lv.smul(&lv2); + r[0].ssmul(&lv); + } +} + +/* Accumulate another set of line functions for n-pairing */ +#[allow(non_snake_case)] +pub fn another(r:&mut [FP12],P1: &ECP2,Q1: &ECP) { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return; + } +// P is needed in affine form for line function, Q for (Qx,Qy) extraction + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + + if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + let mut A = ECP2::new(); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb-1).rev() { + let mut lv=linedbl(&mut A,&qx,&qy); + + let bt=n3.bit(i)-n.bit(i); + if bt==1 { + let lv2=lineadd(&mut A,&P,&qx,&qy); + lv.smul(&lv2); + } + if bt==-1 { + let lv2=lineadd(&mut A,&NP,&qx,&qy); + lv.smul(&lv2); + } + r[i].ssmul(&lv); + } + +/* R-ate fixup required for BN curves */ + if ecp::CURVE_PAIRING_TYPE==ecp::BN { + if ecp::SIGN_OF_X==ecp::NEGATIVEX { + A.neg(); + } + K.copy(&P); + K.frob(&f); + let mut lv=lineadd(&mut A,&K,&qx,&qy); + K.frob(&f); + K.neg(); + let lv2=lineadd(&mut A,&K,&qx,&qy); + lv.smul(&lv2); + r[0].ssmul(&lv); + } +} + +#[allow(non_snake_case)] +/* Optimal R-ate pairing */ +pub fn ate(P1: &ECP2, Q1: &ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return FP12::new_int(1); + } + + if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let mut A = ECP2::new(); + let mut r = FP12::new_int(1); + + A.copy(&P); + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb - 1).rev() { + r.sqr(); + let mut lv = linedbl(&mut A, &qx, &qy); + let bt = n3.bit(i) - n.bit(i); + if bt == 1 { + let lv2 = lineadd(&mut A, &P, &qx, &qy); + lv.smul(&lv2); + } + if bt == -1 { + let lv2 = lineadd(&mut A, &NP, &qx, &qy); + lv.smul(&lv2); + } + r.ssmul(&lv); + } + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + r.conj(); + } + + /* R-ate fixup required for BN curves */ + + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + A.neg(); + } + + K.copy(&P); + K.frob(&f); + + let mut lv = lineadd(&mut A, &K, &qx, &qy); + K.frob(&f); + K.neg(); + let lv2 = lineadd(&mut A, &K, &qx, &qy); + lv.smul(&lv2); + r.ssmul(&lv); + } + + r +} + +#[allow(non_snake_case)] +/* Optimal R-ate double pairing e(P,Q).e(R,S) */ +pub fn ate2(P1: &ECP2, Q1: &ECP, R1: &ECP2, S1: &ECP) -> FP12 { + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let mut n = BIG::new(); + let mut n3 = BIG::new(); + let mut K = ECP2::new(); + + if Q1.is_infinity() { + return ate(R1,S1); + } + if S1.is_infinity() { + return ate(P1,Q1); + } + + if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { + f.inverse(None); + f.norm(); + } + + let mut P = ECP2::new(); + P.copy(P1); + P.affine(); + let mut Q = ECP::new(); + Q.copy(Q1); + Q.affine(); + let mut R = ECP2::new(); + R.copy(R1); + R.affine(); + let mut S = ECP::new(); + S.copy(S1); + S.affine(); + + let qx = FP::new_copy(&Q.getpx()); + let qy = FP::new_copy(&Q.getpy()); + + let sx = FP::new_copy(&S.getpx()); + let sy = FP::new_copy(&S.getpy()); + + let mut A = ECP2::new(); + let mut B = ECP2::new(); + let mut r = FP12::new_int(1); + + A.copy(&P); + B.copy(&R); + + let mut NP = ECP2::new(); + NP.copy(&P); + NP.neg(); + let mut NR = ECP2::new(); + NR.copy(&R); + NR.neg(); + + let nb=lbits(&mut n3,&mut n); + + for i in (1..nb - 1).rev() { + r.sqr(); + let mut lv = linedbl(&mut A, &qx, &qy); + let lv2 = linedbl(&mut B, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + let bt = n3.bit(i) - n.bit(i); + if bt == 1 { + lv = lineadd(&mut A, &P, &qx, &qy); + let lv2 = lineadd(&mut B, &R, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + } + if bt == -1 { + lv = lineadd(&mut A, &NP, &qx, &qy); + let lv2 = lineadd(&mut B, &NR, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + } + } + + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + r.conj(); + } + + /* R-ate fixup */ + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + A.neg(); + B.neg(); + } + K.copy(&P); + K.frob(&f); + + let mut lv = lineadd(&mut A, &K, &qx, &qy); + K.frob(&f); + K.neg(); + let mut lv2 = lineadd(&mut A, &K, &qx, &qy); + lv.smul(&lv2); + r.ssmul(&lv); + + K.copy(&R); + K.frob(&f); + + lv = lineadd(&mut B, &K, &sx, &sy); + K.frob(&f); + K.neg(); + lv2 = lineadd(&mut B, &K, &sx, &sy); + lv.smul(&lv2); + r.ssmul(&lv); + + } + + r +} + +/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ +pub fn fexp(m: &FP12) -> FP12 { + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut r = FP12::new_copy(m); + + /* Easy part of final exp */ + let mut lv = FP12::new_copy(&r); + lv.inverse(); + r.conj(); + + r.mul(&lv); + lv.copy(&r); + r.frob(&f); + r.frob(&f); + r.mul(&lv); + + /* Hard part of final exp */ + if ecp::CURVE_PAIRING_TYPE == ecp::BN { + lv.copy(&r); + lv.frob(&f); + let mut x0 = FP12::new_copy(&lv); + x0.frob(&f); + lv.mul(&r); + x0.mul(&lv); + x0.frob(&f); + let mut x1 = FP12::new_copy(&r); + x1.conj(); + let mut x4 = r.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + x4.conj(); + } + + let mut x3 = FP12::new_copy(&x4); + x3.frob(&f); + + let mut x2 = x4.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + x2.conj(); + } + let mut x5 = FP12::new_copy(&x2); + x5.conj(); + lv = x2.pow(&x); + if ecp::SIGN_OF_X == ecp::POSITIVEX { + lv.conj(); + } + x2.frob(&f); + r.copy(&x2); + r.conj(); + + x4.mul(&r); + x2.frob(&f); + + r.copy(&lv); + r.frob(&f); + lv.mul(&r); + + lv.usqr(); + lv.mul(&x4); + lv.mul(&x5); + r.copy(&x3); + r.mul(&x5); + r.mul(&lv); + lv.mul(&x2); + r.usqr(); + r.mul(&lv); + r.usqr(); + lv.copy(&r); + lv.mul(&x1); + r.mul(&x0); + lv.usqr(); + r.mul(&lv); + r.reduce(); + } else { + +// See https://eprint.iacr.org/2020/875.pdf + let mut y1 = FP12::new_copy(&r); + y1.usqr(); + y1.mul(&r); // y1=r^3 + + let mut y0 = FP12::new_copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + let mut t0 = FP12::new_copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + + y0.copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + t0.copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + +// ^(x+p) + y0.copy(&r.pow(&x)); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + y0.conj(); + } + t0.copy(&r); + t0.frob(&f); + r.copy(&y0); + r.mul(&t0); + +// ^(x^2+p^2-1) + y0.copy(&r.pow(&x)); + y0.copy(&y0.pow(&x)); + t0.copy(&r); + t0.frob(&f); t0.frob(&f); + y0.mul(&t0); + t0.copy(&r); t0.conj(); + r.copy(&y0); + r.mul(&t0); + + r.mul(&y1); + r.reduce(); + } + r +} + +#[allow(non_snake_case)] +/* GLV method */ +fn glv(ee: &BIG) -> [BIG; 2] { + let mut u: [BIG; 2] = [BIG::new(), BIG::new()]; + let q = BIG::new_ints(&rom::CURVE_ORDER); + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +/* */ + let mut t = BIG::new(); + let mut v: [BIG; 2] = [BIG::new(), BIG::new()]; + + for i in 0..2 { + t.copy(&BIG::new_ints(&rom::CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); + let mut d: DBIG = BIG::mul(&t, &ee); + v[i].copy(&d.ctdiv(&q,t.nbits())); + } + u[0].copy(&ee); + for i in 0..2 { + for j in 0..2 { + t = BIG::new_ints(&rom::CURVE_SB[j][i]); + t = BIG::modmul(&mut v[j], &mut t, &q); + u[i].add(&q); + u[i].sub(&t); + u[i].ctmod(&q,1); + } + } +/* */ + } else { + let x = BIG::new_ints(&rom::CURVE_BNX); + let x2 = BIG::smul(&x, &x); + let bd=q.nbits()-x2.nbits(); + u[0].copy(&ee); + u[0].ctmod(&x2,bd); + u[1].copy(&ee); + u[1].ctdiv(&x2,bd); + u[1].rsub(&q); + } + u +} + +#[allow(non_snake_case)] +/* Galbraith & Scott Method */ +pub fn gs(ee: &BIG) -> [BIG; 4] { + let mut u: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; + let q = BIG::new_ints(&rom::CURVE_ORDER); + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +/* */ + let mut t = BIG::new(); + + let mut v: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; + for i in 0..4 { + t.copy(&BIG::new_ints(&rom::CURVE_WB[i])); + let mut d: DBIG = BIG::mul(&t, &ee); + v[i].copy(&d.ctdiv(&q,t.nbits())); + } + u[0].copy(&ee); + for i in 0..4 { + for j in 0..4 { + t = BIG::new_ints(&rom::CURVE_BB[j][i]); + t = BIG::modmul(&mut v[j], &mut t, &q); + u[i].add(&q); + u[i].sub(&t); + u[i].ctmod(&q,1); + } + } +/* */ + } else { + let x = BIG::new_ints(&rom::CURVE_BNX); + let bd=q.nbits()-x.nbits(); // fixed + + let mut w = BIG::new_copy(&ee); + for i in 0..3 { + u[i].copy(&w); + u[i].ctmod(&x,bd); + w.ctdiv(&x,bd); + } + u[3].copy(&w); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + let mut t = BIG::new(); + t.copy(&BIG::modneg(&u[1], &q)); + u[1].copy(&t); + t.copy(&BIG::modneg(&u[3], &q)); + u[3].copy(&t); + } + } + u +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G1 */ +pub fn g1mul(P: &ECP, e: &BIG) -> ECP { + let mut R = ECP::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GLV { + R.copy(P); + let mut Q = ECP::new(); + Q.copy(P); + Q.affine(); + + let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); + let mut u = glv(&ee); + Q.mulx(&mut cru); + + let mut np = u[0].nbits(); + let mut t: BIG = BIG::modneg(&u[0], &q); + let mut nn = t.nbits(); + if nn < np { + u[0].copy(&t); + R.neg(); + } + + np = u[1].nbits(); + t = BIG::modneg(&u[1], &q); + nn = t.nbits(); + if nn < np { + u[1].copy(&t); + Q.neg(); + } + u[0].norm(); + u[1].norm(); + R = R.mul2(&u[0], &Q, &u[1]); + } else { + R = P.clmul(&ee,&q); + } + R +} + +#[allow(non_snake_case)] +/* Multiply P by e in group G2 */ +pub fn g2mul(P: &ECP2, e: &BIG) -> ECP2 { + let mut R = ECP2::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GS_G2 { + let mut Q: [ECP2; 4] = [ECP2::new(), ECP2::new(), ECP2::new(), ECP2::new()]; + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + + let mut u = gs(&ee); + let mut T = ECP2::new(); + + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + f.inverse(None); + f.norm(); + } + + let mut t = BIG::new(); + Q[0].copy(&P); + for i in 1..4 { + T.copy(&Q[i - 1]); + Q[i].copy(&T); + Q[i].frob(&f); + } + for i in 0..4 { + let np = u[i].nbits(); + t.copy(&BIG::modneg(&u[i], &q)); + let nn = t.nbits(); + if nn < np { + u[i].copy(&t); + Q[i].neg(); + } + u[i].norm(); + } + + R.copy(&ECP2::mul4(&Q, &u)); + } else { + R.copy(&P.mul(&ee)); + } + R +} + +/* f=f^e */ +/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ +pub fn gtpow(d: &FP12, e: &BIG) -> FP12 { + let mut r = FP12::new(); + let q = BIG::new_ints(&rom::CURVE_ORDER); + let mut ee= BIG::new_copy(e); + ee.rmod(&q); + if rom::USE_GS_GT { + let mut g: [FP12; 4] = [FP12::new(), FP12::new(), FP12::new(), FP12::new()]; + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + + let mut t = BIG::new(); + let mut u = gs(&ee); + let mut w = FP12::new(); + + g[0].copy(&d); + for i in 1..4 { + w.copy(&g[i - 1]); + g[i].copy(&w); + g[i].frob(&f); + } + for i in 0..4 { + let np = u[i].nbits(); + t.copy(&BIG::modneg(&u[i], &q)); + let nn = t.nbits(); + if nn < np { + u[i].copy(&t); + g[i].conj(); + } + u[i].norm(); + } + r.copy(&FP12::pow4(&g, &u)); + } else { + r.copy(&d.pow(&ee)); + } + r +} + +/* test G1 group membership */ +#[allow(non_snake_case)] +pub fn g1member(P: &ECP) -> bool { + //let q = BIG::new_ints(&rom::CURVE_ORDER); + if P.is_infinity() { + return false; + } + if ecp::CURVE_PAIRING_TYPE != ecp::BN { + let x = BIG::new_ints(&rom::CURVE_BNX); + let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); + let mut W=ECP::new(); W.copy(P); W.mulx(&mut cru); + let mut T=P.mul(&x); + if P.equals(&T) {return false;} // P is of low order + + T=T.mul(&x); T.neg(); + if !W.equals(&T) { + return false; + } + +// Not needed +// W.add(P); T.mulx(&mut cru); W.add(&T); +// if !W.is_infinity() { +// return false; +// } +/* + let W=P.mul(&q); + if !W.is_infinity() { + return false; + } */ + } + true +} + +/* test G2 group membership */ +#[allow(non_snake_case)] +pub fn g2member(P: &ECP2) -> bool { + if P.is_infinity() { + return false; + } + let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + if ecp::SEXTIC_TWIST == ecp::M_TYPE { + f.inverse(None); + f.norm(); + } + let x = BIG::new_ints(&rom::CURVE_BNX); + + let mut W=ECP2::new(); + let mut T=P.mul(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + T.neg(); + } + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +//https://eprint.iacr.org/2022/348.pdf + W.copy(&T); + W.frob(&f); + T.add(P); + T.add(&W); + W.frob(&f); + T.add(&W); + W.frob(&f); + W.dbl(); + } else { +//https://eprint.iacr.org/2021/1130 + W.copy(P); W.frob(&f); + } + + if !W.equals(&T) { + return false; + } + true +} + +/* Check that m is in cyclotomic sub-group */ +/* Check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ +pub fn gtcyclotomic(m: &FP12) -> bool { + if m.isunity() { + return false; + } + let mut r = FP12::new_copy(&m); + r.conj(); + r.mul(&m); + if !r.isunity() { + return false; + } + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + r.copy(&m); r.frob(&f); r.frob(&f); + let mut w = FP12::new_copy(&r); w.frob(&f); w.frob(&f); + w.mul(&m); + if !w.equals(&r) { + return false; + } + return true; +} + +/* test for full GT group membership */ +pub fn gtmember(m: &FP12) -> bool { + if !gtcyclotomic(m) { + return false; + } + let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); + let x = BIG::new_ints(&rom::CURVE_BNX); + + let mut r=FP12::new(); + let mut t=m.pow(&x); + if ecp::SIGN_OF_X == ecp::NEGATIVEX { + t.conj(); + } + if ecp::CURVE_PAIRING_TYPE == ecp::BN { +//https://eprint.iacr.org/2022/348.pdf + r.copy(&t); + r.frob(&f); + t.mul(m); + t.mul(&r); + r.frob(&f); + t.mul(&r); + r.frob(&f); + r.usqr(); + } else { +//https://eprint.iacr.org/2021/1130 + r.copy(m); r.frob(&f); + } + + if !r.equals(&t) { + return false; + } + + true +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs new file mode 100644 index 000000000000..b53157c96674 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use crate::arch::Chunk; +use crate::bn254::big::NLEN; + +// BN254 Modulus +// Base Bits= 56 +pub const MODULUS: [Chunk; NLEN] = [0x13, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const ROI: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const R2MODP: [Chunk; NLEN] = [ + 0x2F2A96FF5E7E39, + 0x64E8642B96F13C, + 0x9926F7B00C7146, + 0x8321E7B4DACD24, + 0x1D127A2E, +]; +pub const MCONST: Chunk = 0x435E50D79435E5; +pub const SQRTM3:[Chunk;NLEN]=[0x4,0x60C,0x3CF0F,0x4000000126CD89,0x25236482]; +pub const FRA: [Chunk; NLEN] = [ + 0x7DE6C06F2A6DE9, + 0x74924D3F77C2E1, + 0x50A846953F8509, + 0x212E7C8CB6499B, + 0x1B377619, +]; +pub const FRB: [Chunk; NLEN] = [ + 0x82193F90D5922A, + 0x8B6DB2C08850C5, + 0x2F57B96AC8DC17, + 0x1ED1837503EAB2, + 0x9EBEE69, +]; + +pub const CURVE_COF_I: isize = 1; +pub const CURVE_B_I: isize = 2; +pub const CURVE_B: [Chunk; NLEN] = [0x2, 0x0, 0x0, 0x0, 0x0]; +pub const CURVE_ORDER: [Chunk; NLEN] = [ + 0xD, + 0x800000000010A1, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, +]; +pub const CURVE_GX: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; +pub const CURVE_GY: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; +pub const CURVE_HTPC:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0]; +pub const CURVE_BNX: [Chunk; NLEN] = [0x80000000000001, 0x40, 0x0, 0x0, 0x0]; +pub const CURVE_COF: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; +pub const CRU: [Chunk; NLEN] = [0x80000000000007, 0x6CD, 0x40000000024909, 0x49B362, 0x0]; +pub const CURVE_PXA: [Chunk; NLEN] = [ + 0xEE4224C803FB2B, + 0x8BBB4898BF0D91, + 0x7E8C61EDB6A464, + 0x519EB62FEB8D8C, + 0x61A10BB, +]; +pub const CURVE_PXB: [Chunk; NLEN] = [ + 0x8C34C1E7D54CF3, + 0x746BAE3784B70D, + 0x8C5982AA5B1F4D, + 0xBA737833310AA7, + 0x516AAF9, +]; +pub const CURVE_PYA: [Chunk; NLEN] = [ + 0xF0E07891CD2B9A, + 0xAE6BDBE09BD19, + 0x96698C822329BD, + 0x6BAF93439A90E0, + 0x21897A0, +]; +pub const CURVE_PYB: [Chunk; NLEN] = [ + 0x2D1AEC6B3ACE9B, + 0x6FFD739C9578A, + 0x56F5F38D37B090, + 0x7C8B15268F6D44, + 0xEBB2B0E, +]; +pub const CURVE_W: [[Chunk; NLEN]; 2] = [ + [0x3, 0x80000000000204, 0x6181, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], +]; +pub const CURVE_SB: [[[Chunk; NLEN]; 2]; 2] = [ + [ + [0x4, 0x80000000000285, 0x6181, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x81, 0x0, 0x0, 0x0], + [0xA, 0xE9D, 0x80000000079E1E, 0x40000001BA344D, 0x25236482], + ], +]; +pub const CURVE_WB: [[Chunk; NLEN]; 4] = [ + [0x80000000000000, 0x80000000000040, 0x2080, 0x0, 0x0], + [0x80000000000005, 0x54A, 0x8000000001C707, 0x312241, 0x0], + [ + 0x80000000000003, + 0x800000000002C5, + 0xC000000000E383, + 0x189120, + 0x0, + ], + [0x80000000000001, 0x800000000000C1, 0x2080, 0x0, 0x0], +]; +pub const CURVE_BB: [[[Chunk; NLEN]; 4]; 4] = [ + [ + [ + 0x8000000000000D, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [0x2, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x81, 0x0, 0x0, 0x0], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000D, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [ + 0x8000000000000C, + 0x80000000001060, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + ], + [ + [0x2, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + [0x1, 0x81, 0x0, 0x0, 0x0], + ], + [ + [0x80000000000002, 0x40, 0x0, 0x0, 0x0], + [0x2, 0x102, 0x0, 0x0, 0x0], + [ + 0xA, + 0x80000000001020, + 0x8000000007FF9F, + 0x40000001BA344D, + 0x25236482, + ], + [0x80000000000002, 0x40, 0x0, 0x0, 0x0], + ], +]; + +pub const USE_GLV: bool = true; +pub const USE_GS_G2: bool = true; +pub const USE_GS_GT: bool = true; +pub const GT_STRONG: bool = false; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs new file mode 100644 index 000000000000..e9c31b7ff59e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs @@ -0,0 +1,1199 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Dilithium API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. + +Note that the Matrix A is calculated on-the-fly to keep memory requirement minimal +But this makes all stages much slower +Note that +1. Matrix A can just be generated randomly for Key generation (without using SHA3 which is very slow) +2. A precalculated A can be included in the public key, for use by signature and verification (which blows up public key size) +3. Precalculating A for signature calculation means that the A does not have to re-calculated for each attempt to find a good signature + +Might be simpler to wait for hardware support for SHA3! + + M.Scott 30/09/2021 +*/ + +use crate::sha3; +use crate::sha3::SHA3; + +//q= 8380417 +const LGN: usize = 8; +const DEGREE: usize = 1< i32 { + let m = (t as u32).wrapping_mul(ND); + (((m as u64) * (PRIME as u64) + t) >> 32) as i32 +} + +fn nres(x: i32) -> i32 { + redc((x as u64) * R2MODP) +} + +fn modmul(a: i32, b: i32) -> i32 { + redc((a as u64) * (b as u64)) +} + +fn poly_pos(p: &mut [i32]) { + for j in 0..DEGREE { + p[j] += (p[j]>>31)&PRIME; + } +} +// NTT code + +// Important! +// nres(x); ntt(x) +// nres(y); ntt(y) +// z=x*y +// intt(z); +// redc(z); + +// is equivalent to (note that nres() and redc() cancel out) + +// ntt(x); +// nres(y); ntt(y); +// z=x*y +// intt(z) + +// is equivalent to + +// ntt(x) +// ntt(y) +// z=x*y +// intt(z) +// nres(z) + +// In all cases z ends up in normal (non-Montgomery) form! +// So the conversion to Montgomery form can be "pushed" through the calculation. + +// Here intt(z) <- intt(z);nres(z); +// Combining is more efficient +// note that ntt() and intt() are not mutually inverse + +/* Cooley-Tukey NTT */ +/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ +fn ntt(x: &mut [i32]) { + let mut t = DEGREE / 2; + let q = PRIME; + + /* Make positive */ + poly_pos(x); + + let mut m = 1; + while m < DEGREE { + let mut k = 0; + for i in 0..m { + let s = ROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = modmul(x[j + t], s); + x[j] = u + v; + x[j + t] = u + 2 * q - v; + } + k += 2 * t; + } + t /= 2; + m *= 2; + } +} + +/* Gentleman-Sande INTT */ +/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ +/* Output fully reduced */ + +const NTTL: usize = 2; // maybe could be 1? + +fn intt(x: &mut [i32]) { + let mut t = 1; + let q = PRIME; + let mut m = DEGREE / 2; + let mut n=LGN; + while m >= 1 { + let lim=NTTL>>n; + n-=1; + let mut k = 0; + for i in 0..m { + let s = IROOTS[m + i]; + for j in k..k + t { + let u:i32; + let v:i32; + if m> 31) & q; + } +} + +fn nres_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = nres(p[i]); + } +} + +fn redc_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = redc(p[i] as u64); + } +} + +fn poly_copy(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = p3[i]; + } +} + +fn poly_scopy(p1: &mut [i32], p3: &[i8]) { + for i in 0..DEGREE { + p1[i] = p3[i] as i32; + } +} + +fn poly_mcopy(p1: &mut [i32], p3: &[i16]) { + for i in 0..DEGREE { + p1[i] = p3[i] as i32; + } +} + +fn poly_zero(p1: &mut [i32]) { + for i in 0..DEGREE { + p1[i] = 0; + } +} + +fn poly_negate(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = PRIME-p3[i]; + } +} + +fn poly_mul(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = modmul(p1[i], p3[i]); + } +} + +fn poly_add(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += p3[i]; + } +} + +fn poly_sub(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += PRIME - p3[i]; + } +} + +/* reduces inputs < 2q */ +fn poly_soft_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let e = poly[i] - PRIME; + poly[i] = e + ((e >> 31) & PRIME); + } +} + +/* fully reduces modulo q */ +fn poly_hard_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let mut e = modmul(poly[i], ONE); + e -= PRIME; + poly[i] = e + ((e >> 31) & PRIME); + } +} + +// Generate a[i][j] from rho +fn expandaij(rho: &[u8],aij: &mut [i32],i:usize,j:usize) { + let mut buff: [u8; 4*DEGREE] = [0; 4*DEGREE]; + let mut sh = SHA3::new(sha3::SHAKE128); + for m in 0..32 { + sh.process(rho[m]) + } + sh.process(j as u8); + sh.process(i as u8); + sh.shake(&mut buff, 4*DEGREE); + let mut m=0; + let mut n=0; + while m=PRIME { + continue; + } + aij[m]=cf; + m+=1; + } +} + +// array t has ab active bits per word +// extract bytes from array of words +// if mx!=0 then -mx<=t[i]<=+mx +fn nextbyte32(ab: usize,mx: usize,t: &[i32],ptr:&mut usize,bts: &mut usize) -> u8 { + let mut left=ab-*bts; + let mut w=t[*ptr]; + let mxm=mx as i32; + if mxm!=0 { + w=mxm-w; + } + let mut r=w>>*bts; + let mut i=0; + while left<8 { + i+=1; + w=t[(*ptr)+i]; + if mxm!=0 { + w=mxm-w; + } + r |= w<=ab { + *bts -= ab; + *ptr+=1; + } + return r as u8; +} + +fn nextbyte16(ab: usize,mx: usize,t: &[i16],ptr:&mut usize,bts: &mut usize) -> u8 { + let mut left=ab-*bts; + let mut w=t[*ptr]; + let mxm=mx as i16; + if mxm!=0 { + w=mxm-w; + } + let mut r=w>>*bts; + let mut i=0; + while left<8 { + i+=1; + w=t[(*ptr)+i]; + if mxm!=0 { + w=mxm-w; + } + r |= w<=ab { + *bts -= ab; + *ptr += 1; + } + return r as u8; +} + +fn nextbyte8(ab: usize,mx: usize,t: &[i8],ptr:&mut usize,bts: &mut usize) -> u8 { + let mut left=ab-*bts; + let mut w=t[*ptr]; + let mxm=mx as i8; + if mxm!=0 { + w=mxm-w; + } + let mut r=w>>*bts; + let mut i=0; + while left<8 { + i+=1; + w=t[(*ptr)+i]; + if mxm!=0 { + w=mxm-w; + } + r |= w<=ab { + *bts -= ab; + *ptr+=1; + } + return r as u8; +} + +fn nextword(ab: usize,mx: usize,t: &[u8],ptr:&mut usize,bts: &mut usize) -> i32 { + let mut r=(t[*ptr]>>*bts) as i32; + let mxm=mx as i32; + let mask=(1<=8 { + *bts -= 8; + *ptr+=1; + } + w=r&mask; + if mxm!=0 { + w=mxm-w; + } + return w; +} + +fn pack_pk(params: &[usize],pk: &mut [u8],rho: &[u8],t1: &[i16]) { + let ck=params[3]; + for i in 0..32 { + pk[i]=rho[i]; + } + let mut ptr=0 as usize; + let mut bts=0 as usize; + let mut n=32; + for _ in 0..(ck*DEGREE*TD)/8 { + pk[n]=nextbyte16(TD,0,t1,&mut ptr,&mut bts); + n += 1; + } +} + +fn unpack_pk(params: &[usize],rho: &mut [u8],t1: &mut [i16],pk: &[u8]) { + let ck=params[3]; + for i in 0..32 { + rho[i]=pk[i]; + } + let mut ptr=0 as usize; + let mut bts=0 as usize; + for i in 0..ck*DEGREE { + t1[i]=nextword(TD,0,&pk[32..],&mut ptr,&mut bts) as i16; + } +} + +fn pack_sk(params: &[usize],sk: &mut [u8],rho: &[u8],bk: &[u8],tr: &[u8],s1: &[i8],s2: &[i8],t0: &[i16]) { + let ck=params[3]; + let el=params[4]; + let eta=params[5]; + let lg2eta1=params[6]; + + for i in 0..32 { + sk[i]=rho[i]; + } + let mut n=32; + for i in 0..32 { + sk[n]=bk[i]; n+=1; + } + for i in 0..32 { + sk[n]=tr[i]; n+=1; + } + let mut ptr=0 as usize; + let mut bts=0 as usize; + + for _ in 0..(el*DEGREE*lg2eta1)/8 { + sk[n]=nextbyte8(lg2eta1,eta,s1,&mut ptr,&mut bts); + n += 1; + } + ptr=0; bts=0; + for _ in 0..(ck*DEGREE*lg2eta1)/8 { + sk[n]=nextbyte8(lg2eta1,eta,s2,&mut ptr,&mut bts); + n += 1; + } + ptr=0; bts=0; + for _ in 0..(ck*DEGREE*D)/8 { + sk[n]=nextbyte16(D,1<<(D-1),t0,&mut ptr,&mut bts); + n += 1; + } +} + +fn unpack_sk(params: &[usize],rho: &mut [u8],bk: &mut [u8],tr: &mut [u8],s1: &mut [i8],s2: &mut [i8],t0: &mut [i16],sk: &[u8]) { + let ck=params[3]; + let el=params[4]; + let eta=params[5]; + let lg2eta1=params[6]; + + for i in 0..32 { + rho[i]=sk[i]; + } + let mut n=32; + for i in 0..32 { + bk[i]=sk[n]; n+=1; + } + for i in 0..32 { + tr[i]=sk[n]; n+=1; + } + let mut ptr=0 as usize; + let mut bts=0 as usize; + + for i in 0..el*DEGREE { + s1[i]=nextword(lg2eta1,eta,&sk[n..],&mut ptr,&mut bts) as i8; + } + n += ptr; + ptr=0; bts=0; + for i in 0..ck*DEGREE { + s2[i]=nextword(lg2eta1,eta,&sk[n..],&mut ptr,&mut bts) as i8; + } + n += ptr; + ptr=0; bts=0; + for i in 0..ck*DEGREE { + t0[i]=nextword(D,1<<(D-1),&sk[n..],&mut ptr,&mut bts) as i16; + } +} + +// pack signature - changes z +fn pack_sig(params: &[usize],sig: &mut [u8],z: &mut [i32],ct: &[u8],h: &[u8]) { + let lg=params[1]; + let gamma1=1<PRIME/2 { + t -= PRIME; + } + t=gamma1-t; + z[row+m]=t; + } + } + for _ in 0..(el*DEGREE*(lg+1))/8 { + sig[n]=nextbyte32(lg+1,0,z,&mut ptr,&mut bts); + n+=1; + } + for i in 0..omega+ck { + sig[n]=h[i]; + n+=1; + } +} + +fn unpack_sig(params: &[usize],z: &mut [i32],ct: &mut [u8],h: &mut [u8],sig: &[u8]) { + let lg=params[1]; + let gamma1=1<>8)&0xff) as u8); + sh.shake(&mut buff, 272); + + let eta=params[5]; + let lg2eta1=params[6]; + + let mut ptr=0 as usize; + let mut bts=0 as usize; + for m in 0..DEGREE { + loop { + s[m]=nextword(lg2eta1,0,&buff,&mut ptr,&mut bts) as i8; + if s[m]<=2*(eta as i8) { + break; + } + } + s[m]=(eta as i8)-s[m]; + } +} + +fn sample_y(params: &[usize],k: usize,rhod: &[u8],y: &mut [i32]) { + let lg=params[1]; + let gamma1=1<>8) as u8); + sh.shake(&mut buff, ((lg+1)*DEGREE)/8); + + let mut ptr=0 as usize; + let mut bts=0 as usize; + + for m in 0..DEGREE { + let mut w=nextword(lg+1,0,&buff,&mut ptr,&mut bts); + w=gamma1-w; + let t=w>>31; + y[row+m]=w+(PRIME&t); + } + } +} + +fn crh1(params: &[usize],h: &mut [u8],rho: &[u8],t1: &[i16]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(rho[j]); + } + let ck=params[3]; + let mut ptr=0 as usize; + let mut bts=0 as usize; + + for _ in 0..(ck*DEGREE*TD)/8 { + sh.process(nextbyte16(TD,0,t1,&mut ptr,&mut bts)); + } + sh.shake(h, 32); +} + +fn crh2(h: &mut [u8],tr: &[u8],mess: &[u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(tr[j]); + } + for j in 0..mess.len() { + sh.process(mess[j]); + } + sh.shake(h, 64); +} + +fn crh3(h: &mut [u8],bk: &[u8],mu: &[u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(bk[j]); + } + for j in 0..64 { + sh.process(mu[j]); + } + sh.shake(h, 64); +} + +fn h4(params: &[usize],ct: &mut [u8], mu: &[u8],w1: &[i8]) { + let ck=params[3]; + let dv=params[2]; + let mut w1b=4; + if dv==88 { + w1b=6; + } + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..64 { + sh.process(mu[j]); + } + + let mut ptr=0 as usize; + let mut bts=0 as usize; + + for _ in 0..(ck*DEGREE*w1b)/8 { + sh.process(nextbyte8(w1b,0,w1,&mut ptr,&mut bts)); + } + sh.shake(ct, 32); +} + +fn sampleinball(params: &[usize],ct: &[u8],c: &mut [i32]) { + let tau=params[0]; + let mut buff: [u8; 136] = [0; 136]; + let mut signs: [u8; 8] = [0; 8]; + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..32 { + sh.process(ct[j]); + } + sh.shake(&mut buff,136); + for i in 0..8 { + signs[i]=buff[i]; + } + let mut k=8; + let mut b=0; + poly_zero(c); + let mut j:usize; + let mut n=1; + let mut sn=signs[0]; + for i in DEGREE-tau..DEGREE { + loop { + j=buff[k] as usize; k+=1; + if j<=i { + break; + } + } + c[i]=c[j]; + c[j]=1-2*((sn as i32)&1); + sn >>= 1; b += 1; + if b==8 { + sn=signs[n]; n += 1; b=0; + } + } +} + +fn p2r(r0: &mut i32) -> i16 { + let d=(1<>D; + *r0-=r1 << D; + return r1 as i16; +} + +fn power2round(t: &[i32],t0: &mut [i16],t1: &mut [i16]) { + for m in 0..DEGREE { + let mut w=t[m]; + t1[m]=p2r(&mut w); + t0[m]=w as i16; + } +} + +fn decompose_lo(params: &[usize],a: i32) -> i32 { + let dv=params[2]; + let mut a1=(a+127) >> 7; + let gamma2:i32; + if dv==32 { + a1 = (a1*1025+(1<<21))>>22; + a1 &= 15; + gamma2=(PRIME-1)/32; + + } else { // 88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; + gamma2=(PRIME-1)/88; + } + + let mut a0=a-a1*2*gamma2; + a0 -= (((PRIME-1)/2-a0)>>31)&PRIME; + a0 += (a0>>31)&PRIME; + return a0; +} + +fn decompose_hi(params: &[usize],a: i32) -> i8 { + let dv=params[2]; + + let mut a1=(a+127) >> 7; + if dv==32 { + a1 = (a1*1025+(1<<21))>>22; + a1 &= 15; + } else { // 88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; + } + return a1 as i8; +} + +fn lobits(params: &[usize],r0: &mut [i32],r: &[i32]) { + for m in 0..DEGREE { + r0[m]=decompose_lo(params,r[m]); + } +} + +fn hibits(params: &[usize],r1: &mut [i8],r: &[i32]) { + for m in 0..DEGREE { + r1[m]=decompose_hi(params,r[m]); + } +} + +fn makepartialhint(params: &[usize],h: &mut [u8],hptr: usize,z: &[i32],r: &[i32]) -> usize { + let mut ptr=hptr; + let omega=params[7]; + for m in 0..DEGREE { + let a0=decompose_hi(params,r[m]); + let mut rz=r[m]+z[m]; + rz-=PRIME; + rz=rz+((rz>>31)&PRIME); + let a1=decompose_hi(params,rz); + if a0!=a1 { + if ptr>=omega { + return omega+1; + } + h[ptr]=(m&0xff) as u8; ptr += 1; + } + } + return ptr; +} + +fn usepartialhint(params: &[usize],r: &mut [i8],h: &[u8], hptr: usize,i: usize,w: &[i32]) -> usize{ + let mut ptr=hptr; + let dv=params[2] as i32; + let omega=params[7]; + let md=(dv/2) as i8; + + for m in 0..DEGREE { + let mut a1=decompose_hi(params,w[m]); + if m==h[ptr] as usize && ptr= md { + a1 -= md; + } + } else { + a1 -= 1; + if a1<0 { + a1 += md; + } + } + } + r[m]=a1; + } + return ptr; +} + +fn infinity_norm(w: &[i32]) -> i32 { + let mut n=0 as i32; + for m in 0..DEGREE { + let mut az=w[m]; + if az>PRIME/2 { + az=PRIME-az; + } + if az>n { + n=az; + } + } + return n; +} + +fn keypair(params: &[usize],tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { + let mut sh = SHA3::new(sha3::SHAKE256); + let mut buff: [u8; 128] = [0; 128]; + let mut rho: [u8; 32] = [0; 32]; + let mut rhod: [u8; 64] = [0; 64]; + let mut bk: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut s1: [i8; MAXL*DEGREE] = [0; MAXL*DEGREE]; + let mut s2: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut t0: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut t1: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let ck=params[3]; + let el=params[4]; + + for i in 0..32 { + sh.process(tau[i]); + } + sh.shake(&mut buff,128); + for i in 0..32 { + rho[i] = buff[i]; + bk[i] = buff[i+96]; + } + for i in 0..64 { + rhod[i] = buff[i+32]; + } + + for i in 0..el { + let row=DEGREE*i; + sample_sn(params,&rhod,&mut s1[row..],i); + } + + for i in 0..ck { + let row=DEGREE*i; + sample_sn(params,&rhod,&mut s2[row..],el+i); + poly_zero(&mut r); + for j in 0..el { + poly_scopy(&mut w,&s1[j*DEGREE..]); + ntt(&mut w); + expandaij(&rho,&mut aij,i,j); + poly_mul(&mut w,&aij); + poly_add(&mut r,&w); + } + poly_hard_reduce(&mut r); + intt(&mut r); + poly_scopy(&mut w,&s2[row..]); + poly_pos(&mut w); + poly_add(&mut r,&w); + poly_soft_reduce(&mut r); + power2round(&r,&mut t0[row..],&mut t1[row..]); + } + crh1(params,&mut tr,&rho,&t1); + pack_pk(params,pk,&rho,&t1); + pack_sk(params,sk,&rho,&bk,&tr,&s1,&s2,&t0); +} + +fn signature(params: &[usize],sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { + let mut rho: [u8; 32] = [0; 32]; + let mut bk: [u8; 32] = [0; 32]; + let mut ct: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut mu: [u8; 64] = [0; 64]; + let mut rhod: [u8; 64] = [0; 64]; + let mut hint: [u8; 100] = [0; 100]; + + //let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut s1: [i8; MAXL*DEGREE] = [0; MAXL*DEGREE]; + let mut s2: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut t0: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; + + let mut y: [i32; MAXL*DEGREE] = [0; MAXL*DEGREE]; + let mut ay: [i32; MAXK*DEGREE] = [0; MAXK*DEGREE]; + + let mut w1: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let tau=params[0]; + let lg=params[1]; + let gamma1=(1<=gamma1-beta { + badone=true; + break; + } + } + if badone { + continue; + } +// Calculate ay=w-c.s2 and r0=lobits(w-c.s2) + let mut nh=0; + for i in 0..omega+ck { + hint[i]=0; + } + for i in 0..ck { + let row=DEGREE*i; + poly_scopy(&mut w,&s2[row..]); + ntt(&mut w); + poly_mul(&mut w,&c); + intt(&mut w); + poly_sub(&mut ay[row..],&w); + poly_soft_reduce(&mut ay[row..]); + lobits(params,&mut w,&ay[row..]); + if infinity_norm(&w) >= gamma2-beta { + badone=true; + break; + } + poly_mcopy(&mut w,&t0[row..]); + ntt(&mut w); + poly_mul(&mut w,&c); + intt(&mut w); + poly_negate(&mut r,&w); + if infinity_norm(&r) >= gamma2 { + badone=true; + break; + } + poly_sub(&mut ay[row..],&r); + poly_soft_reduce(&mut ay[row..]); + nh=makepartialhint(params,&mut hint,nh,&r,&ay[row..]); + if nh>omega { + badone=true; + break; + } + hint[omega+i]=nh as u8; + } + if badone { + continue; + } + break; + } + pack_sig(params,sig,&mut y,&ct,&hint); + return k; +} + +fn verify(params: &[usize],pk: &[u8],m: &[u8],sig: &[u8]) -> bool { + let mut rho: [u8; 32] = [0; 32]; + let mut ct: [u8; 32] = [0; 32]; + let mut cct: [u8; 32] = [0; 32]; + let mut tr: [u8; 32] = [0; 32]; + let mut mu: [u8; 64] = [0; 64]; + let mut hint: [u8; 100] = [0; 100]; + + let mut z: [i32; MAXL*DEGREE] = [0; MAXL*DEGREE]; + let mut t1: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; + let mut w1d: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; + + let mut aij: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + let mut w: [i32; DEGREE] = [0; DEGREE]; + let mut r: [i32; DEGREE] = [0; DEGREE]; + + let tau=params[0]; + let lg=params[1]; + let gamma1=(1<= gamma1-beta { + return false; + } + ntt(&mut z[row..]); + } + crh1(params,&mut tr,&rho,&t1); + crh2(&mut mu,&tr,m); + + sampleinball(params,&ct,&mut c); + ntt(&mut c); + +// Calculate az + let mut hints=0; + for i in 0..ck { + let row=DEGREE*i; + poly_zero(&mut r); + for j in 0..el { + poly_copy(&mut w,&z[j*DEGREE..]); + expandaij(&rho,&mut aij,i,j); + poly_mul(&mut w,&aij); + poly_add(&mut r,&w); + } + poly_hard_reduce(&mut r); + +// Calculate Az-ct1.2^d + for m in 0..DEGREE { + w[m]=((t1[row+m]) as i32) << D; + } + ntt(&mut w); + poly_mul(&mut w,&c); + poly_sub(&mut r,&w); + intt(&mut r); + + hints=usepartialhint(params,&mut w1d[row..],&mut hint,hints,i,&r); + if hints>omega { + return false; + } + } + + h4(params,&mut cct,&mu,&w1d); + + for i in 0..32 { + if ct[i]!=cct[i] { + return false; + } + } + return true; +} + +// Dilithium API + +pub fn keypair_2(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { + keypair(&PARAMS_2,tau,sk,pk); +} + +pub fn signature_2(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { + return signature(&PARAMS_2,sk,m,sig); +} + +pub fn verify_2(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { + return verify(&PARAMS_2,pk,m,sig); +} + + +pub fn keypair_3(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { + keypair(&PARAMS_3,tau,sk,pk); +} + +pub fn signature_3(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { + return signature(&PARAMS_3,sk,m,sig); +} + +pub fn verify_3(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { + return verify(&PARAMS_3,pk,m,sig); +} + + +pub fn keypair_5(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { + keypair(&PARAMS_5,tau,sk,pk); +} + +pub fn signature_5(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { + return signature(&PARAMS_5,sk,m,sig); +} + +pub fn verify_5(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { + return verify(&PARAMS_5,pk,m,sig); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs new file mode 100644 index 000000000000..310b02b972cc --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const GCM_NB: usize = 4; +const GCM_ACCEPTING_HEADER: usize = 0; +const GCM_ACCEPTING_CIPHER: usize = 1; +const GCM_NOT_ACCEPTING_MORE: usize = 2; +const GCM_FINISHED: usize = 3; +//const GCM_ENCRYPTING: usize = 0; +//const GCM_DECRYPTING: usize = 1; + +use crate::aes; +use crate::aes::AES; + +pub struct GCM { + table: [[u32; 4]; 128], + statex: [u8; 16], + y_0: [u8; 16], + // counter: usize, + lena: [u32; 2], + lenc: [u32; 2], + status: usize, + a: AES, +} + +impl GCM { + fn pack(b: [u8; 4]) -> u32 { + /* pack bytes into a 32-bit Word */ + ((b[0] as u32) << 24) + | ((b[1] as u32) << 16) + | ((b[2] as u32) << 8) + | (b[3] as u32) + } + + fn unpack(a: u32) -> [u8; 4] { + /* unpack bytes from a word */ + [ + ((a >> 24) & 0xff) as u8, + ((a >> 16) & 0xff) as u8, + ((a >> 8) & 0xff) as u8, + (a & 0xff) as u8, + ] + } + + fn precompute(&mut self, h: &[u8]) { + let mut b: [u8; 4] = [0; 4]; + let mut j = 0; + for i in 0..GCM_NB { + b[0] = h[j]; + b[1] = h[j + 1]; + b[2] = h[j + 2]; + b[3] = h[j + 3]; + self.table[0][i] = GCM::pack(b); + j += 4; + } + for i in 1..128 { + let mut c: u32 = 0; + for j in 0..GCM_NB { + self.table[i][j] = c | (self.table[i - 1][j]) >> 1; + c = self.table[i - 1][j] << 31; + } + if c != 0 { + self.table[i][0] ^= 0xE1000000 + } /* irreducible polynomial */ + } + } + + fn gf2mul(&mut self) { + /* gf2m mul - Z=H*X mod 2^128 */ + let mut p: [u32; 4] = [0; 4]; + + for i in 0..4 { + p[i] = 0 + } + let mut j: usize = 8; + let mut m = 0; + for i in 0..128 { + j -= 1; + let mut c = ((self.statex[m] >> j) & 1) as u32; + c = (!c).wrapping_add(1); // + 1; + for k in 0..GCM_NB { + p[k] ^= self.table[i][k] & c + } + if j == 0 { + j = 8; + m += 1; + if m == 16 { + break; + } + } + } + j = 0; + for i in 0..GCM_NB { + let b = GCM::unpack(p[i]); + self.statex[j] = b[0]; + self.statex[j + 1] = b[1]; + self.statex[j + 2] = b[2]; + self.statex[j + 3] = b[3]; + j += 4; + } + } + + fn wrap(&mut self) { + /* Finish off GHASH */ + let mut f: [u32; 4] = [0; 4]; + let mut el: [u8; 16] = [0; 16]; + + /* convert lengths from bytes to bits */ + f[0] = (self.lena[0] << 3) | (self.lena[1] & 0xE0000000) >> 29; + f[1] = self.lena[1] << 3; + f[2] = (self.lenc[0] << 3) | (self.lenc[1] & 0xE0000000) >> 29; + f[3] = self.lenc[1] << 3; + let mut j = 0; + for i in 0..GCM_NB { + let b = GCM::unpack(f[i]); + el[j] = b[0]; + el[j + 1] = b[1]; + el[j + 2] = b[2]; + el[j + 3] = b[3]; + j += 4; + } + for i in 0..16 { + self.statex[i] ^= el[i] + } + self.gf2mul(); + } + + fn ghash(&mut self, plain: &[u8], len: usize) -> bool { + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + for i in 0..16 { + if j >= len { + break; + } + self.statex[i] ^= plain[j]; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul(); + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Initialize GCM mode */ + pub fn init(&mut self, nk: usize, key: &[u8], niv: usize, iv: &[u8]) { + /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ + let mut h: [u8; 16] = [0; 16]; + + for i in 0..16 { + h[i] = 0; + self.statex[i] = 0 + } + + self.a = AES::new(); + + self.a.init(aes::ECB, nk, key, None); + self.a.ecb_encrypt(&mut h); /* E(K,0) */ + self.precompute(&h); + + self.lena[0] = 0; + self.lenc[0] = 0; + self.lena[1] = 0; + self.lenc[1] = 0; + if niv == 12 { + for i in 0..12 { + self.a.f[i] = iv[i] + } + let b = GCM::unpack(1); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* initialise IV */ + for i in 0..16 { + self.y_0[i] = self.a.f[i] + } + } else { + self.status = GCM_ACCEPTING_CIPHER; + self.ghash(iv, niv); /* GHASH(H,0,IV) */ + self.wrap(); + for i in 0..16 { + self.a.f[i] = self.statex[i]; + self.y_0[i] = self.a.f[i]; + self.statex[i] = 0 + } + self.lena[0] = 0; + self.lenc[0] = 0; + self.lena[1] = 0; + self.lenc[1] = 0; + } + self.status = GCM_ACCEPTING_HEADER; + } + + pub fn new() -> GCM { + GCM { + table: [[0; 4]; 128], + statex: [0; 16], + y_0: [0; 16], + //counter:0, + lena: [0; 2], + lenc: [0; 2], + status: 0, + a: AES::new(), + } + } + + /* Add Header data - included but not encrypted */ + pub fn add_header(&mut self, header: &[u8], len: usize) -> bool { + /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ + if self.status != GCM_ACCEPTING_HEADER { + return false; + } + let mut j = 0; + while j < len { + for i in 0..16 { + if j >= len { + break; + } + self.statex[i] ^= header[j]; + j += 1; + self.lena[1] += 1; + if self.lena[1] == 0 { + self.lena[0] += 1 + } + } + self.gf2mul(); + } + if len % 16 != 0 { + self.status = GCM_ACCEPTING_CIPHER + } + true + } + + /* Add Plaintext - included and encrypted */ + /* if plain is None - encrypts cipher in place */ + pub fn add_plain(&mut self, cipher: &mut [u8], plain: Option<&[u8]>, len: usize) -> bool { + let mut cb: [u8; 16] = [0; 16]; + let mut b: [u8; 4] = [0; 4]; + + let mut counter: u32; + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + b[0] = self.a.f[12]; + b[1] = self.a.f[13]; + b[2] = self.a.f[14]; + b[3] = self.a.f[15]; + counter = GCM::pack(b); + counter += 1; + b = GCM::unpack(counter); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* increment counter */ + for i in 0..16 { + cb[i] = self.a.f[i] + } + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + + for i in 0..16 { + if j >= len { + break; + } + + if let Some(sp) = plain { + cipher[j] = sp[j] ^ cb[i]; + } else { + cipher[j] ^=cb[i]; + } + + self.statex[i] ^= cipher[j]; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul() + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Add Ciphertext - decrypts to plaintext */ + /* if cipher is None - decrypts plain in place */ + pub fn add_cipher(&mut self, plain: &mut [u8], cipher: Option<&[u8]>, len: usize) -> bool { + let mut cb: [u8; 16] = [0; 16]; + let mut b: [u8; 4] = [0; 4]; + + let mut counter: u32; + + if self.status == GCM_ACCEPTING_HEADER { + self.status = GCM_ACCEPTING_CIPHER + } + if self.status != GCM_ACCEPTING_CIPHER { + return false; + } + + let mut j = 0; + while j < len { + b[0] = self.a.f[12]; + b[1] = self.a.f[13]; + b[2] = self.a.f[14]; + b[3] = self.a.f[15]; + counter = GCM::pack(b); + counter += 1; + b = GCM::unpack(counter); + self.a.f[12] = b[0]; + self.a.f[13] = b[1]; + self.a.f[14] = b[2]; + self.a.f[15] = b[3]; /* increment counter */ + for i in 0..16 { + cb[i] = self.a.f[i] + } + self.a.ecb_encrypt(&mut cb); /* encrypt it */ + for i in 0..16 { + if j >= len { + break; + } + let oc:u8; + if let Some(sc) = cipher { + oc = sc[j]; + } else { + oc = plain[j]; + } + + plain[j] = oc ^ cb[i]; + self.statex[i] ^= oc; + j += 1; + self.lenc[1] += 1; + if self.lenc[1] == 0 { + self.lenc[0] += 1 + } + } + self.gf2mul() + } + if len % 16 != 0 { + self.status = GCM_NOT_ACCEPTING_MORE + } + true + } + + /* Finish and extract Tag */ + pub fn finish(&mut self,tag: &mut [u8], extract: bool) { + /* Finish off GHASH and extract tag (MAC) */ + self.wrap(); + /* extract tag */ + if extract { + self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ + for i in 0..16 { + self.y_0[i] ^= self.statex[i] + } + for i in 0..16 { + tag[i] = self.y_0[i]; + self.y_0[i] = 0; + self.statex[i] = 0 + } + } + self.status = GCM_FINISHED; + self.a.end(); + } + + pub fn hex2bytes(hex: &[u8], bin: &mut [u8]) { + let len = hex.len(); + + for i in 0..len / 2 { + let mut v: u8; + let mut c = hex[2 * i]; + if c >= b'0' && c <= b'9' { + v = c - b'0'; + } else if c >= b'A' && c <= b'F' { + v = c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v = c - b'a' + 10; + } else { + v = 0; + } + v <<= 4; + c = hex[2 * i + 1]; + if c >= b'0' && c <= b'9' { + v += c - b'0'; + } else if c >= b'A' && c <= b'F' { + v += c - b'A' + 10; + } else if c >= b'a' && c <= b'f' { + v += c - b'a' + 10; + } else { + v = 0; + } + bin[i] = v; + } + } +} + +pub fn encrypt(c: &mut [u8],t: &mut [u8],k: &[u8],iv: &[u8],h: &[u8],p: &[u8]) { + let mut g=GCM::new(); + g.init(k.len(),k,iv.len(),iv); + g.add_header(h,h.len()); + g.add_plain(c,Some(p),p.len()); + g.finish(t,true) +} + +pub fn decrypt(p: &mut [u8],t: &mut [u8],k: &[u8],iv: &[u8],h: &[u8],c: &[u8]) { + let mut g=GCM::new(); + g.init(k.len(),k,iv.len(),iv); + g.add_header(h,h.len()); + g.add_cipher(p,Some(c),c.len()); + g.finish(t,true); +} + +/* +fn main() +{ + let kt=b"feffe9928665731c6d6a8f9467308308"; + let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; + let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; + let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; +// Tag should be 619cc5aefffe0bfa462af43c1699d050 + + let mut gcm=GCM::new(); + + let len=mt.len()/2; + let lenh=ht.len()/2; + let lenk=kt.len()/2; + let leniv=nt.len()/2; + + //let mut t:[u8;16]=[0;16]; // Tag + let mut k:[u8;16]=[0;16]; // AES Key + let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted + let mut n:[u8;100]=[0;100]; // IV - Initialisation vector + let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated + let mut c:[u8;100]=[0;100]; // Ciphertext + let mut p:[u8;100]=[0;100]; // Recovered Plaintext + + GCM::hex2bytes(mt,&mut m); + GCM::hex2bytes(ht,&mut h); + GCM::hex2bytes(kt,&mut k); + GCM::hex2bytes(nt,&mut n); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",m[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_plain(&mut c,&m,len); + let mut t=gcm.finish(true); + + println!("Ciphertext="); + for i in 0..len {print!("{:02x}",c[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + + gcm.init(lenk,&k,leniv,&n); + + gcm.add_header(&h,lenh); + gcm.add_cipher(&mut p,&c,len); + t=gcm.finish(true); + + println!("Plaintext="); + for i in 0..len {print!("{:02x}",p[i])} + println!(""); + + println!("Tag="); + for i in 0..16 {print!("{:02x}",t[i])} + println!(""); + +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs new file mode 100644 index 000000000000..8a7b7668a8db --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH256_H0: u32 = 0x6A09E667; +const HASH256_H1: u32 = 0xBB67AE85; +const HASH256_H2: u32 = 0x3C6EF372; +const HASH256_H3: u32 = 0xA54FF53A; +const HASH256_H4: u32 = 0x510E527F; +const HASH256_H5: u32 = 0x9B05688C; +const HASH256_H6: u32 = 0x1F83D9AB; +const HASH256_H7: u32 = 0x5BE0CD19; + +const HASH256_K: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; + +pub struct HASH256 { + length: [u32; 2], + h: [u32; 8], + w: [u32; 64], +} + +impl HASH256 { + fn s(n: u32, x: u32) -> u32 { + ((x) >> n) | ((x) << (32 - n)) + } + fn r(n: u32, x: u32) -> u32 { + (x) >> n + } + + fn ch(x: u32, y: u32, z: u32) -> u32 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u32, y: u32, z: u32) -> u32 { + (x & y) ^ (x & z) ^ (y & z) + } + fn sig0(x: u32) -> u32 { + HASH256::s(2, x) ^ HASH256::s(13, x) ^ HASH256::s(22, x) + } + + fn sig1(x: u32) -> u32 { + HASH256::s(6, x) ^ HASH256::s(11, x) ^ HASH256::s(25, x) + } + + fn theta0(x: u32) -> u32 { + HASH256::s(7, x) ^ HASH256::s(18, x) ^ HASH256::r(3, x) + } + + fn theta1(x: u32) -> u32 { + HASH256::s(17, x) ^ HASH256::s(19, x) ^ HASH256::r(10, x) + } + + pub fn as_bytes(&self,array: &mut [u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=self.length[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..8 { + let mut t=self.h[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..64 { + let mut t=self.w[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + } + + pub fn from_bytes(&mut self,array: &[u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=array[ptr+3] as u32; + t=256*t+(array[ptr+2] as u32); + t=256*t+(array[ptr+1] as u32); + t=256*t+(array[ptr] as u32); + self.length[i]=t; ptr+=4; + } + for i in 0..8 { + let mut t=array[ptr+3] as u32; + t=256*t+(array[ptr+2] as u32); + t=256*t+(array[ptr+1] as u32); + t=256*t+(array[ptr] as u32); + self.h[i]=t; ptr+=4; + } + for i in 0..64 { + let mut t=array[ptr+3] as u32; + t=256*t+(array[ptr+2] as u32); + t=256*t+(array[ptr+1] as u32); + t=256*t+(array[ptr] as u32); + self.w[i]=t; ptr+=4; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..64 { + self.w[j] = HASH256::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH256::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..64 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH256::sig1(e)) + .wrapping_add(HASH256::ch(e, f, g)) + .wrapping_add(HASH256_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH256::sig0(a).wrapping_add(HASH256::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH256_H0; + self.h[1] = HASH256_H1; + self.h[2] = HASH256_H2; + self.h[3] = HASH256_H3; + self.h[4] = HASH256_H4; + self.h[5] = HASH256_H5; + self.h[6] = HASH256_H6; + self.h[7] = HASH256_H7; + } + + pub fn new() -> HASH256 { + let mut nh = HASH256 { + length: [0; 2], + h: [0; 8], + w: [0; 64], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH256) -> HASH256 { + let mut nh = HASH256 { + length: [0; 2], + h: [0; 8], + w: [0; 64], + }; + nh.length[0]=hh.length[0]; + nh.length[1]=hh.length[1]; + for i in 0..64 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 32) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u32; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 512) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 32] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 32] = [0; 32]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 512) != 448 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..32 { + /* convert to bytes */ + digest[i] = ((self.h[i / 4] >> (8 * (3 - i % 4))) & 0xff) as u8; + } + self.init(); + digest + } + + pub fn continuing_hash(&self) -> [u8; 32] { + let mut sh=HASH256::new_copy(self); + sh.hash() + } +} + +//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 +/* +fn main() { + let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + let test = s.into_bytes(); + let mut sh=HASH256::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..32 {print!("{:02x}",digest[i])} +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs new file mode 100644 index 000000000000..3b41197cc160 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH384_H0: u64 = 0xcbbb9d5dc1059ed8; +const HASH384_H1: u64 = 0x629a292a367cd507; +const HASH384_H2: u64 = 0x9159015a3070dd17; +const HASH384_H3: u64 = 0x152fecd8f70e5939; +const HASH384_H4: u64 = 0x67332667ffc00b31; +const HASH384_H5: u64 = 0x8eb44a8768581511; +const HASH384_H6: u64 = 0xdb0c2e0d64f98fa7; +const HASH384_H7: u64 = 0x47b5481dbefa4fa4; + +const HASH384_K: [u64; 80] = [ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +]; + +pub struct HASH384 { + length: [u64; 2], + h: [u64; 8], + w: [u64; 80], +} + +impl HASH384 { + fn s(n: u64, x: u64) -> u64 { + ((x) >> n) | ((x) << (64 - n)) + } + fn r(n: u64, x: u64) -> u64 { + (x) >> n + } + + fn ch(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (x & z) ^ (y & z) + } + + fn sig0(x: u64) -> u64 { + HASH384::s(28, x) ^ HASH384::s(34, x) ^ HASH384::s(39, x) + } + + fn sig1(x: u64) -> u64 { + HASH384::s(14, x) ^ HASH384::s(18, x) ^ HASH384::s(41, x) + } + + fn theta0(x: u64) -> u64 { + HASH384::s(1, x) ^ HASH384::s(8, x) ^ HASH384::r(7, x) + } + + fn theta1(x: u64) -> u64 { + HASH384::s(19, x) ^ HASH384::s(61, x) ^ HASH384::r(6, x) + } + + pub fn as_bytes(&self,array: &mut [u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=self.length[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..8 { + let mut t=self.h[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..80 { + let mut t=self.w[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + } + + pub fn from_bytes(&mut self,array: &[u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.length[i]=t; ptr+=8; + } + for i in 0..8 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.h[i]=t; ptr+=8; + } + for i in 0..80 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.w[i]=t; ptr+=8; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..80 { + self.w[j] = HASH384::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH384::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..80 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH384::sig1(e)) + .wrapping_add(HASH384::ch(e, f, g)) + .wrapping_add(HASH384_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH384::sig0(a).wrapping_add(HASH384::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH384_H0; + self.h[1] = HASH384_H1; + self.h[2] = HASH384_H2; + self.h[3] = HASH384_H3; + self.h[4] = HASH384_H4; + self.h[5] = HASH384_H5; + self.h[6] = HASH384_H6; + self.h[7] = HASH384_H7; + } + + pub fn new() -> HASH384 { + let mut nh = HASH384 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH384) -> HASH384 { + let mut nh = HASH384 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.length[0]=hh.length[0]; + nh.length[1]=hh.length[1]; + for i in 0..80 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 64) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u64; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 1024) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 48] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 48] = [0; 48]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 1024) != 896 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..48 { + /* convert to bytes */ + digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; + } + self.init(); + digest + } + pub fn continuing_hash(&self) -> [u8; 48] { + let mut sh=HASH384::new_copy(self); + sh.hash() + } +} + +//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH384::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..48 {print!("{:02x}",digest[i])} +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs new file mode 100644 index 000000000000..94f8cca6468f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const HASH512_H0: u64 = 0x6a09e667f3bcc908; +const HASH512_H1: u64 = 0xbb67ae8584caa73b; +const HASH512_H2: u64 = 0x3c6ef372fe94f82b; +const HASH512_H3: u64 = 0xa54ff53a5f1d36f1; +const HASH512_H4: u64 = 0x510e527fade682d1; +const HASH512_H5: u64 = 0x9b05688c2b3e6c1f; +const HASH512_H6: u64 = 0x1f83d9abfb41bd6b; +const HASH512_H7: u64 = 0x5be0cd19137e2179; + +const HASH512_K: [u64; 80] = [ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +]; + +pub struct HASH512 { + length: [u64; 2], + h: [u64; 8], + w: [u64; 80], +} + +impl HASH512 { + fn s(n: u64, x: u64) -> u64 { + ((x) >> n) | ((x) << (64 - n)) + } + fn r(n: u64, x: u64) -> u64 { + (x) >> n + } + + fn ch(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (!(x) & z) + } + + fn maj(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (x & z) ^ (y & z) + } + + fn sig0(x: u64) -> u64 { + HASH512::s(28, x) ^ HASH512::s(34, x) ^ HASH512::s(39, x) + } + + fn sig1(x: u64) -> u64 { + HASH512::s(14, x) ^ HASH512::s(18, x) ^ HASH512::s(41, x) + } + + fn theta0(x: u64) -> u64 { + HASH512::s(1, x) ^ HASH512::s(8, x) ^ HASH512::r(7, x) + } + + fn theta1(x: u64) -> u64 { + HASH512::s(19, x) ^ HASH512::s(61, x) ^ HASH512::r(6, x) + } + + pub fn as_bytes(&self,array: &mut [u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=self.length[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..8 { + let mut t=self.h[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + for i in 0..80 { + let mut t=self.w[i]; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=(t%256) as u8; t/=256; ptr+=1; + array[ptr]=t as u8; ptr+=1; + } + } + + pub fn from_bytes(&mut self,array: &[u8]) { + let mut ptr=0; + for i in 0..2 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.length[i]=t; ptr+=8; + } + for i in 0..8 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.h[i]=t; ptr+=8; + } + for i in 0..80 { + let mut t=array[ptr+7] as u64; + t=256*t+(array[ptr+6] as u64); + t=256*t+(array[ptr+5] as u64); + t=256*t+(array[ptr+4] as u64); + t=256*t+(array[ptr+3] as u64); + t=256*t+(array[ptr+2] as u64); + t=256*t+(array[ptr+1] as u64); + t=256*t+(array[ptr] as u64); + self.w[i]=t; ptr+=8; + } + } + + fn transform(&mut self) { + /* basic transformation step */ + for j in 16..80 { + self.w[j] = HASH512::theta1(self.w[j - 2]) + .wrapping_add(self.w[j - 7]) + .wrapping_add(HASH512::theta0(self.w[j - 15])) + .wrapping_add(self.w[j - 16]); + } + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut hh = self.h[7]; + for j in 0..80 { + /* 64 times - mush it up */ + let t1 = hh + .wrapping_add(HASH512::sig1(e)) + .wrapping_add(HASH512::ch(e, f, g)) + .wrapping_add(HASH512_K[j]) + .wrapping_add(self.w[j]); + let t2 = HASH512::sig0(a).wrapping_add(HASH512::maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.wrapping_add(t1); + d = c; + c = b; + b = a; + a = t1.wrapping_add(t2); + } + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(hh); + } + + /* Initialise Hash function */ + pub fn init(&mut self) { + /* initialise */ + for i in 0..64 { + self.w[i] = 0 + } + self.length[0] = 0; + self.length[1] = 0; + self.h[0] = HASH512_H0; + self.h[1] = HASH512_H1; + self.h[2] = HASH512_H2; + self.h[3] = HASH512_H3; + self.h[4] = HASH512_H4; + self.h[5] = HASH512_H5; + self.h[6] = HASH512_H6; + self.h[7] = HASH512_H7; + } + + pub fn new() -> HASH512 { + let mut nh = HASH512 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.init(); + nh + } + + pub fn new_copy(hh: &HASH512) -> HASH512 { + let mut nh = HASH512 { + length: [0; 2], + h: [0; 8], + w: [0; 80], + }; + nh.length[0]=hh.length[0]; + nh.length[1]=hh.length[1]; + for i in 0..80 { + nh.w[i] = hh.w[i]; + } + for i in 0..8 { + nh.h[i] = hh.h[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = ((self.length[0] / 64) % 16) as usize; + self.w[cnt] <<= 8; + self.w[cnt] |= byt as u64; + self.length[0] += 8; + if self.length[0] == 0 { + self.length[1] += 1; + self.length[0] = 0 + } + if (self.length[0] % 1024) == 0 { + self.transform() + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self) -> [u8; 64] { + /* pad message and finish - supply digest */ + let mut digest: [u8; 64] = [0; 64]; + let len0 = self.length[0]; + let len1 = self.length[1]; + self.process(0x80); + while (self.length[0] % 1024) != 896 { + self.process(0) + } + self.w[14] = len1; + self.w[15] = len0; + self.transform(); + for i in 0..64 { + /* convert to bytes */ + digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; + } + self.init(); + digest + } + pub fn continuing_hash(&self) -> [u8; 64] { + let mut sh=HASH512::new_copy(self); + sh.hash() + } +} + +//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let test = s.into_bytes(); + let mut sh=HASH512::new(); + + for i in 0..test.len(){ + sh.process(test[i]); + } + + let digest=sh.hash(); + for i in 0..64 {print!("{:02x}",digest[i])} +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs new file mode 100644 index 000000000000..eb2dc0a6c16d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +use crate::hash256::HASH256; +use crate::hash384::HASH384; +use crate::hash512::HASH512; +use crate::sha3::SHA3; +use crate::rand::RAND; + +pub const MC_SHA2: usize = 2; +pub const MC_SHA3: usize = 3; +pub const SHA256: usize = 32; +pub const SHA384: usize = 48; +pub const SHA512: usize = 64; + +#[allow(non_snake_case)] + +/* General Purpose Hash function */ + +#[allow(clippy::too_many_arguments)] +pub fn GPhashit(hash: usize, sha: usize,w: &mut [u8],pad: usize,zpad: usize,a: Option<&[u8]>, n: isize, b: Option<&[u8]>) { + let mut r: [u8; 64] = [0; 64]; + + if hash == MC_SHA2 { + if sha == SHA256 { + let mut h = HASH256::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + if sha == SHA384 { + let mut h = HASH384::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + if sha == SHA512 { + let mut h = HASH512::new(); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + let hs = h.hash(); + for i in 0..sha { + r[i] = hs[i]; + } + } + } + if hash == MC_SHA3 { + let mut h = SHA3::new(sha); + for _ in 0..zpad { + h.process(0); + } + if let Some(x) = a { + h.process_array(x); + } + if n >= 0 { + h.process_num(n as i32) + } + if let Some(x) = b { + h.process_array(x); + } + h.hash(&mut r); + } + + if pad == 0 { + for i in 0..sha { + w[i] = r[i] + } + } else if pad <= sha { + for i in 0..pad { + w[i] = r[i] + } + } else { + for i in 0..sha { + w[i + pad - sha] = r[i] + } + for i in 0..(pad - sha) { + w[i] = 0 + } + } +} + +#[allow(non_snake_case)] +pub fn SPhashit(hash: usize, sha: usize,w: &mut [u8],a: Option<&[u8]>) { + GPhashit(hash,sha,w,0,0,a,-1,None); +} + +pub fn inttobytes(n: usize, b: &mut [u8]) { + let mut i = b.len(); + let mut m = n; + while m > 0 && i > 0 { + i -= 1; + b[i] = (m & 0xff) as u8; + m /= 256; + } +} + +pub fn kdf2(hash: usize, sha: usize, z: &[u8], p: Option<&[u8]>, olen: usize, k: &mut [u8]) { + /* NOTE: the parameter olen is the length of the output K in bytes */ + let hlen = sha; + let mut lk = 0; + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + + for counter in 1..cthreshold + 1 { + let mut b: [u8; 64] = [0; 64]; + GPhashit(hash, sha, &mut b,0,0,Some(z), counter as isize, p); + if lk + hlen > olen { + for i in 0..(olen % hlen) { + k[lk] = b[i]; + lk += 1 + } + } else { + for i in 0..hlen { + k[lk] = b[i]; + lk += 1 + } + } + } +} + +/* Password based Key Derivation Function */ +/* Input password p, salt s, and repeat count */ +/* Output key of length olen */ +pub fn pbkdf2(hash: usize, sha: usize, pass: &[u8], salt: &[u8], rep: usize, olen: usize, k: &mut [u8]) { + let mut d = olen / sha; + if olen % sha != 0 { + d += 1 + } + let mut f: [u8; 64] = [0; 64]; + let mut u: [u8; 64] = [0; 64]; + let mut ku: [u8; 64] = [0; 64]; + let mut s: [u8; 36] = [0; 36]; // Maximum salt of 32 bytes + 4 + let mut n: [u8; 4] = [0; 4]; + + let sl = salt.len(); + let mut kp = 0; + for i in 0..d { + for j in 0..sl { + s[j] = salt[j] + } + inttobytes(i + 1, &mut n); + for j in 0..4 { + s[sl + j] = n[j] + } + + hmac1(hash, sha, &mut f, sha, &s[0..sl + 4], pass); + + for j in 0..sha { + u[j] = f[j] + } + + for _ in 1..rep { + hmac1(hash, sha, &mut ku, sha, &u, pass); + for m in 0..sha { + u[m] = ku[m]; + f[m] ^= u[m] + } + } + for j in 0..sha { + if kp < olen { + k[kp] = f[j] + } + kp += 1 + } + } +} + +fn blksize(hash: usize, sha: usize) -> usize { + let mut lb=0; + if hash == MC_SHA2 { + lb=64; + if sha > 32 { + lb=128; + } + } + if hash == MC_SHA3 { + lb=200-2*sha; + } + lb +} + +/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */ +pub fn hmac1(hash: usize, sha: usize, tag: &mut [u8], olen: usize, k: &[u8], m: &[u8]) -> bool { + /* Input is from an octet m * + * olen is requested output length in bytes. k is the key * + * The output is the calculated tag */ + let mut b: [u8; 64] = [0; 64]; /* Not good */ + let mut k0: [u8; 128] = [0; 128]; + + let lb=blksize(hash,sha); + if lb == 0 { + return false; + } + + for i in 0..lb { + k0[i] = 0 + } + + if k.len() > lb { + SPhashit(hash,sha,&mut b,Some(k)); + //GPhashit(hash, sha, &mut b,0,0,k, 0, None); + for i in 0..sha { + k0[i] = b[i] + } + } else { + for i in 0..k.len() { + k0[i] = k[i] + } + } + + for i in 0..lb { + k0[i] ^= 0x36 + } + + GPhashit(hash, sha, &mut b,0,0,Some(&k0[0..lb]), -1, Some(m)); + + for i in 0..lb { + k0[i] ^= 0x6a + } + GPhashit(hash, sha, tag,olen,0,Some(&k0[0..lb]), -1, Some(&b[0..sha])); + + true +} + +pub fn hkdf_extract(hash: usize, hlen: usize, prk: &mut [u8],salt: Option<&[u8]>,ikm: &[u8]) { + if let Some(x)=salt { + hmac1(hash,hlen,prk,hlen,x,ikm); + } else { + let h: [u8; 64] = [0; 64]; + hmac1(hash,hlen,prk,hlen,&h[0..hlen],ikm); + } +} + +pub fn hkdf_expand(hash: usize, hlen: usize, okm: &mut [u8], olen: usize, prk: &[u8], info: &[u8]) { + let n=olen/hlen; + let flen=olen%hlen; + + let mut t: [u8; 1024] = [0; 1024]; // >= info.length+hlen+1 + let mut k: [u8; 64] = [0; 64]; + + let mut l=0; + let mut m=0; + for i in 1..=n { + for j in 0..info.len() { + t[l]=info[j]; l+=1; + } + t[l]=i as u8; l+=1; + hmac1(hash,hlen,&mut k,hlen,prk,&t[0..l]); + l=0; + for j in 0..hlen { + okm[m]=k[j]; m+=1; + t[l]=k[j]; l+=1; + } + } + if flen>0 { + for j in 0..info.len() { + t[l]=info[j]; l+=1; + } + t[l]=(n+1) as u8; l+=1; + hmac1(hash,hlen,&mut k,flen,prk,&t[0..l]); + for j in 0..flen { + okm[m]=k[j]; m+=1; + } + } +} + +fn ceil(a: usize,b: usize) -> usize { + (a-1)/b+1 +} + +pub fn xof_expand(hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { + let mut h = SHA3::new(hlen); + for i in 0..msg.len() { + h.process(msg[i]); + } + h.process(((olen >> 8) & 0xff) as u8); + h.process((olen & 0xff) as u8); + + for i in 0..dst.len() { + h.process(dst[i]); + } + h.process((dst.len() & 0xff) as u8); + + h.shake(okm,olen); +} + +pub fn xmd_expand(hash: usize,hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { + let mut w:[u8; 64]=[0;64]; + if dst.len() >= 256 { + GPhashit(hash, hlen, &mut w, 0, 0, Some(b"H2C-OVERSIZE-DST-"), -1, Some(&dst)); + xmd_expand_short_dst(hash, hlen, okm, olen, &w[0..hlen], msg); + } else { + xmd_expand_short_dst(hash, hlen, okm, olen, dst, msg); + } +} + +// Assumes dst.len() < 256. +fn xmd_expand_short_dst(hash: usize,hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { + + let mut tmp: [u8; 260] = [0; 260]; + let mut h0: [u8; 64]=[0;64]; + let mut h1: [u8; 64]=[0;64]; + let mut h2: [u8; 64]=[0;64]; + + let ell=ceil(olen,hlen); + let blk=blksize(hash,hlen); + tmp[0]=((olen >> 8) & 0xff) as u8; + tmp[1]=(olen & 0xff) as u8; + tmp[2]=0; + + for j in 0..dst.len() { + tmp[3+j]=dst[j]; + } + tmp[3+dst.len()]=(dst.len() & 0xff) as u8; + + GPhashit(hash, hlen, &mut h0, 0, blk, Some(msg), -1, Some(&tmp[0..dst.len()+4])); + + let mut k=0; + for i in 1..=ell { + for j in 0..hlen { + h1[j]^=h0[j]; + h2[j]=h1[j]; + } + tmp[0]=i as u8; + + for j in 0..dst.len() { + tmp[1+j]=dst[j]; + } + tmp[1+dst.len()]=(dst.len() & 0xff) as u8; + + GPhashit(hash, hlen, &mut h1, 0, 0, Some(&h2[0..hlen]), -1, Some(&tmp[0..dst.len()+2])); + for j in 0..hlen { + okm[k]=h1[j]; + k+=1; + if k==olen { + break; + } + } + } + +} + +/* Mask Generation Function */ + +pub fn mgf1(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { + let hlen = sha; + + let mut j = 0; + for i in 0..k.len() { + k[i] = 0 + } + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + for counter in 0..cthreshold { + let mut b: [u8; 64] = [0; 64]; + GPhashit(MC_SHA2,sha,&mut b,0,0,Some(z),counter as isize,None); + //hashit(sha, Some(z), counter as isize, &mut b); + + if j + hlen > olen { + for i in 0..(olen % hlen) { + k[j] = b[i]; + j += 1 + } + } else { + for i in 0..hlen { + k[j] = b[i]; + j += 1 + } + } + } +} + +pub fn mgf1xor(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { + let hlen = sha; + let mut j = 0; + + let mut cthreshold = olen / hlen; + if olen % hlen != 0 { + cthreshold += 1 + } + for counter in 0..cthreshold { + let mut b: [u8; 64] = [0; 64]; + GPhashit(MC_SHA2,sha,&mut b,0,0,Some(z),counter as isize,None); + + if j + hlen > olen { + for i in 0..(olen % hlen) { + k[j] ^= b[i]; + j += 1 + } + } else { + for i in 0..hlen { + k[j] ^= b[i]; + j += 1 + } + } + } +} + +// PKCS 1.5 +/* SHAXXX identifier strings */ +const SHA256ID: [u8; 19] = [ + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20, +]; +const SHA384ID: [u8; 19] = [ + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30, +]; +const SHA512ID: [u8; 19] = [ + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40, +]; + +pub fn pkcs15(sha: usize, m: &[u8], w: &mut [u8],rfs: usize) -> bool { + let olen = rfs; + let hlen = sha; + let idlen = 19; + let mut b: [u8; 64] = [0; 64]; /* Not good */ + + if olen < idlen + hlen + 10 { + return false; + } + SPhashit(MC_SHA2,sha,&mut b,Some(m)); + + for i in 0..w.len() { + w[i] = 0 + } + let mut i = 0; + w[i] = 0; + i += 1; + w[i] = 1; + i += 1; + for _ in 0..olen - idlen - hlen - 3 { + w[i] = 0xff; + i += 1 + } + w[i] = 0; + i += 1; + if hlen == SHA256 { + for j in 0..idlen { + w[i] = SHA256ID[j]; + i += 1 + } + } + if hlen == SHA384 { + for j in 0..idlen { + w[i] = SHA384ID[j]; + i += 1 + } + } + if hlen == SHA512 { + for j in 0..idlen { + w[i] = SHA512ID[j]; + i += 1 + } + } + for j in 0..hlen { + w[i] = b[j]; + i += 1 + } + true +} + +// Alternate PKCS 1.5 +/* SHAXXX identifier strings */ +const SHA256IDB: [u8; 17] = [ + 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20]; +const SHA384IDB: [u8; 17] = [ + 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30]; +const SHA512IDB: [u8; 17] = [ + 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40]; + +pub fn pkcs15b(sha: usize, m: &[u8], w: &mut [u8],rfs: usize) -> bool { + let olen = rfs; + let hlen = sha; + let idlen = 17; + let mut b: [u8; 64] = [0; 64]; /* Not good */ + + if olen < idlen + hlen + 10 { + return false; + } + SPhashit(MC_SHA2,sha,&mut b,Some(m)); + for i in 0..w.len() { + w[i] = 0 + } + let mut i = 0; + w[i] = 0; + i += 1; + w[i] = 1; + i += 1; + for _ in 0..olen - idlen - hlen - 3 { + w[i] = 0xff; + i += 1 + } + w[i] = 0; + i += 1; + if hlen == SHA256 { + for j in 0..idlen { + w[i] = SHA256IDB[j]; + i += 1 + } + } + if hlen == SHA384 { + for j in 0..idlen { + w[i] = SHA384IDB[j]; + i += 1 + } + } + if hlen == SHA512 { + for j in 0..idlen { + w[i] = SHA512IDB[j]; + i += 1 + } + } + for j in 0..hlen { + w[i] = b[j]; + i += 1 + } + true +} + +pub fn pss_encode(sha: usize, m: &[u8], rng: &mut RAND, f: &mut [u8], rfs: usize) -> bool { + let emlen=rfs; + let embits=8*emlen-1; + let hlen=sha; + let mut h:[u8;64]=[0;64]; + let mut salt: [u8; 64] = [0; 64]; + let mut md: [u8;136]=[0;136]; + for i in 0..hlen { + salt[i] = rng.getbyte() + } + let mask=(0xff as u8)>> (8*emlen-embits); + SPhashit(MC_SHA2,sha,&mut h,Some(m)); + if emlen bool { + let emlen=f.len(); + let embits=8*emlen-1; + let hlen=sha; + let mut db:[u8;512]=[0;512]; + let mut hmask:[u8;64]=[0;64]; + let mut h:[u8;64]=[0;64]; + let mut salt: [u8; 64] = [0; 64]; + let mut md: [u8;136]=[0;136]; + let mask=(0xff as u8)>> (8*emlen-embits); + + SPhashit(MC_SHA2,sha,&mut hmask,Some(m)); + if emlen, f: &mut [u8], rfs: usize) -> bool { + let olen = rfs - 1; + let mlen = m.len(); + + let hlen = sha; + + let mut seed: [u8; 64] = [0; 64]; + + let seedlen = hlen; + if mlen > olen - hlen - seedlen - 1 { + return false; + } + + let mut dbmask: [u8; 512] = [0; 512]; + + SPhashit(MC_SHA2,sha,f,p); + //hashit(sha, p, -1, f); + let slen = olen - mlen - hlen - seedlen - 1; + + for i in 0..slen { + f[hlen + i] = 0 + } + f[hlen + slen] = 1; + for i in 0..mlen { + f[hlen + slen + 1 + i] = m[i] + } + + for i in 0..seedlen { + seed[i] = rng.getbyte() + } + + mgf1(sha, &seed[0..seedlen], olen - seedlen, &mut dbmask); + + for i in 0..olen - seedlen { + dbmask[i] ^= f[i] + } + + mgf1(sha, &dbmask[0..olen - seedlen], seedlen, f); + + for i in 0..seedlen { + f[i] ^= seed[i] + } + + for i in 0..olen - seedlen { + f[i + seedlen] = dbmask[i] + } + + /* pad to length rfs */ + let d = 1; + for i in (d..rfs).rev() { + f[i] = f[i - d]; + } + for i in (0..d).rev() { + f[i] = 0; + } + true +} + +/* OAEP Message Decoding for Decryption */ +pub fn oaep_decode(sha: usize, p: Option<&[u8]>, f: &mut [u8],rfs :usize) -> usize { + let olen = rfs - 1; + + let hlen = sha; + let mut seed: [u8; 64] = [0; 64]; + let seedlen = hlen; + let mut chash: [u8; 64] = [0; 64]; + + if olen < seedlen + hlen + 1 { + return 0; + } + let mut dbmask: [u8; 512] = [0; 512]; + + if f.len() < rfs { + let d = rfs - f.len(); + for i in (d..rfs).rev() { + f[i] = f[i - d]; + } + for i in (0..d).rev() { + f[i] = 0; + } + } + SPhashit(MC_SHA2,sha,&mut chash,p); + //hashit(sha, p, -1, &mut chash); + + let x = f[0]; + + for i in seedlen..olen { + dbmask[i - seedlen] = f[i + 1]; + } + + mgf1(sha, &dbmask[0..olen - seedlen], seedlen, &mut seed); + for i in 0..seedlen { + seed[i] ^= f[i + 1] + } + mgf1(sha, &seed[0..seedlen], olen - seedlen, f); + for i in 0..olen - seedlen { + dbmask[i] ^= f[i] + } + + let mut comp=0; + for i in 0..hlen { + comp |= (chash[i]^dbmask[i]) as usize; + } + + for i in 0..olen - seedlen - hlen { + dbmask[i] = dbmask[i + hlen] + } + + for i in 0..hlen { + seed[i] = 0; + chash[i] = 0 + } + +// find first non-zero t in array + let mut k=0; + let mut t=0; + let m=olen-seedlen-hlen; + for i in 0..m { + if t==0 && dbmask[i]!=0 { + k=i; + t=dbmask[i]; + } + } + + if comp!=0 || x != 0 || t != 0x01 { + for i in 0..olen - seedlen { + dbmask[i] = 0 + } + return 0; + } + + for i in 0..m - k - 1 { + f[i] = dbmask[i + k + 1]; + } + + for i in 0..olen - seedlen { + dbmask[i] = 0 + } + + m - k - 1 +} + +/* + +use core::sha3; +use core::hmac; + + + + let mut okm: [u8;100]=[0;100]; + let msg: &[u8] = b"abc"; + let dst: &[u8] = b"P256_XMD:SHA-256_SSWU_RO_TESTGEN"; + hmac::xof_expand(sha3::SHAKE128,&mut okm,48,&dst,&msg); + print!("okm= "); printbinary(&okm[0..48]); + hmac::xmd_expand(hmac::MC_SHA2,32,&mut okm,48,&dst,&msg); + print!("okm= "); printbinary(&okm[0..48]); + + + let mut ikm: [u8;22]=[0;22]; + let mut salt: [u8;13]=[0;13]; + let mut info: [u8;10]=[0;10]; + let mut prk: [u8;32]=[0;32]; + let mut okm: [u8;42]=[0;42]; + + for i in 0..22 {ikm[i]=0x0b;} + for i in 0..13 {salt[i]=i as u8;} + for i in 0..10 {info[i]=(0xf0+i) as u8;} + + hmac::hkdf_extract(hmac::MC_SHA2,32,&mut prk,Some(&salt),&ikm); + + print!("PRK= "); + for i in 0..32 { + print!("{:02X}",prk[i]); + } + + hmac::hkdf_expand(hmac::MC_SHA2,32,&mut okm,42,&prk,&info); + print!("OKM= "); + for i in 0..42 { + print!("{:02X}",okm[i]); + } + + +*/ + diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs new file mode 100644 index 000000000000..fdd96edd7673 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Kyber API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. + + M.Scott 06/07/2022 +*/ + +use crate::sha3; +use crate::sha3::SHA3; + +const LGN: usize = 8; +const DEGREE: usize = 1< i16 { + let dp=PRIME as i32; + let dt=(((a&0xffff)*QINV)&0xffff) as i16; + let t=((a-((dt as i32)*dp))>>16) as i16; + return t; +} + +fn barrett_reduce(a: i16) -> i16 { + let da=a as i32; + let mut t=((BARC*da + TWO25) >> 26) as i16; + t*=PRIME; + return a-t; +} + +fn fqmul(a: i16, b: i16) -> i16 { + return montgomery_reduce((a as i32)*(b as i32)); +} + +fn ntt(r: &mut [i16]) { + let mut k=1; + let mut len=128; + while len>=2 { + let mut start=0; + while start<256 { + let zeta=ZETAS[k]; k+=1; + let mut j=start; + while j>= 1; + } +} + +fn invntt(r: &mut [i16]) { + let f=1441 as i16; + let mut k=127; + let mut len=2; + while len<=128 { + let mut start=0; + while start<256 { + let zeta=ZETAS[k]; k-=1; + let mut j=start; + while j i16 { + let wd=n/8; + let bt=n%8; + return ((b[wd]>>bt)&1) as i16; +} + +fn cbd(bts: &[u8],eta: usize,f: &mut [i16]) { + for i in 0..DEGREE { + let mut a=0 as i16; + let mut b=0 as i16; + for j in 0..eta { + a+=getbit(bts,2*i*eta+j); + b+=getbit(bts,2*i*eta+eta+j); + } + f[i] = a-b; + } +} + +// extract ab bits into word from dense byte stream +fn nextword(ab: usize,t: &[u8],ptr: &mut usize,bts: &mut usize) -> i16 { + let mut r=(t[*ptr]>>(*bts)) as i16; + let mask=((1<=8 { + *bts -= 8; + *ptr += 1; + } + return r&mask; +} + +fn nextbyte16(ab: usize,t: &[i16],ptr: &mut usize,bts: &mut usize) -> u8 { + let mut left=ab-(*bts); + let mut i=0; + let mut w=t[*ptr]; w+=(w>>15)&PRIME; + let mut r=w>>(*bts); + while left<8 { + i+=1; + w=t[(*ptr)+i]; w+=(w>>15)&PRIME; + r|=w<=ab { + *bts -= ab; + *ptr += 1; + } + return (r&0xff) as u8; +} + +fn encode(t: &[i16],len: usize,l: usize,pack: &mut [u8]) { + let mut ptr=0; + let mut bts=0; + for n in 0..len*(DEGREE*l)/8 { + pack[n]=nextbyte16(l,t,&mut ptr, &mut bts); + } +} + +// return 0 if encoding is unchanged +fn chk_encode(t: &[i16],len: usize,l: usize,pack: &[u8]) -> u8 { + let mut ptr=0; + let mut bts=0; + let mut diff=0 as u8; + for n in 0..len*(DEGREE*l)/8 { + let m=nextbyte16(l,t,&mut ptr, &mut bts); + diff|=m^pack[n]; + } + return diff; +} + +fn decode(pack: &[u8],l: usize,t: &mut [i16],len: usize) { + let mut ptr=0; + let mut bts=0; + for i in 0..len*DEGREE { + t[i]=nextword(l,pack,&mut ptr,&mut bts); + } +} + +// Bernsteins safe division by 0xD01 +fn safediv(xx: i32) -> i32 { + let mut x=xx; + let mut q = 0 as i32; + + let mut qpart = (((x as i64)*645083)>>31) as i32; + x -= qpart*0xD01; q += qpart; + + qpart = ((((x as i64)*645083)>>31) as i32)+1; + x -= qpart*0xD01; q += qpart+(x>>31); + + return q; +} + +fn compress(t: &mut [i16],len:usize,d:usize) { + let twod=(1<>15)&PRIME; + t[i]= (safediv(twod*(t[i] as i32)+dp/2)&(twod-1)) as i16; + } +} +fn decompress(t: &mut [i16],len:usize,d:usize) { + let twod1=(1<<(d-1)) as i32; + let dp=PRIME as i32; + for i in 0..len*DEGREE { + t[i]=((dp*(t[i] as i32)+twod1)>>d) as i16; + } +} + + +fn cpa_keypair(params: &[usize],tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { + let mut rho:[u8;32]=[0;32]; + let mut sigma:[u8;33]=[0;33]; + let mut buff:[u8;256]=[0;256]; + + let mut r:[i16;DEGREE]=[0;DEGREE]; + let mut w:[i16;DEGREE]=[0;DEGREE]; + let mut aij:[i16;DEGREE]=[0;DEGREE]; + let mut s:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let mut e:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let mut p:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + + let mut sh = SHA3::new(sha3::HASH512); + + let ck=params[0]; + let eta1=params[1]; + let public_key_size=32+ck*(DEGREE*3)/2; + + for i in 0..32 { + sh.process(tau[i]); + } + sh.hash(&mut buff); + for i in 0..32 { + rho[i]=buff[i]; + sigma[i]=buff[i+32]; + } + sigma[32]=0; + +// create s + for i in 0..ck { + sh=SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff,64*eta1); + cbd(&buff,eta1,&mut s[i*DEGREE..]); + sigma[32] += 1; + } + +// create e + for i in 0..ck { + sh=SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff,64*eta1); + cbd(&buff,eta1,&mut e[i*DEGREE..]); + sigma[32] += 1; + } + + for k in 0..ck { + let row=k*DEGREE; + poly_ntt(&mut s[row..]); + poly_ntt(&mut e[row..]); + } + + for i in 0..ck { + let row=i*DEGREE; + expandaij(&rho,&mut aij,i,0); + poly_mul(&mut r,&aij,&s); + for j in 1..ck { + expandaij(&rho,&mut aij,i,j); + poly_mul(&mut w,&s[j*DEGREE..],&aij); + poly_acc(&mut r,&w); + } + poly_reduce(&mut r); + poly_tomont(&mut r); + poly_add(&mut p[row..],&r,&e[row..]); + poly_reduce(&mut p[row..]); + } + + encode(&s,ck,12,sk); + encode(&p,ck,12,pk); + for i in 0..32 { + pk[public_key_size-32+i]=rho[i]; + } +} + +fn cpa_base_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],u: &mut [i16],v: &mut [i16]) { + let mut rho:[u8;32]=[0;32]; + let mut sigma:[u8;33]=[0;33]; + let mut buff:[u8;256]=[0;256]; + + let mut r:[i16;DEGREE]=[0;DEGREE]; + let mut w:[i16;DEGREE]=[0;DEGREE]; + let mut aij:[i16;DEGREE]=[0;DEGREE]; + let mut q:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let mut p:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + + let ck=params[0]; + let eta1=params[1]; + let eta2=params[2]; + let du=params[3]; + let dv=params[4]; + let public_key_size=32+ck*(DEGREE*3)/2; + + for i in 0..32 { + sigma[i]=coins[i]; + } + sigma[32]=0; + for i in 0..32 { + rho[i]=pk[i+public_key_size-32]; + } +// create q + for i in 0..ck { + let mut sh=SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff,64*eta1); + cbd(&buff,eta1,&mut q[i*DEGREE..]); + sigma[32] += 1; + } +// create e1 + for i in 0..ck { + let mut sh=SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff,64*eta2); + cbd(&buff,eta1,&mut u[i*DEGREE..]); + sigma[32] += 1; + } + for i in 0..ck { + let row=DEGREE*i; + poly_ntt(&mut q[row..]); + } + + for i in 0..ck { + let row=i*DEGREE; + expandaij(&rho,&mut aij,0,i); + poly_mul(&mut r,&aij,&q); + for j in 1..ck { + expandaij(&rho,&mut aij,j,i); + poly_mul(&mut w,&q[j*DEGREE..],&aij); + poly_acc(&mut r,&w); + } + poly_reduce(&mut r); + poly_invntt(&mut r); + poly_acc(&mut u[row..],&r); + poly_reduce(&mut u[row..]); + } + + decode(&pk,12,&mut p,ck); + + poly_mul(v,&p,&q); + for i in 1..ck { + let row=DEGREE*i; + poly_mul(&mut r,&p[row..],&q[row..]); + poly_acc(v,&r); + } + poly_invntt(v); + + let mut sh = SHA3::new(sha3::SHAKE256); + for j in 0..33 { + sh.process(sigma[j]); + } + sh.shake(&mut buff,64*eta2); + cbd(&buff,eta1,&mut w); // e2 + + poly_acc(v,&w); + + decode(&ss,1,&mut r,1); + decompress(&mut r,1,1); + poly_acc(v,&r); + poly_reduce(v); + compress(u,ck,du); + compress(v,1,dv); +} + +fn cpa_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],ct: &mut [u8]) { + let mut v:[i16;DEGREE]=[0;DEGREE]; + let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let ck=params[0]; + let du=params[3]; + let dv=params[4]; + let ciphertext_size=(du*ck+dv)*DEGREE/8; + cpa_base_encrypt(params,coins,pk,ss,&mut u,&mut v); + encode(&u,ck,du,ct); + encode(&v,1,dv,&mut ct[ciphertext_size-(dv*DEGREE/8)..]); +} + +// Re-encrypt and check that ct is OK (if so return is zero) +fn cpa_check_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],ct: &[u8]) -> u8 { + let mut v:[i16;DEGREE]=[0;DEGREE]; + let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let ck=params[0]; + let du=params[3]; + let dv=params[4]; + let ciphertext_size=(du*ck+dv)*DEGREE/8; + cpa_base_encrypt(params,coins,pk,ss,&mut u,&mut v); + let d1=chk_encode(&u,ck,du,ct); + let d2=chk_encode(&v,1,dv,&ct[ciphertext_size-(dv*DEGREE/8)..]); + if (d1|d2)==0 { + return 0; + } else { + return 0xff; + } +} + +fn cpa_decrypt(params: &[usize],sk: &[u8],ct: &[u8],ss: &mut [u8]) { + let mut w:[i16;DEGREE]=[0;DEGREE]; + let mut v:[i16;DEGREE]=[0;DEGREE]; + let mut r:[i16;DEGREE]=[0;DEGREE]; + let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + let mut s:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; + + let ck=params[0]; + let du=params[3]; + let dv=params[4]; + + decode(ct,du,&mut u,ck); + decode(&ct[(du*ck*DEGREE)/8..],dv,&mut v,1); + decompress(&mut u,ck,du); + decompress(&mut v,1,dv); + decode(sk,12,&mut s,ck); + + poly_ntt(&mut u); + poly_mul(&mut w,&u,&s); + for i in 1..ck { + let row=DEGREE*i; + poly_ntt(&mut u[row..]); + poly_mul(&mut r,&u[row..],&s[row..]); + poly_acc(&mut w,&r); + } + poly_reduce(&mut w); + poly_invntt(&mut w); + poly_dec(&mut v,&w); + compress(&mut v,1,1); + encode(&v,1,1,ss); +} + +fn cca_keypair(params: &[usize],randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { + let ck=params[0]; + let secret_cpa_key_size=ck*(DEGREE*3)/2; + let public_key_size=32+ck*(DEGREE*3)/2; + + cpa_keypair(params,randbytes64,sk,pk); + for i in 0..public_key_size { + sk[i+secret_cpa_key_size]=pk[i]; + } + let mut sh = SHA3::new(sha3::HASH256); + for i in 0..public_key_size { + sh.process(pk[i]); + } + sh.hash(&mut sk[secret_cpa_key_size+public_key_size..]); + for i in 0..32 { + sk[i+secret_cpa_key_size+public_key_size+32]=randbytes64[i+32]; + } +} + +fn cca_encrypt(params: &[usize],randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { + let mut hm:[u8;32]=[0;32]; + let mut h:[u8;32]=[0;32]; + let mut g:[u8;64]=[0;64]; + let ck=params[0]; + let du=params[3]; + let dv=params[4]; + let public_key_size=32+ck*(DEGREE*3)/2; + let ciphertext_size=(du*ck+dv)*DEGREE/8; + let shared_secret_size=params[5]; + + let mut sh = SHA3::new(sha3::HASH256); + for i in 0..32 { + sh.process(randbytes32[i]); + } + sh.hash(&mut hm); + + sh = SHA3::new(sha3::HASH256); + for i in 0..public_key_size { + sh.process(pk[i]); + } + sh.hash(&mut h); + + sh = SHA3::new(sha3::HASH512); + sh.process_array(&hm); + sh.process_array(&h); + sh.hash(&mut g); + cpa_encrypt(params,&g[32..],&pk,&hm,ct); + + sh = SHA3::new(sha3::HASH256); + for i in 0..ciphertext_size { + sh.process(ct[i]); + } + sh.hash(&mut h); + sh = SHA3::new(sha3::SHAKE256); + sh.process_array(&g[0..32]); + sh.process_array(&h); + sh.shake(ss,shared_secret_size); +} + +fn cca_decrypt(params: &[usize],sk: &[u8],ct: &[u8],ss: &mut [u8]) { + let mut m:[u8;32]=[0;32]; + let mut g:[u8;64]=[0;64]; + let ck=params[0]; + let secret_cpa_key_size=ck*(DEGREE*3)/2; + let public_key_size=32+ck*(DEGREE*3)/2; + let shared_secret_size=params[5]; + + let pk=&sk[secret_cpa_key_size..secret_cpa_key_size+public_key_size]; + let h=&sk[secret_cpa_key_size+public_key_size..secret_cpa_key_size+public_key_size+32]; + let z=&sk[secret_cpa_key_size+public_key_size+32..secret_cpa_key_size+public_key_size+64]; + + cpa_decrypt(params,sk,ct,&mut m); + + let mut sh = SHA3::new(sha3::HASH512); + sh.process_array(&m); + sh.process_array(h); + sh.hash(&mut g); + + let mask=cpa_check_encrypt(params,&g[32..],pk,&m,ct); // FO check ct is correct + + for i in 0..32 { + g[i]^=(g[i]^z[i])&mask; + } + + sh = SHA3::new(sha3::HASH256); + sh.process_array(&ct); + sh.hash(&mut m); + + sh = SHA3::new(sha3::SHAKE256); + sh.process_array(&g[0..32]); + sh.process_array(&m); + sh.shake(ss,shared_secret_size); +} + +// ********************* Kyber API ****************************** + +pub fn keypair_512(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { + cca_keypair(&PARAMS_512,randbytes64,sk,pk); +} + +pub fn keypair_768(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { + cca_keypair(&PARAMS_768,randbytes64,sk,pk); +} + +pub fn keypair_1024(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { + cca_keypair(&PARAMS_1024,randbytes64,sk,pk); +} + +pub fn encrypt_512(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { + cca_encrypt(&PARAMS_512,randbytes32,pk,ss,ct); +} + +pub fn encrypt_768(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { + cca_encrypt(&PARAMS_768,randbytes32,pk,ss,ct); +} + +pub fn encrypt_1024(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { + cca_encrypt(&PARAMS_1024,randbytes32,pk,ss,ct); +} + +pub fn decrypt_512(sk: &[u8],ct: &[u8],ss: &mut [u8]) { + cca_decrypt(&PARAMS_512,sk,ct,ss); +} + +pub fn decrypt_768(sk: &[u8],ct: &[u8],ss: &mut [u8]) { + cca_decrypt(&PARAMS_768,sk,ct,ss); +} + +pub fn decrypt_1024(sk: &[u8],ct: &[u8],ss: &mut [u8]) { + cca_decrypt(&PARAMS_1024,sk,ct,ss); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs new file mode 100644 index 000000000000..7d2ebe7e4536 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// comment out if debugging with print macros !!! +#![cfg_attr(not(feature = "std"), no_std)] + +#![allow(clippy::many_single_char_names)] +#![allow(clippy::needless_range_loop)] +#![allow(clippy::manual_memcpy)] +#![allow(clippy::new_without_default)] +pub mod arch; +pub mod aes; +pub mod gcm; +pub mod hmac; +pub mod hash256; +pub mod hash384; +pub mod hash512; +pub mod rand; +pub mod share; +pub mod sha3; +pub mod nhs; +pub mod dilithium; +pub mod kyber; +pub mod x509; +pub mod bn254; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs new file mode 100644 index 000000000000..e7a11a969c03 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs new file mode 100644 index 000000000000..8fc70fb1c3d7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* NewHope Simple API high-level functions */ + +use crate::rand::RAND; +use crate::sha3; +use crate::sha3::SHA3; + +const PRIME: i32 = 0x3001; // q in Hex +const LGN: usize = 10; // Degree n=2^LGN +const ND: u32 = 0xF7002FFF; // 1/(R-q) mod R +const ONE: i32 = 0x2AC8; // R mod q +const R2MODP: u64 = 0x1620; // R^2 mod q + +const DEGREE: usize = 1 << LGN; +const WL: usize = 32; + +const INV: i32 = 0xeab; +const INVPR: i32 = 0x2c2a; + +const ROOTS: [i32; 1024] = [ + 0x2ac8, 0x2baf, 0x299b, 0x685, 0x2f04, 0x158d, 0x2d49, 0x24b5, 0x1edc, 0xab3, 0x2a95, 0x24d, + 0x3cb, 0x6a8, 0x12f9, 0x15ba, 0x1861, 0x2a89, 0x1c5c, 0xbe6, 0xc1e, 0x2024, 0x207, 0x19ce, + 0x2710, 0x1744, 0x18bc, 0x2cd7, 0x396, 0x18d5, 0x1c45, 0xc4, 0x21a6, 0xe03, 0x2b3c, 0x2d91, + 0xc5d, 0x432, 0x1fbc, 0xcae, 0x2512, 0x2979, 0x3b2, 0x714, 0xb2e, 0x1a97, 0x1a03, 0x1bcd, + 0x2216, 0x2701, 0xa, 0x263c, 0x1179, 0x200c, 0x2d08, 0x1c34, 0x291, 0x2c99, 0x2a5a, 0x723, + 0xb1d, 0x1ccc, 0x1fb6, 0x2f58, 0x2bfe, 0x1cda, 0x2a0, 0x5f1, 0x2de, 0x1fc7, 0x1ea8, 0x1719, + 0x2fa7, 0x27ec, 0x20ff, 0x12c0, 0x1ac1, 0x2232, 0x2f9b, 0xd3e, 0x2aed, 0x15f0, 0x11e8, 0xed0, + 0x26a, 0x1de5, 0xa3f, 0xf43, 0xebf, 0x204e, 0xac7, 0x2d9c, 0x5ea, 0x25d1, 0xb6, 0x49c, 0x995, + 0x2555, 0x26e2, 0x100, 0x1878, 0x5aa, 0x2e10, 0x271c, 0xcb, 0x1b4c, 0x2fb8, 0x25b7, 0x1543, + 0x2c7b, 0x241a, 0x2223, 0x20ca, 0x24ed, 0x137, 0x1b65, 0x1dc2, 0x7c7, 0x2ec3, 0xd0c, 0x1169, + 0x1c7a, 0x1ea1, 0xf89, 0x2199, 0x291d, 0x1088, 0x2046, 0x256d, 0x2bc7, 0x2e9b, 0x41f, 0x1b55, + 0x2b38, 0xd0, 0x2e6a, 0x1755, 0x6bc, 0x2724, 0x3ba, 0x222e, 0x2c5c, 0x2da5, 0x213c, 0x10fe, + 0x169a, 0x1552, 0x5d3, 0x300, 0x1b5d, 0x1342, 0x2004, 0x256f, 0x2039, 0x667, 0x23b5, 0x1123, + 0xdb, 0x2da0, 0xe1e, 0x2f54, 0x2767, 0x154a, 0x40a, 0x11d3, 0x2821, 0xc09, 0x974, 0x694, 0xfbf, + 0x27ba, 0x132, 0x83f, 0x2d06, 0x10e, 0x183f, 0x29ae, 0x28c3, 0x2dc9, 0x1144, 0x2c70, 0x2a4a, + 0xf3c, 0x1e32, 0x1171, 0x1e43, 0xdd4, 0x2ddf, 0x28d2, 0xfac, 0x3c4, 0x2f19, 0x10a6, 0x2f7, + 0xe1d, 0x828, 0x138f, 0x1332, 0xfab, 0xcf6, 0x13f8, 0x24a0, 0x112d, 0x2717, 0x6e7, 0x1044, + 0x36e, 0xfe8, 0x6a, 0xba7, 0x1d69, 0x29ec, 0x23b2, 0xaee, 0x16df, 0x1068, 0x1a7e, 0x253f, + 0x24c, 0xb33, 0x2683, 0x15ce, 0x1ad3, 0x1a36, 0xc96, 0xaea, 0x260a, 0xce, 0x28b1, 0xe4f, + 0x2b11, 0x5f8, 0x1fc4, 0xe77, 0x2366, 0x11f9, 0x153c, 0x24eb, 0x20cd, 0x1398, 0x22, 0x2b97, + 0x249b, 0x8eb, 0x12b2, 0x2fe3, 0x29c1, 0x1b00, 0x2663, 0xeaa, 0x2e06, 0xe0, 0x1569, 0x10f5, + 0x284e, 0xa38, 0x201d, 0x1c53, 0x1681, 0x1f6f, 0x2f95, 0x2fe8, 0xacb, 0x1680, 0x17fd, 0x2c39, + 0x165a, 0x10bb, 0x29d8, 0x2622, 0x1196, 0x884, 0x2a79, 0x140e, 0x2d80, 0x6fa, 0x11b2, 0x26c4, + 0x355, 0x1054, 0x29e9, 0x23ed, 0xbe3, 0x24fa, 0x1fb3, 0x10ac, 0x2919, 0x2584, 0x10a4, 0xe85, + 0x650, 0x1893, 0x1dc1, 0xd8e, 0x12dc, 0x2d42, 0x284d, 0xfff, 0x250f, 0xacd, 0x13c3, 0x6cc, + 0x1a79, 0x1221, 0x2614, 0x270a, 0x1ea, 0x155, 0x2818, 0x222c, 0x2e5b, 0x25d8, 0x1dbf, 0x191c, + 0xb0f, 0xdac, 0x1082, 0x12ef, 0x11b6, 0xfa8, 0x2b72, 0x159d, 0x209e, 0x31b, 0x2c7c, 0x14f7, + 0xe09, 0x1bb2, 0x1ec7, 0x2404, 0x20ae, 0x6ad, 0xed6, 0x2b70, 0x1c7b, 0x18d1, 0x2732, 0x12da, + 0xd56, 0x5c1, 0x1648, 0x18b7, 0x1605, 0x1bc4, 0x280, 0x2ece, 0xc, 0x1aae, 0x1c4, 0x1cdb, + 0x22d6, 0x21d8, 0x257c, 0x51f, 0x211b, 0xff, 0x2ee0, 0x2585, 0xe1, 0x2c35, 0x26db, 0x2971, + 0x2208, 0x17e1, 0x21be, 0x135e, 0x28d6, 0x2891, 0x1689, 0x2138, 0xb86, 0x2e3a, 0x1204, 0x2d10, + 0x2324, 0xf3f, 0x2508, 0x33d, 0xcb2, 0x292a, 0xe27, 0x2e64, 0x29f8, 0x2d46, 0x9b7, 0x20eb, + 0x1b7c, 0x9eb, 0x2b2a, 0x58c, 0x27d0, 0x121b, 0x272e, 0x29f6, 0x2dbd, 0x2697, 0x2aac, 0xd6f, + 0x1c67, 0x2c5b, 0x108d, 0x363, 0x249d, 0x2d5e, 0x2fd, 0x2cb2, 0x1f8f, 0x20a4, 0xa19, 0x2ac9, + 0x19b1, 0x1581, 0x17a2, 0x29eb, 0x1b72, 0x13b0, 0xee4, 0xa8f, 0x2315, 0x5e6, 0x951, 0x2e29, + 0xdad, 0x1f2b, 0x224e, 0x37f, 0x1a72, 0xa91, 0x1407, 0x2df9, 0x3ad, 0x23f7, 0x1a24, 0x1d2a, + 0x234b, 0x1df3, 0x1143, 0x7ff, 0x1a6d, 0x2774, 0x2690, 0x2ab5, 0x586, 0x2781, 0x2009, 0x2fdd, + 0x2881, 0x399, 0x2fb6, 0x144, 0x137f, 0xfa0, 0x2e4c, 0x1c7f, 0x2fac, 0xb09, 0x1264, 0x127b, + 0x198c, 0x2b40, 0x230, 0x1cf4, 0x180b, 0xb58, 0x144a, 0x2aec, 0xfb, 0x2602, 0x14ee, 0x783, + 0x1098, 0x23d8, 0x203, 0xe9, 0x108a, 0x14b8, 0xeec, 0xc58, 0x1248, 0x243c, 0x28aa, 0x6bf, + 0x27c4, 0x276e, 0x19b8, 0x1d11, 0x2e16, 0x472, 0x1464, 0x24b9, 0x662, 0x1097, 0x2067, 0x20d6, + 0x171c, 0x4, 0x682, 0x17bb, 0x1186, 0x4f2, 0x3ff, 0x2a43, 0x1dc7, 0x1ae5, 0x8cc, 0x2e7c, + 0x2ef8, 0x2ae0, 0x2904, 0xed4, 0x6c5, 0x14ae, 0xb72, 0x11c3, 0x337, 0x2da3, 0x2916, 0x6d8, + 0x1cf9, 0x10ee, 0x1800, 0x1ae4, 0xa0d, 0x101b, 0x1a8d, 0x2e98, 0x24cd, 0x813, 0x1aa4, 0x9b9, + 0x680, 0x2349, 0x24d1, 0x20f8, 0xe31, 0x249f, 0x216b, 0x12d9, 0x1d21, 0x19db, 0x191a, 0x1dd0, + 0x5df, 0x55c, 0x2b86, 0x213, 0xe9e, 0x1ef1, 0x268a, 0x1d5e, 0x1e20, 0x28c1, 0x1379, 0x249, + 0x19de, 0x18b, 0x1e41, 0x2a1e, 0x2612, 0x297, 0x2e96, 0x2102, 0x46, 0x1b9f, 0x1a4d, 0x2050, + 0x1b32, 0x568, 0x11f7, 0x1829, 0x870, 0x1f4, 0x1dca, 0x990, 0x1df6, 0x2b62, 0x13ec, 0x9f2, + 0x1260, 0x2997, 0x1412, 0x1e6d, 0x1694, 0x11ac, 0x2d8b, 0x276f, 0x26f5, 0x233e, 0x2b44, 0x2f5a, + 0x2d37, 0x2cb1, 0xc75, 0x98d, 0x1d56, 0x7ae, 0x10e6, 0x113f, 0x17b8, 0xad3, 0x737, 0x221e, + 0x1b70, 0x1f3e, 0x2966, 0x18b2, 0x4fa, 0x2044, 0x1312, 0x154e, 0x2029, 0x700, 0x1b45, 0x27a6, + 0x226a, 0x21bf, 0x58d, 0x2f11, 0x2e02, 0x17fc, 0x4d2, 0x1757, 0xcb1, 0x2ef1, 0x2582, 0x1276, + 0x881, 0x2fc0, 0x104a, 0x670, 0x274f, 0x2b53, 0x19dd, 0x752, 0x1663, 0xcbd, 0x2b2b, 0x2fc6, + 0x13b6, 0x21e6, 0x15f6, 0x126b, 0x2637, 0x1cd9, 0x2f50, 0xe82, 0x5b0, 0x24e0, 0x1350, 0x2f24, + 0x21f7, 0x1a16, 0x2f3e, 0x167e, 0x1f7d, 0x28a0, 0x16f0, 0xe33, 0x53b, 0x28c5, 0x1500, 0x2f88, + 0x26cc, 0x2018, 0x1604, 0x218b, 0x2cd1, 0x9ee, 0x17f3, 0x5fd, 0x1f5a, 0x2d0, 0x2b46, 0x23cc, + 0x503, 0x1c46, 0x1cc3, 0x28e2, 0x243e, 0x122b, 0x2e0c, 0xe37, 0x2611, 0x85e, 0x9b8, 0x1b24, + 0x762, 0x19b6, 0x3bc, 0x2d50, 0x2079, 0x18da, 0x170a, 0x800, 0xaa2, 0x135a, 0x1a15, 0x13d1, + 0xca, 0x2113, 0x2db9, 0xdb2, 0x1a5c, 0x29a9, 0x1488, 0x14c1, 0x2c9, 0x917, 0x28e7, 0x265c, + 0xdab, 0x2ab9, 0x2bc6, 0x105b, 0x1839, 0x219c, 0x50, 0x11da, 0x1802, 0xf56, 0x2e6, 0x2190, + 0xddb, 0x56e, 0x9d9, 0x1c81, 0x1016, 0x12d6, 0x296f, 0x14b4, 0x1014, 0x1e64, 0x1d90, 0x89f, + 0x2bc2, 0x2777, 0x2819, 0x1c65, 0x1a41, 0x5a2, 0x2cd2, 0x427, 0xd71, 0x29c8, 0x1e58, 0x53f, + 0x7c5, 0x1dcd, 0x4a1, 0x1268, 0x2597, 0x2926, 0xee, 0x111b, 0x1038, 0xe6c, 0x22dc, 0x2f2f, + 0x441, 0x2cfd, 0x1cb0, 0x6a4, 0x2224, 0x620, 0x5dc, 0x16b1, 0x2a1d, 0x1787, 0x20c7, 0x641, + 0xd84, 0x1c05, 0x2d0d, 0x2f52, 0x1b8c, 0xd7d, 0x17e8, 0x1589, 0xc73, 0x151b, 0x4e2, 0x1ae9, + 0x1b18, 0xb9b, 0x949, 0x2c60, 0x1e7a, 0xd5, 0x1bdc, 0x1f57, 0x1753, 0x124a, 0x559, 0xb76, + 0x2334, 0x12d1, 0x1de1, 0x14b2, 0x2faa, 0x1697, 0x147a, 0x5a1, 0x2c30, 0x1c02, 0x1043, 0x2ee1, + 0x2402, 0x1cc8, 0x2a16, 0xff7, 0x1364, 0x1b9a, 0x2a53, 0x2f94, 0x294c, 0x1ee5, 0x1a87, 0x2141, + 0xd66, 0x953, 0x28a3, 0x2f30, 0x2477, 0x18e3, 0x1035, 0x1fc1, 0x1d68, 0x2fb3, 0x138c, 0x2487, + 0x1bf8, 0xd96, 0x1018, 0x748, 0x244e, 0x15bd, 0x175e, 0x2be, 0x23d, 0x1da, 0x176d, 0xc17, + 0x24be, 0x2ebb, 0x7d8, 0x100a, 0x759, 0x1db4, 0x2259, 0x23f4, 0x2d59, 0x2847, 0xbf5, 0x1cfe, + 0xa20, 0x258, 0x1180, 0x279c, 0x54, 0x2abf, 0xc5c, 0x9f9, 0x3d5, 0x2ce4, 0x165f, 0x23d9, + 0x27b9, 0x6f9, 0x281a, 0x169e, 0x627, 0x156d, 0x1ff8, 0x211, 0x2e34, 0x1724, 0x2c2e, 0x2790, + 0x2dd5, 0x2bf2, 0xdbc, 0x2884, 0x20a9, 0x2390, 0x1e1a, 0x1b6a, 0x5f7, 0xab7, 0x1333, 0x16ab, + 0x28dd, 0x20, 0x30f, 0x24b6, 0x5c2, 0x1ce4, 0x1400, 0x2669, 0x60, 0x156c, 0xe20, 0x26d4, + 0x26ab, 0x1ebb, 0x223d, 0x5b4, 0x2025, 0x1e1c, 0xaae, 0x2e08, 0x6cd, 0x1677, 0x13d9, 0x17b5, + 0x1046, 0x1d8c, 0x14eb, 0x18d8, 0x1ce5, 0x2478, 0x16ae, 0xb79, 0x23d4, 0x684, 0x156b, 0x567, + 0x1a, 0x29ce, 0x83a, 0x19e8, 0x58e, 0x294a, 0x1136, 0x2319, 0x2fba, 0x1a29, 0x1d, 0x1879, + 0x291b, 0x19f6, 0x2c2f, 0x21c9, 0x19bb, 0xbbc, 0x26f9, 0xc22, 0x708, 0x11a1, 0x18d3, 0x7f8, + 0x28f8, 0x2427, 0x1deb, 0xaed, 0x26aa, 0x2482, 0x203b, 0x2f05, 0x2b82, 0x192f, 0x2df4, 0x8dc, + 0x2877, 0xd5e, 0x240e, 0x775, 0x2dae, 0x1d3e, 0x20ba, 0x215b, 0x22d1, 0xeba, 0xf50, 0xaa8, + 0x184a, 0x1f67, 0x2e04, 0xc6e, 0x6dd, 0x1a09, 0x27f, 0x494, 0x1426, 0xae3, 0xe15, 0x65f, + 0x13c4, 0x105, 0x872, 0x2667, 0x1ff6, 0xd9f, 0x2ca1, 0x2f39, 0x2657, 0x23fd, 0x2405, 0xb73, + 0x2294, 0x1f1e, 0x2eba, 0x110a, 0x2cae, 0x141f, 0x22cd, 0x25d6, 0x11c1, 0x1c, 0x2d8e, 0x161a, + 0x1aa8, 0x229e, 0x1bf9, 0x7cf, 0x106d, 0x2c40, 0xd93, 0x255e, 0x28c2, 0xc1a, 0x2f17, 0x7ca, + 0x2f63, 0xbf, +]; +const IROOTS: [i32; 1024] = [ + 0x2ac8, 0x452, 0x297c, 0x666, 0xb4c, 0x2b8, 0x1a74, 0xfd, 0x1a47, 0x1d08, 0x2959, 0x2c36, + 0x2db4, 0x56c, 0x254e, 0x1125, 0x2f3d, 0x13bc, 0x172c, 0x2c6b, 0x32a, 0x1745, 0x18bd, 0x8f1, + 0x1633, 0x2dfa, 0xfdd, 0x23e3, 0x241b, 0x13a5, 0x578, 0x17a0, 0xa9, 0x104b, 0x1335, 0x24e4, + 0x28de, 0x5a7, 0x368, 0x2d70, 0x13cd, 0x2f9, 0xff5, 0x1e88, 0x9c5, 0x2ff7, 0x900, 0xdeb, + 0x1434, 0x15fe, 0x156a, 0x24d3, 0x28ed, 0x2c4f, 0x688, 0xaef, 0x2353, 0x1045, 0x2bcf, 0x23a4, + 0x270, 0x4c5, 0x21fe, 0xe5b, 0xfbb, 0x1f79, 0x6e4, 0xe68, 0x2078, 0x1160, 0x1387, 0x1e98, + 0x22f5, 0x13e, 0x283a, 0x123f, 0x149c, 0x2eca, 0xb14, 0xf37, 0xdde, 0xbe7, 0x386, 0x1abe, + 0xa4a, 0x49, 0x14b5, 0x2f36, 0x8e5, 0x1f1, 0x2a57, 0x1789, 0x2f01, 0x91f, 0xaac, 0x266c, + 0x2b65, 0x2f4b, 0xa30, 0x2a17, 0x265, 0x253a, 0xfb3, 0x2142, 0x20be, 0x25c2, 0x121c, 0x2d97, + 0x2131, 0x1e19, 0x1a11, 0x514, 0x22c3, 0x66, 0xdcf, 0x1540, 0x1d41, 0xf02, 0x815, 0x5a, 0x18e8, + 0x1159, 0x103a, 0x2d23, 0x2a10, 0x2d61, 0x1327, 0x403, 0x25c9, 0x7b3, 0x1f0c, 0x1a98, 0x2f21, + 0x1fb, 0x2157, 0x99e, 0x1501, 0x640, 0x1e, 0x1d4f, 0x2716, 0xb66, 0x46a, 0x2fdf, 0x1c69, 0xf34, + 0xb16, 0x1ac5, 0x1e08, 0xc9b, 0x218a, 0x103d, 0x2a09, 0x4f0, 0x21b2, 0x750, 0x2f33, 0x9f7, + 0x2517, 0x236b, 0x15cb, 0x152e, 0x1a33, 0x97e, 0x24ce, 0x2db5, 0xac2, 0x1583, 0x1f99, 0x1922, + 0x2513, 0xc4f, 0x615, 0x1298, 0x245a, 0x2f97, 0x2019, 0x2c93, 0x1fbd, 0x291a, 0x8ea, 0x1ed4, + 0xb61, 0x1c09, 0x230b, 0x2056, 0x1ccf, 0x1c72, 0x27d9, 0x21e4, 0x2d0a, 0x1f5b, 0xe8, 0x2c3d, + 0x2055, 0x72f, 0x222, 0x222d, 0x11be, 0x1e90, 0x11cf, 0x20c5, 0x5b7, 0x391, 0x1ebd, 0x238, + 0x73e, 0x653, 0x17c2, 0x2ef3, 0x2fb, 0x27c2, 0x2ecf, 0x847, 0x2042, 0x296d, 0x268d, 0x23f8, + 0x7e0, 0x1e2e, 0x2bf7, 0x1ab7, 0x89a, 0xad, 0x21e3, 0x261, 0x2f26, 0x1ede, 0xc4c, 0x299a, + 0xfc8, 0xa92, 0xffd, 0x1cbf, 0x14a4, 0x2d01, 0x2a2e, 0x1aaf, 0x1967, 0x1f03, 0xec5, 0x25c, + 0x3a5, 0xdd3, 0x2c47, 0x8dd, 0x2945, 0x18ac, 0x197, 0x2f31, 0x4c9, 0x14ac, 0x2be2, 0x166, + 0x43a, 0xa94, 0x1b53, 0x293c, 0x212d, 0x6fd, 0x521, 0x109, 0x185, 0x2735, 0x151c, 0x123a, + 0x5be, 0x2c02, 0x2b0f, 0x1e7b, 0x1846, 0x297f, 0x2ffd, 0x18e5, 0xf2b, 0xf9a, 0x1f6a, 0x299f, + 0xb48, 0x1b9d, 0x2b8f, 0x1eb, 0x12f0, 0x1649, 0x893, 0x83d, 0x2942, 0x757, 0xbc5, 0x1db9, + 0x23a9, 0x2115, 0x1b49, 0x1f77, 0x2f18, 0x2dfe, 0xc29, 0x1f69, 0x287e, 0x1b13, 0x9ff, 0x2f06, + 0x515, 0x1bb7, 0x24a9, 0x17f6, 0x130d, 0x2dd1, 0x4c1, 0x1675, 0x1d86, 0x1d9d, 0x24f8, 0x55, + 0x1382, 0x1b5, 0x2061, 0x1c82, 0x2ebd, 0x4b, 0x2c68, 0x780, 0x24, 0xff8, 0x880, 0x2a7b, 0x54c, + 0x971, 0x88d, 0x1594, 0x2802, 0x1ebe, 0x120e, 0xcb6, 0x12d7, 0x15dd, 0xc0a, 0x2c54, 0x208, + 0x1bfa, 0x2570, 0x158f, 0x2c82, 0xdb3, 0x10d6, 0x2254, 0x1d8, 0x26b0, 0x2a1b, 0xcec, 0x2572, + 0x211d, 0x1c51, 0x148f, 0x616, 0x185f, 0x1a80, 0x1650, 0x538, 0x25e8, 0xf5d, 0x1072, 0x34f, + 0x2d04, 0x2a3, 0xb64, 0x2c9e, 0x1f74, 0x3a6, 0x139a, 0x2292, 0x555, 0x96a, 0x244, 0x60b, 0x8d3, + 0x1de6, 0x831, 0x2a75, 0x4d7, 0x2616, 0x1485, 0xf16, 0x264a, 0x2bb, 0x609, 0x19d, 0x21da, + 0x6d7, 0x234f, 0x2cc4, 0xaf9, 0x20c2, 0xcdd, 0x2f1, 0x1dfd, 0x1c7, 0x247b, 0xec9, 0x1978, + 0x770, 0x72b, 0x1ca3, 0xe43, 0x1820, 0xdf9, 0x690, 0x926, 0x3cc, 0x2f20, 0xa7c, 0x121, 0x2f02, + 0xee6, 0x2ae2, 0xa85, 0xe29, 0xd2b, 0x1326, 0x2e3d, 0x1553, 0x2ff5, 0x133, 0x2d81, 0x143d, + 0x19fc, 0x174a, 0x19b9, 0x2a40, 0x22ab, 0x1d27, 0x8cf, 0x1730, 0x1386, 0x491, 0x212b, 0x2954, + 0xf53, 0xbfd, 0x113a, 0x144f, 0x21f8, 0x1b0a, 0x385, 0x2ce6, 0xf63, 0x1a64, 0x48f, 0x2059, + 0x1e4b, 0x1d12, 0x1f7f, 0x2255, 0x24f2, 0x16e5, 0x1242, 0xa29, 0x1a6, 0xdd5, 0x7e9, 0x2eac, + 0x2e17, 0x8f7, 0x9ed, 0x1de0, 0x1588, 0x2935, 0x1c3e, 0x2534, 0xaf2, 0x2002, 0x7b4, 0x2bf, + 0x1d25, 0x2273, 0x1240, 0x176e, 0x29b1, 0x217c, 0x1f5d, 0xa7d, 0x6e8, 0x1f55, 0x104e, 0xb07, + 0x241e, 0xc14, 0x618, 0x1fad, 0x2cac, 0x93d, 0x1e4f, 0x2907, 0x281, 0x1bf3, 0x588, 0x277d, + 0x1e6b, 0x9df, 0x629, 0x1f46, 0x19a7, 0x3c8, 0x1804, 0x1981, 0x2536, 0x19, 0x6c, 0x1092, + 0x1980, 0x13ae, 0xfe4, 0x2f42, 0x9e, 0x2837, 0xea, 0x23e7, 0x73f, 0xaa3, 0x226e, 0x3c1, 0x1f94, + 0x2832, 0x1408, 0xd63, 0x1559, 0x19e7, 0x273, 0x2fe5, 0x1e40, 0xa2b, 0xd34, 0x1be2, 0x353, + 0x1ef7, 0x147, 0x10e3, 0xd6d, 0x248e, 0xbfc, 0xc04, 0x9aa, 0xc8, 0x360, 0x2262, 0x100b, 0x99a, + 0x278f, 0x2efc, 0x1c3d, 0x29a2, 0x21ec, 0x251e, 0x1bdb, 0x2b6d, 0x2d82, 0x15f8, 0x2924, 0x2393, + 0x1fd, 0x109a, 0x17b7, 0x2559, 0x20b1, 0x2147, 0xd30, 0xea6, 0xf47, 0x12c3, 0x253, 0x288c, + 0xbf3, 0x22a3, 0x78a, 0x2725, 0x20d, 0x16d2, 0x47f, 0xfc, 0xfc6, 0xb7f, 0x957, 0x2514, 0x1216, + 0xbda, 0x709, 0x2809, 0x172e, 0x1e60, 0x28f9, 0x23df, 0x908, 0x2445, 0x1646, 0xe38, 0x3d2, + 0x160b, 0x6e6, 0x1788, 0x2fe4, 0x15d8, 0x47, 0xce8, 0x1ecb, 0x6b7, 0x2a73, 0x1619, 0x27c7, + 0x633, 0x2fe7, 0x2a9a, 0x1a96, 0x297d, 0xc2d, 0x2488, 0x1953, 0xb89, 0x131c, 0x1729, 0x1b16, + 0x1275, 0x1fbb, 0x184c, 0x1c28, 0x198a, 0x2934, 0x1f9, 0x2553, 0x11e5, 0xfdc, 0x2a4d, 0xdc4, + 0x1146, 0x956, 0x92d, 0x21e1, 0x1a95, 0x2fa1, 0x998, 0x1c01, 0x131d, 0x2a3f, 0xb4b, 0x2cf2, + 0x2fe1, 0x724, 0x1956, 0x1cce, 0x254a, 0x2a0a, 0x1497, 0x11e7, 0xc71, 0xf58, 0x77d, 0x2245, + 0x40f, 0x22c, 0x871, 0x3d3, 0x18dd, 0x1cd, 0x2df0, 0x1009, 0x1a94, 0x29da, 0x1963, 0x7e7, + 0x2908, 0x848, 0xc28, 0x19a2, 0x31d, 0x2c2c, 0x2608, 0x23a5, 0x542, 0x2fad, 0x865, 0x1e81, + 0x2da9, 0x25e1, 0x1303, 0x240c, 0x7ba, 0x2a8, 0xc0d, 0xda8, 0x124d, 0x28a8, 0x1ff7, 0x2829, + 0x146, 0xb43, 0x23ea, 0x1894, 0x2e27, 0x2dc4, 0x2d43, 0x18a3, 0x1a44, 0xbb3, 0x28b9, 0x1fe9, + 0x226b, 0x1409, 0xb7a, 0x1c75, 0x4e, 0x1299, 0x1040, 0x1fcc, 0x171e, 0xb8a, 0xd1, 0x75e, + 0x26ae, 0x229b, 0xec0, 0x157a, 0x111c, 0x6b5, 0x6d, 0x5ae, 0x1467, 0x1c9d, 0x200a, 0x5eb, + 0x1339, 0xbff, 0x120, 0x1fbe, 0x13ff, 0x3d1, 0x2a60, 0x1b87, 0x196a, 0x57, 0x1b4f, 0x1220, + 0x1d30, 0xccd, 0x248b, 0x2aa8, 0x1db7, 0x18ae, 0x10aa, 0x1425, 0x2f2c, 0x1187, 0x3a1, 0x26b8, + 0x2466, 0x14e9, 0x1518, 0x2b1f, 0x1ae6, 0x238e, 0x1a78, 0x1819, 0x2284, 0x1475, 0xaf, 0x2f4, + 0x13fc, 0x227d, 0x29c0, 0xf3a, 0x187a, 0x5e4, 0x1950, 0x2a25, 0x29e1, 0xddd, 0x295d, 0x1351, + 0x304, 0x2bc0, 0xd2, 0xd25, 0x2195, 0x1fc9, 0x1ee6, 0x2f13, 0x6db, 0xa6a, 0x1d99, 0x2b60, + 0x1234, 0x283c, 0x2ac2, 0x11a9, 0x639, 0x2290, 0x2bda, 0x32f, 0x2a5f, 0x15c0, 0x139c, 0x7e8, + 0x88a, 0x43f, 0x2762, 0x1271, 0x119d, 0x1fed, 0x1b4d, 0x692, 0x1d2b, 0x1feb, 0x1380, 0x2628, + 0x2a93, 0x2226, 0xe71, 0x2d1b, 0x20ab, 0x17ff, 0x1e27, 0x2fb1, 0xe65, 0x17c8, 0x1fa6, 0x43b, + 0x548, 0x2256, 0x9a5, 0x71a, 0x26ea, 0x2d38, 0x1b40, 0x1b79, 0x658, 0x15a5, 0x224f, 0x248, + 0xeee, 0x2f37, 0x1c30, 0x15ec, 0x1ca7, 0x255f, 0x2801, 0x18f7, 0x1727, 0xf88, 0x2b1, 0x2c45, + 0x164b, 0x289f, 0x14dd, 0x2649, 0x27a3, 0x9f0, 0x21ca, 0x1f5, 0x1dd6, 0xbc3, 0x71f, 0x133e, + 0x13bb, 0x2afe, 0xc35, 0x4bb, 0x2d31, 0x10a7, 0x2a04, 0x180e, 0x2613, 0x330, 0xe76, 0x19fd, + 0xfe9, 0x935, 0x79, 0x1b01, 0x73c, 0x2ac6, 0x21ce, 0x1911, 0x761, 0x1084, 0x1983, 0xc3, 0x15eb, + 0xe0a, 0xdd, 0x1cb1, 0xb21, 0x2a51, 0x217f, 0xb1, 0x1328, 0x9ca, 0x1d96, 0x1a0b, 0xe1b, 0x1c4b, + 0x3b, 0x4d6, 0x2344, 0x199e, 0x28af, 0x1624, 0x4ae, 0x8b2, 0x2991, 0x1fb7, 0x41, 0x2780, + 0x1d8b, 0xa7f, 0x110, 0x2350, 0x18aa, 0x2b2f, 0x1805, 0x1ff, 0xf0, 0x2a74, 0xe42, 0xd97, 0x85b, + 0x14bc, 0x2901, 0xfd8, 0x1ab3, 0x1cef, 0xfbd, 0x2b07, 0x174f, 0x69b, 0x10c3, 0x1491, 0xde3, + 0x28ca, 0x252e, 0x1849, 0x1ec2, 0x1f1b, 0x2853, 0x12ab, 0x2674, 0x238c, 0x350, 0x2ca, 0xa7, + 0x4bd, 0xcc3, 0x90c, 0x892, 0x276, 0x1e55, 0x196d, 0x1194, 0x1bef, 0x66a, 0x1da1, 0x260f, + 0x1c15, 0x49f, 0x120b, 0x2671, 0x1237, 0x2e0d, 0x2791, 0x17d8, 0x1e0a, 0x2a99, 0x14cf, 0xfb1, + 0x15b4, 0x1462, 0x2fbb, 0xeff, 0x16b, 0x2d6a, 0x9ef, 0x5e3, 0x11c0, 0x2e76, 0x1623, 0x2db8, + 0x1c88, 0x740, 0x11e1, 0x12a3, 0x977, 0x1110, 0x2163, 0x2dee, 0x47b, 0x2aa5, 0x2a22, 0x1231, + 0x16e7, 0x1626, 0x12e0, 0x1d28, 0xe96, 0xb62, 0x21d0, 0xf09, 0xb30, 0xcb8, 0x2981, 0x2648, + 0x155d, 0x27ee, 0xb34, 0x169, 0x1574, 0x1fe6, 0x25f4, 0x151d, 0x1801, 0x1f13, 0x1308, 0x2929, + 0x6eb, 0x25e, 0x2cca, 0x1e3e, 0x248f, +]; + +fn round(a: i32, b: i32) -> i32 { + (a + b / 2) / b +} + +/* Constant time absolute value */ +fn nabs(x: i32) -> i32 { + let mask = x >> 31; + (x + mask) ^ mask +} + +/* Montgomery stuff */ + +fn redc(t: u64) -> i32 { + let m = (t as u32).wrapping_mul(ND); + (((m as u64) * (PRIME as u64) + t) >> WL) as i32 +} + +fn nres(x: i32) -> i32 { + redc((x as u64) * R2MODP) +} + +fn modmul(a: i32, b: i32) -> i32 { + redc((a as u64) * (b as u64)) +} + +/* Cooley-Tukey NTT */ +fn ntt(x: &mut [i32]) { + let mut t = DEGREE / 2; + let q = PRIME; + + /* Convert to Montgomery form */ + for j in 0..DEGREE { + x[j] = nres(x[j]) + } + let mut m = 1; + while m < DEGREE { + let mut k = 0; + for i in 0..m { + let s = ROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = modmul(x[j + t], s); + x[j] = u + v; + x[j + t] = u + 2 * q - v; + } + k += 2 * t; + } + t /= 2; + m *= 2; + } +} + +/* Gentleman-Sande INTT */ + +fn intt(x: &mut [i32]) { + let mut t = 1; + let q = PRIME; + let mut m = DEGREE / 2; + while m > 1 { + let mut k = 0; + for i in 0..m { + let s = IROOTS[m + i]; + for j in k..k + t { + let u = x[j]; + let v = x[j + t]; + x[j] = u + v; + let w = u + (DEGREE as i32) * q - v; + x[j + t] = modmul(w, s); + } + k += 2 * t; + } + t *= 2; + m /= 2; + } + + /* Last iteration merged with n^-1 */ + t = DEGREE / 2; + for j in 0..t { + let u = x[j]; + let v = x[j + t]; + let w = u + (DEGREE as i32) * q - v; + x[j + t] = modmul(w, INVPR); + x[j] = modmul(u + v, INV); + } + /* convert back from Montgomery to "normal" form */ + for j in 0..DEGREE { + x[j] = redc(x[j] as u64); + x[j] -= q; + x[j] += (x[j] >> (WL - 1)) & q; + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +fn encode(key: &[u8], poly: &mut [i32]) { + let q2 = PRIME / 2; + let mut j = 0; + let mut i = 0; + while i < 256 { + let mut kj = key[j]; + j += 1; + for _ in 0..8 { + let b = (kj & 1) as i32; + poly[i] = b * q2; + poly[i + 256] = b * q2; + poly[i + 512] = b * q2; + poly[i + 768] = b * q2; + kj >>= 1; + i += 1; + } + } +} + +fn decode(poly: &[i32], key: &mut [u8]) { + let q2 = PRIME / 2; + for i in 0..32 { + key[i] = 0; + } + + let mut i = 0; + let mut j = 0; + while i < 256 { + for _ in 0..8 { + let t = nabs(poly[i] - q2) + + nabs(poly[i + 256] - q2) + + nabs(poly[i + 512] - q2) + + nabs(poly[i + 768] - q2); + let mut b = t - PRIME; + b = (b >> 31) & 1; + key[j] = (key[j] >> 1) + ((b << 7) as u8); + i += 1; + } + j += 1; + } +} + +/* convert 32-byte seed to random polynomial */ + +fn parse(seed: &[u8], poly: &mut [i32]) { + let mut hash: [u8; 4 * DEGREE] = [0; 4 * DEGREE]; + let mut sh = SHA3::new(sha3::SHAKE128); + for i in 0..32 { + sh.process(seed[i]) + } + sh.shake(&mut hash, 4 * DEGREE); + + let mut j = 0; + for i in 0..DEGREE { + let mut n = (hash[j] & 0x7f) as i32; + n <<= 8; + n += (hash[j + 1]) as i32; + n <<= 8; + n += (hash[j + 2]) as i32; + n <<= 8; + n += (hash[j + 3]) as i32; + j += 4; + poly[i] = nres(n); + //poly[i]=modmul(n,ONE); // reduce 31-bit random number mod q + } +} + +/* Compress 14 bits polynomial coefficients into byte array */ +/* 7 bytes is 3x14 */ + +fn nhs_pack(poly: &[i32], array: &mut [u8]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let a = poly[i]; + let b = poly[i + 1]; + let c = poly[i + 2]; + let d = poly[i + 3]; + i += 4; + array[j] = (a & 0xff) as u8; + array[j + 1] = (((a >> 8) | (b << 6)) & 0xff) as u8; + array[j + 2] = ((b >> 2) & 0xff) as u8; + array[j + 3] = (((b >> 10) | (c << 4)) & 0xff) as u8; + array[j + 4] = ((c >> 4) & 0xff) as u8; + array[j + 5] = (((c >> 12) | (d << 2)) & 0xff) as u8; + array[j + 6] = (d >> 6) as u8; + j += 7; + } +} + +fn nhs_unpack(array: &[u8], poly: &mut [i32]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let a = array[j] as i32; + let b = array[j + 1] as i32; + let c = array[j + 2] as i32; + let d = array[j + 3] as i32; + let e = array[j + 4] as i32; + let f = array[j + 5] as i32; + let g = array[j + 6] as i32; + j += 7; + poly[i] = a | ((b & 0x3f) << 8); + poly[i + 1] = (b >> 6) | (c << 2) | ((d & 0xf) << 10); + poly[i + 2] = (d >> 4) | (e << 4) | ((f & 3) << 12); + poly[i + 3] = (f >> 2) | (g << 6); + i += 4; + } +} + +/* See https://eprint.iacr.org/2016/1157.pdf */ + +fn compress(poly: &[i32], array: &mut [u8]) { + let mut col = 0 as i32; + let mut j = 0; + let mut i = 0; + while i < DEGREE { + for _ in 0..8 { + let b = round(poly[i] * 8, PRIME) & 7; + col = (col << 3) + b; + i += 1; + } + array[j] = (col & 0xff) as u8; + array[j + 1] = ((col >> 8) & 0xff) as u8; + array[j + 2] = ((col >> 16) & 0xff) as u8; + j += 3; + col = 0; + } +} + +fn decompress(array: &[u8], poly: &mut [i32]) { + let mut j = 0; + let mut i = 0; + while i < DEGREE { + let mut col = (array[j + 2] as i32) & 0xff; + col = (col << 8) + ((array[j + 1] as i32) & 0xff); + col = (col << 8) + ((array[j] as i32) & 0xff); + j += 3; + for _ in 0..8 { + let b = (col & 0xe00000) >> 21; + col <<= 3; + poly[i] = round(b * PRIME, 8); + i += 1; + } + } +} + +/* generate centered binomial distribution */ + +fn error(rng: &mut RAND, poly: &mut [i32]) { + for i in 0..DEGREE { + let mut n1 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); + let mut n2 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); + let mut r = 0 as i32; + for _ in 0..16 { + r += (n1 & 1) - (n2 & 1); + n1 >>= 1; + n2 >>= 1; + } + poly[i] = r + PRIME; + } +} + +fn redc_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = redc(p[i] as u64); + } +} + +fn nres_it(p: &mut [i32]) { + for i in 0..DEGREE { + p[i] = nres(p[i]); + } +} + +fn poly_mul(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] = modmul(p1[i], p3[i]); + } +} + +fn poly_add(p1: &mut [i32], p3: &[i32]) { + for i in 0..DEGREE { + p1[i] += p3[i]; + } +} + +fn poly_rsub(p1: &mut [i32], p2: &[i32]) { + for i in 0..DEGREE { + p1[i] = p2[i] + PRIME - p1[i]; + } +} + +/* reduces inputs < 2q */ +fn poly_soft_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let e = poly[i] - PRIME; + poly[i] = e + ((e >> (WL - 1)) & PRIME); + } +} + +/* fully reduces modulo q */ +fn poly_hard_reduce(poly: &mut [i32]) { + for i in 0..DEGREE { + let mut e = modmul(poly[i], ONE); + e -= PRIME; + poly[i] = e + ((e >> (WL - 1)) & PRIME); + } +} + +/* API functions. See https://eprint.iacr.org/2016/1157.pdf Protocol 1 */ +// ss is secret key key, sb is seed|public key to be sent to client +pub fn server_1(rng: &mut RAND, sb: &mut [u8], ss: &mut [u8]) { + let mut seed: [u8; 32] = [0; 32]; + let mut array: [u8; 1792] = [0; 1792]; + let mut s: [i32; DEGREE] = [0; DEGREE]; + let mut e: [i32; DEGREE] = [0; DEGREE]; + let mut b: [i32; DEGREE] = [0; DEGREE]; + + for i in 0..32 { + seed[i] = rng.getbyte(); + } + + parse(&seed, &mut b); + + error(rng, &mut e); + error(rng, &mut s); + + ntt(&mut s); + ntt(&mut e); + poly_mul(&mut b, &s); + poly_add(&mut b, &e); + poly_hard_reduce(&mut b); + + redc_it(&mut b); + nhs_pack(&b, &mut array); + + for i in 0..32 { + sb[i] = seed[i]; + } + + for i in 0..1792 { + sb[i + 32] = array[i]; + } + + poly_hard_reduce(&mut s); + nhs_pack(&s, &mut array); + + for i in 0..1792 { + ss[i] = array[i]; + } +} + +// optimized to reduce memory +// uc is U|cbar to be returned to server +// okey is shared key +pub fn client(rng: &mut RAND, sb: &[u8], uc: &mut [u8], okey: &mut [u8]) { + let mut sh = SHA3::new(sha3::HASH256); + + let mut seed: [u8; 32] = [0; 32]; + let mut array: [u8; 1792] = [0; 1792]; + let mut key: [u8; 32] = [0; 32]; + let mut cc: [u8; 384] = [0; 384]; + + let mut sd: [i32; DEGREE] = [0; DEGREE]; + let mut ed: [i32; DEGREE] = [0; DEGREE]; + let mut u: [i32; DEGREE] = [0; DEGREE]; + let mut k: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + + error(rng, &mut sd); + error(rng, &mut ed); + + ntt(&mut sd); + ntt(&mut ed); + + for i in 0..32 { + seed[i] = sb[i]; + } + + for i in 0..1792 { + array[i] = sb[i + 32]; + } + + parse(&seed, &mut u); + + poly_mul(&mut u, &sd); + poly_add(&mut u, &ed); + poly_hard_reduce(&mut u); + + for i in 0..32 { + key[i] = rng.getbyte(); + } + + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + encode(&key, &mut k); + + nhs_unpack(&array, &mut c); + nres_it(&mut c); + + poly_mul(&mut c, &sd); + intt(&mut c); + error(rng, &mut ed); + poly_add(&mut c, &ed); + poly_add(&mut c, &k); + + compress(&c, &mut cc); + + sh = SHA3::new(sha3::HASH256); + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + for i in 0..32 { + okey[i] = key[i]; + } + + redc_it(&mut u); + nhs_pack(&u, &mut array); + + for i in 0..1792 { + uc[i] = array[i]; + } + + for i in 0..384 { + uc[i + 1792] = cc[i]; + } +} + +// calculate shared okey from uc and secret key ss +pub fn server_2(ss: &[u8], uc: &[u8], okey: &mut [u8]) { + let mut sh = SHA3::new(sha3::HASH256); + + let mut s: [i32; DEGREE] = [0; DEGREE]; + let mut k: [i32; DEGREE] = [0; DEGREE]; + let mut c: [i32; DEGREE] = [0; DEGREE]; + + let mut array: [u8; 1792] = [0; 1792]; + let mut key: [u8; 32] = [0; 32]; + let mut cc: [u8; 384] = [0; 384]; + + for i in 0..1792 { + array[i] = uc[i]; + } + + nhs_unpack(&array, &mut k); + nres_it(&mut k); + + for i in 0..384 { + cc[i] = uc[i + 1792]; + } + + decompress(&cc, &mut c); + + for i in 0..1792 { + array[i] = ss[i]; + } + + nhs_unpack(&array, &mut s); + + poly_mul(&mut k, &s); + intt(&mut k); + poly_rsub(&mut k, &c); + poly_soft_reduce(&mut k); + + decode(&k, &mut key); + + for i in 0..32 { + sh.process(key[i]); + } + sh.hash(&mut key); + + for i in 0..32 { + okey[i] = key[i]; + } +} + +/* +fn main() { + let x=3; + let y=redc(x as u64); + let z=redc((y as u64)*(R2MODP)); + println!("{:02x}",z); + + let mut a:[i32;1024]=[0;1024]; + for i in 0..1024 {a[i]=i as i32} + + ntt(&mut a); + + for i in 0..1024 {a[i]=modmul(a[i],ONE)} + + intt(&mut a); + + println!("{:02x}",a[7]); + +} +*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs new file mode 100644 index 000000000000..5d099ecd0a50 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//extern crate mcore; + +use crate::hash256::HASH256; + +pub const RAND_NK: usize = 21; +const RAND_NJ: usize = 6; +const RAND_NV: usize = 8; + +// Marsaglia-Zaman random generator (https://projecteuclid.org/euclid.aoap/1177005878) +// Analysis: https://ieeexplore.ieee.org/document/669305 +#[allow(non_camel_case_types)] +pub struct RAND { + pub ira: [u32; RAND_NK], /* random number... */ + pub rndptr: usize, + pub borrow: u32, + pub pool_ptr: usize, + pub pool: [u8; 32], +} + +impl RAND { + pub fn new() -> RAND { + RAND { + ira: [0; RAND_NK], + rndptr: 0, + borrow: 0, + pool_ptr: 0, + pool: [0; 32], + } + } + + #[allow(dead_code)] + pub fn clean(&mut self) { + self.pool_ptr = 0; + self.rndptr = 0; + for i in 0..32 { + self.pool[i] = 0 + } + for i in 0..RAND_NK { + self.ira[i] = 0 + } + self.borrow = 0; + } + + fn sbrand(&mut self) -> u32 { + /* Marsaglia & Zaman random number generator */ + self.rndptr += 1; + if self.rndptr < RAND_NK { + return self.ira[self.rndptr]; + } + self.rndptr = 0; + let mut k = RAND_NK - RAND_NJ; + for i in 0..RAND_NK { + /* calculate next NK values */ + if k == RAND_NK { + k = 0 + } + let t = self.ira[k]; + let pdiff = t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow); + if pdiff < t { + self.borrow = 0 + } + if pdiff > t { + self.borrow = 1 + } + self.ira[i] = pdiff; + k += 1; + } + self.ira[0] + } + + fn sirand(&mut self, seed: u32) { + let mut m: u32 = 1; + let mut sd = seed; + self.borrow = 0; + self.rndptr = 0; + self.ira[0] ^= sd; + for i in 1..RAND_NK { + /* fill initialisation vector */ + let inn = (RAND_NV * i) % RAND_NK; + self.ira[inn] ^= m; /* note XOR */ + let t = m; + m = sd.wrapping_sub(m); + sd = t; + } + for _ in 0..10000 { + self.sbrand(); + } /* "warm-up" & stir the generator */ + } + + fn fill_pool(&mut self) { + let mut sh = HASH256::new(); + for _ in 0..128 { + sh.process((self.sbrand() & 0xff) as u8) + } + let w = sh.hash(); + for i in 0..32 { + self.pool[i] = w[i] + } + self.pool_ptr = 0; + } + + fn pack(b: [u8; 4]) -> u32 { + /* pack 4 bytes into a 32-bit Word */ + (((b[3] as u32) & 0xff) << 24) + | (((b[2] as u32) & 0xff) << 16) + | (((b[1] as u32) & 0xff) << 8) + | ((b[0] as u32) & 0xff) + } + + pub fn seed(&mut self, rawlen: usize, raw: &[u8]) { + /* initialise from at least 128 byte string of raw random entropy */ + let mut b: [u8; 4] = [0; 4]; + let mut sh = HASH256::new(); + self.pool_ptr = 0; + + for i in 0..RAND_NK { + self.ira[i] = 0 + } + if rawlen > 0 { + for i in 0..rawlen { + sh.process(raw[i]); + } + let digest = sh.hash(); + + /* initialise PRNG from distilled randomness */ + + for i in 0..8 { + b[0] = digest[4 * i]; + b[1] = digest[4 * i + 1]; + b[2] = digest[4 * i + 2]; + b[3] = digest[4 * i + 3]; + self.sirand(RAND::pack(b)); + } + } + self.fill_pool(); + } + + pub fn getbyte(&mut self) -> u8 { + let r = self.pool[self.pool_ptr]; + self.pool_ptr += 1; + if self.pool_ptr >= 32 { + self.fill_pool() + } + r + } +} + + + +/* test main program + +fn main() { + let mut raw : [u8;100]=[0;100]; + let mut rng=RAND::new(); + + rng.clean(); + for i in 0..100 {raw[i]=i as u8} + + rng.seed(100,&raw); + + for _ in 0..1000 { + print!("{:03} ",rng.getbyte()); + } +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs new file mode 100644 index 000000000000..43f47a42f5ee --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub const HASH224: usize = 28; +pub const HASH256: usize = 32; +pub const HASH384: usize = 48; +pub const HASH512: usize = 64; +pub const SHAKE128: usize = 16; +pub const SHAKE256: usize = 32; + +const ROUNDS: usize = 24; + +const RC: [u64; 24] = [ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +]; + +pub struct SHA3 { + length: usize, + rate: usize, + len: usize, + //s: [[u64; 5]; 5], + s: [u64;25], +} + +impl SHA3 { + fn rotl(x: u64, n: u64) -> u64 { + ((x) << n) | ((x) >> (64 - n)) + } + + fn transform(&mut self) { + for k in 0..ROUNDS { + let c0=self.s[0]^self.s[5]^self.s[10]^self.s[15]^self.s[20]; + let c1=self.s[1]^self.s[6]^self.s[11]^self.s[16]^self.s[21]; + let c2=self.s[2]^self.s[7]^self.s[12]^self.s[17]^self.s[22]; + let c3=self.s[3]^self.s[8]^self.s[13]^self.s[18]^self.s[23]; + let c4=self.s[4]^self.s[9]^self.s[14]^self.s[19]^self.s[24]; + + let d0=c4^SHA3::rotl(c1,1); + let d1=c0^SHA3::rotl(c2,1); + let d2=c1^SHA3::rotl(c3,1); + let d3=c2^SHA3::rotl(c4,1); + let d4=c3^SHA3::rotl(c0,1); + + let b00 = self.s[0]^d0; + let b02 = SHA3::rotl(self.s[1]^d1, 1); + let b04 = SHA3::rotl(self.s[2]^d2, 62); + let b01 = SHA3::rotl(self.s[3]^d3, 28); + let b03 = SHA3::rotl(self.s[4]^d4, 27); + + let b13 = SHA3::rotl(self.s[5]^d0, 36); + let b10 = SHA3::rotl(self.s[6]^d1, 44); + let b12 = SHA3::rotl(self.s[7]^d2, 6); + let b14 = SHA3::rotl(self.s[8]^d3, 55); + let b11 = SHA3::rotl(self.s[9]^d4, 20); + + let b21 = SHA3::rotl(self.s[10]^d0, 3); + let b23 = SHA3::rotl(self.s[11]^d1, 10); + let b20 = SHA3::rotl(self.s[12]^d2, 43); + let b22 = SHA3::rotl(self.s[13]^d3, 25); + let b24 = SHA3::rotl(self.s[14]^d4, 39); + + let b34 = SHA3::rotl(self.s[15]^d0, 41); + let b31 = SHA3::rotl(self.s[16]^d1, 45); + let b33 = SHA3::rotl(self.s[17]^d2, 15); + let b30 = SHA3::rotl(self.s[18]^d3, 21); + let b32 = SHA3::rotl(self.s[19]^d4, 8); + + let b42 = SHA3::rotl(self.s[20]^d0, 18); + let b44 = SHA3::rotl(self.s[21]^d1, 2); + let b41 = SHA3::rotl(self.s[22]^d2, 61); + let b43 = SHA3::rotl(self.s[23]^d3, 56); + let b40 = SHA3::rotl(self.s[24]^d4, 14); + + self.s[0]=b00^(!b10&b20); + self.s[1]=b10^(!b20&b30); + self.s[2]=b20^(!b30&b40); + self.s[3]=b30^(!b40&b00); + self.s[4]=b40^(!b00&b10); + + self.s[5]=b01^(!b11&b21); + self.s[6]=b11^(!b21&b31); + self.s[7]=b21^(!b31&b41); + self.s[8]=b31^(!b41&b01); + self.s[9]=b41^(!b01&b11); + + self.s[10]=b02^(!b12&b22); + self.s[11]=b12^(!b22&b32); + self.s[12]=b22^(!b32&b42); + self.s[13]=b32^(!b42&b02); + self.s[14]=b42^(!b02&b12); + + self.s[15]=b03^(!b13&b23); + self.s[16]=b13^(!b23&b33); + self.s[17]=b23^(!b33&b43); + self.s[18]=b33^(!b43&b03); + self.s[19]=b43^(!b03&b13); + + self.s[20]=b04^(!b14&b24); + self.s[21]=b14^(!b24&b34); + self.s[22]=b24^(!b34&b44); + self.s[23]=b34^(!b44&b04); + self.s[24]=b44^(!b04&b14); + + self.s[0] ^= RC[k]; + } + } + + /* Initialise Hash function */ + pub fn init(&mut self, olen: usize) { + /* initialise */ + for i in 0..25 { + self.s[i] = 0; + } + self.length = 0; + self.len = olen; + self.rate = 200 - 2 * olen; + } + + pub fn new(olen: usize) -> SHA3 { + let mut nh = SHA3 { + length: 0, + rate: 0, + len: 0, + s: [0; 25], + }; + nh.init(olen); + nh + } + + pub fn new_copy(hh: &SHA3) -> SHA3 { + let mut nh = SHA3 { + length: 0, + rate: 0, + len: 0, + s: [0; 25], + }; + nh.length=hh.length; + nh.len=hh.len; + nh.rate=hh.rate; + for i in 0..25 { + nh.s[i] = hh.s[i]; + } + nh + } + + /* process a single byte */ + pub fn process(&mut self, byt: u8) { + /* process the next message byte */ + let cnt = self.length as usize; + let b = cnt % 8; + let ind = cnt / 8; + self.s[ind] ^= (byt as u64) << (8 * b); + self.length += 1; + if self.length == self.rate { + self.length=0; + self.transform(); + } + } + + /* process an array of bytes */ + + pub fn process_array(&mut self, b: &[u8]) { + for i in 0..b.len() { + self.process(b[i]) + } + } + + /* process a 32-bit integer */ + pub fn process_num(&mut self, n: i32) { + self.process(((n >> 24) & 0xff) as u8); + self.process(((n >> 16) & 0xff) as u8); + self.process(((n >> 8) & 0xff) as u8); + self.process((n & 0xff) as u8); + } + + pub fn squeeze(&mut self, buff: &mut [u8], olen: usize) { + let mut m = 0; + let nb=olen/self.rate; + + for _ in 0..nb { + for i in 0..self.rate/8 { + let mut el=self.s[i]; + for _ in 0..8 { + buff[m]=(el & 0xff) as u8; + m += 1; + el >>= 8; + } + } + self.transform(); + } + + let mut i=0; + while m= olen { + break; + } + el >>= 8; + } + } + +/* + loop { + for i in 0..25 { + let mut el = self.s[i]; + for _ in 0..8 { + buff[m] = (el & 0xff) as u8; + m += 1; + if m >= olen || (m % self.rate) == 0 { + done = true; + break; + } + el >>= 8; + } + if done { + break; + } + } + if m >= olen { + break; + } + done = false; + self.transform(); + } */ + } + + /* Generate 32-byte Hash */ + pub fn hash(&mut self, digest: &mut [u8]) { + /* pad message and finish - supply digest */ + let q = self.rate - self.length; + if q == 1 { + self.process(0x86); + } else { + self.process(0x06); + while self.length != self.rate - 1 { + self.process(0x00) + } + self.process(0x80); + } + let hlen = self.len as usize; + self.squeeze(digest, hlen); + } + + pub fn continuing_hash(&mut self, digest: &mut [u8]) { + let mut sh=SHA3::new_copy(self); + sh.hash(digest) + } + + pub fn shake(&mut self, digest: &mut [u8], olen: usize) { + let q = self.rate - self.length; + if q == 1 { + self.process(0x9f); + } else { + self.process(0x1f); + while self.length != self.rate - 1 { + self.process(0x00) + } + self.process(0x80); + } + self.squeeze(digest, olen); + } + + pub fn continuing_shake(&mut self, digest: &mut [u8], olen: usize) { + let mut sh=SHA3::new_copy(self); + sh.shake(digest,olen); + } +} + +//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 +//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 +//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 +/* +fn main() { + let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + let mut digest: [u8;100]=[0;100]; + let test = s.into_bytes(); + + let mut sh=SHA3::new(HASH256); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.hash(&mut digest); + for i in 0..32 {print!("{:02x}",digest[i])} + println!(""); + + sh=SHA3::new(HASH512); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.hash(&mut digest); + for i in 0..64 {print!("{:02x}",digest[i])} + println!(""); + + sh=SHA3::new(SHAKE256); + for i in 0..test.len(){ + sh.process(test[i]); + } + sh.shake(&mut digest,72); + for i in 0..72 {print!("{:02x}",digest[i])} + println!(""); + +} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs new file mode 100644 index 000000000000..4c434d64c9ce --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Shamir threshold secret sharing module */ +/* Split any byte array into number of shares < 256 */ +/* Specify number of shares required for recovery - nsr */ + +/* See TestMPIN.rs for an example of use */ + +use crate::rand::RAND; + +const PTAB: [u8; 256] = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, + 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, + 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, + 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, + 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, + 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, + 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, + 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, + 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, + 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +]; + +const LTAB: [u8; 256] = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, + 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, + 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, + 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, + 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, + 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, + 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, + 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, + 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, + 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, + 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, + 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, + 24, 13, 99, 140, 128, 192, 247, 112, 7, +]; + +pub struct SHARE<'a> { + id: u8, + nsr: u8, + b: &'a [u8] +} + +fn mul(x: u8, y: u8) -> u8 { +/* x.y= AntiLog(Log(x) + Log(y)) */ + let ix = (x as usize) & 0xff; + let iy = (y as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + let ly = (LTAB[iy] as usize) & 0xff; + + if x != 0 && y != 0 { + PTAB[(lx + ly) % 255] + } else { + 0 + } +} + +fn add(x: u8,y: u8) -> u8 { + x^y +} + +fn inv(x: u8) -> u8 { + let ix = (x as usize) & 0xff; + let lx = (LTAB[ix] as usize) & 0xff; + PTAB[255-lx] +} + +/* Lagrange interpolation */ +fn interpolate(n: usize, x: &[u8], y: &[u8]) -> u8 { + let mut yp=0 as u8; + for i in 0..n { + let mut p=1 as u8; + for j in 0..n { + if i!=j { + p=mul(p,mul(x[j],inv(add(x[i],x[j])))); + } + } + yp=add(yp,mul(p,y[i])); + } + yp +} + +impl<'a> SHARE<'a> { + +/* Return a share of M */ +/* input id - Unique share ID */ +/* input nsr - Number of shares required for recovery */ +/* input Message M to be shared */ +/* input Random number generator rng to be used */ +/* return share structure */ +// must bind lifetime of the byte array stored by structure, to lifetime of s + pub fn new(ident: usize,numshare: usize,s: &'a mut [u8],m: &[u8], rng: &mut RAND) -> SHARE<'a> { + if ident<1 || ident>=256 || numshare<2 || numshare>=256 { + return SHARE{id:0,nsr:0,b:s}; + } + let len=m.len(); + for j in 0..len { + let mut x=ident as u8; + s[j]=m[j]; + for _ in 1..numshare { + s[j]=add(s[j],mul(rng.getbyte(),x)); + x=mul(x,ident as u8); + } + } + SHARE{id: ident as u8,nsr: numshare as u8,b:s} + } +/* recover M from shares */ + pub fn recover(m: &mut [u8],s: &[SHARE]) { + let len=s[0].b.len(); + let nsr=s[0].nsr as usize; + if nsr!=s.len() { + return; + } + for i in 1..nsr { + if s[i].nsr as usize != nsr || s[i].b.len()!=len { + return; + } + } + let mut x: [u8; 256] = [0; 256]; + let mut y: [u8; 256] = [0; 256]; + + for j in 0..len { + for i in 0..nsr { + x[i]=s[i].id; + y[i]=s[i].b[j]; + } + m[j]=interpolate(nsr,&x,&y); + } + } +} + + diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs new file mode 100644 index 000000000000..e1891b22940f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs @@ -0,0 +1,1285 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE X.509 Functions */ + +pub struct PKTYPE { + pub kind: usize, + pub hash: usize, + pub curve: usize, + pub len: usize, +} + +pub struct FDTYPE { + pub index: usize, + pub length: usize, +} + +// Supported Encryption/Signature Methods + +pub const ECC:usize = 1; +pub const RSA:usize = 2; +pub const ECD:usize = 3; // for Ed25519 and Ed448 +pub const PQ:usize = 4; + +// Supported Hash functions + +pub const H256:usize = 2; +pub const H384:usize = 3; +pub const H512:usize = 4; +pub const SHAKE256:usize = 5; + +// Supported Curves + +pub const USE_NIST256:usize = 4; /**< For the NIST 256-bit standard curve - WEIERSTRASS only */ +pub const USE_ED25519:usize = 1; /**< Bernstein's Modulus 2^255-19 - EDWARDS only */ +pub const USE_ED448:usize = 5; +//const USE_BRAINPOOL:usize = 2; /**< For Brainpool 256-bit curve - WEIERSTRASS only */ +//const USE_ANSSI:usize = 3; /**< For French 256-bit standard curve - WEIERSTRASS only */ +pub const USE_NIST384:usize = 10; /**< For the NIST 384-bit standard curve - WEIERSTRASS only */ +pub const USE_NIST521:usize = 12; /**< For the NIST 521-bit standard curve - WEIERSTRASS only */ + +const ANY: u8 = 0x00; +const SEQ: u8 = 0x30; +const OID: u8 = 0x006; +const INT: u8 = 0x02; +const NUL: u8 = 0x05; +//const ZER: u8 = 0x00; +//const UTF: u8 = 0x0C; +const UTC: u8 = 0x17; +const GTM: u8 = 0x18; +//const LOG: u8 = 0x01; +const BIT: u8 = 0x03; +const OCT: u8 = 0x04; +//const STR: u8 = 0x13; +const SET: u8 = 0x31; +//const IA5: u8 = 0x16; +const EXT: u8 = 0xA3; +const DNS: u8 = 0x82; + +// Define some OIDs +// Elliptic Curve with SHA256 + +const ECCSHA256:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02]; +const ECCSHA384:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03]; +const ECCSHA512:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04]; +const ECPK:[u8;7]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01]; +const EDPK25519:[u8;3]=[0x2b, 0x65, 0x70]; +const EDPK448:[u8;3]=[0x2b, 0x65, 0x71]; +const PRIME25519:[u8;9]=[0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01]; +const PRIME256V1:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]; +const SECP384R1:[u8;5]=[0x2B, 0x81, 0x04, 0x00, 0x22]; +const SECP521R1:[u8;5]=[0x2B, 0x81, 0x04, 0x00, 0x23]; +const RSAPK:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]; +const RSASHA256:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b]; +const RSASHA384:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0]; +const RSASHA512:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d]; +const DILITHIUM3:[u8;11]=[0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, 0x06, 0x05]; +// Cert details + +pub const CN:[u8;3]=[0x55, 0x04, 0x06]; // countryName +pub const SN:[u8;3]=[0x55, 0x04, 0x08]; // stateName +pub const LN:[u8;3]=[0x55, 0x04, 0x07]; // localName +pub const ON:[u8;3]=[0x55, 0x04, 0x0A]; // orgName +pub const UN:[u8;3]=[0x55, 0x04, 0x0B]; // unitName +pub const MN:[u8;3]=[0x55, 0x04, 0x03]; // myName +pub const EN:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01]; // emailName + +// Extensions +pub const AN:[u8;3]=[0x55,0x1D,0x11]; // altName +pub const KU:[u8;3]=[0x55,0x1D,0x0F]; // keyUsage +pub const BC:[u8;3]=[0x55,0x1D,0x13]; // basicConstraints + +fn getalen(tag: u8,b:&[u8],j:usize) -> usize { + let mut k=j; + let mut len:usize; + if tag!=0 && b[k]!=tag { + return 0; + } + k+=1; + if b[k] == 0x81 { + k+=1; + len=b[k] as usize; + } else if b[k]==0x82 { + k+=1; + len=256*(b[k] as usize); k+=1; + len+= b[k] as usize; + } else { + len=b[k] as usize; + if len>127 { + return 0; + } + } + return len; +} + +fn skip(len: usize) -> usize { + if len<128 { + return 2; + } + if len<256 { + return 3; + } + return 4; +} + +fn bround(len:usize) -> usize { + if len%8 == 0 { + return len; + } + return len+(8-len%8); +} + +impl PKTYPE { + pub fn new() -> PKTYPE { + PKTYPE { + kind: 0, + hash: 0, + curve:0, + len:0, + } + } +} + +impl FDTYPE { + pub fn new() -> FDTYPE { + FDTYPE { + index: 0, + length: 0, + } + } +} + +// Input private key in PKCS#8 format +// e.g. openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 +// e.g. openssl req -x509 -nodes -days 3650 -newkey ec:<(openssl ecparam -name prime256v1) -keyout key.pem -out ecdsacert.pem +// extract private key from uncompressed key.pem into octet +// For RSA octet = p|q|dp|dq|c where pk->len is multiple of 5 +// For ECC octet = k +pub fn extract_private_key(c: &[u8],pk: &mut [u8]) -> PKTYPE { + let mut soid:[u8;12]=[0;12]; + let mut ret=PKTYPE::new(); + let mut j=0 as usize; + let pklen=pk.len(); + + let mut len=getalen(SEQ,c,j); // Check for expected SEQ clause, and get length + if len == 0 { // if not a SEQ clause, there is a problem, exit + return ret; + } + j+=skip(len); // skip over length to clause contents. + if len+j != c.len() { + return ret; + } + len=getalen(INT,c,j); + if len == 0 { // if not a SEQ clause, there is a problem, exit + return ret; + } + j+=skip(len)+len; + len=getalen(SEQ,c,j); + if len == 0 { // if not a SEQ clause, there is a problem, exit + return ret; + } + j+=skip(len); +// extract OID + len=getalen(OID,c,j); + if len==0 { + return ret; + } + j+=skip(len); + + let mut fin=j+len; + if len>soid.len() { + return ret; + } + let mut slen=0; + while jpklen { + return ret; + } + ret.len=rlen; + for i in 0..rlen-len { + pk[i]=0; + } + for i in rlen-len..rlen { + pk[i]=c[j]; + j+=1; + } + ret.kind = ECD; + ret.curve = USE_ED25519; + } + if EDPK448 == soid[0..slen] { + len=getalen(OCT,c,j); + if len==0 { + return ret; + } + j+=skip(len); + len=getalen(OCT,c,j); + if len==0 { + return ret; + } + j+=skip(len); + let rlen=57; + if rlen>pklen { + return ret; + } + ret.len=rlen; + for i in 0..rlen-len { + pk[i]=0; + } + for i in rlen-len..rlen { + pk[i]=c[j]; + j+=1; + } + ret.kind = ECD; + ret.curve = USE_ED448; + } + if DILITHIUM3 == soid[0..slen] { + len=getalen(OCT,c,j); + if len==0 { + return ret; + } + j+=skip(len); + len=getalen(OCT,c,j); + if len==0 { + return ret; + } + j+=skip(len); + let mut tlen=len; + if tlen>pk.len() { + tlen=pk.len(); + } + + for i in 0..tlen { + pk[i]=c[j]; + j+=1; + } + ret.len=tlen; + ret.kind=PQ; + ret.curve=8*tlen; + } + if ECPK == soid[0..slen] { + len=getalen(OID,c,j); + if len==0 { + return ret; + } + j+=skip(len); + + fin=j+len; + if len>soid.len() { + return ret; + } + slen=0; + while jpklen { + ret.curve=0; + ret.len=0; + return ret; + } + ret.len=rlen; + for i in 0..rlen-len { + pk[i]=0; + } + for i in rlen-len..rlen { + pk[i]=c[j]; + j+=1; + } + } + if RSAPK == soid[0..slen] { + len=getalen(NUL,c,j); + if len!=0 { + return ret; + } + j+=skip(len); + + len=getalen(OCT,c,j); + if len==0 { + return ret; + } + j+=skip(len); + + len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j+=skip(len); + + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len)+len; // jump over version + + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len)+len; // jump over n + + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len)+len; // jump over e + + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len)+len; // jump over d + + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len); // get p + + if c[j]==0 { + j+=1; + len-=1; + } + let mut rlen=bround(len); + + if 5*rlen>pklen { + return ret; + } + + for i in 0..rlen-len { + pk[i]=0; + } + for i in rlen-len..rlen { + pk[i]=c[j]; + j+=1; + } + + let flen=rlen; // should be same length for all + for k in 1..5 { + len=getalen(INT,c,j); + if len==0 { + return ret; + } + j+=skip(len); // get q,dp,dq,c + if c[j]==0 { + j+=1; + len-=1; + } + rlen=bround(len); + if rlen!=flen { + return ret; + } + for i in 0..rlen-len { + pk[i]=0; + } + for i in rlen-len..rlen { + pk[k*flen+i]=c[j]; + j+=1; + } + } + ret.len=5*flen; + ret.kind=RSA; + ret.curve=16*flen; + } + return ret; +} + +// Input signed cert as octet, and extract signature +// Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature +// Note that signature type is not provided here - its the type of the public key that +// is used to verify it that matters, and which determines for example the curve to be used! +pub fn extract_cert_sig(sc: &[u8],sig: &mut [u8]) -> PKTYPE { + let mut soid:[u8;12]=[0;12]; + let mut ret=PKTYPE::new(); + let mut j=0 as usize; + let mut len=getalen(SEQ,sc,j); // Check for expected SEQ clause, and get length + let siglen=sig.len(); + + if len == 0 { // if not a SEQ clause, there is a problem, exit + return ret; + } + j+=skip(len); // skip over length to clause contents. Add len to skip clause + if len+j != sc.len() { + return ret; + } + len=getalen(SEQ,sc,j); + if len==0 { + return ret; + } + j+=skip(len) + len; // jump over cert to signature OID + len=getalen(SEQ,sc,j); + if len==0 { + return ret; + } + j+=skip(len); + let sj=j+len; // Needed to jump over signature OID + +// dive in to extract OID + len=getalen(OID,sc,j); + if len==0 { + return ret; + } + j+=skip(len); + let mut fin=j+len; + if len>soid.len() { + return ret; + } + + let mut slen=0; + while jsiglen { + ret.kind=0; + return ret; + } + ret.len=len; + slen=0; + fin=j+len; + while jsiglen { + ret.kind=0; + return ret; + } + ret.len=2*rlen; + + slen=0; + for _ in 0..ex { + sig[slen]=0; + slen+=1; + } + fin=j+len; + while jsiglen { + ret.kind=0; + ret.curve=0; + return ret; + } + ret.len=rlen; + slen=0; + for _ in 0..ex { + sig[slen]=0; + slen+=1; + } + fin=j+len; + while jsiglen { + ret.kind=0; + ret.curve=0; + return ret; + } + ret.len=len; + slen=0; + fin=j+len; + while j usize { + let mut j:usize=0; + + let mut len=getalen(SEQ,sc,j); + if len==0 { + return 0; + } + j+=skip(len); + + let k=j; + len=getalen(SEQ,sc,j); + if len==0 { + return 0; + } + j+=skip(len); + let fin=j+len; + *ptr=k; + return fin-k; +} + +// Extract certificate from signed cert +pub fn extract_cert(sc: &[u8],cert: &mut [u8]) -> usize { + let mut ptr=0; + let n=find_cert(sc,&mut ptr); + let k=ptr; + let fin=n+k; + if fin-k>cert.len() { + return 0; + } + for i in k..fin { + cert[i-k]=sc[i]; + } + return n; +} + +// extract pointer to ASN.1 raw public Key inside certificate, and return its length; +// let public_key=&c[ptr..ptr+len] +pub fn find_public_key(c: &[u8],ptr: &mut usize) -> usize { + let mut j:usize=0; + let mut len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j+=skip(len); + + if len+j != c.len() { + return 0; + } + + len=getalen(ANY,c,j); + if len==0 { + return 0; + } + j+=skip(len)+len; //jump over version clause + + len=getalen(INT,c,j); + if len>0 { + j+=skip(len)+len; // jump over serial number clause (if there is one) + } + + len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j+=skip(len)+len; // jump over signature algorithm + + len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j += skip(len) + len; // skip issuer + + len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j += skip(len) + len; // skip validity + + len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j += skip(len) + len; // skip subject + + let k=j; + len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j += skip(len); // + + let fin=j+len; + *ptr=k; + return fin-k; +} + +// get Public details from ASN.1 description +pub fn get_public_key(c: &[u8],key: &mut [u8]) -> PKTYPE { + let mut koid:[u8;12]=[0;12]; + let mut ret=PKTYPE::new(); + let mut j=0; + let keylen=key.len(); + + let mut len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j += skip(len); // + + len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j += skip(len); // + +// ** Maybe dive in and check Public Key OIDs here? +// ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC +// rsapublicKey for RSA + + let sj=j+len; + + len=getalen(OID,c,j); + if len==0 { + return ret; + } + j += skip(len); + + let mut fin=j+len; + if len>koid.len() { + return ret; + } + let mut slen=0; + while jkoid.len() { + ret.kind=0; + return ret; + } + slen=0; + while jkeylen { + ret.kind=0; + return ret; + } + ret.len=len; + fin=j+len; + slen=0; + while jkeylen { + ret.kind=0; + return ret; + } + ret.len=len; + fin=j+len; + slen=0; + while j PKTYPE { + let mut ptr=0; + let pklen = find_public_key(c,&mut ptr); // ptr is pointer into certificate, at start of ASN.1 raw public key + let cc=&c[ptr..ptr+pklen]; + return get_public_key(&cc,key); +} + +pub fn find_issuer(c: &[u8]) -> FDTYPE { + let mut j:usize=0; + let mut ret=FDTYPE::new(); + let mut len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j += skip(len); + + if len+j!=c.len() { + return ret; + } + + len=getalen(ANY,c,j); + if len==0 { + return ret; + } + j += skip(len)+len; // jump over version clause + + len=getalen(INT,c,j); + if len>0 { + j+=skip(len)+len; // jump over serial number clause (if there is one) + } + + len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j += skip(len) + len; // jump over signature algorithm + + len=getalen(SEQ,c,j); + ret.index=j; + ret.length=len+skip(len); + + return ret; +} + +pub fn find_validity(c: &[u8]) -> usize { + let pos=find_issuer(c); + let j=pos.index+pos.length; // skip issuer + + //let mut j=find_issuer(c); + //let len=getalen(SEQ,c,j); + //if len==0 { + // return 0; + //} + //j+=skip(len)+len; // skip issuer + return j; +} + +pub fn find_subject(c: &[u8]) -> FDTYPE { + let mut j=find_validity(c); + let mut ret=FDTYPE::new(); + let mut len=getalen(SEQ,c,j); + if len==0 { + return ret; + } + j+=skip(len)+len; // skip validity + + len=getalen(SEQ,c,j); + ret.index=j; + ret.length=len+skip(len); + + return ret; +} + +pub fn self_signed(c: &[u8]) -> bool { + let ksub=find_subject(c); + let kiss=find_issuer(c); + + if ksub.length!=kiss.length { + return false; + } + +// let sublen=getalen(SEQ,c,ksub); +// let isslen=getalen(SEQ,c,kiss); +// if sublen != isslen { +// return false; +// } +// ksub+=skip(sublen); +// kiss+=skip(isslen); + let mut m:u8=0; + for i in 0..ksub.length { + m |= c[i+ksub.index]-c[i+kiss.index]; + } + if m!=0 { + return false; + } + return true; +} + +// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length +// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy +// cert information into it. + +// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field + +pub fn find_entity_property(c: &[u8],soid: &[u8],start: usize) -> FDTYPE { + let mut ret=FDTYPE::new(); + let mut foid:[u8;32]=[0;32]; + let mut j=start; + let tlen=getalen(SEQ,c,j); + if tlen==0 { + return ret; + } + j+=skip(tlen); + let k=j; + while jfoid.len() { + return ret; + } + let mut flen:usize=0; + while j usize { + let mut j=start; + let mut len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j+=skip(len); + + len=getalen(UTC,c,j); + if len==0 { // could be generalised time + len=getalen(GTM,c,j); + if len==0 { + return 0; + } + j += skip(len); + j +=2; // skip century + } else { + j+=skip(len); + } + return j; +} + +pub fn find_expiry_date(c: &[u8],start: usize) -> usize { + let mut j=start; + let mut len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j+=skip(len); + + len=getalen(UTC,c,j); + if len==0 { + len=getalen(GTM,c,j); + if len==0 { + return 0; + } + } + j+=skip(len)+len; + + len=getalen(UTC,c,j); + if len==0 { // could be generalised time + len=getalen(GTM,c,j); + if len==0 { + return 0; + } + j += skip(len); + j +=2; // skip century + } else { + j+=skip(len); + } + return j; +} + +pub fn find_extensions(c: &[u8]) -> usize { + let pos=find_subject(c); + let mut j=pos.index+pos.length; + +// let mut len=getalen(SEQ,c,j); +// if len==0 { +// return 0; +// } +// j+=skip(len)+len; // skip subject + + let len=getalen(SEQ,c,j); + if len==0 { + return 0; + } + j+=skip(len)+len; // skip public key + + if j>=c.len() { + return 0; + } + return j; +} + +pub fn find_extension(c: &[u8],soid: &[u8],start:usize) -> FDTYPE { + let mut ret=FDTYPE::new(); + let mut foid:[u8;32]=[0;32]; + + let mut j=start; + let tlen=getalen(EXT,c,j); + if tlen==0 { + return ret; + } + j+=skip(tlen); + + let tlen=getalen(SEQ,c,j); + if tlen==0 { + return ret; + } + j+=skip(tlen); + + let k=j; + while jfoid.len() { + return ret; + } + let mut flen:usize=0; + while j bool { + if start==0 { + return false; + } + let mut j=start; + let mut tlen=getalen(OCT,c,j); + if tlen==0 { + return false; + } + j+=skip(tlen); + + tlen=getalen(SEQ,c,j); + if tlen==0 { + return false; + } + j+=skip(tlen); + let k=j; + while j Date: Fri, 26 Apr 2024 13:09:58 -0700 Subject: [PATCH 04/36] Add WDP keyed service --- ...browser_context_keyed_service_factories.cc | 3 ++ browser/sources.gni | 2 +- browser/web_discovery/BUILD.gn | 11 +++++ browser/web_discovery/wdp_service_factory.cc | 42 +++++++++++++++++++ browser/web_discovery/wdp_service_factory.h | 36 ++++++++++++++++ .../browser/BUILD.gn | 7 +++- .../browser/anonymous_credentials/rs/BUILD.gn | 4 +- .../anonymous_credentials/rs/Cargo.lock | 0 .../anonymous_credentials/rs/Cargo.toml | 0 .../anonymous_credentials/rs/src/lib.rs | 0 .../web_discovery/browser/wdp_service.cc | 14 +++++++ .../web_discovery/browser/wdp_service.h | 29 +++++++++++++ 12 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 browser/web_discovery/wdp_service_factory.cc create mode 100644 browser/web_discovery/wdp_service_factory.h rename components/{web_discovery_project => web_discovery}/browser/BUILD.gn (72%) rename components/{web_discovery_project => web_discovery}/browser/anonymous_credentials/rs/BUILD.gn (88%) rename components/{web_discovery_project => web_discovery}/browser/anonymous_credentials/rs/Cargo.lock (100%) rename components/{web_discovery_project => web_discovery}/browser/anonymous_credentials/rs/Cargo.toml (100%) rename components/{web_discovery_project => web_discovery}/browser/anonymous_credentials/rs/src/lib.rs (100%) create mode 100644 components/web_discovery/browser/wdp_service.cc create mode 100644 components/web_discovery/browser/wdp_service.h diff --git a/browser/browser_context_keyed_service_factories.cc b/browser/browser_context_keyed_service_factories.cc index 5f00475ef7c9..8a4614bf9a45 100644 --- a/browser/browser_context_keyed_service_factories.cc +++ b/browser/browser_context_keyed_service_factories.cc @@ -30,6 +30,7 @@ #include "brave/browser/search_engines/search_engine_tracker.h" #include "brave/browser/sync/brave_sync_alerts_service_factory.h" #include "brave/browser/url_sanitizer/url_sanitizer_service_factory.h" +#include "brave/browser/web_discovery/wdp_service_factory.h" #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/brave_perf_predictor/browser/named_third_party_registry_factory.h" #include "brave/components/brave_vpn/common/buildflags/buildflags.h" @@ -216,6 +217,8 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { #if BUILDFLAG(ENABLE_AI_CHAT) ai_chat::ModelServiceFactory::GetInstance(); #endif + + web_discovery::WDPServiceFactory::GetInstance(); } } // namespace brave diff --git a/browser/sources.gni b/browser/sources.gni index 885ce2b23587..c260cc27f66c 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -135,6 +135,7 @@ brave_chrome_browser_deps = [ "//brave/browser/sync", "//brave/browser/themes", "//brave/browser/ui", + "//brave/browser/web_discovery", "//brave/common", "//brave/components/ai_chat/core/common/buildflags", "//brave/components/ai_rewriter/common/buildflags", @@ -204,7 +205,6 @@ brave_chrome_browser_deps = [ "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/version_info", - "//brave/components/web_discovery_project/browser", "//brave/components/webcompat:core", "//brave/services/network/public/cpp", "//brave/third_party/blink/renderer", diff --git a/browser/web_discovery/BUILD.gn b/browser/web_discovery/BUILD.gn index ba369e8cb8e3..5439157e3481 100644 --- a/browser/web_discovery/BUILD.gn +++ b/browser/web_discovery/BUILD.gn @@ -5,6 +5,17 @@ import("//extensions/buildflags/buildflags.gni") +source_set("web_discovery") { + sources = [ + "wdp_service_factory.cc", + "wdp_service_factory.h", + ] + deps = [ + "//base", + "//brave/components/web_discovery/browser", + ] +} + source_set("unit_tests") { if (enable_extensions) { testonly = true diff --git a/browser/web_discovery/wdp_service_factory.cc b/browser/web_discovery/wdp_service_factory.cc new file mode 100644 index 000000000000..e9fc397fb5d3 --- /dev/null +++ b/browser/web_discovery/wdp_service_factory.cc @@ -0,0 +1,42 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/web_discovery/wdp_service_factory.h" + +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/user_prefs/user_prefs.h" +#include "content/public/browser/browser_context.h" + +namespace web_discovery { + +WDPServiceFactory* WDPServiceFactory::GetInstance() { + static base::NoDestructor instance; + return instance.get(); +} + +WDPServiceFactory::WDPServiceFactory() + : BrowserContextKeyedServiceFactory( + "WDPService", + BrowserContextDependencyManager::GetInstance()) {} + +WDPServiceFactory::~WDPServiceFactory() = default; + +KeyedService* WDPServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new WDPService(user_prefs::UserPrefs::Get(context)); +} + +content::BrowserContext* WDPServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + // Prevents creation of service instance for incognito/OTR profiles + return context->IsOffTheRecord() ? nullptr : context; +} + +bool WDPServiceFactory::ServiceIsCreatedWithBrowserContext() const { + return true; +} + +} // namespace web_discovery diff --git a/browser/web_discovery/wdp_service_factory.h b/browser/web_discovery/wdp_service_factory.h new file mode 100644 index 000000000000..4c194af66112 --- /dev/null +++ b/browser/web_discovery/wdp_service_factory.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_WEB_DISCOVERY_WDP_SERVICE_FACTORY_H_ +#define BRAVE_BROWSER_WEB_DISCOVERY_WDP_SERVICE_FACTORY_H_ + +#include "base/no_destructor.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace web_discovery { + +class WDPServiceFactory : public BrowserContextKeyedServiceFactory { + public: + static WDPServiceFactory* GetInstance(); + + private: + friend base::NoDestructor; + + WDPServiceFactory(); + ~WDPServiceFactory() override; + + WDPServiceFactory(const WDPServiceFactory&) = delete; + WDPServiceFactory& operator=(const WDPServiceFactory&) = delete; + + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; +}; + +} // namespace web_discovery + +#endif // BRAVE_BROWSER_WEB_DISCOVERY_WDP_SERVICE_FACTORY_H_ diff --git a/components/web_discovery_project/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn similarity index 72% rename from components/web_discovery_project/browser/BUILD.gn rename to components/web_discovery/browser/BUILD.gn index eb59e4c02ea3..3129d0a05eac 100644 --- a/components/web_discovery_project/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -4,7 +4,12 @@ # You can obtain one at https://mozilla.org/MPL/2.0/. static_library("browser") { + sources = [ + "wdp_service.cc", + "wdp_service.h", + ] deps = [ - "anonymous_credentials/rs:rust_lib" + "anonymous_credentials/rs:rust_lib", + "//base", ] } diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn b/components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn similarity index 88% rename from components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn rename to components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn index 6c2f9e6f564b..2ffc161db1be 100644 --- a/components/web_discovery_project/browser/anonymous_credentials/rs/BUILD.gn +++ b/components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn @@ -13,9 +13,7 @@ rust_static_library("rust_lib") { edition = "2021" sources = [ "src/lib.rs" ] - visibility = [ - "//brave/components/web_discovery_project/browser:*", - ] + visibility = [ "//brave/components/web_discovery/browser:*" ] cxx_bindings = [ "src/lib.rs" ] diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock similarity index 100% rename from components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.lock rename to components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml similarity index 100% rename from components/web_discovery_project/browser/anonymous_credentials/rs/Cargo.toml rename to components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml diff --git a/components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs similarity index 100% rename from components/web_discovery_project/browser/anonymous_credentials/rs/src/lib.rs rename to components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc new file mode 100644 index 000000000000..4c80758623a2 --- /dev/null +++ b/components/web_discovery/browser/wdp_service.cc @@ -0,0 +1,14 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/pref_service.h" + +namespace web_discovery { + +WDPService::WDPService(PrefService* profile_prefs) + : profile_prefs_(profile_prefs) {} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h new file mode 100644 index 000000000000..6e77498d9cec --- /dev/null +++ b/components/web_discovery/browser/wdp_service.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ + +#include "base/memory/raw_ptr.h" +#include "components/keyed_service/core/keyed_service.h" + +class PrefService; + +namespace web_discovery { + +class WDPService : public KeyedService { + public: + explicit WDPService(PrefService* profile_prefs); + + WDPService(const WDPService&) = delete; + WDPService& operator=(const WDPService&) = delete; + + private: + raw_ptr profile_prefs_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ From 55959d4f4c2ca978ef9cca0bb3d74941d58bd02c Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Mon, 29 Apr 2024 11:40:10 -0700 Subject: [PATCH 05/36] Add WDP server config loader --- browser/web_discovery/BUILD.gn | 3 + browser/web_discovery/wdp_service_factory.cc | 7 +- components/web_discovery/browser/BUILD.gn | 11 + components/web_discovery/browser/DEPS | 3 + .../browser/server_config_loader.cc | 197 ++++++++++++++++++ .../browser/server_config_loader.h | 69 ++++++ components/web_discovery/browser/util.cc | 20 ++ components/web_discovery/browser/util.h | 17 ++ .../web_discovery/browser/wdp_service.cc | 42 +++- .../web_discovery/browser/wdp_service.h | 25 ++- 10 files changed, 390 insertions(+), 4 deletions(-) create mode 100644 components/web_discovery/browser/DEPS create mode 100644 components/web_discovery/browser/server_config_loader.cc create mode 100644 components/web_discovery/browser/server_config_loader.h create mode 100644 components/web_discovery/browser/util.cc create mode 100644 components/web_discovery/browser/util.h diff --git a/browser/web_discovery/BUILD.gn b/browser/web_discovery/BUILD.gn index 5439157e3481..2475bf5924de 100644 --- a/browser/web_discovery/BUILD.gn +++ b/browser/web_discovery/BUILD.gn @@ -13,6 +13,9 @@ source_set("web_discovery") { deps = [ "//base", "//brave/components/web_discovery/browser", + "//components/keyed_service/content", + "//components/user_prefs", + "//content/public/browser", ] } diff --git a/browser/web_discovery/wdp_service_factory.cc b/browser/web_discovery/wdp_service_factory.cc index e9fc397fb5d3..9e883ecbc7c3 100644 --- a/browser/web_discovery/wdp_service_factory.cc +++ b/browser/web_discovery/wdp_service_factory.cc @@ -9,6 +9,7 @@ #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" namespace web_discovery { @@ -26,7 +27,11 @@ WDPServiceFactory::~WDPServiceFactory() = default; KeyedService* WDPServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - return new WDPService(user_prefs::UserPrefs::Get(context)); + auto* default_storage_partition = context->GetDefaultStoragePartition(); + auto shared_url_loader_factory = + default_storage_partition->GetURLLoaderFactoryForBrowserProcess(); + return new WDPService(user_prefs::UserPrefs::Get(context), + shared_url_loader_factory); } content::BrowserContext* WDPServiceFactory::GetBrowserContextToUse( diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 3129d0a05eac..0d4274e88850 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -5,11 +5,22 @@ static_library("browser") { sources = [ + "server_config_loader.cc", + "server_config_loader.h", + "util.cc", + "util.h", "wdp_service.cc", "wdp_service.h", ] deps = [ "anonymous_credentials/rs:rust_lib", "//base", + "//brave/brave_domains", + "//brave/components/constants", + "//components/keyed_service/core", + "//components/prefs", + "//net", + "//services/network/public/cpp", + "//url", ] } diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS new file mode 100644 index 000000000000..28eae2e9ad3e --- /dev/null +++ b/components/web_discovery/browser/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+services/network/public", +] diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc new file mode 100644 index 000000000000..f96911dbfb91 --- /dev/null +++ b/components/web_discovery/browser/server_config_loader.cc @@ -0,0 +1,197 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/server_config_loader.h" + +#include + +#include "base/base64.h" +#include "base/json/json_reader.h" +#include "base/location.h" +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/values.h" +#include "brave/components/web_discovery/browser/util.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kMaxResponseSize = 16 * 1024; + +constexpr net::BackoffEntry::Policy kBackoffPolicy = { + .num_errors_to_ignore = 0, + .initial_delay_ms = 10 * 1000, + .multiply_factor = 2.0, + .jitter_factor = 0.1, + .maximum_backoff_ms = 10 * 60 * 1000, + .entry_lifetime_ms = -1, + .always_use_initial_delay = false}; + +constexpr base::TimeDelta kMinReloadInterval = base::Hours(1); +constexpr base::TimeDelta kMaxReloadInterval = base::Hours(4); + +constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("wdp_config", R"( + semantics { + sender: "Brave Web Discovery Project Server Configuration Fetch" + description: + "Requests server configuration needed to send Web Discovery " + "measurements to Brave servers." + trigger: + "Requests are automatically sent at intervals " + "while Brave is running." + data: "Configuration attributes" + destination: WEBSITE + } + policy { + cookies_allowed: NO + setting: + "Users can opt-in or out via brave://settings/search" + })"); + +constexpr char kVersionHeader[] = "Version"; +constexpr int kCurrentVersion = 1; + +constexpr char kGroupPubKeysFieldName[] = "groupPubKeys"; +constexpr char kPubKeysFieldName[] = "pubKeys"; +constexpr char kMinVersionFieldName[] = "minVersion"; + +constexpr char kConfigPathWithFields[] = + "/config?fields=minVersion,groupPubKeys,pubKeys,sourceMap"; + +KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { + KeyMap map; + for (const auto [date, key_b64] : encoded_keys) { + std::vector decoded_data; + auto key = base::Base64Decode(key_b64.GetString()); + base::Time time; + bool time_parse_result = base::Time::FromString(date.c_str(), &time); + if (time_parse_result && key) { + map[time] = *key; + } + } + return map; +} + +} // namespace + +ServerConfig::ServerConfig() = default; + +ServerConfig::~ServerConfig() = default; + +ServerConfigLoader::ServerConfigLoader( + network::SharedURLLoaderFactory* shared_url_loader_factory, + ConfigCallback config_callback) + : shared_url_loader_factory_(shared_url_loader_factory), + config_callback_(config_callback), + backoff_entry_(&kBackoffPolicy) { + config_url_ = + GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, + GetCollectorHost(), kConfigPathWithFields})); +} + +ServerConfigLoader::~ServerConfigLoader() = default; + +void ServerConfigLoader::Load() { + // TODO(djandries): create a backoff url loader if one doenst exist + // but consider how join retries will work before you do. we might want to + // generate gsk beforehand... in which case it might make sense to add a + // repeating callback for generating state + network requests + if (url_loader_) { + // Another request is in progress + return; + } + auto resource_request = std::make_unique(); + resource_request->url = config_url_; + resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; + resource_request->headers.SetHeader(kVersionHeader, + base::NumberToString(kCurrentVersion)); + + url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), + kNetworkTrafficAnnotation); + + url_loader_->DownloadToString( + shared_url_loader_factory_.get(), + base::BindOnce(&ServerConfigLoader::OnConfigResponse, + base::Unretained(this)), + kMaxResponseSize); + + backoff_entry_.InformOfRequest(false); +} + +void ServerConfigLoader::OnConfigResponse( + std::optional response_body) { + base::Time update_time = base::Time::Now(); + bool result = !ProcessConfigResponse(response_body); + + backoff_entry_.InformOfRequest(response_body.has_value()); + + if (!result) { + update_time += backoff_entry_.GetTimeUntilRelease(); + } else { + update_time += base::RandTimeDelta(kMinReloadInterval, kMaxReloadInterval); + } + + update_timer_.Start( + FROM_HERE, update_time, + base::BindOnce(&ServerConfigLoader::Load, base::Unretained(this))); +} + +bool ServerConfigLoader::ProcessConfigResponse( + const std::optional& response_body) { + auto* response_info = url_loader_->ResponseInfo(); + if (!response_body || !response_info || + response_info->headers->response_code() != 200) { + VLOG(1) << "Failed to fetch server config"; + return false; + } + + auto parsed_json = base::JSONReader::ReadAndReturnValueWithError( + *response_body, base::JSON_PARSE_RFC); + + if (!parsed_json.has_value()) { + VLOG(1) << "Failed to parse server config json"; + return false; + } + + const auto* root = parsed_json.value().GetIfDict(); + if (!root) { + VLOG(1) << "Failed to parse server config: not a dict"; + return false; + } + + const auto min_version = root->FindInt(kMinVersionFieldName); + if (min_version && *min_version > kCurrentVersion) { + VLOG(1) << "Server minimum version is higher than current version, failing"; + return false; + } + + ServerConfig config; + + const auto* group_pub_keys = root->FindDict(kGroupPubKeysFieldName); + if (!group_pub_keys) { + VLOG(1) << "Failed to retrieve groupPubKeys from server config"; + return false; + } + const auto* pub_keys = root->FindDict(kPubKeysFieldName); + if (!pub_keys) { + VLOG(1) << "Failed to retrieve pubKeys from server config"; + return false; + } + + config.group_pub_keys = ParseKeys(*group_pub_keys); + config.pub_keys = ParseKeys(*pub_keys); + + config_callback_.Run(config); + return true; +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h new file mode 100644 index 000000000000..50d490b2b911 --- /dev/null +++ b/components/web_discovery/browser/server_config_loader.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SERVER_CONFIG_LOADER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SERVER_CONFIG_LOADER_H_ + +#include +#include +#include +#include + +#include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/timer/wall_clock_timer.h" +#include "net/base/backoff_entry.h" +#include "url/gurl.h" + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace web_discovery { + +using KeyMap = base::flat_map>; + +struct ServerConfig { + ServerConfig(); + ~ServerConfig(); + + KeyMap group_pub_keys; + KeyMap pub_keys; +}; + +class ServerConfigLoader { + public: + using ConfigCallback = base::RepeatingCallback; + + explicit ServerConfigLoader( + network::SharedURLLoaderFactory* shared_url_loader_factory, + ConfigCallback config_callback); + ~ServerConfigLoader(); + + ServerConfigLoader(const ServerConfigLoader&) = delete; + ServerConfigLoader& operator=(const ServerConfigLoader&) = delete; + + void Load(); + + private: + void OnConfigResponse(std::optional response_body); + bool ProcessConfigResponse(const std::optional& response_body); + + GURL config_url_; + raw_ptr shared_url_loader_factory_; + + ConfigCallback config_callback_; + + std::unique_ptr url_loader_; + net::BackoffEntry backoff_entry_; + + base::WallClockTimer update_timer_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SERVER_CONFIG_LOADER_H_ diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc new file mode 100644 index 000000000000..630aeac182c7 --- /dev/null +++ b/components/web_discovery/browser/util.cc @@ -0,0 +1,20 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/util.h" + +#include "brave/brave_domains/service_domains.h" + +namespace web_discovery { + +namespace { +constexpr char kCollectorHostPrefix[] = "collector.wdp"; +} // namespace + +std::string GetCollectorHost() { + return brave_domains::GetServicesDomain(kCollectorHostPrefix); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h new file mode 100644 index 000000000000..a5e67c067978 --- /dev/null +++ b/components/web_discovery/browser/util.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ + +#include + +namespace web_discovery { + +std::string GetCollectorHost(); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 4c80758623a2..10ef2c7689f8 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -4,11 +4,49 @@ * You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "brave/components/web_discovery/browser/wdp_service.h" +#include "brave/components/constants/pref_names.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_service.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace web_discovery { -WDPService::WDPService(PrefService* profile_prefs) - : profile_prefs_(profile_prefs) {} +WDPService::WDPService( + PrefService* profile_prefs, + scoped_refptr shared_url_loader_factory) + : profile_prefs_(profile_prefs), + shared_url_loader_factory_(shared_url_loader_factory) { + pref_change_registrar_.Init(profile_prefs); + pref_change_registrar_.Add(kWebDiscoveryEnabled, + base::BindRepeating(&WDPService::OnEnabledChange, + base::Unretained(this))); + + if (profile_prefs_->GetBoolean(kWebDiscoveryEnabled)) { + Start(); + } +} + +WDPService::~WDPService() = default; + +void WDPService::Start() { + server_config_loader_ = std::make_unique( + shared_url_loader_factory_.get(), + base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this))); + server_config_loader_->Load(); +} + +void WDPService::Stop() { + server_config_loader_ = nullptr; +} + +void WDPService::OnEnabledChange() { + if (profile_prefs_->GetBoolean(kWebDiscoveryEnabled)) { + Start(); + } else { + Stop(); + } +} + +void WDPService::OnConfigChange(const ServerConfig& config) {} } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 6e77498d9cec..79e8f179f8cc 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -6,22 +6,45 @@ #ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ +#include + #include "base/memory/raw_ptr.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/prefs/pref_change_registrar.h" class PrefService; +namespace network { +class SharedURLLoaderFactory; +} // namespace network + namespace web_discovery { class WDPService : public KeyedService { public: - explicit WDPService(PrefService* profile_prefs); + WDPService( + PrefService* profile_prefs, + scoped_refptr shared_url_loader_factory); + ~WDPService() override; WDPService(const WDPService&) = delete; WDPService& operator=(const WDPService&) = delete; private: + void Start(); + void Stop(); + + void OnEnabledChange(); + + void OnConfigChange(const ServerConfig& config); + raw_ptr profile_prefs_; + PrefChangeRegistrar pref_change_registrar_; + + scoped_refptr shared_url_loader_factory_; + + std::unique_ptr server_config_loader_; }; } // namespace web_discovery From 4c9f06f5259669c0d2f15887475cf0ae1319f622 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Mon, 6 May 2024 12:17:04 -0700 Subject: [PATCH 06/36] Add credential manager for Web Discovery --- browser/brave_profile_prefs.cc | 3 + browser/sources.gni | 1 + components/web_discovery/browser/BUILD.gn | 5 + components/web_discovery/browser/DEPS | 2 + .../browser/credential_manager.cc | 419 ++++++++++++++++++ .../browser/credential_manager.h | 91 ++++ components/web_discovery/browser/pref_names.h | 20 + .../browser/server_config_loader.cc | 35 +- .../browser/server_config_loader.h | 7 +- components/web_discovery/browser/util.cc | 22 + components/web_discovery/browser/util.h | 13 + .../web_discovery/browser/wdp_service.cc | 29 +- .../web_discovery/browser/wdp_service.h | 9 +- 13 files changed, 626 insertions(+), 30 deletions(-) create mode 100644 components/web_discovery/browser/credential_manager.cc create mode 100644 components/web_discovery/browser/credential_manager.h create mode 100644 components/web_discovery/browser/pref_names.h diff --git a/browser/brave_profile_prefs.cc b/browser/brave_profile_prefs.cc index 28398f78e9ad..b69a5de51801 100644 --- a/browser/brave_profile_prefs.cc +++ b/browser/brave_profile_prefs.cc @@ -48,6 +48,7 @@ #include "brave/components/search_engines/brave_prepopulated_engines.h" #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/browser/wdp_service.h" #include "build/build_config.h" #include "chrome/browser/prefetch/pref_names.h" #include "chrome/browser/prefs/session_startup_pref.h" @@ -508,6 +509,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { registry->SetDefaultPrefValue(prefs::kSearchSuggestEnabled, base::Value(false)); + + web_discovery::WDPService::RegisterProfilePrefs(registry); } } // namespace brave diff --git a/browser/sources.gni b/browser/sources.gni index c260cc27f66c..7b4421ab895e 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -205,6 +205,7 @@ brave_chrome_browser_deps = [ "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/version_info", + "//brave/components/web_discovery/browser", "//brave/components/webcompat:core", "//brave/services/network/public/cpp", "//brave/third_party/blink/renderer", diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 0d4274e88850..e468c8afcd34 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -5,6 +5,9 @@ static_library("browser") { sources = [ + "credential_manager.cc", + "credential_manager.h", + "pref_names.h", "server_config_loader.cc", "server_config_loader.h", "util.cc", @@ -19,8 +22,10 @@ static_library("browser") { "//brave/components/constants", "//components/keyed_service/core", "//components/prefs", + "//components/webcrypto", "//net", "//services/network/public/cpp", + "//third_party/blink/public:blink_headers", "//url", ] } diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index 28eae2e9ad3e..de723fd20295 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -1,3 +1,5 @@ include_rules = [ "+services/network/public", + "+third_party/blink/public/platform", + "+third_party/boringssl/src/include", ] diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc new file mode 100644 index 000000000000..3486ea263c6e --- /dev/null +++ b/components/web_discovery/browser/credential_manager.cc @@ -0,0 +1,419 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/credential_manager.h" + +#include + +#include "base/base64.h" +#include "base/functional/bind.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/util.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" +#include "components/webcrypto/algorithm_dispatch.h" +#include "components/webcrypto/blink_key_handle.h" +#include "components/webcrypto/generate_key_result.h" +#include "components/webcrypto/status.h" +#include "crypto/sha2.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/blink/public/platform/web_crypto_algorithm.h" +#include "third_party/blink/public/platform/web_crypto_algorithm_params.h" +#include "third_party/blink/public/platform/web_crypto_key.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "third_party/boringssl/src/include/openssl/rsa.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kRsaKeySize = 2048; +constexpr unsigned char kRsaPublicExponent[] = {0x01, 0x00, 0x01}; +constexpr char kJoinPath[] = "/join"; + +constexpr char kJoinDateField[] = "ts"; +constexpr char kJoinMessageField[] = "joinMsg"; +constexpr char kJoinRSAPublicKeyField[] = "pk"; +constexpr char kJoinRSASignatureField[] = "sig"; +constexpr char kJoinResponseField[] = "joinResponse"; + +constexpr char kGSKDictKey[] = "gsk"; +constexpr char kCredentialDictKey[] = "credential"; + +blink::WebCryptoAlgorithm GetRSAAlgorithm() { + auto hash = blink::WebCryptoAlgorithm::AdoptParamsAndCreate( + blink::WebCryptoAlgorithmId::kWebCryptoAlgorithmIdSha256, nullptr); + return blink::WebCryptoAlgorithm::AdoptParamsAndCreate( + blink::WebCryptoAlgorithmId::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5, + new blink::WebCryptoRsaHashedKeyGenParams( + hash, kRsaKeySize, + blink::WebVector(kRsaPublicExponent, + sizeof(kRsaPublicExponent)))); +} + +std::optional EncodeRSAPublicKey(const blink::WebCryptoKey& key) { + auto* evp_pkey = webcrypto::GetEVP_PKEY(key); + if (!evp_pkey) { + return std::nullopt; + } + auto* rsa = EVP_PKEY_get0_RSA(evp_pkey); + if (!rsa) { + return std::nullopt; + } + CBB cbb; + uint8_t* out_bytes; + size_t out_len; + if (!CBB_init(&cbb, 0) || !RSA_marshal_public_key(&cbb, rsa) || + !CBB_finish(&cbb, &out_bytes, &out_len)) { + CBB_cleanup(&cbb); + return std::nullopt; + } + auto key_b64 = base::Base64Encode(base::span(out_bytes, out_len)); + OPENSSL_free(out_bytes); + return key_b64; +} + +constexpr net::BackoffEntry::Policy kBackoffPolicy = { + .num_errors_to_ignore = 0, + .initial_delay_ms = 10 * 1000, + .multiply_factor = 2.0, + .jitter_factor = 0.1, + .maximum_backoff_ms = 10 * 60 * 1000, + .entry_lifetime_ms = -1, + .always_use_initial_delay = false}; + +constexpr net::NetworkTrafficAnnotationTag kJoinNetworkTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("wdp_join", R"( + semantics { + sender: "Brave Web Discovery HPNv2 Join" + description: + "Retrieves anonymous credentials in order to sign Web Discovery + measurements sent via the HumanWeb Proxy Network." + trigger: + "Requests are automatically sent on daily intervals " + "while Brave is running." + data: "Configuration attributes" + destination: WEBSITE + } + policy { + cookies_allowed: NO + setting: + "Users can opt-in or out via brave://settings/search" + })"); + +} // namespace + +CredentialManager::CredentialManager( + PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + std::unique_ptr* last_loaded_server_config, + base::RepeatingClosure credentials_loaded_callback) + : profile_prefs_(profile_prefs), + shared_url_loader_factory_(shared_url_loader_factory), + last_loaded_server_config_(last_loaded_server_config), + backoff_entry_(&kBackoffPolicy), + credentials_loaded_callback_(credentials_loaded_callback), + anonymous_credential_manager_( + anonymous_credentials::new_credential_manager()) { + join_url_ = + GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, + GetCollectorHost(), kJoinPath})); +} + +CredentialManager::~CredentialManager() = default; + +bool CredentialManager::LoadRSAKey() { + std::string private_key_b64 = + profile_prefs_->GetString(kCredentialRSAPrivateKey); + rsa_public_key_b64_ = profile_prefs_->GetString(kCredentialRSAPublicKey); + + if (private_key_b64.empty() || !rsa_public_key_b64_) { + return true; + } + + std::string private_key_data; + + if (!base::Base64Decode(private_key_b64, &private_key_data)) { + VLOG(1) << "Failed to decode base64 of stored RSA keys"; + return false; + } + + auto algo = GetRSAAlgorithm(); + base::span private_key_data_span( + reinterpret_cast(private_key_data.data()), + private_key_data.size()); + + rsa_private_key_ = std::make_unique(); + + auto status = webcrypto::ImportKey( + blink::WebCryptoKeyFormat::kWebCryptoKeyFormatPkcs8, + private_key_data_span, algo, true, + blink::WebCryptoKeyUsage::kWebCryptoKeyUsageSign, rsa_private_key_.get()); + + if (status.IsError()) { + VLOG(1) << "RSA private key import failed: " << status.error_details(); + rsa_private_key_ = nullptr; + return false; + } + + return true; +} + +bool CredentialManager::GenerateRSAKey() { + webcrypto::GenerateKeyResult result; + auto algo = GetRSAAlgorithm(); + auto status = webcrypto::GenerateKey( + algo, true, blink::WebCryptoKeyUsage::kWebCryptoKeyUsageSign, &result); + if (status.IsError()) { + VLOG(1) << "RSA key generation failed: " << status.error_details(); + return false; + } + + rsa_private_key_ = + std::make_unique(result.private_key()); + + std::vector private_key_bytes; + + status = + webcrypto::ExportKey(blink::WebCryptoKeyFormat::kWebCryptoKeyFormatPkcs8, + *rsa_private_key_, &private_key_bytes); + if (status.IsError()) { + VLOG(1) << "RSA key private key export failed: " << status.error_details(); + return false; + } + + auto public_key_b64 = EncodeRSAPublicKey(result.public_key()); + if (!public_key_b64) { + VLOG(1) << "RSA key public key export failed"; + return false; + } + + profile_prefs_->SetString(kCredentialRSAPrivateKey, + base::Base64Encode(private_key_bytes)); + profile_prefs_->SetString(kCredentialRSAPublicKey, *public_key_b64); + + return true; +} + +void CredentialManager::JoinGroups() { + if (!*last_loaded_server_config_) { + return; + } + auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); + const auto& anon_creds_dict = + profile_prefs_->GetDict(kAnonymousCredentialsDict); + for (const auto& [date, group_pub_key_b64] : + (*last_loaded_server_config_)->group_pub_keys) { + if (date < today_date || join_url_loaders_.contains(date) || + anon_creds_dict.contains(date)) { + continue; + } + + if (rsa_private_key_ == nullptr) { + if (!LoadRSAKey()) { + return; + } + if (rsa_private_key_ == nullptr) { + if (!GenerateRSAKey()) { + return; + } + } + } + + StartJoinGroup(date, group_pub_key_b64); + } +} + +void CredentialManager::StartJoinGroup(const std::string& date, + const std::string& group_pub_key_b64) { + auto algo = GetRSAAlgorithm(); + + auto group_pub_key = base::Base64Decode(group_pub_key_b64); + if (!group_pub_key) { + VLOG(1) << "Failed to decode group public key for " << date; + return; + } + + auto challenge_elements = base::Value::List::with_capacity(2); + challenge_elements.Append(*rsa_public_key_b64_); + challenge_elements.Append(group_pub_key_b64); + + std::string pre_challenge; + base::JSONWriter::Write(challenge_elements, &pre_challenge); + base::span pre_challenge_span( + reinterpret_cast(pre_challenge.data()), pre_challenge.size()); + auto challenge = crypto::SHA256Hash(pre_challenge_span); + + auto start_join_result = anonymous_credential_manager_->start_join( + rust::Slice(challenge.data(), challenge.size())); + auto gsk = std::vector(start_join_result.gsk.begin(), + start_join_result.gsk.end()); + + std::vector signature; + auto status = webcrypto::Sign(algo, *rsa_private_key_, + start_join_result.join_request, &signature); + if (status.IsError()) { + VLOG(1) << "RSA signature failed: " << status.error_details(); + return; + } + + base::Value::Dict body_fields; + + body_fields.Set(kJoinDateField, date); + body_fields.Set(kJoinMessageField, + base::Base64Encode(start_join_result.join_request)); + body_fields.Set(kJoinRSAPublicKeyField, *rsa_public_key_b64_); + body_fields.Set(kJoinRSASignatureField, base::Base64Encode(signature)); + + std::string json_body; + if (!base::JSONWriter::Write(body_fields, &json_body)) { + VLOG(1) << "Join body serialization failed"; + return; + } + + auto resource_request = CreateResourceRequest(join_url_); + + join_url_loaders_[date] = network::SimpleURLLoader::Create( + std::move(resource_request), kJoinNetworkTrafficAnnotation); + auto& url_loader = join_url_loaders_[date]; + + url_loader->AttachStringForUpload(json_body); + + url_loader->DownloadToString( + shared_url_loader_factory_.get(), + base::BindOnce(&CredentialManager::OnJoinResponse, base::Unretained(this), + date, *group_pub_key, gsk), + kMaxResponseSize); +} + +void CredentialManager::OnJoinResponse( + std::string date, + std::vector group_pub_key, + std::vector gsk, + std::optional response_body) { + bool result = ProcessJoinResponse(date, group_pub_key, gsk, response_body); + + backoff_entry_.InformOfRequest(result); + if (!result) { + retry_timer_.Start( + FROM_HERE, base::Time::Now() + backoff_entry_.GetTimeUntilRelease(), + base::BindOnce(&CredentialManager::JoinGroups, base::Unretained(this))); + } +} + +bool CredentialManager::ProcessJoinResponse( + const std::string& date, + const std::vector& group_pub_key, + const std::vector& gsk, + const std::optional& response_body) { + CHECK(join_url_loaders_[date]); + auto& url_loader = join_url_loaders_[date]; + auto* response_info = url_loader->ResponseInfo(); + if (!response_body || !response_info || + response_info->headers->response_code() != 200) { + VLOG(1) << "Failed to fetch credentials for " << date; + return false; + } + + auto parsed_json = base::JSONReader::ReadAndReturnValueWithError( + *response_body, base::JSON_PARSE_RFC); + + if (!parsed_json.has_value()) { + VLOG(1) << "Failed to parse join response json"; + return false; + } + + const auto* root = parsed_json.value().GetIfDict(); + if (!root) { + VLOG(1) << "Failed to parse join response json: not a dict"; + return false; + } + + const auto* join_resp = root->FindString(kJoinResponseField); + if (!join_resp) { + VLOG(1) << "Failed to find content in join response json"; + return false; + } + + auto join_resp_bytes = base::Base64Decode(*join_resp); + if (!join_resp_bytes) { + VLOG(1) << "Failed to decode join response base64"; + return false; + } + + auto finish_res = anonymous_credential_manager_->finish_join( + rust::Slice(group_pub_key.data(), group_pub_key.size()), + rust::Slice(gsk.data(), gsk.size()), + rust::Slice(reinterpret_cast(join_resp_bytes->data()), + join_resp_bytes->size())); + if (!finish_res.error_message.empty()) { + VLOG(1) << "Failed to finish credential join for " << date << ": " + << finish_res.error_message.c_str(); + return false; + } + + ScopedDictPrefUpdate update(profile_prefs_, kAnonymousCredentialsDict); + auto* date_dict = update->EnsureDict(date); + date_dict->Set(kGSKDictKey, base::Base64Encode(gsk)); + date_dict->Set(kCredentialDictKey, base::Base64Encode(finish_res.data)); + + return true; +} + +std::optional> CredentialManager::Sign( + const std::vector& msg, + const std::vector& basename) { + auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); + const auto& anon_creds_dict = + profile_prefs_->GetDict(kAnonymousCredentialsDict); + if (!loaded_credential_date_ || loaded_credential_date_ != today_date) { + auto* today_cred_dict = anon_creds_dict.FindDict(today_date); + if (!today_cred_dict) { + VLOG(1) << "Failed to sign due to unavailability of credentials"; + return std::nullopt; + } + auto* gsk_b64 = today_cred_dict->FindString(kGSKDictKey); + auto* credential_b64 = today_cred_dict->FindString(kCredentialDictKey); + if (!gsk_b64 || !credential_b64) { + VLOG(1) << "Failed to sign due to unavailability of gsk/credential"; + return std::nullopt; + } + auto gsk_bytes = base::Base64Decode(*gsk_b64); + auto credential_bytes = base::Base64Decode(*credential_b64); + if (!gsk_bytes || !credential_bytes) { + VLOG(1) << "Failed to sign due to bad gsk/credential base64"; + return std::nullopt; + } + auto set_res = anonymous_credential_manager_->set_gsk_and_credentials( + rust::Slice(reinterpret_cast(gsk_bytes->data()), + gsk_bytes->size()), + rust::Slice(reinterpret_cast(credential_bytes->data()), + credential_bytes->size())); + if (!set_res.error_message.empty()) { + VLOG(1) << "Failed to sign due to credential set failure: " + << set_res.error_message.c_str(); + return std::nullopt; + } + loaded_credential_date_ = today_date; + } + auto sig_res = anonymous_credential_manager_->sign( + rust::Slice(msg.data(), msg.size()), + rust::Slice(basename.data(), basename.size())); + if (!sig_res.error_message.empty()) { + VLOG(1) << "Failed to sign: " << sig_res.error_message.c_str(); + return std::nullopt; + } + return std::vector(sig_res.data.begin(), sig_res.data.end()); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h new file mode 100644 index 000000000000..191fa395b3c5 --- /dev/null +++ b/components/web_discovery/browser/credential_manager.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_MANAGER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_MANAGER_H_ + +#include +#include +#include +#include + +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/timer/wall_clock_timer.h" +#include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" +#include "net/base/backoff_entry.h" + +class PrefService; + +namespace blink { +class WebCryptoKey; +} // namespace blink + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace web_discovery { + +class CredentialManager { + public: + CredentialManager(PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + std::unique_ptr* last_loaded_server_config, + base::RepeatingClosure credentials_loaded_callback); + ~CredentialManager(); + + CredentialManager(const CredentialManager&) = delete; + CredentialManager& operator=(const CredentialManager&) = delete; + + void JoinGroups(); + + std::optional> Sign( + const std::vector& msg, + const std::vector& basename); + + private: + // TODO(djandries): maybe split this into sign_encrypt.h + bool LoadRSAKey(); + bool GenerateRSAKey(); + + void StartJoinGroup(const std::string& date, + const std::string& group_pub_key_b64); + + void OnJoinResponse(std::string date, + std::vector group_pub_key, + std::vector gsk, + std::optional response_body); + bool ProcessJoinResponse(const std::string& date, + const std::vector& group_pub_key, + const std::vector& gsk, + const std::optional& response_body); + + raw_ptr profile_prefs_; + raw_ptr shared_url_loader_factory_; + raw_ptr> last_loaded_server_config_; + + GURL join_url_; + base::flat_map> + join_url_loaders_; + net::BackoffEntry backoff_entry_; + base::WallClockTimer retry_timer_; + + base::RepeatingClosure credentials_loaded_callback_; + + rust::Box + anonymous_credential_manager_; + + std::unique_ptr rsa_private_key_; + std::optional rsa_public_key_b64_; + + std::optional loaded_credential_date_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_MANAGER_H_ diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h new file mode 100644 index 000000000000..c509587844ac --- /dev/null +++ b/components/web_discovery/browser/pref_names.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PREF_NAMES_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PREF_NAMES_H_ + +namespace web_discovery { + +inline constexpr char kCredentialRSAPrivateKey[] = + "brave.web_discovery.rsa_priv_key"; +inline constexpr char kCredentialRSAPublicKey[] = + "brave.web_discovery.rsa_pub_key"; +inline constexpr char kAnonymousCredentialsDict[] = + "brave.web_discovery.anon_creds"; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PREF_NAMES_H_ diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index f96911dbfb91..a7d14a388197 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -6,16 +6,15 @@ #include "brave/components/web_discovery/browser/server_config_loader.h" #include +#include #include "base/base64.h" #include "base/json/json_reader.h" #include "base/location.h" #include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "brave/components/web_discovery/browser/util.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" @@ -24,8 +23,6 @@ namespace web_discovery { namespace { -constexpr size_t kMaxResponseSize = 16 * 1024; - constexpr net::BackoffEntry::Policy kBackoffPolicy = { .num_errors_to_ignore = 0, .initial_delay_ms = 10 * 1000, @@ -41,7 +38,7 @@ constexpr base::TimeDelta kMaxReloadInterval = base::Hours(4); constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = net::DefineNetworkTrafficAnnotation("wdp_config", R"( semantics { - sender: "Brave Web Discovery Project Server Configuration Fetch" + sender: "Brave Web Discovery Server Configuration Fetch" description: "Requests server configuration needed to send Web Discovery " "measurements to Brave servers." @@ -57,9 +54,6 @@ constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = "Users can opt-in or out via brave://settings/search" })"); -constexpr char kVersionHeader[] = "Version"; -constexpr int kCurrentVersion = 1; - constexpr char kGroupPubKeysFieldName[] = "groupPubKeys"; constexpr char kPubKeysFieldName[] = "pubKeys"; constexpr char kMinVersionFieldName[] = "minVersion"; @@ -71,12 +65,11 @@ KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { KeyMap map; for (const auto [date, key_b64] : encoded_keys) { std::vector decoded_data; - auto key = base::Base64Decode(key_b64.GetString()); - base::Time time; - bool time_parse_result = base::Time::FromString(date.c_str(), &time); - if (time_parse_result && key) { - map[time] = *key; + // Decode to check for valid base64 + if (!base::Base64Decode(key_b64.GetString())) { + continue; } + map[date] = key_b64.GetString(); } return map; } @@ -109,11 +102,7 @@ void ServerConfigLoader::Load() { // Another request is in progress return; } - auto resource_request = std::make_unique(); - resource_request->url = config_url_; - resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; - resource_request->headers.SetHeader(kVersionHeader, - base::NumberToString(kCurrentVersion)); + auto resource_request = CreateResourceRequest(config_url_); url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), kNetworkTrafficAnnotation); @@ -123,8 +112,6 @@ void ServerConfigLoader::Load() { base::BindOnce(&ServerConfigLoader::OnConfigResponse, base::Unretained(this)), kMaxResponseSize); - - backoff_entry_.InformOfRequest(false); } void ServerConfigLoader::OnConfigResponse( @@ -174,7 +161,7 @@ bool ServerConfigLoader::ProcessConfigResponse( return false; } - ServerConfig config; + auto config = std::make_unique(); const auto* group_pub_keys = root->FindDict(kGroupPubKeysFieldName); if (!group_pub_keys) { @@ -187,10 +174,10 @@ bool ServerConfigLoader::ProcessConfigResponse( return false; } - config.group_pub_keys = ParseKeys(*group_pub_keys); - config.pub_keys = ParseKeys(*pub_keys); + config->group_pub_keys = ParseKeys(*group_pub_keys); + config->pub_keys = ParseKeys(*pub_keys); - config_callback_.Run(config); + config_callback_.Run(std::move(config)); return true; } diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 50d490b2b911..4697b9b1bf95 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -9,11 +9,9 @@ #include #include #include -#include #include "base/containers/flat_map.h" #include "base/memory/raw_ptr.h" -#include "base/memory/scoped_refptr.h" #include "base/timer/wall_clock_timer.h" #include "net/base/backoff_entry.h" #include "url/gurl.h" @@ -25,7 +23,7 @@ class SimpleURLLoader; namespace web_discovery { -using KeyMap = base::flat_map>; +using KeyMap = base::flat_map; struct ServerConfig { ServerConfig(); @@ -37,7 +35,8 @@ struct ServerConfig { class ServerConfigLoader { public: - using ConfigCallback = base::RepeatingCallback; + using ConfigCallback = + base::RepeatingCallback)>; explicit ServerConfigLoader( network::SharedURLLoaderFactory* shared_url_loader_factory, diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 630aeac182c7..1c11529a96ed 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -5,16 +5,38 @@ #include "brave/components/web_discovery/browser/util.h" +#include "base/strings/stringprintf.h" #include "brave/brave_domains/service_domains.h" namespace web_discovery { namespace { constexpr char kCollectorHostPrefix[] = "collector.wdp"; +constexpr char kVersionHeader[] = "Version"; } // namespace std::string GetCollectorHost() { + auto* cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch(kCollectorHostSwitch)) { + return cmd_line->GetSwitchValueASCII(kCollectorHostSwitch); + } return brave_domains::GetServicesDomain(kCollectorHostPrefix); } +std::unique_ptr CreateResourceRequest(GURL url) { + auto resource_request = std::make_unique(); + resource_request->url = url; + resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; + resource_request->headers.SetHeader(kVersionHeader, + base::NumberToString(kCurrentVersion)); + return resource_request; +} + +std::string FormatServerDate(const base::Time& date) { + base::Time::Exploded exploded; + date.UTCExplode(&exploded); + return base::StringPrintf("%04d%02d%02d", exploded.year, exploded.month, + exploded.day_of_month); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index a5e67c067978..d01eb24750b0 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -6,12 +6,25 @@ #ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ +#include #include +#include "base/time/time.h" +#include "services/network/public/cpp/resource_request.h" +#include "url/gurl.h" + namespace web_discovery { +inline constexpr size_t kMaxResponseSize = 16 * 1024; +inline constexpr char kCollectorHostSwitch[] = "wdp-collector-host"; +inline constexpr int kCurrentVersion = 1; + std::string GetCollectorHost(); +std::unique_ptr CreateResourceRequest(GURL url); + +std::string FormatServerDate(const base::Time& date); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 10ef2c7689f8..7521c4a93801 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -4,8 +4,14 @@ * You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "brave/components/web_discovery/browser/wdp_service.h" + +#include + +#include "base/functional/bind.h" #include "brave/components/constants/pref_names.h" +#include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/server_config_loader.h" +#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -28,7 +34,18 @@ WDPService::WDPService( WDPService::~WDPService() = default; +void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kAnonymousCredentialsDict); + registry->RegisterStringPref(kCredentialRSAPrivateKey, {}); + registry->RegisterStringPref(kCredentialRSAPublicKey, {}); +} + void WDPService::Start() { + credential_manager_ = std::make_unique( + profile_prefs_, shared_url_loader_factory_.get(), + &last_loaded_server_config_, + base::BindRepeating(&WDPService::OnCredentialsLoaded, + base::Unretained(this))); server_config_loader_ = std::make_unique( shared_url_loader_factory_.get(), base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this))); @@ -37,6 +54,8 @@ void WDPService::Start() { void WDPService::Stop() { server_config_loader_ = nullptr; + credential_manager_ = nullptr; + last_loaded_server_config_ = nullptr; } void WDPService::OnEnabledChange() { @@ -47,6 +66,14 @@ void WDPService::OnEnabledChange() { } } -void WDPService::OnConfigChange(const ServerConfig& config) {} +void WDPService::OnConfigChange(std::unique_ptr config) { + last_loaded_server_config_ = std::move(config); + credential_manager_->JoinGroups(); +} + +void WDPService::OnCredentialsLoaded() { + // TODO(djandries): send queued messages if any, or remove this method + // if not needed +} } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 79e8f179f8cc..3d2feb75c07d 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -9,10 +9,12 @@ #include #include "base/memory/raw_ptr.h" +#include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" +class PrefRegistrySimple; class PrefService; namespace network { @@ -31,13 +33,16 @@ class WDPService : public KeyedService { WDPService(const WDPService&) = delete; WDPService& operator=(const WDPService&) = delete; + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + private: void Start(); void Stop(); void OnEnabledChange(); - void OnConfigChange(const ServerConfig& config); + void OnConfigChange(std::unique_ptr config); + void OnCredentialsLoaded(); raw_ptr profile_prefs_; PrefChangeRegistrar pref_change_registrar_; @@ -45,6 +50,8 @@ class WDPService : public KeyedService { scoped_refptr shared_url_loader_factory_; std::unique_ptr server_config_loader_; + std::unique_ptr last_loaded_server_config_; + std::unique_ptr credential_manager_; }; } // namespace web_discovery From bb9f2aed71ea7a5713eba2b8086482276f3630c0 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Fri, 10 May 2024 21:14:15 -0700 Subject: [PATCH 07/36] Replace Web Discovery webcrypto usages with boringssl, misc bug fixes --- components/web_discovery/browser/BUILD.gn | 5 +- components/web_discovery/browser/DEPS | 1 - .../browser/credential_manager.cc | 138 ++++-------------- .../browser/credential_manager.h | 8 +- components/web_discovery/browser/rsa.cc | 121 +++++++++++++++ components/web_discovery/browser/rsa.h | 37 +++++ .../browser/server_config_loader.cc | 4 +- components/web_discovery/browser/util.cc | 3 +- 8 files changed, 194 insertions(+), 123 deletions(-) create mode 100644 components/web_discovery/browser/rsa.cc create mode 100644 components/web_discovery/browser/rsa.h diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index e468c8afcd34..40e51b0300b5 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -8,6 +8,8 @@ static_library("browser") { "credential_manager.cc", "credential_manager.h", "pref_names.h", + "rsa.cc", + "rsa.h", "server_config_loader.cc", "server_config_loader.h", "util.cc", @@ -22,10 +24,9 @@ static_library("browser") { "//brave/components/constants", "//components/keyed_service/core", "//components/prefs", - "//components/webcrypto", "//net", "//services/network/public/cpp", - "//third_party/blink/public:blink_headers", + "//third_party/boringssl", "//url", ] } diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index de723fd20295..f24c187a1099 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -1,5 +1,4 @@ include_rules = [ "+services/network/public", - "+third_party/blink/public/platform", "+third_party/boringssl/src/include", ] diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 3486ea263c6e..f58268064635 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -17,29 +17,17 @@ #include "brave/components/web_discovery/browser/util.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" -#include "components/webcrypto/algorithm_dispatch.h" -#include "components/webcrypto/blink_key_handle.h" -#include "components/webcrypto/generate_key_result.h" -#include "components/webcrypto/status.h" #include "crypto/sha2.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" -#include "third_party/blink/public/platform/web_crypto_algorithm.h" -#include "third_party/blink/public/platform/web_crypto_algorithm_params.h" -#include "third_party/blink/public/platform/web_crypto_key.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/mem.h" -#include "third_party/boringssl/src/include/openssl/rsa.h" namespace web_discovery { namespace { -constexpr size_t kRsaKeySize = 2048; -constexpr unsigned char kRsaPublicExponent[] = {0x01, 0x00, 0x01}; constexpr char kJoinPath[] = "/join"; +constexpr char kJoinContentType[] = "application/json"; constexpr char kJoinDateField[] = "ts"; constexpr char kJoinMessageField[] = "joinMsg"; @@ -50,39 +38,6 @@ constexpr char kJoinResponseField[] = "joinResponse"; constexpr char kGSKDictKey[] = "gsk"; constexpr char kCredentialDictKey[] = "credential"; -blink::WebCryptoAlgorithm GetRSAAlgorithm() { - auto hash = blink::WebCryptoAlgorithm::AdoptParamsAndCreate( - blink::WebCryptoAlgorithmId::kWebCryptoAlgorithmIdSha256, nullptr); - return blink::WebCryptoAlgorithm::AdoptParamsAndCreate( - blink::WebCryptoAlgorithmId::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5, - new blink::WebCryptoRsaHashedKeyGenParams( - hash, kRsaKeySize, - blink::WebVector(kRsaPublicExponent, - sizeof(kRsaPublicExponent)))); -} - -std::optional EncodeRSAPublicKey(const blink::WebCryptoKey& key) { - auto* evp_pkey = webcrypto::GetEVP_PKEY(key); - if (!evp_pkey) { - return std::nullopt; - } - auto* rsa = EVP_PKEY_get0_RSA(evp_pkey); - if (!rsa) { - return std::nullopt; - } - CBB cbb; - uint8_t* out_bytes; - size_t out_len; - if (!CBB_init(&cbb, 0) || !RSA_marshal_public_key(&cbb, rsa) || - !CBB_finish(&cbb, &out_bytes, &out_len)) { - CBB_cleanup(&cbb); - return std::nullopt; - } - auto key_b64 = base::Base64Encode(base::span(out_bytes, out_len)); - OPENSSL_free(out_bytes); - return key_b64; -} - constexpr net::BackoffEntry::Policy kBackoffPolicy = { .num_errors_to_ignore = 0, .initial_delay_ms = 10 * 1000, @@ -125,9 +80,7 @@ CredentialManager::CredentialManager( credentials_loaded_callback_(credentials_loaded_callback), anonymous_credential_manager_( anonymous_credentials::new_credential_manager()) { - join_url_ = - GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, - GetCollectorHost(), kJoinPath})); + join_url_ = GURL(GetCollectorHost() + kJoinPath); } CredentialManager::~CredentialManager() = default; @@ -141,28 +94,10 @@ bool CredentialManager::LoadRSAKey() { return true; } - std::string private_key_data; - - if (!base::Base64Decode(private_key_b64, &private_key_data)) { - VLOG(1) << "Failed to decode base64 of stored RSA keys"; - return false; - } - - auto algo = GetRSAAlgorithm(); - base::span private_key_data_span( - reinterpret_cast(private_key_data.data()), - private_key_data.size()); - - rsa_private_key_ = std::make_unique(); + rsa_private_key_ = ImportRSAKeyPair(private_key_b64); - auto status = webcrypto::ImportKey( - blink::WebCryptoKeyFormat::kWebCryptoKeyFormatPkcs8, - private_key_data_span, algo, true, - blink::WebCryptoKeyUsage::kWebCryptoKeyUsageSign, rsa_private_key_.get()); - - if (status.IsError()) { - VLOG(1) << "RSA private key import failed: " << status.error_details(); - rsa_private_key_ = nullptr; + if (!rsa_private_key_) { + VLOG(1) << "Failed to decode stored RSA key"; return false; } @@ -170,37 +105,18 @@ bool CredentialManager::LoadRSAKey() { } bool CredentialManager::GenerateRSAKey() { - webcrypto::GenerateKeyResult result; - auto algo = GetRSAAlgorithm(); - auto status = webcrypto::GenerateKey( - algo, true, blink::WebCryptoKeyUsage::kWebCryptoKeyUsageSign, &result); - if (status.IsError()) { - VLOG(1) << "RSA key generation failed: " << status.error_details(); + auto key_info = GenerateRSAKeyPair(); + if (!key_info) { + VLOG(1) << "RSA key generation failed"; return false; } - rsa_private_key_ = - std::make_unique(result.private_key()); - - std::vector private_key_bytes; - - status = - webcrypto::ExportKey(blink::WebCryptoKeyFormat::kWebCryptoKeyFormatPkcs8, - *rsa_private_key_, &private_key_bytes); - if (status.IsError()) { - VLOG(1) << "RSA key private key export failed: " << status.error_details(); - return false; - } - - auto public_key_b64 = EncodeRSAPublicKey(result.public_key()); - if (!public_key_b64) { - VLOG(1) << "RSA key public key export failed"; - return false; - } + rsa_private_key_ = std::move(key_info->key_pair); + rsa_public_key_b64_ = key_info->public_key_b64; profile_prefs_->SetString(kCredentialRSAPrivateKey, - base::Base64Encode(private_key_bytes)); - profile_prefs_->SetString(kCredentialRSAPublicKey, *public_key_b64); + key_info->private_key_b64); + profile_prefs_->SetString(kCredentialRSAPublicKey, *rsa_public_key_b64_); return true; } @@ -236,8 +152,6 @@ void CredentialManager::JoinGroups() { void CredentialManager::StartJoinGroup(const std::string& date, const std::string& group_pub_key_b64) { - auto algo = GetRSAAlgorithm(); - auto group_pub_key = base::Base64Decode(group_pub_key_b64); if (!group_pub_key) { VLOG(1) << "Failed to decode group public key for " << date; @@ -259,11 +173,9 @@ void CredentialManager::StartJoinGroup(const std::string& date, auto gsk = std::vector(start_join_result.gsk.begin(), start_join_result.gsk.end()); - std::vector signature; - auto status = webcrypto::Sign(algo, *rsa_private_key_, - start_join_result.join_request, &signature); - if (status.IsError()) { - VLOG(1) << "RSA signature failed: " << status.error_details(); + auto signature = RSASign(rsa_private_key_, start_join_result.join_request); + if (!signature) { + VLOG(1) << "RSA signature failed"; return; } @@ -273,7 +185,7 @@ void CredentialManager::StartJoinGroup(const std::string& date, body_fields.Set(kJoinMessageField, base::Base64Encode(start_join_result.join_request)); body_fields.Set(kJoinRSAPublicKeyField, *rsa_public_key_b64_); - body_fields.Set(kJoinRSASignatureField, base::Base64Encode(signature)); + body_fields.Set(kJoinRSASignatureField, *signature); std::string json_body; if (!base::JSONWriter::Write(body_fields, &json_body)) { @@ -282,12 +194,13 @@ void CredentialManager::StartJoinGroup(const std::string& date, } auto resource_request = CreateResourceRequest(join_url_); + resource_request->method = net::HttpRequestHeaders::kPostMethod; join_url_loaders_[date] = network::SimpleURLLoader::Create( std::move(resource_request), kJoinNetworkTrafficAnnotation); auto& url_loader = join_url_loaders_[date]; - url_loader->AttachStringForUpload(json_body); + url_loader->AttachStringForUpload(json_body, kJoinContentType); url_loader->DownloadToString( shared_url_loader_factory_.get(), @@ -302,12 +215,17 @@ void CredentialManager::OnJoinResponse( std::vector gsk, std::optional response_body) { bool result = ProcessJoinResponse(date, group_pub_key, gsk, response_body); + join_url_loaders_.erase(date); + + if (join_url_loaders_.empty()) { + backoff_entry_.InformOfRequest(result); - backoff_entry_.InformOfRequest(result); - if (!result) { - retry_timer_.Start( - FROM_HERE, base::Time::Now() + backoff_entry_.GetTimeUntilRelease(), - base::BindOnce(&CredentialManager::JoinGroups, base::Unretained(this))); + if (!result) { + retry_timer_.Start( + FROM_HERE, base::Time::Now() + backoff_entry_.GetTimeUntilRelease(), + base::BindOnce(&CredentialManager::JoinGroups, + base::Unretained(this))); + } } } diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index 191fa395b3c5..b9c71fc3139f 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -15,15 +15,12 @@ #include "base/memory/raw_ptr.h" #include "base/timer/wall_clock_timer.h" #include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/rsa.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "net/base/backoff_entry.h" class PrefService; -namespace blink { -class WebCryptoKey; -} // namespace blink - namespace network { class SharedURLLoaderFactory; class SimpleURLLoader; @@ -49,7 +46,6 @@ class CredentialManager { const std::vector& basename); private: - // TODO(djandries): maybe split this into sign_encrypt.h bool LoadRSAKey(); bool GenerateRSAKey(); @@ -80,7 +76,7 @@ class CredentialManager { rust::Box anonymous_credential_manager_; - std::unique_ptr rsa_private_key_; + EVPKey rsa_private_key_; std::optional rsa_public_key_b64_; std::optional loaded_credential_date_; diff --git a/components/web_discovery/browser/rsa.cc b/components/web_discovery/browser/rsa.cc new file mode 100644 index 000000000000..7a569e62ff5d --- /dev/null +++ b/components/web_discovery/browser/rsa.cc @@ -0,0 +1,121 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/rsa.h" + +#include + +#include "base/base64.h" +#include "third_party/boringssl/src/include/openssl/bn.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "third_party/boringssl/src/include/openssl/rsa.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kRsaKeySize = 2048; + +} // namespace + +RSAKeyInfo::RSAKeyInfo() = default; +RSAKeyInfo::~RSAKeyInfo() = default; + +std::unique_ptr GenerateRSAKeyPair() { + bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr)); + BIGNUM* bn = BN_new(); + if (!ctx || !bn || !BN_set_word(bn, RSA_F4)) { + return nullptr; + } + + if (!EVP_PKEY_keygen_init(ctx.get()) || + !EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx.get(), bn) || + !EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), kRsaKeySize)) { + return nullptr; + } + + auto info = std::make_unique(); + + EVP_PKEY* private_key = nullptr; + if (!EVP_PKEY_keygen(ctx.get(), &private_key)) { + return nullptr; + } + + info->key_pair = bssl::UniquePtr(private_key); + + CBB pub_cbb; + uint8_t* pub_der; + size_t pub_der_len; + if (!CBB_init(&pub_cbb, 0) || + !EVP_marshal_public_key(&pub_cbb, private_key) || + !CBB_finish(&pub_cbb, &pub_der, &pub_der_len)) { + CBB_cleanup(&pub_cbb); + return nullptr; + } + + info->public_key_b64 = base::Base64Encode( + base::span(static_cast(pub_der), pub_der_len)); + OPENSSL_free(pub_der); + + CBB priv_cbb; + uint8_t* priv_der; + size_t priv_der_len; + if (!CBB_init(&priv_cbb, 0) || + !EVP_marshal_private_key(&priv_cbb, private_key) || + !CBB_finish(&priv_cbb, &priv_der, &priv_der_len)) { + CBB_cleanup(&priv_cbb); + return nullptr; + } + + info->private_key_b64 = base::Base64Encode( + base::span(static_cast(priv_der), priv_der_len)); + OPENSSL_free(priv_der); + + return info; +} + +EVPKey ImportRSAKeyPair(const std::string& private_key_b64) { + std::string decoded_key; + if (!base::Base64Decode(private_key_b64, &decoded_key)) { + return nullptr; + } + + const unsigned char* pkey_data = + reinterpret_cast(decoded_key.data()); + return EVPKey( + d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &pkey_data, decoded_key.length())); +} + +std::optional RSASign(const EVPKey& key, + base::span message) { + CHECK(key); + bssl::ScopedEVP_MD_CTX ctx; + + if (!EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, + key.get())) { + return std::nullopt; + } + + size_t sig_len; + // Write max size of signature to sig_len + if (!EVP_DigestSign(ctx.get(), nullptr, &sig_len, message.data(), + message.size())) { + return std::nullopt; + } + + std::vector sig(sig_len); + // Write actual signature to sig + if (!EVP_DigestSign(ctx.get(), sig.data(), &sig_len, message.data(), + message.size())) { + return std::nullopt; + } + + // Truncate signature to actual sig_len + sig.resize(sig_len); + return base::Base64Encode(sig); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/rsa.h b/components/web_discovery/browser/rsa.h new file mode 100644 index 000000000000..87d44ec5f30d --- /dev/null +++ b/components/web_discovery/browser/rsa.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_RSA_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_RSA_H_ + +#include +#include +#include + +#include "base/containers/span.h" +#include "third_party/boringssl/src/include/openssl/evp.h" + +namespace web_discovery { + +using EVPKey = bssl::UniquePtr; + +struct RSAKeyInfo { + RSAKeyInfo(); + ~RSAKeyInfo(); + EVPKey key_pair; + std::string private_key_b64; + std::string public_key_b64; +}; + +std::unique_ptr GenerateRSAKeyPair(); + +EVPKey ImportRSAKeyPair(const std::string& private_key_b64); + +std::optional RSASign(const EVPKey& key, + base::span message); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_RSA_H_ diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index a7d14a388197..f13a00637745 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -86,9 +86,7 @@ ServerConfigLoader::ServerConfigLoader( : shared_url_loader_factory_(shared_url_loader_factory), config_callback_(config_callback), backoff_entry_(&kBackoffPolicy) { - config_url_ = - GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, - GetCollectorHost(), kConfigPathWithFields})); + config_url_ = GURL(GetCollectorHost() + kConfigPathWithFields); } ServerConfigLoader::~ServerConfigLoader() = default; diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 1c11529a96ed..95636d5dddcb 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -20,7 +20,8 @@ std::string GetCollectorHost() { if (cmd_line->HasSwitch(kCollectorHostSwitch)) { return cmd_line->GetSwitchValueASCII(kCollectorHostSwitch); } - return brave_domains::GetServicesDomain(kCollectorHostPrefix); + return base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, + brave_domains::GetServicesDomain(kCollectorHostPrefix)}); } std::unique_ptr CreateResourceRequest(GURL url) { From dca6a55647d9b508dba7682f35bf08c74ad297f9 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 16 May 2024 16:12:37 -0700 Subject: [PATCH 08/36] Execute WDP credential crypto operations on thread pool --- .../browser/credential_manager.cc | 197 ++++++++++++------ .../browser/credential_manager.h | 43 ++-- components/web_discovery/browser/rsa.cc | 6 +- components/web_discovery/browser/rsa.h | 8 +- .../web_discovery/browser/wdp_service.cc | 9 +- .../web_discovery/browser/wdp_service.h | 1 - 6 files changed, 174 insertions(+), 90 deletions(-) diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index f58268064635..387cceb85a1e 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -12,6 +12,8 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" #include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/util.h" @@ -66,21 +68,64 @@ constexpr net::NetworkTrafficAnnotationTag kJoinNetworkTrafficAnnotation = "Users can opt-in or out via brave://settings/search" })"); +std::optional GenerateJoinRequest( + anonymous_credentials::CredentialManager* anonymous_credential_manager, + EVPKeyPtr* rsa_private_key, + std::string pre_challenge) { + base::span pre_challenge_span( + reinterpret_cast(pre_challenge.data()), pre_challenge.size()); + auto challenge = crypto::SHA256Hash(pre_challenge_span); + + auto join_request = anonymous_credential_manager->start_join( + rust::Slice(challenge.data(), challenge.size())); + + auto signature = RSASign(*rsa_private_key, join_request.join_request); + + if (!signature) { + VLOG(1) << "RSA signature failed"; + return std::nullopt; + } + + return GenerateJoinRequestResult{.start_join_result = join_request, + .signature = *signature}; +} + +std::optional FinishJoin( + anonymous_credentials::CredentialManager* anonymous_credential_manager, + std::string date, + std::vector group_pub_key, + std::vector gsk, + std::vector join_resp_bytes) { + auto finish_res = anonymous_credential_manager->finish_join( + rust::Slice(group_pub_key.data(), group_pub_key.size()), + rust::Slice(gsk.data(), gsk.size()), + rust::Slice(join_resp_bytes.data(), join_resp_bytes.size())); + if (!finish_res.error_message.empty()) { + VLOG(1) << "Failed to finish credential join for " << date << ": " + << finish_res.error_message.c_str(); + return std::nullopt; + } + return base::Base64Encode(finish_res.data); +} + } // namespace CredentialManager::CredentialManager( PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - std::unique_ptr* last_loaded_server_config, - base::RepeatingClosure credentials_loaded_callback) + std::unique_ptr* last_loaded_server_config) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), last_loaded_server_config_(last_loaded_server_config), + join_url_(GetCollectorHost() + kJoinPath), backoff_entry_(&kBackoffPolicy), - credentials_loaded_callback_(credentials_loaded_callback), + pool_sequenced_task_runner_( + base::ThreadPool::CreateSequencedTaskRunner({})), anonymous_credential_manager_( - anonymous_credentials::new_credential_manager()) { - join_url_ = GURL(GetCollectorHost() + kJoinPath); + new rust::Box(anonymous_credentials::new_credential_manager()), + base::OnTaskRunnerDeleter(pool_sequenced_task_runner_)), + rsa_private_key_(new EVPKeyPtr(), + base::OnTaskRunnerDeleter(pool_sequenced_task_runner_)) { } CredentialManager::~CredentialManager() = default; @@ -90,11 +135,12 @@ bool CredentialManager::LoadRSAKey() { profile_prefs_->GetString(kCredentialRSAPrivateKey); rsa_public_key_b64_ = profile_prefs_->GetString(kCredentialRSAPublicKey); - if (private_key_b64.empty() || !rsa_public_key_b64_) { + if (private_key_b64.empty() || !rsa_public_key_b64_->empty()) { + rsa_public_key_b64_ = std::nullopt; return true; } - rsa_private_key_ = ImportRSAKeyPair(private_key_b64); + *rsa_private_key_ = ImportRSAKeyPair(private_key_b64); if (!rsa_private_key_) { VLOG(1) << "Failed to decode stored RSA key"; @@ -104,21 +150,20 @@ bool CredentialManager::LoadRSAKey() { return true; } -bool CredentialManager::GenerateRSAKey() { - auto key_info = GenerateRSAKeyPair(); +void CredentialManager::OnNewRSAKey(std::unique_ptr key_info) { if (!key_info) { VLOG(1) << "RSA key generation failed"; - return false; + return; } - rsa_private_key_ = std::move(key_info->key_pair); + *rsa_private_key_ = std::move(key_info->key_pair); rsa_public_key_b64_ = key_info->public_key_b64; profile_prefs_->SetString(kCredentialRSAPrivateKey, key_info->private_key_b64); profile_prefs_->SetString(kCredentialRSAPublicKey, *rsa_public_key_b64_); - return true; + JoinGroups(); } void CredentialManager::JoinGroups() { @@ -135,14 +180,16 @@ void CredentialManager::JoinGroups() { continue; } - if (rsa_private_key_ == nullptr) { + if (*rsa_private_key_ == nullptr) { if (!LoadRSAKey()) { return; } - if (rsa_private_key_ == nullptr) { - if (!GenerateRSAKey()) { - return; - } + if (*rsa_private_key_ == nullptr) { + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&GenerateRSAKeyPair), + base::BindOnce(&CredentialManager::OnNewRSAKey, + weak_ptr_factory_.GetWeakPtr())); + return; } } @@ -157,6 +204,8 @@ void CredentialManager::StartJoinGroup(const std::string& date, VLOG(1) << "Failed to decode group public key for " << date; return; } + std::vector group_pub_key_const(group_pub_key->begin(), + group_pub_key->end()); auto challenge_elements = base::Value::List::with_capacity(2); challenge_elements.Append(*rsa_public_key_b64_); @@ -164,28 +213,31 @@ void CredentialManager::StartJoinGroup(const std::string& date, std::string pre_challenge; base::JSONWriter::Write(challenge_elements, &pre_challenge); - base::span pre_challenge_span( - reinterpret_cast(pre_challenge.data()), pre_challenge.size()); - auto challenge = crypto::SHA256Hash(pre_challenge_span); - auto start_join_result = anonymous_credential_manager_->start_join( - rust::Slice(challenge.data(), challenge.size())); - auto gsk = std::vector(start_join_result.gsk.begin(), - start_join_result.gsk.end()); + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&GenerateJoinRequest, &**anonymous_credential_manager_, + rsa_private_key_.get(), pre_challenge), + base::BindOnce(&CredentialManager::OnJoinRequestReady, + weak_ptr_factory_.GetWeakPtr(), date, + group_pub_key_const)); +} - auto signature = RSASign(rsa_private_key_, start_join_result.join_request); - if (!signature) { - VLOG(1) << "RSA signature failed"; +void CredentialManager::OnJoinRequestReady( + std::string date, + std::vector group_pub_key, + std::optional generate_join_result) { + if (!generate_join_result) { return; } - base::Value::Dict body_fields; body_fields.Set(kJoinDateField, date); - body_fields.Set(kJoinMessageField, - base::Base64Encode(start_join_result.join_request)); + body_fields.Set( + kJoinMessageField, + base::Base64Encode(generate_join_result->start_join_result.join_request)); body_fields.Set(kJoinRSAPublicKeyField, *rsa_public_key_b64_); - body_fields.Set(kJoinRSASignatureField, *signature); + body_fields.Set(kJoinRSASignatureField, generate_join_result->signature); std::string json_body; if (!base::JSONWriter::Write(body_fields, &json_body)) { @@ -193,6 +245,10 @@ void CredentialManager::StartJoinGroup(const std::string& date, return; } + auto gsk = std::vector( + generate_join_result->start_join_result.gsk.begin(), + generate_join_result->start_join_result.gsk.end()); + auto resource_request = CreateResourceRequest(join_url_); resource_request->method = net::HttpRequestHeaders::kPostMethod; @@ -205,18 +261,26 @@ void CredentialManager::StartJoinGroup(const std::string& date, url_loader->DownloadToString( shared_url_loader_factory_.get(), base::BindOnce(&CredentialManager::OnJoinResponse, base::Unretained(this), - date, *group_pub_key, gsk), + date, group_pub_key, gsk), kMaxResponseSize); } void CredentialManager::OnJoinResponse( std::string date, - std::vector group_pub_key, - std::vector gsk, + std::vector group_pub_key, + std::vector gsk, std::optional response_body) { bool result = ProcessJoinResponse(date, group_pub_key, gsk, response_body); - join_url_loaders_.erase(date); + if (!result) { + HandleJoinResponseStatus(date, result); + } +} +void CredentialManager::HandleJoinResponseStatus(const std::string& date, + bool result) { + join_url_loaders_.erase(date); + // TODO(djandries): what if the last request succeeds and the other requests + // fail? fix if (join_url_loaders_.empty()) { backoff_entry_.InformOfRequest(result); @@ -231,8 +295,8 @@ void CredentialManager::OnJoinResponse( bool CredentialManager::ProcessJoinResponse( const std::string& date, - const std::vector& group_pub_key, - const std::vector& gsk, + const std::vector& group_pub_key, + const std::vector& gsk, const std::optional& response_body) { CHECK(join_url_loaders_[date]); auto& url_loader = join_url_loaders_[date]; @@ -268,29 +332,37 @@ bool CredentialManager::ProcessJoinResponse( VLOG(1) << "Failed to decode join response base64"; return false; } + std::vector join_resp_bytes_const(join_resp_bytes->begin(), + join_resp_bytes->end()); + + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&FinishJoin, &**anonymous_credential_manager_, date, + group_pub_key, gsk, join_resp_bytes_const), + base::BindOnce(&CredentialManager::OnCredentialsReady, + weak_ptr_factory_.GetWeakPtr(), date, gsk)); + return true; +} - auto finish_res = anonymous_credential_manager_->finish_join( - rust::Slice(group_pub_key.data(), group_pub_key.size()), - rust::Slice(gsk.data(), gsk.size()), - rust::Slice(reinterpret_cast(join_resp_bytes->data()), - join_resp_bytes->size())); - if (!finish_res.error_message.empty()) { - VLOG(1) << "Failed to finish credential join for " << date << ": " - << finish_res.error_message.c_str(); - return false; +void CredentialManager::OnCredentialsReady( + std::string date, + std::vector gsk, + std::optional credentials) { + if (!credentials) { + HandleJoinResponseStatus(date, false); + return; } - ScopedDictPrefUpdate update(profile_prefs_, kAnonymousCredentialsDict); auto* date_dict = update->EnsureDict(date); date_dict->Set(kGSKDictKey, base::Base64Encode(gsk)); - date_dict->Set(kCredentialDictKey, base::Base64Encode(finish_res.data)); - - return true; + date_dict->Set(kCredentialDictKey, *credentials); + HandleJoinResponseStatus(date, true); } -std::optional> CredentialManager::Sign( - const std::vector& msg, - const std::vector& basename) { +std::optional> CredentialManager::Sign( + const std::vector& msg, + const std::vector& basename) { + // TODO(djandries): execute on thread pool auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); const auto& anon_creds_dict = profile_prefs_->GetDict(kAnonymousCredentialsDict); @@ -312,10 +384,13 @@ std::optional> CredentialManager::Sign( VLOG(1) << "Failed to sign due to bad gsk/credential base64"; return std::nullopt; } - auto set_res = anonymous_credential_manager_->set_gsk_and_credentials( - rust::Slice(reinterpret_cast(gsk_bytes->data()), - gsk_bytes->size()), - rust::Slice(reinterpret_cast(credential_bytes->data()), + auto set_res = + (*anonymous_credential_manager_) + ->set_gsk_and_credentials( + rust::Slice(reinterpret_cast(gsk_bytes->data()), + gsk_bytes->size()), + rust::Slice( + reinterpret_cast(credential_bytes->data()), credential_bytes->size())); if (!set_res.error_message.empty()) { VLOG(1) << "Failed to sign due to credential set failure: " @@ -324,14 +399,14 @@ std::optional> CredentialManager::Sign( } loaded_credential_date_ = today_date; } - auto sig_res = anonymous_credential_manager_->sign( - rust::Slice(msg.data(), msg.size()), - rust::Slice(basename.data(), basename.size())); + auto sig_res = (*anonymous_credential_manager_) + ->sign(rust::Slice(msg.data(), msg.size()), + rust::Slice(basename.data(), basename.size())); if (!sig_res.error_message.empty()) { VLOG(1) << "Failed to sign: " << sig_res.error_message.c_str(); return std::nullopt; } - return std::vector(sig_res.data.begin(), sig_res.data.end()); + return std::vector(sig_res.data.begin(), sig_res.data.end()); } } // namespace web_discovery diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index b9c71fc3139f..3ff7ad35b0ec 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -11,8 +11,8 @@ #include #include -#include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "base/task/sequenced_task_runner.h" #include "base/timer/wall_clock_timer.h" #include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" #include "brave/components/web_discovery/browser/rsa.h" @@ -28,12 +28,16 @@ class SimpleURLLoader; namespace web_discovery { +struct GenerateJoinRequestResult { + anonymous_credentials::StartJoinResult start_join_result; + std::string signature; +}; + class CredentialManager { public: CredentialManager(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - std::unique_ptr* last_loaded_server_config, - base::RepeatingClosure credentials_loaded_callback); + std::unique_ptr* last_loaded_server_config); ~CredentialManager(); CredentialManager(const CredentialManager&) = delete; @@ -41,25 +45,35 @@ class CredentialManager { void JoinGroups(); - std::optional> Sign( - const std::vector& msg, - const std::vector& basename); + std::optional> Sign( + const std::vector& msg, + const std::vector& basename); private: bool LoadRSAKey(); bool GenerateRSAKey(); + void OnNewRSAKey(std::unique_ptr key_info); void StartJoinGroup(const std::string& date, const std::string& group_pub_key_b64); + void OnJoinRequestReady( + std::string date, + std::vector group_pub_key, + std::optional generate_join_result); + void OnJoinResponse(std::string date, - std::vector group_pub_key, - std::vector gsk, + std::vector group_pub_key, + std::vector gsk, std::optional response_body); + void HandleJoinResponseStatus(const std::string& date, bool result); bool ProcessJoinResponse(const std::string& date, - const std::vector& group_pub_key, - const std::vector& gsk, + const std::vector& group_pub_key, + const std::vector& gsk, const std::optional& response_body); + void OnCredentialsReady(std::string date, + std::vector gsk, + std::optional credentials); raw_ptr profile_prefs_; raw_ptr shared_url_loader_factory_; @@ -71,15 +85,18 @@ class CredentialManager { net::BackoffEntry backoff_entry_; base::WallClockTimer retry_timer_; - base::RepeatingClosure credentials_loaded_callback_; + scoped_refptr pool_sequenced_task_runner_; - rust::Box + std::unique_ptr, + base::OnTaskRunnerDeleter> anonymous_credential_manager_; - EVPKey rsa_private_key_; + std::unique_ptr rsa_private_key_; std::optional rsa_public_key_b64_; std::optional loaded_credential_date_; + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace web_discovery diff --git a/components/web_discovery/browser/rsa.cc b/components/web_discovery/browser/rsa.cc index 7a569e62ff5d..73f8be74ff57 100644 --- a/components/web_discovery/browser/rsa.cc +++ b/components/web_discovery/browser/rsa.cc @@ -77,7 +77,7 @@ std::unique_ptr GenerateRSAKeyPair() { return info; } -EVPKey ImportRSAKeyPair(const std::string& private_key_b64) { +EVPKeyPtr ImportRSAKeyPair(const std::string& private_key_b64) { std::string decoded_key; if (!base::Base64Decode(private_key_b64, &decoded_key)) { return nullptr; @@ -85,11 +85,11 @@ EVPKey ImportRSAKeyPair(const std::string& private_key_b64) { const unsigned char* pkey_data = reinterpret_cast(decoded_key.data()); - return EVPKey( + return EVPKeyPtr( d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &pkey_data, decoded_key.length())); } -std::optional RSASign(const EVPKey& key, +std::optional RSASign(const EVPKeyPtr& key, base::span message) { CHECK(key); bssl::ScopedEVP_MD_CTX ctx; diff --git a/components/web_discovery/browser/rsa.h b/components/web_discovery/browser/rsa.h index 87d44ec5f30d..9a261b91273c 100644 --- a/components/web_discovery/browser/rsa.h +++ b/components/web_discovery/browser/rsa.h @@ -15,21 +15,21 @@ namespace web_discovery { -using EVPKey = bssl::UniquePtr; +using EVPKeyPtr = bssl::UniquePtr; struct RSAKeyInfo { RSAKeyInfo(); ~RSAKeyInfo(); - EVPKey key_pair; + EVPKeyPtr key_pair; std::string private_key_b64; std::string public_key_b64; }; std::unique_ptr GenerateRSAKeyPair(); -EVPKey ImportRSAKeyPair(const std::string& private_key_b64); +EVPKeyPtr ImportRSAKeyPair(const std::string& private_key_b64); -std::optional RSASign(const EVPKey& key, +std::optional RSASign(const EVPKeyPtr& key, base::span message); } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 7521c4a93801..8923d4e22d53 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -43,9 +43,7 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { void WDPService::Start() { credential_manager_ = std::make_unique( profile_prefs_, shared_url_loader_factory_.get(), - &last_loaded_server_config_, - base::BindRepeating(&WDPService::OnCredentialsLoaded, - base::Unretained(this))); + &last_loaded_server_config_); server_config_loader_ = std::make_unique( shared_url_loader_factory_.get(), base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this))); @@ -71,9 +69,4 @@ void WDPService::OnConfigChange(std::unique_ptr config) { credential_manager_->JoinGroups(); } -void WDPService::OnCredentialsLoaded() { - // TODO(djandries): send queued messages if any, or remove this method - // if not needed -} - } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 3d2feb75c07d..f664efbd7a4b 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -42,7 +42,6 @@ class WDPService : public KeyedService { void OnEnabledChange(); void OnConfigChange(std::unique_ptr config); - void OnCredentialsLoaded(); raw_ptr profile_prefs_; PrefChangeRegistrar pref_change_registrar_; From d9be342ad9e8a0d7e4aca141f268d9249e4ccb5b Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 23 May 2024 16:48:19 -0700 Subject: [PATCH 09/36] Fetch, store and parse web discovery patterns --- browser/brave_local_state_prefs.cc | 2 + browser/web_discovery/BUILD.gn | 2 + browser/web_discovery/wdp_service_factory.cc | 8 +- components/web_discovery/browser/BUILD.gn | 3 + components/web_discovery/browser/DEPS | 1 + components/web_discovery/browser/patterns.cc | 180 ++++++++++++++++ components/web_discovery/browser/patterns.h | 65 ++++++ components/web_discovery/browser/pref_names.h | 3 + .../browser/server_config_loader.cc | 195 ++++++++++++++++-- .../browser/server_config_loader.h | 40 +++- components/web_discovery/browser/util.cc | 8 + components/web_discovery/browser/util.h | 1 + .../web_discovery/browser/wdp_service.cc | 20 +- .../web_discovery/browser/wdp_service.h | 10 + 14 files changed, 518 insertions(+), 20 deletions(-) create mode 100644 components/web_discovery/browser/patterns.cc create mode 100644 components/web_discovery/browser/patterns.h diff --git a/browser/brave_local_state_prefs.cc b/browser/brave_local_state_prefs.cc index eab1e74657db..04c3db8a51a9 100644 --- a/browser/brave_local_state_prefs.cc +++ b/browser/brave_local_state_prefs.cc @@ -38,6 +38,7 @@ #include "brave/components/p3a/star_randomness_meta.h" #include "brave/components/skus/browser/skus_utils.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/browser/wdp_service.h" #include "build/build_config.h" #include "chrome/common/pref_names.h" #include "components/metrics/metrics_pref_names.h" @@ -169,6 +170,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry) { misc_metrics::GeneralBrowserUsage::RegisterPrefs(registry); playlist::PlaylistServiceFactory::RegisterLocalStatePrefs(registry); + web_discovery::WDPService::RegisterLocalStatePrefs(registry); } } // namespace brave diff --git a/browser/web_discovery/BUILD.gn b/browser/web_discovery/BUILD.gn index 2475bf5924de..3687366894a5 100644 --- a/browser/web_discovery/BUILD.gn +++ b/browser/web_discovery/BUILD.gn @@ -13,6 +13,8 @@ source_set("web_discovery") { deps = [ "//base", "//brave/components/web_discovery/browser", + "//chrome/browser:browser_process", + "//chrome/common:constants", "//components/keyed_service/content", "//components/user_prefs", "//content/public/browser", diff --git a/browser/web_discovery/wdp_service_factory.cc b/browser/web_discovery/wdp_service_factory.cc index 9e883ecbc7c3..80fed85109ee 100644 --- a/browser/web_discovery/wdp_service_factory.cc +++ b/browser/web_discovery/wdp_service_factory.cc @@ -5,7 +5,10 @@ #include "brave/browser/web_discovery/wdp_service_factory.h" +#include "base/path_service.h" #include "brave/components/web_discovery/browser/wdp_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/chrome_paths.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" @@ -30,7 +33,10 @@ KeyedService* WDPServiceFactory::BuildServiceInstanceFor( auto* default_storage_partition = context->GetDefaultStoragePartition(); auto shared_url_loader_factory = default_storage_partition->GetURLLoaderFactoryForBrowserProcess(); - return new WDPService(user_prefs::UserPrefs::Get(context), + base::FilePath user_data_dir; + CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); + return new WDPService(g_browser_process->local_state(), + user_prefs::UserPrefs::Get(context), user_data_dir, shared_url_loader_factory); } diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 40e51b0300b5..c046beecb786 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -7,6 +7,8 @@ static_library("browser") { sources = [ "credential_manager.cc", "credential_manager.h", + "patterns.cc", + "patterns.h", "pref_names.h", "rsa.cc", "rsa.h", @@ -27,6 +29,7 @@ static_library("browser") { "//net", "//services/network/public/cpp", "//third_party/boringssl", + "//third_party/zlib/google:compression_utils", "//url", ] } diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index f24c187a1099..5bba53b6abdd 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -1,4 +1,5 @@ include_rules = [ "+services/network/public", "+third_party/boringssl/src/include", + "+third_party/zlib/google", ] diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc new file mode 100644 index 000000000000..1ac04e1ee597 --- /dev/null +++ b/components/web_discovery/browser/patterns.cc @@ -0,0 +1,180 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/patterns.h" + +#include + +#include "base/containers/fixed_flat_map.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" + +namespace web_discovery { + +namespace { + +constexpr char kNormalPatternsKey[] = "normal"; +constexpr char kStrictPatternsKey[] = "strict"; +constexpr char kUrlPatternsKey[] = "urlPatterns"; +constexpr char kSearchEnginesKey[] = "searchEngines"; +constexpr char kIdMappingKey[] = "idMapping"; +constexpr char kScrapeRulesKey[] = "scrape"; +constexpr char kSubSelectorKey[] = "item"; +constexpr char kRuleTypeKey[] = "type"; +constexpr char kAttributeKey[] = "etype"; + +constexpr auto kRuleTypeMap = + base::MakeFixedFlatMap({ + {"standard", ScrapeRuleType::kStandard}, + {"searchQuery", ScrapeRuleType::kSearchQuery}, + {"widgetTitle", ScrapeRuleType::kWidgetTitle}, + }); + +std::optional> ParseScrapeRules( + const base::Value::Dict* scrape_url_dict) { + std::vector result(scrape_url_dict->size()); + + for (const auto [selector, rule_group_value] : *scrape_url_dict) { + auto* rule_group_dict = rule_group_value.GetIfDict(); + if (!rule_group_dict) { + VLOG(1) << "Rule group is not a dict"; + return std::nullopt; + } + auto rule_group_it = result.begin(); + rule_group_it->selector = selector; + rule_group_it->rules = std::vector(rule_group_dict->size()); + + auto rule_it = rule_group_it->rules.begin(); + for (const auto [report_key, rule_value] : *rule_group_dict) { + auto* rule_dict = rule_value.GetIfDict(); + if (!rule_dict) { + VLOG(1) << "Rule details is not a dict"; + return std::nullopt; + } + auto* sub_selector = rule_dict->FindString(kSubSelectorKey); + auto* attribute = rule_dict->FindString(kAttributeKey); + auto* rule_type_str = rule_dict->FindString(kRuleTypeKey); + if (!attribute) { + VLOG(1) << "Attribute missing from rule"; + return std::nullopt; + } + rule_it->rule_type = ScrapeRuleType::kOther; + if (rule_type_str) { + auto rule_type_it = kRuleTypeMap.find(*rule_type_str); + if (rule_type_it != kRuleTypeMap.end()) { + rule_it->rule_type = rule_type_it->second; + } + } + rule_it->attribute = *attribute; + if (sub_selector) { + rule_it->sub_selector = *sub_selector; + } + rule_it = std::next(rule_it); + } + + rule_group_it = std::next(rule_group_it); + } + return result; +} + +std::optional> ParsePatternsURLDetails( + const base::Value::Dict* root_dict) { + auto* url_patterns_list = root_dict->FindList(kUrlPatternsKey); + auto* search_engines_list = root_dict->FindList(kSearchEnginesKey); + auto* scrape_dict = root_dict->FindDict(kScrapeRulesKey); + auto* id_mapping_dict = root_dict->FindDict(kIdMappingKey); + if (!url_patterns_list || !search_engines_list || !scrape_dict || + !id_mapping_dict) { + VLOG(1) + << "Missing URL patterns, search engines, scrape rules or id mapping"; + return std::nullopt; + } + + std::vector result(url_patterns_list->size()); + + for (size_t i = 0; i < url_patterns_list->size(); i++) { + auto* url_regex = (*url_patterns_list)[i].GetIfString(); + if (!url_regex) { + VLOG(1) << "URL pattern is not string"; + return std::nullopt; + } + auto& details = result[i]; + + details.url_regex = *url_regex; + + std::string i_str = base::NumberToString(i); + + auto* id = id_mapping_dict->FindString(i_str); + auto* scrape_url_dict = scrape_dict->FindDict(i_str); + if (!id || !scrape_url_dict) { + VLOG(1) << "ID or scrape dict missing for pattern"; + return std::nullopt; + } + details.id = *id; + + details.is_search_engine = + base::ranges::find(search_engines_list->begin(), + search_engines_list->end(), + i_str) != search_engines_list->end(); + + auto scrape_rule_groups = ParseScrapeRules(scrape_url_dict); + if (!scrape_rule_groups) { + return std::nullopt; + } + details.scrape_rule_groups = std::move(*scrape_rule_groups); + } + + return result; +} + +} // namespace + +ScrapeRule::ScrapeRule() = default; +ScrapeRule::~ScrapeRule() = default; + +ScrapeRuleGroup::ScrapeRuleGroup() = default; +ScrapeRuleGroup::~ScrapeRuleGroup() = default; + +PatternsURLDetails::PatternsURLDetails() = default; +PatternsURLDetails::~PatternsURLDetails() = default; + +PatternsGroup::PatternsGroup() = default; +PatternsGroup::~PatternsGroup() = default; + +std::unique_ptr ParsePatterns(const std::string& patterns_json) { + auto result = std::make_unique(); + auto patterns_value = base::JSONReader::Read(patterns_json); + if (!patterns_value || !patterns_value->is_dict()) { + VLOG(1) << "Patterns is not JSON or is not dict"; + return nullptr; + } + const auto& patterns_dict = patterns_value->GetDict(); + + auto* normal_dict = patterns_dict.FindDict(kNormalPatternsKey); + auto* strict_dict = patterns_dict.FindDict(kStrictPatternsKey); + if (!normal_dict && !strict_dict) { + VLOG(1) << "No normal or strict rules in patterns"; + return nullptr; + } + + if (normal_dict) { + auto details = ParsePatternsURLDetails(normal_dict); + if (!details) { + return nullptr; + } + result->normal_patterns = std::move(*details); + } + if (strict_dict) { + auto details = ParsePatternsURLDetails(strict_dict); + if (!details) { + return nullptr; + } + result->strict_patterns = std::move(*details); + } + return result; +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h new file mode 100644 index 000000000000..f233f212e0e3 --- /dev/null +++ b/components/web_discovery/browser/patterns.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PATTERNS_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PATTERNS_H_ + +#include +#include +#include +#include + +namespace web_discovery { + +enum class ScrapeRuleType { kStandard, kSearchQuery, kWidgetTitle, kOther }; + +struct ScrapeRule { + ScrapeRule(); + ~ScrapeRule(); + + ScrapeRule(const ScrapeRule&) = delete; + + std::string report_key; + std::string selector; + std::optional sub_selector; + ScrapeRuleType rule_type; + std::string attribute; +}; + +struct ScrapeRuleGroup { + ScrapeRuleGroup(); + ~ScrapeRuleGroup(); + + ScrapeRuleGroup(const ScrapeRuleGroup&) = delete; + + std::string selector; + std::vector rules; +}; + +struct PatternsURLDetails { + PatternsURLDetails(); + ~PatternsURLDetails(); + + PatternsURLDetails(const PatternsURLDetails&) = delete; + + std::string url_regex; + bool is_search_engine; + std::string id; + std::vector scrape_rule_groups; +}; + +struct PatternsGroup { + PatternsGroup(); + ~PatternsGroup(); + + std::vector normal_patterns; + std::vector strict_patterns; +}; + +std::unique_ptr ParsePatterns(const std::string& patterns_json); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PATTERNS_H_ diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index c509587844ac..ed196b56ce0c 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -15,6 +15,9 @@ inline constexpr char kCredentialRSAPublicKey[] = inline constexpr char kAnonymousCredentialsDict[] = "brave.web_discovery.anon_creds"; +inline constexpr char kPatternsRetrievalTime[] = + "brave.web_discovery.patterns_retrieval_time"; + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PREF_NAMES_H_ diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index f13a00637745..926771cbb57f 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -9,15 +9,21 @@ #include #include "base/base64.h" +#include "base/files/file_util.h" +#include "base/functional/bind.h" #include "base/json/json_reader.h" #include "base/location.h" #include "base/rand_util.h" +#include "base/task/thread_pool.h" #include "base/values.h" +#include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/util.h" +#include "components/prefs/pref_service.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/zlib/google/compression_utils.h" namespace web_discovery { @@ -35,6 +41,12 @@ constexpr net::BackoffEntry::Policy kBackoffPolicy = { constexpr base::TimeDelta kMinReloadInterval = base::Hours(1); constexpr base::TimeDelta kMaxReloadInterval = base::Hours(4); +constexpr base::TimeDelta kPatternsMaxAge = base::Hours(2); +constexpr base::TimeDelta kPatternsRequestLatestDelay = base::Minutes(3); +constexpr base::TimeDelta kPatternsRequestInitDelay = base::Seconds(15); + +constexpr size_t kPatternsMaxFileSize = 128000; + constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = net::DefineNetworkTrafficAnnotation("wdp_config", R"( semantics { @@ -60,6 +72,7 @@ constexpr char kMinVersionFieldName[] = "minVersion"; constexpr char kConfigPathWithFields[] = "/config?fields=minVersion,groupPubKeys,pubKeys,sourceMap"; +constexpr char kPatternsFilename[] = "wdp_patterns.json"; KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { KeyMap map; @@ -74,6 +87,27 @@ KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { return map; } +std::optional GunzipContents(std::string gzipped_contents) { + std::string result; + if (!compression::GzipUncompress(gzipped_contents, &result)) { + return std::nullopt; + } + return result; +} + +bool WritePatternsFile(base::FilePath patterns_path, std::string contents) { + return base::WriteFile(patterns_path, contents); +} + +std::optional ReadPatternsFile(base::FilePath patterns_path) { + std::string contents; + if (!base::ReadFileToStringWithMaxSize(patterns_path, &contents, + kPatternsMaxFileSize)) { + return std::nullopt; + } + return contents; +} + } // namespace ServerConfig::ServerConfig() = default; @@ -81,12 +115,23 @@ ServerConfig::ServerConfig() = default; ServerConfig::~ServerConfig() = default; ServerConfigLoader::ServerConfigLoader( + PrefService* local_state, + base::FilePath user_data_dir, network::SharedURLLoaderFactory* shared_url_loader_factory, - ConfigCallback config_callback) - : shared_url_loader_factory_(shared_url_loader_factory), + ConfigCallback config_callback, + PatternsCallback patterns_callback) + : local_state_(local_state), + pool_sequenced_task_runner_( + base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), + shared_url_loader_factory_(shared_url_loader_factory), config_callback_(config_callback), - backoff_entry_(&kBackoffPolicy) { + patterns_callback_(patterns_callback), + config_backoff_entry_(&kBackoffPolicy), + patterns_backoff_entry_(&kBackoffPolicy) { config_url_ = GURL(GetCollectorHost() + kConfigPathWithFields); + patterns_url_ = GetPatternsEndpoint(); + + patterns_path_ = user_data_dir.Append(kPatternsFilename); } ServerConfigLoader::~ServerConfigLoader() = default; @@ -96,16 +141,16 @@ void ServerConfigLoader::Load() { // but consider how join retries will work before you do. we might want to // generate gsk beforehand... in which case it might make sense to add a // repeating callback for generating state + network requests - if (url_loader_) { + if (config_url_loader_) { // Another request is in progress return; } auto resource_request = CreateResourceRequest(config_url_); - url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), - kNetworkTrafficAnnotation); + config_url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), kNetworkTrafficAnnotation); - url_loader_->DownloadToString( + config_url_loader_->DownloadToString( shared_url_loader_factory_.get(), base::BindOnce(&ServerConfigLoader::OnConfigResponse, base::Unretained(this)), @@ -115,24 +160,26 @@ void ServerConfigLoader::Load() { void ServerConfigLoader::OnConfigResponse( std::optional response_body) { base::Time update_time = base::Time::Now(); - bool result = !ProcessConfigResponse(response_body); + bool result = ProcessConfigResponse(response_body); - backoff_entry_.InformOfRequest(response_body.has_value()); + config_backoff_entry_.InformOfRequest(result); if (!result) { - update_time += backoff_entry_.GetTimeUntilRelease(); + update_time += config_backoff_entry_.GetTimeUntilRelease(); } else { update_time += base::RandTimeDelta(kMinReloadInterval, kMaxReloadInterval); + + SchedulePatternsRequest(); } - update_timer_.Start( + config_update_timer_.Start( FROM_HERE, update_time, base::BindOnce(&ServerConfigLoader::Load, base::Unretained(this))); } bool ServerConfigLoader::ProcessConfigResponse( const std::optional& response_body) { - auto* response_info = url_loader_->ResponseInfo(); + auto* response_info = config_url_loader_->ResponseInfo(); if (!response_body || !response_info || response_info->headers->response_code() != 200) { VLOG(1) << "Failed to fetch server config"; @@ -179,4 +226,128 @@ bool ServerConfigLoader::ProcessConfigResponse( return true; } +void ServerConfigLoader::LoadStoredPatterns() { + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&ReadPatternsFile, patterns_path_), + base::BindOnce(&ServerConfigLoader::OnPatternsFileLoaded, + weak_ptr_factory_.GetWeakPtr())); +} + +void ServerConfigLoader::OnPatternsFileLoaded( + std::optional patterns_json) { + if (!patterns_json) { + VLOG(1) << "Failed to load local patterns file"; + local_state_->ClearPref(kPatternsRetrievalTime); + SchedulePatternsRequest(); + return; + } + auto parsed_patterns = ParsePatterns(*patterns_json); + if (!parsed_patterns) { + local_state_->ClearPref(kPatternsRetrievalTime); + SchedulePatternsRequest(); + return; + } + patterns_callback_.Run(std::move(parsed_patterns)); +} + +void ServerConfigLoader::SchedulePatternsRequest() { + base::Time update_time = base::Time::Now(); + base::TimeDelta time_since_last_retrieval = + base::Time::Now() - local_state_->GetTime(kPatternsRetrievalTime); + if (time_since_last_retrieval >= kPatternsMaxAge) { + update_time += kPatternsRequestInitDelay; + } else { + if (!patterns_first_request_made_) { + LoadStoredPatterns(); + } + update_time += kPatternsMaxAge - time_since_last_retrieval + + base::RandTimeDelta({}, kPatternsRequestLatestDelay); + } + patterns_first_request_made_ = true; + patterns_update_timer_.Start( + FROM_HERE, update_time, + base::BindOnce(&ServerConfigLoader::RequestPatterns, + base::Unretained(this))); +} + +void ServerConfigLoader::RequestPatterns() { + if (patterns_url_loader_) { + return; + } + auto resource_request = CreateResourceRequest(patterns_url_); + + patterns_url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), kNetworkTrafficAnnotation); + + patterns_url_loader_->DownloadToString( + shared_url_loader_factory_.get(), + base::BindOnce(&ServerConfigLoader::OnPatternsResponse, + base::Unretained(this)), + kMaxResponseSize); +} + +void ServerConfigLoader::HandlePatternsStatus(bool result) { + patterns_url_loader_ = nullptr; + patterns_backoff_entry_.InformOfRequest(result); + + if (result) { + SchedulePatternsRequest(); + return; + } + + patterns_update_timer_.Start( + FROM_HERE, + base::Time::Now() + patterns_backoff_entry_.GetTimeUntilRelease(), + base::BindOnce(&ServerConfigLoader::RequestPatterns, + base::Unretained(this))); +} + +void ServerConfigLoader::OnPatternsResponse( + std::optional response_body) { + auto* response_info = config_url_loader_->ResponseInfo(); + if (!response_body || !response_info || + response_info->headers->response_code() != 200) { + VLOG(1) << "Failed to retrieve patterns file"; + HandlePatternsStatus(false); + return; + } + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&GunzipContents, *response_body), + base::BindOnce(&ServerConfigLoader::OnPatternsGunzip, + weak_ptr_factory_.GetWeakPtr())); +} + +void ServerConfigLoader::OnPatternsGunzip( + std::optional patterns_json) { + if (!patterns_json) { + VLOG(1) << "Failed to decompress patterns file"; + HandlePatternsStatus(false); + return; + } + auto parsed_patterns = ParsePatterns(*patterns_json); + if (!parsed_patterns) { + HandlePatternsStatus(false); + return; + } + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&WritePatternsFile, patterns_path_, *patterns_json), + base::BindOnce(&ServerConfigLoader::OnPatternsWritten, + weak_ptr_factory_.GetWeakPtr(), + std::move(parsed_patterns))); +} + +void ServerConfigLoader::OnPatternsWritten( + std::unique_ptr parsed_group, + bool result) { + if (!result) { + VLOG(1) << "Failed to write patterns file"; + HandlePatternsStatus(false); + return; + } + local_state_->SetTime(kPatternsRetrievalTime, base::Time::Now()); + HandlePatternsStatus(true); + patterns_callback_.Run(std::move(parsed_group)); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 4697b9b1bf95..7c41bae0c36b 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -11,11 +11,15 @@ #include #include "base/containers/flat_map.h" +#include "base/files/file_path.h" #include "base/memory/raw_ptr.h" #include "base/timer/wall_clock_timer.h" +#include "brave/components/web_discovery/browser/patterns.h" #include "net/base/backoff_entry.h" #include "url/gurl.h" +class PrefService; + namespace network { class SharedURLLoaderFactory; class SimpleURLLoader; @@ -37,10 +41,15 @@ class ServerConfigLoader { public: using ConfigCallback = base::RepeatingCallback)>; + using PatternsCallback = + base::RepeatingCallback)>; explicit ServerConfigLoader( + PrefService* local_state, + base::FilePath user_data_dir, network::SharedURLLoaderFactory* shared_url_loader_factory, - ConfigCallback config_callback); + ConfigCallback config_callback, + PatternsCallback patterns_callback); ~ServerConfigLoader(); ServerConfigLoader(const ServerConfigLoader&) = delete; @@ -52,15 +61,38 @@ class ServerConfigLoader { void OnConfigResponse(std::optional response_body); bool ProcessConfigResponse(const std::optional& response_body); + void LoadStoredPatterns(); + void OnPatternsFileLoaded(std::optional patterns_json); + void SchedulePatternsRequest(); + void RequestPatterns(); + void OnPatternsResponse(std::optional response_body); + void OnPatternsGunzip(std::optional patterns_json); + void OnPatternsWritten(std::unique_ptr parsed_group, + bool result); + void HandlePatternsStatus(bool result); + + raw_ptr local_state_; + + scoped_refptr pool_sequenced_task_runner_; + GURL config_url_; + GURL patterns_url_; + base::FilePath patterns_path_; raw_ptr shared_url_loader_factory_; ConfigCallback config_callback_; + PatternsCallback patterns_callback_; + + std::unique_ptr config_url_loader_; + std::unique_ptr patterns_url_loader_; + net::BackoffEntry config_backoff_entry_; + net::BackoffEntry patterns_backoff_entry_; - std::unique_ptr url_loader_; - net::BackoffEntry backoff_entry_; + base::WallClockTimer config_update_timer_; + base::WallClockTimer patterns_update_timer_; + bool patterns_first_request_made_ = false; - base::WallClockTimer update_timer_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace web_discovery diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 95636d5dddcb..d1663379bcb8 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -12,7 +12,9 @@ namespace web_discovery { namespace { constexpr char kCollectorHostPrefix[] = "collector.wdp"; +constexpr char kPatternsHostPrefix[] = "patterns.wdp"; constexpr char kVersionHeader[] = "Version"; +constexpr char kPatternsPath[] = "/patterns.gz"; } // namespace std::string GetCollectorHost() { @@ -24,6 +26,12 @@ std::string GetCollectorHost() { brave_domains::GetServicesDomain(kCollectorHostPrefix)}); } +GURL GetPatternsEndpoint() { + return GURL(base::StrCat( + {url::kHttpsScheme, url::kStandardSchemeSeparator, + brave_domains::GetServicesDomain(kPatternsHostPrefix), kPatternsPath})); +} + std::unique_ptr CreateResourceRequest(GURL url) { auto resource_request = std::make_unique(); resource_request->url = url; diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index d01eb24750b0..dd88175d84d9 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -20,6 +20,7 @@ inline constexpr char kCollectorHostSwitch[] = "wdp-collector-host"; inline constexpr int kCurrentVersion = 1; std::string GetCollectorHost(); +GURL GetPatternsEndpoint(); std::unique_ptr CreateResourceRequest(GURL url); diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 8923d4e22d53..b1cea350f380 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -18,9 +18,13 @@ namespace web_discovery { WDPService::WDPService( + PrefService* local_state, PrefService* profile_prefs, + base::FilePath user_data_dir, scoped_refptr shared_url_loader_factory) - : profile_prefs_(profile_prefs), + : local_state_(local_state), + profile_prefs_(profile_prefs), + user_data_dir_(user_data_dir), shared_url_loader_factory_(shared_url_loader_factory) { pref_change_registrar_.Init(profile_prefs); pref_change_registrar_.Add(kWebDiscoveryEnabled, @@ -34,6 +38,10 @@ WDPService::WDPService( WDPService::~WDPService() = default; +void WDPService::RegisterLocalStatePrefs(PrefRegistrySimple* registry) { + registry->RegisterTimePref(kPatternsRetrievalTime, {}); +} + void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kAnonymousCredentialsDict); registry->RegisterStringPref(kCredentialRSAPrivateKey, {}); @@ -45,8 +53,10 @@ void WDPService::Start() { profile_prefs_, shared_url_loader_factory_.get(), &last_loaded_server_config_); server_config_loader_ = std::make_unique( - shared_url_loader_factory_.get(), - base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this))); + local_state_, user_data_dir_, shared_url_loader_factory_.get(), + base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this)), + base::BindRepeating(&WDPService::OnPatternsLoaded, + base::Unretained(this))); server_config_loader_->Load(); } @@ -69,4 +79,8 @@ void WDPService::OnConfigChange(std::unique_ptr config) { credential_manager_->JoinGroups(); } +void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { + last_loaded_patterns_ = std::move(patterns); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index f664efbd7a4b..747fb27f534b 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -8,8 +8,10 @@ #include +#include "base/files/file_path.h" #include "base/memory/raw_ptr.h" #include "brave/components/web_discovery/browser/credential_manager.h" +#include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -26,13 +28,16 @@ namespace web_discovery { class WDPService : public KeyedService { public: WDPService( + PrefService* local_state, PrefService* profile_prefs, + base::FilePath user_data_dir, scoped_refptr shared_url_loader_factory); ~WDPService() override; WDPService(const WDPService&) = delete; WDPService& operator=(const WDPService&) = delete; + static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); static void RegisterProfilePrefs(PrefRegistrySimple* registry); private: @@ -42,14 +47,19 @@ class WDPService : public KeyedService { void OnEnabledChange(); void OnConfigChange(std::unique_ptr config); + void OnPatternsLoaded(std::unique_ptr patterns); + raw_ptr local_state_; raw_ptr profile_prefs_; PrefChangeRegistrar pref_change_registrar_; + base::FilePath user_data_dir_; + scoped_refptr shared_url_loader_factory_; std::unique_ptr server_config_loader_; std::unique_ptr last_loaded_server_config_; + std::unique_ptr last_loaded_patterns_; std::unique_ptr credential_manager_; }; From ca74dc7cc1045dd5290026e81c4eb78905ba600c Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Mon, 27 May 2024 13:54:48 -0700 Subject: [PATCH 10/36] Add Web Discovery page scraping via Blink --- browser/brave_tab_helpers.cc | 9 ++ browser/web_discovery/wdp_service_factory.cc | 10 ++- browser/web_discovery/wdp_service_factory.h | 3 + chromium_src/chrome/renderer/DEPS | 1 + .../chrome_content_renderer_client.cc | 3 + components/web_discovery/browser/BUILD.gn | 7 ++ components/web_discovery/browser/DEPS | 3 + .../web_discovery/browser/content_scraper.cc | 86 ++++++++++++++++++ .../web_discovery/browser/content_scraper.h | 64 ++++++++++++++ components/web_discovery/browser/patterns.cc | 4 +- components/web_discovery/browser/patterns.h | 14 ++- .../web_discovery/browser/wdp_service.cc | 30 +++++++ .../web_discovery/browser/wdp_service.h | 13 +++ .../browser/web_discovery_tab_helper.cc | 34 +++++++ .../browser/web_discovery_tab_helper.h | 47 ++++++++++ components/web_discovery/common/BUILD.gn | 11 +++ .../web_discovery/common/web_discovery.mojom | 26 ++++++ components/web_discovery/renderer/BUILD.gn | 20 +++++ components/web_discovery/renderer/DEPS | 5 ++ .../renderer/blink_document_extractor.cc | 88 +++++++++++++++++++ .../renderer/blink_document_extractor.h | 45 ++++++++++ renderer/sources.gni | 1 + 22 files changed, 520 insertions(+), 4 deletions(-) create mode 100644 components/web_discovery/browser/content_scraper.cc create mode 100644 components/web_discovery/browser/content_scraper.h create mode 100644 components/web_discovery/browser/web_discovery_tab_helper.cc create mode 100644 components/web_discovery/browser/web_discovery_tab_helper.h create mode 100644 components/web_discovery/common/BUILD.gn create mode 100644 components/web_discovery/common/web_discovery.mojom create mode 100644 components/web_discovery/renderer/BUILD.gn create mode 100644 components/web_discovery/renderer/DEPS create mode 100644 components/web_discovery/renderer/blink_document_extractor.cc create mode 100644 components/web_discovery/renderer/blink_document_extractor.h diff --git a/browser/brave_tab_helpers.cc b/browser/brave_tab_helpers.cc index 4516155624f6..9f98a772eb14 100644 --- a/browser/brave_tab_helpers.cc +++ b/browser/brave_tab_helpers.cc @@ -24,6 +24,7 @@ #include "brave/browser/profiles/profile_util.h" #include "brave/browser/skus/skus_service_factory.h" #include "brave/browser/ui/bookmark/brave_bookmark_tab_helper.h" +#include "brave/browser/web_discovery/wdp_service_factory.h" #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/brave_perf_predictor/browser/perf_predictor_tab_helper.h" #include "brave/components/brave_wayback_machine/buildflags/buildflags.h" @@ -34,6 +35,7 @@ #include "brave/components/request_otr/common/buildflags/buildflags.h" #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/browser/web_discovery_tab_helper.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/common/channel_info.h" @@ -218,6 +220,13 @@ void AttachTabHelpers(content::WebContents* web_contents) { } } #endif // BUILDFLAG(ENABLE_PLAYLIST) + + auto* wdp_service = web_discovery::WDPServiceFactory::GetForBrowserContext( + web_contents->GetBrowserContext()); + if (wdp_service) { + web_discovery::WebDiscoveryTabHelper::CreateForWebContents(web_contents, + wdp_service); + } } } // namespace brave diff --git a/browser/web_discovery/wdp_service_factory.cc b/browser/web_discovery/wdp_service_factory.cc index 80fed85109ee..567bd184e745 100644 --- a/browser/web_discovery/wdp_service_factory.cc +++ b/browser/web_discovery/wdp_service_factory.cc @@ -16,6 +16,12 @@ namespace web_discovery { +WDPService* WDPServiceFactory::GetForBrowserContext( + content::BrowserContext* context) { + return static_cast( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + WDPServiceFactory* WDPServiceFactory::GetInstance() { static base::NoDestructor instance; return instance.get(); @@ -33,8 +39,8 @@ KeyedService* WDPServiceFactory::BuildServiceInstanceFor( auto* default_storage_partition = context->GetDefaultStoragePartition(); auto shared_url_loader_factory = default_storage_partition->GetURLLoaderFactoryForBrowserProcess(); - base::FilePath user_data_dir; - CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); + base::FilePath user_data_dir = + base::PathService::CheckedGet(chrome::DIR_USER_DATA); return new WDPService(g_browser_process->local_state(), user_prefs::UserPrefs::Get(context), user_data_dir, shared_url_loader_factory); diff --git a/browser/web_discovery/wdp_service_factory.h b/browser/web_discovery/wdp_service_factory.h index 4c194af66112..ca7773b19e81 100644 --- a/browser/web_discovery/wdp_service_factory.h +++ b/browser/web_discovery/wdp_service_factory.h @@ -11,9 +11,12 @@ namespace web_discovery { +class WDPService; + class WDPServiceFactory : public BrowserContextKeyedServiceFactory { public: static WDPServiceFactory* GetInstance(); + static WDPService* GetForBrowserContext(content::BrowserContext* context); private: friend base::NoDestructor; diff --git a/chromium_src/chrome/renderer/DEPS b/chromium_src/chrome/renderer/DEPS index 24268d37bd82..4a76c2faf903 100644 --- a/chromium_src/chrome/renderer/DEPS +++ b/chromium_src/chrome/renderer/DEPS @@ -8,6 +8,7 @@ include_rules = [ "+brave/components/content_settings/renderer", "+brave/components/tor/buildflags", "+brave/components/tor/renderer", + "+brave/components/web_discovery/renderer", "+brave/renderer", "+media/base/key_system_info.h", "+services/network/public/cpp", diff --git a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc index b07798ed5f30..32bc898dadc9 100644 --- a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc +++ b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc @@ -6,6 +6,7 @@ #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/ai_rewriter/common/buildflags/buildflags.h" #include "brave/components/content_settings/renderer/brave_content_settings_agent_impl.h" +#include "brave/components/web_discovery/renderer/blink_document_extractor.h" #include "chrome/common/chrome_isolated_world_ids.h" #include "chrome/renderer/chrome_render_thread_observer.h" #include "components/dom_distiller/content/renderer/distillability_agent.h" @@ -42,6 +43,8 @@ void RenderFrameWithBinderRegistryCreated( new ai_rewriter::AIRewriterAgent(render_frame, registry); } #endif + + new web_discovery::BlinkDocumentExtractor(render_frame, registry); } } // namespace diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index c046beecb786..0455a7ae3b83 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -5,6 +5,8 @@ static_library("browser") { sources = [ + "content_scraper.cc", + "content_scraper.h", "credential_manager.cc", "credential_manager.h", "patterns.cc", @@ -18,17 +20,22 @@ static_library("browser") { "util.h", "wdp_service.cc", "wdp_service.h", + "web_discovery_tab_helper.cc", + "web_discovery_tab_helper.h", ] deps = [ "anonymous_credentials/rs:rust_lib", "//base", "//brave/brave_domains", "//brave/components/constants", + "//brave/components/web_discovery/common:mojom", "//components/keyed_service/core", "//components/prefs", + "//content/public/browser", "//net", "//services/network/public/cpp", "//third_party/boringssl", + "//third_party/re2", "//third_party/zlib/google:compression_utils", "//url", ] diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index 5bba53b6abdd..e331506526be 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -1,5 +1,8 @@ include_rules = [ "+services/network/public", + "+content/public/browser", + "+services/service_manager/public/cpp", "+third_party/boringssl/src/include", + "+third_party/re2", "+third_party/zlib/google", ] diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc new file mode 100644 index 000000000000..023e0aff3601 --- /dev/null +++ b/components/web_discovery/browser/content_scraper.cc @@ -0,0 +1,86 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/content_scraper.h" + +#include + +#include "third_party/re2/src/re2/re2.h" + +namespace web_discovery { + +constexpr char kUrlAttrId[] = "url"; + +PageScrapeResult::PageScrapeResult() = default; +PageScrapeResult::~PageScrapeResult() = default; + +ContentScraper::ContentScraper(std::unique_ptr* patterns) + : patterns_(patterns) {} + +ContentScraper::~ContentScraper() = default; + +const PatternsURLDetails* ContentScraper::GetMatchingURLPattern( + const GURL& url, + bool is_strict_scrape) { + const auto& patterns = is_strict_scrape ? patterns_->get()->strict_patterns + : patterns_->get()->normal_patterns; + for (const auto& pattern : patterns) { + if (re2::RE2::PartialMatch(url.spec(), *pattern.url_regex) && + !pattern.scrape_rule_groups.empty()) { + return &pattern; + } + } + return nullptr; +} + +void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, + const GURL& url, + mojom::DocumentExtractor* document_extractor, + PageScrapeResultCallback callback) { + auto interim_result = std::make_unique(); + interim_result->id = url_details->id; + + std::vector select_requests; + for (const auto& group : url_details->scrape_rule_groups) { + auto select_request = mojom::SelectRequest::New(); + select_request->root_selector = group.selector; + for (const auto& rule : group.rules) { + if (rule.rule_type == ScrapeRuleType::kStandard) { + if (rule.attribute == kUrlAttrId) { + interim_result->fields.insert_or_assign( + rule.report_key, std::vector({url.spec()})); + } + } else { + auto attribute_request = mojom::SelectAttributeRequest::New(); + attribute_request->sub_selector = rule.sub_selector; + attribute_request->attribute = rule.attribute; + attribute_request->key = rule.report_key; + + select_request->attribute_requests.push_back( + std::move(attribute_request)); + } + } + select_requests.push_back(std::move(select_request)); + } + + document_extractor->QueryElementAttributes( + std::move(select_requests), + base::BindOnce(&ContentScraper::OnElementAttributes, + weak_ptr_factory_.GetWeakPtr(), std::move(interim_result), + std::move(callback))); +} + +void ContentScraper::OnElementAttributes( + std::unique_ptr scrape_result, + PageScrapeResultCallback callback, + std::vector attribute_results) { + for (const auto& attribute_result : attribute_results) { + scrape_result->fields.insert_or_assign(attribute_result->key, + attribute_result->attribute_values); + } + std::move(callback).Run(std::move(scrape_result)); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h new file mode 100644 index 000000000000..f17d5a08b131 --- /dev/null +++ b/components/web_discovery/browser/content_scraper.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CONTENT_SCRAPER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CONTENT_SCRAPER_H_ + +#include +#include +#include +#include + +#include "base/containers/flat_map.h" +#include "base/functional/callback.h" +#include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/common/web_discovery.mojom.h" +#include "url/gurl.h" + +namespace web_discovery { + +struct PageScrapeResult { + PageScrapeResult(); + ~PageScrapeResult(); + + PageScrapeResult(const PageScrapeResult&) = delete; + PageScrapeResult& operator=(const PageScrapeResult&) = delete; + + base::flat_map> fields; + std::string id; +}; + +class ContentScraper { + public: + using PageScrapeResultCallback = + base::OnceCallback)>; + + explicit ContentScraper(std::unique_ptr* patterns); + ~ContentScraper(); + + ContentScraper(const ContentScraper&) = delete; + ContentScraper& operator=(const ContentScraper&) = delete; + + const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, + bool is_strict_scrape); + void ScrapePage(const PatternsURLDetails* url_details, + const GURL& url, + mojom::DocumentExtractor* document_extractor, + PageScrapeResultCallback callback); + + private: + void OnElementAttributes( + std::unique_ptr scrape_result, + PageScrapeResultCallback callback, + std::vector attribute_results); + + raw_ptr> patterns_; + + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CONTENT_SCRAPER_H_ diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index 1ac04e1ee597..15a99a5952fc 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -11,6 +11,7 @@ #include "base/json/json_reader.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "third_party/re2/src/re2/re2.h" namespace web_discovery { @@ -61,6 +62,7 @@ std::optional> ParseScrapeRules( VLOG(1) << "Attribute missing from rule"; return std::nullopt; } + rule_it->report_key = report_key; rule_it->rule_type = ScrapeRuleType::kOther; if (rule_type_str) { auto rule_type_it = kRuleTypeMap.find(*rule_type_str); @@ -103,7 +105,7 @@ std::optional> ParsePatternsURLDetails( } auto& details = result[i]; - details.url_regex = *url_regex; + details.url_regex = std::make_unique(*url_regex); std::string i_str = base::NumberToString(i); diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index f233f212e0e3..509214215603 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -11,6 +11,12 @@ #include #include +#include "base/containers/flat_map.h" + +namespace re2 { +class RE2; +} // namespace re2 + namespace web_discovery { enum class ScrapeRuleType { kStandard, kSearchQuery, kWidgetTitle, kOther }; @@ -20,6 +26,7 @@ struct ScrapeRule { ~ScrapeRule(); ScrapeRule(const ScrapeRule&) = delete; + ScrapeRule& operator=(const ScrapeRule&) = delete; std::string report_key; std::string selector; @@ -33,6 +40,7 @@ struct ScrapeRuleGroup { ~ScrapeRuleGroup(); ScrapeRuleGroup(const ScrapeRuleGroup&) = delete; + ScrapeRuleGroup& operator=(const ScrapeRuleGroup&) = delete; std::string selector; std::vector rules; @@ -43,8 +51,9 @@ struct PatternsURLDetails { ~PatternsURLDetails(); PatternsURLDetails(const PatternsURLDetails&) = delete; + PatternsURLDetails& operator=(const PatternsURLDetails&) = delete; - std::string url_regex; + std::unique_ptr url_regex; bool is_search_engine; std::string id; std::vector scrape_rule_groups; @@ -54,6 +63,9 @@ struct PatternsGroup { PatternsGroup(); ~PatternsGroup(); + PatternsGroup(const PatternsGroup&) = delete; + PatternsGroup& operator=(const PatternsGroup&) = delete; + std::vector normal_patterns; std::vector strict_patterns; }; diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index b1cea350f380..5d79bf9804d3 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -13,7 +13,10 @@ #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace web_discovery { @@ -61,6 +64,7 @@ void WDPService::Start() { } void WDPService::Stop() { + content_scraper_ = nullptr; server_config_loader_ = nullptr; credential_manager_ = nullptr; last_loaded_server_config_ = nullptr; @@ -81,6 +85,32 @@ void WDPService::OnConfigChange(std::unique_ptr config) { void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { last_loaded_patterns_ = std::move(patterns); + content_scraper_ = std::make_unique(&last_loaded_patterns_); +} + +void WDPService::OnFinishNavigation( + const GURL& url, + content::RenderFrameHost* render_frame_host) { + if (!content_scraper_) { + return; + } + auto* url_pattern = content_scraper_->GetMatchingURLPattern(url, false); + if (!url_pattern) { + return; + } + mojo::Remote remote; + render_frame_host->GetRemoteInterfaces()->GetInterface( + remote.BindNewPipeAndPassReceiver()); + auto remote_id = document_extractor_remotes_.Add(std::move(remote)); + content_scraper_->ScrapePage( + url_pattern, url, document_extractor_remotes_.Get(remote_id), + base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this))); +} + +void WDPService::OnContentScraped(std::unique_ptr result) { + if (!result) { + return; + } } } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 747fb27f534b..3c741722670a 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -10,15 +10,21 @@ #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" +#include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" +#include "mojo/public/cpp/bindings/remote_set.h" class PrefRegistrySimple; class PrefService; +namespace content { +class RenderFrameHost; +} + namespace network { class SharedURLLoaderFactory; } // namespace network @@ -40,6 +46,9 @@ class WDPService : public KeyedService { static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); static void RegisterProfilePrefs(PrefRegistrySimple* registry); + void OnFinishNavigation(const GURL& url, + content::RenderFrameHost* render_frame_host); + private: void Start(); void Stop(); @@ -48,6 +57,7 @@ class WDPService : public KeyedService { void OnConfigChange(std::unique_ptr config); void OnPatternsLoaded(std::unique_ptr patterns); + void OnContentScraped(std::unique_ptr result); raw_ptr local_state_; raw_ptr profile_prefs_; @@ -57,10 +67,13 @@ class WDPService : public KeyedService { scoped_refptr shared_url_loader_factory_; + mojo::RemoteSet document_extractor_remotes_; + std::unique_ptr server_config_loader_; std::unique_ptr last_loaded_server_config_; std::unique_ptr last_loaded_patterns_; std::unique_ptr credential_manager_; + std::unique_ptr content_scraper_; }; } // namespace web_discovery diff --git a/components/web_discovery/browser/web_discovery_tab_helper.cc b/components/web_discovery/browser/web_discovery_tab_helper.cc new file mode 100644 index 000000000000..98c120e2be25 --- /dev/null +++ b/components/web_discovery/browser/web_discovery_tab_helper.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "brave/components/web_discovery/browser/web_discovery_tab_helper.h" + +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "content/public/browser/navigation_handle.h" + +namespace web_discovery { + +WebDiscoveryTabHelper::WebDiscoveryTabHelper(content::WebContents* web_contents, + WDPService* wdp_service) + : content::WebContentsObserver(web_contents), + content::WebContentsUserData(*web_contents), + wdp_service_(wdp_service) { + CHECK(wdp_service); +} + +WebDiscoveryTabHelper::~WebDiscoveryTabHelper() = default; + +void WebDiscoveryTabHelper::DidFinishLoad( + content::RenderFrameHost* render_frame_host, + const GURL& url) { + if (!render_frame_host->IsInPrimaryMainFrame()) { + return; + } + wdp_service_->OnFinishNavigation(url, render_frame_host); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(WebDiscoveryTabHelper); + +} // namespace web_discovery diff --git a/components/web_discovery/browser/web_discovery_tab_helper.h b/components/web_discovery/browser/web_discovery_tab_helper.h new file mode 100644 index 000000000000..1d3ee38d84b6 --- /dev/null +++ b/components/web_discovery/browser/web_discovery_tab_helper.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WEB_DISCOVERY_TAB_HELPER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WEB_DISCOVERY_TAB_HELPER_H_ + +#include "base/memory/raw_ptr.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { +class RenderFrameHost; +} // namespace content + +namespace web_discovery { + +class WDPService; + +class WebDiscoveryTabHelper + : public content::WebContentsObserver, + public content::WebContentsUserData { + public: + WebDiscoveryTabHelper(content::WebContents* web_contents, + WDPService* wdp_service); + ~WebDiscoveryTabHelper() override; + + WebDiscoveryTabHelper(const WebDiscoveryTabHelper&) = delete; + WebDiscoveryTabHelper& operator=(const WebDiscoveryTabHelper&) = delete; + + private: + friend class content::WebContentsUserData; + + // content::WebContentsObserver: + void DidFinishLoad(content::RenderFrameHost* render_frame_host, + const GURL& url) override; + + raw_ptr wdp_service_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WEB_DISCOVERY_TAB_HELPER_H_ diff --git a/components/web_discovery/common/BUILD.gn b/components/web_discovery/common/BUILD.gn new file mode 100644 index 000000000000..b937e4a19138 --- /dev/null +++ b/components/web_discovery/common/BUILD.gn @@ -0,0 +1,11 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojom") { + sources = [ "web_discovery.mojom" ] + deps = [ "//mojo/public/mojom/base" ] +} diff --git a/components/web_discovery/common/web_discovery.mojom b/components/web_discovery/common/web_discovery.mojom new file mode 100644 index 000000000000..198f5ab6931d --- /dev/null +++ b/components/web_discovery/common/web_discovery.mojom @@ -0,0 +1,26 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +module web_discovery.mojom; + +struct SelectAttributeRequest { + string? sub_selector; + string key; + string attribute; +}; + +struct SelectRequest { + string root_selector; + array attribute_requests; +}; + +struct AttributeResult { + string key; + array attribute_values; +}; + +interface DocumentExtractor { + QueryElementAttributes(array requests) => (array results); +}; diff --git a/components/web_discovery/renderer/BUILD.gn b/components/web_discovery/renderer/BUILD.gn new file mode 100644 index 000000000000..aa993a8db043 --- /dev/null +++ b/components/web_discovery/renderer/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +source_set("renderer") { + sources = [ + "blink_document_extractor.cc", + "blink_document_extractor.h", + ] + + deps = [ + "//base", + "//brave/components/web_discovery/common:mojom", + "//content/public/renderer", + "//mojo/public/cpp/bindings", + "//services/service_manager/public/cpp", + "//third_party/blink/public:blink", + ] +} diff --git a/components/web_discovery/renderer/DEPS b/components/web_discovery/renderer/DEPS new file mode 100644 index 000000000000..082311a6a709 --- /dev/null +++ b/components/web_discovery/renderer/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + "+content/public/renderer", + "+services/service_manager/public/cpp", + "+third_party/blink/public/web", +] diff --git a/components/web_discovery/renderer/blink_document_extractor.cc b/components/web_discovery/renderer/blink_document_extractor.cc new file mode 100644 index 000000000000..06b2a474f0f0 --- /dev/null +++ b/components/web_discovery/renderer/blink_document_extractor.cc @@ -0,0 +1,88 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/renderer/blink_document_extractor.h" + +#include +#include + +#include "third_party/blink/public/web/web_element.h" +#include "third_party/blink/public/web/web_local_frame.h" + +namespace web_discovery { + +namespace { + +mojom::AttributeResultPtr ProcessAttributeRequest( + mojom::SelectAttributeRequest* request, + const blink::WebVector& elements) { + auto attributes_result = mojom::AttributeResult::New(); + attributes_result->key = request->key; + for (const auto& element : elements) { + std::optional sub_element; + const auto* element_to_query = &element; + if (request->sub_selector) { + auto web_sub_selector = + blink::WebString::FromUTF8(*request->sub_selector); + sub_element = element.QuerySelector(web_sub_selector); + element_to_query = &*sub_element; + } + std::string attribute_value; + if (element_to_query->IsNull()) { + continue; + } + auto attribute_name = blink::WebString::FromUTF8(request->attribute); + auto web_attribute_value = element_to_query->GetAttribute(attribute_name); + if (web_attribute_value.IsNull()) { + continue; + } + attributes_result->attribute_values.push_back(web_attribute_value.Utf8()); + } + return attributes_result; +} + +} // namespace + +BlinkDocumentExtractor::BlinkDocumentExtractor( + content::RenderFrame* render_frame, + service_manager::BinderRegistry* registry) + : content::RenderFrameObserver(render_frame), render_frame_(render_frame) { + registry->AddInterface(base::BindRepeating( + &BlinkDocumentExtractor::BindReceiver, base::Unretained(this))); +} + +BlinkDocumentExtractor::~BlinkDocumentExtractor() = default; + +void BlinkDocumentExtractor::QueryElementAttributes( + std::vector requests, + QueryElementAttributesCallback callback) { + blink::WebDocument document = render_frame_->GetWebFrame()->GetDocument(); + std::vector results; + for (const auto& request : requests) { + auto result = mojom::AttributeResult::New(); + + auto selector = blink::WebString::FromUTF8(request->root_selector); + auto elements = document.QuerySelectorAll(selector); + for (const auto& attribute_request : request->attribute_requests) { + auto attributes_result = + ProcessAttributeRequest(attribute_request.get(), elements); + results.push_back(std::move(attributes_result)); + } + } + + std::move(callback).Run(std::move(results)); +} + +void BlinkDocumentExtractor::OnDestruct() { + delete this; +} + +void BlinkDocumentExtractor::BindReceiver( + mojo::PendingReceiver receiver) { + receiver_.reset(); + receiver_.Bind(std::move(receiver)); +} + +} // namespace web_discovery diff --git a/components/web_discovery/renderer/blink_document_extractor.h b/components/web_discovery/renderer/blink_document_extractor.h new file mode 100644 index 000000000000..ce4e19c4b252 --- /dev/null +++ b/components/web_discovery/renderer/blink_document_extractor.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_RENDERER_BLINK_DOCUMENT_EXTRACTOR_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_RENDERER_BLINK_DOCUMENT_EXTRACTOR_H_ + +#include + +#include "brave/components/web_discovery/common/web_discovery.mojom.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_frame_observer.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "services/service_manager/public/cpp/binder_registry.h" + +namespace web_discovery { + +class BlinkDocumentExtractor : public content::RenderFrameObserver, + public mojom::DocumentExtractor { + public: + BlinkDocumentExtractor(content::RenderFrame* render_frame, + service_manager::BinderRegistry* registry); + ~BlinkDocumentExtractor() override; + + BlinkDocumentExtractor(const BlinkDocumentExtractor&) = delete; + BlinkDocumentExtractor& operator=(const BlinkDocumentExtractor&) = delete; + + // mojom::DocumentExtractor: + void QueryElementAttributes(std::vector requests, + QueryElementAttributesCallback callback) override; + + // RenderFrameObserver: + void OnDestruct() override; + + private: + void BindReceiver(mojo::PendingReceiver receiver); + + raw_ptr render_frame_; + mojo::Receiver receiver_{this}; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_RENDERER_BLINK_DOCUMENT_EXTRACTOR_H_ diff --git a/renderer/sources.gni b/renderer/sources.gni index 0fb4561218a8..b555dd352afe 100644 --- a/renderer/sources.gni +++ b/renderer/sources.gni @@ -36,6 +36,7 @@ brave_chrome_renderer_deps = [ "//brave/components/skus/renderer", "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", + "//brave/components/web_discovery/renderer", "//brave/renderer/brave_wallet", "//mojo/public/cpp/bindings", "//third_party/blink/public:blink", From 36a9fa552f4aea98fd628b96ae89d90d4457b84a Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 30 May 2024 14:22:08 -0700 Subject: [PATCH 11/36] Add Web Discovery double fetch, page parsing and scraping --- components/web_discovery/browser/BUILD.gn | 3 + .../web_discovery/browser/content_scraper.cc | 152 +++- .../web_discovery/browser/content_scraper.h | 26 +- .../browser/credential_manager.cc | 13 +- .../browser/document_extractor/rs/.gitignore | 2 + .../browser/document_extractor/rs/BUILD.gn | 24 + .../browser/document_extractor/rs/Cargo.lock | 767 ++++++++++++++++++ .../browser/document_extractor/rs/Cargo.toml | 15 + .../browser/document_extractor/rs/src/lib.rs | 95 +++ .../web_discovery/browser/double_fetcher.cc | 162 ++++ .../web_discovery/browser/double_fetcher.h | 61 ++ components/web_discovery/browser/patterns.cc | 2 +- components/web_discovery/browser/pref_names.h | 4 + .../browser/server_config_loader.cc | 9 - components/web_discovery/browser/util.cc | 3 - components/web_discovery/browser/util.h | 10 + .../web_discovery/browser/wdp_service.cc | 46 +- .../web_discovery/browser/wdp_service.h | 12 +- .../renderer/blink_document_extractor.cc | 19 +- .../rust/chromium_crates_io/Cargo.lock | 10 + .../rust/chromium_crates_io/Cargo.toml | 5 + .../v0_1/README.chromium | 8 + 22 files changed, 1393 insertions(+), 55 deletions(-) create mode 100644 components/web_discovery/browser/document_extractor/rs/.gitignore create mode 100644 components/web_discovery/browser/document_extractor/rs/BUILD.gn create mode 100644 components/web_discovery/browser/document_extractor/rs/Cargo.lock create mode 100644 components/web_discovery/browser/document_extractor/rs/Cargo.toml create mode 100644 components/web_discovery/browser/document_extractor/rs/src/lib.rs create mode 100644 components/web_discovery/browser/double_fetcher.cc create mode 100644 components/web_discovery/browser/double_fetcher.h create mode 100644 third_party/rust/document_extractor_cxx/v0_1/README.chromium diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 0455a7ae3b83..a27eb1ba782c 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -9,6 +9,8 @@ static_library("browser") { "content_scraper.h", "credential_manager.cc", "credential_manager.h", + "double_fetcher.cc", + "double_fetcher.h", "patterns.cc", "patterns.h", "pref_names.h", @@ -25,6 +27,7 @@ static_library("browser") { ] deps = [ "anonymous_credentials/rs:rust_lib", + "document_extractor/rs:rust_lib", "//base", "//brave/brave_domains", "//brave/components/constants", diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 023e0aff3601..6b81dcc63d3f 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -7,20 +7,79 @@ #include +#include "base/ranges/algorithm.h" +#include "base/task/thread_pool.h" #include "third_party/re2/src/re2/re2.h" namespace web_discovery { +namespace { + constexpr char kUrlAttrId[] = "url"; +constexpr char kFieldsValueKey[] = "fields"; +constexpr char kIdValueKey[] = "id"; +constexpr char kUrlValueKey[] = "url"; + +} // namespace -PageScrapeResult::PageScrapeResult() = default; +PageScrapeResult::PageScrapeResult(GURL url, std::string id) + : url(url), id(id) {} PageScrapeResult::~PageScrapeResult() = default; ContentScraper::ContentScraper(std::unique_ptr* patterns) - : patterns_(patterns) {} + : pool_sequenced_task_runner_( + base::ThreadPool::CreateSequencedTaskRunner({})), + patterns_(patterns) {} ContentScraper::~ContentScraper() = default; +base::Value PageScrapeResult::SerializeToValue() { + base::Value::Dict result; + base::Value::Dict fields_dict; + + for (const auto& [key, values] : fields) { + base::Value::List list; + for (const auto& value : values) { + list.Append(value); + } + fields_dict.Set(key, std::move(list)); + } + + result.Set(kFieldsValueKey, std::move(fields_dict)); + result.Set(kIdValueKey, id); + result.Set(kUrlValueKey, url.spec()); + return base::Value(std::move(result)); +} + +std::unique_ptr PageScrapeResult::FromValue( + const base::Value& value) { + if (!value.is_dict()) { + return nullptr; + } + const auto& dict = value.GetDict(); + const auto* fields_dict = dict.FindDict(kFieldsValueKey); + const auto* id = dict.FindString(kIdValueKey); + const auto* url = dict.FindString(kUrlValueKey); + + if (!fields_dict || !id || !url) { + return nullptr; + } + + auto result = std::make_unique(GURL(*url), *id); + for (const auto [key, values] : *fields_dict) { + std::vector values_vec; + for (const auto& val : values.GetList()) { + if (!val.is_string()) { + return nullptr; + } + values_vec.push_back(val.GetString()); + } + result->fields[key] = std::move(values_vec); + } + + return result; +} + const PatternsURLDetails* ContentScraper::GetMatchingURLPattern( const GURL& url, bool is_strict_scrape) { @@ -39,8 +98,8 @@ void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, const GURL& url, mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback) { - auto interim_result = std::make_unique(); - interim_result->id = url_details->id; + auto interim_result = + std::make_unique(url, url_details->id); std::vector select_requests; for (const auto& group : url_details->scrape_rule_groups) { @@ -48,31 +107,72 @@ void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, select_request->root_selector = group.selector; for (const auto& rule : group.rules) { if (rule.rule_type == ScrapeRuleType::kStandard) { - if (rule.attribute == kUrlAttrId) { - interim_result->fields.insert_or_assign( - rule.report_key, std::vector({url.spec()})); - } - } else { - auto attribute_request = mojom::SelectAttributeRequest::New(); - attribute_request->sub_selector = rule.sub_selector; - attribute_request->attribute = rule.attribute; - attribute_request->key = rule.report_key; - - select_request->attribute_requests.push_back( - std::move(attribute_request)); + ProcessStandardRule(rule, url, interim_result.get()); + continue; } + auto attribute_request = mojom::SelectAttributeRequest::New(); + attribute_request->sub_selector = rule.sub_selector; + attribute_request->attribute = rule.attribute; + attribute_request->key = rule.report_key; + + select_request->attribute_requests.push_back( + std::move(attribute_request)); } select_requests.push_back(std::move(select_request)); } document_extractor->QueryElementAttributes( std::move(select_requests), - base::BindOnce(&ContentScraper::OnElementAttributes, + base::BindOnce(&ContentScraper::OnScrapedElementAttributes, + base::Unretained(this), std::move(interim_result), + std::move(callback))); +} + +void ContentScraper::ParseAndScrapePage( + std::unique_ptr prev_result, + const PatternsURLDetails* url_details, + std::string html, + PageScrapeResultCallback callback) { + auto interim_result = std::move(prev_result); + + std::vector select_requests; + for (const auto& group : url_details->scrape_rule_groups) { + rust_document_extractor::SelectRequest select_request; + select_request.root_selector = group.selector; + for (const auto& rule : group.rules) { + if (rule.rule_type == ScrapeRuleType::kStandard) { + ProcessStandardRule(rule, interim_result->url, interim_result.get()); + continue; + } + rust_document_extractor::SelectAttributeRequest attribute_request{ + .sub_selector = rule.sub_selector.value_or(""), + .key = rule.report_key, + .attribute = rule.attribute, + }; + select_request.attribute_requests.push_back(std::move(attribute_request)); + } + select_requests.push_back(std::move(select_request)); + } + + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&rust_document_extractor::query_element_attributes, html, + select_requests), + base::BindOnce(&ContentScraper::OnRustElementAttributes, weak_ptr_factory_.GetWeakPtr(), std::move(interim_result), std::move(callback))); } -void ContentScraper::OnElementAttributes( +void ContentScraper::ProcessStandardRule(const ScrapeRule& rule, + const GURL& url, + PageScrapeResult* scrape_result) { + if (rule.attribute == kUrlAttrId) { + scrape_result->fields.insert_or_assign( + rule.report_key, std::vector({url.spec()})); + } +} + +void ContentScraper::OnScrapedElementAttributes( std::unique_ptr scrape_result, PageScrapeResultCallback callback, std::vector attribute_results) { @@ -83,4 +183,20 @@ void ContentScraper::OnElementAttributes( std::move(callback).Run(std::move(scrape_result)); } +void ContentScraper::OnRustElementAttributes( + std::unique_ptr scrape_result, + PageScrapeResultCallback callback, + rust::Vec attribute_results) { + for (const auto& attribute_result : attribute_results) { + std::vector attribute_values; + base::ranges::transform(attribute_result.attribute_values.begin(), + attribute_result.attribute_values.end(), + std::back_inserter(attribute_values), + [](auto value) { return std::string(value); }); + scrape_result->fields.insert_or_assign(std::string(attribute_result.key), + attribute_values); + } + std::move(callback).Run(std::move(scrape_result)); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index f17d5a08b131..e5856c2fabf1 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -7,12 +7,13 @@ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CONTENT_SCRAPER_H_ #include -#include #include #include #include "base/containers/flat_map.h" #include "base/functional/callback.h" +#include "base/values.h" +#include "brave/components/web_discovery/browser/document_extractor/rs/src/lib.rs.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" #include "url/gurl.h" @@ -20,12 +21,16 @@ namespace web_discovery { struct PageScrapeResult { - PageScrapeResult(); + PageScrapeResult(GURL url, std::string id); ~PageScrapeResult(); PageScrapeResult(const PageScrapeResult&) = delete; PageScrapeResult& operator=(const PageScrapeResult&) = delete; + base::Value SerializeToValue(); + static std::unique_ptr FromValue(const base::Value& dict); + + GURL url; base::flat_map> fields; std::string id; }; @@ -43,16 +48,31 @@ class ContentScraper { const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, bool is_strict_scrape); + // For initial page scrape in renderer void ScrapePage(const PatternsURLDetails* url_details, const GURL& url, mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback); + // For subsequent double fetches after initial scrape + void ParseAndScrapePage(std::unique_ptr prev_result, + const PatternsURLDetails* url_details, + std::string html, + PageScrapeResultCallback callback); private: - void OnElementAttributes( + void ProcessStandardRule(const ScrapeRule& rule, + const GURL& url, + PageScrapeResult* scrape_result); + void OnScrapedElementAttributes( std::unique_ptr scrape_result, PageScrapeResultCallback callback, std::vector attribute_results); + void OnRustElementAttributes( + std::unique_ptr scrape_result, + PageScrapeResultCallback callback, + rust::Vec attribute_results); + + scoped_refptr pool_sequenced_task_runner_; raw_ptr> patterns_; diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 387cceb85a1e..3c8fe8377cfa 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -37,18 +37,11 @@ constexpr char kJoinRSAPublicKeyField[] = "pk"; constexpr char kJoinRSASignatureField[] = "sig"; constexpr char kJoinResponseField[] = "joinResponse"; +constexpr char kVersionHeader[] = "Version"; + constexpr char kGSKDictKey[] = "gsk"; constexpr char kCredentialDictKey[] = "credential"; -constexpr net::BackoffEntry::Policy kBackoffPolicy = { - .num_errors_to_ignore = 0, - .initial_delay_ms = 10 * 1000, - .multiply_factor = 2.0, - .jitter_factor = 0.1, - .maximum_backoff_ms = 10 * 60 * 1000, - .entry_lifetime_ms = -1, - .always_use_initial_delay = false}; - constexpr net::NetworkTrafficAnnotationTag kJoinNetworkTrafficAnnotation = net::DefineNetworkTrafficAnnotation("wdp_join", R"( semantics { @@ -250,6 +243,8 @@ void CredentialManager::OnJoinRequestReady( generate_join_result->start_join_result.gsk.end()); auto resource_request = CreateResourceRequest(join_url_); + resource_request->headers.SetHeader(kVersionHeader, + base::NumberToString(kCurrentVersion)); resource_request->method = net::HttpRequestHeaders::kPostMethod; join_url_loaders_[date] = network::SimpleURLLoader::Create( diff --git a/components/web_discovery/browser/document_extractor/rs/.gitignore b/components/web_discovery/browser/document_extractor/rs/.gitignore new file mode 100644 index 000000000000..436cbd991cdd --- /dev/null +++ b/components/web_discovery/browser/document_extractor/rs/.gitignore @@ -0,0 +1,2 @@ +target +example/main diff --git a/components/web_discovery/browser/document_extractor/rs/BUILD.gn b/components/web_discovery/browser/document_extractor/rs/BUILD.gn new file mode 100644 index 000000000000..976310b3cdb3 --- /dev/null +++ b/components/web_discovery/browser/document_extractor/rs/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//build/rust/rust_static_library.gni") + +rust_static_library("rust_lib") { + crate_name = "document_extractor_cxx" + crate_root = "src/lib.rs" + allow_unsafe = true + + edition = "2021" + sources = [ "src/lib.rs" ] + + visibility = [ "//brave/components/web_discovery/browser:*" ] + + cxx_bindings = [ "src/lib.rs" ] + + deps = [ + "//brave/third_party/rust/html5ever/v0_25:lib", + "//brave/third_party/rust/kuchikiki/v0_8:lib", + ] +} diff --git a/components/web_discovery/browser/document_extractor/rs/Cargo.lock b/components/web_discovery/browser/document_extractor/rs/Cargo.lock new file mode 100644 index 000000000000..dd4a2a1e7410 --- /dev/null +++ b/components/web_discovery/browser/document_extractor/rs/Cargo.lock @@ -0,0 +1,767 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.66", +] + +[[package]] +name = "cxx" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb497fad022245b29c2a0351df572e2d67c1046bcef2260ebc022aec81efea82" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c799a4a846f1c0acb9f36bb9c6272d9b3d9457f3633c7753c6057270df13c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bc249a7e3cd554fd2e8e08a426e9670c50bbfc9a621653cfa9accc9641783" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "document-extractor-cxx" +version = "0.1.0" +dependencies = [ + "cxx", + "html5ever", + "kuchikiki", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" +dependencies = [ + "dtoa", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "html5ever" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "kuchikiki" +version = "0.8.4-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af921794306a6885fc7510012ce12015d2cf0bfdba82fb217b9c2caf324a4618" +dependencies = [ + "cssparser", + "html5ever", + "indexmap", + "matches", + "selectors", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/components/web_discovery/browser/document_extractor/rs/Cargo.toml b/components/web_discovery/browser/document_extractor/rs/Cargo.toml new file mode 100644 index 000000000000..cde2a9183587 --- /dev/null +++ b/components/web_discovery/browser/document_extractor/rs/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "document-extractor-cxx" +version = "0.1.0" +authors = ["Darnell Andries "] +edition = "2021" +license = "MPL-2.0" + +[dependencies] +cxx = "1" +kuchikiki = "0.8.4-speedreader" +html5ever = "0.25" + +[lib] +name = "document_extractor_cxx" +crate-type = ["rlib"] diff --git a/components/web_discovery/browser/document_extractor/rs/src/lib.rs b/components/web_discovery/browser/document_extractor/rs/src/lib.rs new file mode 100644 index 000000000000..592670b50707 --- /dev/null +++ b/components/web_discovery/browser/document_extractor/rs/src/lib.rs @@ -0,0 +1,95 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::collections::HashMap; + +use cxx::{CxxString, CxxVector}; +use html5ever::tree_builder::TreeSink; +use kuchikiki::{ + iter::{Descendants, Elements, Select}, + parse_html, + traits::TendrilSink, +}; + +#[allow(unsafe_op_in_unsafe_fn)] +#[cxx::bridge(namespace = "rust_document_extractor")] +mod ffi { + pub struct SelectAttributeRequest { + pub sub_selector: String, + pub key: String, + pub attribute: String, + } + + pub struct SelectRequest { + pub root_selector: String, + pub attribute_requests: Vec, + } + + pub struct AttributeResult { + pub key: String, + pub attribute_values: Vec, + } + + extern "Rust" { + fn query_element_attributes( + html: &CxxString, + requests: &CxxVector, + ) -> Vec; + } +} + +use ffi::*; + +const TEXT_CONTENT_ATTRIBUTE_NAME: &str = "textContent"; + +fn extract_attributes_from_nodes( + attribute_requests: &[SelectAttributeRequest], + nodes: Select>, +) -> HashMap> { + let mut result: HashMap> = HashMap::new(); + for node in nodes { + for attribute_request in attribute_requests { + let sub_node = match attribute_request.sub_selector.is_empty() { + false => match node.as_node().select_first(&attribute_request.sub_selector) { + Ok(e) => Some(e), + Err(_) => continue, + }, + true => None, + }; + let node_to_query = sub_node.as_ref().unwrap_or(&node).as_node(); + + let attribute_value = match attribute_request.attribute == TEXT_CONTENT_ATTRIBUTE_NAME { + true => Some(node_to_query.text_contents()), + false => node_to_query.as_element().and_then(|element| { + let attributes = element.attributes.borrow(); + attributes.get(attribute_request.attribute.as_str()).map(|v| v.to_string()) + }), + }; + if let Some(value) = attribute_value { + result.entry(attribute_request.key.clone()).or_default().push(value); + } + } + } + result +} + +pub fn query_element_attributes( + html: &CxxString, + requests: &CxxVector, +) -> Vec { + let mut sink = parse_html().one(html.to_str().unwrap_or_default()); + let mut result = Vec::new(); + let document = sink.get_document(); + for request in requests { + if let Ok(nodes) = document.select(&request.root_selector) { + result.extend( + extract_attributes_from_nodes(&request.attribute_requests, nodes) + .into_iter() + .map(|(key, attribute_values)| AttributeResult { key, attribute_values }), + ); + } + } + result +} diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc new file mode 100644 index 000000000000..42e02be8e535 --- /dev/null +++ b/components/web_discovery/browser/double_fetcher.cc @@ -0,0 +1,162 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/double_fetcher.h" + +#include + +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/util.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace web_discovery { + +namespace { +constexpr char kUrlKey[] = "url"; +constexpr char kAssociatedDataKey[] = "assoc_data"; +constexpr char kRequestTimeKey[] = "request_time"; +constexpr char kRetriesKey[] = "retries"; + +constexpr base::TimeDelta kRequestMaxAge = base::Hours(1); +constexpr base::TimeDelta kRequestInterval = base::Minutes(1); +constexpr size_t kMaxRetries = 3; +constexpr size_t kMaxDoubleFetchResponseSize = 2 * 1024 * 1024; + +constexpr net::NetworkTrafficAnnotationTag kFetchNetworkTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("wdp_doublefetch", R"( + semantics { + sender: "Brave Web Discovery Double Fetch" + description: + "Retrieves a page of interest without session cookies for + scraping and reporting via Web Discovery." + trigger: + "Requests are sent minutes after the original + page request is made by the user." + data: "Page data" + destination: WEBSITE + } + policy { + cookies_allowed: NO + setting: + "Users can opt-in or out via brave://settings/search" + })"); + +} // namespace + +DoubleFetcher::DoubleFetcher( + PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + FetchedCallback callback) + : profile_prefs_(profile_prefs), + shared_url_loader_factory_(shared_url_loader_factory), + backoff_entry_(&kBackoffPolicy), + callback_(callback) { + StartFetchTimer(kRequestInterval); +} + +DoubleFetcher::~DoubleFetcher() = default; + +void DoubleFetcher::ScheduleDoubleFetch(const GURL& url, + base::Value associated_data) { + base::Value::Dict fetch_dict; + fetch_dict.Set(kUrlKey, url.spec()); + fetch_dict.Set(kAssociatedDataKey, std::move(associated_data)); + fetch_dict.Set(kRequestTimeKey, + static_cast(base::Time::Now().ToTimeT())); + + ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); + update->Append(std::move(fetch_dict)); + + if (!fetch_timer_.IsRunning()) { + StartFetchTimer(kRequestInterval); + } +} + +void DoubleFetcher::OnFetchTimer() { + ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); + for (auto it = update->begin(); it != update->end();) { + const auto* fetch_dict = it->GetIfDict(); + const auto request_time = + fetch_dict ? fetch_dict->FindDouble(kRequestTimeKey) : std::nullopt; + const auto* url = fetch_dict ? fetch_dict->FindString(kUrlKey) : nullptr; + if (!request_time || + (base::Time::Now() - base::Time::FromTimeT(static_cast( + *request_time))) > kRequestMaxAge || + !url) { + it = update->erase(it); + continue; + } + auto resource_request = CreateResourceRequest(GURL(*url)); + url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), kFetchNetworkTrafficAnnotation); + url_loader_->DownloadToString( + shared_url_loader_factory_.get(), + base::BindOnce(&DoubleFetcher::OnRequestComplete, + base::Unretained(this)), + kMaxDoubleFetchResponseSize); + return; + } +} + +void DoubleFetcher::StartFetchTimer(base::TimeDelta delta) { + fetch_timer_.Start( + FROM_HERE, delta, + base::BindOnce(&DoubleFetcher::OnFetchTimer, base::Unretained(this))); +} + +void DoubleFetcher::OnRequestComplete( + std::optional response_body) { + auto result = ProcessCompletedRequest(&response_body); + backoff_entry_.InformOfRequest(result); + + ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); + auto& request_dict = update->front().GetDict(); + + base::TimeDelta next_fetch_time = kRequestInterval; + bool should_remove = result; + + if (!result) { + next_fetch_time = backoff_entry_.GetTimeUntilRelease(); + auto retries = request_dict.FindInt(kRetriesKey); + if (retries && retries >= kMaxRetries) { + should_remove = true; + } else { + request_dict.Set(kRetriesKey, retries.value_or(0) + 1); + } + } + + if (should_remove) { + auto* assoc_data = request_dict.Find(kAssociatedDataKey); + if (assoc_data) { + callback_.Run(*assoc_data, response_body); + } + update->erase(update->begin()); + } + + StartFetchTimer(next_fetch_time); +} + +bool DoubleFetcher::ProcessCompletedRequest( + std::optional* response_body) { + auto* response_info = url_loader_->ResponseInfo(); + if (!response_body || !response_info) { + return false; + } + auto response_code = response_info->headers->response_code(); + if (response_code < 200 || response_code >= 300) { + if (response_code >= 500) { + // Only retry failures due to server error + return false; + } + *response_body = std::nullopt; + } + return true; +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/double_fetcher.h b/components/web_discovery/browser/double_fetcher.h new file mode 100644 index 000000000000..cbc8954b6e05 --- /dev/null +++ b/components/web_discovery/browser/double_fetcher.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_DOUBLE_FETCHER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_DOUBLE_FETCHER_H_ + +#include +#include +#include + +#include "base/memory/raw_ptr.h" +#include "base/timer/timer.h" +#include "base/values.h" +#include "net/base/backoff_entry.h" +#include "url/gurl.h" + +class PrefService; + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace web_discovery { + +class DoubleFetcher { + public: + using FetchedCallback = + base::RepeatingCallback response_body)>; + DoubleFetcher(PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + FetchedCallback callback); + ~DoubleFetcher(); + + DoubleFetcher(const DoubleFetcher&) = delete; + DoubleFetcher& operator=(const DoubleFetcher&) = delete; + + void ScheduleDoubleFetch(const GURL& url, base::Value associated_data); + + private: + void OnFetchTimer(); + void StartFetchTimer(base::TimeDelta delta); + void OnRequestComplete(std::optional response_body); + bool ProcessCompletedRequest(std::optional* response_body); + + raw_ptr profile_prefs_; + raw_ptr shared_url_loader_factory_; + std::unique_ptr url_loader_; + + net::BackoffEntry backoff_entry_; + + base::OneShotTimer fetch_timer_; + FetchedCallback callback_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_DOUBLE_FETCHER_H_ diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index 15a99a5952fc..556d4b2afce5 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -38,13 +38,13 @@ std::optional> ParseScrapeRules( const base::Value::Dict* scrape_url_dict) { std::vector result(scrape_url_dict->size()); + auto rule_group_it = result.begin(); for (const auto [selector, rule_group_value] : *scrape_url_dict) { auto* rule_group_dict = rule_group_value.GetIfDict(); if (!rule_group_dict) { VLOG(1) << "Rule group is not a dict"; return std::nullopt; } - auto rule_group_it = result.begin(); rule_group_it->selector = selector; rule_group_it->rules = std::vector(rule_group_dict->size()); diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index ed196b56ce0c..77ab0f48235a 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -8,13 +8,17 @@ namespace web_discovery { +// Profile prefs inline constexpr char kCredentialRSAPrivateKey[] = "brave.web_discovery.rsa_priv_key"; inline constexpr char kCredentialRSAPublicKey[] = "brave.web_discovery.rsa_pub_key"; inline constexpr char kAnonymousCredentialsDict[] = "brave.web_discovery.anon_creds"; +inline constexpr char kScheduledDoubleFetches[] = + "brave.web_discovery.scheduled_double_fetches"; +// Local state inline constexpr char kPatternsRetrievalTime[] = "brave.web_discovery.patterns_retrieval_time"; diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 926771cbb57f..76977264f1f3 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -29,15 +29,6 @@ namespace web_discovery { namespace { -constexpr net::BackoffEntry::Policy kBackoffPolicy = { - .num_errors_to_ignore = 0, - .initial_delay_ms = 10 * 1000, - .multiply_factor = 2.0, - .jitter_factor = 0.1, - .maximum_backoff_ms = 10 * 60 * 1000, - .entry_lifetime_ms = -1, - .always_use_initial_delay = false}; - constexpr base::TimeDelta kMinReloadInterval = base::Hours(1); constexpr base::TimeDelta kMaxReloadInterval = base::Hours(4); diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index d1663379bcb8..ff21514dd5fc 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -13,7 +13,6 @@ namespace web_discovery { namespace { constexpr char kCollectorHostPrefix[] = "collector.wdp"; constexpr char kPatternsHostPrefix[] = "patterns.wdp"; -constexpr char kVersionHeader[] = "Version"; constexpr char kPatternsPath[] = "/patterns.gz"; } // namespace @@ -36,8 +35,6 @@ std::unique_ptr CreateResourceRequest(GURL url) { auto resource_request = std::make_unique(); resource_request->url = url; resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; - resource_request->headers.SetHeader(kVersionHeader, - base::NumberToString(kCurrentVersion)); return resource_request; } diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index dd88175d84d9..fd9e75ac4a02 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -10,6 +10,7 @@ #include #include "base/time/time.h" +#include "net/base/backoff_entry.h" #include "services/network/public/cpp/resource_request.h" #include "url/gurl.h" @@ -19,6 +20,15 @@ inline constexpr size_t kMaxResponseSize = 16 * 1024; inline constexpr char kCollectorHostSwitch[] = "wdp-collector-host"; inline constexpr int kCurrentVersion = 1; +inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { + .num_errors_to_ignore = 0, + .initial_delay_ms = 10 * 1000, + .multiply_factor = 2.0, + .jitter_factor = 0.1, + .maximum_backoff_ms = 10 * 60 * 1000, + .entry_lifetime_ms = -1, + .always_use_initial_delay = false}; + std::string GetCollectorHost(); GURL GetPatternsEndpoint(); diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 5d79bf9804d3..ffe90d2c949a 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -9,6 +9,7 @@ #include "base/functional/bind.h" #include "brave/components/constants/pref_names.h" +#include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_registry_simple.h" @@ -49,6 +50,7 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kAnonymousCredentialsDict); registry->RegisterStringPref(kCredentialRSAPrivateKey, {}); registry->RegisterStringPref(kCredentialRSAPublicKey, {}); + registry->RegisterListPref(kScheduledDoubleFetches); } void WDPService::Start() { @@ -64,6 +66,7 @@ void WDPService::Start() { } void WDPService::Stop() { + double_fetcher_ = nullptr; content_scraper_ = nullptr; server_config_loader_ = nullptr; credential_manager_ = nullptr; @@ -86,6 +89,30 @@ void WDPService::OnConfigChange(std::unique_ptr config) { void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { last_loaded_patterns_ = std::move(patterns); content_scraper_ = std::make_unique(&last_loaded_patterns_); + double_fetcher_ = std::make_unique( + profile_prefs_.get(), shared_url_loader_factory_.get(), + base::BindRepeating(&WDPService::OnDoubleFetched, + base::Unretained(this))); +} + +void WDPService::OnDoubleFetched(const base::Value& associated_data, + std::optional response_body) { + if (!response_body) { + return; + } + auto prev_scrape_result = PageScrapeResult::FromValue(associated_data); + if (!prev_scrape_result) { + return; + } + auto* url_pattern = + content_scraper_->GetMatchingURLPattern(prev_scrape_result->url, true); + if (!url_pattern) { + return; + } + content_scraper_->ParseAndScrapePage( + std::move(prev_scrape_result), url_pattern, *response_body, + base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this), + true)); } void WDPService::OnFinishNavigation( @@ -102,15 +129,26 @@ void WDPService::OnFinishNavigation( render_frame_host->GetRemoteInterfaces()->GetInterface( remote.BindNewPipeAndPassReceiver()); auto remote_id = document_extractor_remotes_.Add(std::move(remote)); - content_scraper_->ScrapePage( - url_pattern, url, document_extractor_remotes_.Get(remote_id), - base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this))); + content_scraper_->ScrapePage(url_pattern, url, + document_extractor_remotes_.Get(remote_id), + base::BindOnce(&WDPService::OnContentScraped, + base::Unretained(this), false)); } -void WDPService::OnContentScraped(std::unique_ptr result) { +void WDPService::OnContentScraped(bool is_strict, + std::unique_ptr result) { if (!result) { return; } + if (!is_strict) { + if (!content_scraper_->GetMatchingURLPattern(result->url, true)) { + return; + } + double_fetcher_->ScheduleDoubleFetch(result->url, + result->SerializeToValue()); + } else { + // TODO(djandries): Create payload and schedule send + } } } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 3c741722670a..24801eb4937b 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -7,11 +7,14 @@ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_WDP_SERVICE_H_ #include +#include +#include #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" #include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/credential_manager.h" +#include "brave/components/web_discovery/browser/double_fetcher.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" @@ -57,7 +60,10 @@ class WDPService : public KeyedService { void OnConfigChange(std::unique_ptr config); void OnPatternsLoaded(std::unique_ptr patterns); - void OnContentScraped(std::unique_ptr result); + void OnContentScraped(bool is_strict, + std::unique_ptr result); + void OnDoubleFetched(const base::Value& associated_data, + std::optional response_body); raw_ptr local_state_; raw_ptr profile_prefs_; @@ -69,11 +75,13 @@ class WDPService : public KeyedService { mojo::RemoteSet document_extractor_remotes_; - std::unique_ptr server_config_loader_; std::unique_ptr last_loaded_server_config_; std::unique_ptr last_loaded_patterns_; + + std::unique_ptr server_config_loader_; std::unique_ptr credential_manager_; std::unique_ptr content_scraper_; + std::unique_ptr double_fetcher_; }; } // namespace web_discovery diff --git a/components/web_discovery/renderer/blink_document_extractor.cc b/components/web_discovery/renderer/blink_document_extractor.cc index 06b2a474f0f0..2fae50d9fef0 100644 --- a/components/web_discovery/renderer/blink_document_extractor.cc +++ b/components/web_discovery/renderer/blink_document_extractor.cc @@ -15,6 +15,8 @@ namespace web_discovery { namespace { +constexpr char kTextContentAttributeName[] = "textContent"; + mojom::AttributeResultPtr ProcessAttributeRequest( mojom::SelectAttributeRequest* request, const blink::WebVector& elements) { @@ -29,16 +31,21 @@ mojom::AttributeResultPtr ProcessAttributeRequest( sub_element = element.QuerySelector(web_sub_selector); element_to_query = &*sub_element; } - std::string attribute_value; if (element_to_query->IsNull()) { continue; } - auto attribute_name = blink::WebString::FromUTF8(request->attribute); - auto web_attribute_value = element_to_query->GetAttribute(attribute_name); - if (web_attribute_value.IsNull()) { - continue; + std::string attribute_value; + if (request->attribute == kTextContentAttributeName) { + attribute_value = element_to_query->TextContent().Utf8(); + } else { + auto attribute_name = blink::WebString::FromUTF8(request->attribute); + auto web_attribute_value = element_to_query->GetAttribute(attribute_name); + if (web_attribute_value.IsNull()) { + continue; + } + attribute_value = web_attribute_value.Utf8(); } - attributes_result->attribute_values.push_back(web_attribute_value.Utf8()); + attributes_result->attribute_values.push_back(attribute_value); } return attributes_result; } diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock index f34713c7d7fe..4bf611fee499 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock @@ -401,6 +401,7 @@ dependencies = [ "brave_wallet", "challenge-bypass-ristretto-cxx", "constellation-cxx", + "document-extractor-cxx", "filecoin-cxx", "json-cxx", "skus-cxx", @@ -684,6 +685,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "document-extractor-cxx" +version = "0.1.0" +dependencies = [ + "cxx", + "html5ever", + "kuchikiki", +] + [[package]] name = "dtoa" version = "0.4.8" diff --git a/third_party/rust/chromium_crates_io/Cargo.toml b/third_party/rust/chromium_crates_io/Cargo.toml index 3b4dbd844f62..465ffeafebc2 100644 --- a/third_party/rust/chromium_crates_io/Cargo.toml +++ b/third_party/rust/chromium_crates_io/Cargo.toml @@ -27,6 +27,7 @@ constellation-cxx = "0.1" challenge-bypass-ristretto-cxx = "1" zcash = "1" anonymous-credentials-cxx = "0.1" +document-extractor-cxx = "0.1" [patch.crates-io.futures-retry_v0_5] path = "../futures_retry/v0_5/crate" @@ -88,6 +89,10 @@ package = "anonymous-credentials" path = "../../../components/web_discovery/browser/anonymous_credentials/rs/cxx" package = "anonymous-credentials-cxx" +[patch.crates-io.document-extractor_v0_1] +path = "../../../components/web_discovery/browser/document_extractor/rs" +package = "document-extractor-cxx" + [patch.crates-io.aho_corasick_v1] path = "../../../../third_party/rust/chromium_crates_io/vendor/aho-corasick-1.1.3" package = "aho-corasick" diff --git a/third_party/rust/document_extractor_cxx/v0_1/README.chromium b/third_party/rust/document_extractor_cxx/v0_1/README.chromium new file mode 100644 index 000000000000..12c09b35e965 --- /dev/null +++ b/third_party/rust/document_extractor_cxx/v0_1/README.chromium @@ -0,0 +1,8 @@ +Name: document-extractor-cxx +URL: https://crates.io/crates/document-extractor-cxx +Description: +Version: 0.1.0 +Security Critical: yes +Shipped: yes +License: Mozilla Public License 2.0 +License File: From 42934f49dea2a18bd92a374c914621988c6988f6 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Fri, 31 May 2024 17:31:10 -0700 Subject: [PATCH 12/36] Add Web Discovery payload generator --- components/web_discovery/browser/BUILD.gn | 2 + .../web_discovery/browser/content_scraper.cc | 80 +++++------ .../web_discovery/browser/content_scraper.h | 5 +- .../browser/document_extractor/rs/src/lib.rs | 58 +++++--- .../web_discovery/browser/double_fetcher.cc | 3 +- components/web_discovery/browser/patterns.cc | 123 ++++++++++++++++- components/web_discovery/browser/patterns.h | 34 ++++- .../browser/payload_generator.cc | 126 ++++++++++++++++++ .../web_discovery/browser/payload_generator.h | 24 ++++ .../web_discovery/browser/wdp_service.cc | 17 ++- .../web_discovery/browser/wdp_service.h | 3 + .../web_discovery/common/web_discovery.mojom | 4 +- .../renderer/blink_document_extractor.cc | 62 +++++---- 13 files changed, 431 insertions(+), 110 deletions(-) create mode 100644 components/web_discovery/browser/payload_generator.cc create mode 100644 components/web_discovery/browser/payload_generator.h diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index a27eb1ba782c..9bebd05c612a 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -13,6 +13,8 @@ static_library("browser") { "double_fetcher.h", "patterns.cc", "patterns.h", + "payload_generator.cc", + "payload_generator.h", "pref_names.h", "rsa.cc", "rsa.h", diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 6b81dcc63d3f..3f08edab8967 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -9,7 +9,6 @@ #include "base/ranges/algorithm.h" #include "base/task/thread_pool.h" -#include "third_party/re2/src/re2/re2.h" namespace web_discovery { @@ -37,12 +36,12 @@ base::Value PageScrapeResult::SerializeToValue() { base::Value::Dict result; base::Value::Dict fields_dict; - for (const auto& [key, values] : fields) { + for (const auto& [root_selector, inner_fields] : fields) { base::Value::List list; - for (const auto& value : values) { - list.Append(value); + for (const auto& values : inner_fields) { + list.Append(values.Clone()); } - fields_dict.Set(key, std::move(list)); + fields_dict.Set(root_selector, std::move(list)); } result.Set(kFieldsValueKey, std::move(fields_dict)); @@ -66,34 +65,23 @@ std::unique_ptr PageScrapeResult::FromValue( } auto result = std::make_unique(GURL(*url), *id); - for (const auto [key, values] : *fields_dict) { - std::vector values_vec; - for (const auto& val : values.GetList()) { - if (!val.is_string()) { - return nullptr; + for (const auto [root_selector, inner_fields_val] : *fields_dict) { + const auto* inner_fields_list = inner_fields_val.GetIfList(); + if (!inner_fields_list) { + continue; + } + for (const auto& values : *inner_fields_list) { + const auto* values_dict = values.GetIfDict(); + if (!values_dict) { + continue; } - values_vec.push_back(val.GetString()); + result->fields[root_selector].push_back(values_dict->Clone()); } - result->fields[key] = std::move(values_vec); } return result; } -const PatternsURLDetails* ContentScraper::GetMatchingURLPattern( - const GURL& url, - bool is_strict_scrape) { - const auto& patterns = is_strict_scrape ? patterns_->get()->strict_patterns - : patterns_->get()->normal_patterns; - for (const auto& pattern : patterns) { - if (re2::RE2::PartialMatch(url.spec(), *pattern.url_regex) && - !pattern.scrape_rule_groups.empty()) { - return &pattern; - } - } - return nullptr; -} - void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, const GURL& url, mojom::DocumentExtractor* document_extractor, @@ -107,7 +95,7 @@ void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, select_request->root_selector = group.selector; for (const auto& rule : group.rules) { if (rule.rule_type == ScrapeRuleType::kStandard) { - ProcessStandardRule(rule, url, interim_result.get()); + ProcessStandardRule(rule, group.selector, url, interim_result.get()); continue; } auto attribute_request = mojom::SelectAttributeRequest::New(); @@ -141,7 +129,8 @@ void ContentScraper::ParseAndScrapePage( select_request.root_selector = group.selector; for (const auto& rule : group.rules) { if (rule.rule_type == ScrapeRuleType::kStandard) { - ProcessStandardRule(rule, interim_result->url, interim_result.get()); + ProcessStandardRule(rule, group.selector, interim_result->url, + interim_result.get()); continue; } rust_document_extractor::SelectAttributeRequest attribute_request{ @@ -164,11 +153,13 @@ void ContentScraper::ParseAndScrapePage( } void ContentScraper::ProcessStandardRule(const ScrapeRule& rule, + const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result) { if (rule.attribute == kUrlAttrId) { - scrape_result->fields.insert_or_assign( - rule.report_key, std::vector({url.spec()})); + base::Value::Dict dict; + dict.Set(rule.report_key, url.spec()); + scrape_result->fields[root_selector].push_back(std::move(dict)); } } @@ -177,8 +168,16 @@ void ContentScraper::OnScrapedElementAttributes( PageScrapeResultCallback callback, std::vector attribute_results) { for (const auto& attribute_result : attribute_results) { - scrape_result->fields.insert_or_assign(attribute_result->key, - attribute_result->attribute_values); + base::Value::Dict attribute_values; + for (const auto& [key, value_str] : attribute_result->attribute_values) { + base::Value value; + if (value_str) { + value = base::Value(*value_str); + } + attribute_values.Set(key, std::move(value)); + } + scrape_result->fields[attribute_result->root_selector].push_back( + std::move(attribute_values)); } std::move(callback).Run(std::move(scrape_result)); } @@ -188,13 +187,16 @@ void ContentScraper::OnRustElementAttributes( PageScrapeResultCallback callback, rust::Vec attribute_results) { for (const auto& attribute_result : attribute_results) { - std::vector attribute_values; - base::ranges::transform(attribute_result.attribute_values.begin(), - attribute_result.attribute_values.end(), - std::back_inserter(attribute_values), - [](auto value) { return std::string(value); }); - scrape_result->fields.insert_or_assign(std::string(attribute_result.key), - attribute_values); + base::Value::Dict attribute_values; + for (const auto& pair : attribute_result.attribute_pairs) { + base::Value value; + if (!pair.value.empty()) { + value = base::Value(std::string(pair.value)); + } + attribute_values.Set(std::string(pair.key), std::move(value)); + } + scrape_result->fields[std::string(attribute_result.root_selector)] + .push_back(std::move(attribute_values)); } std::move(callback).Run(std::move(scrape_result)); } diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index e5856c2fabf1..3d856cd00332 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -31,7 +31,7 @@ struct PageScrapeResult { static std::unique_ptr FromValue(const base::Value& dict); GURL url; - base::flat_map> fields; + base::flat_map> fields; std::string id; }; @@ -46,8 +46,6 @@ class ContentScraper { ContentScraper(const ContentScraper&) = delete; ContentScraper& operator=(const ContentScraper&) = delete; - const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, - bool is_strict_scrape); // For initial page scrape in renderer void ScrapePage(const PatternsURLDetails* url_details, const GURL& url, @@ -61,6 +59,7 @@ class ContentScraper { private: void ProcessStandardRule(const ScrapeRule& rule, + const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result); void OnScrapedElementAttributes( diff --git a/components/web_discovery/browser/document_extractor/rs/src/lib.rs b/components/web_discovery/browser/document_extractor/rs/src/lib.rs index 592670b50707..ac52e8940731 100644 --- a/components/web_discovery/browser/document_extractor/rs/src/lib.rs +++ b/components/web_discovery/browser/document_extractor/rs/src/lib.rs @@ -27,9 +27,14 @@ mod ffi { pub attribute_requests: Vec, } - pub struct AttributeResult { + pub struct AttributePair { pub key: String, - pub attribute_values: Vec, + pub value: String, + } + + pub struct AttributeResult { + pub root_selector: String, + pub attribute_pairs: Vec, } extern "Rust" { @@ -45,34 +50,46 @@ use ffi::*; const TEXT_CONTENT_ATTRIBUTE_NAME: &str = "textContent"; fn extract_attributes_from_nodes( + root_selector: &str, attribute_requests: &[SelectAttributeRequest], nodes: Select>, -) -> HashMap> { - let mut result: HashMap> = HashMap::new(); + results: &mut Vec, +) { for node in nodes { + let mut attribute_map = HashMap::new(); for attribute_request in attribute_requests { let sub_node = match attribute_request.sub_selector.is_empty() { false => match node.as_node().select_first(&attribute_request.sub_selector) { Ok(e) => Some(e), - Err(_) => continue, + Err(_) => { + attribute_map.insert(attribute_request.key.clone(), String::new()); + continue; + } }, true => None, }; let node_to_query = sub_node.as_ref().unwrap_or(&node).as_node(); let attribute_value = match attribute_request.attribute == TEXT_CONTENT_ATTRIBUTE_NAME { - true => Some(node_to_query.text_contents()), - false => node_to_query.as_element().and_then(|element| { - let attributes = element.attributes.borrow(); - attributes.get(attribute_request.attribute.as_str()).map(|v| v.to_string()) - }), + true => node_to_query.text_contents(), + false => node_to_query + .as_element() + .and_then(|element| { + let attributes = element.attributes.borrow(); + attributes.get(attribute_request.attribute.as_str()).map(|v| v.to_string()) + }) + .unwrap_or_default(), }; - if let Some(value) = attribute_value { - result.entry(attribute_request.key.clone()).or_default().push(value); - } + attribute_map.insert(attribute_request.key.clone(), attribute_value); } + results.push(AttributeResult { + root_selector: root_selector.to_string(), + attribute_pairs: attribute_map + .into_iter() + .map(|(key, value)| AttributePair { key, value }) + .collect(), + }); } - result } pub fn query_element_attributes( @@ -80,16 +97,17 @@ pub fn query_element_attributes( requests: &CxxVector, ) -> Vec { let mut sink = parse_html().one(html.to_str().unwrap_or_default()); - let mut result = Vec::new(); + let mut results = Vec::new(); let document = sink.get_document(); for request in requests { if let Ok(nodes) = document.select(&request.root_selector) { - result.extend( - extract_attributes_from_nodes(&request.attribute_requests, nodes) - .into_iter() - .map(|(key, attribute_values)| AttributeResult { key, attribute_values }), + extract_attributes_from_nodes( + &request.root_selector, + &request.attribute_requests, + nodes, + &mut results, ); } } - result + results } diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index 42e02be8e535..41a425554c33 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -24,7 +24,8 @@ constexpr char kRequestTimeKey[] = "request_time"; constexpr char kRetriesKey[] = "retries"; constexpr base::TimeDelta kRequestMaxAge = base::Hours(1); -constexpr base::TimeDelta kRequestInterval = base::Minutes(1); +// constexpr base::TimeDelta kRequestInterval = base::Minutes(1); +constexpr base::TimeDelta kRequestInterval = base::Seconds(5); constexpr size_t kMaxRetries = 3; constexpr size_t kMaxDoubleFetchResponseSize = 2 * 1024 * 1024; diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index 556d4b2afce5..9725e04b6a32 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -26,13 +26,98 @@ constexpr char kScrapeRulesKey[] = "scrape"; constexpr char kSubSelectorKey[] = "item"; constexpr char kRuleTypeKey[] = "type"; constexpr char kAttributeKey[] = "etype"; +constexpr char kResultTypeKey[] = "results"; +constexpr char kActionKey[] = "action"; +constexpr char kFieldsKey[] = "fields"; +constexpr char kPayloadsKey[] = "payloads"; +constexpr char kJoinFieldAction[] = "join"; -constexpr auto kRuleTypeMap = +constexpr auto kScrapeRuleTypeMap = base::MakeFixedFlatMap({ {"standard", ScrapeRuleType::kStandard}, {"searchQuery", ScrapeRuleType::kSearchQuery}, {"widgetTitle", ScrapeRuleType::kWidgetTitle}, }); +constexpr auto kPayloadRuleTypeMap = + base::MakeFixedFlatMap({ + {"query", PayloadRuleType::kQuery}, + {"single", PayloadRuleType::kSingle}, + }); +constexpr auto kPayloadResultTypeMap = + base::MakeFixedFlatMap({ + {"single", PayloadResultType::kSingle}, + {"clustered", PayloadResultType::kClustered}, + {"custom", PayloadResultType::kCustom}, + }); + +bool ParsePayloadRule(const base::Value& rule_value, PayloadRule* rule_out) { + auto* rule_list = rule_value.GetIfList(); + if (!rule_list || rule_list->size() < 2) { + VLOG(1) << "Payload rule details is not a list of appropiate size"; + return false; + } + auto* selector = (*rule_list)[0].GetIfString(); + auto* payload_key = (*rule_list)[1].GetIfString(); + if (!selector || !payload_key) { + VLOG(1) << "Selector or key missing from payload rule"; + return false; + } + rule_out->selector = *selector; + rule_out->key = *payload_key; + if (rule_list->size() > 2) { + auto* field_action = (*rule_list)[2].GetIfString(); + if (field_action && *field_action == kJoinFieldAction) { + rule_out->is_join = true; + } + } + return true; +} + +std::optional> ParsePayloadRules( + const base::Value::Dict* payload_dict) { + std::vector result(payload_dict->size()); + + auto rule_group_it = result.begin(); + for (const auto [key, rule_group_value] : *payload_dict) { + auto* rule_group_dict = rule_group_value.GetIfDict(); + if (!rule_group_dict) { + VLOG(1) << "Payload rule group is not a dict"; + return std::nullopt; + } + auto* action = rule_group_dict->FindString(kActionKey); + auto* fields = rule_group_dict->FindList(kFieldsKey); + auto* rule_type_str = rule_group_dict->FindString(kRuleTypeKey); + auto* result_type_str = rule_group_dict->FindString(kResultTypeKey); + if (!action || !rule_type_str || !result_type_str) { + VLOG(1) << "Payload rule group attributes missing"; + return std::nullopt; + } + auto rule_type_it = kPayloadRuleTypeMap.find(*rule_type_str); + auto result_type_it = kPayloadResultTypeMap.find(*result_type_str); + if (rule_type_it == kPayloadRuleTypeMap.end() || + result_type_it == kPayloadResultTypeMap.end()) { + VLOG(1) << "Payload rule or result types unknown"; + return std::nullopt; + } + rule_group_it->key = key; + rule_group_it->result_type = result_type_it->second; + rule_group_it->rule_type = rule_type_it->second; + if (fields) { + rule_group_it->rules = std::vector(fields->size()); + + auto rule_it = rule_group_it->rules.begin(); + for (const auto& rule_value : *fields) { + if (!ParsePayloadRule(rule_value, rule_it.base())) { + return std::nullopt; + } + rule_it = std::next(rule_it); + } + } + + rule_group_it = std::next(rule_group_it); + } + return result; +} std::optional> ParseScrapeRules( const base::Value::Dict* scrape_url_dict) { @@ -42,7 +127,7 @@ std::optional> ParseScrapeRules( for (const auto [selector, rule_group_value] : *scrape_url_dict) { auto* rule_group_dict = rule_group_value.GetIfDict(); if (!rule_group_dict) { - VLOG(1) << "Rule group is not a dict"; + VLOG(1) << "Scrape rule group is not a dict"; return std::nullopt; } rule_group_it->selector = selector; @@ -52,7 +137,7 @@ std::optional> ParseScrapeRules( for (const auto [report_key, rule_value] : *rule_group_dict) { auto* rule_dict = rule_value.GetIfDict(); if (!rule_dict) { - VLOG(1) << "Rule details is not a dict"; + VLOG(1) << "Scrape rule details is not a dict"; return std::nullopt; } auto* sub_selector = rule_dict->FindString(kSubSelectorKey); @@ -65,8 +150,8 @@ std::optional> ParseScrapeRules( rule_it->report_key = report_key; rule_it->rule_type = ScrapeRuleType::kOther; if (rule_type_str) { - auto rule_type_it = kRuleTypeMap.find(*rule_type_str); - if (rule_type_it != kRuleTypeMap.end()) { + auto rule_type_it = kScrapeRuleTypeMap.find(*rule_type_str); + if (rule_type_it != kScrapeRuleTypeMap.end()) { rule_it->rule_type = rule_type_it->second; } } @@ -87,6 +172,7 @@ std::optional> ParsePatternsURLDetails( auto* url_patterns_list = root_dict->FindList(kUrlPatternsKey); auto* search_engines_list = root_dict->FindList(kSearchEnginesKey); auto* scrape_dict = root_dict->FindDict(kScrapeRulesKey); + auto* payloads_dict = root_dict->FindDict(kPayloadsKey); auto* id_mapping_dict = root_dict->FindDict(kIdMappingKey); if (!url_patterns_list || !search_engines_list || !scrape_dict || !id_mapping_dict) { @@ -111,6 +197,7 @@ std::optional> ParsePatternsURLDetails( auto* id = id_mapping_dict->FindString(i_str); auto* scrape_url_dict = scrape_dict->FindDict(i_str); + auto* payloads_url_dict = payloads_dict->FindDict(i_str); if (!id || !scrape_url_dict) { VLOG(1) << "ID or scrape dict missing for pattern"; return std::nullopt; @@ -127,6 +214,13 @@ std::optional> ParsePatternsURLDetails( return std::nullopt; } details.scrape_rule_groups = std::move(*scrape_rule_groups); + if (payloads_url_dict) { + auto payload_rule_groups = ParsePayloadRules(payloads_url_dict); + if (!payload_rule_groups) { + return std::nullopt; + } + details.payload_rule_groups = std::move(*payload_rule_groups); + } } return result; @@ -140,12 +234,31 @@ ScrapeRule::~ScrapeRule() = default; ScrapeRuleGroup::ScrapeRuleGroup() = default; ScrapeRuleGroup::~ScrapeRuleGroup() = default; +PayloadRule::PayloadRule() = default; +PayloadRule::~PayloadRule() = default; + +PayloadRuleGroup::PayloadRuleGroup() = default; +PayloadRuleGroup::~PayloadRuleGroup() = default; + PatternsURLDetails::PatternsURLDetails() = default; PatternsURLDetails::~PatternsURLDetails() = default; PatternsGroup::PatternsGroup() = default; PatternsGroup::~PatternsGroup() = default; +const PatternsURLDetails* PatternsGroup::GetMatchingURLPattern( + const GURL& url, + bool is_strict_scrape) { + const auto& patterns = is_strict_scrape ? strict_patterns : normal_patterns; + for (const auto& pattern : patterns) { + if (re2::RE2::PartialMatch(url.spec(), *pattern.url_regex) && + !pattern.scrape_rule_groups.empty()) { + return &pattern; + } + } + return nullptr; +} + std::unique_ptr ParsePatterns(const std::string& patterns_json) { auto result = std::make_unique(); auto patterns_value = base::JSONReader::Read(patterns_json); diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index 509214215603..b3bc6f1050e7 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -11,7 +11,7 @@ #include #include -#include "base/containers/flat_map.h" +#include "url/gurl.h" namespace re2 { class RE2; @@ -20,6 +20,8 @@ class RE2; namespace web_discovery { enum class ScrapeRuleType { kStandard, kSearchQuery, kWidgetTitle, kOther }; +enum class PayloadRuleType { kQuery, kSingle }; +enum class PayloadResultType { kSingle, kClustered, kCustom }; struct ScrapeRule { ScrapeRule(); @@ -46,6 +48,32 @@ struct ScrapeRuleGroup { std::vector rules; }; +struct PayloadRule { + PayloadRule(); + ~PayloadRule(); + + PayloadRule(const PayloadRule&) = delete; + PayloadRule& operator=(const PayloadRule&) = delete; + + std::string selector; + std::string key; + bool is_join = false; +}; + +struct PayloadRuleGroup { + PayloadRuleGroup(); + ~PayloadRuleGroup(); + + PayloadRuleGroup(const PayloadRuleGroup&) = delete; + PayloadRuleGroup& operator=(const PayloadRuleGroup&) = delete; + + std::string key; + PayloadRuleType rule_type; + PayloadResultType result_type; + std::string action; + std::vector rules; +}; + struct PatternsURLDetails { PatternsURLDetails(); ~PatternsURLDetails(); @@ -57,6 +85,7 @@ struct PatternsURLDetails { bool is_search_engine; std::string id; std::vector scrape_rule_groups; + std::vector payload_rule_groups; }; struct PatternsGroup { @@ -66,6 +95,9 @@ struct PatternsGroup { PatternsGroup(const PatternsGroup&) = delete; PatternsGroup& operator=(const PatternsGroup&) = delete; + const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, + bool is_strict_scrape); + std::vector normal_patterns; std::vector strict_patterns; }; diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc new file mode 100644 index 000000000000..b58c245fbbbb --- /dev/null +++ b/components/web_discovery/browser/payload_generator.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/payload_generator.h" + +#include + +namespace web_discovery { + +namespace { + +constexpr char kActionKey[] = "action"; +constexpr char kInnerPayloadKey[] = "payload"; + +bool ValueHasContent(const base::Value& value) { + const auto* value_str = value.GetIfString(); + if (value_str && !value_str->empty()) { + return true; + } + if (!value.is_none()) { + return true; + } + return false; +} + +bool AggregatedDictHasContent(const base::Value::Dict& dict) { + for (const auto [_k1, value] : dict) { + const auto* value_dict = value.GetIfDict(); + if (!value_dict) { + continue; + } + for (const auto [_k2, sub_value] : *value_dict) { + if (ValueHasContent(sub_value)) { + return true; + } + } + } + return false; +} + +base::Value::Dict CreatePayloadDict(const PayloadRuleGroup& rule_group, + base::Value::Dict inner_payload) { + base::Value::Dict payload; + payload.Set(kActionKey, rule_group.action); + payload.Set(kInnerPayloadKey, std::move(inner_payload)); + return payload; +} + +std::optional GenerateClusteredPayload( + const PayloadRuleGroup& rule_group, + const PageScrapeResult* scrape_result) { + base::Value::Dict inner_payload; + for (const auto& rule : rule_group.rules) { + base::Value payload_rule_data; + auto attribute_values_it = scrape_result->fields.find(rule.selector); + if (attribute_values_it == scrape_result->fields.end() || + attribute_values_it->second.empty()) { + // TODO(djandries): remove this exception and actually insert ctry + if (rule.selector == "ctry") { + continue; + } + return std::nullopt; + } + if (rule.is_join) { + base::Value::Dict joined_data; + size_t counter = 0; + for (const auto& value : attribute_values_it->second) { + if (value.empty()) { + continue; + } + joined_data.Set(base::NumberToString(counter++), value.Clone()); + } + if (!AggregatedDictHasContent(joined_data)) { + VLOG(1) << "Skipped joined clustered payload"; + return std::nullopt; + } + payload_rule_data = base::Value(std::move(joined_data)); + } else { + const auto* value = attribute_values_it->second[0].FindString(rule.key); + if (!value || value->empty()) { + VLOG(1) << "Skipped non-joined clustered payload"; + return std::nullopt; + } + payload_rule_data = base::Value(*value); + } + inner_payload.Set(rule.key, std::move(payload_rule_data)); + } + return CreatePayloadDict(rule_group, std::move(inner_payload)); +} + +void GenerateSinglePayloads(const PayloadRuleGroup& rule_group, + const PageScrapeResult* scrape_result, + std::vector& payloads) { + auto attribute_values_it = scrape_result->fields.find(rule_group.key); + if (attribute_values_it == scrape_result->fields.end()) { + return; + } + for (const auto& attribute_value : attribute_values_it->second) { + payloads.push_back(CreatePayloadDict(rule_group, attribute_value.Clone())); + } +} + +} // namespace + +std::vector GeneratePayloads( + const PatternsURLDetails* url_details, + std::unique_ptr scrape_result) { + std::vector payloads; + for (const auto& rule_group : url_details->payload_rule_groups) { + if (rule_group.rule_type == PayloadRuleType::kQuery && + rule_group.result_type == PayloadResultType::kClustered) { + auto payload = GenerateClusteredPayload(rule_group, scrape_result.get()); + if (payload) { + payloads.push_back(std::move(*payload)); + } + } else if (rule_group.rule_type == PayloadRuleType::kSingle && + rule_group.result_type == PayloadResultType::kSingle) { + GenerateSinglePayloads(rule_group, scrape_result.get(), payloads); + } + } + return payloads; +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h new file mode 100644 index 000000000000..7a57cc18db5b --- /dev/null +++ b/components/web_discovery/browser/payload_generator.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ + +#include +#include + +#include "base/values.h" +#include "brave/components/web_discovery/browser/content_scraper.h" +#include "brave/components/web_discovery/browser/patterns.h" + +namespace web_discovery { + +std::vector GeneratePayloads( + const PatternsURLDetails* url_details, + std::unique_ptr scrape_result); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index ffe90d2c949a..8c57633504ba 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -104,8 +104,8 @@ void WDPService::OnDoubleFetched(const base::Value& associated_data, if (!prev_scrape_result) { return; } - auto* url_pattern = - content_scraper_->GetMatchingURLPattern(prev_scrape_result->url, true); + auto* url_pattern = last_loaded_patterns_->GetMatchingURLPattern( + prev_scrape_result->url, true); if (!url_pattern) { return; } @@ -121,7 +121,7 @@ void WDPService::OnFinishNavigation( if (!content_scraper_) { return; } - auto* url_pattern = content_scraper_->GetMatchingURLPattern(url, false); + auto* url_pattern = last_loaded_patterns_->GetMatchingURLPattern(url, false); if (!url_pattern) { return; } @@ -140,14 +140,17 @@ void WDPService::OnContentScraped(bool is_strict, if (!result) { return; } + auto* url_details = + last_loaded_patterns_->GetMatchingURLPattern(result->url, true); + if (!url_details) { + return; + } if (!is_strict) { - if (!content_scraper_->GetMatchingURLPattern(result->url, true)) { - return; - } double_fetcher_->ScheduleDoubleFetch(result->url, result->SerializeToValue()); } else { - // TODO(djandries): Create payload and schedule send + auto payloads = GeneratePayloads(url_details, std::move(result)); + // TODO(djandries): send payloads } } diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 24801eb4937b..6aeb8e19863e 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -16,6 +16,7 @@ #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/double_fetcher.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/payload_generator.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -60,6 +61,8 @@ class WDPService : public KeyedService { void OnConfigChange(std::unique_ptr config); void OnPatternsLoaded(std::unique_ptr patterns); + void extracted(std::unique_ptr& result, + const PatternsURLDetails*& url_details); void OnContentScraped(bool is_strict, std::unique_ptr result); void OnDoubleFetched(const base::Value& associated_data, diff --git a/components/web_discovery/common/web_discovery.mojom b/components/web_discovery/common/web_discovery.mojom index 198f5ab6931d..709d3bab3a57 100644 --- a/components/web_discovery/common/web_discovery.mojom +++ b/components/web_discovery/common/web_discovery.mojom @@ -17,8 +17,8 @@ struct SelectRequest { }; struct AttributeResult { - string key; - array attribute_values; + string root_selector; + map attribute_values; }; interface DocumentExtractor { diff --git a/components/web_discovery/renderer/blink_document_extractor.cc b/components/web_discovery/renderer/blink_document_extractor.cc index 2fae50d9fef0..cffd7cf0d9bb 100644 --- a/components/web_discovery/renderer/blink_document_extractor.cc +++ b/components/web_discovery/renderer/blink_document_extractor.cc @@ -17,37 +17,40 @@ namespace { constexpr char kTextContentAttributeName[] = "textContent"; -mojom::AttributeResultPtr ProcessAttributeRequest( - mojom::SelectAttributeRequest* request, - const blink::WebVector& elements) { - auto attributes_result = mojom::AttributeResult::New(); - attributes_result->key = request->key; +void ProcessAttributeRequests( + std::string root_selector, + const std::vector& requests, + const blink::WebVector& elements, + std::vector& results) { for (const auto& element : elements) { + auto attributes_result = mojom::AttributeResult::New(); + attributes_result->root_selector = root_selector; + std::optional sub_element; const auto* element_to_query = &element; - if (request->sub_selector) { - auto web_sub_selector = - blink::WebString::FromUTF8(*request->sub_selector); - sub_element = element.QuerySelector(web_sub_selector); - element_to_query = &*sub_element; - } - if (element_to_query->IsNull()) { - continue; - } - std::string attribute_value; - if (request->attribute == kTextContentAttributeName) { - attribute_value = element_to_query->TextContent().Utf8(); - } else { - auto attribute_name = blink::WebString::FromUTF8(request->attribute); - auto web_attribute_value = element_to_query->GetAttribute(attribute_name); - if (web_attribute_value.IsNull()) { - continue; + for (const auto& request : requests) { + if (request->sub_selector) { + auto web_sub_selector = + blink::WebString::FromUTF8(*request->sub_selector); + sub_element = element.QuerySelector(web_sub_selector); + element_to_query = &*sub_element; } - attribute_value = web_attribute_value.Utf8(); + std::optional attribute_value; + if (!element_to_query->IsNull()) { + if (request->attribute == kTextContentAttributeName) { + attribute_value = element_to_query->TextContent().Utf8(); + } else { + auto attribute_name = blink::WebString::FromUTF8(request->attribute); + auto web_attribute_value = + element_to_query->GetAttribute(attribute_name); + if (!web_attribute_value.IsNull()) { + attribute_value = web_attribute_value.Utf8(); + } + } + } + attributes_result->attribute_values[request->key] = attribute_value; } - attributes_result->attribute_values.push_back(attribute_value); } - return attributes_result; } } // namespace @@ -68,15 +71,10 @@ void BlinkDocumentExtractor::QueryElementAttributes( blink::WebDocument document = render_frame_->GetWebFrame()->GetDocument(); std::vector results; for (const auto& request : requests) { - auto result = mojom::AttributeResult::New(); - auto selector = blink::WebString::FromUTF8(request->root_selector); auto elements = document.QuerySelectorAll(selector); - for (const auto& attribute_request : request->attribute_requests) { - auto attributes_result = - ProcessAttributeRequest(attribute_request.get(), elements); - results.push_back(std::move(attributes_result)); - } + ProcessAttributeRequests(request->root_selector, + request->attribute_requests, elements, results); } std::move(callback).Run(std::move(results)); From 6c63f17e7f48f513889c55a545bae9f64c562620 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 5 Jun 2024 16:46:14 -0700 Subject: [PATCH 13/36] Add Web Discovery reporter, ECDH-AES encryption --- components/web_discovery/browser/BUILD.gn | 9 + components/web_discovery/browser/DEPS | 2 +- .../browser/credential_manager.cc | 49 ++-- .../browser/credential_manager.h | 10 +- .../web_discovery/browser/double_fetcher.cc | 96 +++---- .../web_discovery/browser/double_fetcher.h | 9 +- components/web_discovery/browser/ecdh_aes.cc | 153 +++++++++++ components/web_discovery/browser/ecdh_aes.h | 33 +++ .../browser/payload_generator.cc | 3 - .../web_discovery/browser/payload_generator.h | 3 + components/web_discovery/browser/pref_names.h | 4 + components/web_discovery/browser/reporter.cc | 259 ++++++++++++++++++ components/web_discovery/browser/reporter.h | 81 ++++++ .../web_discovery/browser/request_queue.cc | 120 ++++++++ .../web_discovery/browser/request_queue.h | 59 ++++ .../browser/server_config_loader.cc | 43 ++- .../browser/server_config_loader.h | 14 + .../browser/signature_basename.cc | 217 +++++++++++++++ .../browser/signature_basename.h | 39 +++ .../web_discovery/browser/wdp_service.cc | 10 +- .../web_discovery/browser/wdp_service.h | 4 +- 21 files changed, 1118 insertions(+), 99 deletions(-) create mode 100644 components/web_discovery/browser/ecdh_aes.cc create mode 100644 components/web_discovery/browser/ecdh_aes.h create mode 100644 components/web_discovery/browser/reporter.cc create mode 100644 components/web_discovery/browser/reporter.h create mode 100644 components/web_discovery/browser/request_queue.cc create mode 100644 components/web_discovery/browser/request_queue.h create mode 100644 components/web_discovery/browser/signature_basename.cc create mode 100644 components/web_discovery/browser/signature_basename.h diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 9bebd05c612a..034e002b58d6 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -11,15 +11,23 @@ static_library("browser") { "credential_manager.h", "double_fetcher.cc", "double_fetcher.h", + "ecdh_aes.cc", + "ecdh_aes.h", "patterns.cc", "patterns.h", "payload_generator.cc", "payload_generator.h", "pref_names.h", + "reporter.cc", + "reporter.h", + "request_queue.cc", + "request_queue.h", "rsa.cc", "rsa.h", "server_config_loader.cc", "server_config_loader.h", + "signature_basename.cc", + "signature_basename.h", "util.cc", "util.h", "wdp_service.cc", @@ -37,6 +45,7 @@ static_library("browser") { "//components/keyed_service/core", "//components/prefs", "//content/public/browser", + "//crypto", "//net", "//services/network/public/cpp", "//third_party/boringssl", diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index e331506526be..b3b1eb332554 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -4,5 +4,5 @@ include_rules = [ "+services/service_manager/public/cpp", "+third_party/boringssl/src/include", "+third_party/re2", - "+third_party/zlib/google", + "+third_party/zlib", ] diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 3c8fe8377cfa..fac586fead2b 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -101,6 +101,20 @@ std::optional FinishJoin( return base::Base64Encode(finish_res.data); } +std::optional> PerformSign( + anonymous_credentials::CredentialManager* anonymous_credential_manager, + std::vector msg, + std::vector basename) { + auto sig_res = anonymous_credential_manager->sign( + rust::Slice(msg.data(), msg.size()), + rust::Slice(basename.data(), basename.size())); + if (!sig_res.error_message.empty()) { + VLOG(1) << "Failed to sign: " << sig_res.error_message.c_str(); + return std::nullopt; + } + return std::vector(sig_res.data.begin(), sig_res.data.end()); +} + } // namespace CredentialManager::CredentialManager( @@ -354,10 +368,14 @@ void CredentialManager::OnCredentialsReady( HandleJoinResponseStatus(date, true); } -std::optional> CredentialManager::Sign( - const std::vector& msg, - const std::vector& basename) { - // TODO(djandries): execute on thread pool +bool CredentialManager::CredentialExistsForToday() { + return profile_prefs_->GetDict(kAnonymousCredentialsDict) + .contains(FormatServerDate(base::Time::Now())); +} + +bool CredentialManager::Sign(std::vector msg, + std::vector basename, + SignCallback callback) { auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); const auto& anon_creds_dict = profile_prefs_->GetDict(kAnonymousCredentialsDict); @@ -365,19 +383,19 @@ std::optional> CredentialManager::Sign( auto* today_cred_dict = anon_creds_dict.FindDict(today_date); if (!today_cred_dict) { VLOG(1) << "Failed to sign due to unavailability of credentials"; - return std::nullopt; + return false; } auto* gsk_b64 = today_cred_dict->FindString(kGSKDictKey); auto* credential_b64 = today_cred_dict->FindString(kCredentialDictKey); if (!gsk_b64 || !credential_b64) { VLOG(1) << "Failed to sign due to unavailability of gsk/credential"; - return std::nullopt; + return false; } auto gsk_bytes = base::Base64Decode(*gsk_b64); auto credential_bytes = base::Base64Decode(*credential_b64); if (!gsk_bytes || !credential_bytes) { VLOG(1) << "Failed to sign due to bad gsk/credential base64"; - return std::nullopt; + return false; } auto set_res = (*anonymous_credential_manager_) @@ -390,18 +408,17 @@ std::optional> CredentialManager::Sign( if (!set_res.error_message.empty()) { VLOG(1) << "Failed to sign due to credential set failure: " << set_res.error_message.c_str(); - return std::nullopt; + return false; } loaded_credential_date_ = today_date; } - auto sig_res = (*anonymous_credential_manager_) - ->sign(rust::Slice(msg.data(), msg.size()), - rust::Slice(basename.data(), basename.size())); - if (!sig_res.error_message.empty()) { - VLOG(1) << "Failed to sign: " << sig_res.error_message.c_str(); - return std::nullopt; - } - return std::vector(sig_res.data.begin(), sig_res.data.end()); + + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&PerformSign, &**anonymous_credential_manager_, msg, + basename), + std::move(callback)); + return true; } } // namespace web_discovery diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index 3ff7ad35b0ec..dc95630d1dca 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -11,6 +11,7 @@ #include #include +#include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/task/sequenced_task_runner.h" #include "base/timer/wall_clock_timer.h" @@ -35,6 +36,8 @@ struct GenerateJoinRequestResult { class CredentialManager { public: + using SignCallback = + base::OnceCallback>)>; CredentialManager(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, std::unique_ptr* last_loaded_server_config); @@ -45,9 +48,10 @@ class CredentialManager { void JoinGroups(); - std::optional> Sign( - const std::vector& msg, - const std::vector& basename); + bool CredentialExistsForToday(); + bool Sign(std::vector msg, + std::vector basename, + SignCallback callback); private: bool LoadRSAKey(); diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index 41a425554c33..c66621be33d0 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -8,9 +8,9 @@ #include #include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/request_queue.h" #include "brave/components/web_discovery/browser/util.h" #include "components/prefs/pref_service.h" -#include "components/prefs/scoped_user_pref_update.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" @@ -20,12 +20,12 @@ namespace web_discovery { namespace { constexpr char kUrlKey[] = "url"; constexpr char kAssociatedDataKey[] = "assoc_data"; -constexpr char kRequestTimeKey[] = "request_time"; -constexpr char kRetriesKey[] = "retries"; constexpr base::TimeDelta kRequestMaxAge = base::Hours(1); -// constexpr base::TimeDelta kRequestInterval = base::Minutes(1); -constexpr base::TimeDelta kRequestInterval = base::Seconds(5); +constexpr base::TimeDelta kMinRequestInterval = + base::Minutes(1) - base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = + base::Minutes(1) + base::Seconds(5); constexpr size_t kMaxRetries = 3; constexpr size_t kMaxDoubleFetchResponseSize = 2 * 1024 * 1024; @@ -56,10 +56,15 @@ DoubleFetcher::DoubleFetcher( FetchedCallback callback) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), - backoff_entry_(&kBackoffPolicy), - callback_(callback) { - StartFetchTimer(kRequestInterval); -} + request_queue_(profile_prefs, + kScheduledDoubleFetches, + kRequestMaxAge, + kMinRequestInterval, + kMaxRequestInterval, + kMaxRetries, + base::BindRepeating(&DoubleFetcher::OnFetchTimer, + base::Unretained(this))), + callback_(callback) {} DoubleFetcher::~DoubleFetcher() = default; @@ -68,79 +73,40 @@ void DoubleFetcher::ScheduleDoubleFetch(const GURL& url, base::Value::Dict fetch_dict; fetch_dict.Set(kUrlKey, url.spec()); fetch_dict.Set(kAssociatedDataKey, std::move(associated_data)); - fetch_dict.Set(kRequestTimeKey, - static_cast(base::Time::Now().ToTimeT())); - - ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); - update->Append(std::move(fetch_dict)); - if (!fetch_timer_.IsRunning()) { - StartFetchTimer(kRequestInterval); - } + request_queue_.ScheduleRequest(base::Value(std::move(fetch_dict))); } -void DoubleFetcher::OnFetchTimer() { - ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); - for (auto it = update->begin(); it != update->end();) { - const auto* fetch_dict = it->GetIfDict(); - const auto request_time = - fetch_dict ? fetch_dict->FindDouble(kRequestTimeKey) : std::nullopt; - const auto* url = fetch_dict ? fetch_dict->FindString(kUrlKey) : nullptr; - if (!request_time || - (base::Time::Now() - base::Time::FromTimeT(static_cast( - *request_time))) > kRequestMaxAge || - !url) { - it = update->erase(it); - continue; - } - auto resource_request = CreateResourceRequest(GURL(*url)); - url_loader_ = network::SimpleURLLoader::Create( - std::move(resource_request), kFetchNetworkTrafficAnnotation); - url_loader_->DownloadToString( - shared_url_loader_factory_.get(), - base::BindOnce(&DoubleFetcher::OnRequestComplete, - base::Unretained(this)), - kMaxDoubleFetchResponseSize); +void DoubleFetcher::OnFetchTimer(const base::Value& request_data) { + const auto* fetch_dict = request_data.GetIfDict(); + const auto* url = fetch_dict ? fetch_dict->FindString(kUrlKey) : nullptr; + if (!url) { + request_queue_.NotifyRequestComplete(true); return; } -} -void DoubleFetcher::StartFetchTimer(base::TimeDelta delta) { - fetch_timer_.Start( - FROM_HERE, delta, - base::BindOnce(&DoubleFetcher::OnFetchTimer, base::Unretained(this))); + auto resource_request = CreateResourceRequest(GURL(*url)); + url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), kFetchNetworkTrafficAnnotation); + url_loader_->DownloadToString( + shared_url_loader_factory_.get(), + base::BindOnce(&DoubleFetcher::OnRequestComplete, base::Unretained(this)), + kMaxDoubleFetchResponseSize); } void DoubleFetcher::OnRequestComplete( std::optional response_body) { auto result = ProcessCompletedRequest(&response_body); - backoff_entry_.InformOfRequest(result); - ScopedListPrefUpdate update(profile_prefs_, kScheduledDoubleFetches); - auto& request_dict = update->front().GetDict(); + auto request_data = request_queue_.NotifyRequestComplete(result); - base::TimeDelta next_fetch_time = kRequestInterval; - bool should_remove = result; - - if (!result) { - next_fetch_time = backoff_entry_.GetTimeUntilRelease(); - auto retries = request_dict.FindInt(kRetriesKey); - if (retries && retries >= kMaxRetries) { - should_remove = true; - } else { - request_dict.Set(kRetriesKey, retries.value_or(0) + 1); - } - } - - if (should_remove) { - auto* assoc_data = request_dict.Find(kAssociatedDataKey); + if (request_data) { + const auto& request_dict = request_data->GetDict(); + const auto* assoc_data = request_dict.Find(kAssociatedDataKey); if (assoc_data) { callback_.Run(*assoc_data, response_body); } - update->erase(update->begin()); } - - StartFetchTimer(next_fetch_time); } bool DoubleFetcher::ProcessCompletedRequest( diff --git a/components/web_discovery/browser/double_fetcher.h b/components/web_discovery/browser/double_fetcher.h index cbc8954b6e05..f24f7e001805 100644 --- a/components/web_discovery/browser/double_fetcher.h +++ b/components/web_discovery/browser/double_fetcher.h @@ -11,9 +11,8 @@ #include #include "base/memory/raw_ptr.h" -#include "base/timer/timer.h" #include "base/values.h" -#include "net/base/backoff_entry.h" +#include "brave/components/web_discovery/browser/request_queue.h" #include "url/gurl.h" class PrefService; @@ -41,8 +40,7 @@ class DoubleFetcher { void ScheduleDoubleFetch(const GURL& url, base::Value associated_data); private: - void OnFetchTimer(); - void StartFetchTimer(base::TimeDelta delta); + void OnFetchTimer(const base::Value& request_data); void OnRequestComplete(std::optional response_body); bool ProcessCompletedRequest(std::optional* response_body); @@ -50,9 +48,8 @@ class DoubleFetcher { raw_ptr shared_url_loader_factory_; std::unique_ptr url_loader_; - net::BackoffEntry backoff_entry_; + RequestQueue request_queue_; - base::OneShotTimer fetch_timer_; FetchedCallback callback_; }; diff --git a/components/web_discovery/browser/ecdh_aes.cc b/components/web_discovery/browser/ecdh_aes.cc new file mode 100644 index 000000000000..94f10ebe9559 --- /dev/null +++ b/components/web_discovery/browser/ecdh_aes.cc @@ -0,0 +1,153 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/ecdh_aes.h" + +#include + +#include "base/base64.h" +#include "base/logging.h" +#include "base/ranges/algorithm.h" +#include "crypto/random.h" +#include "crypto/sha2.h" +#include "third_party/boringssl/src/include/openssl/aead.h" +#include "third_party/boringssl/src/include/openssl/ec.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/ecdh.h" +#include "third_party/boringssl/src/include/openssl/nid.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kAesKeySize = 16; +constexpr size_t kAesTagLength = 128; +constexpr size_t kIvSize = 12; +constexpr size_t kKeyMaterialSize = 32; +// P-256 field size * 2 + type byte +constexpr size_t kComponentOctSize = 32 * 2 + 1; +// type byte + public component + initialization vector +constexpr size_t kEncodedPubKeyAndIv = 1 + kComponentOctSize + kIvSize; +constexpr uint8_t kP256TypeByte = 0xea; + +bssl::UniquePtr CreateECKey() { + return bssl::UniquePtr( + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); +} + +} // namespace + +AESEncryptResult::AESEncryptResult(std::vector data, + std::string encoded_public_component_and_iv) + : data(data), + encoded_public_component_and_iv(encoded_public_component_and_iv) {} + +AESEncryptResult::~AESEncryptResult() = default; + +std::optional DeriveAESKeyAndEncrypt( + const std::string& server_pub_key_b64, + const std::vector& data) { + auto server_pub_key_data = base::Base64Decode(server_pub_key_b64); + if (!server_pub_key_data) { + VLOG(1) << "ec p-256 public component not available or incorrect size"; + return std::nullopt; + } + + // auto server_public_key = CreateECKey(); + auto client_private_key = CreateECKey(); + // auto client_public_key = CreateECKey(); + + if (!client_private_key) { // || !client_public_key) {// || + // !server_public_key) { + VLOG(1) << "Failed to init P-256 curve"; + return std::nullopt; + } + + bssl::UniquePtr server_public_point(EC_POINT_new(EC_group_p256())); + if (!server_public_point) { + VLOG(1) << "Failed to init EC public point"; + return std::nullopt; + } + + if (!EC_POINT_oct2point(EC_group_p256(), server_public_point.get(), + server_pub_key_data->data(), + server_pub_key_data->size(), nullptr)) { + VLOG(1) << "Failed to load server public key data into EC point"; + return std::nullopt; + } + + // if (!EC_KEY_set_public_key(server_public_key.get(), + // server_public_point.get()) || !EC_KEY_check_key(server_public_key.get())) { + // VLOG(1) << "Failed to load point into server EC public key"; + // return std::nullopt; + // } + + if (!EC_KEY_generate_key(client_private_key.get())) { + VLOG(1) << "Failed to generate client EC key"; + return std::nullopt; + } + + // if (!EC_KEY_set_public_key(client_public_key.get(), + // EC_KEY_get0_public_key(client_private_key.get()))) { + // VLOG(1) << "Failed to set client EC public key"; + // return std::nullopt; + // } + + uint8_t shared_key_material[kKeyMaterialSize]; + if (!ECDH_compute_key(shared_key_material, kKeyMaterialSize, + server_public_point.get(), client_private_key.get(), + nullptr)) { + VLOG(1) << "Failed to set derive key via ECDH"; + return std::nullopt; + } + + auto key_material_hash = crypto::SHA256Hash(shared_key_material); + + auto aes_key = std::vector(key_material_hash.begin(), + key_material_hash.begin() + kAesKeySize); + + auto* algo = EVP_aead_aes_128_gcm(); + + bssl::ScopedEVP_AEAD_CTX ctx; + if (!EVP_AEAD_CTX_init(ctx.get(), algo, aes_key.data(), aes_key.size(), + kAesTagLength, nullptr)) { + VLOG(1) << "Failed to init AEAD context"; + return std::nullopt; + } + + size_t len; + std::array iv; + + crypto::RandBytes(iv); + + std::vector output(data.size() + EVP_AEAD_max_overhead(algo)); + if (!EVP_AEAD_CTX_seal(ctx.get(), output.data(), &len, output.size(), + iv.data(), iv.size(), data.data(), data.size(), + nullptr, 0)) { + VLOG(1) << "Failed to encrypt via AES"; + return std::nullopt; + } + + output.resize(len); + + std::array public_component_and_iv; + public_component_and_iv[0] = kP256TypeByte; + + if (!EC_POINT_point2oct( + EC_group_p256(), EC_KEY_get0_public_key(client_private_key.get()), + POINT_CONVERSION_UNCOMPRESSED, public_component_and_iv.data() + 1, + kComponentOctSize, nullptr)) { + VLOG(1) << "Failed to export EC public point/key"; + return std::nullopt; + } + + base::ranges::copy(iv.begin(), iv.end(), + public_component_and_iv.begin() + kComponentOctSize + 1); + + return std::make_optional( + output, base::Base64Encode(public_component_and_iv)); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/ecdh_aes.h b/components/web_discovery/browser/ecdh_aes.h new file mode 100644 index 000000000000..a7ad0c7e3551 --- /dev/null +++ b/components/web_discovery/browser/ecdh_aes.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_ECDH_AES_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_ECDH_AES_H_ + +#include +#include +#include + +namespace web_discovery { + +struct AESEncryptResult { + AESEncryptResult(std::vector data, + std::string encoded_public_component_and_iv); + ~AESEncryptResult(); + + AESEncryptResult(const AESEncryptResult&) = delete; + AESEncryptResult& operator=(const AESEncryptResult&) = delete; + + std::vector data; + std::string encoded_public_component_and_iv; +}; + +std::optional DeriveAESKeyAndEncrypt( + const std::string& server_pub_key_b64, + const std::vector& data); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_ECDH_AES_H_ diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index b58c245fbbbb..ace73cab8f35 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -11,9 +11,6 @@ namespace web_discovery { namespace { -constexpr char kActionKey[] = "action"; -constexpr char kInnerPayloadKey[] = "payload"; - bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); if (value_str && !value_str->empty()) { diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h index 7a57cc18db5b..ea08f92b1d83 100644 --- a/components/web_discovery/browser/payload_generator.h +++ b/components/web_discovery/browser/payload_generator.h @@ -15,6 +15,9 @@ namespace web_discovery { +inline constexpr char kActionKey[] = "action"; +inline constexpr char kInnerPayloadKey[] = "payload"; + std::vector GeneratePayloads( const PatternsURLDetails* url_details, std::unique_ptr scrape_result); diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index 77ab0f48235a..d71051d1c684 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -17,6 +17,10 @@ inline constexpr char kAnonymousCredentialsDict[] = "brave.web_discovery.anon_creds"; inline constexpr char kScheduledDoubleFetches[] = "brave.web_discovery.scheduled_double_fetches"; +inline constexpr char kScheduledReports[] = + "brave.web_discovery.scheduled_reports"; +inline constexpr char kUsedBasenameCounts[] = + "brave.web_discovery.used_basename_counts"; // Local state inline constexpr char kPatternsRetrievalTime[] = diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc new file mode 100644 index 000000000000..d999615b1442 --- /dev/null +++ b/components/web_discovery/browser/reporter.cc @@ -0,0 +1,259 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/reporter.h" + +#include + +#include "base/containers/span_writer.h" +#include "base/json/json_writer.h" +#include "base/numerics/byte_conversions.h" +#include "base/rand_util.h" +#include "base/task/thread_pool.h" +#include "brave/components/web_discovery/browser/ecdh_aes.h" +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/signature_basename.h" +#include "brave/components/web_discovery/browser/util.h" +#include "crypto/sha2.h" +#include "services/network/public/cpp/resource_request_body.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/zlib/google/compression_utils_portable.h" +#include "third_party/zlib/zlib.h" + +namespace web_discovery { + +namespace { + +constexpr net::NetworkTrafficAnnotationTag kSubmitNetworkTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("wdp_submit", R"( + semantics { + sender: "Brave Web Discovery Submission" + description: + "Sends search engine results & page interaction metrics + that are deemed private by risk assessment heuristics." + trigger: + "Requests are automatically sent every minute " + "while Brave is running, and as content is collected." + data: "Search engine results & page interaction metrics" + destination: WEBSITE + } + policy { + cookies_allowed: NO + setting: + "Users can opt-in or out via brave://settings/search" + })"); + +constexpr base::TimeDelta kRequestMaxAge = base::Hours(36); +constexpr base::TimeDelta kMinRequestInterval = + base::Minutes(1) - base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = + base::Minutes(1) + base::Seconds(5); +constexpr size_t kMaxRetries = 10; + +constexpr char kTypeField[] = "type"; +constexpr char kWdpType[] = "wdp"; +constexpr char kChannelField[] = "channel"; +constexpr char kBraveChannel[] = "brave"; +constexpr char kReporterVersionField[] = "ver"; +constexpr char kCurrentReporterVersion[] = "1.0"; +constexpr char kAntiDuplicatesField[] = "anti-duplicates"; +constexpr char kTimestampField[] = "ts"; +constexpr int kMaxAntiDuplicatesNonce = 10000000; +constexpr char kSenderField[] = "sender"; +constexpr char kHpnSenderValue[] = "hpnv2"; + +constexpr uint8_t kSignedMessageId = 0x03; +// id byte + basename count + signature +constexpr size_t kSignedMessageMetadataSize = 1 + 8 + 389; +constexpr size_t kMaxCompressedMessageSize = 32767; + +constexpr char kSubmitPath[] = "/"; +constexpr char kMessageContentType[] = "application/octet-stream"; +constexpr char kKeyDateHeader[] = "Key-Date"; +constexpr char kEncryptionHeader[] = "Encryption"; + +base::Value GenerateFinalPayload(const base::Value::Dict& pre_payload) { + base::Value::Dict result = pre_payload.Clone(); + + result.Set(kTypeField, kWdpType); + result.Set(kReporterVersionField, kCurrentReporterVersion); + result.Set(kSenderField, kHpnSenderValue); + result.Set(kTimestampField, FormatServerDate(base::Time::Now())); + result.Set(kAntiDuplicatesField, base::RandInt(0, kMaxAntiDuplicatesNonce)); + result.Set(kChannelField, kBraveChannel); + + return base::Value(std::move(result)); +} + +std::optional CompressAndEncrypt( + std::vector full_signed_message, + std::string server_pub_key) { + uLongf compressed_data_size = compressBound(full_signed_message.size()); + std::vector compressed_data(compressed_data_size + 2); + if (zlib_internal::CompressHelper( + zlib_internal::ZLIB, compressed_data.data(), &compressed_data_size, + full_signed_message.data() + 2, full_signed_message.size(), + Z_DEFAULT_COMPRESSION, nullptr, nullptr) != Z_OK) { + return std::nullopt; + } + if (compressed_data_size > kMaxCompressedMessageSize) { + return std::nullopt; + } + base::ranges::copy(base::U16ToBigEndian(compressed_data_size), + compressed_data.begin()); + auto encrypt_result = DeriveAESKeyAndEncrypt(server_pub_key, compressed_data); + if (!encrypt_result) { + return std::nullopt; + } + return std::make_optional( + compressed_data, encrypt_result->encoded_public_component_and_iv); +} + +} // namespace + +CompressEncryptResult::CompressEncryptResult(std::vector data, + std::string encoded) + : encrypted_data(data), encoded_public_component_and_iv(encoded) {} + +CompressEncryptResult::~CompressEncryptResult() = default; +CompressEncryptResult::CompressEncryptResult(const CompressEncryptResult&) = + default; + +Reporter::Reporter(PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + CredentialManager* credential_manager, + std::unique_ptr* last_loaded_server_config) + : profile_prefs_(profile_prefs), + shared_url_loader_factory_(shared_url_loader_factory), + last_loaded_server_config_(last_loaded_server_config), + credential_manager_(credential_manager), + pool_sequenced_task_runner_( + base::ThreadPool::CreateSequencedTaskRunner({})), + request_queue_(profile_prefs, + kScheduledReports, + kRequestMaxAge, + kMinRequestInterval, + kMaxRequestInterval, + kMaxRetries, + base::BindRepeating(&Reporter::PrepareRequest, + base::Unretained(this))) { + submit_url_ = GURL(GetCollectorHost() + kSubmitPath); +} + +Reporter::~Reporter() = default; + +void Reporter::ScheduleSend(base::Value::Dict payload) { + request_queue_.ScheduleRequest(base::Value(std::move(payload))); +} + +void Reporter::PrepareRequest(const base::Value& request_data) { + if (!credential_manager_->CredentialExistsForToday()) { + // Backoff until credential is available to today + request_queue_.NotifyRequestComplete(false); + return; + } + const auto* payload_dict = request_data.GetIfDict(); + if (!payload_dict) { + // Drop request due to bad data + request_queue_.NotifyRequestComplete(true); + return; + } + auto basename_result = GenerateBasename( + profile_prefs_, (*last_loaded_server_config_).get(), *payload_dict); + if (!basename_result) { + // Drop request due to exceeded basename quota + request_queue_.NotifyRequestComplete(true); + return; + } + auto final_payload = GenerateFinalPayload(*payload_dict); + + std::string final_payload_json; + if (base::JSONWriter::Write(final_payload, &final_payload_json)) { + request_queue_.NotifyRequestComplete(true); + return; + } + + auto payload_hash = crypto::SHA256HashString(final_payload_json); + credential_manager_->Sign( + std::vector(payload_hash.begin(), payload_hash.end()), + basename_result->basename, + base::BindOnce(&Reporter::OnRequestSigned, weak_ptr_factory_.GetWeakPtr(), + final_payload_json, basename_result->count)); +} + +void Reporter::OnRequestSigned( + std::string final_payload_json, + size_t basename_count, + std::optional> signature) { + if (!signature) { + request_queue_.NotifyRequestComplete(false); + return; + } + auto pub_key = (*last_loaded_server_config_) + ->pub_keys.find(FormatServerDate(base::Time::Now())); + if (pub_key == (*last_loaded_server_config_)->pub_keys.end()) { + request_queue_.NotifyRequestComplete(false); + return; + } + std::vector full_signed_message(kSignedMessageMetadataSize + + final_payload_json.size()); + base::SpanWriter message_writer(full_signed_message); + if (!message_writer.WriteU8BigEndian(kSignedMessageId) || + !message_writer.Write(base::span( + reinterpret_cast(final_payload_json.data()), + final_payload_json.size())) || + !message_writer.Write(base::DoubleToBigEndian(basename_count)) || + !message_writer.Write(*signature)) { + request_queue_.NotifyRequestComplete(true); + return; + } + pool_sequenced_task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&CompressAndEncrypt, full_signed_message, pub_key->second), + base::BindOnce(&Reporter::OnRequestCompressedAndEncrypted, + weak_ptr_factory_.GetWeakPtr())); +} + +void Reporter::OnRequestCompressedAndEncrypted( + std::optional result) { + if (!result) { + request_queue_.NotifyRequestComplete(true); + return; + } + auto request = CreateResourceRequest(submit_url_); + request->headers.SetHeader(kKeyDateHeader, + FormatServerDate(base::Time::Now())); + request->headers.SetHeader(kEncryptionHeader, + result->encoded_public_component_and_iv); + + url_loader_ = network::SimpleURLLoader::Create( + std::move(request), kSubmitNetworkTrafficAnnotation); + url_loader_->AttachStringForUpload( + std::string(result->encrypted_data.begin(), result->encrypted_data.end()), + kMessageContentType); +} + +void Reporter::OnRequestComplete(std::optional response_body) { + request_queue_.NotifyRequestComplete(ValidateResponse(response_body)); +} + +bool Reporter::ValidateResponse( + const std::optional& response_body) { + auto* response_info = url_loader_->ResponseInfo(); + if (!response_body || !response_info) { + return false; + } + auto response_code = response_info->headers->response_code(); + if (response_code < 200 || response_code >= 300) { + if (response_code >= 500) { + // Only retry failures due to server error + return false; + } + } + return true; +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h new file mode 100644 index 000000000000..7c64342c58a7 --- /dev/null +++ b/components/web_discovery/browser/reporter.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REPORTER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REPORTER_H_ + +#include +#include +#include +#include + +#include "base/memory/raw_ptr.h" +#include "base/values.h" +#include "brave/components/web_discovery/browser/credential_manager.h" +#include "brave/components/web_discovery/browser/request_queue.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" + +class PrefService; + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace web_discovery { + +struct CompressEncryptResult { + CompressEncryptResult(std::vector data, std::string encoded); + ~CompressEncryptResult(); + + CompressEncryptResult(const CompressEncryptResult&); + + std::vector encrypted_data; + std::string encoded_public_component_and_iv; +}; + +class Reporter { + public: + Reporter(PrefService* profile_prefs, + network::SharedURLLoaderFactory* shared_url_loader_factory, + CredentialManager* credential_manager, + std::unique_ptr* last_loaded_server_config); + ~Reporter(); + + Reporter(const Reporter&) = delete; + Reporter& operator=(const Reporter&) = delete; + + void ScheduleSend(base::Value::Dict payload); + + private: + void PrepareRequest(const base::Value& request_data); + void OnRequestSigned(std::string final_payload_json, + size_t basename_count, + std::optional> signature); + void OnRequestCompressedAndEncrypted( + std::optional result); + void OnRequestComplete(std::optional response_body); + bool ValidateResponse(const std::optional& response_body); + + GURL submit_url_; + + raw_ptr profile_prefs_; + raw_ptr shared_url_loader_factory_; + raw_ptr> last_loaded_server_config_; + + raw_ptr credential_manager_; + + scoped_refptr pool_sequenced_task_runner_; + + RequestQueue request_queue_; + + std::unique_ptr url_loader_; + + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REPORTER_H_ diff --git a/components/web_discovery/browser/request_queue.cc b/components/web_discovery/browser/request_queue.cc new file mode 100644 index 000000000000..fa0e62ee63c3 --- /dev/null +++ b/components/web_discovery/browser/request_queue.cc @@ -0,0 +1,120 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/request_queue.h" + +#include + +#include "base/rand_util.h" +#include "brave/components/web_discovery/browser/util.h" +#include "components/prefs/scoped_user_pref_update.h" + +namespace web_discovery { + +namespace { + +constexpr char kRequestTimeKey[] = "request_time"; +constexpr char kRetriesKey[] = "retries"; +constexpr char kDataKey[] = "data"; + +} // namespace + +RequestQueue::RequestQueue( + PrefService* profile_prefs, + const char* list_pref_name, + base::TimeDelta request_max_age, + base::TimeDelta min_request_interval, + base::TimeDelta max_request_interval, + size_t max_retries, + base::RepeatingCallback start_request_callback) + : profile_prefs_(profile_prefs), + list_pref_name_(list_pref_name), + backoff_entry_(&kBackoffPolicy), + request_max_age_(request_max_age), + min_request_interval_(min_request_interval), + max_request_interval_(max_request_interval), + max_retries_(max_retries), + start_request_callback_(start_request_callback) { + StartFetchTimer(false); +} + +RequestQueue::~RequestQueue() = default; + +void RequestQueue::ScheduleRequest(base::Value request_data) { + base::Value::Dict fetch_dict; + fetch_dict.Set(kDataKey, std::move(request_data)); + fetch_dict.Set(kRequestTimeKey, + static_cast(base::Time::Now().ToTimeT())); + + ScopedListPrefUpdate update(profile_prefs_, list_pref_name_); + update->Append(std::move(fetch_dict)); + + if (!fetch_timer_.IsRunning()) { + StartFetchTimer(false); + } +} + +std::optional RequestQueue::NotifyRequestComplete(bool success) { + backoff_entry_.InformOfRequest(success); + + ScopedListPrefUpdate update(profile_prefs_, list_pref_name_); + auto& request_dict = update->front().GetDict(); + + std::optional removed_value; + bool use_backoff_delta = false; + bool should_remove = success; + + if (!success) { + use_backoff_delta = true; + auto retries = request_dict.FindInt(kRetriesKey); + if (retries && retries >= max_retries_) { + should_remove = true; + } else { + request_dict.Set(kRetriesKey, retries.value_or(0) + 1); + } + } + + if (should_remove) { + auto* data = request_dict.Find(kDataKey); + removed_value = data ? data->Clone() : base::Value(); + update->erase(update->begin()); + } + + StartFetchTimer(use_backoff_delta); + return removed_value; +} + +void RequestQueue::OnFetchTimer() { + ScopedListPrefUpdate update(profile_prefs_, list_pref_name_); + for (auto it = update->begin(); it != update->end();) { + const auto* fetch_dict = it->GetIfDict(); + const auto request_time = + fetch_dict ? fetch_dict->FindDouble(kRequestTimeKey) : std::nullopt; + const auto* data = fetch_dict ? fetch_dict->Find(kDataKey) : nullptr; + if (!request_time || + (base::Time::Now() - base::Time::FromTimeT(static_cast( + *request_time))) > request_max_age_ || + !data) { + it = update->erase(it); + continue; + } + start_request_callback_.Run(*data); + return; + } +} + +void RequestQueue::StartFetchTimer(bool use_backoff_delta) { + base::TimeDelta delta; + if (use_backoff_delta) { + delta = backoff_entry_.GetTimeUntilRelease(); + } else { + delta = base::RandTimeDelta(min_request_interval_, max_request_interval_); + } + fetch_timer_.Start( + FROM_HERE, delta, + base::BindOnce(&RequestQueue::OnFetchTimer, base::Unretained(this))); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/request_queue.h b/components/web_discovery/browser/request_queue.h new file mode 100644 index 000000000000..6fbfbd194b20 --- /dev/null +++ b/components/web_discovery/browser/request_queue.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REQUEST_QUEUE_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REQUEST_QUEUE_H_ + +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/timer/timer.h" +#include "base/values.h" +#include "net/base/backoff_entry.h" + +class PrefService; + +namespace web_discovery { + +class RequestQueue { + public: + RequestQueue( + PrefService* profile_prefs, + const char* list_pref_name, + base::TimeDelta request_max_age, + base::TimeDelta min_request_interval, + base::TimeDelta max_request_interval, + size_t max_retries, + base::RepeatingCallback start_request_callback); + ~RequestQueue(); + + RequestQueue(const RequestQueue&) = delete; + RequestQueue& operator=(const RequestQueue&) = delete; + + void ScheduleRequest(base::Value request_data); + // Returns data value if request is deleted from queue, due to the retry limit + // or success + std::optional NotifyRequestComplete(bool success); + + private: + void OnFetchTimer(); + void StartFetchTimer(bool use_backoff_delta); + + raw_ptr profile_prefs_; + const char* list_pref_name_; + + net::BackoffEntry backoff_entry_; + + base::TimeDelta request_max_age_; + base::TimeDelta min_request_interval_; + base::TimeDelta max_request_interval_; + size_t max_retries_; + base::RepeatingCallback start_request_callback_; + + base::OneShotTimer fetch_timer_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REQUEST_QUEUE_H_ diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 76977264f1f3..98888f9fe7ce 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -6,7 +6,6 @@ #include "brave/components/web_discovery/browser/server_config_loader.h" #include -#include #include "base/base64.h" #include "base/files/file_util.h" @@ -60,6 +59,10 @@ constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = constexpr char kGroupPubKeysFieldName[] = "groupPubKeys"; constexpr char kPubKeysFieldName[] = "pubKeys"; constexpr char kMinVersionFieldName[] = "minVersion"; +constexpr char kKeysFieldName[] = "keys"; +constexpr char kLimitFieldName[] = "limit"; +constexpr char kPeriodFieldName[] = "period"; +constexpr char kSourceMapFieldName[] = "sourceMap"; constexpr char kConfigPathWithFields[] = "/config?fields=minVersion,groupPubKeys,pubKeys,sourceMap"; @@ -78,6 +81,32 @@ KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { return map; } +base::flat_map ParseSourceMapActionConfigs( + const base::Value::Dict& configs_dict) { + base::flat_map map; + for (const auto [action, config_dict_val] : configs_dict) { + auto* config_dict = config_dict_val.GetIfDict(); + if (!config_dict) { + continue; + } + auto& action_config = map[action]; + auto* keys_list = config_dict->FindList(kKeysFieldName); + if (keys_list) { + for (const auto& key_val : *keys_list) { + if (key_val.is_string()) { + action_config.keys.push_back(key_val.GetString()); + } + } + } + auto limit = config_dict->FindInt(kLimitFieldName); + auto period = config_dict->FindInt(kPeriodFieldName); + + action_config.limit = limit && limit >= 0 ? *limit : 1; + action_config.period = period && period >= 0 ? *period : 24; + } + return map; +} + std::optional GunzipContents(std::string gzipped_contents) { std::string result; if (!compression::GzipUncompress(gzipped_contents, &result)) { @@ -101,8 +130,12 @@ std::optional ReadPatternsFile(base::FilePath patterns_path) { } // namespace -ServerConfig::ServerConfig() = default; +SourceMapActionConfig::SourceMapActionConfig() = default; +SourceMapActionConfig::~SourceMapActionConfig() = default; +SourceMapActionConfig::SourceMapActionConfig(const SourceMapActionConfig&) = + default; +ServerConfig::ServerConfig() = default; ServerConfig::~ServerConfig() = default; ServerConfigLoader::ServerConfigLoader( @@ -209,9 +242,15 @@ bool ServerConfigLoader::ProcessConfigResponse( VLOG(1) << "Failed to retrieve pubKeys from server config"; return false; } + const auto* source_map = root->FindDict(kSourceMapFieldName); + if (!source_map) { + VLOG(1) << "Failed to retrieve sourceMap from server config"; + return false; + } config->group_pub_keys = ParseKeys(*group_pub_keys); config->pub_keys = ParseKeys(*pub_keys); + config->source_map_actions = ParseSourceMapActionConfigs(*source_map); config_callback_.Run(std::move(config)); return true; diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 7c41bae0c36b..455490427754 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "base/containers/flat_map.h" #include "base/files/file_path.h" @@ -29,12 +30,25 @@ namespace web_discovery { using KeyMap = base::flat_map; +struct SourceMapActionConfig { + SourceMapActionConfig(); + ~SourceMapActionConfig(); + + SourceMapActionConfig(const SourceMapActionConfig&); + + std::vector keys; + size_t limit; + size_t period; +}; + struct ServerConfig { ServerConfig(); ~ServerConfig(); KeyMap group_pub_keys; KeyMap pub_keys; + + base::flat_map source_map_actions; }; class ServerConfigLoader { diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc new file mode 100644 index 000000000000..06067d2c801f --- /dev/null +++ b/components/web_discovery/browser/signature_basename.cc @@ -0,0 +1,217 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/signature_basename.h" + +#include +#include + +#include "base/hash/hash.h" +#include "base/json/json_writer.h" +#include "base/rand_util.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "brave/components/web_discovery/browser/payload_generator.h" +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" +#include "components/prefs/scoped_user_pref_update.h" +#include "crypto/sha2.h" +#include "third_party/re2/src/re2/re2.h" + +namespace web_discovery { + +namespace { + +constexpr char kPunctuationRegex[] = "[!\"'()*,-./:;?[\\]^_`{|}~%$=&+#]"; +constexpr char kUrlNormalizationFunc[] = "url"; +constexpr char kFlattenObjNormalizationFunc[] = "obj"; +constexpr size_t kMsInHour = 60 * 60 * 1000; + +constexpr char kExpiresAtKey[] = "expires_at"; +constexpr char kUsedCountsKey[] = "counts"; + +void RecurseFlattenObject(const base::Value& value, + const base::Value::List& parent_keys, + base::Value::List& output) { + if (value.is_dict()) { + const auto& dict = value.GetDict(); + base::flat_set keys; + // insert into set so we can sort keys + for (const auto [key, _] : dict) { + keys.insert(key); + } + for (const auto& key : keys) { + base::Value::List next_parent_keys = parent_keys.Clone(); + next_parent_keys.Append(key); + RecurseFlattenObject(*dict.Find(key), next_parent_keys, output); + } + } else if (value.is_list()) { + const auto& list = value.GetList(); + for (size_t i = 0; i < list.size(); i++) { + base::Value::List next_parent_keys = parent_keys.Clone(); + next_parent_keys.Append(base::NumberToString(i)); + RecurseFlattenObject(list[i], next_parent_keys, output); + } + } else { + base::Value::List flattened_value; + flattened_value.Append(parent_keys.Clone()); + flattened_value.Append(value.Clone()); + output.Append(std::move(flattened_value)); + } +} + +base::Value FlattenObject(const base::Value& obj) { + base::Value::List result; + RecurseFlattenObject(obj, base::Value::List(), result); + return base::Value(std::move(result)); +} + +base::Value CleanURL(const base::Value& url) { + if (!url.is_string()) { + return base::Value(); + } + auto url_str = base::ToLowerASCII(url.GetString()); + base::RemoveChars(url_str, " ", &url_str); + base::ReplaceSubstringsAfterOffset(&url_str, 0, "https://", ""); + base::ReplaceSubstringsAfterOffset(&url_str, 0, "http://", ""); + base::ReplaceSubstringsAfterOffset(&url_str, 0, "www.", ""); + + re2::RE2 punc_regex(kPunctuationRegex); + re2::RE2::GlobalReplace(&url_str, punc_regex, ""); + return base::Value(std::move(url_str)); +} + +int GetPeriodHoursSinceEpoch(size_t period_hours) { + auto hours_since_epoch = + base::Time::Now().InMillisecondsSinceUnixEpoch() / kMsInHour; + auto epoch_period_hours = period_hours * (hours_since_epoch / period_hours); + return epoch_period_hours; +} + +std::optional GetBasenameCount(PrefService* profile_prefs, + const base::Value::List& interim_tag_list, + const SourceMapActionConfig& action_config, + size_t period_hours) { + std::string interim_tag_json; + if (!base::JSONWriter::Write(base::Value(interim_tag_list.Clone()), + &interim_tag_json)) { + return std::nullopt; + } + auto tag_hash = base::NumberToString(base::PersistentHash(interim_tag_json)); + + // clean up expired counts + ScopedDictPrefUpdate update(profile_prefs, kUsedBasenameCounts); + base::Time now = base::Time::Now(); + for (auto it = update->begin(); it != update->end();) { + const auto* value_dict = it->second.GetIfDict(); + if (!value_dict) { + it = update->erase(it); + continue; + } + const auto expire_time = value_dict->FindDouble(kExpiresAtKey); + if (!expire_time || + now >= base::Time::FromTimeT(static_cast(*expire_time))) { + it = update->erase(it); + continue; + } + it++; + } + + auto* count_dict = update->EnsureDict(tag_hash); + if (!count_dict->contains(kExpiresAtKey)) { + auto expire_time = + base::Time::FromMillisecondsSinceUnixEpoch(static_cast( + (period_hours + action_config.period) * kMsInHour)); + count_dict->Set(kExpiresAtKey, static_cast(expire_time.ToTimeT())); + } + + auto* used_counts_list = count_dict->EnsureList(kUsedCountsKey); + if (used_counts_list->size() >= action_config.limit) { + return std::nullopt; + } + + while (auto count = base::RandInt(0, action_config.limit - 1)) { + if (base::ranges::find(used_counts_list->begin(), used_counts_list->end(), + count) != used_counts_list->end()) { + continue; + } + used_counts_list->Append(count); + return count; + } + NOTREACHED(); + return 0; +} + +} // namespace + +BasenameResult::BasenameResult(std::vector basename, + size_t count) + : basename(basename), count(count) {} + +BasenameResult::~BasenameResult() = default; + +std::optional GenerateBasename( + PrefService* profile_prefs, + ServerConfig* server_config, + const base::Value::Dict& payload) { + const std::string* action = payload.FindString(kActionKey); + if (!action || action->empty()) { + return std::nullopt; + } + const auto action_config = server_config->source_map_actions.find(*action); + if (action_config == server_config->source_map_actions.end()) { + return std::nullopt; + } + const auto* inner_payload = payload.FindDict(kInnerPayloadKey); + if (!inner_payload) { + return std::nullopt; + } + base::Value::List tag_list; + tag_list.Append(*action); + tag_list.Append(static_cast(action_config->second.period)); + tag_list.Append(static_cast(action_config->second.limit)); + + base::Value::List key_values; + for (const auto& key : action_config->second.keys) { + auto parts = + base::SplitString(key, "->", base::WhitespaceHandling::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL); + if (parts.empty() || parts[0].empty()) { + continue; + } + const auto* value = inner_payload->FindByDottedPath(parts[0]); + auto final_value = value ? value->Clone() : base::Value(); + if (parts.size() > 1) { + if (parts[1] == kUrlNormalizationFunc) { + final_value = CleanURL(final_value); + } else if (parts[1] == kFlattenObjNormalizationFunc) { + final_value = FlattenObject(final_value); + } + } + key_values.Append(std::move(final_value)); + } + + auto period_hours = GetPeriodHoursSinceEpoch(action_config->second.period); + tag_list.Append(std::move(key_values)); + tag_list.Append(period_hours); + + auto basename_count = GetBasenameCount(profile_prefs, tag_list, + action_config->second, period_hours); + if (!basename_count) { + return std::nullopt; + } + tag_list.Append(*basename_count); + + std::string tag_json; + if (!base::JSONWriter::Write(base::Value(std::move(tag_list)), &tag_json)) { + return std::nullopt; + } + + auto tag_hash = crypto::SHA256HashString(tag_json); + std::vector tag_hash_vector(tag_hash.begin(), tag_hash.end()); + return std::make_optional(tag_hash_vector, *basename_count); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/signature_basename.h b/components/web_discovery/browser/signature_basename.h new file mode 100644 index 000000000000..2c784f2b9c3e --- /dev/null +++ b/components/web_discovery/browser/signature_basename.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SIGNATURE_BASENAME_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SIGNATURE_BASENAME_H_ + +#include +#include + +#include "base/values.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" + +class PrefService; + +namespace web_discovery { + +struct BasenameResult { + BasenameResult(std::vector basename, size_t count); + ~BasenameResult(); + + BasenameResult(const BasenameResult&) = delete; + BasenameResult& operator=(const BasenameResult&) = delete; + + std::vector basename; + // The count index for a given "pre-tag". It should be under the limit for a + // given action + size_t count; +}; + +std::optional GenerateBasename( + PrefService* profile_prefs, + ServerConfig* server_config, + const base::Value::Dict& payload); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 8c57633504ba..4031ca777df2 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -51,6 +51,8 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterStringPref(kCredentialRSAPrivateKey, {}); registry->RegisterStringPref(kCredentialRSAPublicKey, {}); registry->RegisterListPref(kScheduledDoubleFetches); + registry->RegisterListPref(kScheduledReports); + registry->RegisterDictionaryPref(kUsedBasenameCounts); } void WDPService::Start() { @@ -66,6 +68,7 @@ void WDPService::Start() { } void WDPService::Stop() { + reporter_ = nullptr; double_fetcher_ = nullptr; content_scraper_ = nullptr; server_config_loader_ = nullptr; @@ -93,6 +96,9 @@ void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { profile_prefs_.get(), shared_url_loader_factory_.get(), base::BindRepeating(&WDPService::OnDoubleFetched, base::Unretained(this))); + reporter_ = std::make_unique( + profile_prefs_.get(), shared_url_loader_factory_.get(), + credential_manager_.get(), &last_loaded_server_config_); } void WDPService::OnDoubleFetched(const base::Value& associated_data, @@ -150,7 +156,9 @@ void WDPService::OnContentScraped(bool is_strict, result->SerializeToValue()); } else { auto payloads = GeneratePayloads(url_details, std::move(result)); - // TODO(djandries): send payloads + for (auto& payload : payloads) { + reporter_->ScheduleSend(std::move(payload)); + } } } diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 6aeb8e19863e..3000da399612 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -17,6 +17,7 @@ #include "brave/components/web_discovery/browser/double_fetcher.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/payload_generator.h" +#include "brave/components/web_discovery/browser/reporter.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -61,8 +62,6 @@ class WDPService : public KeyedService { void OnConfigChange(std::unique_ptr config); void OnPatternsLoaded(std::unique_ptr patterns); - void extracted(std::unique_ptr& result, - const PatternsURLDetails*& url_details); void OnContentScraped(bool is_strict, std::unique_ptr result); void OnDoubleFetched(const base::Value& associated_data, @@ -85,6 +84,7 @@ class WDPService : public KeyedService { std::unique_ptr credential_manager_; std::unique_ptr content_scraper_; std::unique_ptr double_fetcher_; + std::unique_ptr reporter_; }; } // namespace web_discovery From c736a10ab39b1b42b6812dc0144773acfb903538 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 6 Jun 2024 20:39:19 -0700 Subject: [PATCH 14/36] Various Web Discovery fixes, add refine functions --- .../web_discovery/browser/content_scraper.cc | 138 ++++++++++++++---- .../web_discovery/browser/content_scraper.h | 17 ++- .../browser/credential_manager.cc | 2 - .../web_discovery/browser/double_fetcher.cc | 10 +- components/web_discovery/browser/ecdh_aes.cc | 22 +-- components/web_discovery/browser/ecdh_aes.h | 3 +- components/web_discovery/browser/patterns.cc | 48 +++--- components/web_discovery/browser/patterns.h | 20 +-- components/web_discovery/browser/reporter.cc | 92 +++++++----- components/web_discovery/browser/reporter.h | 24 ++- .../browser/server_config_loader.cc | 11 +- .../browser/signature_basename.cc | 54 ++++--- .../browser/signature_basename.h | 9 +- components/web_discovery/browser/util.h | 1 + .../web_discovery/browser/wdp_service.cc | 14 +- .../web_discovery/browser/wdp_service.h | 1 - .../renderer/blink_document_extractor.cc | 1 + 17 files changed, 297 insertions(+), 170 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 3f08edab8967..8819176677e4 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -8,7 +8,10 @@ #include #include "base/ranges/algorithm.h" +#include "base/strings/string_split.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" +#include "url/url_util.h" namespace web_discovery { @@ -19,6 +22,44 @@ constexpr char kFieldsValueKey[] = "fields"; constexpr char kIdValueKey[] = "id"; constexpr char kUrlValueKey[] = "url"; +constexpr char kRefineSplitFuncId[] = "splitF"; + +std::string RefineSplit(const std::string& value, + const std::string& delimiter, + int index) { + auto split = base::SplitStringUsingSubstr( + value, delimiter, base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL); + std::string encoded_result; + if (index < 0 || static_cast(index) >= split.size()) { + encoded_result = value; + } else { + encoded_result = split[index]; + } + url::RawCanonOutputT result; + url::DecodeURLEscapeSequences(encoded_result, + url::DecodeURLMode::kUTF8OrIsomorphic, &result); + return base::UTF16ToUTF8(result.view()); +} + +std::string ExecuteRefineFunctions(const RefineFunctionList& function_list, + const std::string& value) { + std::string result = value; + for (const auto& function_args : function_list) { + if (function_args.empty()) { + continue; + } + if (function_args[0] == kRefineSplitFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_int()) { + result = RefineSplit(result, function_args[1].GetString(), + function_args[2].GetInt()); + } + } + } + return result; +} + } // namespace PageScrapeResult::PageScrapeResult(GURL url, std::string id) @@ -82,26 +123,32 @@ std::unique_ptr PageScrapeResult::FromValue( return result; } -void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, - const GURL& url, +void ContentScraper::ScrapePage(const GURL& url, + bool is_strict_scrape, mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback) { + const auto* url_details = + (*patterns_)->GetMatchingURLPattern(url, is_strict_scrape); + if (!url_details) { + return; + } auto interim_result = std::make_unique(url, url_details->id); std::vector select_requests; - for (const auto& group : url_details->scrape_rule_groups) { + for (const auto& [selector, group] : url_details->scrape_rule_groups) { auto select_request = mojom::SelectRequest::New(); - select_request->root_selector = group.selector; - for (const auto& rule : group.rules) { - if (rule.rule_type == ScrapeRuleType::kStandard) { - ProcessStandardRule(rule, group.selector, url, interim_result.get()); + select_request->root_selector = selector; + for (const auto& [report_key, rule] : group) { + if (rule->rule_type == ScrapeRuleType::kStandard) { + ProcessStandardRule(report_key, *rule, selector, url, + interim_result.get()); continue; } auto attribute_request = mojom::SelectAttributeRequest::New(); - attribute_request->sub_selector = rule.sub_selector; - attribute_request->attribute = rule.attribute; - attribute_request->key = rule.report_key; + attribute_request->sub_selector = rule->sub_selector; + attribute_request->attribute = rule->attribute; + attribute_request->key = report_key; select_request->attribute_requests.push_back( std::move(attribute_request)); @@ -112,31 +159,36 @@ void ContentScraper::ScrapePage(const PatternsURLDetails* url_details, document_extractor->QueryElementAttributes( std::move(select_requests), base::BindOnce(&ContentScraper::OnScrapedElementAttributes, - base::Unretained(this), std::move(interim_result), - std::move(callback))); + base::Unretained(this), is_strict_scrape, + std::move(interim_result), std::move(callback))); } void ContentScraper::ParseAndScrapePage( + bool is_strict_scrape, std::unique_ptr prev_result, - const PatternsURLDetails* url_details, std::string html, PageScrapeResultCallback callback) { + const auto* url_details = + (*patterns_)->GetMatchingURLPattern(prev_result->url, is_strict_scrape); + if (!url_details) { + return; + } auto interim_result = std::move(prev_result); std::vector select_requests; - for (const auto& group : url_details->scrape_rule_groups) { + for (const auto& [selector, group] : url_details->scrape_rule_groups) { rust_document_extractor::SelectRequest select_request; - select_request.root_selector = group.selector; - for (const auto& rule : group.rules) { - if (rule.rule_type == ScrapeRuleType::kStandard) { - ProcessStandardRule(rule, group.selector, interim_result->url, + select_request.root_selector = selector; + for (const auto& [report_key, rule] : group) { + if (rule->rule_type == ScrapeRuleType::kStandard) { + ProcessStandardRule(report_key, *rule, selector, interim_result->url, interim_result.get()); continue; } rust_document_extractor::SelectAttributeRequest attribute_request{ - .sub_selector = rule.sub_selector.value_or(""), - .key = rule.report_key, - .attribute = rule.attribute, + .sub_selector = rule->sub_selector.value_or(""), + .key = report_key, + .attribute = rule->attribute, }; select_request.attribute_requests.push_back(std::move(attribute_request)); } @@ -148,31 +200,39 @@ void ContentScraper::ParseAndScrapePage( base::BindOnce(&rust_document_extractor::query_element_attributes, html, select_requests), base::BindOnce(&ContentScraper::OnRustElementAttributes, - weak_ptr_factory_.GetWeakPtr(), std::move(interim_result), - std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), is_strict_scrape, + std::move(interim_result), std::move(callback))); } -void ContentScraper::ProcessStandardRule(const ScrapeRule& rule, +void ContentScraper::ProcessStandardRule(const std::string& report_key, + const ScrapeRule& rule, const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result) { if (rule.attribute == kUrlAttrId) { base::Value::Dict dict; - dict.Set(rule.report_key, url.spec()); + dict.Set(report_key, url.spec()); scrape_result->fields[root_selector].push_back(std::move(dict)); } } void ContentScraper::OnScrapedElementAttributes( + bool is_strict_scrape, std::unique_ptr scrape_result, PageScrapeResultCallback callback, std::vector attribute_results) { + const auto* url_details = + (*patterns_)->GetMatchingURLPattern(scrape_result->url, is_strict_scrape); + if (!url_details) { + return; + } for (const auto& attribute_result : attribute_results) { base::Value::Dict attribute_values; for (const auto& [key, value_str] : attribute_result->attribute_values) { base::Value value; if (value_str) { - value = base::Value(*value_str); + value = base::Value(MaybeExecuteRefineFunctions( + url_details, attribute_result->root_selector, key, *value_str)); } attribute_values.Set(key, std::move(value)); } @@ -183,15 +243,23 @@ void ContentScraper::OnScrapedElementAttributes( } void ContentScraper::OnRustElementAttributes( + bool is_strict_scrape, std::unique_ptr scrape_result, PageScrapeResultCallback callback, rust::Vec attribute_results) { + const auto* url_details = + (*patterns_)->GetMatchingURLPattern(scrape_result->url, is_strict_scrape); + if (!url_details) { + return; + } for (const auto& attribute_result : attribute_results) { base::Value::Dict attribute_values; for (const auto& pair : attribute_result.attribute_pairs) { base::Value value; if (!pair.value.empty()) { - value = base::Value(std::string(pair.value)); + value = base::Value(MaybeExecuteRefineFunctions( + url_details, std::string(attribute_result.root_selector), + std::string(pair.key), std::string(pair.value))); } attribute_values.Set(std::string(pair.key), std::move(value)); } @@ -201,4 +269,20 @@ void ContentScraper::OnRustElementAttributes( std::move(callback).Run(std::move(scrape_result)); } +std::string ContentScraper::MaybeExecuteRefineFunctions( + const PatternsURLDetails* url_details, + const std::string& root_selector, + const std::string& report_key, + std::string value) { + const auto rule_group = url_details->scrape_rule_groups.find(root_selector); + if (rule_group != url_details->scrape_rule_groups.end()) { + auto rule = rule_group->second.find(report_key); + if (rule != rule_group->second.end() && + !rule->second->functions_applied.empty()) { + return ExecuteRefineFunctions(rule->second->functions_applied, value); + } + } + return value; +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index 3d856cd00332..c4010336d9da 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -47,29 +47,36 @@ class ContentScraper { ContentScraper& operator=(const ContentScraper&) = delete; // For initial page scrape in renderer - void ScrapePage(const PatternsURLDetails* url_details, - const GURL& url, + void ScrapePage(const GURL& url, + bool is_strict_scrape, mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback); // For subsequent double fetches after initial scrape - void ParseAndScrapePage(std::unique_ptr prev_result, - const PatternsURLDetails* url_details, + void ParseAndScrapePage(bool is_strict_scrape, + std::unique_ptr prev_result, std::string html, PageScrapeResultCallback callback); private: - void ProcessStandardRule(const ScrapeRule& rule, + void ProcessStandardRule(const std::string& report_key, + const ScrapeRule& rule, const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result); void OnScrapedElementAttributes( + bool is_strict_scrape, std::unique_ptr scrape_result, PageScrapeResultCallback callback, std::vector attribute_results); void OnRustElementAttributes( + bool is_strict_scrape, std::unique_ptr scrape_result, PageScrapeResultCallback callback, rust::Vec attribute_results); + std::string MaybeExecuteRefineFunctions(const PatternsURLDetails* url_details, + const std::string& root_selector, + const std::string& report_key, + std::string value); scoped_refptr pool_sequenced_task_runner_; diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index fac586fead2b..2b4fdb2d0357 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -37,8 +37,6 @@ constexpr char kJoinRSAPublicKeyField[] = "pk"; constexpr char kJoinRSASignatureField[] = "sig"; constexpr char kJoinResponseField[] = "joinResponse"; -constexpr char kVersionHeader[] = "Version"; - constexpr char kGSKDictKey[] = "gsk"; constexpr char kCredentialDictKey[] = "credential"; diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index c66621be33d0..fae3f6f8b78f 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -22,10 +22,12 @@ constexpr char kUrlKey[] = "url"; constexpr char kAssociatedDataKey[] = "assoc_data"; constexpr base::TimeDelta kRequestMaxAge = base::Hours(1); -constexpr base::TimeDelta kMinRequestInterval = - base::Minutes(1) - base::Seconds(5); -constexpr base::TimeDelta kMaxRequestInterval = - base::Minutes(1) + base::Seconds(5); +// constexpr base::TimeDelta kMinRequestInterval = +// base::Minutes(1) - base::Seconds(5); +// constexpr base::TimeDelta kMaxRequestInterval = +// base::Minutes(1) + base::Seconds(5); +constexpr base::TimeDelta kMinRequestInterval = base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = base::Seconds(6); constexpr size_t kMaxRetries = 3; constexpr size_t kMaxDoubleFetchResponseSize = 2 * 1024 * 1024; diff --git a/components/web_discovery/browser/ecdh_aes.cc b/components/web_discovery/browser/ecdh_aes.cc index 94f10ebe9559..4d0c59b38fec 100644 --- a/components/web_discovery/browser/ecdh_aes.cc +++ b/components/web_discovery/browser/ecdh_aes.cc @@ -10,6 +10,7 @@ #include "base/base64.h" #include "base/logging.h" #include "base/ranges/algorithm.h" +#include "base/strings/string_number_conversions.h" #include "crypto/random.h" #include "crypto/sha2.h" #include "third_party/boringssl/src/include/openssl/aead.h" @@ -23,7 +24,7 @@ namespace web_discovery { namespace { constexpr size_t kAesKeySize = 16; -constexpr size_t kAesTagLength = 128; +constexpr size_t kAesTagLength = 16; constexpr size_t kIvSize = 12; constexpr size_t kKeyMaterialSize = 32; // P-256 field size * 2 + type byte @@ -45,6 +46,7 @@ AESEncryptResult::AESEncryptResult(std::vector data, encoded_public_component_and_iv(encoded_public_component_and_iv) {} AESEncryptResult::~AESEncryptResult() = default; +AESEncryptResult::AESEncryptResult(const AESEncryptResult&) = default; std::optional DeriveAESKeyAndEncrypt( const std::string& server_pub_key_b64, @@ -55,12 +57,9 @@ std::optional DeriveAESKeyAndEncrypt( return std::nullopt; } - // auto server_public_key = CreateECKey(); auto client_private_key = CreateECKey(); - // auto client_public_key = CreateECKey(); - if (!client_private_key) { // || !client_public_key) {// || - // !server_public_key) { + if (!client_private_key) { VLOG(1) << "Failed to init P-256 curve"; return std::nullopt; } @@ -78,23 +77,11 @@ std::optional DeriveAESKeyAndEncrypt( return std::nullopt; } - // if (!EC_KEY_set_public_key(server_public_key.get(), - // server_public_point.get()) || !EC_KEY_check_key(server_public_key.get())) { - // VLOG(1) << "Failed to load point into server EC public key"; - // return std::nullopt; - // } - if (!EC_KEY_generate_key(client_private_key.get())) { VLOG(1) << "Failed to generate client EC key"; return std::nullopt; } - // if (!EC_KEY_set_public_key(client_public_key.get(), - // EC_KEY_get0_public_key(client_private_key.get()))) { - // VLOG(1) << "Failed to set client EC public key"; - // return std::nullopt; - // } - uint8_t shared_key_material[kKeyMaterialSize]; if (!ECDH_compute_key(shared_key_material, kKeyMaterialSize, server_public_point.get(), client_private_key.get(), @@ -107,7 +94,6 @@ std::optional DeriveAESKeyAndEncrypt( auto aes_key = std::vector(key_material_hash.begin(), key_material_hash.begin() + kAesKeySize); - auto* algo = EVP_aead_aes_128_gcm(); bssl::ScopedEVP_AEAD_CTX ctx; diff --git a/components/web_discovery/browser/ecdh_aes.h b/components/web_discovery/browser/ecdh_aes.h index a7ad0c7e3551..d9ce7604888f 100644 --- a/components/web_discovery/browser/ecdh_aes.h +++ b/components/web_discovery/browser/ecdh_aes.h @@ -17,8 +17,7 @@ struct AESEncryptResult { std::string encoded_public_component_and_iv); ~AESEncryptResult(); - AESEncryptResult(const AESEncryptResult&) = delete; - AESEncryptResult& operator=(const AESEncryptResult&) = delete; + AESEncryptResult(const AESEncryptResult&); std::vector data; std::string encoded_public_component_and_iv; diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index 9725e04b6a32..a07767c7aac6 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -31,6 +31,7 @@ constexpr char kActionKey[] = "action"; constexpr char kFieldsKey[] = "fields"; constexpr char kPayloadsKey[] = "payloads"; constexpr char kJoinFieldAction[] = "join"; +constexpr char kFunctionsAppliedKey[] = "functionsApplied"; constexpr auto kScrapeRuleTypeMap = base::MakeFixedFlatMap({ @@ -99,6 +100,7 @@ std::optional> ParsePayloadRules( VLOG(1) << "Payload rule or result types unknown"; return std::nullopt; } + rule_group_it->action = *action; rule_group_it->key = key; rule_group_it->result_type = result_type_it->second; rule_group_it->rule_type = rule_type_it->second; @@ -119,21 +121,34 @@ std::optional> ParsePayloadRules( return result; } -std::optional> ParseScrapeRules( +RefineFunctionList ParseFunctionsApplied(const base::Value::List* list) { + RefineFunctionList result; + for (const auto& function_val : *list) { + const auto* function_list = function_val.GetIfList(); + if (!function_list || function_list->size() <= 1) { + continue; + } + std::vector function_vec; + for (const auto& element : *function_list) { + function_vec.push_back(element.Clone()); + } + result.push_back(std::move(function_vec)); + } + return result; +} + +std::optional> ParseScrapeRules( const base::Value::Dict* scrape_url_dict) { - std::vector result(scrape_url_dict->size()); + base::flat_map result; - auto rule_group_it = result.begin(); for (const auto [selector, rule_group_value] : *scrape_url_dict) { auto* rule_group_dict = rule_group_value.GetIfDict(); if (!rule_group_dict) { VLOG(1) << "Scrape rule group is not a dict"; return std::nullopt; } - rule_group_it->selector = selector; - rule_group_it->rules = std::vector(rule_group_dict->size()); - auto rule_it = rule_group_it->rules.begin(); + auto& rule_group = result[selector]; for (const auto [report_key, rule_value] : *rule_group_dict) { auto* rule_dict = rule_value.GetIfDict(); if (!rule_dict) { @@ -143,26 +158,28 @@ std::optional> ParseScrapeRules( auto* sub_selector = rule_dict->FindString(kSubSelectorKey); auto* attribute = rule_dict->FindString(kAttributeKey); auto* rule_type_str = rule_dict->FindString(kRuleTypeKey); + auto* functions_applied = rule_dict->FindList(kFunctionsAppliedKey); if (!attribute) { VLOG(1) << "Attribute missing from rule"; return std::nullopt; } - rule_it->report_key = report_key; - rule_it->rule_type = ScrapeRuleType::kOther; + auto rule = std::make_unique(); + rule->rule_type = ScrapeRuleType::kOther; if (rule_type_str) { auto rule_type_it = kScrapeRuleTypeMap.find(*rule_type_str); if (rule_type_it != kScrapeRuleTypeMap.end()) { - rule_it->rule_type = rule_type_it->second; + rule->rule_type = rule_type_it->second; } } - rule_it->attribute = *attribute; + rule->attribute = *attribute; if (sub_selector) { - rule_it->sub_selector = *sub_selector; + rule->sub_selector = *sub_selector; + } + if (functions_applied) { + rule->functions_applied = ParseFunctionsApplied(functions_applied); } - rule_it = std::next(rule_it); + rule_group[report_key] = std::move(rule); } - - rule_group_it = std::next(rule_group_it); } return result; } @@ -231,9 +248,6 @@ std::optional> ParsePatternsURLDetails( ScrapeRule::ScrapeRule() = default; ScrapeRule::~ScrapeRule() = default; -ScrapeRuleGroup::ScrapeRuleGroup() = default; -ScrapeRuleGroup::~ScrapeRuleGroup() = default; - PayloadRule::PayloadRule() = default; PayloadRule::~PayloadRule() = default; diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index b3bc6f1050e7..3a2584eb38a6 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -11,6 +11,8 @@ #include #include +#include "base/containers/flat_map.h" +#include "base/values.h" #include "url/gurl.h" namespace re2 { @@ -23,6 +25,8 @@ enum class ScrapeRuleType { kStandard, kSearchQuery, kWidgetTitle, kOther }; enum class PayloadRuleType { kQuery, kSingle }; enum class PayloadResultType { kSingle, kClustered, kCustom }; +using RefineFunctionList = std::vector>; + struct ScrapeRule { ScrapeRule(); ~ScrapeRule(); @@ -30,23 +34,15 @@ struct ScrapeRule { ScrapeRule(const ScrapeRule&) = delete; ScrapeRule& operator=(const ScrapeRule&) = delete; - std::string report_key; std::string selector; std::optional sub_selector; ScrapeRuleType rule_type; std::string attribute; + RefineFunctionList functions_applied; }; -struct ScrapeRuleGroup { - ScrapeRuleGroup(); - ~ScrapeRuleGroup(); - - ScrapeRuleGroup(const ScrapeRuleGroup&) = delete; - ScrapeRuleGroup& operator=(const ScrapeRuleGroup&) = delete; - - std::string selector; - std::vector rules; -}; +using ScrapeRuleGroup = + base::flat_map>; struct PayloadRule { PayloadRule(); @@ -84,7 +80,7 @@ struct PatternsURLDetails { std::unique_ptr url_regex; bool is_search_engine; std::string id; - std::vector scrape_rule_groups; + base::flat_map scrape_rule_groups; std::vector payload_rule_groups; }; diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index d999615b1442..cade1d545664 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -12,14 +12,13 @@ #include "base/numerics/byte_conversions.h" #include "base/rand_util.h" #include "base/task/thread_pool.h" -#include "brave/components/web_discovery/browser/ecdh_aes.h" #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/signature_basename.h" #include "brave/components/web_discovery/browser/util.h" #include "crypto/sha2.h" #include "services/network/public/cpp/resource_request_body.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" -#include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/zlib/google/compression_utils_portable.h" #include "third_party/zlib/zlib.h" @@ -47,10 +46,12 @@ constexpr net::NetworkTrafficAnnotationTag kSubmitNetworkTrafficAnnotation = })"); constexpr base::TimeDelta kRequestMaxAge = base::Hours(36); -constexpr base::TimeDelta kMinRequestInterval = - base::Minutes(1) - base::Seconds(5); -constexpr base::TimeDelta kMaxRequestInterval = - base::Minutes(1) + base::Seconds(5); +// constexpr base::TimeDelta kMinRequestInterval = +// base::Minutes(1) - base::Seconds(5); +// constexpr base::TimeDelta kMaxRequestInterval = +// base::Minutes(1) + base::Seconds(5); +constexpr base::TimeDelta kMinRequestInterval = base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = base::Seconds(6); constexpr size_t kMaxRetries = 10; constexpr char kTypeField[] = "type"; @@ -66,6 +67,7 @@ constexpr char kSenderField[] = "sender"; constexpr char kHpnSenderValue[] = "hpnv2"; constexpr uint8_t kSignedMessageId = 0x03; +constexpr uint8_t kCompressedMessageId = 0x80; // id byte + basename count + signature constexpr size_t kSignedMessageMetadataSize = 1 + 8 + 389; constexpr size_t kMaxCompressedMessageSize = 32767; @@ -88,40 +90,33 @@ base::Value GenerateFinalPayload(const base::Value::Dict& pre_payload) { return base::Value(std::move(result)); } -std::optional CompressAndEncrypt( +std::optional CompressAndEncrypt( std::vector full_signed_message, std::string server_pub_key) { uLongf compressed_data_size = compressBound(full_signed_message.size()); std::vector compressed_data(compressed_data_size + 2); if (zlib_internal::CompressHelper( - zlib_internal::ZLIB, compressed_data.data(), &compressed_data_size, - full_signed_message.data() + 2, full_signed_message.size(), - Z_DEFAULT_COMPRESSION, nullptr, nullptr) != Z_OK) { + zlib_internal::ZLIB, compressed_data.data() + 2, + &compressed_data_size, full_signed_message.data(), + full_signed_message.size(), Z_DEFAULT_COMPRESSION, nullptr, + nullptr) != Z_OK) { + VLOG(1) << "Failed to compress payload"; return std::nullopt; } + compressed_data.resize(compressed_data_size + 2); if (compressed_data_size > kMaxCompressedMessageSize) { + VLOG(1) << "Compressed payload exceeds limit of " + << kMaxCompressedMessageSize << " bytes"; return std::nullopt; } base::ranges::copy(base::U16ToBigEndian(compressed_data_size), compressed_data.begin()); - auto encrypt_result = DeriveAESKeyAndEncrypt(server_pub_key, compressed_data); - if (!encrypt_result) { - return std::nullopt; - } - return std::make_optional( - compressed_data, encrypt_result->encoded_public_component_and_iv); + compressed_data[0] |= kCompressedMessageId; + return DeriveAESKeyAndEncrypt(server_pub_key, compressed_data); } } // namespace -CompressEncryptResult::CompressEncryptResult(std::vector data, - std::string encoded) - : encrypted_data(data), encoded_public_component_and_iv(encoded) {} - -CompressEncryptResult::~CompressEncryptResult() = default; -CompressEncryptResult::CompressEncryptResult(const CompressEncryptResult&) = - default; - Reporter::Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, CredentialManager* credential_manager, @@ -150,14 +145,17 @@ void Reporter::ScheduleSend(base::Value::Dict payload) { } void Reporter::PrepareRequest(const base::Value& request_data) { + VLOG(1) << "Preparing request"; if (!credential_manager_->CredentialExistsForToday()) { // Backoff until credential is available to today + VLOG(1) << "Credential does not exist for today"; request_queue_.NotifyRequestComplete(false); return; } const auto* payload_dict = request_data.GetIfDict(); if (!payload_dict) { // Drop request due to bad data + VLOG(1) << "Payload is not a dictionary"; request_queue_.NotifyRequestComplete(true); return; } @@ -165,13 +163,14 @@ void Reporter::PrepareRequest(const base::Value& request_data) { profile_prefs_, (*last_loaded_server_config_).get(), *payload_dict); if (!basename_result) { // Drop request due to exceeded basename quota + VLOG(1) << "Failed to generate basename"; request_queue_.NotifyRequestComplete(true); return; } auto final_payload = GenerateFinalPayload(*payload_dict); std::string final_payload_json; - if (base::JSONWriter::Write(final_payload, &final_payload_json)) { + if (!base::JSONWriter::Write(final_payload, &final_payload_json)) { request_queue_.NotifyRequestComplete(true); return; } @@ -181,11 +180,13 @@ void Reporter::PrepareRequest(const base::Value& request_data) { std::vector(payload_hash.begin(), payload_hash.end()), basename_result->basename, base::BindOnce(&Reporter::OnRequestSigned, weak_ptr_factory_.GetWeakPtr(), - final_payload_json, basename_result->count)); + final_payload_json, basename_result->count_tag_hash, + basename_result->count)); } void Reporter::OnRequestSigned( std::string final_payload_json, + uint8_t count_tag_hash, size_t basename_count, std::optional> signature) { if (!signature) { @@ -195,6 +196,7 @@ void Reporter::OnRequestSigned( auto pub_key = (*last_loaded_server_config_) ->pub_keys.find(FormatServerDate(base::Time::Now())); if (pub_key == (*last_loaded_server_config_)->pub_keys.end()) { + VLOG(1) << "No ECDH server public key available"; request_queue_.NotifyRequestComplete(false); return; } @@ -207,6 +209,7 @@ void Reporter::OnRequestSigned( final_payload_json.size())) || !message_writer.Write(base::DoubleToBigEndian(basename_count)) || !message_writer.Write(*signature)) { + VLOG(1) << "Failed to pack signed message"; request_queue_.NotifyRequestComplete(true); return; } @@ -214,39 +217,58 @@ void Reporter::OnRequestSigned( FROM_HERE, base::BindOnce(&CompressAndEncrypt, full_signed_message, pub_key->second), base::BindOnce(&Reporter::OnRequestCompressedAndEncrypted, - weak_ptr_factory_.GetWeakPtr())); + + weak_ptr_factory_.GetWeakPtr(), count_tag_hash, + basename_count)); } void Reporter::OnRequestCompressedAndEncrypted( - std::optional result) { + uint8_t count_tag_hash, + size_t basename_count, + std::optional result) { if (!result) { request_queue_.NotifyRequestComplete(true); return; } auto request = CreateResourceRequest(submit_url_); + request->method = net::HttpRequestHeaders::kPostMethod; request->headers.SetHeader(kKeyDateHeader, FormatServerDate(base::Time::Now())); request->headers.SetHeader(kEncryptionHeader, result->encoded_public_component_and_iv); + request->headers.SetHeader(kVersionHeader, + base::NumberToString(kCurrentVersion)); + VLOG(1) << "Sending message"; url_loader_ = network::SimpleURLLoader::Create( std::move(request), kSubmitNetworkTrafficAnnotation); url_loader_->AttachStringForUpload( - std::string(result->encrypted_data.begin(), result->encrypted_data.end()), + std::string(result->data.begin(), result->data.end()), kMessageContentType); + url_loader_->DownloadHeadersOnly( + shared_url_loader_factory_.get(), + base::BindOnce(&Reporter::OnRequestComplete, base::Unretained(this), + count_tag_hash, basename_count)); } -void Reporter::OnRequestComplete(std::optional response_body) { - request_queue_.NotifyRequestComplete(ValidateResponse(response_body)); +void Reporter::OnRequestComplete( + uint8_t count_tag_hash, + size_t basename_count, + scoped_refptr headers) { + auto result = ValidateResponse(headers); + VLOG(1) << "Submission result: " << result; + if (result) { + SaveBasenameCount(profile_prefs_, count_tag_hash, basename_count); + } + request_queue_.NotifyRequestComplete(result); } bool Reporter::ValidateResponse( - const std::optional& response_body) { - auto* response_info = url_loader_->ResponseInfo(); - if (!response_body || !response_info) { + scoped_refptr headers) { + if (!headers) { return false; } - auto response_code = response_info->headers->response_code(); + auto response_code = headers->response_code(); if (response_code < 200 || response_code >= 300) { if (response_code >= 500) { // Only retry failures due to server error diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index 7c64342c58a7..d049e3873d0b 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -14,8 +14,10 @@ #include "base/memory/raw_ptr.h" #include "base/values.h" #include "brave/components/web_discovery/browser/credential_manager.h" +#include "brave/components/web_discovery/browser/ecdh_aes.h" #include "brave/components/web_discovery/browser/request_queue.h" #include "brave/components/web_discovery/browser/server_config_loader.h" +#include "net/http/http_response_headers.h" class PrefService; @@ -26,16 +28,6 @@ class SimpleURLLoader; namespace web_discovery { -struct CompressEncryptResult { - CompressEncryptResult(std::vector data, std::string encoded); - ~CompressEncryptResult(); - - CompressEncryptResult(const CompressEncryptResult&); - - std::vector encrypted_data; - std::string encoded_public_component_and_iv; -}; - class Reporter { public: Reporter(PrefService* profile_prefs, @@ -52,12 +44,16 @@ class Reporter { private: void PrepareRequest(const base::Value& request_data); void OnRequestSigned(std::string final_payload_json, + uint8_t count_tag_hash, size_t basename_count, std::optional> signature); - void OnRequestCompressedAndEncrypted( - std::optional result); - void OnRequestComplete(std::optional response_body); - bool ValidateResponse(const std::optional& response_body); + void OnRequestCompressedAndEncrypted(uint8_t count_tag_hash, + size_t basename_count, + std::optional result); + void OnRequestComplete(uint8_t count_tag_hash, + size_t basename_count, + scoped_refptr headers); + bool ValidateResponse(scoped_refptr headers); GURL submit_url_; diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 98888f9fe7ce..c785f2784812 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -63,6 +63,7 @@ constexpr char kKeysFieldName[] = "keys"; constexpr char kLimitFieldName[] = "limit"; constexpr char kPeriodFieldName[] = "period"; constexpr char kSourceMapFieldName[] = "sourceMap"; +constexpr char kSourceMapActionsFieldName[] = "actions"; constexpr char kConfigPathWithFields[] = "/config?fields=minVersion,groupPubKeys,pubKeys,sourceMap"; @@ -101,8 +102,8 @@ base::flat_map ParseSourceMapActionConfigs( auto limit = config_dict->FindInt(kLimitFieldName); auto period = config_dict->FindInt(kPeriodFieldName); - action_config.limit = limit && limit >= 0 ? *limit : 1; - action_config.period = period && period >= 0 ? *period : 24; + action_config.limit = limit && limit > 0 ? *limit : 1; + action_config.period = period && period > 0 ? *period : 24; } return map; } @@ -243,14 +244,16 @@ bool ServerConfigLoader::ProcessConfigResponse( return false; } const auto* source_map = root->FindDict(kSourceMapFieldName); - if (!source_map) { + const auto* source_map_actions = + source_map ? source_map->FindDict(kSourceMapActionsFieldName) : nullptr; + if (!source_map_actions) { VLOG(1) << "Failed to retrieve sourceMap from server config"; return false; } config->group_pub_keys = ParseKeys(*group_pub_keys); config->pub_keys = ParseKeys(*pub_keys); - config->source_map_actions = ParseSourceMapActionConfigs(*source_map); + config->source_map_actions = ParseSourceMapActionConfigs(*source_map_actions); config_callback_.Run(std::move(config)); return true; diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc index 06067d2c801f..f1731fac178c 100644 --- a/components/web_discovery/browser/signature_basename.cc +++ b/components/web_discovery/browser/signature_basename.cc @@ -91,16 +91,9 @@ int GetPeriodHoursSinceEpoch(size_t period_hours) { } std::optional GetBasenameCount(PrefService* profile_prefs, - const base::Value::List& interim_tag_list, + uint32_t count_tag_hash, const SourceMapActionConfig& action_config, size_t period_hours) { - std::string interim_tag_json; - if (!base::JSONWriter::Write(base::Value(interim_tag_list.Clone()), - &interim_tag_json)) { - return std::nullopt; - } - auto tag_hash = base::NumberToString(base::PersistentHash(interim_tag_json)); - // clean up expired counts ScopedDictPrefUpdate update(profile_prefs, kUsedBasenameCounts); base::Time now = base::Time::Now(); @@ -119,7 +112,8 @@ std::optional GetBasenameCount(PrefService* profile_prefs, it++; } - auto* count_dict = update->EnsureDict(tag_hash); + auto count_tag_hash_str = base::NumberToString(count_tag_hash); + auto* count_dict = update->EnsureDict(count_tag_hash_str); if (!count_dict->contains(kExpiresAtKey)) { auto expire_time = base::Time::FromMillisecondsSinceUnixEpoch(static_cast( @@ -129,26 +123,27 @@ std::optional GetBasenameCount(PrefService* profile_prefs, auto* used_counts_list = count_dict->EnsureList(kUsedCountsKey); if (used_counts_list->size() >= action_config.limit) { + VLOG(1) << "used count = " << used_counts_list + << ", limit = " << action_config.limit; return std::nullopt; } - while (auto count = base::RandInt(0, action_config.limit - 1)) { + while (true) { + auto count = base::RandInt(0, action_config.limit - 1); if (base::ranges::find(used_counts_list->begin(), used_counts_list->end(), count) != used_counts_list->end()) { continue; } - used_counts_list->Append(count); return count; } - NOTREACHED(); - return 0; } } // namespace BasenameResult::BasenameResult(std::vector basename, - size_t count) - : basename(basename), count(count) {} + size_t count, + uint32_t count_tag_hash) + : basename(basename), count(count), count_tag_hash(count_tag_hash) {} BasenameResult::~BasenameResult() = default; @@ -157,15 +152,20 @@ std::optional GenerateBasename( ServerConfig* server_config, const base::Value::Dict& payload) { const std::string* action = payload.FindString(kActionKey); + std::string json; + base::JSONWriter::Write(payload, &json); if (!action || action->empty()) { + VLOG(1) << "No action"; return std::nullopt; } const auto action_config = server_config->source_map_actions.find(*action); if (action_config == server_config->source_map_actions.end()) { + VLOG(1) << "No action config for " << action; return std::nullopt; } const auto* inner_payload = payload.FindDict(kInnerPayloadKey); if (!inner_payload) { + VLOG(1) << "No inner payload"; return std::nullopt; } base::Value::List tag_list; @@ -197,9 +197,16 @@ std::optional GenerateBasename( tag_list.Append(std::move(key_values)); tag_list.Append(period_hours); - auto basename_count = GetBasenameCount(profile_prefs, tag_list, + std::string interim_tag_json; + if (!base::JSONWriter::Write(base::Value(tag_list.Clone()), + &interim_tag_json)) { + return std::nullopt; + } + auto count_tag_hash = base::PersistentHash(interim_tag_json); + auto basename_count = GetBasenameCount(profile_prefs, count_tag_hash, action_config->second, period_hours); if (!basename_count) { + VLOG(1) << "No basename count available"; return std::nullopt; } tag_list.Append(*basename_count); @@ -211,7 +218,20 @@ std::optional GenerateBasename( auto tag_hash = crypto::SHA256HashString(tag_json); std::vector tag_hash_vector(tag_hash.begin(), tag_hash.end()); - return std::make_optional(tag_hash_vector, *basename_count); + return std::make_optional(tag_hash_vector, *basename_count, + count_tag_hash); +} + +void SaveBasenameCount(PrefService* profile_prefs, + uint32_t count_tag_hash, + size_t count) { + ScopedDictPrefUpdate update(profile_prefs, kUsedBasenameCounts); + + auto count_tag_hash_str = base::NumberToString(count_tag_hash); + auto* count_dict = update->EnsureDict(count_tag_hash_str); + + auto* used_counts_list = count_dict->EnsureList(kUsedCountsKey); + used_counts_list->Append(static_cast(count)); } } // namespace web_discovery diff --git a/components/web_discovery/browser/signature_basename.h b/components/web_discovery/browser/signature_basename.h index 2c784f2b9c3e..775dbe8c60d1 100644 --- a/components/web_discovery/browser/signature_basename.h +++ b/components/web_discovery/browser/signature_basename.h @@ -17,7 +17,9 @@ class PrefService; namespace web_discovery { struct BasenameResult { - BasenameResult(std::vector basename, size_t count); + BasenameResult(std::vector basename, + size_t count, + uint32_t count_tag_hash); ~BasenameResult(); BasenameResult(const BasenameResult&) = delete; @@ -27,6 +29,7 @@ struct BasenameResult { // The count index for a given "pre-tag". It should be under the limit for a // given action size_t count; + uint32_t count_tag_hash; }; std::optional GenerateBasename( @@ -34,6 +37,10 @@ std::optional GenerateBasename( ServerConfig* server_config, const base::Value::Dict& payload); +void SaveBasenameCount(PrefService* profile_prefs, + uint32_t count_tag_hash, + size_t count); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index fd9e75ac4a02..97f68a89c15c 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -18,6 +18,7 @@ namespace web_discovery { inline constexpr size_t kMaxResponseSize = 16 * 1024; inline constexpr char kCollectorHostSwitch[] = "wdp-collector-host"; +inline constexpr char kVersionHeader[] = "Version"; inline constexpr int kCurrentVersion = 1; inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 4031ca777df2..38c341ade56b 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "brave/components/constants/pref_names.h" #include "brave/components/web_discovery/browser/content_scraper.h" +#include "brave/components/web_discovery/browser/payload_generator.h" #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_registry_simple.h" @@ -110,13 +111,8 @@ void WDPService::OnDoubleFetched(const base::Value& associated_data, if (!prev_scrape_result) { return; } - auto* url_pattern = last_loaded_patterns_->GetMatchingURLPattern( - prev_scrape_result->url, true); - if (!url_pattern) { - return; - } content_scraper_->ParseAndScrapePage( - std::move(prev_scrape_result), url_pattern, *response_body, + true, std::move(prev_scrape_result), *response_body, base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this), true)); } @@ -127,15 +123,11 @@ void WDPService::OnFinishNavigation( if (!content_scraper_) { return; } - auto* url_pattern = last_loaded_patterns_->GetMatchingURLPattern(url, false); - if (!url_pattern) { - return; - } mojo::Remote remote; render_frame_host->GetRemoteInterfaces()->GetInterface( remote.BindNewPipeAndPassReceiver()); auto remote_id = document_extractor_remotes_.Add(std::move(remote)); - content_scraper_->ScrapePage(url_pattern, url, + content_scraper_->ScrapePage(url, false, document_extractor_remotes_.Get(remote_id), base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this), false)); diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 3000da399612..1206a06fc45f 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -16,7 +16,6 @@ #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/double_fetcher.h" #include "brave/components/web_discovery/browser/patterns.h" -#include "brave/components/web_discovery/browser/payload_generator.h" #include "brave/components/web_discovery/browser/reporter.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" diff --git a/components/web_discovery/renderer/blink_document_extractor.cc b/components/web_discovery/renderer/blink_document_extractor.cc index cffd7cf0d9bb..87afbaa33600 100644 --- a/components/web_discovery/renderer/blink_document_extractor.cc +++ b/components/web_discovery/renderer/blink_document_extractor.cc @@ -50,6 +50,7 @@ void ProcessAttributeRequests( } attributes_result->attribute_values[request->key] = attribute_value; } + results.push_back(std::move(attributes_result)); } } From 5e2c7626dcdc7419ccc939b3fa1f423d066a7777 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Fri, 7 Jun 2024 11:04:57 -0700 Subject: [PATCH 15/36] Retrieve Web Discovery quorum config, add country code to messages --- .../web_discovery/browser/content_scraper.cc | 16 ++- .../web_discovery/browser/content_scraper.h | 5 +- .../browser/payload_generator.cc | 23 ++-- .../web_discovery/browser/payload_generator.h | 1 + .../browser/server_config_loader.cc | 106 ++++++++++++------ .../browser/server_config_loader.h | 18 ++- .../browser/signature_basename.cc | 23 ++-- components/web_discovery/browser/util.cc | 6 + components/web_discovery/browser/util.h | 1 + .../web_discovery/browser/wdp_service.cc | 7 +- 10 files changed, 137 insertions(+), 69 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 8819176677e4..31b727acb120 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -18,6 +18,7 @@ namespace web_discovery { namespace { constexpr char kUrlAttrId[] = "url"; +constexpr char kCountryCodeAttrId[] = "ctry"; constexpr char kFieldsValueKey[] = "fields"; constexpr char kIdValueKey[] = "id"; constexpr char kUrlValueKey[] = "url"; @@ -66,9 +67,12 @@ PageScrapeResult::PageScrapeResult(GURL url, std::string id) : url(url), id(id) {} PageScrapeResult::~PageScrapeResult() = default; -ContentScraper::ContentScraper(std::unique_ptr* patterns) +ContentScraper::ContentScraper( + std::unique_ptr* last_loaded_server_config, + std::unique_ptr* patterns) : pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), + last_loaded_server_config_(last_loaded_server_config), patterns_(patterns) {} ContentScraper::~ContentScraper() = default; @@ -209,10 +213,14 @@ void ContentScraper::ProcessStandardRule(const std::string& report_key, const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result) { + auto& fields = scrape_result->fields[root_selector]; + if (fields.empty()) { + fields.emplace_back(); + } if (rule.attribute == kUrlAttrId) { - base::Value::Dict dict; - dict.Set(report_key, url.spec()); - scrape_result->fields[root_selector].push_back(std::move(dict)); + fields[0].Set(report_key, url.spec()); + } else if (rule.attribute == kCountryCodeAttrId) { + fields[0].Set(report_key, (*last_loaded_server_config_)->location); } } diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index c4010336d9da..4b9f57a2e57d 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -15,6 +15,7 @@ #include "base/values.h" #include "brave/components/web_discovery/browser/document_extractor/rs/src/lib.rs.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" #include "url/gurl.h" @@ -40,7 +41,8 @@ class ContentScraper { using PageScrapeResultCallback = base::OnceCallback)>; - explicit ContentScraper(std::unique_ptr* patterns); + ContentScraper(std::unique_ptr* last_loaded_server_config, + std::unique_ptr* patterns); ~ContentScraper(); ContentScraper(const ContentScraper&) = delete; @@ -80,6 +82,7 @@ class ContentScraper { scoped_refptr pool_sequenced_task_runner_; + raw_ptr> last_loaded_server_config_; raw_ptr> patterns_; base::WeakPtrFactory weak_ptr_factory_{this}; diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index ace73cab8f35..bcc551f4d20b 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -11,6 +11,8 @@ namespace web_discovery { namespace { +constexpr char kCountryCodeFieldName[] = "ctry"; + bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); if (value_str && !value_str->empty()) { @@ -54,10 +56,6 @@ std::optional GenerateClusteredPayload( auto attribute_values_it = scrape_result->fields.find(rule.selector); if (attribute_values_it == scrape_result->fields.end() || attribute_values_it->second.empty()) { - // TODO(djandries): remove this exception and actually insert ctry - if (rule.selector == "ctry") { - continue; - } return std::nullopt; } if (rule.is_join) { @@ -70,14 +68,16 @@ std::optional GenerateClusteredPayload( joined_data.Set(base::NumberToString(counter++), value.Clone()); } if (!AggregatedDictHasContent(joined_data)) { - VLOG(1) << "Skipped joined clustered payload"; + VLOG(1) << "Skipped joined clustered payload, action = " + << rule_group.action; return std::nullopt; } payload_rule_data = base::Value(std::move(joined_data)); } else { const auto* value = attribute_values_it->second[0].FindString(rule.key); if (!value || value->empty()) { - VLOG(1) << "Skipped non-joined clustered payload"; + VLOG(1) << "Skipped non-joined clustered payload, action = " + << rule_group.action; return std::nullopt; } payload_rule_data = base::Value(*value); @@ -87,7 +87,8 @@ std::optional GenerateClusteredPayload( return CreatePayloadDict(rule_group, std::move(inner_payload)); } -void GenerateSinglePayloads(const PayloadRuleGroup& rule_group, +void GenerateSinglePayloads(const ServerConfig& server_config, + const PayloadRuleGroup& rule_group, const PageScrapeResult* scrape_result, std::vector& payloads) { auto attribute_values_it = scrape_result->fields.find(rule_group.key); @@ -95,13 +96,16 @@ void GenerateSinglePayloads(const PayloadRuleGroup& rule_group, return; } for (const auto& attribute_value : attribute_values_it->second) { - payloads.push_back(CreatePayloadDict(rule_group, attribute_value.Clone())); + auto dict = attribute_value.Clone(); + dict.Set(kCountryCodeFieldName, server_config.location); + payloads.push_back(CreatePayloadDict(rule_group, std::move(dict))); } } } // namespace std::vector GeneratePayloads( + const ServerConfig& server_config, const PatternsURLDetails* url_details, std::unique_ptr scrape_result) { std::vector payloads; @@ -114,7 +118,8 @@ std::vector GeneratePayloads( } } else if (rule_group.rule_type == PayloadRuleType::kSingle && rule_group.result_type == PayloadResultType::kSingle) { - GenerateSinglePayloads(rule_group, scrape_result.get(), payloads); + GenerateSinglePayloads(server_config, rule_group, scrape_result.get(), + payloads); } } return payloads; diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h index ea08f92b1d83..cb788673e115 100644 --- a/components/web_discovery/browser/payload_generator.h +++ b/components/web_discovery/browser/payload_generator.h @@ -19,6 +19,7 @@ inline constexpr char kActionKey[] = "action"; inline constexpr char kInnerPayloadKey[] = "payload"; std::vector GeneratePayloads( + const ServerConfig& server_config, const PatternsURLDetails* url_details, std::unique_ptr scrape_result); diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index c785f2784812..a4219099f40c 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -7,7 +7,9 @@ #include +#include "base/barrier_callback.h" #include "base/base64.h" +#include "base/containers/fixed_flat_set.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/json/json_reader.h" @@ -64,11 +66,20 @@ constexpr char kLimitFieldName[] = "limit"; constexpr char kPeriodFieldName[] = "period"; constexpr char kSourceMapFieldName[] = "sourceMap"; constexpr char kSourceMapActionsFieldName[] = "actions"; +constexpr char kLocationFieldName[] = "location"; -constexpr char kConfigPathWithFields[] = +constexpr char kCollectorConfigPathWithFields[] = "/config?fields=minVersion,groupPubKeys,pubKeys,sourceMap"; +constexpr char kQuorumConfigPath[] = "/config"; constexpr char kPatternsFilename[] = "wdp_patterns.json"; +constexpr char kOmittedLocationValue[] = "--"; +constexpr auto kAllowedReportLocations = + base::MakeFixedFlatSet( + {"de", "at", "ch", "es", "us", "fr", "nl", "gb", "it", "be", + "se", "dk", "fi", "cz", "gr", "hu", "ro", "no", "ca", "au", + "ru", "ua", "in", "pl", "jp", "br", "mx", "cn", "ar"}); + KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { KeyMap map; for (const auto [date, key_b64] : encoded_keys) { @@ -153,39 +164,46 @@ ServerConfigLoader::ServerConfigLoader( patterns_callback_(patterns_callback), config_backoff_entry_(&kBackoffPolicy), patterns_backoff_entry_(&kBackoffPolicy) { - config_url_ = GURL(GetCollectorHost() + kConfigPathWithFields); + collector_config_url_ = + GURL(GetCollectorHost() + kCollectorConfigPathWithFields); + quorum_config_url_ = GURL(GetQuorumHost() + kQuorumConfigPath); patterns_url_ = GetPatternsEndpoint(); patterns_path_ = user_data_dir.Append(kPatternsFilename); + LoadConfigs(); } ServerConfigLoader::~ServerConfigLoader() = default; -void ServerConfigLoader::Load() { - // TODO(djandries): create a backoff url loader if one doenst exist - // but consider how join retries will work before you do. we might want to - // generate gsk beforehand... in which case it might make sense to add a - // repeating callback for generating state + network requests - if (config_url_loader_) { +void ServerConfigLoader::LoadConfigs() { + if (collector_config_url_loader_ || quorum_config_url_loader_) { // Another request is in progress return; } - auto resource_request = CreateResourceRequest(config_url_); - - config_url_loader_ = network::SimpleURLLoader::Create( - std::move(resource_request), kNetworkTrafficAnnotation); - - config_url_loader_->DownloadToString( - shared_url_loader_factory_.get(), - base::BindOnce(&ServerConfigLoader::OnConfigResponse, - base::Unretained(this)), - kMaxResponseSize); + auto collector_resource_request = + CreateResourceRequest(collector_config_url_); + auto quorum_resource_request = CreateResourceRequest(quorum_config_url_); + + collector_config_url_loader_ = network::SimpleURLLoader::Create( + std::move(collector_resource_request), kNetworkTrafficAnnotation); + quorum_config_url_loader_ = network::SimpleURLLoader::Create( + std::move(quorum_resource_request), kNetworkTrafficAnnotation); + + auto callback = base::BarrierCallback>( + 2, base::BindOnce(&ServerConfigLoader::OnConfigResponses, + base::Unretained(this))); + + collector_config_url_loader_->DownloadToString( + shared_url_loader_factory_.get(), callback, kMaxResponseSize); + quorum_config_url_loader_->DownloadToString(shared_url_loader_factory_.get(), + callback, kMaxResponseSize); } -void ServerConfigLoader::OnConfigResponse( - std::optional response_body) { +void ServerConfigLoader::OnConfigResponses( + std::vector> response_bodies) { + CHECK_EQ(response_bodies.size(), 2u); base::Time update_time = base::Time::Now(); - bool result = ProcessConfigResponse(response_body); + bool result = ProcessConfigResponses(response_bodies[0], response_bodies[1]); config_backoff_entry_.InformOfRequest(result); @@ -199,33 +217,40 @@ void ServerConfigLoader::OnConfigResponse( config_update_timer_.Start( FROM_HERE, update_time, - base::BindOnce(&ServerConfigLoader::Load, base::Unretained(this))); + base::BindOnce(&ServerConfigLoader::LoadConfigs, base::Unretained(this))); } -bool ServerConfigLoader::ProcessConfigResponse( - const std::optional& response_body) { - auto* response_info = config_url_loader_->ResponseInfo(); - if (!response_body || !response_info || - response_info->headers->response_code() != 200) { +bool ServerConfigLoader::ProcessConfigResponses( + const std::optional& collector_response_body, + const std::optional& quorum_response_body) { + auto* collector_response_info = collector_config_url_loader_->ResponseInfo(); + auto* quorum_response_info = quorum_config_url_loader_->ResponseInfo(); + if (!collector_response_body || !collector_response_info || + !quorum_response_body || !collector_response_info || + collector_response_info->headers->response_code() != 200 || + quorum_response_info->headers->response_code() != 200) { VLOG(1) << "Failed to fetch server config"; return false; } - auto parsed_json = base::JSONReader::ReadAndReturnValueWithError( - *response_body, base::JSON_PARSE_RFC); + auto collector_parsed_json = base::JSONReader::ReadAndReturnValueWithError( + *collector_response_body, base::JSON_PARSE_RFC); + auto quorum_parsed_json = base::JSONReader::ReadAndReturnValueWithError( + *quorum_response_body, base::JSON_PARSE_RFC); - if (!parsed_json.has_value()) { + if (!collector_parsed_json.has_value() || !quorum_parsed_json.has_value()) { VLOG(1) << "Failed to parse server config json"; return false; } - const auto* root = parsed_json.value().GetIfDict(); - if (!root) { + const auto* collector_root = collector_parsed_json.value().GetIfDict(); + const auto* quorum_root = quorum_parsed_json.value().GetIfDict(); + if (!collector_root || !quorum_root) { VLOG(1) << "Failed to parse server config: not a dict"; return false; } - const auto min_version = root->FindInt(kMinVersionFieldName); + const auto min_version = collector_root->FindInt(kMinVersionFieldName); if (min_version && *min_version > kCurrentVersion) { VLOG(1) << "Server minimum version is higher than current version, failing"; return false; @@ -233,17 +258,17 @@ bool ServerConfigLoader::ProcessConfigResponse( auto config = std::make_unique(); - const auto* group_pub_keys = root->FindDict(kGroupPubKeysFieldName); + const auto* group_pub_keys = collector_root->FindDict(kGroupPubKeysFieldName); if (!group_pub_keys) { VLOG(1) << "Failed to retrieve groupPubKeys from server config"; return false; } - const auto* pub_keys = root->FindDict(kPubKeysFieldName); + const auto* pub_keys = collector_root->FindDict(kPubKeysFieldName); if (!pub_keys) { VLOG(1) << "Failed to retrieve pubKeys from server config"; return false; } - const auto* source_map = root->FindDict(kSourceMapFieldName); + const auto* source_map = collector_root->FindDict(kSourceMapFieldName); const auto* source_map_actions = source_map ? source_map->FindDict(kSourceMapActionsFieldName) : nullptr; if (!source_map_actions) { @@ -251,6 +276,13 @@ bool ServerConfigLoader::ProcessConfigResponse( return false; } + const auto* location = quorum_root->FindString(kLocationFieldName); + if (location && kAllowedReportLocations.contains(*location)) { + config->location = *location; + } else { + config->location = kOmittedLocationValue; + } + config->group_pub_keys = ParseKeys(*group_pub_keys); config->pub_keys = ParseKeys(*pub_keys); config->source_map_actions = ParseSourceMapActionConfigs(*source_map_actions); @@ -337,7 +369,7 @@ void ServerConfigLoader::HandlePatternsStatus(bool result) { void ServerConfigLoader::OnPatternsResponse( std::optional response_body) { - auto* response_info = config_url_loader_->ResponseInfo(); + auto* response_info = collector_config_url_loader_->ResponseInfo(); if (!response_body || !response_info || response_info->headers->response_code() != 200) { VLOG(1) << "Failed to retrieve patterns file"; diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 455490427754..87bbf3448486 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -49,6 +49,8 @@ struct ServerConfig { KeyMap pub_keys; base::flat_map source_map_actions; + + std::string location; }; class ServerConfigLoader { @@ -69,11 +71,13 @@ class ServerConfigLoader { ServerConfigLoader(const ServerConfigLoader&) = delete; ServerConfigLoader& operator=(const ServerConfigLoader&) = delete; - void Load(); - private: - void OnConfigResponse(std::optional response_body); - bool ProcessConfigResponse(const std::optional& response_body); + void LoadConfigs(); + void OnConfigResponses( + std::vector> response_bodies); + bool ProcessConfigResponses( + const std::optional& collector_response_body, + const std::optional& quorum_response_body); void LoadStoredPatterns(); void OnPatternsFileLoaded(std::optional patterns_json); @@ -89,7 +93,8 @@ class ServerConfigLoader { scoped_refptr pool_sequenced_task_runner_; - GURL config_url_; + GURL collector_config_url_; + GURL quorum_config_url_; GURL patterns_url_; base::FilePath patterns_path_; raw_ptr shared_url_loader_factory_; @@ -97,7 +102,8 @@ class ServerConfigLoader { ConfigCallback config_callback_; PatternsCallback patterns_callback_; - std::unique_ptr config_url_loader_; + std::unique_ptr collector_config_url_loader_; + std::unique_ptr quorum_config_url_loader_; std::unique_ptr patterns_url_loader_; net::BackoffEntry config_backoff_entry_; net::BackoffEntry patterns_backoff_entry_; diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc index f1731fac178c..89b1fcbc7461 100644 --- a/components/web_discovery/browser/signature_basename.cc +++ b/components/web_discovery/browser/signature_basename.cc @@ -175,22 +175,27 @@ std::optional GenerateBasename( base::Value::List key_values; for (const auto& key : action_config->second.keys) { - auto parts = - base::SplitString(key, "->", base::WhitespaceHandling::TRIM_WHITESPACE, - base::SPLIT_WANT_ALL); - if (parts.empty() || parts[0].empty()) { + auto parts = base::SplitStringUsingSubstr( + key, "->", base::WhitespaceHandling::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL); + if (parts.empty()) { continue; } - const auto* value = inner_payload->FindByDottedPath(parts[0]); - auto final_value = value ? value->Clone() : base::Value(); + base::Value value; + if (parts[0].empty()) { + value = base::Value(inner_payload->Clone()); + } else if (const auto* found_value = + inner_payload->FindByDottedPath(parts[0])) { + value = found_value->Clone(); + } if (parts.size() > 1) { if (parts[1] == kUrlNormalizationFunc) { - final_value = CleanURL(final_value); + value = CleanURL(value); } else if (parts[1] == kFlattenObjNormalizationFunc) { - final_value = FlattenObject(final_value); + value = FlattenObject(value); } } - key_values.Append(std::move(final_value)); + key_values.Append(std::move(value)); } auto period_hours = GetPeriodHoursSinceEpoch(action_config->second.period); diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index ff21514dd5fc..7fc2298603c0 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -12,6 +12,7 @@ namespace web_discovery { namespace { constexpr char kCollectorHostPrefix[] = "collector.wdp"; +constexpr char kQuorumHostPrefix[] = "quorum.wdp"; constexpr char kPatternsHostPrefix[] = "patterns.wdp"; constexpr char kPatternsPath[] = "/patterns.gz"; } // namespace @@ -25,6 +26,11 @@ std::string GetCollectorHost() { brave_domains::GetServicesDomain(kCollectorHostPrefix)}); } +std::string GetQuorumHost() { + return base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator, + brave_domains::GetServicesDomain(kQuorumHostPrefix)}); +} + GURL GetPatternsEndpoint() { return GURL(base::StrCat( {url::kHttpsScheme, url::kStandardSchemeSeparator, diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index 97f68a89c15c..0bab17248a47 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -31,6 +31,7 @@ inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { .always_use_initial_delay = false}; std::string GetCollectorHost(); +std::string GetQuorumHost(); GURL GetPatternsEndpoint(); std::unique_ptr CreateResourceRequest(GURL url); diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 38c341ade56b..e153a6b2a934 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -65,7 +65,6 @@ void WDPService::Start() { base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this)), base::BindRepeating(&WDPService::OnPatternsLoaded, base::Unretained(this))); - server_config_loader_->Load(); } void WDPService::Stop() { @@ -92,7 +91,8 @@ void WDPService::OnConfigChange(std::unique_ptr config) { void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { last_loaded_patterns_ = std::move(patterns); - content_scraper_ = std::make_unique(&last_loaded_patterns_); + content_scraper_ = std::make_unique( + &last_loaded_server_config_, &last_loaded_patterns_); double_fetcher_ = std::make_unique( profile_prefs_.get(), shared_url_loader_factory_.get(), base::BindRepeating(&WDPService::OnDoubleFetched, @@ -147,7 +147,8 @@ void WDPService::OnContentScraped(bool is_strict, double_fetcher_->ScheduleDoubleFetch(result->url, result->SerializeToValue()); } else { - auto payloads = GeneratePayloads(url_details, std::move(result)); + auto payloads = GeneratePayloads(*last_loaded_server_config_, url_details, + std::move(result)); for (auto& payload : payloads) { reporter_->ScheduleSend(std::move(payload)); } From 043a0418bc0d9f9684e5bb0d0b38e3061d538227 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 11 Jun 2024 15:27:23 -0700 Subject: [PATCH 16/36] Add Web Discovery privacy risk assessment & data sanitization --- components/web_discovery/browser/BUILD.gn | 4 + .../web_discovery/browser/content_scraper.cc | 65 +- .../web_discovery/browser/content_scraper.h | 8 +- .../browser/credential_manager.cc | 50 +- .../browser/credential_manager.h | 4 + .../web_discovery/browser/hash_detection.cc | 1487 +++++++++++++++++ .../web_discovery/browser/hash_detection.h | 17 + components/web_discovery/browser/patterns.cc | 16 +- components/web_discovery/browser/patterns.h | 1 + .../browser/payload_generator.cc | 73 +- .../web_discovery/browser/privacy_guard.cc | 279 ++++ .../web_discovery/browser/privacy_guard.h | 29 + components/web_discovery/browser/reporter.cc | 2 +- components/web_discovery/browser/util.cc | 7 + components/web_discovery/browser/util.h | 2 + .../web_discovery/browser/wdp_service.cc | 31 +- 16 files changed, 2003 insertions(+), 72 deletions(-) create mode 100644 components/web_discovery/browser/hash_detection.cc create mode 100644 components/web_discovery/browser/hash_detection.h create mode 100644 components/web_discovery/browser/privacy_guard.cc create mode 100644 components/web_discovery/browser/privacy_guard.h diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 034e002b58d6..f27717c71c7f 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -13,11 +13,15 @@ static_library("browser") { "double_fetcher.h", "ecdh_aes.cc", "ecdh_aes.h", + "hash_detection.cc", + "hash_detection.h", "patterns.cc", "patterns.h", "payload_generator.cc", "payload_generator.h", "pref_names.h", + "privacy_guard.cc", + "privacy_guard.h", "reporter.cc", "reporter.h", "request_queue.cc", diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 31b727acb120..1c629486ea15 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -11,6 +11,7 @@ #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" +#include "brave/components/web_discovery/browser/patterns.h" #include "url/url_util.h" namespace web_discovery { @@ -61,6 +62,16 @@ std::string ExecuteRefineFunctions(const RefineFunctionList& function_list, return result; } +void MaybeSetQueryInResult(const ScrapeRule& rule, + const std::string& value, + PageScrapeResult* result) { + if (rule.rule_type != ScrapeRuleType::kSearchQuery && + rule.rule_type != ScrapeRuleType::kWidgetTitle) { + return; + } + result->query = value; +} + } // namespace PageScrapeResult::PageScrapeResult(GURL url, std::string id) @@ -235,12 +246,24 @@ void ContentScraper::OnScrapedElementAttributes( return; } for (const auto& attribute_result : attribute_results) { + const auto rule_group = + url_details->scrape_rule_groups.find(attribute_result->root_selector); + if (rule_group == url_details->scrape_rule_groups.end()) { + continue; + } base::Value::Dict attribute_values; for (const auto& [key, value_str] : attribute_result->attribute_values) { + const auto rule = rule_group->second.find(key); + if (rule == rule_group->second.end()) { + continue; + } base::Value value; if (value_str) { - value = base::Value(MaybeExecuteRefineFunctions( - url_details, attribute_result->root_selector, key, *value_str)); + std::string final_value_str = + ExecuteRefineFunctions(rule->second->functions_applied, *value_str); + MaybeSetQueryInResult(*rule->second, final_value_str, + scrape_result.get()); + value = base::Value(final_value_str); } attribute_values.Set(key, std::move(value)); } @@ -261,36 +284,30 @@ void ContentScraper::OnRustElementAttributes( return; } for (const auto& attribute_result : attribute_results) { + const auto root_selector = std::string(attribute_result.root_selector); + const auto rule_group = url_details->scrape_rule_groups.find(root_selector); + if (rule_group == url_details->scrape_rule_groups.end()) { + continue; + } base::Value::Dict attribute_values; for (const auto& pair : attribute_result.attribute_pairs) { + const auto key_str = std::string(pair.key); + const auto rule = rule_group->second.find(key_str); + if (rule == rule_group->second.end()) { + continue; + } base::Value value; if (!pair.value.empty()) { - value = base::Value(MaybeExecuteRefineFunctions( - url_details, std::string(attribute_result.root_selector), - std::string(pair.key), std::string(pair.value))); + std::string value_str = ExecuteRefineFunctions( + rule->second->functions_applied, std::string(pair.value)); + MaybeSetQueryInResult(*rule->second, value_str, scrape_result.get()); + value = base::Value(value_str); } - attribute_values.Set(std::string(pair.key), std::move(value)); + attribute_values.Set(key_str, std::move(value)); } - scrape_result->fields[std::string(attribute_result.root_selector)] - .push_back(std::move(attribute_values)); + scrape_result->fields[root_selector].push_back(std::move(attribute_values)); } std::move(callback).Run(std::move(scrape_result)); } -std::string ContentScraper::MaybeExecuteRefineFunctions( - const PatternsURLDetails* url_details, - const std::string& root_selector, - const std::string& report_key, - std::string value) { - const auto rule_group = url_details->scrape_rule_groups.find(root_selector); - if (rule_group != url_details->scrape_rule_groups.end()) { - auto rule = rule_group->second.find(report_key); - if (rule != rule_group->second.end() && - !rule->second->functions_applied.empty()) { - return ExecuteRefineFunctions(rule->second->functions_applied, value); - } - } - return value; -} - } // namespace web_discovery diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index 4b9f57a2e57d..6719d89d7ce8 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -34,6 +34,10 @@ struct PageScrapeResult { GURL url; base::flat_map> fields; std::string id; + + // Only available for non-strict scrapes with "searchQuery"/"widgetTitle" + // scrape rules + std::optional query; }; class ContentScraper { @@ -75,10 +79,6 @@ class ContentScraper { std::unique_ptr scrape_result, PageScrapeResultCallback callback, rust::Vec attribute_results); - std::string MaybeExecuteRefineFunctions(const PatternsURLDetails* url_details, - const std::string& root_selector, - const std::string& report_key, - std::string value); scoped_refptr pool_sequenced_task_runner_; diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 2b4fdb2d0357..039da5bac014 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -102,7 +102,21 @@ std::optional FinishJoin( std::optional> PerformSign( anonymous_credentials::CredentialManager* anonymous_credential_manager, std::vector msg, - std::vector basename) { + std::vector basename, + std::optional> gsk_bytes, + std::optional> credential_bytes) { + if (gsk_bytes && credential_bytes) { + auto set_res = anonymous_credential_manager->set_gsk_and_credentials( + rust::Slice(reinterpret_cast(gsk_bytes->data()), + gsk_bytes->size()), + rust::Slice(reinterpret_cast(credential_bytes->data()), + credential_bytes->size())); + if (!set_res.error_message.empty()) { + VLOG(1) << "Failed to sign due to credential set failure: " + << set_res.error_message.c_str(); + return std::nullopt; + } + } auto sig_res = anonymous_credential_manager->sign( rust::Slice(msg.data(), msg.size()), rust::Slice(basename.data(), basename.size())); @@ -377,6 +391,8 @@ bool CredentialManager::Sign(std::vector msg, auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); const auto& anon_creds_dict = profile_prefs_->GetDict(kAnonymousCredentialsDict); + std::optional> gsk_bytes; + std::optional> credential_bytes; if (!loaded_credential_date_ || loaded_credential_date_ != today_date) { auto* today_cred_dict = anon_creds_dict.FindDict(today_date); if (!today_cred_dict) { @@ -389,34 +405,30 @@ bool CredentialManager::Sign(std::vector msg, VLOG(1) << "Failed to sign due to unavailability of gsk/credential"; return false; } - auto gsk_bytes = base::Base64Decode(*gsk_b64); - auto credential_bytes = base::Base64Decode(*credential_b64); + gsk_bytes = base::Base64Decode(*gsk_b64); + credential_bytes = base::Base64Decode(*credential_b64); if (!gsk_bytes || !credential_bytes) { VLOG(1) << "Failed to sign due to bad gsk/credential base64"; return false; } - auto set_res = - (*anonymous_credential_manager_) - ->set_gsk_and_credentials( - rust::Slice(reinterpret_cast(gsk_bytes->data()), - gsk_bytes->size()), - rust::Slice( - reinterpret_cast(credential_bytes->data()), - credential_bytes->size())); - if (!set_res.error_message.empty()) { - VLOG(1) << "Failed to sign due to credential set failure: " - << set_res.error_message.c_str(); - return false; - } - loaded_credential_date_ = today_date; } pool_sequenced_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&PerformSign, &**anonymous_credential_manager_, msg, - basename), - std::move(callback)); + basename, gsk_bytes, credential_bytes), + base::BindOnce(&CredentialManager::OnSignResult, + weak_ptr_factory_.GetWeakPtr(), today_date, + std::move(callback))); return true; } +void CredentialManager::OnSignResult( + std::string credential_date, + SignCallback callback, + std::optional> signed_message) { + loaded_credential_date_ = credential_date; + std::move(callback).Run(signed_message); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index dc95630d1dca..5301a3b4e9cd 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -79,6 +79,10 @@ class CredentialManager { std::vector gsk, std::optional credentials); + void OnSignResult(std::string credential_date, + SignCallback callback, + std::optional> signed_message); + raw_ptr profile_prefs_; raw_ptr shared_url_loader_factory_; raw_ptr> last_loaded_server_config_; diff --git a/components/web_discovery/browser/hash_detection.cc b/components/web_discovery/browser/hash_detection.cc new file mode 100644 index 000000000000..251f5c891955 --- /dev/null +++ b/components/web_discovery/browser/hash_detection.cc @@ -0,0 +1,1487 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/hash_detection.h" + +#include + +#include "base/containers/fixed_flat_map.h" +#include "brave/components/web_discovery/browser/util.h" + +namespace web_discovery { + +constexpr size_t kClassifierTokenCount = 62; + +// Markov chain transition matrix for hash classifier +constexpr float + kClassifierTransitionMatrix[kClassifierTokenCount][kClassifierTokenCount] = + {{ + -1.839225984234144, -1.8009413231413045, -2.5864601561900273, + -2.779077348461893, -2.41154163187108, -2.8701669802592216, + -3.010853183897427, -2.9831997811803244, -3.0258844950086354, + -3.028549665472028, -4.922879838696041, -4.503195676571833, + -4.598154161855354, -5.027344698225922, -5.217723368153992, + -5.366375752342653, -5.195909278900248, -3.2940850310881387, + -5.181468249477294, -6.110371416838184, -5.766202229535159, + -5.393352786265537, -4.920024681004049, -6.049294408676102, + -6.399015490326156, -4.690163484884073, -7.459851804835359, + -5.825337077308845, -4.675000760327133, -5.3635239851672845, + -6.331713706782754, -6.169284763337202, -5.951151191317628, + -5.768078242705815, -7.332129653597336, -6.766704624275413, + -6.01222435569866, -5.268617743244878, -6.279416117827666, + -5.861972559492891, -5.838071468059843, -6.267250173459698, + -6.283981033030117, -6.454759516784266, -6.5195694451700765, + -6.83526729571271, -6.458157413359671, -6.359696067797872, + -6.250241538141395, -6.647172527007435, -6.973987597161365, + -6.4598607011160425, -7.685547265665763, -6.5912026847359835, + -5.794718807999361, -6.474629988987015, -7.135098972554303, + -6.880960523371609, -6.747429130747086, -7.733118660641065, + -8.398636456057481, -7.6323973914922005, + }, + { + -2.11332750230783, -2.3060786022344897, -2.3740965556720726, + -2.5398307619465608, -2.463417892707307, -2.130953109899374, + -2.8009573227909073, -2.9401508827086436, -2.748847204575824, + -2.8414237914951976, -5.010884149435608, -4.7716590964777925, + -4.868359687249472, -5.322380370933768, -5.037006822424893, + -5.279762905036231, -5.635270908532894, -2.9219817650555973, + -5.50179037155463, -6.5406369920023, -6.311742070591071, + -5.516975693542294, -5.7251712834206305, -6.083331008626942, + -6.409455776722731, -4.856277028595425, -7.356357334609669, + -6.255977591877104, -5.042089425488359, -5.723688703460408, + -6.9306288690141455, -5.879866127104103, -6.269949621534028, + -6.969512838475713, -7.475373123729266, -6.802062729887527, + -6.566109586768108, -6.661695002244713, -6.634070998648396, + -6.128265317507457, -6.0654489711795785, -6.79728322915323, + -6.99559673771516, -6.996654379273295, -7.671972036661277, + -7.840255377779173, -7.132455920432357, -7.233113706563278, + -6.737551430374816, -7.2706736012479585, -7.430290364348156, + -6.991903776514698, -8.559572276072503, -7.231105001502197, + -6.117005677632925, -6.669675284003577, -7.87022016648111, + -7.635233211015519, -7.18343028641663, -8.53463332772525, + -8.567176875457722, -7.573077285525099, + }, + { + -1.6313545940843748, -2.457209014039589, -2.565380346827546, + -2.767788786784649, -2.6386222432933284, -2.595661570703591, + -2.6893427324813977, -2.7198733792574403, -2.720533202987637, + -2.8467380805237736, -5.029918409868431, -4.178710463028381, + -5.07588590483658, -5.057436988529895, -4.899938336310833, + -5.271744381251988, -5.715419865537325, -3.1739071041721116, + -5.367102243680773, -6.224018730172038, -5.866973141306898, + -5.730015933050199, -5.360958031920617, -6.20201967617667, + -6.328452890969734, -4.837569916970598, -7.520833339090353, + -5.8325529174204185, -4.950768880962046, -5.339171801246006, + -6.500538943869661, -6.141626179853517, -5.826929659866057, + -6.371549418153106, -7.095602530626063, -6.863928261303842, + -6.26532998038965, -6.486382994639529, -6.568804701240378, + -5.928030195562504, -6.138501621140467, -6.375855129864318, + -6.672567424416514, -6.87690014131182, -7.500698430681298, + -7.486404619424152, -7.110483757622713, -6.948864783187929, + -6.7689909475117735, -7.44680608044408, -7.305175362028806, + -6.490004000406482, -8.278142463867583, -7.100043692626031, + -6.262757631704339, -6.785644569035485, -7.917859578552653, + -6.966883288690608, -6.7663306639529575, -7.827911341889713, + -7.709275282211631, -7.650980633730635, + }, + { + -2.2483023852308777, -2.2601431921520803, -2.543211818297523, + -2.6290975996017654, -2.597012293697696, -2.425038774903284, + -2.6464962853598264, -2.7268820909874645, -2.7170988469992086, + -2.6384412943652213, -4.8059842634060495, -4.801920790322523, + -4.881995682865955, -4.399130557719554, -4.977525552072196, + -5.254333597613871, -5.4861286120783905, -3.172333855510997, + -5.311009967578493, -6.3787775808955045, -6.060833750357407, + -5.179488625881995, -5.284849141539821, -6.185226477248653, + -6.342526765978808, -5.0477193482508715, -7.229508117457252, + -5.92913163950562, -4.781563610047119, -5.175693021409531, + -6.686598785853124, -5.953265540842049, -5.765108625614716, + -6.249636653394711, -7.053405713688212, -6.871084156894258, + -4.746700678954438, -4.435206614193364, -6.2492260600816145, + -5.437566316202071, -5.90294982336378, -6.5708663077474965, + -6.4774110336687505, -6.642451113295277, -7.490560332753359, + -7.638809897851904, -7.037026821604173, -6.792453878834064, + -6.557926605402683, -7.183535297458448, -7.556615154408894, + -6.675849393697125, -7.929241490870054, -6.920447880012594, + -5.937211886970303, -6.536908132533395, -7.266281062975223, + -7.138583909596181, -6.9407325511841, -7.611188320541975, + -8.063402408224212, -7.7539194100649205, + }, + { + -2.0350349956205984, -2.348602646771946, -2.41594411405956, + -2.651370395735765, -2.563410442434685, -2.706962611141542, + -2.7917112923152776, -2.7483543933766477, -2.6785026736567357, + -2.8111298756441037, -4.759837736546805, -4.20618015484438, + -4.787453629928326, -4.659538126267765, -5.015532806050122, + -5.056335259588051, -5.339468177159593, -3.040667184111712, + -5.203144447478613, -6.2264472230490675, -5.7097357671058155, + -5.585194192596145, -5.035187712987706, -5.542988699592872, + -6.206189420830567, -4.864552817623237, -7.387161020524848, + -5.130725109803191, -4.710070938057912, -5.015532806050122, + -5.563665939332496, -5.8412571088023135, -5.744609136156329, + -6.206575148897066, -6.842735398083401, -6.794361813799185, + -5.850672107736916, -6.088449236501511, -6.348519254409916, + -5.725588459198469, -6.064735388153122, -6.479956671206651, + -6.2209527037314265, -6.70094736915976, -7.3405268040104845, + -7.140183173146506, -6.467358872953416, -6.7233339772218645, + -6.184068000080206, -6.381516598393398, -7.406185056529545, + -6.368731036096427, -7.402351186018824, -6.6091509166536255, + -5.9623588984476195, -6.352529061520146, -7.133337180638517, + -7.24783614109371, -6.901266731308386, -7.234806640803376, + -7.432126848507545, -7.494477663675224, + }, + { + -2.0215812860615885, -2.455637406643175, -2.4330253990141046, + -2.6113902739466517, -2.6033787533338284, -2.6337646574813993, + -2.7111759743895725, -2.7471499108067454, -2.721672070749707, + -2.7644985821403028, -4.771735346669196, -4.967298931497775, + -4.806933772233218, -4.796223062219612, -4.702049659123834, + -4.615986584200591, -5.422222957790021, -3.024083897225106, + -5.341473161524181, -5.691932137893965, -5.870247680316981, + -5.6516120254419615, -4.85258639108815, -5.9684706438872475, + -6.205102036008844, -4.762283950640148, -7.106211026775939, + -5.754565801069223, -4.28552037163959, -5.083154204506742, + -6.514533306380853, -5.91282033178054, -5.801594696670316, + -6.211408552601299, -6.884100000075919, -6.5060032575028, + -6.051550266183317, -6.1528452495165125, -6.237040028392324, + -5.845664774991169, -5.83750622157883, -6.376088248894053, + -6.3936457603588925, -6.58430154569624, -7.071724850704769, + -7.213982427018076, -6.56730052905341, -6.608473779316545, + -6.403307671270629, -6.973970456584425, -7.485700648480843, + -6.5060032575028, -7.126013654072119, -6.592294210440276, + -5.525669597265563, -6.0726189713973024, -6.168884085714272, + -7.057863242618145, -6.702467385782517, -7.84259108644045, + -7.932742183434748, -6.889071012797939, + }, + { + -2.3515175517946965, -2.4895377785815813, -2.455794452354539, + -2.6177065611128625, -2.3916765698655924, -2.55893036105207, + -2.621684157393488, -2.6988517931658524, -2.630805311213068, + -2.6634082117951667, -4.639123440452939, -4.108116635400416, + -4.850674635561831, -4.879642999369406, -5.020506071184806, + -5.079702479761731, -5.3856932140647995, -2.922465393995544, + -5.272571266829349, -6.095451326503016, -5.703507123198923, + -5.5861660464475555, -5.144197286007818, -5.722031888813277, + -6.28586346876822, -4.872555039237073, -6.886991750607913, + -5.521389523166842, -4.712785087276782, -4.712557943607434, + -6.258849400356963, -5.781080159458192, -5.683518571573409, + -6.497978247391754, -6.801813554699944, -6.640350228026399, + -6.23670827447975, -6.480528140170159, -6.503409353749256, + -6.035279500709713, -6.187868456644626, -6.634900623258835, + -6.227883924459252, -6.665648019797556, -7.5457712876636505, + -7.422426740346121, -6.235666064901307, -6.769319721223498, + -6.343344078699495, -6.975730165249003, -7.353206363454935, + -6.635677322327007, -7.937813375439674, -6.762240045635436, + -6.147006740966892, -6.741296871790193, -7.715813334827543, + -7.183705495090042, -6.938232467377743, -7.593211012735211, + -8.021194984378726, -7.326496213127361, + }, + { + -2.404503840183417, -2.43761707422273, -2.4108252303609095, + -2.2999425986283435, -2.542843475674806, -2.6029429346724786, + -2.584141922741018, -2.5855127818195496, -2.5510561981552526, + -2.647681869737238, -4.782820501953572, -4.808208666935694, + -4.979563332219715, -5.008211525808261, -5.046432738628459, + -5.142457459370653, -5.485491564024772, -3.1144173778919617, + -5.417825855041213, -6.245547233803318, -5.938268453446564, + -5.963941744764968, -5.450843208258146, -6.059373833665894, + -6.223182084343739, -4.942745700375246, -7.208409268623897, + -6.038143491827719, -4.6277437642171355, -4.892513996642899, + -6.694766741586792, -6.117821568685912, -5.949820065666706, + -6.502648045547855, -6.835922059321975, -6.694766741586792, + -6.361312919572388, -6.403294392961231, -6.118769885494771, + -5.676056523505988, -6.406451957946552, -6.5244722133881785, + -6.6333977952105005, -6.6574953467895615, -7.573786078663716, + -7.446115322000925, -6.883692335590661, -6.903250344490318, + -6.3498910941692, -6.905331510694142, -7.588115904218541, + -6.879623153983935, -8.035692497676832, -6.939233062369824, + -5.959077527634608, -6.324513515108117, -7.549688527084656, + -7.120692921566297, -6.988939594552065, -7.891731808755324, + -7.727259481120012, -7.430143376434873, + }, + { + -2.2924692182301323, -2.450539739657926, -2.3769703926915984, + -2.532604294663703, -2.55393918066343, -2.609718771364289, + -2.6246425013179655, -2.661744915258029, -2.6011009513028984, + -2.6236780353341946, -4.669477044233787, -4.1521285006409165, + -4.955491059584871, -4.818890308190988, -5.030853379357302, + -5.002039294312803, -5.278250342600015, -3.076829272811893, + -5.307731406455737, -5.826171280206974, -6.022604681193609, + -5.8364861502494865, -5.222160875948972, -5.86734719439116, + -6.263453577434854, -5.1217643044016885, -7.32073988901422, + -5.758783848671988, -4.666476541899311, -5.259001445170042, + -6.374002568031498, -6.083417735921755, -5.695962812152638, + -6.490715185357981, -6.417147740477192, -6.55681384079998, + -5.431378631989581, -5.843302320137157, -6.369727752361356, + -5.638321273173884, -6.50456582229188, -6.275027142828877, + -6.210627212225794, -6.774279201200845, -7.54625217416398, + -7.377527245335997, -6.968174323388823, -6.961544464850153, + -6.5738576027632725, -6.808653231033201, -7.247759185607984, + -6.667823395181603, -8.06567857870257, -6.862038055489511, + -5.923075085846576, -6.772454383176216, -7.732534132174032, + -6.980444415980637, -6.935456028765855, -7.926350068393722, + -7.409760739910981, -7.357691884279851, + }, + { + -2.395140177772492, -2.3972905877762423, -2.4380054501613637, + -2.59514809923619, -2.5304957080424493, -2.553494441315067, + -2.592658670737186, -2.6234135177213647, -2.5068257242437872, + -2.493912396989218, -4.415128005729072, -4.8162395242315545, + -4.805681457561184, -4.959588437581088, -5.013259465745109, + -5.070148436368585, -5.778302005668334, -3.0289910877331776, + -5.527143864017425, -6.11105402601701, -6.123887370951674, + -5.975929983744964, -5.442482986164537, -6.151079378646925, + -6.120416006196215, -5.065655600056955, -7.071974876907828, + -5.957253719340739, -4.781773843113505, -5.354948164056644, + -6.520450343119245, -6.293473674919533, -5.817016517849025, + -6.85914069525248, -6.81356318675616, -6.777584585720929, + -5.97764525003172, -6.226877237430227, -6.02961643394924, + -5.9729353291005545, -6.418715298488868, -5.532354351604477, + -6.803710890313149, -6.889653320113874, -7.354541848692839, + -7.502757793000282, -6.938924369120657, -6.214291571987144, + -6.749334119435077, -7.237514956739779, -7.394443065445024, + -6.457482478746571, -7.947443614261728, -6.86121538479334, + -5.698583920623846, -6.845759126556648, -7.683896617545187, + -7.180188461548061, -6.757725777071325, -7.8704825731256, + -7.881944016644606, -7.107203568791572, + }, + { + -6.7847523397462, -4.956382101946025, -5.55168468117927, + -6.54694976738503, -6.679027997805541, -6.920449307304025, + -6.651631877885628, -7.028532297007316, -6.819873006155468, + -6.9668156836069475, -5.07824502580267, -3.6978375281608122, + -3.2158001218369128, -3.221520357616586, -3.5888259593254497, + -4.18118917224718, -3.0226572253435795, -3.971027081545084, + -3.562365839815367, -6.241860395850777, -3.738063429007306, + -2.286143322088719, -2.8154088123469325, -1.9366972011829824, + -6.402763696295053, -4.09673956284193, -6.7632686126933175, + -2.217315348390325, -2.7898081670861736, -2.2970370063901697, + -2.7943042308650328, -4.45525252224197, -5.6170558845712195, + -5.634999368405547, -4.204524838877218, -5.247540598697068, + -7.679731693977602, -7.496500850432476, -7.694782629326121, + -7.660949127015419, -8.444625153562612, -8.02242837580043, + -7.9107342568656245, -7.844229700045118, -8.496568431723452, + -8.90528981102539, -7.744710798608082, -7.796294560812227, + -7.4084137546993, -8.54315037261458, -8.96995880381818, + -7.702981796781846, -9.818649422090688, -7.982756374523151, + -7.087136791691802, -7.726484291615801, -9.302472289566692, + -8.264363329731667, -8.520253749464962, -9.573314897467998, + -10.041792973404897, -9.03352354731742, + }, + { + -5.530908158078372, -5.12660572425173, -5.285205739999349, + -5.724471900365845, -5.873312125055024, -6.16534879225732, + -6.148934708170209, -6.3610443530793574, -6.311033932504697, + -6.085846837289822, -1.9318371570117603, -3.9897678769234868, + -4.264721024425275, -4.508665668126993, -1.397989588361542, + -5.165043688633805, -5.1354703161064155, -4.710076673495516, + -2.2812710196631696, -5.744808587095395, -6.153180999051661, + -2.7741841902487896, -4.878049696777151, -5.0409257316634655, + -2.3898944653854226, -5.13595610674021, -7.841822106027579, + -2.8471437524600627, -3.4340095911141377, -4.619316513108799, + -2.3549200090866647, -5.921518406898233, -5.302848234969303, + -6.786138406296854, -4.207750888408638, -6.039012800612939, + -7.841822106027579, -7.704962923310382, -7.065002449743519, + -7.589296290560376, -8.260096172428325, -8.035112694192108, + -7.871344545293901, -7.140827013169332, -8.545938317958099, + -8.836893715754849, -7.993349965830133, -7.27788665694764, + -7.741565502287929, -7.888977243944857, -8.111485672976682, + -7.875096894912451, -10.091297373707675, -7.392485113590403, + -6.863268166852988, -7.610229500226842, -8.901213681542407, + -8.92241588919301, -8.313038591698524, -9.803615301255896, + -9.310181420201774, -9.00812940746704, + }, + { + -5.262771475279199, -4.784242541566078, -5.27970172852834, + -5.684918512820975, -5.945292208575153, -6.218979090786592, + -6.228233983716081, -6.354509212158639, -6.204315840281487, + -6.442281485719593, -2.526983467749325, -5.114296740462473, + -4.530006859098648, -5.422625873895182, -2.9651924820539826, + -5.615416770210166, -5.759915004501759, -0.738654569892248, + -3.9951800832331146, -7.496424744983864, -2.271649654828947, + -3.6688863968618732, -4.479075949205008, -6.406971077861438, + -2.7704548687771466, -5.064362048924221, -7.65209604855975, + -4.10990241837356, -4.3379100438872245, -3.144791234860585, + -4.257400003418622, -6.678114421469913, -6.866487433947222, + -7.697728752690109, -5.8045538215356425, -6.443871311173693, + -8.079096309219214, -8.153204281372934, -8.17767713789166, + -8.353264662504271, -8.864090286270262, -8.820319623214933, + -8.693771874337664, -8.686253041923635, -8.948055666387596, + -9.842684901480572, -8.909864867655205, -8.569719225667685, + -8.285794202093616, -9.08611589448313, -9.094531091408415, + -7.571541334321345, -10.622843459030147, -8.818180584966184, + -7.823031278179709, -8.265917771336019, -8.826764328657575, + -9.481851947393176, -9.0917181500318, -8.558120089824332, + -9.233307603986084, -10.138335143581529, + }, + { + -6.352576341887475, -4.375482811098582, -5.097247890129581, + -5.253867383491415, -5.300921501088017, -5.719261065235271, + -5.695077377144448, -4.664604980788103, -6.0509261540753565, + -6.1211148128546835, -2.6955840583648807, -4.0885439717448415, + -4.601612684872268, -4.3272866151564005, -0.8335121453767717, + -4.368698782518719, -4.841722524158204, -3.6648788033138118, + -2.5172646408008483, -5.8838060715240985, -5.03345350892465, + -4.275021730152804, -4.6405776530763765, -5.25643229403688, + -3.133213396702524, -3.881602832644344, -7.333792367288475, + -3.6375800962202542, -3.280343679384232, -4.168603006615407, + -3.0158762344692915, -4.957870530657444, -4.673357005846336, + -7.071279326505898, -4.732292586433726, -6.102987428262127, + -6.308187629826426, -6.692855118141101, -6.912844895031934, + -6.811275201992611, -7.387021770702892, -6.866694309094154, + -6.971677700053924, -7.120054614261141, -7.672123196561181, + -8.47105299909571, -7.06564216575394, -7.303313817631059, + -6.877175818825198, -7.588372692026248, -7.710844848156796, + -7.012073355807918, -9.487490679574803, -7.203069557208429, + -6.086293297912648, -6.450936411500557, -8.098699438256325, + -7.677018501414594, -7.313496820953744, -9.611543328244782, + -8.931691690166081, -8.112931574673333, + }, + { + -6.278777370845214, -4.701340011999448, -5.078865738235898, + -5.8830885176004895, -6.165050673343658, -6.274964098411205, + -6.212416394644692, -6.400778791567437, -6.741692863598321, + -6.816576094912807, -3.3928904712107735, -3.566247086795751, + -3.646180662937257, -3.523693462975528, -4.243767227003855, + -4.080529251966207, -3.795135190780714, -3.596123418433819, + -2.7581828008765474, -6.336206897605354, -4.412794119233608, + -2.7790238541384125, -3.7937492847610685, -1.8714655708089012, + -4.039189587014222, -3.917817104421266, -7.57147815542886, + -1.7211826197805813, -2.454732555101985, -3.258178620019967, + -3.831607640543702, -4.745787338078659, -3.8173867609921763, + -3.6132042458306612, -5.788388393117924, -5.078865738235898, + -6.509442541403006, -6.358094961721853, -6.982655840165303, + -5.955633264954192, -7.203135532877834, -6.519814112808369, + -6.508748303549079, -6.5805671825510945, -7.521390752829464, + -8.307422019239775, -6.987204748691672, -6.90870144071007, + -6.578332663638785, -7.263487211998134, -7.281252691733005, + -6.635300404511988, -9.747550691415777, -6.939413018359865, + -5.8716986926591, -6.717215468733563, -8.061948046761787, + -7.4055504084105825, -7.052394044113555, -9.471951436870118, + -9.440772718621666, -8.392393495069179, + }, + { + -6.019277337678054, -4.809610930457335, -5.353723551448762, + -5.676382755872694, -5.70371603264992, -5.986064759126338, + -5.8139317591377235, -5.978144349530662, -6.042881895447475, + -6.198360420377549, -2.2921047448703056, -4.34095023979577, + -4.345648109454055, -4.367598309292761, -2.0155741702111323, + -3.0132780221373907, -4.923111941566577, -4.563679111444075, + -2.223531060167143, -6.691102686207805, -5.506010794027101, + -3.0594865563826104, -4.849221407410736, -4.504665385487454, + -1.9294270482862954, -4.87704758753489, -7.8125932274537675, + -2.476262613634102, -3.9821539473427885, -2.8193399945915623, + -2.274864811699418, -5.85738068573614, -5.424700477670406, + -7.189965927648669, -6.389275800912233, -5.638934468614081, + -7.03745392086323, -7.341255375194895, -6.260863632640313, + -7.279063354938447, -7.679061834829245, -7.811259004440631, + -7.236144890792278, -7.5275849533863886, -7.494018129747305, + -9.1181262319292, -7.907769904821474, -7.576977708715964, + -7.061731490444577, -8.083943001314976, -8.105182737815888, + -7.709906510180343, -8.65367988774833, -7.560240916360441, + -6.676421938949557, -6.335428678009885, -9.006382193489584, + -8.143473650809202, -7.5376758563683515, -10.154666091954931, + -9.349927845986523, -8.656780665426579, + }, + { + -6.45948206141902, -4.541389017548509, -5.0469147172405115, + -5.714893702071352, -5.93765911006474, -6.159588168280474, + -6.484829040506417, -6.54643138634695, -6.777423978144398, + -6.472536180151478, -2.0992585177991696, -4.351360197286945, + -4.810779680772453, -4.478347221038041, -1.057979923268165, + -4.503803429976553, -4.369600328148692, -3.1761274441594316, + -2.5925706700973334, -6.132316774171815, -5.0527495258256305, + -3.548319221739584, -4.665298532220545, -4.239092161682817, + -2.8823289365699227, -3.9799558061803935, -7.613527691788449, + -2.9149052754992715, -3.0856952412535055, -3.988705873974733, + -3.519423658731669, -5.380012776918168, -5.236242140888087, + -7.294418265937878, -5.378236234528395, -5.653900468202214, + -6.843339306558724, -6.1506932535462235, -7.23734725322546, + -6.366553451469326, -7.364460455464448, -6.868708500684183, + -6.652923233094938, -6.285920796794185, -7.434940854111734, + -8.332992180665768, -7.045904469629325, -7.3935637933916185, + -6.8666551118723405, -7.771896007559911, -7.6868589648739984, + -6.982133113853507, -9.79784886428876, -7.098382406877942, + -6.05045863483477, -6.643853499354418, -7.8988076492249855, + -7.62952803313489, -7.2191872449632415, -9.030593711575094, + -9.78510983851133, -8.512650620040239, + }, + { + -7.312010848930209, -5.9704021836204655, -6.3878250976208735, + -6.964626238636961, -6.946983784483292, -7.4124339237241115, + -7.3181741966378775, -7.680384414313297, -7.712878247789743, + -7.554150900935073, -2.446039713635401, -5.2426041270797, + -5.947299500896444, -4.663409565765878, -1.9484553212571183, + -5.736061416021277, -5.712018325729332, -4.9933347157551395, + -3.124667578606162, -6.881965531986077, -5.837272445819192, + -3.4071965596735665, -4.466780007835062, -3.7439634287862087, + -2.4245394005655605, -2.7481043832730636, -7.96925132102691, + -3.001717011027925, -4.3613498567188325, -1.0557054893757776, + -3.70597885137566, -6.306264213716016, -4.571775536818785, + -8.174476930790583, -5.896948417633875, -6.225037976827956, + -7.408704473732679, -7.482057817244962, -7.278478028822127, + -7.6772808871048746, -8.27951403118039, -7.874318428531343, + -7.723948471543991, -7.700568997316141, -8.91379761462879, + -8.048158534515101, -7.944081716081054, -7.980577820654186, + -7.290733450482923, -8.159308709317411, -8.547715834521, + -7.821812931153412, -10.179602578494553, -7.600205085285631, + -6.935111692528849, -7.541317747952087, -8.80008790436004, + -8.364689804291782, -8.08874001915325, -10.681459532277783, + -10.11675467483489, -9.167510387022356, + }, + { + -7.888212115175222, -6.644858293408979, -6.899926832152373, + -7.644887076927795, -7.6845832447435445, -7.532598742461448, + -8.35541557609491, -8.047237610771814, -8.039272966898704, + -8.151069111852731, -3.668932909455333, -4.782855975285661, + -2.6659061839419613, -2.8967154778709228, -2.0223904901109755, + -4.446771913881909, -3.000219123980515, -4.8870757508472185, + -5.930891109758962, -6.823383785692898, -3.2455278628878323, + -2.6715253337166462, -3.4540042231373063, -1.613293110190054, + -3.32378892967727, -4.249589417392827, -7.22956773062339, + -3.479217249500404, -2.6394006861426296, -2.505331420610824, + -5.608431497999796, -3.9128781321838506, -6.817651617834854, + -5.899129031817539, -6.838124773860243, -4.798082958969038, + -6.707198867504101, -6.862144714309829, -6.946702102337892, + -6.119321735858142, -7.3106242225785305, -7.047703884629593, + -7.1735103563413185, -7.1142937780684905, -7.8727953781736435, + -7.684274173500164, -7.105593531784784, -7.043298950514618, + -6.705339482889372, -7.153500510194026, -7.545964351744817, + -6.429130146514012, -9.208169648866278, -7.146978747947639, + -6.381569697965211, -6.863775814304458, -8.274721978073412, + -7.87653370028425, -7.678419897035876, -9.611509357662127, + -9.195484489338961, -8.64028017837942, + }, + { + -5.479179331884548, -5.058052917950845, -5.462604366790335, + -6.042749073104725, -5.955329948912708, -5.958323963125313, + -6.182592584875092, -6.134964535885837, -5.987223312688662, + -6.092926822690444, -1.4103668710151773, -5.3350267357418115, + -4.970584606980225, -5.289457186272422, -1.770010358993832, + -4.901554513033236, -5.37688758694302, -5.089624713826659, + -3.3520314691389803, -5.392942008652894, -4.734460344193294, + -5.4364649785873, -5.373540303482963, -5.098468738623112, + -1.787587681664556, -3.2734283276295595, -6.018573842572738, + -5.287155689284143, -2.4508369623232906, -5.268931950327691, + -2.1042922431924556, -5.627005270227098, -5.60465202444635, + -5.974953220096848, -5.917202163476144, -5.89303609762896, + -7.4048682036926285, -7.92851451588768, -7.027392005486696, + -7.609083745121319, -7.38594019380711, -7.373517673808553, + -7.797674914928869, -7.69894007424318, -6.9721762828842495, + -7.92851451588768, -7.9072371174403955, -7.498269378781029, + -7.24617825143195, -7.836141195756666, -7.972477639308797, + -8.030297210197622, -7.424161406627308, -8.130380668754604, + -5.985681292336846, -7.548459123304884, -7.876146530370365, + -7.886403030537553, -8.383576565135217, -8.509870290459508, + -8.104405182351345, -7.3612475812167375, + }, + { + -4.615704248273826, -5.059874046144977, -5.605352624766998, + -6.125932548297868, -6.262849675716521, -6.79239877505316, + -6.990929985784472, -6.841047905444769, -7.1584533214794765, + -6.9886390340379165, -2.1061188583709898, -4.694960766195293, + -5.294767434713961, -4.877455498156362, -1.7372915500183557, + -4.54913156517679, -5.204152324138941, -4.129384627657894, + -2.037945671503165, -6.073264053143508, -4.589028985169175, + -2.990753289694604, -4.778969963958759, -4.689721987339014, + -2.425686266522293, -4.746481928875957, -7.836127606736178, + -3.351158263461062, -3.2418172438356554, -2.1018059989954563, + -2.7036646563447677, -4.616611132654885, -4.89196974360223, + -7.672674534246606, -4.594182160042578, -5.702759391924034, + -6.928687676907251, -6.888038111045066, -6.879281938695605, + -7.0247524516915965, -7.464610089759517, -7.314413547152238, + -7.29014621148154, -7.293244587314209, -7.623992355607218, + -8.372647679876952, -7.108856380340105, -7.38925322665568, + -6.931385277679899, -7.915280634635728, -8.074744053353632, + -6.836124212582984, -10.164407149105006, -7.372318020898097, + -6.283267109907934, -7.0071153102054895, -7.702596214111655, + -7.848216404055182, -7.332806708624255, -9.549591811814969, + -9.295811291038868, -8.128717117098297, + }, + { + -6.86596902684244, -5.052082122851932, -5.150933488599681, + -5.292208274141252, -6.214682697483703, -6.745331904339627, + -6.68552490120206, -6.760045968476806, -7.227305715576431, + -6.950863382929711, -2.1215717821722215, -3.9228106947364623, + -4.840908762978201, -3.0664686008437925, -1.6983460154315366, + -4.061987675375524, -4.329017422576037, -4.468146834761754, + -2.0559567932823986, -6.284656471404593, -4.495653917304999, + -2.239702601986903, -4.059167724800704, -4.675038779649125, + -2.554078005507218, -4.208324039380938, -7.846798279854166, + -4.952711862629422, -3.1510988852700317, -2.942373372199169, + -3.3895078376634635, -4.604176621456193, -5.1138376420493366, + -7.9144140567925305, -4.640693910453494, -5.102920313867999, + -6.555881088992486, -6.826369644359554, -6.799686147757116, + -6.863359893400418, -7.558312671802701, -7.067443904093005, + -7.193279183729173, -7.1899393531824245, -7.705592764618944, + -8.457679157012771, -7.256276285899237, -7.186610639983997, + -7.0503828029559665, -7.591798854832744, -8.06246715675167, + -7.178062400973902, -9.768878866076495, -6.917516203514602, + -5.665418470446385, -7.260143611855673, -6.937390775844807, + -7.687607497719584, -7.3485921408206325, -9.2384661090352, + -9.464847655623185, -7.897922355187247, + }, + { + -6.774920173861653, -5.204290861824316, -5.43566671911157, + -6.296930641076284, -6.565626027570306, -6.7373590105822805, + -6.991252066666452, -7.063233360250443, -7.2676834795551315, + -7.1966044322333405, -2.083909994196951, -4.067585265323549, + -5.182321460673428, -4.835732283228186, -1.980079058156674, + -5.0283663440075825, -5.072641431371989, -4.6392056435133515, + -2.7086094993416667, -6.770304135451181, -5.008181972697398, + -1.1019554288598505, -3.2594369265598493, -5.6765883311043766, + -2.736784393019736, -3.364824539297133, -7.918041582638827, + -5.789527217909832, -3.4282422713486094, -4.498435097687583, + -3.6322465613937016, -5.355734234640129, -5.0804532195051415, + -7.17597860187687, -4.9759313787901425, -6.718299350460867, + -6.452973839496266, -6.266241964550636, -6.756169624516277, + -6.43275589071587, -7.149632742116933, -6.722481373881418, + -6.632646871978412, -6.5830057991087605, -7.441299494170494, + -7.5325638154552745, -7.295254585596671, -7.196283868037615, + -6.683920964952739, -7.4835386813502325, -7.587428922371031, + -6.992558402580507, -9.54477866233574, -7.0691430439756715, + -6.0008086042221205, -6.0079129112663265, -8.273962947039259, + -7.457398913104675, -7.183861348039058, -9.235518989239411, + -9.247910721534573, -8.527701618931673, + }, + { + -6.725963719695806, -4.710012269685353, -4.981543035572536, + -5.7693914443296395, -5.741238652017211, -6.34104225410854, + -6.461701921452123, -6.616580803658851, -7.050213688876461, + -6.932988782385651, -2.7442254377569215, -3.902092293780571, + -4.081087684032349, -1.8459531867558991, -2.260196124051401, + -3.8113055093318327, -2.1904142607255017, -3.5077174805325915, + -3.070625904070985, -5.688404814159279, -3.676818033328958, + -3.705969932950152, -4.175966474127823, -3.555777846153588, + -3.6599169276373167, -4.233380646142029, -7.565625193952616, + -4.758247211588438, -2.668505149650637, -2.593317887541856, + -3.982238613532973, -4.922572014698711, -4.457568202222798, + -6.922768742308341, -4.874097132395777, -3.7366670217502587, + -6.099051002533345, -5.950541812233132, -6.754321355464054, + -6.000835251677606, -6.818602573551164, -6.538250446625281, + -6.5136752899401404, -5.7389354920585625, -6.837502673710269, + -7.922940958163197, -6.4879709082904045, -6.559235554477551, + -6.415308634074, -6.963830229106114, -7.464928001069955, + -6.466545899251641, -9.489635645899149, -6.3635319575989815, + -5.527598474760337, -6.407003965795449, -7.463914829757348, + -7.418626873140783, -6.4607730713017455, -8.850715648219035, + -9.544876513609825, -7.984492491801492, + }, + { + -7.251231594323855, -5.21374696908488, -5.698223064924641, + -6.1375976604763816, -6.322511629217009, -6.768362468268195, + -6.494106816635844, -6.457670861321346, -6.860741199932812, + -6.755693520691695, -4.0580333694338515, -3.9411669781297105, + -3.7467312772977017, -3.0227837077197126, -3.61529958808048, + -3.574469853485688, -3.2007714947116837, -4.080705573827712, + -4.670471138732819, -5.7966968651863855, -4.155602316322404, + -2.9527040483599185, -2.862751521261682, -2.037725742388079, + -3.7818488691194445, -3.113228390392548, -8.164264994327704, + -1.8458475827404217, -2.5467378386179824, -2.7020967605017185, + -3.188124830525815, -3.6799312814828857, -3.4909044267832696, + -5.197365837878935, -5.202188998354364, -5.870321468395694, + -7.4721345906728445, -7.508740887837122, -7.308294052687071, + -7.524695844262695, -8.528908107915612, -7.92499206108361, + -7.684820971302881, -8.246116020758024, -8.52404191826444, + -9.16793672064164, -7.835273241415741, -7.178620119286367, + -7.559608480967977, -8.499112535221915, -8.875184344633446, + -7.775193695995215, -10.198665810583236, -8.01769231637253, + -6.730988787795164, -7.673144441641045, -9.323628945401888, + -8.330457169191774, -8.013022138590646, -9.77099654516406, + -9.908396414566504, -9.416350685452109, + }, + { + -6.383306695601549, -4.903894061372386, -5.294037540593016, + -5.450500954330478, -5.333223053427145, -6.308171725769449, + -6.710407117707228, -6.887542628987831, -6.847572675445971, + -7.035457528925254, -2.2105034037003235, -5.0202198363584465, + -4.228806005807516, -4.2610399361561155, -2.630714925229401, + -3.899363165669206, -4.911168632565807, -1.9598915311908123, + -2.357698156549484, -6.874278408705108, -5.4856719078268386, + -2.9453898821076563, -4.76865138002776, -5.849682782165729, + -2.1582691520417923, -3.13711767038794, -7.932068702852963, + -2.1341546758789423, -3.3759594869296796, -3.525124340216131, + -3.4812218611704324, -5.083766155674364, -5.7936328268294535, + -4.353576622920111, -5.907706290260866, -6.135534326871947, + -6.846532994187875, -4.609063889576182, -7.503287789431182, + -7.483445868632177, -7.2287173521187755, -7.853210127940644, + -7.155334806184752, -7.407188463381393, -8.090673733029602, + -9.081164896953064, -7.857960730699241, -7.896800564015505, + -7.262268886290009, -8.128645226782451, -8.177248142566354, + -7.485412437604219, -9.720755973044048, -7.9739596445621235, + -6.796539470357211, -6.907958941482774, -8.646989682962468, + -8.283628546124925, -7.797896489956591, -6.6686665609139695, + -9.771081056931564, -8.750720965163202, + }, + { + -4.685181991517679, -3.1394221383869034, -4.505733999919456, + -4.7128201143378075, -4.721709061755053, -4.800636320344724, + -4.867216645426291, -4.85864761270119, -4.820149134568306, + -4.881081685563463, -3.6610088191091923, -4.523883318425133, + -4.405422178721609, -4.511747247142908, -4.4973757423052545, + -4.410859930021738, -4.692381446660533, -3.970040309575452, + -4.061847858828575, -4.724689689893191, -4.678033998252392, + -4.350556098635668, -4.167208374486401, -4.450909776342023, + -4.644417387453407, -3.724277324458299, -4.630737283549326, + -4.509337607422754, -3.787718752781497, -4.309323510802315, + -0.6823718671879156, -4.449775346271411, -4.306372205167735, + -4.410859930021738, -4.920232593125288, -4.3914208729895154, + -6.478377211171838, -6.487035273914953, -6.801150603434889, + -6.531487036485786, -6.875258575588611, -6.039010551387992, + -6.9553012832621475, -5.362670489144429, -7.042312660251777, + -7.027274782887236, -6.983472160228843, -6.58757650313683, + -6.732157731947938, -5.820321350423163, -6.504579583565862, + -6.710178825229162, -6.395685495326725, -6.710178825229162, + -6.559138567816296, -5.802621773323762, -6.789316145787886, + -6.8131267944816045, -6.29749346914751, -7.1889161344436525, + -7.012459697102096, -6.888161980424519, + }, + { + -6.973841065843466, -5.090695336189662, -5.341561221116127, + -6.0115634498929555, -6.202945132409144, -6.628849553394376, + -6.911669409716161, -7.0009992844957765, -6.886081347969349, + -6.711294966663227, -2.260331825727248, -3.839334077735597, + -3.9667628422059718, -3.420241689905642, -1.8735787833427253, + -4.188499103605226, -3.691171678101274, -3.8593630820739957, + -2.3524981891706576, -6.231341006564324, -3.7662373591100775, + -3.6465568924129386, -3.4963200738799767, -3.4321214183238204, + -2.593050419274572, -4.346868167488547, -7.8364379197408365, + -3.990422275679548, -2.904818352752614, -2.3714612152432646, + -3.1378637759089556, -4.357037863124861, -4.651314292504279, + -6.760867254793699, -4.107313187039242, -4.3976920060255535, + -6.440759053046417, -6.465477098310146, -6.582182413654962, + -6.610599862587676, -6.978263755093254, -6.719449335464573, + -6.730879435939417, -6.514035039942995, -7.843934206718764, + -7.66305587798569, -6.780807453646412, -6.810345466083276, + -6.347157031161333, -7.321885120582923, -7.779113558339937, + -6.602957069625781, -9.658525717989464, -6.893034874465941, + -5.640541915214837, -6.61808064554899, -7.825297811959789, + -7.623352248005446, -6.729273803531229, -8.625119353004427, + -9.394209194493895, -8.033505455437194, + }, + { + -5.604855175474509, -4.462285490693087, -4.571350651692403, + -5.056493889833258, -5.072440143885144, -5.681064638387167, + -6.280536665394942, -5.74786868753166, -6.300402104581103, + -6.443541857970619, -3.08781816164275, -3.6971443171127936, + -2.396573090959646, -4.216785762291264, -2.055069601332964, + -4.2400357108180975, -4.510301966657801, -2.8725223515174108, + -2.985980079879496, -6.151031964062443, -4.17853136290412, + -3.739735408911567, -4.177743865892257, -4.758224336321508, + -3.406169247786832, -2.7407038589797272, -6.9336687884910315, + -4.884332887441078, -2.4403221799860293, -1.8263508274951405, + -3.4054696763623764, -4.562592776233452, -4.420217843796468, + -6.782722037918705, -4.9372619598181355, -5.457485531187882, + -6.256287610141627, -6.611108985431037, -6.565907361549403, + -6.49534726380481, -7.061567128112425, -6.599672447239019, + -6.7013251912547664, -6.80746927442344, -7.516987128232732, + -8.06324629910308, -6.809992050813993, -6.860502751231873, + -6.646463246903641, -7.480934599971211, -7.54322475844959, + -6.575185095427639, -8.985698479921282, -6.994899040702809, + -5.767168821265772, -6.530694737719788, -7.839611467995152, + -7.435063610819411, -7.091053743823944, -8.707954377459634, + -9.10781723001913, -8.370947238445352, + }, + { + -6.890344120648169, -5.02940421086846, -5.408867487897182, + -5.967857793669728, -6.047653312106489, -6.46237897058548, + -6.749954722267399, -6.888388607925276, -6.98955227182629, + -7.21719797180092, -2.4868466816371, -4.771074471877903, + -3.6481121610473157, -4.664656454469179, -1.6817234068168874, + -4.586866350603287, -4.845552155508254, -3.154508356873059, + -2.57905575846229, -6.254276196451527, -4.921506816489567, + -4.4705470709445265, -1.6402347840968394, -5.1280286653720175, + -2.882844123251368, -4.595878517780293, -8.231899529453244, + -3.131328577959143, -2.841674626039629, -3.3059284308174086, + -3.1776616460738145, -4.478455963747706, -4.881954395151054, + -7.651052083171771, -4.569886902888001, -4.27044926534142, + -6.859624364774909, -6.620591583748609, -7.035724951332805, + -7.0226528697654516, -7.663432064808081, -6.880725735179707, + -7.096836038369936, -7.001238775261635, -7.94609099384926, + -8.742881147291776, -7.2506609077408095, -7.3153280695559095, + -7.053568548019118, -7.728589206441718, -8.033869830584925, + -6.95515998225557, -10.250083546611185, -7.317576103473792, + -6.34314386192865, -6.83930777142871, -8.443181097280567, + -7.8493114938202, -7.476614929901965, -9.60010853791645, + -8.54213954241637, -8.677952686589895, + }, + { + -7.97530600380511, -6.415691397743754, -6.861539964259856, + -7.354178676035024, -7.5544322703441, -7.956843940965374, + -8.00285595557334, -7.941715059369074, -7.997284910523884, + -7.042078762400056, -4.593656623473984, -3.4358427231129607, + -2.813804032113097, -3.8443096208464707, -2.253236786554918, + -3.523372060796657, -3.771274119941123, -4.213005093082092, + -4.26676474950711, -6.604661414352346, -4.071781743539046, + -3.0636392294004997, -2.748766550188664, -1.5979085155684218, + -6.096125476162904, -3.8319741165296572, -8.437883856353995, + -2.362166563210972, -2.079080404566457, -2.423752746988421, + -6.1373971409737065, -6.112261605870961, -6.033619491127531, + -6.187046440930159, -5.880551407088361, -5.508879098944167, + -8.771401153617497, -8.582218506443597, -8.081702252336468, + -7.820268405959624, -9.01805471242806, -8.991966276343762, + -8.037776271878622, -8.339328192194554, -9.20125771484982, + -9.932145223392613, -8.711282886564021, -8.633361864553784, + -8.75433589306331, -8.724333642759511, -9.49070501282617, + -8.37573721938598, -10.194509487860104, -8.552742688310644, + -7.968342726152964, -7.956843940965374, -9.863152351905661, + -9.598817643450872, -9.08877973142313, -9.278218755985948, + -10.729432663205156, -9.20125771484982, + }, + { + -5.1527222081970026, -5.012025127950751, -5.39388426501389, + -6.217687012129963, -6.355002880531065, -5.6351154829069525, + -6.363993950090922, -6.903492332891861, -6.853964796193012, + -7.129436704737862, -2.71361594954537, -4.917813116205636, + -4.909342477322127, -4.834757647401019, -1.3606202815267094, + -5.049186428683174, -4.831934627067998, -4.02878090419557, + -0.9857025802248848, -6.9583248115172545, -5.928056254423655, + -5.1548164498001166, -5.532591229650075, -5.575217341325883, + -2.1159432194090155, -4.2897086796604516, -7.362881241689201, + -5.200780422733714, -4.007732553855012, -4.899317914996637, + -5.732412626945404, -5.409409253401815, -4.570479874572386, + -6.004563148213606, -4.806034206660294, -6.602559371961363, + -8.008146936015933, -8.264296783798311, -8.114951495245993, + -7.067733915701082, -8.653122572902513, -8.40456220860418, + -8.35558820400772, -8.362968311305343, -9.101577865942044, + -9.242891399008622, -8.693532111240389, -8.468328826963168, + -8.348262163915647, -8.71436619814323, -8.123659823137777, + -7.872345394856871, -9.1093600063841, -8.693532111240389, + -7.279281672853908, -7.536521246398329, -8.924437667890087, + -8.99854564004381, -8.061492916721225, -8.91796515338447, + -7.579574252897618, -8.90514446495541, + }, + { + -6.625065979493934, -4.788580474517243, -5.256407824340383, + -5.37832984858721, -5.2038978790684185, -6.079823689638168, + -6.317086566978479, -6.646320764762257, -6.72855886299923, + -6.886116701148103, -1.505097000684665, -4.82588581184553, + -5.253602398681012, -4.989577089424305, -1.5758741362397704, + -5.185784176269271, -4.916501452893276, -3.8159863951228723, + -1.6041923545980379, -5.633841418592661, -5.7199839934992545, + -5.2161585690547705, -5.369003667873634, -3.3721189713516244, + -2.661522576130661, -4.670108701549678, -7.227790153984301, + -5.183916064386551, -2.494756625753895, -3.869077211017653, + -4.27104038948766, -6.0954898063825675, -4.71167529774246, + -7.136943681210728, -5.987593808088792, -6.590446143960144, + -7.403791666759668, -6.814987319540992, -7.030531087602099, + -7.451894781778061, -8.262224216961, -7.8389014914528286, + -7.199379152151521, -7.871278420177289, -7.002535480112671, + -8.630549778119708, -8.06204504276704, -7.169938203345767, + -7.199379152151521, -8.169374062997537, -8.264930578558742, + -7.090662928646722, -9.550754409315, -8.033689817011913, + -7.078178371984477, -7.674437552058881, -7.921898411023797, + -8.116604027017473, -8.273093889197904, -9.39660372948774, + -7.831846788472939, -9.063739434242727, + }, + { + -5.33959692367457, -3.901875433911095, -3.3263523840890916, + -4.682859878096868, -5.0569946532038434, -4.833678156338227, + -5.439237690659609, -5.4278954140556746, -5.662170026427569, + -5.462315637942154, -3.751806551579704, -4.660118258928943, + -3.8333548860836233, -3.8811153084238335, -3.4958051088141735, + -4.553750303632283, -4.534932311997922, -1.8458046740483725, + -3.0281790617647277, -4.436160927561686, -4.943995470762378, + -4.549402848736927, -3.9218705969950047, -5.328568099202016, + -4.452091297246621, -1.4302390343932077, -6.080922600826194, + -5.1148485422425125, -3.3219189169449392, -2.621905648275213, + -4.3789508674983555, -4.262632175345694, -5.088920047216344, + -3.3849839728869298, -3.307281062205608, -5.974439120423745, + -4.379829216259262, -6.791884017661267, -6.8166991867809905, + -6.068955964208674, -7.1565271312491765, -6.683586642330131, + -6.801736314104279, -6.532793078538745, -7.518256845849533, + -8.152370494825284, -7.391505140210389, -6.7194113688482755, + -6.416271872702784, -7.279027156783699, -6.4871905993829495, + -6.66039719741122, -8.204669994228134, -6.878895394650897, + -6.094660190607558, -6.427558674237414, -8.084652320770335, + -7.339319387039819, -7.347830076707727, -6.950948712290955, + -8.303341521735163, -7.468823387994359, + }, + { + -5.431835629645527, -3.900968951139421, -4.151004765492447, + -4.646528675532386, -4.521804796114552, -5.283128043243618, + -5.29007437093391, -5.66335521876192, -5.740643416211578, + -5.366660147370001, -2.670098748915231, -3.286242237340954, + -3.3585141055181613, -3.755602707715123, -2.5586532961090027, + -3.6926656242369105, -3.8330192649391925, -3.254475467118251, + -3.8290307266838655, -5.019290301102854, -4.363753678748955, + -2.9684754808494547, -3.151618081678543, -3.50657051212598, + -2.895083629045828, -2.91665360144011, -6.285849431998168, + -3.6228229122699127, -2.152751777383897, -3.3162167836347605, + -4.2488413058475105, -4.652746019284857, -3.9288228848114928, + -5.349158624766704, -5.572231075081914, -5.261791793324819, + -5.624778734167247, -5.278347157643276, -5.3043854022704995, + -5.210237912616575, -6.346428699255328, -5.93048158286466, + -5.615084400228674, -5.89255288484716, -5.916841563358977, + -6.777270925569916, -6.237681480853062, -5.483828321441287, + -5.599254877723378, -5.735607736245962, -6.332645938959907, + -5.443956990177872, -7.787390135984574, -5.974679054270741, + -4.487700164671342, -5.484479363130949, -7.787390135984574, + -6.624646575217306, -5.915838554247808, -7.256570295689133, + -7.872330812633658, -7.3300889926342885, + }, + { + -5.8962959205599565, -5.022482812723318, -5.262967235210922, + -5.638331471894197, -5.778457744433211, -6.3109845765456285, + -6.29163873510587, -6.56832765910669, -6.49255510063436, + -6.3650100589758205, -2.863492599093995, -4.089024629780227, + -5.154949557468251, -4.484159695248834, -0.9343644420039627, + -4.498161263246394, -4.6279862283262885, -3.982370058053253, + -2.2035282537140866, -6.199482179547703, -4.571665803362194, + -4.084960905072187, -4.755413554835734, -4.800997636581884, + -3.6971982708382995, -4.566795129611478, -6.871351961660363, + -5.099526707333125, -4.135788994836005, -3.1706024468180507, + -2.212641008744242, -5.078715683958774, -3.5811841558979225, + -6.741940888008861, -4.856098125468122, -3.980907107020626, + -6.712325967469931, -6.644006723492454, -7.153784678226001, + -6.945055157447498, -6.898020208742524, -7.021563043483541, + -7.173168545047049, -6.854391346353318, -7.669859657878135, + -8.284314569862415, -6.895321151773359, -7.513205847832758, + -6.795366054682441, -7.556635405760094, -7.827916592672458, + -7.241272132349116, -8.35137880044296, -7.187505708193456, + -6.1188193168155305, -7.139919638088829, -8.075324765986299, + -7.379987004046535, -7.364785842714484, -8.480789874094464, + -8.527936652520165, -7.717773013574032, + }, + { + -5.1596391409467905, -4.446625879300866, -4.792661465824471, + -5.092676376197713, -3.486026851337387, -5.293817992318437, + -5.4207097441730605, -5.031624556083574, -5.433394903700377, + -5.123410202650332, -4.715036303793935, -3.7021536789683007, + -3.7870302329121537, -4.088809455118969, -4.812132309601868, + -4.898021981482298, -4.704305701448848, -5.045386241156256, + -4.694501701352228, -7.439823297251669, -3.3979941838940024, + -2.7387677229303073, -3.4751598040428164, -2.0375451283648167, + -7.179408351140228, -3.811103778633784, -5.971540702552751, + -2.9729698958508197, -3.825149191015764, -4.478865937874288, + -2.6641628726801234, -5.3193066285353545, -5.996634270150407, + -6.375549146164451, -6.785390628872414, -6.572829186888741, + -4.124487206195906, -4.535138151336436, -3.7135200209337587, + -3.96463850525401, -4.554386339641352, -4.765674647825141, + -4.429638997109137, -5.277664924510665, -5.02086262836912, + -5.937153360243275, -4.7565501004863675, -3.693750268171921, + -3.749678820831146, -3.176252392796863, -5.722496422806384, + -4.546642548744449, -5.417354036326088, -3.1803577086920454, + -3.749362815140414, -4.066652137558128, -4.660532401294013, + -5.1570534898617675, -5.430844966067104, -5.284241491875228, + -5.5748604240003194, -5.63236491848051, + }, + { + -2.1543734650260515, -4.349659150265929, -4.518901599180162, + -4.334150339570116, -5.146931928181808, -4.726677895862385, + -3.8738862022041083, -5.547738126032732, -4.965611539500847, + -5.329386916158828, -2.0510193107742145, -7.017067715762613, + -6.5514024881154755, -6.782731624016124, -2.1387030138865364, + -6.887331394106641, -7.26098839501858, -5.915573580719614, + -2.792353319034718, -6.475549145597215, -8.196805549243091, + -2.7290425937620233, -6.57338139483425, -7.482751683863832, + -2.7069370493135643, -6.6217549791184664, -7.959675755954141, + -2.6929063910157374, -6.402701413055781, -7.378081061299943, + -3.038722067403394, -7.146279447242619, -7.442205589469482, + -7.777354199160186, -5.436617340201765, -7.9268859331311505, + -4.21410095816366, -3.7159537926574395, -3.274052690014408, + -3.8709022387814955, -3.903841048493916, -4.907248138723605, + -5.564815386850924, -5.634025390029099, -4.794669640998671, + -6.37044055083756, -5.773624479216047, -4.984713243886536, + -4.705003878814023, -5.884409585684786, -4.869643914101749, + -5.8105008762596295, -6.426399204485604, -4.552569937605819, + -4.688840192155229, -5.1496039404596194, -5.387063525747035, + -5.940338138344011, -5.40158748887255, -6.8282736444630405, + -6.302506440698851, -6.49077786629904, + }, + { + -5.042027972011844, -4.299718672656642, -4.243324982365076, + -1.9825142998026875, -4.725280240738409, -4.751810055033314, + -5.528415080508104, -5.372269658882421, -5.58057814379269, + -5.634199235231788, -2.092585085927561, -5.359310514239916, + -4.924244936355461, -6.182928172882705, -4.358300013368391, + -5.644135441890917, -5.3193472574280785, -2.4216711986248063, + -3.5454438576615357, -6.6553797837670805, -6.406683158028254, + -3.42063060974259, -6.230496589801815, -5.313180742512414, + -2.1141313157147192, -6.38251279710044, -7.199431055161392, + -3.210947634389801, -4.823896962521179, -5.599497627038855, + -3.7500872171087103, -6.903338504201014, -6.960201366095558, + -7.542682978767983, -5.613234106766742, -6.36476085164199, + -3.6714819678600925, -4.875454772186028, -4.20471280907303, + -3.884017303250544, -3.4828969984685907, -4.20471280907303, + -5.449056802096191, -3.411103801364231, -4.476181634325785, + -6.299489461288767, -4.386290645201218, -5.042027972011844, + -4.789932598747867, -5.333885415874105, -4.1803254304220925, + -4.950988261330972, -6.251222720318932, -4.73156059252596, + -4.355150404465494, -4.750641830601388, -5.174666905853347, + -5.78646844695934, -5.852762894799176, -6.180486169227153, + -6.353098911894147, -6.096324376905443, + }, + { + -3.621153540136533, -3.927545190670303, -4.761298021301781, + -5.2327070159671, -5.390836480884121, -5.489330016767771, + -5.419938023343771, -5.638503085521277, -4.333907884333748, + -4.5925613698517225, -2.3774699118392917, -7.240027999198052, + -5.856199730573355, -5.309006462636489, -2.1188535037876086, + -6.988713570917146, -7.259929153515347, -5.733217613565709, + -2.1988937611323722, -6.914879308906094, -7.285375819176511, + -7.471829613255376, -6.297483936486472, -6.369085087302357, + -3.0144535413397078, -6.131611710433321, -8.510182710405289, + -3.290870578196505, -5.79050447130796, -7.191941812530414, + -3.661034886200146, -5.933160771709483, -6.992552347224311, + -6.430741168725453, -6.006448567479316, -7.6405790925037875, + -3.820123280601132, -4.60874181430768, -4.552214016916188, + -4.152125265844404, -1.8440074384079603, -4.33229280995845, + -4.748982594711727, -5.590043992369601, -4.083551769494654, + -5.885005729822436, -5.570371226770897, -4.35431953325285, + -5.037889407059404, -5.600505333614971, -5.2234842891983275, + -5.239347146606377, -6.012203979049936, -3.2506791222758458, + -3.493367719618491, -4.386449689183688, -4.5929103490909995, + -3.6635121789617022, -5.259536257638402, -6.071656848963408, + -5.913358144413303, -6.637031915632404, + }, + { + -2.697794466436189, -3.604662393389068, -4.011263957500705, + -4.728080882146555, -4.781372179196779, -5.33155887684335, + -5.439355447299057, -5.586922158039964, -5.370633615250003, + -5.513150772897161, -4.398260316869362, -5.11207163673225, + -4.190082883743458, -3.4501177344839546, -6.597640067453566, + -5.490434815062624, -5.150911470048515, -4.837107457567751, + -2.85030853825846, -7.320346050255055, -5.997701716211621, + -3.4753179136511876, -4.2866759373606715, -3.397053452568678, + -6.703360230660674, -4.113003141200578, -6.444877312901155, + -3.074043686998346, -3.452623303723489, -5.193702907090925, + -3.9327969395172757, -4.131242383720524, -5.418238523858134, + -3.7478131640115406, -6.184652086682414, -7.063123185287982, + -3.7394230709797665, -3.4179694218787144, -4.267288710081795, + -3.0709940324857143, -4.263518677341253, -4.701005637323521, + -4.417094629495229, -4.569236359692398, -4.473887479448818, + -5.8432973258667005, -4.728080882146555, -3.754953367214181, + -4.1263095154005, -3.415012032977706, -4.81618158386264, + -4.691820172692138, -5.666572324000903, -2.795735372125381, + -3.2437129699651224, -3.9019638438387987, -3.582993942690341, + -5.112804505947904, -4.894364079117085, -4.722110715160052, + -6.056219323109372, -5.5022692727096265, + }, + { + -4.619141531251806, -4.242478414047348, -4.655112011634125, + -5.260049492712331, -5.018630839221239, -5.434973330528597, + -5.291682300504695, -5.652426966065128, -4.133100006910822, + -4.834429582625707, -1.998550183209591, -5.7433143168994505, + -6.845817661060527, -6.562531200081784, -2.4549848852751466, + -6.626189051853761, -6.290387731057782, -5.567486289416045, + -2.141146196531367, -7.242549089199937, -7.104679294976816, + -2.8517566389677937, -5.192894636686687, -7.082206439124757, + -2.3092018462234853, -6.71448165899944, -8.017189304011065, + -2.1705324264442973, -5.663122255181876, -6.392769837961348, + -2.584044215625091, -7.28700085177077, -6.816997222525035, + -7.454881724409931, -7.498844847831047, -6.3210545294507545, + -3.9234738704665255, -5.210974225191004, -4.156261002958894, + -4.841496749848799, -4.597299789336757, -4.421170202790724, + -4.975365923256807, -5.672123216040852, -4.474317672329112, + -6.090327349926446, -5.367408011032831, -4.491383872387231, + -5.280618880960439, -5.815780620152271, -4.640826054386648, + -5.541761398177608, -6.307308608546119, -4.360911011272527, + -3.968855752517438, -5.060904184340462, -5.092811178129705, + -5.9935197902566175, -5.119506808592894, -5.086750553518014, + -6.052587021943599, -5.38489332537385, + }, + { + -5.261046281621696, -4.9148297535258045, -5.093521542269181, + -5.160962823064713, -5.492794680129424, -5.583178741597693, + -5.608843109973599, -5.828958322395465, -5.818217080564052, + -5.6351835265880075, -1.9431063436877503, -5.762127613913009, + -6.364566555601998, -6.310693565661846, -1.465488331318766, + -6.653479397439911, -6.983078754773362, -4.701955198551832, + -2.920630198813372, -7.381717897811127, -7.114655112562081, + -3.628618850962897, -4.741931970713727, -6.050483313874263, + -2.961525855445553, -6.683481647743711, -7.823550650090166, + -2.1208799042866553, -6.236585593508124, -6.735576759627112, + -3.3232120191551315, -6.891511561247872, -6.08336298799342, + -7.9413336857465495, -5.554867108771802, -7.122498290023107, + -4.193090909121505, -3.901105949199606, -4.152689701478908, + -4.935827900365578, -3.224590180736388, -5.347946392964479, + -5.205112607677643, -4.550306897288771, -4.485129674572183, + -6.303724896345753, -5.654950567328784, -4.928779413034516, + -5.0770940681272325, -5.30867433061095, -4.570963767879653, + -4.7737511552658995, -6.146602446129337, -3.6472116840395126, + -4.583317229489316, -4.247999881283233, -5.050961927850385, + -5.554867108771802, -5.239253651630843, -5.752077278059507, + -6.0889495947020595, -6.114482896707225, + }, + { + -4.8357984388643835, -4.657872493543467, -5.438431611883497, + -5.481947249319659, -5.480513557317811, -5.739017089171186, + -5.670890393572083, -5.859121927588727, -6.047318448825703, + -5.930658377913943, -1.7234534048021994, -6.808376835001858, + -7.018097365983928, -6.515303913915201, -2.0800327647225068, + -6.985307543160936, -6.434021280478344, -5.690138581877, + -3.0546210789668655, -7.433612809945593, -7.609892052283585, + -6.846949109788098, -7.145930737493813, -6.771237288052402, + -1.3242305561151027, -6.88123818326673, -7.934388097858083, + -6.599387031125742, -6.8029859863669815, -6.569147145936024, + -2.3927324727103167, -7.200418922777882, -7.33738477785104, + -7.62201341281593, -4.893045313052039, -5.366877919534872, + -4.1899951004809015, -5.453656819480563, -4.694403309779647, + -3.431804500645092, -4.0124147615767685, -5.525942614164559, + -5.309719505694924, -5.568828205702649, -4.124028746206436, + -6.415604553692113, -5.4275025413513065, -4.984699762805498, + -5.237511197353998, -5.157641365469638, -4.101047614464405, + -5.085610237260755, -5.550223017871613, -4.869440755282619, + -4.489173830779152, -4.234321454353582, -5.041242413079193, + -5.780689785571754, -5.231908941805328, -5.964947451392574, + -5.752089170738539, -6.139854701747302, + }, + { + -5.508465007700513, -4.839258034686576, -5.109472414097966, + -5.519275923804729, -5.707703038161169, -5.439902336263216, + -5.7235763873174585, -5.821556795677663, -5.734300350680434, + -5.610247702010455, -5.910709501108635, -5.7235763873174585, + -4.435262434557772, -3.8610478472011964, -5.758858201462099, + -6.0632537548876195, -6.044700346991872, -4.117878794499082, + -6.575328598054043, -7.243783166023616, -6.403478341127383, + -5.083829983484629, -3.317712944869911, -1.7163886672099804, + -5.622223893057171, -5.543479525545615, -7.373836294271814, + -4.235327303674574, -3.4757995308184078, -3.8216678856997803, + -6.863010670505823, -5.619817153026606, -5.966922645949188, + -7.096625521687328, -7.1845942946332855, -6.5629060780554855, + -3.9611313057581787, -4.164449795424729, -3.6745940531223313, + -2.809054169189011, -3.303860323066671, -4.356804692686432, + -4.075943929085389, -4.993775889109478, -3.5055329961999946, + -5.4956443192714515, -3.896020865817486, -3.604273312212492, + -3.5622476861654384, -2.789152302491872, -3.9102728885246876, + -3.0660244750660355, -5.631909198791635, -4.404134333185408, + -2.9033092297609358, -3.155554830818952, -5.387104150696246, + -4.341290047595106, -5.258585299895267, -5.109472414097966, + -5.821556795677663, -5.14024407276472, + }, + { + -4.364789554126129, -4.918384854279969, -4.918384854279969, + -5.1613310328903585, -4.587530609962979, -4.784853461655446, + -5.006160465162354, -5.0403784224726955, -4.994002260682545, + -5.402493089707247, -1.4796200682550344, -6.181000119218348, + -6.701776073837507, -6.252825853789604, -2.1508860947624866, + -6.086590434747274, -5.772240115213331, -5.482914657017821, + -3.9652464014134288, -6.426672783592586, -6.401671481387169, + -6.285261129542758, -5.890845857621178, -6.3772800282630095, + -1.9660163181458141, -6.770768945324459, -7.107241181945672, + -5.362398632505369, -5.920923312858457, -6.7530693682250575, + -2.0597919147266994, -6.701776073837507, -6.505661194911217, + -6.5476253940102485, -6.637237552699936, -6.7530693682250575, + -3.9354569646113213, -4.092932522818745, -4.814706424805127, + -4.961309898997003, -4.355174095426687, -4.949681861001884, + -4.869194610089197, -5.046727650151355, -4.8507000274530325, + -5.115948027042541, -4.814706424805127, -4.689097748317353, + -4.863875448611597, -5.043547997233975, -3.6732539774605253, + -3.9481153614832447, -5.340799520701906, -4.835115296436334, + -4.068688911208753, -5.024679512929592, -4.753487802377227, + -4.994002260682545, -5.247044551164388, -4.698046353893368, + -5.307182909902921, -5.227776132298511, + }, + { + -5.115394338583977, -4.7561420736309445, -5.007842676853897, + -5.66123448019507, -5.033665707964376, -5.645764558422938, + -5.535809351386801, -5.907471144471458, -5.828086115216893, + -6.105296887801378, -1.6832402388074508, -7.437524027650993, + -5.590313253886724, -6.862982589498895, -3.0491034044747836, + -5.586172461220692, -6.632458930887062, -5.218606625703514, + -2.4710973040085813, -7.398809515470303, -7.268447697607059, + -2.7116510959031834, -6.686853002952861, -3.7188303108266303, + -1.9217106058640063, -6.098376444956805, -7.548749662761217, + -2.711068175455316, -6.088084758920257, -7.1630871819492326, + -2.4953178542046213, -6.5371487510827375, -6.531815405107375, + -6.592107635363495, -5.218606625703514, -7.464192274733154, + -4.025855346121542, -5.098759278079445, -4.812664759541027, + -5.369662433402117, -3.845996309584077, -5.031290409935469, + -4.627804324836165, -5.549657248245595, -3.554062953084761, + -6.151486270270753, -4.8426621708268565, -4.640563668589926, + -5.069989313821911, -5.128381534110789, -4.6191257693799175, + -5.164313543336852, -5.9721996171719525, -5.146851716173189, + -4.482065653234942, -4.222339216728002, -5.190396010216277, + -5.978297197040071, -4.681519433426748, -6.057830350562455, + -5.619789072019677, -5.749664153441089, + }, + { + -4.867406343870729, -4.4533740975545415, -4.953434176237852, + -5.384635998990067, -5.328952912513263, -5.6593669190947695, + -5.597013688377717, -5.757806991908022, -5.710273291442284, + -6.117674508577314, -2.0752354231922467, -5.330274789771179, + -7.239817294655618, -4.653127950557675, -1.9861891376978962, + -6.498730651806554, -6.748830013109291, -5.799220777458779, + -1.8880861157511444, -7.060476365999801, -6.592340150928861, + -6.615981913985901, -5.98705432616025, -6.055682832549346, + -2.2283490142554703, -6.244583360441343, -7.060476365999801, + -6.9543698600052535, -6.005072831662928, -6.675112437212724, + -3.324941220245065, -6.737960340872387, -6.846328377594169, + -7.276184938826493, -5.466076330930241, -7.601607339261121, + -3.2284338811241238, -4.7571452826690335, -4.2772171644143535, + -3.794375211195705, -2.9321390456478555, -4.655146114713912, + -4.556474587206883, -4.658518799192551, -3.9133691163329902, + -6.159223511490186, -4.874928318325417, -3.9851607325065794, + -4.593769151695071, -4.865742449976033, -4.192747084853396, + -4.158562847663465, -5.583291346122616, -4.6687056444995445, + -4.403457644910037, -4.135470875670939, -4.338591952168042, + -5.484425469598437, -5.10713123845697, -4.666659956776251, + -5.507845743806536, -5.56639905255811, + }, + { + -5.367738120634485, -4.778432275797196, -5.153988612512787, + -4.9880684755260525, -5.022992659762126, -5.315533041364984, + -5.937669186281741, -6.10637419308453, -5.985149724514735, + -6.0666028696576335, -1.4917500304139726, -5.449683054485573, + -5.538947192058466, -5.596026010244295, -2.1356770840200325, + -7.153812526227932, -7.094389105757131, -6.013018623523528, + -2.2775252846627545, -6.010847070010019, -7.246405313055757, + -6.755173383190167, -6.697507741340358, -5.530860894627108, + -1.9981251565724831, -5.698525293621089, -8.083802102460249, + -4.860110306811463, -5.882753428685626, -6.945748081740843, + -2.8863534391722627, -7.100819996087421, -6.962461562714583, + -7.231590227270615, -4.4224533361891325, -6.0688990819179836, + -3.292438554454217, -4.782234561746934, -4.459461169483883, + -4.359771877270199, -3.9163352754091854, -5.15214868559078, + -5.0863471755948115, -5.622152314836516, -4.041658687615878, + -6.321199217523649, -5.22160122153078, -5.082053480720112, + -4.742403534262838, -4.896452531238822, -4.577416633798337, + -4.325814840936012, -5.22258692885554, -5.570564946046022, + -3.7753199382595333, -4.751597592285044, -5.351900685535859, + -5.538947192058466, -3.6838339356894148, -5.717756655548977, + -5.9396873504379775, -6.193602560418941, + }, + { + -4.999514188504179, -4.700587505853424, -4.67022803135639, + -4.81576740495976, -4.92872993147181, -5.418517964945142, + -5.4525477135314535, -5.471965799388554, -5.601583292691941, + -5.294558257397029, -2.0675057720915833, -6.606510097282728, + -6.66295140818768, -6.268297216183731, -1.8472066532219233, + -6.801101746668497, -6.464629510047284, -5.518112402024337, + -2.6153829107633095, -5.40926720517299, -7.042937430994859, + -6.122880216325227, -4.984950824316282, -6.978988706394586, + -2.5341534752438712, -6.335738496979263, -7.22903971062872, + -5.047082605423289, -6.606510097282728, -7.195517018590076, + -3.3881221963080814, -6.764734102497622, -6.935691900641261, + -6.06802185577318, -5.518112402024337, -6.21743879895024, + -3.306166689176508, -4.5835098665078435, -4.096018906794089, + -2.7778687007936327, -3.149770331333854, -4.522505810044474, + -3.6065186143693406, -4.579485716208118, -3.9009018998360694, + -5.695109350702764, -4.592420415540891, -4.39850374434322, + -4.858371250530563, -4.687974726037726, -4.284600731462279, + -4.828050056815601, -5.7714823294873385, -4.760362534007699, + -3.6910492160852075, -3.1337486268025883, -5.114702793098268, + -5.044521784561615, -4.990993138772245, -5.21262268525524, + -5.1495981689488834, -4.939033399841534, + }, + { + -5.573013579156251, -4.7557456323553735, -4.835888625843566, + -5.4310032481645445, -5.375816832597254, -5.748275644237248, + -5.617589203744957, -5.426286258286405, -5.527732874623095, + -6.027336973645122, -5.771265162461947, -3.4363190171520683, + -4.863649827007062, -5.342810536129083, -3.9603112459777443, + -3.1741279621323484, -6.522548369609561, -4.089429329592385, + -5.667234434234122, -6.573100648772392, -5.74180312973163, + -3.6814950844272993, -4.555731535734934, -2.60141208694855, + -6.057840427938536, -2.6538446056843625, -7.3352407008192895, + -2.4633202784204524, -3.0508881488790776, -5.069846636151324, + -3.6495408996227328, -4.548858656447172, -5.7613477258046, + -6.031638055544512, -6.61856302284915, -5.764642621701453, + -4.906092884516815, -3.945751808422034, -4.075923906392578, + -4.145352412824341, -4.3284585910787134, -4.1375398730875474, + -4.386633312115669, -4.864991208831262, -5.2459274106602996, + -5.389330551763976, -4.366047982499911, -3.5236520927129136, + -3.6216686341149815, -3.0467401241562313, -4.4457511661828155, + -3.28056139498962, -5.728982441302569, -3.2282776746379773, + -3.3483163872180257, -3.6120365041642786, -4.280940073114231, + -4.240597235287379, -4.439591885822281, -4.571620648562269, + -5.13801612348307, -5.583972592945972, + }, + { + -5.648871675811755, -4.741030782968909, -5.070478143556586, + -5.038332518583169, -4.984450311189462, -5.652113169735926, + -5.878916005474925, -6.018576120040821, -5.698633185370818, + -5.924757364823166, -1.8468585970227798, -6.844251516414859, + -7.126600242891277, -6.081398705962876, -2.934905888757429, + -3.6595354362414967, -6.817864761241664, -3.5921374614243615, + -2.9623018840998165, -7.15537920744132, -5.837035508229937, + -2.956367800752568, -5.44072677540776, -6.135188880549014, + -2.35874447462609, -6.817864761241664, -7.744626792983114, + -1.829808862763535, -4.656579250518651, -7.012765100242478, + -3.346772137573546, -6.156466278996299, -6.772055225210369, + -5.459294948136628, -6.2464145156592386, -6.772055225210369, + -3.9054574859103, -5.259720143195114, -3.484916480113615, + -4.59888775210554, -4.26703708287839, -5.280773552392946, + -4.568219053541838, -5.236954932422101, -4.227597595795837, + -6.429913235626207, -5.14878310004672, -4.299244656170703, + -5.066854951187166, -5.722730736949879, -4.343868104023761, + -4.895290258966649, -5.924757364823166, -4.2366225736701635, + -3.439140235431567, -5.290903070631802, -4.913738130330258, + -5.32777360644013, -5.700335313441349, -4.118883335232663, + -6.285399962372192, -5.825384891009962, + }, + { + -4.134798672989471, -4.089847285127205, -4.1376763728170864, + -4.175860159787245, -3.5867437074551245, -4.073498147125676, + -4.247208240584712, -4.485742942219219, -4.161001045383496, + -4.76664532768562, -4.782994465687151, -5.224827217966189, + -5.79734641073752, -5.371880635922686, -5.362028339479674, + -4.805217602471861, -5.696541711615555, -5.1428140663053545, + -4.243997964954463, -5.696541711615555, -6.074978147335799, + -4.388579193765571, -4.887134724939747, -5.433124261163405, + -5.127188748402274, -5.465212575714905, -5.5681605449673475, + -3.871109027280912, -4.3522115495946965, -4.887134724939747, + -1.4812734394569864, -4.9697213159490214, -5.42265296129611, + -5.5681605449673475, -5.696541711615555, -5.592551998091507, + -3.9025017396887742, -4.303421385425264, -4.377529357578986, + -3.2036759521599856, -4.414847120586181, -4.370230055097374, + -4.283218678107745, -4.293269013961246, -4.570900750559526, + -4.639893622046477, -4.473572406598963, -3.944368319081564, + -3.9659778034144195, -4.663991173625537, -3.393956618621509, + -4.489832927470744, -3.9232159440763374, -4.221810049979101, + -3.677082874537429, -4.095356940938174, -3.0285527594662907, + -4.570900750559526, -4.348646483430199, -4.449666885745409, + -4.481669616831582, -4.21556002963393, + }, + { + -5.468543074118657, -4.3409301123745765, -4.939132602788878, + -5.030955774234888, -5.486636817561356, -5.444018684255573, + -5.476853371252285, -5.808607963491769, -5.908385471304435, + -5.666153323427702, -2.5849374499856705, -5.739356727450997, + -6.452595908093631, -6.391754248837386, -1.3630653142736813, + -7.218432822021854, -6.741508749931544, -4.321907198551311, + -2.3295168721177877, -7.554905058643067, -7.600367432719824, + -7.660265574300893, -6.068262723688894, -7.064282142194595, + -2.4089621725210324, -6.261701120589188, -7.218432822021854, + -7.400754378815808, -6.405740490812126, -6.66108718262097, + -3.202908170420881, -7.345184527660997, -7.318516280578836, + -7.17951740577218, -6.2346317986209705, -7.685266876506311, + -3.523815890500982, -5.001129001779655, -4.254551658580372, + -3.1791480369827805, -3.272238460048792, -4.979751531007288, + -4.696520976240299, -4.996816791561475, -3.7821441205484283, + -6.068262723688894, -4.767838317222632, -4.961310103104565, + -3.3169412686460493, -4.254142074302682, -3.686717843919221, + -4.781622132973809, -6.395232513213711, -4.882290151848487, + -4.035101934573064, -4.142657840794326, -4.886134831709296, + -5.154991621688459, -5.261248596393322, -5.763145589415012, + -5.307128202144016, -5.4187681732866855, + }, + { + -3.7153348719791315, -4.23835637018879, -5.401341822408315, + -5.655381048015406, -5.3230099791384085, -5.723838105173554, + -5.787159933132683, -6.191069830974041, -6.118044695959151, + -6.512733837722823, -2.85919837658876, -7.902248813542757, + -2.4061387894065027, -6.693770047296114, -2.250325724429897, + -7.350962550860164, -6.005451461342365, -3.2057646919026945, + -3.1269276063809657, -8.282234836349936, -4.929356031958588, + -4.893377430923357, -4.350779231381914, -5.039126698093967, + -3.0950598675329433, -2.702149075140166, -7.065140944061303, + -6.4656293685353505, -6.6671525062961585, -1.5532677412410396, + -3.407685858090993, -6.917395410231305, -4.818860209735889, + -8.330553413620743, -4.697144805661785, -7.44034239452964, + -4.201345166462018, -5.036551747250591, -4.447052124631202, + -4.271306064673767, -4.3875307527168115, -5.68024420720805, + -5.463555006909888, -4.6680077696105, -4.729585831829687, + -6.877248342217893, -5.7894972929813875, -4.744562286019245, + -4.863271676535759, -5.996776708148691, -5.115645847928164, + -4.782587554878788, -6.69569868820252, -5.6198664278662305, + -4.372289459396023, -3.8304137647360905, -5.143464614214886, + -5.692911512408815, -5.442384299786921, -6.144390895990383, + -6.553756817069401, -6.771887826560066, + }, + { + -5.439192275092616, -4.781176186054329, -4.766861598657258, + -5.578787193555129, -5.543563426336324, -5.577507602849504, + -5.742587353208953, -6.240425781448133, -6.11031213333427, + -6.461710020172159, -2.6665339561656087, -5.7471225083743445, + -6.597455272456702, -6.655866034613116, -2.1677366785812078, + -7.063212610820987, -6.615344837207477, -1.8542823223629723, + -2.8203019407701473, -7.921874229858505, -5.964600322152877, + -7.4190807777897785, -7.115398363991557, -7.50316389500032, + -2.434370037607787, -6.75042461723813, -8.501692725111447, + -2.436966652419961, -5.508344242912733, -7.262628600974241, + -3.3318853658660776, -6.320468489121669, -4.662752576421778, + -7.96269622437876, -4.3951216252530045, -7.773454224740232, + -3.4248833433841024, -4.6171877485771935, -4.856615893655904, + -5.148452521314832, -3.262215858586344, -5.067705520626301, + -4.995134827791466, -4.808655260848847, -4.056803079326151, + -6.372894286461519, -5.283769734998518, -4.869131701587735, + -4.356292992089062, -5.580068423711178, -4.205055407055328, + -5.300108397353307, -6.413362236014366, -4.081705328198343, + -3.5651654031689133, -4.4607321960690065, -4.914213385439241, + -3.3562768189902368, -5.301077859377855, -5.2191716350828905, + -5.66568217643417, -5.148452521314832, + }, + { + -4.692472771166889, -4.3008934499719516, -4.549181741142988, + -4.955265087292482, -5.083773336506403, -5.36724487642184, + -5.286555965171697, -5.606625988867734, -5.3561026998685985, + -5.6766361544403825, -6.310506725070788, -5.345083304618988, + -6.354631529979725, -5.436838168221035, -2.778870257014558, + -5.888394383529467, -5.518132910614282, -3.971194340356585, + -5.541198183545278, -7.353160360090853, -5.418980550821029, + -3.590537431731367, -3.3241709789128793, -1.8944436557320132, + -5.91226186493611, -3.390599447549114, -7.2559966116372046, + -3.6807421830309885, -3.742794171598555, -5.40143624117012, + -6.914247317915148, -6.268246915780905, -5.966865998970962, + -6.802329401711162, -7.18453764765506, -6.063197107909394, + -4.040088147996806, -3.4233375319614976, -2.7095546985241823, + -4.374927246403353, -3.562959147374605, -4.404434128912793, + -4.579296940419071, -4.391681565015401, -4.438151297809303, + -5.606625988867734, -4.3282656378478706, -4.1449534915722195, + -4.0950638220693705, -3.3913758451036427, -5.0164696546102965, + -4.409796072054178, -6.030044900592494, -3.187603169643488, + -2.500811269450856, -3.4121731416766146, -5.192891489277063, + -4.804034117568558, -4.273312053475689, -5.056716535118889, + -5.514880875227905, -5.219114684376165, + }, + { + -5.262101982971463, -4.751704716461968, -4.4750082149096455, + -5.006514043913175, -5.07515161250067, -5.251452255054804, + -5.285938431125974, -5.392274080942006, -5.414469813333791, + -5.840086736879263, -2.606359904105076, -6.823463761969788, + -6.89757173412351, -5.234645136738424, -1.8016665052081617, + -5.931967688708849, -5.7146991018376605, -5.437169400849897, + -1.672652532530341, -6.72630001351614, -6.773702252410724, + -5.308112288620296, -6.00575385876808, -6.6810434219280195, + -2.3521748840468923, -5.96169386897405, -7.419447194076086, + -6.095225261598572, -5.008173795331539, -6.397795946544104, + -5.514028406375509, -5.907173030095633, -6.070893160939042, + -4.572171963363293, -6.91979487090822, -6.823463761969788, + -3.666029218824578, -4.169934399745995, -4.315857524665681, + -2.6071122929751187, -3.822642418908326, -5.326212330263914, + -4.3600448319184775, -4.917707706137853, -3.8075287810982776, + -5.953110125282659, -5.187841070540621, -4.792366055507543, + -4.8403533292283845, -5.164264339976624, -4.320022461964966, + -3.8952676954062846, -5.745470760504414, -4.036941945426083, + -4.228361366337563, -4.708930900478682, -5.247223918945283, + -5.006514043913175, -3.8952676954062846, -4.574322501826521, + -5.886970322778113, -5.748949024880739, + }, + { + -5.49714261021104, -4.668772759709356, -4.7793028170607235, + -5.269011517385791, -5.403728165571614, -5.600190986110487, + -5.607143505425369, -5.736034518493389, -5.749350294469161, + -5.980569259788917, -1.8463761496649909, -6.7957313909118255, + -6.842614976810675, -6.277301167760615, -1.6016725181239624, + -6.834646807161499, -6.483542908272222, -3.3781298559126016, + -1.9147238137262874, -7.264209466848723, -6.97044834832056, + -6.2503937148406905, -6.323821183395508, -6.466922027036182, + -2.304012035094697, -6.232849405189781, -7.182292344380837, + -4.500040235600472, -6.194465162181466, -7.045955900828706, + -3.7335540179496816, -6.633976111699347, -6.224191342446667, + -7.560054849939665, -6.541029999189903, -7.7391030813886506, + -3.9953827115751284, -5.225208894727398, -4.2623981472183505, + -4.983820106246462, -3.5900722944719905, -4.880831478599072, + -4.625152137233465, -5.350160419862394, -4.464551422640724, + -6.03257404477923, -5.25911044640308, -4.290672925686517, + -4.802954305142684, -5.287422079228971, -4.798800612773991, + -4.757191363453292, -5.977196575310277, -4.844383490556383, + -2.946883968159507, -4.887603513509017, -5.795997983260946, + -5.6188395451885595, -4.719156549714065, -5.921535728204724, + -6.1778672707724285, -5.694577804815043, + }, + { + -4.469097220436953, -3.6430767584970343, -3.7844067498952314, + -3.931680914923784, -4.272838155799217, -4.129621978555971, + -4.297357772973536, -4.384369149963165, -4.338992745625113, + -4.178787025578902, -4.976420213651742, -4.292052720743842, + -5.461928029433443, -5.887479896108345, -4.57562801124297, + -5.526466550571014, -6.262964172004573, -4.4462034005711, + -5.238784478119233, -6.017291507630335, -6.355745905455539, + -5.968972930359527, -5.520424236115051, -6.328346931267425, + -5.70515833931439, -4.218953067304238, -6.6434279779073195, + -5.648805402763258, -5.5635078222513625, -4.870360641691417, + -6.412904319295488, -1.949196049230905, -5.968972930359527, + -4.4990139814749455, -6.027241838483503, -6.442757282445169, + -4.057336183871974, -4.448263133534111, -4.000410247075965, + -3.7940068236242506, -4.150834895195163, -4.166267300233975, + -4.566303934367847, -4.3901887590164295, -4.028468199871122, + -4.376661982718227, -4.915384323065373, -3.014652447863089, + -3.369082406994758, -4.61381880997536, -4.55706599338291, + -3.5814225774035497, -4.577972678202224, -4.001728638829222, + -3.270401473211861, -3.264703452097223, -3.9718368746319084, + -3.132988733879366, -4.361423592613295, -2.595191993338583, + -4.516519898988561, -4.912100247864183, + }, + { + -3.9699474093476774, -4.189042372135887, -4.058989243887689, + -4.102030995146257, -4.171520021443684, -4.318254103615893, + -4.424253392850214, -4.758810531535327, -4.504029895277935, + -4.414714369803455, -3.0879080140350674, -5.469976217597951, + -3.790334046490602, -5.366435538657111, -3.235086137375257, + -5.727805326900051, -5.408282648592611, -4.971959552124542, + -5.070590155566169, -5.076706382583605, -6.181472536826093, + -5.921961341341008, -4.9999725883522155, -5.5070174892783, + -1.5568628976878147, -5.5070174892783, -6.110013572843948, + -4.0678979887767985, -5.089052218405905, -5.200643283814367, + -3.6661684098537215, -4.557328477002297, -5.479108701161223, + -5.159821289294111, -5.479108701161223, -5.616579691789827, + -3.7152580200502454, -4.23556238777078, -4.212031890360586, + -3.866007780968386, -4.0678979887767985, -4.4633463186414915, + -4.142178063159669, -4.318254103615893, -4.276053749125516, + -4.772293881872614, -4.332726136224427, -4.11133338780857, + -3.9089648990693253, -4.309670359924501, -3.9127889955077286, + -4.338574106106851, -4.528549512452254, -4.149433234040841, + -3.5292744136497762, -3.6009751629760713, -4.350373653038005, + -4.828122331425556, -4.047963773875981, -4.665125047458004, + -4.673288358097166, -4.633122316371831, + }, + { + -4.806719860900339, -3.6507473420444714, -4.429814962058902, + -4.347330952102998, -4.3949170222076255, -4.698366552912107, + -4.809448375553543, -4.35423944244681, -4.534137594904308, + -4.3611959922401695, -2.871768725634745, -4.598399529122678, + -5.564587232141456, -5.519124858064699, -2.4250566837898457, + -5.688201188108633, -5.967149580591659, -5.01834957015221, + -2.505498094634157, -5.3939617151106924, -6.3813483686685775, + -5.360223575478843, -5.821732580733155, -5.742268409378909, + -2.5427453130265225, -6.0299504818306895, -5.949907774157153, + -6.048642614842842, -6.106911522966818, -6.522426966928483, + -1.9368412502165815, -5.384205540165328, -3.2469989725553616, + -5.166904264475346, -4.662348253722951, -5.93295821584338, + -4.052787789271272, -3.8964417188805776, -4.725629703670472, + -3.994277013931218, -3.570836586604418, -4.883136091344702, + -4.20182336843176, -4.894970548991704, -4.1342203512338624, + -5.159122124033291, -4.442985425248647, -4.740819869164446, + -4.583031498894364, -4.589588899440523, -4.4058064220068935, + -4.87144005158151, -4.8541485544714496, -4.806719860900339, + -4.241282205172307, -4.937530163410501, -4.382360803432213, + -5.0116381355642226, -4.368201274828579, -4.782492565565015, + -4.544565218066568, -4.4563316672015425, + }}; + +constexpr auto kTokenMap = base::MakeFixedFlatMap( + {{'1', 1}, {'0', 0}, {'3', 3}, {'2', 2}, {'5', 5}, {'4', 4}, + {'7', 7}, {'6', 6}, {'9', 9}, {'8', 8}, {'A', 36}, {'C', 38}, + {'B', 37}, {'E', 40}, {'D', 39}, {'G', 42}, {'F', 41}, {'I', 44}, + {'H', 43}, {'K', 46}, {'J', 45}, {'M', 48}, {'L', 47}, {'O', 50}, + {'N', 49}, {'Q', 52}, {'P', 51}, {'S', 54}, {'R', 53}, {'U', 56}, + {'T', 55}, {'W', 58}, {'V', 57}, {'Y', 60}, {'X', 59}, {'Z', 61}, + {'a', 10}, {'c', 12}, {'b', 11}, {'e', 14}, {'d', 13}, {'g', 16}, + {'f', 15}, {'i', 18}, {'h', 17}, {'k', 20}, {'j', 19}, {'m', 22}, + {'l', 21}, {'o', 24}, {'n', 23}, {'q', 26}, {'p', 25}, {'s', 28}, + {'r', 27}, {'u', 30}, {'t', 29}, {'w', 32}, {'v', 31}, {'y', 34}, + {'x', 33}, {'z', 35}}); + +constexpr double kClassifierThreshold = 0.015; + +bool IsHashLikely(std::string value, double threshold_multiplier) { + TransformToAlphanumeric(value); + + double log_prob_sum = 0.0; + size_t add_count = 0; + for (size_t i = 0; i < value.length() - 1; i++) { + auto matrix_pos_a = kTokenMap.find(value[i]); + auto matrix_pos_b = kTokenMap.find(value[i + 1]); + if (matrix_pos_a == kTokenMap.end() || matrix_pos_b == kTokenMap.end()) { + continue; + } + + log_prob_sum += + kClassifierTransitionMatrix[matrix_pos_a->second][matrix_pos_b->second]; + add_count++; + } + + if (add_count == 0) { + return 1.0; + } + + double prob = std::exp(log_prob_sum / add_count); + return prob < (threshold_multiplier * kClassifierThreshold); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/hash_detection.h b/components/web_discovery/browser/hash_detection.h new file mode 100644 index 000000000000..4f5cd6975ba0 --- /dev/null +++ b/components/web_discovery/browser/hash_detection.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_HASH_DETECTION_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_HASH_DETECTION_H_ + +#include + +namespace web_discovery { + +bool IsHashLikely(std::string value, double probability_multiplier = 1.0); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_HASH_DETECTION_H_ diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index a07767c7aac6..78892accbbf8 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -32,6 +32,8 @@ constexpr char kFieldsKey[] = "fields"; constexpr char kPayloadsKey[] = "payloads"; constexpr char kJoinFieldAction[] = "join"; constexpr char kFunctionsAppliedKey[] = "functionsApplied"; +constexpr char kQueryTemplateKey[] = "queryTemplate"; +constexpr char kQueryTemplatePrefixKey[] = "prefix"; constexpr auto kScrapeRuleTypeMap = base::MakeFixedFlatMap({ @@ -191,10 +193,11 @@ std::optional> ParsePatternsURLDetails( auto* scrape_dict = root_dict->FindDict(kScrapeRulesKey); auto* payloads_dict = root_dict->FindDict(kPayloadsKey); auto* id_mapping_dict = root_dict->FindDict(kIdMappingKey); + auto* query_templates_dict = root_dict->FindDict(kQueryTemplateKey); if (!url_patterns_list || !search_engines_list || !scrape_dict || - !id_mapping_dict) { - VLOG(1) - << "Missing URL patterns, search engines, scrape rules or id mapping"; + !id_mapping_dict || query_templates_dict) { + VLOG(1) << "Missing URL patterns, search engines, scrape rules, id " + "mapping, or query templates"; return std::nullopt; } @@ -215,6 +218,7 @@ std::optional> ParsePatternsURLDetails( auto* id = id_mapping_dict->FindString(i_str); auto* scrape_url_dict = scrape_dict->FindDict(i_str); auto* payloads_url_dict = payloads_dict->FindDict(i_str); + auto* query_template_dict = query_templates_dict->FindDict(i_str); if (!id || !scrape_url_dict) { VLOG(1) << "ID or scrape dict missing for pattern"; return std::nullopt; @@ -238,6 +242,12 @@ std::optional> ParsePatternsURLDetails( } details.payload_rule_groups = std::move(*payload_rule_groups); } + if (query_template_dict) { + auto* prefix = query_template_dict->FindString(kQueryTemplatePrefixKey); + if (prefix) { + details.search_template_prefix = *prefix; + } + } } return result; diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index 3a2584eb38a6..e63aa1824afe 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -80,6 +80,7 @@ struct PatternsURLDetails { std::unique_ptr url_regex; bool is_search_engine; std::string id; + std::optional search_template_prefix; base::flat_map scrape_rule_groups; std::vector payload_rule_groups; }; diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index bcc551f4d20b..15c50a43efeb 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -7,11 +7,16 @@ #include +#include "brave/components/web_discovery/browser/privacy_guard.h" + namespace web_discovery { namespace { constexpr char kCountryCodeFieldName[] = "ctry"; +constexpr char kSearchResultKey[] = "r"; +constexpr char kSearchResultURLKey[] = "u"; +constexpr size_t kMinSearchResultSize = 4; bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); @@ -39,6 +44,27 @@ bool AggregatedDictHasContent(const base::Value::Dict& dict) { return false; } +bool IsPrivateResult(const PayloadRule& rule, + const PatternsURLDetails* matching_url_details, + const base::Value::Dict& dict) { + if (rule.key != kSearchResultKey) { + return false; + } + const auto* url = dict.FindString(kSearchResultURLKey); + if (!url) { + return false; + } + return IsPrivateURLLikely(GURL(*url), matching_url_details); +} + +bool ShouldDropSearchResultPayload(const PayloadRule& rule, + size_t result_size) { + if (rule.key != kSearchResultKey) { + return false; + } + return result_size < kMinSearchResultSize; +} + base::Value::Dict CreatePayloadDict(const PayloadRuleGroup& rule_group, base::Value::Dict inner_payload) { base::Value::Dict payload; @@ -47,8 +73,36 @@ base::Value::Dict CreatePayloadDict(const PayloadRuleGroup& rule_group, return payload; } +std::optional GenerateClusteredJoinedPayload( + const PayloadRule& rule, + const PatternsURLDetails* matching_url_details, + const std::vector& attribute_values) { + base::Value::Dict joined_data; + size_t counter = 0; + for (const auto& value : attribute_values) { + if (value.empty()) { + continue; + } + if (IsPrivateResult(rule, matching_url_details, value)) { + VLOG(1) << "Omitting private search result"; + continue; + } + joined_data.Set(base::NumberToString(counter++), value.Clone()); + } + if (!AggregatedDictHasContent(joined_data)) { + VLOG(1) << "Skipped joined clustered payload"; + return std::nullopt; + } + if (ShouldDropSearchResultPayload(rule, joined_data.size())) { + VLOG(1) << "Skipped search result payload due to too few results"; + return std::nullopt; + } + return base::Value(std::move(joined_data)); +} + std::optional GenerateClusteredPayload( const PayloadRuleGroup& rule_group, + const PatternsURLDetails* matching_url_details, const PageScrapeResult* scrape_result) { base::Value::Dict inner_payload; for (const auto& rule : rule_group.rules) { @@ -59,20 +113,12 @@ std::optional GenerateClusteredPayload( return std::nullopt; } if (rule.is_join) { - base::Value::Dict joined_data; - size_t counter = 0; - for (const auto& value : attribute_values_it->second) { - if (value.empty()) { - continue; - } - joined_data.Set(base::NumberToString(counter++), value.Clone()); - } - if (!AggregatedDictHasContent(joined_data)) { - VLOG(1) << "Skipped joined clustered payload, action = " - << rule_group.action; + auto joined_payload = GenerateClusteredJoinedPayload( + rule, matching_url_details, attribute_values_it->second); + if (!joined_payload) { return std::nullopt; } - payload_rule_data = base::Value(std::move(joined_data)); + payload_rule_data = std::move(*joined_payload); } else { const auto* value = attribute_values_it->second[0].FindString(rule.key); if (!value || value->empty()) { @@ -112,7 +158,8 @@ std::vector GeneratePayloads( for (const auto& rule_group : url_details->payload_rule_groups) { if (rule_group.rule_type == PayloadRuleType::kQuery && rule_group.result_type == PayloadResultType::kClustered) { - auto payload = GenerateClusteredPayload(rule_group, scrape_result.get()); + auto payload = GenerateClusteredPayload(rule_group, url_details, + scrape_result.get()); if (payload) { payloads.push_back(std::move(*payload)); } diff --git a/components/web_discovery/browser/privacy_guard.cc b/components/web_discovery/browser/privacy_guard.cc new file mode 100644 index 000000000000..2e3258a03a2f --- /dev/null +++ b/components/web_discovery/browser/privacy_guard.cc @@ -0,0 +1,279 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/privacy_guard.h" + +#include + +#include "base/logging.h" +#include "base/strings/strcat.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "brave/components/web_discovery/browser/hash_detection.h" +#include "brave/components/web_discovery/browser/util.h" +#include "third_party/re2/src/re2/re2.h" +#include "url/url_util.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kMaxSearchEngineRefLength = 8; +constexpr size_t kMaxQueryLength = 50; +constexpr size_t kMaxQueryNumberLength = 7; +constexpr size_t kMaxQuerySplitLength = 7; +constexpr size_t kMaxQueryWordLength = 20; +constexpr size_t kHashCheckMinimumLength = 13; +constexpr double kHashCheckThresholdMultiplier = 1.5; + +constexpr size_t kMaxQueryStringLength = 30; +constexpr size_t kMaxQueryStringParts = 4; +constexpr size_t kMaxQueryStringOrPathNumberLength = 12; +constexpr size_t kMaxPathPartLength = 18; +constexpr size_t kMinPathPartHashCheckLength = 13; +constexpr size_t kMinSegmentHashCheckLength = 16; + +constexpr size_t kMaxDotSplitDomainSize = 6; +constexpr size_t kMaxHyphenSplitDomainSize = 4; +constexpr size_t kMaxDomainNumberLength = 5; + +constexpr char kLongNumberRegexPrefix[] = "[0-9]{"; +constexpr char kLongNumberRegexSuffix[] = ",}"; +constexpr char kEmailRegex[] = + "[a-z0-9\\-_@]+(@|%40|%(25)+40)[a-z0-9\\-_]+\\.[a-z0-9\\-_]"; +constexpr char kHttpPasswordRegex[] = "[^:]+:[^@]+@"; +constexpr char kDefaultSearchPrefix[] = "search?q="; + +constexpr char kOnionSiteSuffix[] = ".onion"; +constexpr char kLocalDomainSuffix[] = ".local"; +constexpr char kLocalhost[] = "localhost"; + +constexpr std::array kPathAndQueryStringCheckRegexes = { + "(?i)\\/admin([\\/\\?#=]|$)", + "(?i)\\/wp-admin([\\/\\?#=]|$)", + "(?i)\\/edit([\\/\\?#=]|$)", + "(?i)[&\\?#\\/]share([\\/\\?#=]|$)", + "(?i)[&\\?#\\/;]sharing([\\/\\?#=]|$)", + "(?i)[&\\?#\\/;]logout([\\/\\?#=]|$)", + "(?i)WebLogic", + "(?i)[&\\?#\\/;]token([\\/\\?#=_;]|$)", + "(?i)[&\\?#\\/;]trk([\\/\\?#=_]|$)", + "[&\\?#\\/=;](http|https)(:\\/|\\%3A\\%2F)"}; + +constexpr std::array kQueryStringAndRefCheckRegexes = { + "(?i)[&\\?#_\\-;]user", "(?i)[&\\?#_\\-;]token", + "(?i)[&\\?#_\\-;]auth", "(?i)[&\\?#_\\-;]uid", + "(?i)[&\\?#_\\-;]email", "(?i)[&\\?#_\\-;]usr", + "(?i)[&\\?#_\\-;]pin", "(?i)[&\\?#_\\-;]pwd", + "(?i)[&\\?#_\\-;]password", "(?i)[&\\?#;]u[=#]", + "(?i)[&\\?#;]url[=#]", "(?i)[&\\?#_\\-;]http", + "(?i)[&\\?#_\\-;]ref[=#]", "(?i)[&\\?#_\\-;]red[=#]", + "(?i)[&\\?#_\\-;]trk", "(?i)[&\\?#_\\-;]track", + "(?i)[&\\?#_\\-;]shar", "(?i)[&\\?#_\\-;]login", + "(?i)[&\\?#_\\-;]logout", "(?i)[&\\?#_\\-;]session", +}; + +bool CheckForEmail(const std::string& str) { + re2::RE2 email_regex(kEmailRegex); + return re2::RE2::PartialMatch(str, email_regex); +} + +bool CheckForLongNumber(const std::string_view str, size_t max_length) { + auto regex_str = base::StrCat({kLongNumberRegexPrefix, + base::NumberToString(max_length + 1), + kLongNumberRegexSuffix}); + re2::RE2 long_number_regex(regex_str); + return re2::RE2::PartialMatch(str, long_number_regex); +} + +bool ContainsForbiddenKeywords(const GURL& url) { + auto path_and_query = + base::StrCat({url.path_piece(), "?", url.query_piece()}); + for (const auto& regex_str : kPathAndQueryStringCheckRegexes) { + re2::RE2 regex(regex_str); + if (re2::RE2::PartialMatch(path_and_query, regex)) { + return true; + } + } + for (const auto& regex_str : kQueryStringAndRefCheckRegexes) { + re2::RE2 regex(regex_str); + if (!url.ref_piece().empty() && + re2::RE2::PartialMatch("#" + url.ref(), regex)) { + return true; + } + if (!url.query_piece().empty() && + re2::RE2::PartialMatch("?" + url.query(), regex)) { + return true; + } + } + return false; +} + +bool IsPrivateDomainLikely(const std::string_view host) { + auto dot_split = + base::SplitString(host, ".", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL); + if (dot_split.size() > kMaxDotSplitDomainSize) { + return true; + } + if (CheckForLongNumber(host, kMaxDomainNumberLength)) { + return true; + } + auto hyphen_split = + base::SplitString(host, ".", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL); + if (hyphen_split.size() > kMaxHyphenSplitDomainSize) { + return true; + } + return false; +} + +} // namespace + +bool IsPrivateURLLikely(const GURL& url, + const PatternsURLDetails* matching_url_details) { + if (!url.SchemeIs("https")) { + VLOG(1) << "Ignoring URL due to non-HTTPS scheme"; + return true; + } + if (url.HostIsIPAddress()) { + VLOG(1) << "Ignoring URL due to IP address host"; + return true; + } + if (url.has_username() || url.has_password()) { + VLOG(1) << "Ignoring URL due to inclusion of credentials"; + return true; + } + if (url.has_port() && url.port_piece() != "443") { + VLOG(1) << "Ignoring URL due to non-standard port"; + return true; + } + if (matching_url_details && matching_url_details->is_search_engine) { + if (url.has_ref() && url.ref_piece().length() > kMaxSearchEngineRefLength) { + VLOG(1) << "Ignoring search engine URL due to long ref"; + return true; + } + } + auto host_piece = url.host_piece(); + if (host_piece.ends_with(kOnionSiteSuffix) || + host_piece.ends_with(kLocalDomainSuffix) || host_piece == kLocalhost) { + VLOG(1) << "Ignoring URL due a local host or onion site"; + return true; + } + if (IsPrivateDomainLikely(url.host_piece())) { + VLOG(1) << "Ignoring URL due likely private domain"; + return true; + } + return false; +} + +bool IsPrivateQueryLikely(const std::string& query) { + if (query.length() > kMaxQueryLength) { + VLOG(1) << "Ignoring query due to long length"; + return true; + } + auto split = + base::SplitString(query, " ", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + if (split.size() > kMaxQuerySplitLength) { + VLOG(1) << "Ignoring query due to long split length"; + return true; + } + if (CheckForLongNumber(query, kMaxQueryNumberLength)) { + VLOG(1) << "Ignoring query due to long number"; + return true; + } + if (CheckForEmail(query)) { + VLOG(1) << "Ignoring query due to inclusion of email"; + return true; + } + re2::RE2 http_pwd_regex(kHttpPasswordRegex); + if (re2::RE2::PartialMatch(query, http_pwd_regex)) { + VLOG(1) << "Ignoring query due to potential inclusion of HTTP credentials"; + return true; + } + for (const auto& word : split) { + if (word.length() > kMaxQueryWordLength) { + VLOG(1) << "Ignoring query due to long word"; + return true; + } + } + if (query.length() >= kHashCheckMinimumLength) { + if (IsHashLikely(query, kHashCheckThresholdMultiplier)) { + VLOG(1) << "Ignoring query due to potential inclusion of hash"; + return true; + } + } + return false; +} + +GURL GeneratePrivateSearchURL(const GURL& original_url, + const std::string& query, + const PatternsURLDetails& matching_url_details) { + url::RawCanonOutputT query_encoded; + url::EncodeURIComponent(query, &query_encoded); + std::string query_encoded_str(query_encoded.view()); + base::ReplaceSubstringsAfterOffset(&query_encoded_str, 0, "%20", "+"); + + return GURL( + base::StrCat({original_url.scheme(), url::kStandardSchemeSeparator, + original_url.host(), "/", + matching_url_details.search_template_prefix.value_or( + kDefaultSearchPrefix), + query_encoded_str})); +} + +bool ShouldDropLongURL(const GURL& url) { + if (CheckForEmail(url.spec())) { + return true; + } + if (!url.query_piece().empty()) { + if (url.query_piece().size() > kMaxQueryStringLength) { + return true; + } + auto query_parts = base::SplitString( + url.query_piece(), "&;", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SplitResult::SPLIT_WANT_ALL); + if (query_parts.size() > kMaxQueryStringParts) { + return true; + } + if (CheckForLongNumber(url.query_piece(), + kMaxQueryStringOrPathNumberLength)) { + return true; + } + } + if (!url.path_piece().empty()) { + if (CheckForLongNumber(url.path_piece(), + kMaxQueryStringOrPathNumberLength)) { + return true; + } + } + auto path_parts = base::SplitString(url.path_piece(), "/._ -:+;", + base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL); + for (const auto& path_part : path_parts) { + if (path_part.length() > kMaxPathPartLength) { + return true; + } + if (path_part.length() >= kMinPathPartHashCheckLength && + IsHashLikely(path_part)) { + return true; + } + } + auto path_segments = base::SplitString( + url.path_piece(), "/", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL); + for (const auto& path_segment : path_segments) { + std::string alphanumeric_path_segment = path_segment; + TransformToAlphanumeric(alphanumeric_path_segment); + if (alphanumeric_path_segment.length() >= kMinSegmentHashCheckLength && + IsHashLikely(alphanumeric_path_segment)) { + return true; + } + } + return ContainsForbiddenKeywords(url); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/privacy_guard.h b/components/web_discovery/browser/privacy_guard.h new file mode 100644 index 000000000000..9fbdbf210045 --- /dev/null +++ b/components/web_discovery/browser/privacy_guard.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PRIVACY_GUARD_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PRIVACY_GUARD_H_ + +#include + +#include "brave/components/web_discovery/browser/patterns.h" +#include "url/gurl.h" + +namespace web_discovery { + +bool IsPrivateURLLikely(const GURL& url, + const PatternsURLDetails* matching_url_details); + +bool IsPrivateQueryLikely(const std::string& query); + +GURL GeneratePrivateSearchURL(const GURL& original_url, + const std::string& query, + const PatternsURLDetails& matching_url_details); + +bool ShouldDropLongURL(const GURL& url); + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PRIVACY_GUARD_H_ diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index cade1d545664..b4ad0aeee0dc 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -179,7 +179,7 @@ void Reporter::PrepareRequest(const base::Value& request_data) { credential_manager_->Sign( std::vector(payload_hash.begin(), payload_hash.end()), basename_result->basename, - base::BindOnce(&Reporter::OnRequestSigned, weak_ptr_factory_.GetWeakPtr(), + base::BindOnce(&Reporter::OnRequestSigned, base::Unretained(this), final_payload_json, basename_result->count_tag_hash, basename_result->count)); } diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 7fc2298603c0..7512b6833da9 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -7,6 +7,7 @@ #include "base/strings/stringprintf.h" #include "brave/brave_domains/service_domains.h" +#include "third_party/re2/src/re2/re2.h" namespace web_discovery { @@ -15,6 +16,7 @@ constexpr char kCollectorHostPrefix[] = "collector.wdp"; constexpr char kQuorumHostPrefix[] = "quorum.wdp"; constexpr char kPatternsHostPrefix[] = "patterns.wdp"; constexpr char kPatternsPath[] = "/patterns.gz"; +constexpr char kNotAlphanumericRegex[] = "[^A-Za-z0-9]"; } // namespace std::string GetCollectorHost() { @@ -51,4 +53,9 @@ std::string FormatServerDate(const base::Time& date) { exploded.day_of_month); } +void TransformToAlphanumeric(std::string& value) { + re2::RE2 cleaning_regex(kNotAlphanumericRegex); + re2::RE2::GlobalReplace(&value, cleaning_regex, ""); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index 0bab17248a47..302a01774327 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -38,6 +38,8 @@ std::unique_ptr CreateResourceRequest(GURL url); std::string FormatServerDate(const base::Time& date); +void TransformToAlphanumeric(std::string& value); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index e153a6b2a934..c7bea6dd6662 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -12,6 +12,7 @@ #include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/payload_generator.h" #include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/privacy_guard.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -123,6 +124,14 @@ void WDPService::OnFinishNavigation( if (!content_scraper_) { return; } + const auto* matching_url_details = + last_loaded_patterns_->GetMatchingURLPattern(url, false); + if (!matching_url_details) { + return; + } + if (IsPrivateURLLikely(url, matching_url_details)) { + return; + } mojo::Remote remote; render_frame_host->GetRemoteInterfaces()->GetInterface( remote.BindNewPipeAndPassReceiver()); @@ -143,15 +152,21 @@ void WDPService::OnContentScraped(bool is_strict, if (!url_details) { return; } - if (!is_strict) { - double_fetcher_->ScheduleDoubleFetch(result->url, - result->SerializeToValue()); - } else { - auto payloads = GeneratePayloads(*last_loaded_server_config_, url_details, - std::move(result)); - for (auto& payload : payloads) { - reporter_->ScheduleSend(std::move(payload)); + if (!is_strict && url_details->is_search_engine) { + auto url = result->url; + if (!result->query) { + return; + } + if (IsPrivateQueryLikely(*result->query)) { + return; } + url = GeneratePrivateSearchURL(url, *result->query, *url_details); + double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); + } + auto payloads = GeneratePayloads(*last_loaded_server_config_, url_details, + std::move(result)); + for (auto& payload : payloads) { + reporter_->ScheduleSend(std::move(payload)); } } From e61b4e6ce3066fc5bc41babe28df3d43bfff5cdd Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 12 Jun 2024 11:50:58 -0700 Subject: [PATCH 17/36] Fix misc Web Discovery bugs, add URL masking refine function --- .../web_discovery/browser/content_scraper.cc | 44 ++++++++++++------ .../web_discovery/browser/content_scraper.h | 3 +- .../web_discovery/browser/double_fetcher.cc | 13 +++--- .../web_discovery/browser/double_fetcher.h | 5 ++- components/web_discovery/browser/patterns.cc | 14 +++--- .../browser/payload_generator.cc | 7 ++- .../web_discovery/browser/privacy_guard.cc | 45 +++++++++++++++++++ .../web_discovery/browser/privacy_guard.h | 2 + .../web_discovery/browser/wdp_service.cc | 39 +++++++++------- .../web_discovery/browser/wdp_service.h | 3 +- 10 files changed, 130 insertions(+), 45 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 1c629486ea15..8e77ccfa7d9b 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/privacy_guard.h" #include "url/url_util.h" namespace web_discovery { @@ -25,6 +26,7 @@ constexpr char kIdValueKey[] = "id"; constexpr char kUrlValueKey[] = "url"; constexpr char kRefineSplitFuncId[] = "splitF"; +constexpr char kRefineMaskURLFuncId[] = "maskU"; std::string RefineSplit(const std::string& value, const std::string& delimiter, @@ -44,31 +46,41 @@ std::string RefineSplit(const std::string& value, return base::UTF16ToUTF8(result.view()); } -std::string ExecuteRefineFunctions(const RefineFunctionList& function_list, - const std::string& value) { - std::string result = value; +std::optional ExecuteRefineFunctions( + const RefineFunctionList& function_list, + const std::string& value) { + std::optional result = value; for (const auto& function_args : function_list) { if (function_args.empty()) { continue; } - if (function_args[0] == kRefineSplitFuncId) { + const auto& func_name = function_args[0]; + if (func_name == kRefineSplitFuncId) { if (function_args.size() >= 3 && function_args[1].is_string() && function_args[2].is_int()) { - result = RefineSplit(result, function_args[1].GetString(), + result = RefineSplit(*result, function_args[1].GetString(), function_args[2].GetInt()); } + } else if (func_name == kRefineMaskURLFuncId) { + result = MaskURL(GURL(value)); + } + if (!result) { + break; } } return result; } void MaybeSetQueryInResult(const ScrapeRule& rule, - const std::string& value, + const std::optional& value, PageScrapeResult* result) { if (rule.rule_type != ScrapeRuleType::kSearchQuery && rule.rule_type != ScrapeRuleType::kWidgetTitle) { return; } + if (!value) { + return; + } result->query = value; } @@ -179,12 +191,13 @@ void ContentScraper::ScrapePage(const GURL& url, } void ContentScraper::ParseAndScrapePage( + const GURL& url, bool is_strict_scrape, std::unique_ptr prev_result, std::string html, PageScrapeResultCallback callback) { const auto* url_details = - (*patterns_)->GetMatchingURLPattern(prev_result->url, is_strict_scrape); + (*patterns_)->GetMatchingURLPattern(url, is_strict_scrape); if (!url_details) { return; } @@ -196,7 +209,7 @@ void ContentScraper::ParseAndScrapePage( select_request.root_selector = selector; for (const auto& [report_key, rule] : group) { if (rule->rule_type == ScrapeRuleType::kStandard) { - ProcessStandardRule(report_key, *rule, selector, interim_result->url, + ProcessStandardRule(report_key, *rule, selector, url, interim_result.get()); continue; } @@ -259,11 +272,13 @@ void ContentScraper::OnScrapedElementAttributes( } base::Value value; if (value_str) { - std::string final_value_str = + auto final_value_str = ExecuteRefineFunctions(rule->second->functions_applied, *value_str); MaybeSetQueryInResult(*rule->second, final_value_str, scrape_result.get()); - value = base::Value(final_value_str); + if (final_value_str) { + value = base::Value(*final_value_str); + } } attribute_values.Set(key, std::move(value)); } @@ -298,10 +313,13 @@ void ContentScraper::OnRustElementAttributes( } base::Value value; if (!pair.value.empty()) { - std::string value_str = ExecuteRefineFunctions( + auto final_value_str = ExecuteRefineFunctions( rule->second->functions_applied, std::string(pair.value)); - MaybeSetQueryInResult(*rule->second, value_str, scrape_result.get()); - value = base::Value(value_str); + MaybeSetQueryInResult(*rule->second, final_value_str, + scrape_result.get()); + if (final_value_str) { + value = base::Value(*final_value_str); + } } attribute_values.Set(key_str, std::move(value)); } diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index 6719d89d7ce8..ac72cfc4d396 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -58,7 +58,8 @@ class ContentScraper { mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback); // For subsequent double fetches after initial scrape - void ParseAndScrapePage(bool is_strict_scrape, + void ParseAndScrapePage(const GURL& url, + bool is_strict_scrape, std::unique_ptr prev_result, std::string html, PageScrapeResultCallback callback); diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index fae3f6f8b78f..3dc902a50d25 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -81,22 +81,25 @@ void DoubleFetcher::ScheduleDoubleFetch(const GURL& url, void DoubleFetcher::OnFetchTimer(const base::Value& request_data) { const auto* fetch_dict = request_data.GetIfDict(); - const auto* url = fetch_dict ? fetch_dict->FindString(kUrlKey) : nullptr; - if (!url) { + const auto* url_str = fetch_dict ? fetch_dict->FindString(kUrlKey) : nullptr; + if (!url_str) { request_queue_.NotifyRequestComplete(true); return; } - auto resource_request = CreateResourceRequest(GURL(*url)); + GURL url(*url_str); + auto resource_request = CreateResourceRequest(url); url_loader_ = network::SimpleURLLoader::Create( std::move(resource_request), kFetchNetworkTrafficAnnotation); url_loader_->DownloadToString( shared_url_loader_factory_.get(), - base::BindOnce(&DoubleFetcher::OnRequestComplete, base::Unretained(this)), + base::BindOnce(&DoubleFetcher::OnRequestComplete, base::Unretained(this), + url), kMaxDoubleFetchResponseSize); } void DoubleFetcher::OnRequestComplete( + GURL url, std::optional response_body) { auto result = ProcessCompletedRequest(&response_body); @@ -106,7 +109,7 @@ void DoubleFetcher::OnRequestComplete( const auto& request_dict = request_data->GetDict(); const auto* assoc_data = request_dict.Find(kAssociatedDataKey); if (assoc_data) { - callback_.Run(*assoc_data, response_body); + callback_.Run(url, *assoc_data, response_body); } } } diff --git a/components/web_discovery/browser/double_fetcher.h b/components/web_discovery/browser/double_fetcher.h index f24f7e001805..08f5e05bd480 100644 --- a/components/web_discovery/browser/double_fetcher.h +++ b/components/web_discovery/browser/double_fetcher.h @@ -27,7 +27,8 @@ namespace web_discovery { class DoubleFetcher { public: using FetchedCallback = - base::RepeatingCallback response_body)>; DoubleFetcher(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, @@ -41,7 +42,7 @@ class DoubleFetcher { private: void OnFetchTimer(const base::Value& request_data); - void OnRequestComplete(std::optional response_body); + void OnRequestComplete(GURL url, std::optional response_body); bool ProcessCompletedRequest(std::optional* response_body); raw_ptr profile_prefs_; diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index 78892accbbf8..e7b747168b88 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -195,7 +195,7 @@ std::optional> ParsePatternsURLDetails( auto* id_mapping_dict = root_dict->FindDict(kIdMappingKey); auto* query_templates_dict = root_dict->FindDict(kQueryTemplateKey); if (!url_patterns_list || !search_engines_list || !scrape_dict || - !id_mapping_dict || query_templates_dict) { + !id_mapping_dict) { VLOG(1) << "Missing URL patterns, search engines, scrape rules, id " "mapping, or query templates"; return std::nullopt; @@ -218,7 +218,6 @@ std::optional> ParsePatternsURLDetails( auto* id = id_mapping_dict->FindString(i_str); auto* scrape_url_dict = scrape_dict->FindDict(i_str); auto* payloads_url_dict = payloads_dict->FindDict(i_str); - auto* query_template_dict = query_templates_dict->FindDict(i_str); if (!id || !scrape_url_dict) { VLOG(1) << "ID or scrape dict missing for pattern"; return std::nullopt; @@ -242,10 +241,13 @@ std::optional> ParsePatternsURLDetails( } details.payload_rule_groups = std::move(*payload_rule_groups); } - if (query_template_dict) { - auto* prefix = query_template_dict->FindString(kQueryTemplatePrefixKey); - if (prefix) { - details.search_template_prefix = *prefix; + if (query_templates_dict) { + auto* query_template_dict = query_templates_dict->FindDict(i_str); + if (query_template_dict) { + auto* prefix = query_template_dict->FindString(kQueryTemplatePrefixKey); + if (prefix) { + details.search_template_prefix = *prefix; + } } } } diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index 15c50a43efeb..3a3df4b813f3 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -90,7 +90,7 @@ std::optional GenerateClusteredJoinedPayload( joined_data.Set(base::NumberToString(counter++), value.Clone()); } if (!AggregatedDictHasContent(joined_data)) { - VLOG(1) << "Skipped joined clustered payload"; + VLOG(1) << "Skipped joined clustered payload due to lack of content"; return std::nullopt; } if (ShouldDropSearchResultPayload(rule, joined_data.size())) { @@ -110,12 +110,17 @@ std::optional GenerateClusteredPayload( auto attribute_values_it = scrape_result->fields.find(rule.selector); if (attribute_values_it == scrape_result->fields.end() || attribute_values_it->second.empty()) { + VLOG(1) << "Skipped clustered payload due to no values for root " + "selector, action = " + << rule_group.action; return std::nullopt; } if (rule.is_join) { auto joined_payload = GenerateClusteredJoinedPayload( rule, matching_url_details, attribute_values_it->second); if (!joined_payload) { + VLOG(1) << "Skipped joined clustered payload, action = " + << rule_group.action; return std::nullopt; } payload_rule_data = std::move(*joined_payload); diff --git a/components/web_discovery/browser/privacy_guard.cc b/components/web_discovery/browser/privacy_guard.cc index 2e3258a03a2f..b5c2e6bfede2 100644 --- a/components/web_discovery/browser/privacy_guard.cc +++ b/components/web_discovery/browser/privacy_guard.cc @@ -11,9 +11,12 @@ #include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "brave/components/web_discovery/browser/hash_detection.h" #include "brave/components/web_discovery/browser/util.h" #include "third_party/re2/src/re2/re2.h" +#include "url/third_party/mozilla/url_parse.h" +#include "url/url_constants.h" #include "url/url_util.h" namespace web_discovery { @@ -50,6 +53,10 @@ constexpr char kOnionSiteSuffix[] = ".onion"; constexpr char kLocalDomainSuffix[] = ".local"; constexpr char kLocalhost[] = "localhost"; +constexpr char kGoogleHostSubstring[] = "google"; +constexpr char kGoogleURLQueryParam[] = "url"; +constexpr char kMaskedURLSuffix[] = "/ (PROTECTED)"; + constexpr std::array kPathAndQueryStringCheckRegexes = { "(?i)\\/admin([\\/\\?#=]|$)", "(?i)\\/wp-admin([\\/\\?#=]|$)", @@ -276,4 +283,42 @@ bool ShouldDropLongURL(const GURL& url) { return ContainsForbiddenKeywords(url); } +std::optional MaskURL(const GURL& url) { + if (!url.SchemeIsHTTPOrHTTPS() || !url.is_valid()) { + return std::nullopt; + } + + if (!ShouldDropLongURL(url)) { + return url.spec(); + } + + if (url.host_piece().find(kGoogleHostSubstring) != std::string::npos && + url.has_query()) { + auto query_piece = url.query_piece(); + url::Component query_slice(0, query_piece.size()); + url::Component key_slice; + url::Component value_slice; + while (url::ExtractQueryKeyValue(query_piece, &query_slice, &key_slice, + &value_slice)) { + if (query_piece.substr(key_slice.begin, key_slice.len) != + kGoogleURLQueryParam) { + continue; + } + url::RawCanonOutputT decoded_embedded_url_str; + url::DecodeURLEscapeSequences( + query_piece.substr(value_slice.begin, value_slice.len), + url::DecodeURLMode::kUTF8OrIsomorphic, &decoded_embedded_url_str); + GURL decoded_embedded_url( + base::UTF16ToUTF8(decoded_embedded_url_str.view())); + if (!decoded_embedded_url.is_valid()) { + return std::nullopt; + } + return MaskURL(decoded_embedded_url); + } + } + + return base::StrCat({url.scheme(), url::kStandardSchemeSeparator, url.host(), + kMaskedURLSuffix}); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/privacy_guard.h b/components/web_discovery/browser/privacy_guard.h index 9fbdbf210045..75430efa82b4 100644 --- a/components/web_discovery/browser/privacy_guard.h +++ b/components/web_discovery/browser/privacy_guard.h @@ -24,6 +24,8 @@ GURL GeneratePrivateSearchURL(const GURL& original_url, bool ShouldDropLongURL(const GURL& url); +std::optional MaskURL(const GURL& url); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PRIVACY_GUARD_H_ diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index c7bea6dd6662..e61de3b6c398 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -103,7 +103,8 @@ void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { credential_manager_.get(), &last_loaded_server_config_); } -void WDPService::OnDoubleFetched(const base::Value& associated_data, +void WDPService::OnDoubleFetched(const GURL& url, + const base::Value& associated_data, std::optional response_body) { if (!response_body) { return; @@ -113,7 +114,7 @@ void WDPService::OnDoubleFetched(const base::Value& associated_data, return; } content_scraper_->ParseAndScrapePage( - true, std::move(prev_scrape_result), *response_body, + url, true, std::move(prev_scrape_result), *response_body, base::BindOnce(&WDPService::OnContentScraped, base::Unretained(this), true)); } @@ -129,6 +130,7 @@ void WDPService::OnFinishNavigation( if (!matching_url_details) { return; } + VLOG(1) << "URL matched pattern " << matching_url_details->id << ": " << url; if (IsPrivateURLLikely(url, matching_url_details)) { return; } @@ -147,24 +149,29 @@ void WDPService::OnContentScraped(bool is_strict, if (!result) { return; } - auto* url_details = - last_loaded_patterns_->GetMatchingURLPattern(result->url, true); - if (!url_details) { + auto* original_url_details = + last_loaded_patterns_->GetMatchingURLPattern(result->url, is_strict); + if (!original_url_details) { return; } - if (!is_strict && url_details->is_search_engine) { - auto url = result->url; - if (!result->query) { - return; + if (!is_strict && original_url_details->is_search_engine) { + auto* strict_url_details = + last_loaded_patterns_->GetMatchingURLPattern(result->url, true); + if (strict_url_details) { + auto url = result->url; + if (!result->query) { + return; + } + if (IsPrivateQueryLikely(*result->query)) { + return; + } + url = GeneratePrivateSearchURL(url, *result->query, *strict_url_details); + VLOG(1) << "Double fetching search page: " << url; + double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); } - if (IsPrivateQueryLikely(*result->query)) { - return; - } - url = GeneratePrivateSearchURL(url, *result->query, *url_details); - double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); } - auto payloads = GeneratePayloads(*last_loaded_server_config_, url_details, - std::move(result)); + auto payloads = GeneratePayloads(*last_loaded_server_config_, + original_url_details, std::move(result)); for (auto& payload : payloads) { reporter_->ScheduleSend(std::move(payload)); } diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 1206a06fc45f..84c12f5882a2 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -63,7 +63,8 @@ class WDPService : public KeyedService { void OnPatternsLoaded(std::unique_ptr patterns); void OnContentScraped(bool is_strict, std::unique_ptr result); - void OnDoubleFetched(const base::Value& associated_data, + void OnDoubleFetched(const GURL& url, + const base::Value& associated_data, std::optional response_body); raw_ptr local_state_; From 60a2b780ba72fab991f9c2bbac0e1bd3d0b5c338 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 12 Jun 2024 13:15:06 -0700 Subject: [PATCH 18/36] Add Web Discovery refine functions --- .../web_discovery/browser/content_scraper.cc | 80 ++++++++++++++++--- .../web_discovery/browser/privacy_guard.cc | 21 +---- components/web_discovery/browser/util.cc | 26 ++++++ components/web_discovery/browser/util.h | 7 ++ 4 files changed, 106 insertions(+), 28 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 8e77ccfa7d9b..4622b081489d 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -7,13 +7,14 @@ #include +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/ranges/algorithm.h" #include "base/strings/string_split.h" -#include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/privacy_guard.h" -#include "url/url_util.h" +#include "brave/components/web_discovery/browser/util.h" namespace web_discovery { @@ -27,6 +28,10 @@ constexpr char kUrlValueKey[] = "url"; constexpr char kRefineSplitFuncId[] = "splitF"; constexpr char kRefineMaskURLFuncId[] = "maskU"; +constexpr char kRefineParseURLFuncId[] = "parseU"; +constexpr char kRefineJsonExtractFuncId[] = "json"; + +constexpr char kParseURLQueryExtractType[] = "qs"; std::string RefineSplit(const std::string& value, const std::string& delimiter, @@ -40,10 +45,45 @@ std::string RefineSplit(const std::string& value, } else { encoded_result = split[index]; } - url::RawCanonOutputT result; - url::DecodeURLEscapeSequences(encoded_result, - url::DecodeURLMode::kUTF8OrIsomorphic, &result); - return base::UTF16ToUTF8(result.view()); + return DecodeURLComponent(encoded_result); +} + +std::optional RefineParseURL(const std::string& value, + const std::string& extract_type, + const std::string& key) { + if (extract_type != kParseURLQueryExtractType) { + return std::nullopt; + } + GURL url(value); + if (!url.is_valid() || !url.has_query()) { + return std::nullopt; + } + auto query_value = ExtractValueFromQueryString(url.query_piece(), key); + return query_value; +} + +std::optional RefineJsonExtract(const std::string& value, + const std::string& path, + bool extract_objects) { + auto parsed = base::JSONReader::Read(value); + if (!parsed || !parsed->is_dict()) { + return std::nullopt; + } + const auto* found_value = parsed->GetDict().FindByDottedPath(path); + if (!found_value) { + return std::nullopt; + } + if (found_value->is_string()) { + return found_value->GetString(); + } + if ((found_value->is_dict() || found_value->is_list()) && !extract_objects) { + return std::nullopt; + } + std::string encoded_value; + if (!base::JSONWriter::Write(*found_value, &encoded_value)) { + return std::nullopt; + } + return encoded_value; } std::optional ExecuteRefineFunctions( @@ -63,6 +103,18 @@ std::optional ExecuteRefineFunctions( } } else if (func_name == kRefineMaskURLFuncId) { result = MaskURL(GURL(value)); + } else if (func_name == kRefineParseURLFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_string()) { + result = RefineParseURL(*result, function_args[1].GetString(), + function_args[2].GetString()); + } + } else if (func_name == kRefineJsonExtractFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_bool()) { + result = RefineJsonExtract(*result, function_args[1].GetString(), + function_args[2].GetBool()); + } } if (!result) { break; @@ -237,15 +289,21 @@ void ContentScraper::ProcessStandardRule(const std::string& report_key, const std::string& root_selector, const GURL& url, PageScrapeResult* scrape_result) { + std::string value; + if (rule.attribute == kUrlAttrId) { + value = url.spec(); + } else if (rule.attribute == kCountryCodeAttrId) { + value = (*last_loaded_server_config_)->location; + } + auto refined_value = ExecuteRefineFunctions(rule.functions_applied, value); + if (!refined_value) { + return; + } auto& fields = scrape_result->fields[root_selector]; if (fields.empty()) { fields.emplace_back(); } - if (rule.attribute == kUrlAttrId) { - fields[0].Set(report_key, url.spec()); - } else if (rule.attribute == kCountryCodeAttrId) { - fields[0].Set(report_key, (*last_loaded_server_config_)->location); - } + fields[0].Set(report_key, *refined_value); } void ContentScraper::OnScrapedElementAttributes( diff --git a/components/web_discovery/browser/privacy_guard.cc b/components/web_discovery/browser/privacy_guard.cc index b5c2e6bfede2..28b590aed93b 100644 --- a/components/web_discovery/browser/privacy_guard.cc +++ b/components/web_discovery/browser/privacy_guard.cc @@ -11,7 +11,6 @@ #include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "brave/components/web_discovery/browser/hash_detection.h" #include "brave/components/web_discovery/browser/util.h" #include "third_party/re2/src/re2/re2.h" @@ -294,22 +293,10 @@ std::optional MaskURL(const GURL& url) { if (url.host_piece().find(kGoogleHostSubstring) != std::string::npos && url.has_query()) { - auto query_piece = url.query_piece(); - url::Component query_slice(0, query_piece.size()); - url::Component key_slice; - url::Component value_slice; - while (url::ExtractQueryKeyValue(query_piece, &query_slice, &key_slice, - &value_slice)) { - if (query_piece.substr(key_slice.begin, key_slice.len) != - kGoogleURLQueryParam) { - continue; - } - url::RawCanonOutputT decoded_embedded_url_str; - url::DecodeURLEscapeSequences( - query_piece.substr(value_slice.begin, value_slice.len), - url::DecodeURLMode::kUTF8OrIsomorphic, &decoded_embedded_url_str); - GURL decoded_embedded_url( - base::UTF16ToUTF8(decoded_embedded_url_str.view())); + auto google_url_param = + ExtractValueFromQueryString(url.query_piece(), kGoogleURLQueryParam); + if (google_url_param) { + GURL decoded_embedded_url(*google_url_param); if (!decoded_embedded_url.is_valid()) { return std::nullopt; } diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 7512b6833da9..1e6dc331e509 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -6,8 +6,10 @@ #include "brave/components/web_discovery/browser/util.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "brave/brave_domains/service_domains.h" #include "third_party/re2/src/re2/re2.h" +#include "url/url_util.h" namespace web_discovery { @@ -58,4 +60,28 @@ void TransformToAlphanumeric(std::string& value) { re2::RE2::GlobalReplace(&value, cleaning_regex, ""); } +std::string DecodeURLComponent(const std::string_view value) { + url::RawCanonOutputT result; + url::DecodeURLEscapeSequences(value, url::DecodeURLMode::kUTF8OrIsomorphic, + &result); + return base::UTF16ToUTF8(result.view()); +} + +std::optional ExtractValueFromQueryString( + const std::string_view query_string, + const std::string_view key) { + url::Component query_slice(0, query_string.length()); + url::Component key_slice; + url::Component value_slice; + while (url::ExtractQueryKeyValue(query_string, &query_slice, &key_slice, + &value_slice)) { + if (query_string.substr(key_slice.begin, key_slice.len) != key) { + continue; + } + return DecodeURLComponent( + query_string.substr(value_slice.begin, value_slice.len)); + } + return std::nullopt; +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index 302a01774327..3aaa4e84b277 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -7,6 +7,7 @@ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ #include +#include #include #include "base/time/time.h" @@ -40,6 +41,12 @@ std::string FormatServerDate(const base::Time& date); void TransformToAlphanumeric(std::string& value); +std::string DecodeURLComponent(const std::string_view value); + +std::optional ExtractValueFromQueryString( + const std::string_view query_string, + const std::string_view key); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_UTIL_H_ From 49f7c850c8607743ff82c5b7abd52761e0801c9d Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 12 Jun 2024 20:04:24 -0700 Subject: [PATCH 19/36] Cache Web Discovery regexes --- components/web_discovery/browser/BUILD.gn | 2 + .../web_discovery/browser/content_scraper.cc | 158 +++++++++--------- .../web_discovery/browser/content_scraper.h | 14 +- .../browser/credential_manager.cc | 2 +- .../web_discovery/browser/hash_detection.cc | 6 +- .../web_discovery/browser/hash_detection.h | 6 +- .../browser/payload_generator.cc | 16 +- .../web_discovery/browser/payload_generator.h | 2 + .../web_discovery/browser/privacy_guard.cc | 120 ++++--------- .../web_discovery/browser/privacy_guard.h | 10 +- .../web_discovery/browser/regex_util.cc | 121 ++++++++++++++ components/web_discovery/browser/regex_util.h | 48 ++++++ components/web_discovery/browser/reporter.cc | 9 +- components/web_discovery/browser/reporter.h | 3 + .../browser/server_config_loader.cc | 2 +- .../browser/signature_basename.cc | 10 +- .../browser/signature_basename.h | 2 + components/web_discovery/browser/util.cc | 14 +- components/web_discovery/browser/util.h | 5 +- .../web_discovery/browser/wdp_service.cc | 10 +- .../web_discovery/browser/wdp_service.h | 3 + 21 files changed, 353 insertions(+), 210 deletions(-) create mode 100644 components/web_discovery/browser/regex_util.cc create mode 100644 components/web_discovery/browser/regex_util.h diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index f27717c71c7f..711e1f8530f5 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -22,6 +22,8 @@ static_library("browser") { "pref_names.h", "privacy_guard.cc", "privacy_guard.h", + "regex_util.cc", + "regex_util.h", "reporter.cc", "reporter.h", "request_queue.cc", diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 4622b081489d..87154b57123a 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -86,56 +86,6 @@ std::optional RefineJsonExtract(const std::string& value, return encoded_value; } -std::optional ExecuteRefineFunctions( - const RefineFunctionList& function_list, - const std::string& value) { - std::optional result = value; - for (const auto& function_args : function_list) { - if (function_args.empty()) { - continue; - } - const auto& func_name = function_args[0]; - if (func_name == kRefineSplitFuncId) { - if (function_args.size() >= 3 && function_args[1].is_string() && - function_args[2].is_int()) { - result = RefineSplit(*result, function_args[1].GetString(), - function_args[2].GetInt()); - } - } else if (func_name == kRefineMaskURLFuncId) { - result = MaskURL(GURL(value)); - } else if (func_name == kRefineParseURLFuncId) { - if (function_args.size() >= 3 && function_args[1].is_string() && - function_args[2].is_string()) { - result = RefineParseURL(*result, function_args[1].GetString(), - function_args[2].GetString()); - } - } else if (func_name == kRefineJsonExtractFuncId) { - if (function_args.size() >= 3 && function_args[1].is_string() && - function_args[2].is_bool()) { - result = RefineJsonExtract(*result, function_args[1].GetString(), - function_args[2].GetBool()); - } - } - if (!result) { - break; - } - } - return result; -} - -void MaybeSetQueryInResult(const ScrapeRule& rule, - const std::optional& value, - PageScrapeResult* result) { - if (rule.rule_type != ScrapeRuleType::kSearchQuery && - rule.rule_type != ScrapeRuleType::kWidgetTitle) { - return; - } - if (!value) { - return; - } - result->query = value; -} - } // namespace PageScrapeResult::PageScrapeResult(GURL url, std::string id) @@ -144,11 +94,13 @@ PageScrapeResult::~PageScrapeResult() = default; ContentScraper::ContentScraper( std::unique_ptr* last_loaded_server_config, - std::unique_ptr* patterns) + std::unique_ptr* patterns, + RegexUtil* regex_util) : pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), last_loaded_server_config_(last_loaded_server_config), - patterns_(patterns) {} + patterns_(patterns), + regex_util_(regex_util) {} ContentScraper::~ContentScraper() = default; @@ -324,21 +276,8 @@ void ContentScraper::OnScrapedElementAttributes( } base::Value::Dict attribute_values; for (const auto& [key, value_str] : attribute_result->attribute_values) { - const auto rule = rule_group->second.find(key); - if (rule == rule_group->second.end()) { - continue; - } - base::Value value; - if (value_str) { - auto final_value_str = - ExecuteRefineFunctions(rule->second->functions_applied, *value_str); - MaybeSetQueryInResult(*rule->second, final_value_str, - scrape_result.get()); - if (final_value_str) { - value = base::Value(*final_value_str); - } - } - attribute_values.Set(key, std::move(value)); + ProcessAttributeValue(rule_group->second, *scrape_result, key, value_str, + attribute_values); } scrape_result->fields[attribute_result->root_selector].push_back( std::move(attribute_values)); @@ -364,26 +303,79 @@ void ContentScraper::OnRustElementAttributes( } base::Value::Dict attribute_values; for (const auto& pair : attribute_result.attribute_pairs) { - const auto key_str = std::string(pair.key); - const auto rule = rule_group->second.find(key_str); - if (rule == rule_group->second.end()) { - continue; - } - base::Value value; - if (!pair.value.empty()) { - auto final_value_str = ExecuteRefineFunctions( - rule->second->functions_applied, std::string(pair.value)); - MaybeSetQueryInResult(*rule->second, final_value_str, - scrape_result.get()); - if (final_value_str) { - value = base::Value(*final_value_str); - } - } - attribute_values.Set(key_str, std::move(value)); + ProcessAttributeValue( + rule_group->second, *scrape_result, std::string(pair.key), + pair.value.empty() ? std::nullopt + : std::make_optional(pair.value), + attribute_values); } scrape_result->fields[root_selector].push_back(std::move(attribute_values)); } std::move(callback).Run(std::move(scrape_result)); } +std::optional ContentScraper::ExecuteRefineFunctions( + const RefineFunctionList& function_list, + std::string value) { + std::optional result = value; + for (const auto& function_args : function_list) { + if (function_args.empty()) { + continue; + } + const auto& func_name = function_args[0]; + if (func_name == kRefineSplitFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_int()) { + result = RefineSplit(*result, function_args[1].GetString(), + function_args[2].GetInt()); + } + } else if (func_name == kRefineMaskURLFuncId) { + result = MaskURL(*regex_util_, GURL(value)); + } else if (func_name == kRefineParseURLFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_string()) { + result = RefineParseURL(*result, function_args[1].GetString(), + function_args[2].GetString()); + } + } else if (func_name == kRefineJsonExtractFuncId) { + if (function_args.size() >= 3 && function_args[1].is_string() && + function_args[2].is_bool()) { + result = RefineJsonExtract(*result, function_args[1].GetString(), + function_args[2].GetBool()); + } + } + if (!result) { + break; + } + } + return result; +} + +void ContentScraper::ProcessAttributeValue( + const ScrapeRuleGroup& rule_group, + PageScrapeResult& scrape_result, + std::string key, + std::optional value_str, + base::Value::Dict& attribute_values) { + const auto rule = rule_group.find(key); + if (rule == rule_group.end()) { + return; + } + base::Value value; + if (value_str) { + value_str = + ExecuteRefineFunctions(rule->second->functions_applied, *value_str); + + if (value_str) { + if (rule->second->rule_type == ScrapeRuleType::kSearchQuery || + rule->second->rule_type == ScrapeRuleType::kWidgetTitle) { + scrape_result.query = value_str; + } + + value = base::Value(*value_str); + } + } + attribute_values.Set(key, std::move(value)); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index ac72cfc4d396..380fbb7e39f6 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -15,6 +15,7 @@ #include "base/values.h" #include "brave/components/web_discovery/browser/document_extractor/rs/src/lib.rs.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" #include "url/gurl.h" @@ -46,7 +47,8 @@ class ContentScraper { base::OnceCallback)>; ContentScraper(std::unique_ptr* last_loaded_server_config, - std::unique_ptr* patterns); + std::unique_ptr* patterns, + RegexUtil* regex_util); ~ContentScraper(); ContentScraper(const ContentScraper&) = delete; @@ -81,10 +83,20 @@ class ContentScraper { PageScrapeResultCallback callback, rust::Vec attribute_results); + std::optional ExecuteRefineFunctions( + const RefineFunctionList& function_list, + std::string value); + void ProcessAttributeValue(const ScrapeRuleGroup& rule_group, + PageScrapeResult& scrape_result, + std::string key, + std::optional value_str, + base::Value::Dict& attribute_values); + scoped_refptr pool_sequenced_task_runner_; raw_ptr> last_loaded_server_config_; raw_ptr> patterns_; + raw_ptr regex_util_; base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 039da5bac014..8812241f107b 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -136,7 +136,7 @@ CredentialManager::CredentialManager( : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), last_loaded_server_config_(last_loaded_server_config), - join_url_(GetCollectorHost() + kJoinPath), + join_url_(GetDirectHPNHost() + kJoinPath), backoff_entry_(&kBackoffPolicy), pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), diff --git a/components/web_discovery/browser/hash_detection.cc b/components/web_discovery/browser/hash_detection.cc index 251f5c891955..d2970c2faf0b 100644 --- a/components/web_discovery/browser/hash_detection.cc +++ b/components/web_discovery/browser/hash_detection.cc @@ -1459,8 +1459,10 @@ constexpr auto kTokenMap = base::MakeFixedFlatMap( constexpr double kClassifierThreshold = 0.015; -bool IsHashLikely(std::string value, double threshold_multiplier) { - TransformToAlphanumeric(value); +bool IsHashLikely(RegexUtil& regex_util, + std::string value, + double threshold_multiplier) { + regex_util.TransformToAlphanumeric(value); double log_prob_sum = 0.0; size_t add_count = 0; diff --git a/components/web_discovery/browser/hash_detection.h b/components/web_discovery/browser/hash_detection.h index 4f5cd6975ba0..376674b4393e 100644 --- a/components/web_discovery/browser/hash_detection.h +++ b/components/web_discovery/browser/hash_detection.h @@ -8,9 +8,13 @@ #include +#include "brave/components/web_discovery/browser/regex_util.h" + namespace web_discovery { -bool IsHashLikely(std::string value, double probability_multiplier = 1.0); +bool IsHashLikely(RegexUtil& regex_util, + std::string value, + double probability_multiplier = 1.0); } // namespace web_discovery diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index 3a3df4b813f3..37437c898215 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -44,7 +44,8 @@ bool AggregatedDictHasContent(const base::Value::Dict& dict) { return false; } -bool IsPrivateResult(const PayloadRule& rule, +bool IsPrivateResult(RegexUtil& regex_util, + const PayloadRule& rule, const PatternsURLDetails* matching_url_details, const base::Value::Dict& dict) { if (rule.key != kSearchResultKey) { @@ -54,7 +55,7 @@ bool IsPrivateResult(const PayloadRule& rule, if (!url) { return false; } - return IsPrivateURLLikely(GURL(*url), matching_url_details); + return IsPrivateURLLikely(regex_util, GURL(*url), matching_url_details); } bool ShouldDropSearchResultPayload(const PayloadRule& rule, @@ -74,6 +75,7 @@ base::Value::Dict CreatePayloadDict(const PayloadRuleGroup& rule_group, } std::optional GenerateClusteredJoinedPayload( + RegexUtil& regex_util, const PayloadRule& rule, const PatternsURLDetails* matching_url_details, const std::vector& attribute_values) { @@ -83,7 +85,7 @@ std::optional GenerateClusteredJoinedPayload( if (value.empty()) { continue; } - if (IsPrivateResult(rule, matching_url_details, value)) { + if (IsPrivateResult(regex_util, rule, matching_url_details, value)) { VLOG(1) << "Omitting private search result"; continue; } @@ -101,6 +103,7 @@ std::optional GenerateClusteredJoinedPayload( } std::optional GenerateClusteredPayload( + RegexUtil& regex_util, const PayloadRuleGroup& rule_group, const PatternsURLDetails* matching_url_details, const PageScrapeResult* scrape_result) { @@ -117,7 +120,7 @@ std::optional GenerateClusteredPayload( } if (rule.is_join) { auto joined_payload = GenerateClusteredJoinedPayload( - rule, matching_url_details, attribute_values_it->second); + regex_util, rule, matching_url_details, attribute_values_it->second); if (!joined_payload) { VLOG(1) << "Skipped joined clustered payload, action = " << rule_group.action; @@ -157,14 +160,15 @@ void GenerateSinglePayloads(const ServerConfig& server_config, std::vector GeneratePayloads( const ServerConfig& server_config, + RegexUtil& regex_util, const PatternsURLDetails* url_details, std::unique_ptr scrape_result) { std::vector payloads; for (const auto& rule_group : url_details->payload_rule_groups) { if (rule_group.rule_type == PayloadRuleType::kQuery && rule_group.result_type == PayloadResultType::kClustered) { - auto payload = GenerateClusteredPayload(rule_group, url_details, - scrape_result.get()); + auto payload = GenerateClusteredPayload(regex_util, rule_group, + url_details, scrape_result.get()); if (payload) { payloads.push_back(std::move(*payload)); } diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h index cb788673e115..b4ee117a5d59 100644 --- a/components/web_discovery/browser/payload_generator.h +++ b/components/web_discovery/browser/payload_generator.h @@ -12,6 +12,7 @@ #include "base/values.h" #include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" namespace web_discovery { @@ -20,6 +21,7 @@ inline constexpr char kInnerPayloadKey[] = "payload"; std::vector GeneratePayloads( const ServerConfig& server_config, + RegexUtil& regex_util, const PatternsURLDetails* url_details, std::unique_ptr scrape_result); diff --git a/components/web_discovery/browser/privacy_guard.cc b/components/web_discovery/browser/privacy_guard.cc index 28b590aed93b..c13ffb6cb986 100644 --- a/components/web_discovery/browser/privacy_guard.cc +++ b/components/web_discovery/browser/privacy_guard.cc @@ -5,16 +5,13 @@ #include "brave/components/web_discovery/browser/privacy_guard.h" -#include - #include "base/logging.h" #include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "brave/components/web_discovery/browser/hash_detection.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/util.h" -#include "third_party/re2/src/re2/re2.h" -#include "url/third_party/mozilla/url_parse.h" #include "url/url_constants.h" #include "url/url_util.h" @@ -41,11 +38,6 @@ constexpr size_t kMaxDotSplitDomainSize = 6; constexpr size_t kMaxHyphenSplitDomainSize = 4; constexpr size_t kMaxDomainNumberLength = 5; -constexpr char kLongNumberRegexPrefix[] = "[0-9]{"; -constexpr char kLongNumberRegexSuffix[] = ",}"; -constexpr char kEmailRegex[] = - "[a-z0-9\\-_@]+(@|%40|%(25)+40)[a-z0-9\\-_]+\\.[a-z0-9\\-_]"; -constexpr char kHttpPasswordRegex[] = "[^:]+:[^@]+@"; constexpr char kDefaultSearchPrefix[] = "search?q="; constexpr char kOnionSiteSuffix[] = ".onion"; @@ -56,75 +48,31 @@ constexpr char kGoogleHostSubstring[] = "google"; constexpr char kGoogleURLQueryParam[] = "url"; constexpr char kMaskedURLSuffix[] = "/ (PROTECTED)"; -constexpr std::array kPathAndQueryStringCheckRegexes = { - "(?i)\\/admin([\\/\\?#=]|$)", - "(?i)\\/wp-admin([\\/\\?#=]|$)", - "(?i)\\/edit([\\/\\?#=]|$)", - "(?i)[&\\?#\\/]share([\\/\\?#=]|$)", - "(?i)[&\\?#\\/;]sharing([\\/\\?#=]|$)", - "(?i)[&\\?#\\/;]logout([\\/\\?#=]|$)", - "(?i)WebLogic", - "(?i)[&\\?#\\/;]token([\\/\\?#=_;]|$)", - "(?i)[&\\?#\\/;]trk([\\/\\?#=_]|$)", - "[&\\?#\\/=;](http|https)(:\\/|\\%3A\\%2F)"}; - -constexpr std::array kQueryStringAndRefCheckRegexes = { - "(?i)[&\\?#_\\-;]user", "(?i)[&\\?#_\\-;]token", - "(?i)[&\\?#_\\-;]auth", "(?i)[&\\?#_\\-;]uid", - "(?i)[&\\?#_\\-;]email", "(?i)[&\\?#_\\-;]usr", - "(?i)[&\\?#_\\-;]pin", "(?i)[&\\?#_\\-;]pwd", - "(?i)[&\\?#_\\-;]password", "(?i)[&\\?#;]u[=#]", - "(?i)[&\\?#;]url[=#]", "(?i)[&\\?#_\\-;]http", - "(?i)[&\\?#_\\-;]ref[=#]", "(?i)[&\\?#_\\-;]red[=#]", - "(?i)[&\\?#_\\-;]trk", "(?i)[&\\?#_\\-;]track", - "(?i)[&\\?#_\\-;]shar", "(?i)[&\\?#_\\-;]login", - "(?i)[&\\?#_\\-;]logout", "(?i)[&\\?#_\\-;]session", -}; - -bool CheckForEmail(const std::string& str) { - re2::RE2 email_regex(kEmailRegex); - return re2::RE2::PartialMatch(str, email_regex); -} - -bool CheckForLongNumber(const std::string_view str, size_t max_length) { - auto regex_str = base::StrCat({kLongNumberRegexPrefix, - base::NumberToString(max_length + 1), - kLongNumberRegexSuffix}); - re2::RE2 long_number_regex(regex_str); - return re2::RE2::PartialMatch(str, long_number_regex); -} - -bool ContainsForbiddenKeywords(const GURL& url) { +bool ContainsForbiddenKeywords(RegexUtil& regex_util, const GURL& url) { auto path_and_query = base::StrCat({url.path_piece(), "?", url.query_piece()}); - for (const auto& regex_str : kPathAndQueryStringCheckRegexes) { - re2::RE2 regex(regex_str); - if (re2::RE2::PartialMatch(path_and_query, regex)) { - return true; - } + if (regex_util.CheckPathAndQueryStringKeywords(path_and_query)) { + return true; } - for (const auto& regex_str : kQueryStringAndRefCheckRegexes) { - re2::RE2 regex(regex_str); - if (!url.ref_piece().empty() && - re2::RE2::PartialMatch("#" + url.ref(), regex)) { - return true; - } - if (!url.query_piece().empty() && - re2::RE2::PartialMatch("?" + url.query(), regex)) { - return true; - } + if (!url.ref_piece().empty() && + regex_util.CheckQueryStringOrRefKeywords("#" + url.ref())) { + return true; + } + if (!url.query_piece().empty() && + regex_util.CheckQueryStringOrRefKeywords("?" + url.query())) { + return true; } return false; } -bool IsPrivateDomainLikely(const std::string_view host) { +bool IsPrivateDomainLikely(RegexUtil& regex_util, const std::string_view host) { auto dot_split = base::SplitString(host, ".", base::WhitespaceHandling::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); if (dot_split.size() > kMaxDotSplitDomainSize) { return true; } - if (CheckForLongNumber(host, kMaxDomainNumberLength)) { + if (regex_util.CheckForLongNumber(host, kMaxDomainNumberLength)) { return true; } auto hyphen_split = @@ -138,7 +86,8 @@ bool IsPrivateDomainLikely(const std::string_view host) { } // namespace -bool IsPrivateURLLikely(const GURL& url, +bool IsPrivateURLLikely(RegexUtil& regex_util, + const GURL& url, const PatternsURLDetails* matching_url_details) { if (!url.SchemeIs("https")) { VLOG(1) << "Ignoring URL due to non-HTTPS scheme"; @@ -168,14 +117,14 @@ bool IsPrivateURLLikely(const GURL& url, VLOG(1) << "Ignoring URL due a local host or onion site"; return true; } - if (IsPrivateDomainLikely(url.host_piece())) { + if (IsPrivateDomainLikely(regex_util, url.host_piece())) { VLOG(1) << "Ignoring URL due likely private domain"; return true; } return false; } -bool IsPrivateQueryLikely(const std::string& query) { +bool IsPrivateQueryLikely(RegexUtil& regex_util, const std::string& query) { if (query.length() > kMaxQueryLength) { VLOG(1) << "Ignoring query due to long length"; return true; @@ -187,16 +136,15 @@ bool IsPrivateQueryLikely(const std::string& query) { VLOG(1) << "Ignoring query due to long split length"; return true; } - if (CheckForLongNumber(query, kMaxQueryNumberLength)) { + if (regex_util.CheckForLongNumber(query, kMaxQueryNumberLength)) { VLOG(1) << "Ignoring query due to long number"; return true; } - if (CheckForEmail(query)) { + if (regex_util.CheckForEmail(query)) { VLOG(1) << "Ignoring query due to inclusion of email"; return true; } - re2::RE2 http_pwd_regex(kHttpPasswordRegex); - if (re2::RE2::PartialMatch(query, http_pwd_regex)) { + if (regex_util.CheckQueryHTTPCredentials(query)) { VLOG(1) << "Ignoring query due to potential inclusion of HTTP credentials"; return true; } @@ -207,7 +155,7 @@ bool IsPrivateQueryLikely(const std::string& query) { } } if (query.length() >= kHashCheckMinimumLength) { - if (IsHashLikely(query, kHashCheckThresholdMultiplier)) { + if (IsHashLikely(regex_util, query, kHashCheckThresholdMultiplier)) { VLOG(1) << "Ignoring query due to potential inclusion of hash"; return true; } @@ -231,8 +179,8 @@ GURL GeneratePrivateSearchURL(const GURL& original_url, query_encoded_str})); } -bool ShouldDropLongURL(const GURL& url) { - if (CheckForEmail(url.spec())) { +bool ShouldDropLongURL(RegexUtil& regex_util, const GURL& url) { + if (regex_util.CheckForEmail(url.spec())) { return true; } if (!url.query_piece().empty()) { @@ -245,14 +193,14 @@ bool ShouldDropLongURL(const GURL& url) { if (query_parts.size() > kMaxQueryStringParts) { return true; } - if (CheckForLongNumber(url.query_piece(), - kMaxQueryStringOrPathNumberLength)) { + if (regex_util.CheckForLongNumber(url.query_piece(), + kMaxQueryStringOrPathNumberLength)) { return true; } } if (!url.path_piece().empty()) { - if (CheckForLongNumber(url.path_piece(), - kMaxQueryStringOrPathNumberLength)) { + if (regex_util.CheckForLongNumber(url.path_piece(), + kMaxQueryStringOrPathNumberLength)) { return true; } } @@ -264,7 +212,7 @@ bool ShouldDropLongURL(const GURL& url) { return true; } if (path_part.length() >= kMinPathPartHashCheckLength && - IsHashLikely(path_part)) { + IsHashLikely(regex_util, path_part)) { return true; } } @@ -273,21 +221,21 @@ bool ShouldDropLongURL(const GURL& url) { base::SPLIT_WANT_ALL); for (const auto& path_segment : path_segments) { std::string alphanumeric_path_segment = path_segment; - TransformToAlphanumeric(alphanumeric_path_segment); + regex_util.TransformToAlphanumeric(alphanumeric_path_segment); if (alphanumeric_path_segment.length() >= kMinSegmentHashCheckLength && - IsHashLikely(alphanumeric_path_segment)) { + IsHashLikely(regex_util, alphanumeric_path_segment)) { return true; } } - return ContainsForbiddenKeywords(url); + return ContainsForbiddenKeywords(regex_util, url); } -std::optional MaskURL(const GURL& url) { +std::optional MaskURL(RegexUtil& regex_util, const GURL& url) { if (!url.SchemeIsHTTPOrHTTPS() || !url.is_valid()) { return std::nullopt; } - if (!ShouldDropLongURL(url)) { + if (!ShouldDropLongURL(regex_util, url)) { return url.spec(); } @@ -300,7 +248,7 @@ std::optional MaskURL(const GURL& url) { if (!decoded_embedded_url.is_valid()) { return std::nullopt; } - return MaskURL(decoded_embedded_url); + return MaskURL(regex_util, decoded_embedded_url); } } diff --git a/components/web_discovery/browser/privacy_guard.h b/components/web_discovery/browser/privacy_guard.h index 75430efa82b4..38328f4068e2 100644 --- a/components/web_discovery/browser/privacy_guard.h +++ b/components/web_discovery/browser/privacy_guard.h @@ -9,22 +9,24 @@ #include #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "url/gurl.h" namespace web_discovery { -bool IsPrivateURLLikely(const GURL& url, +bool IsPrivateURLLikely(RegexUtil& regex_util, + const GURL& url, const PatternsURLDetails* matching_url_details); -bool IsPrivateQueryLikely(const std::string& query); +bool IsPrivateQueryLikely(RegexUtil& regex_util, const std::string& query); GURL GeneratePrivateSearchURL(const GURL& original_url, const std::string& query, const PatternsURLDetails& matching_url_details); -bool ShouldDropLongURL(const GURL& url); +bool ShouldDropLongURL(RegexUtil& regex_util, const GURL& url); -std::optional MaskURL(const GURL& url); +std::optional MaskURL(RegexUtil& regex_util, const GURL& url); } // namespace web_discovery diff --git a/components/web_discovery/browser/regex_util.cc b/components/web_discovery/browser/regex_util.cc new file mode 100644 index 000000000000..88f19f14aa69 --- /dev/null +++ b/components/web_discovery/browser/regex_util.cc @@ -0,0 +1,121 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "brave/components/web_discovery/browser/regex_util.h" + +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" + +namespace { + +constexpr char kLongNumberRegexPrefix[] = "[0-9]{"; +constexpr char kLongNumberRegexSuffix[] = ",}"; +constexpr char kEmailRegex[] = + "[a-z0-9\\-_@]+(@|%40|%(25)+40)[a-z0-9\\-_]+\\.[a-z0-9\\-_]"; +constexpr char kHttpPasswordRegex[] = "[^:]+:[^@]+@"; +constexpr char kNotAlphanumericRegex[] = "[^a-zA-Z0-9]"; +constexpr char kPunctuationRegex[] = "[!\"'()*,-./:;?[\\]^_`{|}~%$=&+#]"; + +constexpr std::array kPathAndQueryStringCheckRegexes = { + "(?i)\\/admin([\\/\\?#=]|$)", + "(?i)\\/wp-admin([\\/\\?#=]|$)", + "(?i)\\/edit([\\/\\?#=]|$)", + "(?i)[&\\?#\\/]share([\\/\\?#=]|$)", + "(?i)[&\\?#\\/;]sharing([\\/\\?#=]|$)", + "(?i)[&\\?#\\/;]logout([\\/\\?#=]|$)", + "(?i)WebLogic", + "(?i)[&\\?#\\/;]token([\\/\\?#=_;]|$)", + "(?i)[&\\?#\\/;]trk([\\/\\?#=_]|$)", + "[&\\?#\\/=;](http|https)(:\\/|\\%3A\\%2F)"}; + +constexpr std::array kQueryStringAndRefCheckRegexes = { + "(?i)[&\\?#_\\-;]user", "(?i)[&\\?#_\\-;]token", + "(?i)[&\\?#_\\-;]auth", "(?i)[&\\?#_\\-;]uid", + "(?i)[&\\?#_\\-;]email", "(?i)[&\\?#_\\-;]usr", + "(?i)[&\\?#_\\-;]pin", "(?i)[&\\?#_\\-;]pwd", + "(?i)[&\\?#_\\-;]password", "(?i)[&\\?#;]u[=#]", + "(?i)[&\\?#;]url[=#]", "(?i)[&\\?#_\\-;]http", + "(?i)[&\\?#_\\-;]ref[=#]", "(?i)[&\\?#_\\-;]red[=#]", + "(?i)[&\\?#_\\-;]trk", "(?i)[&\\?#_\\-;]track", + "(?i)[&\\?#_\\-;]shar", "(?i)[&\\?#_\\-;]login", + "(?i)[&\\?#_\\-;]logout", "(?i)[&\\?#_\\-;]session", +}; + +} // anonymous namespace + +namespace web_discovery { + +RegexUtil::RegexUtil() = default; +RegexUtil::~RegexUtil() = default; + +bool RegexUtil::CheckForEmail(const std::string_view str) { + if (!email_regex_) { + email_regex_.emplace(kEmailRegex); + } + return re2::RE2::PartialMatch(str, *email_regex_); +} + +bool RegexUtil::CheckForLongNumber(const std::string_view str, + size_t max_length) { + if (!long_number_regexes_.contains(max_length)) { + auto regex_str = base::StrCat({kLongNumberRegexPrefix, + base::NumberToString(max_length + 1), + kLongNumberRegexSuffix}); + long_number_regexes_[max_length] = std::make_unique(regex_str); + } + return re2::RE2::PartialMatch(str, *long_number_regexes_[max_length]); +} + +void RegexUtil::RemovePunctuation(std::string& str) { + if (!punctuation_regex_) { + punctuation_regex_.emplace(kPunctuationRegex); + } + re2::RE2::GlobalReplace(&str, *punctuation_regex_, ""); +} + +void RegexUtil::TransformToAlphanumeric(std::string& str) { + if (!non_alphanumeric_regex_) { + non_alphanumeric_regex_.emplace(kNotAlphanumericRegex); + } + re2::RE2::GlobalReplace(&str, *non_alphanumeric_regex_, ""); +} + +bool RegexUtil::CheckPathAndQueryStringKeywords( + const std::string_view path_and_query) { + if (path_and_query_string_keyword_regexes_.empty()) { + for (const auto& regex_str : kPathAndQueryStringCheckRegexes) { + path_and_query_string_keyword_regexes_.emplace_back(regex_str); + } + } + for (const auto& regex : path_and_query_string_keyword_regexes_) { + if (re2::RE2::PartialMatch(path_and_query, regex)) { + return true; + } + } + return false; +} + +bool RegexUtil::CheckQueryStringOrRefKeywords(const std::string_view str) { + if (query_string_and_ref_keyword_regexes_.empty()) { + for (const auto& regex_str : kQueryStringAndRefCheckRegexes) { + query_string_and_ref_keyword_regexes_.emplace_back(regex_str); + } + } + for (const auto& regex : query_string_and_ref_keyword_regexes_) { + if (re2::RE2::PartialMatch(str, regex)) { + return true; + } + } + return false; +} + +bool RegexUtil::CheckQueryHTTPCredentials(const std::string_view str) { + if (!http_password_regex_) { + http_password_regex_.emplace(kHttpPasswordRegex); + } + return re2::RE2::PartialMatch(str, *http_password_regex_); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/regex_util.h b/components/web_discovery/browser/regex_util.h new file mode 100644 index 000000000000..970030c55230 --- /dev/null +++ b/components/web_discovery/browser/regex_util.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REGEX_UTIL_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REGEX_UTIL_H_ + +#include +#include +#include +#include + +#include "base/containers/flat_map.h" +#include "third_party/re2/src/re2/re2.h" + +namespace web_discovery { + +class RegexUtil { + public: + RegexUtil(); + ~RegexUtil(); + + RegexUtil(const RegexUtil&) = delete; + RegexUtil& operator=(const RegexUtil&) = delete; + + bool CheckForEmail(const std::string_view str); + bool CheckForLongNumber(const std::string_view str, size_t max_length); + bool CheckPathAndQueryStringKeywords(const std::string_view path_and_query); + bool CheckQueryStringOrRefKeywords(const std::string_view str); + bool CheckQueryHTTPCredentials(const std::string_view str); + void RemovePunctuation(std::string& str); + void TransformToAlphanumeric(std::string& str); + + private: + std::optional email_regex_; + // key is long number map length + base::flat_map> long_number_regexes_; + std::deque path_and_query_string_keyword_regexes_; + std::deque query_string_and_ref_keyword_regexes_; + std::optional http_password_regex_; + std::optional punctuation_regex_; + std::optional non_alphanumeric_regex_; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_REGEX_UTIL_H_ diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index b4ad0aeee0dc..6d05d8e00737 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -120,11 +120,13 @@ std::optional CompressAndEncrypt( Reporter::Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, CredentialManager* credential_manager, + RegexUtil* regex_util, std::unique_ptr* last_loaded_server_config) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), last_loaded_server_config_(last_loaded_server_config), credential_manager_(credential_manager), + regex_util_(regex_util), pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), request_queue_(profile_prefs, @@ -135,7 +137,7 @@ Reporter::Reporter(PrefService* profile_prefs, kMaxRetries, base::BindRepeating(&Reporter::PrepareRequest, base::Unretained(this))) { - submit_url_ = GURL(GetCollectorHost() + kSubmitPath); + submit_url_ = GURL(GetAnonymousHPNHost() + kSubmitPath); } Reporter::~Reporter() = default; @@ -159,8 +161,9 @@ void Reporter::PrepareRequest(const base::Value& request_data) { request_queue_.NotifyRequestComplete(true); return; } - auto basename_result = GenerateBasename( - profile_prefs_, (*last_loaded_server_config_).get(), *payload_dict); + auto basename_result = + GenerateBasename(profile_prefs_, (*last_loaded_server_config_).get(), + *regex_util_, *payload_dict); if (!basename_result) { // Drop request due to exceeded basename quota VLOG(1) << "Failed to generate basename"; diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index d049e3873d0b..7341a0c16780 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -15,6 +15,7 @@ #include "base/values.h" #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/ecdh_aes.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/request_queue.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "net/http/http_response_headers.h" @@ -33,6 +34,7 @@ class Reporter { Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, CredentialManager* credential_manager, + RegexUtil* regex_util, std::unique_ptr* last_loaded_server_config); ~Reporter(); @@ -62,6 +64,7 @@ class Reporter { raw_ptr> last_loaded_server_config_; raw_ptr credential_manager_; + raw_ptr regex_util_; scoped_refptr pool_sequenced_task_runner_; diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index a4219099f40c..be13c9dcb878 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -165,7 +165,7 @@ ServerConfigLoader::ServerConfigLoader( config_backoff_entry_(&kBackoffPolicy), patterns_backoff_entry_(&kBackoffPolicy) { collector_config_url_ = - GURL(GetCollectorHost() + kCollectorConfigPathWithFields); + GURL(GetAnonymousHPNHost() + kCollectorConfigPathWithFields); quorum_config_url_ = GURL(GetQuorumHost() + kQuorumConfigPath); patterns_url_ = GetPatternsEndpoint(); diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc index 89b1fcbc7461..8c9bc295e2c3 100644 --- a/components/web_discovery/browser/signature_basename.cc +++ b/components/web_discovery/browser/signature_basename.cc @@ -18,13 +18,11 @@ #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/scoped_user_pref_update.h" #include "crypto/sha2.h" -#include "third_party/re2/src/re2/re2.h" namespace web_discovery { namespace { -constexpr char kPunctuationRegex[] = "[!\"'()*,-./:;?[\\]^_`{|}~%$=&+#]"; constexpr char kUrlNormalizationFunc[] = "url"; constexpr char kFlattenObjNormalizationFunc[] = "obj"; constexpr size_t kMsInHour = 60 * 60 * 1000; @@ -68,7 +66,7 @@ base::Value FlattenObject(const base::Value& obj) { return base::Value(std::move(result)); } -base::Value CleanURL(const base::Value& url) { +base::Value CleanURL(RegexUtil& regex_util, const base::Value& url) { if (!url.is_string()) { return base::Value(); } @@ -78,8 +76,7 @@ base::Value CleanURL(const base::Value& url) { base::ReplaceSubstringsAfterOffset(&url_str, 0, "http://", ""); base::ReplaceSubstringsAfterOffset(&url_str, 0, "www.", ""); - re2::RE2 punc_regex(kPunctuationRegex); - re2::RE2::GlobalReplace(&url_str, punc_regex, ""); + regex_util.RemovePunctuation(url_str); return base::Value(std::move(url_str)); } @@ -150,6 +147,7 @@ BasenameResult::~BasenameResult() = default; std::optional GenerateBasename( PrefService* profile_prefs, ServerConfig* server_config, + RegexUtil& regex_util, const base::Value::Dict& payload) { const std::string* action = payload.FindString(kActionKey); std::string json; @@ -190,7 +188,7 @@ std::optional GenerateBasename( } if (parts.size() > 1) { if (parts[1] == kUrlNormalizationFunc) { - value = CleanURL(value); + value = CleanURL(regex_util, value); } else if (parts[1] == kFlattenObjNormalizationFunc) { value = FlattenObject(value); } diff --git a/components/web_discovery/browser/signature_basename.h b/components/web_discovery/browser/signature_basename.h index 775dbe8c60d1..1422b2398d2d 100644 --- a/components/web_discovery/browser/signature_basename.h +++ b/components/web_discovery/browser/signature_basename.h @@ -10,6 +10,7 @@ #include #include "base/values.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/server_config_loader.h" class PrefService; @@ -35,6 +36,7 @@ struct BasenameResult { std::optional GenerateBasename( PrefService* profile_prefs, ServerConfig* server_config, + RegexUtil& regex_util, const base::Value::Dict& payload); void SaveBasenameCount(PrefService* profile_prefs, diff --git a/components/web_discovery/browser/util.cc b/components/web_discovery/browser/util.cc index 1e6dc331e509..acb38bdf63e2 100644 --- a/components/web_discovery/browser/util.cc +++ b/components/web_discovery/browser/util.cc @@ -8,7 +8,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "brave/brave_domains/service_domains.h" -#include "third_party/re2/src/re2/re2.h" #include "url/url_util.h" namespace web_discovery { @@ -18,10 +17,14 @@ constexpr char kCollectorHostPrefix[] = "collector.wdp"; constexpr char kQuorumHostPrefix[] = "quorum.wdp"; constexpr char kPatternsHostPrefix[] = "patterns.wdp"; constexpr char kPatternsPath[] = "/patterns.gz"; -constexpr char kNotAlphanumericRegex[] = "[^A-Za-z0-9]"; } // namespace -std::string GetCollectorHost() { +std::string GetDirectHPNHost() { + // TODO(djandries): Replace with non-proxied endpoint once available + return GetAnonymousHPNHost(); +} + +std::string GetAnonymousHPNHost() { auto* cmd_line = base::CommandLine::ForCurrentProcess(); if (cmd_line->HasSwitch(kCollectorHostSwitch)) { return cmd_line->GetSwitchValueASCII(kCollectorHostSwitch); @@ -55,11 +58,6 @@ std::string FormatServerDate(const base::Time& date) { exploded.day_of_month); } -void TransformToAlphanumeric(std::string& value) { - re2::RE2 cleaning_regex(kNotAlphanumericRegex); - re2::RE2::GlobalReplace(&value, cleaning_regex, ""); -} - std::string DecodeURLComponent(const std::string_view value) { url::RawCanonOutputT result; url::DecodeURLEscapeSequences(value, url::DecodeURLMode::kUTF8OrIsomorphic, diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index 3aaa4e84b277..4a00b6c17262 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -31,7 +31,8 @@ inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { .entry_lifetime_ms = -1, .always_use_initial_delay = false}; -std::string GetCollectorHost(); +std::string GetDirectHPNHost(); +std::string GetAnonymousHPNHost(); std::string GetQuorumHost(); GURL GetPatternsEndpoint(); @@ -39,8 +40,6 @@ std::unique_ptr CreateResourceRequest(GURL url); std::string FormatServerDate(const base::Time& date); -void TransformToAlphanumeric(std::string& value); - std::string DecodeURLComponent(const std::string_view value); std::optional ExtractValueFromQueryString( diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index e61de3b6c398..8da9d0d9d2ab 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -93,14 +93,14 @@ void WDPService::OnConfigChange(std::unique_ptr config) { void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { last_loaded_patterns_ = std::move(patterns); content_scraper_ = std::make_unique( - &last_loaded_server_config_, &last_loaded_patterns_); + &last_loaded_server_config_, &last_loaded_patterns_, ®ex_util_); double_fetcher_ = std::make_unique( profile_prefs_.get(), shared_url_loader_factory_.get(), base::BindRepeating(&WDPService::OnDoubleFetched, base::Unretained(this))); reporter_ = std::make_unique( profile_prefs_.get(), shared_url_loader_factory_.get(), - credential_manager_.get(), &last_loaded_server_config_); + credential_manager_.get(), ®ex_util_, &last_loaded_server_config_); } void WDPService::OnDoubleFetched(const GURL& url, @@ -131,7 +131,7 @@ void WDPService::OnFinishNavigation( return; } VLOG(1) << "URL matched pattern " << matching_url_details->id << ": " << url; - if (IsPrivateURLLikely(url, matching_url_details)) { + if (IsPrivateURLLikely(regex_util_, url, matching_url_details)) { return; } mojo::Remote remote; @@ -162,7 +162,7 @@ void WDPService::OnContentScraped(bool is_strict, if (!result->query) { return; } - if (IsPrivateQueryLikely(*result->query)) { + if (IsPrivateQueryLikely(regex_util_, *result->query)) { return; } url = GeneratePrivateSearchURL(url, *result->query, *strict_url_details); @@ -170,7 +170,7 @@ void WDPService::OnContentScraped(bool is_strict, double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); } } - auto payloads = GeneratePayloads(*last_loaded_server_config_, + auto payloads = GeneratePayloads(*last_loaded_server_config_, regex_util_, original_url_details, std::move(result)); for (auto& payload : payloads) { reporter_->ScheduleSend(std::move(payload)); diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 84c12f5882a2..3d223a499a27 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -16,6 +16,7 @@ #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/double_fetcher.h" #include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/reporter.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/keyed_service/core/keyed_service.h" @@ -73,6 +74,8 @@ class WDPService : public KeyedService { base::FilePath user_data_dir_; + RegexUtil regex_util_; + scoped_refptr shared_url_loader_factory_; mojo::RemoteSet document_extractor_remotes_; From 904d1195d46b2a281ca7f38cc4e8acd355561718 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 13 Jun 2024 15:31:11 -0700 Subject: [PATCH 20/36] Add Web discovery 'alive' message --- .../browser/payload_generator.cc | 18 ++++- .../web_discovery/browser/payload_generator.h | 6 +- components/web_discovery/browser/pref_names.h | 1 + components/web_discovery/browser/reporter.cc | 6 +- components/web_discovery/browser/reporter.h | 6 +- .../browser/signature_basename.cc | 3 +- .../web_discovery/browser/wdp_service.cc | 71 ++++++++++++++++++- .../web_discovery/browser/wdp_service.h | 7 ++ 8 files changed, 105 insertions(+), 13 deletions(-) diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index 37437c898215..af02279b22c1 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -18,6 +18,10 @@ constexpr char kSearchResultKey[] = "r"; constexpr char kSearchResultURLKey[] = "u"; constexpr size_t kMinSearchResultSize = 4; +constexpr char kAliveAction[] = "alive"; +constexpr char kStatusFieldName[] = "status"; +constexpr char kTimestampFieldName[] = "t"; + bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); if (value_str && !value_str->empty()) { @@ -158,7 +162,7 @@ void GenerateSinglePayloads(const ServerConfig& server_config, } // namespace -std::vector GeneratePayloads( +std::vector GenerateQueryPayloads( const ServerConfig& server_config, RegexUtil& regex_util, const PatternsURLDetails* url_details, @@ -181,4 +185,16 @@ std::vector GeneratePayloads( return payloads; } +base::Value::Dict GenerateAlivePayload(const ServerConfig& server_config, + std::string date_hour) { + base::Value::Dict payload; + payload.Set(kActionKey, kAliveAction); + base::Value::Dict inner_payload; + inner_payload.Set(kStatusFieldName, true); + inner_payload.Set(kTimestampFieldName, date_hour); + inner_payload.Set(kCountryCodeFieldName, server_config.location); + payload.Set(kInnerPayloadKey, std::move(inner_payload)); + return payload; +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h index b4ee117a5d59..732eff6234fa 100644 --- a/components/web_discovery/browser/payload_generator.h +++ b/components/web_discovery/browser/payload_generator.h @@ -7,6 +7,7 @@ #define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ #include +#include #include #include "base/values.h" @@ -19,12 +20,15 @@ namespace web_discovery { inline constexpr char kActionKey[] = "action"; inline constexpr char kInnerPayloadKey[] = "payload"; -std::vector GeneratePayloads( +std::vector GenerateQueryPayloads( const ServerConfig& server_config, RegexUtil& regex_util, const PatternsURLDetails* url_details, std::unique_ptr scrape_result); +base::Value::Dict GenerateAlivePayload(const ServerConfig& server_config, + std::string date_hour); + } // namespace web_discovery #endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index d71051d1c684..3734d8ae88b0 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -21,6 +21,7 @@ inline constexpr char kScheduledReports[] = "brave.web_discovery.scheduled_reports"; inline constexpr char kUsedBasenameCounts[] = "brave.web_discovery.used_basename_counts"; +inline constexpr char kPageCounts[] = "brave.web_discovery.page_counts"; // Local state inline constexpr char kPatternsRetrievalTime[] = diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index 6d05d8e00737..4de17fecdeda 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -189,7 +189,7 @@ void Reporter::PrepareRequest(const base::Value& request_data) { void Reporter::OnRequestSigned( std::string final_payload_json, - uint8_t count_tag_hash, + uint32_t count_tag_hash, size_t basename_count, std::optional> signature) { if (!signature) { @@ -226,7 +226,7 @@ void Reporter::OnRequestSigned( } void Reporter::OnRequestCompressedAndEncrypted( - uint8_t count_tag_hash, + uint32_t count_tag_hash, size_t basename_count, std::optional result) { if (!result) { @@ -255,7 +255,7 @@ void Reporter::OnRequestCompressedAndEncrypted( } void Reporter::OnRequestComplete( - uint8_t count_tag_hash, + uint32_t count_tag_hash, size_t basename_count, scoped_refptr headers) { auto result = ValidateResponse(headers); diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index 7341a0c16780..1c5f5e016653 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -46,13 +46,13 @@ class Reporter { private: void PrepareRequest(const base::Value& request_data); void OnRequestSigned(std::string final_payload_json, - uint8_t count_tag_hash, + uint32_t count_tag_hash, size_t basename_count, std::optional> signature); - void OnRequestCompressedAndEncrypted(uint8_t count_tag_hash, + void OnRequestCompressedAndEncrypted(uint32_t count_tag_hash, size_t basename_count, std::optional result); - void OnRequestComplete(uint8_t count_tag_hash, + void OnRequestComplete(uint32_t count_tag_hash, size_t basename_count, scoped_refptr headers); bool ValidateResponse(scoped_refptr headers); diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc index 8c9bc295e2c3..02fd9c2d6f6c 100644 --- a/components/web_discovery/browser/signature_basename.cc +++ b/components/web_discovery/browser/signature_basename.cc @@ -120,8 +120,7 @@ std::optional GetBasenameCount(PrefService* profile_prefs, auto* used_counts_list = count_dict->EnsureList(kUsedCountsKey); if (used_counts_list->size() >= action_config.limit) { - VLOG(1) << "used count = " << used_counts_list - << ", limit = " << action_config.limit; + VLOG(1) << "No basename counts left"; return std::nullopt; } diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 8da9d0d9d2ab..20fb28d44468 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -8,6 +8,7 @@ #include #include "base/functional/bind.h" +#include "base/strings/stringprintf.h" #include "brave/components/constants/pref_names.h" #include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/payload_generator.h" @@ -16,6 +17,7 @@ #include "brave/components/web_discovery/browser/server_config_loader.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -23,6 +25,12 @@ namespace web_discovery { +namespace { +// constexpr base::TimeDelta kAliveCheckInterval = base::Minutes(5); +constexpr base::TimeDelta kAliveCheckInterval = base::Seconds(10); +constexpr size_t kMinPageCountForAliveMessage = 2; +} // namespace + WDPService::WDPService( PrefService* local_state, PrefService* profile_prefs, @@ -55,6 +63,7 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterListPref(kScheduledDoubleFetches); registry->RegisterListPref(kScheduledReports); registry->RegisterDictionaryPref(kUsedBasenameCounts); + registry->RegisterDictionaryPref(kPageCounts); } void WDPService::Start() { @@ -75,6 +84,7 @@ void WDPService::Stop() { server_config_loader_ = nullptr; credential_manager_ = nullptr; last_loaded_server_config_ = nullptr; + alive_message_timer_.Stop(); } void WDPService::OnEnabledChange() { @@ -101,6 +111,7 @@ void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { reporter_ = std::make_unique( profile_prefs_.get(), shared_url_loader_factory_.get(), credential_manager_.get(), ®ex_util_, &last_loaded_server_config_); + MaybeSendAliveMessage(); } void WDPService::OnDoubleFetched(const GURL& url, @@ -122,11 +133,19 @@ void WDPService::OnDoubleFetched(const GURL& url, void WDPService::OnFinishNavigation( const GURL& url, content::RenderFrameHost* render_frame_host) { - if (!content_scraper_) { + if (!content_scraper_ || !last_loaded_patterns_) { return; } const auto* matching_url_details = last_loaded_patterns_->GetMatchingURLPattern(url, false); + if (!matching_url_details || !matching_url_details->is_search_engine) { + if (!current_page_count_hour_key_.empty()) { + ScopedDictPrefUpdate page_count_update(profile_prefs_, kPageCounts); + auto existing_count = + page_count_update->FindInt(current_page_count_hour_key_).value_or(0); + page_count_update->Set(current_page_count_hour_key_, existing_count + 1); + } + } if (!matching_url_details) { return; } @@ -170,11 +189,57 @@ void WDPService::OnContentScraped(bool is_strict, double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); } } - auto payloads = GeneratePayloads(*last_loaded_server_config_, regex_util_, - original_url_details, std::move(result)); + auto payloads = + GenerateQueryPayloads(*last_loaded_server_config_, regex_util_, + original_url_details, std::move(result)); for (auto& payload : payloads) { reporter_->ScheduleSend(std::move(payload)); } } +bool WDPService::UpdatePageCountStartTime() { + auto now = base::Time::Now(); + if (!current_page_count_start_time_.is_null() && + (now - current_page_count_start_time_) < base::Hours(1)) { + return false; + } + base::Time::Exploded exploded; + now.UTCExplode(&exploded); + exploded.millisecond = 0; + exploded.second = 0; + exploded.minute = 0; + if (!base::Time::FromUTCExploded(exploded, ¤t_page_count_start_time_)) { + return false; + } + current_page_count_hour_key_ = + base::StringPrintf("%04d%02d%02d%02d", exploded.year, exploded.month, + exploded.day_of_month, exploded.hour); + return true; +} + +void WDPService::MaybeSendAliveMessage() { + if (!alive_message_timer_.IsRunning()) { + alive_message_timer_.Start( + FROM_HERE, kAliveCheckInterval, + base::BindRepeating(&WDPService::MaybeSendAliveMessage, + base::Unretained(this))); + } + if (!UpdatePageCountStartTime()) { + return; + } + ScopedDictPrefUpdate update(profile_prefs_, kPageCounts); + for (auto it = update->begin(); it != update->end();) { + if (it->first == current_page_count_hour_key_) { + it++; + continue; + } + if (it->second.is_int() && static_cast(it->second.GetInt()) >= + kMinPageCountForAliveMessage) { + reporter_->ScheduleSend( + GenerateAlivePayload(*last_loaded_server_config_, it->first)); + } + it = update->erase(it); + } +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 3d223a499a27..97043fe071eb 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -68,6 +68,9 @@ class WDPService : public KeyedService { const base::Value& associated_data, std::optional response_body); + bool UpdatePageCountStartTime(); + void MaybeSendAliveMessage(); + raw_ptr local_state_; raw_ptr profile_prefs_; PrefChangeRegistrar pref_change_registrar_; @@ -88,6 +91,10 @@ class WDPService : public KeyedService { std::unique_ptr content_scraper_; std::unique_ptr double_fetcher_; std::unique_ptr reporter_; + + base::Time current_page_count_start_time_; + std::string current_page_count_hour_key_; + base::RepeatingTimer alive_message_timer_; }; } // namespace web_discovery From 102e55e201f9c2e6a82327fac62216ac7c2e10fc Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 13 Jun 2024 16:54:14 -0700 Subject: [PATCH 21/36] Move ownership of Web Discovery ServerConfig and PatternsGroup to ServerConfigLoader --- .../web_discovery/browser/content_scraper.cc | 23 +++--- .../web_discovery/browser/content_scraper.h | 6 +- .../browser/credential_manager.cc | 11 ++- .../browser/credential_manager.h | 4 +- components/web_discovery/browser/patterns.cc | 2 +- components/web_discovery/browser/patterns.h | 2 +- components/web_discovery/browser/reporter.cc | 17 ++--- components/web_discovery/browser/reporter.h | 4 +- .../browser/server_config_loader.cc | 40 +++++++---- .../browser/server_config_loader.h | 28 +++++--- .../browser/signature_basename.cc | 16 ++--- .../browser/signature_basename.h | 2 +- .../web_discovery/browser/wdp_service.cc | 72 +++++++++++-------- .../web_discovery/browser/wdp_service.h | 8 +-- 14 files changed, 129 insertions(+), 106 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.cc b/components/web_discovery/browser/content_scraper.cc index 87154b57123a..ad8310ec4e6d 100644 --- a/components/web_discovery/browser/content_scraper.cc +++ b/components/web_discovery/browser/content_scraper.cc @@ -92,14 +92,11 @@ PageScrapeResult::PageScrapeResult(GURL url, std::string id) : url(url), id(id) {} PageScrapeResult::~PageScrapeResult() = default; -ContentScraper::ContentScraper( - std::unique_ptr* last_loaded_server_config, - std::unique_ptr* patterns, - RegexUtil* regex_util) +ContentScraper::ContentScraper(const ServerConfigLoader* server_config_loader, + RegexUtil* regex_util) : pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), - last_loaded_server_config_(last_loaded_server_config), - patterns_(patterns), + server_config_loader_(server_config_loader), regex_util_(regex_util) {} ContentScraper::~ContentScraper() = default; @@ -159,7 +156,8 @@ void ContentScraper::ScrapePage(const GURL& url, mojom::DocumentExtractor* document_extractor, PageScrapeResultCallback callback) { const auto* url_details = - (*patterns_)->GetMatchingURLPattern(url, is_strict_scrape); + server_config_loader_->GetLastPatterns().GetMatchingURLPattern( + url, is_strict_scrape); if (!url_details) { return; } @@ -201,7 +199,8 @@ void ContentScraper::ParseAndScrapePage( std::string html, PageScrapeResultCallback callback) { const auto* url_details = - (*patterns_)->GetMatchingURLPattern(url, is_strict_scrape); + server_config_loader_->GetLastPatterns().GetMatchingURLPattern( + url, is_strict_scrape); if (!url_details) { return; } @@ -245,7 +244,7 @@ void ContentScraper::ProcessStandardRule(const std::string& report_key, if (rule.attribute == kUrlAttrId) { value = url.spec(); } else if (rule.attribute == kCountryCodeAttrId) { - value = (*last_loaded_server_config_)->location; + value = server_config_loader_->GetLastServerConfig().location; } auto refined_value = ExecuteRefineFunctions(rule.functions_applied, value); if (!refined_value) { @@ -264,7 +263,8 @@ void ContentScraper::OnScrapedElementAttributes( PageScrapeResultCallback callback, std::vector attribute_results) { const auto* url_details = - (*patterns_)->GetMatchingURLPattern(scrape_result->url, is_strict_scrape); + server_config_loader_->GetLastPatterns().GetMatchingURLPattern( + scrape_result->url, is_strict_scrape); if (!url_details) { return; } @@ -291,7 +291,8 @@ void ContentScraper::OnRustElementAttributes( PageScrapeResultCallback callback, rust::Vec attribute_results) { const auto* url_details = - (*patterns_)->GetMatchingURLPattern(scrape_result->url, is_strict_scrape); + server_config_loader_->GetLastPatterns().GetMatchingURLPattern( + scrape_result->url, is_strict_scrape); if (!url_details) { return; } diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index 380fbb7e39f6..980db82b15b4 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -46,8 +46,7 @@ class ContentScraper { using PageScrapeResultCallback = base::OnceCallback)>; - ContentScraper(std::unique_ptr* last_loaded_server_config, - std::unique_ptr* patterns, + ContentScraper(const ServerConfigLoader* server_config_loader, RegexUtil* regex_util); ~ContentScraper(); @@ -94,8 +93,7 @@ class ContentScraper { scoped_refptr pool_sequenced_task_runner_; - raw_ptr> last_loaded_server_config_; - raw_ptr> patterns_; + raw_ptr server_config_loader_; raw_ptr regex_util_; base::WeakPtrFactory weak_ptr_factory_{this}; diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 8812241f107b..de61a86db995 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -132,10 +132,10 @@ std::optional> PerformSign( CredentialManager::CredentialManager( PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - std::unique_ptr* last_loaded_server_config) + const ServerConfigLoader* server_config_loader) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), - last_loaded_server_config_(last_loaded_server_config), + server_config_loader_(server_config_loader), join_url_(GetDirectHPNHost() + kJoinPath), backoff_entry_(&kBackoffPolicy), pool_sequenced_task_runner_( @@ -186,14 +186,11 @@ void CredentialManager::OnNewRSAKey(std::unique_ptr key_info) { } void CredentialManager::JoinGroups() { - if (!*last_loaded_server_config_) { - return; - } + const auto& server_config = server_config_loader_->GetLastServerConfig(); auto today_date = FormatServerDate(base::Time::Now().UTCMidnight()); const auto& anon_creds_dict = profile_prefs_->GetDict(kAnonymousCredentialsDict); - for (const auto& [date, group_pub_key_b64] : - (*last_loaded_server_config_)->group_pub_keys) { + for (const auto& [date, group_pub_key_b64] : server_config.group_pub_keys) { if (date < today_date || join_url_loaders_.contains(date) || anon_creds_dict.contains(date)) { continue; diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index 5301a3b4e9cd..9e2defacb09e 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -40,7 +40,7 @@ class CredentialManager { base::OnceCallback>)>; CredentialManager(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - std::unique_ptr* last_loaded_server_config); + const ServerConfigLoader* server_config_loader); ~CredentialManager(); CredentialManager(const CredentialManager&) = delete; @@ -85,7 +85,7 @@ class CredentialManager { raw_ptr profile_prefs_; raw_ptr shared_url_loader_factory_; - raw_ptr> last_loaded_server_config_; + raw_ptr server_config_loader_; GURL join_url_; base::flat_map> diff --git a/components/web_discovery/browser/patterns.cc b/components/web_discovery/browser/patterns.cc index e7b747168b88..34cce886417e 100644 --- a/components/web_discovery/browser/patterns.cc +++ b/components/web_discovery/browser/patterns.cc @@ -274,7 +274,7 @@ PatternsGroup::~PatternsGroup() = default; const PatternsURLDetails* PatternsGroup::GetMatchingURLPattern( const GURL& url, - bool is_strict_scrape) { + bool is_strict_scrape) const { const auto& patterns = is_strict_scrape ? strict_patterns : normal_patterns; for (const auto& pattern : patterns) { if (re2::RE2::PartialMatch(url.spec(), *pattern.url_regex) && diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index e63aa1824afe..ff7c614b2992 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -93,7 +93,7 @@ struct PatternsGroup { PatternsGroup& operator=(const PatternsGroup&) = delete; const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, - bool is_strict_scrape); + bool is_strict_scrape) const; std::vector normal_patterns; std::vector strict_patterns; diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index 4de17fecdeda..3b04e00528a1 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -121,12 +121,12 @@ Reporter::Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, CredentialManager* credential_manager, RegexUtil* regex_util, - std::unique_ptr* last_loaded_server_config) + const ServerConfigLoader* server_config_loader) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), - last_loaded_server_config_(last_loaded_server_config), credential_manager_(credential_manager), regex_util_(regex_util), + server_config_loader_(server_config_loader), pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({})), request_queue_(profile_prefs, @@ -161,9 +161,9 @@ void Reporter::PrepareRequest(const base::Value& request_data) { request_queue_.NotifyRequestComplete(true); return; } - auto basename_result = - GenerateBasename(profile_prefs_, (*last_loaded_server_config_).get(), - *regex_util_, *payload_dict); + auto basename_result = GenerateBasename( + profile_prefs_, server_config_loader_->GetLastServerConfig(), + *regex_util_, *payload_dict); if (!basename_result) { // Drop request due to exceeded basename quota VLOG(1) << "Failed to generate basename"; @@ -196,9 +196,10 @@ void Reporter::OnRequestSigned( request_queue_.NotifyRequestComplete(false); return; } - auto pub_key = (*last_loaded_server_config_) - ->pub_keys.find(FormatServerDate(base::Time::Now())); - if (pub_key == (*last_loaded_server_config_)->pub_keys.end()) { + const auto& server_config = server_config_loader_->GetLastServerConfig(); + auto pub_key = + server_config.pub_keys.find(FormatServerDate(base::Time::Now())); + if (pub_key == server_config.pub_keys.end()) { VLOG(1) << "No ECDH server public key available"; request_queue_.NotifyRequestComplete(false); return; diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index 1c5f5e016653..85eb398607ae 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -35,7 +35,7 @@ class Reporter { network::SharedURLLoaderFactory* shared_url_loader_factory, CredentialManager* credential_manager, RegexUtil* regex_util, - std::unique_ptr* last_loaded_server_config); + const ServerConfigLoader* server_config_loader); ~Reporter(); Reporter(const Reporter&) = delete; @@ -61,10 +61,10 @@ class Reporter { raw_ptr profile_prefs_; raw_ptr shared_url_loader_factory_; - raw_ptr> last_loaded_server_config_; raw_ptr credential_manager_; raw_ptr regex_util_; + raw_ptr server_config_loader_; scoped_refptr pool_sequenced_task_runner_; diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index be13c9dcb878..8a3787ba7937 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -93,28 +93,31 @@ KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { return map; } -base::flat_map ParseSourceMapActionConfigs( - const base::Value::Dict& configs_dict) { - base::flat_map map; +base::flat_map> +ParseSourceMapActionConfigs(const base::Value::Dict& configs_dict) { + base::flat_map> map; for (const auto [action, config_dict_val] : configs_dict) { auto* config_dict = config_dict_val.GetIfDict(); if (!config_dict) { continue; } auto& action_config = map[action]; + if (!action_config) { + action_config = std::make_unique(); + } auto* keys_list = config_dict->FindList(kKeysFieldName); if (keys_list) { for (const auto& key_val : *keys_list) { if (key_val.is_string()) { - action_config.keys.push_back(key_val.GetString()); + action_config->keys.push_back(key_val.GetString()); } } } auto limit = config_dict->FindInt(kLimitFieldName); auto period = config_dict->FindInt(kPeriodFieldName); - action_config.limit = limit && limit > 0 ? *limit : 1; - action_config.period = period && period > 0 ? *period : 24; + action_config->limit = limit && limit > 0 ? *limit : 1; + action_config->period = period && period > 0 ? *period : 24; } return map; } @@ -144,8 +147,6 @@ std::optional ReadPatternsFile(base::FilePath patterns_path) { SourceMapActionConfig::SourceMapActionConfig() = default; SourceMapActionConfig::~SourceMapActionConfig() = default; -SourceMapActionConfig::SourceMapActionConfig(const SourceMapActionConfig&) = - default; ServerConfig::ServerConfig() = default; ServerConfig::~ServerConfig() = default; @@ -154,8 +155,8 @@ ServerConfigLoader::ServerConfigLoader( PrefService* local_state, base::FilePath user_data_dir, network::SharedURLLoaderFactory* shared_url_loader_factory, - ConfigCallback config_callback, - PatternsCallback patterns_callback) + base::RepeatingClosure config_callback, + base::RepeatingClosure patterns_callback) : local_state_(local_state), pool_sequenced_task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), @@ -175,6 +176,16 @@ ServerConfigLoader::ServerConfigLoader( ServerConfigLoader::~ServerConfigLoader() = default; +const ServerConfig& ServerConfigLoader::GetLastServerConfig() const { + CHECK(last_loaded_server_config_); + return *last_loaded_server_config_; +} + +const PatternsGroup& ServerConfigLoader::GetLastPatterns() const { + CHECK(last_loaded_patterns_); + return *last_loaded_patterns_; +} + void ServerConfigLoader::LoadConfigs() { if (collector_config_url_loader_ || quorum_config_url_loader_) { // Another request is in progress @@ -287,7 +298,8 @@ bool ServerConfigLoader::ProcessConfigResponses( config->pub_keys = ParseKeys(*pub_keys); config->source_map_actions = ParseSourceMapActionConfigs(*source_map_actions); - config_callback_.Run(std::move(config)); + last_loaded_server_config_ = std::move(config); + config_callback_.Run(); return true; } @@ -312,7 +324,8 @@ void ServerConfigLoader::OnPatternsFileLoaded( SchedulePatternsRequest(); return; } - patterns_callback_.Run(std::move(parsed_patterns)); + last_loaded_patterns_ = std::move(parsed_patterns); + patterns_callback_.Run(); } void ServerConfigLoader::SchedulePatternsRequest() { @@ -412,7 +425,8 @@ void ServerConfigLoader::OnPatternsWritten( } local_state_->SetTime(kPatternsRetrievalTime, base::Time::Now()); HandlePatternsStatus(true); - patterns_callback_.Run(std::move(parsed_group)); + last_loaded_patterns_ = std::move(parsed_group); + patterns_callback_.Run(); } } // namespace web_discovery diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 87bbf3448486..290ecf206f3f 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -34,7 +34,8 @@ struct SourceMapActionConfig { SourceMapActionConfig(); ~SourceMapActionConfig(); - SourceMapActionConfig(const SourceMapActionConfig&); + SourceMapActionConfig(const SourceMapActionConfig&) = delete; + SourceMapActionConfig& operator=(const SourceMapActionConfig&) = delete; std::vector keys; size_t limit; @@ -45,32 +46,34 @@ struct ServerConfig { ServerConfig(); ~ServerConfig(); + ServerConfig(const ServerConfig&) = delete; + ServerConfig& operator=(const ServerConfig&) = delete; + KeyMap group_pub_keys; KeyMap pub_keys; - base::flat_map source_map_actions; + base::flat_map> + source_map_actions; std::string location; }; class ServerConfigLoader { public: - using ConfigCallback = - base::RepeatingCallback)>; - using PatternsCallback = - base::RepeatingCallback)>; - explicit ServerConfigLoader( PrefService* local_state, base::FilePath user_data_dir, network::SharedURLLoaderFactory* shared_url_loader_factory, - ConfigCallback config_callback, - PatternsCallback patterns_callback); + base::RepeatingClosure config_callback, + base::RepeatingClosure patterns_callback); ~ServerConfigLoader(); ServerConfigLoader(const ServerConfigLoader&) = delete; ServerConfigLoader& operator=(const ServerConfigLoader&) = delete; + const ServerConfig& GetLastServerConfig() const; + const PatternsGroup& GetLastPatterns() const; + private: void LoadConfigs(); void OnConfigResponses( @@ -99,8 +102,8 @@ class ServerConfigLoader { base::FilePath patterns_path_; raw_ptr shared_url_loader_factory_; - ConfigCallback config_callback_; - PatternsCallback patterns_callback_; + base::RepeatingClosure config_callback_; + base::RepeatingClosure patterns_callback_; std::unique_ptr collector_config_url_loader_; std::unique_ptr quorum_config_url_loader_; @@ -112,6 +115,9 @@ class ServerConfigLoader { base::WallClockTimer patterns_update_timer_; bool patterns_first_request_made_ = false; + std::unique_ptr last_loaded_server_config_; + std::unique_ptr last_loaded_patterns_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/components/web_discovery/browser/signature_basename.cc b/components/web_discovery/browser/signature_basename.cc index 02fd9c2d6f6c..06cc4127ebe7 100644 --- a/components/web_discovery/browser/signature_basename.cc +++ b/components/web_discovery/browser/signature_basename.cc @@ -145,7 +145,7 @@ BasenameResult::~BasenameResult() = default; std::optional GenerateBasename( PrefService* profile_prefs, - ServerConfig* server_config, + const ServerConfig& server_config, RegexUtil& regex_util, const base::Value::Dict& payload) { const std::string* action = payload.FindString(kActionKey); @@ -155,8 +155,8 @@ std::optional GenerateBasename( VLOG(1) << "No action"; return std::nullopt; } - const auto action_config = server_config->source_map_actions.find(*action); - if (action_config == server_config->source_map_actions.end()) { + const auto action_config = server_config.source_map_actions.find(*action); + if (action_config == server_config.source_map_actions.end()) { VLOG(1) << "No action config for " << action; return std::nullopt; } @@ -167,11 +167,11 @@ std::optional GenerateBasename( } base::Value::List tag_list; tag_list.Append(*action); - tag_list.Append(static_cast(action_config->second.period)); - tag_list.Append(static_cast(action_config->second.limit)); + tag_list.Append(static_cast(action_config->second->period)); + tag_list.Append(static_cast(action_config->second->limit)); base::Value::List key_values; - for (const auto& key : action_config->second.keys) { + for (const auto& key : action_config->second->keys) { auto parts = base::SplitStringUsingSubstr( key, "->", base::WhitespaceHandling::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); @@ -195,7 +195,7 @@ std::optional GenerateBasename( key_values.Append(std::move(value)); } - auto period_hours = GetPeriodHoursSinceEpoch(action_config->second.period); + auto period_hours = GetPeriodHoursSinceEpoch(action_config->second->period); tag_list.Append(std::move(key_values)); tag_list.Append(period_hours); @@ -206,7 +206,7 @@ std::optional GenerateBasename( } auto count_tag_hash = base::PersistentHash(interim_tag_json); auto basename_count = GetBasenameCount(profile_prefs, count_tag_hash, - action_config->second, period_hours); + *action_config->second, period_hours); if (!basename_count) { VLOG(1) << "No basename count available"; return std::nullopt; diff --git a/components/web_discovery/browser/signature_basename.h b/components/web_discovery/browser/signature_basename.h index 1422b2398d2d..fb6101608649 100644 --- a/components/web_discovery/browser/signature_basename.h +++ b/components/web_discovery/browser/signature_basename.h @@ -35,7 +35,7 @@ struct BasenameResult { std::optional GenerateBasename( PrefService* profile_prefs, - ServerConfig* server_config, + const ServerConfig& server_config, RegexUtil& regex_util, const base::Value::Dict& payload); diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 20fb28d44468..2ae68c91658e 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -67,14 +67,19 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { } void WDPService::Start() { - credential_manager_ = std::make_unique( - profile_prefs_, shared_url_loader_factory_.get(), - &last_loaded_server_config_); - server_config_loader_ = std::make_unique( - local_state_, user_data_dir_, shared_url_loader_factory_.get(), - base::BindRepeating(&WDPService::OnConfigChange, base::Unretained(this)), - base::BindRepeating(&WDPService::OnPatternsLoaded, - base::Unretained(this))); + if (!server_config_loader_) { + server_config_loader_ = std::make_unique( + local_state_, user_data_dir_, shared_url_loader_factory_.get(), + base::BindRepeating(&WDPService::OnConfigChange, + base::Unretained(this)), + base::BindRepeating(&WDPService::OnPatternsLoaded, + base::Unretained(this))); + } + if (!credential_manager_) { + credential_manager_ = std::make_unique( + profile_prefs_, shared_url_loader_factory_.get(), + server_config_loader_.get()); + } } void WDPService::Stop() { @@ -83,7 +88,6 @@ void WDPService::Stop() { content_scraper_ = nullptr; server_config_loader_ = nullptr; credential_manager_ = nullptr; - last_loaded_server_config_ = nullptr; alive_message_timer_.Stop(); } @@ -95,22 +99,26 @@ void WDPService::OnEnabledChange() { } } -void WDPService::OnConfigChange(std::unique_ptr config) { - last_loaded_server_config_ = std::move(config); +void WDPService::OnConfigChange() { credential_manager_->JoinGroups(); } -void WDPService::OnPatternsLoaded(std::unique_ptr patterns) { - last_loaded_patterns_ = std::move(patterns); - content_scraper_ = std::make_unique( - &last_loaded_server_config_, &last_loaded_patterns_, ®ex_util_); - double_fetcher_ = std::make_unique( - profile_prefs_.get(), shared_url_loader_factory_.get(), - base::BindRepeating(&WDPService::OnDoubleFetched, - base::Unretained(this))); - reporter_ = std::make_unique( - profile_prefs_.get(), shared_url_loader_factory_.get(), - credential_manager_.get(), ®ex_util_, &last_loaded_server_config_); +void WDPService::OnPatternsLoaded() { + if (!content_scraper_) { + content_scraper_ = std::make_unique( + server_config_loader_.get(), ®ex_util_); + } + if (!double_fetcher_) { + double_fetcher_ = std::make_unique( + profile_prefs_.get(), shared_url_loader_factory_.get(), + base::BindRepeating(&WDPService::OnDoubleFetched, + base::Unretained(this))); + } + if (!reporter_) { + reporter_ = std::make_unique( + profile_prefs_.get(), shared_url_loader_factory_.get(), + credential_manager_.get(), ®ex_util_, server_config_loader_.get()); + } MaybeSendAliveMessage(); } @@ -133,11 +141,12 @@ void WDPService::OnDoubleFetched(const GURL& url, void WDPService::OnFinishNavigation( const GURL& url, content::RenderFrameHost* render_frame_host) { - if (!content_scraper_ || !last_loaded_patterns_) { + if (!content_scraper_) { return; } const auto* matching_url_details = - last_loaded_patterns_->GetMatchingURLPattern(url, false); + server_config_loader_->GetLastPatterns().GetMatchingURLPattern(url, + false); if (!matching_url_details || !matching_url_details->is_search_engine) { if (!current_page_count_hour_key_.empty()) { ScopedDictPrefUpdate page_count_update(profile_prefs_, kPageCounts); @@ -168,14 +177,15 @@ void WDPService::OnContentScraped(bool is_strict, if (!result) { return; } + const auto& patterns = server_config_loader_->GetLastPatterns(); auto* original_url_details = - last_loaded_patterns_->GetMatchingURLPattern(result->url, is_strict); + patterns.GetMatchingURLPattern(result->url, is_strict); if (!original_url_details) { return; } if (!is_strict && original_url_details->is_search_engine) { auto* strict_url_details = - last_loaded_patterns_->GetMatchingURLPattern(result->url, true); + patterns.GetMatchingURLPattern(result->url, true); if (strict_url_details) { auto url = result->url; if (!result->query) { @@ -189,9 +199,9 @@ void WDPService::OnContentScraped(bool is_strict, double_fetcher_->ScheduleDoubleFetch(url, result->SerializeToValue()); } } - auto payloads = - GenerateQueryPayloads(*last_loaded_server_config_, regex_util_, - original_url_details, std::move(result)); + auto payloads = GenerateQueryPayloads( + server_config_loader_->GetLastServerConfig(), regex_util_, + original_url_details, std::move(result)); for (auto& payload : payloads) { reporter_->ScheduleSend(std::move(payload)); } @@ -235,8 +245,8 @@ void WDPService::MaybeSendAliveMessage() { } if (it->second.is_int() && static_cast(it->second.GetInt()) >= kMinPageCountForAliveMessage) { - reporter_->ScheduleSend( - GenerateAlivePayload(*last_loaded_server_config_, it->first)); + reporter_->ScheduleSend(GenerateAlivePayload( + server_config_loader_->GetLastServerConfig(), it->first)); } it = update->erase(it); } diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 97043fe071eb..33ffb8f596b7 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -15,7 +15,6 @@ #include "brave/components/web_discovery/browser/content_scraper.h" #include "brave/components/web_discovery/browser/credential_manager.h" #include "brave/components/web_discovery/browser/double_fetcher.h" -#include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/reporter.h" #include "brave/components/web_discovery/browser/server_config_loader.h" @@ -60,8 +59,8 @@ class WDPService : public KeyedService { void OnEnabledChange(); - void OnConfigChange(std::unique_ptr config); - void OnPatternsLoaded(std::unique_ptr patterns); + void OnConfigChange(); + void OnPatternsLoaded(); void OnContentScraped(bool is_strict, std::unique_ptr result); void OnDoubleFetched(const GURL& url, @@ -83,9 +82,6 @@ class WDPService : public KeyedService { mojo::RemoteSet document_extractor_remotes_; - std::unique_ptr last_loaded_server_config_; - std::unique_ptr last_loaded_patterns_; - std::unique_ptr server_config_loader_; std::unique_ptr credential_manager_; std::unique_ptr content_scraper_; From 52f3501c5f3754bb27c77a68398c6ab289ea96d3 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Fri, 14 Jun 2024 13:59:58 -0700 Subject: [PATCH 22/36] Only omit Web Discovery results for query actions --- .../web_discovery/browser/payload_generator.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index af02279b22c1..6b7111eb0615 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -7,6 +7,7 @@ #include +#include "base/containers/fixed_flat_set.h" #include "brave/components/web_discovery/browser/privacy_guard.h" namespace web_discovery { @@ -22,6 +23,9 @@ constexpr char kAliveAction[] = "alive"; constexpr char kStatusFieldName[] = "status"; constexpr char kTimestampFieldName[] = "t"; +constexpr auto kQueryActions = base::MakeFixedFlatSet( + {"query", "anon-query", "widgetTitle"}); + bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); if (value_str && !value_str->empty()) { @@ -80,6 +84,7 @@ base::Value::Dict CreatePayloadDict(const PayloadRuleGroup& rule_group, std::optional GenerateClusteredJoinedPayload( RegexUtil& regex_util, + bool is_query_action, const PayloadRule& rule, const PatternsURLDetails* matching_url_details, const std::vector& attribute_values) { @@ -89,7 +94,8 @@ std::optional GenerateClusteredJoinedPayload( if (value.empty()) { continue; } - if (IsPrivateResult(regex_util, rule, matching_url_details, value)) { + if (is_query_action && + IsPrivateResult(regex_util, rule, matching_url_details, value)) { VLOG(1) << "Omitting private search result"; continue; } @@ -99,7 +105,8 @@ std::optional GenerateClusteredJoinedPayload( VLOG(1) << "Skipped joined clustered payload due to lack of content"; return std::nullopt; } - if (ShouldDropSearchResultPayload(rule, joined_data.size())) { + if (is_query_action && + ShouldDropSearchResultPayload(rule, joined_data.size())) { VLOG(1) << "Skipped search result payload due to too few results"; return std::nullopt; } @@ -124,7 +131,8 @@ std::optional GenerateClusteredPayload( } if (rule.is_join) { auto joined_payload = GenerateClusteredJoinedPayload( - regex_util, rule, matching_url_details, attribute_values_it->second); + regex_util, kQueryActions.contains(rule_group.action), rule, + matching_url_details, attribute_values_it->second); if (!joined_payload) { VLOG(1) << "Skipped joined clustered payload, action = " << rule_group.action; From c6d22ad0f133cbb639f388451dee82856ed8f811 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 20 Jun 2024 16:33:25 -0700 Subject: [PATCH 23/36] Add first batch of Web Discovery tests --- components/web_discovery/browser/BUILD.gn | 35 ++ .../browser/content_scraper_browsertest.cc | 247 +++++++++++++ .../web_discovery/browser/double_fetcher.cc | 10 +- .../browser/double_fetcher_unittest.cc | 183 ++++++++++ .../browser/hash_detection_unittest.cc | 29 ++ components/web_discovery/browser/patterns.h | 1 - .../browser/patterns_unittest.cc | 345 ++++++++++++++++++ .../web_discovery/browser/privacy_guard.cc | 2 +- .../browser/privacy_guard_unittest.cc | 169 +++++++++ components/web_discovery/browser/reporter.cc | 10 +- .../web_discovery/browser/request_queue.cc | 2 +- .../browser/server_config_loader.cc | 11 +- .../browser/server_config_loader.h | 17 +- .../browser/signature_basename_unittest.cc | 249 +++++++++++++ .../web_discovery/browser/wdp_service.cc | 1 + test/BUILD.gn | 2 + test/data/web_discovery/page.html | 21 ++ test/data/web_discovery/patterns.json | 200 ++++++++++ 18 files changed, 1511 insertions(+), 23 deletions(-) create mode 100644 components/web_discovery/browser/content_scraper_browsertest.cc create mode 100644 components/web_discovery/browser/double_fetcher_unittest.cc create mode 100644 components/web_discovery/browser/hash_detection_unittest.cc create mode 100644 components/web_discovery/browser/patterns_unittest.cc create mode 100644 components/web_discovery/browser/privacy_guard_unittest.cc create mode 100644 components/web_discovery/browser/signature_basename_unittest.cc create mode 100644 test/data/web_discovery/page.html create mode 100644 test/data/web_discovery/patterns.json diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 711e1f8530f5..2d73d62ac128 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -60,3 +60,38 @@ static_library("browser") { "//url", ] } + +source_set("unit_tests") { + testonly = true + sources = [ + "double_fetcher_unittest.cc", + "hash_detection_unittest.cc", + "patterns_unittest.cc", + "privacy_guard_unittest.cc", + "signature_basename_unittest.cc", + ] + deps = [ + ":browser", + "//base/test:test_support", + "//brave/components/constants", + "//components/prefs:test_support", + "//crypto", + "//services/network:test_support", + "//services/network/public/cpp", + "//testing/gtest", + ] +} + +source_set("browser_tests") { + testonly = true + sources = [ "content_scraper_browsertest.cc" ] + deps = [ + ":browser", + "//base/test:test_support", + "//brave/components/constants", + "//brave/components/web_discovery/common:mojom", + "//chrome/test:test_support_ui", + "//testing/gtest", + ] + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] +} diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc new file mode 100644 index 000000000000..2c4593be4bd8 --- /dev/null +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -0,0 +1,247 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/content_scraper.h" + +#include +#include + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/test/bind.h" +#include "brave/components/constants/brave_paths.h" +#include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" +#include "brave/components/web_discovery/common/web_discovery.mojom.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test.h" +#include "net/dns/mock_host_resolver.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/re2/src/re2/re2.h" + +namespace web_discovery { + +class WebDiscoveryContentScraperTest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + base::FilePath data_path = + base::PathService::CheckedGet(brave::DIR_TEST_DATA); + data_path = data_path.AppendASCII("web_discovery"); + + host_resolver()->AddRule("*", "127.0.0.1"); + auto& test_server = embedded_https_test_server(); + test_server.ServeFilesFromDirectory(data_path); + ASSERT_TRUE(test_server.Start()); + + InitScraper(); + run_loop_ = std::make_unique(); + + ASSERT_TRUE( + base::ReadFileToString(data_path.Append("page.html"), &page_content_)); + } + + protected: + mojo::Remote LoadTestPageAndGetExtractor() { + mojo::Remote remote; + + auto url = embedded_https_test_server().GetURL("example.com", "/page.html"); + auto* render_frame_host = ui_test_utils::NavigateToURL(browser(), url); + + if (render_frame_host) { + render_frame_host->GetRemoteInterfaces()->GetInterface( + remote.BindNewPipeAndPassReceiver()); + } + return remote; + } + + std::string page_content_; + std::unique_ptr scraper_; + std::unique_ptr run_loop_; + + private: + void InitScraper() { + server_config_loader_ = std::make_unique( + nullptr, base::FilePath(), nullptr, base::DoNothing(), + base::DoNothing()); + auto server_config = std::make_unique(); + server_config->location = "us"; + server_config_loader_->SetLastServerConfigForTest(std::move(server_config)); + + auto patterns_group = std::make_unique(); + std::vector normal_patterns(1); + std::vector strict_patterns(1); + normal_patterns[0].url_regex = + std::make_unique("^https:\\/\\/example\\.com"); + normal_patterns[0].id = "ex1"; + strict_patterns[0].url_regex = + std::make_unique("^https:\\/\\/example\\.com"); + strict_patterns[0].id = "ex1"; + + auto* normal_rule_group = + &normal_patterns[0].scrape_rule_groups["#b .result1"]; + auto scrape_rule1 = std::make_unique(); + scrape_rule1->sub_selector = "a"; + scrape_rule1->rule_type = ScrapeRuleType::kOther; + scrape_rule1->attribute = "href"; + normal_rule_group->insert_or_assign("href", std::move(scrape_rule1)); + auto scrape_rule2 = std::make_unique(); + scrape_rule2->sub_selector = "a"; + scrape_rule2->rule_type = ScrapeRuleType::kOther; + scrape_rule2->attribute = "textContent"; + normal_rule_group->insert_or_assign("text", std::move(scrape_rule2)); + auto scrape_rule3 = std::make_unique(); + scrape_rule3->sub_selector = "#query"; + scrape_rule3->rule_type = ScrapeRuleType::kSearchQuery; + scrape_rule3->attribute = "textContent"; + normal_rule_group->insert_or_assign("q", std::move(scrape_rule3)); + normal_rule_group = &normal_patterns[0].scrape_rule_groups["dont>match"]; + auto scrape_rule4 = std::make_unique(); + scrape_rule4->rule_type = ScrapeRuleType::kStandard; + scrape_rule4->attribute = "url"; + scrape_rule4->functions_applied.emplace_back(); + scrape_rule4->functions_applied[0].push_back(base::Value("parseU")); + scrape_rule4->functions_applied[0].push_back(base::Value("qs")); + scrape_rule4->functions_applied[0].push_back(base::Value("q")); + + normal_rule_group->insert_or_assign("q2", std::move(scrape_rule4)); + + patterns_group->normal_patterns = std::move(normal_patterns); + + auto* strict_rule_group = + &strict_patterns[0].scrape_rule_groups["#b #result2"]; + scrape_rule1 = std::make_unique(); + scrape_rule1->sub_selector = "a"; + scrape_rule1->rule_type = ScrapeRuleType::kOther; + scrape_rule1->attribute = "textContent"; + strict_rule_group->insert_or_assign("text", std::move(scrape_rule1)); + scrape_rule2 = std::make_unique(); + scrape_rule2->sub_selector = "#input1"; + scrape_rule2->rule_type = ScrapeRuleType::kOther; + scrape_rule2->attribute = "value"; + strict_rule_group->insert_or_assign("input", std::move(scrape_rule2)); + strict_rule_group = &strict_patterns[0].scrape_rule_groups["dont>match"]; + scrape_rule3 = std::make_unique(); + scrape_rule3->rule_type = ScrapeRuleType::kStandard; + scrape_rule3->attribute = "ctry"; + strict_rule_group->insert_or_assign("ctry", std::move(scrape_rule3)); + + patterns_group->strict_patterns = std::move(strict_patterns); + + server_config_loader_->SetLastPatternsForTest(std::move(patterns_group)); + + scraper_ = std::make_unique(server_config_loader_.get(), + ®ex_util_); + } + + RegexUtil regex_util_; + std::unique_ptr server_config_loader_; +}; + +IN_PROC_BROWSER_TEST_F(WebDiscoveryContentScraperTest, RendererScrape) { + auto extractor = LoadTestPageAndGetExtractor(); + ASSERT_TRUE(extractor.is_bound() && extractor.is_connected()); + + GURL url("https://example.com/page?q=testquery"); + scraper_->ScrapePage( + url, false, extractor.get(), + base::BindLambdaForTesting( + [&](std::unique_ptr scrape_result) { + [&] { + ASSERT_TRUE(scrape_result); + EXPECT_EQ(scrape_result->url, url); + EXPECT_EQ(scrape_result->fields.size(), 2u); + EXPECT_EQ(scrape_result->id, "ex1"); + + EXPECT_EQ(scrape_result->query, "A query"); + + auto field_map_it = scrape_result->fields.find("#b .result1"); + ASSERT_TRUE(field_map_it != scrape_result->fields.end()); + const auto* fields = &field_map_it->second; + + ASSERT_EQ(fields->size(), 2u); + + const auto* href_value = (*fields)[0].FindString("href"); + const auto* text_value = (*fields)[0].FindString("text"); + const auto* query_value_str = (*fields)[0].FindString("q"); + ASSERT_TRUE(href_value); + ASSERT_TRUE(text_value); + ASSERT_TRUE(query_value_str); + EXPECT_EQ(*href_value, "https://example.com/foo1"); + EXPECT_EQ(*text_value, "Foo1"); + EXPECT_EQ(*query_value_str, "A query"); + + href_value = (*fields)[1].FindString("href"); + text_value = (*fields)[1].FindString("text"); + const auto* query_value = (*fields)[1].Find("q"); + ASSERT_TRUE(href_value); + ASSERT_TRUE(text_value); + ASSERT_TRUE(query_value); + EXPECT_EQ(*href_value, "https://example.com/foo2"); + EXPECT_EQ(*text_value, "Foo2"); + EXPECT_TRUE(query_value->is_none()); + + field_map_it = scrape_result->fields.find("dont>match"); + ASSERT_TRUE(field_map_it != scrape_result->fields.end()); + fields = &field_map_it->second; + + ASSERT_EQ(fields->size(), 1u); + const auto* url_query_value = (*fields)[0].FindString("q2"); + ASSERT_TRUE(url_query_value); + EXPECT_EQ(*url_query_value, "testquery"); + }(); + run_loop_->Quit(); + })); + run_loop_->Run(); +} + +IN_PROC_BROWSER_TEST_F(WebDiscoveryContentScraperTest, RustParseAndScrape) { + GURL url("https://example.com/page.html"); + + auto prev_scrape_result = std::make_unique(url, "ex1"); + scraper_->ParseAndScrapePage( + url, true, std::move(prev_scrape_result), page_content_, + base::BindLambdaForTesting( + [&](std::unique_ptr scrape_result) { + [&] { + ASSERT_TRUE(scrape_result); + EXPECT_EQ(scrape_result->url, url); + EXPECT_EQ(scrape_result->fields.size(), 2u); + EXPECT_EQ(scrape_result->id, "ex1"); + + EXPECT_FALSE(scrape_result->query); + + auto field_map_it = scrape_result->fields.find("#b #result2"); + ASSERT_TRUE(field_map_it != scrape_result->fields.end()); + const auto* fields = &field_map_it->second; + + ASSERT_EQ(fields->size(), 1u); + + const auto* text_value = (*fields)[0].FindString("text"); + const auto* input_value = (*fields)[0].FindString("input"); + ASSERT_TRUE(text_value); + ASSERT_TRUE(input_value); + EXPECT_EQ(*text_value, "Foo3"); + EXPECT_EQ(*input_value, "Foo4"); + + field_map_it = scrape_result->fields.find("dont>match"); + ASSERT_TRUE(field_map_it != scrape_result->fields.end()); + fields = &field_map_it->second; + + ASSERT_EQ(fields->size(), 1u); + + const auto* ctry_value = (*fields)[0].FindString("ctry"); + ASSERT_TRUE(ctry_value); + EXPECT_EQ(*ctry_value, "us"); + }(); + run_loop_->Quit(); + })); + run_loop_->Run(); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index 3dc902a50d25..ab04b56c6e6b 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -22,12 +22,10 @@ constexpr char kUrlKey[] = "url"; constexpr char kAssociatedDataKey[] = "assoc_data"; constexpr base::TimeDelta kRequestMaxAge = base::Hours(1); -// constexpr base::TimeDelta kMinRequestInterval = -// base::Minutes(1) - base::Seconds(5); -// constexpr base::TimeDelta kMaxRequestInterval = -// base::Minutes(1) + base::Seconds(5); -constexpr base::TimeDelta kMinRequestInterval = base::Seconds(5); -constexpr base::TimeDelta kMaxRequestInterval = base::Seconds(6); +constexpr base::TimeDelta kMinRequestInterval = + base::Minutes(1) - base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = + base::Minutes(1) + base::Seconds(5); constexpr size_t kMaxRetries = 3; constexpr size_t kMaxDoubleFetchResponseSize = 2 * 1024 * 1024; diff --git a/components/web_discovery/browser/double_fetcher_unittest.cc b/components/web_discovery/browser/double_fetcher_unittest.cc new file mode 100644 index 000000000000..bfd08244f808 --- /dev/null +++ b/components/web_discovery/browser/double_fetcher_unittest.cc @@ -0,0 +1,183 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/double_fetcher.h" + +#include +#include +#include +#include + +#include "base/functional/bind.h" +#include "base/memory/scoped_refptr.h" +#include "base/test/task_environment.h" +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/testing_pref_service.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +namespace { +constexpr char kTestUrl[] = "https://example.com/test"; +constexpr char kTestResponseText[] = "test"; +} // namespace + +class WebDiscoveryDoubleFetcherTest : public testing::Test { + public: + WebDiscoveryDoubleFetcherTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), + shared_url_loader_factory_( + base::MakeRefCounted( + &url_loader_factory_)) {} + ~WebDiscoveryDoubleFetcherTest() override = default; + + // testing::Test: + void SetUp() override { + WDPService::RegisterProfilePrefs(profile_prefs_.registry()); + + InitDoubleFetcher(); + SetUpResponse(net::HTTP_OK); + } + + protected: + void InitDoubleFetcher() { + double_fetcher_ = std::make_unique( + &profile_prefs_, shared_url_loader_factory_.get(), + base::BindRepeating(&WebDiscoveryDoubleFetcherTest::HandleDoubleFetch, + base::Unretained(this))); + } + + void SetUpResponse(net::HttpStatusCode status) { + url_loader_factory_.ClearResponses(); + url_loader_factory_.AddResponse(kTestUrl, kTestResponseText, status); + } + + base::test::TaskEnvironment task_environment_; + struct CompletedFetch { + GURL url; + base::Value associated_data; + std::optional response_body; + }; + std::unique_ptr double_fetcher_; + std::vector completed_fetches_; + network::TestURLLoaderFactory url_loader_factory_; + + private: + void HandleDoubleFetch(const GURL& url, + const base::Value& associated_data, + std::optional response_body) { + completed_fetches_.push_back( + CompletedFetch{.url = url, + .associated_data = associated_data.Clone(), + .response_body = response_body}); + } + + TestingPrefServiceSimple profile_prefs_; + scoped_refptr shared_url_loader_factory_; +}; + +TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleAndFetch) { + GURL url(kTestUrl); + double_fetcher_->ScheduleDoubleFetch(url, base::Value("foo1 data")); + double_fetcher_->ScheduleDoubleFetch(url, base::Value("foo2 data")); + + task_environment_.FastForwardBy(base::Seconds(45)); + EXPECT_TRUE(completed_fetches_.empty()); + + task_environment_.FastForwardBy(base::Seconds(30)); + ASSERT_EQ(completed_fetches_.size(), 1u); + + EXPECT_EQ(completed_fetches_[0].url, url); + EXPECT_EQ(completed_fetches_[0].associated_data, base::Value("foo1 data")); + ASSERT_TRUE(completed_fetches_[0].response_body); + EXPECT_EQ(*completed_fetches_[0].response_body, kTestResponseText); + + completed_fetches_.clear(); + + task_environment_.FastForwardBy(base::Seconds(25)); + EXPECT_TRUE(completed_fetches_.empty()); + + task_environment_.FastForwardBy(base::Seconds(45)); + ASSERT_EQ(completed_fetches_.size(), 1u); + + EXPECT_EQ(completed_fetches_[0].url, url); + EXPECT_EQ(completed_fetches_[0].associated_data, base::Value("foo2 data")); + ASSERT_TRUE(completed_fetches_[0].response_body); + EXPECT_EQ(*completed_fetches_[0].response_body, kTestResponseText); + + completed_fetches_.clear(); + + task_environment_.FastForwardBy(base::Seconds(180)); + EXPECT_TRUE(completed_fetches_.empty()); +} + +TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleRetry) { + GURL url(kTestUrl); + SetUpResponse(net::HTTP_INTERNAL_SERVER_ERROR); + double_fetcher_->ScheduleDoubleFetch(url, base::Value(true)); + + task_environment_.FastForwardBy(base::Seconds(75)); + EXPECT_TRUE(completed_fetches_.empty()); + + SetUpResponse(net::HTTP_OK); + task_environment_.FastForwardBy(base::Seconds(30)); + + ASSERT_EQ(completed_fetches_.size(), 1u); + + EXPECT_EQ(completed_fetches_[0].url, url); + EXPECT_EQ(completed_fetches_[0].associated_data, base::Value(true)); + ASSERT_TRUE(completed_fetches_[0].response_body); + EXPECT_EQ(*completed_fetches_[0].response_body, kTestResponseText); + + completed_fetches_.clear(); + + task_environment_.FastForwardBy(base::Seconds(180)); + EXPECT_TRUE(completed_fetches_.empty()); +} + +TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleMaxRetries) { + GURL url(kTestUrl); + SetUpResponse(net::HTTP_INTERNAL_SERVER_ERROR); + double_fetcher_->ScheduleDoubleFetch(url, base::Value(true)); + + task_environment_.FastForwardBy(base::Seconds(70)); + EXPECT_TRUE(completed_fetches_.empty()); + + task_environment_.FastForwardBy(base::Seconds(120)); + ASSERT_EQ(completed_fetches_.size(), 1u); + + EXPECT_EQ(completed_fetches_[0].url, url); + EXPECT_EQ(completed_fetches_[0].associated_data, base::Value(true)); + ASSERT_FALSE(completed_fetches_[0].response_body); + + completed_fetches_.clear(); + + SetUpResponse(net::HTTP_OK); + task_environment_.FastForwardBy(base::Minutes(10)); + EXPECT_TRUE(completed_fetches_.empty()); +} + +TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleNoRetry) { + GURL url(kTestUrl); + SetUpResponse(net::HTTP_NOT_FOUND); + double_fetcher_->ScheduleDoubleFetch(url, base::Value(123)); + + task_environment_.FastForwardBy(base::Seconds(70)); + ASSERT_EQ(completed_fetches_.size(), 1u); + + EXPECT_EQ(completed_fetches_[0].url, url); + EXPECT_EQ(completed_fetches_[0].associated_data, base::Value(123)); + ASSERT_FALSE(completed_fetches_[0].response_body); + + completed_fetches_.clear(); + + SetUpResponse(net::HTTP_OK); + task_environment_.FastForwardBy(base::Minutes(10)); + EXPECT_TRUE(completed_fetches_.empty()); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/hash_detection_unittest.cc b/components/web_discovery/browser/hash_detection_unittest.cc new file mode 100644 index 000000000000..94e6b944b28b --- /dev/null +++ b/components/web_discovery/browser/hash_detection_unittest.cc @@ -0,0 +1,29 @@ + +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/hash_detection.h" + +#include "brave/components/web_discovery/browser/regex_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +TEST(WebDiscoveryHashDetectionTest, Basic) { + RegexUtil regex_util; + + EXPECT_FALSE(IsHashLikely(regex_util, "test")); + EXPECT_FALSE(IsHashLikely(regex_util, "this is a test query")); + + EXPECT_FALSE(IsHashLikely(regex_util, + "pneumonoultramicroscopicsilicovolcanoconiosis")); + + EXPECT_TRUE(IsHashLikely(regex_util, + "N46iSNekpT:08ca45b7d7ea58ee:88dcbe4446168966a1")); + EXPECT_TRUE( + IsHashLikely(regex_util, "2btjjy78REtmYkkW0csHUbJZOstRXoWdX1mGrmmfeHI")); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index ff7c614b2992..6416089eddec 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -34,7 +34,6 @@ struct ScrapeRule { ScrapeRule(const ScrapeRule&) = delete; ScrapeRule& operator=(const ScrapeRule&) = delete; - std::string selector; std::optional sub_selector; ScrapeRuleType rule_type; std::string attribute; diff --git a/components/web_discovery/browser/patterns_unittest.cc b/components/web_discovery/browser/patterns_unittest.cc new file mode 100644 index 000000000000..f25f07091d62 --- /dev/null +++ b/components/web_discovery/browser/patterns_unittest.cc @@ -0,0 +1,345 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/patterns.h" + +#include +#include + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "brave/components/constants/brave_paths.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/re2/src/re2/re2.h" + +namespace web_discovery { + +class WebDiscoveryPatternsTest : public testing::Test { + public: + ~WebDiscoveryPatternsTest() override = default; + + protected: + std::unique_ptr LoadAndParsePatterns() { + base::FilePath data_path = + base::PathService::CheckedGet(brave::DIR_TEST_DATA); + + std::string patterns_json; + bool read_result = base::ReadFileToString( + data_path.AppendASCII("web_discovery/patterns.json"), &patterns_json); + EXPECT_TRUE(read_result); + + auto parsed_patterns = ParsePatterns(patterns_json); + EXPECT_TRUE(parsed_patterns); + EXPECT_EQ(parsed_patterns->normal_patterns.size(), 3u); + EXPECT_EQ(parsed_patterns->strict_patterns.size(), 3u); + + return parsed_patterns; + } +}; + +TEST_F(WebDiscoveryPatternsTest, GroupURLDetails) { + auto parsed_patterns = LoadAndParsePatterns(); + ASSERT_TRUE(parsed_patterns); + + const auto* normal_pattern = &parsed_patterns->normal_patterns[0]; + EXPECT_EQ(normal_pattern->id, "ex1"); + EXPECT_EQ(normal_pattern->url_regex->pattern(), "^https://example1.com"); + EXPECT_TRUE(normal_pattern->is_search_engine); + EXPECT_FALSE(normal_pattern->search_template_prefix); + EXPECT_TRUE(normal_pattern->payload_rule_groups.empty()); + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 1u); + + normal_pattern = &parsed_patterns->normal_patterns[1]; + EXPECT_EQ(normal_pattern->id, "nase"); + EXPECT_EQ(normal_pattern->url_regex->pattern(), + "^https://notasearchengine.biz"); + EXPECT_FALSE(normal_pattern->is_search_engine); + EXPECT_FALSE(normal_pattern->search_template_prefix); + EXPECT_FALSE(normal_pattern->payload_rule_groups.empty()); + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 2u); + + normal_pattern = &parsed_patterns->normal_patterns[2]; + EXPECT_EQ(normal_pattern->id, "ex2"); + EXPECT_EQ(normal_pattern->url_regex->pattern(), + "^https://search.example2.com"); + EXPECT_TRUE(normal_pattern->is_search_engine); + EXPECT_FALSE(normal_pattern->search_template_prefix); + EXPECT_TRUE(normal_pattern->payload_rule_groups.empty()); + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 1u); + + const auto* strict_pattern = &parsed_patterns->strict_patterns[0]; + EXPECT_EQ(strict_pattern->id, "ex1"); + EXPECT_EQ(strict_pattern->url_regex->pattern(), "^https://example1.com."); + EXPECT_TRUE(strict_pattern->is_search_engine); + EXPECT_EQ(strict_pattern->search_template_prefix, "search?query="); + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 3u); + + strict_pattern = &parsed_patterns->strict_patterns[1]; + EXPECT_EQ(strict_pattern->id, "nase"); + EXPECT_EQ(strict_pattern->url_regex->pattern(), + "^https://notasearchengine.biz"); + EXPECT_FALSE(strict_pattern->is_search_engine); + EXPECT_EQ(strict_pattern->search_template_prefix, "directory?query="); + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 2u); + + strict_pattern = &parsed_patterns->strict_patterns[2]; + EXPECT_EQ(strict_pattern->id, "ex2"); + EXPECT_EQ(strict_pattern->url_regex->pattern(), + "^https://search.example2.com"); + EXPECT_TRUE(strict_pattern->is_search_engine); + EXPECT_FALSE(strict_pattern->search_template_prefix); + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 1u); +} + +TEST_F(WebDiscoveryPatternsTest, NormalScrapeRules) { + auto parsed_patterns = LoadAndParsePatterns(); + ASSERT_TRUE(parsed_patterns); + const auto* normal_pattern = &parsed_patterns->normal_patterns[0]; + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 1u); + + auto rule_group_it = normal_pattern->scrape_rule_groups.find("form .search"); + ASSERT_TRUE(rule_group_it != normal_pattern->scrape_rule_groups.end()); + const auto* rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + auto rule_it = rule_group->find("q"); + ASSERT_TRUE(rule_it != rule_group->end()); + const auto* rule = rule_it->second.get(); + + EXPECT_EQ(rule->sub_selector, "input"); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kSearchQuery); + EXPECT_EQ(rule->attribute, "value"); + EXPECT_TRUE(rule->functions_applied.empty()); + + normal_pattern = &parsed_patterns->normal_patterns[1]; + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 2u); + + rule_group_it = normal_pattern->scrape_rule_groups.find(".field1 input"); + ASSERT_TRUE(rule_group_it != normal_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("t"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kOther); + EXPECT_EQ(rule->attribute, "href"); + EXPECT_TRUE(rule->functions_applied.empty()); + + rule_group_it = normal_pattern->scrape_rule_groups.find(".field2 input"); + ASSERT_TRUE(rule_group_it != normal_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 2u); + + rule_it = rule_group->find("t"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kOther); + EXPECT_EQ(rule->attribute, "href"); + EXPECT_EQ(rule->functions_applied.size(), 1u); + EXPECT_EQ(rule->functions_applied[0].size(), 3u); + EXPECT_EQ(rule->functions_applied[0][0], "parseU"); + EXPECT_EQ(rule->functions_applied[0][1], "qs"); + EXPECT_EQ(rule->functions_applied[0][2], "t"); + + rule_it = rule_group->find("b"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kOther); + EXPECT_EQ(rule->attribute, "textContent"); + EXPECT_TRUE(rule->functions_applied.empty()); + + normal_pattern = &parsed_patterns->normal_patterns[2]; + EXPECT_EQ(normal_pattern->scrape_rule_groups.size(), 1u); + + rule_group_it = normal_pattern->scrape_rule_groups.find("form .search-box"); + ASSERT_TRUE(rule_group_it != normal_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("q"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_EQ(rule->sub_selector, "input"); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kSearchQuery); + EXPECT_EQ(rule->attribute, "value"); + EXPECT_TRUE(rule->functions_applied.empty()); +} + +TEST_F(WebDiscoveryPatternsTest, StrictScrapeRules) { + auto parsed_patterns = LoadAndParsePatterns(); + ASSERT_TRUE(parsed_patterns); + const auto* strict_pattern = &parsed_patterns->strict_patterns[0]; + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 3u); + + auto rule_group_it = strict_pattern->scrape_rule_groups.find("form .search"); + ASSERT_TRUE(rule_group_it != strict_pattern->scrape_rule_groups.end()); + const auto* rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + auto rule_it = rule_group->find("q"); + ASSERT_TRUE(rule_it != rule_group->end()); + const auto* rule = rule_it->second.get(); + + EXPECT_EQ(rule->sub_selector, "input"); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kSearchQuery); + EXPECT_EQ(rule->attribute, "value"); + EXPECT_TRUE(rule->functions_applied.empty()); + + rule_group_it = strict_pattern->scrape_rule_groups.find("qurl"); + ASSERT_TRUE(rule_group_it != strict_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("qurl"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kStandard); + EXPECT_EQ(rule->attribute, "url"); + EXPECT_EQ(rule->functions_applied.size(), 1u); + EXPECT_EQ(rule->functions_applied[0].size(), 3u); + EXPECT_EQ(rule->functions_applied[0][0], "maskU"); + EXPECT_EQ(rule->functions_applied[0][1], false); + EXPECT_EQ(rule->functions_applied[0][2], false); + + rule_group_it = strict_pattern->scrape_rule_groups.find("ctry"); + ASSERT_TRUE(rule_group_it != strict_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("ctry"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kStandard); + EXPECT_EQ(rule->attribute, "ctry"); + EXPECT_TRUE(rule->functions_applied.empty()); + + strict_pattern = &parsed_patterns->strict_patterns[1]; + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 2u); + + rule_group_it = strict_pattern->scrape_rule_groups.find("#content .a1"); + ASSERT_TRUE(rule_group_it != strict_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("age"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_FALSE(rule->sub_selector); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kOther); + EXPECT_EQ(rule->attribute, "textContent"); + EXPECT_TRUE(rule->functions_applied.empty()); + + strict_pattern = &parsed_patterns->strict_patterns[2]; + EXPECT_EQ(strict_pattern->scrape_rule_groups.size(), 1u); + + rule_group_it = strict_pattern->scrape_rule_groups.find("form .search-box"); + ASSERT_TRUE(rule_group_it != strict_pattern->scrape_rule_groups.end()); + rule_group = &rule_group_it->second; + EXPECT_EQ(rule_group->size(), 1u); + + rule_it = rule_group->find("age"); + ASSERT_TRUE(rule_it != rule_group->end()); + rule = rule_it->second.get(); + + EXPECT_EQ(rule->sub_selector, ".created-at"); + EXPECT_EQ(rule->rule_type, ScrapeRuleType::kOther); + EXPECT_EQ(rule->attribute, "value"); + EXPECT_TRUE(rule->functions_applied.empty()); +} + +TEST_F(WebDiscoveryPatternsTest, NormalPayloadRules) { + auto parsed_patterns = LoadAndParsePatterns(); + ASSERT_TRUE(parsed_patterns); + + const auto* normal_pattern = &parsed_patterns->normal_patterns[0]; + EXPECT_TRUE(normal_pattern->payload_rule_groups.empty()); + normal_pattern = &parsed_patterns->normal_patterns[2]; + EXPECT_TRUE(normal_pattern->payload_rule_groups.empty()); + + normal_pattern = &parsed_patterns->normal_patterns[1]; + EXPECT_EQ(normal_pattern->payload_rule_groups.size(), 1u); + + const auto& payload_group_it = normal_pattern->payload_rule_groups.front(); + EXPECT_EQ(payload_group_it.key, "key1"); + EXPECT_EQ(payload_group_it.rule_type, PayloadRuleType::kSingle); + EXPECT_EQ(payload_group_it.result_type, PayloadResultType::kSingle); + EXPECT_EQ(payload_group_it.action, "t"); + EXPECT_TRUE(payload_group_it.rules.empty()); +} + +TEST_F(WebDiscoveryPatternsTest, StrictPayloadRules) { + auto parsed_patterns = LoadAndParsePatterns(); + ASSERT_TRUE(parsed_patterns); + + const auto* strict_pattern = &parsed_patterns->strict_patterns[0]; + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + + const auto* payload_group = &strict_pattern->payload_rule_groups[0]; + EXPECT_EQ(payload_group->key, "key1"); + EXPECT_EQ(payload_group->rule_type, PayloadRuleType::kSingle); + EXPECT_EQ(payload_group->result_type, PayloadResultType::kSingle); + EXPECT_EQ(payload_group->action, "query"); + EXPECT_TRUE(payload_group->rules.empty()); + + strict_pattern = &parsed_patterns->strict_patterns[1]; + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + + payload_group = &strict_pattern->payload_rule_groups[0]; + EXPECT_EQ(payload_group->key, "key1"); + EXPECT_EQ(payload_group->rule_type, PayloadRuleType::kQuery); + EXPECT_EQ(payload_group->result_type, PayloadResultType::kClustered); + EXPECT_EQ(payload_group->action, "age-info"); + EXPECT_EQ(payload_group->rules.size(), 2u); + + const auto* payload_rule = &payload_group->rules[0]; + EXPECT_EQ(payload_rule->selector, "#content .a1"); + EXPECT_EQ(payload_rule->key, "age"); + EXPECT_FALSE(payload_rule->is_join); + + payload_rule = &payload_group->rules[1]; + EXPECT_EQ(payload_rule->selector, "ctry"); + EXPECT_EQ(payload_rule->key, "ctry"); + EXPECT_FALSE(payload_rule->is_join); + + strict_pattern = &parsed_patterns->strict_patterns[2]; + EXPECT_EQ(strict_pattern->payload_rule_groups.size(), 1u); + + payload_group = &strict_pattern->payload_rule_groups[0]; + EXPECT_EQ(payload_group->key, "key2"); + EXPECT_EQ(payload_group->rule_type, PayloadRuleType::kQuery); + EXPECT_EQ(payload_group->result_type, PayloadResultType::kClustered); + EXPECT_EQ(payload_group->action, "age-info"); + EXPECT_EQ(payload_group->rules.size(), 1u); + + payload_rule = &payload_group->rules[0]; + EXPECT_EQ(payload_rule->selector, "form .search-box"); + EXPECT_EQ(payload_rule->key, "age"); + EXPECT_TRUE(payload_rule->is_join); +} + +TEST_F(WebDiscoveryPatternsTest, BadPatterns) { + ASSERT_FALSE(ParsePatterns("ABC")); + ASSERT_FALSE(ParsePatterns("{}")); + ASSERT_FALSE(ParsePatterns(R"({"normal":{}, "strict":{}})")); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/privacy_guard.cc b/components/web_discovery/browser/privacy_guard.cc index c13ffb6cb986..889af91a7fe4 100644 --- a/components/web_discovery/browser/privacy_guard.cc +++ b/components/web_discovery/browser/privacy_guard.cc @@ -76,7 +76,7 @@ bool IsPrivateDomainLikely(RegexUtil& regex_util, const std::string_view host) { return true; } auto hyphen_split = - base::SplitString(host, ".", base::WhitespaceHandling::KEEP_WHITESPACE, + base::SplitString(host, "-", base::WhitespaceHandling::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); if (hyphen_split.size() > kMaxHyphenSplitDomainSize) { return true; diff --git a/components/web_discovery/browser/privacy_guard_unittest.cc b/components/web_discovery/browser/privacy_guard_unittest.cc new file mode 100644 index 000000000000..e67871a298d5 --- /dev/null +++ b/components/web_discovery/browser/privacy_guard_unittest.cc @@ -0,0 +1,169 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/privacy_guard.h" + +#include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +class WebDiscoveryPrivacyGuardTest : public testing::Test { + public: + ~WebDiscoveryPrivacyGuardTest() override = default; + + // testing::Test: + void SetUp() override { + search_engine_pattern_.is_search_engine = true; + search_engine_pattern_.search_template_prefix = "find?testquery="; + } + + protected: + PatternsURLDetails search_engine_pattern_; + RegexUtil regex_util_; +}; + +TEST_F(WebDiscoveryPrivacyGuardTest, IsPrivateURLLikely) { + EXPECT_FALSE(IsPrivateURLLikely(regex_util_, + GURL("https://www.search1.com/search?q=test"), + &search_engine_pattern_)); + EXPECT_FALSE(IsPrivateURLLikely( + regex_util_, + GURL("https://search2.com/search?query=testing+a+nice+query"), + &search_engine_pattern_)); + EXPECT_FALSE(IsPrivateURLLikely( + regex_util_, + GURL( + "https://search2.com/search?query=quick+brown+fox+jumped&country=us"), + &search_engine_pattern_)); + EXPECT_FALSE(IsPrivateURLLikely( + regex_util_, GURL("https://www.website.com/page/test"), nullptr)); + + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("http://www.website.com/page/test"), nullptr)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://88.88.88.88/page/test"), nullptr)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://website.com:8443/page/test"), nullptr)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://user:pass@website.com/page/test"), nullptr)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://www.search1.com/search?q=test#ABCDEFGHIJK"), + &search_engine_pattern_)); + + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://a.nested.sub.domain.website.co.uk/test/page"), + &search_engine_pattern_)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://abc192738284732929abc.com/test/page"), + &search_engine_pattern_)); + EXPECT_TRUE(IsPrivateURLLikely( + regex_util_, GURL("https://a-long-hyphenated-web-site.com/test/page"), + &search_engine_pattern_)); +} + +TEST_F(WebDiscoveryPrivacyGuardTest, IsPrivateQueryLikely) { + EXPECT_FALSE(IsPrivateQueryLikely(regex_util_, "test")); + EXPECT_FALSE(IsPrivateQueryLikely(regex_util_, "99 cake recipes")); + EXPECT_FALSE(IsPrivateQueryLikely(regex_util_, "grapefruit and pineapple")); + EXPECT_FALSE(IsPrivateQueryLikely(regex_util_, "a quick brown fox")); + + EXPECT_TRUE(IsPrivateQueryLikely( + regex_util_, + "ABC123ABC123ABC123ABC123ABC123ABC123ABC123ABC123ABC123ABC123")); + EXPECT_TRUE(IsPrivateQueryLikely( + regex_util_, + "a long query that is potentially private and should not be considered")); + EXPECT_TRUE( + IsPrivateQueryLikely(regex_util_, "aliases for me@testemail.com")); + EXPECT_TRUE( + IsPrivateQueryLikely(regex_util_, "access site with user:pass@site.com")); + EXPECT_TRUE(IsPrivateQueryLikely(regex_util_, "php $P$MArzfx58u")); + EXPECT_TRUE(IsPrivateQueryLikely( + regex_util_, "Hippopotomonstrosesquippedaliophobia symptoms")); +} + +TEST_F(WebDiscoveryPrivacyGuardTest, GeneratePrivateSearchURL) { + GURL original_url("https://example.com/search?q=aaa&country=us&f=1"); + + EXPECT_EQ(GeneratePrivateSearchURL(original_url, "a simple test query", + search_engine_pattern_) + .spec(), + "https://example.com/find?testquery=a+simple+test+query"); + EXPECT_EQ( + GeneratePrivateSearchURL(original_url, "another simple test query 123", + PatternsURLDetails()) + .spec(), + "https://example.com/search?q=another+simple+test+query+123"); + EXPECT_EQ( + GeneratePrivateSearchURL(original_url, + "special chars @#$%^&=", search_engine_pattern_) + .spec(), + "https://example.com/find?testquery=special+chars+%40%23%24%25%5E%26%3D"); +} + +TEST_F(WebDiscoveryPrivacyGuardTest, ShouldDropLongURL) { + EXPECT_FALSE(ShouldDropLongURL( + regex_util_, GURL("https://www.search1.com/search?q=test"))); + EXPECT_FALSE(ShouldDropLongURL( + regex_util_, + GURL("https://search2.com/search?query=testing+a+nice+query"))); + EXPECT_FALSE(ShouldDropLongURL( + regex_util_, + GURL("https://search2.com/search?query=quick+fox&country=us&d=1"))); + EXPECT_FALSE(ShouldDropLongURL(regex_util_, + GURL("https://www.website.com/page/test"))); + + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, + GURL("https://www.website.com/page/test?id=12823871923991"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/test1283192831292"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/1283192831292?q=1"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, + GURL("https://www.website.com/page/test?a=1&b=2&c=3&d=4&e=5"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, + GURL("https://www.website.com/page/" + "test?query=a+super+long+query+string+that+is+too+long"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/ayLxezLhK1Lh1H1"))); + EXPECT_TRUE(ShouldDropLongURL(regex_util_, + GURL("https://www.website.com/page/WebLogic"))); + EXPECT_TRUE(ShouldDropLongURL(regex_util_, + GURL("https://www.website.com/page/admin"))); + EXPECT_TRUE(ShouldDropLongURL(regex_util_, + GURL("https://www.website.com/page/edit/"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/doc?share=1"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/doc?user=abc"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/doc#logout"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/doc?password=abc"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://user:pass@www.website.com/page/test"))); + EXPECT_TRUE(ShouldDropLongURL( + regex_util_, GURL("https://www.website.com/page/test?e=test@test.com"))); +} + +TEST_F(WebDiscoveryPrivacyGuardTest, MaskURL) { + GURL url("https://www.website.com/page/test"); + auto masked_url = MaskURL(regex_util_, url); + ASSERT_TRUE(masked_url); + EXPECT_EQ(*masked_url, url); + + masked_url = MaskURL(regex_util_, GURL("https://www.website.com/page/admin")); + ASSERT_TRUE(masked_url); + EXPECT_EQ(*masked_url, "https://www.website.com/ (PROTECTED)"); + + EXPECT_FALSE(MaskURL(regex_util_, GURL("file:///etc"))); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index 3b04e00528a1..bffc3e8b03f8 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -46,12 +46,10 @@ constexpr net::NetworkTrafficAnnotationTag kSubmitNetworkTrafficAnnotation = })"); constexpr base::TimeDelta kRequestMaxAge = base::Hours(36); -// constexpr base::TimeDelta kMinRequestInterval = -// base::Minutes(1) - base::Seconds(5); -// constexpr base::TimeDelta kMaxRequestInterval = -// base::Minutes(1) + base::Seconds(5); -constexpr base::TimeDelta kMinRequestInterval = base::Seconds(5); -constexpr base::TimeDelta kMaxRequestInterval = base::Seconds(6); +constexpr base::TimeDelta kMinRequestInterval = + base::Minutes(1) - base::Seconds(5); +constexpr base::TimeDelta kMaxRequestInterval = + base::Minutes(1) + base::Seconds(5); constexpr size_t kMaxRetries = 10; constexpr char kTypeField[] = "type"; diff --git a/components/web_discovery/browser/request_queue.cc b/components/web_discovery/browser/request_queue.cc index fa0e62ee63c3..f5743a3500c6 100644 --- a/components/web_discovery/browser/request_queue.cc +++ b/components/web_discovery/browser/request_queue.cc @@ -69,7 +69,7 @@ std::optional RequestQueue::NotifyRequestComplete(bool success) { if (!success) { use_backoff_delta = true; auto retries = request_dict.FindInt(kRetriesKey); - if (retries && retries >= max_retries_) { + if (retries && static_cast(*retries + 1) >= max_retries_) { should_remove = true; } else { request_dict.Set(kRetriesKey, retries.value_or(0) + 1); diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 8a3787ba7937..dedba4f37ee8 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -171,7 +171,6 @@ ServerConfigLoader::ServerConfigLoader( patterns_url_ = GetPatternsEndpoint(); patterns_path_ = user_data_dir.Append(kPatternsFilename); - LoadConfigs(); } ServerConfigLoader::~ServerConfigLoader() = default; @@ -186,6 +185,16 @@ const PatternsGroup& ServerConfigLoader::GetLastPatterns() const { return *last_loaded_patterns_; } +void ServerConfigLoader::SetLastServerConfigForTest( + std::unique_ptr server_config) { + last_loaded_server_config_ = std::move(server_config); +} + +void ServerConfigLoader::SetLastPatternsForTest( + std::unique_ptr patterns) { + last_loaded_patterns_ = std::move(patterns); +} + void ServerConfigLoader::LoadConfigs() { if (collector_config_url_loader_ || quorum_config_url_loader_) { // Another request is in progress diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 290ecf206f3f..7f72d4d901a8 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -60,22 +60,25 @@ struct ServerConfig { class ServerConfigLoader { public: - explicit ServerConfigLoader( - PrefService* local_state, - base::FilePath user_data_dir, - network::SharedURLLoaderFactory* shared_url_loader_factory, - base::RepeatingClosure config_callback, - base::RepeatingClosure patterns_callback); + ServerConfigLoader(PrefService* local_state, + base::FilePath user_data_dir, + network::SharedURLLoaderFactory* shared_url_loader_factory, + base::RepeatingClosure config_callback, + base::RepeatingClosure patterns_callback); ~ServerConfigLoader(); ServerConfigLoader(const ServerConfigLoader&) = delete; ServerConfigLoader& operator=(const ServerConfigLoader&) = delete; + void LoadConfigs(); + const ServerConfig& GetLastServerConfig() const; const PatternsGroup& GetLastPatterns() const; + void SetLastServerConfigForTest(std::unique_ptr server_config); + void SetLastPatternsForTest(std::unique_ptr patterns); + private: - void LoadConfigs(); void OnConfigResponses( std::vector> response_bodies); bool ProcessConfigResponses( diff --git a/components/web_discovery/browser/signature_basename_unittest.cc b/components/web_discovery/browser/signature_basename_unittest.cc new file mode 100644 index 000000000000..3e0f0f9a7c40 --- /dev/null +++ b/components/web_discovery/browser/signature_basename_unittest.cc @@ -0,0 +1,249 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/signature_basename.h" + +#include +#include +#include + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/test/task_environment.h" +#include "brave/components/web_discovery/browser/regex_util.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/testing_pref_service.h" +#include "crypto/sha2.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +namespace { + +constexpr size_t kMsInHour = 60 * 60 * 1000; + +int GetPeriodHoursSinceEpoch(size_t period_hours) { + auto hours_since_epoch = + base::Time::Now().InMillisecondsSinceUnixEpoch() / kMsInHour; + auto epoch_period_hours = period_hours * (hours_since_epoch / period_hours); + return epoch_period_hours; +} + +base::TimeDelta TimeUntilNextPeriod(int period, int epoch_period_hours) { + return base::Time::FromMillisecondsSinceUnixEpoch( + (epoch_period_hours + period) * static_cast(kMsInHour)) - + base::Time::Now(); +} + +std::vector GenerateExpectedBasename(std::string action, + int period, + int limit, + base::Value::List key_list, + size_t actual_count, + int epoch_period_hours) { + base::Value::List expected_tag_list; + expected_tag_list.Append(action); + expected_tag_list.Append(period); + expected_tag_list.Append(limit); + expected_tag_list.Append(std::move(key_list)); + expected_tag_list.Append(static_cast(epoch_period_hours)); + expected_tag_list.Append(static_cast(actual_count)); + + std::string tag_json; + EXPECT_TRUE(base::JSONWriter::Write(base::Value(std::move(expected_tag_list)), + &tag_json)); + + auto tag_hash = crypto::SHA256HashString(tag_json); + return std::vector(tag_hash.begin(), tag_hash.end()); +} + +base::Value::Dict GeneratePayload(std::string action, + base::Value::Dict inner_payload) { + base::Value::Dict payload; + payload.Set("action", action); + payload.Set("payload", std::move(inner_payload)); + return payload; +} + +} // namespace + +class WebDiscoverySignatureBasenameTest : public testing::Test { + public: + WebDiscoverySignatureBasenameTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + ~WebDiscoverySignatureBasenameTest() override = default; + + // testing::Test: + void SetUp() override { + WDPService::RegisterProfilePrefs(profile_prefs_.registry()); + + auto action_config = std::make_unique(); + action_config->keys.push_back("q->url"); + action_config->period = 24; + action_config->limit = 3; + server_config_.source_map_actions["query"] = std::move(action_config); + + action_config = std::make_unique(); + action_config->keys.push_back("field->obj"); + action_config->period = 12; + action_config->limit = 1; + server_config_.source_map_actions["img"] = std::move(action_config); + + action_config = std::make_unique(); + action_config->keys.push_back("field"); + action_config->period = 12; + action_config->limit = 1; + server_config_.source_map_actions["basic"] = std::move(action_config); + } + + protected: + base::test::TaskEnvironment task_environment_; + ServerConfig server_config_; + TestingPrefServiceSimple profile_prefs_; + RegexUtil regex_util_; +}; + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameForURL) { + base::flat_set used_counts; + + base::Value::List key_list; + key_list.Append("examplecomtesttestpage"); + + base::Value::Dict inner_payload; + inner_payload.Set("q", "https://www.EXample.com/test test/page"); + auto payload = GeneratePayload("query", std::move(inner_payload)); + + auto epoch_period_hours = GetPeriodHoursSinceEpoch(24); + for (size_t i = 0; i < 3; i++) { + auto actual_basename = + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload); + ASSERT_TRUE(actual_basename); + EXPECT_LT(actual_basename->count, 3u); + EXPECT_FALSE(used_counts.contains(actual_basename->count)); + + auto expected_basename = + GenerateExpectedBasename("query", 24, 3, key_list.Clone(), + actual_basename->count, epoch_period_hours); + + EXPECT_EQ(actual_basename->basename, expected_basename); + used_counts.insert(actual_basename->count); + + SaveBasenameCount(&profile_prefs_, actual_basename->count_tag_hash, + actual_basename->count); + } + + EXPECT_FALSE( + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload)); +} + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameNotSaved) { + base::Value::Dict inner_payload; + inner_payload.Set("q", "https://www.example.com/test/page"); + auto payload = GeneratePayload("query", std::move(inner_payload)); + + for (size_t i = 0; i < 10; i++) { + EXPECT_TRUE(GenerateBasename(&profile_prefs_, server_config_, regex_util_, + payload)); + } +} + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameLimitExpiry) { + base::Value::Dict inner_payload; + inner_payload.Set("q", "https://www.example.com/test/page"); + auto payload = GeneratePayload("query", std::move(inner_payload)); + + for (size_t i = 0; i < 3; i++) { + auto epoch_period_hours = GetPeriodHoursSinceEpoch(24); + for (size_t j = 0; j < 3; j++) { + auto basename = GenerateBasename(&profile_prefs_, server_config_, + regex_util_, payload); + ASSERT_TRUE(basename); + SaveBasenameCount(&profile_prefs_, basename->count_tag_hash, + basename->count); + } + + auto time_until_next_period = TimeUntilNextPeriod(24, epoch_period_hours); + task_environment_.AdvanceClock(time_until_next_period / 2); + EXPECT_FALSE(GenerateBasename(&profile_prefs_, server_config_, regex_util_, + payload)); + task_environment_.AdvanceClock(time_until_next_period / 2); + } +} + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameForFlattenedObj) { + auto field_obj = base::JSONReader::Read(R"({ + "this": { + "is": { + "test": "object" + } + }, + "example1": [ 1, 2 ], + "example2": { "abc": "def" } + })"); + ASSERT_TRUE(field_obj); + auto expected_flattened_obj = base::JSONReader::Read(R"([ + [ + [["example1", "0"], 1], + [["example1", "1"], 2], + [["example2", "abc"], "def"], + [["this", "is", "test"], "object"] + ] + ])"); + ASSERT_TRUE(expected_flattened_obj); + + base::Value::Dict inner_payload; + inner_payload.Set("field", std::move(*field_obj)); + auto payload = GeneratePayload("img", std::move(inner_payload)); + + auto actual_basename = + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload); + ASSERT_TRUE(actual_basename); + EXPECT_EQ(actual_basename->count, 0u); + + auto epoch_period_hours = GetPeriodHoursSinceEpoch(24); + auto expected_basename = GenerateExpectedBasename( + "img", 12, 1, expected_flattened_obj->GetList().Clone(), 0u, + epoch_period_hours); + + EXPECT_EQ(actual_basename->basename, expected_basename); + + SaveBasenameCount(&profile_prefs_, actual_basename->count_tag_hash, + actual_basename->count); + + EXPECT_FALSE( + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload)); +} + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameSimple) { + base::Value::List key_list; + key_list.Append("test"); + + base::Value::Dict inner_payload; + inner_payload.Set("field", "test"); + auto payload = GeneratePayload("basic", std::move(inner_payload)); + + auto actual_basename = + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload); + ASSERT_TRUE(actual_basename); + EXPECT_EQ(actual_basename->count, 0u); + + auto epoch_period_hours = GetPeriodHoursSinceEpoch(24); + auto expected_basename = GenerateExpectedBasename( + "basic", 12, 1, std::move(key_list), 0u, epoch_period_hours); + + EXPECT_EQ(actual_basename->basename, expected_basename); +} + +TEST_F(WebDiscoverySignatureBasenameTest, BasenameNoAction) { + base::Value::Dict inner_payload; + inner_payload.Set("field", "test"); + auto payload = GeneratePayload("bad_action", std::move(inner_payload)); + + ASSERT_FALSE( + GenerateBasename(&profile_prefs_, server_config_, regex_util_, payload)); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 2ae68c91658e..39e8399ebdfd 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -74,6 +74,7 @@ void WDPService::Start() { base::Unretained(this)), base::BindRepeating(&WDPService::OnPatternsLoaded, base::Unretained(this))); + server_config_loader_->LoadConfigs(); } if (!credential_manager_) { credential_manager_ = std::make_unique( diff --git a/test/BUILD.gn b/test/BUILD.gn index 8df214c359ae..be475d6132e2 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -266,6 +266,7 @@ test("brave_unit_tests") { "//brave/components/tor/buildflags", "//brave/components/url_sanitizer/browser:unittests", "//brave/components/version_info:unit_tests", + "//brave/components/web_discovery/browser:unit_tests", "//brave/extensions:common", "//brave/mojo/brave_ast_patcher:unit_tests", "//brave/net:unit_tests", @@ -923,6 +924,7 @@ test("brave_browser_tests") { "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/url_sanitizer/browser", + "//brave/components/web_discovery/browser:browser_tests", "//brave/components/webcompat:core", "//brave/renderer/skus:browser_tests", "//brave/renderer/test:browser_tests", diff --git a/test/data/web_discovery/page.html b/test/data/web_discovery/page.html new file mode 100644 index 000000000000..d987ae3ed875 --- /dev/null +++ b/test/data/web_discovery/page.html @@ -0,0 +1,21 @@ + + + + Test Page To Scrape + + +
+
+
A query
+ Foo1 +
+
+ Foo2 +
+
+ Foo3 + +
+
+ + diff --git a/test/data/web_discovery/patterns.json b/test/data/web_discovery/patterns.json new file mode 100644 index 000000000000..cdbfeec9dd70 --- /dev/null +++ b/test/data/web_discovery/patterns.json @@ -0,0 +1,200 @@ +{ + "normal": { + "urlPatterns": [ + "^https://example1.com", + "^https://notasearchengine.biz", + "^https://search.example2.com" + ], + "searchEngines": [ + "0", + "2" + ], + "scrape": { + "0": { + "form .search": { + "q": { + "item": "input", + "type": "searchQuery", + "etype": "value", + "keyName": "q" + } + } + }, + "1": { + ".field1 input": { + "t": { + "type": "other", + "etype": "href", + "keyName": "t" + } + }, + ".field2 input": { + "t": { + "type": "other", + "etype": "href", + "keyName": "t", + "functionsApplied": [ + [ + "parseU", + "qs", + "t" + ] + ] + }, + "b": { + "type": "other", + "etype": "textContent", + "keyName": "b" + } + } + }, + "2": { + "form .search-box": { + "q": { + "item": "input", + "type": "searchQuery", + "etype": "value", + "keyName": "q" + } + } + } + }, + "payloads": { + "1": { + "key1": { + "type": "single", + "results": "single", + "action": "t" + } + } + }, + "idMapping": { + "0": "ex1", + "1": "nase", + "2": "ex2" + } + }, + "strict": { + "urlPatterns": [ + "^https://example1.com.", + "^https://notasearchengine.biz", + "^https://search.example2.com" + ], + "searchEngines": [ + "0", + "2" + ], + "scrape": { + "0": { + "form .search": { + "q": { + "item": "input", + "type": "searchQuery", + "etype": "value", + "keyName": "q" + } + }, + "qurl": { + "qurl": { + "type": "standard", + "etype": "url", + "keyName": "qurl", + "functionsApplied": [ + [ + "maskU", + false, + false + ] + ] + } + }, + "ctry": { + "ctry": { + "type": "standard", + "etype": "ctry", + "keyName": "ctry" + } + } + }, + "1": { + "ctry": { + "ctry": { + "type": "standard", + "etype": "ctry", + "keyName": "ctry" + } + }, + "#content .a1": { + "age": { + "type": "arr", + "etype": "textContent", + "keyName": "age" + } + } + }, + "2": { + "form .search-box": { + "age": { + "item": ".created-at", + "type": "other", + "etype": "value", + "keyName": "age" + } + } + } + }, + "payloads": { + "0": { + "key1": { + "type": "single", + "results": "single", + "action": "query" + } + }, + "1": { + "key1": { + "type": "query", + "results": "clustered", + "action": "age-info", + "fields": [ + [ + "#content .a1", + "age" + ], + [ + "ctry", + "ctry" + ] + ] + } + }, + "2": { + "key2": { + "type": "query", + "results": "clustered", + "action": "age-info", + "fields": [ + [ + "form .search-box", + "age", + "join" + ] + ] + } + } + }, + "queryTemplate": { + "0": { + "prefix": "search?query=" + }, + "1": { + "prefix": "directory?query=" + } + }, + "idMapping": { + "0": "ex1", + "1": "nase", + "2": "ex2" + } + } +} From 628804d46d8f41ec81f83ed18a085ac205b1883e Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 20 Jun 2024 21:32:18 -0700 Subject: [PATCH 24/36] Update anonymous-credentials for Web Discovery --- .../browser/anonymous_credentials/rs/Cargo.lock | 4 ++-- .../browser/anonymous_credentials/rs/Cargo.toml | 2 +- .../rust/anonymous_credentials/v0_1/BUILD.gn | 14 +++++++------- .../rust/chromium_crates_io/gnrt_config.toml | 3 +++ .../.cargo_vcs_info.json | 6 ------ .../.cargo-checksum.json | 0 .../.cargo_vcs_info.json | 6 ++++++ .../.gitignore | 0 .../Cargo.toml | 2 +- .../Cargo.toml.orig | 2 +- .../LICENSE | 0 .../README.md | 0 .../src/data.rs | 0 .../src/join.rs | 0 .../src/lib.rs | 2 +- .../src/sign.rs | 0 .../src/util.rs | 0 17 files changed, 22 insertions(+), 19 deletions(-) delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/.cargo-checksum.json (100%) create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/.gitignore (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/Cargo.toml (98%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/Cargo.toml.orig (96%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/LICENSE (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/README.md (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/src/data.rs (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/src/join.rs (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/src/lib.rs (99%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/src/sign.rs (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.2 => anonymous-credentials-0.1.3}/src/util.rs (100%) diff --git a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock index f3866ed78a68..20ff89ce66fc 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock +++ b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anonymous-credentials" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d3a6796aee3f2a4c4bd1fe2473908faa815d54ca693bc8d7c063e7d77f23" +checksum = "1acf2ababbdec2b27c687c7bc761c314055af0453f70f2df2417b686b475c3df" dependencies = [ "brave-miracl", "lazy_static", diff --git a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml index c0cbc7f34835..2d8d350f2594 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml +++ b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MPL-2.0" [dependencies] -anonymous-credentials = "0.1.2" +anonymous-credentials = "0.1" cxx = "1" [lib] diff --git a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn index 54e91148a236..0bee7aeebbbb 100644 --- a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn +++ b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn @@ -13,19 +13,19 @@ cargo_crate("lib") { crate_name = "anonymous_credentials" epoch = "0.1" crate_type = "rlib" - crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs" + crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs" sources = [ - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs", ] inputs = [] build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.1.2" + cargo_pkg_version = "0.1.3" cargo_pkg_authors = "Darnell Andries " cargo_pkg_name = "anonymous-credentials" cargo_pkg_description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml index 72fa94df9966..b75efa445cea 100644 --- a/third_party/rust/chromium_crates_io/gnrt_config.toml +++ b/third_party/rust/chromium_crates_io/gnrt_config.toml @@ -110,6 +110,9 @@ if (target_os == "android" && target_cpu == "arm64") { } ''' } +[crate.anonymous_credentials] +license_files = ['LICENCE'] + [crate.ansi_term] license_files = ['LICENCE'] diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json deleted file mode 100644 index 90abaf468340..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "33e360909c77f1dd485db47668b410fc2b2532d5" - }, - "path_in_vcs": "" -} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo-checksum.json similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.cargo-checksum.json rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo-checksum.json diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json new file mode 100644 index 000000000000..caa8d9ccd7d4 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "54001a03a26180747ed3a748acf7706c8f8bb8e7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.gitignore similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/.gitignore rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.gitignore diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml similarity index 98% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml index 1d6385e3d791..62e3f2249448 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "anonymous-credentials" -version = "0.1.2" +version = "0.1.3" authors = ["Darnell Andries "] description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" readme = "README.md" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig similarity index 96% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig index a33afba07d5a..fb480d37bc81 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/Cargo.toml.orig +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "anonymous-credentials" -version = "0.1.2" +version = "0.1.3" edition = "2021" authors = ["Darnell Andries "] description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/LICENSE similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/LICENSE rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/LICENSE diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/README.md similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/README.md rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/README.md diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/data.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/join.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs similarity index 99% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs index 088720f48a35..b0a5767be942 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/lib.rs +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs @@ -49,7 +49,7 @@ impl CredentialManager { Self::new_with_seed(&entropy) } - fn new_with_seed(entropy: &[u8]) -> Self { + pub fn new_with_seed(entropy: &[u8]) -> Self { let mut rng = RAND::new(); rng.seed(entropy.len(), entropy); diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/sign.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.2/src/util.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs From dd55f4aa588c610b93fe21667ada7e888dfb942b Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Mon, 24 Jun 2024 23:07:38 -0700 Subject: [PATCH 25/36] Add more Web Discovery tests, misc fixes --- components/web_discovery/browser/BUILD.gn | 6 + .../anonymous_credentials/rs/src/lib.rs | 7 + .../browser/content_scraper_browsertest.cc | 5 +- .../browser/credential_manager.cc | 11 +- .../browser/credential_manager.h | 15 +- .../browser/credential_manager_unittest.cc | 195 ++++++++++++ .../browser/credential_signer.cc | 12 + .../web_discovery/browser/credential_signer.h | 30 ++ .../browser/double_fetcher_unittest.cc | 13 + .../browser/payload_generator.cc | 4 +- .../browser/payload_generator_unittest.cc | 283 ++++++++++++++++++ components/web_discovery/browser/reporter.cc | 8 +- components/web_discovery/browser/reporter.h | 6 +- .../browser/reporter_unittest.cc | 259 ++++++++++++++++ .../browser/server_config_loader.cc | 9 +- .../browser/server_config_loader.h | 5 +- .../browser/server_config_loader_unittest.cc | 281 +++++++++++++++++ .../web_discovery/browser/wdp_service.cc | 3 +- .../credential_keys_and_responses.json | 10 + test/data/web_discovery/hpn-config.json | 146 +++++++++ test/data/web_discovery/patterns.gz | Bin 0 -> 3762 bytes test/data/web_discovery/quorum-config.json | 1 + 22 files changed, 1284 insertions(+), 25 deletions(-) create mode 100644 components/web_discovery/browser/credential_manager_unittest.cc create mode 100644 components/web_discovery/browser/credential_signer.cc create mode 100644 components/web_discovery/browser/credential_signer.h create mode 100644 components/web_discovery/browser/payload_generator_unittest.cc create mode 100644 components/web_discovery/browser/reporter_unittest.cc create mode 100644 components/web_discovery/browser/server_config_loader_unittest.cc create mode 100644 test/data/web_discovery/credential_keys_and_responses.json create mode 100644 test/data/web_discovery/hpn-config.json create mode 100644 test/data/web_discovery/patterns.gz create mode 100644 test/data/web_discovery/quorum-config.json diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 2d73d62ac128..346e4bab36dc 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -9,6 +9,8 @@ static_library("browser") { "content_scraper.h", "credential_manager.cc", "credential_manager.h", + "credential_signer.cc", + "credential_signer.h", "double_fetcher.cc", "double_fetcher.h", "ecdh_aes.cc", @@ -64,10 +66,14 @@ static_library("browser") { source_set("unit_tests") { testonly = true sources = [ + "credential_manager_unittest.cc", "double_fetcher_unittest.cc", "hash_detection_unittest.cc", "patterns_unittest.cc", + "payload_generator_unittest.cc", "privacy_guard_unittest.cc", + "reporter_unittest.cc", + "server_config_loader_unittest.cc", "signature_basename_unittest.cc", ] deps = [ diff --git a/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs index 4f6bc14caad8..a474f63f0816 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs +++ b/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs @@ -25,6 +25,7 @@ mod ffi { extern "Rust" { type CredentialManager; fn new_credential_manager() -> Box; + fn new_credential_manager_with_fixed_seed() -> Box; fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult; fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result; fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult; @@ -41,6 +42,12 @@ fn new_credential_manager() -> Box { Box::new(CredentialManager(InternalCredentialManager::new())) } +fn new_credential_manager_with_fixed_seed() -> Box { + Box::new(CredentialManager(InternalCredentialManager::new_with_seed( + &[0u8; 1], + ))) +} + impl CredentialManager { fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { let result = self.0.start_join(challenge); diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc index 2c4593be4bd8..a7493daf3e75 100644 --- a/components/web_discovery/browser/content_scraper_browsertest.cc +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -71,7 +71,8 @@ class WebDiscoveryContentScraperTest : public InProcessBrowserTest { base::DoNothing()); auto server_config = std::make_unique(); server_config->location = "us"; - server_config_loader_->SetLastServerConfigForTest(std::move(server_config)); + server_config_loader_->SetLastServerConfigForTesting( + std::move(server_config)); auto patterns_group = std::make_unique(); std::vector normal_patterns(1); @@ -133,7 +134,7 @@ class WebDiscoveryContentScraperTest : public InProcessBrowserTest { patterns_group->strict_patterns = std::move(strict_patterns); - server_config_loader_->SetLastPatternsForTest(std::move(patterns_group)); + server_config_loader_->SetLastPatternsForTesting(std::move(patterns_group)); scraper_ = std::make_unique(server_config_loader_.get(), ®ex_util_); diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index de61a86db995..619ab40adbfa 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -154,7 +154,7 @@ bool CredentialManager::LoadRSAKey() { profile_prefs_->GetString(kCredentialRSAPrivateKey); rsa_public_key_b64_ = profile_prefs_->GetString(kCredentialRSAPublicKey); - if (private_key_b64.empty() || !rsa_public_key_b64_->empty()) { + if (private_key_b64.empty() || rsa_public_key_b64_->empty()) { rsa_public_key_b64_ = std::nullopt; return true; } @@ -428,4 +428,13 @@ void CredentialManager::OnSignResult( std::move(callback).Run(signed_message); } +void CredentialManager::UseFixedSeedForTesting() { + anonymous_credential_manager_ = + std::unique_ptr, + base::OnTaskRunnerDeleter>( + new rust::Box( + anonymous_credentials::new_credential_manager_with_fixed_seed()), + base::OnTaskRunnerDeleter(pool_sequenced_task_runner_)); +} + } // namespace web_discovery diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index 9e2defacb09e..e32333e58f8b 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -16,6 +16,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/timer/wall_clock_timer.h" #include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/credential_signer.h" #include "brave/components/web_discovery/browser/rsa.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "net/base/backoff_entry.h" @@ -34,24 +35,26 @@ struct GenerateJoinRequestResult { std::string signature; }; -class CredentialManager { +class CredentialManager : public CredentialSigner { public: - using SignCallback = - base::OnceCallback>)>; CredentialManager(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, const ServerConfigLoader* server_config_loader); - ~CredentialManager(); + ~CredentialManager() override; CredentialManager(const CredentialManager&) = delete; CredentialManager& operator=(const CredentialManager&) = delete; void JoinGroups(); - bool CredentialExistsForToday(); + // CredentialSigner: + bool CredentialExistsForToday() override; + bool Sign(std::vector msg, std::vector basename, - SignCallback callback); + SignCallback callback) override; + + void UseFixedSeedForTesting(); private: bool LoadRSAKey(); diff --git a/components/web_discovery/browser/credential_manager_unittest.cc b/components/web_discovery/browser/credential_manager_unittest.cc new file mode 100644 index 000000000000..9ed1e461eee2 --- /dev/null +++ b/components/web_discovery/browser/credential_manager_unittest.cc @@ -0,0 +1,195 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/credential_manager.h" + +#include +#include +#include + +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/path_service.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "brave/components/constants/brave_paths.h" +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/browser/util.h" +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/testing_pref_service.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +class WebDiscoveryCredentialManagerTest : public testing::Test { + public: + WebDiscoveryCredentialManagerTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), + shared_url_loader_factory_( + base::MakeRefCounted( + &url_loader_factory_)) {} + ~WebDiscoveryCredentialManagerTest() override = default; + + // testing::Test: + void SetUp() override { + base::Time set_time; + ASSERT_TRUE(base::Time::FromUTCString("2024-06-22", &set_time)); + task_environment_.AdvanceClock(set_time - base::Time::Now()); + + WDPService::RegisterProfilePrefs(profile_prefs_.registry()); + + base::FilePath data_path = + base::PathService::CheckedGet(brave::DIR_TEST_DATA); + std::string test_data_json; + ASSERT_TRUE(base::ReadFileToString( + data_path.Append("web_discovery/credential_keys_and_responses.json"), + &test_data_json)); + auto test_data_value = base::JSONReader::Read(test_data_json); + ASSERT_TRUE(test_data_value); + const auto& test_data_dict = test_data_value->GetDict(); + const auto* rsa_priv_key = test_data_dict.FindString("rsa_priv_key"); + const auto* rsa_pub_key = test_data_dict.FindString("rsa_pub_key"); + const auto* group_pub_key = test_data_dict.FindString("group_pub_key"); + const auto* join_responses = test_data_dict.FindDict("join_responses"); + ASSERT_TRUE(rsa_priv_key && rsa_pub_key && group_pub_key && join_responses); + + profile_prefs_.SetString(kCredentialRSAPublicKey, *rsa_pub_key); + profile_prefs_.SetString(kCredentialRSAPrivateKey, *rsa_priv_key); + + server_config_loader_ = std::make_unique( + nullptr, base::FilePath(), nullptr, base::DoNothing(), + base::DoNothing()); + + auto server_config = std::make_unique(); + for (const auto [date, join_response] : *join_responses) { + server_config->group_pub_keys[date] = *group_pub_key; + join_responses_[date] = join_response.GetString(); + } + server_config_loader_->SetLastServerConfigForTesting( + std::move(server_config)); + + url_loader_factory_.SetInterceptor( + base::BindRepeating(&WebDiscoveryCredentialManagerTest::HandleRequest, + base::Unretained(this))); + + SetUpCredentialManager(); + } + + protected: + void SetUpCredentialManager() { + credential_manager_ = std::make_unique( + &profile_prefs_, shared_url_loader_factory_.get(), + server_config_loader_.get()); + credential_manager_->UseFixedSeedForTesting(); + } + + base::test::TaskEnvironment task_environment_; + std::unique_ptr credential_manager_; + TestingPrefServiceSimple profile_prefs_; + size_t join_requests_made_ = 0; + + private: + void HandleRequest(const network::ResourceRequest& request) { + url_loader_factory_.ClearResponses(); + std::string response; + const auto* elements = request.request_body->elements(); + ASSERT_EQ(elements->size(), 1u); + ASSERT_EQ(elements->at(0).type(), network::DataElement::Tag::kBytes); + auto body_json = + elements->at(0).As().AsStringPiece(); + + auto body_value = base::JSONReader::Read(body_json); + ASSERT_TRUE(body_value && body_value->is_dict()); + const auto* ts = body_value->GetDict().FindString("ts"); + ASSERT_TRUE(ts); + ASSERT_TRUE(join_responses_.contains(*ts)); + ASSERT_EQ(request.url.spec(), GetDirectHPNHost() + "/join"); + + base::Value::Dict dict; + dict.Set("joinResponse", join_responses_.at(*ts)); + ASSERT_TRUE( + base::JSONWriter::Write(base::Value(std::move(dict)), &response)); + url_loader_factory_.AddResponse(request.url.spec(), response); + join_requests_made_++; + } + + base::flat_map join_responses_; + std::unique_ptr server_config_loader_; + network::TestURLLoaderFactory url_loader_factory_; + scoped_refptr shared_url_loader_factory_; +}; + +TEST_F(WebDiscoveryCredentialManagerTest, JoinGroups) { + credential_manager_->JoinGroups(); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(join_requests_made_, 3u); + join_requests_made_ = 0; + + for (size_t i = 0; i < 3; i++) { + EXPECT_TRUE(credential_manager_->CredentialExistsForToday()); + task_environment_.FastForwardBy(base::Days(1)); + } + EXPECT_FALSE(credential_manager_->CredentialExistsForToday()); + EXPECT_EQ(join_requests_made_, 0u); +} + +TEST_F(WebDiscoveryCredentialManagerTest, LoadKeysFromStorage) { + credential_manager_->JoinGroups(); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(join_requests_made_, 3u); + join_requests_made_ = 0; + + SetUpCredentialManager(); + for (size_t i = 0; i < 3; i++) { + ASSERT_TRUE(credential_manager_->CredentialExistsForToday()); + task_environment_.FastForwardBy(base::Days(1)); + } + ASSERT_FALSE(credential_manager_->CredentialExistsForToday()); + EXPECT_EQ(join_requests_made_, 0u); +} + +TEST_F(WebDiscoveryCredentialManagerTest, Sign) { + std::vector message({0, 1, 2, 3, 4}); + std::vector basename({5, 6, 7, 8, 9}); + credential_manager_->Sign( + message, basename, + base::BindLambdaForTesting( + [&](const std::optional> signature) { + EXPECT_FALSE(signature); + })); + task_environment_.RunUntilIdle(); + + credential_manager_->JoinGroups(); + task_environment_.RunUntilIdle(); + + base::flat_set> signatures; + for (size_t i = 0; i < 3; i++) { + credential_manager_->Sign( + message, basename, + base::BindLambdaForTesting( + [&](const std::optional> signature) { + ASSERT_TRUE(signature); + EXPECT_FALSE(signature->empty()); + EXPECT_FALSE(signatures.contains(*signature)); + signatures.insert(*signature); + })); + task_environment_.FastForwardBy(base::Days(1)); + } + credential_manager_->Sign( + message, basename, + base::BindLambdaForTesting( + [&](const std::optional> signature) { + EXPECT_FALSE(signature); + })); + task_environment_.RunUntilIdle(); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/credential_signer.cc b/components/web_discovery/browser/credential_signer.cc new file mode 100644 index 000000000000..ca8fce0c3b51 --- /dev/null +++ b/components/web_discovery/browser/credential_signer.cc @@ -0,0 +1,12 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/credential_signer.h" + +namespace web_discovery { + +CredentialSigner::~CredentialSigner() = default; + +} // namespace web_discovery diff --git a/components/web_discovery/browser/credential_signer.h b/components/web_discovery/browser/credential_signer.h new file mode 100644 index 000000000000..ef80cbb8ddc2 --- /dev/null +++ b/components/web_discovery/browser/credential_signer.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_SIGNER_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_SIGNER_H_ + +#include +#include + +#include "base/functional/callback.h" + +namespace web_discovery { + +class CredentialSigner { + public: + using SignCallback = + base::OnceCallback>)>; + virtual ~CredentialSigner(); + + virtual bool CredentialExistsForToday() = 0; + virtual bool Sign(std::vector msg, + std::vector basename, + SignCallback callback) = 0; +}; + +} // namespace web_discovery + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_CREDENTIAL_SIGNER_H_ diff --git a/components/web_discovery/browser/double_fetcher_unittest.cc b/components/web_discovery/browser/double_fetcher_unittest.cc index bfd08244f808..ea1241c2a8e3 100644 --- a/components/web_discovery/browser/double_fetcher_unittest.cc +++ b/components/web_discovery/browser/double_fetcher_unittest.cc @@ -115,6 +115,19 @@ TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleAndFetch) { EXPECT_TRUE(completed_fetches_.empty()); } +TEST_F(WebDiscoveryDoubleFetcherTest, LoadScheduleFromStorageAndFetch) { + GURL url(kTestUrl); + double_fetcher_->ScheduleDoubleFetch(url, base::Value(1)); + double_fetcher_->ScheduleDoubleFetch(url, base::Value(2)); + + EXPECT_TRUE(completed_fetches_.empty()); + + InitDoubleFetcher(); + + task_environment_.FastForwardBy(base::Seconds(240)); + EXPECT_EQ(completed_fetches_.size(), 2u); +} + TEST_F(WebDiscoveryDoubleFetcherTest, ScheduleRetry) { GURL url(kTestUrl); SetUpResponse(net::HTTP_INTERNAL_SERVER_ERROR); diff --git a/components/web_discovery/browser/payload_generator.cc b/components/web_discovery/browser/payload_generator.cc index 6b7111eb0615..2c631c15ad54 100644 --- a/components/web_discovery/browser/payload_generator.cc +++ b/components/web_discovery/browser/payload_generator.cc @@ -28,8 +28,8 @@ constexpr auto kQueryActions = base::MakeFixedFlatSet( bool ValueHasContent(const base::Value& value) { const auto* value_str = value.GetIfString(); - if (value_str && !value_str->empty()) { - return true; + if (value_str) { + return !value_str->empty(); } if (!value.is_none()) { return true; diff --git a/components/web_discovery/browser/payload_generator_unittest.cc b/components/web_discovery/browser/payload_generator_unittest.cc new file mode 100644 index 000000000000..853f6c816c9c --- /dev/null +++ b/components/web_discovery/browser/payload_generator_unittest.cc @@ -0,0 +1,283 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/payload_generator.h" + +#include +#include + +#include "brave/components/web_discovery/browser/content_scraper.h" +#include "brave/components/web_discovery/browser/patterns.h" +#include "brave/components/web_discovery/browser/regex_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +class WebDiscoveryPayloadGeneratorTest : public testing::Test { + public: + ~WebDiscoveryPayloadGeneratorTest() override = default; + + // testing::Test: + void SetUp() override { + server_config_ = std::make_unique(); + server_config_->location = "us"; + + url_details_ = std::make_unique(); + + url_details_->payload_rule_groups = std::vector(2); + + auto& single_group = url_details_->payload_rule_groups[0]; + single_group.key = ".single-element"; + single_group.rule_type = PayloadRuleType::kSingle; + single_group.result_type = PayloadResultType::kSingle; + single_group.action = "single_action"; + + auto& query_group = url_details_->payload_rule_groups[1]; + query_group.key = "query_group"; + query_group.rule_type = PayloadRuleType::kQuery; + query_group.result_type = PayloadResultType::kClustered; + query_group.action = "query"; + query_group.rules = std::vector(2); + + auto& join_rule = query_group.rules[0]; + join_rule.selector = "#results"; + join_rule.key = "r"; + join_rule.is_join = true; + + auto& qurl_rule = query_group.rules[1]; + qurl_rule.selector = "qurl"; + qurl_rule.key = "qurl"; + qurl_rule.is_join = false; + } + + protected: + std::vector GenerateQueryPayloadsHelper( + std::unique_ptr scrape_result) { + return GenerateQueryPayloads(*server_config_.get(), regex_util_, + url_details_.get(), std::move(scrape_result)); + } + + std::unique_ptr server_config_; + + private: + RegexUtil regex_util_; + std::unique_ptr url_details_; +}; + +TEST_F(WebDiscoveryPayloadGeneratorTest, GenerateQueryPayloads) { + GURL test_url("https://example.com/test"); + auto scrape_result = std::make_unique(test_url, "test_id"); + + std::vector single_dicts; + base::Value::Dict single_dict1; + single_dict1.Set("ab", "value1"); + single_dict1.Set("cd", "value2"); + single_dicts.push_back(std::move(single_dict1)); + base::Value::Dict single_dict2; + single_dict2.Set("ef", "value3"); + single_dict2.Set("gh", "value4"); + single_dicts.push_back(std::move(single_dict2)); + scrape_result->fields[".single-element"] = std::move(single_dicts); + + std::vector result_dicts1; + base::Value::Dict result_dict1, result_dict2, result_dict3, result_dict4, + result_dict5; + result_dict1.Set("njk", "joinvalue1"); + result_dict2.Set("abc", "joinvalue2"); + result_dict3.Set("njk", "joinvalue3"); + result_dict4.Set("abc", "joinvalue4"); + result_dicts1.push_back(std::move(result_dict1)); + result_dicts1.push_back(std::move(result_dict2)); + result_dicts1.push_back(std::move(result_dict3)); + result_dicts1.push_back(std::move(result_dict4)); + std::vector result_dicts2; + result_dict5.Set("qurl", "https://example.com/test1"); + result_dicts2.push_back(std::move(result_dict5)); + scrape_result->fields["#results"] = std::move(result_dicts1); + scrape_result->fields["qurl"] = std::move(result_dicts2); + + auto payloads = GenerateQueryPayloadsHelper(std::move(scrape_result)); + ASSERT_EQ(payloads.size(), 3u); + + const auto* payload = &payloads[0]; + const auto* action = payload->FindString(kActionKey); + const auto* inner_payload = payload->FindDict(kInnerPayloadKey); + ASSERT_TRUE(action && inner_payload); + EXPECT_EQ(*action, "single_action"); + + EXPECT_EQ(inner_payload->size(), 3u); + + const auto* ctry = inner_payload->FindString("ctry"); + const auto* val1 = inner_payload->FindString("ab"); + const auto* val2 = inner_payload->FindString("cd"); + ASSERT_TRUE(ctry && val1 && val2); + EXPECT_EQ(*ctry, "us"); + EXPECT_EQ(*val1, "value1"); + EXPECT_EQ(*val2, "value2"); + + payload = &payloads[1]; + action = payload->FindString(kActionKey); + inner_payload = payload->FindDict(kInnerPayloadKey); + ASSERT_TRUE(action && inner_payload); + EXPECT_EQ(*action, "single_action"); + + EXPECT_EQ(inner_payload->size(), 3u); + + ctry = inner_payload->FindString("ctry"); + val1 = inner_payload->FindString("ef"); + val2 = inner_payload->FindString("gh"); + ASSERT_TRUE(ctry && val1 && val2); + EXPECT_EQ(*ctry, "us"); + EXPECT_EQ(*val1, "value3"); + EXPECT_EQ(*val2, "value4"); + + payload = &payloads[2]; + action = payload->FindString(kActionKey); + inner_payload = payload->FindDict(kInnerPayloadKey); + ASSERT_TRUE(action && inner_payload); + EXPECT_EQ(*action, "query"); + + EXPECT_EQ(inner_payload->size(), 2u); + + const auto* qurl = inner_payload->FindString("qurl"); + const auto* r_dict = inner_payload->FindDict("r"); + ASSERT_TRUE(qurl && r_dict); + EXPECT_EQ(*qurl, "https://example.com/test1"); + EXPECT_EQ(r_dict->size(), 4u); + const auto* r0_dict = r_dict->FindDict("0"); + const auto* r1_dict = r_dict->FindDict("1"); + const auto* r2_dict = r_dict->FindDict("2"); + const auto* r3_dict = r_dict->FindDict("3"); + ASSERT_TRUE(r0_dict && r1_dict && r2_dict && r3_dict); + EXPECT_EQ(r0_dict->size(), 1u); + EXPECT_EQ(r1_dict->size(), 1u); + EXPECT_EQ(r2_dict->size(), 1u); + EXPECT_EQ(r3_dict->size(), 1u); + const auto* r0_val = r0_dict->FindString("njk"); + const auto* r1_val = r1_dict->FindString("abc"); + const auto* r2_val = r2_dict->FindString("njk"); + const auto* r3_val = r3_dict->FindString("abc"); + ASSERT_TRUE(r0_val && r1_val && r2_val && r2_val); + EXPECT_EQ(*r0_val, "joinvalue1"); + EXPECT_EQ(*r1_val, "joinvalue2"); + EXPECT_EQ(*r2_val, "joinvalue3"); + EXPECT_EQ(*r3_val, "joinvalue4"); +} + +TEST_F(WebDiscoveryPayloadGeneratorTest, GenerateAlivePayload) { + std::string date_hour = "2023051509"; + + auto alive_payload = GenerateAlivePayload(*server_config_.get(), date_hour); + + const auto* action = alive_payload.FindString("action"); + const auto* inner_payload = alive_payload.FindDict("payload"); + + ASSERT_TRUE(action && inner_payload); + + EXPECT_EQ(*action, "alive"); + const auto* ctry = inner_payload->FindString("ctry"); + const auto* ts = inner_payload->FindString("t"); + const auto status = inner_payload->FindBool("status"); + + ASSERT_TRUE(ctry && ts && status); + EXPECT_EQ(*ctry, "us"); + EXPECT_EQ(*ts, date_hour); + EXPECT_EQ(*status, true); +} + +TEST_F(WebDiscoveryPayloadGeneratorTest, ExcludePrivateResult) { + GURL test_url("https://example.com/search"); + auto scrape_result = std::make_unique(test_url, "test_id"); + + std::vector result_dicts1; + for (int i = 0; i < 5; i++) { + base::Value::Dict result_dict; + std::string url = "https://example.com/result"; + if (i == 1) { + url = "https://423947892374892879.com/example"; + } else { + url += base::NumberToString(i == 0 ? 0 : i - 1); + } + result_dict.Set("u", url); + result_dicts1.push_back(std::move(result_dict)); + } + scrape_result->fields["#results"] = std::move(result_dicts1); + std::vector result_dicts2; + base::Value::Dict qurl_dict; + qurl_dict.Set("qurl", "https://example.com/test1"); + result_dicts2.push_back(std::move(qurl_dict)); + scrape_result->fields["qurl"] = std::move(result_dicts2); + + auto payloads = GenerateQueryPayloadsHelper(std::move(scrape_result)); + ASSERT_EQ(payloads.size(), 1u); + + const auto* payload = &payloads[0]; + const auto* inner_payload = payload->FindDict("payload"); + const auto* r_dict = inner_payload->FindDict("r"); + ASSERT_TRUE(inner_payload && r_dict); + + ASSERT_EQ(r_dict->size(), 4u); + + for (int i = 0; i < 4; i++) { + const auto* ri_dict = r_dict->FindDict(base::NumberToString(i)); + ASSERT_TRUE(ri_dict); + + const auto* url = ri_dict->FindString("u"); + ASSERT_TRUE(url); + + EXPECT_EQ(*url, "https://example.com/result" + base::NumberToString(i)); + } +} + +TEST_F(WebDiscoveryPayloadGeneratorTest, ShouldDropSearchResult) { + GURL test_url("https://example.com/search"); + auto scrape_result = std::make_unique(test_url, "test_id"); + + std::vector result_dicts; + for (int i = 0; i < 3; i++) { + base::Value::Dict result_dict; + result_dict.Set("u", + "https://example.com/result" + base::NumberToString(i)); + result_dicts.push_back(std::move(result_dict)); + } + scrape_result->fields["#results"] = std::move(result_dicts); + + std::vector qurl_dicts; + base::Value::Dict qurl_dict; + qurl_dict.Set("qurl", "https://example.com/test1"); + qurl_dicts.push_back(std::move(qurl_dict)); + scrape_result->fields["qurl"] = std::move(qurl_dicts); + + auto payloads = GenerateQueryPayloadsHelper(std::move(scrape_result)); + ASSERT_EQ(payloads.size(), 0u); +} + +TEST_F(WebDiscoveryPayloadGeneratorTest, ContentMissing) { + GURL test_url("https://example.com/search"); + auto scrape_result = std::make_unique(test_url, "test_id"); + + std::vector result_dicts; + for (int i = 0; i < 9; i++) { + base::Value::Dict result_dict; + if (i < 5) { + result_dict.Set("x", ""); + } else { + result_dict.Set("x", base::Value()); + } + result_dicts.push_back(std::move(result_dict)); + } + scrape_result->fields["#results"] = std::move(result_dicts); + + std::vector qurl_dicts; + base::Value::Dict qurl_dict; + qurl_dict.Set("qurl", "https://example.com/test1"); + qurl_dicts.push_back(std::move(qurl_dict)); + scrape_result->fields["qurl"] = std::move(qurl_dicts); + + auto payloads = GenerateQueryPayloadsHelper(std::move(scrape_result)); + ASSERT_EQ(payloads.size(), 0u); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/reporter.cc b/components/web_discovery/browser/reporter.cc index bffc3e8b03f8..fa8b1a5ba8fa 100644 --- a/components/web_discovery/browser/reporter.cc +++ b/components/web_discovery/browser/reporter.cc @@ -117,12 +117,12 @@ std::optional CompressAndEncrypt( Reporter::Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - CredentialManager* credential_manager, + CredentialSigner* credential_signer, RegexUtil* regex_util, const ServerConfigLoader* server_config_loader) : profile_prefs_(profile_prefs), shared_url_loader_factory_(shared_url_loader_factory), - credential_manager_(credential_manager), + credential_signer_(credential_signer), regex_util_(regex_util), server_config_loader_(server_config_loader), pool_sequenced_task_runner_( @@ -146,7 +146,7 @@ void Reporter::ScheduleSend(base::Value::Dict payload) { void Reporter::PrepareRequest(const base::Value& request_data) { VLOG(1) << "Preparing request"; - if (!credential_manager_->CredentialExistsForToday()) { + if (!credential_signer_->CredentialExistsForToday()) { // Backoff until credential is available to today VLOG(1) << "Credential does not exist for today"; request_queue_.NotifyRequestComplete(false); @@ -177,7 +177,7 @@ void Reporter::PrepareRequest(const base::Value& request_data) { } auto payload_hash = crypto::SHA256HashString(final_payload_json); - credential_manager_->Sign( + credential_signer_->Sign( std::vector(payload_hash.begin(), payload_hash.end()), basename_result->basename, base::BindOnce(&Reporter::OnRequestSigned, base::Unretained(this), diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index 85eb398607ae..a3649b049c72 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -13,7 +13,7 @@ #include "base/memory/raw_ptr.h" #include "base/values.h" -#include "brave/components/web_discovery/browser/credential_manager.h" +#include "brave/components/web_discovery/browser/credential_signer.h" #include "brave/components/web_discovery/browser/ecdh_aes.h" #include "brave/components/web_discovery/browser/regex_util.h" #include "brave/components/web_discovery/browser/request_queue.h" @@ -33,7 +33,7 @@ class Reporter { public: Reporter(PrefService* profile_prefs, network::SharedURLLoaderFactory* shared_url_loader_factory, - CredentialManager* credential_manager, + CredentialSigner* credential_signer, RegexUtil* regex_util, const ServerConfigLoader* server_config_loader); ~Reporter(); @@ -62,7 +62,7 @@ class Reporter { raw_ptr profile_prefs_; raw_ptr shared_url_loader_factory_; - raw_ptr credential_manager_; + raw_ptr credential_signer_; raw_ptr regex_util_; raw_ptr server_config_loader_; diff --git a/components/web_discovery/browser/reporter_unittest.cc b/components/web_discovery/browser/reporter_unittest.cc new file mode 100644 index 000000000000..12b04a6247db --- /dev/null +++ b/components/web_discovery/browser/reporter_unittest.cc @@ -0,0 +1,259 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/reporter.h" + +#include +#include + +#include "base/base64.h" +#include "base/test/task_environment.h" +#include "brave/components/web_discovery/browser/regex_util.h" +#include "brave/components/web_discovery/browser/server_config_loader.h" +#include "brave/components/web_discovery/browser/util.h" +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/testing_pref_service.h" +#include "net/http/http_status_code.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +namespace { +constexpr char kTestPubKey[] = + "BECQDFoOR0DE3wLaDidGAC/2Mpgjasf9QgJDGGLTkTdll+pW2S/" + "RgX0pkFyDjQZc6efyX3RGQKJ2cq8HOB8vZOo="; +} + +class WebDiscoveryReporterTest : public testing::Test { + public: + WebDiscoveryReporterTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), + shared_url_loader_factory_( + base::MakeRefCounted( + &url_loader_factory_)) {} + ~WebDiscoveryReporterTest() override = default; + + // testing::Test: + void SetUp() override { + WDPService::RegisterProfilePrefs(profile_prefs_.registry()); + auto server_config = std::make_unique(); + + auto action_config = std::make_unique(); + action_config->keys.push_back("q->url"); + action_config->period = 24; + action_config->limit = 3; + server_config->source_map_actions["query"] = std::move(action_config); + + for (size_t i = 0; i < 3; i++) { + base::Time date = base::Time::Now() + base::Days(i); + server_config->pub_keys[FormatServerDate(date)] = kTestPubKey; + } + + server_config_loader_ = std::make_unique( + nullptr, base::FilePath(), nullptr, base::DoNothing(), + base::DoNothing()); + server_config_loader_->SetLastServerConfigForTesting( + std::move(server_config)); + + url_loader_factory_.SetInterceptor(base::BindRepeating( + &WebDiscoveryReporterTest::HandleRequest, base::Unretained(this))); + + AddCredentialForToday(); + SetupReporter(); + } + + protected: + class TestCredentialSigner : public CredentialSigner { + public: + bool CredentialExistsForToday() override { + std::string today = FormatServerDate(base::Time::Now()); + return allowed_credentials_.contains(today); + } + + bool Sign(std::vector msg, + std::vector basename, + SignCallback callback) override { + if (CredentialExistsForToday()) { + std::vector dummy_signature( + {static_cast(sign_count_ + 1)}); + std::move(callback).Run(std::move(dummy_signature)); + sign_count_++; + } else { + std::move(callback).Run(std::nullopt); + } + return true; + } + + size_t sign_count_ = 0; + base::flat_set allowed_credentials_; + }; + + void SetupReporter() { + reporter_ = std::make_unique( + &profile_prefs_, shared_url_loader_factory_.get(), &credential_signer_, + ®ex_util_, server_config_loader_.get()); + } + + void AddCredentialForToday() { + std::string today = FormatServerDate(base::Time::Now()); + credential_signer_.allowed_credentials_.insert(today); + } + + base::Value::Dict GenerateTestPayload() { + base::Value::Dict payload; + base::Value::Dict inner_payload; + inner_payload.Set("q", "test query"); + payload.Set("payload", std::move(inner_payload)); + payload.Set("action", "query"); + return payload; + } + + base::test::TaskEnvironment task_environment_; + std::unique_ptr reporter_; + TestCredentialSigner credential_signer_; + size_t report_requests_made_ = 0; + net::HttpStatusCode submit_status_code_ = net::HTTP_OK; + + private: + void HandleRequest(const network::ResourceRequest& request) { + url_loader_factory_.ClearResponses(); + + EXPECT_EQ(request.url.spec(), GetAnonymousHPNHost() + "/"); + EXPECT_EQ(request.method, net::HttpRequestHeaders::kPostMethod); + std::string key_date, encryption, version; + request.headers.GetHeader("Key-Date", &key_date); + request.headers.GetHeader("Encryption", &encryption); + request.headers.GetHeader(kVersionHeader, &version); + EXPECT_EQ(key_date, FormatServerDate(base::Time::Now())); + auto decoded_pubkey_and_iv = base::Base64Decode(encryption); + ASSERT_TRUE(decoded_pubkey_and_iv); + EXPECT_EQ(decoded_pubkey_and_iv->size(), 78u); + EXPECT_EQ(version, base::NumberToString(kCurrentVersion)); + + std::string response; + const auto* elements = request.request_body->elements(); + ASSERT_EQ(elements->size(), 1u); + ASSERT_EQ(elements->at(0).type(), network::DataElement::Tag::kBytes); + auto body = elements->at(0).As().bytes(); + EXPECT_FALSE(body.empty()); + + url_loader_factory_.AddResponse(request.url.spec(), "", + submit_status_code_); + report_requests_made_++; + } + + std::unique_ptr server_config_loader_; + RegexUtil regex_util_; + TestingPrefServiceSimple profile_prefs_; + network::TestURLLoaderFactory url_loader_factory_; + scoped_refptr shared_url_loader_factory_; +}; + +TEST_F(WebDiscoveryReporterTest, BasicReport) { + reporter_->ScheduleSend(GenerateTestPayload()); + reporter_->ScheduleSend(GenerateTestPayload()); + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + task_environment_.FastForwardBy(base::Seconds(30)); + + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + task_environment_.FastForwardBy(base::Seconds(60)); + + EXPECT_EQ(report_requests_made_, 1u); + EXPECT_EQ(credential_signer_.sign_count_, 1u); + + task_environment_.FastForwardBy(base::Seconds(80)); + + EXPECT_EQ(report_requests_made_, 2u); + EXPECT_EQ(credential_signer_.sign_count_, 2u); + report_requests_made_ = 0; + credential_signer_.sign_count_ = 0; + + task_environment_.FastForwardBy(base::Minutes(5)); + + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); +} + +TEST_F(WebDiscoveryReporterTest, LoadReportFromStorage) { + reporter_->ScheduleSend(GenerateTestPayload()); + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + SetupReporter(); + + task_environment_.FastForwardBy(base::Seconds(30)); + + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + task_environment_.FastForwardBy(base::Seconds(60)); + + EXPECT_EQ(report_requests_made_, 1u); + EXPECT_EQ(credential_signer_.sign_count_, 1u); +} + +TEST_F(WebDiscoveryReporterTest, CredentialUnavailableRetry) { + task_environment_.FastForwardBy(base::Days(1)); + + reporter_->ScheduleSend(GenerateTestPayload()); + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + task_environment_.FastForwardBy(base::Seconds(150)); + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); + + AddCredentialForToday(); + task_environment_.FastForwardBy(base::Seconds(120)); + + EXPECT_EQ(report_requests_made_, 1u); + EXPECT_EQ(credential_signer_.sign_count_, 1u); + report_requests_made_ = 0; + credential_signer_.sign_count_ = 0; + + task_environment_.FastForwardBy(base::Minutes(5)); + + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); +} + +TEST_F(WebDiscoveryReporterTest, ServerUnavailableRetry) { + submit_status_code_ = net::HTTP_INTERNAL_SERVER_ERROR; + reporter_->ScheduleSend(GenerateTestPayload()); + + task_environment_.FastForwardBy(base::Seconds(80)); + EXPECT_GE(report_requests_made_, 1u); + EXPECT_GE(credential_signer_.sign_count_, 1u); + + size_t prev_report_requests_made = report_requests_made_; + size_t prev_sign_count = credential_signer_.sign_count_; + task_environment_.FastForwardBy(base::Seconds(100)); + + EXPECT_GT(report_requests_made_, prev_report_requests_made); + EXPECT_GT(credential_signer_.sign_count_, prev_sign_count); + report_requests_made_ = 0; + credential_signer_.sign_count_ = 0; + + submit_status_code_ = net::HTTP_OK; + task_environment_.FastForwardBy(base::Seconds(100)); + + EXPECT_EQ(report_requests_made_, 1u); + EXPECT_EQ(credential_signer_.sign_count_, 1u); + report_requests_made_ = 0; + credential_signer_.sign_count_ = 0; + + task_environment_.FastForwardBy(base::Minutes(5)); + + EXPECT_EQ(report_requests_made_, 0u); + EXPECT_EQ(credential_signer_.sign_count_, 0u); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index dedba4f37ee8..403d0b9216de 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -185,12 +185,12 @@ const PatternsGroup& ServerConfigLoader::GetLastPatterns() const { return *last_loaded_patterns_; } -void ServerConfigLoader::SetLastServerConfigForTest( +void ServerConfigLoader::SetLastServerConfigForTesting( std::unique_ptr server_config) { last_loaded_server_config_ = std::move(server_config); } -void ServerConfigLoader::SetLastPatternsForTest( +void ServerConfigLoader::SetLastPatternsForTesting( std::unique_ptr patterns) { last_loaded_patterns_ = std::move(patterns); } @@ -227,6 +227,9 @@ void ServerConfigLoader::OnConfigResponses( config_backoff_entry_.InformOfRequest(result); + collector_config_url_loader_ = nullptr; + quorum_config_url_loader_ = nullptr; + if (!result) { update_time += config_backoff_entry_.GetTimeUntilRelease(); } else { @@ -391,7 +394,7 @@ void ServerConfigLoader::HandlePatternsStatus(bool result) { void ServerConfigLoader::OnPatternsResponse( std::optional response_body) { - auto* response_info = collector_config_url_loader_->ResponseInfo(); + auto* response_info = patterns_url_loader_->ResponseInfo(); if (!response_body || !response_info || response_info->headers->response_code() != 200) { VLOG(1) << "Failed to retrieve patterns file"; diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 7f72d4d901a8..797227ca7256 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -75,8 +75,9 @@ class ServerConfigLoader { const ServerConfig& GetLastServerConfig() const; const PatternsGroup& GetLastPatterns() const; - void SetLastServerConfigForTest(std::unique_ptr server_config); - void SetLastPatternsForTest(std::unique_ptr patterns); + void SetLastServerConfigForTesting( + std::unique_ptr server_config); + void SetLastPatternsForTesting(std::unique_ptr patterns); private: void OnConfigResponses( diff --git a/components/web_discovery/browser/server_config_loader_unittest.cc b/components/web_discovery/browser/server_config_loader_unittest.cc new file mode 100644 index 000000000000..cef07c5d7c90 --- /dev/null +++ b/components/web_discovery/browser/server_config_loader_unittest.cc @@ -0,0 +1,281 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/browser/server_config_loader.h" + +#include + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/path_service.h" +#include "base/test/task_environment.h" +#include "brave/components/constants/brave_paths.h" +#include "brave/components/web_discovery/browser/util.h" +#include "brave/components/web_discovery/browser/wdp_service.h" +#include "components/prefs/testing_pref_service.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +class WebDiscoveryServerConfigLoaderTest : public testing::Test { + public: + WebDiscoveryServerConfigLoaderTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), + shared_url_loader_factory_( + base::MakeRefCounted( + &url_loader_factory_)) {} + ~WebDiscoveryServerConfigLoaderTest() override = default; + + // testing::Test: + void SetUp() override { + WDPService::RegisterLocalStatePrefs(local_state_.registry()); + + ASSERT_TRUE(install_dir_.CreateUniqueTempDir()); + + base::FilePath data_path = + base::PathService::CheckedGet(brave::DIR_TEST_DATA) + .AppendASCII("web_discovery"); + ASSERT_TRUE(base::ReadFileToString(data_path.AppendASCII("hpn-config.json"), + &hpn_config_contents_)); + ASSERT_TRUE(base::ReadFileToString( + data_path.AppendASCII("quorum-config.json"), &quorum_config_contents_)); + ASSERT_TRUE(base::ReadFileToString(data_path.AppendASCII("patterns.gz"), + &patterns_gz_contents_)); + + url_loader_factory_.SetInterceptor( + base::BindRepeating(&WebDiscoveryServerConfigLoaderTest::HandleRequest, + base::Unretained(this))); + SetupServerConfigLoader(); + } + + protected: + void SetupServerConfigLoader() { + server_config_loader_ = std::make_unique( + &local_state_, install_dir_.GetPath(), shared_url_loader_factory_.get(), + base::BindRepeating( + &WebDiscoveryServerConfigLoaderTest::HandleConfigReady, + base::Unretained(this)), + base::BindRepeating( + &WebDiscoveryServerConfigLoaderTest::HandlePatternsReady, + base::Unretained(this))); + } + + void ResetCounts() { + hpn_config_requests_made_ = 0; + quorum_config_requests_made_ = 0; + patterns_requests_made_ = 0; + config_ready_calls_made_ = 0; + patterns_ready_calls_made_ = 0; + } + + bool PatternsFileExists() { + return base::PathExists( + install_dir_.GetPath().AppendASCII("wdp_patterns.json")); + } + + base::test::TaskEnvironment task_environment_; + std::unique_ptr server_config_loader_; + base::ScopedTempDir install_dir_; + + size_t hpn_config_requests_made_ = 0; + size_t quorum_config_requests_made_ = 0; + size_t patterns_requests_made_ = 0; + + size_t config_ready_calls_made_ = 0; + size_t patterns_ready_calls_made_ = 0; + + net::HttpStatusCode hpn_config_status_code_ = net::HTTP_OK; + net::HttpStatusCode quorum_config_status_code_ = net::HTTP_OK; + net::HttpStatusCode patterns_status_code_ = net::HTTP_OK; + + private: + void HandleRequest(const network::ResourceRequest& request) { + url_loader_factory_.ClearResponses(); + + ASSERT_EQ(request.method, net::HttpRequestHeaders::kGetMethod); + if (request.url.spec().starts_with(GetAnonymousHPNHost() + "/config")) { + hpn_config_requests_made_++; + url_loader_factory_.AddResponse(request.url.spec(), hpn_config_contents_, + hpn_config_status_code_); + } else if (request.url.spec() == GetQuorumHost() + "/config") { + quorum_config_requests_made_++; + url_loader_factory_.AddResponse(request.url.spec(), + quorum_config_contents_, + quorum_config_status_code_); + } else if (request.url.spec() == GetPatternsEndpoint()) { + patterns_requests_made_++; + url_loader_factory_.AddResponse(request.url.spec(), patterns_gz_contents_, + patterns_status_code_); + } else { + FAIL(); + } + } + + void HandleConfigReady() { config_ready_calls_made_++; } + + void HandlePatternsReady() { patterns_ready_calls_made_++; } + + std::string patterns_gz_contents_; + std::string quorum_config_contents_; + std::string hpn_config_contents_; + + TestingPrefServiceSimple local_state_; + network::TestURLLoaderFactory url_loader_factory_; + scoped_refptr shared_url_loader_factory_; +}; + +TEST_F(WebDiscoveryServerConfigLoaderTest, LoadConfigs) { + EXPECT_EQ(hpn_config_requests_made_, 0u); + EXPECT_EQ(quorum_config_requests_made_, 0u); + EXPECT_EQ(patterns_requests_made_, 0u); + EXPECT_EQ(config_ready_calls_made_, 0u); + EXPECT_EQ(patterns_ready_calls_made_, 0u); + + task_environment_.FastForwardBy(base::Seconds(40)); + + server_config_loader_->LoadConfigs(); + task_environment_.RunUntilIdle(); + + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 0u); + EXPECT_EQ(config_ready_calls_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 0u); + + EXPECT_FALSE(PatternsFileExists()); + + const auto& server_config = server_config_loader_->GetLastServerConfig(); + EXPECT_EQ(server_config.location, "ca"); + EXPECT_EQ(server_config.group_pub_keys.size(), 4u); + EXPECT_EQ(server_config.pub_keys.size(), 4u); + EXPECT_EQ(server_config.source_map_actions.size(), 27u); + + task_environment_.FastForwardBy(base::Seconds(40)); + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 1u); + EXPECT_EQ(config_ready_calls_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 1u); + + EXPECT_TRUE(PatternsFileExists()); + + const auto& patterns = server_config_loader_->GetLastPatterns(); + EXPECT_EQ(patterns.normal_patterns.size(), 9u); + EXPECT_EQ(patterns.strict_patterns.size(), 8u); +} + +TEST_F(WebDiscoveryServerConfigLoaderTest, ReloadConfigs) { + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + + for (size_t i = 0; i < 3; i++) { + ResetCounts(); + task_environment_.FastForwardBy(base::Hours(4)); + + EXPECT_GE(hpn_config_requests_made_, 1u); + EXPECT_GE(quorum_config_requests_made_, 1u); + EXPECT_GE(patterns_requests_made_, 1u); + EXPECT_GE(config_ready_calls_made_, 1u); + EXPECT_GE(patterns_ready_calls_made_, 1u); + EXPECT_TRUE(PatternsFileExists()); + } +} + +TEST_F(WebDiscoveryServerConfigLoaderTest, LoadPatternsFromStorage) { + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + EXPECT_TRUE(PatternsFileExists()); + + ResetCounts(); + SetupServerConfigLoader(); + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 0u); + EXPECT_EQ(config_ready_calls_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 1u); + EXPECT_TRUE(PatternsFileExists()); + + task_environment_.AdvanceClock(base::Hours(3)); + ResetCounts(); + SetupServerConfigLoader(); + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 1u); + EXPECT_EQ(config_ready_calls_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 1u); + EXPECT_TRUE(PatternsFileExists()); +} + +TEST_F(WebDiscoveryServerConfigLoaderTest, ConfigRetry) { + hpn_config_status_code_ = net::HTTP_INTERNAL_SERVER_ERROR; + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_GE(hpn_config_requests_made_, 1u); + EXPECT_GE(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 0u); + EXPECT_EQ(config_ready_calls_made_, 0u); + EXPECT_EQ(patterns_ready_calls_made_, 0u); + + ResetCounts(); + hpn_config_status_code_ = net::HTTP_OK; + quorum_config_status_code_ = net::HTTP_INTERNAL_SERVER_ERROR; + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_GE(hpn_config_requests_made_, 1u); + EXPECT_GE(quorum_config_requests_made_, 1u); + EXPECT_EQ(patterns_requests_made_, 0u); + EXPECT_EQ(config_ready_calls_made_, 0u); + EXPECT_EQ(patterns_ready_calls_made_, 0u); + EXPECT_FALSE(PatternsFileExists()); + + ResetCounts(); + quorum_config_status_code_ = net::HTTP_OK; + task_environment_.FastForwardBy(base::Seconds(90)); + + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_EQ(config_ready_calls_made_, 1u); + + task_environment_.FastForwardBy(base::Seconds(40)); + EXPECT_EQ(patterns_requests_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 1u); + EXPECT_TRUE(PatternsFileExists()); +} + +TEST_F(WebDiscoveryServerConfigLoaderTest, PatternsRetry) { + patterns_status_code_ = net::HTTP_INTERNAL_SERVER_ERROR; + server_config_loader_->LoadConfigs(); + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_EQ(hpn_config_requests_made_, 1u); + EXPECT_EQ(quorum_config_requests_made_, 1u); + EXPECT_GE(patterns_requests_made_, 1u); + EXPECT_EQ(config_ready_calls_made_, 1u); + EXPECT_EQ(patterns_ready_calls_made_, 0u); + EXPECT_FALSE(PatternsFileExists()); + + ResetCounts(); + patterns_status_code_ = net::HTTP_OK; + task_environment_.FastForwardBy(base::Seconds(40)); + + EXPECT_EQ(hpn_config_requests_made_, 0u); + EXPECT_EQ(quorum_config_requests_made_, 0u); + EXPECT_EQ(patterns_requests_made_, 1u); + EXPECT_EQ(config_ready_calls_made_, 0u); + EXPECT_EQ(patterns_ready_calls_made_, 1u); + EXPECT_TRUE(PatternsFileExists()); +} + +} // namespace web_discovery diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 39e8399ebdfd..692d3ad5afdf 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -26,8 +26,7 @@ namespace web_discovery { namespace { -// constexpr base::TimeDelta kAliveCheckInterval = base::Minutes(5); -constexpr base::TimeDelta kAliveCheckInterval = base::Seconds(10); +constexpr base::TimeDelta kAliveCheckInterval = base::Minutes(1); constexpr size_t kMinPageCountForAliveMessage = 2; } // namespace diff --git a/test/data/web_discovery/credential_keys_and_responses.json b/test/data/web_discovery/credential_keys_and_responses.json new file mode 100644 index 000000000000..9fbc3cce99e8 --- /dev/null +++ b/test/data/web_discovery/credential_keys_and_responses.json @@ -0,0 +1,10 @@ +{ + "rsa_priv_key": "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCsD7x4pzqvukjWYyPQiH4KTgxV+ep6hsW+3V3z5vo0M86a4fXcvPnVJ2N4doYz3CsC4YJWftZKiLyY1h/e8ZB9ERd6bkaxRD6lXg26Gry/YPO+gFlhszolLPnFxYaBtTTq4Pt34xseD5jQkiTNXSYNSbpxX/ZNiCn/C55IcUWf7LL6Buufr1ckqz4GIFPclV3+W1+qCb82I3ToMjluKIcApHjXhvZmw7EPogAaxFHXWJmixAE0EVIesBR+DGlPZqqDayiOw2BKZl5zlzvnL04AGyFX7/BWUBZthJuNb6whY20WoU0pZTsf92W0AFthafW4CqPqGXK+QQe4fbtG7f+dAgMBAAECggEAHiUbph/WXldKz5TK/4wKWQ/XhXClrhXSq1/pSAQdreuttOEFzEinlLqz6LULSia2umh8B19td92A/V32c37rC55k+KQ9am1EdICH8yUgEH+R9LxT7JQUCdNZZ1b1+9+dh9Em/Zgidh/RbClOnVRGiGl0asyfQHIsuWx1rMd7pUrvBufy/bEFbcEio7r009qM8CxluS6zRmXO4tWNoZFu42JYjJcEnU+a1mRJ06n1GaVJ0dLd1IA5g4pvVF8wy6R3bQb9xRiwLQMBuG0vLhm69YeyJwHShE5S4WqsubtcxkiZrPak7MLlzwsxk1wU52PbTk1T3geqH5JIerwJ5g7CGQKBgQDq17z9e9OedERboUgXU/nZpSWOqZp5Ukw/dx2xWVtMKhGg6wWoIvadDEeke9RB6JbAlSmBcvT5A8D8P0/1OiatK0i2Yyj1MzuxACnJkYaPjp0Xl4wpZJH1t4QkWEpztPx/JdY6O08WYAbdl0GJhNbL5rqCOS3FZhLpj9OH42IRgwKBgQC7kA0nfifnRRoiL2NwVLeAuG2O4b8JfRPehLw63kl/C4VVbZt0P99EqZwUuKv/nvlrvAfBinwhXvtWhX3GvLUnAQm5eGEt1BMd7GJaIylHFpmlt4+qcoyD+jyd0Jbq4vwiNiupZSZctqRmbu9rLdkoEzSGkkvyY6GQbJxc/ZiAXwKBgAJSb8Px3X3LmIFvbs8MPYQxZdWrR6O7dJWMD/cY8xYltFbq+/tVnSqgXHT75HViX1s4HljxUgrERrw3xAqgsJE1xFpJULZb81MktUUQ80uoFVWOYgxmuiq7zcquNM5AE98N+LhKrdWCzY6TWEqLzbPmbCGtfw5cnANDMMw/K1ERAoGAaLrMvYqR2W8aYpA3ZBfJxxQ0CJ5Av5mZqJxRRkWsoEXck5D6RnULxBk4z9E2KSupdeCuLAGZwkB48xzi2D+yny7TMT7odGCAtCqz2ETd3ZXfAUt36uK/V0o44p4ARvOreabpxlJ2kzpgndm/0gbtxJTEtYem5JeBNVWQEdSAfN0CgYABJjSTY6fDJ1Cj18eiTWY4Tq2phUJQedhZr7/m6e/OZCi40MBiBZ8rdpqqIJzwIVqeei3CTvgZGPa8uKBjMxFZ1ikfNe2+/MA629Cq2FfSNEw1k/+w8uMUMet/Zb+mJ2a6HGZdNfck/5STVYkjKVoIx9jagBBaG1gTbkUcA/XA8Q==", + "rsa_pub_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArA+8eKc6r7pI1mMj0Ih+Ck4MVfnqeobFvt1d8+b6NDPOmuH13Lz51SdjeHaGM9wrAuGCVn7WSoi8mNYf3vGQfREXem5GsUQ+pV4Nuhq8v2DzvoBZYbM6JSz5xcWGgbU06uD7d+MbHg+Y0JIkzV0mDUm6cV/2TYgp/wueSHFFn+yy+gbrn69XJKs+BiBT3JVd/ltfqgm/NiN06DI5biiHAKR414b2ZsOxD6IAGsRR11iZosQBNBFSHrAUfgxpT2aqg2sojsNgSmZec5c75y9OABshV+/wVlAWbYSbjW+sIWNtFqFNKWU7H/dltABbYWn1uAqj6hlyvkEHuH27Ru3/nQIDAQAB", + "group_pub_key": "I8s5zyMT4UHmqR4a99qBnZWXcQt8l4sePztiSEudSeUZqfnUZaWvV8MmeI/Wo0QwKpFNoxYabxfoqXr26KgDLyRdJc5/pCH4o6v714iE+QqNWQDItrGff9l2UcSYI0QhDugl3PWLCswyqeQjLYZkCIk/Qo4iE5eOmW9cM5TsxQ8DYk2USWuMtz+h72xmfomQo28Fyb1GtdQU4LWxfXMLUR3ttXPoJ/IYTxeZNfFuDWGUa3MWdlAJLgdWNsWaDyPiBgzntlxiw5q5xdCTJkmNcNzbZlVRHeng+ZX41gxY4scIP0+pMVtPQFj4NFAFAxVjMl4Zlrvzuy6+Iut3LYLBxBQG1TiY2dANuXJlvZbOC8jUsgeZvKZnwCG/ljnaZQ0CGyF0/ydNadCsSLPFfTiecSJkXL1Pi5NLxzacG/4QBPIhy4VjU4Gg17HNzbYuKljCvS0jAbYsuDEHqi7Z4MXTpREafV3WTE9yGdB2zE/RMRklUNukcAC1ayAjb4tIw6yD", + "join_responses": { + "20240622": "BAh+HPSF0v2NgWIsqbaFlZokWS5+yuzg0WJAcT1AlAZwIz5/e7n2v7P79pa3LzKjklJ4xUM/WZiujbNZd3gfX5QEFS55KwibK5dEdYMTzDiHWMU4OSIV7p/ZWmjs61Apbx8gnckDONbUOrf4FR2Y46SMp4/VxaZju+S6qBVFdbgqdQQG85r4caFZa56KdERRvy19pfnCdYTDvKedWs7V8xc6LhXjMbFIMlRv0ExlONRTtD3NqOynppR9UCIZmVyaQ+FiBA+uiU9RkwWpAvg2oTAWyS0XbgV6xFe2YlY1mvbpX2ZyEPS+aCmbJo/8/X0piHvcd01D6ytLZfUKQ3qFcoh2mZUGRo7N4bow9J5+dHZkSDQN/r94XLA4uJrTM2dxeFeNAyNlEuSYnxzA9YBRF6YyPuRlWRHXxhSlqO0rbspV+fEX", + "20240623": "BAms4nX6G89VWTmPwwy+sMc9H+ymwfTeBGbtkle0XByTFtkhnki68EGUgfgrYzOQBffl7XlMvIfmtV9nTPr6GF4EFpldOPmsuo9qj6xcL5sSKt5UJh2GrKi2Xd1pXtsU3b0gRy3TCQfxrbLN9UtJTlgazIraaVLOaD9mNiG2A71s8gQk0AdA+70haTw/ATXuEn0nQwVxNs/ZQokykOJ2d3GUmh7VG7Hwdylc/kwQxBqx7G3qILydEifJ6rI9XBFiYjSUBAutyyC9rWtcFLspGoyeb26/8vDtR0xpB6EyNSRmuiYKGHzY4FJPI5LzWrbawR7EDMfQmX2d4UbH3s6tbAK7we8BdyNNdafqz7Lu4FMS8FzI6dVsO/kkxsgK8ihAgCYpBxOTcw5QkXxHzbyMfMv04hJ0GM0xpjAtqe32r197jvC7", + "20240624": "BCHYKUHSD/1fgTW15TKBdgdT15gxg3vVwycHfZfdwhT9DTLp6o/AoAq31yBKjCdS2YOyR+w1jU9XTIA5fhaeWxUEA97oWXnmVn1A+K6laHCRvi2XvBl8JpZHX329Z013j1oKVPhnAoAPpk3l365bQ5YTtl2xTzRtYRGjkGs+VtKvWwQSkXXdd7SotMuCuMmigtm35FYzv1Y6u3Xc5DbTAfL56BFXKGErbIfHXsoO6XsDgp0wDMMsDsLiMFqwSpzNZu48BBc1Cx4hYcLGAiJAHArLDAJhtQReTBQy0rxEjB+/ZIBCB+M54YCaL8w1Ug71oXxzHrMlxq9Ba1R8vSaXxtUhb1MWLRJM7HftXZsekyYF7XzCyjZCij56fl7Sm/N0NPoPnAOQJ3joU8LCUWJKTvaxBE5SpcVXauvY8jm3xUSoEtIz" + } +} diff --git a/test/data/web_discovery/hpn-config.json b/test/data/web_discovery/hpn-config.json new file mode 100644 index 000000000000..c4d335233ca9 --- /dev/null +++ b/test/data/web_discovery/hpn-config.json @@ -0,0 +1,146 @@ +{ + "minVersion": 1, + "groupPubKeys": { + "20240624": "ITmwC7dQpF5vcMFbe8U/k7hdg7ZSWXsOswfkcxm7nJoBsx1c6O+kJcyiXIZR08t5Nf64tUOwptEDqxWkIWLToQ0S2G21Yfh9Vif0+zAb45f1m3+9plm9sKncHFNuoeJZI/f/vQfeo8yd/jpqCKMXNY6VWWlEMESYIeIsLZtUxPUOx6lQG09iRtrvHUHVGlaN5VGAKNoTVFfiCgNl373iZR1k0ZvW0wdA7OkJiTVj3+osawlfpeYhZSmdWo7qsZ3UDkoy9faYFBGsTScQJsLsgQh72gQBa3VgIWPWt/lLn38QbqymAMc/OZsf11hjkXP59t9V/9Ugv7vYFsAxRT9SLQR8eB8sATtrQ1DmqCesvhdCpOIftZOfn70u4S8pYrXGHTyXNZBSYo6CG0nj0cJOfXK9wrm/PeSXB5wdLQSLzqoHrzR8cEuJEbWW1D/4lAVGMGQTMOLLOcxo0n9nH+QG6iNoT1aIaPjmn2QwAx/ohIEH53YKkxp0DNmTDQOETI/k", + "20240625": "DSoyIdA3VA6CjOhWEBh7ZCreAI2nOYD2JUUynaP+prUgM/GOl68av5u+3KFRhrrITKwGDOLzPV3wCM/FRkG1HxINxQRHFNOgcE9qKbc75LAmjIYuoAE+VqBdmvlYXzzsFyKCFhytVsiZ7DLAPX9fmRdkxJidA5KEF8k5EzOKtXkLp/PzWaFqDsif3zSsm/yXkQOtjfd7XhpJ0kmYEuhS0BY9FeuCGvkIhvW1zEf7WDVaty06yAr2QlpsPDHd604fGlrzNh/41PiXsiWtWLgKG1MLRvt6yV0jnfhF2Okawl4ecdl0CkSvxiusZyKgLSKVSiEP00fY2BR1fYyH/DL3fQXrAZo+MhY91V3M55oxsnliSxLRtcU559rNokQuTKFXAHiVTnDPI40Def11OLLPp/ZQgICtUa/azW4cu6sEkY0KE8ebJDplsqM5ehsMh5RZeVm7NJZEret4z6hFtm45jhgyEDoQMyv5Mn86X0q8QtAdM6wKpVRU2ymy9S2DdqKt", + "20240626": "FuqBHl3PCRXlhHSqFSrQBhCOzgmZQDCZLR27U/a+AlUj6H+XXoN5jroQTKJ091Rb7W360aIgS+I4CLCQgZS+ERCEikPh5WNlvLV1UpQ6pDtpCFZagrirsLQLx+CEqEojC436N9vC+OOM9Gg/gZWuBliAQRkDwzlwhJ+at/qFZeojH+NSvCDdgUVIgkw60BxDNFrOFoJknfxXf7B6m9pjYQ+ZDGppdvJMrhMiARX1jMce72QbzSlSxbzRE1PK951gJIKICdDjY51hP7aQM9WqSswd8LNEp741yAVyFd3n4aEVSaYUgzykpzzTIGf7pVOt8CQXqBzJZzTc6/+1WuUyfhDNFEnO3Ep4yAb3H03Mv9SXBSwGaoucaL8kGRZfSyMUC2idJUQKbg6VOPXAEE2LMfSQQzz5Zgl6GSROv45QgRIMhXqDLdiSknFfmUQUKFkMi7oBN2JYesemz8QIIyw0px90wMchsF23n7EdtVVBj0E7HVj/uMISTIxeQY7mv27n", + "20240627": "DTwg0yh8wrUSKWVXlhp879+E64ART4w5Drt47ezgCdIb0HgZeU3iE2pc8kMb+UarK0XWA5uC0jA6vrkXJlcNVAY1sEl7NO/V8eDI5EavwbXiTJzBlCJabHeeanE7yLMTGXofjgxYUvGjAiompViQsaQH+6hAh96LNxBmL8lnGscRjn6t12/YeaiYui/fvmGfjf+05bnz4gcKl8U+3k2lQg+t9jY8qzzNJZOwk4FutovPBWwDcu8Mms2Z2K1+MErJAkGjP2wrNDBqgQm2s0hdQDNhOPGKqLv1CnPsLf+5EZEF6FYvU3e71n0fX9y8pGBMVRvSW0zlqbF9l/W7+oM4+g3WHQrPirJq4v7D7OZ4pjgpLTHjxGms7qhOqJHrEbCzBBtgR1MjKvPj2lIjGld+TE2JznLavqJ9aKhxc5EfoZAczdWSIR+qbFpt7RcyeTpNIdZWQkDG2sEavlFXWfzb7gn5GZwg8YPL4XKoSyErqKl1TvIuGws/oehTzNe4Nz/B" + }, + "pubKeys": { + "20240624": "BECQDFoOR0DE3wLaDidGAC/2Mpgjasf9QgJDGGLTkTdll+pW2S/RgX0pkFyDjQZc6efyX3RGQKJ2cq8HOB8vZOo=", + "20240625": "BEURJ7UWSqV/OsxhCDyoQtAX2F5Vm/CKh6NS8SjIvz5RWtVOkyfEnR+XkdcldmyQk2AwOhLMEV/ZIwbThVmvmrQ=", + "20240626": "BDjEnHSmPhNywOIvDo2kWAzz7S/Cf2xDZEjZTTOp0FCb/Qk6uoSb8R7PF8Ne2RAMkCifeKIUtR1mF/Enmb+VFBM=", + "20240627": "BO7isKljTTltnCBtM4hRUV0fcxlH4kjvWVVummU2irqq6i/jLSgF+lR+/qOL4fqrzCsBJnIn8lTvsEOAfzg9XDM=" + }, + "sourceMap": { + "actions": { + "alive": { + "keys": [ + "t->url" + ] + }, + "page": { + "keys": [ + "url->url" + ] + }, + "query": { + "keys": [ + "q->url" + ] + }, + "query0": { + "keys": [ + "q->url" + ] + }, + "query-am": { + "keys": [ + "q->url" + ] + }, + "img": { + "keys": [ + "q->url" + ] + }, + "img-p": { + "keys": [ + "q->url" + ] + }, + "video-p": { + "keys": [ + "q->url" + ] + }, + "videos-p": { + "keys": [ + "q->url" + ] + }, + "place": { + "keys": [ + "->obj" + ] + }, + "places": { + "keys": [ + "->obj" + ] + }, + "places2": { + "keys": [ + "q->url" + ] + }, + "category-am": { + "keys": [ + "curl" + ] + }, + "ads_A": { + "keys": [ + "q->url" + ] + }, + "ads_B": { + "keys": [ + "q->url" + ] + }, + "ads_C": { + "keys": [ + "q->url" + ] + }, + "snippet": { + "keys": [ + "q->url" + ] + }, + "snippet2": { + "keys": [ + "q->url" + ] + }, + "snippet3": { + "keys": [ + "q->url" + ] + }, + "linkedin": { + "keys": [ + "profileLink->url" + ] + }, + "hw.telemetry.actionstats": {}, + "locdata": { + "keys": [ + "q->url" + ] + }, + "ads_D": { + "keys": [ + "q->url" + ] + }, + "usercontext": { + "limit": 0 + }, + "sq": { + "keys": [ + "oq->url" + ] + }, + "ad-ctr": { + "limit": 0 + }, + "top-stories": { + "keys": [ + "q->url" + ] + } + } + } +} diff --git a/test/data/web_discovery/patterns.gz b/test/data/web_discovery/patterns.gz new file mode 100644 index 0000000000000000000000000000000000000000..966ab484915258f96cb9ba8b620416ea617ff024 GIT binary patch literal 3762 zcmV;j4o&eNiwFP!000021Kk{JbK5rZ`~3=yd=uNTNF{a>C+;}DJepkEyj?d=6h;G* zkjR)X0gz<5&40Pya=+|$0a79>@M~JEcr(>2$@g3=FuO`A@kl6 zAt(!Y^QhDO{8{gZVc(;0q2D~|Y@OWr$=KN$9CyClF!pZjsGr@N!t{?_ZaKSu?j)D9 z#<=(HZnM?=;s_D(qfXnvzb|d$W=A&^3bV&vK}2DmDTU@wh8-e_}5nB{a%j2(Ti zbHms@K>+^*2ryn(jrxQ*VVItElZh0i_s9LnAnBN0VSxrJXn zP@E16J$n2(2K2dUV8Z~vTtWTjk?hoPgJ>u^0r9cx0DHBXVuGOJf$xTtP2eVt?~aH! zr0_q?>otsmJA>x8Z{LtM0BwhXc<2*hIS!@v@5 z81P3?wx1|(=d>P^3&G)FP}|%8=3e1UqA0HKQvvBY6^H`i}$QR z)dL*7}0*%E=@PvOy}m6)L+ zjHSSHW@UiGSg(oP8hW0(H3MXUhR{GXoP!2g1W(XQkpb8X5L`^+OR#QLAv%oqG7uw4 zpfzL+hJFZHA;d^W{RL}Emr?pe_0E8|#!_7@0ZazK$#23hK>{23JOdsMUsJBvQ)4VU2Q$R+s8PcTxOVF%8*R3&`^xOd4dtWmd=%>Yo zzRA0&v;G&pG zMtpQjC{-?<(Q1hRV<9@}EMQGbO&mMKT$MlQ(|}ypenp}PV8>BSvmd%L1j4J4421AX zMngx<37Wt=IOX8NmeJ8s6Jt16MoH>g21{Vca2ogJg%Um&%(cY-MVMVkahWi>6Ag?X zEt1|yl&sVo3}Aa2*C>m1)N>gZn&r5joe5{^S~96?gV+`%zl#mcTui8L6o!R9;TI4U z_K3%+`c{GACd``tJ`ksVPcDy?brlRuyFmM1KKK|eqMyU1cm}O)m?Wfq&DL$S3e(#+ zh#&pL$?=)I7@>W-mF)nHc+UWWS(;4!*#q}U+_3m}R#z{`W@cZpdS zphzW4TS|52!Vbp6Ri0S-eZnV!rOBWz7dH-8GFsaHBjmI3W2z-`36hPxT7uKp1BZOt zw<_snPRJ=J&Or?kLoh&tEW9Lpion~#2!hPYgj`wRgt!OyUI{+)6! zVh1qnZYCC6z&0<9Qm*=5)pg=6z=`0U^tz57UG6_O72m2NaTei7F%-pNo1D!l;CJNS zv*+F^v9F7T(ltE@&quwD@(*1!(LZ<-`wg8k?>le|r}O5Nou8XEy+t-Kl7 zBp*Aj{pEOj6nP}tHu8KdXY&$6ws_Ej2r@P;W++7Hmov+%IkJYvwXF|P6fDL+>(g?MO#wo+r9pwTYscLr|(f@BYG^YPpxc5~jLmyG#Yf zJicEV4PZ!nfF#+#%)$$;i`gD}tRue!;}1#r`t#)R`=Kc>-QKGQZ(_%UJGy}=&hlc- z#m%ILjiUg9c)5?Xb9=Wc%kh7C21M;@s17Qlk~lEV4|vWbUO>9hGc`+G>c2id_wUeF zLkBgA6O*Y0Awn?MHtIQU#5zp{A-~k0Pae?^lI>DjN)~4?PcJ9ERwLglUfK8G^k2}T zJ%Kn++hku18|rqF$qiSkRtQt`QVjB=M{)RM)TM?rTW#Kw}-zaDZKvSg55id z?`=kX@`(0SX0|tvuhm%Cm#iLLPXpzNHgV+!3eV&&f{Ytmy@+v7@4tNT?@3ko01beL z8JGwT=E5WDdEJn?{i;Ai2~>5Of%S%6pF}NO8(+B}+SEI?&%(=3meHAcX1Ml*5qH8= z3)ZwpnIX3^`kL$a@%+s1t8RE9*BOMa76cG&K)~DE3dq8ZBrj*e@%Ad!Zm5($5ky1( z{UUn)*vvZ=-8!eXW5w}w|5jwzawx>MS#G&LdHup1CH6PA{ZtUw<8W^-L)*h{(k94U zC?36AX}J2XY_yQ{v}5UO+(IGZnV3abIONom5|kmI4OiXykS~YJ6&}s|NM#sPu1INu z7m+?)0dLl^0H~60Y~#lswfj_)9+c?WcS8F2;L4Of(!u60$9T?Y=$Eesk!j~i zL^QvCB%innX+B+^9zHeeM}k#|lzJ9vV+U3sDx?;278TK#2`=>0x1X-=nGI(@9cDo2 zBUj3jP4r6Jz12`EbD_VudVPABY#+TFJimQvs|{MSs{&MMkQ5Ba1dQEkx;}3ibL3oD zM{QV~a{qUFafHJt=SZe>$>aNjN354P=$Gv3oYgaQu=+x4J~f1yP2CYBwH9qJPT7(H z*|iv2tB(eotvi`r(0|R=CUbaf)iI9usE;QsY@#e}K?$vWLG{ z-99apkwiUy`tj1S(gcD=p?0Hq>Wt+a$KvE87DlAE1JaDYI&@crAZvCH2A2I zoTQ9YRrex_QlwNDJi?xC)*GT*??w)&+L8Q5q7(!>uJN=FBBw^^6IHeijk1Du z!XcB~6H*D|0-+ff{-{Q&9F(d9w{4wx{cz4y9W|?( zBMsX;d8k13oKNf|oIZ^6G&cxT5}%7NoPAjzRy%$r>77r4g;yTI%BvA=z!cz+ zT$R-$Kxe&5r=s17Qghp6*%9d6oR?|?oa5=%@FGdYk1=YpEPP&4>+FzyzZtf!_jvYu z8iV{}C2Q8cS9^FwNjvq>NKM4@VMh>3JpDoP;7C%P4urtxYv=}r&yyq-*R!JGYSWN= z;XL>FOI%>Lh_nRRO49b@C?;0{TZzD=TZ+Cc#2gi?h|f{Ew1%%5r2wY;D96bKu-B$} zaRFU5nnf6CT!hS}#X2yDVN;Z+E7dkk@)Y#iwC1bAHbrO#?z&XY)m&BA+9z51vJlti z;);r_>f}Dnv2z)Mb*Z108&#sx3oRrgOQ!@?g&t$`bv@Ol!2>sns3=}$o1kc2>1?K? zrWRB73w+Xgl&rnbN|fc)n(9GL0aoGJkdH_*)`~O_a@5L#n-<=e#KixGg9Yn-`rt%0 zvlN7ZRuHNvaCwFlK6O-{J*onyI+5}OlkYDN_7Vn3(B=_W2e%kIF&OREvlFaRHCSi92eICUHfE~pkGCK z#bTrC8Cqq*lqabC+~(_pzUM@;*vnD9uxhAAj$DuOLJC$Azr5_D+Cm6=A#Q9|qCG>A z%=i})lo-RMUF6B?%3i}2U9PpB0^gP~6^c=(%%HlnLD>|fhGmh?SYK(-u+AVnw68HN zCHP9?rcScrI6R`RF)XS)Xx+nOBvsaF)(w*jkB`^gS(^gOS*ZAgwmfN-k1^NVdtHfQ zE+vT%#LCa;o|@5N>irh$o$*wc)%<&k)} Date: Tue, 25 Jun 2024 19:30:55 -0700 Subject: [PATCH 26/36] Add Web Discovery Android pref, add buildflag and feature guards --- android/BUILD.gn | 2 ++ .../org/chromium/base/BraveFeatureList.java | 1 + .../settings/BravePrivacySettings.java | 24 ++++++++++++++ .../res/xml/brave_privacy_preferences.xml | 6 ++++ browser/brave_local_state_prefs.cc | 8 ++++- browser/brave_profile_prefs.cc | 13 ++++++-- .../brave_stats_updater_browsertest.cc | 1 - browser/brave_tab_helpers.cc | 24 ++++++++++---- ...browser_context_keyed_service_factories.cc | 8 ++++- browser/sources.gni | 11 ++++++- .../android/strings/android_brave_strings.grd | 6 ++++ browser/web_discovery/BUILD.gn | 33 +++++++++++-------- browser/web_discovery/wdp_service_factory.cc | 4 +++ .../java/templates/BraveConfig.template | 1 + chromium_src/chrome/browser/DEPS | 1 + .../flags/android/chrome_feature_list.cc | 4 ++- chromium_src/chrome/renderer/DEPS | 1 + .../chrome_content_renderer_client.cc | 15 +++++++-- components/web_discovery/browser/BUILD.gn | 13 +++++++- .../browser/content_scraper_browsertest.cc | 9 +++-- components/web_discovery/common/BUILD.gn | 21 ++++++++++-- .../web_discovery/common/buildflags/BUILD.gn | 12 +++++++ .../common/buildflags/buildflags.gni | 8 +++++ components/web_discovery/common/features.cc | 14 ++++++++ components/web_discovery/common/features.h | 17 ++++++++++ components/web_discovery/renderer/BUILD.gn | 4 +++ renderer/sources.gni | 9 ++++- test/BUILD.gn | 10 +++++- 28 files changed, 241 insertions(+), 39 deletions(-) create mode 100644 components/web_discovery/common/buildflags/BUILD.gn create mode 100644 components/web_discovery/common/buildflags/buildflags.gni create mode 100644 components/web_discovery/common/features.cc create mode 100644 components/web_discovery/common/features.h diff --git a/android/BUILD.gn b/android/BUILD.gn index 878875f741bf..e92bcd159773 100644 --- a/android/BUILD.gn +++ b/android/BUILD.gn @@ -6,6 +6,7 @@ import("//brave/components/ai_chat/core/common/buildflags/buildflags.gni") import("//brave/components/ipfs/buildflags/buildflags.gni") import("//brave/components/p3a/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//brave/components/webcompat_reporter/buildflags/buildflags.gni") import("//build/config/android/rules.gni") @@ -29,5 +30,6 @@ java_cpp_template("brave_config_java") { "BRAVE_ANDROID_ENABLE_IPFS=$enable_ipfs", "BRAVE_ANDROID_WEBCOMPAT_REPORT_ENDPOINT=\"$webcompat_report_api_endpoint\"", "BRAVE_ANDROID_AI_CHAT_ENABLED=$enable_ai_chat", + "BRAVE_ANDROID_WEB_DISCOVERY_ENABLED=$enable_web_discovery_native", ] } diff --git a/android/java/org/chromium/base/BraveFeatureList.java b/android/java/org/chromium/base/BraveFeatureList.java index f850435e94d8..9992d39deb54 100644 --- a/android/java/org/chromium/base/BraveFeatureList.java +++ b/android/java/org/chromium/base/BraveFeatureList.java @@ -33,4 +33,5 @@ public abstract class BraveFeatureList { "BraveShowStrictFingerprintingMode"; public static final String BRAVE_DAY_ZERO_EXPERIMENT = "BraveDayZeroExperiment"; public static final String BRAVE_FALLBACK_DOH_PROVIDER = "BraveFallbackDoHProvider"; + public static final String BRAVE_WEB_DISCOVERY_NATIVE = "BraveWebDiscoveryNative"; } diff --git a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java index f2a0d6a8e0bc..c5a9b20926f3 100644 --- a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java +++ b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java @@ -86,6 +86,7 @@ public class BravePrivacySettings extends PrivacySettings implements ConnectionE public static final String PREF_FINGERPRINTING_PROTECTION2 = "fingerprinting_protection2"; private static final String PREF_CLOSE_TABS_ON_EXIT = "close_tabs_on_exit"; private static final String PREF_SEND_P3A = "send_p3a_analytics"; + private static final String PREF_SEND_WEB_DISCOVERY = "send_web_discovery"; private static final String PREF_SEND_CRASH_REPORTS = "send_crash_reports"; private static final String PREF_BRAVE_STATS_USAGE_PING = "brave_stats_usage_ping"; private static final String PREF_SEARCH_SUGGESTIONS = "search_suggestions"; @@ -156,6 +157,7 @@ public class BravePrivacySettings extends PrivacySettings implements ConnectionE PREF_PHONE_AS_A_SECURITY_KEY, PREF_CLOSE_TABS_ON_EXIT, PREF_SEND_P3A, + PREF_SEND_WEB_DISCOVERY, PREF_SEND_CRASH_REPORTS, PREF_BRAVE_STATS_USAGE_PING, PREF_SHOW_AUTOCOMPLETE_IN_ADDRESS_BAR, @@ -191,6 +193,7 @@ public class BravePrivacySettings extends PrivacySettings implements ConnectionE private ChromeSwitchPreference mForgetFirstPartyStoragePref; private ChromeSwitchPreference mCloseTabsOnExitPref; private ChromeSwitchPreference mSendP3A; + private ChromeSwitchPreference mSendWebDiscovery; private ChromeSwitchPreference mSendCrashReports; private ChromeSwitchPreference mBraveStatsUsagePing; private ChromeSwitchPreference mIpfsGatewayPref; @@ -328,6 +331,14 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { mSendP3A = (ChromeSwitchPreference) findPreference(PREF_SEND_P3A); mSendP3A.setOnPreferenceChangeListener(this); + if (BraveConfig.WEB_DISCOVERY_ENABLED + && ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_WEB_DISCOVERY_NATIVE)) { + mSendWebDiscovery = (ChromeSwitchPreference) findPreference(PREF_SEND_WEB_DISCOVERY); + mSendWebDiscovery.setOnPreferenceChangeListener(this); + } else { + removePreferenceIfPresent(PREF_SEND_WEB_DISCOVERY); + } + mSendCrashReports = (ChromeSwitchPreference) findPreference(PREF_SEND_CRASH_REPORTS); mSendCrashReports.setOnPreferenceChangeListener(this); mBraveStatsUsagePing = (ChromeSwitchPreference) findPreference(PREF_BRAVE_STATS_USAGE_PING); @@ -556,6 +567,9 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { } else if (PREF_SEND_P3A.equals(key)) { BraveLocalState.get().setBoolean(BravePref.P3A_ENABLED, (boolean) newValue); BraveLocalState.commitPendingWrite(); + } else if (PREF_SEND_WEB_DISCOVERY.equals(key)) { + UserPrefs.get(ProfileManager.getLastUsedRegularProfile()) + .setBoolean(BravePref.WEB_DISCOVERY_ENABLED, (boolean) newValue); } else if (PREF_SEND_CRASH_REPORTS.equals(key)) { UmaSessionStats.changeMetricsReportingConsent( (boolean) newValue, ChangeMetricsReportingStateCalledFrom.UI_SETTINGS); @@ -730,6 +744,16 @@ private void updateBravePreferences() { getPreferenceScreen().removePreference(mSendP3A); } + if (mSendWebDiscovery != null) { + mSendWebDiscovery.setTitle( + getActivity().getResources().getString(R.string.send_web_discovery_title)); + mSendWebDiscovery.setSummary( + getActivity().getResources().getString(R.string.send_web_discovery_summary)); + mSendWebDiscovery.setChecked( + UserPrefs.get(ProfileManager.getLastUsedRegularProfile()) + .getBoolean(BravePref.WEB_DISCOVERY_ENABLED)); + } + mSendCrashReports.setChecked(mPrivacyPrefManager.isUsageAndCrashReportingPermittedByUser()); mBraveStatsUsagePing.setChecked( diff --git a/android/java/res/xml/brave_privacy_preferences.xml b/android/java/res/xml/brave_privacy_preferences.xml index ef69a07e7ed5..86e95afd69d4 100644 --- a/android/java/res/xml/brave_privacy_preferences.xml +++ b/android/java/res/xml/brave_privacy_preferences.xml @@ -191,6 +191,12 @@ android:title="@string/send_p3a_analytics_title" android:summary="@string/send_p3a_analytics_summary" android:defaultValue="false" /> + RegisterBooleanPref(kWebDiscoveryEnabled, false); +#endif +#if BUILDFLAG(ENABLE_EXTENSIONS) registry->RegisterDictionaryPref(kWebDiscoveryCTAState); #endif @@ -510,7 +515,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { registry->SetDefaultPrefValue(prefs::kSearchSuggestEnabled, base::Value(false)); +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) web_discovery::WDPService::RegisterProfilePrefs(registry); +#endif } } // namespace brave diff --git a/browser/brave_stats/brave_stats_updater_browsertest.cc b/browser/brave_stats/brave_stats_updater_browsertest.cc index 477465328909..39fc2b354649 100644 --- a/browser/brave_stats/brave_stats_updater_browsertest.cc +++ b/browser/brave_stats/brave_stats_updater_browsertest.cc @@ -32,7 +32,6 @@ #if BUILDFLAG(IS_ANDROID) #include "chrome/test/base/android/android_browser_test.h" #else -#include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #endif diff --git a/browser/brave_tab_helpers.cc b/browser/brave_tab_helpers.cc index 9f98a772eb14..f759d5046ec1 100644 --- a/browser/brave_tab_helpers.cc +++ b/browser/brave_tab_helpers.cc @@ -24,7 +24,6 @@ #include "brave/browser/profiles/profile_util.h" #include "brave/browser/skus/skus_service_factory.h" #include "brave/browser/ui/bookmark/brave_bookmark_tab_helper.h" -#include "brave/browser/web_discovery/wdp_service_factory.h" #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/brave_perf_predictor/browser/perf_predictor_tab_helper.h" #include "brave/components/brave_wayback_machine/buildflags/buildflags.h" @@ -35,7 +34,7 @@ #include "brave/components/request_otr/common/buildflags/buildflags.h" #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" -#include "brave/components/web_discovery/browser/web_discovery_tab_helper.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/common/channel_info.h" @@ -68,6 +67,12 @@ #include "brave/components/ai_chat/core/browser/utils.h" #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/browser/web_discovery/wdp_service_factory.h" +#include "brave/components/web_discovery/browser/web_discovery_tab_helper.h" +#include "brave/components/web_discovery/common/features.h" +#endif + #if BUILDFLAG(ENABLE_WIDEVINE) #include "brave/browser/brave_drm_tab_helper.h" #endif @@ -221,12 +226,17 @@ void AttachTabHelpers(content::WebContents* web_contents) { } #endif // BUILDFLAG(ENABLE_PLAYLIST) - auto* wdp_service = web_discovery::WDPServiceFactory::GetForBrowserContext( - web_contents->GetBrowserContext()); - if (wdp_service) { - web_discovery::WebDiscoveryTabHelper::CreateForWebContents(web_contents, - wdp_service); +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + if (base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)) { + auto* wdp_service = web_discovery::WDPServiceFactory::GetForBrowserContext( + web_contents->GetBrowserContext()); + if (wdp_service) { + web_discovery::WebDiscoveryTabHelper::CreateForWebContents(web_contents, + wdp_service); + } } +#endif } } // namespace brave diff --git a/browser/browser_context_keyed_service_factories.cc b/browser/browser_context_keyed_service_factories.cc index 8a4614bf9a45..48061a474399 100644 --- a/browser/browser_context_keyed_service_factories.cc +++ b/browser/browser_context_keyed_service_factories.cc @@ -30,7 +30,6 @@ #include "brave/browser/search_engines/search_engine_tracker.h" #include "brave/browser/sync/brave_sync_alerts_service_factory.h" #include "brave/browser/url_sanitizer/url_sanitizer_service_factory.h" -#include "brave/browser/web_discovery/wdp_service_factory.h" #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/brave_perf_predictor/browser/named_third_party_registry_factory.h" #include "brave/components/brave_vpn/common/buildflags/buildflags.h" @@ -42,6 +41,7 @@ #include "brave/components/request_otr/common/buildflags/buildflags.h" #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_BRAVE_VPN) #include "brave/browser/brave_vpn/brave_vpn_service_factory.h" @@ -111,6 +111,10 @@ #include "brave/components/ai_chat/content/browser/model_service_factory.h" #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/browser/web_discovery/wdp_service_factory.h" +#endif + namespace brave { void EnsureBrowserContextKeyedServiceFactoriesBuilt() { @@ -218,7 +222,9 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { ai_chat::ModelServiceFactory::GetInstance(); #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) web_discovery::WDPServiceFactory::GetInstance(); +#endif } } // namespace brave diff --git a/browser/sources.gni b/browser/sources.gni index 7b4421ab895e..29f317d87e78 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -55,6 +55,7 @@ import("//brave/components/brave_wayback_machine/buildflags/buildflags.gni") import("//brave/components/brave_webtorrent/browser/buildflags/buildflags.gni") import("//brave/components/commander/common/buildflags/buildflags.gni") import("//brave/components/tor/buildflags/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") brave_chrome_browser_visibility = [ @@ -135,7 +136,6 @@ brave_chrome_browser_deps = [ "//brave/browser/sync", "//brave/browser/themes", "//brave/browser/ui", - "//brave/browser/web_discovery", "//brave/common", "//brave/components/ai_chat/core/common/buildflags", "//brave/components/ai_rewriter/common/buildflags", @@ -206,6 +206,8 @@ brave_chrome_browser_deps = [ "//brave/components/tor/buildflags", "//brave/components/version_info", "//brave/components/web_discovery/browser", + "//brave/components/web_discovery/common", + "//brave/components/web_discovery/common/buildflags", "//brave/components/webcompat:core", "//brave/services/network/public/cpp", "//brave/third_party/blink/renderer", @@ -326,6 +328,13 @@ if (enable_ai_rewriter) { brave_chrome_browser_deps += [ "//brave/components/ai_rewriter/common" ] } +if (enable_web_discovery_native) { + brave_chrome_browser_deps += [ + "//brave/browser/web_discovery", + "//brave/components/web_discovery/browser", + ] +} + if (enable_brave_vpn) { brave_chrome_browser_deps += [ "//brave/components/brave_vpn/browser", diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index fb34224fdd9d..a1cc87f068ef 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -746,6 +746,12 @@ This file contains all "about" strings. It is set to NOT be translated, in tran Anonymized P3A info helps Brave estimate overall usage, and ensure we’re improving popular features. + + Web Discovery Project + + + Contribute some anonymous search & browsing data to refine Brave Search. + Automatically send diagnostic reports diff --git a/browser/web_discovery/BUILD.gn b/browser/web_discovery/BUILD.gn index 3687366894a5..5d9aaf0de907 100644 --- a/browser/web_discovery/BUILD.gn +++ b/browser/web_discovery/BUILD.gn @@ -3,22 +3,27 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") -source_set("web_discovery") { - sources = [ - "wdp_service_factory.cc", - "wdp_service_factory.h", - ] - deps = [ - "//base", - "//brave/components/web_discovery/browser", - "//chrome/browser:browser_process", - "//chrome/common:constants", - "//components/keyed_service/content", - "//components/user_prefs", - "//content/public/browser", - ] +if (enable_web_discovery_native) { + source_set("web_discovery") { + sources = [ + "wdp_service_factory.cc", + "wdp_service_factory.h", + ] + deps = [ + "//base", + "//brave/components/web_discovery/browser", + "//brave/components/web_discovery/common", + "//chrome/browser:browser_process", + "//chrome/common:constants", + "//components/keyed_service/content", + "//components/user_prefs", + "//content/public/browser", + "//third_party/re2", + ] + } } source_set("unit_tests") { diff --git a/browser/web_discovery/wdp_service_factory.cc b/browser/web_discovery/wdp_service_factory.cc index 567bd184e745..e0b7fb36a3e5 100644 --- a/browser/web_discovery/wdp_service_factory.cc +++ b/browser/web_discovery/wdp_service_factory.cc @@ -7,6 +7,7 @@ #include "base/path_service.h" #include "brave/components/web_discovery/browser/wdp_service.h" +#include "brave/components/web_discovery/common/features.h" #include "chrome/browser/browser_process.h" #include "chrome/common/chrome_paths.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -48,6 +49,9 @@ KeyedService* WDPServiceFactory::BuildServiceInstanceFor( content::BrowserContext* WDPServiceFactory::GetBrowserContextToUse( content::BrowserContext* context) const { + if (!base::FeatureList::IsEnabled(features::kWebDiscoveryNative)) { + return nullptr; + } // Prevents creation of service instance for incognito/OTR profiles return context->IsOffTheRecord() ? nullptr : context; } diff --git a/build/android/java/templates/BraveConfig.template b/build/android/java/templates/BraveConfig.template index fdbfe6008bfe..e29815a59180 100644 --- a/build/android/java/templates/BraveConfig.template +++ b/build/android/java/templates/BraveConfig.template @@ -14,4 +14,5 @@ public class BraveConfig { public static final boolean IPFS_ENABLED = BRAVE_ANDROID_ENABLE_IPFS; public static final boolean AI_CHAT_ENABLED = BRAVE_ANDROID_AI_CHAT_ENABLED; public static final String WEBCOMPAT_REPORT_ENDPOINT = BRAVE_ANDROID_WEBCOMPAT_REPORT_ENDPOINT; + public static final boolean WEB_DISCOVERY_ENABLED = BRAVE_ANDROID_WEB_DISCOVERY_ENABLED; } diff --git a/chromium_src/chrome/browser/DEPS b/chromium_src/chrome/browser/DEPS index 60fc416c8e7f..a8285992aa86 100644 --- a/chromium_src/chrome/browser/DEPS +++ b/chromium_src/chrome/browser/DEPS @@ -48,6 +48,7 @@ include_rules = [ "+brave/components/url_sanitizer", "+brave/components/vector_icons", "+brave/components/version_info", + "+brave/components/web_discovery/common", "+brave/components/webcompat", "+brave/net", "+brave/services/network/public", diff --git a/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc b/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc index 44bc0f023b42..f31b1a84e4eb 100644 --- a/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chromium_src/chrome/browser/flags/android/chrome_feature_list.cc @@ -18,6 +18,7 @@ #include "brave/components/playlist/common/features.h" #include "brave/components/request_otr/common/features.h" #include "brave/components/speedreader/common/features.h" +#include "brave/components/web_discovery/common/features.h" #include "brave/components/webcompat/features.h" #include "net/base/features.h" #include "third_party/blink/public/common/features.h" @@ -48,7 +49,8 @@ &google_sign_in_permission::features::kBraveGoogleSignInPermission, \ &net::features::kBraveForgetFirstPartyStorage, \ &brave_shields::features::kBraveShowStrictFingerprintingMode, \ - &brave_shields::features::kBraveLocalhostAccessPermission + &brave_shields::features::kBraveLocalhostAccessPermission, \ + &web_discovery::features::kWebDiscoveryNative // clang-format on diff --git a/chromium_src/chrome/renderer/DEPS b/chromium_src/chrome/renderer/DEPS index 4a76c2faf903..2eace837fd59 100644 --- a/chromium_src/chrome/renderer/DEPS +++ b/chromium_src/chrome/renderer/DEPS @@ -8,6 +8,7 @@ include_rules = [ "+brave/components/content_settings/renderer", "+brave/components/tor/buildflags", "+brave/components/tor/renderer", + "+brave/components/web_discovery/common", "+brave/components/web_discovery/renderer", "+brave/renderer", "+media/base/key_system_info.h", diff --git a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc index 32bc898dadc9..0c3d8e8717af 100644 --- a/chromium_src/chrome/renderer/chrome_content_renderer_client.cc +++ b/chromium_src/chrome/renderer/chrome_content_renderer_client.cc @@ -3,10 +3,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "base/feature_list.h" #include "brave/components/ai_chat/core/common/buildflags/buildflags.h" #include "brave/components/ai_rewriter/common/buildflags/buildflags.h" #include "brave/components/content_settings/renderer/brave_content_settings_agent_impl.h" -#include "brave/components/web_discovery/renderer/blink_document_extractor.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "chrome/common/chrome_isolated_world_ids.h" #include "chrome/renderer/chrome_render_thread_observer.h" #include "components/dom_distiller/content/renderer/distillability_agent.h" @@ -23,6 +24,11 @@ #include "brave/components/ai_rewriter/renderer/ai_rewriter_agent.h" #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/components/web_discovery/common/features.h" +#include "brave/components/web_discovery/renderer/blink_document_extractor.h" +#endif + namespace { void RenderFrameWithBinderRegistryCreated( @@ -44,7 +50,12 @@ void RenderFrameWithBinderRegistryCreated( } #endif - new web_discovery::BlinkDocumentExtractor(render_frame, registry); +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + if (base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)) { + new web_discovery::BlinkDocumentExtractor(render_frame, registry); + } +#endif } } // namespace diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 346e4bab36dc..274a51716f18 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -3,6 +3,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at https://mozilla.org/MPL/2.0/. +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") + +assert(enable_web_discovery_native) + static_library("browser") { sources = [ "content_scraper.cc", @@ -96,8 +100,15 @@ source_set("browser_tests") { "//base/test:test_support", "//brave/components/constants", "//brave/components/web_discovery/common:mojom", - "//chrome/test:test_support_ui", + "//content/test:test_support", + "//net:test_support", + "//services/service_manager/public/cpp", "//testing/gtest", ] + if (!is_android) { + deps += [ "//chrome/test:test_support_ui" ] + } else { + deps += [ "//chrome/test:test_support_ui_android" ] + } defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] } diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc index a7493daf3e75..e1d2586e4eca 100644 --- a/components/web_discovery/browser/content_scraper_browsertest.cc +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -16,7 +16,6 @@ #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" -#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" @@ -24,9 +23,15 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/re2/src/re2/re2.h" +#if BUILDFLAG(IS_ANDROID) +#include "chrome/test/base/android/android_browser_test.h" +#else +#include "chrome/test/base/in_process_browser_test.h" +#endif + namespace web_discovery { -class WebDiscoveryContentScraperTest : public InProcessBrowserTest { +class WebDiscoveryContentScraperTest : public PlatformBrowserTest { public: void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); diff --git a/components/web_discovery/common/BUILD.gn b/components/web_discovery/common/BUILD.gn index b937e4a19138..69a2e888bad0 100644 --- a/components/web_discovery/common/BUILD.gn +++ b/components/web_discovery/common/BUILD.gn @@ -3,9 +3,24 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at https://mozilla.org/MPL/2.0/. +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//mojo/public/tools/bindings/mojom.gni") -mojom("mojom") { - sources = [ "web_discovery.mojom" ] - deps = [ "//mojo/public/mojom/base" ] +if (enable_web_discovery_native) { + mojom("mojom") { + sources = [ "web_discovery.mojom" ] + deps = [ "//mojo/public/mojom/base" ] + } +} + +static_library("common") { + sources = [ + "features.cc", + "features.h", + ] + + deps = [ + "//base", + "//brave/components/web_discovery/common/buildflags", + ] } diff --git a/components/web_discovery/common/buildflags/BUILD.gn b/components/web_discovery/common/buildflags/BUILD.gn new file mode 100644 index 000000000000..5d0fc823c167 --- /dev/null +++ b/components/web_discovery/common/buildflags/BUILD.gn @@ -0,0 +1,12 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") +import("//build/buildflag_header.gni") + +buildflag_header("buildflags") { + header = "buildflags.h" + flags = [ "ENABLE_WEB_DISCOVERY_NATIVE=$enable_web_discovery_native" ] +} diff --git a/components/web_discovery/common/buildflags/buildflags.gni b/components/web_discovery/common/buildflags/buildflags.gni new file mode 100644 index 000000000000..4b6d5e413031 --- /dev/null +++ b/components/web_discovery/common/buildflags/buildflags.gni @@ -0,0 +1,8 @@ +# Copyright (c) 2024 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +declare_args() { + enable_web_discovery_native = is_win || is_mac || is_linux || is_android +} diff --git a/components/web_discovery/common/features.cc b/components/web_discovery/common/features.cc new file mode 100644 index 000000000000..6eec658cfc8b --- /dev/null +++ b/components/web_discovery/common/features.cc @@ -0,0 +1,14 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/web_discovery/common/features.h" + +namespace web_discovery::features { + +BASE_FEATURE(kWebDiscoveryNative, + "BraveWebDiscoveryNative", + base::FEATURE_DISABLED_BY_DEFAULT); + +} // namespace web_discovery::features diff --git a/components/web_discovery/common/features.h b/components/web_discovery/common/features.h new file mode 100644 index 000000000000..2083a40ec39c --- /dev/null +++ b/components/web_discovery/common/features.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_COMPONENTS_WEB_DISCOVERY_COMMON_FEATURES_H_ +#define BRAVE_COMPONENTS_WEB_DISCOVERY_COMMON_FEATURES_H_ + +#include "base/feature_list.h" + +namespace web_discovery::features { + +BASE_DECLARE_FEATURE(kWebDiscoveryNative); + +} // namespace web_discovery::features + +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_COMMON_FEATURES_H_ diff --git a/components/web_discovery/renderer/BUILD.gn b/components/web_discovery/renderer/BUILD.gn index aa993a8db043..b6988bb12d97 100644 --- a/components/web_discovery/renderer/BUILD.gn +++ b/components/web_discovery/renderer/BUILD.gn @@ -3,6 +3,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at https://mozilla.org/MPL/2.0/. +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") + +assert(enable_web_discovery_native) + source_set("renderer") { sources = [ "blink_document_extractor.cc", diff --git a/renderer/sources.gni b/renderer/sources.gni index b555dd352afe..7b2f6bb62f51 100644 --- a/renderer/sources.gni +++ b/renderer/sources.gni @@ -9,6 +9,7 @@ import("//brave/components/brave_vpn/common/buildflags/buildflags.gni") import("//brave/components/playlist/common/buildflags/buildflags.gni") import("//brave/components/speedreader/common/buildflags/buildflags.gni") import("//brave/components/tor/buildflags/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//third_party/widevine/cdm/widevine.gni") brave_chrome_renderer_sources = [ @@ -36,7 +37,6 @@ brave_chrome_renderer_deps = [ "//brave/components/skus/renderer", "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", - "//brave/components/web_discovery/renderer", "//brave/renderer/brave_wallet", "//mojo/public/cpp/bindings", "//third_party/blink/public:blink", @@ -61,6 +61,13 @@ if (enable_ai_chat) { ] } +if (enable_web_discovery_native) { + brave_chrome_renderer_deps += [ + "//brave/components/web_discovery/common", + "//brave/components/web_discovery/renderer", + ] +} + if (enable_playlist) { brave_chrome_renderer_deps += [ "//brave/components/playlist/renderer" ] } diff --git a/test/BUILD.gn b/test/BUILD.gn index be475d6132e2..f095441d66f5 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -18,6 +18,7 @@ import("//brave/components/playlist/common/buildflags/buildflags.gni") import("//brave/components/request_otr/common/buildflags/buildflags.gni") import("//brave/components/speedreader/common/buildflags/buildflags.gni") import("//brave/components/tor/buildflags/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//brave/test/testing.gni") import("//brave/updater/config.gni") import("//chrome/common/features.gni") @@ -266,7 +267,6 @@ test("brave_unit_tests") { "//brave/components/tor/buildflags", "//brave/components/url_sanitizer/browser:unittests", "//brave/components/version_info:unit_tests", - "//brave/components/web_discovery/browser:unit_tests", "//brave/extensions:common", "//brave/mojo/brave_ast_patcher:unit_tests", "//brave/net:unit_tests", @@ -373,6 +373,10 @@ test("brave_unit_tests") { ] } + if (enable_web_discovery_native) { + deps += [ "//brave/components/web_discovery/browser:unit_tests" ] + } + data = [ "data/" ] if (enable_custom_background) { @@ -1044,6 +1048,10 @@ test("brave_browser_tests") { ] } + if (enable_web_discovery_native) { + deps += [ "//brave/components/web_discovery/browser:browser_tests" ] + } + if (ethereum_remote_client_enabled) { sources += [ "//brave/browser/extensions/brave_wallet_apitest.cc" ] From 4dba090af0093c2c4227ea17ac61a3c70b184df4 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 26 Jun 2024 16:29:57 -0700 Subject: [PATCH 27/36] Add separate pref for Web Discovery native --- .../settings/BravePrivacySettings.java | 4 +- browser/android/preferences/BUILD.gn | 1 + browser/brave_profile_prefs.cc | 4 +- .../api/settings_private/brave_prefs_util.cc | 12 +++++- browser/profiles/brave_profile_manager.cc | 9 ++++ browser/resources/settings/BUILD.gn | 2 + .../brave_search_engines_page.html | 27 ++++++++---- .../brave_search_engines_page.ts | 4 ++ .../search_engines/search_engine_tracker.cc | 41 +++++++++++++++---- .../search_engines/search_engine_tracker.h | 5 ++- .../search_engine_tracker_browsertest.cc | 4 +- browser/ui/webui/brave_settings_ui.cc | 5 +++ .../webui/welcome_page/welcome_dom_handler.cc | 2 +- .../web_discovery/web_discovery_cta_util.cc | 3 +- .../web_discovery_infobar_delegate.cc | 2 +- .../web_discovery/web_discovery_unittest.cc | 6 +-- components/constants/pref_names.h | 3 +- components/web_discovery/browser/BUILD.gn | 1 + components/web_discovery/browser/DEPS | 1 + components/web_discovery/browser/pref_names.h | 2 + .../web_discovery/browser/wdp_service.cc | 28 +++++++++++-- .../web_discovery/browser/wdp_service.h | 2 + 22 files changed, 131 insertions(+), 37 deletions(-) diff --git a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java index c5a9b20926f3..148448c0aa59 100644 --- a/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java +++ b/android/java/org/chromium/chrome/browser/privacy/settings/BravePrivacySettings.java @@ -569,7 +569,7 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { BraveLocalState.commitPendingWrite(); } else if (PREF_SEND_WEB_DISCOVERY.equals(key)) { UserPrefs.get(ProfileManager.getLastUsedRegularProfile()) - .setBoolean(BravePref.WEB_DISCOVERY_ENABLED, (boolean) newValue); + .setBoolean(BravePref.WEB_DISCOVERY_NATIVE_ENABLED, (boolean) newValue); } else if (PREF_SEND_CRASH_REPORTS.equals(key)) { UmaSessionStats.changeMetricsReportingConsent( (boolean) newValue, ChangeMetricsReportingStateCalledFrom.UI_SETTINGS); @@ -751,7 +751,7 @@ private void updateBravePreferences() { getActivity().getResources().getString(R.string.send_web_discovery_summary)); mSendWebDiscovery.setChecked( UserPrefs.get(ProfileManager.getLastUsedRegularProfile()) - .getBoolean(BravePref.WEB_DISCOVERY_ENABLED)); + .getBoolean(BravePref.WEB_DISCOVERY_NATIVE_ENABLED)); } mSendCrashReports.setChecked(mPrivacyPrefManager.isUsageAndCrashReportingPermittedByUser()); diff --git a/browser/android/preferences/BUILD.gn b/browser/android/preferences/BUILD.gn index 17a3651be378..03fd7df099d0 100644 --- a/browser/android/preferences/BUILD.gn +++ b/browser/android/preferences/BUILD.gn @@ -52,6 +52,7 @@ java_cpp_strings("java_pref_names_srcjar") { "//brave/components/p3a/pref_names.h", "//brave/components/request_otr/common/pref_names.h", "//brave/components/speedreader/speedreader_pref_names.h", + "//brave/components/web_discovery/browser/pref_names.h", "//components/translate/core/browser/translate_pref_names.h", ] diff --git a/browser/brave_profile_prefs.cc b/browser/brave_profile_prefs.cc index ebac2c2070f4..6b9a8839f5c2 100644 --- a/browser/brave_profile_prefs.cc +++ b/browser/brave_profile_prefs.cc @@ -440,10 +440,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { prefs::kBraveDefaultSearchVersion, TemplateURLPrepopulateData::kBraveCurrentDataVersion); -#if BUILDFLAG(ENABLE_EXTENSIONS) || BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) - registry->RegisterBooleanPref(kWebDiscoveryEnabled, false); -#endif #if BUILDFLAG(ENABLE_EXTENSIONS) + registry->RegisterBooleanPref(kWebDiscoveryExtensionEnabled, false); registry->RegisterDictionaryPref(kWebDiscoveryCTAState); #endif diff --git a/browser/extensions/api/settings_private/brave_prefs_util.cc b/browser/extensions/api/settings_private/brave_prefs_util.cc index cd53aa553475..f1931f8344e0 100644 --- a/browser/extensions/api/settings_private/brave_prefs_util.cc +++ b/browser/extensions/api/settings_private/brave_prefs_util.cc @@ -28,6 +28,7 @@ #include "brave/components/request_otr/common/pref_names.h" #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/extensions/api/settings_private/prefs_util.h" @@ -80,6 +81,10 @@ #include "brave/components/playlist/browser/pref_names.h" #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/components/web_discovery/browser/pref_names.h" +#endif + namespace extensions { using ntp_background_images::prefs::kNewTabPageShowBackgroundImage; @@ -204,7 +209,12 @@ const PrefsUtil::TypedPrefMap& BravePrefsUtil::GetAllowlistedKeys() { settings_api::PrefType::kNumber; #if BUILDFLAG(ENABLE_EXTENSIONS) // Web discovery prefs - (*s_brave_allowlist)[kWebDiscoveryEnabled] = settings_api::PrefType::kBoolean; + (*s_brave_allowlist)[kWebDiscoveryExtensionEnabled] = + settings_api::PrefType::kBoolean; +#endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + (*s_brave_allowlist)[web_discovery::kWebDiscoveryNativeEnabled] = + settings_api::PrefType::kBoolean; #endif // Clear browsing data on exit prefs. (*s_brave_allowlist)[browsing_data::prefs::kDeleteBrowsingHistoryOnExit] = diff --git a/browser/profiles/brave_profile_manager.cc b/browser/profiles/brave_profile_manager.cc index 89a437216f96..54fbdb5ae11a 100644 --- a/browser/profiles/brave_profile_manager.cc +++ b/browser/profiles/brave_profile_manager.cc @@ -26,6 +26,7 @@ #include "brave/components/ipfs/buildflags/buildflags.h" #include "brave/components/request_otr/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" @@ -58,6 +59,10 @@ #include "brave/components/tor/tor_constants.h" #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/components/web_discovery/browser/wdp_service.h" +#endif + using content::BrowserThread; BraveProfileManager::BraveProfileManager(const base::FilePath& user_data_dir) @@ -100,6 +105,10 @@ void BraveProfileManager::InitProfileUserPrefs(Profile* profile) { #if BUILDFLAG(ENABLE_IPFS) ipfs::IpfsService::MigrateProfilePrefs(profile->GetPrefs()); #endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + web_discovery::WDPService::SetExtensionPrefIfNativeDisabled( + profile->GetPrefs()); +#endif } void BraveProfileManager::DoFinalInitForServices(Profile* profile, diff --git a/browser/resources/settings/BUILD.gn b/browser/resources/settings/BUILD.gn index 67bbc5e76d88..2905c82c9241 100644 --- a/browser/resources/settings/BUILD.gn +++ b/browser/resources/settings/BUILD.gn @@ -8,6 +8,7 @@ import("//brave/build/config.gni") import("//brave/components/brave_vpn/common/buildflags/buildflags.gni") import("//brave/components/brave_wayback_machine/buildflags/buildflags.gni") import("//brave/components/tor/buildflags/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//brave/resources/brave_grit.gni") import("//chrome/common/features.gni") import("//extensions/buildflags/buildflags.gni") @@ -75,6 +76,7 @@ preprocess_if_expr("preprocess") { "enable_brave_vpn_wireguard=$enable_brave_vpn_wireguard", "enable_extensions=$enable_extensions", "enable_pin_shortcut=$enable_pin_shortcut", + "enable_web_discovery_native=$enable_web_discovery_native", ] out_folder = "$root_gen_dir/chrome/browser/resources/settings/$preprocess_folder" diff --git a/browser/resources/settings/brave_search_engines_page/brave_search_engines_page.html b/browser/resources/settings/brave_search_engines_page/brave_search_engines_page.html index 69dc389036e9..735879d62fe2 100644 --- a/browser/resources/settings/brave_search_engines_page/brave_search_engines_page.html +++ b/browser/resources/settings/brave_search_engines_page/brave_search_engines_page.html @@ -18,13 +18,26 @@ - - + + + + GetBoolean(kWebDiscoveryEnabled)); - UMA_HISTOGRAM_BOOLEAN(kWebDiscoveryAndAdsMetric, - profile_prefs_->GetBoolean(kWebDiscoveryEnabled) && - profile_prefs_->GetBoolean( - brave_ads::prefs::kOptedInToNotificationAds)); + bool enabled = false; +#if BUILDFLAG(ENABLE_EXTENSIONS) + enabled = profile_prefs_->GetBoolean(kWebDiscoveryExtensionEnabled); +#endif +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + if (base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)) { + enabled = + profile_prefs_->GetBoolean(web_discovery::kWebDiscoveryNativeEnabled); + } +#endif + UMA_HISTOGRAM_BOOLEAN(kWebDiscoveryEnabledMetric, enabled); + UMA_HISTOGRAM_BOOLEAN( + kWebDiscoveryAndAdsMetric, + enabled && profile_prefs_->GetBoolean( + brave_ads::prefs::kOptedInToNotificationAds)); } #endif diff --git a/browser/search_engines/search_engine_tracker.h b/browser/search_engines/search_engine_tracker.h index c7c61d700889..a3eb2e2c4f93 100644 --- a/browser/search_engines/search_engine_tracker.h +++ b/browser/search_engines/search_engine_tracker.h @@ -9,6 +9,7 @@ #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "brave/components/time_period_storage/weekly_event_storage.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -110,7 +111,7 @@ class SearchEngineTracker : public KeyedService, // TemplateURLServiceObserver overrides: void OnTemplateURLServiceChanged() override; -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) || BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) void RecordWebDiscoveryEnabledP3A(); #endif @@ -130,7 +131,7 @@ class SearchEngineTracker : public KeyedService, raw_ptr template_url_service_ = nullptr; -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) || BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) PrefChangeRegistrar pref_change_registrar_; #endif }; diff --git a/browser/search_engines/search_engine_tracker_browsertest.cc b/browser/search_engines/search_engine_tracker_browsertest.cc index 7cb32e0000cd..b651468e8d42 100644 --- a/browser/search_engines/search_engine_tracker_browsertest.cc +++ b/browser/search_engines/search_engine_tracker_browsertest.cc @@ -163,7 +163,7 @@ IN_PROC_BROWSER_TEST_F(SearchEngineProviderP3ATest, WebDiscoveryEnabledP3A) { histogram_tester_->ExpectBucketCount(kWebDiscoveryEnabledMetric, 0, 1); PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(kWebDiscoveryEnabled, true); + prefs->SetBoolean(kWebDiscoveryExtensionEnabled, true); histogram_tester_->ExpectBucketCount(kWebDiscoveryEnabledMetric, 1, 1); @@ -171,7 +171,7 @@ IN_PROC_BROWSER_TEST_F(SearchEngineProviderP3ATest, WebDiscoveryEnabledP3A) { prefs->SetBoolean(brave_ads::prefs::kOptedInToNotificationAds, true); histogram_tester_->ExpectBucketCount(kWebDiscoveryAndAdsMetric, 1, 1); - prefs->SetBoolean(kWebDiscoveryEnabled, false); + prefs->SetBoolean(kWebDiscoveryExtensionEnabled, false); histogram_tester_->ExpectBucketCount(kWebDiscoveryEnabledMetric, 0, 2); histogram_tester_->ExpectBucketCount(kWebDiscoveryAndAdsMetric, 0, 3); diff --git a/browser/ui/webui/brave_settings_ui.cc b/browser/ui/webui/brave_settings_ui.cc index b91727e792f9..743148b7d889 100644 --- a/browser/ui/webui/brave_settings_ui.cc +++ b/browser/ui/webui/brave_settings_ui.cc @@ -38,6 +38,8 @@ #include "brave/components/speedreader/common/buildflags/buildflags.h" #include "brave/components/tor/buildflags/buildflags.h" #include "brave/components/version_info/version_info.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" +#include "brave/components/web_discovery/common/features.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/metrics_reporting_handler.h" @@ -187,6 +189,9 @@ void BraveSettingsUI::AddResources(content::WebUIDataSource* html_source, ShouldExposeElementsForTesting()); html_source->AddBoolean("enable_extensions", BUILDFLAG(ENABLE_EXTENSIONS)); + html_source->AddBoolean("isWebDiscoveryNativeEnabled", + base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)); html_source->AddBoolean("extensionsManifestV2Feature", base::FeatureList::IsEnabled(kExtensionsManifestV2)); diff --git a/browser/ui/webui/welcome_page/welcome_dom_handler.cc b/browser/ui/webui/welcome_page/welcome_dom_handler.cc index 11f13039ef92..0478aaaaab8a 100644 --- a/browser/ui/webui/welcome_page/welcome_dom_handler.cc +++ b/browser/ui/webui/welcome_page/welcome_dom_handler.cc @@ -170,7 +170,7 @@ void WelcomeDOMHandler::HandleSetMetricsReportingEnabled( void WelcomeDOMHandler::HandleEnableWebDiscovery( const base::Value::List& args) { DCHECK(profile_); - profile_->GetPrefs()->SetBoolean(kWebDiscoveryEnabled, true); + profile_->GetPrefs()->SetBoolean(kWebDiscoveryExtensionEnabled, true); } void WelcomeDOMHandler::SetLocalStateBooleanEnabled( diff --git a/browser/web_discovery/web_discovery_cta_util.cc b/browser/web_discovery/web_discovery_cta_util.cc index 9251daac6c70..04d0dbff1648 100644 --- a/browser/web_discovery/web_discovery_cta_util.cc +++ b/browser/web_discovery/web_discovery_cta_util.cc @@ -87,8 +87,9 @@ bool ShouldShowWebDiscoveryInfoBar(TemplateURLService* service, PrefService* prefs, const WebDiscoveryCTAState& state, base::Clock* test_clock) { - if (prefs->GetBoolean(kWebDiscoveryEnabled)) + if (prefs->GetBoolean(kWebDiscoveryExtensionEnabled)) { return false; + } if (!service || !IsBraveSearchDefault(service)) return false; diff --git a/browser/web_discovery/web_discovery_infobar_delegate.cc b/browser/web_discovery/web_discovery_infobar_delegate.cc index c9db24eaa35b..49a275b6a810 100644 --- a/browser/web_discovery/web_discovery_infobar_delegate.cc +++ b/browser/web_discovery/web_discovery_infobar_delegate.cc @@ -42,6 +42,6 @@ void WebDiscoveryInfoBarDelegate::Close(bool dismiss) { } void WebDiscoveryInfoBarDelegate::EnableWebDiscovery() { - prefs_->SetBoolean(kWebDiscoveryEnabled, true); + prefs_->SetBoolean(kWebDiscoveryExtensionEnabled, true); infobar()->RemoveSelf(); } diff --git a/browser/web_discovery/web_discovery_unittest.cc b/browser/web_discovery/web_discovery_unittest.cc index 8591bee29ff4..f04051a236e3 100644 --- a/browser/web_discovery/web_discovery_unittest.cc +++ b/browser/web_discovery/web_discovery_unittest.cc @@ -108,7 +108,7 @@ class WebDiscoveryCTATest : public testing::Test { }; TEST_F(WebDiscoveryCTATest, InitialDataTest) { - EXPECT_FALSE(prefs()->GetBoolean(kWebDiscoveryEnabled)); + EXPECT_FALSE(prefs()->GetBoolean(kWebDiscoveryExtensionEnabled)); const auto& info_value = prefs()->GetDict(kWebDiscoveryCTAState); EXPECT_TRUE(info_value.empty()); @@ -141,10 +141,10 @@ TEST_F(WebDiscoveryCTATest, ShouldShowInfoBarTest) { EXPECT_TRUE(ShouldShowWebDiscoveryInfoBar()); // Don't show if already enabled. - prefs()->SetBoolean(kWebDiscoveryEnabled, true); + prefs()->SetBoolean(kWebDiscoveryExtensionEnabled, true); EXPECT_FALSE(ShouldShowWebDiscoveryInfoBar()); - prefs()->SetBoolean(kWebDiscoveryEnabled, false); + prefs()->SetBoolean(kWebDiscoveryExtensionEnabled, false); EXPECT_TRUE(ShouldShowWebDiscoveryInfoBar()); WebDiscoveryCTAState state = GetCurrentCTAState(); diff --git a/components/constants/pref_names.h b/components/constants/pref_names.h index fde64ba8fb14..83c7842c44ee 100644 --- a/components/constants/pref_names.h +++ b/components/constants/pref_names.h @@ -85,7 +85,8 @@ inline constexpr char kBraveShieldsSettingsVersion[] = inline constexpr char kDefaultBrowserPromptEnabled[] = "brave.default_browser_prompt_enabled"; -inline constexpr char kWebDiscoveryEnabled[] = "brave.web_discovery_enabled"; +inline constexpr char kWebDiscoveryExtensionEnabled[] = + "brave.web_discovery_enabled"; inline constexpr char kWebDiscoveryCTAState[] = "brave.web_discovery.cta_state"; inline constexpr char kDontAskEnableWebDiscovery[] = "brave.dont_ask_enable_web_discovery"; diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 274a51716f18..c78c130f6ead 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -58,6 +58,7 @@ static_library("browser") { "//components/prefs", "//content/public/browser", "//crypto", + "//extensions/buildflags", "//net", "//services/network/public/cpp", "//third_party/boringssl", diff --git a/components/web_discovery/browser/DEPS b/components/web_discovery/browser/DEPS index b3b1eb332554..972312b69aa4 100644 --- a/components/web_discovery/browser/DEPS +++ b/components/web_discovery/browser/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+services/network/public", "+content/public/browser", + "+extensions/buildflags/buildflags.h", "+services/service_manager/public/cpp", "+third_party/boringssl/src/include", "+third_party/re2", diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index 3734d8ae88b0..ba9ac515e4a3 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -9,6 +9,8 @@ namespace web_discovery { // Profile prefs +inline constexpr char kWebDiscoveryNativeEnabled[] = + "brave.web_discovery.wdp_native_enabled"; inline constexpr char kCredentialRSAPrivateKey[] = "brave.web_discovery.rsa_priv_key"; inline constexpr char kCredentialRSAPublicKey[] = diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index 692d3ad5afdf..c2cea0ca4a25 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -7,6 +7,7 @@ #include +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/strings/stringprintf.h" #include "brave/components/constants/pref_names.h" @@ -15,11 +16,13 @@ #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/privacy_guard.h" #include "brave/components/web_discovery/browser/server_config_loader.h" +#include "brave/components/web_discovery/common/features.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" +#include "extensions/buildflags/buildflags.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -39,12 +42,19 @@ WDPService::WDPService( profile_prefs_(profile_prefs), user_data_dir_(user_data_dir), shared_url_loader_factory_(shared_url_loader_factory) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (profile_prefs_->GetBoolean(kWebDiscoveryExtensionEnabled)) { + profile_prefs_->ClearPref(kWebDiscoveryExtensionEnabled); + profile_prefs_->SetBoolean(kWebDiscoveryNativeEnabled, true); + } +#endif + pref_change_registrar_.Init(profile_prefs); - pref_change_registrar_.Add(kWebDiscoveryEnabled, + pref_change_registrar_.Add(kWebDiscoveryNativeEnabled, base::BindRepeating(&WDPService::OnEnabledChange, base::Unretained(this))); - if (profile_prefs_->GetBoolean(kWebDiscoveryEnabled)) { + if (profile_prefs_->GetBoolean(kWebDiscoveryNativeEnabled)) { Start(); } } @@ -56,6 +66,7 @@ void WDPService::RegisterLocalStatePrefs(PrefRegistrySimple* registry) { } void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterBooleanPref(kWebDiscoveryNativeEnabled, false); registry->RegisterDictionaryPref(kAnonymousCredentialsDict); registry->RegisterStringPref(kCredentialRSAPrivateKey, {}); registry->RegisterStringPref(kCredentialRSAPublicKey, {}); @@ -65,6 +76,15 @@ void WDPService::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kPageCounts); } +void WDPService::SetExtensionPrefIfNativeDisabled(PrefService* profile_prefs) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (!base::FeatureList::IsEnabled(features::kWebDiscoveryNative) && + profile_prefs->GetBoolean(kWebDiscoveryNativeEnabled)) { + profile_prefs->SetBoolean(kWebDiscoveryExtensionEnabled, true); + } +#endif +} + void WDPService::Start() { if (!server_config_loader_) { server_config_loader_ = std::make_unique( @@ -83,16 +103,16 @@ void WDPService::Start() { } void WDPService::Stop() { + alive_message_timer_.Stop(); reporter_ = nullptr; double_fetcher_ = nullptr; content_scraper_ = nullptr; server_config_loader_ = nullptr; credential_manager_ = nullptr; - alive_message_timer_.Stop(); } void WDPService::OnEnabledChange() { - if (profile_prefs_->GetBoolean(kWebDiscoveryEnabled)) { + if (profile_prefs_->GetBoolean(kWebDiscoveryNativeEnabled)) { Start(); } else { Stop(); diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index 33ffb8f596b7..f2ea1f068b35 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -50,6 +50,8 @@ class WDPService : public KeyedService { static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); static void RegisterProfilePrefs(PrefRegistrySimple* registry); + static void SetExtensionPrefIfNativeDisabled(PrefService* profile_prefs); + void OnFinishNavigation(const GURL& url, content::RenderFrameHost* render_frame_host); From 308288f816daf01ff2a879d9962ba078c4274e37 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 26 Jun 2024 21:35:38 -0700 Subject: [PATCH 28/36] Update Web Discovery CTA to set correct pref --- browser/ui/BUILD.gn | 8 ++++++++ browser/ui/webui/brave_settings_ui.cc | 2 ++ browser/web_discovery/web_discovery_cta_util.cc | 16 +++++++++++++++- .../web_discovery_infobar_delegate.cc | 15 ++++++++++++++- components/web_discovery/browser/BUILD.gn | 2 ++ .../browser/content_scraper_browsertest.cc | 4 ++++ 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index ed5b29ccfd95..3fdfea684adb 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -19,6 +19,7 @@ import("//brave/components/request_otr/common/buildflags/buildflags.gni") import("//brave/components/speedreader/common/buildflags/buildflags.gni") import("//brave/components/text_recognition/common/buildflags/buildflags.gni") import("//brave/components/tor/buildflags/buildflags.gni") +import("//brave/components/web_discovery/common/buildflags/buildflags.gni") import("//build/config/features.gni") import("//chrome/common/features.gni") import("//components/gcm_driver/config.gni") @@ -843,6 +844,13 @@ source_set("ui") { } } + if (enable_web_discovery_native) { + deps += [ + "//brave/components/web_discovery/common", + "//brave/components/web_discovery/common/buildflags", + ] + } + if (is_linux) { sources += [ "views/brave_views_delegate_linux.cc", diff --git a/browser/ui/webui/brave_settings_ui.cc b/browser/ui/webui/brave_settings_ui.cc index 743148b7d889..812e59af6895 100644 --- a/browser/ui/webui/brave_settings_ui.cc +++ b/browser/ui/webui/brave_settings_ui.cc @@ -189,9 +189,11 @@ void BraveSettingsUI::AddResources(content::WebUIDataSource* html_source, ShouldExposeElementsForTesting()); html_source->AddBoolean("enable_extensions", BUILDFLAG(ENABLE_EXTENSIONS)); +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) html_source->AddBoolean("isWebDiscoveryNativeEnabled", base::FeatureList::IsEnabled( web_discovery::features::kWebDiscoveryNative)); +#endif html_source->AddBoolean("extensionsManifestV2Feature", base::FeatureList::IsEnabled(kExtensionsManifestV2)); diff --git a/browser/web_discovery/web_discovery_cta_util.cc b/browser/web_discovery/web_discovery_cta_util.cc index 04d0dbff1648..0a053023faeb 100644 --- a/browser/web_discovery/web_discovery_cta_util.cc +++ b/browser/web_discovery/web_discovery_cta_util.cc @@ -14,6 +14,7 @@ #include "brave/components/constants/pref_names.h" #include "brave/components/constants/url_constants.h" #include "brave/components/search_engines/brave_prepopulated_engines.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/search_engines/template_url.h" @@ -21,6 +22,11 @@ #include "net/base/url_util.h" #include "url/gurl.h" +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/common/features.h" +#endif + namespace { constexpr int kMaxDisplayCount = 5; @@ -87,7 +93,15 @@ bool ShouldShowWebDiscoveryInfoBar(TemplateURLService* service, PrefService* prefs, const WebDiscoveryCTAState& state, base::Clock* test_clock) { - if (prefs->GetBoolean(kWebDiscoveryExtensionEnabled)) { + const char* enabled_pref_name = kWebDiscoveryExtensionEnabled; +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + if (base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)) { + enabled_pref_name = web_discovery::kWebDiscoveryNativeEnabled; + } +#endif + + if (prefs->GetBoolean(enabled_pref_name)) { return false; } diff --git a/browser/web_discovery/web_discovery_infobar_delegate.cc b/browser/web_discovery/web_discovery_infobar_delegate.cc index 49a275b6a810..b604262e05b1 100644 --- a/browser/web_discovery/web_discovery_infobar_delegate.cc +++ b/browser/web_discovery/web_discovery_infobar_delegate.cc @@ -7,9 +7,15 @@ #include "brave/browser/web_discovery/web_discovery_cta_util.h" #include "brave/components/constants/pref_names.h" +#include "brave/components/web_discovery/common/buildflags/buildflags.h" #include "components/infobars/core/infobar.h" #include "components/prefs/pref_service.h" +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) +#include "brave/components/web_discovery/browser/pref_names.h" +#include "brave/components/web_discovery/common/features.h" +#endif + WebDiscoveryInfoBarDelegate::WebDiscoveryInfoBarDelegate(PrefService* prefs) : prefs_(prefs) {} @@ -42,6 +48,13 @@ void WebDiscoveryInfoBarDelegate::Close(bool dismiss) { } void WebDiscoveryInfoBarDelegate::EnableWebDiscovery() { - prefs_->SetBoolean(kWebDiscoveryExtensionEnabled, true); + const char* pref_name = kWebDiscoveryExtensionEnabled; +#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE) + if (base::FeatureList::IsEnabled( + web_discovery::features::kWebDiscoveryNative)) { + pref_name = web_discovery::kWebDiscoveryNativeEnabled; + } +#endif + prefs_->SetBoolean(pref_name, true); infobar()->RemoveSelf(); } diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index c78c130f6ead..17ea3538b7eb 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -53,6 +53,7 @@ static_library("browser") { "//base", "//brave/brave_domains", "//brave/components/constants", + "//brave/components/web_discovery/common", "//brave/components/web_discovery/common:mojom", "//components/keyed_service/core", "//components/prefs", @@ -100,6 +101,7 @@ source_set("browser_tests") { ":browser", "//base/test:test_support", "//brave/components/constants", + "//brave/components/web_discovery/common", "//brave/components/web_discovery/common:mojom", "//content/test:test_support", "//net:test_support", diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc index e1d2586e4eca..88b1261fcd9d 100644 --- a/components/web_discovery/browser/content_scraper_browsertest.cc +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -15,6 +15,7 @@ #include "brave/components/constants/brave_paths.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" +#include "brave/components/web_discovery/common/features.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" @@ -33,6 +34,8 @@ namespace web_discovery { class WebDiscoveryContentScraperTest : public PlatformBrowserTest { public: + WebDiscoveryContentScraperTest() + : scoped_features_(features::kWebDiscoveryNative) {} void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); base::FilePath data_path = @@ -145,6 +148,7 @@ class WebDiscoveryContentScraperTest : public PlatformBrowserTest { ®ex_util_); } + base::test::ScopedFeatureList scoped_features_; RegexUtil regex_util_; std::unique_ptr server_config_loader_; }; From 8d07c0210ec224cb7c186f8475c2339453087f7f Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 27 Jun 2024 14:19:38 -0700 Subject: [PATCH 29/36] Add comments for Web Discovery --- .../web_discovery/browser/content_scraper.h | 15 ++++ .../browser/credential_manager.h | 15 ++++ .../web_discovery/browser/credential_signer.h | 9 +++ .../browser/document_extractor/rs/src/lib.rs | 12 +++ .../web_discovery/browser/double_fetcher.h | 8 ++ .../web_discovery/browser/hash_detection.h | 3 + components/web_discovery/browser/patterns.h | 75 ++++++++++++++++++- .../web_discovery/browser/payload_generator.h | 4 + .../web_discovery/browser/privacy_guard.h | 11 +++ components/web_discovery/browser/regex_util.h | 2 + components/web_discovery/browser/reporter.h | 10 +++ .../web_discovery/browser/request_queue.h | 6 ++ .../browser/server_config_loader.h | 13 ++++ .../browser/signature_basename.h | 13 +++- components/web_discovery/browser/util.h | 13 ++++ .../web_discovery/browser/wdp_service.cc | 5 +- .../web_discovery/browser/wdp_service.h | 10 ++- .../browser/web_discovery_tab_helper.cc | 2 +- components/web_discovery/common/features.h | 2 + .../web_discovery/common/web_discovery.mojom | 10 +++ .../renderer/blink_document_extractor.h | 2 + 21 files changed, 230 insertions(+), 10 deletions(-) diff --git a/components/web_discovery/browser/content_scraper.h b/components/web_discovery/browser/content_scraper.h index 980db82b15b4..68d6cb60178a 100644 --- a/components/web_discovery/browser/content_scraper.h +++ b/components/web_discovery/browser/content_scraper.h @@ -33,6 +33,9 @@ struct PageScrapeResult { static std::unique_ptr FromValue(const base::Value& dict); GURL url; + // A map of DOM selectors to list of scraped values embedded in a Dict. + // Each dict contains arbitrary keys (defined in the patterns) to scraped + // values. base::flat_map> fields; std::string id; @@ -41,6 +44,18 @@ struct PageScrapeResult { std::optional query; }; +// Extracts attribute values from the page DOM for reporting purposes. +// ContentScraper utilizes the following techniques: +// +// a) Extraction within the current page in the renderer (via `ScrapePage`). +// The `mojom::DocumentExtractor` is used to request attribute values +// from the current DOM in the view. Typically, this is used to exact a +// search query, and decide whether the page is worthy of investigation +// and reporting. +// b) Parsing and extracting HTML from a double fetch. This follows +// the extraction in a). Used to extract all other needed details +// from the page i.e. search results. Uses a Rust library for DOM +// operations, in respect of Rule of Two. class ContentScraper { public: using PageScrapeResultCallback = diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index e32333e58f8b..4eb7418484fd 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -35,6 +35,16 @@ struct GenerateJoinRequestResult { std::string signature; }; +// Manages and utilizes anonymous credentials used for communicating +// with Web Discovery servers. These Direct Anonymous Attestation credentials +// are used to prevent Sybil attacks on the servers. +// The manager provides two key functions: +// +// a) "joining": acquires credentials from the Web Discovery server. Join +// requests +// are signed with a random RSA key that is persisted with the profile. +// b) "signing": uses the previously acquired credentials to sign submissions +// which is required in order for the servers to accept the request. class CredentialManager : public CredentialSigner { public: CredentialManager(PrefService* profile_prefs, @@ -45,6 +55,8 @@ class CredentialManager : public CredentialSigner { CredentialManager(const CredentialManager&) = delete; CredentialManager& operator=(const CredentialManager&) = delete; + // Acquires credentials for all dates/"group public keys" published in + // the server config, if not stored already. void JoinGroups(); // CredentialSigner: @@ -54,6 +66,9 @@ class CredentialManager : public CredentialSigner { std::vector basename, SignCallback callback) override; + // Uses a fixed seed in the anonymous credential manager + // to provide deterministic credentials & signatures which + // are useful for testing. void UseFixedSeedForTesting(); private: diff --git a/components/web_discovery/browser/credential_signer.h b/components/web_discovery/browser/credential_signer.h index ef80cbb8ddc2..b7e167cf1e49 100644 --- a/components/web_discovery/browser/credential_signer.h +++ b/components/web_discovery/browser/credential_signer.h @@ -19,7 +19,16 @@ class CredentialSigner { base::OnceCallback>)>; virtual ~CredentialSigner(); + // Returns true is a credential is available for the current date. + // The caller can expect future calls to `Sign` to succeed, if made today. virtual bool CredentialExistsForToday() = 0; + + // Signs a message for a given basename. The server has the ability + // to check whether two messages with the same basename were signed + // with the same credential without revealing the credential used, + // preventing Sybil attacks. + // See signature_basename.h/cc for more information on how the basename + // should be generated. virtual bool Sign(std::vector msg, std::vector basename, SignCallback callback) = 0; diff --git a/components/web_discovery/browser/document_extractor/rs/src/lib.rs b/components/web_discovery/browser/document_extractor/rs/src/lib.rs index ac52e8940731..17ce268b19e2 100644 --- a/components/web_discovery/browser/document_extractor/rs/src/lib.rs +++ b/components/web_discovery/browser/document_extractor/rs/src/lib.rs @@ -17,27 +17,39 @@ use kuchikiki::{ #[cxx::bridge(namespace = "rust_document_extractor")] mod ffi { pub struct SelectAttributeRequest { + /// An optional selector for an element within the current selected element. + /// The attribute will be retrieved from the embedded element. + /// If not needed, an empty string should be provided. pub sub_selector: String, + /// Arbitrary ID used for storing the scraped result. pub key: String, + /// Name of the attribute to scrape. pub attribute: String, } pub struct SelectRequest { + /// The DOM selector for the element to scrape. pub root_selector: String, + /// Scrape requests for the selected element. pub attribute_requests: Vec, } pub struct AttributePair { + /// Arbitrary ID for the scraped result. pub key: String, + /// The scraped value. Will be empty if attribute is not available. pub value: String, } pub struct AttributeResult { + /// The DOM selector for the scraped element. pub root_selector: String, + /// A list of arbitrary IDs and scraped value pairs. pub attribute_pairs: Vec, } extern "Rust" { + /// Extracts DOM attributes from the result of a double fetch. fn query_element_attributes( html: &CxxString, requests: &CxxVector, diff --git a/components/web_discovery/browser/double_fetcher.h b/components/web_discovery/browser/double_fetcher.h index 08f5e05bd480..e2b8c979a78d 100644 --- a/components/web_discovery/browser/double_fetcher.h +++ b/components/web_discovery/browser/double_fetcher.h @@ -24,6 +24,11 @@ class SimpleURLLoader; namespace web_discovery { +// Makes anonymous requests to relevant page URLs, without involvement of the +// user's session. In the case of search engine result pages, the result of the +// double fetch will scraped for search engine results for a future submission. +// Uses `RequestQueue` to persist and schedule double fetches. Requests +// will be sent on somewhat random intervals averaging to a minute. class DoubleFetcher { public: using FetchedCallback = @@ -38,6 +43,9 @@ class DoubleFetcher { DoubleFetcher(const DoubleFetcher&) = delete; DoubleFetcher& operator=(const DoubleFetcher&) = delete; + // Queues a double fetch for a given URL. The associated data will be stored + // beside the queue request, and will be passed to the `FetchedCallback` + // upon completion. void ScheduleDoubleFetch(const GURL& url, base::Value associated_data); private: diff --git a/components/web_discovery/browser/hash_detection.h b/components/web_discovery/browser/hash_detection.h index 376674b4393e..c6461aa40bc4 100644 --- a/components/web_discovery/browser/hash_detection.h +++ b/components/web_discovery/browser/hash_detection.h @@ -12,6 +12,9 @@ namespace web_discovery { +// Uses a pre-trained Markov chain classifier to detect the likelihood +// of a hash in a given piece of text. Used in privacy guard functions +// for detecting potentially private URLs/queries. bool IsHashLikely(RegexUtil& regex_util, std::string value, double probability_multiplier = 1.0); diff --git a/components/web_discovery/browser/patterns.h b/components/web_discovery/browser/patterns.h index 6416089eddec..b9e3b749e104 100644 --- a/components/web_discovery/browser/patterns.h +++ b/components/web_discovery/browser/patterns.h @@ -21,12 +21,40 @@ class RE2; namespace web_discovery { -enum class ScrapeRuleType { kStandard, kSearchQuery, kWidgetTitle, kOther }; -enum class PayloadRuleType { kQuery, kSingle }; -enum class PayloadResultType { kSingle, kClustered, kCustom }; +enum class ScrapeRuleType { + // Will retrieve a value not defined in the DOM, such as the client country + // code or the current url. + kStandard, + // If the following two types are used for a rule, the value will be marked + // as the search query, which will be used for privacy checks. + kSearchQuery, + kWidgetTitle, + // All other rules should have this type. No special processing will be + // performed. + kOther +}; +enum class PayloadRuleType { + // Coupled with the `kClustered` result type. + // All instances of a given attribute will be grouped into a single payload. + kQuery, + // Coupled with the `kSingle` result type. + // Each instance of a given attribute will have its own payload. + kSingle +}; +enum class PayloadResultType { + // Coupled with the `kSingle` rule type. + kSingle, + // Coupled with the `kClustered` rule type. + kClustered, + // Currently unsupported/ignored. + kCustom +}; +// Contains functions for refining the scraped value. The inner vector +// contains the function name and arguments for the function. using RefineFunctionList = std::vector>; +// Defines rule for scraping an attribute from a given selected element. struct ScrapeRule { ScrapeRule(); ~ScrapeRule(); @@ -34,15 +62,23 @@ struct ScrapeRule { ScrapeRule(const ScrapeRule&) = delete; ScrapeRule& operator=(const ScrapeRule&) = delete; + // An optional selector for an element within the current selected element. + // The attribute will be retrieved from the embedded element. std::optional sub_selector; ScrapeRuleType rule_type; + // The name of the attribute to retrieve for a DOM element. std::string attribute; + // Functions used to refine the retrieved value. See the "func ids" defined + // in content_scraper.cc for all possible functions. RefineFunctionList functions_applied; }; +// A map of keys (arbitrary IDs used for storing the scraped result) to scrape +// rules. using ScrapeRuleGroup = base::flat_map>; +// A rule for provided a single key/value pair within the submission payload. struct PayloadRule { PayloadRule(); ~PayloadRule(); @@ -50,11 +86,19 @@ struct PayloadRule { PayloadRule(const PayloadRule&) = delete; PayloadRule& operator=(const PayloadRule&) = delete; + // The DOM selector of the scraped attribute. std::string selector; + // The arbitrary key associated with the scraped value. std::string key; + // If set to true, an array-like Dict (each dict key is an index) + // will be rendered. + // Each value in the Dict will be a Dict containing all keys/values + // associated with the selector. This is commonly used for listing search + // results. bool is_join = false; }; +// Contains rules for generating a payload for submission. struct PayloadRuleGroup { PayloadRuleGroup(); ~PayloadRuleGroup(); @@ -62,13 +106,18 @@ struct PayloadRuleGroup { PayloadRuleGroup(const PayloadRuleGroup&) = delete; PayloadRuleGroup& operator=(const PayloadRuleGroup&) = delete; + // An arbitrary ID for the rule group. Current, this isn't used in the + // payload. std::string key; PayloadRuleType rule_type; PayloadResultType result_type; + // The name of the "action" for the given payload. std::string action; + // The rules for generating the fields within the payload. std::vector rules; }; +// Contains settings and rule groups associated with a particular URL. struct PatternsURLDetails { PatternsURLDetails(); ~PatternsURLDetails(); @@ -76,14 +125,24 @@ struct PatternsURLDetails { PatternsURLDetails(const PatternsURLDetails&) = delete; PatternsURLDetails& operator=(const PatternsURLDetails&) = delete; + // The regex used to match the URL in the address bar. std::unique_ptr url_regex; bool is_search_engine; + // The two or three-letter arbitrary id associated with the site. std::string id; + // The search path prefix used for constructing private search queries + // for double fetching. std::optional search_template_prefix; + // The scraping rules for the site. A map of DOM selectors + // to rule groups. base::flat_map scrape_rule_groups; + // The payload generation rules used for generating submissions + // from scraped attributes. std::vector payload_rule_groups; }; +// The full "patterns" configuration provided by the Web Discovery server. +// The configuration provides rules for scraping certain pages. struct PatternsGroup { PatternsGroup(); ~PatternsGroup(); @@ -91,13 +150,23 @@ struct PatternsGroup { PatternsGroup(const PatternsGroup&) = delete; PatternsGroup& operator=(const PatternsGroup&) = delete; + // Checks URL against all URL regexes in either the "normal" or "strict" set, + // and returns the URL details/rules if available. const PatternsURLDetails* GetMatchingURLPattern(const GURL& url, bool is_strict_scrape) const; + // A list of URLs and rules used for scraping pages in the renderer, + // pre-"double fetch". These rules typically scrape simple attributes which + // are used to determine whether a page is private (i.e. the search query). std::vector normal_patterns; + // A list of URLS and rules used for scraping contents from a "double fetch". + // The rules are usually more involved than the "normal" rules. In the case of + // search engine result pages, the rules will be used to retrieve the + // search results and any other relevant details. std::vector strict_patterns; }; +// Returns nullptr if parsing fails. std::unique_ptr ParsePatterns(const std::string& patterns_json); } // namespace web_discovery diff --git a/components/web_discovery/browser/payload_generator.h b/components/web_discovery/browser/payload_generator.h index 732eff6234fa..b234c5872abc 100644 --- a/components/web_discovery/browser/payload_generator.h +++ b/components/web_discovery/browser/payload_generator.h @@ -20,12 +20,16 @@ namespace web_discovery { inline constexpr char kActionKey[] = "action"; inline constexpr char kInnerPayloadKey[] = "payload"; +// Generates "query" messages using the payload generation rules +// and scraped data for a given site. std::vector GenerateQueryPayloads( const ServerConfig& server_config, RegexUtil& regex_util, const PatternsURLDetails* url_details, std::unique_ptr scrape_result); +// Generates an "alive" message to indicate an opted-in +// status to the server. base::Value::Dict GenerateAlivePayload(const ServerConfig& server_config, std::string date_hour); diff --git a/components/web_discovery/browser/privacy_guard.h b/components/web_discovery/browser/privacy_guard.h index 38328f4068e2..36c2fcc971b4 100644 --- a/components/web_discovery/browser/privacy_guard.h +++ b/components/web_discovery/browser/privacy_guard.h @@ -14,18 +14,29 @@ namespace web_discovery { +// Checks if a URL is likely to be private based on various criteria. +// If true, the page should not be investigated or reported. bool IsPrivateURLLikely(RegexUtil& regex_util, const GURL& url, const PatternsURLDetails* matching_url_details); +// Determines if a search query is likely to contain private information. +// If true, the search query should not be investigated or reported. bool IsPrivateQueryLikely(RegexUtil& regex_util, const std::string& query); +// Generates a simple search URL (without additional query parameters) +// based on the original search URL and query. Used for the double fetch +// to ensure that the user's profile is not involved in the query. GURL GeneratePrivateSearchURL(const GURL& original_url, const std::string& query, const PatternsURLDetails& matching_url_details); +// Checks if a URL should be dropped due to its length or content. +// Currently only used for determining whether to mask a URL +// in the function below. bool ShouldDropLongURL(RegexUtil& regex_util, const GURL& url); +// Masks a URL to protect privacy. Returns nullopt if URL is invalid. std::optional MaskURL(RegexUtil& regex_util, const GURL& url); } // namespace web_discovery diff --git a/components/web_discovery/browser/regex_util.h b/components/web_discovery/browser/regex_util.h index 970030c55230..e08dad02fd6e 100644 --- a/components/web_discovery/browser/regex_util.h +++ b/components/web_discovery/browser/regex_util.h @@ -16,6 +16,8 @@ namespace web_discovery { +// Lazily creates and caches pre-compiled regexes, mainly used for +// privacy risk assessment of page URLs/contents. class RegexUtil { public: RegexUtil(); diff --git a/components/web_discovery/browser/reporter.h b/components/web_discovery/browser/reporter.h index a3649b049c72..f79e14fcdbc7 100644 --- a/components/web_discovery/browser/reporter.h +++ b/components/web_discovery/browser/reporter.h @@ -29,6 +29,15 @@ class SimpleURLLoader; namespace web_discovery { +// Handles all functions required for reporting generated payloads: +// - zlib compression +// - ECDH key derivation + key exchange +// - AES encryption (to prevent eavesdropping by the server proxy) +// - signing the request using anonymous credentials from the +// `CredentialManager` (to prevent Sybil attacks on the server) +// - performing the request for submission +// Uses `RequestQueue` to persist and schedule submissions. Reports +// will be processed on somewhat random intervals averaging to a minute. class Reporter { public: Reporter(PrefService* profile_prefs, @@ -41,6 +50,7 @@ class Reporter { Reporter(const Reporter&) = delete; Reporter& operator=(const Reporter&) = delete; + // Schedule a generated payload for submission. void ScheduleSend(base::Value::Dict payload); private: diff --git a/components/web_discovery/browser/request_queue.h b/components/web_discovery/browser/request_queue.h index 6fbfbd194b20..fd385bcee22a 100644 --- a/components/web_discovery/browser/request_queue.h +++ b/components/web_discovery/browser/request_queue.h @@ -16,6 +16,10 @@ class PrefService; namespace web_discovery { +// Persists and schedules requests on randomized intervals within +// an interval range. If request failures exceed the threshold defined in +// `max_retries`, the request will be dropped from the list. If a persisted +// request age exceeds `request_max_age`, the request will be dropped. class RequestQueue { public: RequestQueue( @@ -31,6 +35,8 @@ class RequestQueue { RequestQueue(const RequestQueue&) = delete; RequestQueue& operator=(const RequestQueue&) = delete; + // Persist and schedule a request. The arbitrary data will be passed + // to `start_request_callback` on the scheduled interval. void ScheduleRequest(base::Value request_data); // Returns data value if request is deleted from queue, due to the retry limit // or success diff --git a/components/web_discovery/browser/server_config_loader.h b/components/web_discovery/browser/server_config_loader.h index 797227ca7256..856073249b34 100644 --- a/components/web_discovery/browser/server_config_loader.h +++ b/components/web_discovery/browser/server_config_loader.h @@ -58,6 +58,12 @@ struct ServerConfig { std::string location; }; +// Handles retrieval, updating and caching of the following server +// configurations: +// - HPN server config: contains public keys, and "source maps" used +// for generating basenames. +// - "quorum" config: contains the country code of the user +// - patterns: contains the rules for scraping/submission of certain pages class ServerConfigLoader { public: ServerConfigLoader(PrefService* local_state, @@ -70,9 +76,16 @@ class ServerConfigLoader { ServerConfigLoader(const ServerConfigLoader&) = delete; ServerConfigLoader& operator=(const ServerConfigLoader&) = delete; + // Loads all three server configurations. Update requests will be scheduled + // once complete. void LoadConfigs(); + // Returns the last loaded server config, which is a combination of the + // HPN and "quorum" configs. May only call after the config_callback is + // triggered. const ServerConfig& GetLastServerConfig() const; + // Returns the pattern config. May only call after the patterns_callback is + // triggered. const PatternsGroup& GetLastPatterns() const; void SetLastServerConfigForTesting( diff --git a/components/web_discovery/browser/signature_basename.h b/components/web_discovery/browser/signature_basename.h index fb6101608649..1a07cf027e25 100644 --- a/components/web_discovery/browser/signature_basename.h +++ b/components/web_discovery/browser/signature_basename.h @@ -33,16 +33,27 @@ struct BasenameResult { uint32_t count_tag_hash; }; +// Generates a basename used for the signature. The basename is a sha hash +// of the message "action" (i.e. "query"), the settings for that action +// (defined in the server's "source map"), cherry-picked attributes from the +// payload and the count index for the given message. The count will be under +// the limit defined for the action; the function will return nullopt if the +// limit for the action is exceeded. std::optional GenerateBasename( PrefService* profile_prefs, const ServerConfig& server_config, RegexUtil& regex_util, const base::Value::Dict& payload); +// Saves the count returned from `GenerateBasename` in the prefs. +// This ensures that the count index cannot be used for future messages +// within the defined action limit period (default is 24 hours). +// This should be called after a submission is successfully sent to +// the server. void SaveBasenameCount(PrefService* profile_prefs, uint32_t count_tag_hash, size_t count); } // namespace web_discovery -#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_PAYLOAD_GENERATOR_H_ +#endif // BRAVE_COMPONENTS_WEB_DISCOVERY_BROWSER_SIGNATURE_BASENAME_H_ diff --git a/components/web_discovery/browser/util.h b/components/web_discovery/browser/util.h index 4a00b6c17262..9792b4622d55 100644 --- a/components/web_discovery/browser/util.h +++ b/components/web_discovery/browser/util.h @@ -22,6 +22,7 @@ inline constexpr char kCollectorHostSwitch[] = "wdp-collector-host"; inline constexpr char kVersionHeader[] = "Version"; inline constexpr int kCurrentVersion = 1; +// The default backoff policy to use for scheduling retry requests. inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { .num_errors_to_ignore = 0, .initial_delay_ms = 10 * 1000, @@ -31,17 +32,29 @@ inline constexpr net::BackoffEntry::Policy kBackoffPolicy = { .entry_lifetime_ms = -1, .always_use_initial_delay = false}; +// Returns the non-proxied HPN host, used for acquiring anonymous credentials. std::string GetDirectHPNHost(); +// Returns the proxied HPN host, used for retrieving server config and page +// content submission. std::string GetAnonymousHPNHost(); +// Returns the "quorum" host, used for location config and page event +// submission. std::string GetQuorumHost(); +// Returns the full URL for the patterns config. GURL GetPatternsEndpoint(); +// Creates a new ResourceRequest with the given URL and credentials omitted. std::unique_ptr CreateResourceRequest(GURL url); +// Formats a given date as a string in the format "YYYYMMDD", in the UTC +// timezone. std::string FormatServerDate(const base::Time& date); +// Decodes URL-encoded components, converting escape sequences to their +// corresponding characters. std::string DecodeURLComponent(const std::string_view value); +// Extracts the value associated with a given key from a URL query string. std::optional ExtractValueFromQueryString( const std::string_view query_string, const std::string_view key); diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index c2cea0ca4a25..a5c31e29d303 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -158,9 +158,8 @@ void WDPService::OnDoubleFetched(const GURL& url, true)); } -void WDPService::OnFinishNavigation( - const GURL& url, - content::RenderFrameHost* render_frame_host) { +void WDPService::DidFinishLoad(const GURL& url, + content::RenderFrameHost* render_frame_host) { if (!content_scraper_) { return; } diff --git a/components/web_discovery/browser/wdp_service.h b/components/web_discovery/browser/wdp_service.h index f2ea1f068b35..6549dcf59356 100644 --- a/components/web_discovery/browser/wdp_service.h +++ b/components/web_discovery/browser/wdp_service.h @@ -35,6 +35,8 @@ class SharedURLLoaderFactory; namespace web_discovery { +// The main service for the native re-implementation of Web Discovery Project. +// Handles scraping and reporting of relevant pages for opted-in users. class WDPService : public KeyedService { public: WDPService( @@ -50,10 +52,14 @@ class WDPService : public KeyedService { static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); static void RegisterProfilePrefs(PrefRegistrySimple* registry); + // Sets the extension preference to true if the preference for the native + // implementation is set to true and the feature is disabled. + // Relevant for a Griffin/variations rollback. static void SetExtensionPrefIfNativeDisabled(PrefService* profile_prefs); - void OnFinishNavigation(const GURL& url, - content::RenderFrameHost* render_frame_host); + // Called by `WebDiscoveryTabHelper` to notify on a page load. + void DidFinishLoad(const GURL& url, + content::RenderFrameHost* render_frame_host); private: void Start(); diff --git a/components/web_discovery/browser/web_discovery_tab_helper.cc b/components/web_discovery/browser/web_discovery_tab_helper.cc index 98c120e2be25..023e260fe501 100644 --- a/components/web_discovery/browser/web_discovery_tab_helper.cc +++ b/components/web_discovery/browser/web_discovery_tab_helper.cc @@ -26,7 +26,7 @@ void WebDiscoveryTabHelper::DidFinishLoad( if (!render_frame_host->IsInPrimaryMainFrame()) { return; } - wdp_service_->OnFinishNavigation(url, render_frame_host); + wdp_service_->DidFinishLoad(url, render_frame_host); } WEB_CONTENTS_USER_DATA_KEY_IMPL(WebDiscoveryTabHelper); diff --git a/components/web_discovery/common/features.h b/components/web_discovery/common/features.h index 2083a40ec39c..45db0afd2555 100644 --- a/components/web_discovery/common/features.h +++ b/components/web_discovery/common/features.h @@ -10,6 +10,8 @@ namespace web_discovery::features { +// Enables the native re-implementation of the Web Discovery Project. +// If enabled, the Web Discovery component of the extension should be disabled. BASE_DECLARE_FEATURE(kWebDiscoveryNative); } // namespace web_discovery::features diff --git a/components/web_discovery/common/web_discovery.mojom b/components/web_discovery/common/web_discovery.mojom index 709d3bab3a57..94de01e15d6d 100644 --- a/components/web_discovery/common/web_discovery.mojom +++ b/components/web_discovery/common/web_discovery.mojom @@ -6,21 +6,31 @@ module web_discovery.mojom; struct SelectAttributeRequest { + // An optional selector for an element within the current selected element. + // The attribute will be retrieved from the embedded element. string? sub_selector; + // Arbitrary ID used for storing the scraped result. string key; + // Name of the attribute to scrape. string attribute; }; struct SelectRequest { + // The DOM selector for the element to scrape. string root_selector; + // Scrape requests for the selected element. array attribute_requests; }; struct AttributeResult { + // The DOM selector for the scraped element. string root_selector; + // A map of arbitrary IDs to scraped results. Value will be set to + // nullopt if the attribute was not available. map attribute_values; }; interface DocumentExtractor { + // Extracts DOM attributes from the current page in renderer. QueryElementAttributes(array requests) => (array results); }; diff --git a/components/web_discovery/renderer/blink_document_extractor.h b/components/web_discovery/renderer/blink_document_extractor.h index ce4e19c4b252..b502872395c3 100644 --- a/components/web_discovery/renderer/blink_document_extractor.h +++ b/components/web_discovery/renderer/blink_document_extractor.h @@ -16,6 +16,8 @@ namespace web_discovery { +// Extracts attributes from the current page +// for the native re-implementation of Web Discovery. class BlinkDocumentExtractor : public content::RenderFrameObserver, public mojom::DocumentExtractor { public: From e7d5399a5ec1f7d1df5ba832271191b7c84cb965 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Thu, 27 Jun 2024 16:37:30 -0700 Subject: [PATCH 30/36] Update anonymous-credentials and brave-miracl --- .../anonymous_credentials/rs/Cargo.lock | 52 +- .../rust/anonymous_credentials/v0_1/BUILD.gn | 14 +- .../rust/chromium_crates_io/gnrt_config.toml | 4 +- .../.cargo_vcs_info.json | 6 - .../.cargo-checksum.json | 0 .../.cargo_vcs_info.json | 6 + .../.gitignore | 0 .../Cargo.toml | 2 +- .../Cargo.toml.orig | 4 +- .../LICENSE | 0 .../README.md | 0 .../src/data.rs | 19 +- .../src/join.rs | 0 .../src/lib.rs | 16 + .../src/sign.rs | 0 .../src/util.rs | 0 .../brave-miracl-0.1.2/.cargo-checksum.json | 1 - .../brave-miracl-0.1.2/.cargo_vcs_info.json | 6 - .../vendor/brave-miracl-0.1.2/.gitignore | 2 - .../vendor/brave-miracl-0.1.2/.gitmodules | 3 - .../vendor/brave-miracl-0.1.2/Cargo.toml | 34 - .../vendor/brave-miracl-0.1.2/Cargo.toml.orig | 18 - .../vendor/brave-miracl-0.1.2/LICENSE | 202 -- .../vendor/brave-miracl-0.1.2/README.md | 15 - .../vendor/brave-miracl-0.1.2/src/aes.rs | 901 -------- .../vendor/brave-miracl-0.1.2/src/arch.rs | 22 - .../brave-miracl-0.1.2/src/bn254/big.rs | 1062 ---------- .../brave-miracl-0.1.2/src/bn254/bls.rs | 181 -- .../brave-miracl-0.1.2/src/bn254/dbig.rs | 314 --- .../brave-miracl-0.1.2/src/bn254/ecdh.rs | 432 ---- .../brave-miracl-0.1.2/src/bn254/ecp.rs | 1824 ----------------- .../brave-miracl-0.1.2/src/bn254/ecp2.rs | 999 --------- .../brave-miracl-0.1.2/src/bn254/eddsa.rs | 455 ---- .../vendor/brave-miracl-0.1.2/src/bn254/fp.rs | 825 -------- .../brave-miracl-0.1.2/src/bn254/fp12.rs | 1111 ---------- .../brave-miracl-0.1.2/src/bn254/fp2.rs | 516 ----- .../brave-miracl-0.1.2/src/bn254/fp4.rs | 784 ------- .../brave-miracl-0.1.2/src/bn254/hpke.rs | 386 ---- .../brave-miracl-0.1.2/src/bn254/mod.rs | 30 - .../brave-miracl-0.1.2/src/bn254/mpin.rs | 228 --- .../brave-miracl-0.1.2/src/bn254/pair.rs | 1038 ---------- .../brave-miracl-0.1.2/src/bn254/rom.rs | 192 -- .../brave-miracl-0.1.2/src/dilithium.rs | 1199 ----------- .../vendor/brave-miracl-0.1.2/src/gcm.rs | 508 ----- .../vendor/brave-miracl-0.1.2/src/hash256.rs | 288 --- .../vendor/brave-miracl-0.1.2/src/hash384.rs | 383 ---- .../vendor/brave-miracl-0.1.2/src/hash512.rs | 383 ---- .../vendor/brave-miracl-0.1.2/src/hmac.rs | 870 -------- .../vendor/brave-miracl-0.1.2/src/kyber.rs | 719 ------- .../vendor/brave-miracl-0.1.2/src/lib.rs | 41 - .../vendor/brave-miracl-0.1.2/src/main.rs | 3 - .../vendor/brave-miracl-0.1.2/src/nhs.rs | 709 ------- .../vendor/brave-miracl-0.1.2/src/rand.rs | 183 -- .../vendor/brave-miracl-0.1.2/src/sha3.rs | 344 ---- .../vendor/brave-miracl-0.1.2/src/share.rs | 154 -- .../vendor/brave-miracl-0.1.2/src/x509.rs | 1285 ------------ 56 files changed, 76 insertions(+), 18697 deletions(-) delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/.cargo-checksum.json (100%) create mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/.gitignore (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/Cargo.toml (98%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/Cargo.toml.orig (83%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/LICENSE (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/README.md (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/src/data.rs (91%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/src/join.rs (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/src/lib.rs (90%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/src/sign.rs (100%) rename third_party/rust/chromium_crates_io/vendor/{anonymous-credentials-0.1.3 => anonymous-credentials-0.1.4}/src/util.rs (100%) delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/arch.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/big.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs diff --git a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock index 20ff89ce66fc..cefc9fa91611 100644 --- a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock +++ b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anonymous-credentials" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1acf2ababbdec2b27c687c7bc761c314055af0453f70f2df2417b686b475c3df" +checksum = "92cf8b44719f5d7259b63e8d729b6a1d04ef475984b463048ef3fb14a1f65884" dependencies = [ "brave-miracl", "lazy_static", @@ -24,15 +24,15 @@ dependencies = [ [[package]] name = "brave-miracl" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22bc3fa88a8cf37713577f7123a18636092c7ef2b6651eee2409fb0f9569f3b3" +checksum = "1529922eb7ce7b0f2cae0be12f200c17bebd5e0141019be023ddd50a8fd435f4" [[package]] name = "cc" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" [[package]] name = "cfg-if" @@ -42,9 +42,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cxx" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21db378d04296a84d8b7d047c36bb3954f0b46529db725d7e62fb02f9ba53ccc" +checksum = "273dcfd3acd4e1e276af13ed2a43eea7001318823e7a726a6b3ed39b4acc0b82" dependencies = [ "cc", "cxxbridge-flags", @@ -54,15 +54,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8dcadd2e2fb4a501e1d9e93d6e88e6ea494306d8272069c92d5a9edf8855c0" +checksum = "839fcd5e43464614ffaa989eaf1c139ef1f0c51672a1ed08023307fa1b909ccd" [[package]] name = "cxxbridge-macro" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad08a837629ad949b73d032c637653d069e909cffe4ee7870b02301939ce39cc" +checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", @@ -71,9 +71,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -82,15 +82,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "link-cplusplus" @@ -109,9 +109,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -157,9 +157,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -168,18 +168,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn index 0bee7aeebbbb..2e45251529ac 100644 --- a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn +++ b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn @@ -13,19 +13,19 @@ cargo_crate("lib") { crate_name = "anonymous_credentials" epoch = "0.1" crate_type = "rlib" - crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs" + crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs" sources = [ - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs", + "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs", ] inputs = [] build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.1.3" + cargo_pkg_version = "0.1.4" cargo_pkg_authors = "Darnell Andries " cargo_pkg_name = "anonymous-credentials" cargo_pkg_description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml index b75efa445cea..b47bfbbbf57e 100644 --- a/third_party/rust/chromium_crates_io/gnrt_config.toml +++ b/third_party/rust/chromium_crates_io/gnrt_config.toml @@ -110,8 +110,8 @@ if (target_os == "android" && target_cpu == "arm64") { } ''' } -[crate.anonymous_credentials] -license_files = ['LICENCE'] +[crate.anonymous-credentials] +license_files = ['LICENSE'] [crate.ansi_term] license_files = ['LICENCE'] diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json deleted file mode 100644 index caa8d9ccd7d4..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "54001a03a26180747ed3a748acf7706c8f8bb8e7" - }, - "path_in_vcs": "" -} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.cargo-checksum.json rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json new file mode 100644 index 000000000000..db43b7fcd30e --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "39c1a940b4ef9cb01c0a21c04a64a581c905426d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.gitignore b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/.gitignore rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml similarity index 98% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml index 62e3f2249448..7624650084b5 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "anonymous-credentials" -version = "0.1.3" +version = "0.1.4" authors = ["Darnell Andries "] description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" readme = "README.md" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig similarity index 83% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig index fb480d37bc81..d8cf642a798e 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/Cargo.toml.orig +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "anonymous-credentials" -version = "0.1.3" +version = "0.1.4" edition = "2021" authors = ["Darnell Andries "] description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" @@ -12,7 +12,7 @@ categories = ["cryptography"] [dependencies] lazy_static = "1.4" rand = "0.8" -brave-miracl = { version = "0.1", features = ["std"] } +brave-miracl = { version = "0.1", features = ["std"], path = "../miracl-rs" } thiserror = "1.0" [dev-dependencies] diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/LICENSE b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/LICENSE rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/README.md b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/README.md rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs similarity index 91% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs index 91fb515e1cff..9952399319ed 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/data.rs +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs @@ -18,17 +18,21 @@ pub const JOIN_RESPONSE_SIZE: usize = USER_CREDENTIALS_SIZE + ECP_PROOF_SIZE; pub const GROUP_PUBLIC_KEY_SIZE: usize = ECP2_COMPAT_SIZE * 2 + BIG_SIZE * 4; pub const SIGNATURE_SIZE: usize = ECP_SIZE * 5 + ECP_PROOF_SIZE; +/// A "join" request to be sent to the issuer. pub struct JoinRequest { pub(crate) q: ECP, // G1 ** gsk pub(crate) proof: ECPProof, } +/// A "join" response from the issuer, to be used +/// to generate DAA credentials. pub struct JoinResponse { pub(crate) cred: UserCredentials, pub(crate) proof: ECPProof, } +/// DAA credentials to be used for signing messages. pub struct UserCredentials { pub(crate) a: ECP, pub(crate) b: ECP, @@ -36,6 +40,7 @@ pub struct UserCredentials { pub(crate) d: ECP, } +/// A DAA signature to be sent to the verifier. pub struct Signature { pub(crate) a: ECP, pub(crate) b: ECP, @@ -46,6 +51,9 @@ pub struct Signature { pub(crate) proof: ECPProof, } +/// A group public key published by the issuer. +/// This is required to finish the "join" process +/// and acquire credentials. pub struct GroupPublicKey { pub(crate) x: ECP2, // G2 ** x pub(crate) y: ECP2, // G2 ** y @@ -57,15 +65,20 @@ pub struct GroupPublicKey { pub(crate) sy: BIG, } -pub struct ECPProof { - pub(crate) c: BIG, - pub(crate) s: BIG, +pub(crate) struct ECPProof { + pub c: BIG, + pub s: BIG, } +/// Wrapper for a big number. pub struct CredentialBIG(pub(crate) BIG); +/// A result of starting the "join" process to acquire credentials. pub struct StartJoinResult { + /// Private key which should be persisted for finishing the "join" + /// process and future signing requests. pub gsk: CredentialBIG, + /// The join request to be sent to the issuer. pub join_msg: JoinRequest, } diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/join.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs similarity index 90% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs index b0a5767be942..ac9a3bfb5ad5 100644 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/lib.rs +++ b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs @@ -1,3 +1,8 @@ +//! Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. +//! Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). +//! +//! bn254 is the only supported curve for this library. + mod data; mod join; mod sign; @@ -37,18 +42,22 @@ pub enum CredentialError { pub type Result = std::result::Result; +/// Creates and manages Direct Anonymous Attestation credentials +/// using the bn254 curve. pub struct CredentialManager { rng: RAND, gsk_and_credentials: Option<(CredentialBIG, UserCredentials)>, } impl CredentialManager { + /// Creates new manager with random seed. pub fn new() -> Self { let mut entropy = [0u8; 128]; OsRng::default().fill_bytes(&mut entropy); Self::new_with_seed(&entropy) } + /// Creates new manager with fixed seed. Should only be used for testing. pub fn new_with_seed(entropy: &[u8]) -> Self { let mut rng = RAND::new(); @@ -60,10 +69,14 @@ impl CredentialManager { } } + /// Creates a "join" requests to be sent to the credential issuer, + /// for a given challenge. pub fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { start_join(&mut self.rng, challenge) } + /// Processes a "join" response from the issuer, and returns anonymous + /// credentials. pub fn finish_join( &mut self, public_key: &GroupPublicKey, @@ -73,10 +86,13 @@ impl CredentialManager { finish_join(public_key, gsk, join_resp) } + /// Sets the key and credentials to be used for signing requests. pub fn set_gsk_and_credentials(&mut self, gsk: CredentialBIG, credentials: UserCredentials) { self.gsk_and_credentials = Some((gsk, credentials)); } + /// Signs a message using the pre-set credentials and a given basename. + /// Returns a signature to be sent to the verifier. pub fn sign(&mut self, msg: &[u8], basename: &[u8]) -> Result { match &self.gsk_and_credentials { Some((gsk, credentials)) => Ok(sign(&mut self.rng, gsk, credentials, msg, basename)), diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/sign.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.3/src/util.rs rename to third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json deleted file mode 100644 index 697c9ce2fbb4..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{}} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json deleted file mode 100644 index a2ca3d221cd8..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "4294e2675ef3016ec941d2011b93226832fb8431" - }, - "path_in_vcs": "" -} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore deleted file mode 100644 index 96ef6c0b944e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Cargo.lock diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules deleted file mode 100644 index 987edd9563d6..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "miracl-core"] - path = miracl-core - url = https://github.com/miracl/core diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml deleted file mode 100644 index f891260784f5..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -name = "brave-miracl" -version = "0.1.2" -authors = ["Mike Scott "] -exclude = [ - "/miracl-core", - "generate.sh", - "renovate.json", -] -description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" -homepage = "https://github.com/miracl/core" -readme = "README.md" -keywords = ["bn254"] -categories = ["cryptography"] -license = "Apache-2.0" -repository = "https://github.com/brave-experiments/miracl-rs" - -[dependencies] - -[features] -default = ["std"] -std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig deleted file mode 100644 index 92fbebeec901..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/Cargo.toml.orig +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "brave-miracl" -version = "0.1.2" -edition = "2021" -authors = ["Mike Scott "] -description = "Subset of the MIRACL Core library that includes the bn254 elliptic curve" -license = "Apache-2.0" -homepage = "https://github.com/miracl/core" -repository = "https://github.com/brave-experiments/miracl-rs" -keywords = ["bn254"] -categories = ["cryptography"] -exclude = ["/miracl-core", "generate.sh", "renovate.json"] - -[dependencies] - -[features] -default = ["std"] -std = [] diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE deleted file mode 100644 index 3c8565d62f17..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2024 Miracl Technologies Ltd - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md deleted file mode 100644 index 67423ec88b3f..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# brave-miracl - -[![Crates.io](https://img.shields.io/crates/v/brave-miracl?style=for-the-badge)](https://crates.io/crates/brave-miracl) - -A subset of the [MIRACL Core](https://github.com/miracl/core) library that includes the bn254 elliptic curve. - -## Updating the library code - -MIRACL Core is embedded in this repository as a git submodule. - -The library code can be updated and regenerated by executing `./generate.sh`. - -## License - -MIRACL Core is licensed under the [Apache 2.0 License](LICENSE). diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs deleted file mode 100644 index 65b0fa41d320..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/aes.rs +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -pub const ECB: usize = 0; -pub const CBC: usize = 1; -pub const CFB1: usize = 2; -pub const CFB2: usize = 3; -pub const CFB4: usize = 5; -pub const OFB1: usize = 14; -pub const OFB2: usize = 15; -pub const OFB4: usize = 17; -pub const OFB8: usize = 21; -pub const OFB16: usize = 29; -pub const CTR1: usize = 30; -pub const CTR2: usize = 31; -pub const CTR4: usize = 33; -pub const CTR8: usize = 37; -pub const CTR16: usize = 45; - -const INCO: [u8; 4] = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */ - -const PTAB: [u8; 256] = [ - 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, - 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, - 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, - 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, - 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, - 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, - 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, - 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, - 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, - 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, - 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, - 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, - 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, -]; - -const LTAB: [u8; 256] = [ - 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, - 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, - 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, - 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, - 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, - 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, - 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, - 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, - 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, - 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, - 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, - 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, - 24, 13, 99, 140, 128, 192, 247, 112, 7, -]; - -const FBSUB: [u8; 256] = [ - 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, - 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, - 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, - 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, - 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, - 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, - 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, - 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, - 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, - 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, - 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, - 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, - 153, 45, 15, 176, 84, 187, 22, -]; - -const RBSUB: [u8; 256] = [ - 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, - 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, - 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, - 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, - 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, - 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, - 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, - 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, - 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, - 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, - 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, - 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, - 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, -]; - -const RCO: [u8; 16] = [ - 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, -]; - -const FTABLE: [u32; 256] = [ - 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, - 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, - 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, - 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, - 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, - 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, - 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, - 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, - 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, - 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, - 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, - 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, - 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, - 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, - 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, - 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, - 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, - 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, - 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, - 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, - 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, - 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, - 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, - 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, - 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, - 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, - 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, - 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, - 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, - 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, - 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, - 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, -]; - -const RTABLE: [u32; 256] = [ - 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, - 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, - 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, - 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, - 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, - 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, - 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, - 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, - 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, - 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, - 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, - 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, - 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, - 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, - 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, - 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, - 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, - 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, - 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, - 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, - 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, - 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, - 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, - 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, - 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, - 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, - 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, - 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, - 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, - 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, - 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, - 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, -]; - -pub struct AES { -// nk: usize, - nr: usize, - mode: usize, - fkey: [u32; 60], - rkey: [u32; 60], - pub f: [u8; 16], -} - - -fn rotl8(x: u32) -> u32 { - ((x) << 8) | ((x) >> 24) -} - -fn rotl16(x: u32) -> u32 { - ((x) << 16) | ((x) >> 16) -} - -fn rotl24(x: u32) -> u32 { - ((x) << 24) | ((x) >> 8) -} - -fn pack(b: [u8; 4]) -> u32 { - /* pack bytes into a 32-bit Word */ - ((b[3] as u32) << 24) - | ((b[2] as u32) << 16) - | ((b[1] as u32) << 8) - | (b[0] as u32) -} - -fn unpack(a: u32) -> [u8; 4] { - /* unpack bytes from a word */ - [ - (a & 0xff) as u8, - ((a >> 8) & 0xff) as u8, - ((a >> 16) & 0xff) as u8, - ((a >> 24) & 0xff) as u8, - ] -} - -fn bmul(x: u8, y: u8) -> u8 { - /* x.y= AntiLog(Log(x) + Log(y)) */ - let ix = (x as usize) & 0xff; - let iy = (y as usize) & 0xff; - let lx = (LTAB[ix] as usize) & 0xff; - let ly = (LTAB[iy] as usize) & 0xff; - - if x != 0 && y != 0 { - PTAB[(lx + ly) % 255] - } else { - 0 - } -} - -fn subbyte(a: u32) -> u32 { - let mut b = unpack(a); - b[0] = FBSUB[b[0] as usize]; - b[1] = FBSUB[b[1] as usize]; - b[2] = FBSUB[b[2] as usize]; - b[3] = FBSUB[b[3] as usize]; - pack(b) -} - -fn product(x: u32, y: u32) -> u8 { - /* dot product of two 4-byte arrays */ - let xb = unpack(x); - let yb = unpack(y); - - bmul(xb[0], yb[0]) - ^ bmul(xb[1], yb[1]) - ^ bmul(xb[2], yb[2]) - ^ bmul(xb[3], yb[3]) -} - -fn invmixcol(x: u32) -> u32 { - /* matrix Multiplication */ - let mut b: [u8; 4] = [0; 4]; - let mut m = pack(INCO); - b[3] = product(m, x); - m = rotl24(m); - b[2] = product(m, x); - m = rotl24(m); - b[1] = product(m, x); - m = rotl24(m); - b[0] = product(m, x); - pack(b) -} - -fn increment(f: &mut [u8; 16]) { - for i in 0..16 { - f[i] += 1; - if f[i] != 0 { - break; - } - } -} - -impl AES { - - pub fn new() -> AES { - AES { -// nk: 0, - nr: 0, - mode: 0, - fkey: [0; 60], - rkey: [0; 60], - f: [0; 16], - } - } - - /* reset cipher */ - pub fn reset(&mut self, m: usize, iv: Option<[u8; 16]>) { - /* reset mode, or reset iv */ - self.mode = m; - for i in 0..16 { - self.f[i] = 0 - } - if self.mode != ECB { - if let Some(x) = iv { - for i in 0..16 { - self.f[i] = x[i] - } - } - } - } - - pub fn init(&mut self, m: usize, nkey: usize, key: &[u8], iv: Option<[u8; 16]>) -> bool { - /* Key Scheduler. Create expanded encryption key */ - let mut cipherkey: [u32; 8] = [0; 8]; - let mut b: [u8; 4] = [0; 4]; - let nk = nkey / 4; - if nk != 4 && nk != 6 && nk != 8 { - return false; - } - let nr = 6 + nk; - //self.nk = nk; - self.nr = nr; - self.reset(m, iv); - let n = 4 * (nr + 1); - - let mut j = 0; - for i in 0..nk { - for k in 0..4 { - b[k] = key[j + k] - } - cipherkey[i] = pack(b); - j += 4; - } - - for i in 0..nk { - self.fkey[i] = cipherkey[i] - } - - j = nk; - let mut k = 0; - while j < n { - self.fkey[j] = - self.fkey[j - nk] ^ subbyte(rotl24(self.fkey[j - 1])) ^ (RCO[k] as u32); - if nk<=6 { - for i in 1..nk { - if (i + j) >= n { - break; - } - self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; - } - } else { - for i in 1..4 { - if (i + j) >= n { - break; - } - self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; - } - - if (j + 4) < n { - self.fkey[j + 4] = self.fkey[j + 4 - nk] ^ subbyte(self.fkey[j + 3]); - } - for i in 5..nk { - if (i + j) >= n { - break; - } - self.fkey[i + j] = self.fkey[i + j - nk] ^ self.fkey[i + j - 1]; - } - } - j += nk; - k += 1; - } - - /* now for the expanded decrypt key in reverse order */ - - for j in 0..4 { - self.rkey[j + n - 4] = self.fkey[j] - } - let mut i = 4; - while i < n - 4 { - let k = n - 4 - i; - for j in 0..4 { - self.rkey[k + j] = invmixcol(self.fkey[i + j]) - } - i += 4; - } - for j in n - 4..n { - self.rkey[j + 4 - n] = self.fkey[j] - } - true - } - - pub fn getreg(&mut self) -> [u8; 16] { - let mut ir: [u8; 16] = [0; 16]; - for i in 0..16 { - ir[i] = self.f[i] - } - ir - } - - /* Encrypt a single block */ - pub fn ecb_encrypt(&mut self, buff: &mut [u8; 16]) { - let mut b: [u8; 4] = [0; 4]; - let mut p: [u32; 4] = [0; 4]; - let mut q: [u32; 4] = [0; 4]; - - let mut j = 0; - for i in 0..4 { - for k in 0..4 { - b[k] = buff[j + k] - } - p[i] = pack(b); - p[i] ^= self.fkey[i]; - j += 4; - } - - let mut k = 4; - - /* State alternates between p and q */ - for _ in 1..self.nr { - q[0] = self.fkey[k] - ^ FTABLE[(p[0] & 0xff) as usize] - ^ rotl8(FTABLE[((p[1] >> 8) & 0xff) as usize]) - ^ rotl16(FTABLE[((p[2] >> 16) & 0xff) as usize]) - ^ rotl24(FTABLE[((p[3] >> 24) & 0xff) as usize]); - - q[1] = self.fkey[k + 1] - ^ FTABLE[(p[1] & 0xff) as usize] - ^ rotl8(FTABLE[((p[2] >> 8) & 0xff) as usize]) - ^ rotl16(FTABLE[((p[3] >> 16) & 0xff) as usize]) - ^ rotl24(FTABLE[((p[0] >> 24) & 0xff) as usize]); - - q[2] = self.fkey[k + 2] - ^ FTABLE[(p[2] & 0xff) as usize] - ^ rotl8(FTABLE[((p[3] >> 8) & 0xff) as usize]) - ^ rotl16(FTABLE[((p[0] >> 16) & 0xff) as usize]) - ^ rotl24(FTABLE[((p[1] >> 24) & 0xff) as usize]); - - q[3] = self.fkey[k + 3] - ^ FTABLE[(p[3] & 0xff) as usize] - ^ rotl8(FTABLE[((p[0] >> 8) & 0xff) as usize]) - ^ rotl16(FTABLE[((p[1] >> 16) & 0xff) as usize]) - ^ rotl24(FTABLE[((p[2] >> 24) & 0xff) as usize]); - - k += 4; - for j in 0..4 { - let t = p[j]; - p[j] = q[j]; - q[j] = t; - } - } - - /* Last Round */ - - q[0] = self.fkey[k] - ^ (FBSUB[(p[0] & 0xff) as usize] as u32) - ^ rotl8((FBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((FBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((FBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); - - q[1] = self.fkey[k + 1] - ^ (FBSUB[(p[1] & 0xff) as usize] as u32) - ^ rotl8((FBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((FBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((FBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); - - q[2] = self.fkey[k + 2] - ^ (FBSUB[(p[2] & 0xff) as usize] as u32) - ^ rotl8((FBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((FBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((FBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); - - q[3] = self.fkey[k + 3] - ^ (FBSUB[(p[3] & 0xff) as usize] as u32) - ^ rotl8((FBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((FBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((FBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); - - j = 0; - for i in 0..4 { - b = unpack(q[i]); - for k in 0..4 { - buff[j + k] = b[k] - } - j += 4; - } - } - - /* Decrypt a single block */ - pub fn ecb_decrypt(&mut self, buff: &mut [u8; 16]) { - let mut b: [u8; 4] = [0; 4]; - let mut p: [u32; 4] = [0; 4]; - let mut q: [u32; 4] = [0; 4]; - - let mut j = 0; - for i in 0..4 { - for k in 0..4 { - b[k] = buff[j + k] - } - p[i] = pack(b); - p[i] ^= self.rkey[i]; - j += 4; - } - - let mut k = 4; - - /* State alternates between p and q */ - for _ in 1..self.nr { - q[0] = self.rkey[k] - ^ RTABLE[(p[0] & 0xff) as usize] - ^ rotl8(RTABLE[((p[3] >> 8) & 0xff) as usize]) - ^ rotl16(RTABLE[((p[2] >> 16) & 0xff) as usize]) - ^ rotl24(RTABLE[((p[1] >> 24) & 0xff) as usize]); - - q[1] = self.rkey[k + 1] - ^ RTABLE[(p[1] & 0xff) as usize] - ^ rotl8(RTABLE[((p[0] >> 8) & 0xff) as usize]) - ^ rotl16(RTABLE[((p[3] >> 16) & 0xff) as usize]) - ^ rotl24(RTABLE[((p[2] >> 24) & 0xff) as usize]); - - q[2] = self.rkey[k + 2] - ^ RTABLE[(p[2] & 0xff) as usize] - ^ rotl8(RTABLE[((p[1] >> 8) & 0xff) as usize]) - ^ rotl16(RTABLE[((p[0] >> 16) & 0xff) as usize]) - ^ rotl24(RTABLE[((p[3] >> 24) & 0xff) as usize]); - - q[3] = self.rkey[k + 3] - ^ RTABLE[(p[3] & 0xff) as usize] - ^ rotl8(RTABLE[((p[2] >> 8) & 0xff) as usize]) - ^ rotl16(RTABLE[((p[1] >> 16) & 0xff) as usize]) - ^ rotl24(RTABLE[((p[0] >> 24) & 0xff) as usize]); - - k += 4; - for j in 0..4 { - let t = p[j]; - p[j] = q[j]; - q[j] = t; - } - } - - /* Last Round */ - - q[0] = self.rkey[k] - ^ (RBSUB[(p[0] & 0xff) as usize] as u32) - ^ rotl8((RBSUB[((p[3] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((RBSUB[((p[2] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((RBSUB[((p[1] >> 24) & 0xff) as usize]) as u32); - - q[1] = self.rkey[k + 1] - ^ (RBSUB[(p[1] & 0xff) as usize] as u32) - ^ rotl8((RBSUB[((p[0] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((RBSUB[((p[3] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((RBSUB[((p[2] >> 24) & 0xff) as usize]) as u32); - - q[2] = self.rkey[k + 2] - ^ (RBSUB[(p[2] & 0xff) as usize] as u32) - ^ rotl8((RBSUB[((p[1] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((RBSUB[((p[0] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((RBSUB[((p[3] >> 24) & 0xff) as usize]) as u32); - - q[3] = self.rkey[k + 3] - ^ (RBSUB[((p[3]) & 0xff) as usize] as u32) - ^ rotl8((RBSUB[((p[2] >> 8) & 0xff) as usize]) as u32) - ^ rotl16((RBSUB[((p[1] >> 16) & 0xff) as usize]) as u32) - ^ rotl24((RBSUB[((p[0] >> 24) & 0xff) as usize]) as u32); - - j = 0; - for i in 0..4 { - b = unpack(q[i]); - for k in 0..4 { - buff[j + k] = b[k] - } - j += 4; - } - } - - /* Encrypt using selected mode of operation */ - pub fn encrypt(&mut self, buff: &mut [u8; 16]) -> u32 { - let mut st: [u8; 16] = [0; 16]; - - // Supported Modes of Operation - - let mut fell_off: u32 = 0; - - match self.mode { - ECB => { - self.ecb_encrypt(buff); - 0 - } - CBC => { - for j in 0..16 { - buff[j] ^= self.f[j] - } - self.ecb_encrypt(buff); - for j in 0..16 { - self.f[j] = buff[j] - } - 0 - } - - CFB1 | CFB2 | CFB4 => { - let bytes = self.mode - CFB1 + 1; - for j in 0..bytes { - fell_off = (fell_off << 8) | (self.f[j] as u32) - } - for j in 0..16 { - st[j] = self.f[j] - } - for j in bytes..16 { - self.f[j - bytes] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - buff[j] ^= st[j]; - self.f[16 - bytes + j] = buff[j]; - } - fell_off - } - - OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { - let bytes = self.mode - OFB1 + 1; - for j in 0..16 { - st[j] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - buff[j] ^= st[j] - } - for j in 0..16 { - self.f[j] = st[j] - } - - //self.ecb_encrypt(&mut (self.f)); - //for j in 0..bytes {buff[j]^=self.f[j]} - 0 - } - - CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { - let bytes = self.mode - CTR1 + 1; - for j in 0..16 { - st[j] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - buff[j] ^= st[j] - } - increment(&mut (self.f)); - 0 - } - - _ => { - 0 - } - } - } - - /* Decrypt using selected mode of operation */ - pub fn decrypt(&mut self, buff: &mut [u8; 16]) -> u32 { - let mut st: [u8; 16] = [0; 16]; - - // Supported Modes of Operation - - let mut fell_off: u32 = 0; - - match self.mode { - ECB => { - self.ecb_decrypt(buff); - 0 - } - CBC => { - for j in 0..16 { - st[j] = self.f[j]; - self.f[j] = buff[j]; - } - self.ecb_decrypt(buff); - for j in 0..16 { - buff[j] ^= st[j]; - st[j] = 0; - } - 0 - } - CFB1 | CFB2 | CFB4 => { - let bytes = self.mode - CFB1 + 1; - for j in 0..bytes { - fell_off = (fell_off << 8) | (self.f[j] as u32) - } - for j in 0..16 { - st[j] = self.f[j] - } - for j in bytes..16 { - self.f[j - bytes] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - self.f[16 - bytes + j] = buff[j]; - buff[j] ^= st[j]; - } - fell_off - } - OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { - let bytes = self.mode - OFB1 + 1; - for j in 0..16 { - st[j] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - buff[j] ^= st[j] - } - for j in 0..16 { - self.f[j] = st[j] - } - // self.ecb_encrypt(A.f[:]); - // for j in 0..bytes {buff[j]^=self.f[j]} - 0 - } - - CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { - let bytes = self.mode - CTR1 + 1; - for j in 0..16 { - st[j] = self.f[j] - } - self.ecb_encrypt(&mut st); - for j in 0..bytes { - buff[j] ^= st[j] - } - increment(&mut (self.f)); - 0 - } - - _ => { - 0 - } - } - } - - /* Clean up and delete left-overs */ - pub fn end(&mut self) { - // clean up - for i in 0..4 * (self.nr + 1) { - self.fkey[i] = 0; - self.rkey[i] = 0 - } - for i in 0..16 { - self.f[i] = 0 - } - } -} - -/* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */ -pub fn cbc_iv0_encrypt(k: &[u8], m: &[u8],c: &mut [u8]) -> usize { - /* AES CBC encryption, with Null IV and key K */ - /* Input is from an octet string m, output is to an octet string c */ - /* Input is padded as necessary to make up a full final block */ - let mut a = AES::new(); - let mut fin = false; - - let mut buff: [u8; 16] = [0; 16]; - - a.init(CBC, k.len(), k, None); - - let mut ipt = 0; - let mut opt = 0; - let mut i; - loop { - i = 0; - while i < 16 { - if ipt < m.len() { - buff[i] = m[ipt]; - i += 1; - ipt += 1; - } else { - fin = true; - break; - } - } - if fin { - break; - } - a.encrypt(&mut buff); - for j in 0..16 { - if opt < c.len() { - c[opt]=buff[j]; opt+=1; - } - } - } - - /* last block, filled up to i-th index */ - - let padlen = 16 - i; - for j in i..16 { - buff[j] = padlen as u8 - } - - a.encrypt(&mut buff); - - for j in 0..16 { - if opt usize { - /* padding is removed */ - let mut a = AES::new(); - let mut fin = false; - - let mut buff: [u8; 16] = [0; 16]; - - a.init(CBC, k.len(), k, None); - - let mut ipt = 0; - let mut opt = 0; - let mut i; - - if c.is_empty() { - return 0; - } - let mut ch = c[ipt]; - ipt += 1; - - loop { - i = 0; - while i < 16 { - buff[i] = ch; - if ipt >= c.len() { - fin = true; - break; - } else { - ch = c[ipt]; - ipt += 1 - } - i += 1; - } - a.decrypt(&mut buff); - if fin { - break; - } - for j in 0..16 { - if opt 16 { - bad = true - } - if padlen >= 2 && padlen <= 16 { - for j in 16 - padlen..16 { - if buff[j] != padlen as u8 { - bad = true - } - } - } - - if !bad { - for i in 0..16 - padlen { - if opt BIG { - *self - } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for BIG { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for BIG { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -impl BIG { - pub const fn new() -> BIG { - BIG { w: [0; NLEN] } - } - - pub fn new_int(x: isize) -> BIG { - let mut s = BIG::new(); - s.w[0] = x as Chunk; - s - } - - pub fn new_ints(a: &[Chunk]) -> BIG { - let mut s = BIG::new(); - for i in 0..NLEN { - s.w[i] = a[i] - } - s - } - - pub fn new_copy(y: &BIG) -> BIG { - let mut s = BIG::new(); - for i in 0..NLEN { - s.w[i] = y.w[i] - } - s - } - - pub fn new_big(y: &BIG) -> BIG { - let mut s = BIG::new(); - for i in 0..NLEN { - s.w[i] = y.w[i] - } - s - } - - pub fn new_dcopy(y: &DBIG) -> BIG { - let mut s = BIG::new(); - for i in 0..NLEN { - s.w[i] = y.w[i] - } - s - } - - pub fn get(&self, i: usize) -> Chunk { - self.w[i] - } - - pub fn set(&mut self, i: usize, x: Chunk) { - self.w[i] = x; - } - - pub fn xortop(&mut self, x: Chunk) { - self.w[NLEN - 1] ^= x; - } - - pub fn ortop(&mut self, x: Chunk) { - self.w[NLEN - 1] |= x; - } - - /* test for zero */ - pub fn iszilch(&self) -> bool { - let mut d = 0 as Chunk; - for i in 0..NLEN { - d |= self.w[i]; - } - (1 & ((d-1)>>BASEBITS)) != 0 - } - - /* set to zero */ - pub fn zero(&mut self) { - for i in 0..NLEN { - self.w[i] = 0 - } - } - - /* Test for equal to one */ - pub fn isunity(&self) -> bool { - let mut d = 0 as Chunk; - for i in 1..NLEN { - d |= self.w[i]; - } - (1 & ((d-1)>>BASEBITS) & (((self.w[0]^1)-1)>>BASEBITS)) != 0 - } - - /* set to one */ - pub fn one(&mut self) { - self.w[0] = 1; - for i in 1..NLEN { - self.w[i] = 0; - } - } - - /* Copy from another BIG */ - pub fn copy(&mut self, x: &BIG) { - for i in 0..NLEN { - self.w[i] = x.w[i] - } - } - - pub fn dcopy(&mut self, x: &DBIG) { - for i in 0..NLEN { - self.w[i] = x.w[i] - } - } - - /* Get top and bottom half of =x*y+c+r */ - pub fn muladd(a: Chunk, b: Chunk, c: Chunk, r: Chunk) -> (Chunk, Chunk) { - let prod: DChunk = (a as DChunk) * (b as DChunk) + (c as DChunk) + (r as DChunk); - let bot = (prod & (BMASK as DChunk)) as Chunk; - let top = (prod >> BASEBITS) as Chunk; - (top, bot) - } - - /* normalise BIG - force all digits < 2^BASEBITS */ - pub fn norm(&mut self) -> Chunk { - let mut carry = self.w[0]>>BASEBITS; - self.w[0] &= BMASK; - for i in 1..NLEN - 1 { - let d = self.w[i] + carry; - self.w[i] = d & BMASK; - carry = d >> BASEBITS; - } - self.w[NLEN - 1] += carry; - (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as Chunk - } - - /* Conditional swap of two bigs depending on d using XOR - no branches */ - pub fn cswap(&mut self, b: &mut BIG, d: isize) -> Chunk { - let c = -d as Chunk; - let mut w=0 as Chunk; - let r=self.w[0]^b.w[1]; - let mut ra=r.wrapping_add(r); ra >>= 1; - for i in 0..NLEN { - let mut t = c & (self.w[i] ^ b.w[i]); - t^=r; - let mut e=self.w[i]^t; w^=e; - self.w[i]=e^ra; - e=b.w[i]^t; w^=e; - b.w[i]=e^ra; - } - return w; - } - - pub fn cmove(&mut self, g: &BIG, d: isize) -> Chunk { - let b = -d as Chunk; - let mut w=0 as Chunk; - let r=self.w[0]^g.w[1]; - let mut ra=r.wrapping_add(r); ra >>= 1; - for i in 0..NLEN { - let mut t = b & (self.w[i] ^ g.w[i]); - t^=r; - let e=self.w[i]^t; w^=e; - self.w[i]=e^ra; - } - return w; - } - - /* Shift right by less than a word */ - pub fn fshr(&mut self, k: usize) -> isize { - let n = k; - let w = self.w[0] & ((1 << n) - 1); /* shifted out part */ - for i in 0..NLEN - 1 { - self.w[i] = (self.w[i] >> k) | ((self.w[i + 1] << (BASEBITS - n)) & BMASK); - } - self.w[NLEN - 1] >>= k; - w as isize - } - - /* general shift right */ - pub fn shr(&mut self, k: usize) { - let n = k % BASEBITS; - let m = k / BASEBITS; - for i in 0..NLEN - m - 1 { - self.w[i] = (self.w[m + i] >> n) | ((self.w[m + i + 1] << (BASEBITS - n)) & BMASK) - } - self.w[NLEN - m - 1] = self.w[NLEN - 1] >> n; - for i in NLEN - m..NLEN { - self.w[i] = 0 - } - } - - /* Shift right by less than a word */ - pub fn fshl(&mut self, k: usize) -> isize { - let n = k; - self.w[NLEN - 1] = (self.w[NLEN - 1] << n) | (self.w[NLEN - 2] >> (BASEBITS - n)); - for i in (1..NLEN - 1).rev() { - self.w[i] = ((self.w[i] << k) & BMASK) | (self.w[i - 1] >> (BASEBITS - n)); - } - self.w[0] = (self.w[0] << n) & BMASK; - (self.w[NLEN - 1] >> ((8 * MODBYTES) % BASEBITS)) as isize /* return excess - only used in ff.c */ - } - - /* general shift left */ - pub fn shl(&mut self, k: usize) { - let n = k % BASEBITS; - let m = k / BASEBITS; - - self.w[NLEN - 1] = self.w[NLEN - 1 - m] << n; - if NLEN >= m + 2 { - self.w[NLEN - 1] |= self.w[NLEN - m - 2] >> (BASEBITS - n) - } - for i in (m + 1..NLEN - 1).rev() { - self.w[i] = ((self.w[i - m] << n) & BMASK) | (self.w[i - m - 1] >> (BASEBITS - n)); - } - self.w[m] = (self.w[0] << n) & BMASK; - for i in 0..m { - self.w[i] = 0 - } - } - - /* return number of bits */ - pub fn nbits(&self) -> usize { - let mut k = NLEN - 1; - let mut s = BIG::new_copy(&self); - s.norm(); - while (k as isize) >= 0 && s.w[k] == 0 { - k = k.wrapping_sub(1) - } - if (k as isize) < 0 { - return 0; - } - let mut bts = BASEBITS * k; - let mut c = s.w[k]; - while c != 0 { - c /= 2; - bts += 1; - } - bts - } - - /* Convert to Hex String */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - let mut s = String::new(); - let mut len = self.nbits(); - - if len % 4 == 0 { - len /= 4; - } else { - len /= 4; - len += 1; - } - let mb = (MODBYTES * 2) as usize; - if len < mb { - len = mb - } - - for i in (0..len).rev() { - let mut b = BIG::new_copy(&self); - b.shr(i * 4); - s = s + &format!("{:X}", b.w[0] & 15); - } - s - } - - #[cfg(feature = "std")] - pub fn fromstring(val: String) -> BIG { - let mut res = BIG::new(); - let len = val.len(); - let op = &val[0..1]; - let n = u8::from_str_radix(op, 16).unwrap(); - res.w[0] += n as Chunk; - for i in 1..len { - res.shl(4); - let op = &val[i..i+1]; - let n = u8::from_str_radix(op, 16).unwrap(); - res.w[0] += n as Chunk; - } - res - } - - pub fn add(&mut self, r: &BIG) { - for i in 0..NLEN { - self.w[i] += r.w[i] - } - } - - pub fn or(&mut self, r: &BIG) { - for i in 0..NLEN { - self.w[i] |= r.w[i] - } - } - - pub fn dbl(&mut self) { - for i in 0..NLEN { - self.w[i] += self.w[i] - } - } - - /* return this+x */ - pub fn plus(&self, x: &BIG) -> BIG { - let mut s = BIG::new(); - for i in 0..NLEN { - s.w[i] = self.w[i] + x.w[i]; - } - s.norm(); - s - } - - pub fn inc(&mut self, x: isize) { - self.norm(); - self.w[0] += x as Chunk; - } - - /* return self-x */ - pub fn minus(&self, x: &BIG) -> BIG { - let mut d = BIG::new(); - for i in 0..NLEN { - d.w[i] = self.w[i] - x.w[i]; - } - d - } - - /* self-=x */ - pub fn sub(&mut self, x: &BIG) { - for i in 0..NLEN { - self.w[i] -= x.w[i]; - } - } - - /* reverse subtract this=x-this */ - - pub fn rsub(&mut self, x: &BIG) { - for i in 0..NLEN { - self.w[i] = x.w[i] - self.w[i] - } - } - - /* self-=x, where x is int */ - pub fn dec(&mut self, x: isize) { - self.norm(); - self.w[0] -= x as Chunk; - } - - /* self*=x, where x is small int BIG { - let mut m = BIG::new(); - for i in 0..(MODBYTES as usize) { - m.fshl(8); - m.w[0] += b[i + n] as Chunk; - } - m - } - - pub fn tobytes(&self, b: &mut [u8]) { - self.tobytearray(b, 0) - } - - pub fn frombytes(b: &[u8]) -> BIG { - BIG::frombytearray(b, 0) - } - - /* self*=x, where x is >NEXCESS */ - pub fn pmul(&mut self, c: isize) -> Chunk { - let mut carry = 0 as Chunk; - for i in 0..NLEN { - let ak = self.w[i]; - let tuple = BIG::muladd(ak, c as Chunk, carry, 0 as Chunk); - carry = tuple.0; - self.w[i] = tuple.1; - } - carry - } - - /* self*=c and catch overflow in DBIG */ - pub fn pxmul(&mut self, c: isize) -> DBIG { - let mut m = DBIG::new(); - let mut carry = 0 as Chunk; - for j in 0..NLEN { - let tuple = BIG::muladd(self.w[j], c as Chunk, carry, m.w[j]); - carry = tuple.0; - m.w[j] = tuple.1; - } - m.w[NLEN] = carry; - m - } - - /* divide by 3 */ - pub fn div3(&mut self) -> Chunk { - let mut carry = 0 as Chunk; - self.norm(); - let base = 1 << BASEBITS; - for i in (0..NLEN).rev() { - let ak = carry * base + self.w[i]; - self.w[i] = ak / 3; - carry = ak % 3; - } - carry - } - - /* return a*b where result fits in a BIG */ - pub fn smul(a: &BIG, b: &BIG) -> BIG { - let mut c = BIG::new(); - for i in 0..NLEN { - let mut carry = 0 as Chunk; - for j in 0..NLEN { - if i + j < NLEN { - let tuple = BIG::muladd(a.w[i], b.w[j], carry, c.w[i + j]); - carry = tuple.0; - c.w[i + j] = tuple.1; - } - } - } - c - } - - /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ - pub fn comp(a: &BIG, b: &BIG) -> isize { - let mut gt = 0 as Chunk; - let mut eq = 1 as Chunk; - for i in (0..NLEN).rev() { - gt |= ((b.w[i]-a.w[i]) >> BASEBITS) & eq; - eq &= ((b.w[i]^a.w[i])-1) >> BASEBITS; - } - (gt+gt+eq-1) as isize - } - - /* set x = x mod 2^m */ - pub fn mod2m(&mut self, m: usize) { - let wd = m / BASEBITS; - let bt = m % BASEBITS; - let msk = (1 << bt) - 1; - self.w[wd] &= msk; - for i in wd + 1..NLEN { - self.w[i] = 0 - } - } - - /* Arazi and Qi inversion mod 256 */ - pub fn invmod256(a: isize) -> isize { - let mut t1: isize = 0; - let mut c = (a >> 1) & 1; - t1 += c; - t1 &= 1; - t1 = 2 - t1; - t1 <<= 1; - let mut u = t1 + 1; - - // i=2 - let mut b = a & 3; - t1 = u * b; - t1 >>= 2; - c = (a >> 2) & 3; - let mut t2 = (u * c) & 3; - t1 += t2; - t1 *= u; - t1 &= 3; - t1 = 4 - t1; - t1 <<= 2; - u += t1; - - // i=4 - b = a & 15; - t1 = u * b; - t1 >>= 4; - c = (a >> 4) & 15; - t2 = (u * c) & 15; - t1 += t2; - t1 *= u; - t1 &= 15; - t1 = 16 - t1; - t1 <<= 4; - u += t1; - - u - } - - /* return parity */ - pub fn parity(&self) -> isize { - (self.w[0] % 2) as isize - } - - /* return n-th bit */ - pub fn bit(&self, n: usize) -> isize { - return ((self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) >> (n%BASEBITS)) as isize; - - - // if (self.w[n / (BASEBITS as usize)] & (1 << (n % BASEBITS))) > 0 { -// 1 -// } else { -// 0 -// } - } - - /* return n last bits */ - pub fn lastbits(&mut self, n: usize) -> isize { - let msk = ((1 << n) - 1) as Chunk; - self.norm(); - (self.w[0] & msk) as isize - } - - /* a=1/a mod 2^256. This is very fast! */ - pub fn invmod2m(&mut self) { - let mut u = BIG::new(); - let mut b = BIG::new(); - let mut c = BIG::new(); - - u.inc(BIG::invmod256(self.lastbits(8))); - - let mut i = 8; - while i < BIGBITS { - u.norm(); - b.copy(self); - b.mod2m(i); - let mut t1 = BIG::smul(&u, &b); - t1.shr(i); - c.copy(self); - c.shr(i); - c.mod2m(i); - - let mut t2 = BIG::smul(&u, &c); - t2.mod2m(i); - t1.add(&t2); - t1.norm(); - b = BIG::smul(&t1, &u); - t1.copy(&b); - t1.mod2m(i); - - t2.one(); - t2.shl(i); - t1.rsub(&t2); - t1.norm(); - t1.shl(i); - u.add(&t1); - i <<= 1; - } - u.mod2m(BIGBITS); - self.copy(&u); - self.norm(); - } - -// Set self=self mod m in constant time (if bd is known at compile time) -// bd is Max number of bits in b - Actual number of bits in m - pub fn ctmod(&mut self,m:&BIG,bd:usize) { - let mut k=bd; - let mut r=BIG::new(); - let mut c=BIG::new_copy(m); - self.norm(); - - c.shl(k); - loop { - r.copy(self); - r.sub(&c); - r.norm(); - self.cmove(&r,(1 - ((r.w[NLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); - if k==0 {break;} - c.fshr(1); - k -= 1; - } - } - - /* reduce self mod m */ - pub fn rmod(&mut self, m: &BIG) { - let ss=self.nbits() as isize; - let ms=m.nbits() as isize; - let mut k=(ss-ms) as usize; - if ss> (arch::CHUNK - 1)) & 1)) as isize; - a.cmove(&r, d); - r.copy(self); - r.add(&e); - r.norm(); - self.cmove(&r, d); - if k==0 {break;} - k -= 1; - c.fshr(1); - e.fshr(1); - } - } - - /* divide self by m */ - pub fn div(&mut self, m: &BIG) { - let ss=self.nbits() as isize; - let ms=m.nbits() as isize; - let mut k=(ss-ms) as usize; - if ss BIG { - let mut m = BIG::new(); - let mut j = 0; - let mut r: u8 = 0; - /* generate random BIG */ - - for _ in 0..8 * (MODBYTES as usize) { - if j == 0 { - r = rng.getbyte() - } else { - r >>= 1 - } - - let b = (r as Chunk) & 1; - m.shl(1); - m.w[0] += b; - j += 1; - j &= 7; - } - m - } - - /* Create random BIG in portable way, one bit at a time */ - pub fn randomnum(q: &BIG, rng: &mut RAND) -> BIG { - let mut d = DBIG::new(); - let mut j = 0; - let mut r: u8 = 0; - let t = BIG::new_copy(q); - for _ in 0..2 * t.nbits() { - if j == 0 { - r = rng.getbyte(); - } else { - r >>= 1 - } - - let b = (r as Chunk) & 1; - d.shl(1); - d.w[0] += b; - j += 1; - j &= 7; - } - d.dmod(q) - } - -/* create randum BIG less than r and less than trunc bits */ - pub fn randtrunc(q: &BIG, trunc: usize, rng: &mut RAND) -> BIG { - let mut m=BIG::randomnum(q,rng); - if q.nbits() > trunc { - m.mod2m(trunc); - } - m - } - - /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ - pub fn jacobi(&mut self, p: &BIG) -> isize { - let mut m: usize = 0; - let mut t = BIG::new(); - let mut x = BIG::new(); - let mut n = BIG::new(); - let zilch = BIG::new(); - let one = BIG::new_int(1); - if p.parity() == 0 || BIG::comp(self, &zilch) == 0 || BIG::comp(p, &one) <= 0 { - return 0; - } - self.norm(); - - x.copy(self); - n.copy(p); - x.rmod(p); - - while BIG::comp(&n, &one) > 0 { - if BIG::comp(&x, &zilch) == 0 { - return 0; - } - let n8 = n.lastbits(3) as usize; - let mut k = 0; - while x.parity() == 0 { - k += 1; - x.shr(1); - } - if k % 2 == 1 { - m += (n8 * n8 - 1) / 8 - } - m += (n8 - 1) * ((x.lastbits(2) as usize) - 1) / 4; - t.copy(&n); - t.rmod(&x); - n.copy(&x); - x.copy(&t); - m %= 2; - } - if m == 0 { - 1 - } else { - -1 - } - } - -// Set self=1/self mod p. Binary method -// NOTE: This function is NOT side-channel safe -// If a is a secret then ALWAYS calculate 1/a = m*(1/am) mod p -// where m is a random masking value - pub fn invmodp(&mut self, p: &BIG) { - self.rmod(p); - if self.iszilch() {return;} - let mut u = BIG::new_copy(self); - let mut v = BIG::new_copy(p); - let mut x1 = BIG::new_int(1); - let mut x2 = BIG::new(); - let mut t = BIG::new(); - let one = BIG::new_int(1); - - while (BIG::comp(&u, &one) != 0) && (BIG::comp(&v, &one) != 0) { - while u.parity() == 0 { - u.fshr(1); - t.copy(&x1); - t.add(p); - x1.cmove(&t,x1.parity()); - x1.norm(); - x1.fshr(1); - } - while v.parity() == 0 { - v.fshr(1); - t.copy(&x2); - t.add(p); - x2.cmove(&t,x2.parity()); - x2.norm(); - x2.fshr(1); - } - if BIG::comp(&u, &v) >= 0 { - u.sub(&v); - u.norm(); - t.copy(&x1); - t.add(p); - x1.cmove(&t,(BIG::comp(&x1,&x2)>>1)&1); - x1.sub(&x2); - x1.norm(); - } else { - v.sub(&u); - v.norm(); - t.copy(&x2); - t.add(p); - x2.cmove(&t,(BIG::comp(&x2,&x1)>>1)&1); - x2.sub(&x1); - x2.norm(); - } - } - self.copy(&x1); - self.cmove(&x2,BIG::comp(&u,&one)&1); - } - - /* return a*b as DBIG - Simple Karatsuba */ - pub fn mul(a: &BIG, b: &BIG) -> DBIG { - let mut c = DBIG::new(); - let rm = BMASK as DChunk; - let rb = BASEBITS; - - let mut d: [DChunk; DNLEN] = [0; DNLEN]; - for i in 0..NLEN { - d[i] = (a.w[i] as DChunk) * (b.w[i] as DChunk); - } - let mut s = d[0]; - let mut t = s; - c.w[0] = (t & rm) as Chunk; - t >>= rb; - for k in 1..NLEN { - s += d[k]; - t += s; - for i in 1 + k / 2..k + 1 { - t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk) - } - c.w[k] = (t & rm) as Chunk; - t >>= rb; - } - for k in NLEN..2 * NLEN - 1 { - s -= d[k - NLEN]; - t += s; - let mut i = 1 + k / 2; - while i < NLEN { - t += ((a.w[i] - a.w[k - i]) as DChunk) * ((b.w[k - i] - b.w[i]) as DChunk); - i += 1; - } - - c.w[k] = (t & rm) as Chunk; - t >>= rb; - } - c.w[2 * NLEN - 1] = t as Chunk; - c - } - - /* return a^2 as DBIG */ - pub fn sqr(a: &BIG) -> DBIG { - let mut c = DBIG::new(); - let rm = BMASK as DChunk; - let rb = BASEBITS; - - let mut t = (a.w[0] as DChunk) * (a.w[0] as DChunk); - c.w[0] = (t & rm) as Chunk; - let mut co = t >> rb; - - let mut j = 1; - while j < NLEN - 1 { - t = (a.w[j] as DChunk) * (a.w[0] as DChunk); - for i in 1..(j + 1) / 2 { - t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); - } - t += t; - t += co; - c.w[j] = (t & rm) as Chunk; - co = t >> rb; - j += 1; - t = (a.w[j] as DChunk) * (a.w[0] as DChunk); - for i in 1..(j + 1) / 2 { - t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); - } - t += t; - t += co; - t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); - c.w[j] = (t & rm) as Chunk; - co = t >> rb; - j += 1; - } - - j = NLEN + (NLEN % 2) - 1; - while j < DNLEN - 3 { - t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); - for i in j + 2 - NLEN..(j + 1) / 2 { - t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); - } - t += t; - t += co; - c.w[j] = (t & rm) as Chunk; - co = t >> rb; - j += 1; - t = (a.w[NLEN - 1] as DChunk) * (a.w[j + 1 - NLEN] as DChunk); - for i in j + 2 - NLEN..(j + 1) / 2 { - t += (a.w[j - i] as DChunk) * (a.w[i] as DChunk); - } - t += t; - t += co; - t += (a.w[j / 2] as DChunk) * (a.w[j / 2] as DChunk); - c.w[j] = (t & rm) as Chunk; - co = t >> rb; - j += 1; - } - - t = (a.w[NLEN - 2] as DChunk) * (a.w[NLEN - 1] as DChunk); - t += t; - t += co; - c.w[DNLEN - 3] = (t & rm) as Chunk; - co = t >> rb; - - t = (a.w[NLEN - 1] as DChunk) * (a.w[NLEN - 1] as DChunk) + co; - c.w[DNLEN - 2] = (t & rm) as Chunk; - co = t >> rb; - c.w[DNLEN - 1] = co as Chunk; - - c - } - - /* Montgomery reduction */ - pub fn monty(md: &BIG, mc: Chunk, d: &mut DBIG) -> BIG { - let mut b = BIG::new(); - let rm = BMASK as DChunk; - let rb = BASEBITS; - - let mut dd: [DChunk; NLEN] = [0; NLEN]; - let mut v: [Chunk; NLEN] = [0; NLEN]; - - b.zero(); - - let mut t = d.w[0] as DChunk; - v[0] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; - t += (v[0] as DChunk) * (md.w[0] as DChunk); - t = (d.w[1] as DChunk) + (t >> rb); - let mut s: DChunk = 0; - for k in 1..NLEN { - t = t + s + (v[0] as DChunk) * (md.w[k] as DChunk); - let mut i = 1 + k / 2; - while i < k { - t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); - i += 1; - } - v[k] = (((t & rm) as Chunk).wrapping_mul(mc)) & BMASK; - t += (v[k] as DChunk) * (md.w[0] as DChunk); - t = (d.w[k + 1] as DChunk) + (t >> rb); - dd[k] = (v[k] as DChunk) * (md.w[k] as DChunk); - s += dd[k]; - } - - for k in NLEN..2 * NLEN - 1 { - t += s; - let mut i = 1 + k / 2; - while i < NLEN { - t += ((v[k - i] - v[i]) as DChunk) * ((md.w[i] - md.w[k - i]) as DChunk); - i += 1; - } - b.w[k - NLEN] = (t & rm) as Chunk; - t = (d.w[k + 1] as DChunk) + (t >> rb); - s -= dd[k + 1 - NLEN]; - } - b.w[NLEN - 1] = (t & rm) as Chunk; - b - } - - /* Fast combined shift, subtract and norm. Return sign of result */ - pub fn ssn(r: &mut BIG, a: &BIG, m: &mut BIG) -> isize { - let n = NLEN - 1; - m.w[0] = (m.w[0] >> 1) | ((m.w[1] << (BASEBITS - 1)) & BMASK); - r.w[0] = a.w[0] - m.w[0]; - let mut carry = r.w[0] >> BASEBITS; - r.w[0] &= BMASK; - for i in 1..n { - m.w[i] = (m.w[i] >> 1) | ((m.w[i + 1] << (BASEBITS - 1)) & BMASK); - r.w[i] = a.w[i] - m.w[i] + carry; - carry = r.w[i] >> BASEBITS; - r.w[i] &= BMASK; - } - m.w[n] >>= 1; - r.w[n] = a.w[n] - m.w[n] + carry; - ((r.w[n] >> (arch::CHUNK - 1)) & 1) as isize - } - - /* return a*b mod m */ - pub fn modmul(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { - let mut a = BIG::new_copy(a1); - let mut b = BIG::new_copy(b1); - a.rmod(m); - b.rmod(m); - let mut d = BIG::mul(&a, &b); - d.ctdmod(m,m.nbits()) - } - - /* return a^2 mod m */ - pub fn modsqr(a1: &BIG, m: &BIG) -> BIG { - let mut a = BIG::new_copy(a1); - a.rmod(m); - let mut d = BIG::sqr(&a); - d.ctdmod(m,m.nbits()) - } - - /* return -a mod m */ - pub fn modneg(a1: &BIG, m: &BIG) -> BIG { - let mut a = BIG::new_copy(a1); - a.rmod(m); - a.rsub(m); - a.norm(); - a - } - - /* return a+b mod m */ - pub fn modadd(a1: &BIG, b1: &BIG, m: &BIG) -> BIG { - let mut a = BIG::new_copy(a1); - let mut b = BIG::new_copy(b1); - a.rmod(m); - b.rmod(m); - a.add(&b); a.norm(); - a.ctmod(m,1); - a - } - - /* return this^e mod m */ - pub fn powmod(&mut self, e1: &BIG, m: &BIG) -> BIG { - self.norm(); - let mut e = BIG::new_copy(e1); - e.norm(); - let mut a = BIG::new_int(1); - let mut z = BIG::new_copy(&e); - let mut s = BIG::new_copy(self); - loop { - let bt = z.parity(); - z.fshr(1); - if bt == 1 { - a = BIG::modmul(&a, &s, m) - } - if z.iszilch() { - break; - } - s = BIG::modsqr(&s, m); - } - a - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs deleted file mode 100644 index 507ce760e626..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/bls.rs +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::fp::FP; -use crate::bn254::ecp; -use crate::bn254::ecp::ECP; -use crate::bn254::dbig::DBIG; -use crate::bn254::ecp2::ECP2; -//use crate::bn254::fp4::FP4; -use crate::bn254::pair; -use crate::bn254::rom; -use crate::hmac; - -/* Boneh-Lynn-Shacham signature 128-bit API Functions */ - -/* Loosely (for now) following https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-02 */ - -// Minimal-signature-size variant - -pub const BFS: usize = big::MODBYTES as usize; -pub const BGS: usize = big::MODBYTES as usize; -pub const BLS_OK: isize = 0; -pub const BLS_FAIL: isize = -1; - -// NOTE this must be accessed in unsafe mode. -// But it is just written to once at start-up, so actually safe. - -// Best not to use precomp if stack memory limited - i.e. embedded use -// Uncomment to use precomp -// static mut G2_TAB: [FP4; ecp::G2_TABLE] = [FP4::new(); ecp::G2_TABLE]; - -fn ceil(a: usize,b: usize) -> usize { - (a-1)/b+1 -} - -/* output u \in F_p */ -fn hash_to_field(hash: usize,hlen: usize ,u: &mut [FP], dst: &[u8],m: &[u8],ctr: usize) { - let q = BIG::new_ints(&rom::MODULUS); - let nbq=q.nbits(); - let el = ceil(nbq+ecp::AESKEY*8,8); - - let mut okm: [u8;256]=[0;256]; - let mut fd: [u8;128]=[0;128]; - - hmac::xmd_expand(hash,hlen,&mut okm,el*ctr,&dst,&m); - for i in 0..ctr { - for j in 0..el { - fd[j]=okm[el*i+j]; - } - u[i]=FP::new_big(&DBIG::frombytes(&fd[0 .. el]).ctdmod(&q,8*el-nbq)); - } -} - -/* hash a message to an ECP point, using SHA2, random oracle method */ -#[allow(non_snake_case)] -pub fn bls_hash_to_point(m: &[u8]) -> ECP { - let dst= "BLS_SIG_BN254G1_XMD:SHA-256_SVDW_RO_NUL_"; - - let mut u: [FP; 2] = [ - FP::new(), - FP::new(), - ]; - hash_to_field(hmac::MC_SHA2,ecp::HASH_TYPE,&mut u,dst.as_bytes(),m,2); - - let mut P=ECP::map2point(&u[0]); - let P1=ECP::map2point(&u[1]); - - P.add(&P1); - P.cfp(); - P.affine(); - P -} - -pub fn init() -> isize { -// Uncomment to use precomp -// let g = ECP2::generator(); -// if g.is_infinity() { -// return BLS_FAIL; -// } -// unsafe { -// pair::precomp(&mut G2_TAB, &g); -// } - BLS_OK -} - -/* generate key pair, private key s, public key w */ -pub fn key_pair_generate(ikm: &[u8], s: &mut [u8], w: &mut [u8]) -> isize { - let r = BIG::new_ints(&rom::CURVE_ORDER); - let nbr=r.nbits(); - let el = ceil(3*ceil(nbr,8),2); - let g = ECP2::generator(); - let mut len: [u8; 2] = [0; 2]; - hmac::inttobytes(el,&mut len); - - let salt="BLS-SIG-KEYGEN-SALT-"; - - let mut prk: [u8;64]=[0;64]; - let mut okm: [u8;128]=[0;128]; - let mut aikm: [u8;65]=[0;65]; - let likm=ikm.len(); - for i in 0..likm { - aikm[i]=ikm[i]; - } - aikm[likm]=0; - - let hlen=ecp::HASH_TYPE; - - hmac::hkdf_extract(hmac::MC_SHA2,hlen,&mut prk,Some(&salt.as_bytes()),&aikm[0 .. likm+1]); - hmac::hkdf_expand(hmac::MC_SHA2,hlen,&mut okm,el,&prk[0 .. hlen],&len); - - let mut dx = DBIG::frombytes(&okm[0 .. el]); - let sc = dx.ctdmod(&r,8*el-nbr); - sc.tobytes(s); -// SkToPk - pair::g2mul(&g, &sc).tobytes(w,true); // true for public key compression - BLS_OK -} - -/* Sign message m using private key s to produce signature sig */ - -pub fn core_sign(sig: &mut [u8], m: &[u8], s: &[u8]) -> isize { - let d = bls_hash_to_point(m); - let sc = BIG::frombytes(&s); - pair::g1mul(&d, &sc).tobytes(sig, true); - BLS_OK -} - -/* Verify signature given message m, the signature sig, and the public key w */ - -pub fn core_verify(sig: &[u8], m: &[u8], w: &[u8]) -> isize { - let hm = bls_hash_to_point(m); - let mut d = ECP::frombytes(&sig); - - if !pair::g1member(&d) { - return BLS_FAIL; - } - d.neg(); - - let pk = ECP2::frombytes(&w); - if !pair::g2member(&pk) { - return BLS_FAIL; - } - -// Uncomment to use precomp - // Use new multi-pairing mechanism - //let mut r = pair::initmp(); - // pair::another(&mut r,&g,&d); - - //unsafe { - // pair::another_pc(&mut r, &G2_TAB, &d); - //} - //pair::another(&mut r, &pk, &hm); - //let mut v = pair::miller(&mut r); - - //.. or else do not use precomp! - let g = ECP2::generator(); - let mut v = pair::ate2(&g, &d, &pk, &hm); - - v = pair::fexp(&v); - if v.isunity() { - return BLS_OK; - } - BLS_FAIL -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs deleted file mode 100644 index 5f2de894baed..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/dbig.rs +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::arch; -use crate::arch::Chunk; -use crate::bn254::big; -use crate::bn254::big::BIG; - -pub struct DBIG { - pub w: [Chunk; big::DNLEN], -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for DBIG { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for DBIG { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -impl DBIG { - pub fn new() -> DBIG { - DBIG { - w: [0; big::DNLEN as usize], - } - } - - pub fn new_copy(y: &DBIG) -> DBIG { - let mut s = DBIG::new(); - for i in 0..big::DNLEN { - s.w[i] = y.w[i] - } - s - } - - pub fn new_scopy(x: &BIG) -> DBIG { - let mut b = DBIG::new(); - for i in 0..big::NLEN { - b.w[i] = x.w[i]; - } - b.w[big::NLEN - 1] = x.get(big::NLEN - 1) & big::BMASK; /* top word normalized */ - b.w[big::NLEN] = x.get(big::NLEN - 1) >> big::BASEBITS; - - for i in big::NLEN + 1..big::DNLEN { - b.w[i] = 0 - } - b - } - - /* split DBIG at position n, return higher half, keep lower half */ - pub fn split(&mut self, n: usize) -> BIG { - let mut t = BIG::new(); - let m = n % big::BASEBITS; - let mut carry = self.w[big::DNLEN - 1] << (big::BASEBITS - m); - - for i in (big::NLEN - 1..big::DNLEN - 1).rev() { - let nw = (self.w[i] >> m) | carry; - carry = (self.w[i] << (big::BASEBITS - m)) & big::BMASK; - t.set(i + 1 - big::NLEN, nw); - } - self.w[big::NLEN - 1] &= ((1 as Chunk) << m) - 1; - t - } - - /* general shift left */ - pub fn shl(&mut self, k: usize) { - let n = k % big::BASEBITS; - let m = k / big::BASEBITS; - self.w[big::DNLEN - 1] = - (self.w[big::DNLEN - 1 - m] << n) | (self.w[big::DNLEN - m - 2] >> (big::BASEBITS - n)); - for i in (m + 1..big::DNLEN - 1).rev() { - self.w[i] = - ((self.w[i - m] << n) & big::BMASK) | (self.w[i - m - 1] >> (big::BASEBITS - n)); - } - - self.w[m] = (self.w[0] << n) & big::BMASK; - for i in 0..m { - self.w[i] = 0 - } - } - - /* general shift right */ - pub fn shr(&mut self, k: usize) { - let n = k % big::BASEBITS; - let m = k / big::BASEBITS; - for i in 0..big::DNLEN - m - 1 { - self.w[i] = - (self.w[m + i] >> n) | ((self.w[m + i + 1] << (big::BASEBITS - n)) & big::BMASK); - } - self.w[big::DNLEN - m - 1] = self.w[big::DNLEN - 1] >> n; - for i in big::DNLEN - m..big::DNLEN { - self.w[i] = 0 - } - } - - /* Copy from another DBIG */ - pub fn copy(&mut self, x: &DBIG) { - for i in 0..big::DNLEN { - self.w[i] = x.w[i]; - } - } - - pub fn ucopy(&mut self, x: &BIG) { - for i in 0..big::NLEN { - self.w[i] = 0; - } - for i in big::NLEN..big::DNLEN { - self.w[i] = x.w[i - big::NLEN]; - } - } - - pub fn cmove(&mut self, g: &DBIG, d: isize) -> Chunk { - let b = -d as Chunk; - let mut w=0 as Chunk; - let r=self.w[0]^g.w[1]; - let mut ra=r.wrapping_add(r); ra >>= 1; - for i in 0..big::DNLEN { - let mut t = b & (self.w[i] ^ g.w[i]); - t^=r; - let e=self.w[i]^t; w^=e; - self.w[i]=e^ra; - } - return w; - } - - /* self+=x */ - pub fn add(&mut self, x: &DBIG) { - for i in 0..big::DNLEN { - self.w[i] += x.w[i]; - } - } - - /* self-=x */ - pub fn sub(&mut self, x: &DBIG) { - for i in 0..big::DNLEN { - self.w[i] -= x.w[i]; - } - } - - /* self=x-self */ - pub fn rsub(&mut self, x: &DBIG) { - for i in 0..big::DNLEN { - self.w[i] = x.w[i] - self.w[i]; - } - } - - /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ - pub fn comp(a: &DBIG, b: &DBIG) -> isize { - let mut gt = 0 as Chunk; - let mut eq = 1 as Chunk; - for i in (0..big::DNLEN).rev() { - gt |= ((b.w[i]-a.w[i]) >> big::BASEBITS) & eq; - eq &= ((b.w[i]^a.w[i])-1) >> big::BASEBITS; - } - (gt+gt+eq-1) as isize - } - - /* convert from byte array to BIG */ - pub fn frombytes(b: &[u8]) -> DBIG { - let mut m = DBIG::new(); - for i in 0..(b.len()) { - m.shl(8); - m.w[0] += b[i] as Chunk; - } - m - } - - /* normalise BIG - force all digits < 2^big::BASEBITS */ - pub fn norm(&mut self) { - let mut carry = self.w[0]>>big::BASEBITS; - self.w[0] &= big::BMASK; - for i in 1..big::DNLEN - 1 { - let d = self.w[i] + carry; - self.w[i] = d & big::BMASK; - carry = d >> big::BASEBITS; - } - self.w[big::DNLEN - 1] += carry - } - -// Set self=self mod m in constant time (if bd is known at compile time) -// bd is Max number of bits in b - Actual number of bits in m - pub fn ctdmod(&mut self, m: &BIG, bd: usize) -> BIG { - let mut k=bd; - self.norm(); - let mut c = DBIG::new_scopy(m); - let mut dr = DBIG::new(); - - c.shl(k); - - loop { - dr.copy(self); - dr.sub(&c); - dr.norm(); - self.cmove(&dr,(1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize); - if k==0 {break;} - c.shr(1); - k -= 1; - } - BIG::new_dcopy(self) - } - - /* reduces self DBIG mod a BIG, and returns the BIG */ - pub fn dmod(&mut self, m: &BIG) -> BIG { - let ss=self.nbits() as isize; - let ms=m.nbits() as isize; - let mut k=(ss-ms) as usize; - if ss BIG { - let mut k=bd; - let mut c = DBIG::new_scopy(m); - let mut a = BIG::new(); - let mut e = BIG::new_int(1); - let mut dr = DBIG::new(); - let mut r = BIG::new(); - self.norm(); - - c.shl(k); - e.shl(k); - - loop { - dr.copy(self); - dr.sub(&c); - dr.norm(); - let d = (1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize; - self.cmove(&dr, d); - r.copy(&a); - r.add(&e); - r.norm(); - a.cmove(&r, d); - if k==0 {break;} - k -= 1; - c.shr(1); - e.shr(1); - } - a - } - - /* return this/c */ - pub fn div(&mut self, m: &BIG) -> BIG { - let ss=self.nbits() as isize; - let ms=m.nbits() as isize; - let mut k=(ss-ms) as usize; - if ss usize { - let mut k = big::DNLEN - 1; - let mut s = DBIG::new_copy(&self); - s.norm(); - while (k as isize) >= 0 && s.w[k] == 0 { - k = k.wrapping_sub(1) - } - if (k as isize) < 0 { - return 0; - } - let mut bts = (big::BASEBITS as usize) * k; - let mut c = s.w[k]; - while c != 0 { - c /= 2; - bts += 1; - } - bts - } - - /* Convert to Hex String */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - let mut s = String::new(); - let mut len = self.nbits(); - - if len % 4 == 0 { - len /= 4; - } else { - len /= 4; - len += 1; - } - - for i in (0..len).rev() { - let mut b = DBIG::new_copy(&self); - b.shr(i * 4); - s = s + &format!("{:X}", b.w[0] & 15); - } - s - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs deleted file mode 100644 index 96ceadf4f311..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecdh.rs +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ECDH/ECIES/ECDSA API Functions */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::ecp; -use crate::bn254::ecp::ECP; -use crate::bn254::rom; - -use crate::aes; -use crate::hmac; -use crate::rand::RAND; - -pub const INVALID_PUBLIC_KEY: isize = -2; -pub const ERROR: isize = -3; -//pub const INVALID: isize = -4; -pub const EFS: usize = big::MODBYTES as usize; -pub const EGS: usize = big::MODBYTES as usize; - -pub fn rfc7748(r: &mut BIG) { - let mut lg=0; - let mut t=BIG::new_int(1); - let mut c=rom::CURVE_COF_I; - while c!=1 { - lg+=1; - c/=2; - } - let n=(8*EGS-lg+1) as usize; - r.mod2m(n); - t.shl(n); - r.add(&t); - c=r.lastbits(lg as usize); - r.dec(c); -} - -#[allow(non_snake_case)] -pub fn in_range(s: &[u8]) -> bool { - let r = BIG::new_ints(&rom::CURVE_ORDER); - let sc = BIG::frombytes(&s); - if sc.iszilch() { - return false; - } - if BIG::comp(&sc, &r) >= 0 { - return false; - } - true -} - -/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), - * where s is the secret key and W is the public key - * and G is fixed generator. - * If RNG is NULL then the private key is provided externally in s - * otherwise it is generated randomly internally */ -#[allow(non_snake_case)] -pub fn key_pair_generate(rng: Option<&mut RAND>, s: &mut [u8], w: &mut [u8]) -> isize { - let res = 0; - let mut sc: BIG; - let G = ECP::generator(); - let r = BIG::new_ints(&rom::CURVE_ORDER); - - if let Some(x) = rng { - if ecp::CURVETYPE != ecp::WEIERSTRASS { - sc = BIG::random(x); // from random bytes - } else { - sc = BIG::randomnum(&r, x); // Removes biases - } - } else { - sc = BIG::frombytes(&s); - } - - if ecp::CURVETYPE != ecp::WEIERSTRASS { - rfc7748(&mut sc); // For Montgomery or Edwards, apply RFC7748 transformation - } - sc.tobytes(s); - let WP = G.clmul(&sc,&r); - WP.tobytes(w, false); // To use point compression on public keys, change to true - - res -} - -/* validate public key */ -#[allow(non_snake_case)] -pub fn public_key_validate(w: &[u8]) -> isize { - let mut WP = ECP::frombytes(w); - let mut res = 0; - - let r = BIG::new_ints(&rom::CURVE_ORDER); - - if WP.is_infinity() { - res = INVALID_PUBLIC_KEY - } - if res == 0 { - let q = BIG::new_ints(&rom::MODULUS); - let nb = q.nbits(); - let mut k = BIG::new(); - k.one(); - k.shl((nb + 4) / 2); - k.add(&q); - k.div(&r); - - while k.parity() == 0 { - k.shr(1); - WP.dbl(); - } - - if !k.isunity() { - WP = WP.mul(&mut k) - } - if WP.is_infinity() { - res = INVALID_PUBLIC_KEY - } - } - res -} - -/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ -#[allow(non_snake_case)] -pub fn ecpsvdp_dh(s: &[u8], wd: &[u8], z: &mut [u8], typ: isize) -> isize { - let mut res = 0; - - let sc = BIG::frombytes(&s); - - let mut W = ECP::frombytes(&wd); - if W.is_infinity() { - res = ERROR - } - - if res == 0 { - let r = BIG::new_ints(&rom::CURVE_ORDER); - W = W.clmul(&sc,&r); - if W.is_infinity() { - res = ERROR; - } else { - if ecp::CURVETYPE != ecp::MONTGOMERY { - if typ>0 { - if typ==1 { - W.tobytes(z,true); - } else { - W.tobytes(z,false); - } - } else { - W.getx().tobytes(z); - } - return res; - } else { - W.getx().tobytes(z); - } - } - } - res -} - -/* IEEE ECDSA Signature, C and D are signature on F using private key S */ -#[allow(non_snake_case)] -pub fn ecpsp_dsa( - sha: usize, - rng: &mut RAND, - s: &[u8], - f: &[u8], - c: &mut [u8], - d: &mut [u8], -) -> isize { - let mut t: [u8; EGS] = [0; EGS]; - let mut b: [u8; EGS] = [0; EGS]; - - hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS,0,Some(f), -1, None); - - let G = ECP::generator(); - - let r = BIG::new_ints(&rom::CURVE_ORDER); - - let sc = BIG::frombytes(s); /* s or &s? */ - let fb = BIG::frombytes(&b); - - let mut cb = BIG::new(); - let mut db = BIG::new(); - let mut tb = BIG::new(); - let mut V = ECP::new(); - - while db.iszilch() { - let mut u = BIG::randomnum(&r, rng); - let w = BIG::randomnum(&r, rng); /* IMPORTANT - side channel masking to protect invmodp() */ - - V.copy(&G); - V = V.clmul(&u,&r); - let vx = V.getx(); - cb.copy(&vx); - cb.rmod(&r); - if cb.iszilch() { - continue; - } - - tb.copy(&BIG::modmul(&u, &w, &r)); - u.copy(&tb); - - u.invmodp(&r); - db.copy(&BIG::modmul(&sc, &cb, &r)); - db.copy(&BIG::modadd(&db, &fb, &r)); - tb.copy(&BIG::modmul(&db, &w, &r)); - db.copy(&tb); - - tb.copy(&BIG::modmul(&u, &db, &r)); - db.copy(&tb); - } - - cb.tobytes(&mut t); - for i in 0..EGS { - c[i] = t[i] - } - db.tobytes(&mut t); - for i in 0..EGS { - d[i] = t[i] - } - 0 -} - -/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ -#[allow(non_snake_case)] -pub fn ecpvp_dsa(sha: usize, w: &[u8], f: &[u8], c: &[u8], d: &[u8]) -> isize { - let mut res = 0; - - let mut b: [u8; EGS] = [0; EGS]; - - hmac::GPhashit(hmac::MC_SHA2, sha, &mut b, EGS, 0,Some(f), -1, None); - - let mut G = ECP::generator(); - - let r = BIG::new_ints(&rom::CURVE_ORDER); - - let mut cb = BIG::frombytes(c); /* c or &c ? */ - let mut db = BIG::frombytes(d); /* d or &d ? */ - let mut fb = BIG::frombytes(&b); - let mut tb = BIG::new(); - - if cb.iszilch() || BIG::comp(&cb, &r) >= 0 || db.iszilch() || BIG::comp(&db, &r) >= 0 { - res = ERROR; - } - - if res == 0 { - db.invmodp(&r); - tb.copy(&BIG::modmul(&mut fb, &mut db, &r)); - fb.copy(&tb); - let h2 = BIG::modmul(&mut cb, &mut db, &r); - - let WP = ECP::frombytes(&w); - if WP.is_infinity() { - res = ERROR; - } else { - let mut P = ECP::new(); - P.copy(&WP); - - P = P.mul2(&h2, &mut G, &fb); - - if P.is_infinity() { - res = ERROR; - } else { - db = P.getx(); - db.rmod(&r); - - if BIG::comp(&db, &cb) != 0 { - res = ERROR - } - } - } - } - - res -} - -/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ -// returns length of ciphertext -#[allow(non_snake_case)] -pub fn ecies_encrypt( - sha: usize, - p1: &[u8], - p2: &[u8], - rng: &mut RAND, - w: &[u8], - m: &[u8], - v: &mut [u8], - c: &mut [u8], - t: &mut [u8], -) -> usize { - let mut z: [u8; EFS] = [0; EFS]; - let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; - let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; - let mut u: [u8; EGS] = [0; EGS]; - let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; - let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; - - if key_pair_generate(Some(rng), &mut u, v) != 0 { - return 0; - } - if ecpsvdp_dh(&u, &w, &mut z, 0) != 0 { - return 0; - } - - for i in 0..2 * EFS + 1 { - vz[i] = v[i] - } - for i in 0..EFS { - vz[2 * EFS + 1 + i] = z[i] - } - - hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); - - for i in 0..ecp::AESKEY { - k1[i] = k[i]; - k2[i] = k[ecp::AESKEY + i] - } - - let clen = aes::cbc_iv0_encrypt(&k1, m, c); - - let mut l2: [u8; 8] = [0; 8]; - let p2l = p2.len(); - - hmac::inttobytes(p2l, &mut l2); - - let mut opt=clen; - for i in 0..p2l { - c[opt]=p2[i]; opt+=1; - } - for i in 0..8 { - c[opt]=l2[i]; opt+=1; - } - - hmac::hmac1(hmac::MC_SHA2, sha, t, t.len(), &k2, &c[0..opt]); - - clen -} - -/* constant time n-byte compare */ -fn ncomp(t1: &[u8], t2: &[u8], n: usize) -> bool { - let mut res = 0; - for i in 0..n { - res |= (t1[i] ^ t2[i]) as isize; - } - if res == 0 { - return true; - } - false -} - -/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ -// returns length of plaintext -#[allow(non_snake_case)] -pub fn ecies_decrypt( - sha: usize, - p1: &[u8], - p2: &[u8], - v: &[u8], - c: &mut [u8], - clen: usize, - t: &[u8], - u: &[u8], - m: &mut [u8], -) -> usize { - let mut z: [u8; EFS] = [0; EFS]; - let mut k1: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; - let mut k2: [u8; ecp::AESKEY] = [0; ecp::AESKEY]; - let mut vz: [u8; 3 * EFS + 1] = [0; 3 * EFS + 1]; - let mut k: [u8; 2 * ecp::AESKEY] = [0; 2 * ecp::AESKEY]; - let mut tag: [u8; 32] = [0; 32]; /* 32 is max length of tag */ - - for i in 0..t.len() { - tag[i] = t[i] - } - - if ecpsvdp_dh(&u, &v, &mut z, 0) != 0 { - return 0; - } - - for i in 0..2 * EFS + 1 { - vz[i] = v[i] - } - for i in 0..EFS { - vz[2 * EFS + 1 + i] = z[i] - } - - hmac::kdf2(hmac::MC_SHA2, sha, &vz, Some(p1), 2 * ecp::AESKEY, &mut k); - - for i in 0..ecp::AESKEY { - k1[i] = k[i]; - k2[i] = k[ecp::AESKEY + i] - } - - let mlen = aes::cbc_iv0_decrypt(&k1, &c[0..clen], m); - - if mlen == 0 { - return 0; - } - - let mut l2: [u8; 8] = [0; 8]; - let p2l = p2.len(); - - hmac::inttobytes(p2l, &mut l2); - let mut opt=clen; - - for i in 0..p2l { - c[opt]=p2[i]; opt+=1; - } - for i in 0..8 { - c[opt]=l2[i]; opt+=1; - } - - let tl=tag.len(); - hmac::hmac1(hmac::MC_SHA2, sha, &mut tag, tl, &k2, &c[0..opt]); - - if !ncomp(&t, &tag, t.len()) { - return 0; - } - - mlen -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs deleted file mode 100644 index 23a6b7adf915..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp.rs +++ /dev/null @@ -1,1824 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::dbig::DBIG; -use crate::bn254::fp::FP; -use crate::bn254::fp; -use crate::bn254::rom; - -#[derive(Clone)] -pub struct ECP { - x: FP, - y: FP, - z: FP, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for ECP { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for ECP { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -pub const WEIERSTRASS: usize = 0; -pub const EDWARDS: usize = 1; -pub const MONTGOMERY: usize = 2; -pub const NOT: usize = 0; -pub const BN: usize = 1; -pub const BLS12: usize = 2; -pub const BLS24: usize = 3; -pub const BLS48: usize = 4; -pub const D_TYPE: usize = 0; -pub const M_TYPE: usize = 1; -pub const POSITIVEX: usize = 0; -pub const NEGATIVEX: usize = 1; - -pub const CURVETYPE:usize=WEIERSTRASS; -pub const CURVE_A:isize=0; -pub const CURVE_PAIRING_TYPE:usize=BN; -pub const SEXTIC_TWIST:usize=D_TYPE; -pub const SIGN_OF_X:usize=NEGATIVEX; -pub const ATE_BITS:usize=66; -pub const G2_TABLE:usize=71; -pub const HTC_ISO:usize=0; -pub const HTC_ISO_G2:usize=0; - -pub const ALLOW_ALT_COMPRESS:bool=false; -pub const HASH_TYPE:usize=32; -pub const AESKEY:usize=16; - -#[allow(non_snake_case)] -impl ECP { - pub fn pnew() -> ECP { - ECP { - x: FP::new(), - y: FP::new_int(1), - z: FP::new(), - } - } - - pub fn new() -> ECP { - let mut E = ECP::pnew(); - if CURVETYPE == EDWARDS { - E.z.one(); - } - E - } - - /* set (x,y) from two BIGs */ - pub fn new_bigs(ix: &BIG, iy: &BIG) -> ECP { - let mut E = ECP::new(); - E.x.bcopy(ix); - E.y.bcopy(iy); - E.z.one(); - E.x.norm(); - let rhs = ECP::rhs(&E.x); - if CURVETYPE == MONTGOMERY { - if rhs.qr(None) != 1 { - E.inf(); - } - } else { - let mut y2 = FP::new_copy(&E.y); - y2.sqr(); - if !y2.equals(&rhs) { - E.inf(); - } - } - E - } - - /* set (x,y) from BIG and a bit */ - pub fn new_bigint(ix: &BIG, s: isize) -> ECP { - let mut E = ECP::new(); - let mut hint = FP::new(); - E.x.bcopy(ix); - E.x.norm(); - E.z.one(); - - let rhs = ECP::rhs(&E.x); - - if rhs.qr(Some(&mut hint)) == 1 { - let mut ny = rhs.sqrt(Some(&hint)); - if ny.sign() != s { - ny.neg(); ny.norm() - } - E.y.copy(&ny); - } else { - E.inf() - } - E - } - - #[allow(non_snake_case)] - /* set from x - calculate y from curve equation */ - pub fn new_big(ix: &BIG) -> ECP { - let mut E = ECP::new(); - let mut hint = FP::new(); - E.x.bcopy(ix); - E.x.norm(); - E.z.one(); - let rhs = ECP::rhs(&E.x); - if rhs.qr(Some(&mut hint)) == 1 { - if CURVETYPE != MONTGOMERY { - E.y.copy(&rhs.sqrt(Some(&hint))) - } - } else { - E.inf(); - } - E - } - - /* set this=O */ - pub fn inf(&mut self) { - self.x.zero(); - if CURVETYPE != MONTGOMERY { - self.y.one(); - } - if CURVETYPE != EDWARDS { - self.z.zero(); - } else { - self.z.one() - } - } - - /* Calculate RHS of curve equation */ - fn rhs(x: &FP) -> FP { - let mut r = FP::new_copy(x); - r.sqr(); - - if CURVETYPE == WEIERSTRASS { - // x^3+Ax+B - let b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); - r.mul(x); - if CURVE_A == -3 { - let mut cx = FP::new_copy(x); - cx.imul(3); - cx.neg(); - cx.norm(); - r.add(&cx); - } - r.add(&b); - } - if CURVETYPE == EDWARDS { - // (Ax^2-1)/(Bx^2-1) - let mut b = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); - let one = FP::new_int(1); - b.mul(&r); - b.sub(&one); - b.norm(); - if CURVE_A == -1 { - r.neg() - } - r.sub(&one); - r.norm(); - b.inverse(None); - r.mul(&b); - } - if CURVETYPE == MONTGOMERY { - // x^3+Ax^2+x - let mut x3 = FP::new(); - x3.copy(&r); - x3.mul(x); - r.imul(CURVE_A); - r.add(&x3); - r.add(&x); - } - r.reduce(); - r - } - - /* test for O point-at-infinity */ - pub fn is_infinity(&self) -> bool { - if CURVETYPE == EDWARDS { - return self.x.iszilch() && self.y.equals(&self.z); - } - if CURVETYPE == WEIERSTRASS { - return self.x.iszilch() && self.z.iszilch(); - } - if CURVETYPE == MONTGOMERY { - return self.z.iszilch(); - } - true - } - - /* Conditional swap of P and Q dependant on d */ - pub fn cswap(&mut self, Q: &mut ECP, d: isize) { - self.x.cswap(&mut Q.x, d); - if CURVETYPE != MONTGOMERY { - self.y.cswap(&mut Q.y, d) - } - self.z.cswap(&mut Q.z, d); - } - - /* Conditional move of Q to P dependant on d */ - pub fn cmove(&mut self, Q: &ECP, d: isize) { - self.x.cmove(&Q.x, d); - if CURVETYPE != MONTGOMERY { - self.y.cmove(&Q.y, d) - } - self.z.cmove(&Q.z, d); - } - - /* return 1 if b==c, no branching */ - fn teq(b: i32, c: i32) -> isize { - let mut x = b ^ c; - x -= 1; // if x=0, x now -1 - ((x >> 31) & 1) as isize - } - - /* this=P */ - pub fn copy(&mut self, P: &ECP) { - self.x.copy(&P.x); - if CURVETYPE != MONTGOMERY { - self.y.copy(&P.y) - } - self.z.copy(&P.z); - } - - /* this=-this */ - pub fn neg(&mut self) { - if CURVETYPE == WEIERSTRASS { - self.y.neg(); - self.y.norm(); - } - if CURVETYPE == EDWARDS { - self.x.neg(); - self.x.norm(); - } - } - /* multiply x coordinate */ - pub fn mulx(&mut self, c: &mut FP) { - self.x.mul(c); - } - - /* Constant time select from pre-computed table */ - fn selector(&mut self, W: &[ECP], b: i32) { - // unsure about &[& syntax. An array of pointers I hope.. - let mut MP = ECP::new(); - let m = b >> 31; - let mut babs = (b ^ m) - m; - - babs = (babs - 1) / 2; - - self.cmove(&W[0], ECP::teq(babs, 0)); // conditional move - self.cmove(&W[1], ECP::teq(babs, 1)); - self.cmove(&W[2], ECP::teq(babs, 2)); - self.cmove(&W[3], ECP::teq(babs, 3)); - self.cmove(&W[4], ECP::teq(babs, 4)); - self.cmove(&W[5], ECP::teq(babs, 5)); - self.cmove(&W[6], ECP::teq(babs, 6)); - self.cmove(&W[7], ECP::teq(babs, 7)); - - MP.copy(self); - MP.neg(); - self.cmove(&MP, (m & 1) as isize); - } - - /* Test P == Q */ - pub fn equals(&self, Q: &ECP) -> bool { - let mut a = FP::new(); - let mut b = FP::new(); - a.copy(&self.x); - a.mul(&Q.z); - b.copy(&Q.x); - b.mul(&self.z); - if !a.equals(&b) { - return false; - } - if CURVETYPE != MONTGOMERY { - a.copy(&self.y); - a.mul(&Q.z); - b.copy(&Q.y); - b.mul(&self.z); - if !a.equals(&b) { - return false; - } - } - true - } - - /* set to affine - from (x,y,z) to (x,y) */ - pub fn affine(&mut self) { - if self.is_infinity() { - return; - } - let one = FP::new_int(1); - if self.z.equals(&one) { - return; - } - self.z.inverse(None); - - self.x.mul(&self.z); - self.x.reduce(); - if CURVETYPE != MONTGOMERY { - self.y.mul(&self.z); - self.y.reduce(); - } - self.z.copy(&one); - } - - /* extract x as a BIG */ - pub fn getx(&self) -> BIG { - let mut W = ECP::new(); - W.copy(self); - W.affine(); - W.x.redc() - } - - /* extract y as a BIG */ - pub fn gety(&self) -> BIG { - let mut W = ECP::new(); - W.copy(self); - W.affine(); - W.y.redc() - } - - /* get sign of Y */ - pub fn gets(&self) -> isize { - let mut W = ECP::new(); - W.copy(self); - W.affine(); - W.y.sign() - } - - /* extract x as an FP */ - pub fn getpx(&self) -> FP { - FP::new_copy(&self.x) - } - /* extract y as an FP */ - pub fn getpy(&self) -> FP { - FP::new_copy(&self.y) - } - - /* extract z as an FP */ - pub fn getpz(&self) -> FP { - FP::new_copy(&self.z) - } - - /* convert to byte array */ - pub fn tobytes(&self, b: &mut [u8], compress: bool) { - const MB:usize = big::MODBYTES as usize; - let mut t: [u8; MB] = [0; MB]; - let mut alt=false; - let mut W = ECP::new(); - W.copy(self); - W.affine(); - W.x.redc().tobytes(&mut t); - - if CURVETYPE == MONTGOMERY { - for i in 0..MB { - b[i] = t[i] - } - return; - } - - if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { - alt=true; - } - - if alt { - for i in 0..MB { - b[i]=t[i]; - } - if compress { - b[0]|=0x80; - if W.y.islarger()==1 { - b[0]|=0x20; - } - } else { - W.y.redc().tobytes(&mut t); - for i in 0..MB { - b[i+MB]=t[i]; - } - } - } else { - for i in 0..MB { - b[i + 1] = t[i]; - } - if compress { - b[0] = 0x02; - if W.y.sign() == 1 { - b[0] = 0x03; - } - return; - } - b[0] = 0x04; - W.y.redc().tobytes(&mut t); - for i in 0..MB { - b[i + MB + 1] = t[i]; - } - } - } - - /* convert from byte array to point */ - pub fn frombytes(b: &[u8]) -> ECP { - const MB:usize = big::MODBYTES as usize; - let mut t: [u8; MB] = [0; MB]; - let mut alt=false; - let p = BIG::new_ints(&rom::MODULUS); - - if CURVETYPE == MONTGOMERY { - for i in 0..MB { - t[i] = b[i]; - } - let px = BIG::frombytes(&t); - if BIG::comp(&px, &p) >= 0 { - return ECP::new(); - } - return ECP::new_big(&px); - } - - if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS { - alt=true; - } - - if alt { - for i in 0..MB { - t[i]=b[i]; - } - t[0]&=0x1f; - let px=BIG::frombytes(&t); - if (b[0]&0x80)==0 { - for i in 0 ..MB { - t[i]=b[i+MB]; - } - let py=BIG::frombytes(&t); - return ECP::new_bigs(&px, &py); - } else { - let sgn=(b[0]&0x20)>>5; - let mut P=ECP::new_bigint(&px,0); - let cmp=P.y.islarger(); - if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { - P.neg(); - } - return P; - } - } else { - for i in 0..MB { - t[i] = b[i + 1]; - } - let px = BIG::frombytes(&t); - if BIG::comp(&px, &p) >= 0 { - return ECP::new(); - } - if b[0] == 0x04 { - for i in 0..MB { - t[i] = b[i + MB + 1]; - } - let py = BIG::frombytes(&t); - if BIG::comp(&py, &p) >= 0 { - return ECP::new(); - } - return ECP::new_bigs(&px, &py); - } - if b[0] == 0x02 || b[0] == 0x03 { - return ECP::new_bigint(&px, (b[0] & 1) as isize); - } - } - - ECP::new() - } - - /* convert to hex string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - let mut W = ECP::new(); - W.copy(self); - W.affine(); - if W.is_infinity() { - return String::from("infinity"); - } - if CURVETYPE == MONTGOMERY { - return format!("({})", W.x.redc().tostring()); - } else { - return format!("({},{})", W.x.redc().tostring(), W.y.redc().tostring()); - }; - } - - /* this*=2 */ - pub fn dbl(&mut self) { - if CURVETYPE == WEIERSTRASS { - if CURVE_A == 0 { - let mut t0 = FP::new_copy(&self.y); - t0.sqr(); - let mut t1 = FP::new_copy(&self.y); - t1.mul(&self.z); - let mut t2 = FP::new_copy(&self.z); - t2.sqr(); - - self.z.copy(&t0); - self.z.add(&t0); - self.z.norm(); - self.z.dbl(); - self.z.dbl(); - self.z.norm(); - t2.imul(3 * rom::CURVE_B_I); - - let mut x3 = FP::new_copy(&t2); - x3.mul(&self.z); - - let mut y3 = FP::new_copy(&t0); - y3.add(&t2); - y3.norm(); - self.z.mul(&t1); - t1.copy(&t2); - t1.add(&t2); - t2.add(&t1); - t0.sub(&t2); - t0.norm(); - y3.mul(&t0); - y3.add(&x3); - t1.copy(&self.x); - t1.mul(&self.y); - self.x.copy(&t0); - self.x.norm(); - self.x.mul(&t1); - self.x.dbl(); - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - } else { - let mut t0 = FP::new_copy(&self.x); - let mut t1 = FP::new_copy(&self.y); - let mut t2 = FP::new_copy(&self.z); - let mut t3 = FP::new_copy(&self.x); - let mut z3 = FP::new_copy(&self.z); - let mut y3 = FP::new(); - let mut x3 = FP::new(); - let mut b = FP::new(); - - if rom::CURVE_B_I == 0 { - b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); - } - - t0.sqr(); //1 x^2 - t1.sqr(); //2 y^2 - t2.sqr(); //3 - - t3.mul(&self.y); //4 - t3.dbl(); - t3.norm(); //5 - z3.mul(&self.x); //6 - z3.dbl(); - z3.norm(); //7 - y3.copy(&t2); - - if rom::CURVE_B_I == 0 { - y3.mul(&b); //8 - } else { - y3.imul(rom::CURVE_B_I); - } - - y3.sub(&z3); //9 *** - x3.copy(&y3); - x3.add(&y3); - x3.norm(); //10 - - y3.add(&x3); //11 - x3.copy(&t1); - x3.sub(&y3); - x3.norm(); //12 - y3.add(&t1); - y3.norm(); //13 - y3.mul(&x3); //14 - x3.mul(&t3); //15 - t3.copy(&t2); - t3.add(&t2); //16 - t2.add(&t3); //17 - - if rom::CURVE_B_I == 0 { - z3.mul(&b); //18 - } else { - z3.imul(rom::CURVE_B_I); - } - - z3.sub(&t2); //19 - z3.sub(&t0); - z3.norm(); //20 *** - t3.copy(&z3); - t3.add(&z3); //21 - - z3.add(&t3); - z3.norm(); //22 - t3.copy(&t0); - t3.add(&t0); //23 - t0.add(&t3); //24 - t0.sub(&t2); - t0.norm(); //25 - - t0.mul(&z3); //26 - y3.add(&t0); //27 - t0.copy(&self.y); - t0.mul(&self.z); //28 - t0.dbl(); - t0.norm(); //29 - z3.mul(&t0); //30 - x3.sub(&z3); //31 - t0.dbl(); - t0.norm(); //32 - t1.dbl(); - t1.norm(); //33 - z3.copy(&t0); - z3.mul(&t1); //34 - - self.x.copy(&x3); - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - self.z.copy(&z3); - self.z.norm(); - } - } - if CURVETYPE == EDWARDS { - let mut c = FP::new_copy(&self.x); - let mut d = FP::new_copy(&self.y); - let mut h = FP::new_copy(&self.z); - let mut j = FP::new(); - - self.x.mul(&self.y); - self.x.dbl(); - self.x.norm(); - c.sqr(); - d.sqr(); - if CURVE_A == -1 { - c.neg() - } - self.y.copy(&c); - self.y.add(&d); - self.y.norm(); - h.sqr(); - h.dbl(); - self.z.copy(&self.y); - j.copy(&self.y); - j.sub(&h); - j.norm(); - self.x.mul(&j); - c.sub(&d); - c.norm(); - self.y.mul(&c); - self.z.mul(&j); - } - if CURVETYPE == MONTGOMERY { - let mut a = FP::new_copy(&self.x); - let mut b = FP::new_copy(&self.x); - let mut aa = FP::new(); - let mut bb = FP::new(); - let mut c = FP::new(); - - a.add(&self.z); - a.norm(); - aa.copy(&a); - aa.sqr(); - b.sub(&self.z); - b.norm(); - bb.copy(&b); - bb.sqr(); - c.copy(&aa); - c.sub(&bb); - c.norm(); - - self.x.copy(&aa); - self.x.mul(&bb); - - a.copy(&c); - a.imul((CURVE_A + 2) / 4); - - bb.add(&a); - bb.norm(); - self.z.copy(&bb); - self.z.mul(&c); - } - } - - /* self+=Q */ - pub fn add(&mut self, Q: &ECP) { - if CURVETYPE == WEIERSTRASS { - if CURVE_A == 0 { - let b = 3 * rom::CURVE_B_I; - let mut t0 = FP::new_copy(&self.x); - t0.mul(&Q.x); - let mut t1 = FP::new_copy(&self.y); - t1.mul(&Q.y); - let mut t2 = FP::new_copy(&self.z); - t2.mul(&Q.z); - let mut t3 = FP::new_copy(&self.x); - t3.add(&self.y); - t3.norm(); - let mut t4 = FP::new_copy(&Q.x); - t4.add(&Q.y); - t4.norm(); - t3.mul(&t4); - t4.copy(&t0); - t4.add(&t1); - - t3.sub(&t4); - t3.norm(); - t4.copy(&self.y); - t4.add(&self.z); - t4.norm(); - let mut x3 = FP::new_copy(&Q.y); - x3.add(&Q.z); - x3.norm(); - - t4.mul(&x3); - x3.copy(&t1); - x3.add(&t2); - - t4.sub(&x3); - t4.norm(); - x3.copy(&self.x); - x3.add(&self.z); - x3.norm(); - let mut y3 = FP::new_copy(&Q.x); - y3.add(&Q.z); - y3.norm(); - x3.mul(&y3); - y3.copy(&t0); - y3.add(&t2); - y3.rsub(&x3); - y3.norm(); - x3.copy(&t0); - x3.add(&t0); - t0.add(&x3); - t0.norm(); - t2.imul(b); - - let mut z3 = FP::new_copy(&t1); - z3.add(&t2); - z3.norm(); - t1.sub(&t2); - t1.norm(); - y3.imul(b); - - x3.copy(&y3); - x3.mul(&t4); - t2.copy(&t3); - t2.mul(&t1); - x3.rsub(&t2); - y3.mul(&t0); - t1.mul(&z3); - y3.add(&t1); - t0.mul(&t3); - z3.mul(&t4); - z3.add(&t0); - - self.x.copy(&x3); - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - self.z.copy(&z3); - self.z.norm(); - } else { - let mut t0 = FP::new_copy(&self.x); - let mut t1 = FP::new_copy(&self.y); - let mut t2 = FP::new_copy(&self.z); - let mut t3 = FP::new_copy(&self.x); - let mut t4 = FP::new_copy(&Q.x); - let mut z3 = FP::new(); - let mut y3 = FP::new_copy(&Q.x); - let mut x3 = FP::new_copy(&Q.y); - let mut b = FP::new(); - - if rom::CURVE_B_I == 0 { - b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); - } - - t0.mul(&Q.x); //1 - t1.mul(&Q.y); //2 - t2.mul(&Q.z); //3 - - t3.add(&self.y); - t3.norm(); //4 - t4.add(&Q.y); - t4.norm(); //5 - t3.mul(&t4); //6 - t4.copy(&t0); - t4.add(&t1); //7 - t3.sub(&t4); - t3.norm(); //8 - t4.copy(&self.y); - t4.add(&self.z); - t4.norm(); //9 - x3.add(&Q.z); - x3.norm(); //10 - t4.mul(&x3); //11 - x3.copy(&t1); - x3.add(&t2); //12 - - t4.sub(&x3); - t4.norm(); //13 - x3.copy(&self.x); - x3.add(&self.z); - x3.norm(); //14 - y3.add(&Q.z); - y3.norm(); //15 - - x3.mul(&y3); //16 - y3.copy(&t0); - y3.add(&t2); //17 - - y3.rsub(&x3); - y3.norm(); //18 - z3.copy(&t2); - - if rom::CURVE_B_I == 0 { - z3.mul(&b); //18 - } else { - z3.imul(rom::CURVE_B_I); - } - - x3.copy(&y3); - x3.sub(&z3); - x3.norm(); //20 - z3.copy(&x3); - z3.add(&x3); //21 - - x3.add(&z3); //22 - z3.copy(&t1); - z3.sub(&x3); - z3.norm(); //23 - x3.add(&t1); - x3.norm(); //24 - - if rom::CURVE_B_I == 0 { - y3.mul(&b); //18 - } else { - y3.imul(rom::CURVE_B_I); - } - - t1.copy(&t2); - t1.add(&t2); //t1.norm();//26 - t2.add(&t1); //27 - - y3.sub(&t2); //28 - - y3.sub(&t0); - y3.norm(); //29 - t1.copy(&y3); - t1.add(&y3); //30 - y3.add(&t1); - y3.norm(); //31 - - t1.copy(&t0); - t1.add(&t0); //32 - t0.add(&t1); //33 - t0.sub(&t2); - t0.norm(); //34 - t1.copy(&t4); - t1.mul(&y3); //35 - t2.copy(&t0); - t2.mul(&y3); //36 - y3.copy(&x3); - y3.mul(&z3); //37 - y3.add(&t2); //y3.norm();//38 - x3.mul(&t3); //39 - x3.sub(&t1); //40 - z3.mul(&t4); //41 - t1.copy(&t3); - t1.mul(&t0); //42 - z3.add(&t1); - self.x.copy(&x3); - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - self.z.copy(&z3); - self.z.norm(); - } - } - if CURVETYPE == EDWARDS { - let bb = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); - let mut a = FP::new_copy(&self.z); - let mut b = FP::new(); - let mut c = FP::new_copy(&self.x); - let mut d = FP::new_copy(&self.y); - let mut e = FP::new(); - let mut f = FP::new(); - let mut g = FP::new(); - - a.mul(&Q.z); - b.copy(&a); - b.sqr(); - c.mul(&Q.x); - d.mul(&Q.y); - - e.copy(&c); - e.mul(&d); - e.mul(&bb); - f.copy(&b); - f.sub(&e); - g.copy(&b); - g.add(&e); - - if CURVE_A == 1 { - e.copy(&d); - e.sub(&c); - } - c.add(&d); - - b.copy(&self.x); - b.add(&self.y); - d.copy(&Q.x); - d.add(&Q.y); - b.norm(); - d.norm(); - b.mul(&d); - b.sub(&c); - b.norm(); - f.norm(); - b.mul(&f); - self.x.copy(&a); - self.x.mul(&b); - g.norm(); - if CURVE_A == 1 { - e.norm(); - c.copy(&e); - c.mul(&g); - } - if CURVE_A == -1 { - c.norm(); - c.mul(&g); - } - self.y.copy(&a); - self.y.mul(&c); - self.z.copy(&f); - self.z.mul(&g); - } - } - - /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ - pub fn dadd(&mut self, Q: &ECP, W: &ECP) { - let mut a = FP::new_copy(&self.x); - let mut b = FP::new_copy(&self.x); - let mut c = FP::new_copy(&Q.x); - let mut d = FP::new_copy(&Q.x); - let mut da = FP::new(); - let mut cb = FP::new(); - - a.add(&self.z); - b.sub(&self.z); - - c.add(&Q.z); - d.sub(&Q.z); - - a.norm(); - d.norm(); - - da.copy(&d); - da.mul(&a); - - c.norm(); - b.norm(); - - cb.copy(&c); - cb.mul(&b); - - a.copy(&da); - a.add(&cb); - a.norm(); - a.sqr(); - b.copy(&da); - b.sub(&cb); - b.norm(); - b.sqr(); - - self.x.copy(&a); - self.z.copy(&W.x); - self.z.mul(&b); - } - - /* self-=Q */ - pub fn sub(&mut self, Q: &ECP) { - let mut NQ = ECP::new(); - NQ.copy(Q); - NQ.neg(); - self.add(&NQ); - } - - /* constant time multiply by small integer of length bts - use ladder */ - pub fn pinmul(&self, e: i32, bts: i32) -> ECP { - if CURVETYPE == MONTGOMERY { - self.mul(&BIG::new_int(e as isize)) - } else { - let mut P = ECP::new(); - let mut R0 = ECP::new(); - let mut R1 = ECP::new(); - R1.copy(&self); - - for i in (0..bts).rev() { - let b = ((e >> i) & 1) as isize; - P.copy(&R1); - P.add(&R0); - R0.cswap(&mut R1, b); - R1.copy(&P); - R0.dbl(); - R0.cswap(&mut R1, b); - } - P.copy(&R0); - P - } - } - -// Point multiplication, multiplies a point P by a scalar e -// This code has no inherent awareness of the order of the curve, or the order of the point. -// The order of the curve will be h.r, where h is a cofactor, and r is a large prime -// Typically P will be of order r (but not always), and typically e will be less than r (but not always) -// A problem can arise if a secret e is a few bits less than r, as the leading zeros in e will leak via a timing attack -// The secret e may however be greater than r (see RFC7748 which combines elimination of a small cofactor h with the point multiplication, using an e>r) -// Our solution is to use as a multiplier an e, whose length in bits is that of the logical OR of e and r, hence allowing e>r while forcing inclusion of leading zeros if e ECP { - return self.clmul(e,e); - } - -// .. but this one does not (typically set maxe=r) -// Set P=e*P - pub fn clmul(&self, e: &BIG, maxe: &BIG) -> ECP { - if e.iszilch() || self.is_infinity() { - return ECP::new(); - } - let mut P = ECP::new(); - let mut cm = BIG::new_copy(e); cm.or(maxe); - let max=cm.nbits(); - - if CURVETYPE == MONTGOMERY { - /* use Ladder */ - let mut D = ECP::new(); - let mut R0 = ECP::new(); - R0.copy(&self); - let mut R1 = ECP::new(); - R1.copy(&self); - R1.dbl(); - D.copy(&self); D.affine(); - let nb = max; - - for i in (0..nb - 1).rev() { - let b = e.bit(i); - P.copy(&R1); - P.dadd(&R0, &D); - R0.cswap(&mut R1, b); - R1.copy(&P); - R0.dbl(); - R0.cswap(&mut R1, b); - } - P.copy(&R0) - } else { - // fixed size windows - let mut mt = BIG::new(); - let mut t = BIG::new(); - let mut Q = ECP::new(); - let mut C = ECP::new(); - - let mut W: [ECP; 8] = [ - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ]; - - const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; - let mut w: [i8; CT] = [0; CT]; - - Q.copy(&self); - Q.dbl(); - - W[0].copy(&self); - - for i in 1..8 { - C.copy(&W[i - 1]); - W[i].copy(&C); - W[i].add(&Q); - } - - // make exponent odd - add 2P if even, P if odd - t.copy(&e); - let s = t.parity(); - t.inc(1); - t.norm(); - let ns = t.parity(); - mt.copy(&t); - mt.inc(1); - mt.norm(); - t.cmove(&mt, s); - Q.cmove(&self, ns); - C.copy(&Q); - - let nb = 1 + (max + 3) / 4; - - // convert exponent to signed 4-bit window - for i in 0..nb { - w[i] = (t.lastbits(5) - 16) as i8; - t.dec(w[i] as isize); - t.norm(); - t.fshr(4); - } - w[nb] = t.lastbits(5) as i8; - - //P.copy(&W[((w[nb] as usize) - 1) / 2]); - - P.selector(&W, w[nb] as i32); - for i in (0..nb).rev() { - Q.selector(&W, w[i] as i32); - P.dbl(); - P.dbl(); - P.dbl(); - P.dbl(); - P.add(&Q); - } - P.sub(&C); /* apply correction */ - } - P - } - -// Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i - pub fn muln(n: usize, X: &[ECP], e: &[BIG]) -> ECP { - let mut B: [ECP; 16] = [ - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ]; - let mut mt = BIG::new(); - let mut t = BIG::new(); - let mut P = ECP::new(); - let mut S = ECP::new(); - let mut R = ECP::new(); - - mt.copy(&e[0]); mt.norm(); - for i in 1..n { // find biggest - t.copy(&e[i]); t.norm(); - let k=BIG::comp(&t,&mt); - mt.cmove(&t,(k+1)/2); - } - let nb=(mt.nbits()+3)/4; - for i in (0..nb).rev() { // Pippenger's algorithm - for j in 0..16 { - B[j].inf(); - } - for j in 0..n { - mt.copy(&e[j]); mt.norm(); - mt.shr((i*4) as usize); - let k=mt.lastbits(4) as usize; - B[k].add(&X[j]); - } - R.inf(); S.inf(); - for j in (1..16).rev() { - R.add(&B[j]); - S.add(&R); - } - for _ in 0..4 { - P.dbl(); - } - P.add(&S); - } - P - } - - /* Return e.this+f.Q */ - - pub fn mul2(&self, e: &BIG, Q: &ECP, f: &BIG) -> ECP { - let mut te = BIG::new(); - let mut tf = BIG::new(); - let mut mt = BIG::new(); - let mut S = ECP::new(); - let mut T = ECP::new(); - let mut C = ECP::new(); - - let mut W: [ECP; 8] = [ - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ECP::new(), - ]; - - const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 1) / 2; - let mut w: [i8; CT] = [0; CT]; - - te.copy(e); - tf.copy(f); - - // precompute table - - W[1].copy(&self); - W[1].sub(Q); - W[2].copy(&self); - W[2].add(Q); - S.copy(&Q); - S.dbl(); - C.copy(&W[1]); - W[0].copy(&C); - W[0].sub(&S); // copy to C is stupid Rust thing.. - C.copy(&W[2]); - W[3].copy(&C); - W[3].add(&S); - T.copy(&self); - T.dbl(); - C.copy(&W[1]); - W[5].copy(&C); - W[5].add(&T); - C.copy(&W[2]); - W[6].copy(&C); - W[6].add(&T); - C.copy(&W[5]); - W[4].copy(&C); - W[4].sub(&S); - C.copy(&W[6]); - W[7].copy(&C); - W[7].add(&S); - - // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction - - let mut s = te.parity(); - te.inc(1); - te.norm(); - let mut ns = te.parity(); - mt.copy(&te); - mt.inc(1); - mt.norm(); - te.cmove(&mt, s); - T.cmove(&self, ns); - C.copy(&T); - - s = tf.parity(); - tf.inc(1); - tf.norm(); - ns = tf.parity(); - mt.copy(&tf); - mt.inc(1); - mt.norm(); - tf.cmove(&mt, s); - S.cmove(&Q, ns); - C.add(&S); - - mt.copy(&te); - mt.add(&tf); - mt.norm(); - let nb = 1 + (mt.nbits() + 1) / 2; - - // convert exponent to signed 2-bit window - for i in 0..nb { - let a = te.lastbits(3) - 4; - te.dec(a); - te.norm(); - te.fshr(2); - let b = tf.lastbits(3) - 4; - tf.dec(b); - tf.norm(); - tf.fshr(2); - w[i] = (4 * a + b) as i8; - } - w[nb] = (4 * te.lastbits(3) + tf.lastbits(3)) as i8; - //S.copy(&W[((w[nb] as usize) - 1) / 2]); - S.selector(&W, w[nb] as i32); - - for i in (0..nb).rev() { - T.selector(&W, w[i] as i32); - S.dbl(); - S.dbl(); - S.add(&T); - } - S.sub(&C); /* apply correction */ - S - } - - pub fn cfp(&mut self) { - let cf = rom::CURVE_COF_I; - if cf == 1 { - return; - } - if cf == 4 { - self.dbl(); - self.dbl(); - return; - } - if cf == 8 { - self.dbl(); - self.dbl(); - self.dbl(); - return; - } - let c = BIG::new_ints(&rom::CURVE_COF); - let P = self.mul(&c); - self.copy(&P); - } - -/* Hunt and Peck a BIG to a curve point */ - #[allow(non_snake_case)] - pub fn hap2point(h: &BIG) -> ECP { - let mut P: ECP; - let mut x =BIG::new_copy(&h); - loop { - if CURVETYPE != MONTGOMERY { - P = ECP::new_bigint(&x, 0); - } else { - P = ECP::new_big(&x); - } - x.inc(1); - x.norm(); - if !P.is_infinity() { - break; - } - } - P - } - -/* Constant time Map to Point */ - #[allow(non_snake_case)] - pub fn map2point(h: &FP) -> ECP { - let mut P = ECP::new(); - - if CURVETYPE == MONTGOMERY { - // Elligator 2 - let mut X1=FP::new(); - let mut X2=FP::new(); - let mut t =FP::new_copy(h); - let mut w =FP::new(); - let one=FP::new_int(1); - let A=FP::new_int(CURVE_A); - let mut N =FP::new(); - let mut D =FP::new(); - let mut hint =FP::new(); - - t.sqr(); // t^2 - - if fp::PM1D2 == 2 { - t.dbl(); // 2t^2 - } - if fp::PM1D2 == 1 { - t.neg(); // -t^2 - } - if fp::PM1D2 > 2 { - t.imul(fp::QNRI as isize); // precomputed QNR - } - - t.norm(); - D.copy(&t); D.add(&one); D.norm(); // Denominator D=1+z.t^2 - - X1.copy(&A); - X1.neg(); X1.norm(); // X1=-A/D - X2.copy(&X1); - X2.mul(&t); // X2=-At/D - - w.copy(&X1); w.sqr(); N.copy(&w); N.mul(&X1); - w.mul(&A); w.mul(&D); N.add(&w); - t.copy(&D); t.sqr(); - t.mul(&X1); - N.add(&t); N.norm(); // Numerator=x^3+ADx^2+D^2x - - t.copy(&N); t.mul(&D); // N*D - let qres=t.qr(Some(&mut hint)); // only exp - w.copy(&t); w.inverse(Some(&hint)); - D.copy(&w); D.mul(&N); // 1/D - X1.mul(&D); // get X1 - X2.mul(&D); // get X2 - X1.cmove(&X2,1-qres); - - let a=X1.redc(); - P.copy(&ECP::new_big(&a)); - - } - if CURVETYPE == EDWARDS { -// Elligator 2 - map to Montgomery, place point, map back - let mut X1=FP::new(); - let mut X2=FP::new(); - let mut t=FP::new_copy(h); - let mut w=FP::new(); - let one=FP::new_int(1); - let mut A=FP::new(); - let mut w1=FP::new(); - let mut w2=FP::new(); - let mut B = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); - let mut Y=FP::new(); - let mut K=FP::new(); - let mut D=FP::new(); - let mut hint=FP::new(); - //let mut Y3=FP::new(); - let rfc: isize; - - if fp::MODTYPE != fp::GENERALISED_MERSENNE { - A.copy(&B); - if CURVE_A==1 { - A.add(&one); // A=B+1 - B.sub(&one); // B=B-1 - } else { - A.sub(&one); // A=B-1 - B.add(&one); // B=B+1 - } - A.norm(); B.norm(); - - A.div2(); // (A+B)/2 = J/K - B.div2(); // (B-A)/2 - B.div2(); // (B-A)/4 = -1/K - - K.copy(&B); - K.neg(); K.norm(); - - K.invsqrt(&mut w2,&mut w1); // return K, sqrt(1/K) - could be precalculated! - K.copy(&w2); - rfc=fp::RIADZ; - if rfc==1 { - A.mul(&K); - K.mul(&w1); - } else { - B.sqr(); - } - } else { - rfc=1; - A.copy(&FP::new_int(156326)); - } -// Map to this Montgomery curve X^2=X^3+AX^2+BX - t.sqr(); // t^2 - let mut qnr=0; - if fp::PM1D2 == 2 { - t.dbl(); - qnr=2; - } - if fp::PM1D2 == 1 { - t.neg(); - qnr = -1; - } - if fp::PM1D2 > 2 { - t.imul(fp::QNRI as isize); // precomputed QNR - qnr=fp::QNRI as isize; - } - t.norm(); - - D.copy(&t); D.add(&one); D.norm(); // Denominator=(1+z.u^2) - X1.copy(&A); - X1.neg(); X1.norm(); // X1=-(J/K).inv(1+z.u^2) - X2.copy(&X1); X2.mul(&t); // X2=X1*z*u^2 - -// Figure out RHS of Montgomery curve in rational form gx1/d^3 - - w.copy(&X1); w.sqr(); w1.copy(&w); w1.mul(&X1); - w.mul(&A); w.mul(&D); w1.add(&w); - w2.copy(&D); w2.sqr(); - - if rfc==0 { - w.copy(&X1); w.mul(&B); - w2.mul(&w); - w1.add(&w2); // w1=X1^3+ADX1^2+BD^2X1 - } else { - w2.mul(&X1); - w1.add(&w2); // w1=X1^3+ADX1^2+D^2X1 - } - w1.norm(); - - B.copy(&w1); B.mul(&D); // gx1=num/den^3 - is_qr num*den (same as num/den, same as num/den^3) - let qres=B.qr(Some(&mut hint)); // Exponentiation - w.copy(&B); w.inverse(Some(&hint)); - D.copy(&w); D.mul(&w1); // 1/D - X1.mul(&D); // get X1 - X2.mul(&D); // get X2 - D.sqr(); - - w1.copy(&B); w1.imul(qnr); - w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); - w.mul(&hint); - w2.copy(&D); w2.mul(&h); - - X1.cmove(&X2,1-qres); - B.cmove(&w1,1-qres); - hint.cmove(&w,1-qres); - D.cmove(&w2,1-qres); - - Y.copy(&B.sqrt(Some(&hint))); - Y.mul(&D); -/* - Y.copy(&B.sqrt(Some(&hint))); // sqrt(num*den) - Y.mul(&D); // sqrt(num/den^3) - - B.imul(qnr); // now for gx2 = Z.u^2.gx1 - w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); // qnr^C3 - hint.mul(&w); // modify hint for gx2 - - Y3.copy(&B.sqrt(Some(&hint))); // second candidate - D.mul(&h); - Y3.mul(&D); - - X1.cmove(&X2,1-qres); // pick correct one - Y.cmove(&Y3,1-qres); -*/ -// correct sign of Y - w.copy(&Y); w.neg(); w.norm(); - Y.cmove(&w,qres^Y.sign()); - - if rfc==0 { - X1.mul(&K); - Y.mul(&K); - } - - if fp::MODTYPE == fp::GENERALISED_MERSENNE { - // GOLDILOCKS isogeny - t.copy(&X1); t.sqr(); - w.copy(&t); w.add(&one); w.norm(); - t.sub(&one); t.norm(); - w1.copy(&t); w1.mul(&Y); - w1.dbl(); X2.copy(&w1); X2.add(&w1); X2.norm(); - t.sqr(); - Y.sqr(); Y.dbl(); Y.dbl(); Y.norm(); - B.copy(&t); B.add(&Y); B.norm(); - - w2.copy(&Y); w2.sub(&t); w2.norm(); - w2.mul(&X1); - t.mul(&X1); - Y.div2(); - w1.copy(&Y); w1.mul(&w); - w1.rsub(&t); w1.norm(); - - t.copy(&X2); t.mul(&w1); // output in projective to avoid inversion - P.x.copy(&t); - t.copy(&w2); t.mul(&B); - P.y.copy(&t); - t.copy(&w1); t.mul(&B); - P.z.copy(&t); - - return P; - } else { - w1.copy(&X1); w1.add(&one); w1.norm(); // s+1 - w2.copy(&X1); w2.sub(&one); w2.norm(); // s-1 - t.copy(&w1); t.mul(&Y); - X1.mul(&w1); - - if rfc==1 { - X1.mul(&K); - } - Y.mul(&w2); // output in projective to avoid inversion - P.x.copy(&X1); - P.y.copy(&Y); - P.z.copy(&t); - - return P - } - } - if CURVETYPE==WEIERSTRASS { - // SSWU or SVDW method - let mut A=FP::new(); - let mut B=FP::new(); - let mut X1=FP::new(); - let mut X2=FP::new(); - let mut X3=FP::new(); - let one=FP::new_int(1); - let mut Y=FP::new(); - let mut D=FP::new(); - let mut t=FP::new_copy(h); - let mut w=FP::new(); - let mut D2=FP::new(); - let mut hint=FP::new(); - let mut GX1=FP::new(); - //let mut Y3=FP::new(); - - let sgn=t.sign(); - - if CURVE_A != 0 || HTC_ISO != 0 - { // Map to point on isogenous curve - if HTC_ISO != 0 { -/* CAHCZS - A.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_AD))); - B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_BD))); -CAHCZF */ - } else { - A.copy(&FP::new_int(CURVE_A)); - B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B))); - } - // SSWU Method - t.sqr(); - t.imul(fp::RIADZ); // Z from hash-to-point draft standard - w.copy(&t); w.add(&one); w.norm(); - - w.mul(&t); D.copy(&A); - D.mul(&w); - - w.add(&one); w.norm(); - w.mul(&B); - w.neg(); w.norm(); - - X2.copy(&w); - X3.copy(&t); X3.mul(&X2); - -// x^3+Ad^2x+Bd^3 - GX1.copy(&X2); GX1.sqr(); D2.copy(&D); - D2.sqr(); w.copy(&A); w.mul(&D2); GX1.add(&w); GX1.norm(); GX1.mul(&X2); D2.mul(&D); w.copy(&B); w.mul(&D2); GX1.add(&w); GX1.norm(); - - w.copy(&GX1); w.mul(&D); - let qr=w.qr(Some(&mut hint)); - D.copy(&w); D.inverse(Some(&hint)); - D.mul(&GX1); - X2.mul(&D); - X3.mul(&D); - t.mul(h); - D2.copy(&D); D2.sqr(); - - D.copy(&D2); D.mul(&t); - t.copy(&w); t.imul(fp::RIADZ); - X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); - X1.mul(&hint); - - X2.cmove(&X3,1-qr); - D2.cmove(&D,1-qr); - w.cmove(&t,1-qr); - hint.cmove(&X1,1-qr); - - Y.copy(&w.sqrt(Some(&hint))); - Y.mul(&D2); -/* - Y.copy(&w.sqrt(Some(&hint))); - Y.mul(&D2); - - D2.mul(&t); - w.imul(fp::RIADZ); - - X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC))); - hint.mul(&X1); - - Y3.copy(&w.sqrt(Some(&hint))); - Y3.mul(&D2); - - X2.cmove(&X3,1-qr); - Y.cmove(&Y3,1-qr); -*/ - let ne=Y.sign()^sgn; - w.copy(&Y); w.neg(); w.norm(); - Y.cmove(&w,ne); - - if HTC_ISO != 0 { - -/* CAHCZS - let mut k=0; - let isox=HTC_ISO; - let isoy=3*(isox-1)/2; - // xnum - let mut xnum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; - for _ in 0..isox { - xnum.mul(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - xnum.add(&w); xnum.norm(); - } - // xden - let mut xden=FP::new_copy(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - xden.add(&w); xden.norm(); - for _ in 0..isox-2 { - xden.mul(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - xden.add(&w); xden.norm(); - } - // ynum - let mut ynum=FP::new_big(&BIG::new_ints(&rom::PC[k])); k+=1; - for _ in 0..isoy { - ynum.mul(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - ynum.add(&w); ynum.norm(); - } - // yden - let mut yden=FP::new_copy(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - yden.add(&w); yden.norm(); - for _ in 0..isoy-1 { - yden.mul(&X2); - w.copy(&FP::new_big(&BIG::new_ints(&rom::PC[k]))); k+=1; - yden.add(&w); yden.norm(); - } - ynum.mul(&Y); - w.copy(&xnum); w.mul(&yden); - P.x.copy(&w); - w.copy(&ynum); w.mul(&xden); - P.y.copy(&w); - w.copy(&xden); w.mul(&yden); - P.z.copy(&w); - return P; -CAHCZF */ - } else { - let x=X2.redc(); - let y=Y.redc(); - P.copy(&ECP::new_bigs(&x,&y)); - return P; - } - } else { -// Shallue and van de Woestijne -// SQRTM3 not available, so preprocess this out -/* */ - let Z=fp::RIADZ; - X1.copy(&FP::new_int(Z)); - X3.copy(&X1); - A.copy(&ECP::rhs(&X1)); - B.copy(&FP::new_big(&BIG::new_ints(&rom::SQRTM3))); - B.imul(Z); - - t.sqr(); - Y.copy(&A); Y.mul(&t); - t.copy(&one); t.add(&Y); t.norm(); - Y.rsub(&one); Y.norm(); - D.copy(&t); D.mul(&Y); - D.mul(&B); - - w.copy(&A); - FP::tpo(&mut D,&mut w); - - w.mul(&B); - if w.sign()==1 { - w.neg(); - w.norm(); - } - w.mul(&B); - w.mul(&h); w.mul(&Y); w.mul(&D); - - X1.neg(); X1.norm(); X1.div2(); - X2.copy(&X1); - X1.sub(&w); X1.norm(); - X2.add(&w); X2.norm(); - A.dbl(); A.dbl(); A.norm(); - t.sqr(); t.mul(&D); t.sqr(); - A.mul(&t); - X3.add(&A); X3.norm(); - - let mut rhs=ECP::rhs(&X2); - X3.cmove(&X2,rhs.qr(None)); - rhs.copy(&ECP::rhs(&X1)); - X3.cmove(&X1,rhs.qr(None)); - rhs.copy(&ECP::rhs(&X3)); - Y.copy(&rhs.sqrt(None)); - - let ne=Y.sign()^sgn; - w.copy(&Y); w.neg(); w.norm(); - Y.cmove(&w,ne); - - let x=X3.redc(); - let y=Y.redc(); - P.copy(&ECP::new_bigs(&x,&y)); - return P; -/* */ - } - } - P - } - -/* Map byte string to curve point */ - #[allow(non_snake_case)] - pub fn mapit(h: &[u8]) -> ECP { - let q = BIG::new_ints(&rom::MODULUS); - let mut dx = DBIG::frombytes(h); - let x=dx.dmod(&q); - let mut P=ECP::hap2point(&x); - P.cfp(); - P - } - - pub fn generator() -> ECP { - let G: ECP; - let gx = BIG::new_ints(&rom::CURVE_GX); - if CURVETYPE != MONTGOMERY { - let gy = BIG::new_ints(&rom::CURVE_GY); - G = ECP::new_bigs(&gx, &gy); - } else { - G = ECP::new_big(&gx); - } - G - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs deleted file mode 100644 index 09c66c6bcd9a..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/ecp2.rs +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::ecp; -use crate::bn254::fp2::FP2; -use crate::bn254::rom; -use crate::bn254::fp; -use crate::bn254::fp::FP; -use crate::bn254::dbig::DBIG; - -#[derive(Clone)] -pub struct ECP2 { - x: FP2, - y: FP2, - z: FP2, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for ECP2 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for ECP2 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[allow(non_snake_case)] -impl ECP2 { - pub fn new() -> ECP2 { - ECP2 { - x: FP2::new(), - y: FP2::new_int(1), - z: FP2::new(), - } - } - #[allow(non_snake_case)] - /* construct this from (x,y) - but set to O if not on curve */ - pub fn new_fp2s(ix: &FP2, iy: &FP2) -> ECP2 { - let mut E = ECP2::new(); - E.x.copy(&ix); - E.y.copy(&iy); - E.z.one(); - E.x.norm(); - - let rhs = ECP2::rhs(&E.x); - let mut y2 = FP2::new_copy(&E.y); - y2.sqr(); - if !y2.equals(&rhs) { - E.inf(); - } - E - } - - /* construct this from x - but set to O if not on curve */ - pub fn new_fp2(ix: &FP2, s:isize) -> ECP2 { - let mut E = ECP2::new(); - let mut h = FP::new(); - E.x.copy(&ix); - E.y.one(); - E.z.one(); - E.x.norm(); - let mut rhs = ECP2::rhs(&E.x); - if rhs.qr(Some(&mut h)) == 1 { - rhs.sqrt(Some(&h)); - if rhs.sign() != s { - rhs.neg(); - } - rhs.reduce(); - E.y.copy(&rhs); - } else { - E.inf(); - } - E - } - - /* Test this=O? */ - pub fn is_infinity(&self) -> bool { - self.x.iszilch() && self.z.iszilch() - } - - /* copy self=P */ - pub fn copy(&mut self, P: &ECP2) { - self.x.copy(&P.x); - self.y.copy(&P.y); - self.z.copy(&P.z); - } - - /* set self=O */ - pub fn inf(&mut self) { - self.x.zero(); - self.y.one(); - self.z.zero(); - } - - /* set self=-self */ - pub fn neg(&mut self) { - self.y.norm(); - self.y.neg(); - self.y.norm(); - } - - /* Conditional move of Q to self dependant on d */ - pub fn cmove(&mut self, Q: &ECP2, d: isize) { - self.x.cmove(&Q.x, d); - self.y.cmove(&Q.y, d); - self.z.cmove(&Q.z, d); - } - - /* return 1 if b==c, no branching */ - fn teq(b: i32, c: i32) -> isize { - let mut x = b ^ c; - x -= 1; // if x=0, x now -1 - ((x >> 31) & 1) as isize - } - - /* Constant time select from pre-computed table */ - pub fn selector(&mut self, W: &[ECP2], b: i32) { - let mut MP = ECP2::new(); - let m = b >> 31; - let mut babs = (b ^ m) - m; - - babs = (babs - 1) / 2; - - self.cmove(&W[0], ECP2::teq(babs, 0)); // conditional move - self.cmove(&W[1], ECP2::teq(babs, 1)); - self.cmove(&W[2], ECP2::teq(babs, 2)); - self.cmove(&W[3], ECP2::teq(babs, 3)); - self.cmove(&W[4], ECP2::teq(babs, 4)); - self.cmove(&W[5], ECP2::teq(babs, 5)); - self.cmove(&W[6], ECP2::teq(babs, 6)); - self.cmove(&W[7], ECP2::teq(babs, 7)); - - MP.copy(self); - MP.neg(); - self.cmove(&MP, (m & 1) as isize); - } - - /* Test if P == Q */ - pub fn equals(&self, Q: &ECP2) -> bool { - let mut a = FP2::new_copy(&self.x); - let mut b = FP2::new_copy(&Q.x); - - a.mul(&Q.z); - b.mul(&self.z); - if !a.equals(&b) { - return false; - } - a.copy(&self.y); - a.mul(&Q.z); - b.copy(&Q.y); - b.mul(&self.z); - if !a.equals(&b) { - return false; - } - - true - } - - /* set to Affine - (x,y,z) to (x,y) */ - pub fn affine(&mut self) { - if self.is_infinity() { - return; - } - let one = FP2::new_int(1); - if self.z.equals(&one) { - return; - } - self.z.inverse(None); - - self.x.mul(&self.z); - self.x.reduce(); - self.y.mul(&self.z); - self.y.reduce(); - self.z.copy(&one); - } - - /* extract affine x as FP2 */ - pub fn getx(&self) -> FP2 { - let mut W = ECP2::new(); - W.copy(self); - W.affine(); - FP2::new_copy(&W.x) - } - - /* extract affine y as FP2 */ - pub fn gety(&self) -> FP2 { - let mut W = ECP2::new(); - W.copy(self); - W.affine(); - FP2::new_copy(&W.y) - } - - /* extract projective x */ - pub fn getpx(&self) -> FP2 { - FP2::new_copy(&self.x) - } - /* extract projective y */ - pub fn getpy(&self) -> FP2 { - FP2::new_copy(&self.y) - } - /* extract projective z */ - pub fn getpz(&self) -> FP2 { - FP2::new_copy(&self.z) - } - - /* convert to byte array */ - pub fn tobytes(&self, b: &mut [u8], compress: bool) { - const MB:usize = 2*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - let mut alt=false; - let mut W = ECP2::new(); - W.copy(self); - W.affine(); - W.x.tobytes(&mut t); - - if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { - alt=true; - } - if alt { - for i in 0..MB { - b[i]=t[i] - } - if !compress { - W.y.tobytes(&mut t); - for i in 0..MB { - b[i+MB]=t[i]; - } - } else { - b[0]|=0x80; - if W.y.islarger()==1 { - b[0]|=0x20; - } - } - - } else { - for i in 0..MB { - b[i+1]=t[i]; - } - if !compress { - b[0]=0x04; - W.y.tobytes(&mut t); - for i in 0..MB { - b[i+MB+1]=t[i]; - } - } else { - b[0]=0x02; - if W.y.sign() == 1 { - b[0]=0x03; - } - } - } - } - - /* convert from byte array to point */ - pub fn frombytes(b: &[u8]) -> ECP2 { - const MB:usize = 2*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - let typ=b[0] as isize; - let mut alt=false; - - if (fp::MODBITS-1)%8 <= 4 && ecp::ALLOW_ALT_COMPRESS { - alt=true; - } - - if alt { - for i in 0..MB { - t[i]=b[i]; - } - t[0]&=0x1f; - let rx=FP2::frombytes(&t); - if (b[0]&0x80)==0 { - for i in 0..MB { - t[i]=b[i+MB]; - } - let ry=FP2::frombytes(&t); - ECP2::new_fp2s(&rx,&ry) - } else { - let sgn=(b[0]&0x20)>>5; - let mut P=ECP2::new_fp2(&rx,0); - let cmp=P.y.islarger(); - if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) { - P.neg(); - } - P - } - } else { - for i in 0..MB { - t[i]=b[i+1]; - } - let rx=FP2::frombytes(&t); - if typ == 0x04 { - for i in 0..MB { - t[i]=b[i+MB+1]; - } - let ry=FP2::frombytes(&t); - ECP2::new_fp2s(&rx,&ry) - } else { - ECP2::new_fp2(&rx,typ&1) - } - } - } - - /* convert this to hex string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - let mut W = ECP2::new(); - W.copy(self); - W.affine(); - if W.is_infinity() { - String::from("infinity") - } else { - format!("({},{})", W.x.tostring(), W.y.tostring()) - } - } - - /* Calculate RHS of twisted curve equation x^3+B/i */ - pub fn rhs(x: &FP2) -> FP2 { - let mut r = FP2::new_copy(x); - r.sqr(); - let mut b = FP2::new_big(&BIG::new_ints(&rom::CURVE_B)); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - b.div_ip(); - } - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - b.norm(); - b.mul_ip(); - b.norm(); - } - - r.mul(x); - r.add(&b); - - r.reduce(); - r - } - - /* self+=self */ - pub fn dbl(&mut self) -> isize { - let mut iy = FP2::new_copy(&self.y); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - iy.mul_ip(); - iy.norm(); - } - - let mut t0 = FP2::new_copy(&self.y); //***** Change - t0.sqr(); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - t0.mul_ip(); - } - let mut t1 = FP2::new_copy(&iy); - t1.mul(&self.z); - let mut t2 = FP2::new_copy(&self.z); - t2.sqr(); - - self.z.copy(&t0); - self.z.add(&t0); - self.z.norm(); - self.z.dbl(); - self.z.dbl(); - self.z.norm(); - - t2.imul(3 * rom::CURVE_B_I); - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - t2.mul_ip(); - t2.norm(); - } - let mut x3 = FP2::new_copy(&t2); - x3.mul(&self.z); - - let mut y3 = FP2::new_copy(&t0); - - y3.add(&t2); - y3.norm(); - self.z.mul(&t1); - t1.copy(&t2); - t1.add(&t2); - t2.add(&t1); - t2.norm(); - t0.sub(&t2); - t0.norm(); //y^2-9bz^2 - y3.mul(&t0); - y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 - t1.copy(&self.x); - t1.mul(&iy); // - self.x.copy(&t0); - self.x.norm(); - self.x.mul(&t1); - self.x.dbl(); //(y^2-9bz^2)xy2 - - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - - 1 - } - - /* self+=Q - return 0 for add, 1 for double, -1 for O */ - pub fn add(&mut self, Q: &ECP2) -> isize { - let b = 3 * rom::CURVE_B_I; - let mut t0 = FP2::new_copy(&self.x); - t0.mul(&Q.x); // x.Q.x - let mut t1 = FP2::new_copy(&self.y); - t1.mul(&Q.y); // y.Q.y - - let mut t2 = FP2::new_copy(&self.z); - t2.mul(&Q.z); - let mut t3 = FP2::new_copy(&self.x); - t3.add(&self.y); - t3.norm(); //t3=X1+Y1 - let mut t4 = FP2::new_copy(&Q.x); - t4.add(&Q.y); - t4.norm(); //t4=X2+Y2 - t3.mul(&t4); //t3=(X1+Y1)(X2+Y2) - t4.copy(&t0); - t4.add(&t1); //t4=X1.X2+Y1.Y2 - - t3.sub(&t4); - t3.norm(); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - t3.mul_ip(); - t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 - } - t4.copy(&self.y); - t4.add(&self.z); - t4.norm(); //t4=Y1+Z1 - let mut x3 = FP2::new_copy(&Q.y); - x3.add(&Q.z); - x3.norm(); //x3=Y2+Z2 - - t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2) - x3.copy(&t1); // - x3.add(&t2); //X3=Y1.Y2+Z1.Z2 - - t4.sub(&x3); - t4.norm(); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - t4.mul_ip(); - t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 - } - x3.copy(&self.x); - x3.add(&self.z); - x3.norm(); // x3=X1+Z1 - let mut y3 = FP2::new_copy(&Q.x); - y3.add(&Q.z); - y3.norm(); // y3=X2+Z2 - x3.mul(&y3); // x3=(X1+Z1)(X2+Z2) - y3.copy(&t0); - y3.add(&t2); // y3=X1.X2+Z1+Z2 - y3.rsub(&x3); - y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 - - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - t0.mul_ip(); - t0.norm(); // x.Q.x - t1.mul_ip(); - t1.norm(); // y.Q.y - } - x3.copy(&t0); - x3.add(&t0); - t0.add(&x3); - t0.norm(); - t2.imul(b); - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - t2.mul_ip(); - t2.norm(); - } - let mut z3 = FP2::new_copy(&t1); - z3.add(&t2); - z3.norm(); - t1.sub(&t2); - t1.norm(); - y3.imul(b); - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - y3.mul_ip(); - y3.norm(); - } - x3.copy(&y3); - x3.mul(&t4); - t2.copy(&t3); - t2.mul(&t1); - x3.rsub(&t2); - y3.mul(&t0); - t1.mul(&z3); - y3.add(&t1); - t0.mul(&t3); - z3.mul(&t4); - z3.add(&t0); - - self.x.copy(&x3); - self.x.norm(); - self.y.copy(&y3); - self.y.norm(); - self.z.copy(&z3); - self.z.norm(); - - 0 - } - - /* set this-=Q */ - pub fn sub(&mut self, Q: &ECP2) -> isize { - let mut NQ = ECP2::new(); - NQ.copy(Q); - NQ.neg(); - self.add(&NQ) - } - - /* set this*=q, where q is Modulus, using Frobenius */ - pub fn frob(&mut self, x: &FP2) { - let mut x2 = FP2::new_copy(x); - x2.sqr(); - self.x.conj(); - self.y.conj(); - self.z.conj(); - self.z.reduce(); - self.x.mul(&x2); - self.y.mul(&x2); - self.y.mul(x); - } - - /* self*=e */ - pub fn mul(&self, e: &BIG) -> ECP2 { - /* fixed size windows */ - let mut mt = BIG::new(); - let mut t = BIG::new(); - let mut P = ECP2::new(); - let mut Q = ECP2::new(); - let mut C = ECP2::new(); - - if self.is_infinity() { - return P; - } - - let mut W: [ECP2; 8] = [ - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ]; - - const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; - let mut w: [i8; CT] = [0; CT]; - - /* precompute table */ - Q.copy(&self); - Q.dbl(); - - W[0].copy(&self); - - for i in 1..8 { - C.copy(&W[i - 1]); - W[i].copy(&C); - W[i].add(&Q); - } - - /* make exponent odd - add 2P if even, P if odd */ - t.copy(&e); - let s = t.parity(); - t.inc(1); - t.norm(); - let ns = t.parity(); - mt.copy(&t); - mt.inc(1); - mt.norm(); - t.cmove(&mt, s); - Q.cmove(&self, ns); - C.copy(&Q); - - let nb = 1 + (t.nbits() + 3) / 4; - - /* convert exponent to signed 4-bit window */ - for i in 0..nb { - w[i] = (t.lastbits(5) - 16) as i8; - t.dec(w[i] as isize); - t.norm(); - t.fshr(4); - } - w[nb] = (t.lastbits(5)) as i8; - - //P.copy(&W[((w[nb] as usize) - 1) / 2]); - - P.selector(&W, w[nb] as i32); - for i in (0..nb).rev() { - Q.selector(&W, w[i] as i32); - P.dbl(); - P.dbl(); - P.dbl(); - P.dbl(); - P.add(&Q); - } - P.sub(&C); - P - } - - #[allow(non_snake_case)] - pub fn cfp(&mut self) { - let mut X = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - X.inverse(None); - X.norm(); - } - let x = BIG::new_ints(&rom::CURVE_BNX); - // Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez - // Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))). - if ecp::CURVE_PAIRING_TYPE == ecp::BN { - let mut T = self.mul(&x); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - T.neg(); - } - let mut K = ECP2::new(); - K.copy(&T); - K.dbl(); - K.add(&T); - - K.frob(&X); - self.frob(&X); - self.frob(&X); - self.frob(&X); - self.add(&T); - self.add(&K); - T.frob(&X); - T.frob(&X); - self.add(&T); - } - // Efficient hash maps to G2 on BLS curves - Budroni, Pintore - // Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) - if ecp::CURVE_PAIRING_TYPE > ecp::BN { - let mut xQ = self.mul(&x); - let mut x2Q = xQ.mul(&x); - - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - xQ.neg(); - } - x2Q.sub(&xQ); - x2Q.sub(&self); - - xQ.sub(&self); - xQ.frob(&X); - - self.dbl(); - self.frob(&X); - self.frob(&X); - - self.add(&x2Q); - self.add(&xQ); - } - } - - - /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ - // Bos & Costello https://eprint.iacr.org/2013/458.pdf - // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf - // Side channel attack secure - - pub fn mul4(Q: &[ECP2], u: &[BIG]) -> ECP2 { - let mut W = ECP2::new(); - let mut P = ECP2::new(); - - let mut T: [ECP2; 8] = [ - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ECP2::new(), - ]; - - let mut mt = BIG::new(); - - let mut t: [BIG; 4] = [ - BIG::new_copy(&u[0]), - BIG::new_copy(&u[1]), - BIG::new_copy(&u[2]), - BIG::new_copy(&u[3]), - ]; - - const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); - let mut w: [i8; CT] = [0; CT]; - let mut s: [i8; CT] = [0; CT]; - - for i in 0..4 { - t[i].norm(); - } - - T[0].copy(&Q[0]); - W.copy(&T[0]); - T[1].copy(&W); - T[1].add(&Q[1]); // Q[0]+Q[1] - T[2].copy(&W); - T[2].add(&Q[2]); - W.copy(&T[1]); // Q[0]+Q[2] - T[3].copy(&W); - T[3].add(&Q[2]); - W.copy(&T[0]); // Q[0]+Q[1]+Q[2] - T[4].copy(&W); - T[4].add(&Q[3]); - W.copy(&T[1]); // Q[0]+Q[3] - T[5].copy(&W); - T[5].add(&Q[3]); - W.copy(&T[2]); // Q[0]+Q[1]+Q[3] - T[6].copy(&W); - T[6].add(&Q[3]); - W.copy(&T[3]); // Q[0]+Q[2]+Q[3] - T[7].copy(&W); - T[7].add(&Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] - - // Make it odd - let pb = 1 - t[0].parity(); - t[0].inc(pb); - t[0].norm(); - - // Number of bits - mt.zero(); - for i in 0..4 { - mt.or(&t[i]); - } - - let nb = 1 + mt.nbits(); - - // Sign pivot - - s[nb - 1] = 1; - for i in 0..nb - 1 { - t[0].fshr(1); - s[i] = (2 * t[0].parity() - 1) as i8; - } - - // Recoded exponent - for i in 0..nb { - w[i] = 0; - let mut k = 1; - for j in 1..4 { - let bt = s[i] * (t[j].parity() as i8); - t[j].fshr(1); - t[j].dec((bt >> 1) as isize); - t[j].norm(); - w[i] += bt * (k as i8); - k *= 2; - } - } - - // Main loop - P.selector(&T, (2 * w[nb - 1] + 1) as i32); - for i in (0..nb - 1).rev() { - P.dbl(); - W.selector(&T, (2 * w[i] + s[i]) as i32); - P.add(&W); - } - - // apply correction - W.copy(&P); - W.sub(&Q[0]); - P.cmove(&W, pb); - - P - } - -/* Hunt and Peck a BIG to a curve point */ - #[allow(non_snake_case)] - pub fn hap2point(h: &BIG) -> ECP2 { - let mut Q: ECP2; - let one = BIG::new_int(1); - let mut x =BIG::new_copy(&h); - loop { - let X = FP2::new_bigs(&one, &x); - Q = ECP2::new_fp2(&X,0); - if !Q.is_infinity() { - break; - } - x.inc(1); - x.norm(); - } - Q - } - -/* Constant time Map to Point */ - #[allow(unreachable_code)] - #[allow(non_snake_case)] - pub fn map2point(H: &FP2) -> ECP2 { - let mut T=FP2::new_copy(H); /**/ - let sgn=T.sign(); /**/ - if ecp::HTC_ISO_G2 == 0 { - // Shallue and van de Woestijne -/* */ - let mut NY=FP2::new_int(1); - let mut Z=FP::new_int(fp::RIADZG2A); - let mut X1=FP2::new_fp(&Z); - let mut X3=FP2::new_copy(&X1); - let mut A=ECP2::rhs(&X1); - let mut W=FP2::new_copy(&A); - - if fp::RIADZG2A==-1 && fp::RIADZG2B==0 && ecp::SEXTIC_TWIST == ecp::M_TYPE && rom::CURVE_B_I==4 { - W.copy(&FP2::new_ints(2,1)); - } else { - W.sqrt(None); - } - let s = FP::new_big(&BIG::new_ints(&rom::SQRTM3)); - Z.mul(&s); - - T.sqr(); - let mut Y=FP2::new_copy(&A); Y.mul(&T); - T.copy(&NY); T.add(&Y); T.norm(); - Y.rsub(&NY); Y.norm(); - NY.copy(&T); NY.mul(&Y); - - NY.pmul(&Z); - NY.inverse(None); - - W.pmul(&Z); - if W.sign()==1 { - W.neg(); - W.norm(); - } - W.pmul(&Z); - W.mul(&H); W.mul(&Y); W.mul(&NY); - - X1.neg(); X1.norm(); X1.div2(); - let mut X2=FP2::new_copy(&X1); - X1.sub(&W); X1.norm(); - X2.add(&W); X2.norm(); - A.dbl(); A.dbl(); A.norm(); - T.sqr(); T.mul(&NY); T.sqr(); - A.mul(&T); - X3.add(&A); X3.norm(); - - Y.copy(&ECP2::rhs(&X2)); - X3.cmove(&X2,Y.qr(None)); - Y.copy(&ECP2::rhs(&X1)); - X3.cmove(&X1,Y.qr(None)); - Y.copy(&ECP2::rhs(&X3)); - Y.sqrt(None); - - let ne=Y.sign()^sgn; - W.copy(&Y); W.neg(); W.norm(); - Y.cmove(&W,ne); - - return ECP2::new_fp2s(&X3,&Y); -/* */ - } else { -/* CAHCZS - let NY=FP2::new_int(1); - let Ad=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_ADR),&BIG::new_ints(&rom::CURVE_ADI)); - let Bd=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_BDR),&BIG::new_ints(&rom::CURVE_BDI)); - let ZZ=FP2::new_ints(fp::RIADZG2A,fp::RIADZG2B); - let mut hint=FP::new(); - - T.sqr(); - T.mul(&ZZ); - let mut W=FP2::new_copy(&T); - W.add(&NY); W.norm(); - - W.mul(&T); - let mut D=FP2::new_copy(&Ad); - D.mul(&W); - - W.add(&NY); W.norm(); - W.mul(&Bd); - W.neg(); W.norm(); - - let mut X2=FP2::new_copy(&W); - let mut X3=FP2::new_copy(&T); - X3.mul(&X2); - - let mut GX1=FP2::new_copy(&X2); GX1.sqr(); - let mut D2=FP2::new_copy(&D); D2.sqr(); - - W.copy(&Ad); W.mul(&D2); GX1.add(&W); GX1.norm(); GX1.mul(&X2); D2.mul(&D); W.copy(&Bd); W.mul(&D2); GX1.add(&W); GX1.norm(); // x^3+Ax+b - - W.copy(&GX1); W.mul(&D); - let qr=W.qr(Some(&mut hint)); - D.copy(&W); D.inverse(Some(&hint)); - D.mul(&GX1); - X2.mul(&D); - X3.mul(&D); - T.mul(&H); - D2.copy(&D); D2.sqr(); - - D.copy(&D2); D.mul(&T); - T.copy(&W); T.mul(&ZZ); - - let mut s=FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC2)); - s.mul(&hint); - - X2.cmove(&X3,1-qr); - W.cmove(&T,1-qr); - D2.cmove(&D,1-qr); - hint.cmove(&s,1-qr); - - let mut Y=FP2::new_copy(&W); Y.sqrt(Some(&hint)); - Y.mul(&D2); - - let ne=Y.sign()^sgn; - W.copy(&Y); W.neg(); W.norm(); - Y.cmove(&W,ne); - - let mut k=0; - let isox=ecp::HTC_ISO_G2; - let isoy=3*(isox-1)/2; - - // xnum - let mut xnum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; - for _ in 0..isox { - xnum.mul(&X2); - xnum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - xnum.norm(); - } - //xden - let mut xden=FP2::new_copy(&X2); - xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - xden.norm(); - for _ in 0..isox-2 { - xden.mul(&X2); - xden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - xden.norm(); - } - //ynum - let mut ynum=FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k])); k+=1; - for _ in 0..isoy { - ynum.mul(&X2); - ynum.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - ynum.norm(); - } - //yden - let mut yden=FP2::new_copy(&X2); - yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - yden.norm(); - for _ in 0..isoy-1 { - yden.mul(&X2); - yden.add(&FP2::new_bigs(&BIG::new_ints(&rom::PCR[k]),&BIG::new_ints(&rom::PCI[k]))); k+=1; - yden.norm(); - } - ynum.mul(&Y); - - let mut Q=ECP2::new(); - T.copy(&xnum); T.mul(&yden); - Q.x.copy(&T); - T.copy(&ynum); T.mul(&xden); - Q.y.copy(&T); - T.copy(&xden); T.mul(&yden); - Q.z.copy(&T); - return Q; -CAHCZF */ - - } - ECP2::new() - } - -/* Map byte string to curve point */ - #[allow(non_snake_case)] - pub fn mapit(h: &[u8]) -> ECP2 { - let q = BIG::new_ints(&rom::MODULUS); - let mut dx = DBIG::frombytes(h); - let x=dx.dmod(&q); - let mut P=ECP2::hap2point(&x); - P.cfp(); - P - } - - pub fn generator() -> ECP2 { - ECP2::new_fp2s( - &FP2::new_bigs( - &BIG::new_ints(&rom::CURVE_PXA), - &BIG::new_ints(&rom::CURVE_PXB), - ), - &FP2::new_bigs( - &BIG::new_ints(&rom::CURVE_PYA), - &BIG::new_ints(&rom::CURVE_PYB), - ), - ) - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs deleted file mode 100644 index 202c88672ebc..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/eddsa.rs +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ECDH/ECIES/ECDSA API Functions */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::fp; -use crate::bn254::fp::FP; -use crate::bn254::dbig::DBIG; -use crate::bn254::ecp; -use crate::bn254::ecp::ECP; -use crate::bn254::rom; -use crate::rand::RAND; -use crate::hash512::HASH512; -use crate::sha3; -use crate::sha3::SHA3; - -pub const INVALID_PUBLIC_KEY: isize = -2; -pub const ERROR: isize = -3; -//pub const INVALID: isize = -4; -pub const EFS: usize = big::MODBYTES as usize; -pub const EGS: usize = big::MODBYTES as usize; - -fn rfc7748(r: &mut BIG) { - let mut lg=0; - let mut t=BIG::new_int(1); - let mut c=rom::CURVE_COF_I; - while c!=1 { - lg+=1; - c/=2; - } - let n=(8*EGS-lg+1) as usize; - r.mod2m(n); - t.shl(n); - r.add(&t); - c=r.lastbits(lg as usize); - r.dec(c); -} - -// reverse first n bytes of buff - for little endian -fn reverse(n: usize,buff: &mut [u8]) { - for i in 0..n/2 { - let ch = buff[i]; - buff[i] = buff[n - i - 1]; - buff[n - i - 1] = ch; - } -} - -// dom - domain function -fn dom(ds: &str,ph: bool,cl: usize,domain: &mut [u8]) -> usize { - let dsb = ds.as_bytes(); - let n=dsb.len(); - for i in 0..n { - domain[i]=dsb[i]; - } - if ph { - domain[n]=1; - } else { - domain[n]=0; - } - domain[n+1]=cl as u8; - return n+2; -} - -fn h(s: &[u8],digest: &mut [u8]) -> usize { - if ecp::AESKEY<=16 { // for ed25519? - let mut sh=HASH512::new(); - for i in 0..s.len() { - sh.process(s[i]); - } - let hs = sh.hash(); - for i in 0..64 { - digest[i]=hs[i]; - } - return 64; - } else { // for ed448? - let mut sh=SHA3::new(sha3::SHAKE256); - for i in 0..s.len() { - sh.process(s[i]); - } - sh.shake(digest,2*s.len()); - return 2*s.len(); - } -} - -fn h2(ph: bool,ctx: Option<&[u8]>,r: &[u8],q: &[u8],m: &[u8]) -> DBIG { - let b=q.len(); - let mut cl=0; - if let Some(sctx) = ctx { - cl=sctx.len(); - } - let mut domain: [u8; 64] = [0; 64]; - if ecp::AESKEY<=16 { // Ed25519?? - let mut sh=HASH512::new(); - if ph || cl>0 { // if not prehash and no context, omit dom2() - let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); - for i in 0..dl { - sh.process(domain[i]); - } - if let Some(sctx) = ctx { - for i in 0..cl { - sh.process(sctx[i]); - } - } - } - for i in 0..b { - sh.process(r[i]); - } - for i in 0..b { - sh.process(q[i]); - } - for i in 0..m.len() { - sh.process(m[i]); - } - let mut h=sh.hash(); - reverse(64,&mut h); - return DBIG::frombytes(&h); - } else { // for ed448? - let dl=dom("Sigbn254",ph,cl,&mut domain); - let mut h: [u8; 128] = [0; 128]; - let mut sh=SHA3::new(sha3::SHAKE256); - for i in 0..dl { - sh.process(domain[i]); - } - if let Some(sctx) = ctx { - for i in 0..cl { - sh.process(sctx[i]); - } - } - for i in 0..b { - sh.process(r[i]); - } - for i in 0..b { - sh.process(q[i]); - } - for i in 0..m.len() { - sh.process(m[i]); - } - - sh.shake(&mut h,2*b); - reverse(2*b,&mut h[0..2*b]); - return DBIG::frombytes(&h[0..2*b]); - } -} - -fn getr(ph: bool,b: usize,digest: &[u8],ctx: Option<&[u8]>,m: &[u8]) -> DBIG { - let mut cl=0; - if let Some(sctx) = ctx { - cl=sctx.len(); - } - let mut domain: [u8; 64] = [0; 64]; - - if ecp::AESKEY<=16 { // Ed25519?? - let mut sh=HASH512::new(); - if ph || cl>0 { // if not prehash and no context, omit dom2() - let dl=dom("Sigbn254 no bn254 collisions",ph,cl,&mut domain); - for i in 0..dl { - sh.process(domain[i]); - } - if let Some(sctx) = ctx { - for i in 0..cl { - sh.process(sctx[i]); - } - } - } - for i in b..2*b { - sh.process(digest[i]); - } - for i in 0..m.len() { - sh.process(m[i]); - } - let mut h=sh.hash(); - reverse(64,&mut h); - return DBIG::frombytes(&h); - } else { // for ed448? - let dl=dom("Sigbn254",ph,cl,&mut domain); - let mut h: [u8; 128] = [0; 128]; - let mut sh=SHA3::new(sha3::SHAKE256); - for i in 0..dl { - sh.process(domain[i]); - } - if let Some(sctx) = ctx { - for i in 0..cl { - sh.process(sctx[i]); - } - } - for i in b..2*b { - sh.process(digest[i]); - } - for i in 0..m.len() { - sh.process(m[i]); - } - sh.shake(&mut h,2*b); - reverse(2*b,&mut h[0..2*b]); - return DBIG::frombytes(&h[0..2*b]); - } -} - -// encode integer (little endian) -fn encode_int(x: &BIG,w: &mut [u8]) -> usize { - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - - w[0]=0; - x.tobytearray(w,index); - reverse(b,w); - return b; -} - -// encode point - #[allow(non_snake_case)] -fn encode(P: &ECP,w: &mut [u8]) { - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - - let x=P.getx(); - let y=P.gety(); - encode_int(&y,w); - w[b-1]|=(x.parity()<<7) as u8; -} - -// get sign -fn getsign(x: &[u8]) -> isize{ - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - - if (x[b-1]&0x80)!=0 { - return 1; - } else { - return 0; - } -} - -// decode integer (little endian) -fn decode_int(strip_sign: bool,ei: &[u8]) -> BIG { - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - - let mut r: [u8; EFS+1] = [0; EFS+1]; - - for i in 0..b { - r[i]=ei[i]; - } - reverse(b,&mut r); - - if strip_sign { - r[0]&=0x7f; - } - return BIG::frombytearray(&r,index); -} - -// decode compressed point -fn decode(w: &[u8]) -> ECP { - let sign=getsign(w); // lsb of x - let y=decode_int(true,w); - let one = FP::new_int(1); - let mut hint=FP::new(); - let mut x=FP::new_big(&y); x.sqr(); - let mut d=FP::new_copy(&x); - x.sub(&one); - x.norm(); - let mut t = FP::new_big(&BIG::new_ints(&rom::CURVE_B)); - d.mul(&t); - if ecp::CURVE_A==1 { - d.sub(&one); - } - if ecp::CURVE_A==-1 { - d.add(&one); - } - d.norm(); -// inverse square root trick for sqrt(x/d) - t.copy(&x); - t.sqr(); - x.mul(&t); - x.mul(&d); - if x.qr(Some(&mut hint))!=1 { - return ECP::new(); - } - d.copy(&x.sqrt(Some(&hint))); - x.inverse(Some(&hint)); - x.mul(&d); - x.mul(&t); - x.reduce(); - if x.redc().parity()!=sign { - x.neg(); - } - x.norm(); - return ECP::new_bigs(&x.redc(),&y); -} - -#[allow(non_snake_case)] -fn key_pair_regenerate(d: &[u8], q: &mut [u8]) { - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - let mut G=ECP::generator(); - - let mut digest: [u8; 128] = [0; 128]; - h(d,&mut digest); - -// reverse bytes for little endian - reverse(b,&mut digest); - let mut s=BIG::frombytearray(&digest,index); - rfc7748(&mut s); - G.copy(&G.mul(&s)); - encode(&G,q); -} - -/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), - * where s is the secret key and W is the public key - * and G is fixed generator. - * If RNG is NULL then the private key is provided externally in s - * otherwise it is generated randomly internally */ -#[allow(non_snake_case)] -pub fn key_pair_generate(rng: Option<&mut RAND>, d: &mut [u8], q: &mut [u8]) -> isize { - let res = 0; - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - let mut G=ECP::generator(); - - if let Some(srng) = rng { - for i in 0..b { - d[i]=srng.getbyte(); - } - } - let mut digest: [u8; 128] = [0; 128]; - h(d,&mut digest); - -// reverse bytes for little endian - reverse(b,&mut digest); - let mut s=BIG::frombytearray(&digest,index); - rfc7748(&mut s); - G.copy(&G.mul(&s)); - encode(&G,q); - return res; -} - -// Generate a signature using key pair (d,q) on message m -// Set ph=true if message has already been pre-hashed -// if ph=false, then context should be NULL for ed25519. However RFC8032 mode ed25519ctx is supported by supplying a non-NULL or non-empty context -#[allow(non_snake_case)] -pub fn signature(ph: bool,d: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &mut [u8]) ->isize { - let mut digest: [u8; 128] = [0; 128]; - let mut q: [u8; EFS+1] = [0; EFS+1]; // public key - h(d,&mut digest); // hash of private key - let mut res = 0; - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - let r = BIG::new_ints(&rom::CURVE_ORDER); - - key_pair_regenerate(d,&mut q); - let qs=&q[0..b]; - - if d.len()!=qs.len() || d.len()!=b { - res=INVALID_PUBLIC_KEY; - } - if res==0 { - let mut dr=getr(ph,b,&digest,ctx,m); - let sr=dr.dmod(&r); - let R=ECP::generator().mul(&sr); - encode(&R,&mut sig[0..b]); - reverse(b,&mut digest); - let mut s=BIG::frombytearray(&digest,index); - rfc7748(&mut s); - dr=h2(ph,ctx,sig,&qs,m); - let sd=dr.dmod(&r); - encode_int(&BIG::modadd(&sr,&BIG::modmul(&s,&sd,&r),&r),&mut sig[b..2*b]); - } - return res; -} - -// verify a signature using public key q -// same context (if any) as used for signature -#[allow(non_snake_case)] -pub fn verify(ph: bool, q: &[u8], ctx: Option<&[u8]>,m: &[u8], sig: &[u8]) ->bool { - - let mut index=0; - if 8*EFS==fp::MODBITS { - index=1; // extra byte needed for compression - } - let b=EFS+index; - - let mut lg=0; - let mut c=rom::CURVE_COF_I; - while c!=1 { - lg+=1; - c/=2; - } - let r = BIG::new_ints(&rom::CURVE_ORDER); - let mut R=decode(&sig[0..b]); - - if R.is_infinity() { - return false; - } - - let t=decode_int(false,&sig[b..2*b]); - - if BIG::comp(&t,&r)>=0 { - return false; - } - let mut du=h2(ph,ctx,&sig,q,m); - let su=du.dmod(&r); - - let mut G=ECP::generator(); - let mut QD=decode(&q); - if QD.is_infinity() { - return false; - } - QD.neg(); - for _ in 0..lg { // use cofactor 2^c - G.dbl(); QD.dbl(); R.dbl(); - } - - if !G.mul2(&t,&QD,&su).equals(&R) { - return false; - } - return true; -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs deleted file mode 100644 index 17caff2ed023..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp.rs +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::arch; -use crate::arch::Chunk; -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::dbig::DBIG; -use crate::bn254::rom; - -use crate::rand::RAND; - -#[derive(Copy, Clone)] -pub struct FP { - pub x: BIG, - pub xes: i32, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for FP { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for FP { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -pub const NOT_SPECIAL: usize = 0; -pub const PSEUDO_MERSENNE: usize = 1; -pub const MONTGOMERY_FRIENDLY: usize = 2; -pub const GENERALISED_MERSENNE: usize = 3; - -pub const NEGATOWER: usize = 0; -pub const POSITOWER: usize = 1; - -pub const MODBITS:usize = 254; /* Number of bits in Modulus */ -pub const PM1D2: usize = 1; /* Modulus mod 8 */ -pub const RIADZ: isize = -1; /* Z for hash-to-point */ -pub const RIADZG2A: isize = -1; /* G2 Z for hash-to-point */ -pub const RIADZG2B: isize = 0; /* G2 Z for hash-to-point */ -pub const MODTYPE:usize=NOT_SPECIAL; -pub const QNRI:usize=0; /* Fp2 QNR 2^i+sqrt(-1) */ -pub const TOWER:usize=NEGATOWER; /* Tower type */ - -pub const FEXCESS:i32 = ((1 as i32)<<26)-1; -pub const OMASK: Chunk = (-1) << (MODBITS % big::BASEBITS); -pub const TBITS: usize = MODBITS % big::BASEBITS; // Number of active bits in top word -pub const TMASK: Chunk = (1 << TBITS) - 1; - -pub const BIG_ENDIAN_SIGN: bool = false; - -impl FP { - /* Constructors */ - pub const fn new() -> FP { - FP { - x: BIG::new(), - xes: 1, - } - } - - pub fn new_int(a: isize) -> FP { - let mut f = FP::new(); - if a<0 { - let mut m = BIG::new_ints(&rom::MODULUS); - m.inc(a); m.norm(); - f.x.copy(&m); - } else { - f.x.inc(a); - } - f.nres(); - f - } - - pub fn new_copy(y: &FP) -> FP { - let mut f = FP::new(); - f.x.copy(&(y.x)); - f.xes = y.xes; - f - } - - pub fn new_big(y: &BIG) -> FP { - let mut f = FP::new(); - f.x.copy(y); - f.nres(); - f - } - - pub fn new_rand(rng: &mut RAND) -> FP { - let m = BIG::new_ints(&rom::MODULUS); - let w = BIG::randomnum(&m,rng); - FP::new_big(&w) - } - - pub fn nres(&mut self) { - if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { - let r = BIG::new_ints(&rom::R2MODP); - let mut d = BIG::mul(&(self.x), &r); - self.x.copy(&FP::modulo(&mut d)); - self.xes = 2; - } else { - let m = BIG::new_ints(&rom::MODULUS); - self.x.rmod(&m); - self.xes = 1; - } - } - - /* convert back to regular form */ - pub fn redc(&self) -> BIG { - if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { - let mut d = DBIG::new_scopy(&(self.x)); - FP::modulo(&mut d) - } else { - BIG::new_copy(&(self.x)) - } - } - - /* reduce a DBIG to a BIG using the appropriate form of the modulus */ - /* dd */ - pub fn modulo(d: &mut DBIG) -> BIG { - if MODTYPE == PSEUDO_MERSENNE { - let mut b = BIG::new(); - let mut t = d.split(MODBITS); - b.dcopy(&d); - let v = t.pmul(rom::MCONST as isize); - - t.add(&b); - t.norm(); - - let tw = t.w[big::NLEN - 1]; - t.w[big::NLEN - 1] &= TMASK; - t.w[0] += rom::MCONST * ((tw >> TBITS) + (v << (big::BASEBITS - TBITS))); - t.norm(); - return t; - } - - if MODTYPE == MONTGOMERY_FRIENDLY { - let mut b = BIG::new(); - for i in 0..big::NLEN { - let x = d.w[i]; - - let tuple = BIG::muladd(x, rom::MCONST - 1, x, d.w[big::NLEN + i - 1]); - d.w[big::NLEN + i] += tuple.0; - d.w[big::NLEN + i - 1] = tuple.1; - } - - b.zero(); - - for i in 0..big::NLEN { - b.w[i] = d.w[big::NLEN + i]; - } - b.norm(); - return b; - } - - if MODTYPE == GENERALISED_MERSENNE { - // GoldiLocks Only - let mut b = BIG::new(); - let t = d.split(MODBITS); - let rm2 = (MODBITS / 2) as usize; - b.dcopy(&d); - b.add(&t); - let mut dd = DBIG::new_scopy(&t); - dd.shl(rm2); - - let mut tt = dd.split(MODBITS); - let lo = BIG::new_dcopy(&dd); - b.add(&tt); - b.add(&lo); - b.norm(); - tt.shl(rm2); - b.add(&tt); - - let carry = b.w[big::NLEN - 1] >> TBITS; - b.w[big::NLEN - 1] &= TMASK; - b.w[0] += carry; - - let ix=(224 / big::BASEBITS) as usize; - b.w[ix] += carry << (224 % big::BASEBITS); - b.norm(); - return b; - } - - if MODTYPE == NOT_SPECIAL { - let m = BIG::new_ints(&rom::MODULUS); - return BIG::monty(&m, rom::MCONST, d); - } - BIG::new() - } - - /* convert to string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - self.redc().tostring() - } - - /* reduce this mod Modulus */ - pub fn reduce(&mut self) { - let mut m = BIG::new_ints(&rom::MODULUS); - let mut r = BIG::new_copy(&m); - let mut sb: usize; - self.x.norm(); - if self.xes > 16 { - let q = FP::quo(&self.x, &m); - let carry = r.pmul(q); - r.w[big::NLEN - 1] += carry << big::BASEBITS; // correction - put any carry out back in again - self.x.sub(&r); - self.x.norm(); - sb = 2; - } else { - sb = FP::logb2((self.xes - 1) as u32); - } - m.fshl(sb); - - while sb > 0 { - let sr = BIG::ssn(&mut r, &self.x, &mut m); - self.x.cmove(&r, 1 - sr); - sb -= 1; - } - - self.xes = 1; - } - - /* test this=0? */ - pub fn iszilch(&self) -> bool { - let mut a = FP::new_copy(self); - a.reduce(); - a.x.iszilch() - } - - pub fn islarger(&self) -> isize { - if self.iszilch() { - return 0; - } - let mut sx = BIG::new_ints(&rom::MODULUS); - let fx=self.redc(); - sx.sub(&fx); sx.norm(); - BIG::comp(&fx,&sx) - } - - pub fn tobytes(&self,b: &mut [u8]) { - self.redc().tobytes(b) - } - - pub fn frombytes(b: &[u8]) -> FP { - let t=BIG::frombytes(b); - FP::new_big(&t) - } - - /* test this=0? */ - pub fn isunity(&self) -> bool { - let mut a = FP::new_copy(self); - a.reduce(); - a.redc().isunity() - } - - pub fn sign(&self) -> isize { - if BIG_ENDIAN_SIGN { - let mut m = BIG::new_ints(&rom::MODULUS); - m.dec(1); - m.fshr(1); - let mut n = FP::new_copy(self); - n.reduce(); - let w=n.redc(); - let cp=BIG::comp(&w,&m); - ((cp+1)&2)>>1 - } else { - let mut a = FP::new_copy(self); - a.reduce(); - a.redc().parity() - } - } - - /* copy from FP b */ - pub fn copy(&mut self, b: &FP) { - self.x.copy(&(b.x)); - self.xes = b.xes; - } - - /* copy from BIG b */ - pub fn bcopy(&mut self, b: &BIG) { - self.x.copy(&b); - self.nres(); - } - - /* set this=0 */ - pub fn zero(&mut self) { - self.x.zero(); - self.xes = 1; - } - - /* set this=1 */ - pub fn one(&mut self) { - self.x.one(); - self.nres() - } - - /* normalise this */ - pub fn norm(&mut self) { - self.x.norm(); - } - - /* swap FPs depending on d */ - pub fn cswap(&mut self, b: &mut FP, d: isize) { - self.x.cswap(&mut (b.x), d); - let mut c = d as i32; - c = !(c - 1); - let t = c & (self.xes ^ b.xes); - self.xes ^= t; - b.xes ^= t; - } - - /* copy FPs depending on d */ - pub fn cmove(&mut self, b: &FP, d: isize) { - self.x.cmove(&(b.x), d); - let c = d as i32; - self.xes ^= (self.xes ^ b.xes) & (-c); - } - - /* this*=b mod Modulus */ - pub fn mul(&mut self, b: &FP) { - if (self.xes as i64) * (b.xes as i64) > FEXCESS as i64 { - self.reduce() - } - - let mut d = BIG::mul(&(self.x), &(b.x)); - self.x.copy(&FP::modulo(&mut d)); - self.xes = 2; - } - - fn logb2(w: u32) -> usize { - let mut v = w; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - - v = v - ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - ((((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize - } - - // find appoximation to quotient of a/m - // Out by at most 2. - // Note that MAXXES is bounded to be 2-bits less than half a word - fn quo(n: &BIG, m: &BIG) -> isize { - let hb = arch::CHUNK / 2; - - if TBITS < hb { - let sh = hb - TBITS; - let num = (n.w[big::NLEN - 1] << sh) | (n.w[big::NLEN - 2] >> (big::BASEBITS - sh)); - let den = (m.w[big::NLEN - 1] << sh) | (m.w[big::NLEN - 2] >> (big::BASEBITS - sh)); - (num / (den + 1)) as isize - } else { - let num = n.w[big::NLEN - 1]; - let den = m.w[big::NLEN - 1]; - (num / (den + 1)) as isize - } - } - - /* this = -this mod Modulus */ - pub fn neg(&mut self) { - let mut p = BIG::new_ints(&rom::MODULUS); - let sb = FP::logb2((self.xes - 1) as u32); - - p.fshl(sb); - self.x.rsub(&p); - self.xes = 1 << ((sb as i32) + 1); - if self.xes > FEXCESS { - self.reduce() - } - } - - /* this*=c mod Modulus, where c is a small int */ - pub fn imul(&mut self, c: isize) { - let mut cc = c; - let mut s = false; - if cc < 0 { - cc = -cc; - s = true; - } - - if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { - let mut d = self.x.pxmul(cc); - self.x.copy(&FP::modulo(&mut d)); - self.xes = 2 - } else if self.xes * (cc as i32) <= FEXCESS { - self.x.pmul(cc); - self.xes *= cc as i32; - } else { - let n = FP::new_int(cc); - self.mul(&n); - } - - if s { - self.neg(); - self.norm(); - } - } - - /* self*=self mod Modulus */ - pub fn sqr(&mut self) { - if (self.xes as i64) * (self.xes as i64) > FEXCESS as i64 { - self.reduce() - } - - let mut d = BIG::sqr(&(self.x)); - self.x.copy(&FP::modulo(&mut d)); - self.xes = 2 - } - - /* self+=b */ - pub fn add(&mut self, b: &FP) { - self.x.add(&(b.x)); - self.xes += b.xes; - if self.xes > FEXCESS { - self.reduce() - } - } - - /* self+=self */ - pub fn dbl(&mut self) { - self.x.dbl(); - self.xes += self.xes; - if self.xes > FEXCESS { - self.reduce() - } - } - - /* self-=b */ - pub fn sub(&mut self, b: &FP) { - let mut n = FP::new_copy(b); - n.neg(); - self.add(&n); - } - - /* self=b-self */ - pub fn rsub(&mut self, b: &FP) { - self.neg(); - self.add(&b); - } - - /* self/=2 mod Modulus */ - pub fn div2(&mut self) { - let p = BIG::new_ints(&rom::MODULUS); - let pr = self.x.parity(); - let mut w = BIG::new_copy(&self.x); - self.x.fshr(1); - w.add(&p); w.norm(); - w.fshr(1); - self.x.cmove(&w,pr); - } - /* return jacobi symbol (this/Modulus) */ - pub fn jacobi(&mut self) -> isize { - let p = BIG::new_ints(&rom::MODULUS); - let mut w = self.redc(); - w.jacobi(&p) - } - /* return TRUE if self==a */ - pub fn equals(&self, a: &FP) -> bool { - let mut f = FP::new_copy(self); - let mut s = FP::new_copy(a); - f.reduce(); - s.reduce(); - BIG::comp(&(f.x), &(s.x)) == 0 - } - - /* return self^e mod Modulus */ - // Could leak size of e - // but not used here with secret exponent e - pub fn pow(&self, e: &BIG) -> FP { - let mut tb: [FP; 16] = [ - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - ]; - const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4; - let mut w: [i8; CT] = [0; CT]; - - let mut s = FP::new_copy(&self); - s.norm(); - let mut t = BIG::new_copy(e); - t.norm(); - let nb = 1 + (t.nbits() + 3) / 4; - - for i in 0..nb { - let lsbs = t.lastbits(4); - t.dec(lsbs); - t.norm(); - w[i] = lsbs as i8; - t.fshr(4); - } - tb[0].one(); - tb[1].copy(&s); - - let mut c = FP::new(); - for i in 2..16 { - c.copy(&tb[i - 1]); - tb[i].copy(&c); - tb[i].mul(&s); - } - let mut r = FP::new_copy(&tb[w[nb - 1] as usize]); - for i in (0..nb - 1).rev() { - r.sqr(); - r.sqr(); - r.sqr(); - r.sqr(); - r.mul(&tb[w[i] as usize]) - } - r.reduce(); - r - } - - // See eprint paper https://eprint.iacr.org/2018/1038 - // return this^(p-3)/4 or this^(p-5)/8 - pub fn fpow(&self) -> FP { - let ac: [isize; 11] = [1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255]; - let mut xp: [FP; 11] = [ - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - FP::new(), - ]; - // phase 1 - let mut t = FP::new(); - xp[0].copy(&self); // 1 - xp[1].copy(&self); - xp[1].sqr(); // 2 - t.copy(&xp[1]); - xp[2].copy(&t); - xp[2].mul(&self); // 3 - t.copy(&xp[2]); - xp[3].copy(&t); - xp[3].sqr(); // 6 - t.copy(&xp[3]); - xp[4].copy(&t); - xp[4].sqr(); // 12 - t.copy(&xp[4]); - t.mul(&xp[2]); - xp[5].copy(&t); // 15 - t.copy(&xp[5]); - xp[6].copy(&t); - xp[6].sqr(); // 30 - t.copy(&xp[6]); - xp[7].copy(&t); - xp[7].sqr(); // 60 - t.copy(&xp[7]); - xp[8].copy(&t); - xp[8].sqr(); // 120 - t.copy(&xp[8]); - xp[9].copy(&t); - xp[9].sqr(); // 240 - t.copy(&xp[9]); - t.mul(&xp[5]); - xp[10].copy(&t); // 255 - - let mut n = MODBITS as isize; - let mut c: isize; - - if MODTYPE == GENERALISED_MERSENNE { - // Goldilocks ONLY - n /= 2; - } - - let e = PM1D2 as isize; - - n-=e+1; - c=((rom::MCONST as isize)+(1< k { - i -= 1; - } - key.copy(&xp[i]); - k -= ac[i]; - } - while k != 0 { - i -= 1; - if ac[i] > k { - continue; - } - key.mul(&xp[i]); - k -= ac[i]; - } - // phase 2 - t.copy(&xp[2]); - xp[1].copy(&t); - t.copy(&xp[5]); - xp[2].copy(&t); - t.copy(&xp[10]); - xp[3].copy(&t); - - let mut j = 3; - let mut m = 8; - let nw = n - bw; - let mut r = FP::new(); - - while 2 * m < nw { - t.copy(&xp[j]); - j += 1; - for _ in 0..m { - t.sqr(); - } - r.copy(&xp[j - 1]); - r.mul(&t); - xp[j].copy(&r); - m *= 2; - } - let mut lo = nw - m; - r.copy(&xp[j]); - - while lo != 0 { - m /= 2; - j -= 1; - if lo < m { - continue; - } - lo -= m; - t.copy(&r); - for _ in 0..m { - t.sqr(); - } - r.copy(&t); - r.mul(&xp[j]); - } - // phase 3 - if bw != 0 { - for _ in 0..bw { - r.sqr(); - } - r.mul(&key); - } - if MODTYPE == GENERALISED_MERSENNE { - // Goldilocks ONLY - key.copy(&r); - r.sqr(); - r.mul(&self); - for _ in 0..n + 1 { - r.sqr(); - } - r.mul(&key); - } - while nd>0 { - r.sqr(); - nd-=1; - } - r - } - - /* Pseudo_inverse square root */ - pub fn progen(&mut self) { - if MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE { - self.copy(&self.fpow()); - return; - } - let e=PM1D2 as usize; - let mut m = BIG::new_ints(&rom::MODULUS); - m.dec(1); - m.shr(e); - m.dec(1); - m.fshr(1); - - self.copy(&self.pow(&m)); - } - - /* self=1/self mod Modulus */ - pub fn inverse(&mut self,take_hint: Option<&FP>) { - let e=PM1D2 as isize; - self.norm(); - let mut s=FP::new_copy(self); - for _ in 0..e-1 { - s.sqr(); - s.mul(self); - } - if let Some(hint) = take_hint { - self.copy(&hint); - } else { - self.progen(); - } - for _ in 0..=e { - self.sqr(); - } - self.mul(&s); - self.reduce(); - } - - /* Test for Quadratic Residue */ - pub fn qr(&self,give_hint: Option<&mut FP>) -> isize { - let e=PM1D2 as isize; - let mut r=FP::new_copy(self); - r.progen(); - if let Some(hint) = give_hint { - hint.copy(&r); - } - - r.sqr(); - r.mul(self); - for _ in 0..e-1 { - r.sqr(); - } - - r.isunity() as isize - } - - pub fn invsqrt(&self,i: &mut FP,s: &mut FP) -> isize { - let mut h=FP::new(); - let qr=self.qr(Some(&mut h)); - s.copy(&self.sqrt(Some(&h))); - i.copy(self); - i.inverse(Some(&h)); - qr - } - -// Two for the price of One - See Hamburg https://eprint.iacr.org/2012/309.pdf -// Calculate inverse of i and square root of s, return QR - pub fn tpo(mut i: &mut FP,mut s: &mut FP) -> isize { - let mut w = FP::new_copy(s); - let mut t = FP::new_copy(i); - w.mul(&i); - t.mul(&w); - let qr=t.invsqrt(&mut i,&mut s); - i.mul(&w); - s.mul(&i); - qr - } - - /* return sqrt(this) mod Modulus */ - pub fn sqrt(&self,take_hint: Option<&FP>) -> FP { - let e=PM1D2 as isize; - let mut g=FP::new_copy(self); - - if let Some(hint) = take_hint { - g.copy(&hint); - } else { - g.progen(); - } - let m = BIG::new_ints(&rom::ROI); - let mut v=FP::new_big(&m); - let mut t=FP::new_copy(&g); - t.sqr(); - t.mul(self); - - let mut r=FP::new_copy(self); - r.mul(&g); - let mut b=FP::new_copy(&t); - - for k in (2..=e).rev() //(int k=e;k>1;k--) - { - for _ in 1..k-1 { - b.sqr(); - } - let u=!b.isunity() as isize; - g.copy(&r); g.mul(&v); - r.cmove(&g,u); - v.sqr(); - g.copy(&t); g.mul(&v); - t.cmove(&g,u); - b.copy(&t); - } - let sgn=r.sign(); - let mut nr=FP::new_copy(&r); - nr.neg(); nr.norm(); - r.cmove(&nr,sgn); - r - } - -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs deleted file mode 100644 index 04df83d8b8a7..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp12.rs +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::ecp; -use crate::bn254::fp::FP; -use crate::bn254::fp2::FP2; -use crate::bn254::fp4::FP4; -use crate::bn254::rom; - -pub const ZERO: usize = 0; -pub const ONE: usize = 1; -pub const SPARSEST: usize = 2; -pub const SPARSER: usize = 3; -pub const SPARSE: usize = 4; -pub const DENSE: usize = 5; - -#[derive(Copy, Clone)] -pub struct FP12 { - a: FP4, - b: FP4, - c: FP4, - stype: usize, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for FP12 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for FP12 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -impl FP12 { - pub fn new() -> FP12 { - FP12 { - a: FP4::new(), - b: FP4::new(), - c: FP4::new(), - stype: ZERO, - } - } - - pub fn settype(&mut self, t: usize) { - self.stype = t; - } - - pub fn gettype(&self) -> usize { - self.stype - } - - pub fn new_int(a: isize) -> FP12 { - let mut f = FP12::new(); - f.a.copy(&FP4::new_int(a)); - f.b.zero(); - f.c.zero(); - if a == 1 { - f.stype = ONE; - } else { - f.stype = SPARSEST; - } - f - } - - pub fn new_copy(x: &FP12) -> FP12 { - let mut f = FP12::new(); - f.a.copy(&x.a); - f.b.copy(&x.b); - f.c.copy(&x.c); - f.stype = x.stype; - f - } - - pub fn new_fp4s(d: &FP4, e: &FP4, f: &FP4) -> FP12 { - let mut g = FP12::new(); - g.a.copy(d); - g.b.copy(e); - g.c.copy(f); - g.stype = DENSE; - g - } - - pub fn new_fp4(d: &FP4) -> FP12 { - let mut g = FP12::new(); - g.a.copy(d); - g.b.zero(); - g.c.zero(); - g.stype = SPARSEST; - g - } - - /* reduce components mod Modulus */ - pub fn reduce(&mut self) { - self.a.reduce(); - self.b.reduce(); - self.c.reduce(); - } - - /* normalise components of w */ - pub fn norm(&mut self) { - self.a.norm(); - self.b.norm(); - self.c.norm(); - } - - /* test self=0 ? */ - pub fn iszilch(&self) -> bool { - //self.reduce(); - self.a.iszilch() && self.b.iszilch() && self.c.iszilch() - } - - /* Conditional move of g to self dependant on d */ - pub fn cmove(&mut self, g: &FP12, d: isize) { - self.a.cmove(&g.a, d); - self.b.cmove(&g.b, d); - self.c.cmove(&g.c, d); - let mut u = d as usize; - u = !(u.wrapping_sub(1)); - self.stype ^= (self.stype ^ g.stype) & u; - } - - /* return 1 if b==c, no branching */ - fn teq(b: i32, c: i32) -> isize { - let mut x = b ^ c; - x -= 1; // if x=0, x now -1 - ((x >> 31) & 1) as isize - } - - /* Constant time select from pre-computed table */ - pub fn selector(&mut self, g: &[FP12], b: i32) { - let m = b >> 31; - let mut babs = (b ^ m) - m; - - babs = (babs - 1) / 2; - - self.cmove(&g[0], FP12::teq(babs, 0)); // conditional move - self.cmove(&g[1], FP12::teq(babs, 1)); - self.cmove(&g[2], FP12::teq(babs, 2)); - self.cmove(&g[3], FP12::teq(babs, 3)); - self.cmove(&g[4], FP12::teq(babs, 4)); - self.cmove(&g[5], FP12::teq(babs, 5)); - self.cmove(&g[6], FP12::teq(babs, 6)); - self.cmove(&g[7], FP12::teq(babs, 7)); - - let mut invf = FP12::new_copy(self); - invf.conj(); - self.cmove(&invf, (m & 1) as isize); - } - - /* test self=1 ? */ - pub fn isunity(&self) -> bool { - let one = FP4::new_int(1); - self.a.equals(&one) && self.b.iszilch() && self.c.iszilch() - } - - /* test self=x */ - pub fn equals(&self, x: &FP12) -> bool { - self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c) - } - - pub fn geta(&mut self) -> FP4 { - self.a - // let f = FP4::new_copy(&self.a); - // return f; - } - - pub fn getb(&mut self) -> FP4 { - self.b - // let f = FP4::new_copy(&self.b); - // return f; - } - - pub fn getc(&mut self) -> FP4 { - self.c - // let f = FP4::new_copy(&self.c); - // return f; - } - - /* copy self=x */ - pub fn copy(&mut self, x: &FP12) { - self.a.copy(&x.a); - self.b.copy(&x.b); - self.c.copy(&x.c); - self.stype = x.stype; - } - - /* set self=1 */ - pub fn one(&mut self) { - self.a.one(); - self.b.zero(); - self.c.zero(); - self.stype = ONE; - } - - /* set self=0 */ - pub fn zero(&mut self) { - self.a.zero(); - self.b.zero(); - self.c.zero(); - self.stype = ZERO; - } - - /* this=conj(this) */ - pub fn conj(&mut self) { - self.a.conj(); - self.b.nconj(); - self.c.conj(); - } - - /* Granger-Scott Unitary Squaring */ - pub fn usqr(&mut self) { - let mut a = FP4::new_copy(&self.a); - let mut b = FP4::new_copy(&self.c); - let mut c = FP4::new_copy(&self.b); - let mut d = FP4::new(); - - self.a.sqr(); - d.copy(&self.a); - d.add(&self.a); - self.a.add(&d); - - self.a.norm(); - a.nconj(); - - a.dbl(); - self.a.add(&a); - b.sqr(); - b.times_i(); - - d.copy(&b); - d.add(&b); - b.add(&d); - b.norm(); - - c.sqr(); - d.copy(&c); - d.add(&c); - c.add(&d); - c.norm(); - - self.b.conj(); - self.b.dbl(); - self.c.nconj(); - - self.c.dbl(); - self.b.add(&b); - self.c.add(&c); - self.stype = DENSE; - self.reduce(); - } - - /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ - pub fn sqr(&mut self) { - if self.stype == ONE { - return; - } - - let mut a = FP4::new_copy(&self.a); - let mut b = FP4::new_copy(&self.b); - let mut c = FP4::new_copy(&self.c); - let mut d = FP4::new_copy(&self.a); - - a.sqr(); - b.mul(&self.c); - b.dbl(); - b.norm(); - c.sqr(); - d.mul(&self.b); - d.dbl(); - - self.c.add(&self.a); - self.c.add(&self.b); - self.c.norm(); - self.c.sqr(); - - self.a.copy(&a); - a.add(&b); - a.norm(); - a.add(&c); - a.add(&d); - a.norm(); - - a.neg(); - b.times_i(); - c.times_i(); - - self.a.add(&b); - - self.b.copy(&c); - self.b.add(&d); - self.c.add(&a); - if self.stype == SPARSER || self.stype == SPARSEST { - self.stype = SPARSE; - } else { - self.stype = DENSE; - } - self.norm(); - } - - /* FP12 full multiplication self=self*y */ - pub fn mul(&mut self, y: &FP12) { - let mut z0 = FP4::new_copy(&self.a); - let mut z1 = FP4::new(); - let mut z2 = FP4::new_copy(&self.b); - let mut z3 = FP4::new(); - let mut t0 = FP4::new_copy(&self.a); - let mut t1 = FP4::new_copy(&y.a); - - z0.mul(&y.a); - z2.mul(&y.b); - - t0.add(&self.b); - t1.add(&y.b); - - t0.norm(); - t1.norm(); - - z1.copy(&t0); - z1.mul(&t1); - t0.copy(&self.b); - t0.add(&self.c); - t1.copy(&y.b); - t1.add(&y.c); - - t0.norm(); - t1.norm(); - - z3.copy(&t0); - z3.mul(&t1); - - t0.copy(&z0); - t0.neg(); - t1.copy(&z2); - t1.neg(); - - z1.add(&t0); - self.b.copy(&z1); - self.b.add(&t1); - - z3.add(&t1); - z2.add(&t0); - - t0.copy(&self.a); - t0.add(&self.c); - t0.norm(); - t1.copy(&y.a); - t1.add(&y.c); - t1.norm(); - t0.mul(&t1); - z2.add(&t0); - - t0.copy(&self.c); - t0.mul(&y.c); - t1.copy(&t0); - t1.neg(); - - self.c.copy(&z2); - self.c.add(&t1); - z3.add(&t1); - t0.times_i(); - self.b.add(&t0); - z3.norm(); - - z3.times_i(); - self.a.copy(&z0); - self.a.add(&z3); - self.stype = DENSE; - self.norm(); - } - - /* FP12 full multiplication w=w*y */ - /* Supports sparse multiplicands */ - /* Usually w is denser than y */ - pub fn ssmul(&mut self, y: &FP12) { - if self.stype == ONE { - self.copy(&y); - return; - } - if y.stype == ONE { - return; - } - if y.stype >= SPARSE { - let mut z0 = FP4::new_copy(&self.a); - let mut z1 = FP4::new(); - let mut z2 = FP4::new(); - let mut z3 = FP4::new(); - z0.mul(&y.a); - - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - if y.stype == SPARSE || self.stype == SPARSE { - let mut ga = FP2::new(); - let mut gb = FP2::new(); - - gb.copy(&self.b.getb()); - gb.mul(&y.b.getb()); - ga.zero(); - if y.stype != SPARSE { - ga.copy(&self.b.getb()); - ga.mul(&y.b.geta()); - } - if self.stype != SPARSE { - ga.copy(&self.b.geta()); - ga.mul(&y.b.getb()); - } - z2.set_fp2s(&ga, &gb); - z2.times_i(); - } else { - z2.copy(&self.b); - z2.mul(&y.b); - } - } else { - z2.copy(&self.b); - z2.mul(&y.b); - } - let mut t0 = FP4::new_copy(&self.a); - let mut t1 = FP4::new_copy(&y.a); - t0.add(&self.b); - t0.norm(); - t1.add(&y.b); - t1.norm(); - - z1.copy(&t0); - z1.mul(&t1); - t0.copy(&self.b); - t0.add(&self.c); - t0.norm(); - t1.copy(&y.b); - t1.add(&y.c); - t1.norm(); - - z3.copy(&t0); - z3.mul(&t1); - - t0.copy(&z0); - t0.neg(); - t1.copy(&z2); - t1.neg(); - - z1.add(&t0); - self.b.copy(&z1); - self.b.add(&t1); - - z3.add(&t1); - z2.add(&t0); - - t0.copy(&self.a); - t0.add(&self.c); - t0.norm(); - t1.copy(&y.a); - t1.add(&y.c); - t1.norm(); - - t0.mul(&t1); - z2.add(&t0); - - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - if y.stype == SPARSE || self.stype == SPARSE { - let mut ga = FP2::new(); - let mut gb = FP2::new(); - - ga.copy(&self.c.geta()); - ga.mul(&y.c.geta()); - gb.zero(); - if y.stype != SPARSE { - gb.copy(&self.c.geta()); - gb.mul(&y.c.getb()); - } - if self.stype != SPARSE { - gb.copy(&self.c.getb()); - gb.mul(&y.c.geta()); - } - t0.set_fp2s(&ga, &gb); - } else { - t0.copy(&self.c); - t0.mul(&y.c); - } - } else { - t0.copy(&self.c); - t0.mul(&y.c); - } - t1.copy(&t0); - t1.neg(); - - self.c.copy(&z2); - self.c.add(&t1); - z3.add(&t1); - t0.times_i(); - self.b.add(&t0); - z3.norm(); - z3.times_i(); - self.a.copy(&z0); - self.a.add(&z3); - } else { - if self.stype == SPARSER || self.stype == SPARSEST { - self.smul(&y); - return; - } - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - // dense by sparser - 13m - let mut z0 = FP4::new_copy(&self.a); - let mut z2 = FP4::new_copy(&self.b); - let mut z3 = FP4::new_copy(&self.b); - let mut t0 = FP4::new(); - let mut t1 = FP4::new_copy(&y.a); - - z0.mul(&y.a); - if y.stype == SPARSEST { - z2.qmul(&y.b.geta().getA()); - } else { - z2.pmul(&y.b.geta()); - } - self.b.add(&self.a); - t1.padd(&y.b.geta()); - - t1.norm(); - self.b.norm(); - self.b.mul(&t1); - z3.add(&self.c); - z3.norm(); - - if y.stype == SPARSEST { - z3.qmul(&y.b.geta().getA()); - } else { - z3.pmul(&y.b.geta()); - } - t0.copy(&z0); - t0.neg(); - t1.copy(&z2); - t1.neg(); - - self.b.add(&t0); - - self.b.add(&t1); - z3.add(&t1); - z2.add(&t0); - - t0.copy(&self.a); - t0.add(&self.c); - t0.norm(); - z3.norm(); - t0.mul(&y.a); - self.c.copy(&z2); - self.c.add(&t0); - - z3.times_i(); - self.a.copy(&z0); - self.a.add(&z3); - } - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - let mut z0 = FP4::new_copy(&self.a); - let mut z1 = FP4::new(); - let mut z2 = FP4::new(); - let mut z3 = FP4::new(); - let mut t0 = FP4::new_copy(&self.a); - let mut t1 = FP4::new(); - - z0.mul(&y.a); - t0.add(&self.b); - t0.norm(); - - z1.copy(&t0); - z1.mul(&y.a); - t0.copy(&self.b); - t0.add(&self.c); - t0.norm(); - - z3.copy(&t0); - if y.stype == SPARSEST { - z3.qmul(&y.c.getb().getA()); - } else { - z3.pmul(&y.c.getb()); - } - z3.times_i(); - - t0.copy(&z0); - t0.neg(); - z1.add(&t0); - self.b.copy(&z1); - z2.copy(&t0); - - t0.copy(&self.a); - t0.add(&self.c); - t0.norm(); - t1.copy(&y.a); - t1.add(&y.c); - t1.norm(); - - t0.mul(&t1); - z2.add(&t0); - t0.copy(&self.c); - - if y.stype == SPARSEST { - t0.qmul(&y.c.getb().getA()); - } else { - t0.pmul(&y.c.getb()); - } - t0.times_i(); - t1.copy(&t0); - t1.neg(); - - self.c.copy(&z2); - self.c.add(&t1); - z3.add(&t1); - t0.times_i(); - self.b.add(&t0); - z3.norm(); - z3.times_i(); - self.a.copy(&z0); - self.a.add(&z3); - } - } - self.stype = DENSE; - self.norm(); - } - - /* Special case of multiplication arises from special form of ATE pairing line function */ - pub fn smul(&mut self, y: &FP12) { - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - let mut w1 = FP2::new_copy(&self.a.geta()); - let mut w2 = FP2::new_copy(&self.a.getb()); - //let mut w3=FP2::new_copy(&self.b.geta()); - - let mut w3: FP2; - - w1.mul(&y.a.geta()); - w2.mul(&y.a.getb()); - - if y.stype == SPARSEST || self.stype == SPARSEST { - if y.stype == SPARSEST && self.stype == SPARSEST { - let mut t = FP::new_copy(&self.b.geta().getA()); - t.mul(&y.b.geta().getA()); - w3 = FP2::new_fp(&t); - } else if y.stype != SPARSEST { - w3 = FP2::new_copy(&y.b.geta()); - w3.pmul(&self.b.geta().getA()); - } else { - w3 = FP2::new_copy(&self.b.geta()); - w3.pmul(&y.b.geta().getA()); - } - } else { - w3 = FP2::new_copy(&self.b.geta()); - w3.mul(&y.b.geta()); - } - let mut ta = FP2::new_copy(&self.a.geta()); - let mut tb = FP2::new_copy(&y.a.geta()); - ta.add(&self.a.getb()); - ta.norm(); - tb.add(&y.a.getb()); - tb.norm(); - let mut tc = FP2::new_copy(&ta); - tc.mul(&tb); - let mut t = FP2::new_copy(&w1); - t.add(&w2); - t.neg(); - tc.add(&t); - - ta.copy(&self.a.geta()); - ta.add(&self.b.geta()); - ta.norm(); - tb.copy(&y.a.geta()); - tb.add(&y.b.geta()); - tb.norm(); - let mut td = FP2::new_copy(&ta); - td.mul(&tb); - t.copy(&w1); - t.add(&w3); - t.neg(); - td.add(&t); - - ta.copy(&self.a.getb()); - ta.add(&self.b.geta()); - ta.norm(); - tb.copy(&y.a.getb()); - tb.add(&y.b.geta()); - tb.norm(); - let mut te = FP2::new_copy(&ta); - te.mul(&tb); - t.copy(&w2); - t.add(&w3); - t.neg(); - te.add(&t); - - w2.mul_ip(); - w1.add(&w2); - - self.a.set_fp2s(&w1, &tc); - self.b.set_fp2s(&td, &te); - self.c.set_fp2(&w3); - - self.a.norm(); - self.b.norm(); - } else { - let mut w1 = FP2::new_copy(&self.a.geta()); - let mut w2 = FP2::new_copy(&self.a.getb()); - // let mut w3=FP2::new_copy(&self.c.getb()); - let mut w3: FP2; - - w1.mul(&y.a.geta()); - w2.mul(&y.a.getb()); - - if y.stype == SPARSEST || self.stype == SPARSEST { - if y.stype == SPARSEST && self.stype == SPARSEST { - let mut t = FP::new_copy(&self.c.getb().getA()); - t.mul(&y.c.getb().getA()); - w3 = FP2::new_fp(&t); - } else if y.stype != SPARSEST { - w3 = FP2::new_copy(&y.c.getb()); - w3.pmul(&self.c.getb().getA()); - } else { - w3 = FP2::new_copy(&self.c.getb()); - w3.pmul(&y.c.getb().getA()); - } - } else { - w3 = FP2::new_copy(&self.c.getb()); - w3.mul(&y.c.getb()); - } - let mut ta = FP2::new_copy(&self.a.geta()); - let mut tb = FP2::new_copy(&y.a.geta()); - ta.add(&self.a.getb()); - ta.norm(); - tb.add(&y.a.getb()); - tb.norm(); - let mut tc = FP2::new_copy(&ta); - tc.mul(&tb); - let mut t = FP2::new_copy(&w1); - t.add(&w2); - t.neg(); - tc.add(&t); - - ta.copy(&self.a.geta()); - ta.add(&self.c.getb()); - ta.norm(); - tb.copy(&y.a.geta()); - tb.add(&y.c.getb()); - tb.norm(); - let mut td = FP2::new_copy(&ta); - td.mul(&tb); - t.copy(&w1); - t.add(&w3); - t.neg(); - td.add(&t); - - ta.copy(&self.a.getb()); - ta.add(&self.c.getb()); - ta.norm(); - tb.copy(&y.a.getb()); - tb.add(&y.c.getb()); - tb.norm(); - let mut te = FP2::new_copy(&ta); - te.mul(&tb); - t.copy(&w2); - t.add(&w3); - t.neg(); - te.add(&t); - - w2.mul_ip(); - w1.add(&w2); - self.a.set_fp2s(&w1, &tc); - - w3.mul_ip(); - w3.norm(); - self.b.set_fp2h(&w3); - - te.norm(); - te.mul_ip(); - self.c.set_fp2s(&te, &td); - - self.a.norm(); - self.c.norm(); - } - self.stype = SPARSE; - } - - /* self=1/self */ - pub fn inverse(&mut self) { - let mut f0 = FP4::new_copy(&self.a); - let mut f1 = FP4::new_copy(&self.b); - let mut f2 = FP4::new_copy(&self.a); - let mut f3 = FP4::new(); - - self.norm(); - f0.sqr(); - f1.mul(&self.c); - f1.times_i(); - f0.sub(&f1); - f0.norm(); - - f1.copy(&self.c); - f1.sqr(); - f1.times_i(); - f2.mul(&self.b); - f1.sub(&f2); - f1.norm(); - - f2.copy(&self.b); - f2.sqr(); - f3.copy(&self.a); - f3.mul(&self.c); - f2.sub(&f3); - f2.norm(); - - f3.copy(&self.b); - f3.mul(&f2); - f3.times_i(); - self.a.mul(&f0); - f3.add(&self.a); - self.c.mul(&f1); - self.c.times_i(); - - f3.add(&self.c); - f3.norm(); - f3.inverse(None); - self.a.copy(&f0); - self.a.mul(&f3); - self.b.copy(&f1); - self.b.mul(&f3); - self.c.copy(&f2); - self.c.mul(&f3); - self.stype = DENSE; - } - - /* self=self^p using Frobenius */ - pub fn frob(&mut self, f: &FP2) { - let mut f2 = FP2::new_copy(f); - let mut f3 = FP2::new_copy(f); - - f2.sqr(); - f3.mul(&f2); - - self.a.frob(&f3); - self.b.frob(&f3); - self.c.frob(&f3); - - self.b.pmul(f); - self.c.pmul(&f2); - self.stype = DENSE; - } - - /* trace function */ - pub fn trace(&mut self) -> FP4 { - let mut t = FP4::new(); - t.copy(&self.a); - t.imul(3); - t.reduce(); - t - } - - /* convert from byte array to FP12 */ - pub fn frombytes(w: &[u8]) -> FP12 { - const MB:usize = 4*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - for i in 0..MB { - t[i]=w[i]; - } - let c=FP4::frombytes(&t); - for i in 0..MB { - t[i]=w[i+MB]; - } - let b=FP4::frombytes(&t); - for i in 0..MB { - t[i]=w[i+2*MB]; - } - let a=FP4::frombytes(&t); - FP12::new_fp4s(&a,&b,&c) - } - - /* convert this to byte array */ - pub fn tobytes(&mut self, w: &mut [u8]) { - const MB:usize = 4*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - - self.c.tobytes(&mut t); - for i in 0..MB { - w[i]=t[i]; - } - self.b.tobytes(&mut t); - for i in 0..MB { - w[i+MB]=t[i]; - } - self.a.tobytes(&mut t); - for i in 0..MB { - w[i+2*MB]=t[i]; - } - } - - /* output to hex string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - format!( - "[{},{},{}]", - self.a.tostring(), - self.b.tostring(), - self.c.tostring() - ) - } - -/* Note this is simple square and multiply, so not side-channel safe */ -/* But fast for final exponentiation where exponent is not a secret */ -/* return this^e */ - pub fn pow(&self, e: &BIG) -> FP12 { - let mut r = FP12::new_copy(self); - r.norm(); - let mut e1 = BIG::new_copy(e); - e1.norm(); - let mut e3 = BIG::new_copy(&e1); - e3.pmul(3); - e3.norm(); - let mut w = FP12::new_copy(&r); - if e3.iszilch() { - w.one(); - return w; - } - - let nb = e3.nbits(); - for i in (1..nb - 1).rev() { - w.usqr(); - let bt = e3.bit(i) - e1.bit(i); - if bt == 1 { - w.mul(&r); - } - if bt == -1 { - r.conj(); - w.mul(&r); - r.conj(); - } - } - - w.reduce(); - w - } - - /* constant time powering by small integer of max length bts */ - pub fn pinpow(&mut self, e: i32, bts: i32) { - let mut r: [FP12; 2] = [FP12::new_int(1), FP12::new_copy(self)]; - let mut t = FP12::new(); - - for i in (0..bts).rev() { - let b: usize = ((e >> i) & 1) as usize; - t.copy(&r[b]); - r[1 - b].mul(&t); - r[b].usqr(); - } - self.copy(&r[0]); - } - - pub fn compow(&mut self, e: &BIG, r: &BIG) -> FP4 { - let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let q = BIG::new_ints(&rom::MODULUS); - - let mut g1 = FP12::new_copy(self); - let mut g2 = FP12::new_copy(self); - - let mut m = BIG::new_copy(&q); - m.rmod(&r); - - let mut a = BIG::new_copy(&e); - a.rmod(&m); - - let mut b = BIG::new_copy(&e); - b.div(&m); - - let mut c = g1.trace(); - - if b.iszilch() { - c = c.xtr_pow(&a); - return c; - } - - g2.frob(&f); - let cp = g2.trace(); - g1.conj(); - g2.mul(&g1); - let cpm1 = g2.trace(); - g2.mul(&g1); - let cpm2 = g2.trace(); - - c.xtr_pow2(&cp, &cpm1, &cpm2, &a, &b) - } - - /* p=q0^u0.q1^u1.q2^u2.q3^u3 */ - // Bos & Costello https://eprint.iacr.org/2013/458.pdf - // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf - // Side channel attack secure - pub fn pow4(q: &[FP12], u: &[BIG]) -> FP12 { - let mut g: [FP12; 8] = [ - FP12::new(), - FP12::new(), - FP12::new(), - FP12::new(), - FP12::new(), - FP12::new(), - FP12::new(), - FP12::new(), - ]; - - let mut r = FP12::new(); - let mut p = FP12::new(); - const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize); - let mut w: [i8; CT] = [0; CT]; - let mut s: [i8; CT] = [0; CT]; - - let mut mt = BIG::new(); - let mut t: [BIG; 4] = [ - BIG::new_copy(&u[0]), - BIG::new_copy(&u[1]), - BIG::new_copy(&u[2]), - BIG::new_copy(&u[3]), - ]; - - for i in 0..4 { - t[i].norm(); - } - - // precomputation - g[0].copy(&q[0]); - r.copy(&g[0]); - g[1].copy(&r); - g[1].mul(&q[1]); // q[0].q[1] - g[2].copy(&r); - g[2].mul(&q[2]); - r.copy(&g[1]); // q[0].q[2] - g[3].copy(&r); - g[3].mul(&q[2]); - r.copy(&g[0]); // q[0].q[1].q[2] - g[4].copy(&r); - g[4].mul(&q[3]); - r.copy(&g[1]); // q[0].q[3] - g[5].copy(&r); - g[5].mul(&q[3]); - r.copy(&g[2]); // q[0].q[1].q[3] - g[6].copy(&r); - g[6].mul(&q[3]); - r.copy(&g[3]); // q[0].q[2].q[3] - g[7].copy(&r); - g[7].mul(&q[3]); // q[0].q[1].q[2].q[3] - - // Make it odd - let pb = 1 - t[0].parity(); - t[0].inc(pb); - t[0].norm(); - - // Number of bits - mt.zero(); - for i in 0..4 { - mt.or(&t[i]); - } - - let nb = 1 + mt.nbits(); - - // Sign pivot - s[nb - 1] = 1; - for i in 0..nb - 1 { - t[0].fshr(1); - s[i] = (2 * t[0].parity() - 1) as i8; - //println!("s={}",s[i]); - } - - // Recoded exponent - for i in 0..nb { - w[i] = 0; - let mut k = 1; - for j in 1..4 { - let bt = s[i] * (t[j].parity() as i8); - t[j].fshr(1); - t[j].dec((bt >> 1) as isize); - t[j].norm(); - w[i] += bt * (k as i8); - k *= 2; - } - } - - // Main loop - p.selector(&g, (2 * w[nb - 1] + 1) as i32); - for i in (0..nb - 1).rev() { - p.usqr(); - r.selector(&g, (2 * w[i] + s[i]) as i32); - p.mul(&r); - } - - // apply correction - r.copy(&q[0]); - r.conj(); - r.mul(&p); - p.cmove(&r, pb); - p.reduce(); - p - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs deleted file mode 100644 index 72eb05861457..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp2.rs +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::dbig::DBIG; -use crate::bn254::fp; -use crate::bn254::fp::FP; -use crate::bn254::rom; - -use crate::rand::RAND; - -#[derive(Copy, Clone)] -pub struct FP2 { - a: FP, - b: FP, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for FP2 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for FP2 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -impl FP2 { - pub const fn new() -> FP2 { - FP2 { - a: FP::new(), - b: FP::new(), - } - } - - pub fn new_int(a: isize) -> FP2 { - let mut f = FP2::new(); - f.a.copy(&FP::new_int(a)); - f.b.zero(); - f - } - - pub fn new_ints(a: isize, b: isize) -> FP2 { - let mut f = FP2::new(); - f.a.copy(&FP::new_int(a)); - f.b.copy(&FP::new_int(b)); - f - } - - pub fn new_copy(x: &FP2) -> FP2 { - let mut f = FP2::new(); - f.a.copy(&x.a); - f.b.copy(&x.b); - f - } - - pub fn new_fps(c: &FP, d: &FP) -> FP2 { - let mut f = FP2::new(); - f.a.copy(c); - f.b.copy(d); - f - } - - pub fn new_bigs(c: &BIG, d: &BIG) -> FP2 { - let mut f = FP2::new(); - f.a.copy(&FP::new_big(c)); - f.b.copy(&FP::new_big(d)); - f - } - - pub fn new_fp(c: &FP) -> FP2 { - let mut f = FP2::new(); - f.a.copy(c); - f.b.zero(); - f - } - - pub fn new_big(c: &BIG) -> FP2 { - let mut f = FP2::new(); - f.a.copy(&FP::new_big(c)); - f.b.zero(); - f - } - - pub fn new_rand(rng: &mut RAND) -> FP2 { - FP2::new_fps(&FP::new_rand(rng),&FP::new_rand(rng)) - } - - /* reduce components mod Modulus */ - pub fn reduce(&mut self) { - self.a.reduce(); - self.b.reduce(); - } - - /* normalise components of w */ - pub fn norm(&mut self) { - self.a.norm(); - self.b.norm(); - } - - /* test self=0 ? */ - pub fn iszilch(&self) -> bool { - self.a.iszilch() && self.b.iszilch() - } - - pub fn islarger(&self) -> isize { - if self.iszilch() { - return 0; - } - let cmp=self.b.islarger(); - if cmp!=0 { - return cmp; - } - self.a.islarger() - } - - pub fn tobytes(&self,bf: &mut [u8]) { - const MB:usize = big::MODBYTES as usize; - let mut t: [u8; MB] = [0; MB]; - self.b.tobytes(&mut t); - for i in 0..MB { - bf[i]=t[i]; - } - self.a.tobytes(&mut t); - for i in 0..MB { - bf[i+MB]=t[i]; - } - } - - pub fn frombytes(bf: &[u8]) -> FP2 { - const MB:usize = big::MODBYTES as usize; - let mut t: [u8; MB] = [0; MB]; - for i in 0..MB { - t[i]=bf[i]; - } - let tb=FP::frombytes(&t); - for i in 0..MB { - t[i]=bf[i+MB]; - } - let ta=FP::frombytes(&t); - FP2::new_fps(&ta,&tb) - } - - pub fn cmove(&mut self, g: &FP2, d: isize) { - self.a.cmove(&g.a, d); - self.b.cmove(&g.b, d); - } - - /* test self=1 ? */ - pub fn isunity(&self) -> bool { - let one = FP::new_int(1); - self.a.equals(&one) && self.b.iszilch() - } - - /* test self=x */ - pub fn equals(&self, x: &FP2) -> bool { - self.a.equals(&x.a) && self.b.equals(&x.b) - } - - /* extract a */ - #[allow(non_snake_case)] - pub fn getA(&mut self) -> FP { - self.a - } - - /* extract b */ - #[allow(non_snake_case)] - pub fn getB(&mut self) -> FP { - self.b - } - - /* extract a */ - pub fn geta(&mut self) -> BIG { - self.a.redc() - } - - /* extract b */ - pub fn getb(&mut self) -> BIG { - self.b.redc() - } - - /* copy self=x */ - pub fn copy(&mut self, x: &FP2) { - self.a.copy(&x.a); - self.b.copy(&x.b); - } - - pub fn set_fp(&mut self, x: &FP) { - self.a.copy(x); - self.b.zero(); - } - - /* set self=0 */ - pub fn zero(&mut self) { - self.a.zero(); - self.b.zero(); - } - - /* set self=1 */ - pub fn one(&mut self) { - self.a.one(); - self.b.zero(); - } - - pub fn sign(&self) -> isize { - let mut p1=self.a.sign(); - let mut p2=self.b.sign(); - if fp::BIG_ENDIAN_SIGN { - let u=self.b.iszilch() as isize; - p2^=(p1^p2)&u; - p2 - } else { - let u=self.a.iszilch() as isize; - p1^=(p1^p2)&u; - p1 - } - } - - /* negate self mod Modulus */ - pub fn neg(&mut self) { - let mut m = FP::new_copy(&self.a); - let mut t = FP::new(); - - m.add(&self.b); - m.neg(); - t.copy(&m); - t.add(&self.b); - self.b.copy(&m); - self.b.add(&self.a); - self.a.copy(&t); - } - - /* set to a-ib */ - pub fn conj(&mut self) { - self.b.neg(); - self.b.norm(); - } - - /* self+=a */ - pub fn add(&mut self, x: &FP2) { - self.a.add(&x.a); - self.b.add(&x.b); - } - - pub fn dbl(&mut self) { - self.a.dbl(); - self.b.dbl(); - } - - /* self-=a */ - pub fn sub(&mut self, x: &FP2) { - let mut m = FP2::new_copy(x); - m.neg(); - self.add(&m); - } - - /* self=a-self */ - pub fn rsub(&mut self, x: &FP2) { - self.neg(); - self.add(x); - } - - /* self*=s, where s is an FP */ - pub fn pmul(&mut self, s: &FP) { - self.a.mul(s); - self.b.mul(s); - } - - /* self*=i, where i is an int */ - pub fn imul(&mut self, c: isize) { - self.a.imul(c); - self.b.imul(c); - } - - /* self*=self */ - pub fn sqr(&mut self) { - let mut w1 = FP::new_copy(&self.a); - let mut w3 = FP::new_copy(&self.a); - let mut mb = FP::new_copy(&self.b); - - w1.add(&self.b); - - w3.add(&self.a); - w3.norm(); - self.b.mul(&w3); - - mb.neg(); - self.a.add(&mb); - - w1.norm(); - self.a.norm(); - - self.a.mul(&w1); - } - - /* this*=y */ - pub fn mul(&mut self, y: &FP2) { - if ((self.a.xes + self.b.xes) as i64) * ((y.a.xes + y.b.xes) as i64) > fp::FEXCESS as i64 { - if self.a.xes > 1 { - self.a.reduce() - } - if self.b.xes > 1 { - self.b.reduce() - } - } - - let p = BIG::new_ints(&rom::MODULUS); - let mut pr = DBIG::new(); - - pr.ucopy(&p); - - let mut c = BIG::new_copy(&(self.a.x)); - let mut d = BIG::new_copy(&(y.a.x)); - - let mut a = BIG::mul(&self.a.x, &y.a.x); - let mut b = BIG::mul(&self.b.x, &y.b.x); - - c.add(&self.b.x); - c.norm(); - d.add(&y.b.x); - d.norm(); - - let mut e = BIG::mul(&c, &d); - let mut f = DBIG::new_copy(&a); - f.add(&b); - b.rsub(&pr); - - a.add(&b); - a.norm(); - e.sub(&f); - e.norm(); - - self.a.x.copy(&FP::modulo(&mut a)); - self.a.xes = 3; - self.b.x.copy(&FP::modulo(&mut e)); - self.b.xes = 2; - } -/* - pub fn pow(&mut self, e: &BIG) { - let mut w = FP2::new_copy(self); - let mut z = BIG::new_copy(&e); - let mut r = FP2::new_int(1); - loop { - let bt = z.parity(); - z.fshr(1); - if bt == 1 { - r.mul(&mut w) - }; - if z.iszilch() { - break; - } - w.sqr(); - } - r.reduce(); - self.copy(&r); - }*/ - - pub fn qr(&mut self,h:Option<&mut FP>) -> isize { - let mut c=FP2::new_copy(self); - c.conj(); - c.mul(self); - c.getA().qr(h) - } - - /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ - pub fn sqrt(&mut self,h:Option<&FP>) { - if self.iszilch() { - return; - } - let mut w1 = FP::new_copy(&self.b); - let mut w2 = FP::new_copy(&self.a); - let mut w3 = FP::new_copy(&self.a); - let mut w4 = FP::new(); - let mut hint = FP::new(); - - w1.sqr(); - w2.sqr(); - w1.add(&w2); w1.norm(); - - w2.copy(&w1.sqrt(h)); - w1.copy(&w2); - - w2.copy(&self.a); - w2.add(&w1); - w2.norm(); - w2.div2(); - - w1.copy(&self.b); w1.div2(); - let qr=w2.qr(Some(&mut hint)); - -// tweak hint - w3.copy(&hint); w3.neg(); w3.norm(); - w4.copy(&w2); w4.neg(); w4.norm(); - - w2.cmove(&w4,1-qr); - hint.cmove(&w3,1-qr); - - self.a.copy(&w2.sqrt(Some(&hint))); - w3.copy(&w2); w3.inverse(Some(&hint)); - w3.mul(&self.a); - self.b.copy(&w3); self.b.mul(&w1); - w4.copy(&self.a); - - self.a.cmove(&self.b,1-qr); - self.b.cmove(&w4,1-qr); - -/* - self.a.copy(&w2.sqrt(Some(&hint))); - w3.copy(&w2); w3.inverse(Some(&hint)); - w3.mul(&self.a); - self.b.copy(&w3); self.b.mul(&w1); - - hint.neg(); hint.norm(); - w2.neg(); w2.norm(); - - w4.copy(&w2.sqrt(Some(&hint))); - w3.copy(&w2); w3.inverse(Some(&hint)); - w3.mul(&w4); - w3.mul(&w1); - - self.a.cmove(&w3,1-qr); - self.b.cmove(&w4,1-qr); -*/ - let sgn=self.sign(); - let mut nr=FP2::new_copy(&self); - nr.neg(); nr.norm(); - self.cmove(&nr,sgn); - } - - /* output to hex string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - format!("[{},{}]", self.a.tostring(), self.b.tostring()) - } - - /* self=1/self */ - pub fn inverse(&mut self,h:Option<&FP>) { - self.norm(); - let mut w1 = FP::new_copy(&self.a); - let mut w2 = FP::new_copy(&self.b); - - w1.sqr(); - w2.sqr(); - w1.add(&w2); - w1.inverse(h); - self.a.mul(&w1); - w1.neg(); - w1.norm(); - self.b.mul(&w1); - } - - /* self/=2 */ - pub fn div2(&mut self) { - self.a.div2(); - self.b.div2(); - } - - /* self*=sqrt(-1) */ - pub fn times_i(&mut self) { - let z = FP::new_copy(&self.a); - self.a.copy(&self.b); - self.a.neg(); - self.b.copy(&z); - } - - /* w*=(1+sqrt(-1)) */ - /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ - pub fn mul_ip(&mut self) { - let mut t = FP2::new_copy(self); - let mut i = fp::QNRI; - self.times_i(); - while i > 0 { - t.dbl(); - t.norm(); - i -= 1; - } - self.add(&t); - if fp::TOWER == fp::POSITOWER { - self.norm(); - self.neg(); - } - } - - /* w/=(1+sqrt(-1)) */ - pub fn div_ip(&mut self) { - let mut z = FP2::new_ints(1 << fp::QNRI, 1); - z.inverse(None); - self.norm(); - self.mul(&z); - if fp::TOWER == fp::POSITOWER { - self.neg(); - self.norm(); - } - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs deleted file mode 100644 index 1f36040c7c20..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/fp4.rs +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::fp; -use crate::bn254::fp::FP; -use crate::bn254::fp2::FP2; -use crate::rand::RAND; -#[allow(unused_imports)] -use crate::bn254::rom; - -#[derive(Copy, Clone)] -pub struct FP4 { - a: FP2, - b: FP2, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for FP4 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for FP4 { - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "{}", self.tostring()) - } -} - -impl FP4 { - pub const fn new() -> FP4 { - FP4 { - a: FP2::new(), - b: FP2::new(), - } - } - - pub fn new_int(a: isize) -> FP4 { - let mut f = FP4::new(); - f.a.copy(&FP2::new_int(a)); - f.b.zero(); - f - } - - pub fn new_ints(a: isize,b: isize) -> FP4 { - let mut f = FP4::new(); - f.a.copy(&FP2::new_int(a)); - f.b.copy(&FP2::new_int(b)); - f - } - - pub fn new_copy(x: &FP4) -> FP4 { - let mut f = FP4::new(); - f.a.copy(&x.a); - f.b.copy(&x.b); - f - } - - pub fn new_fp2s(c: &FP2, d: &FP2) -> FP4 { - let mut f = FP4::new(); - f.a.copy(c); - f.b.copy(d); - f - } - - pub fn new_fp2(c: &FP2) -> FP4 { - let mut f = FP4::new(); - f.a.copy(c); - f.b.zero(); - f - } - - pub fn new_fp(c: &FP) -> FP4 { - let mut f = FP4::new(); - f.a.set_fp(c); - f.b.zero(); - f - } - - pub fn new_rand(rng: &mut RAND) -> FP4 { - FP4::new_fp2s(&FP2::new_rand(rng),&FP2::new_rand(rng)) - } - - pub fn set_fp2s(&mut self, c: &FP2, d: &FP2) { - self.a.copy(&c); - self.b.copy(&d); - } - - pub fn set_fp(&mut self, c: &FP) { - self.a.set_fp(&c); - self.b.zero(); - } - - pub fn set_fp2(&mut self, c: &FP2) { - self.a.copy(&c); - self.b.zero(); - } - - pub fn set_fp2h(&mut self, c: &FP2) { - self.b.copy(&c); - self.a.zero(); - } - - /* reduce components mod Modulus */ - pub fn reduce(&mut self) { - self.a.reduce(); - self.b.reduce(); - } - - /* normalise components of w */ - pub fn norm(&mut self) { - self.a.norm(); - self.b.norm(); - } - - pub fn cmove(&mut self, g: &FP4, d: isize) { - self.a.cmove(&g.a, d); - self.b.cmove(&g.b, d); - } - - /* test self=0 ? */ - pub fn iszilch(&self) -> bool { - self.a.iszilch() && self.b.iszilch() - } - - pub fn islarger(&self) -> isize { - if self.iszilch() { - 0 - } else { - let cmp=self.b.islarger(); - if cmp!=0 { - cmp - } else { - self.a.islarger() - } - } - } - - pub fn tobytes(&self,bf: &mut [u8]) { - const MB:usize = 2*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - self.b.tobytes(&mut t); - for i in 0..MB { - bf[i]=t[i]; - } - self.a.tobytes(&mut t); - for i in 0..MB { - bf[i+MB]=t[i]; - } - } - - pub fn frombytes(bf: &[u8]) -> FP4 { - const MB:usize = 2*(big::MODBYTES as usize); - let mut t: [u8; MB] = [0; MB]; - for i in 0..MB { - t[i]=bf[i]; - } - let tb=FP2::frombytes(&t); - for i in 0..MB { - t[i]=bf[i+MB]; - } - let ta=FP2::frombytes(&t); - FP4::new_fp2s(&ta,&tb) - } - - - - /* test self=1 ? */ - pub fn isunity(&self) -> bool { - let one = FP2::new_int(1); - self.a.equals(&one) && self.b.iszilch() - } - - /* test is w real? That is in a+ib test b is zero */ - pub fn isreal(&mut self) -> bool { - self.b.iszilch() - } - /* extract real part a */ - pub fn real(&self) -> FP2 { - FP2::new_copy(&self.a) - } - - pub fn geta(&self) -> FP2 { - FP2::new_copy(&self.a) - } - /* extract imaginary part b */ - pub fn getb(&self) -> FP2 { - FP2::new_copy(&self.b) - } - - /* test self=x */ - pub fn equals(&self, x: &FP4) -> bool { - self.a.equals(&x.a) && self.b.equals(&x.b) - } - /* copy self=x */ - pub fn copy(&mut self, x: &FP4) { - self.a.copy(&x.a); - self.b.copy(&x.b); - } - - /* set self=0 */ - pub fn zero(&mut self) { - self.a.zero(); - self.b.zero(); - } - - /* set self=1 */ - pub fn one(&mut self) { - self.a.one(); - self.b.zero(); - } - - pub fn sign(&self) -> isize { - let mut p1=self.a.sign(); - let mut p2=self.b.sign(); - if fp::BIG_ENDIAN_SIGN { - let u=self.b.iszilch() as isize; - p2^=(p1^p2)&u; - p2 - } else { - let u=self.a.iszilch() as isize; - p1^=(p1^p2)&u; - p1 - } - } - - /* negate self mod Modulus */ - pub fn neg(&mut self) { - self.norm(); - let mut m = FP2::new_copy(&self.a); - let mut t = FP2::new(); - - m.add(&self.b); - m.neg(); - t.copy(&m); - t.add(&self.b); - self.b.copy(&m); - self.b.add(&self.a); - self.a.copy(&t); - self.norm(); - } - - /* set to a-ib */ - pub fn conj(&mut self) { - self.b.neg(); - self.norm(); - } - - /* self=-conjugate(self) */ - pub fn nconj(&mut self) { - self.a.neg(); - self.norm(); - } - - /* self+=a */ - pub fn add(&mut self, x: &FP4) { - self.a.add(&x.a); - self.b.add(&x.b); - } - - pub fn padd(&mut self, x: &FP2) { - self.a.add(x); - } - - pub fn dbl(&mut self) { - self.a.dbl(); - self.b.dbl(); - } - - /* self-=a */ - pub fn sub(&mut self, x: &FP4) { - let mut m = FP4::new_copy(x); - m.neg(); - self.add(&m); - } - - /* self-=a */ - pub fn rsub(&mut self, x: &FP4) { - self.neg(); - self.add(x); - } - - /* self*=s, where s is an FP2 */ - pub fn pmul(&mut self, s: &FP2) { - self.a.mul(s); - self.b.mul(s); - } - - /* self*=s, where s is an FP */ - pub fn qmul(&mut self, s: &FP) { - self.a.pmul(s); - self.b.pmul(s); - } - - /* self*=i, where i is an int */ - pub fn imul(&mut self, c: isize) { - self.a.imul(c); - self.b.imul(c); - } - - /* self*=self */ - - pub fn sqr(&mut self) { - let mut t1 = FP2::new_copy(&self.a); - let mut t2 = FP2::new_copy(&self.b); - let mut t3 = FP2::new_copy(&self.a); - - t3.mul(&self.b); - t1.add(&self.b); - t2.mul_ip(); - - t2.add(&self.a); - - t1.norm(); - t2.norm(); - - self.a.copy(&t1); - - self.a.mul(&t2); - - t2.copy(&t3); - t2.mul_ip(); - t2.add(&t3); - t2.norm(); - t2.neg(); - self.a.add(&t2); - - t3.dbl(); - self.b.copy(&t3); - - self.norm(); - } - - /* self*=y */ - pub fn mul(&mut self, y: &FP4) { - //self.norm(); - - let mut t1 = FP2::new_copy(&self.a); - let mut t2 = FP2::new_copy(&self.b); - let mut t3 = FP2::new(); - let mut t4 = FP2::new_copy(&self.b); - - t1.mul(&y.a); - t2.mul(&y.b); - t3.copy(&y.b); - t3.add(&y.a); - t4.add(&self.a); - - t3.norm(); - t4.norm(); - - t4.mul(&t3); - - t3.copy(&t1); - t3.neg(); - t4.add(&t3); - t4.norm(); - - t3.copy(&t2); - t3.neg(); - self.b.copy(&t4); - self.b.add(&t3); - - t2.mul_ip(); - self.a.copy(&t2); - self.a.add(&t1); - - self.norm(); - } - - /* output to hex string */ - #[cfg(feature = "std")] - pub fn tostring(&self) -> String { - format!("[{},{}]", self.a.tostring(), self.b.tostring()) - } - - /* self=1/self */ - pub fn inverse(&mut self,h:Option<&FP>) { - //self.norm(); - - let mut t1 = FP2::new_copy(&self.a); - let mut t2 = FP2::new_copy(&self.b); - - t1.sqr(); - t2.sqr(); - t2.mul_ip(); - t2.norm(); - t1.sub(&t2); - t1.inverse(h); - self.a.mul(&t1); - t1.neg(); - t1.norm(); - self.b.mul(&t1); - } - - /* self*=i where i = sqrt(-1+sqrt(-1)) */ - pub fn times_i(&mut self) { - let mut t = FP2::new_copy(&self.b); - self.b.copy(&self.a); - t.mul_ip(); - self.a.copy(&t); - self.norm(); - if fp::TOWER == fp::POSITOWER { - self.neg(); - self.norm(); - } - } - - /* self=self^p using Frobenius */ - pub fn frob(&mut self, f: &FP2) { - self.a.conj(); - self.b.conj(); - self.b.mul(f); - } - - /* return this^e */ -/* - pub fn pow(&self, e: &BIG) -> FP4 { - let mut w = FP4::new_copy(self); - w.norm(); - let mut z = BIG::new_copy(&e); - let mut r = FP4::new_int(1); - z.norm(); - loop { - let bt = z.parity(); - z.fshr(1); - if bt == 1 { - r.mul(&mut w) - }; - if z.iszilch() { - break; - } - w.sqr(); - } - r.reduce(); - r - } -*/ - /* XTR xtr_a function */ - pub fn xtr_a(&mut self, w: &FP4, y: &FP4, z: &FP4) { - let mut r = FP4::new_copy(w); - let mut t = FP4::new_copy(w); - r.sub(y); - r.norm(); - r.pmul(&self.a); - t.add(y); - t.norm(); - t.pmul(&self.b); - t.times_i(); - - self.copy(&r); - self.add(&t); - self.add(z); - - self.norm(); - } - - /* XTR xtr_d function */ - pub fn xtr_d(&mut self) { - let mut w = FP4::new_copy(self); - self.sqr(); - w.conj(); - w.dbl(); - w.norm(); - self.sub(&w); - self.reduce(); - } - - /* r=x^n using XTR method on traces of FP12s */ - pub fn xtr_pow(&self, n: &BIG) -> FP4 { - let mut sf = FP4::new_copy(self); - sf.norm(); - let mut a = FP4::new_int(3); - let mut b = FP4::new_copy(&sf); - let mut c = FP4::new_copy(&b); - c.xtr_d(); - let mut t = FP4::new(); - let mut r = FP4::new(); - - let par = n.parity(); - let mut v = BIG::new_copy(n); - v.norm(); - v.fshr(1); - if par == 0 { - v.dec(1); - v.norm(); - } - - let nb = v.nbits(); - for i in (0..nb).rev() { - if v.bit(i) != 1 { - t.copy(&b); - sf.conj(); - c.conj(); - b.xtr_a(&a, &sf, &c); - sf.conj(); - c.copy(&t); - c.xtr_d(); - a.xtr_d(); - } else { - t.copy(&a); - t.conj(); - a.copy(&b); - a.xtr_d(); - b.xtr_a(&c, &sf, &t); - c.xtr_d(); - } - } - if par == 0 { - r.copy(&c) - } else { - r.copy(&b) - } - r.reduce(); - r - } - - /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ - pub fn xtr_pow2(&mut self, ck: &FP4, ckml: &FP4, ckm2l: &FP4, a: &BIG, b: &BIG) -> FP4 { - let mut e = BIG::new_copy(a); - let mut d = BIG::new_copy(b); - let mut w = BIG::new(); - e.norm(); - d.norm(); - - let mut cu = FP4::new_copy(ck); // can probably be passed in w/o copying - let mut cv = FP4::new_copy(self); - let mut cumv = FP4::new_copy(ckml); - let mut cum2v = FP4::new_copy(ckm2l); - let mut r = FP4::new(); - let mut t = FP4::new(); - - let mut f2: usize = 0; - while d.parity() == 0 && e.parity() == 0 { - d.fshr(1); - e.fshr(1); - f2 += 1; - } - - while BIG::comp(&d, &e) != 0 { - if BIG::comp(&d, &e) > 0 { - w.copy(&e); - w.imul(4); - w.norm(); - if BIG::comp(&d, &w) <= 0 { - w.copy(&d); - d.copy(&e); - e.rsub(&w); - e.norm(); - - t.copy(&cv); - t.xtr_a(&cu, &cumv, &cum2v); - cum2v.copy(&cumv); - cum2v.conj(); - cumv.copy(&cv); - cv.copy(&cu); - cu.copy(&t); - } else if d.parity() == 0 { - d.fshr(1); - r.copy(&cum2v); - r.conj(); - t.copy(&cumv); - t.xtr_a(&cu, &cv, &r); - cum2v.copy(&cumv); - cum2v.xtr_d(); - cumv.copy(&t); - cu.xtr_d(); - } else if e.parity() == 1 { - d.sub(&e); - d.norm(); - d.fshr(1); - t.copy(&cv); - t.xtr_a(&cu, &cumv, &cum2v); - cu.xtr_d(); - cum2v.copy(&cv); - cum2v.xtr_d(); - cum2v.conj(); - cv.copy(&t); - } else { - w.copy(&d); - d.copy(&e); - d.fshr(1); - e.copy(&w); - t.copy(&cumv); - t.xtr_d(); - cumv.copy(&cum2v); - cumv.conj(); - cum2v.copy(&t); - cum2v.conj(); - t.copy(&cv); - t.xtr_d(); - cv.copy(&cu); - cu.copy(&t); - } - } - if BIG::comp(&d, &e) < 0 { - w.copy(&d); - w.imul(4); - w.norm(); - if BIG::comp(&e, &w) <= 0 { - e.sub(&d); - e.norm(); - t.copy(&cv); - t.xtr_a(&cu, &cumv, &cum2v); - cum2v.copy(&cumv); - cumv.copy(&cu); - cu.copy(&t); - } else if e.parity() == 0 { - w.copy(&d); - d.copy(&e); - d.fshr(1); - e.copy(&w); - t.copy(&cumv); - t.xtr_d(); - cumv.copy(&cum2v); - cumv.conj(); - cum2v.copy(&t); - cum2v.conj(); - t.copy(&cv); - t.xtr_d(); - cv.copy(&cu); - cu.copy(&t); - } else if d.parity() == 1 { - w.copy(&e); - e.copy(&d); - w.sub(&d); - w.norm(); - d.copy(&w); - d.fshr(1); - t.copy(&cv); - t.xtr_a(&cu, &cumv, &cum2v); - cumv.conj(); - cum2v.copy(&cu); - cum2v.xtr_d(); - cum2v.conj(); - cu.copy(&cv); - cu.xtr_d(); - cv.copy(&t); - } else { - d.fshr(1); - r.copy(&cum2v); - r.conj(); - t.copy(&cumv); - t.xtr_a(&cu, &cv, &r); - cum2v.copy(&cumv); - cum2v.xtr_d(); - cumv.copy(&t); - cu.xtr_d(); - } - } - } - r.copy(&cv); - r.xtr_a(&cu, &cumv, &cum2v); - for _ in 0..f2 { - r.xtr_d() - } - r = r.xtr_pow(&d); - r - } - - /* this/=2 */ - pub fn div2(&mut self) { - self.a.div2(); - self.b.div2(); - } - - pub fn div_i(&mut self) { - let mut u = FP2::new_copy(&self.a); - let v = FP2::new_copy(&self.b); - u.div_ip(); - self.a.copy(&v); - self.b.copy(&u); - if fp::TOWER == fp::POSITOWER { - self.neg(); - self.norm(); - } - } -/* - pub fn pow(&mut self, e: &BIG) { - let mut w = FP4::new_copy(self); - let mut z = BIG::new_copy(&e); - let mut r = FP4::new_int(1); - loop { - let bt = z.parity(); - z.fshr(1); - if bt == 1 { - r.mul(&mut w) - }; - if z.iszilch() { - break; - } - w.sqr(); - } - r.reduce(); - self.copy(&r); - } -*/ - -/* PFGE24S - - pub fn qr(&mut self,h:Option<&mut FP>) -> isize { - let mut c=FP4::new_copy(self); - c.conj(); - c.mul(self); - c.geta().qr(h) - } - - // sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) - // returns true if this is QR - pub fn sqrt(&mut self,h:Option<&FP>) { - if self.iszilch() { - return; - } - - let mut a = FP2::new_copy(&self.a); - let mut b = FP2::new_copy(&self.a); - let mut s = FP2::new_copy(&self.b); - let mut t = FP2::new_copy(&self.a); - let mut hint = FP::new(); - - s.sqr(); - a.sqr(); - s.mul_ip(); - s.norm(); - a.sub(&s); - - s.copy(&a); s.norm(); - - s.sqrt(h); - - a.copy(&t); - a.add(&s); - a.norm(); - a.div2(); - - - b.copy(&self.b); b.div2(); - let qr=a.qr(Some(&mut hint)); - - -// tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial - s.copy(&a); - let mut twk = FP::new_big(&BIG::new_ints(&rom::TWK)); - twk.mul(&hint); - s.div_ip(); s.norm(); - - a.cmove(&s,1-qr); - hint.cmove(&twk,1-qr); - - self.a.copy(&a); self.a.sqrt(Some(&hint)); - s.copy(&a); s.inverse(Some(&hint)); - s.mul(&self.a); - self.b.copy(&s); self.b.mul(&b); - t.copy(&self.a); - - self.a.cmove(&self.b,1-qr); - self.b.cmove(&t,1-qr); - - let sgn=self.sign(); - let mut nr=FP4::new_copy(&self); - nr.neg(); nr.norm(); - self.cmove(&nr,sgn); - } -PFGE24F */ -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs deleted file mode 100644 index 6aa0b7ce0f19..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/hpke.rs +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::ecp; -use crate::bn254::ecdh; - -use crate::hmac; -use crate::rand::RAND; - -const GROUP: usize = ecdh::EGS; -const POINT: usize = 2*ecdh::EFS+1; - -const MAX_LABEL: usize = 20; // may need adjustment - -#[allow(non_snake_case)] -fn reverse (x: &mut [u8]) { - let lx=x.len(); - for i in 0..lx/2 { - let ch=x[i]; - x[i]=x[lx-i-1]; - x[lx-i-1]=ch; - } -} -/* -fn printbinary(array: &[u8]) { - for i in 0..array.len() { - print!("{:02X}", array[i]) - } - println!("") -} -*/ - -#[allow(non_snake_case)] -fn labeledExtract(prk: &mut [u8],salt: Option<&[u8]>,suite_id: &[u8],label: &str,ikm: Option<&[u8]>) { - let rfc="HPKE-v1"; - let prefix1=rfc.as_bytes(); - let prefix2=label.as_bytes(); - let mut likm: [u8; 18+MAX_LABEL+2*POINT] = [0; 18+MAX_LABEL+2*POINT]; - let mut k=0; - for i in 0..prefix1.len() { - likm[k]=prefix1[i]; - k+=1; - } - for i in 0..suite_id.len() { - likm[k]=suite_id[i]; - k+=1; - } - for i in 0..prefix2.len() { - likm[k]=prefix2[i]; - k+=1; - } - if let Some(sikm) = ikm { - for i in 0..sikm.len() { - likm[k]=sikm[i]; - k+=1; - } - } - hmac::hkdf_extract(hmac::MC_SHA2,ecp::HASH_TYPE,prk,salt,&likm[0..k]); -} - -#[allow(non_snake_case)] -fn labeledExpand(okm: &mut [u8],prk: &[u8],suite_id: &[u8],label: &str,info: Option<&[u8]>,el: usize) { - let mut ar: [u8; 2] = [0; 2]; - let rfc="HPKE-v1"; - let prefix1=rfc.as_bytes(); - let prefix2=label.as_bytes(); - hmac::inttobytes(el,&mut ar); - let mut linfo: [u8; 20+MAX_LABEL+3*POINT] = [0; 20+MAX_LABEL+3*POINT]; - linfo[0]=ar[0]; - linfo[1]=ar[1]; - let mut k=2; - for i in 0..prefix1.len() { - linfo[k]=prefix1[i]; - k+=1; - } - for i in 0..suite_id.len() { - linfo[k]=suite_id[i]; - k+=1; - } - for i in 0..prefix2.len() { - linfo[k]=prefix2[i]; - k+=1; - } - if let Some(sinfo) = info { - for i in 0..sinfo.len() { - linfo[k]=sinfo[i]; - k+=1; - } - } - hmac:: hkdf_expand(hmac::MC_SHA2,ecp::HASH_TYPE,okm,el,prk,&linfo[0..k]); -} - -#[allow(non_snake_case)] -fn extractAndExpand(config_id: usize,okm: &mut [u8],dh: &[u8],context: &[u8]) { - let kem = config_id&255; - let txt="KEM"; - let mut suite_id: [u8;5] = [0;5]; - let mut kem_id: [u8; 2] = [0; 2]; - let ckem=txt.as_bytes(); - hmac::inttobytes(kem,&mut kem_id); - let mut k=0; - for i in 0..ckem.len() { - suite_id[k]=ckem[i]; - k+=1; - } - suite_id[k]=kem_id[0]; k+=1; - suite_id[k]=kem_id[1]; - - let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; - labeledExtract(&mut prk,None,&suite_id,"eae_prk",Some(dh)); - labeledExpand(okm,&prk,&suite_id,"shared_secret",Some(&context),ecp::HASH_TYPE); -} - -#[allow(non_snake_case)] -pub fn deriveKeyPair(config_id: usize,mut sk: &mut [u8],mut pk: &mut [u8],seed: &[u8]) -> bool { - let mut counter=0; - let kem = config_id&255; - let txt="KEM"; - let mut suite_id: [u8;5] = [0;5]; - let mut kem_id: [u8; 2] = [0; 2]; - let ckem=txt.as_bytes(); - hmac::inttobytes(kem,&mut kem_id); - let mut k=0; - for i in 0..ckem.len() { - suite_id[k]=ckem[i]; - k+=1; - } - suite_id[k]=kem_id[0]; k+=1; - suite_id[k]=kem_id[1]; - - let mut prk: [u8;ecp::HASH_TYPE]=[0;ecp::HASH_TYPE]; - labeledExtract(&mut prk,None,&suite_id,"dkp_prk",Some(&seed)); - - //println!("prk= {:02X?}",prk); - - if kem==32 || kem==33 { // RFC7748 - labeledExpand(&mut sk,&prk,&suite_id,"sk",None,GROUP); - reverse(&mut sk); - if kem==32 { - sk[GROUP-1]&=248; - sk[0]&=127; - sk[0]|=64; - } else { - sk[GROUP-1]&=252; - sk[0]|=128; - } - } else { - let mut bit_mask=0xff; - if kem==18 { - bit_mask=1; - } - for i in 0..GROUP { - sk[i]=0; - } - while !ecdh::in_range(&sk) && counter<256 { - let mut info: [u8;1]=[0;1]; - info[0]=counter as u8; - labeledExpand(sk,&prk,&suite_id,"candidate",Some(&info),GROUP); - sk[0] &= bit_mask as u8; - counter += 1; - } - } - //for i in 0..sk.len() { -// print!({} -// println!("SK= {:02X?}",sk); - // println!("kem= {}",kem); - //println!("counter= {}",counter); - ecdh::key_pair_generate(None::<&mut RAND>, &mut sk, &mut pk); - if kem==32 || kem==33 { - reverse(&mut pk); - } - counter<256 -} - -#[allow(non_snake_case)] -pub fn encap(config_id: usize,skE: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { - let pklen=pkE.len(); - let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; - let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; - let kem = config_id&255; - let mut rev: [u8; POINT]=[0; POINT]; - - if kem==32 || kem==33 { - for i in 0..pklen { - rev[i]=pkR[i]; - } - reverse(&mut rev[0..pklen]); - ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); - reverse(&mut dh[0..pklen]); - } else { - ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); - } - let mut k=0; - for i in 0..pklen { - kemcontext[k]=pkE[i]; - k+=1; - } - for i in 0..pklen { - kemcontext[k]=pkR[i]; - k+=1; - } -//print!("e dh= "); printbinary(&dh[0..pklen]); - extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); -} - -#[allow(non_snake_case)] -pub fn decap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8]) { - let pklen=pkE.len(); - let mut dh: [u8; ecdh::EFS] = [0; ecdh::EFS]; - let mut kemcontext: [u8; 2*POINT] = [0;2*POINT]; - let mut rev: [u8; POINT]=[0; POINT]; - let kem = config_id&255; - - if kem==32 || kem==33 { - for i in 0..pklen { - rev[i]=pkE[i]; - } - reverse(&mut rev[0..pklen]); - ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); - reverse(&mut dh[0..pklen]); - } else { - ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); - } - - let mut k=0; - for i in 0..pklen { - kemcontext[k]=pkE[i]; - k+=1; - } - for i in 0..pklen { // not a mistake - kemcontext[k]=pkR[i]; - k+=1; - } -//print!("d dh= "); printbinary(&dh[0..pklen]); - extractAndExpand(config_id,z,&dh,&kemcontext[0..k]); -} - -#[allow(non_snake_case)] -pub fn authencap(config_id: usize,skE: &[u8],skS: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { - let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; - let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; - - let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; - let kem = config_id&255; - let pklen=pkE.len(); - let mut rev: [u8; POINT]=[0; POINT]; - - - if kem==32 || kem==33 { - for i in 0..pklen { - rev[i]=pkR[i]; - } - reverse(&mut rev[0..pklen]); - ecdh::ecpsvdp_dh(&skE, &rev[0..pklen], &mut dh, 0); - ecdh::ecpsvdp_dh(&skS, &rev[0..pklen], &mut dh1, 0); - reverse(&mut dh[0..pklen]); - reverse(&mut dh1[0..pklen]); - } else { - ecdh::ecpsvdp_dh(&skE, &pkR, &mut dh, 0); - ecdh::ecpsvdp_dh(&skS, &pkR, &mut dh1, 0); - } - - for i in 0..ecdh::EFS { - dh[i+ecdh::EFS] = dh1[i]; - } - - for i in 0..pklen { - kemcontext[i]=pkE[i]; - kemcontext[pklen+i]= pkR[i]; - kemcontext[2*pklen+i]= pkS[i]; - } -//print!("e dh= "); printbinary(&dh[0..pklen]); -//print!("e kemcontext= "); printbinary(&kemcontext[0..3*pklen]); - extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); -} - -#[allow(non_snake_case)] -pub fn authdecap(config_id: usize,skR: &[u8],z: &mut [u8],pkE: &[u8],pkR: &[u8],pkS: &[u8]) { - let mut dh: [u8; 2*ecdh::EFS] = [0; 2*ecdh::EFS]; - let mut dh1: [u8; ecdh::EFS] = [0; ecdh::EFS]; - let mut kemcontext: [u8; 3*POINT] = [0;3*POINT]; - let kem = config_id&255; - let pklen=pkE.len(); - let mut rev: [u8; POINT]=[0; POINT]; - - if kem==32 || kem==33 { - for i in 0..pklen { - rev[i]=pkE[i]; - } - reverse(&mut rev[0..pklen]); - ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh, 0); - for i in 0..pklen { - rev[i]=pkS[i]; - } - reverse(&mut rev[0..pklen]); - ecdh::ecpsvdp_dh(&skR, &rev[0..pklen], &mut dh1, 0); - reverse(&mut dh[0..pklen]); - reverse(&mut dh1[0..pklen]); - } else { - ecdh::ecpsvdp_dh(&skR, &pkE, &mut dh, 0); - ecdh::ecpsvdp_dh(&skR, &pkS, &mut dh1, 0); - } - - for i in 0..ecdh::EFS { - dh[i+ecdh::EFS] = dh1[i]; - } - - for i in 0..pklen { - kemcontext[i]=pkE[i]; - kemcontext[pklen+i]= pkR[i]; - kemcontext[2*pklen+i]= pkS[i]; - } -//print!("d dh= "); printbinary(&dh[0..pklen]); -//print!("d kemcontext= "); printbinary(&kemcontext[0..3*pklen]); - extractAndExpand(config_id,z,&dh,&kemcontext[0..3*pklen]); -} - -#[allow(non_snake_case)] -pub fn keyschedule(config_id: usize,key: &mut [u8],nonce: &mut [u8],exp_secret: &mut [u8],mode: usize,z: &mut [u8],info: &[u8],psk: Option<&[u8]>,pskID: Option<&[u8]>) { - - let mut context: [u8; 1+2*ecp::HASH_TYPE] = [0; 1+2*ecp::HASH_TYPE]; - let kem=config_id&255; - let kdf=(config_id>>8)&3; - let aead=(config_id>>10)&3; - - let txt="HPKE"; - let ckem=txt.as_bytes(); - let mut suite_id: [u8;10] = [0;10]; - let mut num: [u8; 2] = [0; 2]; - - let mut k=0; - for i in 0..ckem.len() { - suite_id[k]=ckem[i]; - k+=1; - } - hmac::inttobytes(kem,&mut num); - suite_id[k]=num[0]; k+=1; - suite_id[k]=num[1]; k+=1; - hmac::inttobytes(kdf,&mut num); - suite_id[k]=num[0]; k+=1; - suite_id[k]=num[1]; k+=1; - hmac::inttobytes(aead,&mut num); - suite_id[k]=num[0]; k+=1; - suite_id[k]=num[1]; - - let mut k=0; - let mut h: [u8; 64] = [0; 64]; - let mut secret: [u8; 64] = [0; 64]; - - context[k]=mode as u8; k+=1; - - labeledExtract(&mut h,None,&suite_id,"psk_id_hash",pskID); - for i in 0..ecp::HASH_TYPE { - context[k] = h[i]; k+=1; - } - labeledExtract(&mut h,None,&suite_id,"info_hash",Some(&info)); - for i in 0..ecp::HASH_TYPE { - context[k] = h[i]; k+=1; - } - - //labeledExtract(&mut h,None,&suite_id,"psk_hash",psk); - - //labeledExtract(&mut secret,Some(&h),&suite_id,"secret",Some(z)); - - labeledExtract(&mut secret,Some(z),&suite_id,"secret",psk); - - labeledExpand(key,&secret,&suite_id,"key",Some(&context[0..k]),ecp::AESKEY); - labeledExpand(nonce,&secret,&suite_id,"base_nonce",Some(&context[0..k]),12); - labeledExpand(exp_secret,&secret,&suite_id,"exp",Some(&context[0..k]),ecp::HASH_TYPE); -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs deleted file mode 100644 index 89eca15de70e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pub mod big; -pub mod bls; -pub mod dbig; -pub mod ecp; -pub mod ecp2; -pub mod fp; -pub mod fp12; -pub mod fp2; -pub mod fp4; -pub mod mpin; -pub mod pair; -pub mod rom; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs deleted file mode 100644 index 3b3121e5dda5..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/mpin.rs +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big; -use crate::bn254::big::BIG; -use crate::bn254::ecp; -use crate::bn254::ecp::ECP; -use crate::bn254::ecp2::ECP2; -use crate::bn254::fp12::FP12; -use crate::bn254::pair; -use crate::bn254::rom; -use crate::bn254::fp::FP; -use crate::bn254::dbig::DBIG; - -use crate::hmac; -use crate::rand::RAND; - -/* MPIN 128-bit API Functions */ - -/* Configure mode of operation */ - -pub const EFS: usize = big::MODBYTES as usize; -pub const EGS: usize = big::MODBYTES as usize; -pub const BAD_PARAMS: isize = -11; -pub const INVALID_POINT: isize = -14; -pub const WRONG_ORDER: isize = -18; -pub const BAD_PIN: isize = -19; -pub const SHA256: usize = 32; -pub const SHA384: usize = 48; -pub const SHA512: usize = 64; - -/* Configure your PIN here */ - -pub const MAXPIN: i32 = 10000; /* PIN less than this */ -pub const PBLEN: i32 = 14; /* Number of bits in PIN */ - -fn ceil(a: usize,b: usize) -> usize { - (a-1)/b+1 -} - -#[allow(non_snake_case)] -pub fn encode_to_curve(dst: &[u8],id: &[u8],hcid: &mut [u8]) { - let q = BIG::new_ints(&rom::MODULUS); - let k=q.nbits(); - let r = BIG::new_ints(&rom::CURVE_ORDER); - let m=r.nbits(); - let el=ceil(k+ceil(m,2),8); - let mut okm: [u8;512]=[0;512]; - hmac::xmd_expand(hmac::MC_SHA2,ecp::HASH_TYPE,&mut okm,el,&dst,&id); - let mut fd: [u8;256]=[0;256]; - for j in 0..el { - fd[j]=okm[j]; - } - let mut dx=DBIG::frombytes(&fd[0..el]); - let u=FP::new_big(&dx.dmod(&q)); - let mut P=ECP::map2point(&u); - P.cfp(); - P.affine(); - P.tobytes(hcid,false); -} - -/* create random secret S */ -pub fn random_generate(rng: &mut RAND, s: &mut [u8]) -> isize { - let r = BIG::new_ints(&rom::CURVE_ORDER); - let sc = BIG::randtrunc(&r, 16 * ecp::AESKEY, rng); - sc.tobytes(s); - 0 -} - -/* Extract PIN from TOKEN for identity CID */ -#[allow(non_snake_case)] -pub fn extract_pin(cid: &[u8], pin: i32, token: &mut [u8]) -> isize { - let mut P = ECP::frombytes(&token); - if P.is_infinity() { - return INVALID_POINT; - } - let mut R = ECP::frombytes(&cid); - if R.is_infinity() { - return INVALID_POINT; - } - - R = R.pinmul(pin%MAXPIN, PBLEN); - P.sub(&R); - P.tobytes(token, false); - 0 -} - -/* Implement step 2 on client side of MPin protocol */ -#[allow(non_snake_case)] -pub fn client_2(x: &[u8], y: &[u8], sec: &mut [u8]) -> isize { - let r = BIG::new_ints(&rom::CURVE_ORDER); - let mut P = ECP::frombytes(sec); - if P.is_infinity() { - return INVALID_POINT; - } - - let mut px = BIG::frombytes(x); - let py = BIG::frombytes(y); - px.add(&py); - px.rmod(&r); - - P = pair::g1mul(&P, &px); - P.neg(); - P.tobytes(sec, false); - 0 -} - -/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ -#[allow(non_snake_case)] -pub fn get_client_secret(s: &mut [u8], idhtc: &[u8], cst: &mut [u8]) -> isize { - let sx=BIG::frombytes(s); - let P=ECP::frombytes(idhtc); - if P.is_infinity() { - return INVALID_POINT; - } - pair::g1mul(&P, &sx).tobytes(cst, false); - 0 -} - -/* Implement step 1 on client side of MPin protocol */ -#[allow(non_snake_case)] -pub fn client_1( - cid: &[u8], - rng: Option<&mut RAND>, - x: &mut [u8], - pin: usize, - token: &[u8], - sec: &mut [u8], - xid: &mut [u8] -) -> isize { - let r = BIG::new_ints(&rom::CURVE_ORDER); - let sx: BIG; - - if let Some(rd) = rng { - sx = BIG::randtrunc(&r, 16 * ecp::AESKEY, rd); - sx.tobytes(x); - } else { - sx = BIG::frombytes(x); - } - let mut P=ECP::frombytes(cid); - if P.is_infinity() { - return INVALID_POINT; - } - - let mut T = ECP::frombytes(&token); - if T.is_infinity() { - return INVALID_POINT; - } - - let W = P.pinmul((pin as i32) % MAXPIN, PBLEN); - T.add(&W); - - P = pair::g1mul(&P, &sx); - P.tobytes(xid, false); - - T.tobytes(sec, false); - 0 -} - - -/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ -#[allow(non_snake_case)] -pub fn get_server_secret(s: &[u8], sst: &mut [u8]) -> isize { - let mut Q = ECP2::generator(); - let sc = BIG::frombytes(s); - Q = pair::g2mul(&Q, &sc); - Q.tobytes(sst,false); - 0 -} - -/* Implement step 2 of MPin protocol on server side */ -#[allow(non_snake_case)] -pub fn server( - hid: &[u8], - y: &[u8], - sst: &[u8], - xid: &[u8], - msec: &[u8], -) -> isize { - let Q = ECP2::generator(); - let sQ = ECP2::frombytes(&sst); - if sQ.is_infinity() { - return INVALID_POINT; - } - let mut R = ECP::frombytes(&xid); - if R.is_infinity() { - return INVALID_POINT; - } - - let sy = BIG::frombytes(&y); - let mut P = ECP::frombytes(&hid); - if P.is_infinity() { - return INVALID_POINT; - } - - P = pair::g1mul(&P, &sy); - P.add(&R); - R = ECP::frombytes(&msec); - if R.is_infinity() { - return INVALID_POINT; - } - - let mut g: FP12; - g = pair::ate2(&Q, &R, &sQ, &P); - g = pair::fexp(&g); - - if !g.isunity() { - return BAD_PIN; - } - 0 -} - diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs deleted file mode 100644 index 360fe0fcd07a..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/pair.rs +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::bn254::big::BIG; -use crate::bn254::ecp; -use crate::bn254::ecp::ECP; -use crate::bn254::ecp2::ECP2; -use crate::bn254::fp::FP; -use crate::bn254::fp12; -use crate::bn254::fp12::FP12; -use crate::bn254::fp2::FP2; -use crate::bn254::fp4::FP4; -use crate::bn254::rom; - -#[allow(unused_imports)] -use crate::bn254::dbig::DBIG; - -#[allow(non_snake_case)] -fn dbl(A: &mut ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { - cc.copy(&A.getpx()); //X - let mut yy = FP2::new_copy(&A.getpy()); //Y - bb.copy(&A.getpz()); //Z - - aa.copy(&yy); //Y - aa.mul(&bb); //YZ - cc.sqr(); //X^2 - yy.sqr(); //Y^2 - bb.sqr(); //Z^2 - - aa.dbl(); - aa.neg(); aa.norm(); - aa.mul_ip(); - aa.norm(); - - let sb = 3 * rom::CURVE_B_I; - bb.imul(sb); - cc.imul(3); - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - yy.mul_ip(); - yy.norm(); - cc.mul_ip(); - cc.norm(); - } - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - bb.mul_ip(); - bb.norm(); - } - bb.sub(&yy); - bb.norm(); - A.dbl(); -} - -#[allow(non_snake_case)] -fn add(A: &mut ECP2, B: &ECP2, aa: &mut FP2, bb: &mut FP2, cc: &mut FP2) { - - aa.copy(&A.getpx()); // X1 - cc.copy(&A.getpy()); // Y1 - let mut t1 = FP2::new_copy(&A.getpz()); // Z1 - bb.copy(&A.getpz()); // Z1 - - t1.mul(&B.getpy()); // T1=Z1.Y2 - bb.mul(&B.getpx()); // T2=Z1.X2 - - aa.sub(&bb); - aa.norm(); // X1=X1-Z1.X2 - cc.sub(&t1); - cc.norm(); // Y1=Y1-Z1.Y2 - - t1.copy(&aa); // T1=X1-Z1.X2 - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - aa.mul_ip(); - aa.norm(); - } - - t1.mul(&B.getpy()); // T1=(X1-Z1.X2).Y2 - - bb.copy(&cc); // T2=Y1-Z1.Y2 - bb.mul(&B.getpx()); // T2=(Y1-Z1.Y2).X2 - bb.sub(&t1); - bb.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 - - cc.neg(); - cc.norm(); // Y1=-(Y1-Z1.Y2).Xs - - A.add(B); -} - -#[allow(non_snake_case)] -fn linedbl(A: &mut ECP2, qx: &FP, qy: &FP) -> FP12 { - let mut a = FP4::new(); - let mut b = FP4::new(); - let mut c = FP4::new(); - let mut aa = FP2::new(); - let mut bb = FP2::new(); - let mut cc = FP2::new(); - - dbl(A,&mut aa,&mut bb,&mut cc); - - cc.pmul(qx); - aa.pmul(qy); - - a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) - } - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - c.copy(&FP4::new_fp2(&cc)); - c.times_i(); - } - let mut res= FP12::new_fp4s(&a, &b, &c); - res.settype(fp12::SPARSER); - res -} - -#[allow(non_snake_case)] -fn lineadd(A: &mut ECP2, B: &ECP2, qx: &FP, qy: &FP) -> FP12 { - let mut a = FP4::new(); - let mut b = FP4::new(); - let mut c = FP4::new(); - let mut aa = FP2::new(); - let mut bb = FP2::new(); - let mut cc = FP2::new(); - - add(A,B,&mut aa,&mut bb,&mut cc); - - cc.pmul(qx); - aa.pmul(qy); - - a.copy(&FP4::new_fp2s(&aa, &bb)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs - if ecp::SEXTIC_TWIST == ecp::D_TYPE { - b.copy(&FP4::new_fp2(&cc)); // L(0,1) | L(0,0) | L(1,0) - } - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - c.copy(&FP4::new_fp2(&cc)); - c.times_i(); - } - let mut res= FP12::new_fp4s(&a, &b, &c); - res.settype(fp12::SPARSER); - res -} - -/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ -#[allow(non_snake_case)] -fn lbits(n3: &mut BIG,n: &mut BIG) -> usize { - n.copy(&BIG::new_ints(&rom::CURVE_BNX)); - if ecp::CURVE_PAIRING_TYPE==ecp::BN { - n.pmul(6); - if ecp::SIGN_OF_X==ecp::POSITIVEX { - n.inc(2); - } else { - n.dec(2); - } - } - n.norm(); - n3.copy(&n); - n3.pmul(3); - n3.norm(); - n3.nbits() -} - -/* prepare for multi-pairing */ -pub fn initmp() -> [FP12; ecp::ATE_BITS] { - [FP12::new_int(1); ecp::ATE_BITS] -} - -/* basic Miller loop */ -pub fn miller(r:&mut [FP12]) -> FP12 { - let mut res=FP12::new_int(1); - for i in (1..ecp::ATE_BITS).rev() { - res.sqr(); - res.ssmul(&r[i]); - r[i].zero(); - } - - if ecp::SIGN_OF_X==ecp::NEGATIVEX { - res.conj(); - } - res.ssmul(&r[0]); - r[0].zero(); - res -} - -fn pack(aa: &FP2,bb: &FP2,cc: &FP2) -> FP4 { - let mut i=FP2::new_copy(cc); - i.inverse(None); - let mut a=FP2::new_copy(aa); - let mut b=FP2::new_copy(bb); - a.mul(&i); - b.mul(&i); - FP4::new_fp2s(&a,&b) -} - -fn unpack(t: &FP4, qx: &FP, qy: &FP) -> FP12 { - let b:FP4; - let mut c:FP4; - let w=FP2::new_fp(qx); - - let mut aa=t.geta(); - let bb=t.getb(); - aa.pmul(qy); - let a=FP4::new_fp2s(&aa,&bb); - - if ecp::SEXTIC_TWIST==ecp::D_TYPE { - b=FP4::new_fp2(&w); - c=FP4::new(); - } else { - b=FP4::new(); - c=FP4::new_fp2(&w); c.times_i(); - } - let mut v=FP12::new_fp4s(&a,&b,&c); - v.settype(fp12::SPARSEST); - v -} - -#[allow(non_snake_case)] -pub fn precomp(T: &mut [FP4],GV: &ECP2) { - let mut n = BIG::new(); - let mut n3 = BIG::new(); - let nb=lbits(&mut n3,&mut n); - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let mut aa = FP2::new(); - let mut bb = FP2::new(); - let mut cc = FP2::new(); - - let mut P=ECP2::new(); P.copy(GV); - - if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { - f.inverse(None); - f.norm(); - } - - let mut A = ECP2::new(); - - A.copy(&P); - let mut NP = ECP2::new(); - NP.copy(&P); - NP.neg(); - let mut j=0; - - for i in (1..nb-1).rev() { - dbl(&mut A,&mut aa,&mut bb,&mut cc); - T[j].copy(&pack(&aa,&bb,&cc)); j+=1; - let bt=n3.bit(i)-n.bit(i); - if bt==1 { - add(&mut A,&P,&mut aa,&mut bb,&mut cc); - T[j].copy(&pack(&aa,&bb,&cc)); j+=1; - } - if bt==-1 { - add(&mut A,&NP,&mut aa,&mut bb,&mut cc); - T[j].copy(&pack(&aa,&bb,&cc)); j+=1; - } - } -/* R-ate fixup required for BN curves */ - if ecp::CURVE_PAIRING_TYPE==ecp::BN { - if ecp::SIGN_OF_X==ecp::NEGATIVEX { - A.neg(); - } - let mut K = ECP2::new(); - K.copy(&P); - K.frob(&f); - add(&mut A,&K,&mut aa,&mut bb,&mut cc); - T[j].copy(&pack(&aa,&bb,&cc)); j+=1; - K.frob(&f); - K.neg(); - add(&mut A,&K,&mut aa,&mut bb,&mut cc); - T[j].copy(&pack(&aa,&bb,&cc)); - } -} - -/* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ -#[allow(non_snake_case)] -pub fn another_pc(r:&mut [FP12],T: &[FP4],QV: &ECP) { - let mut n = BIG::new(); - let mut n3 = BIG::new(); - - if QV.is_infinity() { - return; - } - - let nb=lbits(&mut n3,&mut n); - - let mut Q = ECP::new(); - Q.copy(QV); - Q.affine(); - let qx = FP::new_copy(&Q.getpx()); - let qy = FP::new_copy(&Q.getpy()); - - let mut j=0; - for i in (1..nb-1).rev() { - let mut lv=unpack(&T[j],&qx,&qy); j+=1; - let bt=n3.bit(i)-n.bit(i); - if bt==1 { - let lv2=unpack(&T[j],&qx,&qy); j+=1; - lv.smul(&lv2); - } - if bt==-1 { - let lv2=unpack(&T[j],&qx,&qy); j+=1; - lv.smul(&lv2); - } - r[i].ssmul(&lv); - } - if ecp::CURVE_PAIRING_TYPE==ecp::BN { - let mut lv=unpack(&T[j],&qx,&qy); j+=1; - let lv2=unpack(&T[j],&qx,&qy); - lv.smul(&lv2); - r[0].ssmul(&lv); - } -} - -/* Accumulate another set of line functions for n-pairing */ -#[allow(non_snake_case)] -pub fn another(r:&mut [FP12],P1: &ECP2,Q1: &ECP) { - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let mut n = BIG::new(); - let mut n3 = BIG::new(); - let mut K = ECP2::new(); - - if Q1.is_infinity() { - return; - } -// P is needed in affine form for line function, Q for (Qx,Qy) extraction - let mut P = ECP2::new(); - P.copy(P1); - P.affine(); - let mut Q = ECP::new(); - Q.copy(Q1); - Q.affine(); - - if (ecp::CURVE_PAIRING_TYPE==ecp::BN) && (ecp::SEXTIC_TWIST==ecp::M_TYPE) { - f.inverse(None); - f.norm(); - } - - let qx = FP::new_copy(&Q.getpx()); - let qy = FP::new_copy(&Q.getpy()); - let mut A = ECP2::new(); - - A.copy(&P); - let mut NP = ECP2::new(); - NP.copy(&P); - NP.neg(); - - let nb=lbits(&mut n3,&mut n); - - for i in (1..nb-1).rev() { - let mut lv=linedbl(&mut A,&qx,&qy); - - let bt=n3.bit(i)-n.bit(i); - if bt==1 { - let lv2=lineadd(&mut A,&P,&qx,&qy); - lv.smul(&lv2); - } - if bt==-1 { - let lv2=lineadd(&mut A,&NP,&qx,&qy); - lv.smul(&lv2); - } - r[i].ssmul(&lv); - } - -/* R-ate fixup required for BN curves */ - if ecp::CURVE_PAIRING_TYPE==ecp::BN { - if ecp::SIGN_OF_X==ecp::NEGATIVEX { - A.neg(); - } - K.copy(&P); - K.frob(&f); - let mut lv=lineadd(&mut A,&K,&qx,&qy); - K.frob(&f); - K.neg(); - let lv2=lineadd(&mut A,&K,&qx,&qy); - lv.smul(&lv2); - r[0].ssmul(&lv); - } -} - -#[allow(non_snake_case)] -/* Optimal R-ate pairing */ -pub fn ate(P1: &ECP2, Q1: &ECP) -> FP12 { - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let mut n = BIG::new(); - let mut n3 = BIG::new(); - let mut K = ECP2::new(); - - if Q1.is_infinity() { - return FP12::new_int(1); - } - - if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { - f.inverse(None); - f.norm(); - } - let mut P = ECP2::new(); - P.copy(P1); - P.affine(); - let mut Q = ECP::new(); - Q.copy(Q1); - Q.affine(); - - let qx = FP::new_copy(&Q.getpx()); - let qy = FP::new_copy(&Q.getpy()); - - let mut A = ECP2::new(); - let mut r = FP12::new_int(1); - - A.copy(&P); - let mut NP = ECP2::new(); - NP.copy(&P); - NP.neg(); - - let nb=lbits(&mut n3,&mut n); - - for i in (1..nb - 1).rev() { - r.sqr(); - let mut lv = linedbl(&mut A, &qx, &qy); - let bt = n3.bit(i) - n.bit(i); - if bt == 1 { - let lv2 = lineadd(&mut A, &P, &qx, &qy); - lv.smul(&lv2); - } - if bt == -1 { - let lv2 = lineadd(&mut A, &NP, &qx, &qy); - lv.smul(&lv2); - } - r.ssmul(&lv); - } - - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - r.conj(); - } - - /* R-ate fixup required for BN curves */ - - if ecp::CURVE_PAIRING_TYPE == ecp::BN { - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - A.neg(); - } - - K.copy(&P); - K.frob(&f); - - let mut lv = lineadd(&mut A, &K, &qx, &qy); - K.frob(&f); - K.neg(); - let lv2 = lineadd(&mut A, &K, &qx, &qy); - lv.smul(&lv2); - r.ssmul(&lv); - } - - r -} - -#[allow(non_snake_case)] -/* Optimal R-ate double pairing e(P,Q).e(R,S) */ -pub fn ate2(P1: &ECP2, Q1: &ECP, R1: &ECP2, S1: &ECP) -> FP12 { - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let mut n = BIG::new(); - let mut n3 = BIG::new(); - let mut K = ECP2::new(); - - if Q1.is_infinity() { - return ate(R1,S1); - } - if S1.is_infinity() { - return ate(P1,Q1); - } - - if (ecp::CURVE_PAIRING_TYPE == ecp::BN) && (ecp::SEXTIC_TWIST == ecp::M_TYPE) { - f.inverse(None); - f.norm(); - } - - let mut P = ECP2::new(); - P.copy(P1); - P.affine(); - let mut Q = ECP::new(); - Q.copy(Q1); - Q.affine(); - let mut R = ECP2::new(); - R.copy(R1); - R.affine(); - let mut S = ECP::new(); - S.copy(S1); - S.affine(); - - let qx = FP::new_copy(&Q.getpx()); - let qy = FP::new_copy(&Q.getpy()); - - let sx = FP::new_copy(&S.getpx()); - let sy = FP::new_copy(&S.getpy()); - - let mut A = ECP2::new(); - let mut B = ECP2::new(); - let mut r = FP12::new_int(1); - - A.copy(&P); - B.copy(&R); - - let mut NP = ECP2::new(); - NP.copy(&P); - NP.neg(); - let mut NR = ECP2::new(); - NR.copy(&R); - NR.neg(); - - let nb=lbits(&mut n3,&mut n); - - for i in (1..nb - 1).rev() { - r.sqr(); - let mut lv = linedbl(&mut A, &qx, &qy); - let lv2 = linedbl(&mut B, &sx, &sy); - lv.smul(&lv2); - r.ssmul(&lv); - let bt = n3.bit(i) - n.bit(i); - if bt == 1 { - lv = lineadd(&mut A, &P, &qx, &qy); - let lv2 = lineadd(&mut B, &R, &sx, &sy); - lv.smul(&lv2); - r.ssmul(&lv); - } - if bt == -1 { - lv = lineadd(&mut A, &NP, &qx, &qy); - let lv2 = lineadd(&mut B, &NR, &sx, &sy); - lv.smul(&lv2); - r.ssmul(&lv); - } - } - - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - r.conj(); - } - - /* R-ate fixup */ - if ecp::CURVE_PAIRING_TYPE == ecp::BN { - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - A.neg(); - B.neg(); - } - K.copy(&P); - K.frob(&f); - - let mut lv = lineadd(&mut A, &K, &qx, &qy); - K.frob(&f); - K.neg(); - let mut lv2 = lineadd(&mut A, &K, &qx, &qy); - lv.smul(&lv2); - r.ssmul(&lv); - - K.copy(&R); - K.frob(&f); - - lv = lineadd(&mut B, &K, &sx, &sy); - K.frob(&f); - K.neg(); - lv2 = lineadd(&mut B, &K, &sx, &sy); - lv.smul(&lv2); - r.ssmul(&lv); - - } - - r -} - -/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ -pub fn fexp(m: &FP12) -> FP12 { - let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let x = BIG::new_ints(&rom::CURVE_BNX); - let mut r = FP12::new_copy(m); - - /* Easy part of final exp */ - let mut lv = FP12::new_copy(&r); - lv.inverse(); - r.conj(); - - r.mul(&lv); - lv.copy(&r); - r.frob(&f); - r.frob(&f); - r.mul(&lv); - - /* Hard part of final exp */ - if ecp::CURVE_PAIRING_TYPE == ecp::BN { - lv.copy(&r); - lv.frob(&f); - let mut x0 = FP12::new_copy(&lv); - x0.frob(&f); - lv.mul(&r); - x0.mul(&lv); - x0.frob(&f); - let mut x1 = FP12::new_copy(&r); - x1.conj(); - let mut x4 = r.pow(&x); - if ecp::SIGN_OF_X == ecp::POSITIVEX { - x4.conj(); - } - - let mut x3 = FP12::new_copy(&x4); - x3.frob(&f); - - let mut x2 = x4.pow(&x); - if ecp::SIGN_OF_X == ecp::POSITIVEX { - x2.conj(); - } - let mut x5 = FP12::new_copy(&x2); - x5.conj(); - lv = x2.pow(&x); - if ecp::SIGN_OF_X == ecp::POSITIVEX { - lv.conj(); - } - x2.frob(&f); - r.copy(&x2); - r.conj(); - - x4.mul(&r); - x2.frob(&f); - - r.copy(&lv); - r.frob(&f); - lv.mul(&r); - - lv.usqr(); - lv.mul(&x4); - lv.mul(&x5); - r.copy(&x3); - r.mul(&x5); - r.mul(&lv); - lv.mul(&x2); - r.usqr(); - r.mul(&lv); - r.usqr(); - lv.copy(&r); - lv.mul(&x1); - r.mul(&x0); - lv.usqr(); - r.mul(&lv); - r.reduce(); - } else { - -// See https://eprint.iacr.org/2020/875.pdf - let mut y1 = FP12::new_copy(&r); - y1.usqr(); - y1.mul(&r); // y1=r^3 - - let mut y0 = FP12::new_copy(&r.pow(&x)); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - y0.conj(); - } - let mut t0 = FP12::new_copy(&r); t0.conj(); - r.copy(&y0); - r.mul(&t0); - - y0.copy(&r.pow(&x)); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - y0.conj(); - } - t0.copy(&r); t0.conj(); - r.copy(&y0); - r.mul(&t0); - -// ^(x+p) - y0.copy(&r.pow(&x)); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - y0.conj(); - } - t0.copy(&r); - t0.frob(&f); - r.copy(&y0); - r.mul(&t0); - -// ^(x^2+p^2-1) - y0.copy(&r.pow(&x)); - y0.copy(&y0.pow(&x)); - t0.copy(&r); - t0.frob(&f); t0.frob(&f); - y0.mul(&t0); - t0.copy(&r); t0.conj(); - r.copy(&y0); - r.mul(&t0); - - r.mul(&y1); - r.reduce(); - } - r -} - -#[allow(non_snake_case)] -/* GLV method */ -fn glv(ee: &BIG) -> [BIG; 2] { - let mut u: [BIG; 2] = [BIG::new(), BIG::new()]; - let q = BIG::new_ints(&rom::CURVE_ORDER); - if ecp::CURVE_PAIRING_TYPE == ecp::BN { -/* */ - let mut t = BIG::new(); - let mut v: [BIG; 2] = [BIG::new(), BIG::new()]; - - for i in 0..2 { - t.copy(&BIG::new_ints(&rom::CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); - let mut d: DBIG = BIG::mul(&t, &ee); - v[i].copy(&d.ctdiv(&q,t.nbits())); - } - u[0].copy(&ee); - for i in 0..2 { - for j in 0..2 { - t = BIG::new_ints(&rom::CURVE_SB[j][i]); - t = BIG::modmul(&mut v[j], &mut t, &q); - u[i].add(&q); - u[i].sub(&t); - u[i].ctmod(&q,1); - } - } -/* */ - } else { - let x = BIG::new_ints(&rom::CURVE_BNX); - let x2 = BIG::smul(&x, &x); - let bd=q.nbits()-x2.nbits(); - u[0].copy(&ee); - u[0].ctmod(&x2,bd); - u[1].copy(&ee); - u[1].ctdiv(&x2,bd); - u[1].rsub(&q); - } - u -} - -#[allow(non_snake_case)] -/* Galbraith & Scott Method */ -pub fn gs(ee: &BIG) -> [BIG; 4] { - let mut u: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; - let q = BIG::new_ints(&rom::CURVE_ORDER); - if ecp::CURVE_PAIRING_TYPE == ecp::BN { -/* */ - let mut t = BIG::new(); - - let mut v: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()]; - for i in 0..4 { - t.copy(&BIG::new_ints(&rom::CURVE_WB[i])); - let mut d: DBIG = BIG::mul(&t, &ee); - v[i].copy(&d.ctdiv(&q,t.nbits())); - } - u[0].copy(&ee); - for i in 0..4 { - for j in 0..4 { - t = BIG::new_ints(&rom::CURVE_BB[j][i]); - t = BIG::modmul(&mut v[j], &mut t, &q); - u[i].add(&q); - u[i].sub(&t); - u[i].ctmod(&q,1); - } - } -/* */ - } else { - let x = BIG::new_ints(&rom::CURVE_BNX); - let bd=q.nbits()-x.nbits(); // fixed - - let mut w = BIG::new_copy(&ee); - for i in 0..3 { - u[i].copy(&w); - u[i].ctmod(&x,bd); - w.ctdiv(&x,bd); - } - u[3].copy(&w); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - let mut t = BIG::new(); - t.copy(&BIG::modneg(&u[1], &q)); - u[1].copy(&t); - t.copy(&BIG::modneg(&u[3], &q)); - u[3].copy(&t); - } - } - u -} - -#[allow(non_snake_case)] -/* Multiply P by e in group G1 */ -pub fn g1mul(P: &ECP, e: &BIG) -> ECP { - let mut R = ECP::new(); - let q = BIG::new_ints(&rom::CURVE_ORDER); - let mut ee= BIG::new_copy(e); - ee.rmod(&q); - if rom::USE_GLV { - R.copy(P); - let mut Q = ECP::new(); - Q.copy(P); - Q.affine(); - - let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); - let mut u = glv(&ee); - Q.mulx(&mut cru); - - let mut np = u[0].nbits(); - let mut t: BIG = BIG::modneg(&u[0], &q); - let mut nn = t.nbits(); - if nn < np { - u[0].copy(&t); - R.neg(); - } - - np = u[1].nbits(); - t = BIG::modneg(&u[1], &q); - nn = t.nbits(); - if nn < np { - u[1].copy(&t); - Q.neg(); - } - u[0].norm(); - u[1].norm(); - R = R.mul2(&u[0], &Q, &u[1]); - } else { - R = P.clmul(&ee,&q); - } - R -} - -#[allow(non_snake_case)] -/* Multiply P by e in group G2 */ -pub fn g2mul(P: &ECP2, e: &BIG) -> ECP2 { - let mut R = ECP2::new(); - let q = BIG::new_ints(&rom::CURVE_ORDER); - let mut ee= BIG::new_copy(e); - ee.rmod(&q); - if rom::USE_GS_G2 { - let mut Q: [ECP2; 4] = [ECP2::new(), ECP2::new(), ECP2::new(), ECP2::new()]; - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - - let mut u = gs(&ee); - let mut T = ECP2::new(); - - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - f.inverse(None); - f.norm(); - } - - let mut t = BIG::new(); - Q[0].copy(&P); - for i in 1..4 { - T.copy(&Q[i - 1]); - Q[i].copy(&T); - Q[i].frob(&f); - } - for i in 0..4 { - let np = u[i].nbits(); - t.copy(&BIG::modneg(&u[i], &q)); - let nn = t.nbits(); - if nn < np { - u[i].copy(&t); - Q[i].neg(); - } - u[i].norm(); - } - - R.copy(&ECP2::mul4(&Q, &u)); - } else { - R.copy(&P.mul(&ee)); - } - R -} - -/* f=f^e */ -/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ -pub fn gtpow(d: &FP12, e: &BIG) -> FP12 { - let mut r = FP12::new(); - let q = BIG::new_ints(&rom::CURVE_ORDER); - let mut ee= BIG::new_copy(e); - ee.rmod(&q); - if rom::USE_GS_GT { - let mut g: [FP12; 4] = [FP12::new(), FP12::new(), FP12::new(), FP12::new()]; - let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - - let mut t = BIG::new(); - let mut u = gs(&ee); - let mut w = FP12::new(); - - g[0].copy(&d); - for i in 1..4 { - w.copy(&g[i - 1]); - g[i].copy(&w); - g[i].frob(&f); - } - for i in 0..4 { - let np = u[i].nbits(); - t.copy(&BIG::modneg(&u[i], &q)); - let nn = t.nbits(); - if nn < np { - u[i].copy(&t); - g[i].conj(); - } - u[i].norm(); - } - r.copy(&FP12::pow4(&g, &u)); - } else { - r.copy(&d.pow(&ee)); - } - r -} - -/* test G1 group membership */ -#[allow(non_snake_case)] -pub fn g1member(P: &ECP) -> bool { - //let q = BIG::new_ints(&rom::CURVE_ORDER); - if P.is_infinity() { - return false; - } - if ecp::CURVE_PAIRING_TYPE != ecp::BN { - let x = BIG::new_ints(&rom::CURVE_BNX); - let mut cru = FP::new_big(&BIG::new_ints(&rom::CRU)); - let mut W=ECP::new(); W.copy(P); W.mulx(&mut cru); - let mut T=P.mul(&x); - if P.equals(&T) {return false;} // P is of low order - - T=T.mul(&x); T.neg(); - if !W.equals(&T) { - return false; - } - -// Not needed -// W.add(P); T.mulx(&mut cru); W.add(&T); -// if !W.is_infinity() { -// return false; -// } -/* - let W=P.mul(&q); - if !W.is_infinity() { - return false; - } */ - } - true -} - -/* test G2 group membership */ -#[allow(non_snake_case)] -pub fn g2member(P: &ECP2) -> bool { - if P.is_infinity() { - return false; - } - let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - if ecp::SEXTIC_TWIST == ecp::M_TYPE { - f.inverse(None); - f.norm(); - } - let x = BIG::new_ints(&rom::CURVE_BNX); - - let mut W=ECP2::new(); - let mut T=P.mul(&x); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - T.neg(); - } - if ecp::CURVE_PAIRING_TYPE == ecp::BN { -//https://eprint.iacr.org/2022/348.pdf - W.copy(&T); - W.frob(&f); - T.add(P); - T.add(&W); - W.frob(&f); - T.add(&W); - W.frob(&f); - W.dbl(); - } else { -//https://eprint.iacr.org/2021/1130 - W.copy(P); W.frob(&f); - } - - if !W.equals(&T) { - return false; - } - true -} - -/* Check that m is in cyclotomic sub-group */ -/* Check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ -pub fn gtcyclotomic(m: &FP12) -> bool { - if m.isunity() { - return false; - } - let mut r = FP12::new_copy(&m); - r.conj(); - r.mul(&m); - if !r.isunity() { - return false; - } - let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - r.copy(&m); r.frob(&f); r.frob(&f); - let mut w = FP12::new_copy(&r); w.frob(&f); w.frob(&f); - w.mul(&m); - if !w.equals(&r) { - return false; - } - return true; -} - -/* test for full GT group membership */ -pub fn gtmember(m: &FP12) -> bool { - if !gtcyclotomic(m) { - return false; - } - let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB)); - let x = BIG::new_ints(&rom::CURVE_BNX); - - let mut r=FP12::new(); - let mut t=m.pow(&x); - if ecp::SIGN_OF_X == ecp::NEGATIVEX { - t.conj(); - } - if ecp::CURVE_PAIRING_TYPE == ecp::BN { -//https://eprint.iacr.org/2022/348.pdf - r.copy(&t); - r.frob(&f); - t.mul(m); - t.mul(&r); - r.frob(&f); - t.mul(&r); - r.frob(&f); - r.usqr(); - } else { -//https://eprint.iacr.org/2021/1130 - r.copy(m); r.frob(&f); - } - - if !r.equals(&t) { - return false; - } - - true -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs deleted file mode 100644 index b53157c96674..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/bn254/rom.rs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -use crate::arch::Chunk; -use crate::bn254::big::NLEN; - -// BN254 Modulus -// Base Bits= 56 -pub const MODULUS: [Chunk; NLEN] = [0x13, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; -pub const ROI: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; -pub const R2MODP: [Chunk; NLEN] = [ - 0x2F2A96FF5E7E39, - 0x64E8642B96F13C, - 0x9926F7B00C7146, - 0x8321E7B4DACD24, - 0x1D127A2E, -]; -pub const MCONST: Chunk = 0x435E50D79435E5; -pub const SQRTM3:[Chunk;NLEN]=[0x4,0x60C,0x3CF0F,0x4000000126CD89,0x25236482]; -pub const FRA: [Chunk; NLEN] = [ - 0x7DE6C06F2A6DE9, - 0x74924D3F77C2E1, - 0x50A846953F8509, - 0x212E7C8CB6499B, - 0x1B377619, -]; -pub const FRB: [Chunk; NLEN] = [ - 0x82193F90D5922A, - 0x8B6DB2C08850C5, - 0x2F57B96AC8DC17, - 0x1ED1837503EAB2, - 0x9EBEE69, -]; - -pub const CURVE_COF_I: isize = 1; -pub const CURVE_B_I: isize = 2; -pub const CURVE_B: [Chunk; NLEN] = [0x2, 0x0, 0x0, 0x0, 0x0]; -pub const CURVE_ORDER: [Chunk; NLEN] = [ - 0xD, - 0x800000000010A1, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, -]; -pub const CURVE_GX: [Chunk; NLEN] = [0x12, 0x13A7, 0x80000000086121, 0x40000001BA344D, 0x25236482]; -pub const CURVE_GY: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; -pub const CURVE_HTPC:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0]; -pub const CURVE_BNX: [Chunk; NLEN] = [0x80000000000001, 0x40, 0x0, 0x0, 0x0]; -pub const CURVE_COF: [Chunk; NLEN] = [0x1, 0x0, 0x0, 0x0, 0x0]; -pub const CRU: [Chunk; NLEN] = [0x80000000000007, 0x6CD, 0x40000000024909, 0x49B362, 0x0]; -pub const CURVE_PXA: [Chunk; NLEN] = [ - 0xEE4224C803FB2B, - 0x8BBB4898BF0D91, - 0x7E8C61EDB6A464, - 0x519EB62FEB8D8C, - 0x61A10BB, -]; -pub const CURVE_PXB: [Chunk; NLEN] = [ - 0x8C34C1E7D54CF3, - 0x746BAE3784B70D, - 0x8C5982AA5B1F4D, - 0xBA737833310AA7, - 0x516AAF9, -]; -pub const CURVE_PYA: [Chunk; NLEN] = [ - 0xF0E07891CD2B9A, - 0xAE6BDBE09BD19, - 0x96698C822329BD, - 0x6BAF93439A90E0, - 0x21897A0, -]; -pub const CURVE_PYB: [Chunk; NLEN] = [ - 0x2D1AEC6B3ACE9B, - 0x6FFD739C9578A, - 0x56F5F38D37B090, - 0x7C8B15268F6D44, - 0xEBB2B0E, -]; -pub const CURVE_W: [[Chunk; NLEN]; 2] = [ - [0x3, 0x80000000000204, 0x6181, 0x0, 0x0], - [0x1, 0x81, 0x0, 0x0, 0x0], -]; -pub const CURVE_SB: [[[Chunk; NLEN]; 2]; 2] = [ - [ - [0x4, 0x80000000000285, 0x6181, 0x0, 0x0], - [0x1, 0x81, 0x0, 0x0, 0x0], - ], - [ - [0x1, 0x81, 0x0, 0x0, 0x0], - [0xA, 0xE9D, 0x80000000079E1E, 0x40000001BA344D, 0x25236482], - ], -]; -pub const CURVE_WB: [[Chunk; NLEN]; 4] = [ - [0x80000000000000, 0x80000000000040, 0x2080, 0x0, 0x0], - [0x80000000000005, 0x54A, 0x8000000001C707, 0x312241, 0x0], - [ - 0x80000000000003, - 0x800000000002C5, - 0xC000000000E383, - 0x189120, - 0x0, - ], - [0x80000000000001, 0x800000000000C1, 0x2080, 0x0, 0x0], -]; -pub const CURVE_BB: [[[Chunk; NLEN]; 4]; 4] = [ - [ - [ - 0x8000000000000D, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [ - 0x8000000000000C, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [ - 0x8000000000000C, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [0x2, 0x81, 0x0, 0x0, 0x0], - ], - [ - [0x1, 0x81, 0x0, 0x0, 0x0], - [ - 0x8000000000000C, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [ - 0x8000000000000D, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [ - 0x8000000000000C, - 0x80000000001060, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - ], - [ - [0x2, 0x81, 0x0, 0x0, 0x0], - [0x1, 0x81, 0x0, 0x0, 0x0], - [0x1, 0x81, 0x0, 0x0, 0x0], - [0x1, 0x81, 0x0, 0x0, 0x0], - ], - [ - [0x80000000000002, 0x40, 0x0, 0x0, 0x0], - [0x2, 0x102, 0x0, 0x0, 0x0], - [ - 0xA, - 0x80000000001020, - 0x8000000007FF9F, - 0x40000001BA344D, - 0x25236482, - ], - [0x80000000000002, 0x40, 0x0, 0x0, 0x0], - ], -]; - -pub const USE_GLV: bool = true; -pub const USE_GS_G2: bool = true; -pub const USE_GS_GT: bool = true; -pub const GT_STRONG: bool = false; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs deleted file mode 100644 index e9c31b7ff59e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/dilithium.rs +++ /dev/null @@ -1,1199 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Dilithium API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. - -Note that the Matrix A is calculated on-the-fly to keep memory requirement minimal -But this makes all stages much slower -Note that -1. Matrix A can just be generated randomly for Key generation (without using SHA3 which is very slow) -2. A precalculated A can be included in the public key, for use by signature and verification (which blows up public key size) -3. Precalculating A for signature calculation means that the A does not have to re-calculated for each attempt to find a good signature - -Might be simpler to wait for hardware support for SHA3! - - M.Scott 30/09/2021 -*/ - -use crate::sha3; -use crate::sha3::SHA3; - -//q= 8380417 -const LGN: usize = 8; -const DEGREE: usize = 1< i32 { - let m = (t as u32).wrapping_mul(ND); - (((m as u64) * (PRIME as u64) + t) >> 32) as i32 -} - -fn nres(x: i32) -> i32 { - redc((x as u64) * R2MODP) -} - -fn modmul(a: i32, b: i32) -> i32 { - redc((a as u64) * (b as u64)) -} - -fn poly_pos(p: &mut [i32]) { - for j in 0..DEGREE { - p[j] += (p[j]>>31)&PRIME; - } -} -// NTT code - -// Important! -// nres(x); ntt(x) -// nres(y); ntt(y) -// z=x*y -// intt(z); -// redc(z); - -// is equivalent to (note that nres() and redc() cancel out) - -// ntt(x); -// nres(y); ntt(y); -// z=x*y -// intt(z) - -// is equivalent to - -// ntt(x) -// ntt(y) -// z=x*y -// intt(z) -// nres(z) - -// In all cases z ends up in normal (non-Montgomery) form! -// So the conversion to Montgomery form can be "pushed" through the calculation. - -// Here intt(z) <- intt(z);nres(z); -// Combining is more efficient -// note that ntt() and intt() are not mutually inverse - -/* Cooley-Tukey NTT */ -/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ -fn ntt(x: &mut [i32]) { - let mut t = DEGREE / 2; - let q = PRIME; - - /* Make positive */ - poly_pos(x); - - let mut m = 1; - while m < DEGREE { - let mut k = 0; - for i in 0..m { - let s = ROOTS[m + i]; - for j in k..k + t { - let u = x[j]; - let v = modmul(x[j + t], s); - x[j] = u + v; - x[j + t] = u + 2 * q - v; - } - k += 2 * t; - } - t /= 2; - m *= 2; - } -} - -/* Gentleman-Sande INTT */ -/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */ -/* Output fully reduced */ - -const NTTL: usize = 2; // maybe could be 1? - -fn intt(x: &mut [i32]) { - let mut t = 1; - let q = PRIME; - let mut m = DEGREE / 2; - let mut n=LGN; - while m >= 1 { - let lim=NTTL>>n; - n-=1; - let mut k = 0; - for i in 0..m { - let s = IROOTS[m + i]; - for j in k..k + t { - let u:i32; - let v:i32; - if m> 31) & q; - } -} - -fn nres_it(p: &mut [i32]) { - for i in 0..DEGREE { - p[i] = nres(p[i]); - } -} - -fn redc_it(p: &mut [i32]) { - for i in 0..DEGREE { - p[i] = redc(p[i] as u64); - } -} - -fn poly_copy(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] = p3[i]; - } -} - -fn poly_scopy(p1: &mut [i32], p3: &[i8]) { - for i in 0..DEGREE { - p1[i] = p3[i] as i32; - } -} - -fn poly_mcopy(p1: &mut [i32], p3: &[i16]) { - for i in 0..DEGREE { - p1[i] = p3[i] as i32; - } -} - -fn poly_zero(p1: &mut [i32]) { - for i in 0..DEGREE { - p1[i] = 0; - } -} - -fn poly_negate(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] = PRIME-p3[i]; - } -} - -fn poly_mul(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] = modmul(p1[i], p3[i]); - } -} - -fn poly_add(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] += p3[i]; - } -} - -fn poly_sub(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] += PRIME - p3[i]; - } -} - -/* reduces inputs < 2q */ -fn poly_soft_reduce(poly: &mut [i32]) { - for i in 0..DEGREE { - let e = poly[i] - PRIME; - poly[i] = e + ((e >> 31) & PRIME); - } -} - -/* fully reduces modulo q */ -fn poly_hard_reduce(poly: &mut [i32]) { - for i in 0..DEGREE { - let mut e = modmul(poly[i], ONE); - e -= PRIME; - poly[i] = e + ((e >> 31) & PRIME); - } -} - -// Generate a[i][j] from rho -fn expandaij(rho: &[u8],aij: &mut [i32],i:usize,j:usize) { - let mut buff: [u8; 4*DEGREE] = [0; 4*DEGREE]; - let mut sh = SHA3::new(sha3::SHAKE128); - for m in 0..32 { - sh.process(rho[m]) - } - sh.process(j as u8); - sh.process(i as u8); - sh.shake(&mut buff, 4*DEGREE); - let mut m=0; - let mut n=0; - while m=PRIME { - continue; - } - aij[m]=cf; - m+=1; - } -} - -// array t has ab active bits per word -// extract bytes from array of words -// if mx!=0 then -mx<=t[i]<=+mx -fn nextbyte32(ab: usize,mx: usize,t: &[i32],ptr:&mut usize,bts: &mut usize) -> u8 { - let mut left=ab-*bts; - let mut w=t[*ptr]; - let mxm=mx as i32; - if mxm!=0 { - w=mxm-w; - } - let mut r=w>>*bts; - let mut i=0; - while left<8 { - i+=1; - w=t[(*ptr)+i]; - if mxm!=0 { - w=mxm-w; - } - r |= w<=ab { - *bts -= ab; - *ptr+=1; - } - return r as u8; -} - -fn nextbyte16(ab: usize,mx: usize,t: &[i16],ptr:&mut usize,bts: &mut usize) -> u8 { - let mut left=ab-*bts; - let mut w=t[*ptr]; - let mxm=mx as i16; - if mxm!=0 { - w=mxm-w; - } - let mut r=w>>*bts; - let mut i=0; - while left<8 { - i+=1; - w=t[(*ptr)+i]; - if mxm!=0 { - w=mxm-w; - } - r |= w<=ab { - *bts -= ab; - *ptr += 1; - } - return r as u8; -} - -fn nextbyte8(ab: usize,mx: usize,t: &[i8],ptr:&mut usize,bts: &mut usize) -> u8 { - let mut left=ab-*bts; - let mut w=t[*ptr]; - let mxm=mx as i8; - if mxm!=0 { - w=mxm-w; - } - let mut r=w>>*bts; - let mut i=0; - while left<8 { - i+=1; - w=t[(*ptr)+i]; - if mxm!=0 { - w=mxm-w; - } - r |= w<=ab { - *bts -= ab; - *ptr+=1; - } - return r as u8; -} - -fn nextword(ab: usize,mx: usize,t: &[u8],ptr:&mut usize,bts: &mut usize) -> i32 { - let mut r=(t[*ptr]>>*bts) as i32; - let mxm=mx as i32; - let mask=(1<=8 { - *bts -= 8; - *ptr+=1; - } - w=r&mask; - if mxm!=0 { - w=mxm-w; - } - return w; -} - -fn pack_pk(params: &[usize],pk: &mut [u8],rho: &[u8],t1: &[i16]) { - let ck=params[3]; - for i in 0..32 { - pk[i]=rho[i]; - } - let mut ptr=0 as usize; - let mut bts=0 as usize; - let mut n=32; - for _ in 0..(ck*DEGREE*TD)/8 { - pk[n]=nextbyte16(TD,0,t1,&mut ptr,&mut bts); - n += 1; - } -} - -fn unpack_pk(params: &[usize],rho: &mut [u8],t1: &mut [i16],pk: &[u8]) { - let ck=params[3]; - for i in 0..32 { - rho[i]=pk[i]; - } - let mut ptr=0 as usize; - let mut bts=0 as usize; - for i in 0..ck*DEGREE { - t1[i]=nextword(TD,0,&pk[32..],&mut ptr,&mut bts) as i16; - } -} - -fn pack_sk(params: &[usize],sk: &mut [u8],rho: &[u8],bk: &[u8],tr: &[u8],s1: &[i8],s2: &[i8],t0: &[i16]) { - let ck=params[3]; - let el=params[4]; - let eta=params[5]; - let lg2eta1=params[6]; - - for i in 0..32 { - sk[i]=rho[i]; - } - let mut n=32; - for i in 0..32 { - sk[n]=bk[i]; n+=1; - } - for i in 0..32 { - sk[n]=tr[i]; n+=1; - } - let mut ptr=0 as usize; - let mut bts=0 as usize; - - for _ in 0..(el*DEGREE*lg2eta1)/8 { - sk[n]=nextbyte8(lg2eta1,eta,s1,&mut ptr,&mut bts); - n += 1; - } - ptr=0; bts=0; - for _ in 0..(ck*DEGREE*lg2eta1)/8 { - sk[n]=nextbyte8(lg2eta1,eta,s2,&mut ptr,&mut bts); - n += 1; - } - ptr=0; bts=0; - for _ in 0..(ck*DEGREE*D)/8 { - sk[n]=nextbyte16(D,1<<(D-1),t0,&mut ptr,&mut bts); - n += 1; - } -} - -fn unpack_sk(params: &[usize],rho: &mut [u8],bk: &mut [u8],tr: &mut [u8],s1: &mut [i8],s2: &mut [i8],t0: &mut [i16],sk: &[u8]) { - let ck=params[3]; - let el=params[4]; - let eta=params[5]; - let lg2eta1=params[6]; - - for i in 0..32 { - rho[i]=sk[i]; - } - let mut n=32; - for i in 0..32 { - bk[i]=sk[n]; n+=1; - } - for i in 0..32 { - tr[i]=sk[n]; n+=1; - } - let mut ptr=0 as usize; - let mut bts=0 as usize; - - for i in 0..el*DEGREE { - s1[i]=nextword(lg2eta1,eta,&sk[n..],&mut ptr,&mut bts) as i8; - } - n += ptr; - ptr=0; bts=0; - for i in 0..ck*DEGREE { - s2[i]=nextword(lg2eta1,eta,&sk[n..],&mut ptr,&mut bts) as i8; - } - n += ptr; - ptr=0; bts=0; - for i in 0..ck*DEGREE { - t0[i]=nextword(D,1<<(D-1),&sk[n..],&mut ptr,&mut bts) as i16; - } -} - -// pack signature - changes z -fn pack_sig(params: &[usize],sig: &mut [u8],z: &mut [i32],ct: &[u8],h: &[u8]) { - let lg=params[1]; - let gamma1=1<PRIME/2 { - t -= PRIME; - } - t=gamma1-t; - z[row+m]=t; - } - } - for _ in 0..(el*DEGREE*(lg+1))/8 { - sig[n]=nextbyte32(lg+1,0,z,&mut ptr,&mut bts); - n+=1; - } - for i in 0..omega+ck { - sig[n]=h[i]; - n+=1; - } -} - -fn unpack_sig(params: &[usize],z: &mut [i32],ct: &mut [u8],h: &mut [u8],sig: &[u8]) { - let lg=params[1]; - let gamma1=1<>8)&0xff) as u8); - sh.shake(&mut buff, 272); - - let eta=params[5]; - let lg2eta1=params[6]; - - let mut ptr=0 as usize; - let mut bts=0 as usize; - for m in 0..DEGREE { - loop { - s[m]=nextword(lg2eta1,0,&buff,&mut ptr,&mut bts) as i8; - if s[m]<=2*(eta as i8) { - break; - } - } - s[m]=(eta as i8)-s[m]; - } -} - -fn sample_y(params: &[usize],k: usize,rhod: &[u8],y: &mut [i32]) { - let lg=params[1]; - let gamma1=1<>8) as u8); - sh.shake(&mut buff, ((lg+1)*DEGREE)/8); - - let mut ptr=0 as usize; - let mut bts=0 as usize; - - for m in 0..DEGREE { - let mut w=nextword(lg+1,0,&buff,&mut ptr,&mut bts); - w=gamma1-w; - let t=w>>31; - y[row+m]=w+(PRIME&t); - } - } -} - -fn crh1(params: &[usize],h: &mut [u8],rho: &[u8],t1: &[i16]) { - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..32 { - sh.process(rho[j]); - } - let ck=params[3]; - let mut ptr=0 as usize; - let mut bts=0 as usize; - - for _ in 0..(ck*DEGREE*TD)/8 { - sh.process(nextbyte16(TD,0,t1,&mut ptr,&mut bts)); - } - sh.shake(h, 32); -} - -fn crh2(h: &mut [u8],tr: &[u8],mess: &[u8]) { - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..32 { - sh.process(tr[j]); - } - for j in 0..mess.len() { - sh.process(mess[j]); - } - sh.shake(h, 64); -} - -fn crh3(h: &mut [u8],bk: &[u8],mu: &[u8]) { - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..32 { - sh.process(bk[j]); - } - for j in 0..64 { - sh.process(mu[j]); - } - sh.shake(h, 64); -} - -fn h4(params: &[usize],ct: &mut [u8], mu: &[u8],w1: &[i8]) { - let ck=params[3]; - let dv=params[2]; - let mut w1b=4; - if dv==88 { - w1b=6; - } - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..64 { - sh.process(mu[j]); - } - - let mut ptr=0 as usize; - let mut bts=0 as usize; - - for _ in 0..(ck*DEGREE*w1b)/8 { - sh.process(nextbyte8(w1b,0,w1,&mut ptr,&mut bts)); - } - sh.shake(ct, 32); -} - -fn sampleinball(params: &[usize],ct: &[u8],c: &mut [i32]) { - let tau=params[0]; - let mut buff: [u8; 136] = [0; 136]; - let mut signs: [u8; 8] = [0; 8]; - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..32 { - sh.process(ct[j]); - } - sh.shake(&mut buff,136); - for i in 0..8 { - signs[i]=buff[i]; - } - let mut k=8; - let mut b=0; - poly_zero(c); - let mut j:usize; - let mut n=1; - let mut sn=signs[0]; - for i in DEGREE-tau..DEGREE { - loop { - j=buff[k] as usize; k+=1; - if j<=i { - break; - } - } - c[i]=c[j]; - c[j]=1-2*((sn as i32)&1); - sn >>= 1; b += 1; - if b==8 { - sn=signs[n]; n += 1; b=0; - } - } -} - -fn p2r(r0: &mut i32) -> i16 { - let d=(1<>D; - *r0-=r1 << D; - return r1 as i16; -} - -fn power2round(t: &[i32],t0: &mut [i16],t1: &mut [i16]) { - for m in 0..DEGREE { - let mut w=t[m]; - t1[m]=p2r(&mut w); - t0[m]=w as i16; - } -} - -fn decompose_lo(params: &[usize],a: i32) -> i32 { - let dv=params[2]; - let mut a1=(a+127) >> 7; - let gamma2:i32; - if dv==32 { - a1 = (a1*1025+(1<<21))>>22; - a1 &= 15; - gamma2=(PRIME-1)/32; - - } else { // 88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; - gamma2=(PRIME-1)/88; - } - - let mut a0=a-a1*2*gamma2; - a0 -= (((PRIME-1)/2-a0)>>31)&PRIME; - a0 += (a0>>31)&PRIME; - return a0; -} - -fn decompose_hi(params: &[usize],a: i32) -> i8 { - let dv=params[2]; - - let mut a1=(a+127) >> 7; - if dv==32 { - a1 = (a1*1025+(1<<21))>>22; - a1 &= 15; - } else { // 88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; - } - return a1 as i8; -} - -fn lobits(params: &[usize],r0: &mut [i32],r: &[i32]) { - for m in 0..DEGREE { - r0[m]=decompose_lo(params,r[m]); - } -} - -fn hibits(params: &[usize],r1: &mut [i8],r: &[i32]) { - for m in 0..DEGREE { - r1[m]=decompose_hi(params,r[m]); - } -} - -fn makepartialhint(params: &[usize],h: &mut [u8],hptr: usize,z: &[i32],r: &[i32]) -> usize { - let mut ptr=hptr; - let omega=params[7]; - for m in 0..DEGREE { - let a0=decompose_hi(params,r[m]); - let mut rz=r[m]+z[m]; - rz-=PRIME; - rz=rz+((rz>>31)&PRIME); - let a1=decompose_hi(params,rz); - if a0!=a1 { - if ptr>=omega { - return omega+1; - } - h[ptr]=(m&0xff) as u8; ptr += 1; - } - } - return ptr; -} - -fn usepartialhint(params: &[usize],r: &mut [i8],h: &[u8], hptr: usize,i: usize,w: &[i32]) -> usize{ - let mut ptr=hptr; - let dv=params[2] as i32; - let omega=params[7]; - let md=(dv/2) as i8; - - for m in 0..DEGREE { - let mut a1=decompose_hi(params,w[m]); - if m==h[ptr] as usize && ptr= md { - a1 -= md; - } - } else { - a1 -= 1; - if a1<0 { - a1 += md; - } - } - } - r[m]=a1; - } - return ptr; -} - -fn infinity_norm(w: &[i32]) -> i32 { - let mut n=0 as i32; - for m in 0..DEGREE { - let mut az=w[m]; - if az>PRIME/2 { - az=PRIME-az; - } - if az>n { - n=az; - } - } - return n; -} - -fn keypair(params: &[usize],tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { - let mut sh = SHA3::new(sha3::SHAKE256); - let mut buff: [u8; 128] = [0; 128]; - let mut rho: [u8; 32] = [0; 32]; - let mut rhod: [u8; 64] = [0; 64]; - let mut bk: [u8; 32] = [0; 32]; - let mut tr: [u8; 32] = [0; 32]; - let mut aij: [i32; DEGREE] = [0; DEGREE]; - let mut s1: [i8; MAXL*DEGREE] = [0; MAXL*DEGREE]; - let mut s2: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut t0: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut t1: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut w: [i32; DEGREE] = [0; DEGREE]; - let mut r: [i32; DEGREE] = [0; DEGREE]; - - let ck=params[3]; - let el=params[4]; - - for i in 0..32 { - sh.process(tau[i]); - } - sh.shake(&mut buff,128); - for i in 0..32 { - rho[i] = buff[i]; - bk[i] = buff[i+96]; - } - for i in 0..64 { - rhod[i] = buff[i+32]; - } - - for i in 0..el { - let row=DEGREE*i; - sample_sn(params,&rhod,&mut s1[row..],i); - } - - for i in 0..ck { - let row=DEGREE*i; - sample_sn(params,&rhod,&mut s2[row..],el+i); - poly_zero(&mut r); - for j in 0..el { - poly_scopy(&mut w,&s1[j*DEGREE..]); - ntt(&mut w); - expandaij(&rho,&mut aij,i,j); - poly_mul(&mut w,&aij); - poly_add(&mut r,&w); - } - poly_hard_reduce(&mut r); - intt(&mut r); - poly_scopy(&mut w,&s2[row..]); - poly_pos(&mut w); - poly_add(&mut r,&w); - poly_soft_reduce(&mut r); - power2round(&r,&mut t0[row..],&mut t1[row..]); - } - crh1(params,&mut tr,&rho,&t1); - pack_pk(params,pk,&rho,&t1); - pack_sk(params,sk,&rho,&bk,&tr,&s1,&s2,&t0); -} - -fn signature(params: &[usize],sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { - let mut rho: [u8; 32] = [0; 32]; - let mut bk: [u8; 32] = [0; 32]; - let mut ct: [u8; 32] = [0; 32]; - let mut tr: [u8; 32] = [0; 32]; - let mut mu: [u8; 64] = [0; 64]; - let mut rhod: [u8; 64] = [0; 64]; - let mut hint: [u8; 100] = [0; 100]; - - //let mut aij: [i32; DEGREE] = [0; DEGREE]; - let mut s1: [i8; MAXL*DEGREE] = [0; MAXL*DEGREE]; - let mut s2: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut t0: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; - - let mut y: [i32; MAXL*DEGREE] = [0; MAXL*DEGREE]; - let mut ay: [i32; MAXK*DEGREE] = [0; MAXK*DEGREE]; - - let mut w1: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut c: [i32; DEGREE] = [0; DEGREE]; - let mut w: [i32; DEGREE] = [0; DEGREE]; - let mut r: [i32; DEGREE] = [0; DEGREE]; - - let tau=params[0]; - let lg=params[1]; - let gamma1=(1<=gamma1-beta { - badone=true; - break; - } - } - if badone { - continue; - } -// Calculate ay=w-c.s2 and r0=lobits(w-c.s2) - let mut nh=0; - for i in 0..omega+ck { - hint[i]=0; - } - for i in 0..ck { - let row=DEGREE*i; - poly_scopy(&mut w,&s2[row..]); - ntt(&mut w); - poly_mul(&mut w,&c); - intt(&mut w); - poly_sub(&mut ay[row..],&w); - poly_soft_reduce(&mut ay[row..]); - lobits(params,&mut w,&ay[row..]); - if infinity_norm(&w) >= gamma2-beta { - badone=true; - break; - } - poly_mcopy(&mut w,&t0[row..]); - ntt(&mut w); - poly_mul(&mut w,&c); - intt(&mut w); - poly_negate(&mut r,&w); - if infinity_norm(&r) >= gamma2 { - badone=true; - break; - } - poly_sub(&mut ay[row..],&r); - poly_soft_reduce(&mut ay[row..]); - nh=makepartialhint(params,&mut hint,nh,&r,&ay[row..]); - if nh>omega { - badone=true; - break; - } - hint[omega+i]=nh as u8; - } - if badone { - continue; - } - break; - } - pack_sig(params,sig,&mut y,&ct,&hint); - return k; -} - -fn verify(params: &[usize],pk: &[u8],m: &[u8],sig: &[u8]) -> bool { - let mut rho: [u8; 32] = [0; 32]; - let mut ct: [u8; 32] = [0; 32]; - let mut cct: [u8; 32] = [0; 32]; - let mut tr: [u8; 32] = [0; 32]; - let mut mu: [u8; 64] = [0; 64]; - let mut hint: [u8; 100] = [0; 100]; - - let mut z: [i32; MAXL*DEGREE] = [0; MAXL*DEGREE]; - let mut t1: [i16; MAXK*DEGREE] = [0; MAXK*DEGREE]; - let mut w1d: [i8; MAXK*DEGREE] = [0; MAXK*DEGREE]; - - let mut aij: [i32; DEGREE] = [0; DEGREE]; - let mut c: [i32; DEGREE] = [0; DEGREE]; - let mut w: [i32; DEGREE] = [0; DEGREE]; - let mut r: [i32; DEGREE] = [0; DEGREE]; - - let tau=params[0]; - let lg=params[1]; - let gamma1=(1<= gamma1-beta { - return false; - } - ntt(&mut z[row..]); - } - crh1(params,&mut tr,&rho,&t1); - crh2(&mut mu,&tr,m); - - sampleinball(params,&ct,&mut c); - ntt(&mut c); - -// Calculate az - let mut hints=0; - for i in 0..ck { - let row=DEGREE*i; - poly_zero(&mut r); - for j in 0..el { - poly_copy(&mut w,&z[j*DEGREE..]); - expandaij(&rho,&mut aij,i,j); - poly_mul(&mut w,&aij); - poly_add(&mut r,&w); - } - poly_hard_reduce(&mut r); - -// Calculate Az-ct1.2^d - for m in 0..DEGREE { - w[m]=((t1[row+m]) as i32) << D; - } - ntt(&mut w); - poly_mul(&mut w,&c); - poly_sub(&mut r,&w); - intt(&mut r); - - hints=usepartialhint(params,&mut w1d[row..],&mut hint,hints,i,&r); - if hints>omega { - return false; - } - } - - h4(params,&mut cct,&mu,&w1d); - - for i in 0..32 { - if ct[i]!=cct[i] { - return false; - } - } - return true; -} - -// Dilithium API - -pub fn keypair_2(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { - keypair(&PARAMS_2,tau,sk,pk); -} - -pub fn signature_2(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { - return signature(&PARAMS_2,sk,m,sig); -} - -pub fn verify_2(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { - return verify(&PARAMS_2,pk,m,sig); -} - - -pub fn keypair_3(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { - keypair(&PARAMS_3,tau,sk,pk); -} - -pub fn signature_3(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { - return signature(&PARAMS_3,sk,m,sig); -} - -pub fn verify_3(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { - return verify(&PARAMS_3,pk,m,sig); -} - - -pub fn keypair_5(tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { - keypair(&PARAMS_5,tau,sk,pk); -} - -pub fn signature_5(sk: &[u8],m: &[u8],sig: &mut[u8]) -> usize { - return signature(&PARAMS_5,sk,m,sig); -} - -pub fn verify_5(pk: &[u8],m: &[u8],sig: &[u8]) -> bool { - return verify(&PARAMS_5,pk,m,sig); -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs deleted file mode 100644 index 310b02b972cc..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/gcm.rs +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const GCM_NB: usize = 4; -const GCM_ACCEPTING_HEADER: usize = 0; -const GCM_ACCEPTING_CIPHER: usize = 1; -const GCM_NOT_ACCEPTING_MORE: usize = 2; -const GCM_FINISHED: usize = 3; -//const GCM_ENCRYPTING: usize = 0; -//const GCM_DECRYPTING: usize = 1; - -use crate::aes; -use crate::aes::AES; - -pub struct GCM { - table: [[u32; 4]; 128], - statex: [u8; 16], - y_0: [u8; 16], - // counter: usize, - lena: [u32; 2], - lenc: [u32; 2], - status: usize, - a: AES, -} - -impl GCM { - fn pack(b: [u8; 4]) -> u32 { - /* pack bytes into a 32-bit Word */ - ((b[0] as u32) << 24) - | ((b[1] as u32) << 16) - | ((b[2] as u32) << 8) - | (b[3] as u32) - } - - fn unpack(a: u32) -> [u8; 4] { - /* unpack bytes from a word */ - [ - ((a >> 24) & 0xff) as u8, - ((a >> 16) & 0xff) as u8, - ((a >> 8) & 0xff) as u8, - (a & 0xff) as u8, - ] - } - - fn precompute(&mut self, h: &[u8]) { - let mut b: [u8; 4] = [0; 4]; - let mut j = 0; - for i in 0..GCM_NB { - b[0] = h[j]; - b[1] = h[j + 1]; - b[2] = h[j + 2]; - b[3] = h[j + 3]; - self.table[0][i] = GCM::pack(b); - j += 4; - } - for i in 1..128 { - let mut c: u32 = 0; - for j in 0..GCM_NB { - self.table[i][j] = c | (self.table[i - 1][j]) >> 1; - c = self.table[i - 1][j] << 31; - } - if c != 0 { - self.table[i][0] ^= 0xE1000000 - } /* irreducible polynomial */ - } - } - - fn gf2mul(&mut self) { - /* gf2m mul - Z=H*X mod 2^128 */ - let mut p: [u32; 4] = [0; 4]; - - for i in 0..4 { - p[i] = 0 - } - let mut j: usize = 8; - let mut m = 0; - for i in 0..128 { - j -= 1; - let mut c = ((self.statex[m] >> j) & 1) as u32; - c = (!c).wrapping_add(1); // + 1; - for k in 0..GCM_NB { - p[k] ^= self.table[i][k] & c - } - if j == 0 { - j = 8; - m += 1; - if m == 16 { - break; - } - } - } - j = 0; - for i in 0..GCM_NB { - let b = GCM::unpack(p[i]); - self.statex[j] = b[0]; - self.statex[j + 1] = b[1]; - self.statex[j + 2] = b[2]; - self.statex[j + 3] = b[3]; - j += 4; - } - } - - fn wrap(&mut self) { - /* Finish off GHASH */ - let mut f: [u32; 4] = [0; 4]; - let mut el: [u8; 16] = [0; 16]; - - /* convert lengths from bytes to bits */ - f[0] = (self.lena[0] << 3) | (self.lena[1] & 0xE0000000) >> 29; - f[1] = self.lena[1] << 3; - f[2] = (self.lenc[0] << 3) | (self.lenc[1] & 0xE0000000) >> 29; - f[3] = self.lenc[1] << 3; - let mut j = 0; - for i in 0..GCM_NB { - let b = GCM::unpack(f[i]); - el[j] = b[0]; - el[j + 1] = b[1]; - el[j + 2] = b[2]; - el[j + 3] = b[3]; - j += 4; - } - for i in 0..16 { - self.statex[i] ^= el[i] - } - self.gf2mul(); - } - - fn ghash(&mut self, plain: &[u8], len: usize) -> bool { - if self.status == GCM_ACCEPTING_HEADER { - self.status = GCM_ACCEPTING_CIPHER - } - if self.status != GCM_ACCEPTING_CIPHER { - return false; - } - - let mut j = 0; - while j < len { - for i in 0..16 { - if j >= len { - break; - } - self.statex[i] ^= plain[j]; - j += 1; - self.lenc[1] += 1; - if self.lenc[1] == 0 { - self.lenc[0] += 1 - } - } - self.gf2mul(); - } - if len % 16 != 0 { - self.status = GCM_NOT_ACCEPTING_MORE - } - true - } - - /* Initialize GCM mode */ - pub fn init(&mut self, nk: usize, key: &[u8], niv: usize, iv: &[u8]) { - /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ - let mut h: [u8; 16] = [0; 16]; - - for i in 0..16 { - h[i] = 0; - self.statex[i] = 0 - } - - self.a = AES::new(); - - self.a.init(aes::ECB, nk, key, None); - self.a.ecb_encrypt(&mut h); /* E(K,0) */ - self.precompute(&h); - - self.lena[0] = 0; - self.lenc[0] = 0; - self.lena[1] = 0; - self.lenc[1] = 0; - if niv == 12 { - for i in 0..12 { - self.a.f[i] = iv[i] - } - let b = GCM::unpack(1); - self.a.f[12] = b[0]; - self.a.f[13] = b[1]; - self.a.f[14] = b[2]; - self.a.f[15] = b[3]; /* initialise IV */ - for i in 0..16 { - self.y_0[i] = self.a.f[i] - } - } else { - self.status = GCM_ACCEPTING_CIPHER; - self.ghash(iv, niv); /* GHASH(H,0,IV) */ - self.wrap(); - for i in 0..16 { - self.a.f[i] = self.statex[i]; - self.y_0[i] = self.a.f[i]; - self.statex[i] = 0 - } - self.lena[0] = 0; - self.lenc[0] = 0; - self.lena[1] = 0; - self.lenc[1] = 0; - } - self.status = GCM_ACCEPTING_HEADER; - } - - pub fn new() -> GCM { - GCM { - table: [[0; 4]; 128], - statex: [0; 16], - y_0: [0; 16], - //counter:0, - lena: [0; 2], - lenc: [0; 2], - status: 0, - a: AES::new(), - } - } - - /* Add Header data - included but not encrypted */ - pub fn add_header(&mut self, header: &[u8], len: usize) -> bool { - /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ - if self.status != GCM_ACCEPTING_HEADER { - return false; - } - let mut j = 0; - while j < len { - for i in 0..16 { - if j >= len { - break; - } - self.statex[i] ^= header[j]; - j += 1; - self.lena[1] += 1; - if self.lena[1] == 0 { - self.lena[0] += 1 - } - } - self.gf2mul(); - } - if len % 16 != 0 { - self.status = GCM_ACCEPTING_CIPHER - } - true - } - - /* Add Plaintext - included and encrypted */ - /* if plain is None - encrypts cipher in place */ - pub fn add_plain(&mut self, cipher: &mut [u8], plain: Option<&[u8]>, len: usize) -> bool { - let mut cb: [u8; 16] = [0; 16]; - let mut b: [u8; 4] = [0; 4]; - - let mut counter: u32; - if self.status == GCM_ACCEPTING_HEADER { - self.status = GCM_ACCEPTING_CIPHER - } - if self.status != GCM_ACCEPTING_CIPHER { - return false; - } - - let mut j = 0; - while j < len { - b[0] = self.a.f[12]; - b[1] = self.a.f[13]; - b[2] = self.a.f[14]; - b[3] = self.a.f[15]; - counter = GCM::pack(b); - counter += 1; - b = GCM::unpack(counter); - self.a.f[12] = b[0]; - self.a.f[13] = b[1]; - self.a.f[14] = b[2]; - self.a.f[15] = b[3]; /* increment counter */ - for i in 0..16 { - cb[i] = self.a.f[i] - } - self.a.ecb_encrypt(&mut cb); /* encrypt it */ - - for i in 0..16 { - if j >= len { - break; - } - - if let Some(sp) = plain { - cipher[j] = sp[j] ^ cb[i]; - } else { - cipher[j] ^=cb[i]; - } - - self.statex[i] ^= cipher[j]; - j += 1; - self.lenc[1] += 1; - if self.lenc[1] == 0 { - self.lenc[0] += 1 - } - } - self.gf2mul() - } - if len % 16 != 0 { - self.status = GCM_NOT_ACCEPTING_MORE - } - true - } - - /* Add Ciphertext - decrypts to plaintext */ - /* if cipher is None - decrypts plain in place */ - pub fn add_cipher(&mut self, plain: &mut [u8], cipher: Option<&[u8]>, len: usize) -> bool { - let mut cb: [u8; 16] = [0; 16]; - let mut b: [u8; 4] = [0; 4]; - - let mut counter: u32; - - if self.status == GCM_ACCEPTING_HEADER { - self.status = GCM_ACCEPTING_CIPHER - } - if self.status != GCM_ACCEPTING_CIPHER { - return false; - } - - let mut j = 0; - while j < len { - b[0] = self.a.f[12]; - b[1] = self.a.f[13]; - b[2] = self.a.f[14]; - b[3] = self.a.f[15]; - counter = GCM::pack(b); - counter += 1; - b = GCM::unpack(counter); - self.a.f[12] = b[0]; - self.a.f[13] = b[1]; - self.a.f[14] = b[2]; - self.a.f[15] = b[3]; /* increment counter */ - for i in 0..16 { - cb[i] = self.a.f[i] - } - self.a.ecb_encrypt(&mut cb); /* encrypt it */ - for i in 0..16 { - if j >= len { - break; - } - let oc:u8; - if let Some(sc) = cipher { - oc = sc[j]; - } else { - oc = plain[j]; - } - - plain[j] = oc ^ cb[i]; - self.statex[i] ^= oc; - j += 1; - self.lenc[1] += 1; - if self.lenc[1] == 0 { - self.lenc[0] += 1 - } - } - self.gf2mul() - } - if len % 16 != 0 { - self.status = GCM_NOT_ACCEPTING_MORE - } - true - } - - /* Finish and extract Tag */ - pub fn finish(&mut self,tag: &mut [u8], extract: bool) { - /* Finish off GHASH and extract tag (MAC) */ - self.wrap(); - /* extract tag */ - if extract { - self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ - for i in 0..16 { - self.y_0[i] ^= self.statex[i] - } - for i in 0..16 { - tag[i] = self.y_0[i]; - self.y_0[i] = 0; - self.statex[i] = 0 - } - } - self.status = GCM_FINISHED; - self.a.end(); - } - - pub fn hex2bytes(hex: &[u8], bin: &mut [u8]) { - let len = hex.len(); - - for i in 0..len / 2 { - let mut v: u8; - let mut c = hex[2 * i]; - if c >= b'0' && c <= b'9' { - v = c - b'0'; - } else if c >= b'A' && c <= b'F' { - v = c - b'A' + 10; - } else if c >= b'a' && c <= b'f' { - v = c - b'a' + 10; - } else { - v = 0; - } - v <<= 4; - c = hex[2 * i + 1]; - if c >= b'0' && c <= b'9' { - v += c - b'0'; - } else if c >= b'A' && c <= b'F' { - v += c - b'A' + 10; - } else if c >= b'a' && c <= b'f' { - v += c - b'a' + 10; - } else { - v = 0; - } - bin[i] = v; - } - } -} - -pub fn encrypt(c: &mut [u8],t: &mut [u8],k: &[u8],iv: &[u8],h: &[u8],p: &[u8]) { - let mut g=GCM::new(); - g.init(k.len(),k,iv.len(),iv); - g.add_header(h,h.len()); - g.add_plain(c,Some(p),p.len()); - g.finish(t,true) -} - -pub fn decrypt(p: &mut [u8],t: &mut [u8],k: &[u8],iv: &[u8],h: &[u8],c: &[u8]) { - let mut g=GCM::new(); - g.init(k.len(),k,iv.len(),iv); - g.add_header(h,h.len()); - g.add_cipher(p,Some(c),c.len()); - g.finish(t,true); -} - -/* -fn main() -{ - let kt=b"feffe9928665731c6d6a8f9467308308"; - let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; - let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; - let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; -// Tag should be 619cc5aefffe0bfa462af43c1699d050 - - let mut gcm=GCM::new(); - - let len=mt.len()/2; - let lenh=ht.len()/2; - let lenk=kt.len()/2; - let leniv=nt.len()/2; - - //let mut t:[u8;16]=[0;16]; // Tag - let mut k:[u8;16]=[0;16]; // AES Key - let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted - let mut n:[u8;100]=[0;100]; // IV - Initialisation vector - let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated - let mut c:[u8;100]=[0;100]; // Ciphertext - let mut p:[u8;100]=[0;100]; // Recovered Plaintext - - GCM::hex2bytes(mt,&mut m); - GCM::hex2bytes(ht,&mut h); - GCM::hex2bytes(kt,&mut k); - GCM::hex2bytes(nt,&mut n); - - println!("Plaintext="); - for i in 0..len {print!("{:02x}",m[i])} - println!(""); - - gcm.init(lenk,&k,leniv,&n); - - gcm.add_header(&h,lenh); - gcm.add_plain(&mut c,&m,len); - let mut t=gcm.finish(true); - - println!("Ciphertext="); - for i in 0..len {print!("{:02x}",c[i])} - println!(""); - - println!("Tag="); - for i in 0..16 {print!("{:02x}",t[i])} - println!(""); - - gcm.init(lenk,&k,leniv,&n); - - gcm.add_header(&h,lenh); - gcm.add_cipher(&mut p,&c,len); - t=gcm.finish(true); - - println!("Plaintext="); - for i in 0..len {print!("{:02x}",p[i])} - println!(""); - - println!("Tag="); - for i in 0..16 {print!("{:02x}",t[i])} - println!(""); - -} -*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs deleted file mode 100644 index 8a7b7668a8db..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash256.rs +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const HASH256_H0: u32 = 0x6A09E667; -const HASH256_H1: u32 = 0xBB67AE85; -const HASH256_H2: u32 = 0x3C6EF372; -const HASH256_H3: u32 = 0xA54FF53A; -const HASH256_H4: u32 = 0x510E527F; -const HASH256_H5: u32 = 0x9B05688C; -const HASH256_H6: u32 = 0x1F83D9AB; -const HASH256_H7: u32 = 0x5BE0CD19; - -const HASH256_K: [u32; 64] = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -]; - -pub struct HASH256 { - length: [u32; 2], - h: [u32; 8], - w: [u32; 64], -} - -impl HASH256 { - fn s(n: u32, x: u32) -> u32 { - ((x) >> n) | ((x) << (32 - n)) - } - fn r(n: u32, x: u32) -> u32 { - (x) >> n - } - - fn ch(x: u32, y: u32, z: u32) -> u32 { - (x & y) ^ (!(x) & z) - } - - fn maj(x: u32, y: u32, z: u32) -> u32 { - (x & y) ^ (x & z) ^ (y & z) - } - fn sig0(x: u32) -> u32 { - HASH256::s(2, x) ^ HASH256::s(13, x) ^ HASH256::s(22, x) - } - - fn sig1(x: u32) -> u32 { - HASH256::s(6, x) ^ HASH256::s(11, x) ^ HASH256::s(25, x) - } - - fn theta0(x: u32) -> u32 { - HASH256::s(7, x) ^ HASH256::s(18, x) ^ HASH256::r(3, x) - } - - fn theta1(x: u32) -> u32 { - HASH256::s(17, x) ^ HASH256::s(19, x) ^ HASH256::r(10, x) - } - - pub fn as_bytes(&self,array: &mut [u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=self.length[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..8 { - let mut t=self.h[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..64 { - let mut t=self.w[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - } - - pub fn from_bytes(&mut self,array: &[u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=array[ptr+3] as u32; - t=256*t+(array[ptr+2] as u32); - t=256*t+(array[ptr+1] as u32); - t=256*t+(array[ptr] as u32); - self.length[i]=t; ptr+=4; - } - for i in 0..8 { - let mut t=array[ptr+3] as u32; - t=256*t+(array[ptr+2] as u32); - t=256*t+(array[ptr+1] as u32); - t=256*t+(array[ptr] as u32); - self.h[i]=t; ptr+=4; - } - for i in 0..64 { - let mut t=array[ptr+3] as u32; - t=256*t+(array[ptr+2] as u32); - t=256*t+(array[ptr+1] as u32); - t=256*t+(array[ptr] as u32); - self.w[i]=t; ptr+=4; - } - } - - fn transform(&mut self) { - /* basic transformation step */ - for j in 16..64 { - self.w[j] = HASH256::theta1(self.w[j - 2]) - .wrapping_add(self.w[j - 7]) - .wrapping_add(HASH256::theta0(self.w[j - 15])) - .wrapping_add(self.w[j - 16]); - } - let mut a = self.h[0]; - let mut b = self.h[1]; - let mut c = self.h[2]; - let mut d = self.h[3]; - let mut e = self.h[4]; - let mut f = self.h[5]; - let mut g = self.h[6]; - let mut hh = self.h[7]; - for j in 0..64 { - /* 64 times - mush it up */ - let t1 = hh - .wrapping_add(HASH256::sig1(e)) - .wrapping_add(HASH256::ch(e, f, g)) - .wrapping_add(HASH256_K[j]) - .wrapping_add(self.w[j]); - let t2 = HASH256::sig0(a).wrapping_add(HASH256::maj(a, b, c)); - hh = g; - g = f; - f = e; - e = d.wrapping_add(t1); - d = c; - c = b; - b = a; - a = t1.wrapping_add(t2); - } - self.h[0] = self.h[0].wrapping_add(a); - self.h[1] = self.h[1].wrapping_add(b); - self.h[2] = self.h[2].wrapping_add(c); - self.h[3] = self.h[3].wrapping_add(d); - self.h[4] = self.h[4].wrapping_add(e); - self.h[5] = self.h[5].wrapping_add(f); - self.h[6] = self.h[6].wrapping_add(g); - self.h[7] = self.h[7].wrapping_add(hh); - } - - /* Initialise Hash function */ - pub fn init(&mut self) { - /* initialise */ - for i in 0..64 { - self.w[i] = 0 - } - self.length[0] = 0; - self.length[1] = 0; - self.h[0] = HASH256_H0; - self.h[1] = HASH256_H1; - self.h[2] = HASH256_H2; - self.h[3] = HASH256_H3; - self.h[4] = HASH256_H4; - self.h[5] = HASH256_H5; - self.h[6] = HASH256_H6; - self.h[7] = HASH256_H7; - } - - pub fn new() -> HASH256 { - let mut nh = HASH256 { - length: [0; 2], - h: [0; 8], - w: [0; 64], - }; - nh.init(); - nh - } - - pub fn new_copy(hh: &HASH256) -> HASH256 { - let mut nh = HASH256 { - length: [0; 2], - h: [0; 8], - w: [0; 64], - }; - nh.length[0]=hh.length[0]; - nh.length[1]=hh.length[1]; - for i in 0..64 { - nh.w[i] = hh.w[i]; - } - for i in 0..8 { - nh.h[i] = hh.h[i]; - } - nh - } - - /* process a single byte */ - pub fn process(&mut self, byt: u8) { - /* process the next message byte */ - let cnt = ((self.length[0] / 32) % 16) as usize; - self.w[cnt] <<= 8; - self.w[cnt] |= byt as u32; - self.length[0] += 8; - if self.length[0] == 0 { - self.length[1] += 1; - self.length[0] = 0 - } - if (self.length[0] % 512) == 0 { - self.transform() - } - } - - /* process an array of bytes */ - - pub fn process_array(&mut self, b: &[u8]) { - for i in 0..b.len() { - self.process(b[i]) - } - } - - /* process a 32-bit integer */ - pub fn process_num(&mut self, n: i32) { - self.process(((n >> 24) & 0xff) as u8); - self.process(((n >> 16) & 0xff) as u8); - self.process(((n >> 8) & 0xff) as u8); - self.process((n & 0xff) as u8); - } - - /* Generate 32-byte Hash */ - pub fn hash(&mut self) -> [u8; 32] { - /* pad message and finish - supply digest */ - let mut digest: [u8; 32] = [0; 32]; - let len0 = self.length[0]; - let len1 = self.length[1]; - self.process(0x80); - while (self.length[0] % 512) != 448 { - self.process(0) - } - self.w[14] = len1; - self.w[15] = len0; - self.transform(); - for i in 0..32 { - /* convert to bytes */ - digest[i] = ((self.h[i / 4] >> (8 * (3 - i % 4))) & 0xff) as u8; - } - self.init(); - digest - } - - pub fn continuing_hash(&self) -> [u8; 32] { - let mut sh=HASH256::new_copy(self); - sh.hash() - } -} - -//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 -/* -fn main() { - let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); - let test = s.into_bytes(); - let mut sh=HASH256::new(); - - for i in 0..test.len(){ - sh.process(test[i]); - } - - let digest=sh.hash(); - for i in 0..32 {print!("{:02x}",digest[i])} -} -*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs deleted file mode 100644 index 3b41197cc160..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash384.rs +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const HASH384_H0: u64 = 0xcbbb9d5dc1059ed8; -const HASH384_H1: u64 = 0x629a292a367cd507; -const HASH384_H2: u64 = 0x9159015a3070dd17; -const HASH384_H3: u64 = 0x152fecd8f70e5939; -const HASH384_H4: u64 = 0x67332667ffc00b31; -const HASH384_H5: u64 = 0x8eb44a8768581511; -const HASH384_H6: u64 = 0xdb0c2e0d64f98fa7; -const HASH384_H7: u64 = 0x47b5481dbefa4fa4; - -const HASH384_K: [u64; 80] = [ - 0x428a2f98d728ae22, - 0x7137449123ef65cd, - 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, - 0x59f111f1b605d019, - 0x923f82a4af194f9b, - 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, - 0x12835b0145706fbe, - 0x243185be4ee4b28c, - 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, - 0x80deb1fe3b1696b1, - 0x9bdc06a725c71235, - 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, - 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, - 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, - 0x5cb0a9dcbd41fbd4, - 0x76f988da831153b5, - 0x983e5152ee66dfab, - 0xa831c66d2db43210, - 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, - 0xd5a79147930aa725, - 0x06ca6351e003826f, - 0x142929670a0e6e70, - 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, - 0x4d2c6dfc5ac42aed, - 0x53380d139d95b3df, - 0x650a73548baf63de, - 0x766a0abb3c77b2a8, - 0x81c2c92e47edaee6, - 0x92722c851482353b, - 0xa2bfe8a14cf10364, - 0xa81a664bbc423001, - 0xc24b8b70d0f89791, - 0xc76c51a30654be30, - 0xd192e819d6ef5218, - 0xd69906245565a910, - 0xf40e35855771202a, - 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, - 0x1e376c085141ab53, - 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, - 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, - 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, - 0x78a5636f43172f60, - 0x84c87814a1f0ab72, - 0x8cc702081a6439ec, - 0x90befffa23631e28, - 0xa4506cebde82bde9, - 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, - 0xca273eceea26619c, - 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, - 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, - 0x113f9804bef90dae, - 0x1b710b35131c471b, - 0x28db77f523047d84, - 0x32caab7b40c72493, - 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, - 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, - 0x6c44198c4a475817, -]; - -pub struct HASH384 { - length: [u64; 2], - h: [u64; 8], - w: [u64; 80], -} - -impl HASH384 { - fn s(n: u64, x: u64) -> u64 { - ((x) >> n) | ((x) << (64 - n)) - } - fn r(n: u64, x: u64) -> u64 { - (x) >> n - } - - fn ch(x: u64, y: u64, z: u64) -> u64 { - (x & y) ^ (!(x) & z) - } - - fn maj(x: u64, y: u64, z: u64) -> u64 { - (x & y) ^ (x & z) ^ (y & z) - } - - fn sig0(x: u64) -> u64 { - HASH384::s(28, x) ^ HASH384::s(34, x) ^ HASH384::s(39, x) - } - - fn sig1(x: u64) -> u64 { - HASH384::s(14, x) ^ HASH384::s(18, x) ^ HASH384::s(41, x) - } - - fn theta0(x: u64) -> u64 { - HASH384::s(1, x) ^ HASH384::s(8, x) ^ HASH384::r(7, x) - } - - fn theta1(x: u64) -> u64 { - HASH384::s(19, x) ^ HASH384::s(61, x) ^ HASH384::r(6, x) - } - - pub fn as_bytes(&self,array: &mut [u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=self.length[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..8 { - let mut t=self.h[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..80 { - let mut t=self.w[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - } - - pub fn from_bytes(&mut self,array: &[u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.length[i]=t; ptr+=8; - } - for i in 0..8 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.h[i]=t; ptr+=8; - } - for i in 0..80 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.w[i]=t; ptr+=8; - } - } - - fn transform(&mut self) { - /* basic transformation step */ - for j in 16..80 { - self.w[j] = HASH384::theta1(self.w[j - 2]) - .wrapping_add(self.w[j - 7]) - .wrapping_add(HASH384::theta0(self.w[j - 15])) - .wrapping_add(self.w[j - 16]); - } - let mut a = self.h[0]; - let mut b = self.h[1]; - let mut c = self.h[2]; - let mut d = self.h[3]; - let mut e = self.h[4]; - let mut f = self.h[5]; - let mut g = self.h[6]; - let mut hh = self.h[7]; - for j in 0..80 { - /* 64 times - mush it up */ - let t1 = hh - .wrapping_add(HASH384::sig1(e)) - .wrapping_add(HASH384::ch(e, f, g)) - .wrapping_add(HASH384_K[j]) - .wrapping_add(self.w[j]); - let t2 = HASH384::sig0(a).wrapping_add(HASH384::maj(a, b, c)); - hh = g; - g = f; - f = e; - e = d.wrapping_add(t1); - d = c; - c = b; - b = a; - a = t1.wrapping_add(t2); - } - self.h[0] = self.h[0].wrapping_add(a); - self.h[1] = self.h[1].wrapping_add(b); - self.h[2] = self.h[2].wrapping_add(c); - self.h[3] = self.h[3].wrapping_add(d); - self.h[4] = self.h[4].wrapping_add(e); - self.h[5] = self.h[5].wrapping_add(f); - self.h[6] = self.h[6].wrapping_add(g); - self.h[7] = self.h[7].wrapping_add(hh); - } - - /* Initialise Hash function */ - pub fn init(&mut self) { - /* initialise */ - for i in 0..64 { - self.w[i] = 0 - } - self.length[0] = 0; - self.length[1] = 0; - self.h[0] = HASH384_H0; - self.h[1] = HASH384_H1; - self.h[2] = HASH384_H2; - self.h[3] = HASH384_H3; - self.h[4] = HASH384_H4; - self.h[5] = HASH384_H5; - self.h[6] = HASH384_H6; - self.h[7] = HASH384_H7; - } - - pub fn new() -> HASH384 { - let mut nh = HASH384 { - length: [0; 2], - h: [0; 8], - w: [0; 80], - }; - nh.init(); - nh - } - - pub fn new_copy(hh: &HASH384) -> HASH384 { - let mut nh = HASH384 { - length: [0; 2], - h: [0; 8], - w: [0; 80], - }; - nh.length[0]=hh.length[0]; - nh.length[1]=hh.length[1]; - for i in 0..80 { - nh.w[i] = hh.w[i]; - } - for i in 0..8 { - nh.h[i] = hh.h[i]; - } - nh - } - - /* process a single byte */ - pub fn process(&mut self, byt: u8) { - /* process the next message byte */ - let cnt = ((self.length[0] / 64) % 16) as usize; - self.w[cnt] <<= 8; - self.w[cnt] |= byt as u64; - self.length[0] += 8; - if self.length[0] == 0 { - self.length[1] += 1; - self.length[0] = 0 - } - if (self.length[0] % 1024) == 0 { - self.transform() - } - } - - /* process an array of bytes */ - - pub fn process_array(&mut self, b: &[u8]) { - for i in 0..b.len() { - self.process(b[i]) - } - } - - /* process a 32-bit integer */ - pub fn process_num(&mut self, n: i32) { - self.process(((n >> 24) & 0xff) as u8); - self.process(((n >> 16) & 0xff) as u8); - self.process(((n >> 8) & 0xff) as u8); - self.process((n & 0xff) as u8); - } - - /* Generate 32-byte Hash */ - pub fn hash(&mut self) -> [u8; 48] { - /* pad message and finish - supply digest */ - let mut digest: [u8; 48] = [0; 48]; - let len0 = self.length[0]; - let len1 = self.length[1]; - self.process(0x80); - while (self.length[0] % 1024) != 896 { - self.process(0) - } - self.w[14] = len1; - self.w[15] = len0; - self.transform(); - for i in 0..48 { - /* convert to bytes */ - digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; - } - self.init(); - digest - } - pub fn continuing_hash(&self) -> [u8; 48] { - let mut sh=HASH384::new_copy(self); - sh.hash() - } -} - -//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039 -/* -fn main() { - let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); - let test = s.into_bytes(); - let mut sh=HASH384::new(); - - for i in 0..test.len(){ - sh.process(test[i]); - } - - let digest=sh.hash(); - for i in 0..48 {print!("{:02x}",digest[i])} -} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs deleted file mode 100644 index 94f8cca6468f..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hash512.rs +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const HASH512_H0: u64 = 0x6a09e667f3bcc908; -const HASH512_H1: u64 = 0xbb67ae8584caa73b; -const HASH512_H2: u64 = 0x3c6ef372fe94f82b; -const HASH512_H3: u64 = 0xa54ff53a5f1d36f1; -const HASH512_H4: u64 = 0x510e527fade682d1; -const HASH512_H5: u64 = 0x9b05688c2b3e6c1f; -const HASH512_H6: u64 = 0x1f83d9abfb41bd6b; -const HASH512_H7: u64 = 0x5be0cd19137e2179; - -const HASH512_K: [u64; 80] = [ - 0x428a2f98d728ae22, - 0x7137449123ef65cd, - 0xb5c0fbcfec4d3b2f, - 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, - 0x59f111f1b605d019, - 0x923f82a4af194f9b, - 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, - 0x12835b0145706fbe, - 0x243185be4ee4b28c, - 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, - 0x80deb1fe3b1696b1, - 0x9bdc06a725c71235, - 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, - 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, - 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, - 0x4a7484aa6ea6e483, - 0x5cb0a9dcbd41fbd4, - 0x76f988da831153b5, - 0x983e5152ee66dfab, - 0xa831c66d2db43210, - 0xb00327c898fb213f, - 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, - 0xd5a79147930aa725, - 0x06ca6351e003826f, - 0x142929670a0e6e70, - 0x27b70a8546d22ffc, - 0x2e1b21385c26c926, - 0x4d2c6dfc5ac42aed, - 0x53380d139d95b3df, - 0x650a73548baf63de, - 0x766a0abb3c77b2a8, - 0x81c2c92e47edaee6, - 0x92722c851482353b, - 0xa2bfe8a14cf10364, - 0xa81a664bbc423001, - 0xc24b8b70d0f89791, - 0xc76c51a30654be30, - 0xd192e819d6ef5218, - 0xd69906245565a910, - 0xf40e35855771202a, - 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, - 0x1e376c085141ab53, - 0x2748774cdf8eeb99, - 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, - 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, - 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, - 0x78a5636f43172f60, - 0x84c87814a1f0ab72, - 0x8cc702081a6439ec, - 0x90befffa23631e28, - 0xa4506cebde82bde9, - 0xbef9a3f7b2c67915, - 0xc67178f2e372532b, - 0xca273eceea26619c, - 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, - 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, - 0x0a637dc5a2c898a6, - 0x113f9804bef90dae, - 0x1b710b35131c471b, - 0x28db77f523047d84, - 0x32caab7b40c72493, - 0x3c9ebe0a15c9bebc, - 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, - 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, - 0x6c44198c4a475817, -]; - -pub struct HASH512 { - length: [u64; 2], - h: [u64; 8], - w: [u64; 80], -} - -impl HASH512 { - fn s(n: u64, x: u64) -> u64 { - ((x) >> n) | ((x) << (64 - n)) - } - fn r(n: u64, x: u64) -> u64 { - (x) >> n - } - - fn ch(x: u64, y: u64, z: u64) -> u64 { - (x & y) ^ (!(x) & z) - } - - fn maj(x: u64, y: u64, z: u64) -> u64 { - (x & y) ^ (x & z) ^ (y & z) - } - - fn sig0(x: u64) -> u64 { - HASH512::s(28, x) ^ HASH512::s(34, x) ^ HASH512::s(39, x) - } - - fn sig1(x: u64) -> u64 { - HASH512::s(14, x) ^ HASH512::s(18, x) ^ HASH512::s(41, x) - } - - fn theta0(x: u64) -> u64 { - HASH512::s(1, x) ^ HASH512::s(8, x) ^ HASH512::r(7, x) - } - - fn theta1(x: u64) -> u64 { - HASH512::s(19, x) ^ HASH512::s(61, x) ^ HASH512::r(6, x) - } - - pub fn as_bytes(&self,array: &mut [u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=self.length[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..8 { - let mut t=self.h[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - for i in 0..80 { - let mut t=self.w[i]; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=(t%256) as u8; t/=256; ptr+=1; - array[ptr]=t as u8; ptr+=1; - } - } - - pub fn from_bytes(&mut self,array: &[u8]) { - let mut ptr=0; - for i in 0..2 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.length[i]=t; ptr+=8; - } - for i in 0..8 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.h[i]=t; ptr+=8; - } - for i in 0..80 { - let mut t=array[ptr+7] as u64; - t=256*t+(array[ptr+6] as u64); - t=256*t+(array[ptr+5] as u64); - t=256*t+(array[ptr+4] as u64); - t=256*t+(array[ptr+3] as u64); - t=256*t+(array[ptr+2] as u64); - t=256*t+(array[ptr+1] as u64); - t=256*t+(array[ptr] as u64); - self.w[i]=t; ptr+=8; - } - } - - fn transform(&mut self) { - /* basic transformation step */ - for j in 16..80 { - self.w[j] = HASH512::theta1(self.w[j - 2]) - .wrapping_add(self.w[j - 7]) - .wrapping_add(HASH512::theta0(self.w[j - 15])) - .wrapping_add(self.w[j - 16]); - } - let mut a = self.h[0]; - let mut b = self.h[1]; - let mut c = self.h[2]; - let mut d = self.h[3]; - let mut e = self.h[4]; - let mut f = self.h[5]; - let mut g = self.h[6]; - let mut hh = self.h[7]; - for j in 0..80 { - /* 64 times - mush it up */ - let t1 = hh - .wrapping_add(HASH512::sig1(e)) - .wrapping_add(HASH512::ch(e, f, g)) - .wrapping_add(HASH512_K[j]) - .wrapping_add(self.w[j]); - let t2 = HASH512::sig0(a).wrapping_add(HASH512::maj(a, b, c)); - hh = g; - g = f; - f = e; - e = d.wrapping_add(t1); - d = c; - c = b; - b = a; - a = t1.wrapping_add(t2); - } - self.h[0] = self.h[0].wrapping_add(a); - self.h[1] = self.h[1].wrapping_add(b); - self.h[2] = self.h[2].wrapping_add(c); - self.h[3] = self.h[3].wrapping_add(d); - self.h[4] = self.h[4].wrapping_add(e); - self.h[5] = self.h[5].wrapping_add(f); - self.h[6] = self.h[6].wrapping_add(g); - self.h[7] = self.h[7].wrapping_add(hh); - } - - /* Initialise Hash function */ - pub fn init(&mut self) { - /* initialise */ - for i in 0..64 { - self.w[i] = 0 - } - self.length[0] = 0; - self.length[1] = 0; - self.h[0] = HASH512_H0; - self.h[1] = HASH512_H1; - self.h[2] = HASH512_H2; - self.h[3] = HASH512_H3; - self.h[4] = HASH512_H4; - self.h[5] = HASH512_H5; - self.h[6] = HASH512_H6; - self.h[7] = HASH512_H7; - } - - pub fn new() -> HASH512 { - let mut nh = HASH512 { - length: [0; 2], - h: [0; 8], - w: [0; 80], - }; - nh.init(); - nh - } - - pub fn new_copy(hh: &HASH512) -> HASH512 { - let mut nh = HASH512 { - length: [0; 2], - h: [0; 8], - w: [0; 80], - }; - nh.length[0]=hh.length[0]; - nh.length[1]=hh.length[1]; - for i in 0..80 { - nh.w[i] = hh.w[i]; - } - for i in 0..8 { - nh.h[i] = hh.h[i]; - } - nh - } - - /* process a single byte */ - pub fn process(&mut self, byt: u8) { - /* process the next message byte */ - let cnt = ((self.length[0] / 64) % 16) as usize; - self.w[cnt] <<= 8; - self.w[cnt] |= byt as u64; - self.length[0] += 8; - if self.length[0] == 0 { - self.length[1] += 1; - self.length[0] = 0 - } - if (self.length[0] % 1024) == 0 { - self.transform() - } - } - - /* process an array of bytes */ - - pub fn process_array(&mut self, b: &[u8]) { - for i in 0..b.len() { - self.process(b[i]) - } - } - - /* process a 32-bit integer */ - pub fn process_num(&mut self, n: i32) { - self.process(((n >> 24) & 0xff) as u8); - self.process(((n >> 16) & 0xff) as u8); - self.process(((n >> 8) & 0xff) as u8); - self.process((n & 0xff) as u8); - } - - /* Generate 32-byte Hash */ - pub fn hash(&mut self) -> [u8; 64] { - /* pad message and finish - supply digest */ - let mut digest: [u8; 64] = [0; 64]; - let len0 = self.length[0]; - let len1 = self.length[1]; - self.process(0x80); - while (self.length[0] % 1024) != 896 { - self.process(0) - } - self.w[14] = len1; - self.w[15] = len0; - self.transform(); - for i in 0..64 { - /* convert to bytes */ - digest[i] = ((self.h[i / 8] >> (8 * (7 - i % 8))) & 0xff) as u8; - } - self.init(); - digest - } - pub fn continuing_hash(&self) -> [u8; 64] { - let mut sh=HASH512::new_copy(self); - sh.hash() - } -} - -//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909 -/* -fn main() { - let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); - let test = s.into_bytes(); - let mut sh=HASH512::new(); - - for i in 0..test.len(){ - sh.process(test[i]); - } - - let digest=sh.hash(); - for i in 0..64 {print!("{:02x}",digest[i])} -} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs deleted file mode 100644 index eb2dc0a6c16d..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/hmac.rs +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -use crate::hash256::HASH256; -use crate::hash384::HASH384; -use crate::hash512::HASH512; -use crate::sha3::SHA3; -use crate::rand::RAND; - -pub const MC_SHA2: usize = 2; -pub const MC_SHA3: usize = 3; -pub const SHA256: usize = 32; -pub const SHA384: usize = 48; -pub const SHA512: usize = 64; - -#[allow(non_snake_case)] - -/* General Purpose Hash function */ - -#[allow(clippy::too_many_arguments)] -pub fn GPhashit(hash: usize, sha: usize,w: &mut [u8],pad: usize,zpad: usize,a: Option<&[u8]>, n: isize, b: Option<&[u8]>) { - let mut r: [u8; 64] = [0; 64]; - - if hash == MC_SHA2 { - if sha == SHA256 { - let mut h = HASH256::new(); - for _ in 0..zpad { - h.process(0); - } - if let Some(x) = a { - h.process_array(x); - } - if n >= 0 { - h.process_num(n as i32) - } - if let Some(x) = b { - h.process_array(x); - } - let hs = h.hash(); - for i in 0..sha { - r[i] = hs[i]; - } - } - if sha == SHA384 { - let mut h = HASH384::new(); - for _ in 0..zpad { - h.process(0); - } - if let Some(x) = a { - h.process_array(x); - } - if n >= 0 { - h.process_num(n as i32) - } - if let Some(x) = b { - h.process_array(x); - } - let hs = h.hash(); - for i in 0..sha { - r[i] = hs[i]; - } - } - if sha == SHA512 { - let mut h = HASH512::new(); - for _ in 0..zpad { - h.process(0); - } - if let Some(x) = a { - h.process_array(x); - } - if n >= 0 { - h.process_num(n as i32) - } - if let Some(x) = b { - h.process_array(x); - } - let hs = h.hash(); - for i in 0..sha { - r[i] = hs[i]; - } - } - } - if hash == MC_SHA3 { - let mut h = SHA3::new(sha); - for _ in 0..zpad { - h.process(0); - } - if let Some(x) = a { - h.process_array(x); - } - if n >= 0 { - h.process_num(n as i32) - } - if let Some(x) = b { - h.process_array(x); - } - h.hash(&mut r); - } - - if pad == 0 { - for i in 0..sha { - w[i] = r[i] - } - } else if pad <= sha { - for i in 0..pad { - w[i] = r[i] - } - } else { - for i in 0..sha { - w[i + pad - sha] = r[i] - } - for i in 0..(pad - sha) { - w[i] = 0 - } - } -} - -#[allow(non_snake_case)] -pub fn SPhashit(hash: usize, sha: usize,w: &mut [u8],a: Option<&[u8]>) { - GPhashit(hash,sha,w,0,0,a,-1,None); -} - -pub fn inttobytes(n: usize, b: &mut [u8]) { - let mut i = b.len(); - let mut m = n; - while m > 0 && i > 0 { - i -= 1; - b[i] = (m & 0xff) as u8; - m /= 256; - } -} - -pub fn kdf2(hash: usize, sha: usize, z: &[u8], p: Option<&[u8]>, olen: usize, k: &mut [u8]) { - /* NOTE: the parameter olen is the length of the output K in bytes */ - let hlen = sha; - let mut lk = 0; - - let mut cthreshold = olen / hlen; - if olen % hlen != 0 { - cthreshold += 1 - } - - for counter in 1..cthreshold + 1 { - let mut b: [u8; 64] = [0; 64]; - GPhashit(hash, sha, &mut b,0,0,Some(z), counter as isize, p); - if lk + hlen > olen { - for i in 0..(olen % hlen) { - k[lk] = b[i]; - lk += 1 - } - } else { - for i in 0..hlen { - k[lk] = b[i]; - lk += 1 - } - } - } -} - -/* Password based Key Derivation Function */ -/* Input password p, salt s, and repeat count */ -/* Output key of length olen */ -pub fn pbkdf2(hash: usize, sha: usize, pass: &[u8], salt: &[u8], rep: usize, olen: usize, k: &mut [u8]) { - let mut d = olen / sha; - if olen % sha != 0 { - d += 1 - } - let mut f: [u8; 64] = [0; 64]; - let mut u: [u8; 64] = [0; 64]; - let mut ku: [u8; 64] = [0; 64]; - let mut s: [u8; 36] = [0; 36]; // Maximum salt of 32 bytes + 4 - let mut n: [u8; 4] = [0; 4]; - - let sl = salt.len(); - let mut kp = 0; - for i in 0..d { - for j in 0..sl { - s[j] = salt[j] - } - inttobytes(i + 1, &mut n); - for j in 0..4 { - s[sl + j] = n[j] - } - - hmac1(hash, sha, &mut f, sha, &s[0..sl + 4], pass); - - for j in 0..sha { - u[j] = f[j] - } - - for _ in 1..rep { - hmac1(hash, sha, &mut ku, sha, &u, pass); - for m in 0..sha { - u[m] = ku[m]; - f[m] ^= u[m] - } - } - for j in 0..sha { - if kp < olen { - k[kp] = f[j] - } - kp += 1 - } - } -} - -fn blksize(hash: usize, sha: usize) -> usize { - let mut lb=0; - if hash == MC_SHA2 { - lb=64; - if sha > 32 { - lb=128; - } - } - if hash == MC_SHA3 { - lb=200-2*sha; - } - lb -} - -/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */ -pub fn hmac1(hash: usize, sha: usize, tag: &mut [u8], olen: usize, k: &[u8], m: &[u8]) -> bool { - /* Input is from an octet m * - * olen is requested output length in bytes. k is the key * - * The output is the calculated tag */ - let mut b: [u8; 64] = [0; 64]; /* Not good */ - let mut k0: [u8; 128] = [0; 128]; - - let lb=blksize(hash,sha); - if lb == 0 { - return false; - } - - for i in 0..lb { - k0[i] = 0 - } - - if k.len() > lb { - SPhashit(hash,sha,&mut b,Some(k)); - //GPhashit(hash, sha, &mut b,0,0,k, 0, None); - for i in 0..sha { - k0[i] = b[i] - } - } else { - for i in 0..k.len() { - k0[i] = k[i] - } - } - - for i in 0..lb { - k0[i] ^= 0x36 - } - - GPhashit(hash, sha, &mut b,0,0,Some(&k0[0..lb]), -1, Some(m)); - - for i in 0..lb { - k0[i] ^= 0x6a - } - GPhashit(hash, sha, tag,olen,0,Some(&k0[0..lb]), -1, Some(&b[0..sha])); - - true -} - -pub fn hkdf_extract(hash: usize, hlen: usize, prk: &mut [u8],salt: Option<&[u8]>,ikm: &[u8]) { - if let Some(x)=salt { - hmac1(hash,hlen,prk,hlen,x,ikm); - } else { - let h: [u8; 64] = [0; 64]; - hmac1(hash,hlen,prk,hlen,&h[0..hlen],ikm); - } -} - -pub fn hkdf_expand(hash: usize, hlen: usize, okm: &mut [u8], olen: usize, prk: &[u8], info: &[u8]) { - let n=olen/hlen; - let flen=olen%hlen; - - let mut t: [u8; 1024] = [0; 1024]; // >= info.length+hlen+1 - let mut k: [u8; 64] = [0; 64]; - - let mut l=0; - let mut m=0; - for i in 1..=n { - for j in 0..info.len() { - t[l]=info[j]; l+=1; - } - t[l]=i as u8; l+=1; - hmac1(hash,hlen,&mut k,hlen,prk,&t[0..l]); - l=0; - for j in 0..hlen { - okm[m]=k[j]; m+=1; - t[l]=k[j]; l+=1; - } - } - if flen>0 { - for j in 0..info.len() { - t[l]=info[j]; l+=1; - } - t[l]=(n+1) as u8; l+=1; - hmac1(hash,hlen,&mut k,flen,prk,&t[0..l]); - for j in 0..flen { - okm[m]=k[j]; m+=1; - } - } -} - -fn ceil(a: usize,b: usize) -> usize { - (a-1)/b+1 -} - -pub fn xof_expand(hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { - let mut h = SHA3::new(hlen); - for i in 0..msg.len() { - h.process(msg[i]); - } - h.process(((olen >> 8) & 0xff) as u8); - h.process((olen & 0xff) as u8); - - for i in 0..dst.len() { - h.process(dst[i]); - } - h.process((dst.len() & 0xff) as u8); - - h.shake(okm,olen); -} - -pub fn xmd_expand(hash: usize,hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { - let mut w:[u8; 64]=[0;64]; - if dst.len() >= 256 { - GPhashit(hash, hlen, &mut w, 0, 0, Some(b"H2C-OVERSIZE-DST-"), -1, Some(&dst)); - xmd_expand_short_dst(hash, hlen, okm, olen, &w[0..hlen], msg); - } else { - xmd_expand_short_dst(hash, hlen, okm, olen, dst, msg); - } -} - -// Assumes dst.len() < 256. -fn xmd_expand_short_dst(hash: usize,hlen: usize,okm: &mut [u8],olen: usize,dst: &[u8],msg: &[u8]) { - - let mut tmp: [u8; 260] = [0; 260]; - let mut h0: [u8; 64]=[0;64]; - let mut h1: [u8; 64]=[0;64]; - let mut h2: [u8; 64]=[0;64]; - - let ell=ceil(olen,hlen); - let blk=blksize(hash,hlen); - tmp[0]=((olen >> 8) & 0xff) as u8; - tmp[1]=(olen & 0xff) as u8; - tmp[2]=0; - - for j in 0..dst.len() { - tmp[3+j]=dst[j]; - } - tmp[3+dst.len()]=(dst.len() & 0xff) as u8; - - GPhashit(hash, hlen, &mut h0, 0, blk, Some(msg), -1, Some(&tmp[0..dst.len()+4])); - - let mut k=0; - for i in 1..=ell { - for j in 0..hlen { - h1[j]^=h0[j]; - h2[j]=h1[j]; - } - tmp[0]=i as u8; - - for j in 0..dst.len() { - tmp[1+j]=dst[j]; - } - tmp[1+dst.len()]=(dst.len() & 0xff) as u8; - - GPhashit(hash, hlen, &mut h1, 0, 0, Some(&h2[0..hlen]), -1, Some(&tmp[0..dst.len()+2])); - for j in 0..hlen { - okm[k]=h1[j]; - k+=1; - if k==olen { - break; - } - } - } - -} - -/* Mask Generation Function */ - -pub fn mgf1(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { - let hlen = sha; - - let mut j = 0; - for i in 0..k.len() { - k[i] = 0 - } - - let mut cthreshold = olen / hlen; - if olen % hlen != 0 { - cthreshold += 1 - } - for counter in 0..cthreshold { - let mut b: [u8; 64] = [0; 64]; - GPhashit(MC_SHA2,sha,&mut b,0,0,Some(z),counter as isize,None); - //hashit(sha, Some(z), counter as isize, &mut b); - - if j + hlen > olen { - for i in 0..(olen % hlen) { - k[j] = b[i]; - j += 1 - } - } else { - for i in 0..hlen { - k[j] = b[i]; - j += 1 - } - } - } -} - -pub fn mgf1xor(sha: usize, z: &[u8], olen: usize, k: &mut [u8]) { - let hlen = sha; - let mut j = 0; - - let mut cthreshold = olen / hlen; - if olen % hlen != 0 { - cthreshold += 1 - } - for counter in 0..cthreshold { - let mut b: [u8; 64] = [0; 64]; - GPhashit(MC_SHA2,sha,&mut b,0,0,Some(z),counter as isize,None); - - if j + hlen > olen { - for i in 0..(olen % hlen) { - k[j] ^= b[i]; - j += 1 - } - } else { - for i in 0..hlen { - k[j] ^= b[i]; - j += 1 - } - } - } -} - -// PKCS 1.5 -/* SHAXXX identifier strings */ -const SHA256ID: [u8; 19] = [ - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20, -]; -const SHA384ID: [u8; 19] = [ - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, - 0x00, 0x04, 0x30, -]; -const SHA512ID: [u8; 19] = [ - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40, -]; - -pub fn pkcs15(sha: usize, m: &[u8], w: &mut [u8],rfs: usize) -> bool { - let olen = rfs; - let hlen = sha; - let idlen = 19; - let mut b: [u8; 64] = [0; 64]; /* Not good */ - - if olen < idlen + hlen + 10 { - return false; - } - SPhashit(MC_SHA2,sha,&mut b,Some(m)); - - for i in 0..w.len() { - w[i] = 0 - } - let mut i = 0; - w[i] = 0; - i += 1; - w[i] = 1; - i += 1; - for _ in 0..olen - idlen - hlen - 3 { - w[i] = 0xff; - i += 1 - } - w[i] = 0; - i += 1; - if hlen == SHA256 { - for j in 0..idlen { - w[i] = SHA256ID[j]; - i += 1 - } - } - if hlen == SHA384 { - for j in 0..idlen { - w[i] = SHA384ID[j]; - i += 1 - } - } - if hlen == SHA512 { - for j in 0..idlen { - w[i] = SHA512ID[j]; - i += 1 - } - } - for j in 0..hlen { - w[i] = b[j]; - i += 1 - } - true -} - -// Alternate PKCS 1.5 -/* SHAXXX identifier strings */ -const SHA256IDB: [u8; 17] = [ - 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20]; -const SHA384IDB: [u8; 17] = [ - 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30]; -const SHA512IDB: [u8; 17] = [ - 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40]; - -pub fn pkcs15b(sha: usize, m: &[u8], w: &mut [u8],rfs: usize) -> bool { - let olen = rfs; - let hlen = sha; - let idlen = 17; - let mut b: [u8; 64] = [0; 64]; /* Not good */ - - if olen < idlen + hlen + 10 { - return false; - } - SPhashit(MC_SHA2,sha,&mut b,Some(m)); - for i in 0..w.len() { - w[i] = 0 - } - let mut i = 0; - w[i] = 0; - i += 1; - w[i] = 1; - i += 1; - for _ in 0..olen - idlen - hlen - 3 { - w[i] = 0xff; - i += 1 - } - w[i] = 0; - i += 1; - if hlen == SHA256 { - for j in 0..idlen { - w[i] = SHA256IDB[j]; - i += 1 - } - } - if hlen == SHA384 { - for j in 0..idlen { - w[i] = SHA384IDB[j]; - i += 1 - } - } - if hlen == SHA512 { - for j in 0..idlen { - w[i] = SHA512IDB[j]; - i += 1 - } - } - for j in 0..hlen { - w[i] = b[j]; - i += 1 - } - true -} - -pub fn pss_encode(sha: usize, m: &[u8], rng: &mut RAND, f: &mut [u8], rfs: usize) -> bool { - let emlen=rfs; - let embits=8*emlen-1; - let hlen=sha; - let mut h:[u8;64]=[0;64]; - let mut salt: [u8; 64] = [0; 64]; - let mut md: [u8;136]=[0;136]; - for i in 0..hlen { - salt[i] = rng.getbyte() - } - let mask=(0xff as u8)>> (8*emlen-embits); - SPhashit(MC_SHA2,sha,&mut h,Some(m)); - if emlen bool { - let emlen=f.len(); - let embits=8*emlen-1; - let hlen=sha; - let mut db:[u8;512]=[0;512]; - let mut hmask:[u8;64]=[0;64]; - let mut h:[u8;64]=[0;64]; - let mut salt: [u8; 64] = [0; 64]; - let mut md: [u8;136]=[0;136]; - let mask=(0xff as u8)>> (8*emlen-embits); - - SPhashit(MC_SHA2,sha,&mut hmask,Some(m)); - if emlen, f: &mut [u8], rfs: usize) -> bool { - let olen = rfs - 1; - let mlen = m.len(); - - let hlen = sha; - - let mut seed: [u8; 64] = [0; 64]; - - let seedlen = hlen; - if mlen > olen - hlen - seedlen - 1 { - return false; - } - - let mut dbmask: [u8; 512] = [0; 512]; - - SPhashit(MC_SHA2,sha,f,p); - //hashit(sha, p, -1, f); - let slen = olen - mlen - hlen - seedlen - 1; - - for i in 0..slen { - f[hlen + i] = 0 - } - f[hlen + slen] = 1; - for i in 0..mlen { - f[hlen + slen + 1 + i] = m[i] - } - - for i in 0..seedlen { - seed[i] = rng.getbyte() - } - - mgf1(sha, &seed[0..seedlen], olen - seedlen, &mut dbmask); - - for i in 0..olen - seedlen { - dbmask[i] ^= f[i] - } - - mgf1(sha, &dbmask[0..olen - seedlen], seedlen, f); - - for i in 0..seedlen { - f[i] ^= seed[i] - } - - for i in 0..olen - seedlen { - f[i + seedlen] = dbmask[i] - } - - /* pad to length rfs */ - let d = 1; - for i in (d..rfs).rev() { - f[i] = f[i - d]; - } - for i in (0..d).rev() { - f[i] = 0; - } - true -} - -/* OAEP Message Decoding for Decryption */ -pub fn oaep_decode(sha: usize, p: Option<&[u8]>, f: &mut [u8],rfs :usize) -> usize { - let olen = rfs - 1; - - let hlen = sha; - let mut seed: [u8; 64] = [0; 64]; - let seedlen = hlen; - let mut chash: [u8; 64] = [0; 64]; - - if olen < seedlen + hlen + 1 { - return 0; - } - let mut dbmask: [u8; 512] = [0; 512]; - - if f.len() < rfs { - let d = rfs - f.len(); - for i in (d..rfs).rev() { - f[i] = f[i - d]; - } - for i in (0..d).rev() { - f[i] = 0; - } - } - SPhashit(MC_SHA2,sha,&mut chash,p); - //hashit(sha, p, -1, &mut chash); - - let x = f[0]; - - for i in seedlen..olen { - dbmask[i - seedlen] = f[i + 1]; - } - - mgf1(sha, &dbmask[0..olen - seedlen], seedlen, &mut seed); - for i in 0..seedlen { - seed[i] ^= f[i + 1] - } - mgf1(sha, &seed[0..seedlen], olen - seedlen, f); - for i in 0..olen - seedlen { - dbmask[i] ^= f[i] - } - - let mut comp=0; - for i in 0..hlen { - comp |= (chash[i]^dbmask[i]) as usize; - } - - for i in 0..olen - seedlen - hlen { - dbmask[i] = dbmask[i + hlen] - } - - for i in 0..hlen { - seed[i] = 0; - chash[i] = 0 - } - -// find first non-zero t in array - let mut k=0; - let mut t=0; - let m=olen-seedlen-hlen; - for i in 0..m { - if t==0 && dbmask[i]!=0 { - k=i; - t=dbmask[i]; - } - } - - if comp!=0 || x != 0 || t != 0x01 { - for i in 0..olen - seedlen { - dbmask[i] = 0 - } - return 0; - } - - for i in 0..m - k - 1 { - f[i] = dbmask[i + k + 1]; - } - - for i in 0..olen - seedlen { - dbmask[i] = 0 - } - - m - k - 1 -} - -/* - -use core::sha3; -use core::hmac; - - - - let mut okm: [u8;100]=[0;100]; - let msg: &[u8] = b"abc"; - let dst: &[u8] = b"P256_XMD:SHA-256_SSWU_RO_TESTGEN"; - hmac::xof_expand(sha3::SHAKE128,&mut okm,48,&dst,&msg); - print!("okm= "); printbinary(&okm[0..48]); - hmac::xmd_expand(hmac::MC_SHA2,32,&mut okm,48,&dst,&msg); - print!("okm= "); printbinary(&okm[0..48]); - - - let mut ikm: [u8;22]=[0;22]; - let mut salt: [u8;13]=[0;13]; - let mut info: [u8;10]=[0;10]; - let mut prk: [u8;32]=[0;32]; - let mut okm: [u8;42]=[0;42]; - - for i in 0..22 {ikm[i]=0x0b;} - for i in 0..13 {salt[i]=i as u8;} - for i in 0..10 {info[i]=(0xf0+i) as u8;} - - hmac::hkdf_extract(hmac::MC_SHA2,32,&mut prk,Some(&salt),&ikm); - - print!("PRK= "); - for i in 0..32 { - print!("{:02X}",prk[i]); - } - - hmac::hkdf_expand(hmac::MC_SHA2,32,&mut okm,42,&prk,&info); - print!("OKM= "); - for i in 0..42 { - print!("{:02X}",okm[i]); - } - - -*/ - diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs deleted file mode 100644 index fdd96edd7673..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/kyber.rs +++ /dev/null @@ -1,719 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Kyber API high-level functions. Constant time where it matters. Slow (spends nearly all of its time running SHA3) but small. - - M.Scott 06/07/2022 -*/ - -use crate::sha3; -use crate::sha3::SHA3; - -const LGN: usize = 8; -const DEGREE: usize = 1< i16 { - let dp=PRIME as i32; - let dt=(((a&0xffff)*QINV)&0xffff) as i16; - let t=((a-((dt as i32)*dp))>>16) as i16; - return t; -} - -fn barrett_reduce(a: i16) -> i16 { - let da=a as i32; - let mut t=((BARC*da + TWO25) >> 26) as i16; - t*=PRIME; - return a-t; -} - -fn fqmul(a: i16, b: i16) -> i16 { - return montgomery_reduce((a as i32)*(b as i32)); -} - -fn ntt(r: &mut [i16]) { - let mut k=1; - let mut len=128; - while len>=2 { - let mut start=0; - while start<256 { - let zeta=ZETAS[k]; k+=1; - let mut j=start; - while j>= 1; - } -} - -fn invntt(r: &mut [i16]) { - let f=1441 as i16; - let mut k=127; - let mut len=2; - while len<=128 { - let mut start=0; - while start<256 { - let zeta=ZETAS[k]; k-=1; - let mut j=start; - while j i16 { - let wd=n/8; - let bt=n%8; - return ((b[wd]>>bt)&1) as i16; -} - -fn cbd(bts: &[u8],eta: usize,f: &mut [i16]) { - for i in 0..DEGREE { - let mut a=0 as i16; - let mut b=0 as i16; - for j in 0..eta { - a+=getbit(bts,2*i*eta+j); - b+=getbit(bts,2*i*eta+eta+j); - } - f[i] = a-b; - } -} - -// extract ab bits into word from dense byte stream -fn nextword(ab: usize,t: &[u8],ptr: &mut usize,bts: &mut usize) -> i16 { - let mut r=(t[*ptr]>>(*bts)) as i16; - let mask=((1<=8 { - *bts -= 8; - *ptr += 1; - } - return r&mask; -} - -fn nextbyte16(ab: usize,t: &[i16],ptr: &mut usize,bts: &mut usize) -> u8 { - let mut left=ab-(*bts); - let mut i=0; - let mut w=t[*ptr]; w+=(w>>15)&PRIME; - let mut r=w>>(*bts); - while left<8 { - i+=1; - w=t[(*ptr)+i]; w+=(w>>15)&PRIME; - r|=w<=ab { - *bts -= ab; - *ptr += 1; - } - return (r&0xff) as u8; -} - -fn encode(t: &[i16],len: usize,l: usize,pack: &mut [u8]) { - let mut ptr=0; - let mut bts=0; - for n in 0..len*(DEGREE*l)/8 { - pack[n]=nextbyte16(l,t,&mut ptr, &mut bts); - } -} - -// return 0 if encoding is unchanged -fn chk_encode(t: &[i16],len: usize,l: usize,pack: &[u8]) -> u8 { - let mut ptr=0; - let mut bts=0; - let mut diff=0 as u8; - for n in 0..len*(DEGREE*l)/8 { - let m=nextbyte16(l,t,&mut ptr, &mut bts); - diff|=m^pack[n]; - } - return diff; -} - -fn decode(pack: &[u8],l: usize,t: &mut [i16],len: usize) { - let mut ptr=0; - let mut bts=0; - for i in 0..len*DEGREE { - t[i]=nextword(l,pack,&mut ptr,&mut bts); - } -} - -// Bernsteins safe division by 0xD01 -fn safediv(xx: i32) -> i32 { - let mut x=xx; - let mut q = 0 as i32; - - let mut qpart = (((x as i64)*645083)>>31) as i32; - x -= qpart*0xD01; q += qpart; - - qpart = ((((x as i64)*645083)>>31) as i32)+1; - x -= qpart*0xD01; q += qpart+(x>>31); - - return q; -} - -fn compress(t: &mut [i16],len:usize,d:usize) { - let twod=(1<>15)&PRIME; - t[i]= (safediv(twod*(t[i] as i32)+dp/2)&(twod-1)) as i16; - } -} -fn decompress(t: &mut [i16],len:usize,d:usize) { - let twod1=(1<<(d-1)) as i32; - let dp=PRIME as i32; - for i in 0..len*DEGREE { - t[i]=((dp*(t[i] as i32)+twod1)>>d) as i16; - } -} - - -fn cpa_keypair(params: &[usize],tau: &[u8],sk: &mut [u8],pk: &mut [u8]) { - let mut rho:[u8;32]=[0;32]; - let mut sigma:[u8;33]=[0;33]; - let mut buff:[u8;256]=[0;256]; - - let mut r:[i16;DEGREE]=[0;DEGREE]; - let mut w:[i16;DEGREE]=[0;DEGREE]; - let mut aij:[i16;DEGREE]=[0;DEGREE]; - let mut s:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let mut e:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let mut p:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - - let mut sh = SHA3::new(sha3::HASH512); - - let ck=params[0]; - let eta1=params[1]; - let public_key_size=32+ck*(DEGREE*3)/2; - - for i in 0..32 { - sh.process(tau[i]); - } - sh.hash(&mut buff); - for i in 0..32 { - rho[i]=buff[i]; - sigma[i]=buff[i+32]; - } - sigma[32]=0; - -// create s - for i in 0..ck { - sh=SHA3::new(sha3::SHAKE256); - for j in 0..33 { - sh.process(sigma[j]); - } - sh.shake(&mut buff,64*eta1); - cbd(&buff,eta1,&mut s[i*DEGREE..]); - sigma[32] += 1; - } - -// create e - for i in 0..ck { - sh=SHA3::new(sha3::SHAKE256); - for j in 0..33 { - sh.process(sigma[j]); - } - sh.shake(&mut buff,64*eta1); - cbd(&buff,eta1,&mut e[i*DEGREE..]); - sigma[32] += 1; - } - - for k in 0..ck { - let row=k*DEGREE; - poly_ntt(&mut s[row..]); - poly_ntt(&mut e[row..]); - } - - for i in 0..ck { - let row=i*DEGREE; - expandaij(&rho,&mut aij,i,0); - poly_mul(&mut r,&aij,&s); - for j in 1..ck { - expandaij(&rho,&mut aij,i,j); - poly_mul(&mut w,&s[j*DEGREE..],&aij); - poly_acc(&mut r,&w); - } - poly_reduce(&mut r); - poly_tomont(&mut r); - poly_add(&mut p[row..],&r,&e[row..]); - poly_reduce(&mut p[row..]); - } - - encode(&s,ck,12,sk); - encode(&p,ck,12,pk); - for i in 0..32 { - pk[public_key_size-32+i]=rho[i]; - } -} - -fn cpa_base_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],u: &mut [i16],v: &mut [i16]) { - let mut rho:[u8;32]=[0;32]; - let mut sigma:[u8;33]=[0;33]; - let mut buff:[u8;256]=[0;256]; - - let mut r:[i16;DEGREE]=[0;DEGREE]; - let mut w:[i16;DEGREE]=[0;DEGREE]; - let mut aij:[i16;DEGREE]=[0;DEGREE]; - let mut q:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let mut p:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - - let ck=params[0]; - let eta1=params[1]; - let eta2=params[2]; - let du=params[3]; - let dv=params[4]; - let public_key_size=32+ck*(DEGREE*3)/2; - - for i in 0..32 { - sigma[i]=coins[i]; - } - sigma[32]=0; - for i in 0..32 { - rho[i]=pk[i+public_key_size-32]; - } -// create q - for i in 0..ck { - let mut sh=SHA3::new(sha3::SHAKE256); - for j in 0..33 { - sh.process(sigma[j]); - } - sh.shake(&mut buff,64*eta1); - cbd(&buff,eta1,&mut q[i*DEGREE..]); - sigma[32] += 1; - } -// create e1 - for i in 0..ck { - let mut sh=SHA3::new(sha3::SHAKE256); - for j in 0..33 { - sh.process(sigma[j]); - } - sh.shake(&mut buff,64*eta2); - cbd(&buff,eta1,&mut u[i*DEGREE..]); - sigma[32] += 1; - } - for i in 0..ck { - let row=DEGREE*i; - poly_ntt(&mut q[row..]); - } - - for i in 0..ck { - let row=i*DEGREE; - expandaij(&rho,&mut aij,0,i); - poly_mul(&mut r,&aij,&q); - for j in 1..ck { - expandaij(&rho,&mut aij,j,i); - poly_mul(&mut w,&q[j*DEGREE..],&aij); - poly_acc(&mut r,&w); - } - poly_reduce(&mut r); - poly_invntt(&mut r); - poly_acc(&mut u[row..],&r); - poly_reduce(&mut u[row..]); - } - - decode(&pk,12,&mut p,ck); - - poly_mul(v,&p,&q); - for i in 1..ck { - let row=DEGREE*i; - poly_mul(&mut r,&p[row..],&q[row..]); - poly_acc(v,&r); - } - poly_invntt(v); - - let mut sh = SHA3::new(sha3::SHAKE256); - for j in 0..33 { - sh.process(sigma[j]); - } - sh.shake(&mut buff,64*eta2); - cbd(&buff,eta1,&mut w); // e2 - - poly_acc(v,&w); - - decode(&ss,1,&mut r,1); - decompress(&mut r,1,1); - poly_acc(v,&r); - poly_reduce(v); - compress(u,ck,du); - compress(v,1,dv); -} - -fn cpa_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],ct: &mut [u8]) { - let mut v:[i16;DEGREE]=[0;DEGREE]; - let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let ck=params[0]; - let du=params[3]; - let dv=params[4]; - let ciphertext_size=(du*ck+dv)*DEGREE/8; - cpa_base_encrypt(params,coins,pk,ss,&mut u,&mut v); - encode(&u,ck,du,ct); - encode(&v,1,dv,&mut ct[ciphertext_size-(dv*DEGREE/8)..]); -} - -// Re-encrypt and check that ct is OK (if so return is zero) -fn cpa_check_encrypt(params: &[usize],coins: &[u8],pk: &[u8],ss: &[u8],ct: &[u8]) -> u8 { - let mut v:[i16;DEGREE]=[0;DEGREE]; - let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let ck=params[0]; - let du=params[3]; - let dv=params[4]; - let ciphertext_size=(du*ck+dv)*DEGREE/8; - cpa_base_encrypt(params,coins,pk,ss,&mut u,&mut v); - let d1=chk_encode(&u,ck,du,ct); - let d2=chk_encode(&v,1,dv,&ct[ciphertext_size-(dv*DEGREE/8)..]); - if (d1|d2)==0 { - return 0; - } else { - return 0xff; - } -} - -fn cpa_decrypt(params: &[usize],sk: &[u8],ct: &[u8],ss: &mut [u8]) { - let mut w:[i16;DEGREE]=[0;DEGREE]; - let mut v:[i16;DEGREE]=[0;DEGREE]; - let mut r:[i16;DEGREE]=[0;DEGREE]; - let mut u:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - let mut s:[i16;MAXK*DEGREE]=[0;MAXK*DEGREE]; - - let ck=params[0]; - let du=params[3]; - let dv=params[4]; - - decode(ct,du,&mut u,ck); - decode(&ct[(du*ck*DEGREE)/8..],dv,&mut v,1); - decompress(&mut u,ck,du); - decompress(&mut v,1,dv); - decode(sk,12,&mut s,ck); - - poly_ntt(&mut u); - poly_mul(&mut w,&u,&s); - for i in 1..ck { - let row=DEGREE*i; - poly_ntt(&mut u[row..]); - poly_mul(&mut r,&u[row..],&s[row..]); - poly_acc(&mut w,&r); - } - poly_reduce(&mut w); - poly_invntt(&mut w); - poly_dec(&mut v,&w); - compress(&mut v,1,1); - encode(&v,1,1,ss); -} - -fn cca_keypair(params: &[usize],randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { - let ck=params[0]; - let secret_cpa_key_size=ck*(DEGREE*3)/2; - let public_key_size=32+ck*(DEGREE*3)/2; - - cpa_keypair(params,randbytes64,sk,pk); - for i in 0..public_key_size { - sk[i+secret_cpa_key_size]=pk[i]; - } - let mut sh = SHA3::new(sha3::HASH256); - for i in 0..public_key_size { - sh.process(pk[i]); - } - sh.hash(&mut sk[secret_cpa_key_size+public_key_size..]); - for i in 0..32 { - sk[i+secret_cpa_key_size+public_key_size+32]=randbytes64[i+32]; - } -} - -fn cca_encrypt(params: &[usize],randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { - let mut hm:[u8;32]=[0;32]; - let mut h:[u8;32]=[0;32]; - let mut g:[u8;64]=[0;64]; - let ck=params[0]; - let du=params[3]; - let dv=params[4]; - let public_key_size=32+ck*(DEGREE*3)/2; - let ciphertext_size=(du*ck+dv)*DEGREE/8; - let shared_secret_size=params[5]; - - let mut sh = SHA3::new(sha3::HASH256); - for i in 0..32 { - sh.process(randbytes32[i]); - } - sh.hash(&mut hm); - - sh = SHA3::new(sha3::HASH256); - for i in 0..public_key_size { - sh.process(pk[i]); - } - sh.hash(&mut h); - - sh = SHA3::new(sha3::HASH512); - sh.process_array(&hm); - sh.process_array(&h); - sh.hash(&mut g); - cpa_encrypt(params,&g[32..],&pk,&hm,ct); - - sh = SHA3::new(sha3::HASH256); - for i in 0..ciphertext_size { - sh.process(ct[i]); - } - sh.hash(&mut h); - sh = SHA3::new(sha3::SHAKE256); - sh.process_array(&g[0..32]); - sh.process_array(&h); - sh.shake(ss,shared_secret_size); -} - -fn cca_decrypt(params: &[usize],sk: &[u8],ct: &[u8],ss: &mut [u8]) { - let mut m:[u8;32]=[0;32]; - let mut g:[u8;64]=[0;64]; - let ck=params[0]; - let secret_cpa_key_size=ck*(DEGREE*3)/2; - let public_key_size=32+ck*(DEGREE*3)/2; - let shared_secret_size=params[5]; - - let pk=&sk[secret_cpa_key_size..secret_cpa_key_size+public_key_size]; - let h=&sk[secret_cpa_key_size+public_key_size..secret_cpa_key_size+public_key_size+32]; - let z=&sk[secret_cpa_key_size+public_key_size+32..secret_cpa_key_size+public_key_size+64]; - - cpa_decrypt(params,sk,ct,&mut m); - - let mut sh = SHA3::new(sha3::HASH512); - sh.process_array(&m); - sh.process_array(h); - sh.hash(&mut g); - - let mask=cpa_check_encrypt(params,&g[32..],pk,&m,ct); // FO check ct is correct - - for i in 0..32 { - g[i]^=(g[i]^z[i])&mask; - } - - sh = SHA3::new(sha3::HASH256); - sh.process_array(&ct); - sh.hash(&mut m); - - sh = SHA3::new(sha3::SHAKE256); - sh.process_array(&g[0..32]); - sh.process_array(&m); - sh.shake(ss,shared_secret_size); -} - -// ********************* Kyber API ****************************** - -pub fn keypair_512(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { - cca_keypair(&PARAMS_512,randbytes64,sk,pk); -} - -pub fn keypair_768(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { - cca_keypair(&PARAMS_768,randbytes64,sk,pk); -} - -pub fn keypair_1024(randbytes64: &[u8],sk: &mut [u8],pk: &mut [u8]) { - cca_keypair(&PARAMS_1024,randbytes64,sk,pk); -} - -pub fn encrypt_512(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { - cca_encrypt(&PARAMS_512,randbytes32,pk,ss,ct); -} - -pub fn encrypt_768(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { - cca_encrypt(&PARAMS_768,randbytes32,pk,ss,ct); -} - -pub fn encrypt_1024(randbytes32: &[u8],pk: &[u8],ss: &mut [u8],ct: &mut [u8]) { - cca_encrypt(&PARAMS_1024,randbytes32,pk,ss,ct); -} - -pub fn decrypt_512(sk: &[u8],ct: &[u8],ss: &mut [u8]) { - cca_decrypt(&PARAMS_512,sk,ct,ss); -} - -pub fn decrypt_768(sk: &[u8],ct: &[u8],ss: &mut [u8]) { - cca_decrypt(&PARAMS_768,sk,ct,ss); -} - -pub fn decrypt_1024(sk: &[u8],ct: &[u8],ss: &mut [u8]) { - cca_decrypt(&PARAMS_1024,sk,ct,ss); -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs deleted file mode 100644 index 7d2ebe7e4536..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/lib.rs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// comment out if debugging with print macros !!! -#![cfg_attr(not(feature = "std"), no_std)] - -#![allow(clippy::many_single_char_names)] -#![allow(clippy::needless_range_loop)] -#![allow(clippy::manual_memcpy)] -#![allow(clippy::new_without_default)] -pub mod arch; -pub mod aes; -pub mod gcm; -pub mod hmac; -pub mod hash256; -pub mod hash384; -pub mod hash512; -pub mod rand; -pub mod share; -pub mod sha3; -pub mod nhs; -pub mod dilithium; -pub mod kyber; -pub mod x509; -pub mod bn254; diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs deleted file mode 100644 index e7a11a969c03..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs deleted file mode 100644 index 8fc70fb1c3d7..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/nhs.rs +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* NewHope Simple API high-level functions */ - -use crate::rand::RAND; -use crate::sha3; -use crate::sha3::SHA3; - -const PRIME: i32 = 0x3001; // q in Hex -const LGN: usize = 10; // Degree n=2^LGN -const ND: u32 = 0xF7002FFF; // 1/(R-q) mod R -const ONE: i32 = 0x2AC8; // R mod q -const R2MODP: u64 = 0x1620; // R^2 mod q - -const DEGREE: usize = 1 << LGN; -const WL: usize = 32; - -const INV: i32 = 0xeab; -const INVPR: i32 = 0x2c2a; - -const ROOTS: [i32; 1024] = [ - 0x2ac8, 0x2baf, 0x299b, 0x685, 0x2f04, 0x158d, 0x2d49, 0x24b5, 0x1edc, 0xab3, 0x2a95, 0x24d, - 0x3cb, 0x6a8, 0x12f9, 0x15ba, 0x1861, 0x2a89, 0x1c5c, 0xbe6, 0xc1e, 0x2024, 0x207, 0x19ce, - 0x2710, 0x1744, 0x18bc, 0x2cd7, 0x396, 0x18d5, 0x1c45, 0xc4, 0x21a6, 0xe03, 0x2b3c, 0x2d91, - 0xc5d, 0x432, 0x1fbc, 0xcae, 0x2512, 0x2979, 0x3b2, 0x714, 0xb2e, 0x1a97, 0x1a03, 0x1bcd, - 0x2216, 0x2701, 0xa, 0x263c, 0x1179, 0x200c, 0x2d08, 0x1c34, 0x291, 0x2c99, 0x2a5a, 0x723, - 0xb1d, 0x1ccc, 0x1fb6, 0x2f58, 0x2bfe, 0x1cda, 0x2a0, 0x5f1, 0x2de, 0x1fc7, 0x1ea8, 0x1719, - 0x2fa7, 0x27ec, 0x20ff, 0x12c0, 0x1ac1, 0x2232, 0x2f9b, 0xd3e, 0x2aed, 0x15f0, 0x11e8, 0xed0, - 0x26a, 0x1de5, 0xa3f, 0xf43, 0xebf, 0x204e, 0xac7, 0x2d9c, 0x5ea, 0x25d1, 0xb6, 0x49c, 0x995, - 0x2555, 0x26e2, 0x100, 0x1878, 0x5aa, 0x2e10, 0x271c, 0xcb, 0x1b4c, 0x2fb8, 0x25b7, 0x1543, - 0x2c7b, 0x241a, 0x2223, 0x20ca, 0x24ed, 0x137, 0x1b65, 0x1dc2, 0x7c7, 0x2ec3, 0xd0c, 0x1169, - 0x1c7a, 0x1ea1, 0xf89, 0x2199, 0x291d, 0x1088, 0x2046, 0x256d, 0x2bc7, 0x2e9b, 0x41f, 0x1b55, - 0x2b38, 0xd0, 0x2e6a, 0x1755, 0x6bc, 0x2724, 0x3ba, 0x222e, 0x2c5c, 0x2da5, 0x213c, 0x10fe, - 0x169a, 0x1552, 0x5d3, 0x300, 0x1b5d, 0x1342, 0x2004, 0x256f, 0x2039, 0x667, 0x23b5, 0x1123, - 0xdb, 0x2da0, 0xe1e, 0x2f54, 0x2767, 0x154a, 0x40a, 0x11d3, 0x2821, 0xc09, 0x974, 0x694, 0xfbf, - 0x27ba, 0x132, 0x83f, 0x2d06, 0x10e, 0x183f, 0x29ae, 0x28c3, 0x2dc9, 0x1144, 0x2c70, 0x2a4a, - 0xf3c, 0x1e32, 0x1171, 0x1e43, 0xdd4, 0x2ddf, 0x28d2, 0xfac, 0x3c4, 0x2f19, 0x10a6, 0x2f7, - 0xe1d, 0x828, 0x138f, 0x1332, 0xfab, 0xcf6, 0x13f8, 0x24a0, 0x112d, 0x2717, 0x6e7, 0x1044, - 0x36e, 0xfe8, 0x6a, 0xba7, 0x1d69, 0x29ec, 0x23b2, 0xaee, 0x16df, 0x1068, 0x1a7e, 0x253f, - 0x24c, 0xb33, 0x2683, 0x15ce, 0x1ad3, 0x1a36, 0xc96, 0xaea, 0x260a, 0xce, 0x28b1, 0xe4f, - 0x2b11, 0x5f8, 0x1fc4, 0xe77, 0x2366, 0x11f9, 0x153c, 0x24eb, 0x20cd, 0x1398, 0x22, 0x2b97, - 0x249b, 0x8eb, 0x12b2, 0x2fe3, 0x29c1, 0x1b00, 0x2663, 0xeaa, 0x2e06, 0xe0, 0x1569, 0x10f5, - 0x284e, 0xa38, 0x201d, 0x1c53, 0x1681, 0x1f6f, 0x2f95, 0x2fe8, 0xacb, 0x1680, 0x17fd, 0x2c39, - 0x165a, 0x10bb, 0x29d8, 0x2622, 0x1196, 0x884, 0x2a79, 0x140e, 0x2d80, 0x6fa, 0x11b2, 0x26c4, - 0x355, 0x1054, 0x29e9, 0x23ed, 0xbe3, 0x24fa, 0x1fb3, 0x10ac, 0x2919, 0x2584, 0x10a4, 0xe85, - 0x650, 0x1893, 0x1dc1, 0xd8e, 0x12dc, 0x2d42, 0x284d, 0xfff, 0x250f, 0xacd, 0x13c3, 0x6cc, - 0x1a79, 0x1221, 0x2614, 0x270a, 0x1ea, 0x155, 0x2818, 0x222c, 0x2e5b, 0x25d8, 0x1dbf, 0x191c, - 0xb0f, 0xdac, 0x1082, 0x12ef, 0x11b6, 0xfa8, 0x2b72, 0x159d, 0x209e, 0x31b, 0x2c7c, 0x14f7, - 0xe09, 0x1bb2, 0x1ec7, 0x2404, 0x20ae, 0x6ad, 0xed6, 0x2b70, 0x1c7b, 0x18d1, 0x2732, 0x12da, - 0xd56, 0x5c1, 0x1648, 0x18b7, 0x1605, 0x1bc4, 0x280, 0x2ece, 0xc, 0x1aae, 0x1c4, 0x1cdb, - 0x22d6, 0x21d8, 0x257c, 0x51f, 0x211b, 0xff, 0x2ee0, 0x2585, 0xe1, 0x2c35, 0x26db, 0x2971, - 0x2208, 0x17e1, 0x21be, 0x135e, 0x28d6, 0x2891, 0x1689, 0x2138, 0xb86, 0x2e3a, 0x1204, 0x2d10, - 0x2324, 0xf3f, 0x2508, 0x33d, 0xcb2, 0x292a, 0xe27, 0x2e64, 0x29f8, 0x2d46, 0x9b7, 0x20eb, - 0x1b7c, 0x9eb, 0x2b2a, 0x58c, 0x27d0, 0x121b, 0x272e, 0x29f6, 0x2dbd, 0x2697, 0x2aac, 0xd6f, - 0x1c67, 0x2c5b, 0x108d, 0x363, 0x249d, 0x2d5e, 0x2fd, 0x2cb2, 0x1f8f, 0x20a4, 0xa19, 0x2ac9, - 0x19b1, 0x1581, 0x17a2, 0x29eb, 0x1b72, 0x13b0, 0xee4, 0xa8f, 0x2315, 0x5e6, 0x951, 0x2e29, - 0xdad, 0x1f2b, 0x224e, 0x37f, 0x1a72, 0xa91, 0x1407, 0x2df9, 0x3ad, 0x23f7, 0x1a24, 0x1d2a, - 0x234b, 0x1df3, 0x1143, 0x7ff, 0x1a6d, 0x2774, 0x2690, 0x2ab5, 0x586, 0x2781, 0x2009, 0x2fdd, - 0x2881, 0x399, 0x2fb6, 0x144, 0x137f, 0xfa0, 0x2e4c, 0x1c7f, 0x2fac, 0xb09, 0x1264, 0x127b, - 0x198c, 0x2b40, 0x230, 0x1cf4, 0x180b, 0xb58, 0x144a, 0x2aec, 0xfb, 0x2602, 0x14ee, 0x783, - 0x1098, 0x23d8, 0x203, 0xe9, 0x108a, 0x14b8, 0xeec, 0xc58, 0x1248, 0x243c, 0x28aa, 0x6bf, - 0x27c4, 0x276e, 0x19b8, 0x1d11, 0x2e16, 0x472, 0x1464, 0x24b9, 0x662, 0x1097, 0x2067, 0x20d6, - 0x171c, 0x4, 0x682, 0x17bb, 0x1186, 0x4f2, 0x3ff, 0x2a43, 0x1dc7, 0x1ae5, 0x8cc, 0x2e7c, - 0x2ef8, 0x2ae0, 0x2904, 0xed4, 0x6c5, 0x14ae, 0xb72, 0x11c3, 0x337, 0x2da3, 0x2916, 0x6d8, - 0x1cf9, 0x10ee, 0x1800, 0x1ae4, 0xa0d, 0x101b, 0x1a8d, 0x2e98, 0x24cd, 0x813, 0x1aa4, 0x9b9, - 0x680, 0x2349, 0x24d1, 0x20f8, 0xe31, 0x249f, 0x216b, 0x12d9, 0x1d21, 0x19db, 0x191a, 0x1dd0, - 0x5df, 0x55c, 0x2b86, 0x213, 0xe9e, 0x1ef1, 0x268a, 0x1d5e, 0x1e20, 0x28c1, 0x1379, 0x249, - 0x19de, 0x18b, 0x1e41, 0x2a1e, 0x2612, 0x297, 0x2e96, 0x2102, 0x46, 0x1b9f, 0x1a4d, 0x2050, - 0x1b32, 0x568, 0x11f7, 0x1829, 0x870, 0x1f4, 0x1dca, 0x990, 0x1df6, 0x2b62, 0x13ec, 0x9f2, - 0x1260, 0x2997, 0x1412, 0x1e6d, 0x1694, 0x11ac, 0x2d8b, 0x276f, 0x26f5, 0x233e, 0x2b44, 0x2f5a, - 0x2d37, 0x2cb1, 0xc75, 0x98d, 0x1d56, 0x7ae, 0x10e6, 0x113f, 0x17b8, 0xad3, 0x737, 0x221e, - 0x1b70, 0x1f3e, 0x2966, 0x18b2, 0x4fa, 0x2044, 0x1312, 0x154e, 0x2029, 0x700, 0x1b45, 0x27a6, - 0x226a, 0x21bf, 0x58d, 0x2f11, 0x2e02, 0x17fc, 0x4d2, 0x1757, 0xcb1, 0x2ef1, 0x2582, 0x1276, - 0x881, 0x2fc0, 0x104a, 0x670, 0x274f, 0x2b53, 0x19dd, 0x752, 0x1663, 0xcbd, 0x2b2b, 0x2fc6, - 0x13b6, 0x21e6, 0x15f6, 0x126b, 0x2637, 0x1cd9, 0x2f50, 0xe82, 0x5b0, 0x24e0, 0x1350, 0x2f24, - 0x21f7, 0x1a16, 0x2f3e, 0x167e, 0x1f7d, 0x28a0, 0x16f0, 0xe33, 0x53b, 0x28c5, 0x1500, 0x2f88, - 0x26cc, 0x2018, 0x1604, 0x218b, 0x2cd1, 0x9ee, 0x17f3, 0x5fd, 0x1f5a, 0x2d0, 0x2b46, 0x23cc, - 0x503, 0x1c46, 0x1cc3, 0x28e2, 0x243e, 0x122b, 0x2e0c, 0xe37, 0x2611, 0x85e, 0x9b8, 0x1b24, - 0x762, 0x19b6, 0x3bc, 0x2d50, 0x2079, 0x18da, 0x170a, 0x800, 0xaa2, 0x135a, 0x1a15, 0x13d1, - 0xca, 0x2113, 0x2db9, 0xdb2, 0x1a5c, 0x29a9, 0x1488, 0x14c1, 0x2c9, 0x917, 0x28e7, 0x265c, - 0xdab, 0x2ab9, 0x2bc6, 0x105b, 0x1839, 0x219c, 0x50, 0x11da, 0x1802, 0xf56, 0x2e6, 0x2190, - 0xddb, 0x56e, 0x9d9, 0x1c81, 0x1016, 0x12d6, 0x296f, 0x14b4, 0x1014, 0x1e64, 0x1d90, 0x89f, - 0x2bc2, 0x2777, 0x2819, 0x1c65, 0x1a41, 0x5a2, 0x2cd2, 0x427, 0xd71, 0x29c8, 0x1e58, 0x53f, - 0x7c5, 0x1dcd, 0x4a1, 0x1268, 0x2597, 0x2926, 0xee, 0x111b, 0x1038, 0xe6c, 0x22dc, 0x2f2f, - 0x441, 0x2cfd, 0x1cb0, 0x6a4, 0x2224, 0x620, 0x5dc, 0x16b1, 0x2a1d, 0x1787, 0x20c7, 0x641, - 0xd84, 0x1c05, 0x2d0d, 0x2f52, 0x1b8c, 0xd7d, 0x17e8, 0x1589, 0xc73, 0x151b, 0x4e2, 0x1ae9, - 0x1b18, 0xb9b, 0x949, 0x2c60, 0x1e7a, 0xd5, 0x1bdc, 0x1f57, 0x1753, 0x124a, 0x559, 0xb76, - 0x2334, 0x12d1, 0x1de1, 0x14b2, 0x2faa, 0x1697, 0x147a, 0x5a1, 0x2c30, 0x1c02, 0x1043, 0x2ee1, - 0x2402, 0x1cc8, 0x2a16, 0xff7, 0x1364, 0x1b9a, 0x2a53, 0x2f94, 0x294c, 0x1ee5, 0x1a87, 0x2141, - 0xd66, 0x953, 0x28a3, 0x2f30, 0x2477, 0x18e3, 0x1035, 0x1fc1, 0x1d68, 0x2fb3, 0x138c, 0x2487, - 0x1bf8, 0xd96, 0x1018, 0x748, 0x244e, 0x15bd, 0x175e, 0x2be, 0x23d, 0x1da, 0x176d, 0xc17, - 0x24be, 0x2ebb, 0x7d8, 0x100a, 0x759, 0x1db4, 0x2259, 0x23f4, 0x2d59, 0x2847, 0xbf5, 0x1cfe, - 0xa20, 0x258, 0x1180, 0x279c, 0x54, 0x2abf, 0xc5c, 0x9f9, 0x3d5, 0x2ce4, 0x165f, 0x23d9, - 0x27b9, 0x6f9, 0x281a, 0x169e, 0x627, 0x156d, 0x1ff8, 0x211, 0x2e34, 0x1724, 0x2c2e, 0x2790, - 0x2dd5, 0x2bf2, 0xdbc, 0x2884, 0x20a9, 0x2390, 0x1e1a, 0x1b6a, 0x5f7, 0xab7, 0x1333, 0x16ab, - 0x28dd, 0x20, 0x30f, 0x24b6, 0x5c2, 0x1ce4, 0x1400, 0x2669, 0x60, 0x156c, 0xe20, 0x26d4, - 0x26ab, 0x1ebb, 0x223d, 0x5b4, 0x2025, 0x1e1c, 0xaae, 0x2e08, 0x6cd, 0x1677, 0x13d9, 0x17b5, - 0x1046, 0x1d8c, 0x14eb, 0x18d8, 0x1ce5, 0x2478, 0x16ae, 0xb79, 0x23d4, 0x684, 0x156b, 0x567, - 0x1a, 0x29ce, 0x83a, 0x19e8, 0x58e, 0x294a, 0x1136, 0x2319, 0x2fba, 0x1a29, 0x1d, 0x1879, - 0x291b, 0x19f6, 0x2c2f, 0x21c9, 0x19bb, 0xbbc, 0x26f9, 0xc22, 0x708, 0x11a1, 0x18d3, 0x7f8, - 0x28f8, 0x2427, 0x1deb, 0xaed, 0x26aa, 0x2482, 0x203b, 0x2f05, 0x2b82, 0x192f, 0x2df4, 0x8dc, - 0x2877, 0xd5e, 0x240e, 0x775, 0x2dae, 0x1d3e, 0x20ba, 0x215b, 0x22d1, 0xeba, 0xf50, 0xaa8, - 0x184a, 0x1f67, 0x2e04, 0xc6e, 0x6dd, 0x1a09, 0x27f, 0x494, 0x1426, 0xae3, 0xe15, 0x65f, - 0x13c4, 0x105, 0x872, 0x2667, 0x1ff6, 0xd9f, 0x2ca1, 0x2f39, 0x2657, 0x23fd, 0x2405, 0xb73, - 0x2294, 0x1f1e, 0x2eba, 0x110a, 0x2cae, 0x141f, 0x22cd, 0x25d6, 0x11c1, 0x1c, 0x2d8e, 0x161a, - 0x1aa8, 0x229e, 0x1bf9, 0x7cf, 0x106d, 0x2c40, 0xd93, 0x255e, 0x28c2, 0xc1a, 0x2f17, 0x7ca, - 0x2f63, 0xbf, -]; -const IROOTS: [i32; 1024] = [ - 0x2ac8, 0x452, 0x297c, 0x666, 0xb4c, 0x2b8, 0x1a74, 0xfd, 0x1a47, 0x1d08, 0x2959, 0x2c36, - 0x2db4, 0x56c, 0x254e, 0x1125, 0x2f3d, 0x13bc, 0x172c, 0x2c6b, 0x32a, 0x1745, 0x18bd, 0x8f1, - 0x1633, 0x2dfa, 0xfdd, 0x23e3, 0x241b, 0x13a5, 0x578, 0x17a0, 0xa9, 0x104b, 0x1335, 0x24e4, - 0x28de, 0x5a7, 0x368, 0x2d70, 0x13cd, 0x2f9, 0xff5, 0x1e88, 0x9c5, 0x2ff7, 0x900, 0xdeb, - 0x1434, 0x15fe, 0x156a, 0x24d3, 0x28ed, 0x2c4f, 0x688, 0xaef, 0x2353, 0x1045, 0x2bcf, 0x23a4, - 0x270, 0x4c5, 0x21fe, 0xe5b, 0xfbb, 0x1f79, 0x6e4, 0xe68, 0x2078, 0x1160, 0x1387, 0x1e98, - 0x22f5, 0x13e, 0x283a, 0x123f, 0x149c, 0x2eca, 0xb14, 0xf37, 0xdde, 0xbe7, 0x386, 0x1abe, - 0xa4a, 0x49, 0x14b5, 0x2f36, 0x8e5, 0x1f1, 0x2a57, 0x1789, 0x2f01, 0x91f, 0xaac, 0x266c, - 0x2b65, 0x2f4b, 0xa30, 0x2a17, 0x265, 0x253a, 0xfb3, 0x2142, 0x20be, 0x25c2, 0x121c, 0x2d97, - 0x2131, 0x1e19, 0x1a11, 0x514, 0x22c3, 0x66, 0xdcf, 0x1540, 0x1d41, 0xf02, 0x815, 0x5a, 0x18e8, - 0x1159, 0x103a, 0x2d23, 0x2a10, 0x2d61, 0x1327, 0x403, 0x25c9, 0x7b3, 0x1f0c, 0x1a98, 0x2f21, - 0x1fb, 0x2157, 0x99e, 0x1501, 0x640, 0x1e, 0x1d4f, 0x2716, 0xb66, 0x46a, 0x2fdf, 0x1c69, 0xf34, - 0xb16, 0x1ac5, 0x1e08, 0xc9b, 0x218a, 0x103d, 0x2a09, 0x4f0, 0x21b2, 0x750, 0x2f33, 0x9f7, - 0x2517, 0x236b, 0x15cb, 0x152e, 0x1a33, 0x97e, 0x24ce, 0x2db5, 0xac2, 0x1583, 0x1f99, 0x1922, - 0x2513, 0xc4f, 0x615, 0x1298, 0x245a, 0x2f97, 0x2019, 0x2c93, 0x1fbd, 0x291a, 0x8ea, 0x1ed4, - 0xb61, 0x1c09, 0x230b, 0x2056, 0x1ccf, 0x1c72, 0x27d9, 0x21e4, 0x2d0a, 0x1f5b, 0xe8, 0x2c3d, - 0x2055, 0x72f, 0x222, 0x222d, 0x11be, 0x1e90, 0x11cf, 0x20c5, 0x5b7, 0x391, 0x1ebd, 0x238, - 0x73e, 0x653, 0x17c2, 0x2ef3, 0x2fb, 0x27c2, 0x2ecf, 0x847, 0x2042, 0x296d, 0x268d, 0x23f8, - 0x7e0, 0x1e2e, 0x2bf7, 0x1ab7, 0x89a, 0xad, 0x21e3, 0x261, 0x2f26, 0x1ede, 0xc4c, 0x299a, - 0xfc8, 0xa92, 0xffd, 0x1cbf, 0x14a4, 0x2d01, 0x2a2e, 0x1aaf, 0x1967, 0x1f03, 0xec5, 0x25c, - 0x3a5, 0xdd3, 0x2c47, 0x8dd, 0x2945, 0x18ac, 0x197, 0x2f31, 0x4c9, 0x14ac, 0x2be2, 0x166, - 0x43a, 0xa94, 0x1b53, 0x293c, 0x212d, 0x6fd, 0x521, 0x109, 0x185, 0x2735, 0x151c, 0x123a, - 0x5be, 0x2c02, 0x2b0f, 0x1e7b, 0x1846, 0x297f, 0x2ffd, 0x18e5, 0xf2b, 0xf9a, 0x1f6a, 0x299f, - 0xb48, 0x1b9d, 0x2b8f, 0x1eb, 0x12f0, 0x1649, 0x893, 0x83d, 0x2942, 0x757, 0xbc5, 0x1db9, - 0x23a9, 0x2115, 0x1b49, 0x1f77, 0x2f18, 0x2dfe, 0xc29, 0x1f69, 0x287e, 0x1b13, 0x9ff, 0x2f06, - 0x515, 0x1bb7, 0x24a9, 0x17f6, 0x130d, 0x2dd1, 0x4c1, 0x1675, 0x1d86, 0x1d9d, 0x24f8, 0x55, - 0x1382, 0x1b5, 0x2061, 0x1c82, 0x2ebd, 0x4b, 0x2c68, 0x780, 0x24, 0xff8, 0x880, 0x2a7b, 0x54c, - 0x971, 0x88d, 0x1594, 0x2802, 0x1ebe, 0x120e, 0xcb6, 0x12d7, 0x15dd, 0xc0a, 0x2c54, 0x208, - 0x1bfa, 0x2570, 0x158f, 0x2c82, 0xdb3, 0x10d6, 0x2254, 0x1d8, 0x26b0, 0x2a1b, 0xcec, 0x2572, - 0x211d, 0x1c51, 0x148f, 0x616, 0x185f, 0x1a80, 0x1650, 0x538, 0x25e8, 0xf5d, 0x1072, 0x34f, - 0x2d04, 0x2a3, 0xb64, 0x2c9e, 0x1f74, 0x3a6, 0x139a, 0x2292, 0x555, 0x96a, 0x244, 0x60b, 0x8d3, - 0x1de6, 0x831, 0x2a75, 0x4d7, 0x2616, 0x1485, 0xf16, 0x264a, 0x2bb, 0x609, 0x19d, 0x21da, - 0x6d7, 0x234f, 0x2cc4, 0xaf9, 0x20c2, 0xcdd, 0x2f1, 0x1dfd, 0x1c7, 0x247b, 0xec9, 0x1978, - 0x770, 0x72b, 0x1ca3, 0xe43, 0x1820, 0xdf9, 0x690, 0x926, 0x3cc, 0x2f20, 0xa7c, 0x121, 0x2f02, - 0xee6, 0x2ae2, 0xa85, 0xe29, 0xd2b, 0x1326, 0x2e3d, 0x1553, 0x2ff5, 0x133, 0x2d81, 0x143d, - 0x19fc, 0x174a, 0x19b9, 0x2a40, 0x22ab, 0x1d27, 0x8cf, 0x1730, 0x1386, 0x491, 0x212b, 0x2954, - 0xf53, 0xbfd, 0x113a, 0x144f, 0x21f8, 0x1b0a, 0x385, 0x2ce6, 0xf63, 0x1a64, 0x48f, 0x2059, - 0x1e4b, 0x1d12, 0x1f7f, 0x2255, 0x24f2, 0x16e5, 0x1242, 0xa29, 0x1a6, 0xdd5, 0x7e9, 0x2eac, - 0x2e17, 0x8f7, 0x9ed, 0x1de0, 0x1588, 0x2935, 0x1c3e, 0x2534, 0xaf2, 0x2002, 0x7b4, 0x2bf, - 0x1d25, 0x2273, 0x1240, 0x176e, 0x29b1, 0x217c, 0x1f5d, 0xa7d, 0x6e8, 0x1f55, 0x104e, 0xb07, - 0x241e, 0xc14, 0x618, 0x1fad, 0x2cac, 0x93d, 0x1e4f, 0x2907, 0x281, 0x1bf3, 0x588, 0x277d, - 0x1e6b, 0x9df, 0x629, 0x1f46, 0x19a7, 0x3c8, 0x1804, 0x1981, 0x2536, 0x19, 0x6c, 0x1092, - 0x1980, 0x13ae, 0xfe4, 0x2f42, 0x9e, 0x2837, 0xea, 0x23e7, 0x73f, 0xaa3, 0x226e, 0x3c1, 0x1f94, - 0x2832, 0x1408, 0xd63, 0x1559, 0x19e7, 0x273, 0x2fe5, 0x1e40, 0xa2b, 0xd34, 0x1be2, 0x353, - 0x1ef7, 0x147, 0x10e3, 0xd6d, 0x248e, 0xbfc, 0xc04, 0x9aa, 0xc8, 0x360, 0x2262, 0x100b, 0x99a, - 0x278f, 0x2efc, 0x1c3d, 0x29a2, 0x21ec, 0x251e, 0x1bdb, 0x2b6d, 0x2d82, 0x15f8, 0x2924, 0x2393, - 0x1fd, 0x109a, 0x17b7, 0x2559, 0x20b1, 0x2147, 0xd30, 0xea6, 0xf47, 0x12c3, 0x253, 0x288c, - 0xbf3, 0x22a3, 0x78a, 0x2725, 0x20d, 0x16d2, 0x47f, 0xfc, 0xfc6, 0xb7f, 0x957, 0x2514, 0x1216, - 0xbda, 0x709, 0x2809, 0x172e, 0x1e60, 0x28f9, 0x23df, 0x908, 0x2445, 0x1646, 0xe38, 0x3d2, - 0x160b, 0x6e6, 0x1788, 0x2fe4, 0x15d8, 0x47, 0xce8, 0x1ecb, 0x6b7, 0x2a73, 0x1619, 0x27c7, - 0x633, 0x2fe7, 0x2a9a, 0x1a96, 0x297d, 0xc2d, 0x2488, 0x1953, 0xb89, 0x131c, 0x1729, 0x1b16, - 0x1275, 0x1fbb, 0x184c, 0x1c28, 0x198a, 0x2934, 0x1f9, 0x2553, 0x11e5, 0xfdc, 0x2a4d, 0xdc4, - 0x1146, 0x956, 0x92d, 0x21e1, 0x1a95, 0x2fa1, 0x998, 0x1c01, 0x131d, 0x2a3f, 0xb4b, 0x2cf2, - 0x2fe1, 0x724, 0x1956, 0x1cce, 0x254a, 0x2a0a, 0x1497, 0x11e7, 0xc71, 0xf58, 0x77d, 0x2245, - 0x40f, 0x22c, 0x871, 0x3d3, 0x18dd, 0x1cd, 0x2df0, 0x1009, 0x1a94, 0x29da, 0x1963, 0x7e7, - 0x2908, 0x848, 0xc28, 0x19a2, 0x31d, 0x2c2c, 0x2608, 0x23a5, 0x542, 0x2fad, 0x865, 0x1e81, - 0x2da9, 0x25e1, 0x1303, 0x240c, 0x7ba, 0x2a8, 0xc0d, 0xda8, 0x124d, 0x28a8, 0x1ff7, 0x2829, - 0x146, 0xb43, 0x23ea, 0x1894, 0x2e27, 0x2dc4, 0x2d43, 0x18a3, 0x1a44, 0xbb3, 0x28b9, 0x1fe9, - 0x226b, 0x1409, 0xb7a, 0x1c75, 0x4e, 0x1299, 0x1040, 0x1fcc, 0x171e, 0xb8a, 0xd1, 0x75e, - 0x26ae, 0x229b, 0xec0, 0x157a, 0x111c, 0x6b5, 0x6d, 0x5ae, 0x1467, 0x1c9d, 0x200a, 0x5eb, - 0x1339, 0xbff, 0x120, 0x1fbe, 0x13ff, 0x3d1, 0x2a60, 0x1b87, 0x196a, 0x57, 0x1b4f, 0x1220, - 0x1d30, 0xccd, 0x248b, 0x2aa8, 0x1db7, 0x18ae, 0x10aa, 0x1425, 0x2f2c, 0x1187, 0x3a1, 0x26b8, - 0x2466, 0x14e9, 0x1518, 0x2b1f, 0x1ae6, 0x238e, 0x1a78, 0x1819, 0x2284, 0x1475, 0xaf, 0x2f4, - 0x13fc, 0x227d, 0x29c0, 0xf3a, 0x187a, 0x5e4, 0x1950, 0x2a25, 0x29e1, 0xddd, 0x295d, 0x1351, - 0x304, 0x2bc0, 0xd2, 0xd25, 0x2195, 0x1fc9, 0x1ee6, 0x2f13, 0x6db, 0xa6a, 0x1d99, 0x2b60, - 0x1234, 0x283c, 0x2ac2, 0x11a9, 0x639, 0x2290, 0x2bda, 0x32f, 0x2a5f, 0x15c0, 0x139c, 0x7e8, - 0x88a, 0x43f, 0x2762, 0x1271, 0x119d, 0x1fed, 0x1b4d, 0x692, 0x1d2b, 0x1feb, 0x1380, 0x2628, - 0x2a93, 0x2226, 0xe71, 0x2d1b, 0x20ab, 0x17ff, 0x1e27, 0x2fb1, 0xe65, 0x17c8, 0x1fa6, 0x43b, - 0x548, 0x2256, 0x9a5, 0x71a, 0x26ea, 0x2d38, 0x1b40, 0x1b79, 0x658, 0x15a5, 0x224f, 0x248, - 0xeee, 0x2f37, 0x1c30, 0x15ec, 0x1ca7, 0x255f, 0x2801, 0x18f7, 0x1727, 0xf88, 0x2b1, 0x2c45, - 0x164b, 0x289f, 0x14dd, 0x2649, 0x27a3, 0x9f0, 0x21ca, 0x1f5, 0x1dd6, 0xbc3, 0x71f, 0x133e, - 0x13bb, 0x2afe, 0xc35, 0x4bb, 0x2d31, 0x10a7, 0x2a04, 0x180e, 0x2613, 0x330, 0xe76, 0x19fd, - 0xfe9, 0x935, 0x79, 0x1b01, 0x73c, 0x2ac6, 0x21ce, 0x1911, 0x761, 0x1084, 0x1983, 0xc3, 0x15eb, - 0xe0a, 0xdd, 0x1cb1, 0xb21, 0x2a51, 0x217f, 0xb1, 0x1328, 0x9ca, 0x1d96, 0x1a0b, 0xe1b, 0x1c4b, - 0x3b, 0x4d6, 0x2344, 0x199e, 0x28af, 0x1624, 0x4ae, 0x8b2, 0x2991, 0x1fb7, 0x41, 0x2780, - 0x1d8b, 0xa7f, 0x110, 0x2350, 0x18aa, 0x2b2f, 0x1805, 0x1ff, 0xf0, 0x2a74, 0xe42, 0xd97, 0x85b, - 0x14bc, 0x2901, 0xfd8, 0x1ab3, 0x1cef, 0xfbd, 0x2b07, 0x174f, 0x69b, 0x10c3, 0x1491, 0xde3, - 0x28ca, 0x252e, 0x1849, 0x1ec2, 0x1f1b, 0x2853, 0x12ab, 0x2674, 0x238c, 0x350, 0x2ca, 0xa7, - 0x4bd, 0xcc3, 0x90c, 0x892, 0x276, 0x1e55, 0x196d, 0x1194, 0x1bef, 0x66a, 0x1da1, 0x260f, - 0x1c15, 0x49f, 0x120b, 0x2671, 0x1237, 0x2e0d, 0x2791, 0x17d8, 0x1e0a, 0x2a99, 0x14cf, 0xfb1, - 0x15b4, 0x1462, 0x2fbb, 0xeff, 0x16b, 0x2d6a, 0x9ef, 0x5e3, 0x11c0, 0x2e76, 0x1623, 0x2db8, - 0x1c88, 0x740, 0x11e1, 0x12a3, 0x977, 0x1110, 0x2163, 0x2dee, 0x47b, 0x2aa5, 0x2a22, 0x1231, - 0x16e7, 0x1626, 0x12e0, 0x1d28, 0xe96, 0xb62, 0x21d0, 0xf09, 0xb30, 0xcb8, 0x2981, 0x2648, - 0x155d, 0x27ee, 0xb34, 0x169, 0x1574, 0x1fe6, 0x25f4, 0x151d, 0x1801, 0x1f13, 0x1308, 0x2929, - 0x6eb, 0x25e, 0x2cca, 0x1e3e, 0x248f, -]; - -fn round(a: i32, b: i32) -> i32 { - (a + b / 2) / b -} - -/* Constant time absolute value */ -fn nabs(x: i32) -> i32 { - let mask = x >> 31; - (x + mask) ^ mask -} - -/* Montgomery stuff */ - -fn redc(t: u64) -> i32 { - let m = (t as u32).wrapping_mul(ND); - (((m as u64) * (PRIME as u64) + t) >> WL) as i32 -} - -fn nres(x: i32) -> i32 { - redc((x as u64) * R2MODP) -} - -fn modmul(a: i32, b: i32) -> i32 { - redc((a as u64) * (b as u64)) -} - -/* Cooley-Tukey NTT */ -fn ntt(x: &mut [i32]) { - let mut t = DEGREE / 2; - let q = PRIME; - - /* Convert to Montgomery form */ - for j in 0..DEGREE { - x[j] = nres(x[j]) - } - let mut m = 1; - while m < DEGREE { - let mut k = 0; - for i in 0..m { - let s = ROOTS[m + i]; - for j in k..k + t { - let u = x[j]; - let v = modmul(x[j + t], s); - x[j] = u + v; - x[j + t] = u + 2 * q - v; - } - k += 2 * t; - } - t /= 2; - m *= 2; - } -} - -/* Gentleman-Sande INTT */ - -fn intt(x: &mut [i32]) { - let mut t = 1; - let q = PRIME; - let mut m = DEGREE / 2; - while m > 1 { - let mut k = 0; - for i in 0..m { - let s = IROOTS[m + i]; - for j in k..k + t { - let u = x[j]; - let v = x[j + t]; - x[j] = u + v; - let w = u + (DEGREE as i32) * q - v; - x[j + t] = modmul(w, s); - } - k += 2 * t; - } - t *= 2; - m /= 2; - } - - /* Last iteration merged with n^-1 */ - t = DEGREE / 2; - for j in 0..t { - let u = x[j]; - let v = x[j + t]; - let w = u + (DEGREE as i32) * q - v; - x[j + t] = modmul(w, INVPR); - x[j] = modmul(u + v, INV); - } - /* convert back from Montgomery to "normal" form */ - for j in 0..DEGREE { - x[j] = redc(x[j] as u64); - x[j] -= q; - x[j] += (x[j] >> (WL - 1)) & q; - } -} - -/* See https://eprint.iacr.org/2016/1157.pdf */ - -fn encode(key: &[u8], poly: &mut [i32]) { - let q2 = PRIME / 2; - let mut j = 0; - let mut i = 0; - while i < 256 { - let mut kj = key[j]; - j += 1; - for _ in 0..8 { - let b = (kj & 1) as i32; - poly[i] = b * q2; - poly[i + 256] = b * q2; - poly[i + 512] = b * q2; - poly[i + 768] = b * q2; - kj >>= 1; - i += 1; - } - } -} - -fn decode(poly: &[i32], key: &mut [u8]) { - let q2 = PRIME / 2; - for i in 0..32 { - key[i] = 0; - } - - let mut i = 0; - let mut j = 0; - while i < 256 { - for _ in 0..8 { - let t = nabs(poly[i] - q2) - + nabs(poly[i + 256] - q2) - + nabs(poly[i + 512] - q2) - + nabs(poly[i + 768] - q2); - let mut b = t - PRIME; - b = (b >> 31) & 1; - key[j] = (key[j] >> 1) + ((b << 7) as u8); - i += 1; - } - j += 1; - } -} - -/* convert 32-byte seed to random polynomial */ - -fn parse(seed: &[u8], poly: &mut [i32]) { - let mut hash: [u8; 4 * DEGREE] = [0; 4 * DEGREE]; - let mut sh = SHA3::new(sha3::SHAKE128); - for i in 0..32 { - sh.process(seed[i]) - } - sh.shake(&mut hash, 4 * DEGREE); - - let mut j = 0; - for i in 0..DEGREE { - let mut n = (hash[j] & 0x7f) as i32; - n <<= 8; - n += (hash[j + 1]) as i32; - n <<= 8; - n += (hash[j + 2]) as i32; - n <<= 8; - n += (hash[j + 3]) as i32; - j += 4; - poly[i] = nres(n); - //poly[i]=modmul(n,ONE); // reduce 31-bit random number mod q - } -} - -/* Compress 14 bits polynomial coefficients into byte array */ -/* 7 bytes is 3x14 */ - -fn nhs_pack(poly: &[i32], array: &mut [u8]) { - let mut j = 0; - let mut i = 0; - while i < DEGREE { - let a = poly[i]; - let b = poly[i + 1]; - let c = poly[i + 2]; - let d = poly[i + 3]; - i += 4; - array[j] = (a & 0xff) as u8; - array[j + 1] = (((a >> 8) | (b << 6)) & 0xff) as u8; - array[j + 2] = ((b >> 2) & 0xff) as u8; - array[j + 3] = (((b >> 10) | (c << 4)) & 0xff) as u8; - array[j + 4] = ((c >> 4) & 0xff) as u8; - array[j + 5] = (((c >> 12) | (d << 2)) & 0xff) as u8; - array[j + 6] = (d >> 6) as u8; - j += 7; - } -} - -fn nhs_unpack(array: &[u8], poly: &mut [i32]) { - let mut j = 0; - let mut i = 0; - while i < DEGREE { - let a = array[j] as i32; - let b = array[j + 1] as i32; - let c = array[j + 2] as i32; - let d = array[j + 3] as i32; - let e = array[j + 4] as i32; - let f = array[j + 5] as i32; - let g = array[j + 6] as i32; - j += 7; - poly[i] = a | ((b & 0x3f) << 8); - poly[i + 1] = (b >> 6) | (c << 2) | ((d & 0xf) << 10); - poly[i + 2] = (d >> 4) | (e << 4) | ((f & 3) << 12); - poly[i + 3] = (f >> 2) | (g << 6); - i += 4; - } -} - -/* See https://eprint.iacr.org/2016/1157.pdf */ - -fn compress(poly: &[i32], array: &mut [u8]) { - let mut col = 0 as i32; - let mut j = 0; - let mut i = 0; - while i < DEGREE { - for _ in 0..8 { - let b = round(poly[i] * 8, PRIME) & 7; - col = (col << 3) + b; - i += 1; - } - array[j] = (col & 0xff) as u8; - array[j + 1] = ((col >> 8) & 0xff) as u8; - array[j + 2] = ((col >> 16) & 0xff) as u8; - j += 3; - col = 0; - } -} - -fn decompress(array: &[u8], poly: &mut [i32]) { - let mut j = 0; - let mut i = 0; - while i < DEGREE { - let mut col = (array[j + 2] as i32) & 0xff; - col = (col << 8) + ((array[j + 1] as i32) & 0xff); - col = (col << 8) + ((array[j] as i32) & 0xff); - j += 3; - for _ in 0..8 { - let b = (col & 0xe00000) >> 21; - col <<= 3; - poly[i] = round(b * PRIME, 8); - i += 1; - } - } -} - -/* generate centered binomial distribution */ - -fn error(rng: &mut RAND, poly: &mut [i32]) { - for i in 0..DEGREE { - let mut n1 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); - let mut n2 = ((rng.getbyte() as i32) & 0xff) + (((rng.getbyte() as i32) & 0xff) << 8); - let mut r = 0 as i32; - for _ in 0..16 { - r += (n1 & 1) - (n2 & 1); - n1 >>= 1; - n2 >>= 1; - } - poly[i] = r + PRIME; - } -} - -fn redc_it(p: &mut [i32]) { - for i in 0..DEGREE { - p[i] = redc(p[i] as u64); - } -} - -fn nres_it(p: &mut [i32]) { - for i in 0..DEGREE { - p[i] = nres(p[i]); - } -} - -fn poly_mul(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] = modmul(p1[i], p3[i]); - } -} - -fn poly_add(p1: &mut [i32], p3: &[i32]) { - for i in 0..DEGREE { - p1[i] += p3[i]; - } -} - -fn poly_rsub(p1: &mut [i32], p2: &[i32]) { - for i in 0..DEGREE { - p1[i] = p2[i] + PRIME - p1[i]; - } -} - -/* reduces inputs < 2q */ -fn poly_soft_reduce(poly: &mut [i32]) { - for i in 0..DEGREE { - let e = poly[i] - PRIME; - poly[i] = e + ((e >> (WL - 1)) & PRIME); - } -} - -/* fully reduces modulo q */ -fn poly_hard_reduce(poly: &mut [i32]) { - for i in 0..DEGREE { - let mut e = modmul(poly[i], ONE); - e -= PRIME; - poly[i] = e + ((e >> (WL - 1)) & PRIME); - } -} - -/* API functions. See https://eprint.iacr.org/2016/1157.pdf Protocol 1 */ -// ss is secret key key, sb is seed|public key to be sent to client -pub fn server_1(rng: &mut RAND, sb: &mut [u8], ss: &mut [u8]) { - let mut seed: [u8; 32] = [0; 32]; - let mut array: [u8; 1792] = [0; 1792]; - let mut s: [i32; DEGREE] = [0; DEGREE]; - let mut e: [i32; DEGREE] = [0; DEGREE]; - let mut b: [i32; DEGREE] = [0; DEGREE]; - - for i in 0..32 { - seed[i] = rng.getbyte(); - } - - parse(&seed, &mut b); - - error(rng, &mut e); - error(rng, &mut s); - - ntt(&mut s); - ntt(&mut e); - poly_mul(&mut b, &s); - poly_add(&mut b, &e); - poly_hard_reduce(&mut b); - - redc_it(&mut b); - nhs_pack(&b, &mut array); - - for i in 0..32 { - sb[i] = seed[i]; - } - - for i in 0..1792 { - sb[i + 32] = array[i]; - } - - poly_hard_reduce(&mut s); - nhs_pack(&s, &mut array); - - for i in 0..1792 { - ss[i] = array[i]; - } -} - -// optimized to reduce memory -// uc is U|cbar to be returned to server -// okey is shared key -pub fn client(rng: &mut RAND, sb: &[u8], uc: &mut [u8], okey: &mut [u8]) { - let mut sh = SHA3::new(sha3::HASH256); - - let mut seed: [u8; 32] = [0; 32]; - let mut array: [u8; 1792] = [0; 1792]; - let mut key: [u8; 32] = [0; 32]; - let mut cc: [u8; 384] = [0; 384]; - - let mut sd: [i32; DEGREE] = [0; DEGREE]; - let mut ed: [i32; DEGREE] = [0; DEGREE]; - let mut u: [i32; DEGREE] = [0; DEGREE]; - let mut k: [i32; DEGREE] = [0; DEGREE]; - let mut c: [i32; DEGREE] = [0; DEGREE]; - - error(rng, &mut sd); - error(rng, &mut ed); - - ntt(&mut sd); - ntt(&mut ed); - - for i in 0..32 { - seed[i] = sb[i]; - } - - for i in 0..1792 { - array[i] = sb[i + 32]; - } - - parse(&seed, &mut u); - - poly_mul(&mut u, &sd); - poly_add(&mut u, &ed); - poly_hard_reduce(&mut u); - - for i in 0..32 { - key[i] = rng.getbyte(); - } - - for i in 0..32 { - sh.process(key[i]); - } - sh.hash(&mut key); - - encode(&key, &mut k); - - nhs_unpack(&array, &mut c); - nres_it(&mut c); - - poly_mul(&mut c, &sd); - intt(&mut c); - error(rng, &mut ed); - poly_add(&mut c, &ed); - poly_add(&mut c, &k); - - compress(&c, &mut cc); - - sh = SHA3::new(sha3::HASH256); - for i in 0..32 { - sh.process(key[i]); - } - sh.hash(&mut key); - - for i in 0..32 { - okey[i] = key[i]; - } - - redc_it(&mut u); - nhs_pack(&u, &mut array); - - for i in 0..1792 { - uc[i] = array[i]; - } - - for i in 0..384 { - uc[i + 1792] = cc[i]; - } -} - -// calculate shared okey from uc and secret key ss -pub fn server_2(ss: &[u8], uc: &[u8], okey: &mut [u8]) { - let mut sh = SHA3::new(sha3::HASH256); - - let mut s: [i32; DEGREE] = [0; DEGREE]; - let mut k: [i32; DEGREE] = [0; DEGREE]; - let mut c: [i32; DEGREE] = [0; DEGREE]; - - let mut array: [u8; 1792] = [0; 1792]; - let mut key: [u8; 32] = [0; 32]; - let mut cc: [u8; 384] = [0; 384]; - - for i in 0..1792 { - array[i] = uc[i]; - } - - nhs_unpack(&array, &mut k); - nres_it(&mut k); - - for i in 0..384 { - cc[i] = uc[i + 1792]; - } - - decompress(&cc, &mut c); - - for i in 0..1792 { - array[i] = ss[i]; - } - - nhs_unpack(&array, &mut s); - - poly_mul(&mut k, &s); - intt(&mut k); - poly_rsub(&mut k, &c); - poly_soft_reduce(&mut k); - - decode(&k, &mut key); - - for i in 0..32 { - sh.process(key[i]); - } - sh.hash(&mut key); - - for i in 0..32 { - okey[i] = key[i]; - } -} - -/* -fn main() { - let x=3; - let y=redc(x as u64); - let z=redc((y as u64)*(R2MODP)); - println!("{:02x}",z); - - let mut a:[i32;1024]=[0;1024]; - for i in 0..1024 {a[i]=i as i32} - - ntt(&mut a); - - for i in 0..1024 {a[i]=modmul(a[i],ONE)} - - intt(&mut a); - - println!("{:02x}",a[7]); - -} -*/ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs deleted file mode 100644 index 5d099ecd0a50..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/rand.rs +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//extern crate mcore; - -use crate::hash256::HASH256; - -pub const RAND_NK: usize = 21; -const RAND_NJ: usize = 6; -const RAND_NV: usize = 8; - -// Marsaglia-Zaman random generator (https://projecteuclid.org/euclid.aoap/1177005878) -// Analysis: https://ieeexplore.ieee.org/document/669305 -#[allow(non_camel_case_types)] -pub struct RAND { - pub ira: [u32; RAND_NK], /* random number... */ - pub rndptr: usize, - pub borrow: u32, - pub pool_ptr: usize, - pub pool: [u8; 32], -} - -impl RAND { - pub fn new() -> RAND { - RAND { - ira: [0; RAND_NK], - rndptr: 0, - borrow: 0, - pool_ptr: 0, - pool: [0; 32], - } - } - - #[allow(dead_code)] - pub fn clean(&mut self) { - self.pool_ptr = 0; - self.rndptr = 0; - for i in 0..32 { - self.pool[i] = 0 - } - for i in 0..RAND_NK { - self.ira[i] = 0 - } - self.borrow = 0; - } - - fn sbrand(&mut self) -> u32 { - /* Marsaglia & Zaman random number generator */ - self.rndptr += 1; - if self.rndptr < RAND_NK { - return self.ira[self.rndptr]; - } - self.rndptr = 0; - let mut k = RAND_NK - RAND_NJ; - for i in 0..RAND_NK { - /* calculate next NK values */ - if k == RAND_NK { - k = 0 - } - let t = self.ira[k]; - let pdiff = t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow); - if pdiff < t { - self.borrow = 0 - } - if pdiff > t { - self.borrow = 1 - } - self.ira[i] = pdiff; - k += 1; - } - self.ira[0] - } - - fn sirand(&mut self, seed: u32) { - let mut m: u32 = 1; - let mut sd = seed; - self.borrow = 0; - self.rndptr = 0; - self.ira[0] ^= sd; - for i in 1..RAND_NK { - /* fill initialisation vector */ - let inn = (RAND_NV * i) % RAND_NK; - self.ira[inn] ^= m; /* note XOR */ - let t = m; - m = sd.wrapping_sub(m); - sd = t; - } - for _ in 0..10000 { - self.sbrand(); - } /* "warm-up" & stir the generator */ - } - - fn fill_pool(&mut self) { - let mut sh = HASH256::new(); - for _ in 0..128 { - sh.process((self.sbrand() & 0xff) as u8) - } - let w = sh.hash(); - for i in 0..32 { - self.pool[i] = w[i] - } - self.pool_ptr = 0; - } - - fn pack(b: [u8; 4]) -> u32 { - /* pack 4 bytes into a 32-bit Word */ - (((b[3] as u32) & 0xff) << 24) - | (((b[2] as u32) & 0xff) << 16) - | (((b[1] as u32) & 0xff) << 8) - | ((b[0] as u32) & 0xff) - } - - pub fn seed(&mut self, rawlen: usize, raw: &[u8]) { - /* initialise from at least 128 byte string of raw random entropy */ - let mut b: [u8; 4] = [0; 4]; - let mut sh = HASH256::new(); - self.pool_ptr = 0; - - for i in 0..RAND_NK { - self.ira[i] = 0 - } - if rawlen > 0 { - for i in 0..rawlen { - sh.process(raw[i]); - } - let digest = sh.hash(); - - /* initialise PRNG from distilled randomness */ - - for i in 0..8 { - b[0] = digest[4 * i]; - b[1] = digest[4 * i + 1]; - b[2] = digest[4 * i + 2]; - b[3] = digest[4 * i + 3]; - self.sirand(RAND::pack(b)); - } - } - self.fill_pool(); - } - - pub fn getbyte(&mut self) -> u8 { - let r = self.pool[self.pool_ptr]; - self.pool_ptr += 1; - if self.pool_ptr >= 32 { - self.fill_pool() - } - r - } -} - - - -/* test main program - -fn main() { - let mut raw : [u8;100]=[0;100]; - let mut rng=RAND::new(); - - rng.clean(); - for i in 0..100 {raw[i]=i as u8} - - rng.seed(100,&raw); - - for _ in 0..1000 { - print!("{:03} ",rng.getbyte()); - } -} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs deleted file mode 100644 index 43f47a42f5ee..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/sha3.rs +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -pub const HASH224: usize = 28; -pub const HASH256: usize = 32; -pub const HASH384: usize = 48; -pub const HASH512: usize = 64; -pub const SHAKE128: usize = 16; -pub const SHAKE256: usize = 32; - -const ROUNDS: usize = 24; - -const RC: [u64; 24] = [ - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -]; - -pub struct SHA3 { - length: usize, - rate: usize, - len: usize, - //s: [[u64; 5]; 5], - s: [u64;25], -} - -impl SHA3 { - fn rotl(x: u64, n: u64) -> u64 { - ((x) << n) | ((x) >> (64 - n)) - } - - fn transform(&mut self) { - for k in 0..ROUNDS { - let c0=self.s[0]^self.s[5]^self.s[10]^self.s[15]^self.s[20]; - let c1=self.s[1]^self.s[6]^self.s[11]^self.s[16]^self.s[21]; - let c2=self.s[2]^self.s[7]^self.s[12]^self.s[17]^self.s[22]; - let c3=self.s[3]^self.s[8]^self.s[13]^self.s[18]^self.s[23]; - let c4=self.s[4]^self.s[9]^self.s[14]^self.s[19]^self.s[24]; - - let d0=c4^SHA3::rotl(c1,1); - let d1=c0^SHA3::rotl(c2,1); - let d2=c1^SHA3::rotl(c3,1); - let d3=c2^SHA3::rotl(c4,1); - let d4=c3^SHA3::rotl(c0,1); - - let b00 = self.s[0]^d0; - let b02 = SHA3::rotl(self.s[1]^d1, 1); - let b04 = SHA3::rotl(self.s[2]^d2, 62); - let b01 = SHA3::rotl(self.s[3]^d3, 28); - let b03 = SHA3::rotl(self.s[4]^d4, 27); - - let b13 = SHA3::rotl(self.s[5]^d0, 36); - let b10 = SHA3::rotl(self.s[6]^d1, 44); - let b12 = SHA3::rotl(self.s[7]^d2, 6); - let b14 = SHA3::rotl(self.s[8]^d3, 55); - let b11 = SHA3::rotl(self.s[9]^d4, 20); - - let b21 = SHA3::rotl(self.s[10]^d0, 3); - let b23 = SHA3::rotl(self.s[11]^d1, 10); - let b20 = SHA3::rotl(self.s[12]^d2, 43); - let b22 = SHA3::rotl(self.s[13]^d3, 25); - let b24 = SHA3::rotl(self.s[14]^d4, 39); - - let b34 = SHA3::rotl(self.s[15]^d0, 41); - let b31 = SHA3::rotl(self.s[16]^d1, 45); - let b33 = SHA3::rotl(self.s[17]^d2, 15); - let b30 = SHA3::rotl(self.s[18]^d3, 21); - let b32 = SHA3::rotl(self.s[19]^d4, 8); - - let b42 = SHA3::rotl(self.s[20]^d0, 18); - let b44 = SHA3::rotl(self.s[21]^d1, 2); - let b41 = SHA3::rotl(self.s[22]^d2, 61); - let b43 = SHA3::rotl(self.s[23]^d3, 56); - let b40 = SHA3::rotl(self.s[24]^d4, 14); - - self.s[0]=b00^(!b10&b20); - self.s[1]=b10^(!b20&b30); - self.s[2]=b20^(!b30&b40); - self.s[3]=b30^(!b40&b00); - self.s[4]=b40^(!b00&b10); - - self.s[5]=b01^(!b11&b21); - self.s[6]=b11^(!b21&b31); - self.s[7]=b21^(!b31&b41); - self.s[8]=b31^(!b41&b01); - self.s[9]=b41^(!b01&b11); - - self.s[10]=b02^(!b12&b22); - self.s[11]=b12^(!b22&b32); - self.s[12]=b22^(!b32&b42); - self.s[13]=b32^(!b42&b02); - self.s[14]=b42^(!b02&b12); - - self.s[15]=b03^(!b13&b23); - self.s[16]=b13^(!b23&b33); - self.s[17]=b23^(!b33&b43); - self.s[18]=b33^(!b43&b03); - self.s[19]=b43^(!b03&b13); - - self.s[20]=b04^(!b14&b24); - self.s[21]=b14^(!b24&b34); - self.s[22]=b24^(!b34&b44); - self.s[23]=b34^(!b44&b04); - self.s[24]=b44^(!b04&b14); - - self.s[0] ^= RC[k]; - } - } - - /* Initialise Hash function */ - pub fn init(&mut self, olen: usize) { - /* initialise */ - for i in 0..25 { - self.s[i] = 0; - } - self.length = 0; - self.len = olen; - self.rate = 200 - 2 * olen; - } - - pub fn new(olen: usize) -> SHA3 { - let mut nh = SHA3 { - length: 0, - rate: 0, - len: 0, - s: [0; 25], - }; - nh.init(olen); - nh - } - - pub fn new_copy(hh: &SHA3) -> SHA3 { - let mut nh = SHA3 { - length: 0, - rate: 0, - len: 0, - s: [0; 25], - }; - nh.length=hh.length; - nh.len=hh.len; - nh.rate=hh.rate; - for i in 0..25 { - nh.s[i] = hh.s[i]; - } - nh - } - - /* process a single byte */ - pub fn process(&mut self, byt: u8) { - /* process the next message byte */ - let cnt = self.length as usize; - let b = cnt % 8; - let ind = cnt / 8; - self.s[ind] ^= (byt as u64) << (8 * b); - self.length += 1; - if self.length == self.rate { - self.length=0; - self.transform(); - } - } - - /* process an array of bytes */ - - pub fn process_array(&mut self, b: &[u8]) { - for i in 0..b.len() { - self.process(b[i]) - } - } - - /* process a 32-bit integer */ - pub fn process_num(&mut self, n: i32) { - self.process(((n >> 24) & 0xff) as u8); - self.process(((n >> 16) & 0xff) as u8); - self.process(((n >> 8) & 0xff) as u8); - self.process((n & 0xff) as u8); - } - - pub fn squeeze(&mut self, buff: &mut [u8], olen: usize) { - let mut m = 0; - let nb=olen/self.rate; - - for _ in 0..nb { - for i in 0..self.rate/8 { - let mut el=self.s[i]; - for _ in 0..8 { - buff[m]=(el & 0xff) as u8; - m += 1; - el >>= 8; - } - } - self.transform(); - } - - let mut i=0; - while m= olen { - break; - } - el >>= 8; - } - } - -/* - loop { - for i in 0..25 { - let mut el = self.s[i]; - for _ in 0..8 { - buff[m] = (el & 0xff) as u8; - m += 1; - if m >= olen || (m % self.rate) == 0 { - done = true; - break; - } - el >>= 8; - } - if done { - break; - } - } - if m >= olen { - break; - } - done = false; - self.transform(); - } */ - } - - /* Generate 32-byte Hash */ - pub fn hash(&mut self, digest: &mut [u8]) { - /* pad message and finish - supply digest */ - let q = self.rate - self.length; - if q == 1 { - self.process(0x86); - } else { - self.process(0x06); - while self.length != self.rate - 1 { - self.process(0x00) - } - self.process(0x80); - } - let hlen = self.len as usize; - self.squeeze(digest, hlen); - } - - pub fn continuing_hash(&mut self, digest: &mut [u8]) { - let mut sh=SHA3::new_copy(self); - sh.hash(digest) - } - - pub fn shake(&mut self, digest: &mut [u8], olen: usize) { - let q = self.rate - self.length; - if q == 1 { - self.process(0x9f); - } else { - self.process(0x1f); - while self.length != self.rate - 1 { - self.process(0x00) - } - self.process(0x80); - } - self.squeeze(digest, olen); - } - - pub fn continuing_shake(&mut self, digest: &mut [u8], olen: usize) { - let mut sh=SHA3::new_copy(self); - sh.shake(digest,olen); - } -} - -//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 -//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 -//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 -/* -fn main() { - let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); - let mut digest: [u8;100]=[0;100]; - let test = s.into_bytes(); - - let mut sh=SHA3::new(HASH256); - for i in 0..test.len(){ - sh.process(test[i]); - } - sh.hash(&mut digest); - for i in 0..32 {print!("{:02x}",digest[i])} - println!(""); - - sh=SHA3::new(HASH512); - for i in 0..test.len(){ - sh.process(test[i]); - } - sh.hash(&mut digest); - for i in 0..64 {print!("{:02x}",digest[i])} - println!(""); - - sh=SHA3::new(SHAKE256); - for i in 0..test.len(){ - sh.process(test[i]); - } - sh.shake(&mut digest,72); - for i in 0..72 {print!("{:02x}",digest[i])} - println!(""); - -} */ diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs deleted file mode 100644 index 4c434d64c9ce..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/share.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Shamir threshold secret sharing module */ -/* Split any byte array into number of shares < 256 */ -/* Specify number of shares required for recovery - nsr */ - -/* See TestMPIN.rs for an example of use */ - -use crate::rand::RAND; - -const PTAB: [u8; 256] = [ - 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, - 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, - 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, - 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, - 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, - 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, - 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, - 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, - 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, - 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, - 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, - 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, - 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, -]; - -const LTAB: [u8; 256] = [ - 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, - 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, - 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, - 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, - 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, - 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, - 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, - 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, - 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, - 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, - 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, - 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, - 24, 13, 99, 140, 128, 192, 247, 112, 7, -]; - -pub struct SHARE<'a> { - id: u8, - nsr: u8, - b: &'a [u8] -} - -fn mul(x: u8, y: u8) -> u8 { -/* x.y= AntiLog(Log(x) + Log(y)) */ - let ix = (x as usize) & 0xff; - let iy = (y as usize) & 0xff; - let lx = (LTAB[ix] as usize) & 0xff; - let ly = (LTAB[iy] as usize) & 0xff; - - if x != 0 && y != 0 { - PTAB[(lx + ly) % 255] - } else { - 0 - } -} - -fn add(x: u8,y: u8) -> u8 { - x^y -} - -fn inv(x: u8) -> u8 { - let ix = (x as usize) & 0xff; - let lx = (LTAB[ix] as usize) & 0xff; - PTAB[255-lx] -} - -/* Lagrange interpolation */ -fn interpolate(n: usize, x: &[u8], y: &[u8]) -> u8 { - let mut yp=0 as u8; - for i in 0..n { - let mut p=1 as u8; - for j in 0..n { - if i!=j { - p=mul(p,mul(x[j],inv(add(x[i],x[j])))); - } - } - yp=add(yp,mul(p,y[i])); - } - yp -} - -impl<'a> SHARE<'a> { - -/* Return a share of M */ -/* input id - Unique share ID */ -/* input nsr - Number of shares required for recovery */ -/* input Message M to be shared */ -/* input Random number generator rng to be used */ -/* return share structure */ -// must bind lifetime of the byte array stored by structure, to lifetime of s - pub fn new(ident: usize,numshare: usize,s: &'a mut [u8],m: &[u8], rng: &mut RAND) -> SHARE<'a> { - if ident<1 || ident>=256 || numshare<2 || numshare>=256 { - return SHARE{id:0,nsr:0,b:s}; - } - let len=m.len(); - for j in 0..len { - let mut x=ident as u8; - s[j]=m[j]; - for _ in 1..numshare { - s[j]=add(s[j],mul(rng.getbyte(),x)); - x=mul(x,ident as u8); - } - } - SHARE{id: ident as u8,nsr: numshare as u8,b:s} - } -/* recover M from shares */ - pub fn recover(m: &mut [u8],s: &[SHARE]) { - let len=s[0].b.len(); - let nsr=s[0].nsr as usize; - if nsr!=s.len() { - return; - } - for i in 1..nsr { - if s[i].nsr as usize != nsr || s[i].b.len()!=len { - return; - } - } - let mut x: [u8; 256] = [0; 256]; - let mut y: [u8; 256] = [0; 256]; - - for j in 0..len { - for i in 0..nsr { - x[i]=s[i].id; - y[i]=s[i].b[j]; - } - m[j]=interpolate(nsr,&x,&y); - } - } -} - - diff --git a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs b/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs deleted file mode 100644 index e1891b22940f..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/brave-miracl-0.1.2/src/x509.rs +++ /dev/null @@ -1,1285 +0,0 @@ -/* - * Copyright (c) 2012-2020 MIRACL UK Ltd. - * - * This file is part of MIRACL Core - * (see https://github.com/miracl/core). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* CORE X.509 Functions */ - -pub struct PKTYPE { - pub kind: usize, - pub hash: usize, - pub curve: usize, - pub len: usize, -} - -pub struct FDTYPE { - pub index: usize, - pub length: usize, -} - -// Supported Encryption/Signature Methods - -pub const ECC:usize = 1; -pub const RSA:usize = 2; -pub const ECD:usize = 3; // for Ed25519 and Ed448 -pub const PQ:usize = 4; - -// Supported Hash functions - -pub const H256:usize = 2; -pub const H384:usize = 3; -pub const H512:usize = 4; -pub const SHAKE256:usize = 5; - -// Supported Curves - -pub const USE_NIST256:usize = 4; /**< For the NIST 256-bit standard curve - WEIERSTRASS only */ -pub const USE_ED25519:usize = 1; /**< Bernstein's Modulus 2^255-19 - EDWARDS only */ -pub const USE_ED448:usize = 5; -//const USE_BRAINPOOL:usize = 2; /**< For Brainpool 256-bit curve - WEIERSTRASS only */ -//const USE_ANSSI:usize = 3; /**< For French 256-bit standard curve - WEIERSTRASS only */ -pub const USE_NIST384:usize = 10; /**< For the NIST 384-bit standard curve - WEIERSTRASS only */ -pub const USE_NIST521:usize = 12; /**< For the NIST 521-bit standard curve - WEIERSTRASS only */ - -const ANY: u8 = 0x00; -const SEQ: u8 = 0x30; -const OID: u8 = 0x006; -const INT: u8 = 0x02; -const NUL: u8 = 0x05; -//const ZER: u8 = 0x00; -//const UTF: u8 = 0x0C; -const UTC: u8 = 0x17; -const GTM: u8 = 0x18; -//const LOG: u8 = 0x01; -const BIT: u8 = 0x03; -const OCT: u8 = 0x04; -//const STR: u8 = 0x13; -const SET: u8 = 0x31; -//const IA5: u8 = 0x16; -const EXT: u8 = 0xA3; -const DNS: u8 = 0x82; - -// Define some OIDs -// Elliptic Curve with SHA256 - -const ECCSHA256:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02]; -const ECCSHA384:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03]; -const ECCSHA512:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04]; -const ECPK:[u8;7]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01]; -const EDPK25519:[u8;3]=[0x2b, 0x65, 0x70]; -const EDPK448:[u8;3]=[0x2b, 0x65, 0x71]; -const PRIME25519:[u8;9]=[0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01]; -const PRIME256V1:[u8;8]=[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]; -const SECP384R1:[u8;5]=[0x2B, 0x81, 0x04, 0x00, 0x22]; -const SECP521R1:[u8;5]=[0x2B, 0x81, 0x04, 0x00, 0x23]; -const RSAPK:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]; -const RSASHA256:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b]; -const RSASHA384:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0]; -const RSASHA512:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d]; -const DILITHIUM3:[u8;11]=[0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, 0x06, 0x05]; -// Cert details - -pub const CN:[u8;3]=[0x55, 0x04, 0x06]; // countryName -pub const SN:[u8;3]=[0x55, 0x04, 0x08]; // stateName -pub const LN:[u8;3]=[0x55, 0x04, 0x07]; // localName -pub const ON:[u8;3]=[0x55, 0x04, 0x0A]; // orgName -pub const UN:[u8;3]=[0x55, 0x04, 0x0B]; // unitName -pub const MN:[u8;3]=[0x55, 0x04, 0x03]; // myName -pub const EN:[u8;9]=[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01]; // emailName - -// Extensions -pub const AN:[u8;3]=[0x55,0x1D,0x11]; // altName -pub const KU:[u8;3]=[0x55,0x1D,0x0F]; // keyUsage -pub const BC:[u8;3]=[0x55,0x1D,0x13]; // basicConstraints - -fn getalen(tag: u8,b:&[u8],j:usize) -> usize { - let mut k=j; - let mut len:usize; - if tag!=0 && b[k]!=tag { - return 0; - } - k+=1; - if b[k] == 0x81 { - k+=1; - len=b[k] as usize; - } else if b[k]==0x82 { - k+=1; - len=256*(b[k] as usize); k+=1; - len+= b[k] as usize; - } else { - len=b[k] as usize; - if len>127 { - return 0; - } - } - return len; -} - -fn skip(len: usize) -> usize { - if len<128 { - return 2; - } - if len<256 { - return 3; - } - return 4; -} - -fn bround(len:usize) -> usize { - if len%8 == 0 { - return len; - } - return len+(8-len%8); -} - -impl PKTYPE { - pub fn new() -> PKTYPE { - PKTYPE { - kind: 0, - hash: 0, - curve:0, - len:0, - } - } -} - -impl FDTYPE { - pub fn new() -> FDTYPE { - FDTYPE { - index: 0, - length: 0, - } - } -} - -// Input private key in PKCS#8 format -// e.g. openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -// e.g. openssl req -x509 -nodes -days 3650 -newkey ec:<(openssl ecparam -name prime256v1) -keyout key.pem -out ecdsacert.pem -// extract private key from uncompressed key.pem into octet -// For RSA octet = p|q|dp|dq|c where pk->len is multiple of 5 -// For ECC octet = k -pub fn extract_private_key(c: &[u8],pk: &mut [u8]) -> PKTYPE { - let mut soid:[u8;12]=[0;12]; - let mut ret=PKTYPE::new(); - let mut j=0 as usize; - let pklen=pk.len(); - - let mut len=getalen(SEQ,c,j); // Check for expected SEQ clause, and get length - if len == 0 { // if not a SEQ clause, there is a problem, exit - return ret; - } - j+=skip(len); // skip over length to clause contents. - if len+j != c.len() { - return ret; - } - len=getalen(INT,c,j); - if len == 0 { // if not a SEQ clause, there is a problem, exit - return ret; - } - j+=skip(len)+len; - len=getalen(SEQ,c,j); - if len == 0 { // if not a SEQ clause, there is a problem, exit - return ret; - } - j+=skip(len); -// extract OID - len=getalen(OID,c,j); - if len==0 { - return ret; - } - j+=skip(len); - - let mut fin=j+len; - if len>soid.len() { - return ret; - } - let mut slen=0; - while jpklen { - return ret; - } - ret.len=rlen; - for i in 0..rlen-len { - pk[i]=0; - } - for i in rlen-len..rlen { - pk[i]=c[j]; - j+=1; - } - ret.kind = ECD; - ret.curve = USE_ED25519; - } - if EDPK448 == soid[0..slen] { - len=getalen(OCT,c,j); - if len==0 { - return ret; - } - j+=skip(len); - len=getalen(OCT,c,j); - if len==0 { - return ret; - } - j+=skip(len); - let rlen=57; - if rlen>pklen { - return ret; - } - ret.len=rlen; - for i in 0..rlen-len { - pk[i]=0; - } - for i in rlen-len..rlen { - pk[i]=c[j]; - j+=1; - } - ret.kind = ECD; - ret.curve = USE_ED448; - } - if DILITHIUM3 == soid[0..slen] { - len=getalen(OCT,c,j); - if len==0 { - return ret; - } - j+=skip(len); - len=getalen(OCT,c,j); - if len==0 { - return ret; - } - j+=skip(len); - let mut tlen=len; - if tlen>pk.len() { - tlen=pk.len(); - } - - for i in 0..tlen { - pk[i]=c[j]; - j+=1; - } - ret.len=tlen; - ret.kind=PQ; - ret.curve=8*tlen; - } - if ECPK == soid[0..slen] { - len=getalen(OID,c,j); - if len==0 { - return ret; - } - j+=skip(len); - - fin=j+len; - if len>soid.len() { - return ret; - } - slen=0; - while jpklen { - ret.curve=0; - ret.len=0; - return ret; - } - ret.len=rlen; - for i in 0..rlen-len { - pk[i]=0; - } - for i in rlen-len..rlen { - pk[i]=c[j]; - j+=1; - } - } - if RSAPK == soid[0..slen] { - len=getalen(NUL,c,j); - if len!=0 { - return ret; - } - j+=skip(len); - - len=getalen(OCT,c,j); - if len==0 { - return ret; - } - j+=skip(len); - - len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j+=skip(len); - - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len)+len; // jump over version - - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len)+len; // jump over n - - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len)+len; // jump over e - - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len)+len; // jump over d - - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len); // get p - - if c[j]==0 { - j+=1; - len-=1; - } - let mut rlen=bround(len); - - if 5*rlen>pklen { - return ret; - } - - for i in 0..rlen-len { - pk[i]=0; - } - for i in rlen-len..rlen { - pk[i]=c[j]; - j+=1; - } - - let flen=rlen; // should be same length for all - for k in 1..5 { - len=getalen(INT,c,j); - if len==0 { - return ret; - } - j+=skip(len); // get q,dp,dq,c - if c[j]==0 { - j+=1; - len-=1; - } - rlen=bround(len); - if rlen!=flen { - return ret; - } - for i in 0..rlen-len { - pk[i]=0; - } - for i in rlen-len..rlen { - pk[k*flen+i]=c[j]; - j+=1; - } - } - ret.len=5*flen; - ret.kind=RSA; - ret.curve=16*flen; - } - return ret; -} - -// Input signed cert as octet, and extract signature -// Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature -// Note that signature type is not provided here - its the type of the public key that -// is used to verify it that matters, and which determines for example the curve to be used! -pub fn extract_cert_sig(sc: &[u8],sig: &mut [u8]) -> PKTYPE { - let mut soid:[u8;12]=[0;12]; - let mut ret=PKTYPE::new(); - let mut j=0 as usize; - let mut len=getalen(SEQ,sc,j); // Check for expected SEQ clause, and get length - let siglen=sig.len(); - - if len == 0 { // if not a SEQ clause, there is a problem, exit - return ret; - } - j+=skip(len); // skip over length to clause contents. Add len to skip clause - if len+j != sc.len() { - return ret; - } - len=getalen(SEQ,sc,j); - if len==0 { - return ret; - } - j+=skip(len) + len; // jump over cert to signature OID - len=getalen(SEQ,sc,j); - if len==0 { - return ret; - } - j+=skip(len); - let sj=j+len; // Needed to jump over signature OID - -// dive in to extract OID - len=getalen(OID,sc,j); - if len==0 { - return ret; - } - j+=skip(len); - let mut fin=j+len; - if len>soid.len() { - return ret; - } - - let mut slen=0; - while jsiglen { - ret.kind=0; - return ret; - } - ret.len=len; - slen=0; - fin=j+len; - while jsiglen { - ret.kind=0; - return ret; - } - ret.len=2*rlen; - - slen=0; - for _ in 0..ex { - sig[slen]=0; - slen+=1; - } - fin=j+len; - while jsiglen { - ret.kind=0; - ret.curve=0; - return ret; - } - ret.len=rlen; - slen=0; - for _ in 0..ex { - sig[slen]=0; - slen+=1; - } - fin=j+len; - while jsiglen { - ret.kind=0; - ret.curve=0; - return ret; - } - ret.len=len; - slen=0; - fin=j+len; - while j usize { - let mut j:usize=0; - - let mut len=getalen(SEQ,sc,j); - if len==0 { - return 0; - } - j+=skip(len); - - let k=j; - len=getalen(SEQ,sc,j); - if len==0 { - return 0; - } - j+=skip(len); - let fin=j+len; - *ptr=k; - return fin-k; -} - -// Extract certificate from signed cert -pub fn extract_cert(sc: &[u8],cert: &mut [u8]) -> usize { - let mut ptr=0; - let n=find_cert(sc,&mut ptr); - let k=ptr; - let fin=n+k; - if fin-k>cert.len() { - return 0; - } - for i in k..fin { - cert[i-k]=sc[i]; - } - return n; -} - -// extract pointer to ASN.1 raw public Key inside certificate, and return its length; -// let public_key=&c[ptr..ptr+len] -pub fn find_public_key(c: &[u8],ptr: &mut usize) -> usize { - let mut j:usize=0; - let mut len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j+=skip(len); - - if len+j != c.len() { - return 0; - } - - len=getalen(ANY,c,j); - if len==0 { - return 0; - } - j+=skip(len)+len; //jump over version clause - - len=getalen(INT,c,j); - if len>0 { - j+=skip(len)+len; // jump over serial number clause (if there is one) - } - - len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j+=skip(len)+len; // jump over signature algorithm - - len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j += skip(len) + len; // skip issuer - - len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j += skip(len) + len; // skip validity - - len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j += skip(len) + len; // skip subject - - let k=j; - len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j += skip(len); // - - let fin=j+len; - *ptr=k; - return fin-k; -} - -// get Public details from ASN.1 description -pub fn get_public_key(c: &[u8],key: &mut [u8]) -> PKTYPE { - let mut koid:[u8;12]=[0;12]; - let mut ret=PKTYPE::new(); - let mut j=0; - let keylen=key.len(); - - let mut len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j += skip(len); // - - len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j += skip(len); // - -// ** Maybe dive in and check Public Key OIDs here? -// ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC -// rsapublicKey for RSA - - let sj=j+len; - - len=getalen(OID,c,j); - if len==0 { - return ret; - } - j += skip(len); - - let mut fin=j+len; - if len>koid.len() { - return ret; - } - let mut slen=0; - while jkoid.len() { - ret.kind=0; - return ret; - } - slen=0; - while jkeylen { - ret.kind=0; - return ret; - } - ret.len=len; - fin=j+len; - slen=0; - while jkeylen { - ret.kind=0; - return ret; - } - ret.len=len; - fin=j+len; - slen=0; - while j PKTYPE { - let mut ptr=0; - let pklen = find_public_key(c,&mut ptr); // ptr is pointer into certificate, at start of ASN.1 raw public key - let cc=&c[ptr..ptr+pklen]; - return get_public_key(&cc,key); -} - -pub fn find_issuer(c: &[u8]) -> FDTYPE { - let mut j:usize=0; - let mut ret=FDTYPE::new(); - let mut len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j += skip(len); - - if len+j!=c.len() { - return ret; - } - - len=getalen(ANY,c,j); - if len==0 { - return ret; - } - j += skip(len)+len; // jump over version clause - - len=getalen(INT,c,j); - if len>0 { - j+=skip(len)+len; // jump over serial number clause (if there is one) - } - - len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j += skip(len) + len; // jump over signature algorithm - - len=getalen(SEQ,c,j); - ret.index=j; - ret.length=len+skip(len); - - return ret; -} - -pub fn find_validity(c: &[u8]) -> usize { - let pos=find_issuer(c); - let j=pos.index+pos.length; // skip issuer - - //let mut j=find_issuer(c); - //let len=getalen(SEQ,c,j); - //if len==0 { - // return 0; - //} - //j+=skip(len)+len; // skip issuer - return j; -} - -pub fn find_subject(c: &[u8]) -> FDTYPE { - let mut j=find_validity(c); - let mut ret=FDTYPE::new(); - let mut len=getalen(SEQ,c,j); - if len==0 { - return ret; - } - j+=skip(len)+len; // skip validity - - len=getalen(SEQ,c,j); - ret.index=j; - ret.length=len+skip(len); - - return ret; -} - -pub fn self_signed(c: &[u8]) -> bool { - let ksub=find_subject(c); - let kiss=find_issuer(c); - - if ksub.length!=kiss.length { - return false; - } - -// let sublen=getalen(SEQ,c,ksub); -// let isslen=getalen(SEQ,c,kiss); -// if sublen != isslen { -// return false; -// } -// ksub+=skip(sublen); -// kiss+=skip(isslen); - let mut m:u8=0; - for i in 0..ksub.length { - m |= c[i+ksub.index]-c[i+kiss.index]; - } - if m!=0 { - return false; - } - return true; -} - -// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length -// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy -// cert information into it. - -// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field - -pub fn find_entity_property(c: &[u8],soid: &[u8],start: usize) -> FDTYPE { - let mut ret=FDTYPE::new(); - let mut foid:[u8;32]=[0;32]; - let mut j=start; - let tlen=getalen(SEQ,c,j); - if tlen==0 { - return ret; - } - j+=skip(tlen); - let k=j; - while jfoid.len() { - return ret; - } - let mut flen:usize=0; - while j usize { - let mut j=start; - let mut len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j+=skip(len); - - len=getalen(UTC,c,j); - if len==0 { // could be generalised time - len=getalen(GTM,c,j); - if len==0 { - return 0; - } - j += skip(len); - j +=2; // skip century - } else { - j+=skip(len); - } - return j; -} - -pub fn find_expiry_date(c: &[u8],start: usize) -> usize { - let mut j=start; - let mut len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j+=skip(len); - - len=getalen(UTC,c,j); - if len==0 { - len=getalen(GTM,c,j); - if len==0 { - return 0; - } - } - j+=skip(len)+len; - - len=getalen(UTC,c,j); - if len==0 { // could be generalised time - len=getalen(GTM,c,j); - if len==0 { - return 0; - } - j += skip(len); - j +=2; // skip century - } else { - j+=skip(len); - } - return j; -} - -pub fn find_extensions(c: &[u8]) -> usize { - let pos=find_subject(c); - let mut j=pos.index+pos.length; - -// let mut len=getalen(SEQ,c,j); -// if len==0 { -// return 0; -// } -// j+=skip(len)+len; // skip subject - - let len=getalen(SEQ,c,j); - if len==0 { - return 0; - } - j+=skip(len)+len; // skip public key - - if j>=c.len() { - return 0; - } - return j; -} - -pub fn find_extension(c: &[u8],soid: &[u8],start:usize) -> FDTYPE { - let mut ret=FDTYPE::new(); - let mut foid:[u8;32]=[0;32]; - - let mut j=start; - let tlen=getalen(EXT,c,j); - if tlen==0 { - return ret; - } - j+=skip(tlen); - - let tlen=getalen(SEQ,c,j); - if tlen==0 { - return ret; - } - j+=skip(tlen); - - let k=j; - while jfoid.len() { - return ret; - } - let mut flen:usize=0; - while j bool { - if start==0 { - return false; - } - let mut j=start; - let mut tlen=getalen(OCT,c,j); - if tlen==0 { - return false; - } - j+=skip(tlen); - - tlen=getalen(SEQ,c,j); - if tlen==0 { - return false; - } - j+=skip(tlen); - let k=j; - while j Date: Tue, 2 Jul 2024 13:59:11 -0700 Subject: [PATCH 31/36] Move anonymous-credentials from third_party to web_discovery component --- components/web_discovery/browser/BUILD.gn | 2 +- .../browser/anonymous_credentials/rs/BUILD.gn | 21 - .../anonymous_credentials/rs/Cargo.lock | 199 ---------- .../anonymous_credentials/rs/Cargo.toml | 13 - .../anonymous_credentials/rs/src/lib.rs | 117 ------ .../browser/credential_manager.cc | 2 +- .../browser/credential_manager.h | 2 +- .../rust/anonymous_credentials/v0_1/BUILD.gn | 44 --- .../rust/chromium_crates_io/gnrt_config.toml | 3 - .../.cargo-checksum.json | 1 - .../.cargo_vcs_info.json | 6 - .../anonymous-credentials-0.1.4/.gitignore | 2 - .../anonymous-credentials-0.1.4/Cargo.toml | 42 -- .../Cargo.toml.orig | 19 - .../anonymous-credentials-0.1.4/LICENSE | 373 ------------------ .../anonymous-credentials-0.1.4/README.md | 11 - .../anonymous-credentials-0.1.4/src/data.rs | 256 ------------ .../anonymous-credentials-0.1.4/src/join.rs | 180 --------- .../anonymous-credentials-0.1.4/src/lib.rs | 244 ------------ .../anonymous-credentials-0.1.4/src/sign.rs | 68 ---- .../anonymous-credentials-0.1.4/src/util.rs | 85 ---- 21 files changed, 3 insertions(+), 1687 deletions(-) delete mode 100644 components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn delete mode 100644 components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock delete mode 100644 components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml delete mode 100644 components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs delete mode 100644 third_party/rust/anonymous_credentials/v0_1/BUILD.gn delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs delete mode 100644 third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 17ea3538b7eb..50d24344e7eb 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -48,7 +48,7 @@ static_library("browser") { "web_discovery_tab_helper.h", ] deps = [ - "anonymous_credentials/rs:rust_lib", + "anonymous_credentials/rs/cxx:rust_lib", "document_extractor/rs:rust_lib", "//base", "//brave/brave_domains", diff --git a/components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn b/components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn deleted file mode 100644 index 2ffc161db1be..000000000000 --- a/components/web_discovery/browser/anonymous_credentials/rs/BUILD.gn +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2024 The Brave Authors. All rights reserved. -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at https://mozilla.org/MPL/2.0/. - -import("//build/rust/rust_static_library.gni") - -rust_static_library("rust_lib") { - crate_name = "anonymous_credentials_cxx" - crate_root = "src/lib.rs" - allow_unsafe = true - - edition = "2021" - sources = [ "src/lib.rs" ] - - visibility = [ "//brave/components/web_discovery/browser:*" ] - - cxx_bindings = [ "src/lib.rs" ] - - deps = [ "//brave/third_party/rust/anonymous_credentials/v0_1:lib" ] -} diff --git a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock deleted file mode 100644 index cefc9fa91611..000000000000 --- a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.lock +++ /dev/null @@ -1,199 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anonymous-credentials" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92cf8b44719f5d7259b63e8d729b6a1d04ef475984b463048ef3fb14a1f65884" -dependencies = [ - "brave-miracl", - "lazy_static", - "rand", - "thiserror", -] - -[[package]] -name = "anonymous-credentials-cxx" -version = "0.1.0" -dependencies = [ - "anonymous-credentials", - "cxx", -] - -[[package]] -name = "brave-miracl" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1529922eb7ce7b0f2cae0be12f200c17bebd5e0141019be023ddd50a8fd435f4" - -[[package]] -name = "cc" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cxx" -version = "1.0.124" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273dcfd3acd4e1e276af13ed2a43eea7001318823e7a726a6b3ed39b4acc0b82" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.124" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839fcd5e43464614ffaa989eaf1c139ef1f0c51672a1ed08023307fa1b909ccd" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.124" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "link-cplusplus" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" -dependencies = [ - "cc", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "syn" -version = "2.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml b/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml deleted file mode 100644 index 2d8d350f2594..000000000000 --- a/components/web_discovery/browser/anonymous_credentials/rs/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "anonymous-credentials-cxx" -version = "0.1.0" -edition = "2021" -license = "MPL-2.0" - -[dependencies] -anonymous-credentials = "0.1" -cxx = "1" - -[lib] -name = "anonymous_credentials_cxx" -crate-type = ["rlib"] diff --git a/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs b/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs deleted file mode 100644 index a474f63f0816..000000000000 --- a/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (c) 2024 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. */ - -use anonymous_credentials::{ - CredentialBIG, CredentialManager as InternalCredentialManager, GroupPublicKey, JoinResponse, - Result, UserCredentials, -}; - -#[allow(unsafe_op_in_unsafe_fn)] -#[cxx::bridge(namespace = "anonymous_credentials")] -mod ffi { - struct StartJoinResult { - gsk: Vec, - join_request: Vec, - } - struct VecU8Result { - data: Vec, - error_message: String, - } - struct EmptyResult { - error_message: String, - } - extern "Rust" { - type CredentialManager; - fn new_credential_manager() -> Box; - fn new_credential_manager_with_fixed_seed() -> Box; - fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult; - fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result; - fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult; - fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result; - } -} - -use ffi::*; - -#[allow(dead_code)] -struct CredentialManager(InternalCredentialManager); - -fn new_credential_manager() -> Box { - Box::new(CredentialManager(InternalCredentialManager::new())) -} - -fn new_credential_manager_with_fixed_seed() -> Box { - Box::new(CredentialManager(InternalCredentialManager::new_with_seed( - &[0u8; 1], - ))) -} - -impl CredentialManager { - fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { - let result = self.0.start_join(challenge); - StartJoinResult { - gsk: result.gsk.to_bytes().to_vec(), - join_request: result.join_msg.to_bytes().to_vec(), - } - } - - /// Processes response and returns user credentials - fn finish_join(&mut self, public_key: &[u8], gsk: &[u8], join_resp: &[u8]) -> VecU8Result { - || -> Result> { - let public_key = GroupPublicKey::try_from(public_key)?; - let gsk = CredentialBIG::try_from(gsk)?; - let join_resp = JoinResponse::try_from(join_resp)?; - self.0 - .finish_join(&public_key, &gsk, join_resp) - .map(|creds| creds.to_bytes().to_vec()) - }() - .into() - } - - fn set_gsk_and_credentials(&mut self, gsk: &[u8], credentials: &[u8]) -> EmptyResult { - || -> Result<()> { - let gsk = CredentialBIG::try_from(gsk)?; - let credentials = UserCredentials::try_from(credentials)?; - self.0.set_gsk_and_credentials(gsk, credentials); - Ok(()) - }() - .into() - } - - fn sign(&mut self, msg: &[u8], basename: &[u8]) -> VecU8Result { - self.0 - .sign(msg, basename) - .map(|sig| sig.to_bytes().to_vec()) - .into() - } -} - -impl From>> for VecU8Result { - fn from(value: Result>) -> Self { - match value { - Ok(data) => VecU8Result { - data, - error_message: String::new(), - }, - Err(e) => VecU8Result { - data: Vec::new(), - error_message: e.to_string(), - }, - } - } -} - -impl From> for EmptyResult { - fn from(value: Result<()>) -> Self { - match value { - Ok(()) => EmptyResult { - error_message: String::new(), - }, - Err(e) => EmptyResult { - error_message: e.to_string(), - }, - } - } -} diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index 619ab40adbfa..d7ca2b4373b6 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -14,7 +14,7 @@ #include "base/logging.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" -#include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs.h" #include "brave/components/web_discovery/browser/pref_names.h" #include "brave/components/web_discovery/browser/util.h" #include "components/prefs/pref_service.h" diff --git a/components/web_discovery/browser/credential_manager.h b/components/web_discovery/browser/credential_manager.h index 4eb7418484fd..21d9ceb35258 100644 --- a/components/web_discovery/browser/credential_manager.h +++ b/components/web_discovery/browser/credential_manager.h @@ -15,7 +15,7 @@ #include "base/memory/raw_ptr.h" #include "base/task/sequenced_task_runner.h" #include "base/timer/wall_clock_timer.h" -#include "brave/components/web_discovery/browser/anonymous_credentials/rs/src/lib.rs.h" +#include "brave/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs.h" #include "brave/components/web_discovery/browser/credential_signer.h" #include "brave/components/web_discovery/browser/rsa.h" #include "brave/components/web_discovery/browser/server_config_loader.h" diff --git a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn b/third_party/rust/anonymous_credentials/v0_1/BUILD.gn deleted file mode 100644 index 2e45251529ac..000000000000 --- a/third_party/rust/anonymous_credentials/v0_1/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2024 The Brave Authors. All rights reserved. -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at https://mozilla.org/MPL/2.0/. - -# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by -# tools/crates/gnrt. -# Do not edit! - -import("//build/rust/cargo_crate.gni") - -cargo_crate("lib") { - crate_name = "anonymous_credentials" - epoch = "0.1" - crate_type = "rlib" - crate_root = "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs" - sources = [ - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs", - "//brave/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs", - ] - inputs = [] - - build_native_rust_unit_tests = false - edition = "2021" - cargo_pkg_version = "0.1.4" - cargo_pkg_authors = "Darnell Andries " - cargo_pkg_name = "anonymous-credentials" - cargo_pkg_description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" - library_configs -= [ "//build/config/compiler:chromium_code" ] - library_configs += [ "//build/config/compiler:no_chromium_code" ] - executable_configs -= [ "//build/config/compiler:chromium_code" ] - executable_configs += [ "//build/config/compiler:no_chromium_code" ] - proc_macro_configs -= [ "//build/config/compiler:chromium_code" ] - proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] - deps = [ - "//brave/third_party/rust/brave_miracl/v0_1:lib", - "//brave/third_party/rust/lazy_static/v1:lib", - "//brave/third_party/rust/rand/v0_8:lib", - "//brave/third_party/rust/thiserror/v1:lib", - ] -} diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml index b47bfbbbf57e..72fa94df9966 100644 --- a/third_party/rust/chromium_crates_io/gnrt_config.toml +++ b/third_party/rust/chromium_crates_io/gnrt_config.toml @@ -110,9 +110,6 @@ if (target_os == "android" && target_cpu == "arm64") { } ''' } -[crate.anonymous-credentials] -license_files = ['LICENSE'] - [crate.ansi_term] license_files = ['LICENCE'] diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json deleted file mode 100644 index 697c9ce2fbb4..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{}} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json deleted file mode 100644 index db43b7fcd30e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "39c1a940b4ef9cb01c0a21c04a64a581c905426d" - }, - "path_in_vcs": "" -} \ No newline at end of file diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore deleted file mode 100644 index 96ef6c0b944e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Cargo.lock diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml deleted file mode 100644 index 7624650084b5..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -name = "anonymous-credentials" -version = "0.1.4" -authors = ["Darnell Andries "] -description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" -readme = "README.md" -keywords = [ - "daa", - "credentials", - "bn254", -] -categories = ["cryptography"] -license = "MPL-2.0" -repository = "https://github.com/brave-experiments/anonymous-credentials-rs" - -[dependencies.brave-miracl] -version = "0.1" -features = ["std"] - -[dependencies.lazy_static] -version = "1.4" - -[dependencies.rand] -version = "0.8" - -[dependencies.thiserror] -version = "1.0" - -[dev-dependencies.hex] -version = "0.4" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig deleted file mode 100644 index d8cf642a798e..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/Cargo.toml.orig +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "anonymous-credentials" -version = "0.1.4" -edition = "2021" -authors = ["Darnell Andries "] -description = "Implementation of Direct Anonymous Attestation for the Web Discovery Project" -license = "MPL-2.0" -repository = "https://github.com/brave-experiments/anonymous-credentials-rs" -keywords = ["daa", "credentials", "bn254"] -categories = ["cryptography"] - -[dependencies] -lazy_static = "1.4" -rand = "0.8" -brave-miracl = { version = "0.1", features = ["std"], path = "../miracl-rs" } -thiserror = "1.0" - -[dev-dependencies] -hex = "0.4" diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE deleted file mode 100644 index d0a1fa1482ee..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at https://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md deleted file mode 100644 index da0fa655154f..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# anonymous-credentials - -[![Crates.io](https://img.shields.io/crates/v/anonymous-credentials?style=for-the-badge)](https://crates.io/crates/anonymous-credentials) - -Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). - -bn254 is the only supported curve for this library. - -## License - -This project is licensed under the terms of the [Mozilla Public License 2.0](LICENSE). diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs deleted file mode 100644 index 9952399319ed..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/data.rs +++ /dev/null @@ -1,256 +0,0 @@ -use brave_miracl::bn254::{ - big::{self, BIG}, - ecp::ECP, - ecp2::ECP2, - fp2::FP2, -}; - -use super::CredentialError; - -pub const BIG_SIZE: usize = big::MODBYTES; -pub const ECP_SIZE: usize = BIG_SIZE * 2 + 1; -pub const ECP2_COMPAT_SIZE: usize = BIG_SIZE * 4; - -pub const ECP_PROOF_SIZE: usize = BIG_SIZE * 2; -pub const JOIN_REQUEST_SIZE: usize = ECP_SIZE + ECP_PROOF_SIZE; -pub const USER_CREDENTIALS_SIZE: usize = ECP_SIZE * 4; -pub const JOIN_RESPONSE_SIZE: usize = USER_CREDENTIALS_SIZE + ECP_PROOF_SIZE; -pub const GROUP_PUBLIC_KEY_SIZE: usize = ECP2_COMPAT_SIZE * 2 + BIG_SIZE * 4; -pub const SIGNATURE_SIZE: usize = ECP_SIZE * 5 + ECP_PROOF_SIZE; - -/// A "join" request to be sent to the issuer. -pub struct JoinRequest { - pub(crate) q: ECP, // G1 ** gsk - - pub(crate) proof: ECPProof, -} - -/// A "join" response from the issuer, to be used -/// to generate DAA credentials. -pub struct JoinResponse { - pub(crate) cred: UserCredentials, - pub(crate) proof: ECPProof, -} - -/// DAA credentials to be used for signing messages. -pub struct UserCredentials { - pub(crate) a: ECP, - pub(crate) b: ECP, - pub(crate) c: ECP, - pub(crate) d: ECP, -} - -/// A DAA signature to be sent to the verifier. -pub struct Signature { - pub(crate) a: ECP, - pub(crate) b: ECP, - pub(crate) c: ECP, - pub(crate) d: ECP, - pub(crate) nym: ECP, - - pub(crate) proof: ECPProof, -} - -/// A group public key published by the issuer. -/// This is required to finish the "join" process -/// and acquire credentials. -pub struct GroupPublicKey { - pub(crate) x: ECP2, // G2 ** x - pub(crate) y: ECP2, // G2 ** y - - // ZK of discrete-log knowledge for X and Y - pub(crate) cx: BIG, - pub(crate) sx: BIG, - pub(crate) cy: BIG, - pub(crate) sy: BIG, -} - -pub(crate) struct ECPProof { - pub c: BIG, - pub s: BIG, -} - -/// Wrapper for a big number. -pub struct CredentialBIG(pub(crate) BIG); - -/// A result of starting the "join" process to acquire credentials. -pub struct StartJoinResult { - /// Private key which should be persisted for finishing the "join" - /// process and future signing requests. - pub gsk: CredentialBIG, - /// The join request to be sent to the issuer. - pub join_msg: JoinRequest, -} - -pub(crate) fn ecp_from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != ECP_SIZE { - return Err(CredentialError::BadECP); - } - Ok(ECP::frombytes(bytes)) -} - -pub(crate) fn ecp2_from_compat_bytes(bytes: &[u8]) -> Result { - if bytes.len() != ECP2_COMPAT_SIZE { - return Err(CredentialError::BadECP2); - } - let x = FP2::new_bigs( - &big_from_bytes(&bytes[..BIG_SIZE])?, - &big_from_bytes(&bytes[BIG_SIZE..BIG_SIZE * 2])?, - ); - let y = FP2::new_bigs( - &big_from_bytes(&bytes[BIG_SIZE * 2..BIG_SIZE * 3])?, - &big_from_bytes(&bytes[BIG_SIZE * 3..BIG_SIZE * 4])?, - ); - Ok(ECP2::new_fp2s(&x, &y)) -} - -pub(crate) fn ecp2_to_compat_bytes(point: &ECP2) -> [u8; ECP2_COMPAT_SIZE] { - let mut result = [0u8; ECP2_COMPAT_SIZE]; - - let mut x = point.getx(); - let mut y = point.gety(); - - x.geta().tobytes(&mut result[..BIG_SIZE]); - x.getb().tobytes(&mut result[BIG_SIZE..BIG_SIZE * 2]); - y.geta().tobytes(&mut result[BIG_SIZE * 2..BIG_SIZE * 3]); - y.getb().tobytes(&mut result[BIG_SIZE * 3..]); - - result -} - -pub(crate) fn big_from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != BIG_SIZE { - return Err(CredentialError::BadBIG); - } - Ok(BIG::frombytes(bytes)) -} - -impl TryFrom<&[u8]> for JoinResponse { - type Error = CredentialError; - - fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != JOIN_RESPONSE_SIZE { - return Err(CredentialError::BadJoinResponse); - } - - Ok(JoinResponse { - cred: bytes[..USER_CREDENTIALS_SIZE].try_into()?, - proof: bytes[USER_CREDENTIALS_SIZE..].try_into()?, - }) - } -} - -impl TryFrom<&[u8]> for UserCredentials { - type Error = CredentialError; - - fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != USER_CREDENTIALS_SIZE { - return Err(CredentialError::BadUserCredentials); - } - Ok(UserCredentials { - a: ecp_from_bytes(&bytes[..ECP_SIZE])?, - b: ecp_from_bytes(&bytes[ECP_SIZE..ECP_SIZE * 2])?, - c: ecp_from_bytes(&bytes[ECP_SIZE * 2..ECP_SIZE * 3])?, - d: ecp_from_bytes(&bytes[ECP_SIZE * 3..ECP_SIZE * 4])?, - }) - } -} - -impl TryFrom<&[u8]> for GroupPublicKey { - type Error = CredentialError; - - fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != GROUP_PUBLIC_KEY_SIZE { - return Err(CredentialError::GroupPublicKeyLength); - } - - let big_start = ECP2_COMPAT_SIZE * 2; - - Ok(GroupPublicKey { - x: ecp2_from_compat_bytes(&bytes[..ECP2_COMPAT_SIZE])?, - y: ecp2_from_compat_bytes(&bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2])?, - cx: big_from_bytes(&bytes[big_start..big_start + BIG_SIZE])?, - sx: big_from_bytes(&bytes[big_start + BIG_SIZE..big_start + BIG_SIZE * 2])?, - cy: big_from_bytes(&bytes[big_start + BIG_SIZE * 2..big_start + BIG_SIZE * 3])?, - sy: big_from_bytes(&bytes[big_start + BIG_SIZE * 3..big_start + BIG_SIZE * 4])?, - }) - } -} - -impl CredentialBIG { - pub fn to_bytes(&self) -> [u8; BIG_SIZE] { - let mut bytes = [0u8; BIG_SIZE]; - self.0.tobytes(&mut bytes); - bytes - } -} - -impl TryFrom<&[u8]> for CredentialBIG { - type Error = CredentialError; - - fn try_from(bytes: &[u8]) -> Result { - Ok(Self(big_from_bytes(bytes)?)) - } -} - -impl JoinRequest { - pub fn to_bytes(&self) -> [u8; JOIN_REQUEST_SIZE] { - let mut result = [0u8; JOIN_REQUEST_SIZE]; - self.q.tobytes(&mut result, false); - result[ECP_SIZE..].copy_from_slice(&self.proof.to_bytes()); - result - } -} - -impl UserCredentials { - pub fn to_bytes(&self) -> [u8; USER_CREDENTIALS_SIZE] { - let mut result = [0u8; USER_CREDENTIALS_SIZE]; - self.a.tobytes(&mut result[..ECP_SIZE], false); - self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); - self.c - .tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); - self.d - .tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); - result - } -} - -impl ECPProof { - pub fn to_bytes(&self) -> [u8; ECP_PROOF_SIZE] { - let mut result = [0u8; ECP_PROOF_SIZE]; - self.c.tobytes(&mut result[..BIG_SIZE]); - self.s.tobytes(&mut result[BIG_SIZE..]); - result - } -} - -impl TryFrom<&[u8]> for ECPProof { - type Error = CredentialError; - - fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != ECP_PROOF_SIZE { - return Err(CredentialError::BadECPProof); - } - - Ok(ECPProof { - c: big_from_bytes(&bytes[0..BIG_SIZE])?, - s: big_from_bytes(&bytes[BIG_SIZE..])?, - }) - } -} - -impl Signature { - pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] { - let mut result = [0u8; SIGNATURE_SIZE]; - self.a.tobytes(&mut result[..ECP_SIZE], false); - self.b.tobytes(&mut result[ECP_SIZE..ECP_SIZE * 2], false); - self.c - .tobytes(&mut result[ECP_SIZE * 2..ECP_SIZE * 3], false); - self.d - .tobytes(&mut result[ECP_SIZE * 3..ECP_SIZE * 4], false); - self.nym - .tobytes(&mut result[ECP_SIZE * 4..ECP_SIZE * 5], false); - result[ECP_SIZE * 5..].copy_from_slice(&self.proof.to_bytes()); - result - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs deleted file mode 100644 index a6eeee031d26..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/join.rs +++ /dev/null @@ -1,180 +0,0 @@ -use brave_miracl::{ - bn254::{ - big::BIG, - ecp::ECP, - ecp2::ECP2, - fp12::FP12, - pair::{g1mul, g2mul}, - }, - rand::RAND, -}; - -use super::data::{ - ecp2_to_compat_bytes, CredentialBIG, ECPProof, GroupPublicKey, JoinRequest, JoinResponse, - StartJoinResult, UserCredentials, BIG_SIZE, ECP2_COMPAT_SIZE, ECP_SIZE, -}; -use super::util::{ - ecp_challenge_equals, hash256, pair_normalized_triple_ate, random_mod_curve_order, - CURVE_ORDER_BIG, G1_ECP, G2_ECP, -}; -use super::{CredentialError, Result}; - -fn ecp_challenge(message: &[u8; BIG_SIZE], y: &ECP, g: &ECP, gr: &ECP) -> BIG { - let mut all_bytes = [0u8; ECP_SIZE * 3 + BIG_SIZE]; - - all_bytes[..BIG_SIZE].copy_from_slice(message); - - y.tobytes(&mut all_bytes[BIG_SIZE..], false); - g.tobytes(&mut all_bytes[ECP_SIZE + BIG_SIZE..], false); - gr.tobytes(&mut all_bytes[ECP_SIZE * 2 + BIG_SIZE..], false); - - let hash = hash256(&all_bytes); - - let mut c = BIG::frombytes(&hash); - c.rmod(&CURVE_ORDER_BIG); - c -} - -fn make_ecp_proof(rng: &mut RAND, y: &ECP, x: &BIG, message: &[u8; BIG_SIZE]) -> ECPProof { - let r = random_mod_curve_order(rng); - - let g = G1_ECP.clone(); - let gr = g1mul(&g, &r); - let c = ecp_challenge(message, y, &g, &gr); - let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); - s.add(&r); - s.rmod(&CURVE_ORDER_BIG); - ECPProof { c, s } -} - -fn verify_ecp_proof_equals(a: &ECP, b: &ECP, y: &ECP, z: &ECP, proof: &ECPProof) -> bool { - let cn = BIG::modneg(&proof.c, &CURVE_ORDER_BIG); - - let mut r#as = g1mul(a, &proof.s); - let yc = g1mul(y, &cn); - let mut bs = g1mul(b, &proof.s); - let zc = g1mul(z, &cn); - - r#as.add(&yc); - bs.add(&zc); - - let cc = ecp_challenge_equals(None, &y, &z, &a, &b, &r#as, &bs); - - BIG::comp(&proof.c, &cc) == 0 -} - -fn verify_aux_fast(a: &ECP, b: &ECP, c: &ECP, d: &ECP, x: &ECP2, y: &ECP2, rng: &mut RAND) -> bool { - if a.is_infinity() { - return false; - } - - let e1 = random_mod_curve_order(rng); - let e2 = random_mod_curve_order(rng); - let ne1 = BIG::modneg(&e1, &CURVE_ORDER_BIG); - let ne2 = BIG::modneg(&e2, &CURVE_ORDER_BIG); - - // AA = e1 * A - let aa = g1mul(a, &e1); - - // BB = -e1 * B - let mut bb = g1mul(b, &ne1); - - // CC = -e2 * C - let mut cc = g1mul(c, &ne2); - - // BB = (-e1 * B) + (-e2 * C) - bb.add(&cc); - - // CC = e2 * (A + D) - cc.copy(a); - cc.add(d); - cc = g1mul(&cc, &e2); - - // w = e(e1·A, Y)·e((-e1·B) + (-e2·C), G2)·e(e2·(A + D), X) - let w = pair_normalized_triple_ate(y, &aa, &G2_ECP, &bb, x, &cc); - - let mut fp12_one = FP12::new(); - fp12_one.one(); - - w.equals(&fp12_one) -} - -pub fn start_join(rng: &mut RAND, challenge: &[u8]) -> StartJoinResult { - let gsk = random_mod_curve_order(rng); - let q = g1mul(&G1_ECP, &gsk); - - let challenge_hash = hash256(challenge); - - let proof = make_ecp_proof(rng, &q, &gsk, &challenge_hash); - - StartJoinResult { - gsk: CredentialBIG(gsk), - join_msg: JoinRequest { q, proof }, - } -} - -pub fn finish_join( - pub_key: &GroupPublicKey, - gsk: &CredentialBIG, - resp: JoinResponse, -) -> Result { - verify_group_public_key(pub_key)?; - - let q = g1mul(&G1_ECP, &gsk.0); - - let mut rng = RAND::new(); - rng.seed(BIG_SIZE, &gsk.to_bytes()); - - if !verify_ecp_proof_equals(&G1_ECP, &q, &resp.cred.b, &resp.cred.d, &resp.proof) { - return Err(CredentialError::JoinResponseValidation); - } - - if !verify_aux_fast( - &resp.cred.a, - &resp.cred.b, - &resp.cred.c, - &resp.cred.d, - &pub_key.x, - &pub_key.y, - &mut rng, - ) { - return Err(CredentialError::JoinResponseValidation); - } - - Ok(resp.cred) -} - -fn ecp2_challenge(y: &ECP2, g: &ECP2, gr: &ECP2) -> BIG { - let mut all_bytes = [0u8; ECP2_COMPAT_SIZE * 3]; - - all_bytes[..ECP2_COMPAT_SIZE].copy_from_slice(&ecp2_to_compat_bytes(y)); - all_bytes[ECP2_COMPAT_SIZE..ECP2_COMPAT_SIZE * 2].copy_from_slice(&ecp2_to_compat_bytes(g)); - all_bytes[ECP2_COMPAT_SIZE * 2..].copy_from_slice(&ecp2_to_compat_bytes(gr)); - - let hash = hash256(&all_bytes); - - let mut c = BIG::frombytes(&hash); - c.rmod(&CURVE_ORDER_BIG); - c -} - -fn verify_ecp2_proof(y: &ECP2, c: &BIG, s: &BIG) -> bool { - let cn = BIG::modneg(c, &CURVE_ORDER_BIG); - - let mut gs = g2mul(&G2_ECP, s); - let yc = g2mul(y, &cn); - - gs.add(&yc); - - let cc = ecp2_challenge(y, &G2_ECP, &gs); - - BIG::comp(c, &cc) == 0 -} - -fn verify_group_public_key(key: &GroupPublicKey) -> Result<()> { - match verify_ecp2_proof(&key.x, &key.cx, &key.sx) && verify_ecp2_proof(&key.y, &key.cy, &key.sy) - { - true => Ok(()), - false => Err(CredentialError::BadGroupPublicKey), - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs deleted file mode 100644 index ac9a3bfb5ad5..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/lib.rs +++ /dev/null @@ -1,244 +0,0 @@ -//! Partial implementation of Direct Anonymous Attestation (DAA) for the Web Discovery Project. -//! Only signer functions are available. Performs the same elliptic curve operations as the [original C library](https://github.com/whotracksme/anonymous-credentials). -//! -//! bn254 is the only supported curve for this library. - -mod data; -mod join; -mod sign; -mod util; - -use brave_miracl::rand::RAND; -use rand::{rngs::OsRng, RngCore}; -use thiserror::Error; - -pub use self::data::*; -use self::join::{finish_join, start_join}; -use self::sign::sign; - -#[derive(Error, Debug)] -pub enum CredentialError { - #[error("ECP should be {0} bytes", ECP_SIZE)] - BadECP, - #[error("ECP2 should be {0} bytes", ECP2_COMPAT_SIZE)] - BadECP2, - #[error("BIG should be {0} bytes", BIG_SIZE)] - BadBIG, - #[error("ECP proof should be {0} bytes", ECP_PROOF_SIZE)] - BadECPProof, - #[error("User credentials should be {0} bytes", USER_CREDENTIALS_SIZE)] - BadUserCredentials, - #[error("Join response should be {0} bytes", JOIN_RESPONSE_SIZE)] - BadJoinResponse, - #[error("Group public key should be {0} bytes", GROUP_PUBLIC_KEY_SIZE)] - GroupPublicKeyLength, - #[error("Join response validation failed")] - JoinResponseValidation, - #[error("Private key and/or credentials not set")] - CredentialsNotSet, - #[error("Group public key verification failed")] - BadGroupPublicKey, -} - -pub type Result = std::result::Result; - -/// Creates and manages Direct Anonymous Attestation credentials -/// using the bn254 curve. -pub struct CredentialManager { - rng: RAND, - gsk_and_credentials: Option<(CredentialBIG, UserCredentials)>, -} - -impl CredentialManager { - /// Creates new manager with random seed. - pub fn new() -> Self { - let mut entropy = [0u8; 128]; - OsRng::default().fill_bytes(&mut entropy); - Self::new_with_seed(&entropy) - } - - /// Creates new manager with fixed seed. Should only be used for testing. - pub fn new_with_seed(entropy: &[u8]) -> Self { - let mut rng = RAND::new(); - - rng.seed(entropy.len(), entropy); - - Self { - rng, - gsk_and_credentials: None, - } - } - - /// Creates a "join" requests to be sent to the credential issuer, - /// for a given challenge. - pub fn start_join(&mut self, challenge: &[u8]) -> StartJoinResult { - start_join(&mut self.rng, challenge) - } - - /// Processes a "join" response from the issuer, and returns anonymous - /// credentials. - pub fn finish_join( - &mut self, - public_key: &GroupPublicKey, - gsk: &CredentialBIG, - join_resp: JoinResponse, - ) -> Result { - finish_join(public_key, gsk, join_resp) - } - - /// Sets the key and credentials to be used for signing requests. - pub fn set_gsk_and_credentials(&mut self, gsk: CredentialBIG, credentials: UserCredentials) { - self.gsk_and_credentials = Some((gsk, credentials)); - } - - /// Signs a message using the pre-set credentials and a given basename. - /// Returns a signature to be sent to the verifier. - pub fn sign(&mut self, msg: &[u8], basename: &[u8]) -> Result { - match &self.gsk_and_credentials { - Some((gsk, credentials)) => Ok(sign(&mut self.rng, gsk, credentials, msg, basename)), - None => Err(CredentialError::CredentialsNotSet), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use lazy_static::lazy_static; - - lazy_static! { - static ref EXPECTED_GSK: Vec = - hex::decode("0198c86f99ede0ca2ed30b8e4ae6cac831c9b398445422a41d95abb4d3f03499") - .unwrap(); - static ref GROUP_PUB_KEY: Vec = hex::decode( - "0477ce930400ab04a6e1caa46601dbd1b1ba5d24f0577834a960285a0512e7ed\ - 0174121707ea5d80e083d2e992236864608998a4d08cb3a41dde1fc6b7eaad5b2\ - 125310b44ca712bf63f62c39cb44917de0772fefd876e170729428142c21d4f17\ - 9f72fcdc1c1ff5f13e272449ac9ff01a74e95bb011045b12bdac942b46168d051\ - 1ecbb4651d9ddd6491437a8d6b6e6e6877038ea4317a5de863e237ff6472014d2\ - 2c88863b6d8de3eb1b73bb46ab12553c2765bcde905487c518936887ba831dc42\ - ca4862bf60b7cccf08ae579f14699fcff5ec8366af5562a2117095dc066105c17\ - 714dadae0b2110b91d0f19f062e9ab410f59e4515cb027e268435502cf12d4a2d\ - de1c5b711619507485e54e6e6bb1b279e7f42067c47b124e7b1e044de0345f28c\ - ea642eef79e0da60dad085b9bec8b73c61a4eee59ec4f024fc83366e1efc63762\ - b2c1c214ad151dd01f1a5f16d5a238187f1afdab361dfea2e0956be24b1bcdba7\ - c9a6a5e0296377bd1cf1b722bc4d375ae8aa4761b7aac5a50e9871" - ) - .unwrap(); - static ref EXPECTED_CREDENTIALS: Vec = hex::decode( - "04246220e5a9d48d359178c9e0994cc10f7288b50\ - cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ - bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ - 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ - 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ - 9939ec717f4f39e114337878f03c9066afc2250332\ - 76f162b4904248822cb548ccb8167480e23f019813\ - 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ - dd7c9f0006eab2576635a36af81e0f781437c4ee35\ - b8672511089830401074ad73c4e9e9aed541bdc5a2\ - df2ee815a3ac4f6297b73da35db2a646e19720475c\ - fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ - bd494be6a551768c8", - ) - .unwrap(); - } - - const CHALLENGE: &[u8] = b"challenge"; - - fn manager_with_fixed_seed() -> CredentialManager { - let entropy = [0u8; 1]; - CredentialManager::new_with_seed(&entropy) - } - - #[test] - fn test_gsk_and_join_msg() { - let mut cm = manager_with_fixed_seed(); - let result = cm.start_join(CHALLENGE); - - let expected_join_msg = hex::decode( - "04185d9e3a0f0e590928568a951a70749c5f3e\ - 969b3c335f109f0e95f4c0cbabe70ddd27e6751\ - df37fa70b906d3d246b388a2a9fb67c3972ea1b\ - 822dc80653454e0de86a209418b4953191caa980\ - 462463ec21b07da451e7becc2d7917ef34f5150c\ - 1c0a4187182af0a43a28868c7b17b2c73704bc26\ - 8071b414d99f48999014b2", - ) - .unwrap(); - - assert_eq!(result.gsk.to_bytes().as_slice(), EXPECTED_GSK.as_slice()); - assert_eq!(result.join_msg.to_bytes().as_slice(), &expected_join_msg); - } - - #[test] - fn test_finish_join_credentials() { - let mut cm = manager_with_fixed_seed(); - - let group_pub_key: GroupPublicKey = GROUP_PUB_KEY.as_slice().try_into().unwrap(); - let gsk: CredentialBIG = EXPECTED_GSK.as_slice().try_into().unwrap(); - let join_response: JoinResponse = hex::decode( - "04246220e5a9d48d359178c9e0994cc10f7288b50\ - cd059c24c5a26fc5919682e8017b66ca6185d62bf2\ - bed7cf02503157ab93ff79d8d34ab3c48669954b7e\ - 2b69c041d98fde59abcd8c0f22790e8d40e253c124\ - 0f3697c161d18a9d04ca24ba2b01f0d100b28b3d52\ - 9939ec717f4f39e114337878f03c9066afc2250332\ - 76f162b4904248822cb548ccb8167480e23f019813\ - 4d1547b005ac84c2a7101a4d39c924ee50298022d7\ - dd7c9f0006eab2576635a36af81e0f781437c4ee35\ - b8672511089830401074ad73c4e9e9aed541bdc5a2\ - df2ee815a3ac4f6297b73da35db2a646e19720475c\ - fe50eb2465833b50758f6c8f09fdf645643a4b3ef5\ - bd494be6a551768c81677932196184249f179d319f\ - eba43b32da42501daa355d3cde30615a08ac687188\ - a8c6e3b8a330f76c233e900acd6ef31c50796b9192\ - 9cfc16b4fcad40b5309", - ) - .unwrap() - .as_slice() - .try_into() - .unwrap(); - - let credentials = cm - .finish_join(&group_pub_key, &gsk, join_response) - .unwrap() - .to_bytes(); - - assert_eq!(credentials.as_slice(), EXPECTED_CREDENTIALS.as_slice()); - } - - #[test] - fn test_signature() { - let mut cm = manager_with_fixed_seed(); - - let gsk = EXPECTED_GSK.as_slice().try_into().unwrap(); - let credentials = EXPECTED_CREDENTIALS.as_slice().try_into().unwrap(); - cm.set_gsk_and_credentials(gsk, credentials); - - let expected_signature = hex::decode( - "0406cb022fcc3dcaef1e4c62dad349bfd263581126c\ - f17b293d1a41e4d96f840da00ad85e4a97aad1247a19\ - a425da6f96978fdac180136f0f486bad0fce0a9ada20\ - 401074ad73c4e9e9aed541bdc5a2df2ee815a3ac4f62\ - 97b73da35db2a646e19720475cfe50eb2465833b5075\ - 8f6c8f09fdf645643a4b3ef5bd494be6a551768c8042\ - 4a006154937bcd3b8f94f12a4672d9a9411928846adc\ - 9132737600089a65915121160cbd4e417435e4acfe66\ - 57840c50584bc8dca420544879fe7fe9c03bc0f0418e\ - e65a71c262c5301d782b20e7f3f252e938282b98a2f8\ - 6a7447e2aa424005819835a0a954d4f6dc53ae4c8bad\ - 2d192a70fcb8883403f69989e43ff66caad0104208cd\ - 8eb5e25486eb754e44f4e2f3b6f5153f5aa73d7eab8c\ - 2f5c867a157276b0463ced7f409f86ef91a4548cf4bb\ - 519392cd657505475e585a3ea0348b6266b1fd3d4ab1\ - 253392386bf2f08afe36072abe575e07865272c3014a\ - b067f5051181fe574571f34d278e2c9359294ca44aa3\ - 3568c546082e4e8d921541e5ccc6c81", - ) - .unwrap(); - - let signature_bytes = cm.sign(b"message", b"basename").unwrap().to_bytes(); - - assert_eq!(signature_bytes, expected_signature.as_slice()); - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs deleted file mode 100644 index 1ee21cf091cc..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/sign.rs +++ /dev/null @@ -1,68 +0,0 @@ -use brave_miracl::{ - bn254::{big::BIG, ecp::ECP, pair::g1mul}, - rand::RAND, -}; - -use super::{ - data::{CredentialBIG, ECPProof, Signature, UserCredentials, BIG_SIZE}, - util::{ecp_challenge_equals, hash256, random_mod_curve_order, CURVE_ORDER_BIG}, -}; - -fn make_ecp_proof_equals( - rng: &mut RAND, - message: &[u8; BIG_SIZE], - a: &ECP, - b: &ECP, - y: &ECP, - z: &ECP, - x: &BIG, -) -> ECPProof { - let r = random_mod_curve_order(rng); - - let ar = g1mul(&a, &r); - let br = g1mul(&b, &r); - - let c = ecp_challenge_equals(Some(message), y, z, a, b, &ar, &br); - let mut s = BIG::modmul(&c, x, &CURVE_ORDER_BIG); - s.add(&r); - s.rmod(&CURVE_ORDER_BIG); - - ECPProof { c, s } -} - -pub fn sign( - rng: &mut RAND, - gsk: &CredentialBIG, - credentials: &UserCredentials, - msg: &[u8], - bsn: &[u8], -) -> Signature { - // Randomize credentials for signature - let r = random_mod_curve_order(rng); - - let a = g1mul(&credentials.a, &r); - let b = g1mul(&credentials.b, &r); - let c = g1mul(&credentials.c, &r); - let d = g1mul(&credentials.d, &r); - - // Map basename to point in G1 - let bsn_hash = hash256(bsn); - let bsn_point = ECP::mapit(&bsn_hash); - let nym = g1mul(&bsn_point, &gsk.0); - - // Compute H(H(msg) || H(bsn)) to be used in proof of equality - let mut msg_bsn_hash_data = [0u8; BIG_SIZE * 2]; - msg_bsn_hash_data[..BIG_SIZE].copy_from_slice(&hash256(msg)); - msg_bsn_hash_data[BIG_SIZE..].copy_from_slice(&hash256(bsn)); - let msg_bsn_hash = hash256(&msg_bsn_hash_data); - - let proof = make_ecp_proof_equals(rng, &msg_bsn_hash, &b, &bsn_point, &d, &nym, &gsk.0); - Signature { - a, - b, - c, - d, - nym, - proof, - } -} diff --git a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs b/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs deleted file mode 100644 index 6a68c682edee..000000000000 --- a/third_party/rust/chromium_crates_io/vendor/anonymous-credentials-0.1.4/src/util.rs +++ /dev/null @@ -1,85 +0,0 @@ -use brave_miracl::{ - bn254::{ - big::BIG, - ecp::ECP, - ecp2::ECP2, - fp12::FP12, - fp2::FP2, - pair::{another, fexp, initmp, miller}, - rom::{CURVE_GX, CURVE_GY, CURVE_ORDER, CURVE_PXA, CURVE_PXB, CURVE_PYA, CURVE_PYB}, - }, - hash256::HASH256, - rand::RAND, -}; -use lazy_static::lazy_static; - -use super::data::{BIG_SIZE, ECP_SIZE}; - -lazy_static! { - pub static ref G1_ECP: ECP = { - let gx = BIG::new_ints(&CURVE_GX); - let gy = BIG::new_ints(&CURVE_GY); - ECP::new_bigs(&gx, &gy) - }; - pub static ref G2_ECP: ECP2 = { - let pxa = BIG::new_ints(&CURVE_PXA); - let pxb = BIG::new_ints(&CURVE_PXB); - let pya = BIG::new_ints(&CURVE_PYA); - let pyb = BIG::new_ints(&CURVE_PYB); - let wx = FP2::new_bigs(&pxa, &pxb); - let wy = FP2::new_bigs(&pya, &pyb); - ECP2::new_fp2s(&wx, &wy) - }; - pub static ref CURVE_ORDER_BIG: BIG = BIG::new_ints(&CURVE_ORDER); -} - -pub fn random_mod_curve_order(rng: &mut RAND) -> BIG { - BIG::randomnum(&CURVE_ORDER_BIG, rng) -} - -pub fn hash256(data: &[u8]) -> [u8; 32] { - let mut hash = HASH256::new(); - hash.process_array(data); - hash.hash() -} - -pub fn pair_normalized_triple_ate(p: &ECP2, q: &ECP, r: &ECP2, s: &ECP, t: &ECP2, u: &ECP) -> FP12 { - let mut rr = initmp(); - another(&mut rr, p, q); - another(&mut rr, r, s); - another(&mut rr, t, u); - let r = miller(&mut rr); - fexp(&r) -} - -pub fn ecp_challenge_equals( - message: Option<&[u8; BIG_SIZE]>, - y: &ECP, - z: &ECP, - a: &ECP, - b: &ECP, - ar: &ECP, - br: &ECP, -) -> BIG { - let (mut all_bytes, msg_len) = match message { - Some(message) => { - let mut all_bytes = vec![0u8; ECP_SIZE * 6 + BIG_SIZE]; - all_bytes[..BIG_SIZE].copy_from_slice(message); - (all_bytes, message.len()) - } - None => (vec![0u8; ECP_SIZE * 6], 0), - }; - - y.tobytes(&mut all_bytes[msg_len..], false); - z.tobytes(&mut all_bytes[msg_len + ECP_SIZE..], false); - a.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 2..], false); - b.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 3..], false); - ar.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 4..], false); - br.tobytes(&mut all_bytes[msg_len + ECP_SIZE * 5..], false); - - let hash = hash256(&all_bytes); - - let mut c = BIG::frombytes(&hash); - c.rmod(&CURVE_ORDER_BIG); - c -} From af6779c2ae43d8b74a7a9beee8dda9ec6bafe594 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 2 Jul 2024 15:09:03 -0700 Subject: [PATCH 32/36] Add document_extractor license exception --- script/brave_license_helper.py | 1 + 1 file changed, 1 insertion(+) diff --git a/script/brave_license_helper.py b/script/brave_license_helper.py index 312ec5cfce7e..657101931c3f 100644 --- a/script/brave_license_helper.py +++ b/script/brave_license_helper.py @@ -50,6 +50,7 @@ def AddBraveCredits(root, prune_paths, special_cases, prune_dirs, os.path.join('brave', 'third_party', 'rust', 'challenge_bypass_ristretto_cxx'), os.path.join('brave', 'third_party', 'rust', 'constellation_cxx'), + os.path.join('brave', 'third_party', 'rust', 'document_extractor_cxx'), os.path.join('brave', 'third_party', 'rust', 'json_cxx'), os.path.join('brave', 'third_party', 'rust', 'filecoin_cxx'), os.path.join('brave', 'third_party', 'rust', 'skus'), From 0a15ebee22d85c753547b165400a502f35670046 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 2 Jul 2024 16:07:21 -0700 Subject: [PATCH 33/36] Add Web Discovery factory test for OTR profiles --- browser/web_discovery/BUILD.gn | 9 ++++++ .../wdp_service_factory_unittest.cc | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 browser/web_discovery/wdp_service_factory_unittest.cc diff --git a/browser/web_discovery/BUILD.gn b/browser/web_discovery/BUILD.gn index 5d9aaf0de907..77a9cd9de33a 100644 --- a/browser/web_discovery/BUILD.gn +++ b/browser/web_discovery/BUILD.gn @@ -31,6 +31,7 @@ source_set("unit_tests") { testonly = true sources = [ "web_discovery_unittest.cc" ] + deps = [ "//brave/browser/profiles", "//brave/components/constants", @@ -44,6 +45,14 @@ source_set("unit_tests") { "//content/test:test_support", "//testing/gtest", ] + + if (enable_web_discovery_native) { + sources += [ "wdp_service_factory_unittest.cc" ] + deps += [ + ":web_discovery", + "//brave/components/web_discovery/common", + ] + } } } diff --git a/browser/web_discovery/wdp_service_factory_unittest.cc b/browser/web_discovery/wdp_service_factory_unittest.cc new file mode 100644 index 000000000000..00e5a30e55f3 --- /dev/null +++ b/browser/web_discovery/wdp_service_factory_unittest.cc @@ -0,0 +1,32 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/web_discovery/wdp_service_factory.h" + +#include "base/test/scoped_feature_list.h" +#include "brave/components/web_discovery/common/features.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_discovery { + +TEST(WDPServiceFactoryTest, PrivateNotCreated) { + content::BrowserTaskEnvironment task_environment; + base::test::ScopedFeatureList scoped_features(features::kWebDiscoveryNative); + auto* browser_process = TestingBrowserProcess::GetGlobal(); + TestingProfileManager profile_manager(browser_process); + ASSERT_TRUE(profile_manager.SetUp()); + + auto* profile = profile_manager.CreateTestingProfile("test"); + + EXPECT_TRUE(WDPServiceFactory::GetForBrowserContext(profile)); + EXPECT_FALSE( + WDPServiceFactory::GetForBrowserContext(profile->GetOffTheRecordProfile( + Profile::OTRProfileID::CreateUniqueForTesting(), true))); +} + +} // namespace web_discovery From a81304d9844980832ba873fef897dcff8c313b60 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 2 Jul 2024 16:27:32 -0700 Subject: [PATCH 34/36] Fix WebDiscovery Windows FilePath append --- .../web_discovery/browser/content_scraper_browsertest.cc | 4 ++-- .../web_discovery/browser/credential_manager_unittest.cc | 3 ++- components/web_discovery/browser/server_config_loader.cc | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc index 88b1261fcd9d..5d76e7a9ee77 100644 --- a/components/web_discovery/browser/content_scraper_browsertest.cc +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -50,8 +50,8 @@ class WebDiscoveryContentScraperTest : public PlatformBrowserTest { InitScraper(); run_loop_ = std::make_unique(); - ASSERT_TRUE( - base::ReadFileToString(data_path.Append("page.html"), &page_content_)); + ASSERT_TRUE(base::ReadFileToString(data_path.AppendASCII("page.html"), + &page_content_)); } protected: diff --git a/components/web_discovery/browser/credential_manager_unittest.cc b/components/web_discovery/browser/credential_manager_unittest.cc index 9ed1e461eee2..81ad1c85e34a 100644 --- a/components/web_discovery/browser/credential_manager_unittest.cc +++ b/components/web_discovery/browser/credential_manager_unittest.cc @@ -48,7 +48,8 @@ class WebDiscoveryCredentialManagerTest : public testing::Test { base::PathService::CheckedGet(brave::DIR_TEST_DATA); std::string test_data_json; ASSERT_TRUE(base::ReadFileToString( - data_path.Append("web_discovery/credential_keys_and_responses.json"), + data_path.AppendASCII( + "web_discovery/credential_keys_and_responses.json"), &test_data_json)); auto test_data_value = base::JSONReader::Read(test_data_json); ASSERT_TRUE(test_data_value); diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 403d0b9216de..39fb722ea6dc 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -170,7 +170,7 @@ ServerConfigLoader::ServerConfigLoader( quorum_config_url_ = GURL(GetQuorumHost() + kQuorumConfigPath); patterns_url_ = GetPatternsEndpoint(); - patterns_path_ = user_data_dir.Append(kPatternsFilename); + patterns_path_ = user_data_dir.AppendASCII(kPatternsFilename); } ServerConfigLoader::~ServerConfigLoader() = default; From fad93bf3d2ad920053b64af8402c8156d1b520e9 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 3 Jul 2024 14:45:04 -0700 Subject: [PATCH 35/36] Fix Web Discovery Android test --- browser/sources.gni | 1 - components/web_discovery/browser/BUILD.gn | 6 +-- .../browser/content_scraper_browsertest.cc | 40 +++++++++++++++---- test/BUILD.gn | 1 - 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/browser/sources.gni b/browser/sources.gni index 29f317d87e78..92dc904384de 100644 --- a/browser/sources.gni +++ b/browser/sources.gni @@ -205,7 +205,6 @@ brave_chrome_browser_deps = [ "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/version_info", - "//brave/components/web_discovery/browser", "//brave/components/web_discovery/common", "//brave/components/web_discovery/common/buildflags", "//brave/components/webcompat:core", diff --git a/components/web_discovery/browser/BUILD.gn b/components/web_discovery/browser/BUILD.gn index 50d24344e7eb..ab2c6b354eb5 100644 --- a/components/web_discovery/browser/BUILD.gn +++ b/components/web_discovery/browser/BUILD.gn @@ -103,15 +103,11 @@ source_set("browser_tests") { "//brave/components/constants", "//brave/components/web_discovery/common", "//brave/components/web_discovery/common:mojom", + "//chrome/test:test_support", "//content/test:test_support", "//net:test_support", "//services/service_manager/public/cpp", "//testing/gtest", ] - if (!is_android) { - deps += [ "//chrome/test:test_support_ui" ] - } else { - deps += [ "//chrome/test:test_support_ui_android" ] - } defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] } diff --git a/components/web_discovery/browser/content_scraper_browsertest.cc b/components/web_discovery/browser/content_scraper_browsertest.cc index 5d76e7a9ee77..2597918e8f9b 100644 --- a/components/web_discovery/browser/content_scraper_browsertest.cc +++ b/components/web_discovery/browser/content_scraper_browsertest.cc @@ -12,13 +12,18 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" #include "brave/components/constants/brave_paths.h" #include "brave/components/web_discovery/browser/patterns.h" #include "brave/components/web_discovery/browser/server_config_loader.h" #include "brave/components/web_discovery/common/features.h" #include "brave/components/web_discovery/common/web_discovery.mojom.h" -#include "chrome/test/base/ui_test_utils.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_base.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,16 +41,18 @@ class WebDiscoveryContentScraperTest : public PlatformBrowserTest { public: WebDiscoveryContentScraperTest() : scoped_features_(features::kWebDiscoveryNative) {} + + // PlatformBrowserTest: void SetUpOnMainThread() override { - InProcessBrowserTest::SetUpOnMainThread(); + PlatformBrowserTest::SetUpOnMainThread(); base::FilePath data_path = base::PathService::CheckedGet(brave::DIR_TEST_DATA); data_path = data_path.AppendASCII("web_discovery"); host_resolver()->AddRule("*", "127.0.0.1"); - auto& test_server = embedded_https_test_server(); - test_server.ServeFilesFromDirectory(data_path); - ASSERT_TRUE(test_server.Start()); + test_server_.ServeFilesFromDirectory(data_path); + mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK); + ASSERT_TRUE(test_server_.Start()); InitScraper(); run_loop_ = std::make_unique(); @@ -54,12 +61,29 @@ class WebDiscoveryContentScraperTest : public PlatformBrowserTest { &page_content_)); } + void SetUpCommandLine(base::CommandLine* command_line) override { + PlatformBrowserTest::SetUpCommandLine(command_line); + mock_cert_verifier_.SetUpCommandLine(command_line); + } + + void SetUpInProcessBrowserTestFixture() override { + PlatformBrowserTest::SetUpInProcessBrowserTestFixture(); + mock_cert_verifier_.SetUpInProcessBrowserTestFixture(); + } + + void TearDownInProcessBrowserTestFixture() override { + mock_cert_verifier_.TearDownInProcessBrowserTestFixture(); + PlatformBrowserTest::TearDownInProcessBrowserTestFixture(); + } + protected: mojo::Remote LoadTestPageAndGetExtractor() { mojo::Remote remote; - auto url = embedded_https_test_server().GetURL("example.com", "/page.html"); - auto* render_frame_host = ui_test_utils::NavigateToURL(browser(), url); + auto url = test_server_.GetURL("example.com", "/page.html"); + auto* contents = chrome_test_utils::GetActiveWebContents(this); + EXPECT_TRUE(content::NavigateToURL(contents, url)); + auto* render_frame_host = contents->GetPrimaryMainFrame(); if (render_frame_host) { render_frame_host->GetRemoteInterfaces()->GetInterface( @@ -148,6 +172,8 @@ class WebDiscoveryContentScraperTest : public PlatformBrowserTest { ®ex_util_); } + content::ContentMockCertVerifier mock_cert_verifier_; + net::EmbeddedTestServer test_server_{net::EmbeddedTestServer::TYPE_HTTPS}; base::test::ScopedFeatureList scoped_features_; RegexUtil regex_util_; std::unique_ptr server_config_loader_; diff --git a/test/BUILD.gn b/test/BUILD.gn index f095441d66f5..2290534c2db1 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -928,7 +928,6 @@ test("brave_browser_tests") { "//brave/components/speedreader/common/buildflags", "//brave/components/tor/buildflags", "//brave/components/url_sanitizer/browser", - "//brave/components/web_discovery/browser:browser_tests", "//brave/components/webcompat:core", "//brave/renderer/skus:browser_tests", "//brave/renderer/test:browser_tests", From 072fdfc3176b60fd71cedf9c05ed83a3420e7415 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Wed, 3 Jul 2024 19:59:51 -0700 Subject: [PATCH 36/36] Fix anonymous-credentials calls after cxx api change, misc feedback changes --- .../browser/credential_manager.cc | 37 +++++++++++++++---- .../browser/document_extractor/rs/src/lib.rs | 1 - .../web_discovery/browser/double_fetcher.cc | 2 +- components/web_discovery/browser/pref_names.h | 6 +++ .../browser/server_config_loader.cc | 6 +-- .../web_discovery/browser/wdp_service.cc | 9 +++++ 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/components/web_discovery/browser/credential_manager.cc b/components/web_discovery/browser/credential_manager.cc index d7ca2b4373b6..e4877039237c 100644 --- a/components/web_discovery/browser/credential_manager.cc +++ b/components/web_discovery/browser/credential_manager.cc @@ -87,10 +87,25 @@ std::optional FinishJoin( std::vector group_pub_key, std::vector gsk, std::vector join_resp_bytes) { - auto finish_res = anonymous_credential_manager->finish_join( - rust::Slice(group_pub_key.data(), group_pub_key.size()), - rust::Slice(gsk.data(), gsk.size()), + auto pub_key_result = anonymous_credentials::load_group_public_key( + rust::Slice(group_pub_key.data(), group_pub_key.size())); + auto gsk_result = anonymous_credentials::load_credential_big( + rust::Slice(gsk.data(), gsk.size())); + auto join_resp_result = anonymous_credentials::load_join_response( rust::Slice(join_resp_bytes.data(), join_resp_bytes.size())); + if (!pub_key_result.error_message.empty() || + !gsk_result.error_message.empty() || + !join_resp_result.error_message.empty()) { + VLOG(1) << "Failed to finish credential join due to deserialization error " + "with group pub key, gsk, or join response: " + << pub_key_result.error_message.c_str() + << gsk_result.error_message.c_str() + << join_resp_result.error_message.c_str(); + return std::nullopt; + } + auto finish_res = anonymous_credential_manager->finish_join( + *pub_key_result.value, *gsk_result.value, + std::move(join_resp_result.value)); if (!finish_res.error_message.empty()) { VLOG(1) << "Failed to finish credential join for " << date << ": " << finish_res.error_message.c_str(); @@ -106,16 +121,22 @@ std::optional> PerformSign( std::optional> gsk_bytes, std::optional> credential_bytes) { if (gsk_bytes && credential_bytes) { - auto set_res = anonymous_credential_manager->set_gsk_and_credentials( + auto gsk_result = anonymous_credentials::load_credential_big( rust::Slice(reinterpret_cast(gsk_bytes->data()), - gsk_bytes->size()), + gsk_bytes->size())); + auto credential_result = anonymous_credentials::load_user_credentials( rust::Slice(reinterpret_cast(credential_bytes->data()), credential_bytes->size())); - if (!set_res.error_message.empty()) { - VLOG(1) << "Failed to sign due to credential set failure: " - << set_res.error_message.c_str(); + if (!gsk_result.error_message.empty() || + !credential_result.error_message.empty()) { + VLOG(1) << "Failed to sign due to deserialization error with gsk, or " + "user credential: " + << gsk_result.error_message.c_str() + << credential_result.error_message.c_str(); return std::nullopt; } + anonymous_credential_manager->set_gsk_and_credentials( + std::move(gsk_result.value), std::move(credential_result.value)); } auto sig_res = anonymous_credential_manager->sign( rust::Slice(msg.data(), msg.size()), diff --git a/components/web_discovery/browser/document_extractor/rs/src/lib.rs b/components/web_discovery/browser/document_extractor/rs/src/lib.rs index 17ce268b19e2..4db51614a395 100644 --- a/components/web_discovery/browser/document_extractor/rs/src/lib.rs +++ b/components/web_discovery/browser/document_extractor/rs/src/lib.rs @@ -13,7 +13,6 @@ use kuchikiki::{ traits::TendrilSink, }; -#[allow(unsafe_op_in_unsafe_fn)] #[cxx::bridge(namespace = "rust_document_extractor")] mod ffi { pub struct SelectAttributeRequest { diff --git a/components/web_discovery/browser/double_fetcher.cc b/components/web_discovery/browser/double_fetcher.cc index ab04b56c6e6b..fbf8697b0010 100644 --- a/components/web_discovery/browser/double_fetcher.cc +++ b/components/web_discovery/browser/double_fetcher.cc @@ -34,7 +34,7 @@ constexpr net::NetworkTrafficAnnotationTag kFetchNetworkTrafficAnnotation = semantics { sender: "Brave Web Discovery Double Fetch" description: - "Retrieves a page of interest without session cookies for + "Retrieves a page of interest without cookies for scraping and reporting via Web Discovery." trigger: "Requests are sent minutes after the original diff --git a/components/web_discovery/browser/pref_names.h b/components/web_discovery/browser/pref_names.h index ba9ac515e4a3..5c957a40b6f4 100644 --- a/components/web_discovery/browser/pref_names.h +++ b/components/web_discovery/browser/pref_names.h @@ -11,12 +11,18 @@ namespace web_discovery { // Profile prefs inline constexpr char kWebDiscoveryNativeEnabled[] = "brave.web_discovery.wdp_native_enabled"; + +// The following pref values are used for generating +// anonymous signatures for user submissions. +// Since they are not used for encrypting sensitive data, +// they do not require secure storage. inline constexpr char kCredentialRSAPrivateKey[] = "brave.web_discovery.rsa_priv_key"; inline constexpr char kCredentialRSAPublicKey[] = "brave.web_discovery.rsa_pub_key"; inline constexpr char kAnonymousCredentialsDict[] = "brave.web_discovery.anon_creds"; + inline constexpr char kScheduledDoubleFetches[] = "brave.web_discovery.scheduled_double_fetches"; inline constexpr char kScheduledReports[] = diff --git a/components/web_discovery/browser/server_config_loader.cc b/components/web_discovery/browser/server_config_loader.cc index 39fb722ea6dc..d1e73f8acd8c 100644 --- a/components/web_discovery/browser/server_config_loader.cc +++ b/components/web_discovery/browser/server_config_loader.cc @@ -76,9 +76,9 @@ constexpr char kPatternsFilename[] = "wdp_patterns.json"; constexpr char kOmittedLocationValue[] = "--"; constexpr auto kAllowedReportLocations = base::MakeFixedFlatSet( - {"de", "at", "ch", "es", "us", "fr", "nl", "gb", "it", "be", - "se", "dk", "fi", "cz", "gr", "hu", "ro", "no", "ca", "au", - "ru", "ua", "in", "pl", "jp", "br", "mx", "cn", "ar"}); + {"ar", "at", "au", "be", "br", "ca", "ch", "cn", "cz", "de", + "dk", "es", "fi", "fr", "gb", "gr", "hu", "in", "it", "jp", + "mx", "nl", "no", "pl", "ro", "ru", "se", "ua", "us"}); KeyMap ParseKeys(const base::Value::Dict& encoded_keys) { KeyMap map; diff --git a/components/web_discovery/browser/wdp_service.cc b/components/web_discovery/browser/wdp_service.cc index a5c31e29d303..3df1c42fe1df 100644 --- a/components/web_discovery/browser/wdp_service.cc +++ b/components/web_discovery/browser/wdp_service.cc @@ -109,6 +109,15 @@ void WDPService::Stop() { content_scraper_ = nullptr; server_config_loader_ = nullptr; credential_manager_ = nullptr; + + profile_prefs_->ClearPref(kWebDiscoveryNativeEnabled); + profile_prefs_->ClearPref(kAnonymousCredentialsDict); + profile_prefs_->ClearPref(kCredentialRSAPrivateKey); + profile_prefs_->ClearPref(kCredentialRSAPublicKey); + profile_prefs_->ClearPref(kScheduledDoubleFetches); + profile_prefs_->ClearPref(kScheduledReports); + profile_prefs_->ClearPref(kUsedBasenameCounts); + profile_prefs_->ClearPref(kPageCounts); } void WDPService::OnEnabledChange() {