lib-q-core 0.0.11

Core types and traits for lib-Q post-quantum cryptography library
Documentation
//! WASM Error Handling Module
//!
//! This module provides secure, consistent error handling for WASM bindings.
//! It ensures all WASM functions return Result<T, JsValue> consistently and
//! provides secure error conversion without information leakage.

#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;

use crate::error::Error;

/// Convert Error to JsValue for WASM compatibility
///
/// This function provides secure error conversion that:
/// - Prevents information leakage through error messages
/// - Ensures consistent error handling across WASM bindings
/// - Maintains security by not exposing internal implementation details
#[cfg(feature = "wasm")]
pub fn error_to_js_value(error: Error) -> JsValue {
    // Security: Use generic error messages to prevent information leakage
    let message = match error {
        Error::InvalidAlgorithm { .. } => "Invalid algorithm specified",
        Error::InvalidKeySize { .. } => "Invalid key size",
        Error::InvalidMessageSize { .. } => "Invalid message size",
        Error::InvalidNonceSize { .. } => "Invalid nonce size",
        Error::InvalidSignatureSize { .. } => "Invalid signature",
        Error::InvalidCiphertextSize { .. } => "Invalid ciphertext",
        Error::InvalidPlaintextSize { .. } => "Invalid plaintext",
        Error::InvalidKeyFormat => "Invalid key material",
        Error::InvalidSecurityLevel { .. } => "Invalid security level",
        Error::NotImplemented { .. } => "Feature not implemented",
        Error::ProviderNotConfigured { .. } => "Provider not configured",
        Error::VerificationFailed { .. } => "Verification failed",
        Error::EncryptionFailed { .. } => "Encryption failed",
        Error::DecryptionFailed { .. } => "Decryption failed",
        Error::KeyGenerationFailed { .. } => "Key generation failed",
        Error::RandomGenerationFailed { .. } => "Random generation failed",
        Error::SigningFailed { .. } => "Signing failed",
        Error::MemoryAllocationFailed { .. } => "Memory allocation failed",
        Error::InternalError { .. } => "Internal error",
        Error::UnsupportedOperation { .. } => "Unsupported operation",
        Error::InvalidState { .. } => "Invalid context state",
        Error::PluginDependencyError { .. } => "Plugin dependency error",
        Error::PluginVersionIncompatible { .. } => "Plugin version incompatible",
        Error::InvalidKey { .. } => "Invalid key",
        Error::UnsupportedAlgorithm { .. } => "Unsupported algorithm",
        Error::AuthenticationFailed { .. } => "Authentication failed",
        Error::InvalidAssociatedDataSize { .. } => "Invalid associated data size",
        Error::InvalidTagSize { .. } => "Invalid tag size",
        Error::InvalidHashSize { .. } => "Invalid hash size",
        Error::InvalidRandomnessSize { .. } => "Invalid randomness size",
        Error::RandomBytesLengthInvalid { .. } => "Invalid random length",
        Error::HexDecode(..) => "Invalid hex encoding",
        Error::BufferTooSmall { .. } => "Insufficient buffer capacity",
    };

    JsValue::from_str(message)
}

/// Helper function to convert Result<T, Error> to Result<T, JsValue>
///
/// This function provides a secure conversion that:
/// - Maintains type safety
/// - Ensures consistent error handling
/// - Prevents information leakage
#[cfg(feature = "wasm")]
pub fn convert_result<T>(result: Result<T, Error>) -> Result<T, JsValue> {
    result.map_err(error_to_js_value)
}

/// WASM-safe algorithm parsing that returns JsValue errors
///
/// This function provides secure algorithm parsing that:
/// - Validates input strings
/// - Returns consistent error types
/// - Prevents injection attacks
#[cfg(feature = "wasm")]
pub fn parse_algorithm_wasm(algorithm: &str) -> Result<crate::api::Algorithm, JsValue> {
    // Security: Validate input length to prevent DoS attacks
    if algorithm.len() > 64 {
        return Err(JsValue::from_str("Algorithm name too long"));
    }

    // Reject control characters; allow Unicode for algorithm string forms that use non-ASCII.
    // [`crate::wasm::conversions::WasmConversions::string_to_algorithm`].
    if algorithm.chars().any(|c| c.is_control()) {
        return Err(JsValue::from_str("Invalid algorithm name format"));
    }

    match crate::wasm::conversions::WasmConversions::string_to_algorithm(algorithm) {
        Ok(a) => Ok(a),
        Err(Error::UnsupportedAlgorithm { .. }) => Err(JsValue::from_str("Unsupported algorithm")),
        Err(_) => Err(JsValue::from_str("Invalid algorithm specified")),
    }
}

/// Secure WASM error handling macro
///
/// This macro provides secure error handling for WASM functions that:
/// - Ensures consistent error types
/// - Prevents information leakage
/// - Maintains security boundaries
#[cfg(feature = "wasm")]
#[macro_export]
macro_rules! wasm_result {
    ($expr:expr) => {
        match $expr {
            Ok(value) => Ok(value),
            Err(error) => Err($crate::wasm::error::error_to_js_value(error)),
        }
    };
}

/// Secure WASM validation macro
///
/// This macro provides secure validation for WASM inputs that:
/// - Validates input parameters
/// - Returns consistent error types
/// - Prevents injection attacks
#[cfg(feature = "wasm")]
#[macro_export]
macro_rules! wasm_validate {
    ($condition:expr, $error_msg:expr) => {
        if !$condition {
            return Err(JsValue::from_str($error_msg));
        }
    };
}

/// Secure WASM serialization helper
///
/// This function provides secure serialization that:
/// - Handles serialization errors gracefully
/// - Returns consistent error types
/// - Prevents information leakage
#[cfg(feature = "wasm")]
pub fn secure_serialize<T: serde::Serialize>(value: &T) -> Result<JsValue, JsValue> {
    match serde_wasm_bindgen::to_value(value) {
        Ok(js_value) => Ok(js_value),
        Err(_) => Err(JsValue::from_str("Serialization error")),
    }
}

/// Secure WASM deserialization helper
///
/// This function provides secure deserialization that:
/// - Handles deserialization errors gracefully
/// - Returns consistent error types
/// - Prevents information leakage
#[cfg(feature = "wasm")]
pub fn secure_deserialize<T: serde::de::DeserializeOwned>(value: &JsValue) -> Result<T, JsValue> {
    match serde_wasm_bindgen::from_value(value.clone()) {
        Ok(deserialized) => Ok(deserialized),
        Err(_) => Err(JsValue::from_str("Deserialization error")),
    }
}

// NOTE: these functions build a `wasm_bindgen::JsValue`, which (per prior audit finding) ABORTS
// the process natively — observed STATUS_STACK_BUFFER_OVERRUN — outside a real wasm32 runtime.
// They previously had `#[test]` (not `#[wasm_bindgen_test]`) fns gated on
// `cfg(target_arch = "wasm32")`: under `cargo test` on a native host that cfg is always false, so
// the functions compiled but the harness reported "0 tests run" — a suite that looks green while
// exercising nothing. There is no native-safe way to test them (constructing a `JsValue` is the
// abort trigger), so the real tests now live in `tests/wasm_smoke.rs` as `#[wasm_bindgen_test]`,
// run only under `wasm-pack test --node` on the `wasm32-unknown-unknown` target where a JS engine
// actually backs `JsValue`. See that file for the executed assertions.