Skip to content

Commit 50f70ed

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

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
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 = { path = "../parsec-interface-rs" }
1717
num = "0.2.1"
1818
rand = "0.7.3"
1919
log = "0.4.8"

src/core/basic_client.rs

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ 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::{AsymmetricSignature, AsymmetricEncryption};
1111
use parsec_interface::operations::psa_destroy_key::Operation as PsaDestroyKey;
1212
use parsec_interface::operations::psa_export_public_key::Operation as PsaExportPublicKey;
1313
use parsec_interface::operations::psa_generate_key::Operation as PsaGenerateKey;
1414
use parsec_interface::operations::psa_import_key::Operation as PsaImportKey;
1515
use parsec_interface::operations::psa_key_attributes::Attributes;
1616
use parsec_interface::operations::psa_sign_hash::Operation as PsaSignHash;
1717
use parsec_interface::operations::psa_verify_hash::Operation as PsaVerifyHash;
18+
use parsec_interface::operations::psa_asymmetric_encrypt::Operation as PsaAsymEncrypt;
19+
use parsec_interface::operations::psa_asymmetric_decrypt::Operation as PsaAsymDecrypt;
1820
use parsec_interface::operations::{NativeOperation, NativeResult};
1921
use parsec_interface::requests::{Opcode, ProviderID};
2022
use parsec_interface::secrecy::Secret;
@@ -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,120 @@ 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 = match salt {
556+
Some(salt) => Some(Zeroizing::new(salt.to_vec())),
557+
None=> None,
558+
};
559+
let crypto_provider = self.can_provide_crypto()?;
560+
561+
let op = PsaAsymEncrypt {
562+
key_name,
563+
alg: encrypt_alg,
564+
plaintext: plaintext.to_vec().into(),
565+
salt,
566+
};
567+
568+
let encrypt_res = self.op_client.process_operation(
569+
NativeOperation::PsaAsymmetricEncrypt(op),
570+
crypto_provider,
571+
&self.auth_data,
572+
)?;
573+
574+
if let NativeResult::PsaAsymmetricEncrypt(res) = encrypt_res {
575+
Ok(res.ciphertext.to_vec())
576+
} else {
577+
// Should really not be reached given the checks we do, but it's not impossible if some
578+
// changes happen in the interface
579+
Err(Error::Client(ClientErrorKind::InvalidServiceResponseType))
580+
}
581+
}
582+
583+
/// **[Cryptographic Operation]** Decrypt a short message.
584+
///
585+
/// The key intended for decrypting **must** have its `decrypt` flag set
586+
/// to `true` in its [key policy](https://docs.rs/parsec-interface/*/parsec_interface/operations/psa_key_attributes/struct.Policy.html).
587+
///
588+
/// The decryption will be performed with the algorithm defined in `alg`,
589+
/// but only after checking that the key policy and type conform with it.
590+
///
591+
/// `salt` can be provided if supported by the algorithm. If the algorithm does not support salt, pass
592+
// an empty vector. If the algorithm supports optional salt, pass an empty vector to indicate no
593+
// salt. For RSA PKCS#1 v1.5 encryption, no salt is supported.
594+
///
595+
/// # Errors
596+
///
597+
/// If the implicit client provider is `ProviderID::Core`, a client error
598+
/// of `InvalidProvider` type is returned.
599+
///
600+
/// If the implicit client provider has not been set, a client error of
601+
/// `NoProvider` type is returned.
602+
///
603+
/// See the operation-specific response codes returned by the service
604+
/// [here](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/psa_asymmetric_decrypt.html#specific-response-status-codes).
605+
pub fn psa_asymmetric_decrypt(
606+
&self,
607+
key_name: String,
608+
encrypt_alg: AsymmetricEncryption,
609+
ciphertext: &[u8],
610+
salt: Option<&[u8]>,
611+
) -> Result<Vec<u8>> {
612+
let salt = match salt {
613+
Some(salt) => Some(Zeroizing::new(salt.to_vec())),
614+
None => None,
615+
};
616+
let crypto_provider = self.can_provide_crypto()?;
617+
618+
let op = PsaAsymDecrypt {
619+
key_name,
620+
alg: encrypt_alg,
621+
ciphertext: Zeroizing::new(ciphertext.to_vec()),
622+
salt,
623+
};
624+
625+
let decrypt_res = self.op_client.process_operation(
626+
NativeOperation::PsaAsymmetricDecrypt(op),
627+
crypto_provider,
628+
&self.auth_data,
629+
)?;
630+
631+
if let NativeResult::PsaAsymmetricDecrypt(res) = decrypt_res {
632+
Ok(res.plaintext.to_vec())
633+
} else {
634+
// Should really not be reached given the checks we do, but it's not impossible if some
635+
// changes happen in the interface
636+
Err(Error::Client(ClientErrorKind::InvalidServiceResponseType))
637+
}
638+
}
639+
525640
fn can_provide_crypto(&self) -> Result<ProviderID> {
526641
match self.implicit_provider {
527642
None => Err(Error::Client(ClientErrorKind::NoProvider)),

0 commit comments

Comments
 (0)