Skip to content

Commit

Permalink
Add support for setting PIN/PUK attempt counters
Browse files Browse the repository at this point in the history
Signed-off-by: Steffen Vogel <[email protected]>
  • Loading branch information
stv0g committed Dec 10, 2024
1 parent 587d5be commit f072b7c
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 0 deletions.
20 changes: 20 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,23 @@ func (c *Card) Retries() (int, error) {

return 0, fmt.Errorf("invalid response: %w", err)
}

// SetRetries sets the number of attempts for PIN and PUK.
//
// Both PIN and PUK will be reset to default values when this is executed.
// Requires authentication with management key and PIN verification.
func (c *Card) SetRetries(key ManagementKey, pin string, pinAttempts, pukAttempts int) error {
if err := login(c.tx, pin); err != nil {
return fmt.Errorf("PIN verification failed: %w", err)
}

if err := c.authenticate(key); err != nil {
return fmt.Errorf("failed to authenticate with management key: %w", err)
}

if _, err := send(c.tx, insSetPINRetries, byte(pinAttempts), byte(pukAttempts), nil); err != nil {
return fmt.Errorf("failed to execute command: %w", err)
}

return nil
}
61 changes: 61 additions & 0 deletions auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,64 @@ func TestChangeManagementKey(t *testing.T) {
require.NoError(t, err, "Failed to reset management key")
})
}

func TestSetRetries(t *testing.T) {
withCard(t, true, false, nil, func(t *testing.T, c *Card) {
// Check default attempt counters
for _, key := range []byte{keyPIN, keyPUK} {
meta, err := c.Metadata(Slot{Key: key})
require.NoError(t, err)
require.Equal(t, 3, meta.RetriesRemaining)
require.Equal(t, 3, meta.RetriesTotal)
require.True(t, meta.IsDefault)
}

retries := map[byte]int{keyPIN: 5, keyPUK: 10}

// Modify retry counter
err := c.SetRetries(DefaultManagementKey, DefaultPIN, retries[keyPIN], retries[keyPUK])
require.NoError(t, err)

for key, cnt := range retries {
meta, err := c.Metadata(Slot{Key: key})
require.NoError(t, err)
require.Equal(t, cnt, meta.RetriesRemaining)
require.Equal(t, cnt, meta.RetriesTotal)
require.True(t, meta.IsDefault)
}

// Update remaining retries
var aErr AuthError

err = c.VerifyPIN("92837492")
require.ErrorAs(t, err, &aErr)
require.Equal(t, retries[keyPIN]-1, aErr.Retries)

err = c.Unblock("92837492", "12345678")
require.ErrorAs(t, err, &aErr)
require.Equal(t, retries[keyPUK]-1, aErr.Retries)

for key, cnt := range retries {
meta, err := c.Metadata(Slot{Key: key})
require.NoError(t, err)
require.Equal(t, cnt-1, meta.RetriesRemaining)
require.Equal(t, cnt, meta.RetriesTotal)
require.True(t, meta.IsDefault)
}

// Modify PIN/PUK
err = c.SetPIN(DefaultPIN, "981211")
require.NoError(t, err)

err = c.SetPUK(DefaultPUK, "981211")
require.NoError(t, err)

for key, cnt := range retries {
meta, err := c.Metadata(Slot{Key: key})
require.NoError(t, err)
require.Equal(t, cnt, meta.RetriesRemaining)
require.Equal(t, cnt, meta.RetriesTotal)
require.False(t, meta.IsDefault)
}
})
}
42 changes: 42 additions & 0 deletions mockdata/TestSetRetries/yk-5.4.3

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions mockdata/TestSetRetries/yk-5.7.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f072b7c

Please sign in to comment.