summaryrefslogtreecommitdiffstats
path: root/dom/origin-trials/ffi
diff options
context:
space:
mode:
Diffstat (limited to 'dom/origin-trials/ffi')
-rw-r--r--dom/origin-trials/ffi/.gitignore2
-rw-r--r--dom/origin-trials/ffi/Cargo.toml14
-rw-r--r--dom/origin-trials/ffi/cbindgen.toml18
-rw-r--r--dom/origin-trials/ffi/lib.rs150
4 files changed, 184 insertions, 0 deletions
diff --git a/dom/origin-trials/ffi/.gitignore b/dom/origin-trials/ffi/.gitignore
new file mode 100644
index 0000000000..2c96eb1b65
--- /dev/null
+++ b/dom/origin-trials/ffi/.gitignore
@@ -0,0 +1,2 @@
+target/
+Cargo.lock
diff --git a/dom/origin-trials/ffi/Cargo.toml b/dom/origin-trials/ffi/Cargo.toml
new file mode 100644
index 0000000000..710b846176
--- /dev/null
+++ b/dom/origin-trials/ffi/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "origin-trials-ffi"
+version = "0.1.0"
+edition = "2021"
+authors = [
+ "Emilio Cobos Álvarez <emilio@crisal.io>",
+]
+license = "MPL-2.0"
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+origin-trial-token = "0.1"
diff --git a/dom/origin-trials/ffi/cbindgen.toml b/dom/origin-trials/ffi/cbindgen.toml
new file mode 100644
index 0000000000..1b95a60280
--- /dev/null
+++ b/dom/origin-trials/ffi/cbindgen.toml
@@ -0,0 +1,18 @@
+header = """/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_OriginTrials_h
+#error "Don't include this file directly, include mozilla/OriginTrials.h instead"
+#endif
+"""
+include_guard = "mozilla_OriginTrials_ffi_h"
+include_version = true
+language = "C++"
+namespaces = ["mozilla", "origin_trials_ffi"]
+includes = ["mozilla/Assertions.h"]
+
+[enum]
+derive_helper_methods = true
+derive_const_casts = true
+cast_assert_name = "MOZ_DIAGNOSTIC_ASSERT"
diff --git a/dom/origin-trials/ffi/lib.rs b/dom/origin-trials/ffi/lib.rs
new file mode 100644
index 0000000000..1745c9e790
--- /dev/null
+++ b/dom/origin-trials/ffi/lib.rs
@@ -0,0 +1,150 @@
+/* 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 origin_trial_token::{RawToken, Token, TokenValidationError, Usage};
+use std::ffi::c_void;
+
+#[repr(u8)]
+pub enum OriginTrial {
+ // NOTE(emilio): 0 is reserved for WebIDL usage.
+ TestTrial = 1,
+ CoepCredentialless = 2,
+
+ MAX,
+}
+
+impl OriginTrial {
+ fn from_str(s: &str) -> Option<Self> {
+ Some(match s {
+ "TestTrial" => Self::TestTrial,
+ "CoepCredentialless" => Self::CoepCredentialless,
+ _ => return None,
+ })
+ }
+}
+
+#[repr(u8)]
+pub enum OriginTrialResult {
+ Ok { trial: OriginTrial },
+ BufferTooSmall,
+ MismatchedPayloadSize { expected: usize, actual: usize },
+ InvalidSignature,
+ UnknownVersion,
+ UnsupportedThirdPartyToken,
+ UnexpectedUsageInNonThirdPartyToken,
+ MalformedPayload,
+ ExpiredToken,
+ UnknownTrial,
+ OriginMismatch,
+}
+
+impl OriginTrialResult {
+ fn from_error(e: TokenValidationError) -> Self {
+ match e {
+ TokenValidationError::BufferTooSmall => OriginTrialResult::BufferTooSmall,
+ TokenValidationError::MismatchedPayloadSize { expected, actual } => {
+ OriginTrialResult::MismatchedPayloadSize { expected, actual }
+ }
+ TokenValidationError::InvalidSignature => OriginTrialResult::InvalidSignature,
+ TokenValidationError::UnknownVersion => OriginTrialResult::UnknownVersion,
+ TokenValidationError::UnsupportedThirdPartyToken => {
+ OriginTrialResult::UnsupportedThirdPartyToken
+ }
+ TokenValidationError::UnexpectedUsageInNonThirdPartyToken => {
+ OriginTrialResult::UnexpectedUsageInNonThirdPartyToken
+ }
+ TokenValidationError::MalformedPayload(..) => OriginTrialResult::MalformedPayload,
+ }
+ }
+}
+
+/// A struct that allows you to configure how validation on works, and pass
+/// state to the signature verification.
+#[repr(C)]
+pub struct OriginTrialValidationParams {
+ /// Verify a given signature against the signed data.
+ pub verify_signature: extern "C" fn(
+ signature: *const u8,
+ signature_len: usize,
+ data: *const u8,
+ data_len: usize,
+ user_data: *mut c_void,
+ ) -> bool,
+
+ /// Returns whether a given origin, which is passed as the first two
+ /// arguments, and guaranteed to be valid UTF-8, passes the validation for a
+ /// given invocation.
+ pub matches_origin: extern "C" fn(
+ origin: *const u8,
+ len: usize,
+ is_subdomain: bool,
+ is_third_party: bool,
+ is_usage_subset: bool,
+ user_data: *mut c_void,
+ ) -> bool,
+
+ /// A pointer with user-supplied data that will be passed down to the
+ /// other functions in this method.
+ pub user_data: *mut c_void,
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn origin_trials_parse_and_validate_token(
+ bytes: *const u8,
+ len: usize,
+ params: &OriginTrialValidationParams,
+) -> OriginTrialResult {
+ let slice = std::slice::from_raw_parts(bytes, len);
+ let raw_token = match RawToken::from_buffer(slice) {
+ Ok(token) => token,
+ Err(e) => return OriginTrialResult::from_error(e),
+ };
+
+ // Verifying the token is usually more expensive than the early-outs here.
+ let token = match Token::from_raw_token_unverified(raw_token) {
+ Ok(token) => token,
+ Err(e) => return OriginTrialResult::from_error(e),
+ };
+
+ if token.is_expired() {
+ return OriginTrialResult::ExpiredToken;
+ }
+
+ let trial = match OriginTrial::from_str(token.feature()) {
+ Some(t) => t,
+ None => return OriginTrialResult::UnknownTrial,
+ };
+
+ let is_usage_subset = match token.usage {
+ Usage::None => false,
+ Usage::Subset => true,
+ };
+
+ if !(params.matches_origin)(
+ token.origin.as_ptr(),
+ token.origin.len(),
+ token.is_subdomain,
+ token.is_third_party,
+ is_usage_subset,
+ params.user_data,
+ ) {
+ return OriginTrialResult::OriginMismatch;
+ }
+
+ let valid_signature = raw_token.verify(|signature, data| {
+ (params.verify_signature)(
+ signature.as_ptr(),
+ signature.len(),
+ data.as_ptr(),
+ data.len(),
+ params.user_data,
+ )
+ });
+
+ if !valid_signature {
+ return OriginTrialResult::InvalidSignature;
+ }
+
+ OriginTrialResult::Ok { trial }
+}