Class AdminData
Use this class to process the Admin Data.
public sealed class AdminData : PivDataObject
- Inheritance
-
objectAdminData
- 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.