similar refactor for responses

This commit is contained in:
blinkasdf 2017-02-07 17:25:44 -07:00
Родитель cd25a91f00
Коммит 4e183bfb94
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
16 изменённых файлов: 439 добавлений и 395 удалений

Просмотреть файл

@ -50,13 +50,21 @@ public struct AuthenticationRequest: RawConvertible {
self.header = CommandHeader(ins: .Authenticate, p1: control.rawValue, dataLength: body.count) self.header = CommandHeader(ins: .Authenticate, p1: control.rawValue, dataLength: body.count)
self.trailer = CommandTrailer(noBody: false) self.trailer = CommandTrailer(noBody: false)
} }
}
extension AuthenticationRequest: Command {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
func validateBody() throws { func validateBody() throws {
// Make sure it's at least long enough to have key-handle length. // Make sure it's at least long enough to have key-handle length.
if body.count < U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 { if body.count < U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 {
throw ResponseStatus.WrongLength throw ResponseStatus.WrongLength
} }
if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 + keyHandleLength { if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 + keyHandleLength {
throw ResponseStatus.WrongLength throw ResponseStatus.WrongLength
} }
@ -66,11 +74,3 @@ public struct AuthenticationRequest: RawConvertible {
} }
} }
} }
extension AuthenticationRequest: CommandProtocol {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
}

Просмотреть файл

@ -8,52 +8,55 @@
import Foundation import Foundation
public struct AuthenticationResponse: MessageProtocol { public struct AuthenticationResponse: RawConvertible {
public let userPresence: UInt8 let body: Data
public let counter: UInt32 let trailer: ResponseStatus
public let signature: Data
public let status: ResponseStatus public var userPresence: UInt8 {
return body[0]
}
public var raw: Data { public var counter: UInt32 {
let lowerBound = MemoryLayout<UInt8>.size
let upperBound = lowerBound + MemoryLayout<UInt32>.size
let data = body.subdata(in: lowerBound..<upperBound)
return data.withUnsafeBytes { (ptr: UnsafePointer<UInt32>) -> UInt32 in
return ptr.pointee.bigEndian
}
}
public var signature: Data {
let lowerBound = MemoryLayout<UInt8>.size + MemoryLayout<UInt32>.size
let upperBound = body.count
return body.subdata(in: lowerBound..<upperBound)
}
public init(userPresence: UInt8, counter: UInt32, signature: Data) {
let writer = DataWriter() let writer = DataWriter()
writer.write(userPresence) writer.write(userPresence)
writer.write(counter) writer.write(counter)
writer.writeData(signature) writer.writeData(signature)
writer.write(status)
body = writer.buffer
return writer.buffer trailer = .NoError
} }
}
public init(raw: Data) throws {
let reader = DataReader(data: raw) extension AuthenticationResponse: Response {
init(body: Data, trailer: ResponseStatus) {
do { self.body = body
userPresence = try reader.read() self.trailer = trailer
counter = try reader.read() }
signature = try reader.readData(reader.remaining - 2)
status = try reader.read() func validateBody() throws {
} catch DataReaderError.End { // TODO: minimum signature size?
throw ResponseStatus.WrongLength if body.count < MemoryLayout<UInt8>.size + MemoryLayout<UInt32>.size + 1 {
} throw ResponseError.BadSize
}
if reader.remaining > 0 {
throw ResponseStatus.WrongLength if trailer != .NoError {
} throw ResponseError.BadStatus
} }
public init(userPresence u: UInt8, counter c: UInt32, signature s: Data) {
userPresence = u
counter = c
signature = s
status = .NoError
}
public func debug() {
print("AuthenticationResponse:")
print(String(format: " User presence: 0x%02x", userPresence))
print(String(format: " Counter: 0x%08x", counter))
print( " Signature: \(signature.base64EncodedString())")
print( " Status: \(status)")
} }
} }

Просмотреть файл

@ -1,5 +1,5 @@
// //
// CommandProtocol.swift // Command.swift
// SoftU2FTool // SoftU2FTool
// //
// Created by Benjamin P Toews on 2/7/17. // Created by Benjamin P Toews on 2/7/17.
@ -14,7 +14,7 @@ public func commandType(raw: Data) throws -> CommandCode {
return header.ins return header.ins
} }
protocol CommandProtocol { protocol Command {
var header: CommandHeader { get } var header: CommandHeader { get }
var body: Data { get } var body: Data { get }
var trailer: CommandTrailer { get } var trailer: CommandTrailer { get }
@ -25,7 +25,7 @@ protocol CommandProtocol {
} }
// Implement RawConvertible // Implement RawConvertible
extension CommandProtocol { extension Command {
public var raw: Data { public var raw: Data {
let writer = DataWriter() let writer = DataWriter()
writer.writeData(header.raw) writer.writeData(header.raw)

Просмотреть файл

@ -16,20 +16,6 @@ let U2F_EC_POINT_SIZE = ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
let MaxResponseSize = Int(UInt16.max) + 1 let MaxResponseSize = Int(UInt16.max) + 1
// ISO7816-4
public enum ResponseStatus: UInt16, EndianEnumProtocol, Error {
public typealias RawValue = UInt16
case NoError = 0x9000
case WrongData = 0x6A80
case ConditionsNotSatisfied = 0x6985
case CommandNotAllowed = 0x6986
case InsNotSupported = 0x6D00
case WrongLength = 0x6700
case ClassNotSupported = 0x6E00
case OtherError = 0x6F00 // "No precise diagnosis"
}
public enum CommandClass: UInt8 { public enum CommandClass: UInt8 {
case Reserved = 0x00 case Reserved = 0x00
} }
@ -49,3 +35,17 @@ public enum Control: UInt8 {
// Used internally. // Used internally.
case Invalid = 0xFF case Invalid = 0xFF
} }
// ISO7816-4
public enum ResponseStatus: UInt16, EndianEnumProtocol, Error {
public typealias RawValue = UInt16
case NoError = 0x9000
case WrongData = 0x6A80
case ConditionsNotSatisfied = 0x6985
case CommandNotAllowed = 0x6986
case InsNotSupported = 0x6D00
case WrongLength = 0x6700
case ClassNotSupported = 0x6E00
case OtherError = 0x6F00 // "No precise diagnosis"
}

Просмотреть файл

@ -8,32 +8,25 @@
import Foundation import Foundation
public struct ErrorResponse: MessageProtocol { public struct ErrorResponse: RawConvertible {
public let status: ResponseStatus let body: Data
let trailer: ResponseStatus
public var raw: Data {
let writer = DataWriter()
writer.write(status)
return writer.buffer
}
public init(status s: ResponseStatus) { public init(status s: ResponseStatus) {
status = s body = Data()
} trailer = s
}
public init(raw: Data) throws { }
let reader = DataReader(data: raw)
status = try reader.read() extension ErrorResponse: Response {
init(body: Data, trailer: ResponseStatus) {
if reader.remaining > 0 { self.body = body
throw ResponseStatus.WrongLength self.trailer = trailer
} }
}
func validateBody() throws {
public func debug() { if body.count != 0 {
print("Error Response:") throw ResponseError.BadSize
print(" Status: \(status)") }
} }
} }

Просмотреть файл

@ -1,16 +0,0 @@
//
// APDUMessage.swift
// SecurityKeyBLE
//
// Created by Benjamin P Toews on 9/12/16.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
public protocol MessageProtocol {
var raw: Data { get }
init(raw: Data) throws
func debug()
}

Просмотреть файл

@ -34,6 +34,14 @@ public struct RegisterRequest: RawConvertible {
self.header = CommandHeader(ins: .Register, dataLength: body.count) self.header = CommandHeader(ins: .Register, dataLength: body.count)
self.trailer = CommandTrailer(noBody: false) self.trailer = CommandTrailer(noBody: false)
} }
}
extension RegisterRequest: Command {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
func validateBody() throws { func validateBody() throws {
if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE { if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE {
@ -41,11 +49,3 @@ public struct RegisterRequest: RawConvertible {
} }
} }
} }
extension RegisterRequest: CommandProtocol {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
}

Просмотреть файл

@ -9,81 +9,120 @@
import Foundation import Foundation
import SelfSignedCertificate import SelfSignedCertificate
public struct RegisterResponse: MessageProtocol { public struct RegisterResponse: RawConvertible {
// Parse a DER formatted X509 certificate from the beginning of a datum and return its length. let body: Data
static func certLength(fromData d: Data) throws -> Int { let trailer: ResponseStatus
var size: Int = 0
if SelfSignedCertificate.parseX509(d, consumed: &size) { public var publicKey: Data {
return size return body.subdata(in: publicKeyRange)
} else { }
throw ResponseStatus.OtherError
} var keyHandleLength: Int {
return Int(body.subdata(in: keyHandleLengthRange)[0])
} }
public let publicKey: Data public var keyHandle: Data {
public let keyHandle: Data return body.subdata(in: keyHandleRange)
public let certificate: Data }
public let signature: Data
public let status: ResponseStatus public var certificate: Data {
return body.subdata(in: certificateRange)
}
public var raw: Data { public var signature: Data {
return body.subdata(in: signatureRange)
}
var publicKeyRange: Range<Int> {
let lowerBound = 0
let upperBound = lowerBound + U2F_EC_POINT_SIZE
return lowerBound..<upperBound
}
var keyHandleLengthRange: Range<Int> {
let lowerBound = publicKeyRange.upperBound
let upperBound = lowerBound + MemoryLayout<UInt8>.size
return lowerBound..<upperBound
}
var keyHandleRange: Range<Int> {
let lowerBound = keyHandleLengthRange.upperBound
let upperBound = lowerBound + keyHandleLength
return lowerBound..<upperBound
}
var certificateSize: Int {
let remainingRange: Range<Int> = keyHandleRange.upperBound..<body.count
let remaining = body.subdata(in: remainingRange)
var size: Int = 0
if SelfSignedCertificate.parseX509(remaining, consumed: &size) {
return size
} else {
return 0
}
}
var certificateRange: Range<Int> {
let lowerBound = keyHandleRange.upperBound
let upperBound = lowerBound + certificateSize
return lowerBound..<upperBound
}
var signatureRange: Range<Int> {
let lowerBound = certificateRange.upperBound
let upperBound = body.count
return lowerBound..<upperBound
}
public init(publicKey: Data, keyHandle: Data, certificate: Data, signature: Data) {
let writer = DataWriter() let writer = DataWriter()
writer.write(UInt8(0x05))
writer.writeData(publicKey) writer.writeData(publicKey)
writer.write(UInt8(keyHandle.count)) writer.write(UInt8(keyHandle.count))
writer.writeData(keyHandle) writer.writeData(keyHandle)
writer.writeData(certificate) writer.writeData(certificate)
writer.writeData(signature) writer.writeData(signature)
writer.write(status)
return writer.buffer body = writer.buffer
} trailer = .NoError
}
public init(raw: Data) throws { }
let reader = DataReader(data: raw)
extension RegisterResponse: Response {
do { init(body: Data, trailer: ResponseStatus) {
// reserved byte self.body = body
let _: UInt8 = try reader.read() self.trailer = trailer
}
publicKey = try reader.readData(U2F_EC_POINT_SIZE)
func validateBody() throws {
let khLen: UInt8 = try reader.read() // Check that we at least have key-handle length.
keyHandle = try reader.readData(Int(khLen)) var min = U2F_EC_POINT_SIZE + MemoryLayout<UInt8>.size
if body.count < min {
// peek at cert to figure out its length throw ResponseError.BadSize
let certLen = try RegisterResponse.certLength(fromData: reader.rest) }
certificate = try reader.readData(certLen)
signature = try reader.readData(reader.remaining - 2) // Check that we at least have one byte of cert.
// TODO: minimum cert size?
status = try reader.read() min += keyHandleLength + 1
} catch DataReaderError.End { if body.count < min {
throw ResponseStatus.WrongLength throw ResponseError.BadSize
} }
if reader.remaining > 0 { // Check that cert is parsable.
throw ResponseStatus.WrongLength if certificateSize == 0 {
} throw ResponseError.BadCertificate
} }
public init(publicKey pk: Data, keyHandle kh: Data, certificate cert: Data, signature sig: Data) { // Check that we at least have one byte of signature.
publicKey = pk // TODO: minimum signature size?
keyHandle = kh min += certificateSize + 1
certificate = cert if body.count < min {
signature = sig throw ResponseError.BadSize
status = .NoError }
}
if trailer != .NoError {
public func debug() { throw ResponseError.BadStatus
print("Registration Response:") }
print( " Reserved: 0x05")
print( " Public key: \(publicKey.base64EncodedString())")
print(String(format: " KH Len: 0x%02x", keyHandle.count))
print( " Key Handle: \(keyHandle.base64EncodedString())")
print( " Certificate: \(certificate.base64EncodedString())")
print( " Signature: \(signature.base64EncodedString())")
print( " Status: \(status)")
} }
} }

52
APDU/Response.swift Normal file
Просмотреть файл

@ -0,0 +1,52 @@
//
// Response.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/7/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
enum ResponseError: Error {
case BadSize
case BadStatus
case BadCertificate
}
protocol Response {
var body: Data { get }
var trailer: ResponseStatus { get }
init(body: Data, trailer: ResponseStatus)
func validateBody() throws
}
// Implement RawConvertible
extension Response {
public var raw: Data {
let writer = DataWriter()
writer.writeData(body)
writer.write(trailer)
return writer.buffer
}
public init(raw: Data) throws {
let reader = DataReader(data: raw)
let body = try reader.readData(reader.remaining - 2)
let trailer: ResponseStatus = try reader.read()
self.init(body: body, trailer: trailer)
}
// For testing with libu2f-host
public init(raw: Data, bodyOnly: Bool) throws {
if bodyOnly {
self.init(body: raw, trailer: .NoError)
} else {
try self.init(raw: raw)
}
}
}

Просмотреть файл

@ -13,12 +13,6 @@ public struct VersionRequest: RawConvertible {
let body: Data let body: Data
let trailer: CommandTrailer let trailer: CommandTrailer
func validateBody() throws {
if body.count > 0 {
throw ResponseStatus.WrongLength
}
}
init() { init() {
self.header = CommandHeader(ins: .Version, dataLength: 0) self.header = CommandHeader(ins: .Version, dataLength: 0)
self.body = Data() self.body = Data()
@ -26,10 +20,16 @@ public struct VersionRequest: RawConvertible {
} }
} }
extension VersionRequest: CommandProtocol { extension VersionRequest: Command {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) { init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header self.header = header
self.body = body self.body = body
self.trailer = trailer self.trailer = trailer
} }
func validateBody() throws {
if body.count > 0 {
throw ResponseStatus.WrongLength
}
}
} }

Просмотреть файл

@ -8,44 +8,33 @@
import Foundation import Foundation
public struct VersionResponse: MessageProtocol { public struct VersionResponse: RawConvertible {
public let version: String let body: Data
public let status: ResponseStatus let trailer: ResponseStatus
public var raw: Data { public var version: String {
let writer = DataWriter() return String(data: body, encoding: .utf8) ?? ""
writer.writeData(version.data(using: .utf8)!)
writer.write(status)
return writer.buffer
} }
public init(version v: String) { public init(version: String) {
version = v body = version.data(using: .utf8)!
status = .NoError trailer = .NoError
} }
}
public init(raw: Data) throws {
let reader = DataReader(data: raw) extension VersionResponse: Response {
init(body: Data, trailer: ResponseStatus) {
let vData = try reader.readData(reader.remaining - 2) self.body = body
if let v = String(data: vData, encoding: .utf8) { self.trailer = trailer
version = v }
} else {
throw ResponseStatus.WrongLength func validateBody() throws {
} if version.lengthOfBytes(using: .utf8) < 1 {
throw ResponseError.BadSize
status = try reader.read() }
if reader.remaining > 0 { if trailer != .NoError {
throw ResponseStatus.WrongLength throw ResponseError.BadStatus
} }
}
public func debug() {
print("Version Response:")
print(" Version: \(version)")
print(" Status: \(status)")
} }
} }

Просмотреть файл

@ -23,7 +23,7 @@ class ResponseTests: XCTestCase {
XCTAssertEqual(r2.keyHandle, r.keyHandle) XCTAssertEqual(r2.keyHandle, r.keyHandle)
XCTAssertEqual(r2.certificate, r.certificate) XCTAssertEqual(r2.certificate, r.certificate)
XCTAssertEqual(r2.signature, r.signature) XCTAssertEqual(r2.signature, r.signature)
XCTAssertEqual(r2.status, r.status) XCTAssertEqual(r2.trailer, r.trailer)
XCTAssertEqual(r.raw, r2.raw) XCTAssertEqual(r.raw, r2.raw)
} }
@ -39,7 +39,7 @@ class ResponseTests: XCTestCase {
let r2 = try VersionResponse(raw: r.raw) let r2 = try VersionResponse(raw: r.raw)
XCTAssertEqual(r.version, r2.version) XCTAssertEqual(r.version, r2.version)
XCTAssertEqual(r.status, r2.status) XCTAssertEqual(r.trailer, r2.trailer)
XCTAssertEqual(r.raw, r2.raw) XCTAssertEqual(r.raw, r2.raw)
} }
@ -47,7 +47,7 @@ class ResponseTests: XCTestCase {
let r = ErrorResponse(status: .ConditionsNotSatisfied) let r = ErrorResponse(status: .ConditionsNotSatisfied)
let r2 = try ErrorResponse(raw: r.raw) let r2 = try ErrorResponse(raw: r.raw)
XCTAssertEqual(r.status, r2.status) XCTAssertEqual(r.trailer, r2.trailer)
XCTAssertEqual(r.raw, r2.raw) XCTAssertEqual(r.raw, r2.raw)
} }
} }

Просмотреть файл

@ -41,7 +41,6 @@
F738F5171E4A2CF6005680A2 /* VersionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */; }; F738F5171E4A2CF6005680A2 /* VersionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */; };
F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; }; F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; };
F738F5211E4A2DDD005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; }; F738F5211E4A2DDD005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; };
F738F5221E4A2DDD005680A2 /* MessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */; };
F738F5281E4A2E57005680A2 /* DataReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5251E4A2E57005680A2 /* DataReader.swift */; }; F738F5281E4A2E57005680A2 /* DataReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5251E4A2E57005680A2 /* DataReader.swift */; };
F738F5291E4A2E57005680A2 /* DataWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5261E4A2E57005680A2 /* DataWriter.swift */; }; F738F5291E4A2E57005680A2 /* DataWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5261E4A2E57005680A2 /* DataWriter.swift */; };
F738F52A1E4A2E57005680A2 /* Endian.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5271E4A2E57005680A2 /* Endian.swift */; }; F738F52A1E4A2E57005680A2 /* Endian.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5271E4A2E57005680A2 /* Endian.swift */; };
@ -51,7 +50,6 @@
F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53D1E4A2ED6005680A2 /* ResponseTests.swift */; }; F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53D1E4A2ED6005680A2 /* ResponseTests.swift */; };
F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; }; F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; };
F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; }; F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; };
F738F5451E4A2F91005680A2 /* MessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */; };
F738F5481E4A2F91005680A2 /* AuthenticationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */; }; F738F5481E4A2F91005680A2 /* AuthenticationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */; };
F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */; }; F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */; };
F738F54A1E4A2F91005680A2 /* ErrorResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */; }; F738F54A1E4A2F91005680A2 /* ErrorResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */; };
@ -77,15 +75,17 @@
F738F5871E4A3C09005680A2 /* DataReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5851E4A3C09005680A2 /* DataReaderTests.swift */; }; F738F5871E4A3C09005680A2 /* DataReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5851E4A3C09005680A2 /* DataReaderTests.swift */; };
F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5861E4A3C09005680A2 /* DataWriterTests.swift */; }; F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5861E4A3C09005680A2 /* DataWriterTests.swift */; };
F738F58A1E4A3C21005680A2 /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5891E4A3C21005680A2 /* TestUtil.swift */; }; F738F58A1E4A3C21005680A2 /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5891E4A3C21005680A2 /* TestUtil.swift */; };
F7B5DBAD1E4A5CED00E5ABD4 /* CommandProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */; }; F7B5DBAD1E4A5CED00E5ABD4 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAC1E4A5CED00E5ABD4 /* Command.swift */; };
F7B5DBAF1E4A815700E5ABD4 /* RawConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */; }; F7B5DBAF1E4A815700E5ABD4 /* RawConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */; };
F7B5DBB01E4A827000E5ABD4 /* RawConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */; }; F7B5DBB01E4A827000E5ABD4 /* RawConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */; };
F7B5DBB11E4A827400E5ABD4 /* CommandProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */; }; F7B5DBB11E4A827400E5ABD4 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAC1E4A5CED00E5ABD4 /* Command.swift */; };
F7B5DBB31E4A82EB00E5ABD4 /* MessagePart.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */; }; F7B5DBB31E4A82EB00E5ABD4 /* MessagePart.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */; };
F7B5DBB41E4A83D900E5ABD4 /* MessagePart.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */; }; F7B5DBB41E4A83D900E5ABD4 /* MessagePart.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */; };
F7B5DBC11E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBD1E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift */; }; F7B5DBC11E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBD1E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift */; };
F7B5DBC21E4A85EB00E5ABD4 /* RegisterRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */; }; F7B5DBC21E4A85EB00E5ABD4 /* RegisterRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */; };
F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */; }; F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */; };
F7B5DBC91E4A8CF000E5ABD4 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBC81E4A8CF000E5ABD4 /* Response.swift */; };
F7B5DBCA1E4A8CF000E5ABD4 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBC81E4A8CF000E5ABD4 /* Response.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -226,7 +226,6 @@
F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionResponse.swift; sourceTree = "<group>"; }; F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionResponse.swift; sourceTree = "<group>"; };
F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandHeader.swift; sourceTree = "<group>"; }; F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandHeader.swift; sourceTree = "<group>"; };
F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTrailer.swift; sourceTree = "<group>"; }; F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTrailer.swift; sourceTree = "<group>"; };
F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageProtocol.swift; sourceTree = "<group>"; };
F738F5251E4A2E57005680A2 /* DataReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataReader.swift; path = Data/DataReader.swift; sourceTree = "<group>"; }; F738F5251E4A2E57005680A2 /* DataReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataReader.swift; path = Data/DataReader.swift; sourceTree = "<group>"; };
F738F5261E4A2E57005680A2 /* DataWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataWriter.swift; path = Data/DataWriter.swift; sourceTree = "<group>"; }; F738F5261E4A2E57005680A2 /* DataWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataWriter.swift; path = Data/DataWriter.swift; sourceTree = "<group>"; };
F738F5271E4A2E57005680A2 /* Endian.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Endian.swift; path = Data/Endian.swift; sourceTree = "<group>"; }; F738F5271E4A2E57005680A2 /* Endian.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Endian.swift; path = Data/Endian.swift; sourceTree = "<group>"; };
@ -248,12 +247,13 @@
F738F5851E4A3C09005680A2 /* DataReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataReaderTests.swift; path = DataTests/DataReaderTests.swift; sourceTree = "<group>"; }; F738F5851E4A3C09005680A2 /* DataReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataReaderTests.swift; path = DataTests/DataReaderTests.swift; sourceTree = "<group>"; };
F738F5861E4A3C09005680A2 /* DataWriterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataWriterTests.swift; path = DataTests/DataWriterTests.swift; sourceTree = "<group>"; }; F738F5861E4A3C09005680A2 /* DataWriterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataWriterTests.swift; path = DataTests/DataWriterTests.swift; sourceTree = "<group>"; };
F738F5891E4A3C21005680A2 /* TestUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtil.swift; sourceTree = "<group>"; }; F738F5891E4A3C21005680A2 /* TestUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtil.swift; sourceTree = "<group>"; };
F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandProtocol.swift; sourceTree = "<group>"; }; F7B5DBAC1E4A5CED00E5ABD4 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawConvertible.swift; sourceTree = "<group>"; }; F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawConvertible.swift; sourceTree = "<group>"; };
F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePart.swift; sourceTree = "<group>"; }; F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePart.swift; sourceTree = "<group>"; };
F7B5DBBD1E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationRequestTests.swift; sourceTree = "<group>"; }; F7B5DBBD1E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationRequestTests.swift; sourceTree = "<group>"; };
F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegisterRequestTests.swift; sourceTree = "<group>"; }; F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegisterRequestTests.swift; sourceTree = "<group>"; };
F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionRequestTests.swift; sourceTree = "<group>"; }; F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionRequestTests.swift; sourceTree = "<group>"; };
F7B5DBC81E4A8CF000E5ABD4 /* Response.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -404,17 +404,17 @@
F738F5521E4A2FF0005680A2 /* Constants.swift */, F738F5521E4A2FF0005680A2 /* Constants.swift */,
F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */, F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */,
F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */, F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */,
F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */, F7B5DBAC1E4A5CED00E5ABD4 /* Command.swift */,
F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */, F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */,
F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */, F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */,
F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */, F7B5DBC81E4A8CF000E5ABD4 /* Response.swift */,
F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */, F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */,
F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */, F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */,
F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */,
F738F5071E4A2CF6005680A2 /* RegisterRequest.swift */, F738F5071E4A2CF6005680A2 /* RegisterRequest.swift */,
F738F5081E4A2CF6005680A2 /* RegisterResponse.swift */, F738F5081E4A2CF6005680A2 /* RegisterResponse.swift */,
F738F5091E4A2CF6005680A2 /* VersionRequest.swift */, F738F5091E4A2CF6005680A2 /* VersionRequest.swift */,
F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */, F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */,
F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */,
F738F4F31E4A2CCC005680A2 /* APDU.h */, F738F4F31E4A2CCC005680A2 /* APDU.h */,
F738F4F41E4A2CCC005680A2 /* Info.plist */, F738F4F41E4A2CCC005680A2 /* Info.plist */,
); );
@ -808,8 +808,9 @@
files = ( files = (
F738F5281E4A2E57005680A2 /* DataReader.swift in Sources */, F738F5281E4A2E57005680A2 /* DataReader.swift in Sources */,
F738F5531E4A2FF0005680A2 /* Constants.swift in Sources */, F738F5531E4A2FF0005680A2 /* Constants.swift in Sources */,
F7B5DBAD1E4A5CED00E5ABD4 /* CommandProtocol.swift in Sources */, F7B5DBAD1E4A5CED00E5ABD4 /* Command.swift in Sources */,
F7B5DBB31E4A82EB00E5ABD4 /* MessagePart.swift in Sources */, F7B5DBB31E4A82EB00E5ABD4 /* MessagePart.swift in Sources */,
F7B5DBC91E4A8CF000E5ABD4 /* Response.swift in Sources */,
F738F5151E4A2CF6005680A2 /* RegisterResponse.swift in Sources */, F738F5151E4A2CF6005680A2 /* RegisterResponse.swift in Sources */,
F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */, F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */,
F738F5141E4A2CF6005680A2 /* RegisterRequest.swift in Sources */, F738F5141E4A2CF6005680A2 /* RegisterRequest.swift in Sources */,
@ -819,7 +820,6 @@
F738F5111E4A2CF6005680A2 /* AuthenticationRequest.swift in Sources */, F738F5111E4A2CF6005680A2 /* AuthenticationRequest.swift in Sources */,
F738F5291E4A2E57005680A2 /* DataWriter.swift in Sources */, F738F5291E4A2E57005680A2 /* DataWriter.swift in Sources */,
F738F5171E4A2CF6005680A2 /* VersionResponse.swift in Sources */, F738F5171E4A2CF6005680A2 /* VersionResponse.swift in Sources */,
F738F5221E4A2DDD005680A2 /* MessageProtocol.swift in Sources */,
F738F5131E4A2CF6005680A2 /* ErrorResponse.swift in Sources */, F738F5131E4A2CF6005680A2 /* ErrorResponse.swift in Sources */,
F738F5121E4A2CF6005680A2 /* AuthenticationResponse.swift in Sources */, F738F5121E4A2CF6005680A2 /* AuthenticationResponse.swift in Sources */,
F738F5161E4A2CF6005680A2 /* VersionRequest.swift in Sources */, F738F5161E4A2CF6005680A2 /* VersionRequest.swift in Sources */,
@ -839,14 +839,14 @@
F7B5DBB01E4A827000E5ABD4 /* RawConvertible.swift in Sources */, F7B5DBB01E4A827000E5ABD4 /* RawConvertible.swift in Sources */,
F7B5DBB41E4A83D900E5ABD4 /* MessagePart.swift in Sources */, F7B5DBB41E4A83D900E5ABD4 /* MessagePart.swift in Sources */,
F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */, F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */,
F7B5DBB11E4A827400E5ABD4 /* CommandProtocol.swift in Sources */, F7B5DBB11E4A827400E5ABD4 /* Command.swift in Sources */,
F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */, F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */,
F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */, F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */,
F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */, F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */,
F7B5DBCA1E4A8CF000E5ABD4 /* Response.swift in Sources */,
F738F5541E4A2FF0005680A2 /* Constants.swift in Sources */, F738F5541E4A2FF0005680A2 /* Constants.swift in Sources */,
F738F5401E4A2ED6005680A2 /* CommandTrailerTests.swift in Sources */, F738F5401E4A2ED6005680A2 /* CommandTrailerTests.swift in Sources */,
F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */, F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */,
F738F5451E4A2F91005680A2 /* MessageProtocol.swift in Sources */,
F738F5501E4A2F9E005680A2 /* DataWriter.swift in Sources */, F738F5501E4A2F9E005680A2 /* DataWriter.swift in Sources */,
F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */, F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */,
F738F5481E4A2F91005680A2 /* AuthenticationRequest.swift in Sources */, F738F5481E4A2F91005680A2 /* AuthenticationRequest.swift in Sources */,

Просмотреть файл

@ -46,45 +46,33 @@ class U2FAuthenticator {
func installMsgHandler() { func installMsgHandler() {
u2fhid.handle(.Msg) { (_ msg: softu2f_hid_message) -> Bool in u2fhid.handle(.Msg) { (_ msg: softu2f_hid_message) -> Bool in
let data = msg.data.takeUnretainedValue() as Data let data = msg.data.takeUnretainedValue() as Data
let cmd: APDU.Command
do { do {
cmd = try APDU.Command(raw: data) let ins = try APDU.commandType(raw: data)
switch ins {
case .Register:
try self.handleRegisterRequest(data, cid: msg.cid)
case .Authenticate:
try self.handleAuthenticationRequest(data, cid: msg.cid)
case .Version:
try self.handleVersionRequest(data, cid: msg.cid)
default:
self.sendError(status: .InsNotSupported, cid: msg.cid)
}
} catch let err as APDU.ResponseStatus { } catch let err as APDU.ResponseStatus {
self.sendError(status: err, cid: msg.cid) self.sendError(status: err, cid: msg.cid)
return true
} catch { } catch {
self.sendError(status: .OtherError, cid: msg.cid) self.sendError(status: .OtherError, cid: msg.cid)
return true
} }
print("↓↓↓↓↓ Received message ↓↓↓↓↓")
cmd.debug()
print("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑\n")
if let req = cmd.registerRequest {
self.handleRegisterRequest(req, cid: msg.cid)
return true
}
if let req = cmd.authenticationRequest {
if let control = APDU.Control(rawValue: cmd.header.p1) {
self.handleAuthenticationRequest(req, control: control, cid: msg.cid)
return true
}
}
if let req = cmd.versionRequest {
self.handleVersionRequest(req, cid: msg.cid)
return true
}
self.sendError(status: .OtherError, cid: msg.cid)
return true return true
} }
} }
func handleRegisterRequest(_ req: APDU.RegisterRequest, cid: UInt32) { func handleRegisterRequest(_ raw: Data, cid: UInt32) throws {
let req = try APDU.RegisterRequest(raw: raw)
let facet = KnownFacets[req.applicationParameter] let facet = KnownFacets[req.applicationParameter]
let notification = UserPresence.Notification.Register(facet: facet) let notification = UserPresence.Notification.Register(facet: facet)
@ -127,13 +115,15 @@ class U2FAuthenticator {
} }
} }
func handleAuthenticationRequest(_ req: APDU.AuthenticationRequest, control: APDU.Control, cid: UInt32) { func handleAuthenticationRequest(_ raw: Data, cid: UInt32) throws {
let req = try APDU.AuthenticationRequest(raw: raw)
guard let reg = U2FRegistration(keyHandle: req.keyHandle, applicationParameter: req.applicationParameter) else { guard let reg = U2FRegistration(keyHandle: req.keyHandle, applicationParameter: req.applicationParameter) else {
sendError(status: .WrongData, cid: cid) sendError(status: .WrongData, cid: cid)
return return
} }
if control == .CheckOnly { if req.control == .CheckOnly {
// success -> error response. It's weird... // success -> error response. It's weird...
sendError(status: .ConditionsNotSatisfied, cid: cid) sendError(status: .ConditionsNotSatisfied, cid: cid)
return return
@ -170,7 +160,8 @@ class U2FAuthenticator {
} }
} }
func handleVersionRequest(_ req: APDU.VersionRequest, cid: UInt32) { func handleVersionRequest(_ raw: Data, cid: UInt32) throws {
let _ = try APDU.VersionRequest(raw: raw)
let resp = APDU.VersionResponse(version: "U2F_V2") let resp = APDU.VersionResponse(version: "U2F_V2")
sendMsg(msg: resp, cid: cid) sendMsg(msg: resp, cid: cid)
} }
@ -180,14 +171,7 @@ class U2FAuthenticator {
sendMsg(msg: resp, cid: cid) sendMsg(msg: resp, cid: cid)
} }
func sendMsg(msg: APDU.MessageProtocol, cid: UInt32) { func sendMsg(msg: APDU.RawConvertible, cid: UInt32) {
if u2fhid.sendMsg(cid: cid, data: msg.raw) { let _ = u2fhid.sendMsg(cid: cid, data: msg.raw)
print("↓↓↓↓↓ Sent message ↓↓↓↓↓")
} else {
print("↓↓↓↓↓ Error sending message ↓↓↓↓↓")
}
msg.debug()
print("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑\n")
} }
} }

Просмотреть файл

@ -7,83 +7,84 @@
// //
import XCTest import XCTest
import APDU
@testable import SoftU2FTool @testable import SoftU2FTool
//class IntegrationTests: SoftU2FTestCase { class IntegrationTests: SoftU2FTestCase {
// override func tearDown() { override func tearDown() {
// let _ = U2FRegistration.deleteAll() let _ = U2FRegistration.deleteAll()
// } }
//
// func testRegister() throws { func testRegister() throws {
// var rc = u2fh_global_init(u2fh_initflags(rawValue: 0)) var rc = u2fh_global_init(u2fh_initflags(rawValue: 0))
//// var rc = u2fh_global_init(U2FH_DEBUG) // var rc = u2fh_global_init(U2FH_DEBUG)
// XCTAssertEqual(rc.name, U2FH_OK.name) XCTAssertEqual(rc.name, U2FH_OK.name)
// defer { u2fh_global_done() } defer { u2fh_global_done() }
//
//
// var devs: OpaquePointer? = nil var devs: OpaquePointer? = nil
// rc = u2fh_devs_init(&devs) rc = u2fh_devs_init(&devs)
// XCTAssertEqual(rc.name, U2FH_OK.name) XCTAssertEqual(rc.name, U2FH_OK.name)
// XCTAssertNotNil(devs) XCTAssertNotNil(devs)
// defer { u2fh_devs_done(devs) } defer { u2fh_devs_done(devs) }
//
// var maxIdx = UInt32(0xFFFFFFFF) var maxIdx = UInt32(0xFFFFFFFF)
// while u2fh_devs_discover(devs, &maxIdx) == U2FH_NO_U2F_DEVICE { while u2fh_devs_discover(devs, &maxIdx) == U2FH_NO_U2F_DEVICE {
// u2fh_devs_done(devs) u2fh_devs_done(devs)
// sleep(1) sleep(1)
//
// rc = u2fh_devs_init(&devs) rc = u2fh_devs_init(&devs)
// XCTAssertEqual(rc.name, U2FH_OK.name) XCTAssertEqual(rc.name, U2FH_OK.name)
// XCTAssertNotNil(devs) XCTAssertNotNil(devs)
// } }
//
// XCTAssertEqual(rc.name, U2FH_OK.name) XCTAssertEqual(rc.name, U2FH_OK.name)
// XCTAssertEqual(maxIdx, 0) XCTAssertEqual(maxIdx, 0)
//
// let appId = "https://github.com/u2f/trusted_facets" let appId = "https://github.com/u2f/trusted_facets"
// let challenge = "VA-qf-tVVQVuPmNI4U2_ShZNYgvaaHnMPp_EnL2dNWY" let challenge = "VA-qf-tVVQVuPmNI4U2_ShZNYgvaaHnMPp_EnL2dNWY"
// let challengeParamBytes = try JSONSerialization.data(withJSONObject: ["challenge": challenge, "version": "U2F_V2", "appId": appId]) let challengeParamBytes = try JSONSerialization.data(withJSONObject: ["challenge": challenge, "version": "U2F_V2", "appId": appId])
// let challengeParam = String(bytes: challengeParamBytes, encoding: .utf8)! let challengeParam = String(bytes: challengeParamBytes, encoding: .utf8)!
// var respPtr: UnsafeMutablePointer<Int8>? = nil var respPtr: UnsafeMutablePointer<Int8>? = nil
//
// rc = u2fh_register(devs, challengeParam, appId, &respPtr, U2FH_REQUEST_USER_PRESENCE) rc = u2fh_register(devs, challengeParam, appId, &respPtr, U2FH_REQUEST_USER_PRESENCE)
// XCTAssertEqual(rc.name, U2FH_OK.name) XCTAssertEqual(rc.name, U2FH_OK.name)
//
// if respPtr == nil { if respPtr == nil {
// XCTFail("Expected registration response") XCTFail("Expected registration response")
// return return
// } }
//
// let respStr = String(cString: respPtr!) let respStr = String(cString: respPtr!)
//
// guard let respData = respStr.data(using: .utf8) else { guard let respData = respStr.data(using: .utf8) else {
// XCTFail("Expected response to utf8 encoded") XCTFail("Expected response to utf8 encoded")
// return return
// } }
//
// let respJSON = try JSONSerialization.jsonObject(with: respData, options: JSONSerialization.ReadingOptions.init(rawValue: 0)) let respJSON = try JSONSerialization.jsonObject(with: respData, options: JSONSerialization.ReadingOptions.init(rawValue: 0))
//
// guard let respDict = respJSON as? [String: String] else { guard let respDict = respJSON as? [String: String] else {
// XCTFail("Expected response to be dictionary") XCTFail("Expected response to be dictionary")
// return return
// } }
//
// guard let regDataStr = respDict["registrationData"] else { guard let regDataStr = respDict["registrationData"] else {
// XCTFail("Expected response dictionary to include registrationData member") XCTFail("Expected response dictionary to include registrationData member")
// return return
// } }
//
// guard let regData = WebSafeBase64.decode(regDataStr) else { guard let regData = WebSafeBase64.decode(regDataStr) else {
// XCTFail("Expected response registrationData member to be b64 encoded") XCTFail("Expected response registrationData member to be b64 encoded")
// return return
// } }
//
// // TODO: this fails because we include the APDU trailer in the RegisterResponse.... // TODO: this fails because we include the APDU trailer in the RegisterResponse....
// let regResp = try RegisterResponse(raw: regData) let regResp = try APDU.RegisterResponse(raw: regData, bodyOnly: true)
//
// guard let _ = U2FRegistration(keyHandle: regResp.keyHandle, applicationParameter: randData()) else { guard let _ = U2FRegistration(keyHandle: regResp.keyHandle, applicationParameter: randData()) else {
// XCTFail("Expected key handle from response to match registration") XCTFail("Expected key handle from response to match registration")
// return return
// } }
// } }
//} }

Просмотреть файл

@ -10,39 +10,38 @@ import XCTest
@testable import SoftU2FTool @testable import SoftU2FTool
func tupleDigestEqual(_ a: SHA256.TupleDigest, _ b: SHA256.TupleDigest) -> Bool { func tupleDigestEqual(_ a: SHA256.TupleDigest, _ b: SHA256.TupleDigest) -> Bool {
return return a.0 == b.0 &&
a.0 == b.0 && a.1 == b.1 &&
a.1 == b.1 && a.2 == b.2 &&
a.2 == b.2 && a.3 == b.3 &&
a.3 == b.3 && a.4 == b.4 &&
a.4 == b.4 && a.5 == b.5 &&
a.5 == b.5 && a.6 == b.6 &&
a.6 == b.6 && a.7 == b.7 &&
a.7 == b.7 && a.8 == b.8 &&
a.8 == b.8 && a.9 == b.9 &&
a.9 == b.9 && a.10 == b.10 &&
a.10 == b.10 && a.11 == b.11 &&
a.11 == b.11 && a.12 == b.12 &&
a.12 == b.12 && a.13 == b.13 &&
a.13 == b.13 && a.14 == b.14 &&
a.14 == b.14 && a.15 == b.15 &&
a.15 == b.15 && a.16 == b.16 &&
a.16 == b.16 && a.17 == b.17 &&
a.17 == b.17 && a.18 == b.18 &&
a.18 == b.18 && a.19 == b.19 &&
a.19 == b.19 && a.20 == b.20 &&
a.20 == b.20 && a.21 == b.21 &&
a.21 == b.21 && a.22 == b.22 &&
a.22 == b.22 && a.23 == b.23 &&
a.23 == b.23 && a.24 == b.24 &&
a.24 == b.24 && a.25 == b.25 &&
a.25 == b.25 && a.26 == b.26 &&
a.26 == b.26 && a.27 == b.27 &&
a.27 == b.27 && a.28 == b.28 &&
a.28 == b.28 && a.29 == b.29 &&
a.29 == b.29 && a.30 == b.30 &&
a.30 == b.30 && a.31 == b.31
a.31 == b.31
} }
func randData(maxLen: Int = 4096) -> Data { func randData(maxLen: Int = 4096) -> Data {