Reorganised and cleaned up testing a bit

This commit is contained in:
Joeri 2017-12-06 13:32:27 +01:00
parent 01a83bbed9
commit 04e5a42649
1 changed files with 261 additions and 156 deletions

View File

@ -1,42 +1,89 @@
package openpgpcard;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.licel.jcardsim.base.Simulator;
import com.licel.jcardsim.smartcardio.CardSimulator;
import javax.smartcardio.*;
import javacard.framework.AID;
import openpgpcard.OpenPGPApplet;
public class OpenPGPAppletTest {
static byte[] SW_NO_ERROR = new byte[] {(byte)0x90, 0x00};
static int CLA_DEFAULT = 0x00;
static int CLA_CHAINING = 0x10;
static int CLA_SM = 0x0C;
static int CLA_SM_CHAINING = 0x1C;
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 int INS_SELECT = 0xA4;
static int INS_SELECT_DATA = 0xA5;
static int INS_GET_DATA = 0xCA;
static int INS_GET_NEXT_DATA = 0xCC;
static int INS_VERIFY = 0x20;
static int INS_CHANGE_REFERENCE_DATA = 0x24;
static int INS_RESET_RETRY_COUNTER = 0x2C;
static int INS_PUT_DATA_DA = 0xDA;
static int INS_PUT_DATA_DB = 0xDB;
static int INS_GENERATE_ASYMMETYRIC_KEY_PAIR = 0x47;
static int INS_PERFORM_SECURITY_OPERATION = 0x2A;
static int INS_INTERNAL_AUTHENTICATE = 0x88;
static int INS_GET_RESPONSE = 0xC0;
static int INS_GET_CHALLENGE = 0x84;
static int INS_TERMINATE_DF = 0xE6;
static int INS_ACTIVATE_FILE = 0x44;
static int INS_MANAGE_SECURITY_ENVIRONMENT = 0x22;
static int SW_NO_ERROR = 0x9000;
static int SW_WARNING_STATE_UNCHANGED = 0x6200;
static int SW_TRIES_REMAINING_0 = 0x63c0;
static int SW_TRIES_REMAINING_1 = 0x63c1;
static int SW_TRIES_REMAINING_2 = 0x63c2;
static int SW_TRIES_REMAINING_3 = 0x63c3;
static int SW_WRONG_LENGTH = 0x6700;
static int SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982;
static int SW_DATA_INVALID = 0x6984;
static int SW_CONDITIONS_NOT_SATISFIED = 0x6985;
static int SW_RECORD_NOT_FOUND = 0x6a83;
static int SW_INCORRECT_P1P2 = 0x6a86;
static int SW_INS_NOT_SUPPORTED = 0x6d00;
static int SW_UNKNOWN = 0x6f00;
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);
static private byte[] bArray = new byte[appletAID.length + 1];
Simulator simulator;
CardSimulator simulator;
CommandAPDU command;
// Test data
static byte[] USER_PIN_DEFAULT = new byte[] { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
static byte[] USER_PIN_INVALID = new byte[] { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 };
static byte[] USER_PIN_NEW = new byte[] { 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 };
static byte[] ADMIN_PIN_DEFAULT = new byte[] { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
static byte[] ADMIN_PIN_INVALID = new byte[] { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 };
static byte[] ADMIN_PIN_NEW = new byte[] { 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 };
RSAPublicKey publicKey;
private static String CHARS = "0123456789ABCDEF";
public static String bytesToHex(byte[] bytes) {
@ -64,6 +111,21 @@ public class OpenPGPAppletTest {
return bytes;
}
public ResponseAPDU test(CommandAPDU command, int expectedSW, byte[] expectedData) {
ResponseAPDU response = simulator.transmitCommand(command);
assertEquals(expectedSW, response.getSW());
if(expectedData != null) {
assertArrayEquals(expectedData, response.getData());
}
return response;
}
public ResponseAPDU test(CommandAPDU command, int expectedSW) {
return test(command, expectedSW, new byte[] {});
}
@BeforeClass
public static void setUpClass() {
@ -72,158 +134,115 @@ public class OpenPGPAppletTest {
}
@Before
public void setUp() {
public void setUp() throws NoSuchAlgorithmException, InvalidKeySpecException {
// Set up the Java Card simulator and install the applet
simulator = new Simulator();
simulator = new CardSimulator();
simulator.resetRuntime();
simulator.installApplet(aid, OpenPGPApplet.class, bArray, (short) 0, (byte) bArray.length);
simulator.selectApplet(aid);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger("B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385CFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A89140BB74C913A079C3A7", 16), new BigInteger("010001", 16));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
}
@Test
public void test_userPINValid() {
byte[] response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(SW_NO_ERROR, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_DEFAULT);
test(command, SW_NO_ERROR);
}
@Test
public void test_userPINInvalid() {
byte[] 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);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(SW_TRIES_REMAINING_0, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_2);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_1);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_0);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_0);
}
@Test
public void test_userPINStatus() {
byte[] 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, 0x00 });
assertArrayEquals(SW_TRIES_REMAINING_2, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_2);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81);
test(command, SW_TRIES_REMAINING_2);
// Verify correct PIN
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(SW_NO_ERROR, response);
test_userPINValid();
// Invalidate correctly verified PIN
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, (byte)0xFF, (byte) 0x81, 0x00 });
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(SW_TRIES_REMAINING_3, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0xFF, 0x81);
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81);
test(command, SW_TRIES_REMAINING_3);
}
@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);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x83, ADMIN_PIN_DEFAULT);
test(command, SW_NO_ERROR);
}
@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);
command = new CommandAPDU(CLA_DEFAULT, INS_PUT_DATA_DA, 0x00, 0xD3, new byte[] { 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 });
test(command, SW_NO_ERROR);
// Invalidate correctly verified admin PIN
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0xFF, 0x83);
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x83);
test(command, SW_TRIES_REMAINING_3);
// 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);
test_userPINInvalid();
// 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);
command = new CommandAPDU(CLA_DEFAULT, INS_RESET_RETRY_COUNTER, 0x00, 0x81, new byte[] { 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 });
test(command, SW_NO_ERROR);
// Check the counter is reset
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(SW_TRIES_REMAINING_3, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81);
test(command, SW_TRIES_REMAINING_3);
// 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);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, new byte[] { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 });
test(command, SW_NO_ERROR);
}
@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);
test_userPINInvalid();
// 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);
command = new CommandAPDU(CLA_DEFAULT, INS_RESET_RETRY_COUNTER, 0x02, 0x81, USER_PIN_NEW);
test(command, SW_CONDITIONS_NOT_SATISFIED);
// 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);
command = new CommandAPDU(CLA_DEFAULT, INS_RESET_RETRY_COUNTER, 0x02, 0x81, USER_PIN_NEW);
test(command, SW_NO_ERROR);
// Check the counter is reset
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x00 });
assertArrayEquals(SW_TRIES_REMAINING_3, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81);
test(command, SW_TRIES_REMAINING_3);
// 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);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_NEW);
test(command, SW_NO_ERROR);
}
/**
@ -233,48 +252,134 @@ public class OpenPGPAppletTest {
*/
@Test
public void test_userPINReset() {
byte[] 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, 0x32, 0x33, 0x34, 0x35, 0x36 });
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(
new byte[] { 0x00, 0x20, 0x00, (byte) 0x81, 0x06, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 });
assertArrayEquals(SW_TRIES_REMAINING_2, response);
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_2);
test_userPINValid();
command = new CommandAPDU(CLA_DEFAULT, INS_VERIFY, 0x00, 0x81, USER_PIN_INVALID);
test(command, SW_TRIES_REMAINING_2);
}
@Test
public void test_generateKey() {
byte[] response = simulator.transmitCommand(hexToBytes("00200083083132333435363738"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes("0047800002B600"));
byte[] response2 = simulator.transmitCommand(hexToBytes("0047810002B600"));
assertArrayEquals(response, response2);
test_adminPINValid();
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x80, 0x00, new byte[] {(byte)0xB6, 0x00});
ResponseAPDU response1 = test(command, 0x610f, null);
command = new CommandAPDU(CLA_DEFAULT, INS_GET_RESPONSE, 0x00, 0x00, 0x0f);
ResponseAPDU response2 = test(command, SW_NO_ERROR, null);
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x81, 0x00, new byte[] {(byte)0xB6, 0x00});
test(command, 0x610f, response1.getData());
command = new CommandAPDU(CLA_DEFAULT, INS_GET_RESPONSE, 0x00, 0x00, 0x0f);
test(command, SW_NO_ERROR, response2.getData());
}
@Test
public void test_importKey() {
byte[] response = simulator.transmitCommand(hexToBytes("0047810002B600"));
assertArrayEquals(new byte[] { (byte) 0x69, (byte) 0x85 }, response);
response = simulator.transmitCommand(hexToBytes("00200083083132333435363738"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes(
"10DB3FFFFE4D8203A2B6007F48159103928180938180948180958180968180978201005F48820383010001C024584779F7C68DB6299D63E06D8DC029631CED208A03634D648EF4984AB7F79FCF620A81D690D6E98B690AB2444311406B8EC97460931EDC39E74C4047325271D993C97F5216345768E53460121BF78FF984595C00123940575342A2E619BBC5A7C8492453F38CD655F13995770477595279FD2E27409B97928F40E8D01F91EB61C12B9EC0A31213D32975A46C95BAADEF06468DD68CE4858C7E7F94754486825E2673CFA86D3B2764973899882DC1ACB2C19C4E90BFCF319272FF5E86CC1B36FBA96BF3F06DEB9CC6B0BDB1BB4F300A07985BDCE8CAF6"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes(
"10DB3FFFFE11FE3CA640852F0334745FE8B16C9239427CA4A4E7EE406EE2773FE7E447F5F6CFF061EACCCC83B7B2201715989214937C59472FA1BD027FCF3F7727CB14F81C7845988A983452E9B7CA04805126F3C19A1E8E802F39125A7BFD34779036038CBC6D96281BCD1C49C87C9BA16F42667FD33EB472FC17B49B2FFAB3321CCB6BAF1167DA55F9A925BC4243D90F3C9649E9664E048FB44E5771F78F21856E735F12B8B1FA6501822EC23BE959497843853ADCC91F156C7E5C8BC59BED02177A51521E68B3969B01F9591210A51E679BD2EFE044A30D3DC6C12ED8EA70CC6A284ED7798DE88C4322B0133B02BFED3D7108116C0BFE2415ACAFE1C297E7E7C123"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes(
"10DB3FFFFE188B977F632BCD057892AF3000E8A59633C3FF752ED168C482B5003A12659A858CC4B73F70C1A99673B17C39CF555227A0E8BD85C86FCA2374B25D71B5022F81784273293EE9DE5435A237D3B0BF966CF19932A5281A3B0D5FF8C348645E3628B6D286FB1FAE1F194D475FB15A2D1B455CFDE874047B58FDDE412049F9E321A7CAD62B90DE396FFBDA5FFAA320AB125896A399AF66C591927077151692A7B417367CD829A9C3DDEA61E9B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385C"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes(
"00DB3FFFACFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A89140BB74C913A079C3A7"));
assertArrayEquals(SW_NO_ERROR, response);
response = simulator.transmitCommand(hexToBytes("0047810002B600"));
assertArrayEquals(
hexToBytes(
"7F4982010981820100B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385CFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A8610F"),
response);
public void test_importSignKey() {
// Test whether a key is already present
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x81, 0x00, new byte[] {(byte)0xB6, 0x00});
test(command, SW_CONDITIONS_NOT_SATISFIED);
test_adminPINValid();
// Import key
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("4D8203A2B6007F48159103928180938180948180958180968180978201005F48820383010001C024584779F7C68DB6299D63E06D8DC029631CED208A03634D648EF4984AB7F79FCF620A81D690D6E98B690AB2444311406B8EC97460931EDC39E74C4047325271D993C97F5216345768E53460121BF78FF984595C00123940575342A2E619BBC5A7C8492453F38CD655F13995770477595279FD2E27409B97928F40E8D01F91EB61C12B9EC0A31213D32975A46C95BAADEF06468DD68CE4858C7E7F94754486825E2673CFA86D3B2764973899882DC1ACB2C19C4E90BFCF319272FF5E86CC1B36FBA96BF3F06DEB9CC6B0BDB1BB4F300A07985BDCE8CAF6"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("11FE3CA640852F0334745FE8B16C9239427CA4A4E7EE406EE2773FE7E447F5F6CFF061EACCCC83B7B2201715989214937C59472FA1BD027FCF3F7727CB14F81C7845988A983452E9B7CA04805126F3C19A1E8E802F39125A7BFD34779036038CBC6D96281BCD1C49C87C9BA16F42667FD33EB472FC17B49B2FFAB3321CCB6BAF1167DA55F9A925BC4243D90F3C9649E9664E048FB44E5771F78F21856E735F12B8B1FA6501822EC23BE959497843853ADCC91F156C7E5C8BC59BED02177A51521E68B3969B01F9591210A51E679BD2EFE044A30D3DC6C12ED8EA70CC6A284ED7798DE88C4322B0133B02BFED3D7108116C0BFE2415ACAFE1C297E7E7C123"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("188B977F632BCD057892AF3000E8A59633C3FF752ED168C482B5003A12659A858CC4B73F70C1A99673B17C39CF555227A0E8BD85C86FCA2374B25D71B5022F81784273293EE9DE5435A237D3B0BF966CF19932A5281A3B0D5FF8C348645E3628B6D286FB1FAE1F194D475FB15A2D1B455CFDE874047B58FDDE412049F9E321A7CAD62B90DE396FFBDA5FFAA320AB125896A399AF66C591927077151692A7B417367CD829A9C3DDEA61E9B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385C"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_DEFAULT, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("FF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A89140BB74C913A079C3A7"));
test(command, SW_NO_ERROR);
// Verify that the key was properly imported
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x81, 0x00, new byte[] {(byte)0xB6, 0x00});
test(command, 0x610f, hexToBytes("7F4982010981820100B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385CFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A8"));
command = new CommandAPDU(CLA_DEFAULT, INS_GET_RESPONSE, 0x00, 0x00, 0x0f);
test(command, SW_NO_ERROR, hexToBytes("9140BB74C913A079C3A78203010001"));
}
@Test
public void test_importDecryptKey() {
// Test whether a key is already present
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x81, 0x00, new byte[] {(byte)0xB8, 0x00});
test(command, SW_CONDITIONS_NOT_SATISFIED);
test_adminPINValid();
// Import key
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("4D8203A2B8007F48159103928180938180948180958180968180978201005F48820383010001C024584779F7C68DB6299D63E06D8DC029631CED208A03634D648EF4984AB7F79FCF620A81D690D6E98B690AB2444311406B8EC97460931EDC39E74C4047325271D993C97F5216345768E53460121BF78FF984595C00123940575342A2E619BBC5A7C8492453F38CD655F13995770477595279FD2E27409B97928F40E8D01F91EB61C12B9EC0A31213D32975A46C95BAADEF06468DD68CE4858C7E7F94754486825E2673CFA86D3B2764973899882DC1ACB2C19C4E90BFCF319272FF5E86CC1B36FBA96BF3F06DEB9CC6B0BDB1BB4F300A07985BDCE8CAF6"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("11FE3CA640852F0334745FE8B16C9239427CA4A4E7EE406EE2773FE7E447F5F6CFF061EACCCC83B7B2201715989214937C59472FA1BD027FCF3F7727CB14F81C7845988A983452E9B7CA04805126F3C19A1E8E802F39125A7BFD34779036038CBC6D96281BCD1C49C87C9BA16F42667FD33EB472FC17B49B2FFAB3321CCB6BAF1167DA55F9A925BC4243D90F3C9649E9664E048FB44E5771F78F21856E735F12B8B1FA6501822EC23BE959497843853ADCC91F156C7E5C8BC59BED02177A51521E68B3969B01F9591210A51E679BD2EFE044A30D3DC6C12ED8EA70CC6A284ED7798DE88C4322B0133B02BFED3D7108116C0BFE2415ACAFE1C297E7E7C123"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_CHAINING, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("188B977F632BCD057892AF3000E8A59633C3FF752ED168C482B5003A12659A858CC4B73F70C1A99673B17C39CF555227A0E8BD85C86FCA2374B25D71B5022F81784273293EE9DE5435A237D3B0BF966CF19932A5281A3B0D5FF8C348645E3628B6D286FB1FAE1F194D475FB15A2D1B455CFDE874047B58FDDE412049F9E321A7CAD62B90DE396FFBDA5FFAA320AB125896A399AF66C591927077151692A7B417367CD829A9C3DDEA61E9B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385C"));
test(command, SW_NO_ERROR);
command = new CommandAPDU(CLA_DEFAULT, INS_PUT_DATA_DB, 0x3F, 0xFF, hexToBytes("FF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A89140BB74C913A079C3A7"));
test(command, SW_NO_ERROR);
// Verify that the key was properly imported
command = new CommandAPDU(CLA_DEFAULT, INS_GENERATE_ASYMMETYRIC_KEY_PAIR, 0x81, 0x00, new byte[] {(byte)0xB8, 0x00});
test(command, 0x610f, hexToBytes("7F4982010981820100B0AABBCB33DB653EA3C0B71231305455489E8107B7B0A5400951519DE51C3ACF3C69EE96BC1DFE6A59CAD1F8889433096930E077FC2AEFA0D9104B1230A4AD282BAFA0ED434BAB96D64145B7E8054B88AFF1385CFF7879152DC7AC34DD5F17826C177D9173D6094396237A7E560122DFD46F9FBCBFFD27A3E1191F08174F0980BAFDCF45613A03B198C4E6C880E96226AD9E9D3CD08BF05412E8EDD49B267702C2A4766805B38D137191AF2B52991F9ABC49E7C02FCA8C7F617C39CB968894A5A773D5B000912A683F9F760DA6D7247DC26C152CA5DA6FDDD50AD8B769EFB87ADF09B792EDB8AE8B2B3D7015C9F62D7EE3F44F1C35A8"));
command = new CommandAPDU(CLA_DEFAULT, INS_GET_RESPONSE, 0x00, 0x00, 0x0f);
test(command, SW_NO_ERROR, hexToBytes("9140BB74C913A079C3A78203010001"));
}
@Test
public void test_sign() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
byte[] testData = new byte[] { (byte)0xAB };
test_importSignKey();
test_userPINValid();
command = new CommandAPDU(CLA_DEFAULT, INS_PERFORM_SECURITY_OPERATION, 0x9E, 0x9A, testData);
ResponseAPDU response1 = test(command, 0x6101, hexToBytes("9E62CCBC302E5FF18C897FC65CA5F5044FDFA2133B53778CA10CF75F929428FADC8135958884DCD7829E32DC3D69D902364DDB37448420DDC9F5F57955CC6CCFD869A32E280482C207877B80CE953352E4B41291E624F7583BA84DC5655D5FEC06FE85304470227337C11F21B3528C0EB626ED01F7AE2DD57BA6F7D2529401EF03047394AFE00B626D65FBB57EE59273D6A37E0CA0BF9958BE75F15989CB77BFC18D445EAD7103B857B6B446B0AA35392B1E902C5B2D31E5B7F1A419016EBAFDE3DF22E42417E870907AF4FF0D376EFF188BD919476CF7F95A013D130ED096F6E5D79F8488B2114AC5D1FA989946411CD571F4DB27247477939457FEA734FF"));
command = new CommandAPDU(CLA_DEFAULT, INS_GET_RESPONSE, 0x00, 0x00, 0x01);
ResponseAPDU response2 = test(command, SW_NO_ERROR, hexToBytes("DB"));
byte[] signedData = new byte[response1.getNr() + response2.getNr()];
System.arraycopy(response1.getData(), 0, signedData, 0, response1.getNr());
System.arraycopy(response2.getData(), 0, signedData, response1.getNr(), response2.getNr());
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] plaintextData = cipher.doFinal(signedData);
assertArrayEquals(testData, plaintextData);
}
@Test
public void test_decrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
byte[] testData = new byte[] { (byte)0xAB };
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedData = cipher.doFinal(testData);
test_importDecryptKey();
test_userPINValid();
byte[] data = new byte[255];
data[0] = 0x00;
System.arraycopy(encryptedData, 0, data, 1, 254);
command = new CommandAPDU(CLA_CHAINING, INS_PERFORM_SECURITY_OPERATION, 0x80, 0x86, data);
test(command, SW_NO_ERROR);
data = new byte[encryptedData.length - 254];
System.arraycopy(encryptedData, 254, data, 0, data.length);
command = new CommandAPDU(CLA_DEFAULT, INS_PERFORM_SECURITY_OPERATION, 0x80, 0x86, data);
test(command, SW_NO_ERROR, testData);
}
}