use std::env;
use std::fmt::Write as _;
use std::io::Write;
use crate::tests::*;
use serial_test::{parallel, serial};
#[cfg(feature = "sqlitedb")]
fn test_token_setup(name: &str) -> TestToken<'_> {
let mut testtokn = TestToken::new(String::from(name));
testtokn.setup_db(None);
testtokn
}
#[cfg(feature = "sqlitedb")]
fn test_token_env(suffix: &str) {
let dbname = format!("test_token_env{}", suffix);
let mut testtokn = test_token_setup(&dbname);
let confname = format!("{}/test_token_env{}.conf", TESTDIR, suffix);
testtokn.make_config_file(&confname, None);
let mut plist: *mut CK_FUNCTION_LIST = std::ptr::null_mut();
let pplist = &mut plist;
let result = fn_get_function_list(&mut *pplist);
assert_eq!(result, 0);
unsafe {
let list: CK_FUNCTION_LIST = *plist;
match list.C_Initialize {
Some(init_fn) => {
let mut args = TestToken::make_init_args(None);
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
env::set_var("KRYOPTIC_CONF", confname);
let ret = force_load_config();
assert_eq!(ret, CKR_OK);
let ret = init_fn(args_ptr as *mut std::ffi::c_void);
env::remove_var("KRYOPTIC_CONF");
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[cfg(feature = "sqlitedb")]
fn test_token_null_args(suffix: &str) {
let dbname = format!("test_token_nullargs{}", suffix);
let mut testtokn = test_token_setup(&dbname);
let confname = format!("{}/test_token_nullargs{}.conf", TESTDIR, suffix);
testtokn.make_config_file(&confname, None);
let mut plist: *mut CK_FUNCTION_LIST = std::ptr::null_mut();
let pplist = &mut plist;
let result = fn_get_function_list(&mut *pplist);
assert_eq!(result, 0);
unsafe {
let list: CK_FUNCTION_LIST = *plist;
match list.C_Initialize {
Some(init_fn) => {
env::set_var("KRYOPTIC_CONF", confname);
let ret = force_load_config();
assert_eq!(ret, CKR_OK);
let ret = init_fn(std::ptr::null_mut());
env::remove_var("KRYOPTIC_CONF");
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[test]
#[serial]
fn test_token_datadir() {
let basedir = format!("{}/datadirtest", TESTDIR);
let confdir = format!("{}/kryoptic", basedir);
let confname = format!("{}/{}", confdir, config::DEFAULT_CONF_NAME);
let dbname = String::from("token");
std::fs::create_dir_all(confdir).unwrap();
let mut testtokn = TestToken::new(dbname);
testtokn.make_config_file(&confname, None);
testtokn.setup_db(None);
let mut plist: *mut CK_FUNCTION_LIST = std::ptr::null_mut();
let pplist = &mut plist;
let result = fn_get_function_list(&mut *pplist);
assert_eq!(result, 0);
unsafe {
let list: CK_FUNCTION_LIST = *plist;
match list.C_Initialize {
Some(init_fn) => {
let mut args = TestToken::make_init_args(None);
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
env::remove_var("KRYOPTIC_CONF");
env::set_var("XDG_CONFIG_HOME", basedir);
let ret = force_load_config();
assert_eq!(ret, CKR_OK);
let ret = init_fn(args_ptr as *mut std::ffi::c_void);
env::remove_var("XDG_CONFIG_HOME");
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[cfg(feature = "sqlitedb")]
#[test]
#[serial]
fn test_token_sql() {
test_token_env(".sql");
test_token_null_args(".sql");
}
#[test]
#[parallel]
fn test_interface_null() {
let dbname = String::from("test_interface_null");
let mut testtokn = TestToken::new(dbname);
testtokn.setup_db(None);
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let result = fn_get_interface(
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut *ppiface,
0,
);
assert_eq!(result, CKR_OK);
unsafe {
let iface: CK_INTERFACE = *piface;
let list: CK_FUNCTION_LIST_3_0 =
*(iface.pFunctionList as CK_FUNCTION_LIST_3_0_PTR);
match list.C_Initialize {
Some(value) => {
let mut args = TestToken::make_init_args(Some(
testtokn.make_init_string(),
));
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
let ret = value(args_ptr as *mut std::ffi::c_void);
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[test]
#[parallel]
fn test_interface_pkcs11() {
let dbname = String::from("test_interface_pkcs11");
let mut testtokn = TestToken::new(dbname);
testtokn.setup_db(None);
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let result = fn_get_interface(
"PKCS 11\0".as_ptr() as CK_UTF8CHAR_PTR,
std::ptr::null_mut(),
&mut *ppiface,
0,
);
assert_eq!(result, CKR_OK);
unsafe {
let iface: CK_INTERFACE = *piface;
let list: CK_FUNCTION_LIST_3_0 =
*(iface.pFunctionList as CK_FUNCTION_LIST_3_0_PTR);
match list.C_Initialize {
Some(value) => {
let mut args = TestToken::make_init_args(Some(
testtokn.make_init_string(),
));
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
let ret = value(args_ptr as *mut std::ffi::c_void);
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[test]
#[parallel]
fn test_interface_pkcs11_version3() {
let dbname = String::from("test_interface_pkcs11_version3");
let mut testtokn = TestToken::new(dbname);
testtokn.setup_db(None);
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let mut version = { CK_VERSION { major: 3, minor: 0 } };
let result = fn_get_interface(
"PKCS 11\0".as_ptr() as CK_UTF8CHAR_PTR,
&mut version,
&mut *ppiface,
0,
);
assert_eq!(result, CKR_OK);
unsafe {
let iface: CK_INTERFACE = *piface;
let list: CK_FUNCTION_LIST_3_0 =
*(iface.pFunctionList as CK_FUNCTION_LIST_3_0_PTR);
match list.C_Initialize {
Some(value) => {
let mut args = TestToken::make_init_args(Some(
testtokn.make_init_string(),
));
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
let ret = value(args_ptr as *mut std::ffi::c_void);
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[test]
#[parallel]
fn test_interface_pkcs11_version240() {
let dbname = String::from("test_interface_pkcs11_version240");
let mut testtokn = TestToken::new(dbname);
testtokn.setup_db(None);
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let mut version = {
CK_VERSION {
major: 2,
minor: 40,
}
};
let result = fn_get_interface(
"PKCS 11\0".as_ptr() as CK_UTF8CHAR_PTR,
&mut version,
&mut *ppiface,
0,
);
assert_eq!(result, CKR_OK);
unsafe {
let iface: CK_INTERFACE = *piface;
let list: CK_FUNCTION_LIST =
*(iface.pFunctionList as CK_FUNCTION_LIST_PTR);
match list.C_Initialize {
Some(value) => {
let mut args = TestToken::make_init_args(Some(
testtokn.make_init_string(),
));
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
let ret = value(args_ptr as *mut std::ffi::c_void);
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
}
None => todo!(),
}
}
testtokn.finalize();
}
#[test]
#[parallel]
fn test_interface_invalid_name() {
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let result = fn_get_interface(
"MyPKCS 12\0".as_ptr() as CK_UTF8CHAR_PTR,
std::ptr::null_mut(),
&mut *ppiface,
0,
);
assert_eq!(result, CKR_ARGUMENTS_BAD);
}
#[test]
#[parallel]
fn test_interface_invalid_version() {
let mut piface: *mut CK_INTERFACE = std::ptr::null_mut();
let ppiface = &mut piface;
let mut version = {
CK_VERSION {
major: 2,
minor: 99,
}
};
let result = fn_get_interface(
"PKCS 11\0".as_ptr() as CK_UTF8CHAR_PTR,
&mut version,
&mut *ppiface,
0,
);
assert_eq!(result, CKR_ARGUMENTS_BAD);
}
#[test]
#[serial]
fn test_config_multiple_tokens() {
let name = String::from("test_config_multiple");
let confname = format!("{}/{}.conf", TESTDIR, name);
let dbs = [
#[cfg(feature = "sqlitedb")]
(
"sqlite",
format!("{}/{}.sql", TESTDIR, name),
"TOKEN SQLITEDB",
),
#[cfg(feature = "nssdb")]
(
"nssdb",
format!("configDir={}/{}", TESTDIR, name),
"TOKEN NSSDB",
),
];
let mut config = String::new();
let mut tokens = Vec::<TestToken>::new();
for db in &dbs {
let mut token =
TestToken::new_type(String::from(db.0), db.1.clone(), name.clone());
token.setup_db(None);
write!(
&mut config,
"[[slots]]\nslot = {}\ndbtype = \"{}\"\ndbargs = \"{}\"\ndescription = \"{}\"\n",
token.get_slot(),
db.0,
db.1,
db.2
)
.unwrap();
tokens.push(token);
}
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&confname)
.unwrap();
file.write(config.as_bytes()).unwrap();
let mut args = TestToken::make_init_args(None);
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
unsafe { env::set_var("KRYOPTIC_CONF", confname) };
let ret = force_load_config();
assert_eq!(ret, CKR_OK);
let ret = fn_initialize(args_ptr as *mut std::ffi::c_void);
unsafe { env::remove_var("KRYOPTIC_CONF") };
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
for tok in &tokens {
let mut info = CK_SLOT_INFO::default();
let ret =
fn_get_slot_info(tok.get_slot(), &mut info as CK_SLOT_INFO_PTR);
assert_eq!(ret, CKR_OK);
let desc = std::str::from_utf8(&info.slotDescription).unwrap();
assert_eq!(desc.starts_with("TOKEN "), true);
}
}