Skip to content

Commit

Permalink
Merge branch 'jens/large-rsa-keys'
Browse files Browse the repository at this point in the history
  • Loading branch information
jensutbult committed May 8, 2024
2 parents 7ad3e24 + 03402e8 commit 4666a2b
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 26 deletions.
22 changes: 21 additions & 1 deletion FullStackTests/Tests/PIVFullStackTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ final class PIVFullStackTests: XCTestCase {
}

func testGenerateRSA2048Key() throws {
runAuthenticatedPIVTest { session in
runAuthenticatedPIVTest(withTimeout: 50) { session in
let publicKey = try await session.generateKeyInSlot(slot: .signature, type: .RSA2048, pinPolicy: .always, touchPolicy: .cached)
let attributes = SecKeyCopyAttributes(publicKey) as! [String: Any]
XCTAssert(attributes[kSecAttrKeySizeInBits as String] as! Int == 2048)
Expand All @@ -219,6 +219,26 @@ final class PIVFullStackTests: XCTestCase {
}
}

func testGenerateRSA3072Key() throws {
runAuthenticatedPIVTest(withTimeout: 200) { session in
let publicKey = try await session.generateKeyInSlot(slot: .signature, type: .RSA3072, pinPolicy: .always, touchPolicy: .cached)
let attributes = SecKeyCopyAttributes(publicKey) as! [String: Any]
XCTAssert(attributes[kSecAttrKeySizeInBits as String] as! Int == 3072)
XCTAssert(attributes[kSecAttrKeyType as String] as! String == kSecAttrKeyTypeRSA as String)
XCTAssert(attributes[kSecAttrKeyClass as String] as! String == kSecAttrKeyClassPublic as String)
}
}

func testGenerateRSA4096Key() throws {
runAuthenticatedPIVTest(withTimeout: 200) { session in
let publicKey = try await session.generateKeyInSlot(slot: .signature, type: .RSA4096, pinPolicy: .always, touchPolicy: .cached)
let attributes = SecKeyCopyAttributes(publicKey) as! [String: Any]
XCTAssert(attributes[kSecAttrKeySizeInBits as String] as! Int == 4096)
XCTAssert(attributes[kSecAttrKeyType as String] as! String == kSecAttrKeyTypeRSA as String)
XCTAssert(attributes[kSecAttrKeyClass as String] as! String == kSecAttrKeyClassPublic as String)
}
}

func testGenerateECCP256Key() throws {
runAuthenticatedPIVTest { session in
let publicKey = try await session.generateKeyInSlot(slot: .signature, type: .ECCP256, pinPolicy: .always, touchPolicy: .cached)
Expand Down
9 changes: 0 additions & 9 deletions YubiKit/YubiKit/Management/DeviceConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,13 @@ public struct DeviceConfig {
public let enabledCapabilities: [DeviceTransport: UInt]

internal let tagUSBEnabled: TKTLVTag = 0x03
// private static final int TAG_USB_ENABLED = 0x03;
internal let tagAutoEjectTimeout: TKTLVTag = 0x06
// private static final int TAG_AUTO_EJECT_TIMEOUT = 0x06;
internal let tagChallengeResponseTimeout: TKTLVTag = 0x07
// private static final int TAG_CHALLENGE_RESPONSE_TIMEOUT = 0x07;
internal let tagDeviceFlags: TKTLVTag = 0x08
// private static final int TAG_DEVICE_FLAGS = 0x08;
internal let tagNFCEnabled: TKTLVTag = 0x0e
// private static final int TAG_NFC_ENABLED = 0x0e;
internal let tagConfigurationLock: TKTLVTag = 0x0a
// private static final int TAG_CONFIGURATION_LOCK = 0x0a;
internal let tagUnlock: TKTLVTag = 0x0b
// private static final int TAG_UNLOCK = 0x0b;
internal let tagReboot: TKTLVTag = 0x0c
// private static final int TAG_REBOOT = 0x0c;


public func isApplicationEnabled(_ application: ApplicationType, overTransport transport: DeviceTransport) -> Bool {
guard let mask = enabledCapabilities[transport] else { return false }
Expand Down
16 changes: 8 additions & 8 deletions YubiKit/YubiKit/Management/DeviceInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ public enum ApplicationType: UInt {

/// The physical form factor of a YubiKey.
public enum FormFactor: UInt8 {
// Used when information about the YubiKey's form factor isn't available.
/// Used when information about the YubiKey's form factor isn't available.
case unknown = 0x00
// A keychain-sized YubiKey with a USB-A connector.
/// A keychain-sized YubiKey with a USB-A connector.
case usbAKeychain = 0x01
// A nano-sized YubiKey with a USB-A connector.
/// A nano-sized YubiKey with a USB-A connector.
case usbANano = 0x02
// A keychain-sized YubiKey with a USB-C connector.
/// A keychain-sized YubiKey with a USB-C connector.
case usbCKeychain = 0x03
// A nano-sized YubiKey with a USB-C connector.
/// A nano-sized YubiKey with a USB-C connector.
case usbCNano = 0x04
// A keychain-sized YubiKey with both USB-C and Lightning connectors.
/// A keychain-sized YubiKey with both USB-C and Lightning connectors.
case usbCLightning = 0x05
// A keychain-sized YubiKey with fingerprint sensor and USB-A connector.
/// A keychain-sized YubiKey with fingerprint sensor and USB-A connector.
case usbABio = 0x06
// A keychain-sized YubiKey with fingerprint sensor and USB-C connector.
/// A keychain-sized YubiKey with fingerprint sensor and USB-C connector.
case usbCBio = 0x07
}

Expand Down
20 changes: 15 additions & 5 deletions YubiKit/YubiKit/PIV/PIVDataTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public enum PIVSlot: UInt8 {
public enum PIVKeyType: UInt8 {
case RSA1024 = 0x06
case RSA2048 = 0x07
case RSA3072 = 0x05
case RSA4096 = 0x16
case ECCP256 = 0x11
case ECCP384 = 0x14
case unknown = 0x00
Expand All @@ -87,6 +89,10 @@ public enum PIVKeyType: UInt8 {
self = .RSA1024
case 2048:
self = .RSA2048
case 3072:
self = .RSA3072
case 4096:
self = .RSA4096
default:
return nil
}
Expand All @@ -108,15 +114,19 @@ public enum PIVKeyType: UInt8 {
var size: UInt {
switch (self) {
case .ECCP256:
return 256 / 8;
return 256 / 8
case .ECCP384:
return 384 / 8;
return 384 / 8
case .RSA1024:
return 1024 / 8;
return 1024 / 8
case .RSA2048:
return 2048 / 8;
return 2048 / 8
case .RSA3072:
return 3072 / 8
case .RSA4096:
return 4096 / 8
default:
return 0;
return 0
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions YubiKit/YubiKit/PIV/PIVSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public final actor PIVSession: Session, InternalSession {
var error: Unmanaged<CFError>?
guard let publicKey = SecKeyCreateWithData(eccKeyData as CFData, attributes, &error) else { throw error!.takeRetainedValue() as Error }
return publicKey
case .RSA1024, .RSA2048:
case .RSA1024, .RSA2048, .RSA3072, .RSA4096:
guard let modulus = records.recordWithTag(0x81)?.value,
let exponentData = records.recordWithTag(0x82)?.value
else { throw PIVSessionError.invalidResponse }
Expand Down Expand Up @@ -226,7 +226,7 @@ public final actor PIVSession: Session, InternalSession {
let keyData = cfKeyData as Data
var data = Data()
switch keyType {
case .RSA1024, .RSA2048:
case .RSA1024, .RSA2048, .RSA3072, .RSA4096:
guard let recordsData = TKBERTLVRecord(from: keyData),
let records = TKBERTLVRecord.sequenceOfRecords(from: recordsData.value)
else { throw PIVSessionError.dataParseError }
Expand Down Expand Up @@ -657,6 +657,9 @@ extension PIVSession {
if generateKey && (keyType == .RSA1024 || keyType == .RSA2048) {
guard self.supports(PIVSessionFeature.rsaGeneration) else { throw SessionError.notSupported }
}
if generateKey && (keyType == .RSA3072 || keyType == .RSA4096) {
guard self.supports(PIVSessionFeature.rsa3072and4096) else { throw SessionError.notSupported }
}
}

private func getPinPukMetadata(p2: UInt8) async throws -> PIVPinPukMetadata {
Expand Down
4 changes: 3 additions & 1 deletion YubiKit/YubiKit/PIV/PIVSessionFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Foundation

public enum PIVSessionFeature: SessionFeature {

case usagePolicy, aesKey, serialNumber, metadata, attestation, p384, touchCached, rsaGeneration
case usagePolicy, aesKey, serialNumber, metadata, attestation, p384, touchCached, rsaGeneration, rsa3072and4096

public func isSupported(by version: Version) -> Bool {
switch self {
Expand All @@ -36,6 +36,8 @@ public enum PIVSessionFeature: SessionFeature {
return version >= Version(withString: "4.3.0")!
case .rsaGeneration:
return version < Version(withString: "4.2.6")! || version >= Version(withString: "4.3.5")!
case .rsa3072and4096:
return version >= Version(withString: "5.7.0")!
}
}
}

0 comments on commit 4666a2b

Please sign in to comment.