use super::set_fips_error_state;
use crate::attribute::Attribute;
use crate::error::Result;
use crate::hmac::test_get_hmac;
use crate::mechanism::Verify;
use crate::native::hmac::HMACOperation;
use crate::native::tlskdf::TLSPRF;
use crate::object::Object;
use crate::pkcs11::*;
use std::sync::LazyLock;
pub struct FIPSSelftest {
pub result: CK_RV,
}
impl FIPSSelftest {
fn fail() -> FIPSSelftest {
set_fips_error_state();
FIPSSelftest {
result: CKR_FIPS_SELF_TEST_FAILED,
}
}
fn pass() -> FIPSSelftest {
FIPSSelftest { result: CKR_OK }
}
}
pub static HMAC_SELFTEST: LazyLock<FIPSSelftest> = LazyLock::new(|| {
let plaintext: [u8; 16] = [
0xDD, 0x0C, 0x30, 0x33, 0x35, 0xF9, 0xE4, 0x2E, 0xC2, 0xEF, 0xCC, 0xBF,
0x07, 0x95, 0xEE, 0xA2,
];
let secret: Vec<u8> = vec![
0xF4, 0x55, 0x66, 0x50, 0xAC, 0x31, 0xD3, 0x54, 0x61, 0x61, 0x0B, 0xAC,
0x4E, 0xD8, 0x1B, 0x1A, 0x18, 0x1B, 0x2D, 0x8A, 0x43, 0xEA, 0x28, 0x54,
0xCB, 0xAE, 0x22, 0xCA, 0x74, 0x56, 0x08, 0x13,
];
let expect: [u8; 32] = [
0xF5, 0xF5, 0xE5, 0xF2, 0x66, 0x49, 0xE2, 0x40, 0xFC, 0x9E, 0x85, 0x7F,
0x2B, 0x9A, 0xBE, 0x28, 0x20, 0x12, 0x00, 0x92, 0x82, 0x21, 0x3E, 0x51,
0x44, 0x5D, 0xE3, 0x31, 0x04, 0x01, 0x72, 0x6B,
];
let mut hmac = match HMACOperation::internal(CKM_SHA256_HMAC, secret, 32) {
Ok(h) => h,
Err(_) => return FIPSSelftest::fail(),
};
if Verify::verify(&mut hmac, &plaintext, &expect).is_err() {
return FIPSSelftest::fail();
}
FIPSSelftest::pass()
});
fn secret_key_object(secret: Vec<u8>) -> Result<Object> {
let mut key = Object::new(CKO_SECRET_KEY);
key.set_attr(Attribute::from_ulong(CKA_KEY_TYPE, CKK_GENERIC_SECRET))?;
key.set_attr(Attribute::from_ulong(
CKA_VALUE_LEN,
secret.len() as CK_ULONG,
))?;
key.set_attr(Attribute::from_bytes(CKA_VALUE, secret))?;
key.set_attr(Attribute::from_bool(CKA_DERIVE, true))?;
Ok(key)
}
pub static TLS_PRF_SELFTEST: LazyLock<FIPSSelftest> = LazyLock::new(|| {
let prf: CK_MECHANISM_TYPE = CKM_SHA256_HMAC;
let secret: Vec<u8> = vec![
0x20, 0x2C, 0x88, 0xC0, 0x0F, 0x84, 0xA1, 0x7A, 0x20, 0x02, 0x70, 0x79,
0x60, 0x47, 0x87, 0x46, 0x11, 0x76, 0x45, 0x55, 0x39, 0xE7, 0x05, 0xBE,
0x73, 0x08, 0x90, 0x60, 0x2C, 0x28, 0x9A, 0x50, 0x01, 0xE3, 0x4E, 0xEB,
0x3A, 0x04, 0x3E, 0x5D, 0x52, 0xA6, 0x5E, 0x66, 0x12, 0x51, 0x88, 0xBF,
];
let seed: Vec<u8> = vec![
b'k', b'e', b'y', b' ', b'e', b'x', b'p', b'a', b'n', b's', b'i', b'o',
b'n', 0xAE, 0x6C, 0x80, 0x6F, 0x8A, 0xD4, 0xD8, 0x07, 0x84, 0x54, 0x9D,
0xFF, 0x28, 0xA4, 0xB5, 0x8F, 0xD8, 0x37, 0x68, 0x1A, 0x51, 0xD9, 0x28,
0xC3, 0xE3, 0x0E, 0xE5, 0xFF, 0x14, 0xF3, 0x98, 0x68, 0x62, 0xE1, 0xFD,
0x91, 0xF2, 0x3F, 0x55, 0x8A, 0x60, 0x5F, 0x28, 0x47, 0x8C, 0x58, 0xCF,
0x72, 0x63, 0x7B, 0x89, 0x78, 0x4D, 0x95, 0x9D, 0xF7, 0xE9, 0x46, 0xD3,
0xF0, 0x7B, 0xD1, 0xB6, 0x16,
];
let expect: Vec<u8> = vec![
0xD0, 0x61, 0x39, 0x88, 0x9F, 0xFF, 0xAC, 0x1E, 0x3A, 0x71, 0x86, 0x5F,
0x50, 0x4A, 0xA5, 0xD0, 0xD2, 0xA2, 0xE8, 0x95, 0x06, 0xC6, 0xF2, 0x27,
0x9B, 0x67, 0x0C, 0x3E, 0x1B, 0x74, 0xF5, 0x31, 0x01, 0x6A, 0x25, 0x30,
0xC5, 0x1A, 0x3A, 0x0F, 0x7E, 0x1D, 0x65, 0x90, 0xD0, 0xF0, 0x56, 0x6B,
0x2F, 0x38, 0x7F, 0x8D, 0x11, 0xFD, 0x4F, 0x73, 0x1C, 0xDD, 0x57, 0x2D,
0x2E, 0xAE, 0x92, 0x7F, 0x6F, 0x2F, 0x81, 0x41, 0x0B, 0x25, 0xE6, 0x96,
0x0B, 0xE6, 0x89, 0x85, 0xAD, 0xD6, 0xC3, 0x84, 0x45, 0xAD, 0x9F, 0x8C,
0x64, 0xBF, 0x80, 0x68, 0xBF, 0x9A, 0x66, 0x79, 0x48, 0x5D, 0x96, 0x6F,
0x1A, 0xD6, 0xF6, 0x8B, 0x43, 0x49, 0x5B, 0x10, 0xA6, 0x83, 0x75, 0x5E,
0xA2, 0xB8, 0x58, 0xD7, 0x0C, 0xCA, 0xC7, 0xEC, 0x8B, 0x05, 0x3C, 0x6B,
0xD4, 0x1C, 0xA2, 0x99, 0xD4, 0xE5, 0x19, 0x28,
];
let key = match secret_key_object(secret) {
Ok(s) => s,
Err(_) => return FIPSSelftest::fail(),
};
let mech = test_get_hmac(prf);
let mut tlsprf = match TLSPRF::init(&key, &mech, prf) {
Ok(a) => a,
Err(_) => return FIPSSelftest::fail(),
};
let out = match tlsprf.finish(&seed, expect.len()) {
Ok(a) => a,
Err(_) => return FIPSSelftest::fail(),
};
if out == expect {
FIPSSelftest::pass()
} else {
FIPSSelftest::fail()
}
});