@@ -507,7 +507,12 @@ func (yk *YubiKey) AttestationCertificate() (*x509.Certificate, error) {
507
507
//
508
508
// If the slot doesn't have a key, the returned error wraps ErrNotFound.
509
509
func (yk * YubiKey ) Attest (slot Slot ) (* x509.Certificate , error ) {
510
- cert , err := ykAttest (yk .tx , slot )
510
+ var cert * x509.Certificate
511
+ err := yk .tx (func (tx * scTx ) error {
512
+ var err error
513
+ cert , err = ykAttest (tx , slot )
514
+ return err
515
+ })
511
516
if err == nil {
512
517
return cert , nil
513
518
}
@@ -558,7 +563,12 @@ func (yk *YubiKey) Certificate(slot Slot) (*x509.Certificate, error) {
558
563
byte (slot .Object ),
559
564
},
560
565
}
561
- resp , err := yk .tx .Transmit (cmd )
566
+ var resp []byte
567
+ err := yk .tx (func (tx * scTx ) error {
568
+ var err error
569
+ resp , err = tx .Transmit (cmd )
570
+ return err
571
+ })
562
572
if err != nil {
563
573
return nil , fmt .Errorf ("command failed: %w" , err )
564
574
}
@@ -605,10 +615,12 @@ func marshalASN1(tag byte, data []byte) []byte {
605
615
// certificate isn't required to use the associated key for signing or
606
616
// decryption.
607
617
func (yk * YubiKey ) SetCertificate (key [24 ]byte , slot Slot , cert * x509.Certificate ) error {
608
- if err := ykAuthenticate (yk .tx , key , yk .rand ); err != nil {
609
- return fmt .Errorf ("authenticating with management key: %w" , err )
610
- }
611
- return ykStoreCertificate (yk .tx , slot , cert )
618
+ return yk .tx (func (tx * scTx ) error {
619
+ if err := ykAuthenticate (tx , key , yk .rand ); err != nil {
620
+ return fmt .Errorf ("authenticating with management key: %w" , err )
621
+ }
622
+ return ykStoreCertificate (tx , slot , cert )
623
+ })
612
624
}
613
625
614
626
func ykStoreCertificate (tx * scTx , slot Slot , cert * x509.Certificate ) error {
@@ -659,10 +671,17 @@ type Key struct {
659
671
// GenerateKey generates an asymmetric key on the card, returning the key's
660
672
// public key.
661
673
func (yk * YubiKey ) GenerateKey (key [24 ]byte , slot Slot , opts Key ) (crypto.PublicKey , error ) {
662
- if err := ykAuthenticate (yk .tx , key , yk .rand ); err != nil {
663
- return nil , fmt .Errorf ("authenticating with management key: %w" , err )
664
- }
665
- return ykGenerateKey (yk .tx , slot , opts )
674
+ var pub crypto.PublicKey
675
+ err := yk .tx (func (tx * scTx ) error {
676
+ if err := ykAuthenticate (tx , key , yk .rand ); err != nil {
677
+ return fmt .Errorf ("authenticating with management key: %w" , err )
678
+ }
679
+
680
+ var err error
681
+ pub , err = ykGenerateKey (tx , slot , opts )
682
+ return err
683
+ })
684
+ return pub , err
666
685
}
667
686
668
687
func ykGenerateKey (tx * scTx , slot Slot , o Key ) (crypto.PublicKey , error ) {
@@ -731,8 +750,12 @@ type KeyAuth struct {
731
750
// If provided, PINPrompt is ignored.
732
751
PIN string
733
752
// PINPrompt can be used to interactively request the PIN from the user. The
734
- // method is only called when needed. For example, if a key specifies
735
- // PINPolicyOnce, PINPrompt will only be called once per YubiKey struct.
753
+ // method is only called when needed for exclusive connections. If a key
754
+ // specifies PINPolicyOnce, PINPrompt will only be called once per YubiKey
755
+ // struct.
756
+ //
757
+ // Clients using a shared connection will call the PIN prompt on every
758
+ // operation, regardless of PIN policy.
736
759
PINPrompt func () (pin string , err error )
737
760
738
761
// PINPolicy can be used to specify the PIN caching strategy for the slot. If
@@ -743,7 +766,7 @@ type KeyAuth struct {
743
766
PINPolicy PINPolicy
744
767
}
745
768
746
- func (k KeyAuth ) authTx (yk * YubiKey , pp PINPolicy ) error {
769
+ func (k KeyAuth ) authTx (tx * scTx , pp PINPolicy ) error {
747
770
// PINPolicyNever shouldn't require a PIN.
748
771
if pp == PINPolicyNever {
749
772
return nil
@@ -752,7 +775,7 @@ func (k KeyAuth) authTx(yk *YubiKey, pp PINPolicy) error {
752
775
// PINPolicyAlways should always prompt a PIN even if the key says that
753
776
// login isn't needed.
754
777
// https://github.com/go-piv/piv-go/issues/49
755
- if pp != PINPolicyAlways && ! ykLoginNeeded (yk . tx ) {
778
+ if pp != PINPolicyAlways && ! ykLoginNeeded (tx ) {
756
779
return nil
757
780
}
758
781
@@ -767,14 +790,20 @@ func (k KeyAuth) authTx(yk *YubiKey, pp PINPolicy) error {
767
790
if pin == "" {
768
791
return fmt .Errorf ("pin required but wasn't provided" )
769
792
}
770
- return ykLogin (yk . tx , pin )
793
+ return ykLogin (tx , pin )
771
794
}
772
795
773
796
func (k KeyAuth ) do (yk * YubiKey , pp PINPolicy , f func (tx * scTx ) ([]byte , error )) ([]byte , error ) {
774
- if err := k .authTx (yk , pp ); err != nil {
775
- return nil , err
776
- }
777
- return f (yk .tx )
797
+ var b []byte
798
+ err := yk .tx (func (tx * scTx ) error {
799
+ var err error
800
+ if err := k .authTx (tx , pp ); err != nil {
801
+ return err
802
+ }
803
+ b , err = f (tx )
804
+ return err
805
+ })
806
+ return b , err
778
807
}
779
808
780
809
func pinPolicy (yk * YubiKey , slot Slot ) (PINPolicy , error ) {
@@ -919,11 +948,12 @@ func (yk *YubiKey) SetPrivateKeyInsecure(key [24]byte, slot Slot, private crypto
919
948
tags = append (tags , param ... )
920
949
}
921
950
922
- if err := ykAuthenticate (yk .tx , key , yk .rand ); err != nil {
923
- return fmt .Errorf ("authenticating with management key: %w" , err )
924
- }
925
-
926
- return ykImportKey (yk .tx , tags , slot , policy )
951
+ return yk .tx (func (tx * scTx ) error {
952
+ if err := ykAuthenticate (tx , key , yk .rand ); err != nil {
953
+ return fmt .Errorf ("authenticating with management key: %w" , err )
954
+ }
955
+ return ykImportKey (tx , tags , slot , policy )
956
+ })
927
957
}
928
958
929
959
func ykImportKey (tx * scTx , tags []byte , slot Slot , o Key ) error {
0 commit comments