Table of Contents

Class PinUvAuthProtocolBase

Namespace
Yubico.YubiKey.Fido2.PinProtocols
Assembly
Yubico.YubiKey.dll

Base class for FIDO2 PIN/UV auth protocol implementations.

public abstract class PinUvAuthProtocolBase
Inheritance
object
PinUvAuthProtocolBase
Derived

Remarks

A PIN/UV auth protocol is a set of methods defined by the FIDO2 CTAP specification. The abstract interface is defined in section 6.5.4. As of FIDO 2.1, there are only two PIN protocols defined: protocol one and protocol two. These two implementations share some common code. The abstract interface as well as any shared code is defined by this class.

Properties

AuthenticationKey

Gets the authentication key derived from the shared value computed during the call to Encapsulate(CoseKey). This can be the same as the EncryptionKey.

public ReadOnlyMemory<byte>? AuthenticationKey { get; protected set; }

Property Value

ReadOnlyMemory<byte>?

Remarks

This will be null until the Encapsulate method is called.

AuthenticatorPublicKey

The public key returned by the YubiKey.

public CoseKey? AuthenticatorPublicKey { get; protected set; }

Property Value

CoseKey

Remarks

The caller will obtain the YubiKey's public key using the GetKeyAgreementCommand and pass it to the Encapsulate(CoseKey) method. A reference to the key passed into that method will be stored in this property.

A call to Initialize() will set this to null. That is, a new public key must be obtained for each PIN/UV authentication session with the YubiKey. Even if the new session is initiated with the previously-used YubiKey, the public key must be obtained, because the YubiKey might generate a new public key.

EncryptionKey

Gets the encryption key derived from the shared value computed during the call to Encapsulate(CoseKey). This can be the same as the AuthenticationKey.

public ReadOnlyMemory<byte>? EncryptionKey { get; protected set; }

Property Value

ReadOnlyMemory<byte>?

Remarks

This will be null until the Encapsulate method is called.

PlatformPublicKey

Gets the public key generated during the call to Encapsulate(CoseKey).

public CoseKey? PlatformPublicKey { get; protected set; }

Property Value

CoseKey

Remarks

This will be null until the Encapsulate method is called.

Protocol

Gets the identifier of the PIN / UV authentication protocol that this instance implements.

public PinUvAuthProtocol Protocol { get; protected set; }

Property Value

PinUvAuthProtocol

Methods

Authenticate(byte[])

Returns the result of computing HMAC-SHA-256 on the given message using the AuthenticationKey. With protocol 1, the result is the first 16 bytes of the HMAC, and with protocol 2 it is the entire 32-byte result.

public abstract byte[] Authenticate(byte[] message)

Parameters

message byte[]

The data to be authenticated.

Returns

byte[]

A new byte array containing the authentication result.

Exceptions

ArgumentNullException

The message argument is null.

InvalidOperationException

The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.

Authenticate(byte[], byte[])

Returns the result of computing HMAC-SHA-256 on the given message using the provided keyData. With protocol 1, the result is the first 16 bytes of the HMAC, and with protocol 2 it is the entire 32-byte result.

protected abstract byte[] Authenticate(byte[] keyData, byte[] message)

Parameters

keyData byte[]

The key to use to authenticate.

message byte[]

The data to be authenticated.

Returns

byte[]

A new byte array containing the authentication result.

Exceptions

ArgumentNullException

The keyData or message argument is null.

AuthenticateUsingPinToken(byte[], byte[])

Returns the result of computing HMAC-SHA-256 on the given message using the pinToken as the key. With protocol 1, the result is the first 16 bytes of the HMAC, and with protocol 2 it is the entire 32-byte result.

public byte[] AuthenticateUsingPinToken(byte[] pinToken, byte[] message)

Parameters

pinToken byte[]

The PIN token returned by the YubiKey. This is the encrypted value, do not decrypt it.

message byte[]

The data to be authenticated.

Returns

byte[]

A new byte array containing the authentication result.

Remarks

It is possible to obtain the PIN token by calling the command GetPinTokenCommand. The YubiKey will return the PIN token encrypted using the shared secret.

Pass that encrypted PIN token to this method as the first argument. This method will decrypt the PIN token using the EncryptionKey and then perform the authentication on the message.

Exceptions

ArgumentNullException

The pinToken or message argument is null.

InvalidOperationException

The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.

AuthenticateUsingPinToken(byte[], int, int, byte[])

Returns the result of computing HMAC-SHA-256 on the given message using the pinToken as the key. With protocol 1, the result is the first 16 bytes of the HMAC, and with protocol 2 it is the entire 32-byte result.

public virtual byte[] AuthenticateUsingPinToken(byte[] pinToken, int offset, int length, byte[] message)

Parameters

pinToken byte[]

The PIN token returned by the YubiKey. This is the encrypted value, do not decrypt it.

offset int

The offset into pinToken buffer where the data begins.

length int

The length, in bytes, of the pin token.

message byte[]

The data to be authenticated.

Returns

byte[]

A new byte array containing the authentication result.

Remarks

This is the same as AuthenticateUsingPinToken(byte[], byte[]), except this specifies an offset and length of the pinToken argument.

Exceptions

ArgumentNullException

The pinToken or message argument is null.

InvalidOperationException

The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.

Decrypt(byte[], int, int)

Returns the AES-256-CBC decryption of ciphertext using an IV specified by the protocol and the EncryptionKey. With protocol 1 the IV is all 00 bytes. With protocol 2, it is the first block size bytes of ciphertext.

public abstract byte[] Decrypt(byte[] ciphertext, int offset, int length)

Parameters

ciphertext byte[]

The data to decrypt.

offset int

The offset in ciphertext where the method will begin decrypting.

length int

The number of bytes to decrypt.

Returns

byte[]

A new byte array containing the decrypted data.

Remarks

Note that this method will verify that the input buffer, offset, and length are valid.

Exceptions

ArgumentNullException

The ciphertext argument is null.

InvalidOperationException

The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.

ArgumentException

The length of the ciphertext is not a multiple of the AES block size (16 bytes).

DeriveKeys(byte[])

The key derivation function to run while performing ECDH. This will derive both the EncryptionKey and the AuthenticationKey.

protected abstract void DeriveKeys(byte[] buffer)

Parameters

buffer byte[]

The shared value computed by ECDH.

Exceptions

ArgumentNullException

The buffer argument is null.

InvalidOperationException

The HMAC with SHA-256 provider failed.

Dispose()

Release resources, overwrite sensitive data.

public void Dispose()

Dispose(bool)

Release resources, overwrite sensitive data.

protected virtual void Dispose(bool disposing)

Parameters

disposing bool

Encapsulate(CoseKey)

Generates a new platform key pair and uses the private key along with the peerPublicKey to compute the shared value. It then derives the shared keys (encryption and authentication) from the shared value.

public virtual void Encapsulate(CoseKey authenticatorPublicKey)

Parameters

authenticatorPublicKey CoseKey

The YubiKey's public key obtained by calling the GetKeyAgreementCommand.

Remarks

This will generate a new public and private key, compute the shared value, and discard the private key. The resulting public key will be found in the PlatformPublicKey property, and the derived keys will be found in the EncryptionKey and AuthenticationKey properties.

This method can be called only after instantiation or a call to Initialize(). Otherwise, this method will throw an exception.

Exceptions

ArgumentNullException

The authenticatorPublicKey argument is null.

ArgumentException

The authenticatorPublicKey argument is not an appropriate key object (e.g. wrong algorithm).

InvalidOperationException

The object is not available for Encapsulate because it still contains data from a previous operation. It is necessary to call Initialize before reusing a Protocol object.

Encrypt(byte[], int, int)

Returns the AES-256-CBC encryption of plaintext using an IV specified by the protocol and the EncryptionKey. With protocol 1 the IV is all 00 bytes. With protocol 2, it is a new, random value.

public abstract byte[] Encrypt(byte[] plaintext, int offset, int length)

Parameters

plaintext byte[]

The data to encrypt.

offset int

The offset in plaintext where the method will begin encrypting.

length int

The number of bytes to encrypt.

Returns

byte[]

A new byte array containing the encrypted data. With protocol 2, the ciphertext is actually the concatenation of the IV and the encrypted data.

Exceptions

ArgumentNullException

The plaintext argument is null.

InvalidOperationException

The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.

ArgumentException

The length of the plaintext is not a multiple of the AES block size (16 bytes).

Initialize()

This is run by the platform when starting a series of transactions with a specific authenticator.

public virtual void Initialize()

Remarks

This will reset the internal state of the object to the same as immediately after instantiation. Any data acquired, generated, or computed during operations in a session of PIN/UV Authentication with a specific authenticator will be lost.

Generally you will create an instance of one of the protocols and use it to perform the appropriate PIN/UV authentication operations with an authenticator. Then, to operate on a different authenticator (or the same authenticator in a new session), create a new instance of the protocol or reuse an existing object but call Initialize before beginning operations.