Rust wrapper: add compatibility with older FIPS v5 package

This commit is contained in:
Josh Holtrop
2026-02-18 16:28:45 -05:00
parent f1e8c1b886
commit 2ada1a3629
7 changed files with 127 additions and 21 deletions
+34 -7
View File
@@ -124,7 +124,11 @@ fn generate_fips_aliases() -> Result<()> {
if non_fips_re.is_match(&binding) {
// Add any new known names defined with both a _fips suffix and not
// here. Warn if any new ones are discovered.
if base_name != "wc_AesGcmEncrypt" {
let known_both = &[
"wc_AesGcmEncrypt",
"wc_AesCcmEncrypt",
];
if !known_both.contains(&base_name) {
println!("cargo:warning=Skipping FIPS symbols alias for {}", base_name);
}
} else {
@@ -166,18 +170,21 @@ fn read_file(path: String) -> Result<String> {
Ok(content)
}
fn check_cfg(binding: &str, function_name: &str, cfg_name: &str) {
fn check_cfg(binding: &str, function_name: &str, cfg_name: &str) -> bool {
let pattern = format!(r"\b{}(_fips)?\b", function_name);
let re = match Regex::new(&pattern) {
Ok(r) => r,
Err(e) => {
eprintln!("Error compiling regex '{}': {}", pattern, e);
return;
std::process::exit(1);
}
};
println!("cargo::rustc-check-cfg=cfg({})", cfg_name);
if re.is_match(binding) {
println!("cargo:rustc-cfg={}", cfg_name);
true
} else {
false
}
}
@@ -199,6 +206,7 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_AesOfbEncrypt", "aes_ofb");
check_cfg(&binding, "wc_AesXtsInit", "aes_xts");
check_cfg(&binding, "wc_AesXtsEncryptInit", "aes_xts_stream");
check_cfg(&binding, "WC_AES_BLOCK_SIZE", "aes_wc_block_size");
/* blake2 */
check_cfg(&binding, "wc_InitBlake2b", "blake2b");
@@ -234,10 +242,19 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_ecc_verify_hash", "ecc_verify");
check_cfg(&binding, "wc_ecc_export_x963", "ecc_export");
check_cfg(&binding, "wc_ecc_import_x963", "ecc_import");
check_cfg(&binding, "ecc_curve_ids_ECC_X25519", "ecc_curve_25519");
check_cfg(&binding, "ecc_curve_ids_ECC_X448", "ecc_curve_448");
check_cfg(&binding, "ecc_curve_ids_ECC_SAKKE_1", "ecc_curve_sakke");
check_cfg(&binding, "ecc_curve_ids_ECC_CURVE_CUSTOM", "ecc_custom_curves");
if check_cfg(&binding, "ecc_curve_ids_ECC_CURVE_INVALID", "ecc_curve_ids") {
check_cfg(&binding, "ecc_curve_ids_ECC_SM2P256V1", "ecc_curve_sm2p256v1");
check_cfg(&binding, "ecc_curve_ids_ECC_X25519", "ecc_curve_25519");
check_cfg(&binding, "ecc_curve_ids_ECC_X448", "ecc_curve_448");
check_cfg(&binding, "ecc_curve_ids_ECC_SAKKE_1", "ecc_curve_sakke");
check_cfg(&binding, "ecc_curve_ids_ECC_CURVE_CUSTOM", "ecc_custom_curves");
} else {
check_cfg(&binding, "ecc_curve_id_ECC_SM2P256V1", "ecc_curve_sm2p256v1");
check_cfg(&binding, "ecc_curve_id_ECC_X25519", "ecc_curve_25519");
check_cfg(&binding, "ecc_curve_id_ECC_X448", "ecc_curve_448");
check_cfg(&binding, "ecc_curve_id_ECC_SAKKE_1", "ecc_curve_sakke");
check_cfg(&binding, "ecc_curve_id_ECC_CURVE_CUSTOM", "ecc_custom_curves");
}
/* ed25519 */
check_cfg(&binding, "wc_ed25519_init", "ed25519");
@@ -263,6 +280,7 @@ fn scan_cfg() -> Result<()> {
/* hmac */
check_cfg(&binding, "wc_HmacSetKey", "hmac");
check_cfg(&binding, "wc_HmacSetKey_ex", "hmac_setkey_ex");
/* kdf */
check_cfg(&binding, "wc_PBKDF2", "kdf_pbkdf2");
@@ -283,6 +301,15 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_RsaDirect", "rsa_direct");
check_cfg(&binding, "wc_MakeRsaKey", "rsa_keygen");
check_cfg(&binding, "wc_RsaPSS_Sign", "rsa_pss");
check_cfg(&binding, "wc_RsaSetRNG", "rsa_setrng");
check_cfg(&binding, "WC_MGF1SHA512_224", "rsa_mgf1sha512_224");
check_cfg(&binding, "WC_MGF1SHA512_256", "rsa_mgf1sha512_256");
// Detect whether wc_RsaExportKey takes a const first arg (new API) or non-const (old API)
let re = Regex::new(r"pub fn wc_RsaExportKey(_fips)?\s*\(\s*\w+\s*:\s*\*\s*const").unwrap();
println!("cargo::rustc-check-cfg=cfg(rsa_const_api)");
if re.is_match(&binding) {
println!("cargo:rustc-cfg=rsa_const_api");
}
/* sha */
check_cfg(&binding, "wc_InitSha", "sha");
+9 -4
View File
@@ -28,6 +28,11 @@ Encryption Standard (AES) functionality.
use crate::sys;
use std::mem::{size_of_val, MaybeUninit};
#[cfg(aes_wc_block_size)]
pub const AES_BLOCK_SIZE: usize = sys::WC_AES_BLOCK_SIZE as usize;
#[cfg(not(aes_wc_block_size))]
pub const AES_BLOCK_SIZE: usize = sys::AES_BLOCK_SIZE as usize;
/// AES Cipher Block Chaining (CBC) mode.
///
/// # Example
@@ -91,7 +96,7 @@ impl CBC {
fn init(&mut self, key: &[u8], iv: &[u8], dir: i32) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() as u32 != sys::WC_AES_BLOCK_SIZE {
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
@@ -506,7 +511,7 @@ impl CFB {
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() as u32 != sys::WC_AES_BLOCK_SIZE {
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
@@ -812,7 +817,7 @@ impl CTR {
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() as u32 != sys::WC_AES_BLOCK_SIZE {
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
@@ -1769,7 +1774,7 @@ impl OFB {
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() as u32 != sys::WC_AES_BLOCK_SIZE {
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
+48
View File
@@ -290,6 +290,7 @@ pub struct ECC {
wc_ecc_key: sys::ecc_key,
}
#[cfg(ecc_curve_ids)]
impl ECC {
pub const CURVE_INVALID: i32 = sys::ecc_curve_ids_ECC_CURVE_INVALID;
pub const CURVE_DEF: i32 = sys::ecc_curve_ids_ECC_CURVE_DEF;
@@ -320,6 +321,7 @@ impl ECC {
pub const BRAINPOOLP320R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP320R1;
pub const BRAINPOOLP384R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP384R1;
pub const BRAINPOOLP512R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP512R1;
#[cfg(ecc_curve_sm2p256v1)]
pub const SM2P256V1: i32 = sys::ecc_curve_ids_ECC_SM2P256V1;
#[cfg(ecc_curve_25519)]
pub const X25519: i32 = sys::ecc_curve_ids_ECC_X25519;
@@ -330,7 +332,53 @@ impl ECC {
#[cfg(ecc_custom_curves)]
pub const CURVE_CUSTOM: i32 = sys::ecc_curve_ids_ECC_CURVE_CUSTOM;
pub const CURVE_MAX: i32 = sys::ecc_curve_ids_ECC_CURVE_MAX;
}
#[cfg(not(ecc_curve_ids))]
impl ECC {
pub const CURVE_INVALID: i32 = sys::ecc_curve_id_ECC_CURVE_INVALID;
pub const CURVE_DEF: i32 = sys::ecc_curve_id_ECC_CURVE_DEF;
pub const SECP192R1: i32 = sys::ecc_curve_id_ECC_SECP192R1;
pub const PRIME192V2: i32 = sys::ecc_curve_id_ECC_PRIME192V2;
pub const PRIME192V3: i32 = sys::ecc_curve_id_ECC_PRIME192V3;
pub const PRIME239V1: i32 = sys::ecc_curve_id_ECC_PRIME239V1;
pub const PRIME239V2: i32 = sys::ecc_curve_id_ECC_PRIME239V2;
pub const PRIME239V3: i32 = sys::ecc_curve_id_ECC_PRIME239V3;
pub const SECP256R1: i32 = sys::ecc_curve_id_ECC_SECP256R1;
pub const SECP112R1: i32 = sys::ecc_curve_id_ECC_SECP112R1;
pub const SECP112R2: i32 = sys::ecc_curve_id_ECC_SECP112R2;
pub const SECP128R1: i32 = sys::ecc_curve_id_ECC_SECP128R1;
pub const SECP128R2: i32 = sys::ecc_curve_id_ECC_SECP128R2;
pub const SECP160R1: i32 = sys::ecc_curve_id_ECC_SECP160R1;
pub const SECP160R2: i32 = sys::ecc_curve_id_ECC_SECP160R2;
pub const SECP224R1: i32 = sys::ecc_curve_id_ECC_SECP224R1;
pub const SECP384R1: i32 = sys::ecc_curve_id_ECC_SECP384R1;
pub const SECP521R1: i32 = sys::ecc_curve_id_ECC_SECP521R1;
pub const SECP160K1: i32 = sys::ecc_curve_id_ECC_SECP160K1;
pub const SECP192K1: i32 = sys::ecc_curve_id_ECC_SECP192K1;
pub const SECP224K1: i32 = sys::ecc_curve_id_ECC_SECP224K1;
pub const SECP256K1: i32 = sys::ecc_curve_id_ECC_SECP256K1;
pub const BRAINPOOLP160R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP160R1;
pub const BRAINPOOLP192R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP192R1;
pub const BRAINPOOLP224R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP224R1;
pub const BRAINPOOLP256R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP256R1;
pub const BRAINPOOLP320R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP320R1;
pub const BRAINPOOLP384R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP384R1;
pub const BRAINPOOLP512R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP512R1;
#[cfg(ecc_curve_sm2p256v1)]
pub const SM2P256V1: i32 = sys::ecc_curve_id_ECC_SM2P256V1;
#[cfg(ecc_curve_25519)]
pub const X25519: i32 = sys::ecc_curve_id_ECC_X25519;
#[cfg(ecc_curve_448)]
pub const X448: i32 = sys::ecc_curve_id_ECC_X448;
#[cfg(ecc_curve_sakke)]
pub const SAKKE_1: i32 = sys::ecc_curve_id_ECC_SAKKE_1;
#[cfg(ecc_custom_curves)]
pub const CURVE_CUSTOM: i32 = sys::ecc_curve_id_ECC_CURVE_CUSTOM;
pub const CURVE_MAX: i32 = sys::ecc_curve_id_ECC_CURVE_MAX;
}
impl ECC {
pub const FLAG_NONE: i32 = sys::WC_ECC_FLAG_NONE as i32;
pub const FLAG_COFACTOR: i32 = sys::WC_ECC_FLAG_COFACTOR as i32;
pub const FLAG_DEC_SIGN: i32 = sys::WC_ECC_FLAG_DEC_SIGN as i32;
@@ -156,10 +156,12 @@ impl HMAC {
/// # Example
///
/// ```rust
/// #![cfg(hmac_setkey_ex)]
/// use wolfssl_wolfcrypt::hmac::HMAC;
/// let key = [0x42u8; 3];
/// let mut hmac = HMAC::new_allow_short_key(HMAC::TYPE_SHA256, &key).expect("Error with new_allow_short_key()");
/// ```
#[cfg(hmac_setkey_ex)]
pub fn new_allow_short_key(typ: i32, key: &[u8]) -> Result<Self, i32> {
Self::new_allow_short_key_ex(typ, key, None, None)
}
@@ -182,10 +184,12 @@ impl HMAC {
/// # Example
///
/// ```rust
/// #![cfg(hmac_setkey_ex)]
/// use wolfssl_wolfcrypt::hmac::HMAC;
/// let key = [0x42u8; 3];
/// let mut hmac = HMAC::new_allow_short_key_ex(HMAC::TYPE_SHA256, &key, None, None).expect("Error with new_allow_short_key_ex()");
/// ```
#[cfg(hmac_setkey_ex)]
pub fn new_allow_short_key_ex(typ: i32, key: &[u8], heap: Option<*mut std::os::raw::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let key_size = key.len() as u32;
let mut wc_hmac: MaybeUninit<sys::Hmac> = MaybeUninit::uninit();
+20 -10
View File
@@ -116,7 +116,9 @@ impl RSA {
pub const MGF1SHA256 : i32 = sys::WC_MGF1SHA256 as i32;
pub const MGF1SHA384 : i32 = sys::WC_MGF1SHA384 as i32;
pub const MGF1SHA512 : i32 = sys::WC_MGF1SHA512 as i32;
#[cfg(rsa_mgf1sha512_224)]
pub const MGF1SHA512_224 : i32 = sys::WC_MGF1SHA512_224 as i32;
#[cfg(rsa_mgf1sha512_256)]
pub const MGF1SHA512_256 : i32 = sys::WC_MGF1SHA512_256 as i32;
// Type constants used for `rsa_direct()`.
@@ -525,8 +527,12 @@ impl RSA {
*d_size = d.len() as u32;
*p_size = p.len() as u32;
*q_size = q.len() as u32;
#[cfg(rsa_const_api)]
let key_ptr = &self.wc_rsakey;
#[cfg(not(rsa_const_api))]
let key_ptr = &mut self.wc_rsakey;
let rc = unsafe {
sys::wc_RsaExportKey(&self.wc_rsakey,
sys::wc_RsaExportKey(key_ptr,
e.as_mut_ptr(), e_size,
n.as_mut_ptr(), n_size,
d.as_mut_ptr(), d_size,
@@ -575,8 +581,12 @@ impl RSA {
n: &mut [u8], n_size: &mut u32) -> Result<(), i32> {
*e_size = e.len() as u32;
*n_size = n.len() as u32;
#[cfg(rsa_const_api)]
let key = &self.wc_rsakey;
#[cfg(not(rsa_const_api))]
let key = &mut self.wc_rsakey;
let rc = unsafe {
sys::wc_RsaFlattenPublicKey(&self.wc_rsakey,
sys::wc_RsaFlattenPublicKey(key,
e.as_mut_ptr(), e_size, n.as_mut_ptr(), n_size)
};
if rc != 0 {
@@ -843,7 +853,7 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss))]
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// {
/// use std::fs;
/// use wolfssl_wolfcrypt::random::RNG;
@@ -873,7 +883,7 @@ impl RSA {
/// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()");
/// }
/// ```
#[cfg(rsa_pss)]
#[cfg(all(rsa_pss, rsa_const_api))]
pub fn pss_check_padding(&mut self, din: &[u8], sig: &[u8], hash_algo: u32) -> Result<(), i32> {
let din_size = din.len() as u32;
let sig_size = sig.len() as u32;
@@ -909,7 +919,7 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss))]
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// {
/// use std::fs;
/// use wolfssl_wolfcrypt::random::RNG;
@@ -939,7 +949,7 @@ impl RSA {
/// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()");
/// }
/// ```
#[cfg(rsa_pss)]
#[cfg(all(rsa_pss, rsa_const_api))]
pub fn pss_verify(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32) -> Result<usize, i32> {
let din_size = din.len() as u32;
let dout_size = dout.len() as u32;
@@ -980,7 +990,7 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss))]
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// {
/// use std::fs;
/// use wolfssl_wolfcrypt::random::RNG;
@@ -1010,7 +1020,7 @@ impl RSA {
/// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()");
/// }
/// ```
#[cfg(rsa_pss)]
#[cfg(all(rsa_pss, rsa_const_api))]
pub fn pss_verify_check(&mut self, din: &[u8], dout: &mut [u8], digest: &[u8], hash_algo: u32, mgf: i32) -> Result<usize, i32> {
let din_size = din.len() as u32;
let dout_size = dout.len() as u32;
@@ -1050,7 +1060,7 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(rsa_direct)]
/// #[cfg(all(rsa_direct, rsa_const_api))]
/// {
/// use std::fs;
/// use wolfssl_wolfcrypt::random::RNG;
@@ -1073,7 +1083,7 @@ impl RSA {
/// assert_eq!(plain_out, plain);
/// }
/// ```
#[cfg(rsa_direct)]
#[cfg(all(rsa_direct, rsa_const_api))]
pub fn rsa_direct(&mut self, din: &[u8], dout: &mut [u8], typ: i32, rng: &mut RNG) -> Result<usize, i32> {
let din_size = din.len() as u32;
let mut dout_size = dout.len() as u32;
@@ -17,3 +17,8 @@ include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
/* Include generated FIPS symbol aliases. */
include!(concat!(env!("OUT_DIR"), "/fips_aliases.rs"));
#[cfg(not(rsa_setrng))]
unsafe extern "C" {
pub fn wc_RsaSetRNG(key: *mut RsaKey, rng: *mut WC_RNG) -> core::ffi::c_int;
}
@@ -33,6 +33,13 @@ fn test_hmac_sha256() {
];
for i in 0..keys.len() {
#[cfg(not(hmac_setkey_ex))]
if keys[i].len() < 14 {
continue;
}
#[cfg(not(hmac_setkey_ex))]
let mut hmac = HMAC::new(HMAC::TYPE_SHA256, keys[i]).expect("Error with new()");
#[cfg(hmac_setkey_ex)]
let mut hmac =
if keys[i].len() < 14 {
HMAC::new_allow_short_key(HMAC::TYPE_SHA256, keys[i]).expect("Error with new_allow_short_key()")