From 73efb00368e461f0f910f0705bcb16bb51c4c510 Mon Sep 17 00:00:00 2001 From: stargateprovider Date: Mon, 8 Nov 2021 23:51:07 +0200 Subject: [PATCH 1/2] Added basic notifications to the user For when exceptions occur when communicating with the ID-card --- .../mobileauthapp/AuthFragment.kt | 38 +++++++++++++++---- .../mobileauthapp/NFC/Comms.java | 9 +++-- .../mobileauthapp/auth/AuthAppException.kt | 10 +++++ .../mobileauthapp/auth/InvalidCANException.kt | 7 ++++ .../app/src/main/res/values-en/strings.xml | 7 +++- .../app/src/main/res/values-et/strings.xml | 7 +++- .../app/src/main/res/values/strings.xml | 7 +++- 7 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/AuthAppException.kt create mode 100644 MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/InvalidCANException.kt diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt index fa5de12..55f82f3 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt @@ -5,7 +5,6 @@ import android.nfc.NfcAdapter import android.nfc.tech.IsoDep import android.os.Bundle import android.os.CountDownTimer -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -15,10 +14,14 @@ import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.tarkvaraprojekt.mobileauthapp.NFC.Comms +import com.tarkvaraprojekt.mobileauthapp.auth.AuthAppException +import com.tarkvaraprojekt.mobileauthapp.auth.InvalidCANException import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentAuthBinding import com.tarkvaraprojekt.mobileauthapp.model.ParametersViewModel import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel +import java.io.IOException import java.lang.Exception +import java.security.GeneralSecurityException import kotlin.system.exitProcess /** @@ -80,6 +83,8 @@ class AuthFragment : Fragment() { requireActivity().runOnUiThread { binding!!.timeCounter.text = getString(R.string.card_detected) } + var msgCode = 0 + val card = IsoDep.get(tag) card.timeout = 32768 card.use { @@ -95,17 +100,36 @@ class AuthFragment : Fragment() { requireActivity().runOnUiThread { binding!!.timeCounter.text = getString(R.string.data_read) } - } catch (e: Exception) { - requireActivity().runOnUiThread { - binding!!.timeCounter.text = getString(R.string.no_success) - } + + } catch (e: android.nfc.TagLostException) { + msgCode = R.string.tag_lost + } catch (e: InvalidCANException) { + msgCode = R.string.invalid_can // If the CAN is wrong we will also delete the saved CAN so that the user won't use it again. viewModel.deleteCan(requireContext()) + } catch (e: AuthAppException) { + msgCode = when (e.code) { + 448 -> R.string.err_bad_data + 500 -> R.string.err_internal + else -> R.string.err_unknown + } + } catch (e: GeneralSecurityException) { + msgCode = R.string.err_internal + } catch (e: IOException) { + msgCode = R.string.err_reading_card + } catch (e: Exception) { + msgCode = R.string.err_unknown + } finally { + adapter.disableReaderMode(activity) + } + + if (msgCode != 0) { + requireActivity().runOnUiThread { + binding!!.timeCounter.text = getString(msgCode) + } // Gives user some time to read the error message Thread.sleep(1000) goToTheStart() - } finally { - adapter.disableReaderMode(activity) } } }, NfcAdapter.FLAG_READER_NFC_A, null) diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java index a4d184b..76b8c4f 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java @@ -3,6 +3,9 @@ package com.tarkvaraprojekt.mobileauthapp.NFC; import android.nfc.tech.IsoDep; import android.util.Log; +import com.tarkvaraprojekt.mobileauthapp.auth.AuthAppException; +import com.tarkvaraprojekt.mobileauthapp.auth.InvalidCANException; + import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.macs.CMac; @@ -209,13 +212,13 @@ public class Comms { Log.i("Mutual authentication", Hex.toHexString(response)); // if the chip-side verification fails, crash and burn - if (response.length == 2) throw new RuntimeException("Invalid CAN."); + if (response.length == 2) throw new InvalidCANException(); // otherwise verify chip's MAC and return session keys APDU = createAPDU(dataForMACIncomplete, publicKey.getEncoded(false), 65); MAC = getMAC(APDU, keyMAC); if (!Hex.toHexString(response, 4, 8).equals(Hex.toHexString(MAC))) { - throw new RuntimeException("Could not verify chip's MAC."); // Should never happen. + throw new AuthAppException("Could not verify chip's MAC.", 448); // Should never happen. } return new byte[][]{keyEnc, keyMAC}; @@ -304,7 +307,7 @@ public class Comms { for (int i = 0; i < FID.length; i++) { byte index = FID[i]; - if (index > 15 || index < 1) throw new RuntimeException("Invalid personal data FID."); + if (index > 15 || index < 1) throw new AuthAppException("Invalid personal data FID.", 500); data[1] = index; APDU = createSecureAPDU(data, personal); diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/AuthAppException.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/AuthAppException.kt new file mode 100644 index 0000000..96b05d5 --- /dev/null +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/AuthAppException.kt @@ -0,0 +1,10 @@ +package com.tarkvaraprojekt.mobileauthapp.auth + +/** + * A specialised RuntimeException class for exceptions related to the mobile authentication app. + * Possible error codes can be found at + * https://github.com/TanelOrumaa/Estonian-ID-card-mobile-authenticator-POC/wiki/Error-codes + * @param message Error message + * @param code An error code defined in the project wiki + */ +open class AuthAppException(message: String, var code: Int) : RuntimeException(message) \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/InvalidCANException.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/InvalidCANException.kt new file mode 100644 index 0000000..073c790 --- /dev/null +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/auth/InvalidCANException.kt @@ -0,0 +1,7 @@ +package com.tarkvaraprojekt.mobileauthapp.auth + +/** + * An AuthAppException for when the user entered CAN does not match the one read from the ID-card + * @see AuthAppException + */ +class InvalidCANException : AuthAppException("Invalid CAN", 400) \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/res/values-en/strings.xml b/MobileAuthApp/app/src/main/res/values-en/strings.xml index 7aa4439..f169ccd 100644 --- a/MobileAuthApp/app/src/main/res/values-en/strings.xml +++ b/MobileAuthApp/app/src/main/res/values-en/strings.xml @@ -44,7 +44,9 @@ Put the ID card against the phone to establish connection Time left %d sek No time left - Wrong CAN + Unknown error + Wrong CAN + Connection between device and ID-card lost NAME @@ -75,4 +77,7 @@ **** Settings currently unavailabe CAN is currently not saved. Do you wish to save the CAN? Saved CAN will be entered automatically in the future. Saved CAN can be changed and deleted in the settings menu. + Failed to read data from the ID-card + Internal error + Read bad data from the ID-card, try using the card again \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/res/values-et/strings.xml b/MobileAuthApp/app/src/main/res/values-et/strings.xml index 66afcfb..b630b90 100644 --- a/MobileAuthApp/app/src/main/res/values-et/strings.xml +++ b/MobileAuthApp/app/src/main/res/values-et/strings.xml @@ -43,7 +43,9 @@ ID kaardiga ühenduse loomiseks pane kaart vastu telefoni Aega on jäänud %d sek Aeg on otsas - Vale CAN + Tundmatu viga + Vale CAN + Ühendus seadme ja kaardi vahel katkes NIMI @@ -73,4 +75,7 @@ PEIDA **** Seaded pole hetkel saadaval + Ei saanud ID-kaardilt andmeid lugeda + Rakendusesisene viga + ID-kaardilt loeti vigased andmed, proovi uuesti kaarti kasutada \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/res/values/strings.xml b/MobileAuthApp/app/src/main/res/values/strings.xml index 0a39206..178763c 100644 --- a/MobileAuthApp/app/src/main/res/values/strings.xml +++ b/MobileAuthApp/app/src/main/res/values/strings.xml @@ -43,7 +43,9 @@ Put the ID card against the phone to establish connection Time left %d sek No time left - Wrong CAN + Unknown error + Wrong CAN + Connection between device and ID-card lost NAME @@ -73,4 +75,7 @@ HIDE **** Settings currently unavailable + Failed to read data from the ID-card + Internal error + Read bad data from the ID-card, try using the card again \ No newline at end of file From dbc758fb14c5d0e0729ee80c041dfe0b886e6406 Mon Sep 17 00:00:00 2001 From: stargateprovider Date: Sat, 4 Dec 2021 21:22:54 +0200 Subject: [PATCH 2/2] More specific errors and notifications --- .../mobileauthapp/AuthFragment.kt | 3 +++ .../tarkvaraprojekt/mobileauthapp/CanFragment.kt | 14 ++++++++++---- .../tarkvaraprojekt/mobileauthapp/NFC/Comms.java | 16 ++++++++-------- .../app/src/main/res/values-en/strings.xml | 3 +++ .../app/src/main/res/values-et/strings.xml | 3 +++ .../app/src/main/res/values/strings.xml | 3 +++ 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt index 2a395f8..5f5b1cb 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt @@ -120,6 +120,9 @@ class AuthFragment : Fragment() { viewModel.deleteCan(requireContext()) } catch (e: AuthAppException) { msgCode = when (e.code) { + 400 -> R.string.err_parameter + 401 -> R.string.err_authentication + 446 -> R.string.err_card_locked 448 -> R.string.err_bad_data 500 -> R.string.err_internal else -> R.string.err_unknown diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/CanFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/CanFragment.kt index 1b281aa..e8ea7a7 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/CanFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/CanFragment.kt @@ -71,6 +71,14 @@ class CanFragment : Fragment() { findNavController().navigate(action) } + /** + * Saves the entered CAN and notifies the user about it + */ + private fun saveCan() { + viewModel.storeCan(requireContext()) + Toast.makeText(requireContext(), getString(R.string.can_status_saved), Toast.LENGTH_SHORT).show() + } + /** * Checks whether the user has entered a 6 digit can to the input field. * If yes then the user is allowed to continue otherwise the user is @@ -81,7 +89,7 @@ class CanFragment : Fragment() { if (enteredCan.length == 6) { viewModel.setUserCan(enteredCan) if (args.saving) { - viewModel.storeCan(requireContext()) + saveCan() goToTheStart() } else { val storeCanQuestion = getDialog() @@ -103,9 +111,7 @@ class CanFragment : Fragment() { builder.apply { // If response is positive then save the CAN on the device. setPositiveButton(R.string.save_text) { _, _ -> - viewModel.storeCan( - requireContext() - ) + saveCan() goToTheNextFragment() } setNegativeButton(R.string.deny_text) { _, _ -> diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java index 21ce9d7..8519c5c 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/NFC/Comms.java @@ -159,7 +159,7 @@ public class Comms { private byte[] getResponse(byte[] APDU, String log) throws IOException { byte[] response = idCard.transceive(APDU); if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { - throw new RuntimeException(String.format("%s failed.", log)); + throw new AuthAppException(String.format("%s failed.", log), 500); } Log.i(log, Hex.toHexString(response)); return response; @@ -227,7 +227,7 @@ public class Comms { selectFile(FID, info); byte[] response = getResponse(new byte[0], readFile, "Read binary"); if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { - throw new RuntimeException(String.format("Could not read %s", info)); + throw new AuthAppException(String.format("Could not read %s", info), 500); } return encryptDecryptData(Arrays.copyOfRange(response, 3, 19), Cipher.DECRYPT_MODE); } @@ -296,7 +296,7 @@ public class Comms { private void selectFile(byte[] FID, String info) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, IOException { byte[] response = getResponse(FID, selectFile, String.format("Select %s", info)); if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { - throw new RuntimeException(String.format("Could not select %s", info)); + throw new AuthAppException(String.format("Could not select %s", info), 500); } } @@ -354,9 +354,9 @@ public class Comms { if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { if (response[response.length - 2] == 0x69 && response[response.length - 1] == (byte) 0x83) { - throw new RuntimeException("Invalid PIN. Authentication method blocked."); + throw new AuthAppException("Invalid PIN. Authentication method blocked.", 446); } else { - throw new RuntimeException(String.format("Invalid PIN. Attempts left: %d.", response[response.length - 1] + 64)); + throw new AuthAppException(String.format("Invalid PIN. Attempts left: %d.", response[response.length - 1] + 64), 401); } } } @@ -385,7 +385,7 @@ public class Comms { readCert[3] = (byte) (certificate.length % 256); byte[] response = getResponse(new byte[0], readCert, "Read the certificate"); if (response[response.length - 2] == 0x6b && response[response.length - 1] == 0x00) { - throw new RuntimeException("Wrong read parameters."); + throw new AuthAppException("Wrong read parameters.", 400); } // Set the range containing a portion of the certificate and decrypt it @@ -420,7 +420,7 @@ public class Comms { byte[] response = getResponse(Env, MSESetEnv, "Set environment"); if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { - throw new RuntimeException("Setting the environment failed."); + throw new AuthAppException("Setting the environment failed.", 500); } InternalAuthenticate[4] = (byte) (0x1d + 16 * (token.length / 16)); @@ -428,7 +428,7 @@ public class Comms { response = getResponse(token, InternalAuthenticate, "Internal Authenticate"); if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) { - throw new RuntimeException("Signing the token failed."); + throw new AuthAppException("Signing the token failed.", 500); } byte[] signature = encryptDecryptData(Arrays.copyOfRange(response, 3, 115), Cipher.DECRYPT_MODE); diff --git a/MobileAuthApp/app/src/main/res/values-en/strings.xml b/MobileAuthApp/app/src/main/res/values-en/strings.xml index 69af501..ef5b013 100644 --- a/MobileAuthApp/app/src/main/res/values-en/strings.xml +++ b/MobileAuthApp/app/src/main/res/values-en/strings.xml @@ -80,4 +80,7 @@ Failed to read data from the ID-card Internal error Read bad data from the ID-card, try using the card again + Required parameter is missing or invalid + Failed to authenticate + Card locked \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/res/values-et/strings.xml b/MobileAuthApp/app/src/main/res/values-et/strings.xml index 1dedbd0..40ee21d 100644 --- a/MobileAuthApp/app/src/main/res/values-et/strings.xml +++ b/MobileAuthApp/app/src/main/res/values-et/strings.xml @@ -78,4 +78,7 @@ Ei saanud ID-kaardilt andmeid lugeda Rakendusesisene viga ID-kaardilt loeti vigased andmed, proovi uuesti kaarti kasutada + Vigane või puuduv parameeter + Autentimine ebaõnnestus + Kaart lukus \ No newline at end of file diff --git a/MobileAuthApp/app/src/main/res/values/strings.xml b/MobileAuthApp/app/src/main/res/values/strings.xml index ac0d78b..2a86337 100644 --- a/MobileAuthApp/app/src/main/res/values/strings.xml +++ b/MobileAuthApp/app/src/main/res/values/strings.xml @@ -78,4 +78,7 @@ Failed to read data from the ID-card Internal error Read bad data from the ID-card, try using the card again + Required parameter is missing or invalid + Failed to authenticate + Card locked \ No newline at end of file