diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org')
12 files changed, 167 insertions, 79 deletions
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<String> mRevokeUserIds;      public ArrayList<Long> 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<Long>) 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<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() { @@ -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<byte[]> 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<SaveKeyringParcel, EditKeyResult> callback                  = new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() { 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<Void, Void, Pair<String, String>>() { +            new AsyncTask<Void, Void, Pair<Passphrase, Passphrase>>() {                  @Override -                protected Pair<String, String> doInBackground(Void... unused) { +                protected Pair<Passphrase, Passphrase> 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<String, String> pair) { +                protected void onPostExecute(Pair<Passphrase, Passphrase> 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  | 
