diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/NfcKeyToCardOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/NfcKeyToCardOperation.java index 95937a233..36f31e20e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/NfcKeyToCardOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/NfcKeyToCardOperation.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.sufficientlysecure.keychain.operations.results.NfcKeyToCardResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; @@ -26,6 +27,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; public class NfcKeyToCardOperation extends BaseOperation { public NfcKeyToCardOperation(Context context, ProviderHelper providerHelper, Progressable progressable) { @@ -43,32 +45,46 @@ public class NfcKeyToCardOperation extends BaseOperation { CanonicalizedSecretKeyRing keyRing = mProviderHelper.getCanonicalizedSecretKeyRing(masterKeyId); - log.add(OperationResult.LogType.MSG_KC_SECRET, indent); + log.add(OperationResult.LogType.MSG_KC_SECRET, indent, + KeyFormattingUtils.convertKeyIdToHex(masterKeyId)); // fetch the specific subkey CanonicalizedSecretKey subKey = keyRing.getSecretKey(subKeyId); - switch (subKey.getSecretKeyType()) { - case DIVERT_TO_CARD: - case GNU_DUMMY: { - throw new AssertionError( - "Cannot export GNU_DUMMY/DIVERT_TO_CARD key to a smart card!" - + " This is a programming error!"); - } - - case PIN: - case PATTERN: - case PASSPHRASE: { - log.add(OperationResult.LogType.MSG_PSE_PENDING_NFC, indent); - return new NfcKeyToCardResult(log, RequiredInputParcel - .createNfcKeyToCardOperation(masterKeyId, subKeyId)); - } - - default: { - throw new AssertionError("Unhandled SecretKeyType! (should not happen)"); - } - + // Key algorithm must be RSA + int algorithm = subKey.getAlgorithm(); + if (algorithm != PublicKeyAlgorithmTags.RSA_ENCRYPT && + algorithm != PublicKeyAlgorithmTags.RSA_SIGN && + algorithm != PublicKeyAlgorithmTags.RSA_GENERAL) { + log.add(OperationResult.LogType.MSG_K2C_ERROR_BAD_ALGO, indent + 1); + return new NfcKeyToCardResult(NfcKeyToCardResult.RESULT_ERROR, log); } + + // Key size must be 2048 + int keySize = subKey.getBitStrength(); + if (keySize != 2048) { + log.add(OperationResult.LogType.MSG_K2C_ERROR_BAD_SIZE, indent + 1); + return new NfcKeyToCardResult(NfcKeyToCardResult.RESULT_ERROR, log); + } + + // Secret key parts must be available + CanonicalizedSecretKey.SecretKeyType type = subKey.getSecretKeyType(); + if (type == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD || + type == CanonicalizedSecretKey.SecretKeyType.GNU_DUMMY) { + log.add(OperationResult.LogType.MSG_K2C_ERROR_BAD_STRIPPED, indent + 1); + return new NfcKeyToCardResult(NfcKeyToCardResult.RESULT_ERROR, log); + } + + if (type == CanonicalizedSecretKey.SecretKeyType.PIN || + type == CanonicalizedSecretKey.SecretKeyType.PATTERN || + type == CanonicalizedSecretKey.SecretKeyType.PASSPHRASE || + type == CanonicalizedSecretKey.SecretKeyType.PASSPHRASE_EMPTY) { + log.add(OperationResult.LogType.MSG_PSE_PENDING_NFC, indent); + return new NfcKeyToCardResult(log, RequiredInputParcel + .createNfcKeyToCardOperation(masterKeyId, subKeyId)); + } + + throw new AssertionError("Unhandled SecretKeyType! (should not happen)"); } catch (ProviderHelper.NotFoundException e) { log.add(OperationResult.LogType.MSG_PSE_ERROR_UNLOCK, indent); return new NfcKeyToCardResult(NfcKeyToCardResult.RESULT_ERROR, log); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/NfcKeyToCardResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/NfcKeyToCardResult.java index c4bd3986c..93899bbbe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/NfcKeyToCardResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/NfcKeyToCardResult.java @@ -17,6 +17,8 @@ package org.sufficientlysecure.keychain.operations.results; +import android.os.Parcel; + import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; public class NfcKeyToCardResult extends InputPendingResult { @@ -27,4 +29,23 @@ public class NfcKeyToCardResult extends InputPendingResult { public NfcKeyToCardResult(OperationLog log, RequiredInputParcel requiredInput) { super(log, requiredInput); } + + public NfcKeyToCardResult(Parcel source) { + super(source); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + } + + public static Creator CREATOR = new Creator() { + public NfcKeyToCardResult createFromParcel(final Parcel source) { + return new NfcKeyToCardResult(source); + } + + public NfcKeyToCardResult[] newArray(final int size) { + return new NfcKeyToCardResult[size]; + } + }; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 094afd4a5..4c40b0e5b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -736,6 +736,11 @@ public abstract class OperationResult implements Parcelable { MSG_EXPORT_LOG_EXPORT_ERROR_FOPEN(LogLevel.ERROR,R.string.msg_export_log_error_fopen), MSG_EXPORT_LOG_EXPORT_ERROR_WRITING(LogLevel.ERROR,R.string.msg_export_log_error_writing), MSG_EXPORT_LOG_EXPORT_SUCCESS (LogLevel.OK, R.string.msg_export_log_success), + + // NFC keytocard + MSG_K2C_ERROR_BAD_ALGO(LogLevel.ERROR, R.string.edit_key_error_bad_nfc_algo), + MSG_K2C_ERROR_BAD_SIZE(LogLevel.ERROR, R.string.edit_key_error_bad_nfc_size), + MSG_K2C_ERROR_BAD_STRIPPED(LogLevel.ERROR, R.string.edit_key_error_bad_nfc_stripped), ; public final int mMsgId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index aef770174..3b342bec0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -36,14 +36,12 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; -import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.SingletonResult; -import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; @@ -430,35 +428,6 @@ public class EditKeyFragment extends CryptoOperationFragment implements break; } case EditSubkeyDialogFragment.MESSAGE_KEYTOCARD: { - // Three checks to verify that this is a smart card compatible key: - - // 1. Key algorithm must be RSA - int algorithm = mSubkeysAdapter.getAlgorithm(position); - if (algorithm != PublicKeyAlgorithmTags.RSA_ENCRYPT && - algorithm != PublicKeyAlgorithmTags.RSA_SIGN && - algorithm != PublicKeyAlgorithmTags.RSA_GENERAL) { - Notify.create(getActivity(), R.string.edit_key_error_bad_nfc_algo, - Notify.Style.ERROR).show(); - return; - } - - // 2. Key size must be 2048 - if (mSubkeysAdapter.getKeySize(position) != 2048) { - Notify.create(getActivity(), R.string.edit_key_error_bad_nfc_size, - Notify.Style.ERROR).show(); - return; - } - - // 3. Secret key parts must be available - CanonicalizedSecretKey.SecretKeyType type = - mSubkeysAdapter.getSecretKeyType(position); - if (type == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD || - type == CanonicalizedSecretKey.SecretKeyType.GNU_DUMMY) { - Notify.create(getActivity(), R.string.edit_key_error_bad_nfc_stripped, - Notify.Style.ERROR).show(); - return; - } - SubkeyChange change; change = mSaveKeyringParcel.getSubkeyChange(keyId); if (change == null) { @@ -480,7 +449,15 @@ public class EditKeyFragment extends CryptoOperationFragment implements ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) { public void handleMessage(Message message) { super.handleMessage(message); - EditKeyFragment.this.handlePendingMessage(message); + if (EditKeyFragment.this.handlePendingMessage(message)) { + return; + } + Bundle data = message.getData(); + OperationResult result = data.getParcelable(OperationResult.EXTRA_RESULT); + if (result.getResult() == OperationResult.RESULT_ERROR) { + result.createNotify(getActivity()).show(); + } + } }; // Create a new Messenger for the communication back