diff --git a/psa-crypto-sys/src/constants.rs b/psa-crypto-sys/src/constants.rs index e546798..9945b61 100644 --- a/psa-crypto-sys/src/constants.rs +++ b/psa-crypto-sys/src/constants.rs @@ -88,6 +88,7 @@ pub const PSA_ALG_RSA_PKCS1V15_CRYPT: psa_algorithm_t = 302_120_960; pub const PSA_KEY_LIFETIME_VOLATILE: psa_key_lifetime_t = 0; pub const PSA_KEY_LIFETIME_PERSISTENT: psa_key_lifetime_t = 1; pub const PSA_KEY_USAGE_EXPORT: psa_key_usage_t = 1; +pub const PSA_KEY_USAGE_COPY: psa_key_usage_t = 2; pub const PSA_KEY_USAGE_ENCRYPT: psa_key_usage_t = 256; pub const PSA_KEY_USAGE_DECRYPT: psa_key_usage_t = 512; pub const PSA_KEY_USAGE_SIGN: psa_key_usage_t = 1024; diff --git a/psa-crypto/Cargo.toml b/psa-crypto/Cargo.toml index ba73fbd..e14a861 100644 --- a/psa-crypto/Cargo.toml +++ b/psa-crypto/Cargo.toml @@ -25,7 +25,7 @@ rand = "0.7.3" base64 = "0.12.3" [features] -default = ["operations", "no-std"] +default = ["operations"] operations = ["psa-crypto-sys/operations", "interface"] interface = ["psa-crypto-sys/interface"] no-std = [] diff --git a/psa-crypto/src/operations/aead.rs b/psa-crypto/src/operations/aead.rs index a67087c..cb803b9 100644 --- a/psa-crypto/src/operations/aead.rs +++ b/psa-crypto/src/operations/aead.rs @@ -38,7 +38,7 @@ use crate::types::status::{Result, Status}; /// }; /// psa_crypto::init().unwrap(); /// let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); -/// let output_buffer_size = unsafe { psa_crypto_sys::PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg.into(), INPUT_DATA.len()) }; +/// let output_buffer_size = psa_crypto_sys::PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg.into(), INPUT_DATA.len()); /// let mut output_buffer = vec![0; output_buffer_size]; /// let length = aead::encrypt(my_key, alg, &NONCE, &ADDITIONAL_DATA, &INPUT_DATA, &mut output_buffer).unwrap(); /// output_buffer.resize(length, 0); diff --git a/psa-crypto/src/operations/hash.rs b/psa-crypto/src/operations/hash.rs index dfaa6d4..4198282 100644 --- a/psa-crypto/src/operations/hash.rs +++ b/psa-crypto/src/operations/hash.rs @@ -54,17 +54,13 @@ pub fn hash_compute(hash_alg: Hash, input: &[u8], hash: &mut [u8]) -> Result Result<()> { initialized()?; diff --git a/psa-crypto/src/operations/key_agreement.rs b/psa-crypto/src/operations/key_agreement.rs index a8ceb11..737bde9 100644 --- a/psa-crypto/src/operations/key_agreement.rs +++ b/psa-crypto/src/operations/key_agreement.rs @@ -13,8 +13,7 @@ use crate::types::status::{Result, Status}; /// ``` /// use psa_crypto::operations::{key_agreement, key_management}; /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags, EccFamily}; -/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash, KeyAgreement, RawKeyAgreement, Algorithm}; -/// use psa_crypto::operations::key_agreement::raw_key_agreement; +/// use psa_crypto::types::algorithm::{KeyAgreement, RawKeyAgreement}; /// /// # const PEER_PUBLIC_KEY: [u8; 65] = [0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, /// # 0x70, 0x39, 0x8c, 0x34, 0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, 0x63, @@ -25,7 +24,7 @@ use crate::types::status::{Result, Status}; /// # const OUR_KEY_DATA: [u8; 32] = [0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, /// # 0x31, 0x6d, 0xe5, 0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33]; /// let alg = RawKeyAgreement::Ecdh; -/// # let mut attributes = Attributes { +/// # let attributes = Attributes { /// # key_type: Type::EccKeyPair {curve_family: EccFamily::SecpR1 }, /// # bits: 0, /// # lifetime: Lifetime::Volatile, diff --git a/psa-crypto/src/operations/key_management.rs b/psa-crypto/src/operations/key_management.rs index a96a97d..f1dcf09 100644 --- a/psa-crypto/src/operations/key_management.rs +++ b/psa-crypto/src/operations/key_management.rs @@ -298,7 +298,9 @@ pub(crate) fn complete_new_key_operation( handle: psa_key_handle_t, ) -> Result { if key_lifetime != Lifetime::Volatile { - Status::from(unsafe { psa_crypto_sys::psa_close_key(handle) }).to_result()?; + Status::from(unsafe { psa_crypto_sys::psa_close_key(handle) }) + .to_result() + .unwrap(); } Ok(Id { id, @@ -322,29 +324,28 @@ pub(crate) fn complete_new_key_operation( /// ``` /// use psa_crypto::operations::key_management; /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; -/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; +/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash, Algorithm}; +/// let key_data = [0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xaf, 0x05, 0x7d, 0x39, 0x6e, 0xe8, 0x4f, 0xb7, 0x5f, 0xdb, 0xb5, 0xc2, 0xb1, 0x3c, 0x7f, 0xe5, 0xa6, 0x54, 0xaa, 0x8a, 0xa2, 0x47, 0x0b, 0x54, 0x1e, 0xe1, 0xfe, 0xb0, 0xb1, 0x2d, 0x25, 0xc7, 0x97, 0x11, 0x53, 0x12, 0x49, 0xe1, 0x12, 0x96, 0x28, 0x04, 0x2d, 0xbb, 0xb6, 0xc1, 0x20, 0xd1, 0x44, 0x35, 0x24, 0xef, 0x4c, 0x0e, 0x6e, 0x1d, 0x89, 0x56, 0xee, 0xb2, 0x07, 0x7a, 0xf1, 0x23, 0x49, 0xdd, 0xee, 0xe5, 0x44, 0x83, 0xbc, 0x06, 0xc2, 0xc6, 0x19, 0x48, 0xcd, 0x02, 0xb2, 0x02, 0xe7, 0x96, 0xae, 0xbd, 0x94, 0xd3, 0xa7, 0xcb, 0xf8, 0x59, 0xc2, 0xc1, 0x81, 0x9c, 0x32, 0x4c, 0xb8, 0x2b, 0x9c, 0xd3, 0x4e, 0xde, 0x26, 0x3a, 0x2a, 0xbf, 0xfe, 0x47, 0x33, 0xf0, 0x77, 0x86, 0x9e, 0x86, 0x60, 0xf7, 0xd6, 0x83, 0x4d, 0xa5, 0x3d, 0x69, 0x0e, 0xf7, 0x98, 0x5f, 0x6b, 0xc3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x81, 0x00, 0x87, 0x4b, 0xf0, 0xff, 0xc2, 0xf2, 0xa7, 0x1d, 0x14, 0x67, 0x1d, 0xdd, 0x01, 0x71, 0xc9, 0x54, 0xd7, 0xfd, 0xbf, 0x50, 0x28, 0x1e, 0x4f, 0x6d, 0x99, 0xea, 0x0e, 0x1e, 0xbc, 0xf8, 0x2f, 0xaa, 0x58, 0xe7, 0xb5, 0x95, 0xff, 0xb2, 0x93, 0xd1, 0xab, 0xe1, 0x7f, 0x11, 0x0b, 0x37, 0xc4, 0x8c, 0xc0, 0xf3, 0x6c, 0x37, 0xe8, 0x4d, 0x87, 0x66, 0x21, 0xd3, 0x27, 0xf6, 0x4b, 0xbe, 0x08, 0x45, 0x7d, 0x3e, 0xc4, 0x09, 0x8b, 0xa2, 0xfa, 0x0a, 0x31, 0x9f, 0xba, 0x41, 0x1c, 0x28, 0x41, 0xed, 0x7b, 0xe8, 0x31, 0x96, 0xa8, 0xcd, 0xf9, 0xda, 0xa5, 0xd0, 0x06, 0x94, 0xbc, 0x33, 0x5f, 0xc4, 0xc3, 0x22, 0x17, 0xfe, 0x04, 0x88, 0xbc, 0xe9, 0xcb, 0x72, 0x02, 0xe5, 0x94, 0x68, 0xb1, 0xea, 0xd1, 0x19, 0x00, 0x04, 0x77, 0xdb, 0x2c, 0xa7, 0x97, 0xfa, 0xc1, 0x9e, 0xda, 0x3f, 0x58, 0xc1, 0x02, 0x41, 0x00, 0xe2, 0xab, 0x76, 0x08, 0x41, 0xbb, 0x9d, 0x30, 0xa8, 0x1d, 0x22, 0x2d, 0xe1, 0xeb, 0x73, 0x81, 0xd8, 0x22, 0x14, 0x40, 0x7f, 0x1b, 0x97, 0x5c, 0xbb, 0xfe, 0x4e, 0x1a, 0x94, 0x67, 0xfd, 0x98, 0xad, 0xbd, 0x78, 0xf6, 0x07, 0x83, 0x6c, 0xa5, 0xbe, 0x19, 0x28, 0xb9, 0xd1, 0x60, 0xd9, 0x7f, 0xd4, 0x5c, 0x12, 0xd6, 0xb5, 0x2e, 0x2c, 0x98, 0x71, 0xa1, 0x74, 0xc6, 0x6b, 0x48, 0x81, 0x13, 0x02, 0x41, 0x00, 0xc5, 0xab, 0x27, 0x60, 0x21, 0x59, 0xae, 0x7d, 0x6f, 0x20, 0xc3, 0xc2, 0xee, 0x85, 0x1e, 0x46, 0xdc, 0x11, 0x2e, 0x68, 0x9e, 0x28, 0xd5, 0xfc, 0xbb, 0xf9, 0x90, 0xa9, 0x9e, 0xf8, 0xa9, 0x0b, 0x8b, 0xb4, 0x4f, 0xd3, 0x64, 0x67, 0xe7, 0xfc, 0x17, 0x89, 0xce, 0xb6, 0x63, 0xab, 0xda, 0x33, 0x86, 0x52, 0xc3, 0xc7, 0x3f, 0x11, 0x17, 0x74, 0x90, 0x2e, 0x84, 0x05, 0x65, 0x92, 0x70, 0x91, 0x02, 0x41, 0x00, 0xb6, 0xcd, 0xbd, 0x35, 0x4f, 0x7d, 0xf5, 0x79, 0xa6, 0x3b, 0x48, 0xb3, 0x64, 0x3e, 0x35, 0x3b, 0x84, 0x89, 0x87, 0x77, 0xb4, 0x8b, 0x15, 0xf9, 0x4e, 0x0b, 0xfc, 0x05, 0x67, 0xa6, 0xae, 0x59, 0x11, 0xd5, 0x7a, 0xd6, 0x40, 0x9c, 0xf7, 0x64, 0x7b, 0xf9, 0x62, 0x64, 0xe9, 0xbd, 0x87, 0xeb, 0x95, 0xe2, 0x63, 0xb7, 0x11, 0x0b, 0x9a, 0x1f, 0x9f, 0x94, 0xac, 0xce, 0xd0, 0xfa, 0xfa, 0x4d, 0x02, 0x40, 0x71, 0x19, 0x5e, 0xec, 0x37, 0xe8, 0xd2, 0x57, 0xde, 0xcf, 0xc6, 0x72, 0xb0, 0x7a, 0xe6, 0x39, 0xf1, 0x0c, 0xbb, 0x9b, 0x0c, 0x73, 0x9d, 0x0c, 0x80, 0x99, 0x68, 0xd6, 0x44, 0xa9, 0x4e, 0x3f, 0xd6, 0xed, 0x92, 0x87, 0x07, 0x7a, 0x14, 0x58, 0x3f, 0x37, 0x90, 0x58, 0xf7, 0x6a, 0x8a, 0xec, 0xd4, 0x3c, 0x62, 0xdc, 0x8c, 0x0f, 0x41, 0x76, 0x66, 0x50, 0xd7, 0x25, 0x27, 0x5a, 0xc4, 0xa1, 0x02, 0x41, 0x00, 0xbb, 0x32, 0xd1, 0x33, 0xed, 0xc2, 0xe0, 0x48, 0xd4, 0x63, 0x38, 0x8b, 0x7b, 0xe9, 0xcb, 0x4b, 0xe2, 0x9f, 0x4b, 0x62, 0x50, 0xbe, 0x60, 0x3e, 0x70, 0xe3, 0x64, 0x75, 0x01, 0xc9, 0x7d, 0xdd, 0xe2, 0x0a, 0x4e, 0x71, 0xbe, 0x95, 0xfd, 0x5e, 0x71, 0x78, 0x4e, 0x25, 0xac, 0xa4, 0xba, 0xf2, 0x5b, 0xe5, 0x73, 0x8a, 0xae, 0x59, 0xbb, 0xfe, 0x1c, 0x99, 0x77, 0x81, 0x44, 0x7a, 0x2b, 0x24]; /// # let mut attributes = Attributes { /// # key_type: Type::RsaKeyPair, /// # bits: 1024, /// # lifetime: Lifetime::Volatile, /// # policy: Policy { /// # usage_flags: UsageFlags { -/// # copy: true, -/// # ..Default::default() +/// copy: true, +/// export: true, +/// .. Default::default() /// # }, -/// # permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { -/// # hash_alg: Hash::Sha256.into(), -/// # }.into(), +/// # permitted_algorithms: Algorithm::None, /// # }, /// # }; /// psa_crypto::init().unwrap(); -/// let my_key = key_management::generate(attributes, None).unwrap(); -/// let my_key_copy = key_management::copy(my_key, attributes, None); +/// let my_key = key_management::import(attributes, None, &key_data).unwrap(); +/// let my_key_copy = key_management::copy(my_key, attributes, None).unwrap(); /// ``` pub fn copy(key_id_to_copy: Id, attributes: Attributes, id: Option) -> Result { initialized()?; let key_handle_to_copy = key_id_to_copy.handle()?; - let mut key_attributes = psa_crypto_sys::psa_key_attributes_t::try_from(attributes)?; let id = if let Some(id) = id { unsafe { psa_crypto_sys::psa_set_key_id(&mut key_attributes, id) }; diff --git a/psa-crypto/src/types/key.rs b/psa-crypto/src/types/key.rs index 33b17c6..787c96f 100644 --- a/psa-crypto/src/types/key.rs +++ b/psa-crypto/src/types/key.rs @@ -774,6 +774,9 @@ impl From for psa_crypto_sys::psa_key_usage_t { if flags.derive { usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_DERIVE; } + if flags.copy { + usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_COPY; + } usage_flags } } diff --git a/psa-crypto/tests/aead.rs b/psa-crypto/tests/aead.rs new file mode 100644 index 0000000..fe37a9d --- /dev/null +++ b/psa-crypto/tests/aead.rs @@ -0,0 +1,185 @@ +use psa_crypto::operations::{aead, key_management}; +use psa_crypto::types::algorithm::{Aead, AeadWithDefaultLengthTag}; +use psa_crypto::types::key::{Attributes, Lifetime, Policy, Type, UsageFlags}; +use psa_crypto::types::status::Error; + +const KEY_DATA: [u8; 16] = [ + 0x41, 0x89, 0x35, 0x1B, 0x5C, 0xAE, 0xA3, 0x75, 0xA0, 0x29, 0x9E, 0x81, 0xC6, 0x21, 0xBF, 0x43, +]; +const NONCE: [u8; 13] = [ + 0x48, 0xc0, 0x90, 0x69, 0x30, 0x56, 0x1e, 0x0a, 0xb0, 0xef, 0x4c, 0xd9, 0x72, +]; +const ADDITIONAL_DATA: [u8; 32] = [ + 0x40, 0xa2, 0x7c, 0x1d, 0x1e, 0x23, 0xea, 0x3d, 0xbe, 0x80, 0x56, 0xb2, 0x77, 0x48, 0x61, 0xa4, + 0xa2, 0x01, 0xcc, 0xe4, 0x9f, 0x19, 0x99, 0x7d, 0x19, 0x20, 0x6d, 0x8c, 0x8a, 0x34, 0x39, 0x51, +]; +const DECRYPTED_DATA: [u8; 24] = [ + 0x45, 0x35, 0xd1, 0x2b, 0x43, 0x77, 0x92, 0x8a, 0x7c, 0x0a, 0x61, 0xc9, 0xf8, 0x25, 0xa4, 0x86, + 0x71, 0xea, 0x05, 0x91, 0x07, 0x48, 0xc8, 0xef, +]; +const ENCRYPTED_DATA: [u8; 40] = [ + 0x26, 0xc5, 0x69, 0x61, 0xc0, 0x35, 0xa7, 0xe4, 0x52, 0xcc, 0xe6, 0x1b, 0xc6, 0xee, 0x22, 0x0d, + 0x77, 0xb3, 0xf9, 0x4d, 0x18, 0xfd, 0x10, 0xb6, 0xd8, 0x0e, 0x8b, 0xf8, 0x0f, 0x4a, 0x46, 0xca, + 0xb0, 0x6d, 0x43, 0x13, 0xf0, 0xdb, 0x9b, 0xe9, +]; + +#[test] +fn aead_encrypt_aes_ccm() { + let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm); + let attributes = Attributes { + key_type: Type::Aes, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + encrypt: true, + ..Default::default() + }, + permitted_algorithms: alg.into(), + }, + }; + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); + let output_buffer_size = + psa_crypto_sys::PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg.into(), DECRYPTED_DATA.len()); + let mut output_buffer = vec![0; output_buffer_size]; + let length = aead::encrypt( + my_key, + alg, + &NONCE, + &ADDITIONAL_DATA, + &DECRYPTED_DATA, + &mut output_buffer, + ) + .unwrap(); + output_buffer.resize(length, 0); + assert_eq!(&ENCRYPTED_DATA[..], &output_buffer[..]); +} + +#[test] +fn aead_encrypt_aes_ccm_no_encrypt_usage_flag() { + let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm); + let attributes = Attributes { + key_type: Type::Aes, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + ..Default::default() + }, + permitted_algorithms: alg.into(), + }, + }; + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); + let output_buffer_size = + psa_crypto_sys::PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg.into(), DECRYPTED_DATA.len()); + let mut output_buffer = vec![0; output_buffer_size]; + let result = aead::encrypt( + my_key, + alg, + &NONCE, + &ADDITIONAL_DATA, + &DECRYPTED_DATA, + &mut output_buffer, + ); + assert_eq!(Err(Error::NotPermitted), result) +} + +#[test] +fn aead_decrypt_aes_ccm() { + let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm); + let attributes = Attributes { + key_type: Type::Aes, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + decrypt: true, + ..Default::default() + }, + permitted_algorithms: alg.into(), + }, + }; + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); + let output_buffer_size = + psa_crypto_sys::PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg.into(), ENCRYPTED_DATA.len()); + let mut output_buffer = vec![0; output_buffer_size]; + let length = aead::decrypt( + my_key, + alg, + &NONCE, + &ADDITIONAL_DATA, + &ENCRYPTED_DATA, + &mut output_buffer, + ) + .unwrap(); + output_buffer.resize(length, 0); + assert_eq!(&DECRYPTED_DATA[..], &output_buffer[..]); +} + +#[test] +fn aead_decrypt_aes_ccm_no_decrypt_usage_flag() { + let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm); + let attributes = Attributes { + key_type: Type::Aes, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + ..Default::default() + }, + permitted_algorithms: alg.into(), + }, + }; + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); + let output_buffer_size = + psa_crypto_sys::PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg.into(), ENCRYPTED_DATA.len()); + let mut output_buffer = vec![0; output_buffer_size]; + let result = aead::decrypt( + my_key, + alg, + &NONCE, + &ADDITIONAL_DATA, + &ENCRYPTED_DATA, + &mut output_buffer, + ); + assert_eq!(Err(Error::NotPermitted), result); +} + +#[test] +fn aead_decrypt_aes_ccm_invalid_signature() { + const RANDOM_INPUT_DATA: [u8; 23] = [ + 0x08, 0xE8, 0xCF, 0x97, 0xD8, 0x20, 0xEA, 0x25, 0x84, 0x60, 0xE9, 0x6A, 0xD9, 0xCF, 0x52, + 0x89, 0x05, 0x4D, 0x89, 0x5C, 0xEA, 0xC4, 0x7C, + ]; + let alg = Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm); + let attributes = Attributes { + key_type: Type::Aes, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + decrypt: true, + ..Default::default() + }, + permitted_algorithms: alg.into(), + }, + }; + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); + let output_buffer_size = + psa_crypto_sys::PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg.into(), RANDOM_INPUT_DATA.len()); + let mut output_buffer = vec![0; output_buffer_size]; + let result = aead::decrypt( + my_key, + alg, + &NONCE, + &ADDITIONAL_DATA, + &RANDOM_INPUT_DATA, + &mut output_buffer, + ); + assert_eq!(Err(Error::InvalidSignature), result); +} diff --git a/psa-crypto/tests/hash.rs b/psa-crypto/tests/hash.rs new file mode 100644 index 0000000..92ba4cd --- /dev/null +++ b/psa-crypto/tests/hash.rs @@ -0,0 +1,83 @@ +use psa_crypto::operations::hash; +use psa_crypto::types::algorithm::Hash; + +#[test] +fn hash_compute_ripemd160() { + const MESSAGE: [u8; 3] = [0x61, 0x62, 0x63]; + const HASH: [u8; 20] = [ + 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, + 0x87, 0xf1, 0x5a, 0x0b, 0xfc, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Ripemd160; + let mut hash = vec![0; hash_alg.hash_length()]; + let size = hash::hash_compute(hash_alg, &MESSAGE, &mut hash).unwrap(); + hash.resize(size, 0); + assert_eq!(&HASH, &hash[..]); +} + +#[test] +fn hash_compute_sha256() { + const MESSAGE: [u8; 3] = [0xb0, 0xbd, 0x69]; + const HASH: [u8; 32] = [ + 0x40, 0x96, 0x80, 0x42, 0x21, 0x09, 0x3d, 0xdc, 0xcf, 0xbf, 0x46, 0x83, 0x14, 0x90, 0xea, + 0x63, 0xe9, 0xe9, 0x94, 0x14, 0x85, 0x8f, 0x8d, 0x75, 0xff, 0x7f, 0x64, 0x2c, 0x7c, 0xa6, + 0x18, 0x03, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Sha256; + let mut hash = vec![0; hash_alg.hash_length()]; + let size = hash::hash_compute(hash_alg, &MESSAGE, &mut hash).unwrap(); + hash.resize(size, 0); + assert_eq!(&HASH, &hash[..]); +} + +#[test] +fn hash_compare_sha256() { + const MESSAGE: [u8; 3] = [0xb0, 0xbd, 0x69]; + const HASH: [u8; 32] = [ + 0x40, 0x96, 0x80, 0x42, 0x21, 0x09, 0x3d, 0xdc, 0xcf, 0xbf, 0x46, 0x83, 0x14, 0x90, 0xea, + 0x63, 0xe9, 0xe9, 0x94, 0x14, 0x85, 0x8f, 0x8d, 0x75, 0xff, 0x7f, 0x64, 0x2c, 0x7c, 0xa6, + 0x18, 0x03, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Sha256; + hash::hash_compare(hash_alg, &MESSAGE, &HASH).unwrap(); +} + +#[test] +fn hash_compare_ripemd160() { + const MESSAGE: [u8; 3] = [0x61, 0x62, 0x63]; + const HASH: [u8; 20] = [ + 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, + 0x87, 0xf1, 0x5a, 0x0b, 0xfc, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Ripemd160; + hash::hash_compare(hash_alg, &MESSAGE, &HASH).unwrap(); +} + +#[test] +fn hash_compare_sha256_fail() { + const MESSAGE: [u8; 3] = [0xb0, 0xbd, 0x69]; + const HASH: [u8; 20] = [ + 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, + 0x87, 0xf1, 0x5a, 0x0b, 0xfc, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Sha256; + hash::hash_compare(hash_alg, &MESSAGE, &HASH).unwrap_err(); +} + +#[test] +fn hash_compare_ripemd160_fail() { + const MESSAGE: [u8; 3] = [0x61, 0x62, 0x63]; + const HASH: [u8; 32] = [ + 0x40, 0x96, 0x80, 0x42, 0x21, 0x09, 0x3d, 0xdc, 0xcf, 0xbf, 0x46, 0x83, 0x14, 0x90, 0xea, + 0x63, 0xe9, 0xe9, 0x94, 0x14, 0x85, 0x8f, 0x8d, 0x75, 0xff, 0x7f, 0x64, 0x2c, 0x7c, 0xa6, + 0x18, 0x03, + ]; + psa_crypto::init().unwrap(); + let hash_alg = Hash::Ripemd160; + hash::hash_compare(hash_alg, &MESSAGE, &HASH).unwrap_err(); +} diff --git a/psa-crypto/tests/key_agreement.rs b/psa-crypto/tests/key_agreement.rs new file mode 100644 index 0000000..44043f8 --- /dev/null +++ b/psa-crypto/tests/key_agreement.rs @@ -0,0 +1,107 @@ +use psa_crypto::operations::{key_agreement, key_management}; +use psa_crypto::types::algorithm::{KeyAgreement, RawKeyAgreement}; +use psa_crypto::types::key::{Attributes, EccFamily, Lifetime, Policy, Type, UsageFlags}; +use psa_crypto::types::status::Error; + +const PEER_PUBLIC_KEY: [u8; 65] = [ + 0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, 0x70, 0x39, 0x8c, + 0x34, 0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, + 0x63, 0x56, 0xfb, 0xf3, 0xca, 0x36, 0x6c, 0xc2, 0x3e, 0x81, 0x57, 0x85, 0x4c, 0x13, 0xc5, 0x8d, + 0x6a, 0xac, 0x23, 0xf0, 0x46, 0xad, 0xa3, 0x0f, 0x83, 0x53, 0xe7, 0x4f, 0x33, 0x03, 0x98, 0x72, + 0xab, +]; + +const OUR_KEY_DATA: [u8; 32] = [ + 0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, 0x31, 0x6d, 0xe5, + 0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33, +]; + +const EXPECTED_OUTPUT: [u8; 32] = [ + 0xd6, 0x84, 0x0f, 0x6b, 0x42, 0xf6, 0xed, 0xaf, 0xd1, 0x31, 0x16, 0xe0, 0xe1, 0x25, 0x65, 0x20, + 0x2f, 0xef, 0x8e, 0x9e, 0xce, 0x7d, 0xce, 0x03, 0x81, 0x24, 0x64, 0xd0, 0x4b, 0x94, 0x42, 0xde, +]; + +#[test] +fn key_agreement() { + let alg = RawKeyAgreement::Ecdh; + let attributes = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + derive: true, + ..Default::default() + }, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &OUR_KEY_DATA).unwrap(); + let mut output = vec![0; 1024]; + let size = + key_agreement::raw_key_agreement(alg, my_key, &PEER_PUBLIC_KEY, &mut output).unwrap(); + output.resize(size, 0); + assert_eq!(&EXPECTED_OUTPUT[..], &output[..]) +} + +#[test] +fn key_agreement_incompatible_keys() { + const RSA_PUB_KEY_DATA: [u8; 140] = [ + 48, 129, 137, 2, 129, 129, 0, 153, 165, 220, 135, 89, 101, 254, 229, 28, 33, 138, 247, 20, + 102, 253, 217, 247, 246, 142, 107, 51, 40, 179, 149, 45, 117, 254, 236, 161, 109, 16, 81, + 135, 72, 112, 132, 150, 175, 128, 173, 182, 122, 227, 214, 196, 130, 54, 239, 93, 5, 203, + 185, 233, 61, 159, 156, 7, 161, 87, 48, 234, 105, 161, 108, 215, 211, 150, 168, 156, 212, + 6, 63, 81, 24, 101, 72, 160, 97, 243, 142, 86, 10, 160, 122, 8, 228, 178, 252, 35, 209, + 222, 228, 16, 143, 99, 143, 146, 241, 186, 187, 22, 209, 86, 141, 24, 159, 12, 146, 44, + 111, 254, 183, 54, 229, 109, 28, 39, 22, 141, 173, 85, 26, 58, 9, 128, 27, 57, 131, 2, 3, + 1, 0, 1, + ]; + + let alg = RawKeyAgreement::Ecdh; + let attributes = Attributes { + key_type: Type::RsaPublicKey, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + derive: true, + ..Default::default() + }, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &RSA_PUB_KEY_DATA).unwrap(); + let mut output = vec![0; 1024]; + let result = key_agreement::raw_key_agreement(alg, my_key, &PEER_PUBLIC_KEY, &mut output); + assert_eq!(Err(Error::InvalidArgument), result); +} + +#[test] +fn key_agreement_no_derive_flag() { + let alg = RawKeyAgreement::Ecdh; + let attributes = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 0, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + ..Default::default() + }, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, &OUR_KEY_DATA).unwrap(); + let mut output = vec![0; 1024]; + let result = key_agreement::raw_key_agreement(alg, my_key, &PEER_PUBLIC_KEY, &mut output); + assert_eq!(Err(Error::NotPermitted), result); +} diff --git a/psa-crypto/tests/mod.rs b/psa-crypto/tests/mod.rs index b8d7893..94b9d7d 100644 --- a/psa-crypto/tests/mod.rs +++ b/psa-crypto/tests/mod.rs @@ -1,8 +1,14 @@ // Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #![allow(clippy::multiple_crate_versions)] + +use psa_crypto::operations::key_management; use psa_crypto::types::algorithm::{Algorithm, AsymmetricSignature, Hash}; -use psa_crypto::types::key::{Attributes, Lifetime, Policy, Type, UsageFlags}; +use psa_crypto::types::key::{Attributes, EccFamily, Lifetime, Policy, Type, UsageFlags}; + +mod aead; +mod hash; +mod key_agreement; #[test] fn generate_integration_test() { @@ -34,7 +40,7 @@ fn generate_integration_test() { // Ensure that a large number of keys can be generated for key_index in 1..101u32 { - test_client.generate(attributes, key_index); + test_client.generate(attributes, Some(key_index)); } } @@ -130,6 +136,74 @@ V/X2l32v6t3B57sw/8ce3LCheEdqLHlSOpQiaD7Qfw=="; assert_eq!(decoded_pk, data); } +#[test] +fn copy_key_success() { + let attributes = Attributes { + key_type: Type::RsaKeyPair, + bits: 1024, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + copy: true, + export: true, + ..Default::default() + }, + permitted_algorithms: Algorithm::None, + }, + }; + let mut test_client = test_tools::TestClient::new(); + + let key_id = test_client.generate(attributes, None); + let copied_key_id = test_client.copy_key(key_id, attributes, None); + let mut original_key_material = vec![0; attributes.export_key_output_size().unwrap()]; + let mut copied_key_material = vec![0; attributes.export_key_output_size().unwrap()]; + test_client + .export_key_pair(key_id, &mut original_key_material) + .unwrap(); + test_client + .export_key_pair(copied_key_id, &mut copied_key_material) + .unwrap(); + assert_eq!(original_key_material, copied_key_material); +} + +#[test] +fn copy_key_incompatible_copy_attrs() { + let attributes = Attributes { + key_type: Type::RsaKeyPair, + bits: 1024, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + copy: true, + export: true, + ..Default::default() + }, + permitted_algorithms: Algorithm::None, + }, + }; + + let incompatible_copy_attrs = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 448, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags: UsageFlags { + copy: true, + export: true, + ..Default::default() + }, + permitted_algorithms: Algorithm::None, + }, + }; + + let mut test_client = test_tools::TestClient::new(); + + let key_id = test_client.generate(attributes, None); + let _copied_key_id = key_management::copy(key_id, incompatible_copy_attrs, None).unwrap_err(); +} + mod test_tools { use psa_crypto::operations::key_management; use psa_crypto::types::key::{Attributes, Id}; @@ -145,8 +219,8 @@ mod test_tools { TestClient { keys: Vec::new() } } - pub fn generate(&mut self, attributes: Attributes, key_id: u32) -> Id { - let id = key_management::generate(attributes, Some(key_id)).unwrap(); + pub fn generate(&mut self, attributes: Attributes, key_id: Option) -> Id { + let id = key_management::generate(attributes, key_id).unwrap(); self.keys.push(id); id } @@ -160,6 +234,17 @@ mod test_tools { pub fn export_key_pair(&mut self, key_id: Id, key_data: &mut [u8]) -> Result { key_management::export(key_id, key_data) } + + pub fn copy_key( + &mut self, + key_id: Id, + attributes: Attributes, + id_for_new_persistent_key: Option, + ) -> Id { + let id = key_management::copy(key_id, attributes, id_for_new_persistent_key).unwrap(); + self.keys.push(id); + id + } } impl Drop for TestClient {