diff --git a/Yubico.YubiKey/docs/users-manual/application-piv/apdu/change-ref.md b/Yubico.YubiKey/docs/users-manual/application-piv/apdu/change-ref.md index 916d7da7..603a5e7e 100644 --- a/Yubico.YubiKey/docs/users-manual/application-piv/apdu/change-ref.md +++ b/Yubico.YubiKey/docs/users-manual/application-piv/apdu/change-ref.md @@ -25,10 +25,14 @@ Which element to change is given in the P2 field of the APDU and the current and data (old and new PIN or PUK) are given in the data field. The data is simply the two values concatenated. -Both the PIN and PUK are allowed to be 6 to 8 characters, but if one is less than 8, it -will be padded with 0xff. For example, the default PIN is "123456", but on the device, +Both the PIN and the PUK are allowed to be 6 to 8 characters. If one is less than 8, it +will be padded with 0xff to reach 8 characters/bytes in length. For example, the default PIN is "123456", but on the device, it is represented as `31 32 33 34 34 36 FF FF`. +The PIN can be composed of any ASCII character, but PUK composition depends on the key's firmware. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` - +`0xFF` range for the PUK. For YubiKeys with firmware version 5.7 and above, the key will only accept values in the `0x00` - +`0x7F` range (not including the padding). + The data is therefore 16 bytes, current value (possibly padded) followed by the new value (possibly padded). @@ -67,6 +71,39 @@ Data Length: 0 The PIN or PUK entered might or might not be correct, however, authentication was denied because the number of retries have been exhausted. +#### Response APDU for CHANGE REFERENCE DATA (PIN or PUK failed length and/or complexity requirements) + +Total Length: 2\ +Data Length: 0 + +| Data | SW1 | SW2 | +|:---------:|:---:|:---:| +| (no data) | 69 | 85 | + +The new PIN or PUK did not meet the specified length requirements, an invalid character/byte was used, and/or the PIN/PUK violated the key's [PIN complexity policy](xref:UsersManualPinComplexityPolicy). + +#### Response APDU for CHANGE REFERENCE DATA (input data failed the length requirement) + +Total Length: 2\ +Data Length: 0 + +| Data | SW1 | SW2 | +|:---------:|:---:|:---:| +| (no data) | 6a | 80 | + +The total data length did not match the 16-byte requirement. + +#### Response APDU for CHANGE REFERENCE DATA (invalid P1 and/or P2) + +Total Length: 2\ +Data Length: 0 + +| Data | SW1 | SW2 | +|:---------:|:---:|:---:| +| (no data) | 6a | 88 | + +The P1 or P2 parameter was not valid given the instruction code. + ### Examples ```C diff --git a/Yubico.YubiKey/docs/users-manual/application-piv/commands.md b/Yubico.YubiKey/docs/users-manual/application-piv/commands.md index 4a17db05..78866699 100644 --- a/Yubico.YubiKey/docs/users-manual/application-piv/commands.md +++ b/Yubico.YubiKey/docs/users-manual/application-piv/commands.md @@ -581,7 +581,9 @@ All YubiKeys with the PIV application. Which reference data element to change (PIN or PUK), the current reference value, and the new value. -Both the PIN and PUK are allowed to be 6 to 8 characters. +Both the PIN and the PUK are allowed to be 6 to 8 characters. The PIN can be composed of any ASCII character, but PUK composition depends on the key's firmware. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the `0x00` - +`0xFF` range. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the `0x00` - +`0x7F` range. ### Output diff --git a/Yubico.YubiKey/docs/users-manual/application-piv/pin-puk-mgmt-key.md b/Yubico.YubiKey/docs/users-manual/application-piv/pin-puk-mgmt-key.md index 41df9852..f92ef72b 100644 --- a/Yubico.YubiKey/docs/users-manual/application-piv/pin-puk-mgmt-key.md +++ b/Yubico.YubiKey/docs/users-manual/application-piv/pin-puk-mgmt-key.md @@ -32,11 +32,17 @@ is a 6- to 8-byte value, each of the bytes an ASCII number ('0' to '9', which in (upper- and lower-case), and even non-alphanumeric characters such as !, %, or # (among others). -The PUK is used to unblock the PIN (see the section below on Blocking). The standard -specifies that it is to be an 8-byte value, each of the bytes any binary value (`0x00` - -`0xFF`). If your application uses the keyboard to insert the PUK, you might limit the user -to ASCII characters, but the YubiKey will accept any byte value in the PUK. In addition, -the YubiKey will allow the PUK to be 6, 7, or 8 bytes long. +The PUK is used to unblock the PIN (see the section below on [blocking](#blocking)). The standard +specifies that the PUK is to be an 8-byte value, with each of the bytes any binary value from `0x00` to +`0xFF`. The YubiKey, however, will accept a PUK of 6 to 8 characters. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` - +`0xFF` range in the PUK. For YubiKeys with firmware version 5.7 and above, the key will only accept values in the `0x00` - +`0x7F` range. Values from `0x80` - `0xFF` will be considered invalid by the key, and any attempt to change the PUK to a byte array containing one of these values will fail. + +These restrictions are due to the YubiKey's PUK length requirements: for firmware versions prior to 5.7, the YubiKey simply requires a PUK length of 6-8 bytes, but for firmware version 5.7 and above, that requirement has changed to 6-8 *Unicode code points* in length. This is an important change because the byte representation (UTF-8 encoding) of a single code point can be 1-4 bytes in length, which means that a 6-byte PUK may be less than 6 code points. In order to accommodate keys of varying firmware versions, the SDK maintains a 6-8 byte length requirement when calling [PivSession.TryChangePuk](xref:Yubico.YubiKey.Piv.PivSession.TryChangePuk) or [Piv.Commands.ChangeReferenceDataCommand](xref:Yubico.YubiKey.Piv.Commands.ChangeReferenceDataCommand). However, keys with firmware 5.7 and above will only accept values that represent single-byte code points, hence the restricted range of `0x00` - `0x7F` (the range of `0x80` - `0xFF` represents code points of two bytes in length). For additional information on Unicode, UTF-8, and the SDK, see the [FIDO2 documentation](xref:TheFido2Pin). + +> [!NOTE] +> If your application uses the keyboard to insert the PUK, you might limit the user +to ASCII characters, regardless of a key's firmware version. The management key is used to authenticate the entity allowed to perform many YubiKey management operations, such as generating a key pair. On YubiKeys before version 5.4.2, it diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/ChangeReferenceDataCommand.cs b/Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/ChangeReferenceDataCommand.cs index 291ef5e9..546f0ce3 100644 --- a/Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/ChangeReferenceDataCommand.cs +++ b/Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/ChangeReferenceDataCommand.cs @@ -29,9 +29,9 @@ namespace Yubico.YubiKey.Piv.Commands /// starts out as a default value as well: "12345678", which in ASCII is the /// 8-byte sequence 0x31 32 33 34 35 36 37 38. Generally, the first /// thing done when a YubiKey is initialized for PIV is to change the PIN and - /// PUK (along with the management key). The PUK must be 6 to 8 bytes. - /// Ultimately the bytes that make up the PIN or PUK can be any binary value, - /// but are generally input from a keyboard, so are usually made up of ASCII + /// PUK (along with the management key). + /// The PIN and PUK are both allowed to be 6 to 8 characters/bytes. The PIN can be any ASCII character. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the 0x00 - 0xFF range for a total length of 6-8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the 0x00 - 0x7F range for a total length of 6-8 Unicode code points. + /// Since the PIN and PUK are generally input from a keyboard, they are usually made up of ASCII /// characters. /// /// @@ -149,7 +149,7 @@ private ChangeReferenceDataCommand() /// or PUK after calling connection.SendCommand. /// /// - /// Both the PIN and PUK are 6 to 8 bytes long. + /// The PIN and PUK are both allowed to be 6 to 8 characters/bytes. The PIN can be any ASCII character. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the 0x00 - 0xFF range for a total length of 6-8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the 0x00 - 0x7F range for a total length of 6-8 Unicode code points. /// /// /// diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Pin.cs b/Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Pin.cs index c47f7fb7..23c6e0b7 100644 --- a/Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Pin.cs +++ b/Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Pin.cs @@ -834,9 +834,8 @@ public bool TryChangePin(ReadOnlyMemory currentPin, ReadOnlyMemory n /// during the initial YubiKey setup to change from the default PUK, or /// later, to change it again. /// - /// The PUK is six to eight bytes byte long. Although most PUKs will be - /// characters, the YubiKey allows any binary data to be a PUK. The - /// default is the ASCII string "12345678" which is the byte array + /// The PUK must be 6-8 characters. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the 0x00 - 0xFF range for a total length of 6-8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the 0x00 - 0x7F range for a total length of 6-8 Unicode code points. The + /// default PUK is the ASCII string "12345678", which is the byte array /// /// 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 ///