@@ -327,3 +327,290 @@ where
327
327
const SIGNATURE_ALGORITHM_IDENTIFIER : AlgorithmIdentifier < Self :: Params > =
328
328
Signature :: < C > :: ALGORITHM_IDENTIFIER ;
329
329
}
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