Table of Contents

Class AdminData

Namespace
Yubico.YubiKey.Piv.Objects
Assembly
Yubico.YubiKey.dll

Use this class to process the Admin Data.

public sealed class AdminData : PivDataObject
Inheritance
object
AdminData
Inherited Members

Remarks

Admin consists of three values:

  • Bit field: PUK blocked? Mgmt Key stored in protected area? (optional)
  • Salt (optional)
  • PIN last updated (optional)

The AdminData is used to store information about "PIN-only" modes of a YubiKey. See the User's Manual entry on setting the YubiKey to be PIN only.

If the YubiKey is PIN-derived, the PUK should be blocked, and there will be a salt. Hence, the PukBlocked property should be true and the Salt should contain the salt used to derive the management key.

If the YubiKey is PIN-protected, the PUK should be blocked, so both the PinProtected and PukBlocked properties should be true.

Note that the YubiKey will not "automatically" set the Admin Data to the appropriate values if the management key is set to one of the PIN-only modes. That is the responsibility of the code that sets the PIN-only mode. In other words, if you write code that sets a YubiKey to one of the PIN-only modes, then you must also write code to correctly set the Admin Data. The PivSession methods that set a YubiKey to PIN-only will store the appropriate Admin Data information, so you should call those methods to set a YubiKey to PIN-only, rather than writing the code yourself.

The salt is used by the code that computes a PIN-derived management key. The management key is derived from the PIN and salt. It must be exactly 16 bytes. This class will accept either no salt (mgmt key is not PIN-derived) or a 16-byte salt. If you want to use the Admin Data storage area to store something other than a 16-byte salt, you will have to write your own implementation.

The PIN last updated element is the date the PIN was changed. It is not mandatory to set this value when the PIN is changed, but the SDK code that changes the PIN will check the ADMIN DATA. If the YubiKey contains ADMIN DATA, the SDK will update the time when the PIN is changed. If there is no ADMIN DATA, the SDK will not create ADMIN DATA when the PIN is changed.

Upon instantiation of this class, it is empty. If you set any of the properties (PukBlocked, (PinProtected, Salt, and PinLastUpdated), the object will no longer be empty. That is the case even if you set the PukBlocked and/or the PinProtected to false, or the other two to null. In this case, the encoding of the Admin Data is

80 03
   81 01
      00
The salt and PinLastUpdated are optional, so
they are not encoded when absent. The bit field
is also optional, so it could be absent, but
this class exercises the option and writes it.

If an object is not empty, you can call the WriteObject(PivDataObject) method, which will call the Encode() method. This class will encode whatever data it is given, even if it is "wrong". For example, if a management key is PIN-derived, then the PUK blocked bit and the Salt should be set. However, if, for example, the PUK blocked bit is set, but not the Salt, this class will encode anyway. It will generate an encoding, not throw an exception. It is the responsibility of the caller to make sure the data in an object is correct for the situation.

Constructors

AdminData()

Build a new object. This will not get the Admin Data from any YubiKey, it will only build an "empty" object.

public AdminData()

Remarks

To read the Admin Data out of a YubiKey, call the ReadObject<T>() method.

Properties

PinLastUpdated

The date the PIN was last updated. If this is not being used, it will be null.

public DateTime? PinLastUpdated { get; set; }

Property Value

DateTime?

Remarks

To set this property to the current time, use DateTime.UtcNow.

var adminData = new AdminData();
adminData.PinLastUpdated = DateTime.UtcNow;

It is possible to set the time to any time at all (Jan. 1, 2000, if you want), but it is likely that you will never need to set it to anything other than the current time.

If you get the ADMIN DATA out of a YubiKey, it will be encoded. This class will decode it and set this property to the time specified in the encoding. It is possible the date is not encoded, in which case this will be null.

Upon construction, the PinLastUpdated is null. If you leave it null or set it to null, then when the data is encoded, no PinLastUpdated value will be included in the encoding.

PinProtected

Set this to true if the YubiKey's management key is PIN-protected. If you set a YubiKey to PIN-protected, then the PUK should be blocked as well.

public bool PinProtected { get; set; }

Property Value

bool

PukBlocked

Set this to true if the PUK is blocked. If you set a YubiKey to PIN-only, then the PUK should be blocked.

public bool PukBlocked { get; set; }

Property Value

bool

Salt

The salt used to derive the management key. If there is no salt, this will be null.

public ReadOnlyMemory<byte>? Salt { get; }

Property Value

ReadOnlyMemory<byte>?

Methods

Dispose(bool)

Releases any unmanaged resources and overwrites any sensitive data.

protected override void Dispose(bool disposing)

Parameters

disposing bool

Encode()

Build the encoding of the data.

public override byte[] Encode()

Returns

byte[]

A new byte array containing the encoded data object.

Remarks

Each data object has a defined format. See the User's Manual entry on GET DATA and GET vendor data for descriptions of the formats. This method will build a new byte array containing the data set in the object. This data will generally then be stored on the YubiKey.

Note that this method returns a new byte array, not a reference to an array inside the object. If this array contains any sensitive data, make sure you overwrite it when done with it.

If the object is empty (IsEmpty is true), then this method will return the encoding of no data, which is 0x53 00.

GetDefinedDataTag()

Get the defined data tag. This is the data tag that the PIV standard or Yubico defines to specify the given data object.

public override int GetDefinedDataTag()

Returns

int

The data tag defined for the data object.

Remarks

This is also called the default data tag. This method will always return the defined tag, regardless of what the DataTag property returns. That is, even if you change the DataTag this method will still return the original, defined tag.

SetSalt(ReadOnlyMemory<byte>)

Set the Salt property with the given value. If the input argument Length is 0, this will set the Salt to be null. Otherwise, it must be exactly 16 bytes. If not, this method will throw an exception.

public void SetSalt(ReadOnlyMemory<byte> salt)

Parameters

salt ReadOnlyMemory<byte>

The salt to use.

Remarks

This method will copy the input salt data, it will not copy a reference.

If there is a salt value already in this object, this method will overwrite it.

If the input salt argument is null or the Length is 0, this method will set the Salt property to null. The object will not be empty (IsEmpty) will be false), but there will be no salt.

Exceptions

ArgumentException

The data, if there is any, is not exactly 16 bytes.

TryDecode(ReadOnlyMemory<byte>)

Try to decode the data given according to the format specified for the data object. If successful, return true, otherwise, return false.

public override bool TryDecode(ReadOnlyMemory<byte> encodedData)

Parameters

encodedData ReadOnlyMemory<byte>

The data to parse.

Returns

bool

A boolean, true if the method successfully decodes, false otherwise.

Remarks

This will parse the encoding and set local properties with the data. The encodedData generally was retrieved from the YubiKey.

This will replace any data in the object.

If there is no data (encodedData.Length is 0) this method will set the object to the empty state (IsEmpty will be true and the contents of any data properties will be meaningless) and return true.

If the input is not encoded as expected, this method will set the object to the empty state and return false. This includes the fixed values. That is, there are some values in some data objects that are fixed for every YubiKey, and this method will expect the contents of the encodedData to contain those fixed values.

If the input is encoded as expected, yet the data in that encoding is invalid (e.g. some element is not the correct length), this method will return false.

Exceptions

ArgumentException

The data is not properly encoded for the data object.