diff --git a/ci.sh b/ci.sh index 29559594..bd693d2d 100755 --- a/ci.sh +++ b/ci.sh @@ -126,6 +126,9 @@ setup_mappings() { reload_service } +# Use the newest version of the Rust toolchain +rustup update + # Parse arguments NO_CARGO_CLEAN= NO_STRESS_TEST= @@ -288,7 +291,6 @@ if [ "$PROVIDER_NAME" = "cargo-check" ]; then # - openSUSE Tumbleweed # - openSUSE Leap 15.3 # The oldest is currently in openSUSE Leap 15.3 and is 1.53.0. - rustup update rustup toolchain install 1.53.0 # The "jwt-svid-authenticator" can not be compiled on 1.53.0 diff --git a/e2e_tests/docker_image/parsec-service-test-all.Dockerfile b/e2e_tests/docker_image/parsec-service-test-all.Dockerfile index 94037654..a141c17f 100644 --- a/e2e_tests/docker_image/parsec-service-test-all.Dockerfile +++ b/e2e_tests/docker_image/parsec-service-test-all.Dockerfile @@ -31,10 +31,10 @@ RUN rm -rf tpm2-tss # Download and install TPM 2.0 Tools verison 4.1.1 RUN git clone https://github.com/tpm2-software/tpm2-tools.git --branch 4.1.1 RUN cd tpm2-tools \ - && ./bootstrap \ - && ./configure --prefix=/usr \ - && make -j$(nproc) \ - && make install + && ./bootstrap \ + && ./configure --prefix=/usr \ + && make -j$(nproc) \ + && make install RUN rm -rf tpm2-tools # Download and install software TPM @@ -48,7 +48,7 @@ RUN mkdir -p $ibmtpm_name \ WORKDIR $ibmtpm_name/src RUN sed -i 's/-DTPM_NUVOTON/-DTPM_NUVOTON $(CFLAGS)/' makefile RUN CFLAGS="-DNV_MEMORY_SIZE=32768 -DMIN_EVICT_OBJECTS=7" make -j$(nproc) \ -&& cp tpm_server /usr/local/bin + && cp tpm_server /usr/local/bin RUN rm -rf $ibmtpm_name/src $ibmtpm_name # Download and install SoftHSMv2 @@ -90,13 +90,13 @@ RUN git config --global user.email "some@email.com" RUN git config --global user.name "Parsec Team" RUN git clone https://git.trustedfirmware.org/TS/trusted-services.git --branch integration \ && cd trusted-services \ - && git reset --hard c1cf9120e4ab0b359a27176b079769b9a7e6bb87 + && git reset --hard 389b50624f25dae860bbbf8b16f75b32f1589c8d # Install correct python dependencies RUN pip3 install -r trusted-services/requirements.txt RUN cd trusted-services/deployments/libts/linux-pc/ \ && cmake . \ && make \ - && cp libts.so nanopb_install/lib/libprotobuf-nanopb.a mbedtls_install/lib/libmbedcrypto.a /usr/local/lib/ + && cp libts.so* nanopb_install/lib/libprotobuf-nanopb.a mbedtls_install/lib/libmbedcrypto.a /usr/local/lib/ RUN rm -rf trusted-services # Create a new token in a new slot. The slot number assigned will be random diff --git a/src/providers/mbed_crypto/mod.rs b/src/providers/mbed_crypto/mod.rs index 5e434bfd..54999f7a 100644 --- a/src/providers/mbed_crypto/mod.rs +++ b/src/providers/mbed_crypto/mod.rs @@ -149,13 +149,10 @@ impl Provider { } }; for key_identity in to_remove.iter() { - if mbed_crypto_provider + mbed_crypto_provider .key_info_store .remove_key_info(key_identity) - .is_err() - { - return None; - } + .ok()?; } } mbed_crypto_provider.id_counter.store(max_key_id, Relaxed); diff --git a/src/providers/trusted_service/asym_encryption.rs b/src/providers/trusted_service/asym_encryption.rs new file mode 100644 index 00000000..bef5d738 --- /dev/null +++ b/src/providers/trusted_service/asym_encryption.rs @@ -0,0 +1,70 @@ +// Copyright 2021 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use super::Provider; +use crate::authenticators::ApplicationIdentity; +use crate::key_info_managers::KeyIdentity; +use log::error; +use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt}; +use parsec_interface::requests::Result; + +impl Provider { + pub(super) fn psa_asymmetric_encrypt_internal( + &self, + application_identity: &ApplicationIdentity, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + let key_identity = KeyIdentity::new( + application_identity.clone(), + self.provider_identity.clone(), + op.key_name.clone(), + ); + let key_id = self.key_info_store.get_key_id(&key_identity)?; + 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) => { + error!("Encrypt failed with status: {}", error); + Err(error) + } + } + } + + pub(super) fn psa_asymmetric_decrypt_internal( + &self, + application_identity: &ApplicationIdentity, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + let key_identity = KeyIdentity::new( + application_identity.clone(), + self.provider_identity.clone(), + op.key_name.clone(), + ); + let key_id = self.key_info_store.get_key_id(&key_identity)?; + 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) => { + error!("Decrypt failed with 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..7b53e0ee --- /dev/null +++ b/src/providers/trusted_service/context/asym_encryption.rs @@ -0,0 +1,58 @@ +// Copyright 2021 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use super::ts_protobuf::{ + AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricEncryptIn, AsymmetricEncryptOut, +}; +use super::Context; +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> { + let alg = alg.try_into().map_err(|e| { + plaintext.zeroize(); + salt.zeroize(); + e + })?; + let req = AsymmetricEncryptIn { + id: key_id, + alg, + plaintext, + salt, + }; + let AsymmetricEncryptOut { ciphertext } = self.send_request(&req)?; + + Ok(ciphertext) + } + + pub fn asym_decrypt( + &self, + key_id: u32, + alg: AsymmetricEncryption, + mut ciphertext: Vec, + mut salt: Vec, + ) -> Result, ResponseStatus> { + let alg = alg.try_into().map_err(|e| { + ciphertext.zeroize(); + salt.zeroize(); + e + })?; + let req = AsymmetricDecryptIn { + id: key_id, + alg, + ciphertext, + salt, + }; + let AsymmetricDecryptOut { plaintext } = self.send_request(&req)?; + + Ok(plaintext) + } +} diff --git a/src/providers/trusted_service/context/error.rs b/src/providers/trusted_service/context/error.rs index a6e9cc62..94660130 100644 --- a/src/providers/trusted_service/context/error.rs +++ b/src/providers/trusted_service/context/error.rs @@ -178,6 +178,8 @@ pub enum WrapperError { CallBufferNull, /// serialization or deserialization of protobuf message failed FailedPbConversion, + /// invalid operation status value + InvalidOpStatus, /// a parameter passed to the function was invalid InvalidParam, } @@ -196,6 +198,9 @@ impl fmt::Display for WrapperError { WrapperError::InvalidParam => { write!(f, "a parameter passed to the function was invalid") } + WrapperError::InvalidOpStatus => { + write!(f, "the RPC layer returned an invalid operation status") + } } } } diff --git a/src/providers/trusted_service/context/mod.rs b/src/providers/trusted_service/context/mod.rs index 2d0fa749..05a53e7a 100644 --- a/src/providers/trusted_service/context/mod.rs +++ b/src/providers/trusted_service/context/mod.rs @@ -3,7 +3,7 @@ use error::{Error, WrapperError}; use log::{error, info, trace}; use prost::Message; -use std::convert::TryInto; +use std::convert::{TryFrom, TryInto}; use std::ffi::{c_void, CString}; use std::io::{self}; use std::ptr::null_mut; @@ -27,9 +27,11 @@ use ts_protobuf::GetOpcode; unused_qualifications )] pub mod ts_binding { + #![allow(deref_nullptr)] include!(concat!(env!("OUT_DIR"), "/ts_bindings.rs")); } +mod asym_encryption; mod asym_sign; pub mod error; mod generate_random; @@ -158,7 +160,11 @@ impl Context { &mut resp_buf_size, ) }; - Error::from_status_opstatus(status, opstatus).map_err(|e| { + Error::from_status_opstatus( + status, + i32::try_from(opstatus).map_err(|_| Error::Wrapper(WrapperError::InvalidOpStatus))?, + ) + .map_err(|e| { unsafe { rpc_caller_end(self.rpc_caller, call_handle) }; e })?; diff --git a/src/providers/trusted_service/context/ts_protobuf.rs b/src/providers/trusted_service/context/ts_protobuf.rs index fd947d3f..e88efc91 100644 --- a/src/providers/trusted_service/context/ts_protobuf.rs +++ b/src/providers/trusted_service/context/ts_protobuf.rs @@ -56,6 +56,8 @@ opcode_impl!(ImportKeyIn, ImportKeyOut, ImportKey); opcode_impl!(ExportPublicKeyIn, ExportPublicKeyOut, ExportPublicKey); opcode_impl!(ExportKeyIn, ExportKeyOut, ExportKey); opcode_impl!(GenerateRandomIn, GenerateRandomOut, GenerateRandom); +opcode_impl!(AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricDecrypt); +opcode_impl!(AsymmetricEncryptIn, AsymmetricEncryptOut, AsymmetricEncrypt); impl Drop for ImportKeyIn { fn drop(&mut self) { diff --git a/src/providers/trusted_service/error.rs b/src/providers/trusted_service/error.rs index 811f3ac0..7fee5e51 100644 --- a/src/providers/trusted_service/error.rs +++ b/src/providers/trusted_service/error.rs @@ -26,7 +26,8 @@ impl From for ResponseStatus { WrapperError::CallBufferNull | WrapperError::CallHandleNull | WrapperError::FailedPbConversion - | WrapperError::InvalidParam => ResponseStatus::PsaErrorCommunicationFailure, + | WrapperError::InvalidParam + | WrapperError::InvalidOpStatus => ResponseStatus::PsaErrorCommunicationFailure, } } } diff --git a/src/providers/trusted_service/mod.rs b/src/providers/trusted_service/mod.rs index 4cce504e..9119eb9b 100644 --- a/src/providers/trusted_service/mod.rs +++ b/src/providers/trusted_service/mod.rs @@ -12,8 +12,9 @@ use derivative::Derivative; use log::{error, trace}; use parsec_interface::operations::list_providers::ProviderInfo; use parsec_interface::operations::{ - can_do_crypto, list_clients, list_keys, psa_destroy_key, psa_export_key, psa_export_public_key, - psa_generate_key, psa_generate_random, psa_import_key, psa_sign_hash, psa_verify_hash, + can_do_crypto, list_clients, list_keys, psa_asymmetric_decrypt, psa_asymmetric_encrypt, + psa_destroy_key, psa_export_key, psa_export_public_key, psa_generate_key, psa_generate_random, + psa_import_key, psa_sign_hash, psa_verify_hash, }; use parsec_interface::requests::{Opcode, ProviderId, Result}; use psa_crypto::types::key; @@ -21,6 +22,7 @@ use std::collections::HashSet; use std::sync::atomic::{AtomicU32, Ordering}; use uuid::Uuid; +mod asym_encryption; mod asym_sign; mod capability_discovery; mod context; @@ -28,7 +30,7 @@ mod error; mod generate_random; mod key_management; -const SUPPORTED_OPCODES: [Opcode; 9] = [ +const SUPPORTED_OPCODES: [Opcode; 11] = [ Opcode::PsaDestroyKey, Opcode::PsaGenerateKey, Opcode::PsaSignHash, @@ -38,6 +40,8 @@ const SUPPORTED_OPCODES: [Opcode; 9] = [ Opcode::PsaExportKey, Opcode::PsaGenerateRandom, Opcode::CanDoCrypto, + Opcode::PsaAsymmetricEncrypt, + Opcode::PsaAsymmetricDecrypt, ]; /// Trusted Service provider structure /// @@ -239,6 +243,24 @@ impl Provide for Provider { trace!("can_do_crypto ingress"); self.can_do_crypto_main(application_identity, op) } + + fn psa_asymmetric_encrypt( + &self, + application_identity: &ApplicationIdentity, + op: psa_asymmetric_encrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_encrypt ingress"); + self.psa_asymmetric_encrypt_internal(application_identity, op) + } + + fn psa_asymmetric_decrypt( + &self, + application_identity: &ApplicationIdentity, + op: psa_asymmetric_decrypt::Operation, + ) -> Result { + trace!("psa_asymmetric_decrypt ingress"); + self.psa_asymmetric_decrypt_internal(application_identity, op) + } } /// Trusted Service provider builder diff --git a/src/utils/service_builder.rs b/src/utils/service_builder.rs index 5a59a9bb..ec53fbce 100644 --- a/src/utils/service_builder.rs +++ b/src/utils/service_builder.rs @@ -422,7 +422,7 @@ unsafe fn get_provider( } #[cfg(feature = "trusted-service-provider")] ProviderConfig::TrustedService { .. } => { - info!("Creating a TPM Provider."); + info!("Creating a Trusted Service Provider."); let provider_identity = ProviderIdentity::new( TrustedServiceProvider::PROVIDER_UUID.to_string(), config.provider_name()?, diff --git a/trusted-services-vendor b/trusted-services-vendor index c1cf9120..389b5062 160000 --- a/trusted-services-vendor +++ b/trusted-services-vendor @@ -1 +1 @@ -Subproject commit c1cf9120e4ab0b359a27176b079769b9a7e6bb87 +Subproject commit 389b50624f25dae860bbbf8b16f75b32f1589c8d