Added functionality to retrieve status of password and reset password with VERIFY command

This commit is contained in:
Joeri 2017-12-01 16:28:47 +01:00
parent 53fcff53f8
commit 5db38b3d31
3 changed files with 97 additions and 27 deletions

View File

@ -4,10 +4,16 @@ This is a Java Card implementation of the OpenPGP smart card specifications.
# Building
`git submodule init ext/oracle_javacard_sdks`
`git submodule update --init --recursive`
`ant`
# Testing
`ant test`
# Installing
This can easily be done using GlobalPlatformPro (https://github.com/martinpaljak/GlobalPlatformPro):
`java -jar gp.jar -install openpgpcard.cap`

View File

@ -236,7 +236,7 @@ public class OpenPGPApplet extends Applet implements ISO7816 {
// VERIFY
case (byte) 0x20:
verify(apdu, p2);
verify(apdu, p2, p1);
break;
// CHANGE REFERENCE DATA
@ -400,6 +400,17 @@ public class OpenPGPApplet extends Applet implements ISO7816 {
in_received = 0;
}
private OwnerPIN getPIN(byte mode) {
OwnerPIN pw = pw1;
if (mode == (byte) 0x81 || mode == (byte) 0x82) {
pw = pw1;
} else if (mode == (byte) 0x83) {
pw = pw3;
} else {
ISOException.throwIt(SW_INCORRECT_P1P2);
}
return pw;
}
/**
* Provide the VERIFY command (INS 20)
*
@ -410,34 +421,61 @@ public class OpenPGPApplet extends Applet implements ISO7816 {
* @param mode
* Password and mode to be verified
*/
private void verify(APDU apdu, byte mode) {
if (mode == (byte) 0x81 || mode == (byte) 0x82) {
// Check length of input
if (in_received < PW1_MIN_LENGTH || in_received > PW1_MAX_LENGTH)
ISOException.throwIt(SW_WRONG_LENGTH);
private void verify(APDU apdu, byte mode, byte action) {
if(in_received == 0) {
// Select correct PIN
OwnerPIN pw = getPIN(mode);
// Check given PW1 and set requested mode if verified succesfully
if (pw1.check(buffer, _0, (byte) in_received)) {
if (mode == (byte) 0x81)
pw1_modes[PW1_MODE_NO81] = true;
else
pw1_modes[PW1_MODE_NO82] = true;
} else {
ISOException
.throwIt((short) (0x63C0 | pw1.getTriesRemaining()));
}
} else if (mode == (byte) 0x83) {
// Check length of input
if (in_received < PW3_MIN_LENGTH || in_received > PW3_MAX_LENGTH)
ISOException.throwIt(SW_WRONG_LENGTH);
// Check PW3
if (!pw3.check(buffer, _0, (byte) in_received)) {
ISOException
.throwIt((short) (0x63C0 | pw3.getTriesRemaining()));
if (action == 0x00) {
// Status for password requested
if(pw.isValidated()) {
// Return 9000 if password is still valid
ISOException.throwIt(SW_NO_ERROR);
} else {
// Return remaining number of tries otherwise
ISOException
.throwIt((short) (0x63C0 | pw.getTriesRemaining()));
}
} else if (action == (byte)0xFF) {
// Reset PIN
pw.reset();
// For PW1 also reset PW1 mode
if (mode == (byte) 0x81 || mode == (byte) 0x82) {
pw1_modes[PW1_MODE_NO81] = false;
pw1_modes[PW1_MODE_NO82] = false;
}
}
} else {
ISOException.throwIt(SW_INCORRECT_P1P2);
if (mode == (byte) 0x81 || mode == (byte) 0x82) {
// Check length of input
if (in_received < PW1_MIN_LENGTH || in_received > PW1_MAX_LENGTH)
ISOException.throwIt(SW_WRONG_LENGTH);
// Check given PW1 and set requested mode if verified succesfully
if (pw1.check(buffer, _0, (byte) in_received)) {
if (mode == (byte) 0x81)
pw1_modes[PW1_MODE_NO81] = true;
else
pw1_modes[PW1_MODE_NO82] = true;
} else {
ISOException
.throwIt((short) (0x63C0 | pw1.getTriesRemaining()));
}
} else if (mode == (byte) 0x83) {
// Check length of input
if (in_received < PW3_MIN_LENGTH || in_received > PW3_MAX_LENGTH)
ISOException.throwIt(SW_WRONG_LENGTH);
// Check PW3
if (!pw3.check(buffer, _0, (byte) in_received)) {
ISOException
.throwIt((short) (0x63C0 | pw3.getTriesRemaining()));
}
} else {
ISOException.throwIt(SW_INCORRECT_P1P2);
}
}
}

View File

@ -84,6 +84,32 @@ public class OpenPGPAppletTest {
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc0 }, response);
}
@Test
public void test_userPINStatus() {
byte[] response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 });
assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc2 }, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc2 }, response);
// Verify correct password
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(new byte[] { (byte) 0x90, 0x00 }, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response);
// Invalidate correctly verified password
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, (byte)0xFF, (byte) 0x81, 0x00 });
assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc3 }, response);
}
/**
* Test reset of PIN try counter by first verifying a wrong PIN, followed by