From 3a89b00a1043fa0df95d651efb1a66c89a1c3f93 Mon Sep 17 00:00:00 2001 From: Darnell Andries Date: Tue, 2 Jul 2024 14:11:55 -0700 Subject: [PATCH] Add anonymous-credentials lib/cxx for Web Discovery --- components/web_discovery/browser/BUILD.gn | 8 + .../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 | 166 ++ .../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 | 293 +++ .../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 ++++++++++++ 60 files changed, 20192 insertions(+) create mode 100644 components/web_discovery/browser/BUILD.gn 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/BUILD.gn b/components/web_discovery/browser/BUILD.gn new file mode 100644 index 000000000000..175ce801e08b --- /dev/null +++ b/components/web_discovery/browser/BUILD.gn @@ -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/. + +static_library("browser") { + deps = [ "anonymous_credentials/rs/cxx:rust_lib" ] +} 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..83a371436ccd --- /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 = { version = "0.1", path = "../lib" } +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..27ee45a287f0 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/cxx/src/lib.rs @@ -0,0 +1,166 @@ +/* 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 as InternalCredentialBIG, CredentialManager as InternalCredentialManager, + GroupPublicKey as InternalGroupPublicKey, JoinResponse as InternalJoinResponse, Result, + UserCredentials as InternalUserCredentials, +}; + +#[cxx::bridge(namespace = "anonymous_credentials")] +mod ffi { + struct StartJoinResult { + gsk: Vec, + join_request: Vec, + } + struct VecU8Result { + data: Vec, + error_message: String, + } + 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(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); + +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: &GroupPublicKey, + gsk: &CredentialBIG, + join_resp: Box, + ) -> VecU8Result { + || -> Result> { + self.0 + .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: 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() + } +} + +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() }, + } + } +} 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..fd87748c6249 --- /dev/null +++ b/components/web_discovery/browser/anonymous_credentials/rs/lib/src/data.rs @@ -0,0 +1,293 @@ +// 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 + } +} + +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(), + } + } +} 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 0de1a8f16aa2..98c665a0e296 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 2a5bccd200cd..e64b6cc803b8 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock @@ -101,6 +101,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" @@ -263,6 +281,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" @@ -384,6 +407,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 007466611429..53401b5471d8 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 +}