From 7c4d1a5aff3a5ab82464affec8e0e7dcfbd2bfb3 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 21 Jan 2011 16:38:26 +0000 Subject: git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@894 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/activation/SecureChannel.java | 137 ++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) (limited to 'smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java') diff --git a/smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java b/smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java index 303b1b68..9bbd39fb 100644 --- a/smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java +++ b/smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java @@ -6,6 +6,13 @@ package at.gv.egiz.smcc.activation; import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.crypto.spec.SecretKeySpec; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -49,7 +56,17 @@ public class SecureChannel extends CardChannel { @Override public ResponseAPDU transmit(CommandAPDU capdu) throws CardException { - return basicChannel.transmit(capdu); + try { + kmacssc[7] += 1; + System.out.println("incrementing kmac_ssc: " + toString(kmacssc)); + System.out.println("kmac: " + toString(kmac.getEncoded())); + CommandAPDU capdu_ = new CommandAPDU(protectAPDU(capdu.getBytes())); + System.out.println(" cmd apdu* " + toString(capdu_.getBytes())); + return basicChannel.transmit(capdu_); + } catch (Exception ex) { + System.out.println("failed to transmit protected APDU: " + ex.getMessage()); + throw new CardException(ex); + } } @Override @@ -62,4 +79,122 @@ public class SecureChannel extends CardChannel { throw new UnsupportedOperationException("Not supported yet."); } + /** + * + * @param apdu + * @return + * @throws IllegalArgumentException + */ + protected byte[] protectAPDU(byte[] apdu) throws IllegalArgumentException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, GeneralSecurityException { + + byte[] apdu_ = null; + byte[] mac_in = null; + int i_mac = 0; + + if (apdu.length < 4) { + throw new IllegalArgumentException("invalid Command APDU " + toString(apdu)); + } else if (apdu.length == 4) { + // no command data, no response data, status not protected + // CLA|INS|P1|P2 -> CLA'|INS|P1|P2|Lc'|TLmac + apdu_ = new byte[15]; + + // authenticate header: CLA* b3=1 + apdu_[0] = (byte) (apdu[0] | (byte) 0x0c); // CLA*: b8-6=000 b4-3=11 + apdu_[1] = apdu[1]; + apdu_[2] = apdu[2]; + apdu_[3] = apdu[3]; + + // Lc': TLmac (blocksize=8) + apdu_[4] = (byte) 0x0a; + // cryptographic checksum + apdu_[5] = (byte) 0x8e; + apdu_[6] = (byte) 0x08; + i_mac = 7; + + // 2 data objects: SSC, header + mac_in = new byte[2*8]; + + //TODO increment SSC + System.arraycopy(kmacssc, 0, mac_in, 0, 8); + + // CLA** INS P1 P2 padding + byte[] header_ = RetailCBCMac.pad(Arrays.copyOf(apdu_, 4), 8); + System.arraycopy(header_, 0, mac_in, 8, 8); + + System.out.println("data covered by cryptographic checksum: " + toString(mac_in)); + + } else if (apdu.length == 5) { + // CLA|INS|P1|P2|Le -> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00 + // no command data, response data + apdu_ = new byte[19]; + + // authenticate header: CLA* b3=1 + apdu_[0] = (byte) (apdu[0] | (byte) 0x0c); // CLA*: b8-6=000 b4-3=11 + apdu_[1] = apdu[1]; + apdu_[2] = apdu[2]; + apdu_[3] = apdu[3]; + + // Lc': TLle TLmac + apdu_[4] = (byte) 0x0d; + + // Ne + apdu_[5] = (byte) 0x97; + apdu_[6] = (byte) 0x01; + apdu_[7] = apdu[4]; + + // cryptographic checksum + apdu_[8] = (byte) 0x8e; + apdu_[9] = (byte) 0x08; + i_mac = 10; + apdu_[18] = 0x00; + + // 3 data objects: SSC, header, Le + mac_in = new byte[3*8]; + + //TODO increment SSC + System.arraycopy(kmacssc, 0, mac_in, 0, 8); + + // CLA** INS P1 P2 padding + byte[] header_ = RetailCBCMac.pad(Arrays.copyOf(apdu_, 4), 8); + System.arraycopy(header_, 0, mac_in, 8, 8); + + System.arraycopy(RetailCBCMac.pad(Arrays.copyOfRange(apdu_, 5, 8), 8), 0, mac_in, 16, 8); + System.out.println("data covered by cryptographic checksum: " + toString(mac_in)); + + + } else if (apdu.length == 5 + apdu[4]){ + // CLA|INS|P1|P2|Lc|Data -> CLA'|INS|P1|P2|Lc'|TLplain|TLmac + // 81 (plain value) 8e (cryptographic checksum) + + } else { + // CLA|INS|P1|P2|Lc|Data|Le -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00 + // 81 (plain value) 97 (Ne) 8e (cryptographic checksum) + + // TODO extended APDUs + + } + + + byte[] mac = RetailCBCMac.retailMac(mac_in, "DES", "DESede", kmac, 8, 8); + System.out.println("mac: " + toString(mac)); + System.arraycopy(mac, 0, apdu_, i_mac, 8); + return apdu_; + + } + + 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(); + } } -- cgit v1.2.3