mod common;
use crate::common::{init_pins, USER_PIN};
use cryptoki::context::Function;
use cryptoki::error::{Error, RvError};
use cryptoki::mechanism::dsa::{HashSignAdditionalContext, HedgeType, SignAdditionalContext};
use cryptoki::mechanism::{Mechanism, MechanismType};
use cryptoki::object::{Attribute, AttributeType, SlhDsaParameterSetType};
use cryptoki::session::UserType;
use cryptoki::types::AuthPin;
use serial_test::serial;
use testresult::TestResult;
#[test]
#[serial]
fn slh_dsa() -> TestResult {
let (pkcs11, slot) = init_pins();
if !pkcs11.is_fn_supported(Function::VerifySignature) {
println!("SKIP: The PKCS#11 module does not support VerifySignature API");
pkcs11.finalize()?;
return Ok(());
}
let mechanism = Mechanism::SlhDsaKeyPairGen;
let mechanism_type = mechanism.mechanism_type();
if pkcs11
.get_mechanism_info(slot, mechanism.mechanism_type())
.is_err()
{
println!("SKIP: {mechanism_type} does not support key pair generation with this backend.");
pkcs11.finalize()?;
return Ok(());
}
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::ParameterSet(SlhDsaParameterSetType::SHA2_256F.into()),
Attribute::Verify(true),
];
let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let mechanism = Mechanism::SlhDsa(SignAdditionalContext::new(HedgeType::Preferred, None));
let data = [0xFF, 0x55, 0xDD];
let signature1 = session.sign(&mechanism, private, &data)?;
session.verify(&mechanism, public, &data, &signature1)?;
session.verify_signature_init(&mechanism, public, &signature1)?;
session.verify_signature(&data)?;
let context = [
0xEE, 0x0B, 0x3F, 0x67, 0x9F, 0xB5, 0x0F, 0x59, 0xAD, 0x31, 0x32, 0x8A, 0xAF, 0x4E, 0x70,
0x2C, 0xCF, 0x60, 0x92, 0xDA, 0x47, 0x94, 0xDC, 0xF0, 0x7C, 0x8, 0xEA, 0x27, 0x8B, 0x34,
0x22, 0x8A, 0x41,
];
let mechanism = Mechanism::SlhDsa(SignAdditionalContext::new(
HedgeType::DeterministicRequired,
Some(&context),
));
let signature2 = session.sign(&mechanism, private, &data)?;
let signature3 = session.sign(&mechanism, private, &data)?;
assert_eq!(signature2, signature3);
session.verify(&mechanism, public, &data, &signature2)?;
session.verify_signature_init(&mechanism, public, &signature2)?;
session.verify_signature(&data)?;
let result = session.verify(&mechanism, public, &data, &signature1);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
Error::Pkcs11(_, Function::Verify)
));
session.verify_signature_init(&mechanism, public, &signature1)?;
let result = session.verify_signature(&data);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
Error::Pkcs11(_, Function::VerifySignature)
));
let param_attribute = session
.get_attributes(public, &[AttributeType::ParameterSet])?
.remove(0);
let param: SlhDsaParameterSetType = if let Attribute::ParameterSet(num) = param_attribute {
num.into()
} else {
panic!("Expected ParameterSet attribute.");
};
assert_eq!(param, SlhDsaParameterSetType::SHA2_256F);
session.destroy_object(public)?;
session.destroy_object(private)?;
session.close()?;
pkcs11.finalize()?;
Ok(())
}
#[test]
#[serial]
fn slh_dsa_multipart() -> TestResult {
let (pkcs11, slot) = init_pins();
if !pkcs11.is_fn_supported(Function::VerifySignature) {
println!("SKIP: The PKCS#11 module does not support VerifySignature API");
pkcs11.finalize()?;
return Ok(());
}
let mechanism = Mechanism::SlhDsaKeyPairGen;
let mechanism_type = mechanism.mechanism_type();
if pkcs11
.get_mechanism_info(slot, mechanism.mechanism_type())
.is_err()
{
println!("SKIP: {mechanism_type} does not support key pair generation with this backend.");
pkcs11.finalize()?;
return Ok(());
}
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::ParameterSet(SlhDsaParameterSetType::SHA2_192S.into()),
Attribute::Verify(true),
];
let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let mechanism = Mechanism::SlhDsa(SignAdditionalContext::new(HedgeType::Required, None));
let data = [
0x1E, 0x5A, 0x78, 0xAD, 0x64, 0xDF, 0x22, 0x9A, 0xA2, 0x2F, 0xD7, 0x94, 0xEC, 0x0E, 0x82,
0xD0, 0xF6, 0x99, 0x53, 0x11, 0x8C, 0x09, 0xD1, 0x34, 0xDF, 0xA2, 0x0F, 0x1C, 0xC6, 0x4A,
0x36, 0x71,
];
session.sign_init(&mechanism, private)?;
for part in data.chunks(10) {
session.sign_update(part)?;
}
let signature = session.sign_final()?;
session.verify_init(&mechanism, public)?;
for part in data.chunks(10) {
session.verify_update(part)?;
}
session.verify_final(&signature)?;
session.verify_signature_init(&mechanism, public, &signature)?;
for part in data.chunks(10) {
session.verify_signature_update(part)?;
}
session.verify_signature_final()?;
session.destroy_object(public)?;
session.destroy_object(private)?;
session.close()?;
pkcs11.finalize()?;
Ok(())
}
#[test]
#[serial]
fn slh_dsa_hash() -> TestResult {
let (pkcs11, slot) = init_pins();
if !pkcs11.is_fn_supported(Function::VerifySignature) {
println!("SKIP: The PKCS#11 module does not support VerifySignature API");
pkcs11.finalize()?;
return Ok(());
}
let mechanism = Mechanism::SlhDsaKeyPairGen;
let mechanism_type = mechanism.mechanism_type();
if pkcs11
.get_mechanism_info(slot, mechanism.mechanism_type())
.is_err()
{
println!("SKIP: {mechanism_type} does not support key pair generation with this backend.");
pkcs11.finalize()?;
return Ok(());
}
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::ParameterSet(SlhDsaParameterSetType::SHA2_128S.into()),
Attribute::Verify(true),
];
let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let mechanism = Mechanism::HashSlhDsa(HashSignAdditionalContext::new(
HedgeType::Preferred,
None,
MechanismType::SHA384,
));
let data = [
0x1E, 0x5A, 0x78, 0xAD, 0x64, 0xDF, 0x22, 0x9A, 0xA2, 0x2F, 0xD7, 0x94, 0xEC, 0x0E, 0x82,
0xD0, 0xF6, 0x99, 0x53, 0x11, 0x8C, 0x09, 0xD1, 0x34, 0xDF, 0xA2, 0x0F, 0x1C, 0xC6, 0x4A,
0xD0, 0xF6, 0x99, 0x53, 0x11, 0x8C, 0x09, 0xD1, 0x34, 0xDF, 0xA2, 0x0F, 0x1C, 0xC6, 0x4A,
0x36, 0x71, 0x31,
];
session.sign_init(&mechanism, private)?;
let result = session.sign_update(&data[..10]);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
Error::Pkcs11(RvError::OperationNotInitialized, Function::SignUpdate)
));
let signature = session.sign(&mechanism, private, &data)?;
session.verify_init(&mechanism, public)?;
let result = session.verify_update(&data[..10]);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
Error::Pkcs11(RvError::OperationNotInitialized, Function::VerifyUpdate)
));
session.verify(&mechanism, public, &data, &signature)?;
session.verify_signature_init(&mechanism, public, &signature)?;
let result = session.verify_signature_update(&data[..10]);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
Error::Pkcs11(
RvError::OperationNotInitialized,
Function::VerifySignatureUpdate
)
));
session.verify_signature_init(&mechanism, public, &signature)?;
session.verify_signature(&data)?;
session.destroy_object(public)?;
session.destroy_object(private)?;
session.close()?;
pkcs11.finalize()?;
Ok(())
}
#[test]
#[serial]
fn slh_dsa_hashes() -> TestResult {
let (pkcs11, slot) = init_pins();
if !pkcs11.is_fn_supported(Function::VerifySignature) {
println!("SKIP: The PKCS#11 module does not support VerifySignature API");
pkcs11.finalize()?;
return Ok(());
}
let mechanism = Mechanism::SlhDsaKeyPairGen;
let mechanism_type = mechanism.mechanism_type();
if pkcs11
.get_mechanism_info(slot, mechanism.mechanism_type())
.is_err()
{
println!("SKIP: {mechanism_type} does not support key pair generation with this backend.");
pkcs11.finalize()?;
return Ok(());
}
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::ParameterSet(SlhDsaParameterSetType::SHA2_128F.into()),
Attribute::Verify(true),
];
let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let mechanism =
Mechanism::HashSlhDsaSha3_224(SignAdditionalContext::new(HedgeType::Required, None));
let data = [
0xD0, 0xF6, 0x99, 0x53, 0x11, 0x8C, 0x09, 0xD1, 0x34, 0xDF, 0xA2, 0x0F, 0x1C, 0xC6, 0x4A,
0x1E, 0x5A, 0x78, 0xAD, 0x64, 0xDF, 0x22, 0x9A, 0xA2, 0x2F, 0xD7, 0x94, 0xEC, 0x0E, 0x82,
];
session.sign_init(&mechanism, private)?;
for part in data.chunks(10) {
session.sign_update(part)?;
}
let signature = session.sign_final()?;
let signature2 = session.sign(&mechanism, private, &data)?;
session.verify_init(&mechanism, public)?;
for part in data.chunks(10) {
session.verify_update(part)?;
}
session.verify_final(&signature)?;
session.verify(&mechanism, public, &data, &signature)?;
session.verify_signature_init(&mechanism, public, &signature2)?;
for part in data.chunks(10) {
session.verify_signature_update(part)?;
}
session.verify_signature_final()?;
session.verify_signature_init(&mechanism, public, &signature2)?;
session.verify_signature(&data)?;
session.destroy_object(public)?;
session.destroy_object(private)?;
session.close()?;
pkcs11.finalize()?;
Ok(())
}