mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
further improve yubikey error handling
This commit is contained in:
parent
3bb194fc08
commit
c694d73cab
@ -124,7 +124,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
|
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
|
||||||
Passphrase passphrase,
|
Passphrase passphrase,
|
||||||
String primaryUserId) {
|
String primaryUserId) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + masterKeyId);
|
Log.d(Constants.TAG, "PassphraseCacheService.addCachedPassphrase() for " + masterKeyId);
|
||||||
|
|
||||||
Intent intent = new Intent(context, PassphraseCacheService.class);
|
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||||
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
|
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
|
||||||
@ -138,6 +138,19 @@ public class PassphraseCacheService extends Service {
|
|||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void clearCachedPassphrase(Context context, long masterKeyId, long subKeyId) {
|
||||||
|
Log.d(Constants.TAG, "PassphraseCacheService.clearCachedPassphrase() for " + masterKeyId);
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||||
|
intent.setAction(ACTION_PASSPHRASE_CACHE_CLEAR);
|
||||||
|
|
||||||
|
intent.putExtra(EXTRA_KEY_ID, masterKeyId);
|
||||||
|
intent.putExtra(EXTRA_SUBKEY_ID, subKeyId);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a cached passphrase from memory by sending an intent to the service. This method is
|
* Gets a cached passphrase from memory by sending an intent to the service. This method is
|
||||||
* designed to wait until the service returns the passphrase.
|
* designed to wait until the service returns the passphrase.
|
||||||
@ -395,12 +408,27 @@ public class PassphraseCacheService extends Service {
|
|||||||
} else if (ACTION_PASSPHRASE_CACHE_CLEAR.equals(intent.getAction())) {
|
} else if (ACTION_PASSPHRASE_CACHE_CLEAR.equals(intent.getAction())) {
|
||||||
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
||||||
|
|
||||||
// Stop all ttl alarms
|
if (intent.hasExtra(EXTRA_SUBKEY_ID) && intent.hasExtra(EXTRA_KEY_ID)) {
|
||||||
for (int i = 0; i < mPassphraseCache.size(); i++) {
|
|
||||||
am.cancel(buildIntent(this, mPassphraseCache.keyAt(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
mPassphraseCache.clear();
|
long keyId;
|
||||||
|
if (Preferences.getPreferences(mContext).getPassphraseCacheSubs()) {
|
||||||
|
keyId = intent.getLongExtra(EXTRA_KEY_ID, 0L);
|
||||||
|
} else {
|
||||||
|
keyId = intent.getLongExtra(EXTRA_SUBKEY_ID, 0L);
|
||||||
|
}
|
||||||
|
// Stop specific ttl alarm and
|
||||||
|
am.cancel(buildIntent(this, keyId));
|
||||||
|
mPassphraseCache.delete(keyId);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Stop all ttl alarms
|
||||||
|
for (int i = 0; i < mPassphraseCache.size(); i++) {
|
||||||
|
am.cancel(buildIntent(this, mPassphraseCache.keyAt(i)));
|
||||||
|
}
|
||||||
|
mPassphraseCache.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
updateService();
|
updateService();
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,6 +56,10 @@ public class RequiredInputParcel implements Parcelable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMasterKeyId() {
|
||||||
|
return mMasterKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
public long getSubKeyId() {
|
public long getSubKeyId() {
|
||||||
return mSubKeyId;
|
return mSubKeyId;
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,12 @@ import android.view.WindowManager;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
|
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -89,4 +91,24 @@ public class NfcOperationActivity extends BaseNfcActivity {
|
|||||||
finish();
|
finish();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handlePinError() {
|
||||||
|
|
||||||
|
// avoid a loop
|
||||||
|
Preferences prefs = Preferences.getPreferences(this);
|
||||||
|
if (prefs.useDefaultYubikeyPin()) {
|
||||||
|
toast(getString(R.string.error_pin_nodefault));
|
||||||
|
setResult(RESULT_CANCELED);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear (invalid) passphrase
|
||||||
|
PassphraseCacheService.clearCachedPassphrase(
|
||||||
|
this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
|
||||||
|
|
||||||
|
obtainYubikeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,12 @@ 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,
|
* Called when the system is about to start resuming a previous activity,
|
||||||
* disables NFC Foreground Dispatch
|
* disables NFC Foreground Dispatch
|
||||||
@ -170,10 +176,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
|
|||||||
+ "D27600012401" // Data (6 bytes)
|
+ "D27600012401" // Data (6 bytes)
|
||||||
+ "00"; // Le
|
+ "00"; // Le
|
||||||
if ( ! nfcCommunicate(opening).equals(accepted)) { // activate connection
|
if ( ! nfcCommunicate(opening).equals(accepted)) { // activate connection
|
||||||
toast("Opening Error!");
|
throw new IOException("Initialization failed!");
|
||||||
setResult(RESULT_CANCELED);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPin != null) {
|
if (mPin != null) {
|
||||||
@ -189,9 +192,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
|
|||||||
+ String.format("%02x", pin.length) // Lc
|
+ String.format("%02x", pin.length) // Lc
|
||||||
+ Hex.toHexString(pin);
|
+ Hex.toHexString(pin);
|
||||||
if (!nfcCommunicate(login).equals(accepted)) { // login
|
if (!nfcCommunicate(login).equals(accepted)) { // login
|
||||||
toast("Wrong PIN!");
|
handlePinError();
|
||||||
setResult(RESULT_CANCELED);
|
|
||||||
finish();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +322,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
|
|||||||
switch (hashAlgo) {
|
switch (hashAlgo) {
|
||||||
case HashAlgorithmTags.SHA1:
|
case HashAlgorithmTags.SHA1:
|
||||||
if (hash.length != 20) {
|
if (hash.length != 20) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 10!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 10!");
|
||||||
}
|
}
|
||||||
dsi = "23" // Lc
|
dsi = "23" // Lc
|
||||||
+ "3021" // Tag/Length of Sequence, the 0x21 includes all following 33 bytes
|
+ "3021" // Tag/Length of Sequence, the 0x21 includes all following 33 bytes
|
||||||
@ -332,36 +333,36 @@ public abstract class BaseNfcActivity extends BaseActivity {
|
|||||||
break;
|
break;
|
||||||
case HashAlgorithmTags.RIPEMD160:
|
case HashAlgorithmTags.RIPEMD160:
|
||||||
if (hash.length != 20) {
|
if (hash.length != 20) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 20!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 20!");
|
||||||
}
|
}
|
||||||
dsi = "233021300906052B2403020105000414" + getHex(hash);
|
dsi = "233021300906052B2403020105000414" + getHex(hash);
|
||||||
break;
|
break;
|
||||||
case HashAlgorithmTags.SHA224:
|
case HashAlgorithmTags.SHA224:
|
||||||
if (hash.length != 28) {
|
if (hash.length != 28) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 28!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 28!");
|
||||||
}
|
}
|
||||||
dsi = "2F302D300D06096086480165030402040500041C" + getHex(hash);
|
dsi = "2F302D300D06096086480165030402040500041C" + getHex(hash);
|
||||||
break;
|
break;
|
||||||
case HashAlgorithmTags.SHA256:
|
case HashAlgorithmTags.SHA256:
|
||||||
if (hash.length != 32) {
|
if (hash.length != 32) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 32!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 32!");
|
||||||
}
|
}
|
||||||
dsi = "333031300D060960864801650304020105000420" + getHex(hash);
|
dsi = "333031300D060960864801650304020105000420" + getHex(hash);
|
||||||
break;
|
break;
|
||||||
case HashAlgorithmTags.SHA384:
|
case HashAlgorithmTags.SHA384:
|
||||||
if (hash.length != 48) {
|
if (hash.length != 48) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 48!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 48!");
|
||||||
}
|
}
|
||||||
dsi = "433041300D060960864801650304020205000430" + getHex(hash);
|
dsi = "433041300D060960864801650304020205000430" + getHex(hash);
|
||||||
break;
|
break;
|
||||||
case HashAlgorithmTags.SHA512:
|
case HashAlgorithmTags.SHA512:
|
||||||
if (hash.length != 64) {
|
if (hash.length != 64) {
|
||||||
throw new RuntimeException("Bad hash length (" + hash.length + ", expected 64!");
|
throw new IOException("Bad hash length (" + hash.length + ", expected 64!");
|
||||||
}
|
}
|
||||||
dsi = "533051300D060960864801650304020305000440" + getHex(hash);
|
dsi = "533051300D060960864801650304020305000440" + getHex(hash);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Not supported hash algo!");
|
throw new IOException("Not supported hash algo!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command APDU for PERFORM SECURITY OPERATION: COMPUTE DIGITAL SIGNATURE (page 37)
|
// Command APDU for PERFORM SECURITY OPERATION: COMPUTE DIGITAL SIGNATURE (page 37)
|
||||||
@ -388,14 +389,12 @@ public abstract class BaseNfcActivity extends BaseActivity {
|
|||||||
Log.d(Constants.TAG, "final response:" + status);
|
Log.d(Constants.TAG, "final response:" + status);
|
||||||
|
|
||||||
if ( ! "9000".equals(status)) {
|
if ( ! "9000".equals(status)) {
|
||||||
toast("Bad NFC response code: " + status);
|
throw new IOException("Bad NFC response code: " + status);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the signature we received is actually the expected number of bytes long!
|
// Make sure the signature we received is actually the expected number of bytes long!
|
||||||
if (signature.length() != 256 && signature.length() != 512) {
|
if (signature.length() != 256 && signature.length() != 512) {
|
||||||
toast("Bad signature length! Expected 128 or 256 bytes, got " + signature.length() / 2);
|
throw new IOException("Bad signature length! Expected 128 or 256 bytes, got " + signature.length() / 2);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Hex.decode(signature);
|
return Hex.decode(signature);
|
||||||
|
@ -1279,5 +1279,6 @@
|
|||||||
<string name="btn_import">"Import"</string>
|
<string name="btn_import">"Import"</string>
|
||||||
<string name="snack_yubi_other">Different key stored on Yubikey!</string>
|
<string name="snack_yubi_other">Different key stored on Yubikey!</string>
|
||||||
<string name="error_nfc">"NFC Error: %s"</string>
|
<string name="error_nfc">"NFC Error: %s"</string>
|
||||||
|
<string name="error_pin_nodefault">Default PIN was rejected!</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user