use core::{ffi::c_char, num::NonZeroU32};
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(feature = "use_ring")]
use crate::{ScramSha1Ring, ScramSha256Ring, ScramSha512Ring};
use crate::
{
scram_ierror_map,
ScramErrorCode,
ScramKey,
ScramPassword,
ScramResult,
ScramSha1RustNative,
ScramSha256RustNative,
ScramSha512RustNative
};
use super::{common, into_boxed_ptr, CApiScramHasherProvider, CApiScramTypeAlias};
#[unsafe(no_mangle)]
pub unsafe extern "C"
fn capi_scram_password_not_found(hash_prov: CApiScramHasherProvider, hash_type: CApiScramTypeAlias) -> *mut ScramResult<*mut ScramPassword>
{
let ret =
match (hash_prov, hash_type)
{
#[cfg(not(feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha1RustNative>().map(|s| into_boxed_ptr(s))),
#[cfg(feature = "exclude_sha1")]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled with exclude_sha1 support"))),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha256RustNative>().map(|s| into_boxed_ptr(s))),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha512RustNative>().map(|s| into_boxed_ptr(s))),
#[cfg(all(feature = "use_ring", not(feature = "exclude_sha1")))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha1Ring>().map(|s| into_boxed_ptr(s))),
#[cfg(any(not(feature = "use_ring"), feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without ring / with exclude_sha1 support"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha256Ring>().map(|s| into_boxed_ptr(s))),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without ring support"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(ScramPassword::not_found::<ScramSha512Ring>().map(|s| into_boxed_ptr(s))),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without ring support"))),
};
return ret;
}
#[unsafe(no_mangle)]
pub unsafe extern "C"
fn capi_scram_password_found_plaintext(hash_prov: CApiScramHasherProvider, hash_type: CApiScramTypeAlias,
password: *const u8, pass_len: usize, scram_keys_opt: *mut ScramKey) -> *mut ScramResult<*mut ScramPassword>
{
let pass =
match common::carr_to_slice_n(password, pass_len, "password is not valid")
{
Ok(r) => r,
Err(e) =>
return into_boxed_ptr(Err(e))
};
let scram_keys =
if scram_keys_opt.is_null() == false
{
Some(* unsafe { Box::from_raw(scram_keys_opt) })
}
else
{
None
};
let ret =
match (hash_prov, hash_type)
{
#[cfg(not(feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha1RustNative>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
#[cfg(feature = "exclude_sha1")]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "Compiled without SHA1 support"))),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha256RustNative>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha512RustNative>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
#[cfg(all(feature = "use_ring", not(feature = "exclude_sha1")))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha1Ring>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
#[cfg(any(not(feature = "use_ring"), feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "Rust Ring is not available"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha256Ring>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "Rust Ring is not available"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(
ScramPassword
::found_plaintext_password
::<ScramSha512Ring>(pass, scram_keys)
.map(|s| into_boxed_ptr(s))
),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "Rust Ring is not available"))),
};
return ret;
}
#[unsafe(no_mangle)]
pub unsafe extern "C"
fn capi_scram_password_with_params(
hash_prov: CApiScramHasherProvider,
hash_type: CApiScramTypeAlias,
plain_password: *const u8,
plain_password_len: usize,
salt_plain_opt: *const u8,
salt_plain_len: usize,
iterations_opt: *const u32,
scram_keys_opt: *mut ScramKey
) -> *mut ScramResult<*mut ScramPassword>
{
let pass =
match common::carr_to_slice_n(plain_password, plain_password_len, "plain_password is not valid")
{
Ok(r) => r,
Err(e) =>
return into_boxed_ptr(Err(e))
}
.to_vec();
let salt =
if salt_plain_opt.is_null() == false
{
match common::carr_to_slice_n(salt_plain_opt, salt_plain_len, "salt_plain_opt is not valid")
{
Ok(r) => Some(r.to_vec()),
Err(e) =>
return into_boxed_ptr(Err(e))
}
}
else
{
None
};
let iters =
if let Some(iterations) = unsafe { iterations_opt.as_ref() }
{
let iters = NonZeroU32::new(*iterations);
if iters.is_none() == true
{
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::InternalError, "iterations can not be 0")));
}
iters
}
else
{
None
};
let scram_keys =
if scram_keys_opt.is_null() == false
{
Some(* unsafe { Box::from_raw(scram_keys_opt) })
}
else
{
None
};
let scram_password_res =
match (hash_prov, hash_type)
{
#[cfg(not(feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
ScramPassword::salt_password_with_params::<_, ScramSha1RustNative>(&pass, salt, iters, scram_keys),
#[cfg(feature = "exclude_sha1")]
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha1) =>
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without sha1 support"))),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha256) =>
ScramPassword::salt_password_with_params::<_, ScramSha256RustNative>(&pass, salt, iters, scram_keys),
(CApiScramHasherProvider::RustNative, CApiScramTypeAlias::Sha512) =>
ScramPassword::salt_password_with_params::<_, ScramSha512RustNative>(&pass, salt, iters, scram_keys),
#[cfg(all(feature = "use_ring", not(feature = "exclude_sha1")))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
ScramPassword::salt_password_with_params::<_, ScramSha1Ring>(&pass, salt, iters, scram_keys),
#[cfg(any(not(feature = "use_ring"), feature = "exclude_sha1"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha1) =>
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without sha1 or ring support"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
ScramPassword::salt_password_with_params::<_, ScramSha256Ring>(&pass, salt, iters, scram_keys),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha256) =>
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without ring support"))),
#[cfg(feature = "use_ring")]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
ScramPassword::salt_password_with_params::<_, ScramSha512Ring>(&pass, salt, iters, scram_keys),
#[cfg(not(feature = "use_ring"))]
(CApiScramHasherProvider::RustRing, CApiScramTypeAlias::Sha512) =>
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::FeatureNotSupported, "compiled without ring support"))),
};
if let Err(e) = scram_password_res
{
return into_boxed_ptr(Err(e));
}
let ret =
into_boxed_ptr(scram_password_res.unwrap());
return into_boxed_ptr(Ok(ret));
}
#[unsafe(no_mangle)]
pub unsafe extern "C"
fn capi_scram_password_found_secret_base64_password(
salted_hashed_password_base64: *const c_char,
salt_base64: *const c_char,
iterations: u32,
scram_keys_opt: *mut ScramKey
) -> *mut ScramResult<*mut ScramPassword>
{
let salt_pass =
match common::cstr_to_string_n(salted_hashed_password_base64, "salted_hashed_password_base64 is not valid")
{
Ok(r) => r,
Err(e) =>
return into_boxed_ptr(Err(e))
};
let salt_base64_str =
match common::cstr_to_string_n(salt_base64, "salt_base64 is not valid")
{
Ok(r) => r,
Err(e) =>
return into_boxed_ptr(Err(e))
};
let iter_nonz =
match NonZeroU32::new(iterations)
{
Some(r) =>
r,
None =>
return into_boxed_ptr(Err(scram_ierror_map!(ScramErrorCode::InternalError, "iterations can not be 0")))
};
let scram_keys =
if scram_keys_opt.is_null() == false
{
Some(* unsafe { Box::from_raw(scram_keys_opt) })
}
else
{
None
};
let ret =
into_boxed_ptr(
ScramPassword
::found_secret_base64_password(salt_pass, salt_base64_str, iter_nonz, scram_keys)
.map(|s| into_boxed_ptr(s))
);
return ret;
}
#[unsafe(no_mangle)]
pub unsafe extern "C"
fn capi_scram_password_free(pass: *mut ScramPassword)
{
if pass.is_null() == true
{
return;
}
drop(unsafe { Box::from_raw(pass) });
return;
}