Skip to content

Adding support for deleting and moving keys between slots #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ dotnet_diagnostic.ca2208.severity = none
csharp_style_var_elsewhere = false:none
csharp_style_var_for_built_in_types = false:none
csharp_style_var_when_type_is_apparent = false:none

csharp_style_unused_value_expression_statement_preference = unused_local_variable:none

# CA1707: Identifiers should not contain underscores
dotnet_diagnostic.ca1707.severity = none
Expand Down
1,823 changes: 523 additions & 1,300 deletions Yubico.YubiKey/src/Resources/ExceptionMessages.Designer.cs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Yubico.YubiKey/src/Resources/ExceptionMessages.resx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@
<data name="InvalidSlot" xml:space="preserve">
<value>Slot number {0:X2} is not valid for the given operation on the given YubiKey.</value>
</data>
<data name="InvalidSlotsSameSourceAndDestinationSlotsCannotBeTheSame" xml:space="preserve">
<value>Source and destination slots cannot be the same.</value>
</data>
<data name="InvalidAlgorithm" xml:space="preserve">
<value>The given algorithm is not valid for the given command.</value>
</data>
Expand Down
75 changes: 75 additions & 0 deletions Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/DeleteKeyCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2024 Yubico AB
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Yubico.Core.Iso7816;

namespace Yubico.YubiKey.Piv.Commands
{
/// <summary>
/// The <see cref="DeleteKeyCommand"/> is used to Delete a PIV key from the target slot
/// <remarks>
/// Any key, including the attestation key can be deleted.
/// </remarks>
/// </summary>
public class DeleteKeyCommand : IYubiKeyCommand<DeleteKeyResponse>
{
/// <summary>
/// The Yubikey slot of the key you want to delete.
/// </summary>
public byte SlotToClear { get; set; }

/// <summary>
/// Constructor for the <see cref="DeleteKeyCommand"/> which is used to delete a PIV key from a slot.
/// </summary>
/// <param name="slotToClear">The Yubikey slot of the key you want to clear.</param>
public DeleteKeyCommand(byte slotToClear)
{
SlotToClear = slotToClear;
}

/// <summary>
/// Gets the YubiKeyApplication to which this command belongs. For this command it's PIV.
/// </summary>
/// <value>
/// YubiKeyApplication.Piv
/// </value>
public YubiKeyApplication Application => YubiKeyApplication.Piv;

/// <summary>
/// Constructs a <see cref="CommandApdu"/> for the Delete-operation.
/// </summary>
/// <returns>
/// The <see cref="CommandApdu"/> that targets the Delete-operation with the correct parameters.
/// </returns>
public CommandApdu CreateCommandApdu() =>
new CommandApdu
{
Ins = 0xF6,
P1 = 0xFF,
P2 = SlotToClear,
};

/// <summary>
/// Creates the <see cref="DeleteKeyResponse"/> from the <see cref="ResponseApdu"/> data.
/// </summary>
/// <param name="responseApdu">The return data with which the Yubikey responded to the
/// <see cref="DeleteKeyCommand"/>
/// </param>
/// <returns>
/// The <see cref="DeleteKeyResponse"/> for the <see cref="DeleteKeyCommand"/>
/// </returns>
public DeleteKeyResponse CreateResponseForApdu(ResponseApdu responseApdu) =>
new DeleteKeyResponse(responseApdu);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2024 Yubico AB
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Yubico.Core.Iso7816;

namespace Yubico.YubiKey.Piv.Commands
{
/// <summary>
/// The <see cref="DeleteKeyResponse"/> for the corresponding <see cref="DeleteKeyCommand"/>
/// <seealso cref="PivResponse"/>
/// <seealso cref="YubiKeyResponse"/>
/// </summary>
public class DeleteKeyResponse : PivResponse
{
/// <summary>
/// The constructor for the <see cref="DeleteKeyResponse"/>
/// </summary>
/// <param name="responseApdu">The return data with which the Yubikey responded
/// to the <see cref="DeleteKeyCommand"/></param>
/// <seealso cref="DeleteKeyCommand"/>
public DeleteKeyResponse(ResponseApdu responseApdu) : base(responseApdu)
{
}
}
}
111 changes: 111 additions & 0 deletions Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/MoveKeyCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2024 Yubico AB
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Globalization;
using Yubico.Core.Iso7816;

namespace Yubico.YubiKey.Piv.Commands
{
/// <summary>
/// The <see cref="MoveKeyCommand"/> is used to move a PIV key from one slot to another.
/// The source slot must not be the <see cref="PivSlot.Attestation"/>-slot and the destination slot must be empty.
/// </summary>
public class MoveKeyCommand : IYubiKeyCommand<MoveKeyResponse>
{
/// <summary>
/// The Yubikey slot of the key you want to move. This must be a valid slot number.
/// </summary>
public byte SourceSlot { get; set; }

/// <summary>
/// The target Yubikey slot for the key you want to move. This must be a valid slot number.
/// </summary>
public byte DestinationSlot { get; set; }

/// <summary>
/// Constructor for the <see cref="MoveKeyCommand"/> which is used to move a PIV key from one slot to another.
/// The source slot must not be the <see cref="PivSlot.Attestation"/>-slot and the destination slot must be empty.
/// </summary>
/// <param name="sourceSlot">The Yubikey slot of the key you want to move. This must be a valid slot number.</param>
/// <param name="destinationSlot">The target Yubikey slot for the key you want to move. This must be a valid slot number.</param>
public MoveKeyCommand(byte sourceSlot, byte destinationSlot)
{
SourceSlot = sourceSlot;
DestinationSlot = destinationSlot;
}

/// <summary>
/// Gets the YubiKeyApplication to which this command belongs. For this
/// command it's PIV.
/// </summary>
/// <value>
/// YubiKeyApplication.Piv
/// </value>
public YubiKeyApplication Application => YubiKeyApplication.Piv;

/// <summary>
/// This will create and validate the <see cref="CommandApdu"/>.
/// </summary>
/// <exception cref="InvalidOperationException">An exception will be thrown upon invalid slot usage.
/// Either one of the slots were the <see cref="PivSlot.Attestation"/> or the source and destination slot were the same.</exception>
/// <returns>The <see cref="CommandApdu"/> that targets the Move-operation with the correct parameters</returns>
public CommandApdu CreateCommandApdu()
{
ValidateSlots(SourceSlot, DestinationSlot);

return new CommandApdu
{
Ins = 0xF6,
P1 = DestinationSlot,
P2 = SourceSlot,
};
}

private static void ValidateSlots(byte sourceSlot, byte destinationSlot)
{
if (sourceSlot == destinationSlot)
{
throw new InvalidOperationException(string.Format(
CultureInfo.CurrentCulture,
ExceptionMessages.InvalidSlotsSameSourceAndDestinationSlotsCannotBeTheSame));
}

ValidateSlot(sourceSlot);
ValidateSlot(destinationSlot);
}

private static void ValidateSlot(byte slot)
{
if (slot == PivSlot.Attestation)
{
throw new InvalidOperationException(
string.Format(
CultureInfo.CurrentCulture,
ExceptionMessages.InvalidSlot,
slot));
}
}

/// <summary>
/// Creates the <see cref="MoveKeyResponse"/> from the <see cref="ResponseApdu"/> data.
/// </summary>
/// <param name="responseApdu">The return data with which the Yubikey responded
/// to the <see cref="MoveKeyCommand"/></param>
/// <returns>
/// The <see cref="MoveKeyResponse"/> for the <see cref="MoveKeyCommand"/>
/// </returns>
public MoveKeyResponse CreateResponseForApdu(ResponseApdu responseApdu) => new MoveKeyResponse(responseApdu);
}
}
36 changes: 36 additions & 0 deletions Yubico.YubiKey/src/Yubico/YubiKey/Piv/Commands/MoveKeyResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2024 Yubico AB
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Yubico.Core.Iso7816;

namespace Yubico.YubiKey.Piv.Commands
{
/// <summary>
/// The <see cref="MoveKeyResponse"/> for the corresponding <see cref="MoveKeyCommand"/>
/// <seealso cref="PivResponse"/>
/// <seealso cref="YubiKeyResponse"/>
/// </summary>
public class MoveKeyResponse : PivResponse
{
/// <summary>
/// The constructor for the <see cref="MoveKeyResponse"/>
/// </summary>
/// <param name="responseApdu">The return data with which the Yubikey responded
/// to the <see cref="MoveKeyCommand"/></param>
/// <seealso cref="MoveKeyCommand"/>
public MoveKeyResponse(ResponseApdu responseApdu) : base(responseApdu)
{
}
}
}
Loading