Skip to content

Commit

Permalink
Add unauthenticated cypher operations in psa-crypto and psa-crypto-sys.
Browse files Browse the repository at this point in the history
Signed-off-by: Edmund Grimley Evans <[email protected]>
  • Loading branch information
egrimley-arm committed Mar 22, 2022
1 parent 00a2d70 commit ac827c5
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 15 deletions.
6 changes: 6 additions & 0 deletions psa-crypto-sys/src/c/shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ shim_key_attributes_init(void)
return psa_key_attributes_init();
}

psa_cipher_operation_t
shim_cipher_operation_init(void)
{
return psa_cipher_operation_init();
}

psa_key_derivation_operation_t
shim_key_derivation_operation_init(void)
{
Expand Down
1 change: 1 addition & 0 deletions psa-crypto-sys/src/c/shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,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_cipher_operation_t shim_cipher_operation_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);
Expand Down
19 changes: 11 additions & 8 deletions psa-crypto-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@ pub use types::*;
#[cfg(feature = "operations")]
pub use psa_crypto_binding::{
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,
psa_cipher_abort, psa_cipher_decrypt_setup, psa_cipher_encrypt_setup, psa_cipher_finish,
psa_cipher_set_iv, psa_cipher_update, 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, psa_key_derivation_operation_t};
pub use psa_crypto_binding::{
psa_cipher_operation_t, psa_key_attributes_t, psa_key_derivation_operation_t,
};

// Secure Element Driver definitions
#[cfg(feature = "interface")]
Expand Down
10 changes: 7 additions & 3 deletions psa-crypto-sys/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
//! generated by bindgen, such as #define or static inline functions.
use super::psa_crypto_binding::{
self, psa_algorithm_t, psa_dh_family_t, psa_ecc_family_t, psa_key_attributes_t,
psa_key_derivation_operation_t, psa_key_derivation_step_t, psa_key_id_t, psa_key_lifetime_t,
psa_key_type_t, psa_key_usage_t,
self, psa_algorithm_t, psa_cipher_operation_t, psa_dh_family_t, psa_ecc_family_t,
psa_key_attributes_t, psa_key_derivation_operation_t, psa_key_derivation_step_t, psa_key_id_t,
psa_key_lifetime_t, psa_key_type_t, psa_key_usage_t,
};

pub const PSA_KEY_DERIVATION_INPUT_SECRET: psa_key_derivation_step_t =
Expand Down Expand Up @@ -45,6 +45,10 @@ pub unsafe fn psa_key_attributes_init() -> psa_key_attributes_t {
psa_crypto_binding::shim_key_attributes_init()
}

pub unsafe fn psa_cipher_operation_init() -> psa_cipher_operation_t {
psa_crypto_binding::shim_cipher_operation_init()
}

pub fn psa_key_derivation_operation_init() -> psa_key_derivation_operation_t {
unsafe { psa_crypto_binding::shim_key_derivation_operation_init() }
}
Expand Down
154 changes: 154 additions & 0 deletions psa-crypto/src/operations/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,157 @@
// SPDX-License-Identifier: Apache-2.0

//! # Unauthenticated Ciphers operations
use crate::initialized;
use crate::types::algorithm::Cipher;
use crate::types::key::Id;
use crate::types::status::{Result, Status};

fn crypt(
encrypt: bool,
key_id: Id,
alg: Cipher,
plaintext: &[u8],
iv: &[u8],
ciphertext: &mut [u8],
) -> Result<usize> {
initialized()?;

let mut operation: psa_crypto_sys::psa_cipher_operation_t =
unsafe { psa_crypto_sys::psa_cipher_operation_init() };

Status::from(unsafe {
(if encrypt {
psa_crypto_sys::psa_cipher_encrypt_setup
} else {
psa_crypto_sys::psa_cipher_decrypt_setup
})(&mut operation, key_id.0, alg.into())
})
.to_result()?;

let mut output_length = 0;
let mut output_length_finish = 0;
match (|| {
Status::from(unsafe {
psa_crypto_sys::psa_cipher_set_iv(&mut operation, iv.as_ptr(), iv.len())
})
.to_result()?;

Status::from(unsafe {
psa_crypto_sys::psa_cipher_update(
&mut operation,
plaintext.as_ptr(),
plaintext.len(),
ciphertext.as_mut_ptr(),
ciphertext.len(),
&mut output_length,
)
})
.to_result()?;

Status::from(unsafe {
psa_crypto_sys::psa_cipher_finish(
&mut operation,
ciphertext.as_mut_ptr().add(output_length),
ciphertext.len() - output_length,
&mut output_length_finish,
)
})
.to_result()?;

Ok(())
})() {
Ok(()) => (),
Err(x) => {
Status::from(unsafe { psa_crypto_sys::psa_cipher_abort(&mut operation) })
.to_result()?;
return Err(x);
}
}

Ok(output_length + output_length_finish)
}

/// Encrypt a short message with a key
///
/// The encrypted message is written in `ciphertext`. The function returns the number of bytes written.
///
/// # Example
///
/// ```
/// # use psa_crypto::operations::cipher::encrypt;
/// # use psa_crypto::operations::key_management::generate;
/// # use psa_crypto::types::algorithm::Cipher;
/// # use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
/// #
/// # let mut usage_flags: UsageFlags = Default::default();
/// # usage_flags.set_encrypt();
/// # let mut attributes = Attributes {
/// # key_type: Type::Aes,
/// # bits: 128,
/// # lifetime: Lifetime::Volatile,
/// # policy: Policy {
/// # usage_flags,
/// # permitted_algorithms: Cipher::CbcNoPadding.into(),
/// # },
/// # };
/// # const MESSAGE: [u8; 16] = [0; 16];
/// psa_crypto::init().unwrap();
/// let my_key = generate(attributes, None).unwrap();
/// let alg = Cipher::CbcNoPadding;
/// let iv = vec![0; 16];
/// let mut encrypted_message = vec![0; MESSAGE.len()];
///
/// let size = encrypt(my_key, alg, &MESSAGE, &iv, &mut encrypted_message).unwrap();
/// ```
pub fn encrypt(
key_id: Id,
alg: Cipher,
plaintext: &[u8],
iv: &[u8],
ciphertext: &mut [u8],
) -> Result<usize> {
crypt(true, key_id, alg, plaintext, iv, ciphertext)
}

/// Decrypt a short message with a key
///
/// The decrypted message is written in `plaintext`. The function returns the number of bytes written.
///
/// # Example
///
/// ```
/// # use psa_crypto::operations::cipher::decrypt;
/// # use psa_crypto::operations::key_management::generate;
/// # use psa_crypto::types::algorithm::Cipher;
/// # use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
/// #
/// # let mut usage_flags: UsageFlags = Default::default();
/// # usage_flags.set_decrypt();
/// # let mut attributes = Attributes {
/// # key_type: Type::Aes,
/// # bits: 128,
/// # lifetime: Lifetime::Volatile,
/// # policy: Policy {
/// # usage_flags,
/// # permitted_algorithms: Cipher::Ctr.into(),
/// # },
/// # };
/// # const MESSAGE: [u8; 13] = [0; 13];
/// psa_crypto::init().unwrap();
/// let my_key = generate(attributes, None).unwrap();
/// let alg = Cipher::Ctr;
/// let iv = vec![0; 16];
/// let mut decrypted_message = vec![0; MESSAGE.len()];
///
/// let size = decrypt(my_key, alg, &MESSAGE, &iv, &mut decrypted_message).unwrap();
/// ```
pub fn decrypt(
key_id: Id,
alg: Cipher,
ciphertext: &[u8],
iv: &[u8],
plaintext: &mut [u8],
) -> Result<usize> {
crypt(false, key_id, alg, ciphertext, iv, plaintext)
}
21 changes: 17 additions & 4 deletions psa-crypto/src/types/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,7 @@ impl TryFrom<Algorithm> for psa_crypto_sys::psa_algorithm_t {
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)
}
Algorithm::Cipher(cipher) => Ok(cipher.into()),
}
}
}
Expand Down Expand Up @@ -770,6 +767,22 @@ impl From<AsymmetricEncryption> for psa_crypto_sys::psa_algorithm_t {
}
}

#[cfg(feature = "interface")]
impl From<Cipher> for psa_crypto_sys::psa_algorithm_t {
fn from(cipher: Cipher) -> Self {
match cipher {
Cipher::StreamCipher => psa_crypto_sys::PSA_ALG_STREAM_CIPHER,
Cipher::Ctr => psa_crypto_sys::PSA_ALG_CTR,
Cipher::Cfb => psa_crypto_sys::PSA_ALG_CFB,
Cipher::Ofb => psa_crypto_sys::PSA_ALG_OFB,
Cipher::Xts => psa_crypto_sys::PSA_ALG_XTS,
Cipher::EcbNoPadding => psa_crypto_sys::PSA_ALG_ECB_NO_PADDING,
Cipher::CbcNoPadding => psa_crypto_sys::PSA_ALG_CBC_NO_PADDING,
Cipher::CbcPkcs7 => psa_crypto_sys::PSA_ALG_CBC_PKCS7,
}
}
}

#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Mac {
type Error = Error;
Expand Down

0 comments on commit ac827c5

Please sign in to comment.