mod common;
use crate::common::{init_pins, USER_PIN};
use cryptoki::context::Function;
use cryptoki::mechanism::Mechanism;
use cryptoki::object::{Attribute, AttributeType, KeyType, MlKemParameterSetType, ObjectClass};
use cryptoki::session::UserType;
use cryptoki::types::AuthPin;
use serial_test::serial;
use testresult::TestResult;
#[test]
#[serial]
fn ml_kem() -> TestResult {
let (pkcs11, slot) = init_pins();
if !pkcs11.is_fn_supported(Function::EncapsulateKey) {
print!("SKIP: The PKCS#11 module does not support encapsulation API");
pkcs11.finalize()?;
return Ok(());
}
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let mechanism = Mechanism::MlKemKeyPairGen;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::ParameterSet(MlKemParameterSetType::ML_KEM_768.into()),
Attribute::Encapsulate(true),
];
let priv_key_template = vec![Attribute::Token(true), Attribute::Decapsulate(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let secret_template = vec![
Attribute::Token(true),
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Sensitive(false),
Attribute::Extractable(true),
Attribute::Encrypt(true),
Attribute::Decrypt(true),
];
let mechanism = Mechanism::MlKem;
let (ciphertext, secret) = session.encapsulate_key(&mechanism, public, &secret_template)?;
let secret2 = session.decapsulate_key(&mechanism, private, &secret_template, &ciphertext)?;
let value_attribute = session
.get_attributes(secret, &[AttributeType::Value])?
.remove(0);
let value = if let Attribute::Value(value) = value_attribute {
value
} else {
panic!("Expected value attribute.");
};
let value_attribute2 = session
.get_attributes(secret2, &[AttributeType::Value])?
.remove(0);
let value2 = if let Attribute::Value(value) = value_attribute2 {
value
} else {
panic!("Expected value attribute.");
};
assert_eq!(value, value2);
let data = vec![
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f,
];
let ctext = session.encrypt(&Mechanism::AesEcb, secret, &data)?;
let ptext = session.decrypt(&Mechanism::AesEcb, secret2, &ctext)?;
assert_eq!(data, ptext);
let ctext = session.encrypt(&Mechanism::AesEcb, secret2, &data)?;
let ptext = session.decrypt(&Mechanism::AesEcb, secret, &ctext)?;
assert_eq!(data, ptext);
let param_attribute = session
.get_attributes(public, &[AttributeType::ParameterSet])?
.remove(0);
let param: MlKemParameterSetType = if let Attribute::ParameterSet(num) = param_attribute {
num.into()
} else {
panic!("Expected ParameterSet attribute.");
};
assert_eq!(param, MlKemParameterSetType::ML_KEM_768);
session.destroy_object(public)?;
session.destroy_object(private)?;
session.destroy_object(secret)?;
session.destroy_object(secret2)?;
session.close()?;
pkcs11.finalize()?;
Ok(())
}