This commit is contained in:
blinkasdf 2017-02-07 15:45:30 -07:00
Родитель 3bacda36a8
Коммит cd25a91f00
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
17 изменённых файлов: 414 добавлений и 269 удалений

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

@ -8,48 +8,69 @@
import Foundation
public struct AuthenticationRequest: CommandDataProtocol {
public static let cmdClass = CommandClass.Reserved
public static let cmdCode = CommandCode.Authenticate
public struct AuthenticationRequest: RawConvertible {
let header: CommandHeader
let body: Data
let trailer: CommandTrailer
public var control: Control {
return Control(rawValue: header.p1) ?? .Invalid
}
public let challengeParameter: Data
public let applicationParameter: Data
public let keyHandle: Data
public var challengeParameter: Data {
let lowerBound = 0
let upperBound = lowerBound + U2F_CHAL_SIZE
return body.subdata(in: lowerBound..<upperBound)
}
public var raw: Data {
public var applicationParameter: Data {
let lowerBound = U2F_CHAL_SIZE
let upperBound = lowerBound + U2F_APPID_SIZE
return body.subdata(in: lowerBound..<upperBound)
}
var keyHandleLength: Int {
return Int(body[U2F_CHAL_SIZE + U2F_APPID_SIZE])
}
public var keyHandle: Data {
let lowerBound = U2F_CHAL_SIZE + U2F_APPID_SIZE + 1
let upperBound = lowerBound + keyHandleLength
return body.subdata(in: lowerBound..<upperBound)
}
public init(challengeParameter: Data, applicationParameter: Data, keyHandle: Data, control: Control) {
let writer = DataWriter()
writer.writeData(challengeParameter)
writer.writeData(applicationParameter)
writer.write(UInt8(keyHandle.count))
writer.writeData(keyHandle)
return writer.buffer
self.body = writer.buffer
self.header = CommandHeader(ins: .Authenticate, p1: control.rawValue, dataLength: body.count)
self.trailer = CommandTrailer(noBody: false)
}
public init(challengeParameter cp: Data, applicationParameter ap: Data, keyHandle kh: Data) {
challengeParameter = cp
applicationParameter = ap
keyHandle = kh
}
public init(raw: Data) throws {
let reader = DataReader(data: raw)
do {
challengeParameter = try reader.readData(U2F_CHAL_SIZE)
applicationParameter = try reader.readData(U2F_APPID_SIZE)
let khLen: UInt8 = try reader.read()
keyHandle = try reader.readData(khLen)
} catch DataReaderError.End {
func validateBody() throws {
// Make sure it's at least long enough to have key-handle length.
if body.count < U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 {
throw ResponseStatus.WrongLength
}
}
public func debug() {
print("AuthenticationRequest:")
print(" Challenge parameter: \(challengeParameter.base64EncodedString())")
print(" Application parameter: \(applicationParameter.base64EncodedString())")
print(" Key handle: \(keyHandle.base64EncodedString())")
if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE + 1 + keyHandleLength {
throw ResponseStatus.WrongLength
}
if control == .Invalid {
throw ResponseStatus.OtherError
}
}
}
extension AuthenticationRequest: CommandProtocol {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
}

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

@ -1,64 +0,0 @@
//
// Command.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 9/11/16.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
let CommandTypes: [CommandDataProtocol.Type] = [
RegisterRequest.self,
AuthenticationRequest.self,
VersionRequest.self
]
public struct Command: MessageProtocol {
static func commandTypeForCode(_ code: CommandCode) -> CommandDataProtocol.Type? {
return CommandTypes.lazy.filter({ $0.cmdCode == code }).first
}
public let header: CommandHeader
let data: CommandDataProtocol
let trailer: CommandTrailer
public var raw: Data {
let writer = DataWriter()
writer.writeData(header.raw)
writer.writeData(data.raw)
writer.writeData(trailer.raw)
return writer.buffer
}
public var registerRequest: RegisterRequest? { return data as? RegisterRequest }
public var authenticationRequest: AuthenticationRequest? { return data as? AuthenticationRequest }
public var versionRequest: VersionRequest? { return data as? VersionRequest }
public init(data d: CommandDataProtocol) throws {
header = try CommandHeader(cmdData: d)
data = d
trailer = CommandTrailer(cmdData: d)
}
public init(raw: Data) throws {
header = try CommandHeader(raw: raw)
guard let cmdType = Command.commandTypeForCode(header.ins) else { throw ResponseStatus.InsNotSupported }
var dOffset = header.raw.count
var dData = raw.subdata(in: dOffset..<raw.count)
data = try cmdType.init(raw: dData)
dOffset += data.raw.count
dData = raw.subdata(in: dOffset..<raw.count)
trailer = try CommandTrailer(raw: dData)
}
public func debug() {
print("APDU Command:")
header.debug()
data.debug()
trailer.debug()
}
}

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

@ -1,26 +0,0 @@
//
// CommandDataProtocol.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 9/12/16.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
public protocol CommandDataProtocol {
static var cmdClass: CommandClass { get }
static var cmdCode: CommandCode { get }
var raw: Data { get }
init(raw: Data) throws
func debug()
}
extension CommandDataProtocol {
// Register request wrapped in an APDU packet.
func apduWrapped() throws -> MessageProtocol {
return try Command(data: self)
}
}

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

@ -8,7 +8,7 @@
import Foundation
public struct CommandHeader {
struct CommandHeader: RawConvertible, MessagePart {
public let cla: CommandClass
public let ins: CommandCode
public let p1: UInt8
@ -31,18 +31,7 @@ public struct CommandHeader {
return writer.buffer
}
init(cmdData: CommandDataProtocol) throws {
cla = type(of: cmdData).cmdClass
ins = type(of: cmdData).cmdCode
p1 = 0x00
p2 = 0x00
dataLength = cmdData.raw.count
if dataLength > 0xFFFF { throw ResponseStatus.WrongLength }
}
init(raw: Data) throws {
let reader = DataReader(data: raw)
init(reader: DataReader) throws {
do {
let claByte: UInt8 = try reader.read()
guard let tmpCla = CommandClass(rawValue: claByte) else { throw ResponseStatus.ClassNotSupported }
@ -75,6 +64,14 @@ public struct CommandHeader {
throw ResponseStatus.WrongLength
}
}
init(cla: CommandClass = .Reserved, ins: CommandCode, p1: UInt8 = 0x00, p2: UInt8 = 0x00, dataLength: Int) {
self.cla = cla
self.ins = ins
self.p1 = p1
self.p2 = p2
self.dataLength = dataLength
}
func debug() {
print( "Command Header:")

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

@ -0,0 +1,54 @@
//
// CommandProtocol.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/7/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
public func commandType(raw: Data) throws -> CommandCode {
let reader = DataReader(data: raw)
let header = try CommandHeader(reader: reader)
return header.ins
}
protocol CommandProtocol {
var header: CommandHeader { get }
var body: Data { get }
var trailer: CommandTrailer { get }
init(header: CommandHeader, body: Data, trailer: CommandTrailer)
func validateBody() throws
}
// Implement RawConvertible
extension CommandProtocol {
public var raw: Data {
let writer = DataWriter()
writer.writeData(header.raw)
writer.writeData(body)
writer.writeData(trailer.raw)
return writer.buffer
}
public init(raw: Data) throws {
let reader = DataReader(data: raw)
let header: CommandHeader
let body: Data
let trailer: CommandTrailer
do {
header = try CommandHeader(reader: reader)
body = try reader.readData(header.dataLength)
trailer = try CommandTrailer(reader: reader)
} catch DataReaderError.End {
throw ResponseStatus.WrongLength
}
self.init(header: header, body: body, trailer: trailer)
}
}

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

@ -8,9 +8,7 @@
import Foundation
struct CommandTrailer {
static let MaxMaxResponse = Int(UInt16.max) + 1
struct CommandTrailer: RawConvertible, MessagePart {
let maxResponse: Int
let noBody: Bool
@ -30,9 +28,7 @@ struct CommandTrailer {
return writer.buffer
}
init(raw: Data) throws {
let reader = DataReader(data: raw)
init(reader: DataReader) throws {
// 0 is prepended to trailer if there was no body.
if reader.remaining == 3 {
noBody = true
@ -50,7 +46,7 @@ struct CommandTrailer {
case 2:
let mr: UInt16 = try reader.read()
if mr == 0x0000 {
maxResponse = CommandTrailer.MaxMaxResponse
maxResponse = MaxResponseSize
} else {
maxResponse = Int(mr)
}
@ -58,10 +54,10 @@ struct CommandTrailer {
throw ResponseStatus.WrongLength
}
}
init(cmdData cd: CommandDataProtocol, maxResponse mr: Int = CommandTrailer.MaxMaxResponse) {
maxResponse = mr
noBody = cd.raw.count == 0
init(noBody: Bool, maxResponse: Int = MaxResponseSize) {
self.noBody = noBody
self.maxResponse = maxResponse
}
func debug() {

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

@ -14,6 +14,8 @@ let U2F_APPID_SIZE = 32
let U2F_EC_KEY_SIZE = 32 // EC key size in bytes
let U2F_EC_POINT_SIZE = ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
let MaxResponseSize = Int(UInt16.max) + 1
// ISO7816-4
public enum ResponseStatus: UInt16, EndianEnumProtocol, Error {
public typealias RawValue = UInt16
@ -43,4 +45,7 @@ public enum CommandCode: UInt8 {
public enum Control: UInt8 {
case EnforceUserPresenceAndSign = 0x03
case CheckOnly = 0x07
// Used internally.
case Invalid = 0xFF
}

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

@ -0,0 +1,22 @@
//
// MessagePart.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/7/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
// Part of a APDU message (header/trailer).
protocol MessagePart {
init(reader: DataReader) throws
}
// Implement RawConvertible
extension MessagePart {
init(raw: Data) throws {
let reader = DataReader(data: raw)
try self.init(reader: reader)
}
}

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

@ -0,0 +1,15 @@
//
// RawConvertible.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/7/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import Foundation
public protocol RawConvertible {
var raw: Data { get }
init(raw: Data) throws
}

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

@ -8,39 +8,44 @@
import Foundation
public struct RegisterRequest: CommandDataProtocol {
public static let cmdClass = CommandClass.Reserved
public static let cmdCode = CommandCode.Register
public struct RegisterRequest: RawConvertible {
let header: CommandHeader
let body: Data
let trailer: CommandTrailer
public var challengeParameter: Data {
let lowerBound = 0
let upperBound = lowerBound + U2F_CHAL_SIZE
return body.subdata(in: lowerBound..<upperBound)
}
public let challengeParameter: Data
public let applicationParameter: Data
public var applicationParameter: Data {
let lowerBound = U2F_CHAL_SIZE
let upperBound = lowerBound + U2F_APPID_SIZE
return body.subdata(in: lowerBound..<upperBound)
}
public var raw: Data {
public init(challengeParameter: Data, applicationParameter: Data) {
let writer = DataWriter()
writer.writeData(challengeParameter)
writer.writeData(applicationParameter)
return writer.buffer
self.body = writer.buffer
self.header = CommandHeader(ins: .Register, dataLength: body.count)
self.trailer = CommandTrailer(noBody: false)
}
public init(challengeParameter c: Data, applicationParameter a: Data) {
challengeParameter = c
applicationParameter = a
}
public init(raw: Data) throws {
let reader = DataReader(data: raw)
do {
challengeParameter = try reader.readData(U2F_CHAL_SIZE)
applicationParameter = try reader.readData(U2F_APPID_SIZE)
} catch DataReaderError.End {
func validateBody() throws {
if body.count != U2F_CHAL_SIZE + U2F_APPID_SIZE {
throw ResponseStatus.WrongLength
}
}
}
public func debug() {
print("RegisterRequest:")
print(" Challenge parameter: \(challengeParameter.base64EncodedString())")
print(" Application parameter: \(applicationParameter.base64EncodedString())")
extension RegisterRequest: CommandProtocol {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
}

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

@ -8,21 +8,28 @@
import Foundation
public struct VersionRequest: CommandDataProtocol {
public static let cmdClass = CommandClass.Reserved
public static let cmdCode = CommandCode.Version
public var raw: Data {
return Data(capacity: 0)
public struct VersionRequest: RawConvertible {
let header: CommandHeader
let body: Data
let trailer: CommandTrailer
func validateBody() throws {
if body.count > 0 {
throw ResponseStatus.WrongLength
}
}
init() {
}
public init(raw: Data) throws {
}
public func debug() {
print("Version Request (no data)")
self.header = CommandHeader(ins: .Version, dataLength: 0)
self.body = Data()
self.trailer = CommandTrailer(noBody: true)
}
}
extension VersionRequest: CommandProtocol {
init(header: CommandHeader, body: Data, trailer: CommandTrailer) {
self.header = header
self.body = body
self.trailer = trailer
}
}

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

@ -0,0 +1,63 @@
//
// AuthenticationRequestTests.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/6/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import XCTest
class AuthenticationRequestTests: XCTestCase {
func testChromeRequest() throws {
let r = Data(base64Encoded: "AAIDAAAAgeOwxEKY/BwUmvv0yJlvuSQnrkHkZJuTTKSVmRt4UrhVcGF9/tBlhjr0fBVVbJF5iICCjMQH/fcK6FARVpRloHVAIA5xiih5UyR97Gx8DMpSZgno9djTV85XM+VQfZNgADuFrTX978Gq3C8F6BfBLgD042ioARsymZUhkDxd3i3nsQAA")!
let c = try AuthenticationRequest(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Authenticate)
XCTAssertEqual(c.header.p1, Control.EnforceUserPresenceAndSign.rawValue)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(c.raw, r)
}
func testRequest() throws {
let c = Data(repeating: 0xAA, count: 32)
let a = Data(repeating: 0xBB, count: 32)
let k = Data(repeating: 0xCC, count: 16)
let cmd = AuthenticationRequest(challengeParameter: c, applicationParameter: a, keyHandle: k, control: .CheckOnly)
XCTAssertEqual(cmd.header.cla, CommandClass.Reserved)
XCTAssertEqual(cmd.header.ins, CommandCode.Authenticate)
XCTAssertEqual(cmd.control, Control.CheckOnly)
XCTAssertEqual(cmd.header.p2, 0x00)
XCTAssertEqual(cmd.challengeParameter, c)
XCTAssertEqual(cmd.applicationParameter, a)
XCTAssertEqual(cmd.keyHandle, k)
XCTAssertEqual(cmd.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(cmd.raw, Data(bytes: [
0x00,
0x02,
0x07,
0x00,
0x00,
0x00,
0x51,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
0x10,
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
0x00,
0x00
]))
let cmd2 = try AuthenticationRequest(raw: cmd.raw)
XCTAssertEqual(cmd.header.cla, cmd2.header.cla)
XCTAssertEqual(cmd.header.ins, cmd2.header.ins)
XCTAssertEqual(cmd.header.p1, cmd2.header.p1)
XCTAssertEqual(cmd.header.p2, cmd2.header.p2)
XCTAssertEqual(cmd.challengeParameter, cmd2.challengeParameter)
XCTAssertEqual(cmd.applicationParameter, cmd2.applicationParameter)
XCTAssertEqual(cmd.keyHandle, cmd2.keyHandle)
XCTAssertEqual(cmd.trailer.maxResponse, cmd2.trailer.maxResponse)
}
}

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

@ -14,29 +14,29 @@ class CommandHeaderTests: XCTestCase {
let a = Data(repeating: 0xAA, count: 32)
let cmd = RegisterRequest(challengeParameter: c, applicationParameter: a)
let apdu = try cmd.apduWrapped()
let apdu = cmd.raw
let h = try CommandHeader(raw: apdu.raw)
let h = try CommandHeader(raw: apdu)
XCTAssertEqual(h.cla, CommandClass.Reserved)
XCTAssertEqual(h.ins, CommandCode.Register)
XCTAssertEqual(h.p1, 0x00)
XCTAssertEqual(h.p2, 0x00)
XCTAssertEqual(h.dataLength, c.count + a.count)
XCTAssert(apdu.raw.starts(with: h.raw))
XCTAssert(apdu.starts(with: h.raw))
}
func testVersionRequest() throws {
let cmd = VersionRequest()
let apdu = try cmd.apduWrapped()
let apdu = cmd.raw
let h = try CommandHeader(raw: apdu.raw)
let h = try CommandHeader(raw: apdu)
XCTAssertEqual(h.cla, CommandClass.Reserved)
XCTAssertEqual(h.ins, CommandCode.Version)
XCTAssertEqual(h.p1, 0x00)
XCTAssertEqual(h.p2, 0x00)
XCTAssertEqual(h.dataLength, 0)
XCTAssert(apdu.raw.starts(with: h.raw))
XCTAssert(apdu.starts(with: h.raw))
}
}

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

@ -1,63 +0,0 @@
//
// CommandTests.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 9/11/16.
// Copyright © 2017 GitHub. All rights reserved.
//
import XCTest
class CommandTests: XCTestCase {
func testChromeRegisterRequest() throws {
let r = Data(base64Encoded: "AAEDAAAAQEr8hj61EL83BjxGaqSnMUyWyXeBIAhGhQ2zbkFcgOzbcGF9/tBlhjr0fBVVbJF5iICCjMQH/fcK6FARVpRloHUAAA==")!
let c = try Command(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Register)
XCTAssertEqual(c.header.p1, Control.EnforceUserPresenceAndSign.rawValue)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.trailer.maxResponse, CommandTrailer.MaxMaxResponse)
XCTAssertEqual(c.trailer.noBody, false)
XCTAssertNotNil(c.registerRequest)
XCTAssertEqual(c.raw, r)
}
func testChromeVersionRequest() throws {
let r = Data(base64Encoded: "AAMAAAAAAA==")!
let c = try Command(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Version)
XCTAssertEqual(c.header.p1, 0x00)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.header.dataLength, 0)
XCTAssertEqual(c.data.raw.count, 0)
XCTAssertEqual(c.trailer.maxResponse, CommandTrailer.MaxMaxResponse)
XCTAssertEqual(c.trailer.noBody, true)
XCTAssertNotNil(c.versionRequest)
XCTAssertEqual(c.raw, r)
}
func testChromeAuthenticationRequest() throws {
let r = Data(base64Encoded: "AAIDAAAAgeOwxEKY/BwUmvv0yJlvuSQnrkHkZJuTTKSVmRt4UrhVcGF9/tBlhjr0fBVVbJF5iICCjMQH/fcK6FARVpRloHVAIA5xiih5UyR97Gx8DMpSZgno9djTV85XM+VQfZNgADuFrTX978Gq3C8F6BfBLgD042ioARsymZUhkDxd3i3nsQAA")!
let c = try Command(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Authenticate)
XCTAssertEqual(c.header.p1, Control.EnforceUserPresenceAndSign.rawValue)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.trailer.maxResponse, CommandTrailer.MaxMaxResponse)
XCTAssertEqual(c.trailer.noBody, false)
XCTAssertNotNil(c.authenticationRequest)
XCTAssertEqual(c.raw, r)
}
func testCommandTypeForCode() {
XCTAssert(Command.commandTypeForCode(.Register) == RegisterRequest.self)
XCTAssert(Command.commandTypeForCode(.Authenticate) == AuthenticationRequest.self)
XCTAssert(Command.commandTypeForCode(.Version) == VersionRequest.self)
XCTAssert(Command.commandTypeForCode(.CheckRegister) == nil)
XCTAssert(Command.commandTypeForCode(.AuthenticateBatch) == nil)
}
}

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

@ -0,0 +1,60 @@
//
// RegisterRequestTests.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/6/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import XCTest
@testable import APDU
class RegisterRequestTests: XCTestCase {
func testChromeRequest() throws {
let r = Data(base64Encoded: "AAEDAAAAQEr8hj61EL83BjxGaqSnMUyWyXeBIAhGhQ2zbkFcgOzbcGF9/tBlhjr0fBVVbJF5iICCjMQH/fcK6FARVpRloHUAAA==")!
let c = try RegisterRequest(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Register)
XCTAssertEqual(c.header.p1, Control.EnforceUserPresenceAndSign.rawValue)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(c.raw, r)
}
func testRequest() throws {
let c = Data(repeating: 0xAA, count: 32)
let a = Data(repeating: 0xBB, count: 32)
let cmd = RegisterRequest(challengeParameter: c, applicationParameter: a)
XCTAssertEqual(cmd.header.cla, CommandClass.Reserved)
XCTAssertEqual(cmd.header.ins, CommandCode.Register)
XCTAssertEqual(cmd.header.p1, 0x00)
XCTAssertEqual(cmd.header.p2, 0x00)
XCTAssertEqual(cmd.challengeParameter, c)
XCTAssertEqual(cmd.applicationParameter, a)
XCTAssertEqual(cmd.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(cmd.raw, Data(bytes: [
0x00,
0x01,
0x00,
0x00,
0x00,
0x00,
0x40,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
0x00,
0x00
]))
let cmd2 = try RegisterRequest(raw: cmd.raw)
XCTAssertEqual(cmd.header.cla, cmd2.header.cla)
XCTAssertEqual(cmd.header.ins, cmd2.header.ins)
XCTAssertEqual(cmd.header.p1, cmd2.header.p1)
XCTAssertEqual(cmd.header.p2, cmd2.header.p2)
XCTAssertEqual(cmd.challengeParameter, cmd2.challengeParameter)
XCTAssertEqual(cmd.applicationParameter, cmd2.applicationParameter)
XCTAssertEqual(cmd.trailer.maxResponse, cmd2.trailer.maxResponse)
}
}

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

@ -0,0 +1,39 @@
//
// VersionRequestTests.swift
// SoftU2FTool
//
// Created by Benjamin P Toews on 2/6/17.
// Copyright © 2017 GitHub. All rights reserved.
//
import XCTest
@testable import APDU
class VersionRequestTests: XCTestCase {
func testChromeRequest() throws {
let r = Data(base64Encoded: "AAMAAAAAAA==")!
let c = try VersionRequest(raw: r)
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Version)
XCTAssertEqual(c.header.p1, 0x00)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.header.dataLength, 0)
XCTAssertEqual(c.body.count, 0)
XCTAssertEqual(c.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(c.raw, r)
}
func testRequest() {
let c = VersionRequest()
XCTAssertEqual(c.header.cla, CommandClass.Reserved)
XCTAssertEqual(c.header.ins, CommandCode.Version)
XCTAssertEqual(c.header.p1, 0x00)
XCTAssertEqual(c.header.p2, 0x00)
XCTAssertEqual(c.header.dataLength, 0)
XCTAssertEqual(c.body.count, 0)
XCTAssertEqual(c.trailer.maxResponse, MaxResponseSize)
XCTAssertEqual(c.raw, Data(bytes: [0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00]))
}
}

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

@ -39,8 +39,6 @@
F738F5151E4A2CF6005680A2 /* RegisterResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5081E4A2CF6005680A2 /* RegisterResponse.swift */; };
F738F5161E4A2CF6005680A2 /* VersionRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5091E4A2CF6005680A2 /* VersionRequest.swift */; };
F738F5171E4A2CF6005680A2 /* VersionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */; };
F738F5191E4A2DD5005680A2 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5181E4A2DD5005680A2 /* Command.swift */; };
F738F51F1E4A2DDD005680A2 /* CommandDataProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51A1E4A2DDD005680A2 /* CommandDataProtocol.swift */; };
F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; };
F738F5211E4A2DDD005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; };
F738F5221E4A2DDD005680A2 /* MessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */; };
@ -49,14 +47,11 @@
F738F52A1E4A2E57005680A2 /* Endian.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5271E4A2E57005680A2 /* Endian.swift */; };
F738F5341E4A2E8A005680A2 /* APDU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F738F4F11E4A2CCB005680A2 /* APDU.framework */; };
F738F53E1E4A2ED6005680A2 /* CommandHeaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53A1E4A2ED6005680A2 /* CommandHeaderTests.swift */; };
F738F53F1E4A2ED6005680A2 /* CommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53B1E4A2ED6005680A2 /* CommandTests.swift */; };
F738F5401E4A2ED6005680A2 /* CommandTrailerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53C1E4A2ED6005680A2 /* CommandTrailerTests.swift */; };
F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F53D1E4A2ED6005680A2 /* ResponseTests.swift */; };
F738F5421E4A2F91005680A2 /* CommandDataProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51A1E4A2DDD005680A2 /* CommandDataProtocol.swift */; };
F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */; };
F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */; };
F738F5451E4A2F91005680A2 /* MessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */; };
F738F5471E4A2F91005680A2 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5181E4A2DD5005680A2 /* Command.swift */; };
F738F5481E4A2F91005680A2 /* AuthenticationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */; };
F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */; };
F738F54A1E4A2F91005680A2 /* ErrorResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */; };
@ -82,6 +77,15 @@
F738F5871E4A3C09005680A2 /* DataReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5851E4A3C09005680A2 /* DataReaderTests.swift */; };
F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5861E4A3C09005680A2 /* DataWriterTests.swift */; };
F738F58A1E4A3C21005680A2 /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738F5891E4A3C21005680A2 /* TestUtil.swift */; };
F7B5DBAD1E4A5CED00E5ABD4 /* CommandProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */; };
F7B5DBAF1E4A815700E5ABD4 /* 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 */; };
F7B5DBB31E4A82EB00E5ABD4 /* 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 */; };
F7B5DBC21E4A85EB00E5ABD4 /* RegisterRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */; };
F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -220,8 +224,6 @@
F738F5081E4A2CF6005680A2 /* RegisterResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegisterResponse.swift; sourceTree = "<group>"; };
F738F5091E4A2CF6005680A2 /* VersionRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionRequest.swift; sourceTree = "<group>"; };
F738F50A1E4A2CF6005680A2 /* VersionResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionResponse.swift; sourceTree = "<group>"; };
F738F5181E4A2DD5005680A2 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
F738F51A1E4A2DDD005680A2 /* CommandDataProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandDataProtocol.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>"; };
F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageProtocol.swift; sourceTree = "<group>"; };
@ -231,7 +233,6 @@
F738F52F1E4A2E8A005680A2 /* APDUTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APDUTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F738F5331E4A2E8A005680A2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F738F53A1E4A2ED6005680A2 /* CommandHeaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandHeaderTests.swift; sourceTree = "<group>"; };
F738F53B1E4A2ED6005680A2 /* CommandTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTests.swift; sourceTree = "<group>"; };
F738F53C1E4A2ED6005680A2 /* CommandTrailerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTrailerTests.swift; sourceTree = "<group>"; };
F738F53D1E4A2ED6005680A2 /* ResponseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResponseTests.swift; sourceTree = "<group>"; };
F738F5521E4A2FF0005680A2 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@ -247,6 +248,12 @@
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>"; };
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>"; };
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>"; };
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>"; };
F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionRequestTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -395,11 +402,12 @@
children = (
F738F5241E4A2E4C005680A2 /* Data */,
F738F5521E4A2FF0005680A2 /* Constants.swift */,
F738F51A1E4A2DDD005680A2 /* CommandDataProtocol.swift */,
F7B5DBAE1E4A815700E5ABD4 /* RawConvertible.swift */,
F7B5DBB21E4A82EB00E5ABD4 /* MessagePart.swift */,
F7B5DBAC1E4A5CED00E5ABD4 /* CommandProtocol.swift */,
F738F51B1E4A2DDD005680A2 /* CommandHeader.swift */,
F738F51C1E4A2DDD005680A2 /* CommandTrailer.swift */,
F738F51D1E4A2DDD005680A2 /* MessageProtocol.swift */,
F738F5181E4A2DD5005680A2 /* Command.swift */,
F738F5041E4A2CF6005680A2 /* AuthenticationRequest.swift */,
F738F5051E4A2CF6005680A2 /* AuthenticationResponse.swift */,
F738F5061E4A2CF6005680A2 /* ErrorResponse.swift */,
@ -427,8 +435,10 @@
isa = PBXGroup;
children = (
F738F5841E4A3BF9005680A2 /* DataTests */,
F7B5DBBD1E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift */,
F7B5DBBE1E4A85EB00E5ABD4 /* RegisterRequestTests.swift */,
F7B5DBBF1E4A85EB00E5ABD4 /* VersionRequestTests.swift */,
F738F53A1E4A2ED6005680A2 /* CommandHeaderTests.swift */,
F738F53B1E4A2ED6005680A2 /* CommandTests.swift */,
F738F53C1E4A2ED6005680A2 /* CommandTrailerTests.swift */,
F738F53D1E4A2ED6005680A2 /* ResponseTests.swift */,
F738F5891E4A3C21005680A2 /* TestUtil.swift */,
@ -798,10 +808,12 @@
files = (
F738F5281E4A2E57005680A2 /* DataReader.swift in Sources */,
F738F5531E4A2FF0005680A2 /* Constants.swift in Sources */,
F7B5DBAD1E4A5CED00E5ABD4 /* CommandProtocol.swift in Sources */,
F7B5DBB31E4A82EB00E5ABD4 /* MessagePart.swift in Sources */,
F738F5151E4A2CF6005680A2 /* RegisterResponse.swift in Sources */,
F738F51F1E4A2DDD005680A2 /* CommandDataProtocol.swift in Sources */,
F738F5201E4A2DDD005680A2 /* CommandHeader.swift in Sources */,
F738F5141E4A2CF6005680A2 /* RegisterRequest.swift in Sources */,
F7B5DBAF1E4A815700E5ABD4 /* RawConvertible.swift in Sources */,
F738F5211E4A2DDD005680A2 /* CommandTrailer.swift in Sources */,
F738F52A1E4A2E57005680A2 /* Endian.swift in Sources */,
F738F5111E4A2CF6005680A2 /* AuthenticationRequest.swift in Sources */,
@ -811,7 +823,6 @@
F738F5131E4A2CF6005680A2 /* ErrorResponse.swift in Sources */,
F738F5121E4A2CF6005680A2 /* AuthenticationResponse.swift in Sources */,
F738F5161E4A2CF6005680A2 /* VersionRequest.swift in Sources */,
F738F5191E4A2DD5005680A2 /* Command.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -820,20 +831,21 @@
buildActionMask = 2147483647;
files = (
F738F58A1E4A3C21005680A2 /* TestUtil.swift in Sources */,
F738F5421E4A2F91005680A2 /* CommandDataProtocol.swift in Sources */,
F738F53E1E4A2ED6005680A2 /* CommandHeaderTests.swift in Sources */,
F738F54E1E4A2F91005680A2 /* VersionResponse.swift in Sources */,
F738F54C1E4A2F91005680A2 /* RegisterResponse.swift in Sources */,
F738F5471E4A2F91005680A2 /* Command.swift in Sources */,
F738F54B1E4A2F91005680A2 /* RegisterRequest.swift in Sources */,
F738F5871E4A3C09005680A2 /* DataReaderTests.swift in Sources */,
F738F53F1E4A2ED6005680A2 /* CommandTests.swift in Sources */,
F7B5DBB01E4A827000E5ABD4 /* RawConvertible.swift in Sources */,
F7B5DBB41E4A83D900E5ABD4 /* MessagePart.swift in Sources */,
F738F5881E4A3C09005680A2 /* DataWriterTests.swift in Sources */,
F7B5DBB11E4A827400E5ABD4 /* CommandProtocol.swift in Sources */,
F738F5411E4A2ED6005680A2 /* ResponseTests.swift in Sources */,
F738F5431E4A2F91005680A2 /* CommandHeader.swift in Sources */,
F738F5441E4A2F91005680A2 /* CommandTrailer.swift in Sources */,
F738F5541E4A2FF0005680A2 /* Constants.swift in Sources */,
F738F5401E4A2ED6005680A2 /* CommandTrailerTests.swift in Sources */,
F7B5DBC31E4A85EB00E5ABD4 /* VersionRequestTests.swift in Sources */,
F738F5451E4A2F91005680A2 /* MessageProtocol.swift in Sources */,
F738F5501E4A2F9E005680A2 /* DataWriter.swift in Sources */,
F738F5491E4A2F91005680A2 /* AuthenticationResponse.swift in Sources */,
@ -841,6 +853,8 @@
F738F54D1E4A2F91005680A2 /* VersionRequest.swift in Sources */,
F738F54F1E4A2F9E005680A2 /* DataReader.swift in Sources */,
F738F5511E4A2F9E005680A2 /* Endian.swift in Sources */,
F7B5DBC11E4A85EB00E5ABD4 /* AuthenticationRequestTests.swift in Sources */,
F7B5DBC21E4A85EB00E5ABD4 /* RegisterRequestTests.swift in Sources */,
F738F54A1E4A2F91005680A2 /* ErrorResponse.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;