diff --git a/psa-crypto-sys/src/c/shim.c b/psa-crypto-sys/src/c/shim.c index fffaf03..6a80f46 100644 --- a/psa-crypto-sys/src/c/shim.c +++ b/psa-crypto-sys/src/c/shim.c @@ -49,6 +49,12 @@ shim_key_attributes_init(void) return psa_key_attributes_init(); } +psa_key_derivation_operation_t +shim_key_derivation_operation_init(void) +{ + return psa_key_derivation_operation_init(); +} + void shim_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg) @@ -102,6 +108,16 @@ shim_PSA_ALG_IS_MAC(psa_algorithm_t alg) { return PSA_ALG_IS_MAC(alg); } +int +shim_PSA_ALG_IS_HMAC(psa_algorithm_t alg) { + return PSA_ALG_IS_HMAC(alg); +} + +int +shim_PSA_ALG_IS_BLOCK_CIPHER_MAC (psa_algorithm_t alg) { + return PSA_ALG_IS_BLOCK_CIPHER_MAC (alg); +} + int shim_PSA_ALG_IS_CIPHER(psa_algorithm_t alg) { return PSA_ALG_IS_CIPHER(alg); @@ -157,14 +173,49 @@ shim_PSA_ALG_IS_DETERMINISTIC_ECDSA(psa_algorithm_t alg) { return PSA_ALG_IS_DETERMINISTIC_ECDSA(alg); } +int +shim_PSA_ALG_IS_HKDF(psa_algorithm_t alg) { + return PSA_ALG_IS_HKDF(alg); +} + +int +shim_PSA_ALG_IS_TLS12_PRF(psa_algorithm_t alg) { + return PSA_ALG_IS_TLS12_PRF(alg); +} + +int +shim_PSA_ALG_IS_TLS12_PSK_TO_MS(psa_algorithm_t alg) { + return PSA_ALG_IS_TLS12_PSK_TO_MS(alg); +} + psa_algorithm_t -shim_PSA_ALG_SIGN_GET_HASH(psa_algorithm_t alg) { - return PSA_ALG_SIGN_GET_HASH(alg); +shim_PSA_ALG_SIGN_GET_HASH(psa_algorithm_t sign_alg) { + return PSA_ALG_SIGN_GET_HASH(sign_alg); } psa_algorithm_t -shim_PSA_ALG_RSA_OAEP_GET_HASH(psa_algorithm_t alg) { - return PSA_ALG_RSA_OAEP_GET_HASH(alg); +shim_PSA_ALG_RSA_OAEP_GET_HASH(psa_algorithm_t rsa_oaep_alg) { + return PSA_ALG_RSA_OAEP_GET_HASH(rsa_oaep_alg); +} + +psa_algorithm_t +shim_PSA_ALG_HMAC_GET_HASH(psa_algorithm_t hmac_alg) { + return PSA_ALG_HMAC_GET_HASH(hmac_alg); +} + +psa_algorithm_t +shim_PSA_ALG_HKDF_GET_HASH(psa_algorithm_t hkdf_alg) { + return PSA_ALG_HKDF_GET_HASH(hkdf_alg); +} + +psa_algorithm_t +shim_PSA_ALG_TLS12_PRF_GET_HASH(psa_algorithm_t tls12_prf_alg) { + return PSA_ALG_TLS12_PRF_GET_HASH(tls12_prf_alg); +} + +psa_algorithm_t +shim_PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(psa_algorithm_t tls12_psk_to_ms_alg) { + return PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(tls12_psk_to_ms_alg); } psa_algorithm_t @@ -187,6 +238,51 @@ shim_PSA_ALG_DETERMINISTIC_ECDSA(psa_algorithm_t hash_alg) { return PSA_ALG_DETERMINISTIC_ECDSA(hash_alg); } +psa_algorithm_t +shim_PSA_ALG_HMAC(psa_algorithm_t hash_alg) { + return PSA_ALG_HMAC(hash_alg); +} + +psa_algorithm_t +shim_PSA_ALG_TRUNCATED_MAC(psa_algorithm_t mac_alg, size_t mac_length) { + return PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length); +} + +psa_algorithm_t +shim_PSA_ALG_FULL_LENGTH_MAC(psa_algorithm_t mac_alg) { + return PSA_ALG_FULL_LENGTH_MAC(mac_alg); +} + +psa_algorithm_t +shim_PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_algorithm_t aead_alg) { + return PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg); +} + +psa_algorithm_t +shim_PSA_ALG_AEAD_WITH_SHORTENED_TAG(psa_algorithm_t aead_alg, size_t tag_length) { + return PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length); +} + +psa_algorithm_t +shim_PSA_ALG_HKDF(psa_algorithm_t hash_alg) { + return PSA_ALG_HKDF(hash_alg); +} + +psa_algorithm_t +shim_PSA_ALG_TLS12_PRF(psa_algorithm_t hash_alg) { + return PSA_ALG_TLS12_PRF(hash_alg); +} + +psa_algorithm_t +shim_PSA_ALG_TLS12_PSK_TO_MS(psa_algorithm_t hash_alg) { + return PSA_ALG_TLS12_PSK_TO_MS(hash_alg); +} + +psa_algorithm_t +shim_PSA_ALG_KEY_AGREEMENT(psa_algorithm_t raw_key_agreement, psa_algorithm_t key_derivation) { + return PSA_ALG_KEY_AGREEMENT(raw_key_agreement, key_derivation); +} + int shim_PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_key_type_t key_type) { @@ -212,9 +308,9 @@ shim_PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_key_type_t key_type) } psa_algorithm_t -shim_PSA_ALG_RSA_OAEP(psa_algorithm_t alg_type) +shim_PSA_ALG_RSA_OAEP(psa_algorithm_t hash_alg) { - return PSA_ALG_RSA_OAEP(alg_type); + return PSA_ALG_RSA_OAEP(hash_alg); } psa_ecc_curve_t @@ -281,4 +377,34 @@ size_t shim_PSA_KEY_EXPORT_MAX_SIZE(psa_key_type_t key_type, size_t key_bits) { return PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); +} + +size_t +shim_PSA_HASH_LENGTH(psa_algorithm_t alg) +{ + return PSA_HASH_SIZE(alg); +} + +size_t +shim_PSA_MAC_LENGTH(psa_key_type_t key_type, size_t key_bits, psa_algorithm_t alg) +{ + return PSA_MAC_FINAL_SIZE(key_type, key_bits, alg); +} + +size_t +shim_PSA_MAC_TRUNCATED_LENGTH(psa_algorithm_t alg) +{ + return PSA_MAC_TRUNCATED_LENGTH(alg); +} + +size_t +shim_PSA_AEAD_ENCRYPT_OUTPUT_SIZE(psa_algorithm_t aead_alg, size_t plaintext_bytes) +{ + return PSA_AEAD_ENCRYPT_OUTPUT_SIZE(aead_alg, plaintext_bytes); +} + +size_t +shim_PSA_AEAD_DECRYPT_OUTPUT_SIZE(psa_algorithm_t aead_alg, size_t ciphertext_bytes) +{ + return PSA_AEAD_DECRYPT_OUTPUT_SIZE(aead_alg, ciphertext_bytes); } \ No newline at end of file diff --git a/psa-crypto-sys/src/c/shim.h b/psa-crypto-sys/src/c/shim.h index 4cb9d8a..3e0d3f0 100644 --- a/psa-crypto-sys/src/c/shim.h +++ b/psa-crypto-sys/src/c/shim.h @@ -80,6 +80,7 @@ psa_key_lifetime_t shim_get_key_lifetime(const psa_key_attributes_t *attributes) psa_key_type_t shim_get_key_type(const psa_key_attributes_t *attributes); psa_key_usage_t shim_get_key_usage_flags(const psa_key_attributes_t *attributes); psa_key_attributes_t shim_key_attributes_init(void); +psa_key_derivation_operation_t shim_key_derivation_operation_init(void); void shim_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg); void shim_set_key_bits(psa_key_attributes_t *attributes, size_t bits); @@ -90,6 +91,9 @@ void shim_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t int shim_PSA_ALG_IS_HASH(psa_algorithm_t alg); int shim_PSA_ALG_IS_MAC(psa_algorithm_t alg); +int shim_PSA_ALG_IS_HMAC(psa_algorithm_t alg); +int shim_PSA_ALG_IS_BLOCK_CIPHER_MAC(psa_algorithm_t alg); +int shim_PSA_ALG_IS_FULL_LENGTH_MAC(psa_algorithm_t alg); int shim_PSA_ALG_IS_CIPHER(psa_algorithm_t alg); int shim_PSA_ALG_IS_AEAD(psa_algorithm_t alg); int shim_PSA_ALG_IS_SIGN(psa_algorithm_t alg); @@ -101,13 +105,29 @@ int shim_PSA_ALG_IS_RSA_PKCS1V15_SIGN(psa_algorithm_t alg); int shim_PSA_ALG_IS_RSA_PSS(psa_algorithm_t alg); int shim_PSA_ALG_IS_ECDSA(psa_algorithm_t alg); int shim_PSA_ALG_IS_DETERMINISTIC_ECDSA(psa_algorithm_t alg); -psa_algorithm_t shim_PSA_ALG_RSA_OAEP(psa_algorithm_t alg); +int shim_PSA_ALG_IS_HKDF(psa_algorithm_t alg); +int shim_PSA_ALG_IS_TLS12_PRF(psa_algorithm_t alg); +int shim_PSA_ALG_IS_TLS12_PSK_TO_MS(psa_algorithm_t alg); +psa_algorithm_t shim_PSA_ALG_RSA_OAEP(psa_algorithm_t hash_alg); psa_algorithm_t shim_PSA_ALG_RSA_PKCS1V15_SIGN(psa_algorithm_t hash_alg); psa_algorithm_t shim_PSA_ALG_RSA_PSS(psa_algorithm_t hash_alg); psa_algorithm_t shim_PSA_ALG_ECDSA(psa_algorithm_t hash_alg); psa_algorithm_t shim_PSA_ALG_DETERMINISTIC_ECDSA(psa_algorithm_t hash_alg); -psa_algorithm_t shim_PSA_ALG_SIGN_GET_HASH(psa_algorithm_t alg); -psa_algorithm_t shim_PSA_ALG_RSA_OAEP_GET_HASH(psa_algorithm_t alg); +psa_algorithm_t shim_PSA_ALG_HMAC(psa_algorithm_t hash_alg); +psa_algorithm_t shim_PSA_ALG_SIGN_GET_HASH(psa_algorithm_t sign_alg); +psa_algorithm_t shim_PSA_ALG_RSA_OAEP_GET_HASH(psa_algorithm_t rsa_oaep_alg); +psa_algorithm_t shim_PSA_ALG_HMAC_GET_HASH(psa_algorithm_t hmac_alg); +psa_algorithm_t shim_PSA_ALG_HKDF_GET_HASH(psa_algorithm_t hkdf_alg); +psa_algorithm_t shim_PSA_ALG_TLS12_PRF_GET_HASH(psa_algorithm_t tls12_prf_alg); +psa_algorithm_t shim_PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(psa_algorithm_t tls12_psk_to_ms_alg); +psa_algorithm_t shim_PSA_ALG_TRUNCATED_MAC(psa_algorithm_t mac_alg, size_t mac_length); +psa_algorithm_t shim_PSA_ALG_FULL_LENGTH_MAC(psa_algorithm_t mac_alg); +psa_algorithm_t shim_PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_algorithm_t aead_alg); +psa_algorithm_t shim_PSA_ALG_AEAD_WITH_SHORTENED_TAG(psa_algorithm_t aead_alg, size_t tag_length); +psa_algorithm_t shim_PSA_ALG_HKDF(psa_algorithm_t hash_alg); +psa_algorithm_t shim_PSA_ALG_TLS12_PRF(psa_algorithm_t hash_alg); +psa_algorithm_t shim_PSA_ALG_TLS12_PSK_TO_MS(psa_algorithm_t hash_alg); +psa_algorithm_t shim_PSA_ALG_KEY_AGREEMENT(psa_algorithm_t raw_key_agreement, psa_algorithm_t key_derivation); int shim_PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_key_type_t key_type); int shim_PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(psa_key_type_t key_type); int shim_PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(psa_key_type_t key_type); @@ -122,4 +142,9 @@ psa_key_type_t shim_PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_key_type_t key_type) size_t shim_PSA_SIGN_OUTPUT_SIZE(psa_key_type_t key_type, size_t key_bits, psa_algorithm_t alg); size_t shim_PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(psa_key_type_t key_type, size_t key_bits, psa_algorithm_t alg); size_t shim_PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(psa_key_type_t key_type, size_t key_bits, psa_algorithm_t alg); -size_t shim_PSA_KEY_EXPORT_MAX_SIZE(psa_key_type_t key_type, size_t key_bits); \ No newline at end of file +size_t shim_PSA_KEY_EXPORT_MAX_SIZE(psa_key_type_t key_type, size_t key_bits); +size_t shim_PSA_HASH_LENGTH(psa_algorithm_t alg); +size_t shim_PSA_MAC_LENGTH(psa_key_type_t key_type, size_t key_bits, psa_algorithm_t alg); +size_t shim_PSA_MAC_TRUNCATED_LENGTH(psa_algorithm_t alg); +size_t shim_PSA_AEAD_ENCRYPT_OUTPUT_SIZE(psa_algorithm_t aead_alg, size_t plaintext_bytes); +size_t shim_PSA_AEAD_DECRYPT_OUTPUT_SIZE(psa_algorithm_t aead_alg, size_t ciphertext_bytes); \ No newline at end of file diff --git a/psa-crypto-sys/src/constants.rs b/psa-crypto-sys/src/constants.rs index 72a0eb4..e546798 100644 --- a/psa-crypto-sys/src/constants.rs +++ b/psa-crypto-sys/src/constants.rs @@ -79,6 +79,9 @@ pub const PSA_ALG_CBC_NO_PADDING: psa_algorithm_t = 73_400_576; pub const PSA_ALG_CBC_PKCS7: psa_algorithm_t = 73_400_577; pub const PSA_ALG_CCM: psa_algorithm_t = 104_861_697; pub const PSA_ALG_GCM: psa_algorithm_t = 104_861_698; +pub const PSA_ALG_CHACHA20_POLY1305: psa_algorithm_t = 84_935_936; +pub const PSA_ALG_FFDH: psa_algorithm_t = 0x30100000; // Doesn't match latest PSA spec +pub const PSA_ALG_ECDH: psa_algorithm_t = 0x30200000; // Doesn't match latest PSA spec pub const PSA_ALG_RSA_PKCS1V15_SIGN_RAW: psa_algorithm_t = 268_566_528; pub const PSA_ALG_ECDSA_ANY: psa_algorithm_t = 268_828_672; pub const PSA_ALG_RSA_PKCS1V15_CRYPT: psa_algorithm_t = 302_120_960; @@ -92,3 +95,9 @@ pub const PSA_KEY_USAGE_VERIFY: psa_key_usage_t = 2048; pub const PSA_KEY_USAGE_DERIVE: psa_key_usage_t = 4096; pub const PSA_KEY_ID_USER_MIN: psa_key_id_t = 0x0000_0001; pub const PSA_KEY_ID_USER_MAX: psa_key_id_t = 0x3fff_ffff; + +pub const PSA_KEY_DERIVATION_INPUT_SECRET: psa_key_derivation_step_t = 0x0101; +pub const PSA_KEY_DERIVATION_INPUT_LABEL: psa_key_derivation_step_t = 0x0201; +pub const PSA_KEY_DERIVATION_INPUT_SALT: psa_key_derivation_step_t = 0x0202; +pub const PSA_KEY_DERIVATION_INPUT_INFO: psa_key_derivation_step_t = 0x0203; +pub const PSA_KEY_DERIVATION_INPUT_SEED: psa_key_derivation_step_t = 0x0204; diff --git a/psa-crypto-sys/src/extras.rs b/psa-crypto-sys/src/extras.rs new file mode 100644 index 0000000..e4a2868 --- /dev/null +++ b/psa-crypto-sys/src/extras.rs @@ -0,0 +1,48 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +#![allow(non_snake_case)] +/// Additional functionality required that PSA Crypto does not provide +use crate::types::psa_algorithm_t; + +/// Retrieves the tag length from an aead_alg. +/// Note: `aead_alg` is an AEAD algorithm, such that `PSA_ALG_IS_AEAD(aead_alg)` is `true`. +pub fn PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(aead_alg: psa_algorithm_t) -> usize { + const TAG_LENGTH_MASK: u32 = 0b111111; // tag lengths are 6 bits in length + const PSA_V1_0_0_TAG_LENGTH_START_BIT: u32 = 16; // tag length at bit position [21:16] + + let pre_mask_tag_length = aead_alg >> PSA_V1_0_0_TAG_LENGTH_START_BIT; + + (pre_mask_tag_length & TAG_LENGTH_MASK) as usize +} + +#[test] +fn truncated_aead_length_1() { + let test_aead_alg = 0b11001110010010110001110011010011; // 21:16 is 001011 + assert_eq!(11, PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(test_aead_alg)); +} + +#[test] +fn truncated_aead_length_2() { + let test_aead_alg = 0b11001110010000000001110011010011; // 21:16 is 000000 + assert_eq!(0, PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(test_aead_alg)); +} + +#[test] +fn truncated_aead_length_3() { + let test_aead_alg = 0b11001110011111110001110011010011; // 21:16 is 111111 + assert_eq!(63, PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(test_aead_alg)); +} + +#[test] +fn truncated_aead_length_full_range() { + // Test from 0 to 63 + let base_mask = 0b11001110010000000001110011010011; + for test_val in 0..63 { + let test_mask = test_val << 16; + let test_aead_alg = base_mask | test_mask; + assert_eq!( + test_val as usize, + PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(test_aead_alg) + ); + } +} diff --git a/psa-crypto-sys/src/lib.rs b/psa-crypto-sys/src/lib.rs index 27b22a0..5545e96 100644 --- a/psa-crypto-sys/src/lib.rs +++ b/psa-crypto-sys/src/lib.rs @@ -28,6 +28,8 @@ mod psa_crypto_binding { #[allow(dead_code)] mod constants; +#[cfg(feature = "interface")] +mod extras; #[allow(dead_code)] #[cfg(feature = "interface")] mod shim_methods; @@ -39,14 +41,18 @@ pub use types::*; #[cfg(feature = "operations")] pub use psa_crypto_binding::{ - psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_close_key, psa_crypto_init, - psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, - psa_get_key_attributes, psa_import_key, psa_open_key, psa_reset_key_attributes, psa_sign_hash, - psa_verify_hash, + psa_aead_decrypt, psa_aead_encrypt, psa_asymmetric_decrypt, psa_asymmetric_encrypt, + psa_close_key, psa_copy_key, psa_crypto_init, psa_destroy_key, psa_export_key, + psa_export_public_key, psa_generate_key, psa_generate_random, psa_get_key_attributes, + psa_hash_compare, psa_hash_compute, psa_import_key, psa_key_derivation_abort, + psa_key_derivation_input_bytes, psa_key_derivation_input_key, psa_key_derivation_key_agreement, + psa_key_derivation_output_key, psa_key_derivation_set_capacity, psa_key_derivation_setup, + psa_mac_compute, psa_mac_verify, psa_open_key, psa_raw_key_agreement, psa_reset_key_attributes, + psa_sign_hash, psa_verify_hash, }; #[cfg(feature = "interface")] -pub use psa_crypto_binding::psa_key_attributes_t; +pub use psa_crypto_binding::{psa_key_attributes_t, psa_key_derivation_operation_t}; // Secure Element Driver definitions #[cfg(feature = "interface")] @@ -55,5 +61,7 @@ pub use psa_crypto_binding::{ psa_key_creation_method_t, psa_key_slot_number_t, }; +#[cfg(feature = "interface")] +pub use extras::*; #[cfg(feature = "interface")] pub use shim_methods::*; diff --git a/psa-crypto-sys/src/shim_methods.rs b/psa-crypto-sys/src/shim_methods.rs index f6d8dc6..9d58074 100644 --- a/psa-crypto-sys/src/shim_methods.rs +++ b/psa-crypto-sys/src/shim_methods.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use super::psa_crypto_binding::{ - self, psa_algorithm_t, psa_dh_group_t, psa_ecc_curve_t, psa_key_attributes_t, psa_key_id_t, - psa_key_lifetime_t, psa_key_type_t, psa_key_usage_t, + self, psa_algorithm_t, psa_dh_group_t, psa_ecc_curve_t, psa_key_attributes_t, + psa_key_derivation_operation_t, psa_key_id_t, psa_key_lifetime_t, psa_key_type_t, + psa_key_usage_t, }; pub unsafe fn psa_get_key_bits(attributes: *const psa_key_attributes_t) -> usize { @@ -30,6 +31,10 @@ pub unsafe fn psa_key_attributes_init() -> psa_key_attributes_t { psa_crypto_binding::shim_key_attributes_init() } +pub fn psa_key_derivation_operation_init() -> psa_key_derivation_operation_t { + unsafe { psa_crypto_binding::shim_key_derivation_operation_init() } +} + pub unsafe fn psa_set_key_algorithm(attributes: *mut psa_key_attributes_t, alg: psa_algorithm_t) { psa_crypto_binding::shim_set_key_algorithm(attributes, alg); } @@ -72,6 +77,19 @@ pub fn PSA_ALG_IS_MAC(alg: psa_algorithm_t) -> bool { unsafe { psa_crypto_binding::shim_PSA_ALG_IS_MAC(alg) == 1 } } +pub fn PSA_ALG_IS_HMAC(alg: psa_algorithm_t) -> bool { + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_HMAC(alg) == 1 } +} + +pub fn PSA_ALG_IS_BLOCK_CIPHER_MAC(alg: psa_algorithm_t) -> bool { + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) == 1 } +} + +pub fn PSA_ALG_IS_FULL_LENGTH_MAC(alg: psa_algorithm_t) -> bool { + // Not in PSA spec but required to convert from psa_alg_t to algorithm/Mac + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_FULL_LENGTH_MAC(alg) == 1 } +} + pub fn PSA_ALG_IS_CIPHER(alg: psa_algorithm_t) -> bool { unsafe { psa_crypto_binding::shim_PSA_ALG_IS_CIPHER(alg) == 1 } } @@ -116,12 +134,40 @@ pub fn PSA_ALG_IS_DETERMINISTIC_ECDSA(alg: psa_algorithm_t) -> bool { unsafe { psa_crypto_binding::shim_PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) == 1 } } -pub fn PSA_ALG_SIGN_GET_HASH(alg: psa_algorithm_t) -> psa_algorithm_t { - unsafe { psa_crypto_binding::shim_PSA_ALG_SIGN_GET_HASH(alg) } +pub fn PSA_ALG_IS_HKDF(alg: psa_algorithm_t) -> bool { + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_HKDF(alg) == 1 } +} + +pub fn PSA_ALG_IS_TLS12_PRF(alg: psa_algorithm_t) -> bool { + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_TLS12_PRF(alg) == 1 } +} + +pub fn PSA_ALG_IS_TLS12_PSK_TO_MS(alg: psa_algorithm_t) -> bool { + unsafe { psa_crypto_binding::shim_PSA_ALG_IS_TLS12_PSK_TO_MS(alg) == 1 } +} + +pub fn PSA_ALG_SIGN_GET_HASH(sign_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_SIGN_GET_HASH(sign_alg) } } -pub fn PSA_ALG_RSA_OAEP_GET_HASH(alg: psa_algorithm_t) -> psa_algorithm_t { - unsafe { psa_crypto_binding::shim_PSA_ALG_RSA_OAEP_GET_HASH(alg) } +pub fn PSA_ALG_RSA_OAEP_GET_HASH(rsa_oaep_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_RSA_OAEP_GET_HASH(rsa_oaep_alg) } +} + +pub fn PSA_ALG_HMAC_GET_HASH(hmac_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_HMAC_GET_HASH(hmac_alg) } +} + +pub fn PSA_ALG_HKDF_GET_HASH(hkdf_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_HKDF_GET_HASH(hkdf_alg) } +} + +pub fn PSA_ALG_TLS12_PRF_GET_HASH(tls12_prf_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_TLS12_PRF_GET_HASH(tls12_prf_alg) } +} + +pub fn PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(tls12_psk_to_ms_alg: psa_algorithm_t) -> psa_algorithm_t { + unsafe { psa_crypto_binding::shim_PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(tls12_psk_to_ms_alg) } } pub fn PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg: psa_algorithm_t) -> psa_algorithm_t { @@ -144,6 +190,51 @@ pub unsafe fn PSA_ALG_RSA_OAEP(hash_alg: psa_algorithm_t) -> psa_algorithm_t { psa_crypto_binding::shim_PSA_ALG_RSA_OAEP(hash_alg) } +pub unsafe fn PSA_ALG_HMAC(hash_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_HMAC(hash_alg) +} + +pub unsafe fn PSA_ALG_TRUNCATED_MAC( + mac_alg: psa_algorithm_t, + mac_length: usize, +) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) +} + +pub unsafe fn PSA_ALG_FULL_LENGTH_MAC(mac_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_FULL_LENGTH_MAC(mac_alg) +} + +pub unsafe fn PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg) +} + +pub unsafe fn PSA_ALG_AEAD_WITH_SHORTENED_TAG( + aead_alg: psa_algorithm_t, + tag_length: usize, +) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) +} + +pub unsafe fn PSA_ALG_HKDF(hash_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_HKDF(hash_alg) +} + +pub unsafe fn PSA_ALG_TLS12_PRF(hash_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_TLS12_PRF(hash_alg) +} + +pub unsafe fn PSA_ALG_TLS12_PSK_TO_MS(hash_alg: psa_algorithm_t) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_TLS12_PSK_TO_MS(hash_alg) +} + +pub unsafe fn PSA_ALG_KEY_AGREEMENT( + raw_key_agreement: psa_algorithm_t, + key_derivation: psa_algorithm_t, +) -> psa_algorithm_t { + psa_crypto_binding::shim_PSA_ALG_KEY_AGREEMENT(raw_key_agreement, key_derivation) +} + pub fn PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type: psa_key_type_t) -> bool { unsafe { psa_crypto_binding::shim_PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) == 1 } } @@ -215,3 +306,28 @@ pub unsafe fn PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE( pub unsafe fn PSA_EXPORT_KEY_OUTPUT_SIZE(key_type: psa_key_type_t, key_bits: usize) -> usize { psa_crypto_binding::shim_PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) } + +pub fn PSA_HASH_LENGTH(alg: psa_algorithm_t) -> usize { + unsafe { psa_crypto_binding::shim_PSA_HASH_LENGTH(alg) } +} + +pub unsafe fn PSA_MAC_LENGTH( + key_type: psa_key_type_t, + key_bits: usize, + alg: psa_algorithm_t, +) -> usize { + psa_crypto_binding::shim_PSA_MAC_LENGTH(key_type, key_bits, alg) +} + +pub unsafe fn PSA_MAC_TRUNCATED_LENGTH(alg: psa_algorithm_t) -> usize { + // No longer in PSA spec but required to convert form psa_algorithm_to to algorithm/Mac + psa_crypto_binding::shim_PSA_MAC_TRUNCATED_LENGTH(alg) +} + +pub fn PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg: psa_algorithm_t, plaintext_bytes: usize) -> usize { + unsafe { psa_crypto_binding::shim_PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_bytes) } +} + +pub fn PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg: psa_algorithm_t, ciphertext_bytes: usize) -> usize { + unsafe { psa_crypto_binding::shim_PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_bytes) } +} diff --git a/psa-crypto/src/operations/aead.rs b/psa-crypto/src/operations/aead.rs index a1280b9..a67087c 100644 --- a/psa-crypto/src/operations/aead.rs +++ b/psa-crypto/src/operations/aead.rs @@ -2,3 +2,146 @@ // SPDX-License-Identifier: Apache-2.0 //! # Authenticated Encryption with Associated Data (AEAD) operations +//! +//! See the PSA Crypto API for the format of the different parameters used in this module. + +use crate::initialized; +use crate::types::algorithm::Aead; +use crate::types::key::Id; +use crate::types::status::{Result, Status}; + +/// Process an authenticated encryption operation. +/// # Example +/// +/// ``` +/// use psa_crypto::types::algorithm::{Aead, AeadWithDefaultLengthTag}; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::operations::{key_management, aead}; +/// # 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 INPUT_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]; +/// 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 = unsafe { 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); +/// ``` +pub fn encrypt( + key_id: Id, + aead_alg: Aead, + nonce: &[u8], + additional_data: &[u8], + plaintext: &[u8], + ciphertext: &mut [u8], +) -> Result { + initialized()?; + + let key_handle = key_id.handle()?; + let mut ciphertext_size = 0; + + let encrypt_res = Status::from(unsafe { + psa_crypto_sys::psa_aead_encrypt( + key_handle, + aead_alg.into(), + nonce.as_ptr(), + nonce.len(), + additional_data.as_ptr(), + additional_data.len(), + plaintext.as_ptr(), + plaintext.len(), + ciphertext.as_mut_ptr(), + ciphertext.len(), + &mut ciphertext_size, + ) + }) + .to_result(); + let key_close_handle_res = key_id.close_handle(key_handle); + encrypt_res?; + key_close_handle_res?; + Ok(ciphertext_size) +} + +/// Process an authenticated decryption operation. +/// # Example +/// +/// ``` +/// use psa_crypto::types::algorithm::{Aead, AeadWithDefaultLengthTag}; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::operations::{key_management, aead}; +/// # 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 INPUT_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]; +/// 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 = unsafe { psa_crypto_sys::PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg.into(), INPUT_DATA.len()) }; +/// let mut output_buffer = vec![0; output_buffer_size]; +/// let length = aead::decrypt(my_key, alg, &NONCE, &ADDITIONAL_DATA, &INPUT_DATA, &mut output_buffer).unwrap(); +/// output_buffer.resize(length, 0); +/// ``` +pub fn decrypt( + key_id: Id, + aead_alg: Aead, + nonce: &[u8], + additional_data: &[u8], + ciphertext: &[u8], + plaintext: &mut [u8], +) -> Result { + initialized()?; + + let key_handle = key_id.handle()?; + let mut plaintext_size = 0; + + let decrypt_res = Status::from(unsafe { + psa_crypto_sys::psa_aead_decrypt( + key_handle, + aead_alg.into(), + nonce.as_ptr(), + nonce.len(), + additional_data.as_ptr(), + additional_data.len(), + ciphertext.as_ptr(), + ciphertext.len(), + plaintext.as_mut_ptr(), + plaintext.len(), + &mut plaintext_size, + ) + }) + .to_result(); + let key_close_handle_res = key_id.close_handle(key_handle); + decrypt_res?; + key_close_handle_res?; + Ok(plaintext_size) +} diff --git a/psa-crypto/src/operations/hash.rs b/psa-crypto/src/operations/hash.rs new file mode 100644 index 0000000..dfaa6d4 --- /dev/null +++ b/psa-crypto/src/operations/hash.rs @@ -0,0 +1,82 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +//! # Hash operations +//! +//! See the PSA Crypto API for the format of the different parameters used in this module. + +use crate::initialized; +use crate::types::algorithm::Hash; +use crate::types::status::{Result, Status}; + +/// Calculate hash of a message +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::hash::hash_compute; +/// use psa_crypto::types::algorithm::Hash; +/// # const MESSAGE: [u8; 32] = [ +/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, +/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, +/// # ]; +/// +/// psa_crypto::init().unwrap(); +/// let hash_alg = Hash::Sha256; +/// let mut hash = vec![0; hash_alg.hash_length()]; +/// let size = hash_compute(hash_alg, +/// &MESSAGE, +/// &mut hash).unwrap(); +/// ``` +pub fn hash_compute(hash_alg: Hash, input: &[u8], hash: &mut [u8]) -> Result { + initialized()?; + + let mut output_length = 0; + + Status::from(unsafe { + psa_crypto_sys::psa_hash_compute( + hash_alg.into(), + input.as_ptr(), + input.len(), + hash.as_mut_ptr(), + hash.len(), + &mut output_length, + ) + }) + .to_result()?; + Ok(output_length) +} + +/// Calculate the hash of a message and compare it with a reference value +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::hash::{hash_compute, hash_compare}; +/// use psa_crypto::types::algorithm::Hash; +/// # const MESSAGE: [u8; 32] = [ +/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, +/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, +/// # ]; +/// +/// psa_crypto::init().unwrap(); +/// let hash_alg = Hash::Sha256; +/// let mut hash = vec![0; hash_alg.hash_length()]; +/// let _size = hash_compute(hash_alg, +/// &MESSAGE, +/// &mut hash).unwrap(); +/// ``` +pub fn hash_compare(hash_alg: Hash, input: &[u8], hash_to_compare: &[u8]) -> Result<()> { + initialized()?; + + Status::from(unsafe { + psa_crypto_sys::psa_hash_compare( + hash_alg.into(), + input.as_ptr(), + input.len(), + hash_to_compare.as_ptr(), + hash_to_compare.len(), + ) + }) + .to_result() +} diff --git a/psa-crypto/src/operations/key_agreement.rs b/psa-crypto/src/operations/key_agreement.rs index 46cc511..a8ceb11 100644 --- a/psa-crypto/src/operations/key_agreement.rs +++ b/psa-crypto/src/operations/key_agreement.rs @@ -2,3 +2,72 @@ // SPDX-License-Identifier: Apache-2.0 //! # Key Agreement operations +use crate::initialized; +use crate::types::algorithm::RawKeyAgreement; +use crate::types::key::Id; +use crate::types::status::{Result, Status}; + +/// Perform a key agreement and return the raw shared secret. +/// # Example +/// +/// ``` +/// 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; +/// +/// # 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]; +/// let alg = RawKeyAgreement::Ecdh; +/// # let mut 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); +/// ``` +pub fn raw_key_agreement( + alg: RawKeyAgreement, + key_id: Id, + peer_key: &[u8], + output: &mut [u8], +) -> Result { + initialized()?; + let key_handle = key_id.handle()?; + let mut output_size = 0; + let key_agreement_res = Status::from(unsafe { + psa_crypto_sys::psa_raw_key_agreement( + alg.into(), + key_handle, + peer_key.as_ptr(), + peer_key.len(), + output.as_mut_ptr(), + output.len(), + &mut output_size, + ) + }) + .to_result(); + + let handle_close_res = key_id.close_handle(key_handle); + key_agreement_res?; + handle_close_res?; + Ok(output_size) +} diff --git a/psa-crypto/src/operations/key_derivation.rs b/psa-crypto/src/operations/key_derivation.rs deleted file mode 100644 index f20b6b5..0000000 --- a/psa-crypto/src/operations/key_derivation.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2020 Contributors to the Parsec project. -// SPDX-License-Identifier: Apache-2.0 - -//! # Key Derivation operations diff --git a/psa-crypto/src/operations/key_management.rs b/psa-crypto/src/operations/key_management.rs index 43b078d..a96a97d 100644 --- a/psa-crypto/src/operations/key_management.rs +++ b/psa-crypto/src/operations/key_management.rs @@ -7,6 +7,8 @@ use crate::initialized; use crate::types::key::{Attributes, Id, Lifetime}; use crate::types::status::{Result, Status}; use core::convert::TryFrom; +#[cfg(feature = "interface")] +use log::error; use psa_crypto_sys::{psa_key_handle_t, psa_key_id_t}; /// Generate a key or a key pair @@ -25,23 +27,23 @@ use psa_crypto_sys::{psa_key_handle_t, psa_key_id_t}; /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; /// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; /// -/// let mut attributes = Attributes { -/// key_type: Type::RsaKeyPair, -/// bits: 1024, -/// lifetime: Lifetime::Volatile, -/// policy: Policy { -/// usage_flags: UsageFlags { -/// sign_hash: true, -/// sign_message: true, -/// verify_hash: true, -/// verify_message: true, -/// ..Default::default() -/// }, -/// permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { -/// hash_alg: Hash::Sha256.into(), -/// }.into(), -/// }, -/// }; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaKeyPair, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # sign_hash: true, +/// # sign_message: true, +/// # verify_hash: true, +/// # verify_message: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { +/// # hash_alg: Hash::Sha256.into(), +/// # }.into(), +/// # }, +/// # }; /// /// psa_crypto::init().unwrap(); /// let _my_key = key_management::generate(attributes, None).unwrap(); @@ -79,9 +81,9 @@ pub fn generate(attributes: Attributes, id: Option) -> Result { /// # Example /// /// ``` -/// # 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::operations::key_management; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; /// # let mut attributes = Attributes { /// # key_type: Type::RsaKeyPair, /// # bits: 1024, @@ -136,23 +138,23 @@ pub unsafe fn destroy(key: Id) -> Result<()> { /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; /// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; /// -/// let mut attributes = Attributes { -/// key_type: Type::RsaPublicKey, -/// bits: 1024, -/// lifetime: Lifetime::Volatile, -/// policy: Policy { -/// usage_flags: UsageFlags { -/// sign_hash: true, -/// sign_message: true, -/// verify_hash: true, -/// verify_message: true, -/// ..Default::default() -/// }, -/// permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { -/// hash_alg: Hash::Sha256.into(), -/// }.into(), -/// }, -/// }; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaPublicKey, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # sign_hash: true, +/// # sign_message: true, +/// # verify_hash: true, +/// # verify_message: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { +/// # hash_alg: Hash::Sha256.into(), +/// # }.into(), +/// # }, +/// # }; /// /// psa_crypto::init().unwrap(); /// let _my_key = key_management::import(attributes, None, &KEY_DATA).unwrap(); @@ -187,9 +189,9 @@ pub fn import(attributes: Attributes, id: Option, data: &[u8]) -> Result Result { /// Export a key pair in binary format /// -/// The key is written in `data`. The functions returns the number of bytes written. +/// The key is written in `data`. The function returns the number of bytes written. /// Please check the PSA Crypto API for a more complete description on the format of `data`. /// /// # Example /// /// ``` -/// # 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::operations::key_management; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; /// # let mut attributes = Attributes { /// # key_type: Type::RsaKeyPair, /// # bits: 1024, @@ -267,10 +269,10 @@ pub fn export_public(key: Id, data: &mut [u8]) -> Result { /// let buffer_size = attributes.export_key_output_size().unwrap(); /// let mut data = vec![0; buffer_size]; /// let my_key = key_management::generate(attributes, None).unwrap(); -/// let size = key_management::export_key(my_key, &mut data).unwrap(); +/// let size = key_management::export(my_key, &mut data).unwrap(); /// data.resize(size, 0); /// ``` -pub fn export_key(key: Id, data: &mut [u8]) -> Result { +pub fn export(key: Id, data: &mut [u8]) -> Result { initialized()?; let handle = key.handle()?; let mut data_length = 0; @@ -290,7 +292,7 @@ pub fn export_key(key: Id, data: &mut [u8]) -> Result { /// If key is not `Volatile` (`Persistent` or `Custom(u32)`), handle is closed. /// /// If a key is `Volatile`, `Id` returned contains the key `handle`. Otherwise, it does not. -fn complete_new_key_operation( +pub(crate) fn complete_new_key_operation( key_lifetime: Lifetime, id: psa_key_id_t, handle: psa_key_handle_t, @@ -307,3 +309,100 @@ fn complete_new_key_operation( }, }) } + +/// Copy key material from one location to another +/// The function returns the key ID of the newly created key `Id` can be set to `None` when creating a volatile key. +/// When generating a persistent key with a specific ID, the `Id` structure can be created after +/// reset with the `from_persistent_key_id` constructor on `Id`. +/// +/// The originating key must have the usage flag `copy` set. +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::key_management; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaKeyPair, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # copy: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { +/// # hash_alg: Hash::Sha256.into(), +/// # }.into(), +/// # }, +/// # }; +/// psa_crypto::init().unwrap(); +/// let my_key = key_management::generate(attributes, None).unwrap(); +/// let my_key_copy = key_management::copy(my_key, attributes, None); +/// ``` +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) }; + id + } else { + 0 + }; + let mut handle_for_new_key = 0; + + let copy_res = Status::from(unsafe { + psa_crypto_sys::psa_copy_key(key_handle_to_copy, &key_attributes, &mut handle_for_new_key) + }) + .to_result(); + Attributes::reset(&mut key_attributes); + copy_res?; + complete_new_key_operation(attributes.lifetime, id, handle_for_new_key) +} + +/// Remove non-essential copies of key material from memory +/// +/// This function will remove these extra copies of the key material from memory. +/// +/// This function is not required to remove key material from memory in any of the following situations: +/// The key is currently in use in a cryptographic operation. +/// The key is volatile. +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::key_management; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// use psa_crypto::types::algorithm::{AsymmetricSignature, Hash}; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaKeyPair, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # cache: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign { +/// # hash_alg: Hash::Sha256.into(), +/// # }.into(), +/// # }, +/// # }; +/// psa_crypto::init().unwrap(); +/// //let my_key = key_management::generate(attributes, None).unwrap(); +/// //let size = key_management::purge(my_key).unwrap(); +/// ``` +pub fn purge(/*key_id: Id*/) /*-> Result<()>*/ +{ + error!("This operation is not yet supported by Mbed Crypto. Once it is supported, uncomment and remove this notice"); + // Also uncomment the example + /*initialized()?; + let handle = key_id.handle()?; + let purge_res = Status::from(psa_crypto_sys::psa_purge_key(handle)).to_result() + let close_handle_res = key_id.close_handle(handle); + purge_res?; + close_handle_res*/ +} diff --git a/psa-crypto/src/operations/mac.rs b/psa-crypto/src/operations/mac.rs index f50fae4..87ff6cf 100644 --- a/psa-crypto/src/operations/mac.rs +++ b/psa-crypto/src/operations/mac.rs @@ -2,3 +2,129 @@ // SPDX-License-Identifier: Apache-2.0 //! # Message Authentication Code (MAC) operations + +use crate::initialized; +use crate::types::key::Id; +use crate::types::algorithm::Mac; +use crate::types::status::{Result, Status, Error}; + + +/// Calculate the message authentication code (MAC) of a message +/// The key must allow `sign_message` +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::{mac::compute_mac, key_management::generate}; +/// use psa_crypto::types::algorithm::{Hash, Mac, FullLengthMac}; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// # const MESSAGE: [u8; 32] = [ +/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, +/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, +/// # ]; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaKeyPair, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # sign_message: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: FullLengthMac::Hmac{hash_alg: Hash::Sha256}.into(), +/// # }, +/// # }; +/// # +/// psa_crypto::init().unwrap(); +/// let my_key = generate(attributes, None).unwrap(); +/// let mac_alg = Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256}); +/// let buffer_size = attributes.mac_length(mac_alg).unwrap(); +/// let mut mac = vec![0; buffer_size]; +/// +/// let size = compute_mac(my_key, +/// mac_alg, +/// &MESSAGE, +/// &mut mac).unwrap(); +/// mac.resize(size, 0); +/// ``` +pub fn compute_mac(key_id: Id, mac_alg: Mac, input_message: &[u8], mac: &mut [u8]) -> Result { + initialized()?; + + let mut output_length = 0; + let key_handle = key_id.handle()?; + + let mac_compute_res = Status::from(unsafe { + psa_crypto_sys::psa_mac_compute( + key_handle, + mac_alg.into(), + input_message.as_ptr(), + input_message.len(), + mac.as_mut_ptr(), + mac.len(), + &mut output_length, + )} + ).to_result(); + let close_handle_res = key_id.close_handle(key_handle); + mac_compute_res?; + close_handle_res?; + Ok(output_length) +} + +/// Calculate the message authentication code (MAC) of a message and compare it with a reference value +/// The key must allow `sign_message` +/// +/// # Example +/// +/// ``` +/// use psa_crypto::operations::{mac::{compute_mac, verify_mac}, key_management::generate}; +/// use psa_crypto::types::algorithm::{Hash, Mac, FullLengthMac}; +/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags}; +/// # const MESSAGE: [u8; 32] = [ +/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2, +/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78, +/// # ]; +/// # let mut attributes = Attributes { +/// # key_type: Type::RsaKeyPair, +/// # bits: 1024, +/// # lifetime: Lifetime::Volatile, +/// # policy: Policy { +/// # usage_flags: UsageFlags { +/// # sign_message: true, +/// # ..Default::default() +/// # }, +/// # permitted_algorithms: Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256}).into(), +/// # }, +/// # }; +/// # +/// psa_crypto::init().unwrap(); +/// let my_key = generate(attributes, None).unwrap(); +/// let mac_alg = Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256}); +/// let buffer_size = attributes.mac_length(mac_alg).unwrap(); +/// let mut mac = vec![0; buffer_size]; +/// +/// let size = compute_mac(my_key, +/// mac_alg, +/// &MESSAGE, +/// &mut mac).unwrap(); +/// mac.resize(size, 0); +/// assert!(verify_mac(my_key, mac_alg, &MESSAGE, &mac)); +/// ``` +pub fn verify_mac(key_id: Id, mac_alg: Mac, input_message: &[u8], expected_mac: &[u8]) -> Result<()> { + initialized()?; + + let key_handle = key_id.handle()?; + + let mac_verify_res = Status::from(unsafe { + psa_crypto_sys::psa_mac_verify( + key_handle, + mac_alg.into(), + input_message.as_ptr(), + input_message.len(), + expected_mac.as_ptr(), + expected_mac.len(), + )} + ).to_result(); + let close_handle_res = key_id.close_handle(key_handle); + mac_verify_res?; + close_handle_res +} \ No newline at end of file diff --git a/psa-crypto/src/operations/mod.rs b/psa-crypto/src/operations/mod.rs index 8f6f81d..35411a3 100644 --- a/psa-crypto/src/operations/mod.rs +++ b/psa-crypto/src/operations/mod.rs @@ -8,8 +8,9 @@ pub mod asym_encryption; pub mod asym_signature; pub mod cipher; pub mod key_agreement; -pub mod key_derivation; +//pub mod key_derivation; separate PR pub mod key_management; -pub mod mac; +//pub mod mac; Mbed Crypto does not support mac compute or verify yet (as of 16/07/20) +pub mod hash; pub mod message_digest; pub mod other; diff --git a/psa-crypto/src/types/algorithm.rs b/psa-crypto/src/types/algorithm.rs index 747bc5a..8fdd6c3 100644 --- a/psa-crypto/src/types/algorithm.rs +++ b/psa-crypto/src/types/algorithm.rs @@ -548,8 +548,8 @@ impl TryFrom for Algorithm { let hash: Hash = alg.try_into()?; Ok(hash.into()) } else if psa_crypto_sys::PSA_ALG_IS_MAC(alg) { - error!("MAC algorithms are not supported."); - Err(Error::NotSupported) + let mac: Mac = alg.try_into()?; + Ok(mac.into()) } else if psa_crypto_sys::PSA_ALG_IS_CIPHER(alg) { error!("Cipher algorithms are not supported."); Err(Error::NotSupported) @@ -584,6 +584,10 @@ impl TryFrom for psa_crypto_sys::psa_algorithm_t { Algorithm::Hash(hash) => Ok(hash.into()), Algorithm::AsymmetricSignature(asym_sign) => Ok(asym_sign.into()), Algorithm::AsymmetricEncryption(asym_encrypt) => Ok(asym_encrypt.into()), + Algorithm::Mac(mac) => Ok(mac.into()), + Algorithm::KeyAgreement(key_agreement) => Ok(key_agreement.into()), + Algorithm::KeyDerivation(key_derivation) => Ok(key_derivation.into()), + Algorithm::Aead(aead) => Ok(aead.into()), _ => { error!("Algorithm not supported: {:?}.", alg); Err(Error::NotSupported) @@ -755,6 +759,211 @@ impl From for psa_crypto_sys::psa_algorithm_t { } } +#[cfg(feature = "interface")] +impl TryFrom for Mac { + type Error = Error; + fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result { + if psa_crypto_sys::PSA_ALG_IS_MAC(alg) { + if unsafe { psa_crypto_sys::PSA_ALG_FULL_LENGTH_MAC(alg) } == alg { + Ok(Mac::FullLength(alg.try_into()?)) + } else { + let mac_length = unsafe { psa_crypto_sys::PSA_MAC_TRUNCATED_LENGTH(alg) }; + let mac_alg: FullLengthMac = + unsafe { psa_crypto_sys::PSA_ALG_FULL_LENGTH_MAC(alg) }.try_into()?; + Ok(Mac::Truncated { + mac_alg, + mac_length, + }) + } + } else { + error!("Can not find a valid MAC algorithm for {}.", alg); + Err(Error::InvalidArgument) + } + } +} + +#[cfg(feature = "interface")] +impl TryFrom for FullLengthMac { + type Error = Error; + + fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result { + if psa_crypto_sys::PSA_ALG_IS_HMAC(alg) { + Ok(FullLengthMac::Hmac { + hash_alg: psa_crypto_sys::PSA_ALG_HMAC_GET_HASH(alg).try_into()?, + }) + } else if alg == psa_crypto_sys::PSA_ALG_CBC_MAC { + Ok(FullLengthMac::CbcMac) + } else if alg == psa_crypto_sys::PSA_ALG_CMAC { + Ok(FullLengthMac::Cmac) + } else { + error!("Can not find a valid MAC algorithm for {}.", alg); + Err(Error::InvalidArgument) + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(mac: Mac) -> Self { + match mac { + Mac::FullLength(full_length_mac) => full_length_mac.into(), + Mac::Truncated { + mac_alg: alg, + mac_length: length, + // The following call is NOT currently checked. If length is invalid, the return of this call is unspecified + } => unsafe { psa_crypto_sys::PSA_ALG_TRUNCATED_MAC(alg.into(), length) }, + } + } +} + +#[cfg(feature = "interface")] +impl From for Mac { + fn from(full_length_mac: FullLengthMac) -> Self { + Mac::FullLength(full_length_mac) + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(full_length_mac: FullLengthMac) -> Self { + match full_length_mac { + FullLengthMac::CbcMac => psa_crypto_sys::PSA_ALG_CBC_MAC, + FullLengthMac::Cmac => psa_crypto_sys::PSA_ALG_CMAC, + FullLengthMac::Hmac { hash_alg } => unsafe { + psa_crypto_sys::PSA_ALG_HMAC(hash_alg.into()) + }, + } + } +} + +#[cfg(feature = "interface")] +impl TryFrom for Aead { + type Error = Error; + fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result { + if let Ok(aead_with_default_length_tag) = AeadWithDefaultLengthTag::try_from(alg) { + Ok(Aead::AeadWithDefaultLengthTag(aead_with_default_length_tag)) + } else { + // Must be shortened tag + let aead_alg = AeadWithDefaultLengthTag::try_from(unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) + })?; + let tag_length = psa_crypto_sys::PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(alg); + Ok(Aead::AeadWithShortenedTag { + aead_alg, + tag_length, + }) + } + } +} + +#[cfg(feature = "interface")] +impl TryFrom for AeadWithDefaultLengthTag { + type Error = Error; + + fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result { + if alg + == unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_CCM) + } + { + Ok(AeadWithDefaultLengthTag::Ccm) + } else if alg + == unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_GCM) + } + { + Ok(AeadWithDefaultLengthTag::Gcm) + } else if alg + == unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( + psa_crypto_sys::PSA_ALG_CHACHA20_POLY1305, + ) + } + { + Ok(AeadWithDefaultLengthTag::Chacha20Poly1305) + } else { + error!("Can not find a valid Aead algorithm for {}.", alg); + Err(Error::InvalidArgument) + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(aead: Aead) -> Self { + match aead { + Aead::AeadWithDefaultLengthTag(aead_with_default_length_mac) => { + aead_with_default_length_mac.into() + } + // The following call is NOT currently checked. If length is invalid, the return of this call is unspecified + Aead::AeadWithShortenedTag { + aead_alg, + tag_length, + } => unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg.into(), tag_length) + }, + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(aead_with_default_length_tag: AeadWithDefaultLengthTag) -> Self { + match aead_with_default_length_tag { + AeadWithDefaultLengthTag::Ccm => unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_CCM) + }, + AeadWithDefaultLengthTag::Gcm => unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_GCM) + }, + AeadWithDefaultLengthTag::Chacha20Poly1305 => unsafe { + psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( + psa_crypto_sys::PSA_ALG_CHACHA20_POLY1305, + ) + }, + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(key_agreement: KeyAgreement) -> Self { + match key_agreement { + KeyAgreement::Raw(raw_key_agreement) => raw_key_agreement.into(), + KeyAgreement::WithKeyDerivation { ka_alg, kdf_alg } => unsafe { + psa_crypto_sys::PSA_ALG_KEY_AGREEMENT(ka_alg.into(), kdf_alg.into()) + }, + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(raw_key_agreement: RawKeyAgreement) -> Self { + match raw_key_agreement { + RawKeyAgreement::Ecdh => psa_crypto_sys::PSA_ALG_ECDH, + RawKeyAgreement::Ffdh => psa_crypto_sys::PSA_ALG_FFDH, + } + } +} + +#[cfg(feature = "interface")] +impl From for psa_crypto_sys::psa_algorithm_t { + fn from(key_derivation: KeyDerivation) -> Self { + match key_derivation { + KeyDerivation::Hkdf { hash_alg, .. } => unsafe { + psa_crypto_sys::PSA_ALG_HKDF(hash_alg.into()) + }, + KeyDerivation::Tls12Prf { hash_alg, .. } => unsafe { + psa_crypto_sys::PSA_ALG_TLS12_PRF(hash_alg.into()) + }, + KeyDerivation::Tls12PskToMs { hash_alg, .. } => unsafe { + psa_crypto_sys::PSA_ALG_TLS12_PSK_TO_MS(hash_alg.into()) + }, + } + } +} + #[cfg(test)] mod test { use crate::types::algorithm::{Algorithm, AsymmetricSignature, Hash, SignHash}; diff --git a/psa-crypto/src/types/key.rs b/psa-crypto/src/types/key.rs index ff76f6b..33b17c6 100644 --- a/psa-crypto/src/types/key.rs +++ b/psa-crypto/src/types/key.rs @@ -8,7 +8,7 @@ use crate::initialized; use crate::types::algorithm::{Algorithm, Cipher}; #[cfg(feature = "interface")] -use crate::types::algorithm::{AsymmetricEncryption, AsymmetricSignature}; +use crate::types::algorithm::{AsymmetricEncryption, AsymmetricSignature, Mac}; #[cfg(feature = "operations")] use crate::types::status::Status; use crate::types::status::{Error, Result}; @@ -405,6 +405,15 @@ impl Attributes { ) }) } + + /// Sufficient buffer size for the MAC of the specified algorithm, if compatible + #[cfg(feature = "interface")] + pub fn mac_length(self, mac_alg: Mac) -> Result { + self.compatible_with_alg(mac_alg.into())?; + Ok(unsafe { + psa_crypto_sys::PSA_MAC_LENGTH(self.key_type.try_into()?, self.bits, mac_alg.into()) + }) + } } /// The lifetime of a key indicates where it is stored and which application and system actions diff --git a/psa-crypto/src/types/mod.rs b/psa-crypto/src/types/mod.rs index 8869616..46a5fb2 100644 --- a/psa-crypto/src/types/mod.rs +++ b/psa-crypto/src/types/mod.rs @@ -5,4 +5,5 @@ pub mod algorithm; pub mod key; +//pub mod key_derivation; separate PR pub mod status; diff --git a/psa-crypto/tests/mod.rs b/psa-crypto/tests/mod.rs index 478a6e6..b8d7893 100644 --- a/psa-crypto/tests/mod.rs +++ b/psa-crypto/tests/mod.rs @@ -158,7 +158,7 @@ mod test_tools { } pub fn export_key_pair(&mut self, key_id: Id, key_data: &mut [u8]) -> Result { - key_management::export_key(key_id, key_data) + key_management::export(key_id, key_data) } }