Skip to content

Commit

Permalink
fixed length info, added apdu
Browse files Browse the repository at this point in the history
  • Loading branch information
equijano21 committed Aug 7, 2024
1 parent 35602b9 commit 9ce6982
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ 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.

The PIN is allowed to be 6 to 8 ASCII characters. If it is less than 8, it
will be padded with 0xff to reach 8 bytes in length. 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 PUK is allowed to be 8 characters. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` -
`0xFF` range for a total length of 8 bytes. For YubiKeys with firmware version 5.7 and above, the key will only accept values in the `0x00` -
`0x7F` range for a total length of 8 Unicode code points.
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).
Expand Down Expand Up @@ -82,6 +82,28 @@ Data Length: 0

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
Expand Down
6 changes: 3 additions & 3 deletions Yubico.YubiKey/docs/users-manual/application-piv/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +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.

The PIN is allowed to be 6 to 8 ASCII characters (6 to 8 bytes in length). 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 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 8 Unicode code points.
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ others).

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`. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` -
`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 8 bytes, but for firmware version 5.7 and above, that requirement has changed to 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 an 8-byte PUK may be less than 8 code points. In order to accommodate keys of varying firmware versions, the SDK maintains an 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).
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace Yubico.YubiKey.Piv.Commands
/// 8-byte sequence <c>0x31 32 33 34 35 36 37 38</c>. 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 PIN is allowed to be 6 to 8 ASCII characters (6 to 8 bytes in length). The PUK must be 8 characters. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the <c>0x00</c> - <c>0xFF</c> range for a total length of 8 bytes. For YubiKeys with firmware version 5.7 and above, the the PUK is allowed to be any character in the <c>0x00</c> - <c>0x7F</c> range for a total length of 8 Unicode code points.
/// 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 <c>0x00</c> - <c>0xFF</c> 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 <c>0x00</c> - <c>0x7F</c> 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.
/// </para>
Expand Down Expand Up @@ -150,7 +150,7 @@ private ChangeReferenceDataCommand()
/// or PUK after calling <c>connection.SendCommand</c>.
/// </para>
/// <para>
/// The PIN is allowed to be 6 to 8 ASCII characters (6 to 8 bytes in length). The PUK must be 8 characters. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the <c>0x00</c> - <c>0xFF</c> range for a total length of 8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the <c>0x00</c> - <c>0x7F</c> range for a total length of 8 Unicode code points.
/// 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 <c>0x00</c> - <c>0xFF</c> 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 <c>0x00</c> - <c>0x7F</c> range for a total length of 6-8 Unicode code points.
/// </para>
/// </remarks>
/// <param name="slotNumber">
Expand Down
2 changes: 1 addition & 1 deletion Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Pin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ public bool TryChangePin(ReadOnlyMemory<byte> currentPin, ReadOnlyMemory<byte> n
/// during the initial YubiKey setup to change from the default PUK, or
/// later, to change it again.
/// <para>
/// The PUK must be 8 characters. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the <c>0x00</c> - <c>0xFF</c> range for a total length of 8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the <c>0x00</c> - <c>0x7F</c> range for a total length of 8 Unicode code points. The
/// 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 <c>0x00</c> - <c>0xFF</c> 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 <c>0x00</c> - <c>0x7F</c> range for a total length of 6-8 Unicode code points. The
/// default PUK is the ASCII string <c>"12345678"</c>, which is the byte array
/// <code>
/// 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
Expand Down

0 comments on commit 9ce6982

Please sign in to comment.