InitializeAuthenticateManagementKeyCommand Class
Namespace: Yubico.YubiKey.Piv.Commands Assembly: Yubico.YubiKey.dllInitiate the process to authenticate the PIV management key.
public sealed class InitializeAuthenticateManagementKeyCommand : Object, IYubiKeyCommand<InitializeAuthenticateManagementKeyResponse>
Remarks
In the PIV standard, there is a command called GENERAL AUTHENTICATE. Although it is one command, it can do four things: authenticate a management key (challenge-response), sign arbitrary data, RSA decryption, and EC Diffie-Hellman. The SDK breaks these four operations into separate classes. This class is how you initialize the process of performing "GENERAL AUTHENTICATE: management key".
The partner Response class is InitializeAuthenticateManagementKeyResponse.
Some operations require the management key. See the User's Manual entry on the management key. Use this command to begin the process of authenticating the key for such operations. The User's Manual entry on access control has more information on how to use this authentication.
Upon manufacture of a YubiKey, the management key is a Triple-DES key and it starts out as a default value:
(hex) 0102030405060708 0102030405060708 0102030405060708
You will likely change it using the SetManagementKeyCommand.
Starting with YubiKey 5.4.2, it is possible to use an AES key as the management key. An AES key can be 128, 192, or 256 bits (16, 24, and 32 bytes respectively).
Authentication is a challenge-response process involving two or three steps. The off-card application sends in the Command APDUs and the YubiKey returns the Response APDUs. Note that both the term "challenge-response" and the APDU pair "Command and Response" use the term "response". To avoid confusion, when discussing the process, there will be the "Command APDU" and "Response APDU", the "Command Class" and the "Response Class", the "Command Object" and the "Response Object". Then there will be "Challenge" and "Response".
There are two versions of the process: (1) authenticate the off-card application to the YubiKey only, or (2) mutual authentication, where the YubiKey is authenticated to the off-card application as well.
Single Authentication
Off-Card Application | YubiKey |
Step 1 | |
Command APDU initiates the Process | |
Generate random Client Authentication Challenge | |
Response APDU contains Client Authentication Challenge | |
Step 2 | |
Compute Client Authentication Response based on Client Authentication Challenge | |
Command APDU contains Client Authentication Response | |
Verify Client Authentication Response | |
Response APDU contains no data Status is either Success or AuthenticationRequired |
Mutual Authentication
Off-Card Application | YubiKey |
Step 1 | |
Command APDU initiates the Process | |
Generate random Client Authentication Challenge | |
Response APDU contains Client Authentication Challenge | |
Step 2 | |
Compute Client Authentication Response based on Client Authentication Challenge | |
Generate random YubiKey Authentication Challenge | |
Command APDU contains Client Authentication Response and YubiKey Authentication Challenge | |
Verify Client Authentication Response | |
Compute YubiKey Authentication Response based on YubiKey Authentication Challenge | |
Response APDU Status is either Success or AuthenticationRequired if Success, Response APDU contains YubiKey Authentication Response | |
Step 3 | |
Verify YubiKey Authentication Response |
Each response is built from the challenge and the management key. If both parties possess the same management key, the response will match what the challenger expects.
Note that the PIV standard has three elements: "witness", "challenge", and "response". In mutual authentication, the YubiKey sends a "witness", which the application decrypts to generate the response. In single authentication, the YubiKey sends a "challenge" and the application encrypts it to generate the response. For the purposes of this documentation, the "witness-response" and "challenge-response" are the same concept, namely a "challenge-response".
To perform step 1, build an InitializeAuthenticateManagementKeyCommand
object,
specifying single or mutual authentication, and send it to the YubiKey
using the Connection class's SendCommand
method.
After the SendCommand
completes, check the Response Object to
verify it worked. To do so, look at the Status
property in the
Response Object, it will be Success
. The return from
GetData
will be a ReadOnlyMemory
object containing the
challenge from the YubiKey (this is "Client Authentication Challenge").
It is likely you will never need to examine the challenge, the Command
object in Step 2 will process it.
To perform step 2, create a new instance of the
CompleteAuthenticateManagementKeyCommand
class, supplying the
previous Response Object, along with the management key. Now call
connection.SendCommand
again. Under the covers, "Client
Authentication Response" (the response to "Client Authentication
Challenge") is computed and both it and "YubiKey Authentication
Challenge" are sent to the YubiKey. If this is single authentication,
only "Client Authentication Response" is sent.
Examine the resulting Response Object. If the Status
property is
Success
, you have authenticated the management key. If the
Status
property is AuthenticationRequired
, the management
key is not authenticated (either the off board app or the YubiKey did not
authenticate). If Status
is not one of those values, then some other error occurred and
the authentication process was not completed. In this situation the Response's
GetData
method will throw an exception if called.
If the process is mutual authentication, and the response object's
Status
is AuthenticationRequired
, you will likely want to
know whether the YubiKey was also authenticated. Call the response
object's GetData
method, the return will be an
AuthenticateManagementKeyResult enum.
Note that if, during mutual authentication, the YubiKey does not authenticate the management key, it will not be able to even attempt to authenticate the YubiKey, so its authentication status will be "Unknown".
Note also that if the YubiKey does not authenticate the management key,
calling GetData
will not throw an exception. The operation
determines whether the management key authenticates or not. If it does
not, then the YubiKey has completed the operation successfully. That is,
the operation was performed to completion, it's just that the operation
determined that the management key was not correct.
Example:
/* This example assumes the application has a method to collect a
* management key.
*/
byte[] mgmtKey;
IYubiKeyConnection connection = key.Connect(YubiKeyApplication.Piv);
var initAuthMgmtKeyCommand =
new InitializeAuthenticateManagementKeyCommand(true, PivAlgorithm.Aes192);
InitializeAuthenticateManagementKeyResponse initAuthMgmtKeyResponse =
connection.SendCommand(initAuthMgmtKeyCommand);
if (initAuthMgmtKeyResponse != ResponseStatus.Success)
{
// Handle error
}
mgmtKey = CollectMgmtKey();
var completeAuthMgmtKeyCommand = new CompleteAuthenticateManagementKeyCommand(
initAuthMgmtKeyResponse, mgmtKey, PivAlgorithm.Aes192);
CompleteAuthenticateManagementKeyResponse completeAuthMgmtKeyResponse =
connection.SendCommand(completeAuthMgmtKeyCommand);
if (completeAuthMgmtKeyResponse.Status == ResponseStatus.AuthenticationRequired)
{
AuthenticateManagementKeyResult authResult = completeAuthMgmtKeyResponse.GetData();
/* The value of authResult will be either MutualOffCardAuthenticationFailed
* or MutualYubiKeyAuthenticationFailed, to indicate why the
* authentication failed. */
}
else if (completeAuthMgmtKeyResponse.Status != ResponseStatus.Success)
{
// Handle error
}
/* Continue with operations that needed the mgmt key authenticated. */
CryptographicOperations.ZeroMemory(mgmtKey);
Constructors
Name | Description |
---|---|
InitializeAuthenticateManagementKeyCommand() | Initializes a new instance of the InitializeAuthenticateManagementKeyCommand class for Mutual Authentication, and a Triple-DES management key. |
InitializeAuthenticateManagementKeyCommand(Boolean) | Initializes a new instance of the InitializeAuthenticateManagementKeyCommand class for the specified mutual or single authentication, and a Triple-DES management key. |
InitializeAuthenticateManagementKeyCommand(Boolean, PivAlgorithm) | Initializes a new instance of the InitializeAuthenticateManagementKeyCommand class for the specified mutual or single authentication, and a management key of the specified algorithm. |
Properties
Name | Description |
---|---|
Algorithm | Which algorithm is the management key. |
Application | Gets the YubiKeyApplication to which this command belongs. For this command it's PIV. |
Methods
Name | Description |
---|---|
CreateCommandApdu() | Creates a well-formed CommandApdu to send to the YubiKey. |
CreateResponseForApdu(ResponseApdu) | Creates the corresponding IYubiKeyResponse implementation for the current command. |