We are using the CryptoTokenKit framework, specifically the classes TKSmartCardSlotManager, TKSmartCardSlot, and TKSmartCard, to communicate with smart cards through external USB readers on iOS and iPadOS. In most cases, we are able to detect readers via TKSmartCardSlotManager, and send APDU commands using transmitRequest method, with the following code (where self->_slot and self->_card are previously created TkSmartCardSlot and TkSmartCard, respectively):
#import <CryptoTokenKit/CryptoTokenKit.h>
- (NSData *)sendCardCommand:(NSData *)command
{
if (!self->_card || !self->_card.valid || self->_slot.state != TKSmartCardSlotStateValidCard)
return nil;
NSMutableData *res = [[NSMutableData alloc] init];
NSError *sessionError = nil;
[self->_card inSessionWithError:&sessionError executeBlock:^BOOL(NSError **error)
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
try {
[self->_card transmitRequest:command reply:^(NSData * _Nullable response, NSError* _Nullable apduError)
{
if (apduError != nil)
self->_error = apduError;
else
[res appendData: response];
dispatch_semaphore_signal(semaphore);
}];
} catch (NSException *exception) {
dispatch_semaphore_signal(semaphore);
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (res.length == 0)
return NO;
return YES;
}];
return res;
}
However, with certain other USB smart card readers, we occasionally encounter APDU communication failures when calling transmitRequest (for instance, with a HID Global OMNIKEY 5422), which returns the following error: "Domain: CryptoTokenKit Code: -2". Once a failure occurs and transmitRequest starts returning this error, all subsequent calls to transmitRequest fail with the same error. This persists even when:
- A different smart card is inserted
- The same card is reinserted
- A different USB reader (previously working correctly) is connected
- The TKSmartCard object is recreated via makeSmartCard
- The slot state changes (observed via KVO)
- All internal objects (TKSmartCard, TKSmartCardSlot) are reset in the application
At this point, the system appears to be stuck in a non-recoverable state which affects all readers and cards, including those that were previously functioning correctly. The only way to recover from this state is terminating and restarting the application which is running the code. After restarting the app, everything works normally again.
We have created a bug report: FB22339746.
The issue has been reproduced on iOS 26.4 and 18.5. Also on iPadOS 18.1.
Anyone has already faced a similar issue? Could it be related to some internal state of TKSmartCardSlotManager?
Thanks for bringing this to the forums.
returns the following error: "Domain: CryptoTokenKit Code: -2"
That is TKErrorCodeCommunicationError, aka TKError.Code.communicationError in Swift. This is a very generic error that basically means that something went wrong with… well… the communication with the smart card.
At this point, the system appears to be stuck in a non-recoverable state which affects all readers and cards
Yeah, that’s not good. This is clearly a bug and I appreciate you filing a bug report about it (FB22339746).
I took a look at your bug and noticed that you haven’t attached a sysdiagnose to it. Or, more accurately, it says that there’s an associated sysdiagnose log but it hasn’t finished uploading. Please run Feedback Assistant on the iOS device that captured the sysdiagnose log and check on its upload status. Alternatively, export the sysdiagnose log to your Mac and upload it from there.
Oh, and I think you already did this, but for the sake of anyone else following along on this thread, make sure that you install the CryptoTokenKit for iOS/iPadOS debug profile before capturing a sysdiagnose log for CryptoTokenKit issues. See our Bug Reporting > Profiles and Logs for more on that.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"