Skip to content

Commit c3ec023

Browse files
committed
Added asymmetric encrypt and decrypt
Signed-off-by: Samuel Bailey <[email protected]>
1 parent 6ca5f87 commit c3ec023

File tree

2 files changed

+115
-3
lines changed

2 files changed

+115
-3
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ edition = "2018"
1313
documentation = "https://docs.rs/crate/parsec-client"
1414

1515
[dependencies]
16-
parsec-interface = "0.17.1"
16+
parsec-interface = "0.18.0"
1717
num = "0.2.1"
1818
rand = "0.7.3"
1919
log = "0.4.8"

src/core/basic_client.rs

+114-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use crate::error::{ClientErrorKind, Error, Result};
77
use parsec_interface::operations::list_opcodes::Operation as ListOpcodes;
88
use parsec_interface::operations::list_providers::{Operation as ListProviders, ProviderInfo};
99
use parsec_interface::operations::ping::Operation as Ping;
10-
use parsec_interface::operations::psa_algorithm::AsymmetricSignature;
10+
use parsec_interface::operations::psa_algorithm::{AsymmetricEncryption, AsymmetricSignature};
11+
use parsec_interface::operations::psa_asymmetric_decrypt::Operation as PsaAsymDecrypt;
12+
use parsec_interface::operations::psa_asymmetric_encrypt::Operation as PsaAsymEncrypt;
1113
use parsec_interface::operations::psa_destroy_key::Operation as PsaDestroyKey;
1214
use parsec_interface::operations::psa_export_public_key::Operation as PsaExportPublicKey;
1315
use parsec_interface::operations::psa_generate_key::Operation as PsaGenerateKey;
@@ -229,7 +231,6 @@ impl BasicClient {
229231
ProviderID::Core,
230232
&self.auth_data,
231233
)?;
232-
233234
if let NativeResult::ListProviders(res) = res {
234235
Ok(res.providers)
235236
} else {
@@ -522,6 +523,117 @@ impl BasicClient {
522523
Ok(())
523524
}
524525

526+
/// **[Cryptographic Operation]** Encrypt a short message.
527+
///
528+
/// The key intended for encrypting **must** have its `encrypt` flag set
529+
/// to `true` in its [key policy](https://docs.rs/parsec-interface/*/parsec_interface/operations/psa_key_attributes/struct.Policy.html).
530+
///
531+
/// The encryption will be performed with the algorithm defined in `alg`,
532+
/// but only after checking that the key policy and type conform with it.
533+
///
534+
/// `salt` can be provided if supported by the algorithm. If the algorithm does not support salt, pass
535+
// an empty vector. If the algorithm supports optional salt, pass an empty vector to indicate no
536+
// salt. For RSA PKCS#1 v1.5 encryption, no salt is supported.
537+
///
538+
/// # Errors
539+
///
540+
/// If the implicit client provider is `ProviderID::Core`, a client error
541+
/// of `InvalidProvider` type is returned.
542+
///
543+
/// If the implicit client provider has not been set, a client error of
544+
/// `NoProvider` type is returned.
545+
///
546+
/// See the operation-specific response codes returned by the service
547+
/// [here](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/psa_asymmetric_encrypt.html#specific-response-status-codes).
548+
pub fn psa_asymmetric_encrypt(
549+
&self,
550+
key_name: String,
551+
encrypt_alg: AsymmetricEncryption,
552+
plaintext: &[u8],
553+
salt: Option<&[u8]>,
554+
) -> Result<Vec<u8>> {
555+
let salt = salt.map(|salt_ref| salt_ref.to_vec().into());
556+
let crypto_provider = self.can_provide_crypto()?;
557+
558+
let op = PsaAsymEncrypt {
559+
key_name,
560+
alg: encrypt_alg,
561+
plaintext: plaintext.to_vec().into(),
562+
salt,
563+
};
564+
565+
let encrypt_res = self.op_client.process_operation(
566+
NativeOperation::PsaAsymmetricEncrypt(op),
567+
crypto_provider,
568+
&self.auth_data,
569+
)?;
570+
571+
if let NativeResult::PsaAsymmetricEncrypt(res) = encrypt_res {
572+
Ok(res.ciphertext.to_vec())
573+
} else {
574+
// Should really not be reached given the checks we do, but it's not impossible if some
575+
// changes happen in the interface
576+
Err(Error::Client(ClientErrorKind::InvalidServiceResponseType))
577+
}
578+
}
579+
580+
/// **[Cryptographic Operation]** Decrypt a short message.
581+
///
582+
/// The key intended for decrypting **must** have its `decrypt` flag set
583+
/// to `true` in its [key policy](https://docs.rs/parsec-interface/*/parsec_interface/operations/psa_key_attributes/struct.Policy.html).
584+
///
585+
/// The decryption will be performed with the algorithm defined in `alg`,
586+
/// but only after checking that the key policy and type conform with it.
587+
///
588+
/// `salt` can be provided if supported by the algorithm. If the algorithm does not support salt, pass
589+
// an empty vector. If the algorithm supports optional salt, pass an empty vector to indicate no
590+
// salt. For RSA PKCS#1 v1.5 encryption, no salt is supported.
591+
///
592+
/// # Errors
593+
///
594+
/// If the implicit client provider is `ProviderID::Core`, a client error
595+
/// of `InvalidProvider` type is returned.
596+
///
597+
/// If the implicit client provider has not been set, a client error of
598+
/// `NoProvider` type is returned.
599+
///
600+
/// See the operation-specific response codes returned by the service
601+
/// [here](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/psa_asymmetric_decrypt.html#specific-response-status-codes).
602+
pub fn psa_asymmetric_decrypt(
603+
&self,
604+
key_name: String,
605+
encrypt_alg: AsymmetricEncryption,
606+
ciphertext: &[u8],
607+
salt: Option<&[u8]>,
608+
) -> Result<Vec<u8>> {
609+
let salt = match salt {
610+
Some(salt) => Some(Zeroizing::new(salt.to_vec())),
611+
None => None,
612+
};
613+
let crypto_provider = self.can_provide_crypto()?;
614+
615+
let op = PsaAsymDecrypt {
616+
key_name,
617+
alg: encrypt_alg,
618+
ciphertext: Zeroizing::new(ciphertext.to_vec()),
619+
salt,
620+
};
621+
622+
let decrypt_res = self.op_client.process_operation(
623+
NativeOperation::PsaAsymmetricDecrypt(op),
624+
crypto_provider,
625+
&self.auth_data,
626+
)?;
627+
628+
if let NativeResult::PsaAsymmetricDecrypt(res) = decrypt_res {
629+
Ok(res.plaintext.to_vec())
630+
} else {
631+
// Should really not be reached given the checks we do, but it's not impossible if some
632+
// changes happen in the interface
633+
Err(Error::Client(ClientErrorKind::InvalidServiceResponseType))
634+
}
635+
}
636+
525637
fn can_provide_crypto(&self) -> Result<ProviderID> {
526638
match self.implicit_provider {
527639
None => Err(Error::Client(ClientErrorKind::NoProvider)),

0 commit comments

Comments
 (0)