From 4855f1b530511b1f6fe7b843cdc48f182cd0643a Mon Sep 17 00:00:00 2001 From: Marten Rebane Date: Tue, 31 Mar 2026 15:47:26 +0300 Subject: [PATCH 1/2] Fix error messages when decrypting with wrong card --- RIADigiDoc/Domain/NFC/NFCOperationBase.swift | 11 +++++++++- RIADigiDoc/Domain/NFC/NFCSessionStrings.swift | 1 + .../Domain/NFC/NFCSessionStringsUtil.swift | 2 ++ .../Domain/NFC/OperationChangePin.swift | 5 +++++ RIADigiDoc/Domain/NFC/OperationDecrypt.swift | 5 +++++ .../Domain/NFC/OperationReadCardData.swift | 5 +++++ .../Domain/NFC/OperationReadCertAndSign.swift | 5 +++++ .../Domain/NFC/OperationUnblockPin.swift | 5 +++++ .../Supporting files/Localizable.xcstrings | 18 +++++++++++++++ .../Container/Signing/IdCard/IdCardView.swift | 1 - .../Signing/IdCard/IdCardViewModel.swift | 22 ++++++++++++++----- 11 files changed, 72 insertions(+), 8 deletions(-) diff --git a/RIADigiDoc/Domain/NFC/NFCOperationBase.swift b/RIADigiDoc/Domain/NFC/NFCOperationBase.swift index 865034c8..a310960c 100644 --- a/RIADigiDoc/Domain/NFC/NFCOperationBase.swift +++ b/RIADigiDoc/Domain/NFC/NFCOperationBase.swift @@ -78,7 +78,16 @@ public class NFCOperationBase: NSObject, Loggable, @MainActor NFCTagReaderSessio nfcError = strings?.technicalErrorMessage ?? "" } } - + + func handleNoCertLockError( + error: Error, + session: NFCTagReaderSession + ) { + Self.logger().error("NFC: Failed to find lock for cert") + nfcError = strings?.wrongCardErrorMessage ?? "" + session.invalidate(errorMessage: nfcError) + } + func handleIdCardInternalError( _ error: IdCardInternalError, session: NFCTagReaderSession diff --git a/RIADigiDoc/Domain/NFC/NFCSessionStrings.swift b/RIADigiDoc/Domain/NFC/NFCSessionStrings.swift index ae0a8e1d..64792b8a 100644 --- a/RIADigiDoc/Domain/NFC/NFCSessionStrings.swift +++ b/RIADigiDoc/Domain/NFC/NFCSessionStrings.swift @@ -28,6 +28,7 @@ public struct NFCSessionStrings: Sendable { let pinWrongMultipleErrorMessage: String let pinWrongErrorMessage: String let pinBlockedErrorMessage: String + let wrongCardErrorMessage: String let technicalErrorMessage: String let sessionErrorMessage: String let ocspTimeslotErrorMessage: String diff --git a/RIADigiDoc/Domain/NFC/NFCSessionStringsUtil.swift b/RIADigiDoc/Domain/NFC/NFCSessionStringsUtil.swift index 480d3bfd..8f12c0b5 100644 --- a/RIADigiDoc/Domain/NFC/NFCSessionStringsUtil.swift +++ b/RIADigiDoc/Domain/NFC/NFCSessionStringsUtil.swift @@ -76,6 +76,7 @@ public struct NFCSessionStringsUtil { pinWrongMultipleErrorMessage: String? = nil, pinWrongErrorMessage: String? = nil, pinBlockedErrorMessage: String? = nil, + wrongCardErrorMessage: String? = nil, technicalErrorMessage: String? = nil, sessionErrorMessage: String? = nil, ocspTimeslotErrorMessage: String? = nil, @@ -103,6 +104,7 @@ public struct NFCSessionStringsUtil { "PIN blocked", [pinAction == .unblock ? CodeType.puk.name : pinName] ), + wrongCardErrorMessage: wrongCardErrorMessage ?? localize("Failed to find lock for cert", []), technicalErrorMessage: technicalErrorMessage ?? localize("NFC technical error", []), sessionErrorMessage: sessionErrorMessage ?? localize("NFC session error", []), ocspTimeslotErrorMessage: ocspTimeslotErrorMessage ?? localize("OCSP response not in valid time slot", []), diff --git a/RIADigiDoc/Domain/NFC/OperationChangePin.swift b/RIADigiDoc/Domain/NFC/OperationChangePin.swift index a3efeac8..a7afc783 100644 --- a/RIADigiDoc/Domain/NFC/OperationChangePin.swift +++ b/RIADigiDoc/Domain/NFC/OperationChangePin.swift @@ -89,6 +89,11 @@ public class OperationChangePin: NFCOperationBase, OperationChangePinProtocol { success() } catch { + if (error as NSError).localizedDescription == "Failed to find lock for cert" { + handleNoCertLockError(error: error, session: session) + return + } + if let idCardInternalError = error as? IdCardInternalError { handleIdCardInternalError(idCardInternalError, session: session) return diff --git a/RIADigiDoc/Domain/NFC/OperationDecrypt.swift b/RIADigiDoc/Domain/NFC/OperationDecrypt.swift index 9a28d9f7..48142a1b 100644 --- a/RIADigiDoc/Domain/NFC/OperationDecrypt.swift +++ b/RIADigiDoc/Domain/NFC/OperationDecrypt.swift @@ -126,6 +126,11 @@ public class OperationDecrypt: NFCOperationBase, OperationDecryptProtocol { success() } catch { + if (error as NSError).localizedDescription == "Failed to find lock for cert" { + handleNoCertLockError(error: error, session: session) + return + } + if let idCardInternalError = error as? IdCardInternalError { handleIdCardInternalError(idCardInternalError, session: session) return diff --git a/RIADigiDoc/Domain/NFC/OperationReadCardData.swift b/RIADigiDoc/Domain/NFC/OperationReadCardData.swift index fb7050f7..8f77cda4 100644 --- a/RIADigiDoc/Domain/NFC/OperationReadCardData.swift +++ b/RIADigiDoc/Domain/NFC/OperationReadCardData.swift @@ -112,6 +112,11 @@ final public class OperationReadCardData: NFCOperationBase, OperationReadCardDat success() } catch { + if (error as NSError).localizedDescription == "Failed to find lock for cert" { + handleNoCertLockError(error: error, session: session) + return + } + if let idCardInternalError = error as? IdCardInternalError { handleIdCardInternalError(idCardInternalError, session: session) return diff --git a/RIADigiDoc/Domain/NFC/OperationReadCertAndSign.swift b/RIADigiDoc/Domain/NFC/OperationReadCertAndSign.swift index b129073c..07fc335e 100644 --- a/RIADigiDoc/Domain/NFC/OperationReadCertAndSign.swift +++ b/RIADigiDoc/Domain/NFC/OperationReadCertAndSign.swift @@ -152,6 +152,11 @@ public class OperationReadCertAndSign: NFCOperationBase, OperationReadCertAndSig success() } catch { + if (error as NSError).localizedDescription == "Failed to find lock for cert" { + handleNoCertLockError(error: error, session: session) + return + } + if let idCardInternalError = error as? IdCardInternalError { handleIdCardInternalError(idCardInternalError, session: session) return diff --git a/RIADigiDoc/Domain/NFC/OperationUnblockPin.swift b/RIADigiDoc/Domain/NFC/OperationUnblockPin.swift index ac9f690b..feb97bd0 100644 --- a/RIADigiDoc/Domain/NFC/OperationUnblockPin.swift +++ b/RIADigiDoc/Domain/NFC/OperationUnblockPin.swift @@ -89,6 +89,11 @@ public class OperationUnblockPin: NFCOperationBase, OperationUnblockPinProtocol success() } catch { + if (error as NSError).localizedDescription == "Failed to find lock for cert" { + handleNoCertLockError(error: error, session: session) + return + } + if let idCardInternalError = error as? IdCardInternalError { handleIdCardInternalError(idCardInternalError, session: session) return diff --git a/RIADigiDoc/Supporting files/Localizable.xcstrings b/RIADigiDoc/Supporting files/Localizable.xcstrings index c7bae94d..55ed7dd0 100644 --- a/RIADigiDoc/Supporting files/Localizable.xcstrings +++ b/RIADigiDoc/Supporting files/Localizable.xcstrings @@ -1722,6 +1722,24 @@ } } }, + "Failed to find lock for cert" : { + "comment" : "Decrypting with ID-card not in recipient list", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Failed to find lock for cert" + } + }, + "et" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sertifikaadi võtmega lukku ei leitud" + } + } + } + }, "Failed to open container" : { "comment" : "Error message when unable to create a new container", "extractionState" : "manual", diff --git a/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift b/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift index 05ac1acb..919edb3d 100644 --- a/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift +++ b/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift @@ -416,7 +416,6 @@ struct IdCardView: View { pinNumber.isEmpty ? () : (pinNumber.removeAll()) isActionEnabled = viewModel .isActionEnabled(pinNumber: pinNumber, pinType: pinCodeType) - resetIdCardAction() } private func resetIdCardAction() { diff --git a/RIADigiDoc/ViewModel/Signing/IdCard/IdCardViewModel.swift b/RIADigiDoc/ViewModel/Signing/IdCard/IdCardViewModel.swift index 34d25fc3..bb9919f8 100644 --- a/RIADigiDoc/ViewModel/Signing/IdCard/IdCardViewModel.swift +++ b/RIADigiDoc/ViewModel/Signing/IdCard/IdCardViewModel.swift @@ -111,6 +111,16 @@ class IdCardViewModel: IdCardViewModelProtocol, Loggable { return container } catch { IdCardViewModel.logger().error("ID-CARD: Unable to decrypt container with ID-card reader. \(error)") + + let nsError = error as NSError + if nsError.localizedDescription == "Failed to find lock for cert" { + IdCardViewModel.logger().error("ID-CARD: Failed to find lock for cert") + errorMessage = "Failed to find lock for cert" + errorExtraArguments = [] + shouldDismissForError = true + return nil + } + guard let exception = error as? IdCardInternalError else { IdCardViewModel.logger().error("ID-CARD: ID Card General error.") errorMessage = "General error" @@ -195,19 +205,19 @@ class IdCardViewModel: IdCardViewModelProtocol, Loggable { let pinResponse = try await readCodeTryCounterRecord() let isPUKChangeable = try await isPukChangeable() - if codeType == CodeType.pin1 { + if codeType == .pin1 { if pinResponse.pin1RetryCount == 0 { throw IdCardInternalError.remainingPinRetryCount(0) } } - if codeType == CodeType.pin2 { + if codeType == .pin2 { if pinResponse.pin2RetryCount == 0 { throw IdCardInternalError.remainingPinRetryCount(0) } - } - - if !pinResponse.pin2Active { - throw IdCardInternalError.pinLocked + + if !pinResponse.pin2Active { + throw IdCardInternalError.pinLocked + } } return IdCardData( From 8d7c79cfd65277df0f76996788d58e60b84307d0 Mon Sep 17 00:00:00 2001 From: Marten Rebane Date: Tue, 31 Mar 2026 17:33:23 +0300 Subject: [PATCH 2/2] Fix reseting card actions --- .../UI/Component/Container/Signing/IdCard/IdCardView.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift b/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift index 919edb3d..5d18fd20 100644 --- a/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift +++ b/RIADigiDoc/UI/Component/Container/Signing/IdCard/IdCardView.swift @@ -183,6 +183,7 @@ struct IdCardView: View { await MainActor.run { Toast.show(errorMessage) viewModel.resetErrors() + resetIdCardAction() if shouldDismiss { dismiss() } @@ -198,6 +199,7 @@ struct IdCardView: View { await viewModel.stopDiscoveringReaders() cancelIdCardAction() + resetIdCardAction() isInProgress = false isShowingPinView = false isShowingLoadingView = false @@ -388,6 +390,7 @@ struct IdCardView: View { await MainActor.run { Toast.show(errorMessage) viewModel.resetErrors() + resetIdCardAction() // Let ID-card alert closure handle dismiss // Dismiss is run when user has pressed OK button on alert @@ -460,6 +463,7 @@ struct IdCardView: View { await MainActor.run { Toast.show(errorMessage) viewModel.resetErrors() + resetIdCardAction() if shouldDismiss { dismiss() }