Skip to content

Commit

Permalink
Return an error if Ed25519ctx or Ed25519ph is used
Browse files Browse the repository at this point in the history
Otherwise, an invalid signature will be returned.

As far as I can tell, the YubiKey only supports straight Ed25519.
  • Loading branch information
AGWA authored and ericchiang committed Oct 9, 2024
1 parent bc889e4 commit 2fae465
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
15 changes: 11 additions & 4 deletions v2/piv/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -1295,9 +1295,9 @@ func (k *keyEd25519) Public() crypto.PublicKey {
return k.pub
}

func (k *keyEd25519) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
func (k *keyEd25519) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) ([]byte, error) {
return k.auth.do(k.yk, k.pp, func(tx *scTx) ([]byte, error) {
return ykSignEd25519(tx, k.slot, k.pub, digest)
return ykSignEd25519(tx, k.slot, k.pub, message, opts)
})
}

Expand Down Expand Up @@ -1400,7 +1400,14 @@ func ykECDHX25519(tx *scTx, slot Slot, pub *ecdh.PublicKey, peer *ecdh.PublicKey
return sharedSecret, nil
}

func ykSignEd25519(tx *scTx, slot Slot, pub ed25519.PublicKey, digest []byte) ([]byte, error) {
func ykSignEd25519(tx *scTx, slot Slot, pub ed25519.PublicKey, message []byte, opts crypto.SignerOpts) ([]byte, error) {
if opts.HashFunc() != crypto.Hash(0) {
return nil, fmt.Errorf("ed25519ph not supported")
}
if ed25519opts, ok := opts.(*ed25519.Options); ok && ed25519opts.Context != "" {
return nil, fmt.Errorf("ed25519ctx not supported")
}

// Adaptation of
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=118
cmd := apdu{
Expand All @@ -1409,7 +1416,7 @@ func ykSignEd25519(tx *scTx, slot Slot, pub ed25519.PublicKey, digest []byte) ([
param2: byte(slot.Key),
data: marshalASN1(0x7c,
append([]byte{0x82, 0x00},
marshalASN1(0x81, digest)...)),
marshalASN1(0x81, message)...)),
}
resp, err := tx.Transmit(cmd)
if err != nil {
Expand Down
31 changes: 24 additions & 7 deletions v2/piv/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -303,13 +304,29 @@ func TestYubiKeySignEd25519(t *testing.T) {
if !ok {
t.Fatalf("expected private key to implement crypto.Signer")
}
sig, err := s.Sign(rand.Reader, data, crypto.Hash(0))
if err != nil {
t.Fatalf("signing failed: %v", err)
}
if !ed25519.Verify(pub, data, sig) {
t.Errorf("signature didn't match")
}

t.Run("good", func(t *testing.T) {
sig, err := s.Sign(rand.Reader, data, crypto.Hash(0))
if err != nil {
t.Fatalf("signing failed: %v", err)
}
if !ed25519.Verify(pub, data, sig) {
t.Errorf("signature didn't match")
}
})
t.Run("unsupported_ed25519ph", func(t *testing.T) {
digest := sha512.Sum512(data)
_, err := s.Sign(rand.Reader, digest[:], crypto.SHA512)
if err == nil {
t.Fatalf("expected signing with Ed25519ph to fail")
}
})
t.Run("unsupported_ed25519ctx", func(t *testing.T) {
_, err := s.Sign(rand.Reader, data, &ed25519.Options{Context: "test"})
if err == nil {
t.Fatalf("expected signing with Ed25519ctx to fail")
}
})
}

func TestPINPrompt(t *testing.T) {
Expand Down

0 comments on commit 2fae465

Please sign in to comment.