PCSC sample in Swift
To continue the list of PC/SC wrappers initiated in 2010 with "PC/SC sample in different languages" I now present a sample in Swift using the Apple Crypto Token Kit API.
Crypto Token Kit API
See my previous article "PCSC sample in Objective-C" to know more about Crypto Token Kit API.Source code
Create a new Swift application in Xcode. You need to enable the App Sandbox and add/set thecom.apple.security.smartcard
entitlement to YES.This code is just a, more or less direct, conversion of the Objective-C source code to Swift.
I used Xcode 7.0 that implements Swift version 2.1.
Swift is a language not yet known by my colorization tool: source-highlight. The colors may not be great.
import CryptoTokenKit let mngr = TKSmartCardSlotManager.defaultManager() // Use the first reader/slot found let slotName = mngr!.slotNames[0] print("slotName:", slotName) // connect to the slot mngr?.getSlotWithName(slotName, reply: { (slot: TKSmartCardSlot?) in // connect to the card let card = slot?.makeSmartCard() if (card != nil) { // begin a session card?.beginSessionWithReply({ (success: Bool, error: NSError?) in if (success) { // send 1st APDU let aid : [UInt8] = [0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01] let data = NSData(bytes: aid, length: aid.count) card?.sendIns(0xA4, p1: 0x04, p2: 0x00, data: data, le: 0, reply: { (data: NSData?, sw: UInt16, error: NSError?) in if (error != nil) { print("sendIns error:", error!) } else { print("Response:", data!, String(sw, radix: 16)) // send 2nd APDU let data = NSData(bytes: nil, length: 0) card?.sendIns(0x0, p1: 0x00, p2: 0x00, data: data, le: 200, reply: { (data: NSData?, sw: UInt16, error: NSError?) in if (error != nil) { print("sendIns error:", error!) } else { print("Response:", data!, String(sw, radix: 16)) let newString = NSString(bytes: data!.bytes, length: data!.length, encoding: NSASCIIStringEncoding) print(newString!) } }) } }) } else { print("Session error:", error) } }) } else { print("No card found") } }) // wait for the asynchronous blocks to finish sleep(1)
Output
slotName: Gemalto PC Twin Reader Response: <> 9000 Response: <48656c6c 6f20776f 726c6421> 9000 Hello world!
Comments
See the previous article "PCSC sample in Objective-C" for comments about the Crypto Token Kit API.Swift may be easier to learn and use than Objective-C. Using the Crypto Token Kit API is not different if you use Objective-C or Swift.
It looks like I am the first to provide a public code sample using the Crypto Token Kit API in Swift. Great! I hope that is a good Swift sample, I am not a Swift expert.
Conclusion
As I wrote in "PCSC framework will stay in Mac OS X 10.11 El Capitan" the PC/SC API is not available from Swift. So the only option (for now) to use a smart card from Swift is to use the Crypto Token Kit API.[Update 5 Oct 2015]
The sample code was not correct in the error treatment.I then discovered that if the card returns an "error" code then the
sendIns
method returns an error in the error parameter. Here is the execution output of the program with a card that does not contain the applet:slotName: Gemalto PC Twin Reader sendIns error: Error Domain=CryptoTokenKit Code=-3 "SmartCard returned error 6a82" UserInfo=0x600000060940 {NSLocalizedDescription=SmartCard returned error 6a82}The card returns 0x6A82 (Wrong parameter(s) P1-P2, File not found) in SW (Status Word).
It may be difficult to differentiate errors at the card/reader communication level from "errors" returned by the card. A SW different from 0x9000 may be completely valid and expected by the application in some cases.