lint fixes
This commit is contained in:
parent
8427ddbb2e
commit
4703e6061f
|
@ -5,6 +5,7 @@
|
|||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
Keycard.xcodeproj
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
|
|
|
@ -9,5 +9,5 @@ file_name:
|
|||
- Package.swift
|
||||
identifier_name:
|
||||
excluded:
|
||||
- id
|
||||
- to
|
||||
- p1
|
||||
- p2
|
||||
|
|
|
@ -8,16 +8,16 @@ struct APDUCommand {
|
|||
let p2: UInt8
|
||||
let data: [UInt8]
|
||||
let needsLE: Bool
|
||||
|
||||
|
||||
init(cla: UInt8, ins: UInt8, p1: UInt8, p2: UInt8, data: [UInt8] = [], needsLE: Bool = false) {
|
||||
self.cla = cla;
|
||||
self.ins = ins;
|
||||
self.p1 = p1;
|
||||
self.p2 = p2;
|
||||
self.data = data;
|
||||
self.needsLE = needsLE;
|
||||
self.cla = cla
|
||||
self.ins = ins
|
||||
self.p1 = p1
|
||||
self.p2 = p2
|
||||
self.data = data
|
||||
self.needsLE = needsLE
|
||||
}
|
||||
|
||||
|
||||
func serialize() -> [UInt8] {
|
||||
let header = [cla, ins, p1, p2, UInt8(data.count)]
|
||||
let footer = needsLE ? [UInt8(0)] : []
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
* ISO7816-4 R-APDU.
|
||||
*/
|
||||
struct APDUResponse {
|
||||
let data : [UInt8]
|
||||
let sw1 : UInt8
|
||||
let sw2 : UInt8
|
||||
|
||||
var sw : UInt16 {
|
||||
let data: [UInt8]
|
||||
let sw1: UInt8
|
||||
let sw2: UInt8
|
||||
|
||||
var sw: UInt16 {
|
||||
get {
|
||||
(UInt16(self.sw1) << 8) | UInt16(self.sw2)
|
||||
return (UInt16(self.sw1) << 8) | UInt16(self.sw2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init(rawData: [UInt8]) {
|
||||
precondition(rawData.count >= 2, "rawData must contain at least the Status Word (2 bytes)")
|
||||
self.sw1 = rawData[rawData.count - 2]
|
||||
self.sw2 = rawData[rawData.count - 1]
|
||||
self.data = rawData.count > 2 ? Array(rawData[0...(rawData.count - 3)]) : []
|
||||
}
|
||||
|
||||
|
||||
func checkOK() throws -> APDUResponse {
|
||||
try checkSW(StatusWord.ok)
|
||||
}
|
||||
|
||||
|
||||
func checkAuthOK() throws -> APDUResponse {
|
||||
if (self.sw & StatusWord.wrongPINMask.rawValue) == StatusWord.wrongPINMask.rawValue {
|
||||
throw CardError.wrongPIN(retryCounter: Int(self.sw2 & 0x0F))
|
||||
|
@ -30,22 +30,22 @@ struct APDUResponse {
|
|||
return try checkOK()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func checkSW(_ codes: StatusWord...) throws -> APDUResponse {
|
||||
try checkSW(codes: codes.map({$0.rawValue}))
|
||||
try checkSW(codes: codes.map({ $0.rawValue }))
|
||||
}
|
||||
|
||||
|
||||
func checkSW(_ codes: UInt16...) throws -> APDUResponse {
|
||||
try checkSW(codes: codes)
|
||||
}
|
||||
|
||||
|
||||
func checkSW(codes: [UInt16]) throws -> APDUResponse {
|
||||
for code in codes {
|
||||
if (self.sw == code) {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if let aSW = StatusWord(rawValue: self.sw) {
|
||||
throw aSW
|
||||
} else {
|
||||
|
|
|
@ -16,56 +16,73 @@ enum AppCapability: UInt8 {
|
|||
|
||||
struct ApplicationInfo {
|
||||
let instanceUID: [UInt8]
|
||||
let freePairingSlots : Int
|
||||
let appVersion : UInt16
|
||||
let freePairingSlots: Int
|
||||
let appVersion: UInt16
|
||||
let keyUID: [UInt8]
|
||||
let secureChannelPubKey: [UInt8]
|
||||
let initializedCard: Bool
|
||||
let capabilities: UInt8
|
||||
|
||||
|
||||
var appVersionString: String {
|
||||
return "\(appVersion >> 8).\(appVersion & 0xff)"
|
||||
}
|
||||
|
||||
var hasMasterKey: Bool {
|
||||
return keyUID.count > 0
|
||||
}
|
||||
|
||||
var hasSecureChannelCapability: Bool {
|
||||
return (capabilities & AppCapability.secureChannel.rawValue) != 0
|
||||
}
|
||||
|
||||
var hasKeyManagementCapability: Bool {
|
||||
return (capabilities & AppCapability.keyManagement.rawValue) != 0
|
||||
}
|
||||
|
||||
var hasCredentialsManagementCapability: Bool {
|
||||
return (capabilities & AppCapability.credentialsManagement.rawValue) != 0
|
||||
}
|
||||
|
||||
var hasNDEFCapability: Bool {
|
||||
return (capabilities & AppCapability.ndef.rawValue) != 0
|
||||
}
|
||||
|
||||
init(_ data: [UInt8]) throws {
|
||||
let tlv = TinyBERTLV(data)
|
||||
let topTag = try tlv.readTag()
|
||||
tlv.unreadLastTag()
|
||||
|
||||
|
||||
if (topTag == AppInfoTag.pubKey.rawValue) {
|
||||
secureChannelPubKey = try tlv.readPrimitive(tag: AppInfoTag.pubKey.rawValue)
|
||||
initializedCard = false
|
||||
|
||||
|
||||
if (secureChannelPubKey.count > 0) {
|
||||
capabilities = AppCapability.credentialsManagement.rawValue | AppCapability.secureChannel.rawValue
|
||||
} else {
|
||||
capabilities = AppCapability.credentialsManagement.rawValue
|
||||
}
|
||||
|
||||
|
||||
instanceUID = []
|
||||
freePairingSlots = 0
|
||||
appVersion = 0
|
||||
keyUID = []
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
_ = try tlv.enterConstructed(tag: AppInfoTag.template.rawValue)
|
||||
instanceUID = try tlv.readPrimitive(tag: AppInfoTag.uid.rawValue)
|
||||
secureChannelPubKey = try tlv.readPrimitive(tag: AppInfoTag.pubKey.rawValue)
|
||||
appVersion = try UInt16(tlv.readInt())
|
||||
freePairingSlots = try tlv.readInt()
|
||||
keyUID = try tlv.readPrimitive(tag: AppInfoTag.keyUID.rawValue)
|
||||
|
||||
|
||||
do {
|
||||
capabilities = try tlv.readPrimitive(tag: AppInfoTag.capabilities.rawValue)[0]
|
||||
} catch TLVError.endOfTLV {
|
||||
capabilities = AppCapability.all.rawValue
|
||||
}
|
||||
|
||||
|
||||
initializedCard = true
|
||||
}
|
||||
|
||||
var appVersionString: String { get { "\(appVersion >> 8).\(appVersion & 0xff)" } }
|
||||
var hasMasterKey: Bool { get { keyUID.count > 0 } }
|
||||
var hasSecureChannelCapability: Bool { get { (capabilities & AppCapability.secureChannel.rawValue) != 0 } }
|
||||
var hasKeyManagementCapability: Bool { get { (capabilities & AppCapability.keyManagement.rawValue) != 0 } }
|
||||
var hasCredentialsManagementCapability: Bool { get { (capabilities & AppCapability.credentialsManagement.rawValue) != 0 } }
|
||||
var hasNDEFCapability: Bool { get { (capabilities & AppCapability.ndef.rawValue) != 0 } }
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ protocol CardChannel {
|
|||
|
||||
extension CardChannel {
|
||||
var pairingPasswordPBKDF2IterationCount: Int {
|
||||
get {
|
||||
return 50000;
|
||||
}
|
||||
return 50000;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
enum CardError : Error {
|
||||
enum CardError: Error {
|
||||
case wrongPIN(retryCounter: Int)
|
||||
}
|
||||
|
|
|
@ -91,15 +91,13 @@ enum Identifier: String {
|
|||
case ndefInstanceAID = "D2760000850101"
|
||||
case keycardCashAID = "A000000804000103"
|
||||
case keycardCashInstanceAID = "A00000080400010301"
|
||||
|
||||
|
||||
var val: [UInt8] {
|
||||
return rawValue.hexToBytes
|
||||
}
|
||||
|
||||
static func getKeycardInstanceAID(instanceId: UInt8 = 1) -> [UInt8] {
|
||||
precondition(instanceId >= 1, "The instance index must be between 1 and 255")
|
||||
return keycardAID.val + [instanceId]
|
||||
}
|
||||
|
||||
var val: [UInt8] {
|
||||
get {
|
||||
self.rawValue.hexToBytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,25 +2,25 @@ class KeycardCommandSet {
|
|||
let cardChannel: CardChannel
|
||||
let secureChannel: SecureChannel
|
||||
var info: ApplicationInfo?
|
||||
|
||||
|
||||
init(cardChannel: CardChannel) {
|
||||
self.cardChannel = cardChannel
|
||||
self.secureChannel = SecureChannel()
|
||||
}
|
||||
|
||||
|
||||
func select(instanceIdx: UInt8 = 1) throws -> APDUResponse {
|
||||
let selectApplet: APDUCommand = APDUCommand(cla: 0x00, ins: 0xA4, p1: 0x04, p2: 0x00, data: Identifier.getKeycardInstanceAID(instanceId: instanceIdx))
|
||||
let resp: APDUResponse = try cardChannel.send(selectApplet)
|
||||
|
||||
|
||||
if resp.sw == StatusWord.ok.rawValue {
|
||||
info = try ApplicationInfo(resp.data)
|
||||
|
||||
|
||||
if (info!.hasSecureChannelCapability) {
|
||||
secureChannel.generateSecret(pubKey: info!.secureChannelPubKey)
|
||||
secureChannel.reset()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return resp
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
struct Pairing {
|
||||
let pairingKey: [UInt8]
|
||||
let pairingIndex: UInt8
|
||||
|
||||
|
||||
var bytes: [UInt8] {
|
||||
get {
|
||||
return [pairingIndex] + pairingKey
|
||||
}
|
||||
}
|
||||
|
||||
init(pairingKey: [UInt8], pairingIndex: UInt8) {
|
||||
self.pairingKey = pairingKey
|
||||
self.pairingIndex = pairingIndex
|
||||
}
|
||||
|
||||
|
||||
init(pairingData: [UInt8]) {
|
||||
self.pairingIndex = pairingData[0]
|
||||
self.pairingKey = Array(pairingData[1...(pairingData.count - 1)])
|
||||
}
|
||||
|
||||
var bytes: [UInt8] {
|
||||
get {
|
||||
[pairingIndex] + pairingKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
class SecureChannel {
|
||||
func generateSecret(pubKey: [UInt8]) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
func reset() {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,17 @@ enum TLVError: Error {
|
|||
class TinyBERTLV {
|
||||
let buf: [UInt8]
|
||||
var pos: Int
|
||||
|
||||
|
||||
init(_ buf: [UInt8]) {
|
||||
self.buf = buf
|
||||
self.pos = 0
|
||||
}
|
||||
|
||||
|
||||
func enterConstructed(tag: UInt8) throws -> Int {
|
||||
try checkTag(expected: tag, actual: readTag())
|
||||
return readLength()
|
||||
}
|
||||
|
||||
|
||||
func readPrimitive(tag: UInt8) throws -> [UInt8] {
|
||||
try checkTag(expected: tag, actual: readTag())
|
||||
let len = readLength()
|
||||
|
@ -34,7 +34,7 @@ class TinyBERTLV {
|
|||
let val = try readPrimitive(tag: TLVTag.bool.rawValue)
|
||||
return val[0] == 0xff
|
||||
}
|
||||
|
||||
|
||||
func readInt() throws -> Int {
|
||||
let val = try readPrimitive(tag: TLVTag.int.rawValue)
|
||||
switch val.count {
|
||||
|
@ -45,24 +45,24 @@ class TinyBERTLV {
|
|||
case 3:
|
||||
return (Int(val[0]) << 16) | (Int(val[1] << 8)) | Int(val[2])
|
||||
case 4:
|
||||
return (Int(val[0]) << 24) | (Int(val[1] << 16)) | (Int(val[2] << 8)) | Int(val[3])
|
||||
return (Int(val[0]) << 24) | (Int(val[1] << 16)) | (Int(val[2] << 8)) | Int(val[3])
|
||||
default:
|
||||
throw TLVError.unexpectedLength(length: val.count)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func readLength() -> Int {
|
||||
var len = Int(buf[pos])
|
||||
pos += 1
|
||||
|
||||
|
||||
if (len == 0x81) {
|
||||
len = Int(buf[pos])
|
||||
pos += 1
|
||||
}
|
||||
|
||||
|
||||
return len
|
||||
}
|
||||
|
||||
|
||||
func readTag() throws -> UInt8 {
|
||||
if (pos < buf.count) {
|
||||
let ret = buf[pos]
|
||||
|
@ -72,13 +72,13 @@ class TinyBERTLV {
|
|||
throw TLVError.endOfTLV
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func unreadLastTag() {
|
||||
if (pos < buf.count) {
|
||||
pos -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func checkTag(expected: UInt8, actual: UInt8) throws {
|
||||
if (expected != actual) {
|
||||
unreadLastTag()
|
||||
|
|
|
@ -3,12 +3,14 @@ extension Collection where Element == Character {
|
|||
var last = first
|
||||
return dropFirst().compactMap {
|
||||
guard
|
||||
let lastHexDigitValue = last?.hexDigitValue,
|
||||
let hexDigitValue = $0.hexDigitValue else {
|
||||
last = $0
|
||||
return nil
|
||||
let lastHexDigitValue = last?.hexDigitValue,
|
||||
let hexDigitValue = $0.hexDigitValue else {
|
||||
last = $0
|
||||
return nil
|
||||
}
|
||||
defer {
|
||||
last = nil
|
||||
}
|
||||
defer { last = nil }
|
||||
return UInt8(lastHexDigitValue * 16 + hexDigitValue)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue