diff --git a/test/openpgpcard/OpenPGPAppletTest.java b/test/openpgpcard/OpenPGPAppletTest.java index 2848e0d..c468467 100644 --- a/test/openpgpcard/OpenPGPAppletTest.java +++ b/test/openpgpcard/OpenPGPAppletTest.java @@ -2,6 +2,8 @@ package openpgpcard; import static org.junit.Assert.assertArrayEquals; +import java.lang.reflect.Array; + import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -12,6 +14,22 @@ import javacard.framework.AID; import openpgpcard.OpenPGPApplet; public class OpenPGPAppletTest { + static byte[] SW_NO_ERROR = new byte[] {(byte)0x90, 0x00}; + + static byte[] SW_WARNING_STATE_UNCHANGED = new byte[] {0x62, 0x00}; + static byte[] SW_TRIES_REMAINING_0 = new byte[] {0x63, (byte)0xc0}; + static byte[] SW_TRIES_REMAINING_1 = new byte[] {0x63, (byte)0xc1}; + static byte[] SW_TRIES_REMAINING_2 = new byte[] {0x63, (byte)0xc2}; + static byte[] SW_TRIES_REMAINING_3 = new byte[] {0x63, (byte)0xc3}; + static byte[] SW_WRONG_LENGTH = new byte[] {0x67, 0x00}; + static byte[] SW_SECURITY_STATUS_NOT_SATISFIED = new byte[] {0x69, (byte)0x82}; + static byte[] SW_DATA_INVALID = new byte[] {0x69, (byte)0x84}; + static byte[] SW_CONDITIONS_NOT_SATISFIED = new byte[] {0x69, (byte)0x85}; + static byte[] SW_RECORD_NOT_FOUND = new byte[] {0x6a, (byte)0x83}; + static byte[] SW_INCORRECT_P1P2 = new byte[] {0x6a, (byte)0x86}; + static byte[] SW_INS_NOT_SUPPORTED = new byte[] {0x6d, 0x00}; + static byte[] SW_UNKNOWN = new byte[] {0x6f, 0x00}; + static private byte[] appletAID = new byte[] { (byte) 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }; static private AID aid = new AID(appletAID, (short) 0, (byte) appletAID.length); @@ -66,50 +84,147 @@ public class OpenPGPAppletTest { public void test_userPINValid() { byte[] response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }); - assertArrayEquals(new byte[] { (byte) 0x90, 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); } @Test public void test_userPINInvalid() { 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); + assertArrayEquals(SW_TRIES_REMAINING_2, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); - assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc1 }, response); + assertArrayEquals(SW_TRIES_REMAINING_1, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); - assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc0 }, response); + assertArrayEquals(SW_TRIES_REMAINING_0, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }); - assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc0 }, response); + assertArrayEquals(SW_TRIES_REMAINING_0, 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); + assertArrayEquals(SW_TRIES_REMAINING_2, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 }); - assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc2 }, response); + assertArrayEquals(SW_TRIES_REMAINING_2, response); - // Verify correct password + // Verify correct PIN response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }); - assertArrayEquals(new byte[] { (byte) 0x90, 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 }); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); - // Invalidate correctly verified password + // Invalidate correctly verified PIN response = simulator.transmitCommand( new byte[] { 0x00, 0x20, (byte)0xFF, (byte) 0x81, 0x00 }); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 }); - assertArrayEquals(new byte[] { (byte) 0x63, (byte) 0xc3 }, response); + assertArrayEquals(SW_TRIES_REMAINING_3, response); } + + @Test + public void test_adminPINValid() { + byte[] response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x83, 0x08, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 }); + assertArrayEquals(SW_NO_ERROR, response); + } + + @Test + public void test_userPINResetRC() { + test_adminPINValid(); + byte[] response = simulator.transmitCommand( + new byte[] { 0x00, (byte)0xDA, 0x00, (byte) 0xD3, 0x08, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + + // Reset admin pasword + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, (byte)0xFF, (byte) 0x83, 0x00 }); + assertArrayEquals(SW_NO_ERROR, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x83, 0x00 }); + assertArrayEquals(SW_TRIES_REMAINING_3, response); + + // Block user PIN + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_2, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_1, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_0, response); + + // Reset user PIN using RC PIN + response = simulator.transmitCommand( + new byte[] { 0x00, 0x2C, 0x00, (byte) 0x81, 0x10, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + + // Check the counter is reset + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 }); + assertArrayEquals(SW_TRIES_REMAINING_3, response); + + // Verify new user PIN + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x08, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + } + + @Test + public void test_userPINResetAdmin() { + test_adminPINValid(); + byte[] response = simulator.transmitCommand( + new byte[] { 0x00, (byte)0xDA, 0x00, (byte) 0xD3, 0x08, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + + // Reset admin pasword + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, (byte)0xFF, (byte) 0x83, 0x00 }); + assertArrayEquals(SW_NO_ERROR, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x83, 0x00 }); + assertArrayEquals(SW_TRIES_REMAINING_3, response); + + // Block user PIN + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_2, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_1, response); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_TRIES_REMAINING_0, response); + + // Reset user PIN without verifying admin password + response = simulator.transmitCommand( + new byte[] { 0x00, 0x2C, 0x02, (byte) 0x81, 0x08, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_CONDITIONS_NOT_SATISFIED, response); + + // Reset user PIN after verifying admin password + test_adminPINValid(); + response = simulator.transmitCommand( + new byte[] { 0x00, 0x2C, 0x02, (byte) 0x81, 0x08, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + + // Check the counter is reset + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 }); + assertArrayEquals(SW_TRIES_REMAINING_3, response); + + // Verify new user PIN + response = simulator.transmitCommand( + new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x08, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }); + assertArrayEquals(SW_NO_ERROR, response); + } /** * Test reset of PIN try counter by first verifying a wrong PIN, followed by @@ -120,19 +235,19 @@ public class OpenPGPAppletTest { public void test_userPINReset() { 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); + assertArrayEquals(SW_TRIES_REMAINING_2, response); response = simulator.transmitCommand( new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); 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); + assertArrayEquals(SW_TRIES_REMAINING_2, response); } @Test public void test_generateKey() { byte[] response = simulator.transmitCommand(hexToBytes("00200083083132333435363738")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes("0047800002B600")); byte[] response2 = simulator.transmitCommand(hexToBytes("0047810002B600")); assertArrayEquals(response, response2); @@ -143,19 +258,19 @@ public class OpenPGPAppletTest { byte[] response = simulator.transmitCommand(hexToBytes("0047810002B600")); assertArrayEquals(new byte[] { (byte) 0x69, (byte) 0x85 }, response); response = simulator.transmitCommand(hexToBytes("00200083083132333435363738")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes( "10DB3FFFFE4D8203A2B6007F48159103928180938180948180958180968180978201005F48820383010001C024584779F7C68DB6299D63E06D8DC029631CED208A03634D648EF4984AB7F79FCF620A81D690D6E98B690AB2444311406B8EC97460931EDC39E74C4047325271D993C97F5216345768E53460121BF78FF984595C00123940575342A2E619BBC5A7C8492453F38CD655F13995770477595279FD2E27409B97928F40E8D01F91EB61C12B9EC0A31213D32975A46C95BAADEF06468DD68CE4858C7E7F94754486825E2673CFA86D3B2764973899882DC1ACB2C19C4E90BFCF319272FF5E86CC1B36FBA96BF3F06DEB9CC6B0BDB1BB4F300A07985BDCE8CAF6")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes( "10DB3FFFFE11FE3CA640852F0334745FE8B16C9239427CA4A4E7EE406EE2773FE7E447F5F6CFF061EACCCC83B7B2201715989214937C59472FA1BD027FCF3F7727CB14F81C7845988A983452E9B7CA04805126F3C19A1E8E802F39125A7BFD34779036038CBC6D96281BCD1C49C87C9BA16F42667FD33EB472FC17B49B2FFAB3321CCB6BAF1167DA55F9A925BC4243D90F3C9649E9664E048FB44E5771F78F21856E735F12B8B1FA6501822EC23BE959497843853ADCC91F156C7E5C8BC59BED02177A51521E68B3969B01F9591210A51E679BD2EFE044A30D3DC6C12ED8EA70CC6A284ED7798DE88C4322B0133B02BFED3D7108116C0BFE2415ACAFE1C297E7E7C123")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes( "10DB3FFFFE188B977F632BCD057892AF3000E8A59633C3FF752ED168C482B5003A12659A858CC4B73F70C1A99673B17C39CF555227A0E8BD85C86FCA2374B25D71B5022F81784273293EE9DE5435A237D3B0BF966CF19932A5281A3B0D5FF8C348645E3628B6D286FB1FAE1F194D475FB15A2D1B455CFDE874047B58FDDE412049F9E321A7CAD62B90DE396FFBDA5FFAA320AB125896A399AF66C591927077151692A7B417367CD829A9C3DDEA61E9B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385C")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes( "00DB3FFFACFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A89140BB74C913A079C3A7")); - assertArrayEquals(new byte[] { (byte) 0x90, (byte) 0x00 }, response); + assertArrayEquals(SW_NO_ERROR, response); response = simulator.transmitCommand(hexToBytes("0047810002B600")); assertArrayEquals( hexToBytes(