use std::ffi::CString;
use std::os::raw::{c_char, c_int};
use crate::ffi::interface::parse_algorithm;
use crate::ffi::interface::validation;
use crate::ffi::interface::write_c_string;
use crate::Cipher;
use zeroize::Zeroize;
use crate::ffi::context::{self, with_context};
use crate::ffi::interface::CiphernError;
#[no_mangle]
pub extern "C" fn ciphern_init() -> CiphernError {
match std::panic::catch_unwind(context::initialize_context) {
Ok(result) => match result {
Ok(_) => CiphernError::Success,
Err(_) => CiphernError::UnknownError,
},
Err(_) => {
eprintln!("ciphern_init: 初始化过程中发生 panic");
CiphernError::UnknownError
}
}
}
#[no_mangle]
pub extern "C" fn ciphern_cleanup() {
match std::panic::catch_unwind(context::cleanup_context) {
Ok(_) => {}
Err(_) => {
eprintln!("ciphern_cleanup: 清理过程中发生 panic");
}
}
}
#[no_mangle]
pub extern "C" fn ciphern_enable_fips() -> CiphernError {
match std::panic::catch_unwind(|| {
with_context(|context| {
match crate::fips::FipsContext::enable() {
Ok(_) => {
let _fips_context =
match crate::fips::FipsContext::new(crate::fips::FipsMode::Enabled) {
Ok(fc) => fc,
Err(_) => return Ok(CiphernError::FipsError),
};
context.set_fips_enabled(true);
Ok(CiphernError::Success)
}
Err(_) => Ok(CiphernError::FipsError),
}
})
.unwrap_or(CiphernError::UnknownError)
}) {
Ok(result) => result,
Err(_) => CiphernError::UnknownError,
}
}
#[no_mangle]
pub extern "C" fn ciphern_is_fips_enabled() -> c_int {
match std::panic::catch_unwind(|| {
with_context(|context| {
if context.is_fips_enabled() {
Ok(1)
} else {
Ok(0)
}
})
.unwrap_or(0)
}) {
Ok(result) => result,
Err(_) => {
eprintln!("ciphern_is_fips_enabled: 发生 panic");
0
}
}
}
#[no_mangle]
pub extern "C" fn ciphern_generate_key(
algorithm_name: *const c_char,
key_id_buffer: *mut c_char,
key_id_buffer_size: usize,
) -> CiphernError {
if algorithm_name.is_null() || key_id_buffer.is_null() {
return CiphernError::InvalidParameter;
}
match std::panic::catch_unwind(|| {
with_context(|context| {
let algo_str = unsafe { validation::validate_c_str(algorithm_name) }
.map_err(|_e| CiphernError::InvalidParameter)?;
validation::validate_mut_ptr(key_id_buffer, "key_id_buffer")
.map_err(|_e| CiphernError::InvalidParameter)?;
let algorithm =
parse_algorithm(algo_str).map_err(|_e| CiphernError::InvalidParameter)?;
let key_manager = context
.key_manager()
.map_err(|_| CiphernError::UnknownError)?;
let key_id = key_manager
.generate_key(algorithm)
.map_err(|_| CiphernError::KeyLifecycleError)?;
if let Ok(mut key) = key_manager.get_key(&key_id) {
let _ = key.activate(None);
}
unsafe { write_c_string(&key_id, key_id_buffer, key_id_buffer_size) }
.map_err(|_e| CiphernError::BufferTooSmall)?;
Ok(CiphernError::Success)
})
.unwrap_or(CiphernError::UnknownError)
}) {
Ok(result) => result,
Err(_) => CiphernError::UnknownError,
}
}
#[no_mangle]
pub extern "C" fn ciphern_destroy_key(key_id: *const c_char) -> CiphernError {
if key_id.is_null() {
return CiphernError::InvalidParameter;
}
match std::panic::catch_unwind(|| {
with_context(|context| {
let key_id_str = unsafe { validation::validate_c_str(key_id) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let key_manager = context
.key_manager()
.map_err(|_| CiphernError::UnknownError)?;
key_manager
.destroy_key(key_id_str)
.map_err(|_| CiphernError::KeyNotFound)?;
Ok(CiphernError::Success)
})
.unwrap_or_else(|e| e)
}) {
Ok(result) => result,
Err(_) => CiphernError::UnknownError,
}
}
#[no_mangle]
pub extern "C" fn ciphern_encrypt(
key_id: *const c_char,
plaintext: *const u8,
plaintext_len: usize,
ciphertext: *mut u8,
ciphertext_buffer_size: usize,
ciphertext_len: *mut usize,
) -> CiphernError {
debug_assert!(!key_id.is_null(), "密钥 ID 不应为 null");
debug_assert!(!plaintext.is_null(), "明文不应为 null");
debug_assert!(!ciphertext.is_null(), "密文缓冲区不应为 null");
debug_assert!(!ciphertext_len.is_null(), "密文长度指针不应为 null");
debug_assert!(plaintext_len > 0, "明文长度应大于 0");
debug_assert!(
plaintext_len <= 1024 * 1024,
"出于性能考虑,明文长度不应超过 1MB"
);
debug_assert!(
ciphertext_buffer_size >= plaintext_len + 32,
"密文缓冲区应足够大以容纳加密数据"
);
if key_id.is_null() || plaintext.is_null() || ciphertext.is_null() || ciphertext_len.is_null() {
return CiphernError::InvalidParameter;
}
match std::panic::catch_unwind(|| {
with_context(|context| {
let key_id_str = unsafe { validation::validate_c_str(key_id) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let plaintext_slice = unsafe { validation::validate_slice(plaintext, plaintext_len) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let ciphertext_buffer =
unsafe { validation::validate_mut_slice(ciphertext, ciphertext_buffer_size) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let ciphertext_len_ptr =
unsafe { validation::validate_mut_usize(ciphertext_len, "ciphertext_len") }
.map_err(|_e| CiphernError::InvalidParameter)?;
let key_manager = context
.key_manager()
.map_err(|_| CiphernError::UnknownError)?;
let key = key_manager
.get_key(key_id_str)
.map_err(|_| CiphernError::KeyNotFound)?;
let cipher =
Cipher::new(key.algorithm()).map_err(|_| CiphernError::AlgorithmNotSupported)?;
let mut encrypted = cipher
.encrypt(&key_manager, key_id_str, plaintext_slice)
.map_err(|_| CiphernError::EncryptionFailed)?;
if encrypted.len() > ciphertext_buffer_size {
return Err(CiphernError::BufferTooSmall);
}
ciphertext_buffer[..encrypted.len()].copy_from_slice(&encrypted);
*ciphertext_len_ptr = encrypted.len();
encrypted.zeroize();
Ok(CiphernError::Success)
})
.unwrap_or(CiphernError::UnknownError)
}) {
Ok(result) => result,
Err(_) => CiphernError::UnknownError,
}
}
#[no_mangle]
pub extern "C" fn ciphern_decrypt(
key_id: *const c_char,
ciphertext: *const u8,
ciphertext_len: usize,
plaintext: *mut u8,
plaintext_buffer_size: usize,
plaintext_len: *mut usize,
) -> CiphernError {
debug_assert!(!key_id.is_null(), "密钥 ID 不应为 null");
debug_assert!(!ciphertext.is_null(), "密文不应为 null");
debug_assert!(!plaintext.is_null(), "明文缓冲区不应为 null");
debug_assert!(!plaintext_len.is_null(), "明文长度指针不应为 null");
debug_assert!(ciphertext_len > 0, "密文长度应大于 0");
debug_assert!(
ciphertext_len <= 1024 * 1024 + 32,
"出于性能考虑,密文长度不应超过 1MB + 32 字节"
);
debug_assert!(
plaintext_buffer_size >= ciphertext_len - 32,
"明文缓冲区应足够大以容纳解密数据"
);
if key_id.is_null() || ciphertext.is_null() || plaintext.is_null() || plaintext_len.is_null() {
return CiphernError::InvalidParameter;
}
match std::panic::catch_unwind(|| {
with_context(|context| {
let key_id_str = unsafe { validation::validate_c_str(key_id) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let ciphertext_slice =
unsafe { validation::validate_slice(ciphertext, ciphertext_len) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let plaintext_buffer =
unsafe { validation::validate_mut_slice(plaintext, plaintext_buffer_size) }
.map_err(|_e| CiphernError::InvalidParameter)?;
let plaintext_len_ptr =
unsafe { validation::validate_mut_usize(plaintext_len, "plaintext_len") }
.map_err(|_e| CiphernError::InvalidParameter)?;
let key_manager = context
.key_manager()
.map_err(|_| CiphernError::UnknownError)?;
let key = key_manager
.get_key(key_id_str)
.map_err(|_| CiphernError::KeyNotFound)?;
let cipher =
Cipher::new(key.algorithm()).map_err(|_| CiphernError::AlgorithmNotSupported)?;
let mut decrypted = cipher
.decrypt(&key_manager, key_id_str, ciphertext_slice)
.map_err(|_| CiphernError::DecryptionFailed)?;
if decrypted.len() > plaintext_buffer_size {
*plaintext_len_ptr = decrypted.len();
return Err(CiphernError::BufferTooSmall);
}
plaintext_buffer[..decrypted.len()].copy_from_slice(&decrypted);
*plaintext_len_ptr = decrypted.len();
decrypted.zeroize();
Ok(CiphernError::Success)
})
.unwrap_or(CiphernError::UnknownError)
}) {
Ok(result) => result,
Err(_) => CiphernError::UnknownError,
}
}
thread_local! {
static ERROR_STRING: std::cell::RefCell<Option<CString>> = const { std::cell::RefCell::new(None) };
}
#[no_mangle]
pub extern "C" fn ciphern_get_last_error() -> *const c_char {
ERROR_STRING.with(|error_string| match error_string.borrow().as_ref() {
Some(s) => s.as_ptr(),
None => c"未知错误".as_ptr(),
})
}
#[allow(dead_code)]
fn set_last_error(msg: &str) {
ERROR_STRING.with(|error_string| {
*error_string.borrow_mut() = Some(CString::new(msg).unwrap_or_default());
});
}
#[cfg(feature = "generate_headers")]
#[allow(dead_code)]
pub fn generate_c_header() -> String {
r#"
#ifndef CIPHERN_H
#define CIPHERN_H
#include <stddef.h>
typedef enum {
CIPHERN_SUCCESS = 0,
CIPHERN_INVALID_PARAMETER = -1,
CIPHERN_MEMORY_ALLOCATION_FAILED = -2,
CIPHERN_KEY_NOT_FOUND = -3,
CIPHERN_ALGORITHM_NOT_SUPPORTED = -4,
CIPHERN_ENCRYPTION_FAILED = -5,
CIPHERN_DECRYPTION_FAILED = -6,
CIPHERN_FIPS_ERROR = -7,
CIPHERN_KEY_LIFECYCLE_ERROR = -8,
CIPHERN_BUFFER_TOO_SMALL = -9,
CIPHERN_INVALID_KEY_SIZE = -10,
CIPHERN_UNKNOWN_ERROR = -999,
} CiphernError;
#ifdef __cplusplus
extern "C" {
#endif
// 初始化和清理
CiphernError ciphern_init(void);
void ciphern_cleanup(void);
// FIPS 模式
CiphernError ciphern_enable_fips(void);
int ciphern_is_fips_enabled(void);
// 密钥管理
CiphernError ciphern_generate_key(const char* algorithm_name, char* key_id_buffer, size_t key_id_buffer_size);
CiphernError ciphern_destroy_key(const char* key_id);
// 加密和解密
CiphernError ciphern_encrypt(
const char* key_id,
const unsigned char* plaintext,
size_t plaintext_len,
unsigned char* ciphertext,
size_t ciphertext_buffer_size,
size_t* ciphertext_len
);
CiphernError ciphern_decrypt(
const char* key_id,
const unsigned char* ciphertext,
size_t ciphertext_len,
unsigned char* plaintext,
size_t plaintext_buffer_size,
size_t* plaintext_len
);
// 错误处理
const char* ciphern_error_string(CiphernError error);
#ifdef __cplusplus
}
#endif
#endif // CIPHERN_H
"#.to_string()
}