Track state of PIN verification on smart card; only verify when needed.

This commit is contained in:
Joey Castillo 2015-04-20 17:27:55 -04:00
parent 71aeffdfc8
commit 104fdcd6bf

View File

@ -57,6 +57,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
public static final int REQUEST_CODE_PASSPHRASE = 1; public static final int REQUEST_CODE_PASSPHRASE = 1;
protected Passphrase mPin; protected Passphrase mPin;
protected boolean mPw1ValidForMultipleSignatures;
protected boolean mPw1ValidatedForSignature;
protected boolean mPw1ValidatedForDecrypt; // Mode 82 does other things; consider renaming?
private NfcAdapter mNfcAdapter; private NfcAdapter mNfcAdapter;
private IsoDep mIsoDep; private IsoDep mIsoDep;
@ -201,6 +204,11 @@ public abstract class BaseNfcActivity extends BaseActivity {
throw new IOException("Initialization failed!"); throw new IOException("Initialization failed!");
} }
byte[] pwStatusBytes = nfcGetPwStatusBytes();
mPw1ValidForMultipleSignatures = (pwStatusBytes[0] == 1);
mPw1ValidatedForSignature = false;
mPw1ValidatedForDecrypt = false;
onNfcPerform(); onNfcPerform();
mIsoDep.close(); mIsoDep.close();
@ -278,6 +286,15 @@ public abstract class BaseNfcActivity extends BaseActivity {
return fptlv.mV; return fptlv.mV;
} }
/** Return the PW Status Bytes from the card. This is a simple DO; no TLV decoding needed.
*
* @return Seven bytes in fixed format, plus 0x9000 status word at the end.
*/
public byte[] nfcGetPwStatusBytes() throws IOException {
String data = "00CA00C400";
return mIsoDep.transceive(Hex.decode(data));
}
/** Return the fingerprint from application specific data stored on tag, or /** Return the fingerprint from application specific data stored on tag, or
* null if it doesn't exist. * null if it doesn't exist.
* *
@ -316,7 +333,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @return a big integer representing the MPI for the given hash * @return a big integer representing the MPI for the given hash
*/ */
public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException { public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException {
nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing) if (!mPw1ValidatedForSignature) {
nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing)
}
// dsi, including Lc // dsi, including Lc
String dsi; String dsi;
@ -391,6 +410,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
Log.d(Constants.TAG, "final response:" + status); Log.d(Constants.TAG, "final response:" + status);
if (!mPw1ValidForMultipleSignatures) {
mPw1ValidatedForSignature = false;
}
if ( ! "9000".equals(status)) { if ( ! "9000".equals(status)) {
throw new IOException("Bad NFC response code: " + status); throw new IOException("Bad NFC response code: " + status);
} }
@ -410,7 +433,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @return the decoded session key * @return the decoded session key
*/ */
public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException { public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException {
nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption) if (!mPw1ValidatedForDecrypt) {
nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption)
}
String firstApdu = "102a8086fe"; String firstApdu = "102a8086fe";
String secondApdu = "002a808603"; String secondApdu = "002a808603";
@ -458,6 +483,12 @@ public abstract class BaseNfcActivity extends BaseActivity {
handlePinError(); handlePinError();
throw new IOException("Bad PIN!"); throw new IOException("Bad PIN!");
} }
if (mode == 0x81) {
mPw1ValidatedForSignature = true;
} else if (mode == 0x82) {
mPw1ValidatedForDecrypt = true;
}
} }
} }