Skip to content

Commit

Permalink
Add asymmetric encryption to TS provider
Browse files Browse the repository at this point in the history
This commit adds asymmetric encryption functionality in the TS
provider. It also moves the TS protobuf code in a new module given
that it now contains a bunch of hand written code as well.

Signed-off-by: Ionut Mihalcea <ionut.mihalcea@arm.com>
  • Loading branch information
ionut-arm committed Nov 27, 2020
1 parent ad00225 commit 27feb4b
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 86 deletions.
68 changes: 68 additions & 0 deletions src/providers/trusted_service/asym_encryption.rs
Original file line number Diff line number Diff line change
@@ -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<psa_asymmetric_encrypt::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<psa_asymmetric_decrypt::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)
}
}
}
}
61 changes: 61 additions & 0 deletions src/providers/trusted_service/context/asym_encryption.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
mut salt: Vec<u8>,
) -> Result<Vec<u8>, 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<u8>,
mut salt: Vec<u8>,
) -> Result<Vec<u8>, 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)
}
}
6 changes: 2 additions & 4 deletions src/providers/trusted_service/context/key_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)?;
Expand Down
84 changes: 5 additions & 79 deletions src/providers/trusted_service/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
///
Expand Down Expand Up @@ -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;
Expand Down
116 changes: 116 additions & 0 deletions src/providers/trusted_service/context/ts_protobuf.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading

0 comments on commit 27feb4b

Please sign in to comment.