From 195508ed92434197d0d6ab2d3ef6e0b4bd0780b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 2 Jul 2015 17:31:01 +0200 Subject: Change PIN and Admin PIN after move to key operation --- .../operations/results/OperationResult.java | 2 + .../keychain/pgp/PgpKeyOperation.java | 20 ++++++ .../keychain/service/SaveKeyringParcel.java | 18 +++++- .../service/input/RequiredInputParcel.java | 73 ++++++++++++++-------- .../keychain/ui/CreateKeyActivity.java | 12 ++-- .../keychain/ui/CreateKeyFinalFragment.java | 10 ++- .../keychain/ui/CreateKeyPassphraseFragment.java | 4 +- .../keychain/ui/CreateYubiKeyPinFragment.java | 32 ++++++---- .../ui/CreateYubiKeyPinRepeatFragment.java | 4 +- .../keychain/ui/NfcOperationActivity.java | 33 +++++++--- .../keychain/ui/base/BaseNfcActivity.java | 25 ++++---- .../keychain/util/Passphrase.java | 13 ++-- 12 files changed, 167 insertions(+), 79 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure') 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 f0561bef2..245623762 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 @@ -510,6 +510,8 @@ public abstract class OperationResult implements Parcelable { MSG_MF_NOTATION_PIN (LogLevel.DEBUG, R.string.msg_mf_notation_pin), MSG_MF_NOTATION_EMPTY (LogLevel.DEBUG, R.string.msg_mf_notation_empty), MSG_MF_PASSPHRASE (LogLevel.INFO, R.string.msg_mf_passphrase), + MSG_MF_PIN (LogLevel.INFO, R.string.msg_mf_pin), + MSG_MF_ADMIN_PIN (LogLevel.INFO, R.string.msg_mf_admin_pin), MSG_MF_PASSPHRASE_KEY (LogLevel.DEBUG, R.string.msg_mf_passphrase_key), MSG_MF_PASSPHRASE_EMPTY_RETRY (LogLevel.DEBUG, R.string.msg_mf_passphrase_empty_retry), MSG_MF_PASSPHRASE_FAIL (LogLevel.WARN, R.string.msg_mf_passphrase_fail), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index a018815f3..8445272fc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -1039,6 +1039,26 @@ public class PgpKeyOperation { indent -= 1; } + // 7. if requested, change PIN and/or Admin PIN on card + if (saveParcel.mCardPin != null) { + progress(R.string.progress_modify_pin, 90); + log.add(LogType.MSG_MF_PIN, indent); + indent += 1; + + nfcKeyToCardOps.setPin(saveParcel.mCardPin); + + indent -= 1; + } + if (saveParcel.mCardAdminPin != null) { + progress(R.string.progress_modify_admin_pin, 90); + log.add(LogType.MSG_MF_ADMIN_PIN, indent); + indent += 1; + + nfcKeyToCardOps.setAdminPin(saveParcel.mCardAdminPin); + + indent -= 1; + } + } catch (IOException e) { Log.e(Constants.TAG, "encountered IOException while modifying key", e); log.add(LogType.MSG_MF_ERROR_ENCODE, indent+1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index e2c4dc542..679f4f817 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -61,6 +61,10 @@ public class SaveKeyringParcel implements Parcelable { public ArrayList mRevokeUserIds; public ArrayList mRevokeSubKeys; + // if these are non-null, PINs will be changed on the card + public Passphrase mCardPin; + public Passphrase mCardAdminPin; + public SaveKeyringParcel() { reset(); } @@ -80,6 +84,8 @@ public class SaveKeyringParcel implements Parcelable { mChangeSubKeys = new ArrayList<>(); mRevokeUserIds = new ArrayList<>(); mRevokeSubKeys = new ArrayList<>(); + mCardPin = null; + mCardAdminPin = null; } public boolean isEmpty() { @@ -225,6 +231,9 @@ public class SaveKeyringParcel implements Parcelable { mRevokeUserIds = source.createStringArrayList(); mRevokeSubKeys = (ArrayList) source.readSerializable(); + + mCardPin = source.readParcelable(Passphrase.class.getClassLoader()); + mCardAdminPin = source.readParcelable(Passphrase.class.getClassLoader()); } @Override @@ -236,7 +245,7 @@ public class SaveKeyringParcel implements Parcelable { destination.writeByteArray(mFingerprint); // yes, null values are ok for parcelables - destination.writeParcelable(mNewUnlock, 0); + destination.writeParcelable(mNewUnlock, flags); destination.writeStringList(mAddUserIds); destination.writeSerializable(mAddUserAttribute); @@ -247,6 +256,9 @@ public class SaveKeyringParcel implements Parcelable { destination.writeStringList(mRevokeUserIds); destination.writeSerializable(mRevokeSubKeys); + + destination.writeParcelable(mCardPin, flags); + destination.writeParcelable(mCardAdminPin, flags); } public static final Creator CREATOR = new Creator() { @@ -274,7 +286,9 @@ public class SaveKeyringParcel implements Parcelable { out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; out += "mRevokeUserIds: " + mRevokeUserIds + "\n"; - out += "mRevokeSubKeys: " + mRevokeSubKeys; + out += "mRevokeSubKeys: " + mRevokeSubKeys + "\n"; + out += "mCardPin: " + mCardPin + "\n"; + out += "mCardAdminPin: " + mCardAdminPin; return out; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java index efe844145..4eca8d8f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java @@ -1,13 +1,16 @@ package org.sufficientlysecure.keychain.service.input; +import android.os.Parcel; +import android.os.Parcelable; + +import org.spongycastle.util.Arrays; +import org.sufficientlysecure.keychain.util.Passphrase; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Date; -import android.os.Parcel; -import android.os.Parcelable; - public class RequiredInputParcel implements Parcelable { @@ -19,16 +22,16 @@ public class RequiredInputParcel implements Parcelable { public final RequiredInputType mType; - public final byte[][] mInputHashes; + public final byte[][] mInputData; public final int[] mSignAlgos; private Long mMasterKeyId; private Long mSubKeyId; - private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes, + private RequiredInputParcel(RequiredInputType type, byte[][] inputData, int[] signAlgos, Date signatureTime, Long masterKeyId, Long subKeyId) { mType = type; - mInputHashes = inputHashes; + mInputData = inputData; mSignAlgos = signAlgos; mSignatureTime = signatureTime; mMasterKeyId = masterKeyId; @@ -38,25 +41,25 @@ public class RequiredInputParcel implements Parcelable { public RequiredInputParcel(Parcel source) { mType = RequiredInputType.values()[source.readInt()]; - // 0 = none, 1 = both, 2 = only hashes (decrypt) - int hashTypes = source.readInt(); - if (hashTypes != 0) { + // 0 = none, 1 = signAlgos + inputData, 2 = only inputData (decrypt) + int inputDataType = source.readInt(); + if (inputDataType != 0) { int count = source.readInt(); - mInputHashes = new byte[count][]; - if (hashTypes == 1) { + mInputData = new byte[count][]; + if (inputDataType == 1) { mSignAlgos = new int[count]; for (int i = 0; i < count; i++) { - mInputHashes[i] = source.createByteArray(); + mInputData[i] = source.createByteArray(); mSignAlgos[i] = source.readInt(); } } else { mSignAlgos = null; for (int i = 0; i < count; i++) { - mInputHashes[i] = source.createByteArray(); + mInputData[i] = source.createByteArray(); } } } else { - mInputHashes = null; + mInputData = null; mSignAlgos = null; } @@ -83,9 +86,9 @@ public class RequiredInputParcel implements Parcelable { } public static RequiredInputParcel createNfcDecryptOperation( - long masterKeyId, long subKeyId, byte[] inputHash) { + long masterKeyId, long subKeyId, byte[] encryptedSessionKey) { return new RequiredInputParcel(RequiredInputType.NFC_DECRYPT, - new byte[][] { inputHash }, null, null, masterKeyId, subKeyId); + new byte[][] { encryptedSessionKey }, null, null, masterKeyId, subKeyId); } public static RequiredInputParcel createRequiredSignPassphrase( @@ -119,11 +122,11 @@ public class RequiredInputParcel implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType.ordinal()); - if (mInputHashes != null) { + if (mInputData != null) { dest.writeInt(mSignAlgos != null ? 1 : 2); - dest.writeInt(mInputHashes.length); - for (int i = 0; i < mInputHashes.length; i++) { - dest.writeByteArray(mInputHashes[i]); + dest.writeInt(mInputData.length); + for (int i = 0; i < mInputData.length; i++) { + dest.writeByteArray(mInputData[i]); if (mSignAlgos != null) { dest.writeInt(mSignAlgos[i]); } @@ -200,7 +203,7 @@ public class RequiredInputParcel implements Parcelable { throw new AssertionError("operation types must match, this is a progrmming error!"); } - Collections.addAll(mInputHashes, input.mInputHashes); + Collections.addAll(mInputHashes, input.mInputData); for (int signAlgo : input.mSignAlgos) { mSignAlgos.add(signAlgo); } @@ -215,19 +218,31 @@ public class RequiredInputParcel implements Parcelable { public static class NfcKeyToCardOperationsBuilder { ArrayList mSubkeysToExport = new ArrayList<>(); Long mMasterKeyId; + byte[] mPin; + byte[] mAdminPin; public NfcKeyToCardOperationsBuilder(Long masterKeyId) { mMasterKeyId = masterKeyId; } public RequiredInputParcel build() { - byte[][] inputHashes = new byte[mSubkeysToExport.size()][]; - mSubkeysToExport.toArray(inputHashes); + byte[][] inputData = new byte[mSubkeysToExport.size() + 2][]; + + // encode all subkeys into inputData + byte[][] subkeyData = new byte[mSubkeysToExport.size()][]; + mSubkeysToExport.toArray(subkeyData); + + // first two are PINs + inputData[0] = mPin; + inputData[1] = mAdminPin; + // then subkeys + System.arraycopy(subkeyData, 0, inputData, 2, subkeyData.length); + ByteBuffer buf = ByteBuffer.wrap(mSubkeysToExport.get(0)); // We need to pass in a subkey here... return new RequiredInputParcel(RequiredInputType.NFC_MOVE_KEY_TO_CARD, - inputHashes, null, null, mMasterKeyId, buf.getLong()); + inputData, null, null, mMasterKeyId, buf.getLong()); } public void addSubkey(long subkeyId) { @@ -237,6 +252,14 @@ public class RequiredInputParcel implements Parcelable { mSubkeysToExport.add(subKeyId); } + public void setPin(Passphrase pin) { + mPin = pin.toStringUnsafe().getBytes(); + } + + public void setAdminPin(Passphrase adminPin) { + mAdminPin = adminPin.toStringUnsafe().getBytes(); + } + public void addAll(RequiredInputParcel input) { if (!mMasterKeyId.equals(input.mMasterKeyId)) { throw new AssertionError("Master keys must match, this is a programming error!"); @@ -245,7 +268,7 @@ public class RequiredInputParcel implements Parcelable { throw new AssertionError("Operation types must match, this is a programming error!"); } - Collections.addAll(mSubkeysToExport, input.mInputHashes); + Collections.addAll(mSubkeysToExport, input.mInputData); } public boolean isEmpty() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java index 36ab62cb4..1db93d2c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -58,8 +58,8 @@ public class CreateKeyActivity extends BaseNfcActivity { Passphrase mPassphrase; boolean mFirstTime; boolean mCreateYubiKey; - String mYubiKeyPin; - String mYubiKeyAdminPin; + Passphrase mYubiKeyPin; + Passphrase mYubiKeyAdminPin; Fragment mCurrentFragment; @@ -93,8 +93,8 @@ public class CreateKeyActivity extends BaseNfcActivity { mPassphrase = savedInstanceState.getParcelable(EXTRA_PASSPHRASE); mFirstTime = savedInstanceState.getBoolean(EXTRA_FIRST_TIME); mCreateYubiKey = savedInstanceState.getBoolean(EXTRA_CREATE_YUBI_KEY); - mYubiKeyPin = savedInstanceState.getString(EXTRA_YUBI_KEY_PIN); - mYubiKeyAdminPin = savedInstanceState.getString(EXTRA_YUBI_KEY_ADMIN_PIN); + mYubiKeyPin = savedInstanceState.getParcelable(EXTRA_YUBI_KEY_PIN); + mYubiKeyAdminPin = savedInstanceState.getParcelable(EXTRA_YUBI_KEY_ADMIN_PIN); mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); } else { @@ -200,8 +200,8 @@ public class CreateKeyActivity extends BaseNfcActivity { outState.putParcelable(EXTRA_PASSPHRASE, mPassphrase); outState.putBoolean(EXTRA_FIRST_TIME, mFirstTime); outState.putBoolean(EXTRA_CREATE_YUBI_KEY, mCreateYubiKey); - outState.putString(EXTRA_YUBI_KEY_PIN, mYubiKeyPin); - outState.putString(EXTRA_YUBI_KEY_ADMIN_PIN, mYubiKeyAdminPin); + outState.putParcelable(EXTRA_YUBI_KEY_PIN, mYubiKeyPin); + outState.putParcelable(EXTRA_YUBI_KEY_ADMIN_PIN, mYubiKeyAdminPin); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 8c7abb874..94bb68f7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -267,10 +267,11 @@ public class CreateKeyFinalFragment extends Fragment { } private void moveToCard(final EditKeyResult saveKeyResult) { - CachedPublicKeyRing key = (new ProviderHelper(getActivity())) - .getCachedPublicKeyRing(saveKeyResult.mMasterKeyId); + final CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity(); final SaveKeyringParcel changeKeyringParcel; + CachedPublicKeyRing key = (new ProviderHelper(getActivity())) + .getCachedPublicKeyRing(saveKeyResult.mMasterKeyId); try { changeKeyringParcel = new SaveKeyringParcel(key.getMasterKeyId(), key.getFingerprint()); } catch (PgpKeyNotFoundException e) { @@ -278,6 +279,7 @@ public class CreateKeyFinalFragment extends Fragment { return; } + // define subkeys that should be moved to the card Cursor cursor = getActivity().getContentResolver().query( KeychainContract.Keys.buildKeysUri(changeKeyringParcel.mMasterKeyId), new String[]{KeychainContract.Keys.KEY_ID,}, null, null, null @@ -293,6 +295,10 @@ public class CreateKeyFinalFragment extends Fragment { } } + // define new PIN and Admin PIN for the card + changeKeyringParcel.mCardPin = createKeyActivity.mYubiKeyPin; + changeKeyringParcel.mCardAdminPin = createKeyActivity.mYubiKeyAdminPin; + CryptoOperationHelper.Callback callback = new CryptoOperationHelper.Callback() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java index 3379e0a6d..6de5e71b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -107,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment { // initial values // TODO: using String here is unsafe... if (mCreateKeyActivity.mPassphrase != null) { - mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); - mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); + mPassphraseEdit.setText(mCreateKeyActivity.mPassphrase.toStringUnsafe()); + mPassphraseEditAgain.setText(mCreateKeyActivity.mPassphrase.toStringUnsafe()); } mPassphraseEdit.requestFocus(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinFragment.java index 8744762fe..a793b31f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinFragment.java @@ -29,6 +29,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; +import org.sufficientlysecure.keychain.util.Passphrase; import java.security.SecureRandom; @@ -63,30 +64,38 @@ public class CreateYubiKeyPinFragment extends Fragment { mNextButton = view.findViewById(R.id.create_key_next_button); if (mCreateKeyActivity.mYubiKeyPin == null) { - new AsyncTask>() { + new AsyncTask>() { @Override - protected Pair doInBackground(Void... unused) { + protected Pair doInBackground(Void... unused) { SecureRandom secureRandom = new SecureRandom(); // min = 6, we choose 6 - String pin = "" + secureRandom.nextInt(999999); + String pin = "" + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9); // min = 8, we choose 10, but 6 are equals the PIN - String adminPin = pin + secureRandom.nextInt(9999); + String adminPin = pin + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9) + + secureRandom.nextInt(9); - return new Pair<>(pin, adminPin); + return new Pair<>(new Passphrase(pin), new Passphrase(adminPin)); } @Override - protected void onPostExecute(Pair pair) { + protected void onPostExecute(Pair pair) { mCreateKeyActivity.mYubiKeyPin = pair.first; mCreateKeyActivity.mYubiKeyAdminPin = pair.second; - mPin.setText(mCreateKeyActivity.mYubiKeyPin); - mAdminPin.setText(mCreateKeyActivity.mYubiKeyAdminPin); + mPin.setText(mCreateKeyActivity.mYubiKeyPin.toStringUnsafe()); + mAdminPin.setText(mCreateKeyActivity.mYubiKeyAdminPin.toStringUnsafe()); } }.execute(); } else { - mPin.setText(mCreateKeyActivity.mYubiKeyPin); - mAdminPin.setText(mCreateKeyActivity.mYubiKeyAdminPin); + mPin.setText(mCreateKeyActivity.mYubiKeyPin.toStringUnsafe()); + mAdminPin.setText(mCreateKeyActivity.mYubiKeyAdminPin.toStringUnsafe()); } mBackButton.setOnClickListener(new View.OnClickListener() { @@ -114,9 +123,6 @@ public class CreateYubiKeyPinFragment extends Fragment { private void nextClicked() { - // save state -// mCreateKeyActivity.mPassphrase = new Passphrase(mPassphraseEdit); - CreateYubiKeyPinRepeatFragment frag = CreateYubiKeyPinRepeatFragment.newInstance(); mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinRepeatFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinRepeatFragment.java index dc437577a..2e752e609 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinRepeatFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyPinRepeatFragment.java @@ -124,9 +124,9 @@ public class CreateYubiKeyPinRepeatFragment extends Fragment { private void nextClicked() { if (isEditTextNotEmpty(getActivity(), mPin) - && checkPin(getActivity(), mPin, mCreateKeyActivity.mYubiKeyPin) + && checkPin(getActivity(), mPin, mCreateKeyActivity.mYubiKeyPin.toStringUnsafe()) && isEditTextNotEmpty(getActivity(), mAdminPin) - && checkPin(getActivity(), mAdminPin, mCreateKeyActivity.mYubiKeyAdminPin)) { + && checkPin(getActivity(), mAdminPin, mCreateKeyActivity.mYubiKeyAdminPin.toStringUnsafe())) { CreateKeyFinalFragment frag = CreateKeyFinalFragment.newInstance(); hideKeyboard(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java index addfb6a23..8a455bcec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java @@ -80,16 +80,16 @@ public class NfcOperationActivity extends BaseNfcActivity { switch (mRequiredInput.mType) { case NFC_DECRYPT: { - for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) { - byte[] hash = mRequiredInput.mInputHashes[i]; - byte[] decryptedSessionKey = nfcDecryptSessionKey(hash); - inputParcel.addCryptoData(hash, decryptedSessionKey); + for (int i = 0; i < mRequiredInput.mInputData.length; i++) { + byte[] encryptedSessionKey = mRequiredInput.mInputData[i]; + byte[] decryptedSessionKey = nfcDecryptSessionKey(encryptedSessionKey); + inputParcel.addCryptoData(encryptedSessionKey, decryptedSessionKey); } break; } case NFC_SIGN: { - for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) { - byte[] hash = mRequiredInput.mInputHashes[i]; + for (int i = 0; i < mRequiredInput.mInputData.length; i++) { + byte[] hash = mRequiredInput.mInputData[i]; int algo = mRequiredInput.mSignAlgos[i]; byte[] signedHash = nfcCalculateSignature(hash, algo); inputParcel.addCryptoData(hash, signedHash); @@ -97,6 +97,10 @@ public class NfcOperationActivity extends BaseNfcActivity { break; } case NFC_MOVE_KEY_TO_CARD: { + // TODO: assume PIN and Admin PIN to be default for this operation + mPin = new Passphrase("123456"); + mAdminPin = new Passphrase("12345678"); + ProviderHelper providerHelper = new ProviderHelper(this); CanonicalizedSecretKeyRing secretKeyRing; try { @@ -107,8 +111,11 @@ public class NfcOperationActivity extends BaseNfcActivity { throw new IOException("Couldn't find subkey for key to card operation."); } - for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) { - byte[] subkeyBytes = mRequiredInput.mInputHashes[i]; + byte[] newPin = mRequiredInput.mInputData[0]; + byte[] newAdminPin = mRequiredInput.mInputData[1]; + + for (int i = 2; i < mRequiredInput.mInputData.length; i++) { + byte[] subkeyBytes = mRequiredInput.mInputData[i]; ByteBuffer buf = ByteBuffer.wrap(subkeyBytes); long subkeyId = buf.getLong(); @@ -155,8 +162,18 @@ public class NfcOperationActivity extends BaseNfcActivity { throw new IOException("Inappropriate key flags for smart card key."); } + // TODO: Is this really needed? inputParcel.addCryptoData(subkeyBytes, cardSerialNumber); } + + // change PINs afterwards + nfcModifyPIN(0x81, newPin); + nfcModifyPIN(0x83, newAdminPin); + + break; + } + default: { + throw new AssertionError("Unhandled mRequiredInput.mType"); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java index bede16b2a..ba8dd3b55 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java @@ -179,8 +179,10 @@ public abstract class BaseNfcActivity extends BaseActivity { Notify.create(this, getString(R.string.error_nfc_unknown), Style.WARN).show(); break; } - default: + default: { Notify.create(this, getString(R.string.error_nfc, e.getMessage()), Style.WARN).show(); + break; + } } } @@ -311,9 +313,6 @@ public abstract class BaseNfcActivity extends BaseActivity { mPw1ValidatedForDecrypt = false; mPw3Validated = false; - // TODO: Handle non-default Admin PIN - mAdminPin = new Passphrase("12345678"); - onNfcPerform(); mIsoDep.close(); @@ -569,12 +568,12 @@ public abstract class BaseNfcActivity extends BaseActivity { */ public void nfcVerifyPIN(int mode) throws IOException { if (mPin != null || mode == 0x83) { - byte[] pin; + byte[] pin; if (mode == 0x83) { - pin = new String(mAdminPin.getCharArray()).getBytes(); + pin = mAdminPin.toStringUnsafe().getBytes(); } else { - pin = new String(mPin.getCharArray()).getBytes(); + pin = mPin.toStringUnsafe().getBytes(); } // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time. @@ -611,12 +610,11 @@ public abstract class BaseNfcActivity extends BaseActivity { * @param pw For PW1, this is 0x81. For PW3 (Admin PIN), mode is 0x83. * @param newPinString The new PW1 or PW3. */ - public void nfcModifyPIN(int pw, String newPinString) throws IOException { + public void nfcModifyPIN(int pw, byte[] newPin) throws IOException { final int MAX_PW1_LENGTH_INDEX = 1; final int MAX_PW3_LENGTH_INDEX = 3; byte[] pwStatusBytes = nfcGetPwStatusBytes(); - byte[] newPin = newPinString.getBytes(); if (pw == 0x81) { if (newPin.length < 6 || newPin.length > pwStatusBytes[MAX_PW1_LENGTH_INDEX]) { @@ -631,11 +629,10 @@ public abstract class BaseNfcActivity extends BaseActivity { } byte[] pin; - if (pw == 0x83) { - pin = new String(mAdminPin.getCharArray()).getBytes(); + pin = mAdminPin.toStringUnsafe().getBytes(); } else { - pin = new String(mPin.getCharArray()).getBytes(); + pin = mPin.toStringUnsafe().getBytes(); } // Command APDU for CHANGE REFERENCE DATA command (page 32) @@ -700,7 +697,7 @@ public abstract class BaseNfcActivity extends BaseActivity { throw new IOException("Invalid key slot"); } - RSAPrivateCrtKey crtSecretKey = null; + RSAPrivateCrtKey crtSecretKey; try { secretKey.unlock(passphrase); crtSecretKey = secretKey.getCrtSecretKey(); @@ -719,7 +716,7 @@ public abstract class BaseNfcActivity extends BaseActivity { } if (!mPw3Validated) { - nfcVerifyPIN(0x83); // (Verify PW1 with mode 83) + nfcVerifyPIN(0x83); // (Verify PW3 with mode 83) } byte[] header= Hex.decode( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java index 06efdde4d..fe42c7a2c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java @@ -117,6 +117,13 @@ public class Passphrase implements Parcelable { } } + /** + * Creates a new String from the char[]. This is considered unsafe! + */ + public String toStringUnsafe() { + return new String(mPassphrase); + } + @Override public boolean equals(Object o) { if (this == o) { @@ -127,11 +134,7 @@ public class Passphrase implements Parcelable { } Passphrase that = (Passphrase) o; - if (!Arrays.equals(mPassphrase, that.mPassphrase)) { - return false; - } - - return true; + return Arrays.equals(mPassphrase, that.mPassphrase); } @Override -- cgit v1.2.3