cypheron-core 0.1.2

Post-quantum cryptography library with NIST-standardized quantum-resistant algorithms
Documentation
// Copyright 2025 Cypheron Labs, Inc.
//
// 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 trait FfiSafe {
    fn is_valid_for_ffi(&self) -> bool;
}

impl<T> FfiSafe for &[T] {
    fn is_valid_for_ffi(&self) -> bool {
        !self.is_empty()
    }
}

impl<T> FfiSafe for &mut [T] {
    fn is_valid_for_ffi(&self) -> bool {
        !self.is_empty()
    }
}

impl<T, const N: usize> FfiSafe for &[T; N] {
    fn is_valid_for_ffi(&self) -> bool {
        true
    }
}

impl<T, const N: usize> FfiSafe for &mut [T; N] {
    fn is_valid_for_ffi(&self) -> bool {
        true
    }
}

impl<T> FfiSafe for &Vec<T> {
    fn is_valid_for_ffi(&self) -> bool {
        !self.is_empty()
    }
}

impl<T> FfiSafe for Vec<T> {
    fn is_valid_for_ffi(&self) -> bool {
        !self.is_empty()
    }
}

macro_rules! validate_ffi_fixed_buffer {
    ($buffer:expr, $expected_size:expr) => {
        if $buffer.len() != $expected_size {
            return Err(
                crate::sig::falcon::errors::FalconErrors::FfiValidationError(
                    "Buffer size mismatch for FFI operation".to_string(),
                ),
            );
        }
        if !$buffer.is_valid_for_ffi() {
            return Err(
                crate::sig::falcon::errors::FalconErrors::FfiValidationError(
                    "Invalid buffer for FFI operation".to_string(),
                ),
            );
        }
    };
}

macro_rules! validate_message_bounds {
    ($msg:expr) => {
        if $msg.len() > usize::MAX / 2 {
            return Err(
                crate::sig::falcon::errors::FalconErrors::FfiValidationError(
                    "Message too large for safe processing".to_string(),
                ),
            );
        }
        if !$msg.is_valid_for_ffi() && !$msg.is_empty() {
            return Err(
                crate::sig::falcon::errors::FalconErrors::FfiValidationError(
                    "Invalid message buffer".to_string(),
                ),
            );
        }
    };
}

macro_rules! safe_cast_to_c_void {
    ($ptr:expr) => {
        $ptr as *const c_void
    };
    (mut $ptr:expr) => {
        $ptr as *mut c_void
    };
}

pub(crate) use safe_cast_to_c_void;
pub(crate) use validate_ffi_fixed_buffer;
pub(crate) use validate_message_bounds;

pub fn sanitize_buffer_for_ffi<T>(buffer: &mut [T]) -> bool {
    !buffer.is_empty()
}

pub fn verify_buffer_initialized<T: PartialEq + Default + Copy>(
    buffer: &[T],
    expected_init_len: usize,
) -> bool {
    if buffer.len() < expected_init_len {
        return false;
    }

    let default_val = T::default();
    let initialized_portion = &buffer[..expected_init_len];

    !initialized_portion.iter().all(|&x| x == default_val)
}

#[cfg(not(debug_assertions))]
macro_rules! secure_debug {
    ($($arg:tt)*) => {};
}

#[cfg(debug_assertions)]
macro_rules! secure_warn {
    ($($arg:tt)*) => {
        eprintln!("[WARN] {}", format_args!($($arg)*));
    };
}

#[cfg(not(debug_assertions))]
macro_rules! secure_warn {
    ($($arg:tt)*) => {};
}

pub(crate) use secure_warn;