diff --git a/src/providers/trusted_service/asym_encryption.rs b/src/providers/trusted_service/asym_encryption.rs new file mode 100644 index 00000000..6887a79a --- /dev/null +++ b/src/providers/trusted_service/asym_encryption.rs @@ -0,0 +1,68 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use super::Provider; +use crate::authenticators::ApplicationName; +use crate::key_info_managers::KeyTriple; +use crate::providers::mbed_crypto::key_management; +use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt}; +use parsec_interface::requests::{ProviderID, ResponseStatus, Result}; + +impl Provider { + pub(super) fn psa_asymmetric_encrypt_internal( + &self, + app_name: ApplicationName, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + let key_name = op.key_name.clone(); + + let key_triple = KeyTriple::new(app_name, ProviderID::TrustedService, key_name); + let store_handle = self.key_info_store.read().expect("Key store lock poisoned"); + let key_id = key_management::get_key_id(&key_triple, &*store_handle)?; + let salt_buff = match &op.salt { + Some(salt) => salt.to_vec(), + None => Vec::new(), + }; + + match self + .context + .asym_encrypt(key_id, op.alg, op.plaintext.to_vec(), salt_buff) + { + Ok(ciphertext) => Ok(psa_asymmetric_encrypt::Result { + ciphertext: ciphertext.into(), + }), + Err(error) => { + let error = ResponseStatus::from(error); + format_error!("Encrypt status: ", error); + Err(error) + } + } + } + + pub(super) fn psa_asymmetric_decrypt_internal( + &self, + app_name: ApplicationName, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + let key_triple = KeyTriple::new(app_name, ProviderID::TrustedService, op.key_name.clone()); + let store_handle = self.key_info_store.read().expect("Key store lock poisoned"); + let key_id = key_management::get_key_id(&key_triple, &*store_handle)?; + let salt_buff = match &op.salt { + Some(salt) => salt.to_vec(), + None => Vec::new(), + }; + + match self + .context + .asym_decrypt(key_id, op.alg, op.ciphertext.to_vec(), salt_buff) + { + Ok(plaintext) => Ok(psa_asymmetric_decrypt::Result { + plaintext: plaintext.into(), + }), + Err(error) => { + let error = ResponseStatus::from(error); + format_error!("Decrypt status: ", error); + Err(error) + } + } + } +} diff --git a/src/providers/trusted_service/context/asym_encryption.rs b/src/providers/trusted_service/context/asym_encryption.rs new file mode 100644 index 00000000..f4897a62 --- /dev/null +++ b/src/providers/trusted_service/context/asym_encryption.rs @@ -0,0 +1,61 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use super::ts_protobuf::{ + AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricEncryptIn, AsymmetricEncryptOut, +}; +use super::Context; +use log::info; +use parsec_interface::operations::psa_algorithm::AsymmetricEncryption; +use parsec_interface::requests::ResponseStatus; +use std::convert::TryInto; +use zeroize::Zeroize; + +impl Context { + pub fn asym_encrypt( + &self, + key_id: u32, + alg: AsymmetricEncryption, + mut plaintext: Vec, + mut salt: Vec, + ) -> Result, ResponseStatus> { + info!("Handling AsymmetricEncrypt request"); + let alg = alg.try_into().map_err(|e| { + plaintext.zeroize(); + salt.zeroize(); + e + })?; + let req = AsymmetricEncryptIn { + handle: 0, + alg, + plaintext, + salt, + }; + let AsymmetricEncryptOut { ciphertext } = self.send_request_with_key(req, key_id)?; + + Ok(ciphertext) + } + + pub fn asym_decrypt( + &self, + key_id: u32, + alg: AsymmetricEncryption, + mut ciphertext: Vec, + mut salt: Vec, + ) -> Result, ResponseStatus> { + info!("Handling AsymmetricDecrypt request"); + let alg = alg.try_into().map_err(|e| { + ciphertext.zeroize(); + salt.zeroize(); + e + })?; + let req = AsymmetricDecryptIn { + handle: 0, + alg, + ciphertext, + salt, + }; + let AsymmetricDecryptOut { plaintext } = self.send_request_with_key(req, key_id)?; + + Ok(plaintext) + } +} diff --git a/src/providers/trusted_service/context/key_management.rs b/src/providers/trusted_service/context/key_management.rs index 483d7dab..3ea7a4d4 100644 --- a/src/providers/trusted_service/context/key_management.rs +++ b/src/providers/trusted_service/context/key_management.rs @@ -53,7 +53,7 @@ impl Context { ) -> Result<(), ResponseStatus> { info!("Handling ImportKey request"); let mut data = key_data.to_vec(); - let mut import_req = ImportKeyIn { + let import_req = ImportKeyIn { attributes: Some(KeyAttributes { r#type: u16::try_from(key_attrs.key_type).map_err(|e| { data.zeroize(); @@ -79,9 +79,7 @@ impl Context { }), data, }; - let res = self.send_request(&import_req); - import_req.data.zeroize(); - let ImportKeyOut { handle } = res?; + let ImportKeyOut { handle } = self.send_request(&import_req)?; let close_req = CloseKeyIn { handle }; self.send_request(&close_req)?; diff --git a/src/providers/trusted_service/context/mod.rs b/src/providers/trusted_service/context/mod.rs index fe1615d3..4ebaddc9 100644 --- a/src/providers/trusted_service/context/mod.rs +++ b/src/providers/trusted_service/context/mod.rs @@ -30,90 +30,13 @@ pub mod ts_binding { include!(concat!(env!("OUT_DIR"), "/ts_bindings.rs")); } +mod asym_encryption; mod asym_sign; mod key_management; - -#[allow( - non_snake_case, - non_camel_case_types, - non_upper_case_globals, - clippy::unseparated_literal_suffix, - // There is an issue where long double become u128 in extern blocks. Check this issue: - // https://github.com/rust-lang/rust-bindgen/issues/1549 - improper_ctypes, - missing_debug_implementations, - trivial_casts, - clippy::all, - unused, - unused_qualifications -)] -mod ts_protobuf { - include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs")); - - /// Trait for associating an Opcode with each operation type - /// and obtaining it in a generic way. - pub trait GetOpcode { - fn opcode(&self) -> Opcode; - } - - macro_rules! opcode_impl { - ($type:ty, $opcode:ident) => { - impl GetOpcode for $type { - fn opcode(&self) -> Opcode { - Opcode::$opcode - } - } - }; - - ($type_in:ty, $type_out:ty, $opcode:ident) => { - impl GetOpcode for $type_in { - fn opcode(&self) -> Opcode { - Opcode::$opcode - } - } - - impl GetOpcode for $type_out { - fn opcode(&self) -> Opcode { - Opcode::$opcode - } - } - }; - } - - opcode_impl!(OpenKeyIn, OpenKeyOut, OpenKey); - opcode_impl!(CloseKeyIn, CloseKey); - opcode_impl!(GenerateKeyIn, GenerateKeyOut, GenerateKey); - opcode_impl!(DestroyKeyIn, DestroyKeyOut, DestroyKey); - opcode_impl!(SignHashIn, SignHashOut, SignHash); - opcode_impl!(VerifyHashIn, VerifyHashOut, VerifyHash); - opcode_impl!(ImportKeyIn, ImportKeyOut, ImportKey); - opcode_impl!(ExportPublicKeyIn, ExportPublicKeyOut, ExportPublicKey); - - /// Trait allowing the handle of opened-key-dependent operations - /// to be set in a generic way. - pub trait SetHandle { - fn set_handle(&mut self, handle: u32); - } - - macro_rules! set_handle_impl { - ($type:ty) => { - impl SetHandle for $type { - fn set_handle(&mut self, handle: u32) { - self.handle = handle; - } - } - }; - } - - set_handle_impl!(DestroyKeyIn); - set_handle_impl!(SignHashIn); - set_handle_impl!(VerifyHashIn); - set_handle_impl!(ExportPublicKeyIn); -} +mod ts_protobuf; // TODO: // * RPC caller error handling -// * proper logging /// Context for interacting with the crypto Trusted Service (TS). /// @@ -222,6 +145,9 @@ impl Context { format_error!("Failed to serialize Protobuf request", e); PsaError::CommunicationFailure })?; + let mut v = Vec::new(); + let _ = req.encode(&mut v); + dbg!(v); trace!("Invoking RPC call"); let mut opstatus = 0; diff --git a/src/providers/trusted_service/context/ts_protobuf.rs b/src/providers/trusted_service/context/ts_protobuf.rs new file mode 100644 index 00000000..96cffa23 --- /dev/null +++ b/src/providers/trusted_service/context/ts_protobuf.rs @@ -0,0 +1,116 @@ +// Copyright 2020 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +#![allow( + non_snake_case, + non_camel_case_types, + non_upper_case_globals, + clippy::unseparated_literal_suffix, + // There is an issue where long double become u128 in extern blocks. Check this issue: + // https://github.com/rust-lang/rust-bindgen/issues/1549 + improper_ctypes, + missing_debug_implementations, + trivial_casts, + clippy::all, + unused, + unused_qualifications +)] +use zeroize::Zeroize; + +include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs")); + +/// Trait for associating an Opcode with each operation type +/// and obtaining it in a generic way. +pub trait GetOpcode { + fn opcode(&self) -> Opcode; +} + +macro_rules! opcode_impl { + ($type:ty, $opcode:ident) => { + impl GetOpcode for $type { + fn opcode(&self) -> Opcode { + Opcode::$opcode + } + } + }; + + ($type_in:ty, $type_out:ty, $opcode:ident) => { + impl GetOpcode for $type_in { + fn opcode(&self) -> Opcode { + Opcode::$opcode + } + } + + impl GetOpcode for $type_out { + fn opcode(&self) -> Opcode { + Opcode::$opcode + } + } + }; +} + +opcode_impl!(OpenKeyIn, OpenKeyOut, OpenKey); +opcode_impl!(CloseKeyIn, CloseKey); +opcode_impl!(GenerateKeyIn, GenerateKeyOut, GenerateKey); +opcode_impl!(DestroyKeyIn, DestroyKeyOut, DestroyKey); +opcode_impl!(SignHashIn, SignHashOut, SignHash); +opcode_impl!(VerifyHashIn, VerifyHashOut, VerifyHash); +opcode_impl!(AsymmetricEncryptIn, AsymmetricEncryptOut, AsymmetricEncrypt); +opcode_impl!(AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricDecrypt); +opcode_impl!(ImportKeyIn, ImportKeyOut, ImportKey); +opcode_impl!(ExportPublicKeyIn, ExportPublicKeyOut, ExportPublicKey); + +/// Trait allowing the handle of opened-key-dependent operations +/// to be set in a generic way. +pub trait SetHandle { + fn set_handle(&mut self, handle: u32); +} + +macro_rules! set_handle_impl { + ($type:ty) => { + impl SetHandle for $type { + fn set_handle(&mut self, handle: u32) { + self.handle = handle; + } + } + }; +} + +set_handle_impl!(DestroyKeyIn); +set_handle_impl!(SignHashIn); +set_handle_impl!(VerifyHashIn); +set_handle_impl!(AsymmetricEncryptIn); +set_handle_impl!(AsymmetricDecryptIn); +set_handle_impl!(ExportPublicKeyIn); + +impl Drop for ImportKeyIn { + fn drop(&mut self) { + self.data.zeroize(); + } +} + +impl Drop for AsymmetricEncryptIn { + fn drop(&mut self) { + self.plaintext.zeroize(); + self.salt.zeroize(); + } +} + +impl Drop for AsymmetricDecryptIn { + fn drop(&mut self) { + self.ciphertext.zeroize(); + self.salt.zeroize(); + } +} + +impl Drop for SignHashIn { + fn drop(&mut self) { + self.hash.zeroize(); + } +} + +impl Drop for VerifyHashIn { + fn drop(&mut self) { + self.hash.zeroize(); + self.signature.zeroize(); + } +} diff --git a/src/providers/trusted_service/mod.rs b/src/providers/trusted_service/mod.rs index fc20f4fd..c0d57540 100644 --- a/src/providers/trusted_service/mod.rs +++ b/src/providers/trusted_service/mod.rs @@ -12,8 +12,8 @@ use derivative::Derivative; use log::{error, trace}; use parsec_interface::operations::list_providers::ProviderInfo; use parsec_interface::operations::{ - list_keys, psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key, - psa_sign_hash, psa_verify_hash, + list_keys, psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_destroy_key, + psa_export_public_key, psa_generate_key, psa_import_key, psa_sign_hash, psa_verify_hash, }; use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result}; use psa_crypto::types::key; @@ -25,17 +25,20 @@ use std::sync::{ }; use uuid::Uuid; +mod asym_encryption; mod asym_sign; mod context; mod key_management; -const SUPPORTED_OPCODES: [Opcode; 6] = [ +const SUPPORTED_OPCODES: [Opcode; 8] = [ Opcode::PsaDestroyKey, Opcode::PsaGenerateKey, Opcode::PsaSignHash, Opcode::PsaVerifyHash, Opcode::PsaImportKey, Opcode::PsaExportPublicKey, + Opcode::PsaAsymmetricEncrypt, + Opcode::PsaAsymmetricDecrypt, ]; /// Trusted Service provider structure @@ -207,6 +210,24 @@ impl Provide for Provider { trace!("psa_verify_hash ingress"); self.psa_verify_hash_internal(app_name, op) } + + fn psa_asymmetric_encrypt( + &self, + app_name: ApplicationName, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_encrypt ingress"); + self.psa_asymmetric_encrypt_internal(app_name, op) + } + + fn psa_asymmetric_decrypt( + &self, + app_name: ApplicationName, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_decrypt ingress"); + self.psa_asymmetric_decrypt_internal(app_name, op) + } } /// Trusted Service provider builder