diff --git a/auth.go b/auth.go index eac9f7c..d58fbaf 100644 --- a/auth.go +++ b/auth.go @@ -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 +} diff --git a/auth_test.go b/auth_test.go index 7191947..f0df679 100644 --- a/auth_test.go +++ b/auth_test.go @@ -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) + } + }) +} diff --git a/mockdata/TestSetRetries/yk-5.4.3 b/mockdata/TestSetRetries/yk-5.4.3 new file mode 100644 index 0000000..230f8f7 --- /dev/null +++ b/mockdata/TestSetRetries/yk-5.4.3 @@ -0,0 +1,42 @@ +mockfile + +file.version v2 +file.created 2024-06-05T21:00:27+02:00 +file.creator stv0g@cam + +meta status.active_protocol t1,any +meta status.atr 3bfd1300008131fe158073c021c057597562694b657940 +meta status.reader Yubico YubiKey OTP+FIDO+CCID +meta status.state present,powered,specific +meta yubikey.serial 23852774 +meta yubikey.version 5.4.3 + +# start end method +on 0.000 0.000 BeginTransaction +on 0.138 0.138 Transmit 00a4040009a00000030800001000 61114f0600001000010079074f05a0000003089000 +on 1.579 1.579 Transmit 00fd0000 0504039000 +on 2.256 2.256 Transmit 00200080083631353832323531 63c2 +on 7.382 7.382 Transmit 00200080083631353832323531 63c1 +on 12.788 12.788 Transmit 00200080083631353832323531 6983 +on 17.968 17.968 Transmit 002400811036313538323235313631353832323531 63c2 +on 22.955 22.955 Transmit 002400811036313538323235313631353832323531 63c1 +on 27.945 27.945 Transmit 002400811036313538323235313631353832323531 6983 +on 33.177 33.177 Transmit 00fb0000 9000 +on 537.346 537.346 Transmit 00f70080 0101ff050101060203039000 +on 539.340 539.340 Transmit 00f70081 0101ff050101060203039000 +on 540.795 540.795 Transmit 0020008008313233343536ffff 9000 +on 550.234 550.234 Transmit 00f7009b 010103020200010501019000 +on 551.240 551.240 Transmit 0087039b047c028000 7c0a80082be171482013eb049000 +on 552.804 552.804 Transmit 0087039b167c1480083b8d1e42d99399af8108abababababababab 7c0a8208b4e0e48bf8e2d06a9000 +on 554.008 554.008 Transmit 00fa050a 9000 +on 570.621 570.621 Transmit 00f70080 0101ff050101060205059000 +on 571.442 571.442 Transmit 00f70081 0101ff05010106020a0a9000 +on 572.211 572.211 Transmit 00200080083932383337343932 63c4 +on 577.762 577.762 Transmit 002c00801039323833373439323132333435363738 63c9 +on 583.199 583.199 Transmit 00f70080 0101ff050101060205049000 +on 584.605 584.605 Transmit 00f70081 0101ff05010106020a099000 +on 586.216 586.216 Transmit 0024008010313233343536ffff393831323131ffff 9000 +on 600.259 600.259 Transmit 00240081103132333435363738393831323131ffff 9000 +on 613.619 613.619 Transmit 00f70080 0101ff050100060205059000 +on 614.708 614.708 Transmit 00f70081 0101ff05010006020a0a9000 +on 616.149 616.149 EndTransaction diff --git a/mockdata/TestSetRetries/yk-5.7.1 b/mockdata/TestSetRetries/yk-5.7.1 new file mode 100644 index 0000000..9113385 --- /dev/null +++ b/mockdata/TestSetRetries/yk-5.7.1 @@ -0,0 +1,51 @@ +mockfile + +file.version v2 +file.created 2024-06-05T20:46:29+02:00 +file.creator stv0g@cam + +meta status.active_protocol t1,any +meta status.atr 3bfd1300008131fe158073c021c057597562694b657940 +meta status.reader Yubico YubiKey OTP+FIDO+CCID +meta status.state powered,specific,present +meta yubikey.serial 29173673 +meta yubikey.version 5.7.1 + +# start end method +on 0.000 0.000 BeginTransaction +on 0.101 0.101 Transmit 00a4040009a00000030800001000 61114f0600001000010079074f05a0000003089000 +on 0.880 0.880 Transmit 00fd0000 0507019000 +on 2.110 2.110 Transmit 00200080083631353832323531 63c4 +on 7.662 7.662 Transmit 00200080083631353832323531 63c3 +on 13.536 13.536 Transmit 00200080083631353832323531 63c2 +on 19.349 19.349 Transmit 00200080083631353832323531 63c1 +on 25.356 25.356 Transmit 00200080083631353832323531 6983 +on 31.124 31.124 Transmit 002400811036313538323235313631353832323531 63c9 +on 36.895 36.895 Transmit 002400811036313538323235313631353832323531 63c8 +on 42.633 42.633 Transmit 002400811036313538323235313631353832323531 63c7 +on 48.149 48.149 Transmit 002400811036313538323235313631353832323531 63c6 +on 53.760 53.760 Transmit 002400811036313538323235313631353832323531 63c5 +on 59.723 59.723 Transmit 002400811036313538323235313631353832323531 63c4 +on 65.379 65.379 Transmit 002400811036313538323235313631353832323531 63c3 +on 70.992 70.992 Transmit 002400811036313538323235313631353832323531 63c2 +on 76.681 76.681 Transmit 002400811036313538323235313631353832323531 63c1 +on 82.493 82.493 Transmit 002400811036313538323235313631353832323531 6983 +on 88.398 88.398 Transmit 00fb0000 9000 +on 1030.660 1030.660 Transmit 00f70080 0101ff050101060203039000 +on 1034.466 1034.466 Transmit 00f70081 0101ff050101060203039000 +on 1036.969 1036.969 Transmit 0020008008313233343536ffff 9000 +on 1047.988 1047.988 Transmit 00f7009b 01010a020200010501019000 +on 1050.016 1050.016 Transmit 00870a9b047c028000 7c1280102714235f1b780dd47f344bab623b48679000 +on 1052.464 1052.464 Transmit 00870a9b267c248010bb65ef29ca9ea3ba4610871d53b61cda8110abababababababababababababababab 7c12821040e0910c0a9420eb12ba9efcb51c48829000 +on 1054.864 1054.864 Transmit 00fa050a 9000 +on 1072.623 1072.623 Transmit 00f70080 0101ff050101060205059000 +on 1074.353 1074.353 Transmit 00f70081 0101ff05010106020a0a9000 +on 1076.041 1076.041 Transmit 00200080083932383337343932 63c4 +on 1082.120 1082.120 Transmit 002c00801039323833373439323132333435363738 63c9 +on 1088.074 1088.074 Transmit 00f70080 0101ff050101060205049000 +on 1089.594 1089.594 Transmit 00f70081 0101ff05010106020a099000 +on 1090.845 1090.845 Transmit 0024008010313233343536ffff393831323131ffff 9000 +on 1116.500 1116.500 Transmit 00240081103132333435363738393831323131ffff 9000 +on 1142.079 1142.079 Transmit 00f70080 0101ff050100060205059000 +on 1143.534 1143.534 Transmit 00f70081 0101ff05010006020a0a9000 +on 1144.840 1144.840 EndTransaction