@@ -327,3 +327,290 @@ where
327327 const SIGNATURE_ALGORITHM_IDENTIFIER : AlgorithmIdentifier < Self :: Params > =
328328 Signature :: < C > :: ALGORITHM_IDENTIFIER ;
329329}
330+
331+ #[ cfg( feature = "rsa" ) ]
332+ mod rsa {
333+ use super :: TpmSigner ;
334+
335+ use crate :: {
336+ abstraction:: { signer:: KeyParams , AssociatedHashingAlgorithm } ,
337+ structures:: { Digest as TpmDigest , RsaScheme } ,
338+ Error , WrapperErrorKind ,
339+ } ;
340+
341+ use std:: fmt;
342+
343+ use digest:: { Digest , FixedOutput , Output } ;
344+ use log:: error;
345+ use pkcs8:: AssociatedOid ;
346+ use signature:: { DigestSigner , Error as SigError , Keypair , Signer } ;
347+ use x509_cert:: {
348+ der:: asn1:: AnyRef ,
349+ spki:: {
350+ self , AlgorithmIdentifier , AlgorithmIdentifierOwned , AssociatedAlgorithmIdentifier ,
351+ DynSignatureAlgorithmIdentifier , SignatureAlgorithmIdentifier ,
352+ } ,
353+ } ;
354+
355+ use :: rsa:: { pkcs1v15, pss, RsaPublicKey } ;
356+
357+ /// [`RsaPkcsSigner`] will sign a payload with an RSA secret key stored on the TPM.
358+ ///
359+ /// ```no_run
360+ /// # use std::sync::Mutex;
361+ /// # use tss_esapi::{
362+ /// # abstraction::{RsaPkcsSigner, transient::{TransientKeyContextBuilder, KeyParams}},
363+ /// # interface_types::{algorithm::{HashingAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits},
364+ /// # structures::{RsaExponent, RsaScheme},
365+ /// # TctiNameConf
366+ /// # };
367+ /// use signature::Signer;
368+ /// #
369+ /// # // Create context
370+ /// # let mut context = TransientKeyContextBuilder::new()
371+ /// # .with_tcti(
372+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
373+ /// # )
374+ /// # .build()
375+ /// # .expect("Failed to create Context");
376+ ///
377+ /// let key_params = KeyParams::Rsa {
378+ /// size: RsaKeyBits::Rsa1024,
379+ /// scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256))
380+ /// .expect("Failed to create RSA scheme"),
381+ /// pub_exponent: RsaExponent::default(),
382+ /// };
383+ /// let (tpm_km, _tpm_auth) = context
384+ /// .create_key(key_params, 0)
385+ /// .expect("Failed to create a private keypair");
386+ ///
387+ /// let signer = RsaPkcsSigner::<_, sha2::Sha256>::new((Mutex::new(&mut context), tpm_km, key_params, None))
388+ /// .expect("Failed to create a signer");
389+ /// let signature = signer.sign(b"Hello Bob, Alice here.");
390+ /// ```
391+ #[ derive( Debug ) ]
392+ pub struct RsaPkcsSigner < Ctx , D >
393+ where
394+ D : Digest ,
395+ {
396+ context : Ctx ,
397+ verifying_key : pkcs1v15:: VerifyingKey < D > ,
398+ }
399+
400+ impl < Ctx , D > RsaPkcsSigner < Ctx , D >
401+ where
402+ Ctx : TpmSigner ,
403+ D : Digest + AssociatedOid + AssociatedHashingAlgorithm + fmt:: Debug ,
404+ {
405+ pub fn new ( context : Ctx ) -> Result < Self , Error > {
406+ match context. key_params ( ) ? {
407+ KeyParams :: Rsa {
408+ scheme : RsaScheme :: RsaSsa ( hash) ,
409+ ..
410+ } if hash. hashing_algorithm ( ) == D :: TPM_DIGEST => { }
411+ other => {
412+ error ! (
413+ "Unsupported key parameters: {other:?}, expected RsaSsa({:?})" ,
414+ D :: new( )
415+ ) ;
416+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
417+ }
418+ }
419+
420+ let public_key = context. public ( ) ?;
421+ let public_key = RsaPublicKey :: try_from ( & public_key) ?;
422+ let verifying_key = pkcs1v15:: VerifyingKey :: new ( public_key) ;
423+
424+ Ok ( Self {
425+ context,
426+ verifying_key,
427+ } )
428+ }
429+ }
430+
431+ impl < Ctx , D > Keypair for RsaPkcsSigner < Ctx , D >
432+ where
433+ D : Digest ,
434+ {
435+ type VerifyingKey = pkcs1v15:: VerifyingKey < D > ;
436+
437+ fn verifying_key ( & self ) -> Self :: VerifyingKey {
438+ self . verifying_key . clone ( )
439+ }
440+ }
441+
442+ impl < Ctx , D > DigestSigner < D , pkcs1v15:: Signature > for RsaPkcsSigner < Ctx , D >
443+ where
444+ D : Digest + FixedOutput ,
445+ D : AssociatedHashingAlgorithm ,
446+ TpmDigest : From < Output < D > > ,
447+ Ctx : TpmSigner ,
448+ {
449+ fn try_sign_digest ( & self , digest : D ) -> Result < pkcs1v15:: Signature , SigError > {
450+ let digest = TpmDigest :: from ( digest. finalize_fixed ( ) ) ;
451+
452+ //let key_params = Self::key_params::<D>();
453+ let signature = self . context . sign ( digest) . map_err ( SigError :: from_source) ?;
454+
455+ let signature =
456+ pkcs1v15:: Signature :: try_from ( signature) . map_err ( SigError :: from_source) ?;
457+
458+ Ok ( signature)
459+ }
460+ }
461+
462+ impl < Ctx , D > Signer < pkcs1v15:: Signature > for RsaPkcsSigner < Ctx , D >
463+ where
464+ D : Digest + FixedOutput ,
465+ D : AssociatedHashingAlgorithm ,
466+ TpmDigest : From < Output < D > > ,
467+ Ctx : TpmSigner ,
468+ {
469+ fn try_sign ( & self , msg : & [ u8 ] ) -> Result < pkcs1v15:: Signature , SigError > {
470+ let mut d = D :: new ( ) ;
471+ Digest :: update ( & mut d, msg) ;
472+
473+ self . try_sign_digest ( d)
474+ }
475+ }
476+
477+ impl < Ctx , D > SignatureAlgorithmIdentifier for RsaPkcsSigner < Ctx , D >
478+ where
479+ D : Digest + pkcs1v15:: RsaSignatureAssociatedOid ,
480+ {
481+ type Params = AnyRef < ' static > ;
482+
483+ const SIGNATURE_ALGORITHM_IDENTIFIER : AlgorithmIdentifier < Self :: Params > =
484+ pkcs1v15:: SigningKey :: < D > :: ALGORITHM_IDENTIFIER ;
485+ }
486+
487+ /// [`RsaPssSigner`] will sign a payload with an RSA secret key stored on the TPM.
488+ ///
489+ /// ```no_run
490+ /// # use std::sync::Mutex;
491+ /// # use tss_esapi::{
492+ /// # abstraction::{RsaPssSigner, transient::{TransientKeyContextBuilder, KeyParams}},
493+ /// # interface_types::{algorithm::{HashingAlgorithm, RsaSchemeAlgorithm}, key_bits::RsaKeyBits},
494+ /// # structures::{RsaExponent, RsaScheme},
495+ /// # TctiNameConf
496+ /// # };
497+ /// use signature::Signer;
498+ /// #
499+ /// # // Create context
500+ /// # let mut context = TransientKeyContextBuilder::new()
501+ /// # .with_tcti(
502+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
503+ /// # )
504+ /// # .build()
505+ /// # .expect("Failed to create Context");
506+ ///
507+ /// let key_params = KeyParams::Rsa {
508+ /// size: RsaKeyBits::Rsa1024,
509+ /// scheme: RsaScheme::create(RsaSchemeAlgorithm::RsaPss, Some(HashingAlgorithm::Sha256))
510+ /// .expect("Failed to create RSA scheme"),
511+ /// pub_exponent: RsaExponent::default(),
512+ /// };
513+ /// let (tpm_km, _tpm_auth) = context
514+ /// .create_key(key_params, 0)
515+ /// .expect("Failed to create a private keypair");
516+ ///
517+ /// let signer = RsaPssSigner::<_, sha2::Sha256>::new((Mutex::new(&mut context), tpm_km, key_params, None))
518+ /// .expect("Failed to create a signer");
519+ /// let signature = signer.sign(b"Hello Bob, Alice here.");
520+ /// ```
521+ #[ derive( Debug ) ]
522+ pub struct RsaPssSigner < Ctx , D >
523+ where
524+ D : Digest ,
525+ {
526+ context : Ctx ,
527+ verifying_key : pss:: VerifyingKey < D > ,
528+ }
529+
530+ impl < Ctx , D > RsaPssSigner < Ctx , D >
531+ where
532+ Ctx : TpmSigner ,
533+ D : Digest + AssociatedHashingAlgorithm + fmt:: Debug ,
534+ {
535+ pub fn new ( context : Ctx ) -> Result < Self , Error > {
536+ match context. key_params ( ) ? {
537+ KeyParams :: Rsa {
538+ scheme : RsaScheme :: RsaPss ( hash) ,
539+ ..
540+ } if hash. hashing_algorithm ( ) == D :: TPM_DIGEST => { }
541+ other => {
542+ error ! (
543+ "Unsupported key parameters: {other:?}, expected RsaSsa({:?})" ,
544+ D :: new( )
545+ ) ;
546+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
547+ }
548+ }
549+
550+ let public_key = context. public ( ) ?;
551+ let public_key = RsaPublicKey :: try_from ( & public_key) ?;
552+ let verifying_key = pss:: VerifyingKey :: new ( public_key) ;
553+
554+ Ok ( Self {
555+ context,
556+ verifying_key,
557+ } )
558+ }
559+ }
560+
561+ impl < Ctx , D > Keypair for RsaPssSigner < Ctx , D >
562+ where
563+ D : Digest ,
564+ {
565+ type VerifyingKey = pss:: VerifyingKey < D > ;
566+
567+ fn verifying_key ( & self ) -> Self :: VerifyingKey {
568+ self . verifying_key . clone ( )
569+ }
570+ }
571+
572+ impl < Ctx , D > DigestSigner < D , pss:: Signature > for RsaPssSigner < Ctx , D >
573+ where
574+ D : Digest + FixedOutput ,
575+ D : AssociatedHashingAlgorithm ,
576+ TpmDigest : From < Output < D > > ,
577+ Ctx : TpmSigner ,
578+ {
579+ fn try_sign_digest ( & self , digest : D ) -> Result < pss:: Signature , SigError > {
580+ let digest = TpmDigest :: from ( digest. finalize_fixed ( ) ) ;
581+
582+ let signature = self . context . sign ( digest) . map_err ( SigError :: from_source) ?;
583+
584+ let signature = pss:: Signature :: try_from ( signature) . map_err ( SigError :: from_source) ?;
585+
586+ Ok ( signature)
587+ }
588+ }
589+
590+ impl < Ctx , D > Signer < pss:: Signature > for RsaPssSigner < Ctx , D >
591+ where
592+ D : Digest + FixedOutput ,
593+ D : AssociatedHashingAlgorithm ,
594+ TpmDigest : From < Output < D > > ,
595+ Ctx : TpmSigner ,
596+ {
597+ fn try_sign ( & self , msg : & [ u8 ] ) -> Result < pss:: Signature , SigError > {
598+ let mut d = D :: new ( ) ;
599+ Digest :: update ( & mut d, msg) ;
600+
601+ self . try_sign_digest ( d)
602+ }
603+ }
604+
605+ impl < Ctx , D > DynSignatureAlgorithmIdentifier for RsaPssSigner < Ctx , D >
606+ where
607+ D : Digest + AssociatedOid ,
608+ {
609+ fn signature_algorithm_identifier ( & self ) -> spki:: Result < AlgorithmIdentifierOwned > {
610+ pss:: get_default_pss_signature_algo_id :: < D > ( )
611+ }
612+ }
613+ }
614+
615+ #[ cfg( feature = "rsa" ) ]
616+ pub use self :: rsa:: { RsaPkcsSigner , RsaPssSigner } ;
0 commit comments