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