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 the
com.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.