Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip][demo] uses crypto traits and allows fxa_client to compile to wasm #6159

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 24 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"components/remote_settings",
"components/rc_log",
"components/suggest",
"components/crypto_traits",
"components/support/error",
"components/support/error/tests",
"components/support/find-places-db",
Expand Down Expand Up @@ -61,26 +62,6 @@ exclude = [
"testing/sync-test",
]

# The `default-members` are the things that are built/tested when you run `cargo
# build`, `cargo test` (or most of the cargo commands not provided by a
# third-party `cargo-foo` binary) from a workspace root *without* doing one of:
#
# - Specifying a specific package (e.g. via `-p <package>`, `--manifest-dir
# <path>` ...)
#
# - Passing `--workspace` or `--all`.
#
# - Running the command from within that package (e.g. running `cargo build`
# inside `megazords/full` will build the full megazord, default or not).
#
# We use this to exclude a couple that have a disproportional compile time
# impact to how likely they are to get broken by average changes:
#
# - The megazords just re-export ffi crates, which we aren't excluding, and get
# built freqently enough as part of gradle/xcode's build process.
#
# To be clear: passing the `--all` or `--workspace` arg to cargo will make it
# use the full member set.
default-members = [
"components/as-ohttp-client",
"components/autofill",
Expand All @@ -92,6 +73,7 @@ default-members = [
"components/push",
"components/remote_settings",
"components/rc_log",
"components/crypto_traits",
"components/support/error",
"components/support/error/macros",
"components/support/error/tests",
Expand All @@ -112,13 +94,32 @@ default-members = [
"components/tabs",
"components/viaduct",
"components/webext-storage",
# Disabled for intermittent failures; see SDK-233 and #3909 for details.
# "testing/sync-test",
# Disabled for intermittent failures; see SDK-233 and #3909 for details.
# "testing/sync-test",
"tools/protobuf-gen",
"tools/embedded-uniffi-bindgen",
"examples/*/",
"testing/separated/*/",
]
] # The `default-members` are the things that are built/tested when you run `cargo
# build`, `cargo test` (or most of the cargo commands not provided by a
# third-party `cargo-foo` binary) from a workspace root *without* doing one of:
#
# - Specifying a specific package (e.g. via `-p <package>`, `--manifest-dir
# <path>` ...)
#
# - Passing `--workspace` or `--all`.
#
# - Running the command from within that package (e.g. running `cargo build`
# inside `megazords/full` will build the full megazord, default or not).
#
# We use this to exclude a couple that have a disproportional compile time
# impact to how likely they are to get broken by average changes:
#
# - The megazords just re-export ffi crates, which we aren't excluding, and get
# built freqently enough as part of gradle/xcode's build process.
#
# To be clear: passing the `--all` or `--workspace` arg to cargo will make it
# use the full member set.

[workspace.dependencies]
rusqlite = "0.30.0"
Expand Down
17 changes: 17 additions & 0 deletions components/crypto_traits/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "crypto_traits"
version = "0.1.0"
edition = "2021"
authors = ["Tarik Eshaq <teshaq@mozilla.com>"]
description = "A Collection of crypto traits used in Application Services components"
license = "MPL-2.0"
exclude = []

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
thiserror = "1.0"
ece = { version = "2.3", default-features = false, features = [
"serializable-keys",
] }
hawk = { version = "5", default-features = false }
95 changes: 95 additions & 0 deletions components/crypto_traits/src/aead.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//! Authenticated Encryption with Additional Data (AEAD)
//!
//! AEAD creates a uniform interface for various underlying cryptographic algorithms, and makes it easy to enforce
//! both confidentiality and data integrity in a simple interface.
//!
//! To read more about AEAD, check out [RFC 5116](https://datatracker.ietf.org/doc/html/rfc5116)
//!
//!
//! This module exposes a trait that represents the AEAD interface described in the RFC.

use crate::error;

/// Implementors of this trait implement Authenticated Encryption with Additional Data.
pub trait Aead {
/// [Authenticated Encryption](https://datatracker.ietf.org/doc/html/rfc5116#section-2.1)
///
/// # Arguments
/// - `key`: A secret key, which must be generated in a way that is uniformly random or pseudorandom
/// - `nonce`: An invocation specific nonce, some invocation may not use a nonce
/// - `plaintext`: The data to be encrypted
/// - `associated_data`: The data to be authenticated
///
/// # Returns
/// Returns a [`Vec<u8>`] representing the ciphertext or an error
fn seal(
&self,
algorithm: AeadAlgorithm,
key: &[u8],
nonce: Option<&[u8]>,
plaintext: &[u8],
associated_data: &[u8],
) -> error::Result<Vec<u8>>;

/// [Authenticated Decryption](https://datatracker.ietf.org/doc/html/rfc5116#section-2.2)
///
/// # Arguments
/// - `key`: A secret key, which must be generated in a way that is uniformly random or pseudorandom
/// - `nonce`: An invocation specific nonce, some invocation may not use a nonce
/// - `ciphertext`: The data to be decrypted
/// - `associated_data`: The data to be authenticated
/// # Returns
/// Returns a [`Vec<u8>`] representing the plaintext or an error
fn open(
&self,
algorithm: AeadAlgorithm,
key: &[u8],
nonce: Option<&[u8]>,
ciphertext: &[u8],
associated_data: &[u8],
) -> error::Result<Vec<u8>>;
}

/// An AEAD Algorithm
///
/// The represents the concrete AEAD algorithms
/// ```
pub enum AeadAlgorithm {
/// Represents an AES_128_GCM Aead algorithm as described
/// in [RFC 5516, section 5.1](https://datatracker.ietf.org/doc/html/rfc5116#section-5.1)
Aes128Gcm,
/// Represents an AES_256_GCM Aead algorithm as described
/// in [RFC 5516, section 5.1](https://datatracker.ietf.org/doc/html/rfc5116#section-5.2)
Aes256Gcm,
/// AES-256 in CBC mode with HMAC-SHA256 tags and 128 bit nonces.
/// This is a Sync 1.5 specific encryption scheme, do not use for new
/// applications, there are better options out there nowadays.
/// Important note: The HMAC tag verification should be done against the
/// base64 representation of the ciphertext.
/// More details here: https://mozilla-services.readthedocs.io/en/latest/sync/storageformat5.html#record-encryption
SyncAes256CBC,
}

impl AeadAlgorithm {
pub fn key_len(&self) -> usize {
match self {
Self::Aes128Gcm => 16,
Self::Aes256Gcm => 32,
Self::SyncAes256CBC => 64,
}
}
pub fn nonce_len(&self) -> usize {
match self {
Self::Aes128Gcm => 96 / 8,
Self::Aes256Gcm => 96 / 8,
Self::SyncAes256CBC => 128 / 8,
}
}
pub fn tag_len(&self) -> usize {
match self {
Self::Aes128Gcm => 16,
Self::Aes256Gcm => 16,
Self::SyncAes256CBC => 32,
}
}
}
84 changes: 84 additions & 0 deletions components/crypto_traits/src/agreement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* 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 http://mozilla.org/MPL/2.0/. */

// This file contains code that was copied from the ring crate which is under
// the ISC license, reproduced below:

// Copyright 2015-2017 Brian Smith.

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.

// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use std::fmt::Display;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Curve {
P256,
P384,
}

impl Display for Curve {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Curve::P256 => "P-256",
Curve::P384 => "P-384",
}
)
}
}

/// A key pair for key agreement.
pub struct KeyPair {
private_key: Vec<u8>,
public_key: Vec<u8>,
}

impl KeyPair {
pub fn new(private_key: Vec<u8>, public_key: Vec<u8>) -> Self {
Self {
private_key,
public_key,
}
}
pub fn private_key(&self) -> &[u8] {
&self.private_key
}

pub fn public_key(&self) -> &[u8] {
&self.public_key
}
}

pub trait Agreement {
/// Generate a new key pair for the given algorithm.
fn generate_keypair(&self, curve: Curve) -> std::result::Result<KeyPair, crate::Error>;
/// Generate a key pair from the given coordinates
fn keypair_from_coordinates(
&self,
curve: Curve,
d: &[u8],
x: &[u8],
y: &[u8],
) -> std::result::Result<KeyPair, crate::Error>;
/// Create agreement
fn agree(
&self,
curve: Curve,
key_pair: KeyPair,
peer_public_key: &[u8],
) -> std::result::Result<Vec<u8>, crate::Error>;
}
Loading