diff options
Diffstat (limited to 'smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java')
-rw-r--r-- | smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java | 343 |
1 files changed, 52 insertions, 291 deletions
diff --git a/smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java b/smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java index a9d147db..d032d45e 100644 --- a/smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java +++ b/smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java @@ -12,24 +12,12 @@ import iaik.asn1.ASN1Object; import iaik.asn1.CodingException; import iaik.asn1.DerCoder; import iaik.security.provider.IAIK; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.nio.charset.Charset; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; +import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.List; -import java.util.Random; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.Mac; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; @@ -132,24 +120,18 @@ public class ActivationTest { resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); -// System.out.println("SELECT EF.GDO"); -// // alternative: read with SFI=02: 00 b0 82 00 fa -// // P1=0x00 -> 6a:80 (incorrect cmd data) -// // no Le -> 67:00 (wrong length) -// cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x02, 0x00, new byte[] {(byte) 0x2f, (byte) 0x02}, 256); -// System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); -// resp = channel.transmit(cmdAPDU); -// System.out.println(" -> " + toString(resp.getBytes()) + "\n"); -// -// System.out.println("READ EF.GDO"); -// // 7.2.2 (case2), offset=0 -// cmdAPDU = new CommandAPDU(0x00, 0xb0, 0x00, 0x00, 256); -// System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); -// resp = channel.transmit(cmdAPDU); -// System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - - System.out.println("READ EF.GDO (SFI=02)"); - cmdAPDU = new CommandAPDU(0x00, 0xb0, 0x82, 0x00, 256); + System.out.println("SELECT EF.GDO"); + // alternative: read with SFI=02: 00 b0 82 00 fa + // P1=0x00 -> 6a:80 (incorrect cmd data) + // no Le -> 67:00 (wrong length) + cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x02, 0x00, new byte[] {(byte) 0x2f, (byte) 0x02}, 256); + System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); + resp = channel.transmit(cmdAPDU); + System.out.println(" -> " + toString(resp.getBytes()) + "\n"); + + System.out.println("READ EF.GDO"); + // 7.2.2 (case2), offset=0 + cmdAPDU = new CommandAPDU(0x00, 0xb0, 0x00, 0x00, 256); System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); @@ -163,7 +145,23 @@ public class ActivationTest { } } - public ASN1Object getCIO_PrK_SS() throws CardException, CodingException { + public static String toString(byte[] b) { + StringBuffer sb = new StringBuffer(); + sb.append('['); + if (b != null && b.length > 0) { + sb.append(Integer.toHexString((b[0] & 240) >> 4)); + sb.append(Integer.toHexString(b[0] & 15)); + for (int i = 1; i < b.length; i++) { + sb.append((i % 32 == 0) ? '\n' : ':'); + sb.append(Integer.toHexString((b[i] & 240) >> 4)); + sb.append(Integer.toHexString(b[i] & 15)); + } + } + sb.append(']'); + return sb.toString(); + } + + public void getPuK_GewSig() throws CardException, SignatureCardException, CodingException { CommandAPDU cmdAPDU; ResponseAPDU resp; @@ -175,14 +173,14 @@ public class ActivationTest { System.out.println("SELECT DF.QualifizierteSignatur"); // P1=0x00 -> 67:00 (wrong length) - cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x00, new byte[]{(byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}, 256); + cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, new byte[] {(byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}); System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); System.out.println("SELECT EF.PrKD"); // P1=0x00 -> 67:00 (wrong length) - cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x02, 0x04, new byte[]{(byte) 0x50, (byte) 0x35}, 256); + cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x02, 0x04, new byte[] {(byte) 0x50, (byte) 0x35}, 256); System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); @@ -205,56 +203,8 @@ public class ActivationTest { BigInteger keyRef = (BigInteger) efPrK_QS.getComponentAt(1).getComponentAt(4).getValue(); System.out.println("PrK_QS keyRef: 0x" + Integer.toHexString(keyRef.intValue()) + "\n"); - return efPrK_QS; - } - - public void getPuK_SicSig(byte[] cin) throws CardException, SignatureCardException, CodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { - CommandAPDU cmdAPDU; - ResponseAPDU resp; - - System.out.println("SELECT MF"); - cmdAPDU = new CommandAPDU(0x00, 0xA4, 0x00, 0x0c, new byte[]{(byte) 0x3f, (byte) 0x00}); - System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); - resp = channel.transmit(cmdAPDU); - System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - - System.out.println("SELECT DF.QualifizierteSignatur"); - // P1=0x00 -> 67:00 (wrong length) - cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x00, new byte[]{(byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}, 256); - System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); - resp = channel.transmit(cmdAPDU); - System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - - byte[] keyNumVer = null; - - if (resp.getSW() == 0x9000) { - byte[] fciBytes = new TLVSequence(resp.getData()).getValue(ISO7816Utils.TAG_FCI); - - TLVSequence fci = new TLVSequence(fciBytes); - System.out.println("FCI DF.QualifizierteSignatur"); - System.out.println(fci); - - TLVSequence proprietary = new TLVSequence(fci.getValue(0xa5)); - System.out.println("proprietary information"); - System.out.println(proprietary); - - keyNumVer = proprietary.getValue(0x54); - if (keyNumVer == null || keyNumVer.length != 2) { - throw new SignatureCardException("invalid key number/version: " + toString(keyNumVer)); - } - - System.out.println("key number: 0x" + Byte.toString(keyNumVer[0])); - System.out.println("key version: 0x" + Byte.toString(keyNumVer[1])); - } else { - throw new SignatureCardException("Failed to read DF.QualifizierteSignatur: 0x" + Integer.toHexString(resp.getSW())); - } - - SecretKeySpec kp_mk_ss = getKP_MK_SS(); - - SecretKeySpec kp_ss = deriveApplicationKey(kp_mk_ss, cin, keyNumVer); - int dfSpecificKeyRef = 1; - byte[] crt_at = new byte[]{ + byte[] crt_at = new byte[] { (byte) 0x83, (byte) 0x01, (byte) (0x80 | (0x7f & dfSpecificKeyRef)), // algorithm id 0x54??? (byte) 0x80, (byte) 0x01, (byte) 0x54 @@ -267,233 +217,44 @@ public class ActivationTest { System.out.println(" -> " + toString(resp.getBytes()) + "\n"); System.out.println("GET CHALLENGE"); + // eg. RNDICC = [ed:9b:a3:78:83:2f:d3:6c:90:00] cmdAPDU = new CommandAPDU(0x00, 0x84, 0x00, 0x00, 0x08); System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - byte[] rnd_icc = resp.getData(); - - SecretKeySpec k_enc = deriveKey(kp_ss, "3DES/CBC/NoPadding", iv, K_ENC); - SecretKeySpec k_mac = deriveKey(kp_ss, "3DES/CBC/NoPadding", iv, K_MAC); - - mutualAuth(cin, rnd_icc, k_enc, k_mac); - - } - - private SecretKeySpec getKP_MK_SS() { - byte[] kp_mk_ss_Bytes = new byte[]{(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09, (byte) 0x0A, (byte) 0x0B, (byte) 0x0C, (byte) 0x0D, (byte) 0x0E, (byte) 0x0F, (byte) 0x10, (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18}; - SecretKeySpec kp_mk_ss = new SecretKeySpec(kp_mk_ss_Bytes, "3DES"); - return kp_mk_ss; - } - - protected SecretKeySpec deriveApplicationKey(SecretKeySpec keySpec, byte[] cin, byte[] keyNumVer) throws NoSuchProviderException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { - - MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); - - sha256.update(cin); - sha256.update(keyNumVer); - byte[] derivationParam = sha256.digest(); - System.out.println("derivationParam = SHA-256(CIN|kNum|kVer) (" + derivationParam.length * 8 + "bit) = " + toString(derivationParam)); - derivationParam = Arrays.copyOf(derivationParam, 24); - System.out.println("derivationParam (" + derivationParam.length * 8 + "bit) = " + toString(derivationParam)); - - // DESedeKeySpec kp_mk_ssSpec = new DESedeKeySpec(kp_mk_ss); - System.out.println("Application Master Key KP_MK_SS (DES-EDE): " + toString(keySpec.getEncoded())); - System.out.println("Derive application key KP_SS"); - Cipher tripleDES = Cipher.getInstance("3DES/CBC/NoPadding", "IAIK"); - tripleDES.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); - System.out.println("derivationParam (" + derivationParam.length * 8 + "bit) = " + toString(derivationParam)); - byte[] x = tripleDES.doFinal(derivationParam); - System.out.println("kp_ss (" + x.length * 8 + "bit): " + toString(x)); - for (int key_i = 0; key_i < x.length; key_i += 8) { - for (int i = 0; i < 8; i++) { - int ones = 0; - for (int j = 1; j < BIT_MASK.length; j++) { - if ((x[i + key_i] & BIT_MASK[j]) == BIT_MASK[j]) { - ones++; - } - } - if ((ones & 0x1) > 0) { - x[i + key_i] &= (byte) 0xfe; // odd - } else { - x[i + key_i] |= 0x1; // even - } - } - } - System.out.println("kp_ss (parity adjusted): " + toString(x)); - SecretKeySpec kp_ss = new SecretKeySpec(x, "3DES"); - return kp_ss; - } - - private void mutualAuth(byte[] cin, byte[] rnd_icc, SecretKeySpec kenc, SecretKeySpec kmac) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, CardException { - if (rnd_icc.length != 8) { - throw new RuntimeException("invalid RND.ICC: " + toString(rnd_icc)); - } - - if (cin.length != 10) { - throw new RuntimeException("invalid CIN: " + toString(cin)); - } - - Random rand = new Random(System.currentTimeMillis()); - byte[] rnd_ifd = new byte[8]; - rand.nextBytes(rnd_ifd); - byte[] icc_id = Arrays.copyOfRange(cin, cin.length - 8, cin.length); - byte[] ifd_id = new byte[8]; - rand.nextBytes(ifd_id); - byte[] kd_ifd = new byte[64]; - rand.nextBytes(kd_ifd); - Cipher tDES = Cipher.getInstance("3DES/CBC/NoPadding"); - tDES.init(Cipher.ENCRYPT_MODE, kenc, new IvParameterSpec(iv)); - - byte[] sendData = new byte[4*8+64]; - System.arraycopy(rnd_ifd, 0, sendData, 0, 8); - System.arraycopy(ifd_id, 0, sendData, 8, 8); - System.arraycopy(rnd_icc, 0, sendData, 16, 8); - System.arraycopy(icc_id, 0, sendData, 24, 8); - System.arraycopy(kd_ifd, 0, sendData, 32, 64); - - System.out.println("cryptogram input (" + sendData.length + "byte): " - + toString(sendData)); + // ICCSN + RNDICC => Kryptogramm_CRS (STARCOS31, p357 authentication according to e-SignK) + // MUTUALAUTH -> Kryptogramm_Karte -> prüfung -> session key + System.out.println("MUTUAL AUTHENTICATE TODO..."); -// tDES.update(rnd_ifd); // 8 byte -// tDES.update(ifd_id); // 8 byte -// tDES.update(rnd_icc); // 8 byte -// tDES.update(icc_id); // 8 byte -// tDES.update(kd_ifd); // 64 byte - - byte[] cryptogram = tDES.doFinal(sendData); - System.out.println("cryptogram (" + cryptogram.length + "byte): " - + toString(cryptogram)); - - Mac retailMac = Mac.getInstance("CMacDESede"); - retailMac.init(kmac); - byte[] mac = retailMac.doFinal(cryptogram); - System.out.println("MAC: " + toString(mac)); - - byte[] c = new byte[cryptogram.length + mac.length]; - System.arraycopy(cryptogram, 0, c, 0, cryptogram.length); - System.arraycopy(mac, 0, c, cryptogram.length, mac.length); - System.out.println(c.length + "bytes :" + toString(c)); - CommandAPDU cmdAPDU = new CommandAPDU(0x00, 0x82, 0x00, 0x81, c, 256); // 81->00 + + System.out.println("SELECT EF.PuK_QS"); + // P1=0x00 -> 67:00 (wrong length) + cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x02, 0x04, new byte[] {(byte) 0x0e, (byte) 0x01}, 256); System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); - ResponseAPDU resp = channel.transmit(cmdAPDU); + resp = channel.transmit(cmdAPDU); System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - } - - private SecretKeySpec deriveKey(SecretKeySpec masterkey, String cipherAlias, byte[] iv, byte[] derivationParam) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { - - if (derivationParam.length != 24) { - throw new RuntimeException("invalid 3TDES derivation parameter: " + toString(derivationParam)); - } - - //3DES/CBC/NoPadding - Cipher cipher = Cipher.getInstance(cipherAlias); - cipher.init(Cipher.ENCRYPT_MODE, masterkey, new IvParameterSpec(iv)); - - System.out.println("derivation parameter (" - + derivationParam.length * 8 + "bit): " - + toString(derivationParam)); - System.out.println("derivation key (" - + masterkey.getAlgorithm() + ") :" - + toString(masterkey.getEncoded())); - - byte[] x = cipher.doFinal(derivationParam); - - System.out.println("x (" + x.length * 8 + "bit): " + toString(x)); - - if (x.length != 24) { - throw new RuntimeException("invalid derived key: " + toString(x)); - } - - for (int offset = 0; offset < x.length; offset += 8) { - adjustParityBit(x, offset); - } - - SecretKeySpec derivedKey = new SecretKeySpec(x, masterkey.getAlgorithm()); + System.out.println("READ EF.PuK_QS"); + // 7.2.2 (case2), offset=0 + cmdAPDU = new CommandAPDU(0x00, 0xb0, 0x00, 0x00, 256); + System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes())); + resp = channel.transmit(cmdAPDU); + System.out.println(" -> " + toString(resp.getBytes()) + "\n"); - System.out.println("derived key (" - + derivedKey.getAlgorithm() + ") :" - + toString(derivedKey.getEncoded())); - - return derivedKey; - } + System.out.println("PuK_QS:\n" + toString(resp.getData())); - private final static byte[] K_ENC; - private final static byte[] K_MAC; - static { - byte[] encBytes; - byte[] macBytes; - try { - MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); - encBytes = sha256.digest("K_ENC".getBytes("ASCII")); - macBytes = sha256.digest("K_MAC".getBytes("ASCII")); - } catch (NoSuchAlgorithmException ex) { - encBytes = new byte[] {(byte)0xe0}; - macBytes = new byte[] {(byte)0xe0}; - } catch (UnsupportedEncodingException ex) { - encBytes = new byte[] {(byte)0xe1}; - macBytes = new byte[] {(byte)0xe1}; - } - K_ENC = Arrays.copyOf(encBytes, 24); - K_MAC = Arrays.copyOf(macBytes, 24); } - private final static byte[] iv = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - /** Bit mask for counting the ones. */ - private final static byte[] BIT_MASK = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, (byte) 0x80 - }; - - private void adjustParityBit(byte[] x, int offset) { - - for (int i = 0; i < 8; i++) { - int ones = 0; - for (int j = 1; j < BIT_MASK.length; j++) { - if ((x[i + offset] & BIT_MASK[j]) == BIT_MASK[j]) { - ones++; - } - } - if ((ones & 0x1) > 0) { - x[i + offset] &= (byte) 0xfe; // odd - } else { - x[i + offset] |= 0x1; // even - } - } - } - - public static String toString(byte[] b) { - StringBuilder sb = new StringBuilder(); - sb.append('['); - if (b != null && b.length > 0) { - sb.append(Integer.toHexString((b[0] & 240) >> 4)); - sb.append(Integer.toHexString(b[0] & 15)); - for (int i = 1; i < b.length; i++) { - sb.append((i % 32 == 0) ? '\n' : ':'); - sb.append(Integer.toHexString((b[i] & 240) >> 4)); - sb.append(Integer.toHexString(b[i] & 15)); - } - } - sb.append(']'); - return sb.toString(); - } - - public static void main(String[] args) throws NoSuchAlgorithmException, CardException, SignatureCardException, CodingException, InvalidKeyException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { + public static void main(String[] args) throws NoSuchAlgorithmException, CardException, SignatureCardException, CodingException { ActivationTest test = new ActivationTest(); test.setUp(); - byte[] cin = test.getCIN(); - - test.getCIO_PrK_SS(); - +// test.getCIN(); // test.getSVNr(); - test.getPuK_SicSig(cin); + test.getPuK_GewSig(); } } |