aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-10-01 17:28:43 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-10-01 17:28:43 +0200
commit7c79902a82602ff4e25b03e1232faa1a1768ba16 (patch)
tree03ec60c97bd961436ffffe17ad6917db768bfafa /OpenKeychain/src
parent7f1dbccb5b1640482e9b83391400506f4ad40e04 (diff)
parent4f13dc4fc5e9be78a73fcc4bbafbc025baaf3aa0 (diff)
downloadopen-keychain-7c79902a82602ff4e25b03e1232faa1a1768ba16.tar.gz
open-keychain-7c79902a82602ff4e25b03e1232faa1a1768ba16.tar.bz2
open-keychain-7c79902a82602ff4e25b03e1232faa1a1768ba16.zip
Merge branch 'master' into encrypted-export
Diffstat (limited to 'OpenKeychain/src')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/BitInputStream.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/SentenceConfirm.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java33
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java42
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java125
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java8
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml2
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java3
12 files changed, 143 insertions, 116 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/BitInputStream.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/BitInputStream.java
index b6ec7234e..111e0b366 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/BitInputStream.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/BitInputStream.java
@@ -26,7 +26,7 @@ import java.io.InputStream;
* general Java InputStream.
* Like the various Stream-classes from Java, the BitInputStream
* has to be created based on another Input stream. It provides
- * a function to read the next bit from the sream, as well as to read multiple
+ * a function to read the next bit from the stream, as well as to read multiple
* bits at once and write the resulting data into an integer value.
* <p/>
* source: http://developer.nokia.com/Community/Wiki/Bit_Input/Output_Stream_utility_classes_for_efficient_data_transfer
@@ -69,11 +69,11 @@ public class BitInputStream {
* @return integer value containing the bits read from the stream.
* @throws IOException
*/
- synchronized public int readBits(final int aNumberOfBits)
+ synchronized public int readBits(final int aNumberOfBits, boolean stuffIfEnd)
throws IOException {
int value = 0;
for (int i = aNumberOfBits - 1; i >= 0; i--) {
- value |= (readBit() << i);
+ value |= (readBit(stuffIfEnd) << i);
}
return value;
}
@@ -92,15 +92,20 @@ public class BitInputStream {
* @return 0 if the bit is 0, 1 if the bit is 1.
* @throws IOException
*/
- synchronized public int readBit() throws IOException {
+ synchronized public int readBit(boolean stuffIfEnd) throws IOException {
if (iIs == null)
throw new IOException("Already closed");
if (iNextBit == 8) {
iBuffer = iIs.read();
- if (iBuffer == -1)
- throw new EOFException();
+ if (iBuffer == -1) {
+ if (stuffIfEnd) {
+ return 1;
+ } else {
+ throw new EOFException();
+ }
+ }
iNextBit = 0;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/SentenceConfirm.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/SentenceConfirm.java
index ead70b8f6..0374d878c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/SentenceConfirm.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/experimental/SentenceConfirm.java
@@ -99,8 +99,12 @@ public class SentenceConfirm {
*/
private EntropyString getWord(List<String> words, BitInputStream bin) throws IOException {
final int neededBits = log(words.size(), 2);
- Log.d(Constants.TAG, "need " + neededBits + " bits of entropy");
- int bits = bin.readBits(neededBits);
+ Log.d(Constants.TAG, "need: " + neededBits + " bits of entropy");
+ Log.d(Constants.TAG, "available: " + bin.available() + " bits");
+ if (neededBits > bin.available()) {
+ Log.d(Constants.TAG, "stuffed with " + (neededBits - bin.available()) + " ones!");
+ }
+ int bits = bin.readBits(neededBits, true);
Log.d(Constants.TAG, "got word " + words.get(bits) + " with " + neededBits + " bits of entropy");
return new EntropyString(words.get(bits), neededBits);
}
@@ -108,7 +112,7 @@ public class SentenceConfirm {
private EntropyString getNounPhrase(BitInputStream bits) throws IOException {
final EntropyString phrase = new EntropyString();
phrase.append(getWord(art, bits)).append(" ");
- if (bits.readBit() != 0) {
+ if (bits.readBit(true) != 0) {
phrase.append(getWord(adj, bits)).append(" ");
}
phrase.incBits();
@@ -121,7 +125,7 @@ public class SentenceConfirm {
EntropyString getSentence(BitInputStream bits) throws IOException {
final EntropyString sentence = new EntropyString();
sentence.append(getNounPhrase(bits)); // Subject
- if (bits.readBit() != 0) {
+ if (bits.readBit(true) != 0) {
sentence.append(" ").append(getWord(vt, bits)); // Transitive verb
sentence.append(" ").append(getNounPhrase(bits)); // Object of transitive verb
} else {
@@ -129,17 +133,17 @@ public class SentenceConfirm {
}
sentence.incBits();
- if (bits.readBit() != 0) {
+ if (bits.readBit(true) != 0) {
sentence.append(" ").append(getWord(adv, bits)); // Adverb
}
sentence.incBits();
- if (bits.readBit() != 0) {
+ if (bits.readBit(true) != 0) {
sentence.append(" ").append(getWord(p, bits)); // Preposition
sentence.append(" ").append(getNounPhrase(bits)); // Object of preposition
}
sentence.incBits();
- Log.d(Constants.TAG, "got sentence " + sentence + " with " + sentence.getBits() + " bits of entropy");
+ Log.d(Constants.TAG, "got sentence '" + sentence + "' with " + sentence.getBits() + " bits of entropy");
// uppercase first character, end with dot (without increasing the bits)
sentence.getBuilder().replace(0, 1,
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
index 2409523bc..85be68505 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
@@ -191,9 +191,10 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
String fingerprint;
try {
- fingerprint = new SentenceConfirm(getActivity()).fromBytes(fingerprintBlob, 16);
- } catch (IOException ioe) {
+ fingerprint = new SentenceConfirm(getActivity()).fromBytes(fingerprintBlob, 20);
+ } catch (IOException e) {
fingerprint = "-";
+ Log.e(Constants.TAG, "Problem when creating sentence!", e);
}
mFingerprint.setTextSize(18);
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 579a001cb..94b5f4e4b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -30,7 +30,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -120,13 +119,9 @@ public class CreateKeyActivity extends BaseNfcActivity {
setTitle(R.string.title_import_keys);
} else {
-// Fragment frag = CreateYubiKeyBlankFragment.newInstance();
-// loadFragment(frag, FragAction.START);
-// setTitle(R.string.title_manage_my_keys);
- Notify.create(this,
- "YubiKey key creation is currently not supported. Please follow our FAQ.",
- Notify.Style.ERROR
- ).show();
+ Fragment frag = CreateYubiKeyBlankFragment.newInstance();
+ loadFragment(frag, FragAction.START);
+ setTitle(R.string.title_manage_my_keys);
}
// done
@@ -160,7 +155,7 @@ public class CreateKeyActivity extends BaseNfcActivity {
}
@Override
- protected void onNfcPostExecute() throws IOException {
+ protected void onNfcPostExecute() {
if (mCurrentFragment instanceof NfcListenerFragment) {
((NfcListenerFragment) mCurrentFragment).onNfcPostExecute();
return;
@@ -186,25 +181,23 @@ public class CreateKeyActivity extends BaseNfcActivity {
loadFragment(frag, FragAction.TO_RIGHT);
}
} else {
-// Fragment frag = CreateYubiKeyBlankFragment.newInstance();
-// loadFragment(frag, FragAction.TO_RIGHT);
- Notify.create(this,
- "YubiKey key creation is currently not supported. Please follow our FAQ.",
- Notify.Style.ERROR
- ).show();
+ Fragment frag = CreateYubiKeyBlankFragment.newInstance();
+ loadFragment(frag, FragAction.TO_RIGHT);
}
}
private boolean containsKeys(byte[] scannedFingerprints) {
+ if (scannedFingerprints == null) {
+ return false;
+ }
+
// If all fingerprint bytes are 0, the card contains no keys.
- boolean cardContainsKeys = false;
for (byte b : scannedFingerprints) {
if (b != 0) {
- cardContainsKeys = true;
- break;
+ return true;
}
}
- return cardContainsKeys;
+ return false;
}
@Override
@@ -264,7 +257,7 @@ public class CreateKeyActivity extends BaseNfcActivity {
interface NfcListenerFragment {
void doNfcInBackground() throws IOException;
- void onNfcPostExecute() throws IOException;
+ void onNfcPostExecute();
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
index d88e6b9f9..f7925b7f4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportFragment.java
@@ -208,7 +208,7 @@ public class CreateYubiKeyImportFragment
}
@Override
- public void onNfcPostExecute() throws IOException {
+ public void onNfcPostExecute() {
setData();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index 425a6755c..7f7532ddf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -377,7 +377,7 @@ public class ImportKeysActivity extends BaseNfcActivity
}
@Override
- protected void onNfcPostExecute() throws IOException {
+ protected void onNfcPostExecute() {
// either way, finish after NFC AsyncTask
finish();
}
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 b811b218e..7a2313e0f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -27,6 +27,7 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
+import android.widget.Toast;
import android.widget.ViewAnimator;
import org.sufficientlysecure.keychain.Constants;
@@ -72,7 +73,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
private RequiredInputParcel mRequiredInput;
private Intent mServiceIntent;
- private static final byte[] BLANK_FINGERPRINT = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ private static final byte[] BLANK_FINGERPRINT = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
private CryptoInputParcel mInputParcel;
@@ -245,7 +246,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
}
@Override
- protected void onNfcPostExecute() throws IOException {
+ protected void onNfcPostExecute() {
if (mServiceIntent != null) {
// if we're triggered by OpenPgpService
// save updated cryptoInputParcel in cache
@@ -276,6 +277,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
}
}
}
+
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
@@ -292,25 +294,14 @@ public class NfcOperationActivity extends BaseNfcActivity {
vAnimator.setDisplayedChild(3);
}
- private boolean shouldPutKey(byte[] fingerprint, int idx) throws IOException {
- byte[] cardFingerprint = nfcGetFingerprint(idx);
- // Slot is empty, or contains this key already. PUT KEY operation is safe
- if (Arrays.equals(cardFingerprint, BLANK_FINGERPRINT) ||
- Arrays.equals(cardFingerprint, fingerprint)) {
- return true;
- }
-
- // Slot already contains a different key; don't overwrite it.
- return false;
- }
-
@Override
- public void handlePinError() {
+ public void onPinError() {
// avoid a loop
Preferences prefs = Preferences.getPreferences(this);
if (prefs.useDefaultYubiKeyPin()) {
- toast(getString(R.string.error_pin_nodefault));
+ // use Toast because activity is finished afterwards
+ Toast.makeText(this, R.string.error_pin_nodefault, Toast.LENGTH_LONG).show();
setResult(RESULT_CANCELED);
finish();
return;
@@ -321,4 +312,23 @@ public class NfcOperationActivity extends BaseNfcActivity {
this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
}
+ private boolean shouldPutKey(byte[] fingerprint, int idx) throws IOException {
+ byte[] cardFingerprint = nfcGetMasterKeyFingerprint(idx);
+
+ // Note: special case: This should not happen, but happens with
+ // https://github.com/FluffyKaon/OpenPGP-Card, thus for now assume true
+ if (cardFingerprint == null) {
+ return true;
+ }
+
+ // Slot is empty, or contains this key already. PUT KEY operation is safe
+ if (Arrays.equals(cardFingerprint, BLANK_FINGERPRINT) ||
+ Arrays.equals(cardFingerprint, fingerprint)) {
+ return true;
+ }
+
+ // Slot already contains a different key; don't overwrite it.
+ return false;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 2279a5cde..4b3889737 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -555,7 +555,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
@Override
- protected void onNfcPostExecute() throws IOException {
+ protected void onNfcPostExecute() {
long yubiKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
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 972421abe..e68684c52 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
@@ -103,7 +103,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
/**
* Override to handle result of NFC operations (UI thread)
*/
- protected void onNfcPostExecute() throws IOException {
+ protected void onNfcPostExecute() {
final long subKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
@@ -134,9 +134,19 @@ public abstract class BaseNfcActivity extends BaseActivity {
Notify.create(this, error, Style.WARN).show();
}
+ /**
+ * Override to do something when PIN is wrong, e.g., clear passphrases (UI thread)
+ */
+ protected void onPinError() {
+ // use Toast because activity is finished afterwards
+ Toast.makeText(this, R.string.error_pin_wrong, Toast.LENGTH_LONG).show();
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
public void handleIntentInBackground(final Intent intent) {
// Actual NFC operations are executed in doInBackground to not block the UI thread
- new AsyncTask<Void, Void, Exception>() {
+ new AsyncTask<Void, Void, IOException>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
@@ -144,11 +154,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
@Override
- protected Exception doInBackground(Void... params) {
+ protected IOException doInBackground(Void... params) {
try {
handleTagDiscoveredIntent(intent);
- } catch (CardException e) {
- return e;
} catch (IOException e) {
return e;
}
@@ -157,7 +165,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
@Override
- protected void onPostExecute(Exception exception) {
+ protected void onPostExecute(IOException exception) {
super.onPostExecute(exception);
if (exception != null) {
@@ -165,11 +173,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
return;
}
- try {
- onNfcPostExecute();
- } catch (IOException e) {
- handleNfcError(e);
- }
+ onNfcPostExecute();
}
}.execute();
}
@@ -221,22 +225,30 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
}
- private void handleNfcError(Exception e) {
- Log.e(Constants.TAG, "nfc error", e);
+ private void handleNfcError(IOException e) {
if (e instanceof TagLostException) {
onNfcError(getString(R.string.error_nfc_tag_lost));
return;
}
+ if (e instanceof IsoDepNotSupportedException) {
+ onNfcError(getString(R.string.error_nfc_iso_dep_not_supported));
+ return;
+ }
+
short status;
if (e instanceof CardException) {
status = ((CardException) e).getResponseCode();
} else {
status = -1;
}
- // When entering a PIN, a status of 63CX indicates X attempts remaining.
- if ((status & (short)0xFFF0) == 0x63C0) {
+
+ // Wrong PIN, a status of 63CX indicates X attempts remaining.
+ if ((status & (short) 0xFFF0) == 0x63C0) {
+ // hook to do something different when PIN is wrong
+ onPinError();
+
int tries = status & 0x000F;
onNfcError(getResources().getQuantityString(R.plurals.error_pin, tries, tries));
return;
@@ -307,12 +319,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
- public void handlePinError() {
- toast("Wrong PIN!");
- setResult(RESULT_CANCELED);
- finish();
- }
-
/**
* Called when the system is about to start resuming a previous activity,
* disables NFC Foreground Dispatch
@@ -337,7 +343,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) {
- // shortcut if we only use the default yubikey pin
+ // shortcut if we only use the default YubiKey pin
Preferences prefs = Preferences.getPreferences(this);
if (prefs.useDefaultYubiKeyPin()) {
mPin = new Passphrase("123456");
@@ -345,10 +351,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
try {
- Passphrase phrase = PassphraseCacheService.getCachedPassphrase(this,
+ Passphrase passphrase = PassphraseCacheService.getCachedPassphrase(this,
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
- if (phrase != null) {
- mPin = phrase;
+ if (passphrase != null) {
+ mPin = passphrase;
return;
}
@@ -363,10 +369,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
- protected void setYubiKeyPin(Passphrase pin) {
- mPin = pin;
- }
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
@@ -406,6 +408,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
// Connect to the detected tag, setting a couple of settings
mIsoDep = IsoDep.get(detectedTag);
+ if (mIsoDep == null) {
+ throw new IsoDepNotSupportedException("Tag does not support ISO-DEP (ISO 14443-4)");
+ }
mIsoDep.setTimeout(TIMEOUT); // timeout is set to 100 seconds to avoid cancellation during calculation
mIsoDep.connect();
@@ -448,7 +453,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @return The long key id of the requested key, or null if not found.
*/
public Long nfcGetKeyId(int idx) throws IOException {
- byte[] fp = nfcGetFingerprint(idx);
+ byte[] fp = nfcGetMasterKeyFingerprint(idx);
if (fp == null) {
return null;
}
@@ -469,7 +474,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
byte[] buf = mIsoDep.transceive(Hex.decode(data));
Iso7816TLV tlv = Iso7816TLV.readSingle(buf, true);
- Log.d(Constants.TAG, "nfc tlv data:\n" + tlv.prettyPrint());
+ Log.d(Constants.TAG, "nfcGetFingerprints() Iso7816TLV tlv data:\n" + tlv.prettyPrint());
Iso7816TLV fptlv = Iso7816TLV.findRecursive(tlv, 0xc5);
if (fptlv == null) {
@@ -494,8 +499,11 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @param idx Index of the key to return the fingerprint from.
* @return The fingerprint of the requested key, or null if not found.
*/
- public byte[] nfcGetFingerprint(int idx) throws IOException {
+ public byte[] nfcGetMasterKeyFingerprint(int idx) throws IOException {
byte[] data = nfcGetFingerprints();
+ if (data == null) {
+ return null;
+ }
// return the master key fingerprint
ByteBuffer fpbuf = ByteBuffer.wrap(data);
@@ -507,14 +515,11 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
public byte[] nfcGetAid() throws IOException {
-
String info = "00CA004F00";
return mIsoDep.transceive(Hex.decode(info));
-
}
public String nfcGetUserId() throws IOException {
-
String info = "00CA006500";
return nfcGetHolderName(nfcCommunicate(info));
}
@@ -648,8 +653,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
String decryptedSessionKey = nfcGetDataField(second);
- Log.d(Constants.TAG, "decryptedSessionKey: " + decryptedSessionKey);
-
return Hex.decode(decryptedSessionKey);
}
@@ -682,7 +685,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
+ Hex.toHexString(pin);
String response = nfcCommunicate(login); // login
if (!response.equals(accepted)) {
- handlePinError();
throw new CardException("Bad PIN!", parseCardStatus(response));
}
@@ -737,7 +739,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
+ getHex(newPin);
String response = nfcCommunicate(changeReferenceDataApdu); // change PIN
if (!response.equals("9000")) {
- handlePinError();
throw new CardException("Failed to change PIN", parseCardStatus(response));
}
}
@@ -906,15 +907,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
/**
- * Prints a message to the screen
- *
- * @param text the text which should be contained within the toast
- */
- protected void toast(String text) {
- Toast.makeText(this, text, Toast.LENGTH_LONG).show();
- }
-
- /**
* Receive new NFC Intents to this activity only by enabling foreground dispatch.
* This can only be done in onResume!
*/
@@ -930,12 +922,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
};
- // https://code.google.com/p/android/issues/detail?id=62918
- // maybe mNfcAdapter.enableReaderMode(); ?
try {
mNfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
} catch (IllegalStateException e) {
- Log.i(Constants.TAG, "NfcForegroundDispatch Error!", e);
+ Log.i(Constants.TAG, "NfcForegroundDispatch Exception: Activity is not currently in the foreground?", e);
}
Log.d(Constants.TAG, "NfcForegroundDispatch has been enabled!");
}
@@ -952,14 +942,23 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
public String nfcGetHolderName(String name) {
- String slength;
- int ilength;
- name = name.substring(6);
- slength = name.substring(0, 2);
- ilength = Integer.parseInt(slength, 16) * 2;
- name = name.substring(2, ilength + 2);
- name = (new String(Hex.decode(name))).replace('<', ' ');
- return (name);
+ try {
+ String slength;
+ int ilength;
+ name = name.substring(6);
+ slength = name.substring(0, 2);
+ ilength = Integer.parseInt(slength, 16) * 2;
+ name = name.substring(2, ilength + 2);
+ name = (new String(Hex.decode(name))).replace('<', ' ');
+ return name;
+ } catch (IndexOutOfBoundsException e) {
+ // try-catch for https://github.com/FluffyKaon/OpenPGP-Card
+ // Note: This should not happen, but happens with
+ // https://github.com/FluffyKaon/OpenPGP-Card, thus return an empty string for now!
+
+ Log.e(Constants.TAG, "Couldn't get holder name, returning empty string!", e);
+ return "";
+ }
}
private String nfcGetDataField(String output) {
@@ -974,6 +973,14 @@ public abstract class BaseNfcActivity extends BaseActivity {
return new String(Hex.encode(raw));
}
+ public class IsoDepNotSupportedException extends IOException {
+
+ public IsoDepNotSupportedException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ }
+
public class CardException extends IOException {
private short mResponseCode;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index 8f5753dae..9ab0db03e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -571,8 +571,9 @@ public class KeyFormattingUtils {
sigIcon = R.drawable.status_signature_invalid_cutout_24dp;
sigColor = R.color.key_flag_red;
- sigActionText = R.string.decrypt_result_action_show;
- sigActionIcon = R.drawable.ic_vpn_key_grey_24dp;
+ // won't be used, but makes compiler happy
+ sigActionText = 0;
+ sigActionIcon = 0;
break;
}
@@ -584,7 +585,8 @@ public class KeyFormattingUtils {
holder.getSignatureStatusText().setText(sigText);
holder.getSignatureStatusText().setTextColor(sigColorRes);
- if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
+ if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE
+ && signatureResult.getResult() != OpenPgpSignatureResult.RESULT_INVALID_SIGNATURE) {
// has a signature, thus display layouts
holder.getSignatureLayout().setVisibility(View.VISIBLE);
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index d6333019a..bad91d9f9 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -1535,8 +1535,10 @@
<string name="error_nfc_chaining_error">"YubiKey expected last command in a chain."</string>
<string name="error_nfc_header">"YubiKey reported invalid %s byte."</string>
<string name="error_nfc_tag_lost">"YubiKey has been taken off too early. Keep the YubiKey at the back until the operation finishes."</string>
+ <string name="error_nfc_iso_dep_not_supported">"Tag does not support ISO-DEP (ISO 14443-4)"</string>
<string name="error_nfc_try_again">"Try again"</string>
<string name="error_pin_nodefault">Default PIN was rejected!</string>
+ <string name="error_pin_wrong">PIN is wrong!</string>
<string name="error_temp_file">Error creating temporary file.</string>
<string name="btn_delete_original">Delete original file</string>
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
index 4cdcf0117..b870e5494 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
@@ -28,6 +28,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;
import org.spongycastle.bcpg.sig.KeyFlags;
+import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.BuildConfig;
import org.sufficientlysecure.keychain.WorkaroundBuildConfig;
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
@@ -41,6 +42,7 @@ import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.security.Security;
import java.util.Iterator;
import java.util.Random;
@@ -53,6 +55,7 @@ public class UncachedKeyringTest {
@BeforeClass
public static void setUpOnce() throws Exception {
+ Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out;
SaveKeyringParcel parcel = new SaveKeyringParcel();