Skip to content

Commit

Permalink
stub blindings
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft committed Jul 12, 2024
1 parent 8a6aac8 commit 9cba77b
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 29 deletions.
115 changes: 90 additions & 25 deletions scripts/s2n2rust/s2n2rust/src/refactor/text_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ fn index_structs(_sh: &Shell, c_src: &Path, overrides: &Overrides) -> Result<Str
},
);

modules.insert(
"s2n_blinding_guard".to_string(),
Owner {
path: "utils/s2n_safety".into(),
module: "utils::s2n_safety".into(),
},
);

modules.insert(
"s2n_debug_info".to_string(),
Owner {
Expand Down Expand Up @@ -147,7 +155,10 @@ fn index_structs(_sh: &Shell, c_src: &Path, overrides: &Overrides) -> Result<Str
for line in file.lines() {
let line = line?;

let Some(name) = line.strip_prefix("struct ") else {
let Some(name) = line
.strip_prefix("struct ")
.or_else(|| line.strip_prefix("union "))
else {
continue;
};

Expand Down Expand Up @@ -280,6 +291,8 @@ processors!(
owning_struct: OwningStruct,
preserve_err: PreserveErrMacro,
errno_api: ErrnoApi,
safety_api: SafetyApi,
unnamed_digest: UnnamedDigest,
libc: LibcOverride,
librs: LibRs,
prelude: Prelude,
Expand Down Expand Up @@ -453,40 +466,45 @@ impl OwningStruct {
return ControlFlow::Continue(());
}

let Some(name) = line.strip_prefix("pub struct ") else {
let Some(name) = line
.strip_prefix("pub struct ")
.or_else(|| line.strip_prefix("pub union "))
else {
return ControlFlow::Continue(());
};

let name = name.trim_end_matches(" {").trim_end_matches("<'a>");

if name.starts_with("C2RustUnnamed") {
return ControlFlow::Continue(());
}

let owner = self.config.structs.get(name);

let owns_struct = owner.as_ref().map_or(false, |v| &v.path == &self.file_name);

// if the file doesn't "own" the struct then remove it
if name == "s2n_result" || !owns_struct {
if !name.starts_with("C2RustUnnamed") {
self.pending_use = Some(match (name, owner) {
(name, Some(owner)) => format!("\nuse crate::{}::{name};\n", owner.module),
(
"iovec" | "msghdr" | "cmsghdr" | "timespec" | "stat" | "sockaddr"
| "sockaddr_storage",
None,
) => {
format!("\nuse libc::{name};\n")
}
// TODO figure out where to pull these from
(name @ ("__pthread_rwlock_arch_t" | "FGN_STATE"), None) => {
println!("UNKNOWN IMPORT {name:?}");
"".to_string()
}
(name, None) if name.starts_with("s2n_") => {
println!("NO OWNER {name:?}");
"".to_string()
}
_ => format!("\nuse crate::libcrypto::{name};\n"),
});
}
self.pending_use = Some(match (name, owner) {
(name, Some(owner)) => format!("\nuse crate::{}::{name};\n", owner.module),
(
"iovec" | "msghdr" | "cmsghdr" | "timespec" | "stat" | "sockaddr"
| "sockaddr_storage",
None,
) => {
format!("\nuse libc::{name};\n")
}
// TODO figure out where to pull these from
(name @ ("__pthread_rwlock_arch_t" | "FGN_STATE"), None) => {
println!("UNKNOWN IMPORT {name:?}");
"".to_string()
}
(name, None) if name.starts_with("s2n_") => {
println!("NO OWNER {name:?}");
"".to_string()
}
_ => format!("\nuse crate::libcrypto::{name};\n"),
});
*line = format!("struct __CLEANUP__{name} {{");
}

Expand Down Expand Up @@ -629,7 +647,6 @@ replace!(
]
);

// TODO get the correct version instead
replace!(
ErrnoApi,
[
Expand All @@ -650,6 +667,28 @@ replace!(
]
);

replace!(
SafetyApi,
[
(
"__STUB_ZERO_TO_DISABLE_DEFER_CLEANUP(",
"crate::utils::s2n_safety::disable_defer_cleanup("
),
(
"__STUB_ADD_IS_OVERFLOW_SAFE(",
"crate::utils::s2n_safety::is_overflow_safe(",
),
(
"__STUB_WITH_ERROR_BLINDING(",
"crate::utils::s2n_safety::with_error_blinding(",
),
(
"__STUB_BLINDING_CANCEL(",
"crate::utils::s2n_safety::blinding_cancel(",
),
]
);

/// Removes #[no_mangle] attributes
struct NoMangle {}

Expand Down Expand Up @@ -758,6 +797,32 @@ rewrite!(
"crate::utils::s2n_safety::memmove("
);

replace!(
UnnamedDigest,
[
(
"digest: C2RustUnnamed_0 {",
"digest: crate::crypto::s2n_hash::C2RustUnnamed_1 {"
),
(
"digest: C2RustUnnamed_1 {",
"digest: crate::crypto::s2n_hash::C2RustUnnamed_1 {"
),
(
"digest: C2RustUnnamed_2 {",
"digest: crate::crypto::s2n_hash::C2RustUnnamed_1 {"
),
(
"digest: C2RustUnnamed_8 {",
"digest: crate::crypto::s2n_hash::C2RustUnnamed_1 {"
),
(
"low_level: s2n_hash_low_level_digest {",
"low_level: crate::crypto::s2n_hash::s2n_hash_low_level_digest {"
)
]
);

rewrite!(IgnoreResult, ["__STUB_RESULT_IGNORE(",], "let _ = (");

replace!(
Expand Down
3 changes: 3 additions & 0 deletions scripts/s2n2rust/s2n2rust/src/replace/libc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::ensure_ref;
pub use ::libc::*;

// alias this for now to reduce compilation errors
pub type c_ulong = usize;

#[inline(always)]
pub unsafe fn memset<L>(ptr: *mut c_void, value: c_int, len: L)
where
Expand Down
117 changes: 117 additions & 0 deletions scripts/s2n2rust/s2n2rust/src/s2n_safety.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "error/s2n_errno.h"
#include "utils/s2n_ensure.h"
#include "utils/s2n_result.h"
#include "utils/s2n_safety_macros.h"

/**
* The goal of s2n_safety is to provide helpers to perform common
* checks, which help with code readability.
*/

/**
* Marks a case of a switch statement as able to fall through to the next case
*/
#if defined(S2N_FALL_THROUGH_SUPPORTED)
#define FALL_THROUGH __attribute__((fallthrough))
#else
#define FALL_THROUGH ((void) 0)
#endif

int s2n_in_unit_test_set(bool is_unit);
int s2n_in_integ_test_set(bool is_integ);
bool s2n_in_unit_test();
bool s2n_in_test();

/* Returns 1 if a and b are equal, in constant time */
bool s2n_constant_time_equals(const uint8_t* a, const uint8_t* b, const uint32_t len);

/* Copy src to dst, or don't copy it, in constant time */
int s2n_constant_time_copy_or_dont(uint8_t* dst, const uint8_t* src, uint32_t len, uint8_t dont);

/* If src contains valid PKCS#1 v1.5 padding of exactly expectlen bytes, decode
* it into dst, otherwise leave dst alone, in constant time.
* Always returns zero. */
int s2n_constant_time_pkcs1_unpad_or_dont(uint8_t* dst, const uint8_t* src, uint32_t srclen, uint32_t expectlen);

/**
* Runs _thecleanup function on _thealloc once _thealloc went out of scope
*/
void __STUB_DEFER_CLEANUP(void *ptr, void *cleanup);
/* TODO fix this */
#define DEFER_CLEANUP(_thealloc, _thecleanup) _thealloc;

/**
* Often we want to free memory on an error, but not on a success.
* We do this by declaring a variable with DEFER_CLEANUP, then zeroing
* that variable after success to prevent DEFER_CLEANUP from accessing
* and freeing any memory it allocated.
*
* This pattern is not intuitive, so a named macro makes it more readable.
*/
void __STUB_ZERO_TO_DISABLE_DEFER_CLEANUP(void *ptr);
#define ZERO_TO_DISABLE_DEFER_CLEANUP(_thealloc) __STUB_ZERO_TO_DISABLE_DEFER_CLEANUP((void*)&_thealloc)

struct s2n_blinding_guard {
struct s2n_connection* conn;
};
struct s2n_blinding_guard __STUB_WITH_ERROR_BLINDING(struct s2n_connection* conn);
void __STUB_BLINDING_CANCEL(struct s2n_blinding_guard guard);

#define WITH_ERROR_BLINDING(conn, action) \
do { \
struct s2n_blinding_guard blinding_guard = __STUB_WITH_ERROR_BLINDING(conn); \
action; \
__STUB_BLINDING_CANCEL(blinding_guard); \
} while (0)

/* Creates cleanup function for pointers from function func which accepts a pointer.
* This is useful for DEFER_CLEANUP as it passes &_thealloc into _thecleanup function,
* so if _thealloc is a pointer _thecleanup will receive a pointer to a pointer.*/
#define DEFINE_POINTER_CLEANUP_FUNC(type, func) \
static inline void func##_pointer(type* p) \
{ \
if (p && *p) \
func(*p); \
} \
struct __useless_struct_to_allow_trailing_semicolon__

size_t __STUB_ARRAY_LEN(const void *ptr);
/* TODO fix this */
/*#define s2n_array_len(array) __STUB_ARRAY_LEN((void*)&array)*/
#define s2n_array_len(array) ((array != NULL) ? (sizeof(array) / sizeof(array[0])) : 0)

int s2n_mul_overflow(uint32_t a, uint32_t b, uint32_t* out);

/**
* Rounds "initial" up to a multiple of "alignment", and stores the result in "out".
* Raises an error if overflow would occur.
* NOT CONSTANT TIME.
*/
int s2n_align_to(uint32_t initial, uint32_t alignment, uint32_t* out);
int s2n_add_overflow(uint32_t a, uint32_t b, uint32_t* out);
int s2n_sub_overflow(uint32_t a, uint32_t b, uint32_t* out);

bool __STUB_ADD_IS_OVERFLOW_SAFE(uint64_t a, uint64_t b, uint64_t max);
#define S2N_ADD_IS_OVERFLOW_SAFE(a, b, max) __STUB_ADD_IS_OVERFLOW_SAFE((a), (b), (max))
5 changes: 5 additions & 0 deletions scripts/s2n2rust/s2n2rust/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ pub fn setup_include(sh: &Shell) -> Result<PathBuf> {
include_str!("./s2n_ensure.h").trim_start(),
)?;

write(
utils.join("s2n_safety.h"),
include_str!("./s2n_safety.h").trim_start(),
)?;

write(
utils.join("s2n_result.h"),
include_str!("./s2n_result.h").trim_start(),
Expand Down
14 changes: 11 additions & 3 deletions scripts/s2n2rust/s2n2rust/src/utils/s2n_random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ use crate::ok;
use crate::utils::s2n_result::s2n_result;

pub unsafe fn s2n_rand_cleanup_thread() -> s2n_result {
ok!()
todo!()
}

pub unsafe fn s2n_rand_cleanup() -> s2n_result {
ok!()
todo!()
}

pub unsafe fn s2n_rand_init() -> s2n_result {
ok!()
todo!()
}

pub unsafe fn s2n_get_public_random_data<T>(out: *mut T) -> s2n_result {
Expand All @@ -24,3 +24,11 @@ pub unsafe fn s2n_get_private_random_data<T>(out: *mut T) -> s2n_result {
pub unsafe fn s2n_public_random(max: i64, output: *mut u64) -> s2n_result {
todo!()
}

pub unsafe fn s2n_get_seed_entropy<T>(out: *mut T) -> s2n_result {
todo!()
}

pub unsafe fn s2n_get_mix_entropy<T>(out: *mut T) -> s2n_result {
todo!()
}
32 changes: 31 additions & 1 deletion scripts/s2n2rust/s2n2rust/src/utils/s2n_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,38 @@ pub unsafe fn s2n_sub_overflow(a: u32, b: u32, out: *mut u32) -> s2n_result {
ok!()
}

pub unsafe fn s2n_constant_time_pkcs1_unpad_or_dont(
dst: *mut u8,
src: *const u8,
srclen: u32,
expectlen: u32,
) -> bool {
todo!()
}

pub unsafe fn disable_defer_cleanup<T>(v: *mut T) {
todo!()
}

pub fn is_overflow_safe<T>(a: T, b: T, max: T) -> bool {
todo!()
}

// TODO add drop
pub struct s2n_blinding_guard<T> {
conn: *mut T,
}

pub fn with_error_blinding<T>(conn: *mut T) -> s2n_blinding_guard<T> {
todo!("return a guard and apply blinding")
}

pub fn blinding_cancel<T>(guard: s2n_blinding_guard<T>) {
todo!()
}

#[inline(never)]
pub unsafe extern "C" fn s2n_constant_time_equals(a: *const u8, b: *const u8, len: u32) -> bool {
pub unsafe fn s2n_constant_time_equals(a: *const u8, b: *const u8, len: u32) -> bool {
if len == 0 {
return true;
}
Expand Down

0 comments on commit 9cba77b

Please sign in to comment.