Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public actor ConfigurationLoader: ConfigurationLoaderProtocol, Loggable {
else {
throw ConfigurationLoaderError.publicKeyNotFound
}

let signatureFile = configDir.appending(
path: CommonsLib.Constants.Configuration.CachedConfigEcc
)
Expand Down
6 changes: 6 additions & 0 deletions RIADigiDoc.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@
Domain/NFC/OperationReadCardData.swift,
Domain/NFC/OperationReadCertAndSign.swift,
Domain/NFC/OperationUnblockPin.swift,
Domain/NFC/Protocols/OperationChangePinProtocol.swift,
Domain/NFC/Protocols/OperationDecryptProtocol.swift,
Domain/NFC/Protocols/OperationReadCardDataProtocol.swift,
Domain/NFC/Protocols/OperationReadCertAndSignProtocol.swift,
Domain/NFC/Protocols/OperationUnblockPinProtocol.swift,
Domain/Preferences/DataStore.swift,
Domain/Preferences/DataStoreProtocol.swift,
Domain/Preferences/KeychainStore.swift,
Expand Down Expand Up @@ -222,6 +227,7 @@
Util/Certificate/CertificateUtil.swift,
Util/Certificate/CertificateUtilProtocol.swift,
Util/EncryptedData/EncryptedDataUtil.swift,
Util/EncryptedData/EncryptedDataUtilProtocol.swift,
Util/File/FileInspector.swift,
Util/File/FileInspectorProtocol.swift,
Util/Language/LanguageSettings.swift,
Expand Down
54 changes: 52 additions & 2 deletions RIADigiDoc/DI/AppContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,50 @@ extension Container {
userAgentUtil: self.userAgentUtil(),
certificateUtil: self.certificateUtil(),
sharedMyEidSession: self.sharedMyEidSession(),
keychainStore: self.keychainStore()
keychainStore: self.keychainStore(),
encryptedDataUtil: self.encryptedDataUtil(),
operationReadCertAndSign: self.operationReadCertAndSign(),
operationReadCardData: self.operationReadCardData(),
operationDecrypt: self.operationDecrypt()
)
}
}

@MainActor
var operationReadCertAndSign: Factory<OperationReadCertAndSign> {
self { @MainActor in
OperationReadCertAndSign()
}
}

@MainActor
var operationReadCardData: Factory<OperationReadCardData> {
self { @MainActor in
OperationReadCardData()
}
}

@MainActor
var operationDecrypt: Factory<OperationDecrypt> {
self { @MainActor in
OperationDecrypt()
}
}

@MainActor
var operationChangePin: Factory<OperationChangePin> {
self { @MainActor in
OperationChangePin()
}
}

@MainActor
var operationUnblockPin: Factory<OperationUnblockPin> {
self { @MainActor in
OperationUnblockPin()
}
}

@MainActor
var myEidRootViewModel: Factory<MyEidRootViewModel> {
self { @MainActor in
Expand Down Expand Up @@ -540,13 +579,24 @@ extension Container {
personalCode: personalCode,
actionMethod: actionMethod,
idCardRepository: self.idCardRepository(),
sharedMyEidSession: self.sharedMyEidSession()
sharedMyEidSession: self.sharedMyEidSession(),
operationChangePin: self.operationChangePin(),
operationUnblockPin: self.operationUnblockPin()
)
}
}
// swiftlint:enable closure_parameter_position
// swiftlint:enable large_tuple

@MainActor
var encryptedDataUtil: Factory<EncryptedDataUtilProtocol> {
self { @MainActor in
EncryptedDataUtil(
fileManager: self.fileManager()
)
}
}

@MainActor
var crashReportManager: Factory<CrashReportManager> {
self { @MainActor in
Expand Down
31 changes: 31 additions & 0 deletions RIADigiDoc/Domain/NFC/NFCOperationBase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class NFCOperationBase: NSObject, Loggable, @MainActor NFCTagReaderSessio
var canNumber: String = ""
var nfcError: String = ""
var strings: NFCSessionStrings?
private var didResumeContinuation = false

let connection = NFCConnection()

Expand Down Expand Up @@ -104,6 +105,36 @@ public class NFCOperationBase: NSObject, Loggable, @MainActor NFCTagReaderSessio
return false
}

func resumeContinuation<T: Sendable>(
_ continuation: inout CheckedContinuation<T, Error>?,
with value: T
) {
guard !didResumeContinuation else {
Self.logger().warning("NFC: Attempted to resume continuation that was already resumed")
return
}
didResumeContinuation = true
continuation?.resume(returning: value)
continuation = nil
}

func resumeContinuation<T: Sendable>(
_ continuation: inout CheckedContinuation<T, Error>?,
throwing error: Error
) {
guard !didResumeContinuation else {
Self.logger().warning("NFC: Attempted to resume continuation that was already resumed (error case)")
return
}
didResumeContinuation = true
continuation?.resume(throwing: error)
continuation = nil
}

func resetContinuationState() {
didResumeContinuation = false
}

// MARK: - NFCTagReaderSessionDelegate

public func tagReaderSessionDidBecomeActive(_: NFCTagReaderSession) { }
Expand Down
32 changes: 17 additions & 15 deletions RIADigiDoc/Domain/NFC/OperationChangePin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import UtilsLib
import IdCardLib

@MainActor
public class OperationChangePin: NFCOperationBase {
public class OperationChangePin: NFCOperationBase, OperationChangePinProtocol {
private var codeType: CodeType?
private var currentPin: SecureData?
private var newPin: SecureData?
Expand All @@ -38,9 +38,10 @@ public class OperationChangePin: NFCOperationBase {
) async throws {
return try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
self.resetContinuationState()

guard NFCTagReaderSession.readingAvailable else {
continuation.resume(throwing: IdCardInternalError.nfcNotSupported)
resumeContinuation(&self.continuation, throwing: IdCardInternalError.nfcNotSupported)
return
}

Expand Down Expand Up @@ -70,7 +71,7 @@ public class OperationChangePin: NFCOperationBase {
OperationChangePin.logger().error("NFC: \(error.localizedDescription)")
session.invalidate(errorMessage: strings?.technicalErrorMessage ??
"Missing required parameters")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

Expand All @@ -87,27 +88,27 @@ public class OperationChangePin: NFCOperationBase {
try await cardCommands.changeCode(codeType, to: newPin, verifyCode: currentPin)
OperationChangePin.logger().info("NFC: \(codeType.name) changed successfully")

self.continuation?.resume(with: .success(()))
resumeContinuation(&self.continuation, with: ())
success()
} catch {
guard !checkIfFinished(error: error) else { return }

if let idCardInternalError = error as? IdCardInternalError {
handleIdCardInternalError(idCardInternalError, session: session)
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

if let changePinError = error as? ChangePinError {
OperationChangePin.logger()
.error("NFC: changePinError: \(changePinError.localizedDescription)")
session.invalidate(errorMessage: strings?.technicalErrorMessage ?? "")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

let wrappedError = UnblockPINError.unknown(handleUnknownError(error, session: session))
continuation?.resume(throwing: wrappedError)
resumeContinuation(&self.continuation, throwing: wrappedError)
}
}
}
Expand All @@ -116,17 +117,18 @@ public class OperationChangePin: NFCOperationBase {
self.session = nil
guard !isFinished else { return }
isFinished = true
if let nfcError = error as? NFCReaderError {
switch nfcError.code {
case .readerSessionInvalidationErrorUserCanceled:
continuation?.resume(throwing: IdCardInternalError.cancelledByUser)
return

if let readerError = error as? NFCReaderError {
switch readerError.code {
case .readerSessionInvalidationErrorUserCanceled:
Self.logger().info("NFC: Session was cancelled by user")
resumeContinuation(&self.continuation, throwing: IdCardInternalError.cancelledByUser)
default:
break
Self.logger().error("NFC: Session invalidated with error: \(error.localizedDescription)")
resumeContinuation(&self.continuation, throwing: error)
}
} else {
resumeContinuation(&self.continuation, throwing: error)
}
continuation?.resume(throwing: error)
}

}
35 changes: 19 additions & 16 deletions RIADigiDoc/Domain/NFC/OperationDecrypt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import CryptoSwift
import UtilsLib

@MainActor
public class OperationDecrypt: NFCOperationBase {
public class OperationDecrypt: NFCOperationBase, OperationDecryptProtocol {
private var containerFile: URL?
private var recipients: [Addressee] = []
private var pin1Number: SecureData = SecureData([0x00])
Expand All @@ -46,9 +46,10 @@ public class OperationDecrypt: NFCOperationBase {

return try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
self.resetContinuationState()

guard NFCTagReaderSession.readingAvailable else {
continuation.resume(throwing: IdCardInternalError.nfcNotSupported)
resumeContinuation(&self.continuation, throwing: IdCardInternalError.nfcNotSupported)
return
}
self.canNumber = canNumber
Expand Down Expand Up @@ -76,7 +77,7 @@ public class OperationDecrypt: NFCOperationBase {
OperationDecrypt.logger().error("NFC: \(error.localizedDescription)")
session.invalidate(errorMessage: strings?.technicalErrorMessage ??
"Failed to read container file")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

Expand All @@ -85,7 +86,7 @@ public class OperationDecrypt: NFCOperationBase {
OperationDecrypt.logger().error("NFC: Container file path is empty")
session.invalidate(errorMessage: strings?.technicalErrorMessage ??
"Failed to read container file")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

Expand All @@ -94,7 +95,7 @@ public class OperationDecrypt: NFCOperationBase {
OperationDecrypt.logger().error("NFC: \(error.localizedDescription)")
session.invalidate(errorMessage: strings?.technicalErrorMessage ??
"No recipients found")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

Expand Down Expand Up @@ -122,27 +123,27 @@ public class OperationDecrypt: NFCOperationBase {
cardCommands: cardCommands,
pin: pin1Number,
)
continuation?.resume(with: .success(decryptedContainer))
resumeContinuation(&self.continuation, with: decryptedContainer)
success()
} catch {
guard !checkIfFinished(error: error) else { return }

if let idCardInternalError = error as? IdCardInternalError {
handleIdCardInternalError(idCardInternalError, session: session)
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

if let decryptError = error as? DecryptError {
OperationDecrypt.logger()
.error("NFC: DecryptError: \(decryptError.localizedDescription)")
session.invalidate(errorMessage: strings?.technicalErrorMessage ?? "")
continuation?.resume(throwing: error)
resumeContinuation(&self.continuation, throwing: error)
return
}

let wrappedError = DecryptError.unknown(handleUnknownError(error, session: session))
continuation?.resume(throwing: wrappedError)
resumeContinuation(&self.continuation, throwing: wrappedError)
}
}
}
Expand All @@ -151,16 +152,18 @@ public class OperationDecrypt: NFCOperationBase {
self.session = nil
guard !isFinished else { return }
isFinished = true
if let nfcError = error as? NFCReaderError {
switch nfcError.code {
case .readerSessionInvalidationErrorUserCanceled:
continuation?.resume(throwing: IdCardInternalError.cancelledByUser)
return

if let readerError = error as? NFCReaderError {
switch readerError.code {
case .readerSessionInvalidationErrorUserCanceled:
Self.logger().info("NFC: Session was cancelled by user")
resumeContinuation(&self.continuation, throwing: IdCardInternalError.cancelledByUser)
default:
break
Self.logger().error("NFC: Session invalidated with error: \(error.localizedDescription)")
resumeContinuation(&self.continuation, throwing: error)
}
} else {
resumeContinuation(&self.continuation, throwing: error)
}
continuation?.resume(throwing: error)
}
}
Loading