Table of Contents

How to set, modify, remove, and use slot access codes

The YubiKey's OTP application slots can be protected by a six-byte access code. Once a slot is configured with an access code, that slot cannot be reconfigured in any way unless the correct access code is provided during the reconfiguration operation.

Attempting to perform a slot configuration operation without providing the correct access code will result in the following exception:

System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]

Slot access code properties

Access codes can only be set, modified, or removed during one of the following slot configuration operations:

Of these options, the only method that allows you to configure a slot access code without changing the slot's current cryptographic credential is UpdateSlot(). However, calling UpdateSlot() will revert a number of other slot settings (such as SetAppendCarriageReturn()) to their default states unless otherwise specified during the operation. See How to update slot settings for more information.

Note

If a slot is configured with an access code, calling ConfigureNdef() will fail, even if the correct access code is provided during the operation. Similarly, if a slot is not configured with an access code, you cannot set one when calling ConfigureNdef().

Access codes must be exactly six bytes (MaxAccessCodeLength). The SlotAccessCode container class pads the code with zeros (0x00) if less than six bytes are provided and throws an exception if more than six bytes are provided.

If a slot is configured with an access code, that code must be specified during any reconfiguration operation. In addition, if you don’t resupply the same (or any) code as a "new" access code, an access code will not be carried over to the new slot configuration, and the slot will no longer be protected after reconfiguration.

If a slot is protected by an access code, deleting the slot's configuration requires the use of the compatible DeleteSlotConfiguration method.

Example code

Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the YubiKeyDevice class.

To select the first available YubiKey connected to your host, use:

IEnumerable<IYubiKeyDevice> yubiKeyList = YubiKeyDevice.FindAll();

var yubiKey = yubiKeyList.First();

Example: set a slot access code

To set a slot's access code when no access code is present, call SetNewAccessCode() during a slot configuration operation, and provide the access code as a SlotAccessCode object. Prior to the configuration operation, initialize the SlotAccessCode object by passing it the access code in ReadOnlyMemory<byte> form.

In this example, we are setting a new access code while configuring the long press slot with a new HOTP credential.

using (OtpSession otp = new OtpSession(yubiKey))
{
  // example HOTP key
  ReadOnlyMemory<byte> hmacKey = new byte[ConfigureHotp.HmacKeySize] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };

  // example slot access code
  ReadOnlyMemory<byte> accessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, };
  SlotAccessCode accessCode = new SlotAccessCode(accessCodeBytes);

  otp.ConfigureHotp(Slot.LongPress)
     .UseKey(hmacKey)
     .SetNewAccessCode(accessCode)
     .Execute();
}

Example: modify a slot access code

To modify a slot's access code, you must provide the current access code with UseCurrentAccessCode() followed by the new access code with SetNewAccessCode() during a slot configuration operation.

In this example, we are reconfiguring the long press slot with a new access code via the UpdateSlot() method. UpdateSlot() will not modify the slot's cryptographic configuration. However, it will revert a number of other slot settings (such as SetAppendCarriageReturn()) to their default states unless otherwise specified during the operation.

using (OtpSession otp = new OtpSession(yubiKey))
{
  // Example current slot access code.
  ReadOnlyMemory<byte> currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, };
  SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes);

  // Example new slot access code.
  ReadOnlyMemory<byte> newAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, };
  SlotAccessCode newAccessCode = new SlotAccessCode(newAccessCodeBytes);

  otp.UpdateSlot(Slot.LongPress)
     .UseCurrentAccessCode(currentAccessCode)
     .SetNewAccessCode(newAccessCode)
     .Execute();
}

Example: remove a slot access code

If you want to remove a slot's access code during a configuration operation, you can either:

  • provide a new access code of all zeros with SetNewAccessCode(), or
  • skip the SetNewAccessCode() call entirely
Note

A 6-byte access code of zeros (0x00) is the factory default state for each OTP slot.

Once the access code is removed, you do not need to call UseCurrentAccessCode() with subsequent configuration operations.

In this example, we are effectively removing the access code from the long press slot by providing a new code of all zeros during the UpdateSlot() operation. UpdateSlot() will not modify the slot's cryptographic configuration. However, it will revert a number of other slot settings (such as SetAppendCarriageReturn()) to their default states unless otherwise specified during the operation.

using (OtpSession otp = new OtpSession(yubiKey))
{
  // Example current access code.
  ReadOnlyMemory<byte> currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, };
  SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes);

  // New access code of all zeros.
  ReadOnlyMemory<byte> newAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
  SlotAccessCode newAccessCode = new SlotAccessCode(newAccessCodeBytes);

  otp.UpdateSlot(Slot.LongPress)
     .UseCurrentAccessCode(currentAccessCode)
     .SetNewAccessCode(newAccessCode)
     .Execute();
}

Example: provide a slot access code during a configuration operation

Once a slot has been configured with an access code, you must provide that access code with UseCurrentAccessCode() when performing a configuration operation on that slot. To retain the access code, you must also call SetNewAccessCode() and provide the same access code. If you do not call SetNewAccessCode(), the access code will be removed.

Note

If a slot does not have an access code, providing any 6-byte code with UseCurrentAccessCode() during a configuration operation will succeed.

In this example, we are reconfiguring an access code-protected long press slot with a new Yubico OTP credential. The access code is carried over to the new slot configuration by the SetNewAccessCode(currentAccessCode) call.

using (OtpSession otp = new OtpSession(yubiKey))
{
  // Example current access code.
  ReadOnlyMemory<byte> currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, };
  SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes);

  Memory<byte> privateId = new byte[ConfigureYubicoOtp.PrivateIdentifierSize];
  Memory<byte> aesKey = new byte[ConfigureYubicoOtp.KeySize];

  otp.ConfigureYubicoOtp(Slot.LongPress)
     .UseCurrentAccessCode(currentAccessCode)
     .SetNewAccessCode(currentAccessCode)
     .UseSerialNumberAsPublicId()
     .GeneratePrivateId(privateId)
     .GenerateKey(aesKey)
     .Execute();
}

Example: deleting a slot configuration when an access code is present

To delete a slot configuration that is protected with an access code, you must call DeleteSlotConfiguration and provide the current access code with UseCurrentAccessCode().

You cannot set a new access code during this operation. The DeleteSlotConfiguration operation will still succeed if you call SetNewAccessCode(), but the new access code will not be applied.

using (OtpSession otp = new OtpSession(yubiKey))
{
  // Example current access code.
  ReadOnlyMemory<byte> currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, };
  SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes);

  otp.DeleteSlotConfiguration(Slot.LongPress)
     .UseCurrentAccessCode(currentAccessCode)
     .Execute();
}
Note

To delete a slot configuration that is not protected with an access code, use DeleteSlot().