From 6655643ccf19554fec2293435990fcbec89eb2ee Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Fri, 25 Oct 2024 12:26:40 +0300 Subject: [PATCH 01/15] use secure area for signing, key agreement --- .../BLETransfer/MdocGATTServer.swift | 4 ++-- Sources/MdocDataTransfer18013/Enumerations.swift | 2 -- Sources/MdocDataTransfer18013/MdocHelpers.swift | 13 ++----------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift index 61f7fb8..832e11b 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift @@ -135,14 +135,14 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { // Create a new device engagement object and start the device engagement process. /// /// ``qrCodePayload`` is set to QR code data corresponding to the device engagement. - public func performDeviceEngagement(rfus: [String]? = nil) { + public func performDeviceEngagement(secureArea: any SecureArea, rfus: [String]? = nil) { guard !isPreview && !isInErrorState else { logger.info("Current status is \(status)") return } // Check that the class is in the right state to start the device engagement process. It will fail if the class is in any other state. guard status == .initialized || status == .disconnected || status == .responseSent else { error = MdocHelpers.makeError(code: .unexpected_error, str: error?.localizedDescription ?? "Not initialized!"); return } - deviceEngagement = DeviceEngagement(isBleServer: true, crv: .P256, rfus: rfus) + deviceEngagement = DeviceEngagement(isBleServer: true, crv: .P256, secureArea: secureArea, rfus: rfus) sessionEncryption = nil #if os(iOS) qrCodePayload = deviceEngagement!.getQrCodePayload() diff --git a/Sources/MdocDataTransfer18013/Enumerations.swift b/Sources/MdocDataTransfer18013/Enumerations.swift index 9b29c92..fe7c404 100644 --- a/Sources/MdocDataTransfer18013/Enumerations.swift +++ b/Sources/MdocDataTransfer18013/Enumerations.swift @@ -69,10 +69,8 @@ public enum ErrorCode: Int, CustomStringConvertible, Sendable { /// String keys for the initialization dictionary public enum InitializeKeys: String, Sendable { - case document_json_data case document_signup_issuer_signed_data case document_signup_issuer_signed_obj - case device_private_key_data case device_private_key_obj case trusted_certificates case device_auth_method diff --git a/Sources/MdocDataTransfer18013/MdocHelpers.swift b/Sources/MdocDataTransfer18013/MdocHelpers.swift index 5ef8f0c..0bdd6ff 100644 --- a/Sources/MdocDataTransfer18013/MdocHelpers.swift +++ b/Sources/MdocDataTransfer18013/MdocHelpers.swift @@ -38,18 +38,9 @@ public class MdocHelpers { var devicePrivateKeys: [String: CoseKeyPrivate]? var iaca: [SecCertificate]? var deviceAuthMethod = DeviceAuthMethod.deviceMac - if let d = parameters[InitializeKeys.document_json_data.rawValue] as? [Data] { - // load json sample data here, deprecated - let sampleData = d.compactMap { $0.decodeJSON(type: SignUpResponse.self) } - let randomIds = (0.. Date: Tue, 29 Oct 2024 11:02:14 +0200 Subject: [PATCH 02/15] Refactor Xcode schemes for MdocDataTransfer18013 and MdocDataTransfer18013Tests --- .../xcschemes/MdocDataTransfer18013.xcscheme | 79 +++++++++++++++++++ .../MdocDataTransfer18013Tests.xcscheme | 54 +++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013Tests.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013.xcscheme new file mode 100644 index 0000000..8b2c3ba --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013.xcscheme @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013Tests.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013Tests.xcscheme new file mode 100644 index 0000000..3b9c8ff --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/MdocDataTransfer18013Tests.xcscheme @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + From 30cbee921803b14c626b318b9ea915068bfa0f9c Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Tue, 29 Oct 2024 11:24:33 +0200 Subject: [PATCH 03/15] Refactor MdocGATTServer to use secure area for signing and key agreement --- .../MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift index 832e11b..781128f 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift @@ -135,14 +135,14 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { // Create a new device engagement object and start the device engagement process. /// /// ``qrCodePayload`` is set to QR code data corresponding to the device engagement. - public func performDeviceEngagement(secureArea: any SecureArea, rfus: [String]? = nil) { - guard !isPreview && !isInErrorState else { + public func performDeviceEngagement(secureArea: any SecureArea, crv: CoseEcCurve, rfus: [String]? = nil) { + guard !isPreview && !isInErrorState else { logger.info("Current status is \(status)") return } // Check that the class is in the right state to start the device engagement process. It will fail if the class is in any other state. guard status == .initialized || status == .disconnected || status == .responseSent else { error = MdocHelpers.makeError(code: .unexpected_error, str: error?.localizedDescription ?? "Not initialized!"); return } - deviceEngagement = DeviceEngagement(isBleServer: true, crv: .P256, secureArea: secureArea, rfus: rfus) + deviceEngagement = DeviceEngagement(isBleServer: true, crv: crv, secureArea: secureArea, rfus: rfus) sessionEncryption = nil #if os(iOS) qrCodePayload = deviceEngagement!.getQrCodePayload() @@ -199,6 +199,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { qrCodePayload = nil advertising = false subscribeCount = 0 + if let pk = deviceEngagement?.privateKey { try? pk.secureArea.deleteKey(id: pk.privateKeyId) } if status == .error && initSuccess { status = .initializing } } From bb0f62719aaa2b6b38ae544b066867ad530f4b80 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 30 Oct 2024 02:22:07 +0200 Subject: [PATCH 04/15] Refactor MdocGATTServer delete ephemeral key after stopping ble --- .../MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift index 781128f..d216504 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift @@ -65,7 +65,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { } @objc(CBPeripheralManagerDelegate) - class Delegate: NSObject, @preconcurrency CBPeripheralManagerDelegate { + class Delegate: NSObject, CBPeripheralManagerDelegate { unowned var server: MdocGattServer init(server: MdocGattServer) { @@ -199,7 +199,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { qrCodePayload = nil advertising = false subscribeCount = 0 - if let pk = deviceEngagement?.privateKey { try? pk.secureArea.deleteKey(id: pk.privateKeyId) } + if let pk = deviceEngagement?.privateKey { try? pk.secureArea.deleteKey(id: pk.privateKeyId); deviceEngagement?.privateKey = nil } if status == .error && initSuccess { status = .initializing } } @@ -268,6 +268,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { } } catch { errorToSend = error } + if let errorToSend { logger.error("Error sending data: \(errorToSend)")} } } From 8d2937fc56a7891812a6bef1ed560fb05eafce06 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 30 Oct 2024 02:54:08 +0200 Subject: [PATCH 05/15] Refactor MdocHelpers.swift to remove unnecessary code and improve readability --- Sources/MdocDataTransfer18013/MdocHelpers.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/MdocDataTransfer18013/MdocHelpers.swift b/Sources/MdocDataTransfer18013/MdocHelpers.swift index 0bdd6ff..0e1ad8f 100644 --- a/Sources/MdocDataTransfer18013/MdocHelpers.swift +++ b/Sources/MdocDataTransfer18013/MdocHelpers.swift @@ -141,7 +141,7 @@ public class MdocHelpers { } else { guard issuerSigned[reqDocIdOrDocType] != nil else { continue } } - let devicePrivateKey = devicePrivateKeys[reqDocIdOrDocType] ?? (try! CoseKeyPrivate(curve: .P256, secureArea: SecureAreaRegistry.shared.defaultSecurityArea!)) // used only if doc.id + let devicePrivateKey = devicePrivateKeys[reqDocIdOrDocType] // used only if doc.id let doc = if haveSelectedItems { issuerSigned[reqDocIdOrDocType]! } else { Array(issuerSigned.values).findDoc(name: reqDocIdOrDocType)!.0 } // Document's data must be in CBOR bytes that has the IssuerSigned structure according to ISO 23220-4 // Currently, the library does not support IssuerSigned structure without the nameSpaces field. @@ -180,7 +180,7 @@ public class MdocHelpers { let issToAdd = IssuerSigned(issuerNameSpaces: IssuerNameSpaces(nameSpaces: nsItemsToAdd), issuerAuth: issuerAuthToAdd) var devSignedToAdd: DeviceSigned? = nil let sessionTranscript = sessionEncryption?.transcript ?? sessionTranscript - if let eReaderKey, let sessionTranscript { + if let eReaderKey, let sessionTranscript, let devicePrivateKey { let authKeys = CoseKeyExchange(publicKey: eReaderKey, privateKey: devicePrivateKey) let mdocAuth = MdocAuthentication(transcript: sessionTranscript, authKeys: authKeys) guard let devAuth = try mdocAuth.getDeviceAuthForTransfer(docType: doc.issuerAuth.mso.docType, dauthMethod: dauthMethod) else { From 1f621ec94bda143cc163c2fc3c8f7e8623269ebf Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Sun, 17 Nov 2024 21:57:08 +0200 Subject: [PATCH 06/15] Refactor MdocGATTServer and MdocHelpers to include unlockData in request handling --- .../BLETransfer/MdocGATTServer.swift | 7 +++++-- Sources/MdocDataTransfer18013/MdocHelpers.swift | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift index d216504..ba8ca88 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift @@ -45,6 +45,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { public var advertising: Bool = false public var error: Error? = nil { willSet { handleErrorSet(newValue) }} public var status: TransferStatus = .initializing { willSet { handleStatusChange(newValue) } } + public var unlockData: [String: Data]! var readBuffer = Data() var sendBuffer = [Data]() var numBlocks: Int = 0 @@ -209,7 +210,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { delegate?.didChangeStatus(newValue) if newValue == .requestReceived { peripheralManager.stopAdvertising() - let decodedRes = MdocHelpers.decodeRequestAndInformUser(deviceEngagement: deviceEngagement, docs: docs, iaca: iaca, requestData: readBuffer, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, readerKeyRawData: nil, handOver: BleTransferMode.QRHandover) + let decodedRes = MdocHelpers.decodeRequestAndInformUser(deviceEngagement: deviceEngagement, docs: docs, iaca: iaca, requestData: readBuffer, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData, readerKeyRawData: nil, handOver: BleTransferMode.QRHandover) switch decodedRes { case .success(let decoded): self.deviceRequest = decoded.deviceRequest @@ -256,7 +257,9 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { if let items { do { let docTypeReq = deviceRequest?.docRequests.first?.itemsRequest.docType ?? "" - guard let (drToSend, _, _) = try MdocHelpers.getDeviceResponseToSend(deviceRequest: deviceRequest!, issuerSigned: docs, selectedItems: items, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption!.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod) else { errorToSend = MdocHelpers.getErrorNoDocuments(docTypeReq); return } + guard let (drToSend, _, _) = try MdocHelpers.getDeviceResponseToSend(deviceRequest: deviceRequest!, issuerSigned: docs, selectedItems: items, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption!.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { + errorToSend = MdocHelpers.getErrorNoDocuments(docTypeReq); return + } guard let dts = drToSend.documents, !dts.isEmpty else { errorToSend = MdocHelpers.getErrorNoDocuments(docTypeReq); return } let dataRes = MdocHelpers.getSessionDataToSend(sessionEncryption: sessionEncryption, status: .requestReceived, docToSend: drToSend) switch dataRes { diff --git a/Sources/MdocDataTransfer18013/MdocHelpers.swift b/Sources/MdocDataTransfer18013/MdocHelpers.swift index 0e1ad8f..b09b407 100644 --- a/Sources/MdocDataTransfer18013/MdocHelpers.swift +++ b/Sources/MdocDataTransfer18013/MdocHelpers.swift @@ -83,7 +83,7 @@ public class MdocHelpers { /// - handOver: handOver structure /// - Returns: A ``DeviceRequest`` object - public static func decodeRequestAndInformUser(deviceEngagement: DeviceEngagement?, docs: [String: IssuerSigned], iaca: [SecCertificate], requestData: Data, devicePrivateKeys: [String: CoseKeyPrivate], dauthMethod: DeviceAuthMethod, readerKeyRawData: [UInt8]?, handOver: CBOR) -> Result<(sessionEncryption: SessionEncryption, deviceRequest: DeviceRequest, userRequestInfo: UserRequestInfo, isValidRequest: Bool), Error> { + public static func decodeRequestAndInformUser(deviceEngagement: DeviceEngagement?, docs: [String: IssuerSigned], iaca: [SecCertificate], requestData: Data, devicePrivateKeys: [String: CoseKeyPrivate], dauthMethod: DeviceAuthMethod, unlockData: [String: Data], readerKeyRawData: [UInt8]?, handOver: CBOR) -> Result<(sessionEncryption: SessionEncryption, deviceRequest: DeviceRequest, userRequestInfo: UserRequestInfo, isValidRequest: Bool), Error> { do { guard let seCbor = try CBOR.decode([UInt8](requestData)) else { logger.error("Request Data is not Cbor"); return .failure(Self.makeError(code: .requestDecodeError)) } guard var se = SessionEstablishment(cbor: seCbor) else { logger.error("Request Data cannot be decoded to session establisment"); return .failure(Self.makeError(code: .requestDecodeError)) } @@ -96,7 +96,7 @@ public class MdocHelpers { guard var sessionEncryption else { logger.error("Session Encryption not initialized"); return .failure(Self.makeError(code: .sessionEncryptionNotInitialized)) } guard let requestData = try sessionEncryption.decrypt(requestCipherData) else { logger.error("Request data cannot be decrypted"); return .failure(Self.makeError(code: .requestDecodeError)) } guard let deviceRequest = DeviceRequest(data: requestData) else { logger.error("Decrypted data cannot be decoded"); return .failure(Self.makeError(code: .requestDecodeError)) } - guard let (drTest, validRequestItems, errorRequestItems) = try Self.getDeviceResponseToSend(deviceRequest: deviceRequest, issuerSigned: docs, selectedItems: nil, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod) else { logger.error("Valid request items nil"); return .failure(Self.makeError(code: .requestDecodeError)) } + guard let (drTest, validRequestItems, errorRequestItems) = try Self.getDeviceResponseToSend(deviceRequest: deviceRequest, issuerSigned: docs, selectedItems: nil, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { logger.error("Valid request items nil"); return .failure(Self.makeError(code: .requestDecodeError)) } let bInvalidReq = (drTest.documents == nil) var userRequestInfo = UserRequestInfo(validItemsRequested: validRequestItems, errorItemsRequested: errorRequestItems) if let docR = deviceRequest.docRequests.first { @@ -122,7 +122,7 @@ public class MdocHelpers { /// - sessionTranscript: Session Transcript object /// - dauthMethod: Mdoc Authentication method /// - Returns: (Device response object, valid requested items, error request items) tuple - public static func getDeviceResponseToSend(deviceRequest: DeviceRequest?, issuerSigned: [String: IssuerSigned], selectedItems: RequestItems? = nil, sessionEncryption: SessionEncryption? = nil, eReaderKey: CoseKey? = nil, devicePrivateKeys: [String: CoseKeyPrivate], sessionTranscript: SessionTranscript? = nil, dauthMethod: DeviceAuthMethod) throws -> (response: DeviceResponse, validRequestItems: RequestItems, errorRequestItems: RequestItems)? { + public static func getDeviceResponseToSend(deviceRequest: DeviceRequest?, issuerSigned: [String: IssuerSigned], selectedItems: RequestItems? = nil, sessionEncryption: SessionEncryption? = nil, eReaderKey: CoseKey? = nil, devicePrivateKeys: [String: CoseKeyPrivate], sessionTranscript: SessionTranscript? = nil, dauthMethod: DeviceAuthMethod, unlockData: [String: Data]) throws -> (response: DeviceResponse, validRequestItems: RequestItems, errorRequestItems: RequestItems)? { var docFiltered = [Document](); var docErrors = [[DocType: UInt64]]() var validReqItemsDocDict = RequestItems(); var errorReqItemsDocDict = RequestItems() guard deviceRequest != nil || selectedItems != nil else { fatalError("Invalid call") } @@ -183,7 +183,7 @@ public class MdocHelpers { if let eReaderKey, let sessionTranscript, let devicePrivateKey { let authKeys = CoseKeyExchange(publicKey: eReaderKey, privateKey: devicePrivateKey) let mdocAuth = MdocAuthentication(transcript: sessionTranscript, authKeys: authKeys) - guard let devAuth = try mdocAuth.getDeviceAuthForTransfer(docType: doc.issuerAuth.mso.docType, dauthMethod: dauthMethod) else { + guard let devAuth = try mdocAuth.getDeviceAuthForTransfer(docType: doc.issuerAuth.mso.docType, dauthMethod: dauthMethod, unlockData: unlockData[reqDocIdOrDocType]) else { logger.error("Cannot create device auth"); return nil } devSignedToAdd = DeviceSigned(deviceAuth: devAuth) From 48445f08764bcc24ec99bbb7f97d526d66814d98 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 20 Nov 2024 01:00:54 +0200 Subject: [PATCH 07/15] Update MdocOfflineDelegate and MdocHelpers to support async handling of requests and session data --- .../BLETransfer/MdocGATTServer.swift | 38 +++++++++++-------- .../BLETransfer/MdocOfflineDelegate.swift | 2 +- .../MdocDataTransfer18013/MdocHelpers.swift | 14 +++---- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift index ba8ca88..bc11564 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocGATTServer.swift @@ -44,7 +44,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { public weak var delegate: (any MdocOfflineDelegate)? public var advertising: Bool = false public var error: Error? = nil { willSet { handleErrorSet(newValue) }} - public var status: TransferStatus = .initializing { willSet { handleStatusChange(newValue) } } + public var status: TransferStatus = .initializing { willSet { Task { @MainActor in await handleStatusChange(newValue) } } } public var unlockData: [String: Data]! var readBuffer = Data() var sendBuffer = [Data]() @@ -61,8 +61,8 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { self.iaca = iaca self.dauthMethod = dauthMethod status = .initialized + initPeripheralManager() initSuccess = true - handleStatusChange(status) } @objc(CBPeripheralManagerDelegate) @@ -136,14 +136,15 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { // Create a new device engagement object and start the device engagement process. /// /// ``qrCodePayload`` is set to QR code data corresponding to the device engagement. - public func performDeviceEngagement(secureArea: any SecureArea, crv: CoseEcCurve, rfus: [String]? = nil) { + public func performDeviceEngagement(secureArea: any SecureArea, crv: CoseEcCurve, rfus: [String]? = nil) async throws { guard !isPreview && !isInErrorState else { logger.info("Current status is \(status)") return } // Check that the class is in the right state to start the device engagement process. It will fail if the class is in any other state. guard status == .initialized || status == .disconnected || status == .responseSent else { error = MdocHelpers.makeError(code: .unexpected_error, str: error?.localizedDescription ?? "Not initialized!"); return } - deviceEngagement = DeviceEngagement(isBleServer: true, crv: crv, secureArea: secureArea, rfus: rfus) + deviceEngagement = DeviceEngagement(isBleServer: true, rfus: rfus) + try await deviceEngagement!.makePrivateKey(crv: crv, secureArea: secureArea) sessionEncryption = nil #if os(iOS) qrCodePayload = deviceEngagement!.getQrCodePayload() @@ -200,17 +201,25 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { qrCodePayload = nil advertising = false subscribeCount = 0 - if let pk = deviceEngagement?.privateKey { try? pk.secureArea.deleteKey(id: pk.privateKeyId); deviceEngagement?.privateKey = nil } + if let pk = deviceEngagement?.privateKey { Task { @MainActor in try? await pk.secureArea.deleteKey(id: pk.privateKeyId); deviceEngagement?.privateKey = nil } } if status == .error && initSuccess { status = .initializing } } - func handleStatusChange(_ newValue: TransferStatus) { + fileprivate func initPeripheralManager() { + guard peripheralManager == nil else { return } + bleDelegate = Delegate(server: self) + logger.info("Initializing BLE peripheral manager") + peripheralManager = CBPeripheralManager(delegate: bleDelegate, queue: nil) + subscribeCount = 0 + } + + func handleStatusChange(_ newValue: TransferStatus) async { guard !isPreview && !isInErrorState else { return } logger.log(level: .info, "Transfer status will change to \(newValue)") delegate?.didChangeStatus(newValue) if newValue == .requestReceived { peripheralManager.stopAdvertising() - let decodedRes = MdocHelpers.decodeRequestAndInformUser(deviceEngagement: deviceEngagement, docs: docs, iaca: iaca, requestData: readBuffer, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData, readerKeyRawData: nil, handOver: BleTransferMode.QRHandover) + let decodedRes = await MdocHelpers.decodeRequestAndInformUser(deviceEngagement: deviceEngagement, docs: docs, iaca: iaca, requestData: readBuffer, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData, readerKeyRawData: nil, handOver: BleTransferMode.QRHandover) switch decodedRes { case .success(let decoded): self.deviceRequest = decoded.deviceRequest @@ -218,7 +227,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { if decoded.isValidRequest { delegate?.didReceiveRequest(decoded.userRequestInfo, handleSelected: userSelected) } else { - userSelected(false, nil) + await userSelected(false, nil) } case .failure(let err): error = err @@ -226,10 +235,7 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { } } else if newValue == .initialized { - bleDelegate = Delegate(server: self) - logger.info("Initializing BLE peripheral manager") - peripheralManager = CBPeripheralManager(delegate: bleDelegate, queue: nil) - subscribeCount = 0 + initPeripheralManager() } else if newValue == .disconnected && status != .disconnected { stop() } @@ -241,9 +247,9 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { var isInErrorState: Bool { status == .error } - public func userSelected(_ b: Bool, _ items: RequestItems?) { + public func userSelected(_ b: Bool, _ items: RequestItems?) async { status = .userSelected - let resError = MdocHelpers.getSessionDataToSend(sessionEncryption: sessionEncryption, status: .error, docToSend: DeviceResponse(status: 0)) + let resError = await MdocHelpers.getSessionDataToSend(sessionEncryption: sessionEncryption, status: .error, docToSend: DeviceResponse(status: 0)) var bytesToSend = try! resError.get() var errorToSend: Error? defer { @@ -257,11 +263,11 @@ public class MdocGattServer: @unchecked Sendable, ObservableObject { if let items { do { let docTypeReq = deviceRequest?.docRequests.first?.itemsRequest.docType ?? "" - guard let (drToSend, _, _) = try MdocHelpers.getDeviceResponseToSend(deviceRequest: deviceRequest!, issuerSigned: docs, selectedItems: items, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption!.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { + guard let (drToSend, _, _) = try await MdocHelpers.getDeviceResponseToSend(deviceRequest: deviceRequest!, issuerSigned: docs, selectedItems: items, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption!.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { errorToSend = MdocHelpers.getErrorNoDocuments(docTypeReq); return } guard let dts = drToSend.documents, !dts.isEmpty else { errorToSend = MdocHelpers.getErrorNoDocuments(docTypeReq); return } - let dataRes = MdocHelpers.getSessionDataToSend(sessionEncryption: sessionEncryption, status: .requestReceived, docToSend: drToSend) + let dataRes = await MdocHelpers.getSessionDataToSend(sessionEncryption: sessionEncryption, status: .requestReceived, docToSend: drToSend) switch dataRes { case .success(let bytes): bytesToSend = bytes diff --git a/Sources/MdocDataTransfer18013/BLETransfer/MdocOfflineDelegate.swift b/Sources/MdocDataTransfer18013/BLETransfer/MdocOfflineDelegate.swift index 703bc5c..8f1f0d1 100644 --- a/Sources/MdocDataTransfer18013/BLETransfer/MdocOfflineDelegate.swift +++ b/Sources/MdocDataTransfer18013/BLETransfer/MdocOfflineDelegate.swift @@ -9,7 +9,7 @@ import MdocSecurity18013 public protocol MdocOfflineDelegate: AnyObject { func didChangeStatus(_ newStatus: TransferStatus) func didFinishedWithError(_ error: Error) - func didReceiveRequest(_ request: UserRequestInfo, handleSelected: @escaping (Bool, RequestItems?) -> Void) + func didReceiveRequest(_ request: UserRequestInfo, handleSelected: @escaping (Bool, RequestItems?) async -> Void) } diff --git a/Sources/MdocDataTransfer18013/MdocHelpers.swift b/Sources/MdocDataTransfer18013/MdocHelpers.swift index 3dd7a06..461ed35 100644 --- a/Sources/MdocDataTransfer18013/MdocHelpers.swift +++ b/Sources/MdocDataTransfer18013/MdocHelpers.swift @@ -61,13 +61,13 @@ public class MdocHelpers { return NSError(domain: "\(MdocGattServer.self)", code: code.rawValue, userInfo: [NSLocalizedDescriptionKey: errorMessage, "key": code.description]) } - public static func getSessionDataToSend(sessionEncryption: SessionEncryption?, status: TransferStatus, docToSend: DeviceResponse) -> Result { + public static func getSessionDataToSend(sessionEncryption: SessionEncryption?, status: TransferStatus, docToSend: DeviceResponse) async -> Result { do { guard var sessionEncryption else { logger.error("Session Encryption not initialized"); return .failure(Self.makeError(code: .sessionEncryptionNotInitialized)) } if docToSend.documents == nil { logger.error("Could not create documents to send") } let cborToSend = docToSend.toCBOR(options: CBOROptions()) let clearBytesToSend = cborToSend.encode() - let cipherData = try sessionEncryption.encrypt(clearBytesToSend) + let cipherData = try await sessionEncryption.encrypt(clearBytesToSend) let sd = SessionData(cipher_data: status == .error ? nil : cipherData, status: status == .error ? 11 : 20) return .success(Data(sd.encode(options: CBOROptions()))) } catch { return .failure(error) } @@ -83,7 +83,7 @@ public class MdocHelpers { /// - handOver: handOver structure /// - Returns: A ``DeviceRequest`` object - public static func decodeRequestAndInformUser(deviceEngagement: DeviceEngagement?, docs: [String: IssuerSigned], iaca: [SecCertificate], requestData: Data, devicePrivateKeys: [String: CoseKeyPrivate], dauthMethod: DeviceAuthMethod, unlockData: [String: Data], readerKeyRawData: [UInt8]?, handOver: CBOR) -> Result<(sessionEncryption: SessionEncryption, deviceRequest: DeviceRequest, userRequestInfo: UserRequestInfo, isValidRequest: Bool), Error> { + public static func decodeRequestAndInformUser(deviceEngagement: DeviceEngagement?, docs: [String: IssuerSigned], iaca: [SecCertificate], requestData: Data, devicePrivateKeys: [String: CoseKeyPrivate], dauthMethod: DeviceAuthMethod, unlockData: [String: Data], readerKeyRawData: [UInt8]?, handOver: CBOR) async -> Result<(sessionEncryption: SessionEncryption, deviceRequest: DeviceRequest, userRequestInfo: UserRequestInfo, isValidRequest: Bool), Error> { do { guard let seCbor = try CBOR.decode([UInt8](requestData)) else { logger.error("Request Data is not Cbor"); return .failure(Self.makeError(code: .requestDecodeError)) } guard var se = SessionEstablishment(cbor: seCbor) else { logger.error("Request Data cannot be decoded to session establisment"); return .failure(Self.makeError(code: .requestDecodeError)) } @@ -94,9 +94,9 @@ public class MdocHelpers { // init session-encryption object from session establish message and device engagement, decrypt data let sessionEncryption = SessionEncryption(se: se, de: deviceEngagement, handOver: handOver) guard var sessionEncryption else { logger.error("Session Encryption not initialized"); return .failure(Self.makeError(code: .sessionEncryptionNotInitialized)) } - guard let requestData = try sessionEncryption.decrypt(requestCipherData) else { logger.error("Request data cannot be decrypted"); return .failure(Self.makeError(code: .requestDecodeError)) } + guard let requestData = try await sessionEncryption.decrypt(requestCipherData) else { logger.error("Request data cannot be decrypted"); return .failure(Self.makeError(code: .requestDecodeError)) } guard let deviceRequest = DeviceRequest(data: requestData) else { logger.error("Decrypted data cannot be decoded"); return .failure(Self.makeError(code: .requestDecodeError)) } - guard let (drTest, validRequestItems, errorRequestItems) = try Self.getDeviceResponseToSend(deviceRequest: deviceRequest, issuerSigned: docs, selectedItems: nil, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { logger.error("Valid request items nil"); return .failure(Self.makeError(code: .requestDecodeError)) } + guard let (drTest, validRequestItems, errorRequestItems) = try await Self.getDeviceResponseToSend(deviceRequest: deviceRequest, issuerSigned: docs, selectedItems: nil, sessionEncryption: sessionEncryption, eReaderKey: sessionEncryption.sessionKeys.publicKey, devicePrivateKeys: devicePrivateKeys, dauthMethod: dauthMethod, unlockData: unlockData) else { logger.error("Valid request items nil"); return .failure(Self.makeError(code: .requestDecodeError)) } let bInvalidReq = (drTest.documents == nil) var userRequestInfo = UserRequestInfo(validItemsRequested: validRequestItems, errorItemsRequested: errorRequestItems) if let docR = deviceRequest.docRequests.first { @@ -122,7 +122,7 @@ public class MdocHelpers { /// - sessionTranscript: Session Transcript object /// - dauthMethod: Mdoc Authentication method /// - Returns: (Device response object, valid requested items, error request items) tuple - public static func getDeviceResponseToSend(deviceRequest: DeviceRequest?, issuerSigned: [String: IssuerSigned], selectedItems: RequestItems? = nil, sessionEncryption: SessionEncryption? = nil, eReaderKey: CoseKey? = nil, devicePrivateKeys: [String: CoseKeyPrivate], sessionTranscript: SessionTranscript? = nil, dauthMethod: DeviceAuthMethod, unlockData: [String: Data]) throws -> (response: DeviceResponse, validRequestItems: RequestItems, errorRequestItems: RequestItems)? { + public static func getDeviceResponseToSend(deviceRequest: DeviceRequest?, issuerSigned: [String: IssuerSigned], selectedItems: RequestItems? = nil, sessionEncryption: SessionEncryption? = nil, eReaderKey: CoseKey? = nil, devicePrivateKeys: [String: CoseKeyPrivate], sessionTranscript: SessionTranscript? = nil, dauthMethod: DeviceAuthMethod, unlockData: [String: Data]) async throws -> (response: DeviceResponse, validRequestItems: RequestItems, errorRequestItems: RequestItems)? { var docFiltered = [Document](); var docErrors = [[DocType: UInt64]]() var validReqItemsDocDict = RequestItems(); var errorReqItemsDocDict = RequestItems() guard deviceRequest != nil || selectedItems != nil else { fatalError("Invalid call") } @@ -183,7 +183,7 @@ public class MdocHelpers { if let eReaderKey, let sessionTranscript, let devicePrivateKey { let authKeys = CoseKeyExchange(publicKey: eReaderKey, privateKey: devicePrivateKey) let mdocAuth = MdocAuthentication(transcript: sessionTranscript, authKeys: authKeys) - guard let devAuth = try mdocAuth.getDeviceAuthForTransfer(docType: doc.issuerAuth.mso.docType, dauthMethod: dauthMethod, unlockData: unlockData[reqDocIdOrDocType]) else { + guard let devAuth = try await mdocAuth.getDeviceAuthForTransfer(docType: doc.issuerAuth.mso.docType, dauthMethod: dauthMethod, unlockData: unlockData[reqDocIdOrDocType]) else { logger.error("Cannot create device auth"); return nil } devSignedToAdd = DeviceSigned(deviceAuth: devAuth) From 7c476a1fa8e034830963faff68422ead5d7fc5e0 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 20 Nov 2024 22:02:52 +0200 Subject: [PATCH 08/15] Update package dependencies to use the SecureArea branch for eudi-lib-ios-iso18013-security --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 6dac242..f10f439 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,8 @@ let package = Package( targets: ["MdocDataTransfer18013"]), ], dependencies: [ - .package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-data-model.git", exact: "0.3.3"), - .package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", exact: "0.2.6"), + .package(url: "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", branch: "SecureArea"), + //.package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", exact: "0.2.6"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. From dfc8eeeb54f976eb393f023c377aab239e28fca9 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 20 Nov 2024 22:08:28 +0200 Subject: [PATCH 09/15] Remove dependency on MdocDataModel18013 from MdocDataTransfer18013 target --- Package.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Package.swift b/Package.swift index f10f439..130ba66 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,6 @@ let package = Package( // Targets can depend on other targets in this package and products from dependencies. .target( name: "MdocDataTransfer18013", dependencies: [ - .product(name: "MdocDataModel18013", package: "eudi-lib-ios-iso18013-data-model"), .product(name: "MdocSecurity18013", package: "eudi-lib-ios-iso18013-security")]), .testTarget( name: "MdocDataTransfer18013Tests", From 66060552751e7d659773f292b3dd9a8cd0c8f816 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 20 Nov 2024 22:27:12 +0200 Subject: [PATCH 10/15] Update package dependencies to point to the SecureArea branch and upgrade versions --- Package.resolved | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Package.resolved b/Package.resolved index feca750..6fb452b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,22 +1,22 @@ { - "originHash" : "fc60708f41996a66ff09913bb5bc0934ff3d47779d3ec833bf24adbed0bb2ad4", + "originHash" : "af712ed5751a7044bc20ef8bc52362e56d7873557161d98e6a526212d9b08a74", "pins" : [ { "identity" : "eudi-lib-ios-iso18013-data-model", "kind" : "remoteSourceControl", - "location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-data-model.git", + "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-data-model.git", "state" : { - "revision" : "c1b4383d6fc3387a8ed4c79177548624c4e34e3a", - "version" : "0.3.3" + "branch" : "SecureArea", + "revision" : "cf7926fcdf85d1c7fc40a051dea112737b372a5a" } }, { "identity" : "eudi-lib-ios-iso18013-security", "kind" : "remoteSourceControl", - "location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", + "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", "state" : { - "revision" : "13d65a1010ee9e6219f8bccbab6eb32f67405d86", - "version" : "0.2.6" + "branch" : "SecureArea", + "revision" : "b91fe696b130aa3bd1ae5f016341f76d4965d0d7" } }, { @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-asn1.git", "state" : { - "revision" : "c7e239b5c1492ffc3ebd7fbcc7a92548ce4e78f0", - "version" : "1.1.0" + "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", + "version" : "1.3.0" } }, { @@ -33,8 +33,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-certificates.git", "state" : { - "revision" : "4688f242811d21a9c7a8ad669b3bc5b336759929", - "version" : "1.4.0" + "revision" : "1fbb6ef21f1525ed5faf4c95207b9c11bea27e94", + "version" : "1.6.1" } }, { @@ -51,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-crypto.git", "state" : { - "revision" : "46072478ca365fe48370993833cb22de9b41567f", - "version" : "3.5.2" + "revision" : "06dc63c6d8da54ee11ceb268cde1fa68161afc96", + "version" : "3.9.1" } }, { From dc1a5d3220d5982f4ea1ad155752472dded12da8 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Wed, 20 Nov 2024 23:34:32 +0200 Subject: [PATCH 11/15] Update package dependencies to use the latest revisions on the SecureArea branch --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 6fb452b..d352938 100644 --- a/Package.resolved +++ b/Package.resolved @@ -7,7 +7,7 @@ "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-data-model.git", "state" : { "branch" : "SecureArea", - "revision" : "cf7926fcdf85d1c7fc40a051dea112737b372a5a" + "revision" : "48a78884b22d8d1abd0d26138a7712f684c8157c" } }, { @@ -16,7 +16,7 @@ "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", "state" : { "branch" : "SecureArea", - "revision" : "b91fe696b130aa3bd1ae5f016341f76d4965d0d7" + "revision" : "19ac64e98219592bbe6cee64cbb6f3fb4de26d92" } }, { From 56909b8c4c942f1cd677c85cbd0a07b6be7084da Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Thu, 21 Nov 2024 00:31:49 +0200 Subject: [PATCH 12/15] Update package dependencies to use the latest revisions on the SecureArea branch --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index d352938..0fc5c1f 100644 --- a/Package.resolved +++ b/Package.resolved @@ -7,7 +7,7 @@ "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-data-model.git", "state" : { "branch" : "SecureArea", - "revision" : "48a78884b22d8d1abd0d26138a7712f684c8157c" + "revision" : "c31db98a1436e9b6ada82caa1905b1eb65586cbc" } }, { @@ -16,7 +16,7 @@ "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", "state" : { "branch" : "SecureArea", - "revision" : "19ac64e98219592bbe6cee64cbb6f3fb4de26d92" + "revision" : "64044b21e1efaa9acf96ecd13b17a158928893bc" } }, { From e9f4aca463a6beafca8dd28f28f5eb9057d2f811 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Thu, 28 Nov 2024 09:53:38 +0200 Subject: [PATCH 13/15] Update package dependencies to point to the eu-digital-identity-wallet security repository 0.3.0 --- Package.resolved | 22 +++++++++++----------- Package.swift | 3 +-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Package.resolved b/Package.resolved index 0fc5c1f..b35df81 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,22 +1,22 @@ { - "originHash" : "af712ed5751a7044bc20ef8bc52362e56d7873557161d98e6a526212d9b08a74", + "originHash" : "aba63bdc14b9431049b57af2080cd340ba4da0baa6a3bfbb3ffb8740ed9dfed2", "pins" : [ { "identity" : "eudi-lib-ios-iso18013-data-model", "kind" : "remoteSourceControl", - "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-data-model.git", + "location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-data-model.git", "state" : { - "branch" : "SecureArea", - "revision" : "c31db98a1436e9b6ada82caa1905b1eb65586cbc" + "revision" : "29f30a92427733db0c7b9cea9616607a1df24284", + "version" : "0.4.0" } }, { "identity" : "eudi-lib-ios-iso18013-security", "kind" : "remoteSourceControl", - "location" : "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", + "location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", "state" : { - "branch" : "SecureArea", - "revision" : "64044b21e1efaa9acf96ecd13b17a158928893bc" + "revision" : "6d335f19cb5bdb590bf2f5557c4d91dda146555b", + "version" : "0.3.0" } }, { @@ -51,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-crypto.git", "state" : { - "revision" : "06dc63c6d8da54ee11ceb268cde1fa68161afc96", - "version" : "3.9.1" + "revision" : "ff0f781cf7c6a22d52957e50b104f5768b50c779", + "version" : "3.10.0" } }, { @@ -60,8 +60,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log.git", "state" : { - "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", - "version" : "1.6.1" + "revision" : "96a2f8a0fa41e9e09af4585e2724c4e825410b91", + "version" : "1.6.2" } }, { diff --git a/Package.swift b/Package.swift index 130ba66..e5e2ebd 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,7 @@ let package = Package( targets: ["MdocDataTransfer18013"]), ], dependencies: [ - .package(url: "https://github.com/niscy-eudiw/eudi-lib-ios-iso18013-security.git", branch: "SecureArea"), - //.package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", exact: "0.2.6"), + .package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git", exact: "0.3.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. From 45fba33ceddad6b8954d258c56b25e147dc8f645 Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Thu, 28 Nov 2024 10:18:20 +0200 Subject: [PATCH 14/15] Update Xcode version to 16.1 in CI workflow --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 9686010..2dbf0ff 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.0' + xcode-version: '16.1' - name: Get swift version run: swift --version - uses: actions/checkout@v4 From 6504a4f5e1ed873f52279fd30775bb170cac983e Mon Sep 17 00:00:00 2001 From: Filippos Sakellaropoulos Date: Thu, 28 Nov 2024 10:21:33 +0200 Subject: [PATCH 15/15] Update pull request trigger types to include 'edited' --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 2dbf0ff..07e70e8 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -4,7 +4,7 @@ name: Swift on: pull_request: - types: [opened, reopened] + types: [opened, reopened, edited] push: branches: ['main'] tags: [ v* ]