TkSmartCard transmitRequest persistently returning Cryptotokenkit error -2 on iOS/iPadOS

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?

TkSmartCard transmitRequest persistently returning Cryptotokenkit error -2 on iOS/iPadOS
 
 
Q