From 3dfb91a882bc602f3a55cb7b2a8a7caf0408a6c2 Mon Sep 17 00:00:00 2001 From: Jens Utbult Date: Mon, 10 Jun 2024 13:14:14 +0200 Subject: [PATCH] Delete key in PIVSession. --- .../Shared/Sessions/PIV/YKFPIVSession.h | 5 ++++ .../Shared/Sessions/PIV/YKFPIVSession.m | 11 ++++++++ YubiKitTests/Tests/PIVTests.swift | 25 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.h b/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.h index db87426f..b7baeede 100644 --- a/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.h +++ b/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.h @@ -276,6 +276,11 @@ typedef void (^YKFPIVSessionManagementKeyMetadataCompletionBlock) /// request. This handler is executed on a background queue. - (void)moveKey:(YKFPIVSlot)sourceSlot destinationSlot:(YKFPIVSlot)destinationSlot completion:(nonnull YKFPIVSessionGenericCompletionBlock)completion; +/// @abstract Delete key from slot. This method requires authentication with the management key. +/// +/// @param slot Slot to delete the key from. +- (void)deleteKeyInSlot:(YKFPIVSlot)slot completion:(nonnull YKFPIVSessionGenericCompletionBlock)completion; + /// @abstract Writes an X.509 certificate to a slot on the YubiKey. /// @discussion This method requires authentication. /// @param certificate Certificate to write. diff --git a/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.m b/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.m index 917746dd..49e36701 100644 --- a/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.m +++ b/YubiKit/YubiKit/Connections/Shared/Sessions/PIV/YKFPIVSession.m @@ -440,6 +440,17 @@ - (void)moveKey:(YKFPIVSlot)sourceSlot destinationSlot:(YKFPIVSlot)destinationSl }]; } +- (void)deleteKeyInSlot:(YKFPIVSlot)slot completion:(nonnull YKFPIVSessionGenericCompletionBlock)completion { + if (![self.features.moveDelete isSupportedBySession:self]) { + completion([[NSError alloc] initWithDomain:YKFPIVErrorDomain code:YKFPIVErrorCodeUnsupportedOperation userInfo:@{NSLocalizedDescriptionKey: @"Delete keys not supported by this YubiKey."}]); + return; + } + YKFAPDU *apdu = [[YKFAPDU alloc] initWithCla:0 ins:YKFPIVInsMoveKey p1:0xff p2:slot data:[NSData data] type:YKFAPDUTypeExtended]; + [self.smartCardInterface executeCommand:apdu completion:^(NSData * _Nullable data, NSError * _Nullable error) { + completion(error); + }]; +} + - (void)putCertificate:(SecCertificateRef)certificate inSlot:(YKFPIVSlot)slot completion:(YKFPIVSessionGenericCompletionBlock)completion { [self putCertificate:certificate inSlot:slot compress:NO completion:completion]; diff --git a/YubiKitTests/Tests/PIVTests.swift b/YubiKitTests/Tests/PIVTests.swift index ffb2ac4d..f54f16a3 100644 --- a/YubiKitTests/Tests/PIVTests.swift +++ b/YubiKitTests/Tests/PIVTests.swift @@ -432,6 +432,31 @@ class PIVTests: XCTestCase { } } + func testDeleteKey() throws { + runYubiKitTest { connection, completion in + connection.authenticatedPivTestSession { session in + session.putCertificate(self.certificate, inSlot: .authentication) { error in + XCTAssertNil(error) + session.generateKey(in: .authentication, type: .RSA1024) { secKey, error in + XCTAssertNil(error) + XCTAssertNotNil(secKey) + session.getMetadataFor(.authentication) { metadata, error in + XCTAssertNil(error) + XCTAssertNotNil(metadata?.publicKey) + session.deleteKey(in: .authentication) { error in + XCTAssertNil(error) + session.getMetadataFor(.authentication) { metadata, error in + XCTAssertNotNil(error) + completion() + } + } + } + } + } + } + } + } + func testPutCompressedAndReadCertificate() throws { runYubiKitTest { connection, completion in connection.authenticatedPivTestSession { session in