@@ -7,14 +7,16 @@ use crate::error::{ClientErrorKind, Error, Result};
7
7
use parsec_interface:: operations:: list_opcodes:: Operation as ListOpcodes ;
8
8
use parsec_interface:: operations:: list_providers:: { Operation as ListProviders , ProviderInfo } ;
9
9
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 } ;
11
11
use parsec_interface:: operations:: psa_destroy_key:: Operation as PsaDestroyKey ;
12
12
use parsec_interface:: operations:: psa_export_public_key:: Operation as PsaExportPublicKey ;
13
13
use parsec_interface:: operations:: psa_generate_key:: Operation as PsaGenerateKey ;
14
14
use parsec_interface:: operations:: psa_import_key:: Operation as PsaImportKey ;
15
15
use parsec_interface:: operations:: psa_key_attributes:: Attributes ;
16
16
use parsec_interface:: operations:: psa_sign_hash:: Operation as PsaSignHash ;
17
17
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 ;
18
20
use parsec_interface:: operations:: { NativeOperation , NativeResult } ;
19
21
use parsec_interface:: requests:: { Opcode , ProviderID } ;
20
22
use parsec_interface:: secrecy:: Secret ;
@@ -229,7 +231,6 @@ impl BasicClient {
229
231
ProviderID :: Core ,
230
232
& self . auth_data ,
231
233
) ?;
232
-
233
234
if let NativeResult :: ListProviders ( res) = res {
234
235
Ok ( res. providers )
235
236
} else {
@@ -522,6 +523,121 @@ impl BasicClient {
522
523
Ok ( ( ) )
523
524
}
524
525
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
+
525
641
fn can_provide_crypto ( & self ) -> Result < ProviderID > {
526
642
match self . implicit_provider {
527
643
None => Err ( Error :: Client ( ClientErrorKind :: NoProvider ) ) ,
0 commit comments