summaryrefslogtreecommitdiff
path: root/smccTest/src
diff options
context:
space:
mode:
Diffstat (limited to 'smccTest/src')
-rw-r--r--smccTest/src/main/java/at/gv/egiz/smcc/activation/Activation.java601
-rw-r--r--smccTest/src/main/java/at/gv/egiz/smcc/activation/ActivationTest.java343
-rw-r--r--smccTest/src/main/java/at/gv/egiz/smcc/activation/RetailCBCMac.java186
-rw-r--r--smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java65
-rw-r--r--smccTest/src/test/java/at/gv/egiz/smcc/activation/TestRetailCBCMac.java358
5 files changed, 52 insertions, 1501 deletions
diff --git a/smccTest/src/main/java/at/gv/egiz/smcc/activation/Activation.java b/smccTest/src/main/java/at/gv/egiz/smcc/activation/Activation.java
deleted file mode 100644
index 8d102c80..00000000
--- a/smccTest/src/main/java/at/gv/egiz/smcc/activation/Activation.java
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package at.gv.egiz.smcc.activation;
-
-import at.gv.egiz.smcc.SignatureCardException;
-import at.gv.egiz.smcc.util.TLVSequence;
-import iaik.security.provider.IAIK;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.security.GeneralSecurityException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.SignatureException;
-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.NoSuchPaddingException;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import javax.smartcardio.Card;
-import javax.smartcardio.CardChannel;
-import javax.smartcardio.CardException;
-import javax.smartcardio.CardTerminal;
-import javax.smartcardio.CommandAPDU;
-import javax.smartcardio.ResponseAPDU;
-import javax.smartcardio.TerminalFactory;
-
-/**
- *
- * @author clemens
- */
-public class Activation {
-
- /**
- * cf. kp_mk_ss_test.xml
- */
- static SecretKeySpec MK_QSig = new SecretKeySpec(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}, "3DES");
-
- /**
- * DES_CBC[MK_Appl](SHA-256(CIN|KeyNum|KeyVer))
- *
- * @param masterKey
- * @param cin
- * @param keyNum
- * @param keyVer
- * @return
- */
- static SecretKeySpec deriveApplicationKey(SecretKeySpec masterKey, byte[] cin, byte keyNum, byte keyVer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
- System.out.println("derive application key for \n CIN "
- + toString(cin)
- + "\n key number 0x0"
- + Byte.toString(keyNum)
- + "\n key version 0x0"
- + Byte.toString(keyVer));
-
- MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
-
- sha256.update(cin);
- sha256.update(keyNum);
- sha256.update(keyVer);
- byte[] derivationParam = sha256.digest();
-
- return deriveKey(masterKey, Arrays.copyOf(derivationParam, 24));
- }
-
- static SecretKeySpec deriveKENC(SecretKeySpec k_appl) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
- System.out.println("derive k_enc");
-
- MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
- byte[] derivationParam = sha256.digest("K_ENC".getBytes("ASCII"));
-
- return deriveKey(k_appl, Arrays.copyOf(derivationParam, 24));
- }
-
- static SecretKeySpec deriveKMAC(SecretKeySpec k_appl) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
- System.out.println("derive k_mac");
-
- MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
- byte[] derivationParam = sha256.digest("K_MAC".getBytes("ASCII"));
-
- return deriveKey(k_appl, Arrays.copyOf(derivationParam, 24));
- }
-
- /**
- * DES_CBC[MK](derivationParam)
- * 3DES/CBC/NoPadding
- *
- * @param masterKey
- * @param derivationParam
- * @return
- */
- static SecretKeySpec deriveKey(SecretKeySpec masterKey, byte[] derivationParam) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
- if (derivationParam.length != 24) {
- throw new RuntimeException("invalid 3TDES derivation parameter: " + toString(derivationParam));
- }
-
- Cipher tdes = Cipher.getInstance("3DES/CBC/NoPadding");
- tdes.init(Cipher.ENCRYPT_MODE, masterKey, new IvParameterSpec(ZEROS));
-
- System.out.println(tdes.getAlgorithm());
- System.out.println("master key : " + toString(masterKey.getEncoded()));
-
- System.out.println("derivation parameter ("
- + derivationParam.length * 8 + "bit): "
- + toString(derivationParam));
- System.out.println("derivation key ("
- + masterKey.getAlgorithm() + ") :"
- + toString(masterKey.getEncoded()));
-
- byte[] x = tdes.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("derived key ("
- + derivedKey.getAlgorithm() + ") :"
- + toString(derivedKey.getEncoded()));
-
- return derivedKey;
-
- }
-
- public final static byte[] AID_QSig = new byte[] {
- (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17,
- (byte) 0x00, (byte) 0x12, (byte) 0x01};
-
- private final static byte[] ZEROS = {
- 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 static 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();
- }
-
-
- CardTerminal ct;
- Card icc;
- CardChannel channel;
-
- public void setUp() throws NoSuchAlgorithmException, CardException {
-
- IAIK.addAsJDK14Provider();
-
- System.out.println("create terminalFactory...\n");
- TerminalFactory terminalFactory = TerminalFactory.getInstance("PC/SC", null);
-
- System.out.println("get supported terminals...\n");
- List<CardTerminal> terminals = terminalFactory.terminals().list();
-
- if (terminals.size() < 1) {
- throw new CardException("no terminals");
- }
-
- ct = terminals.get(0);
- System.out.println("found " + terminals.size() + " terminals, using " + ct.getName() + "\n");
-
- System.out.println("connecting " + ct.getName() + "\n");
- icc = ct.connect("*");
- byte[] atr = icc.getATR().getBytes();
- byte[] historicalBytes = icc.getATR().getHistoricalBytes();
- System.out.println("found card " + toString(atr) + " " + new String(historicalBytes, Charset.forName("ASCII")) + "\n\n");
-
- channel = icc.getBasicChannel();
- }
-
- public void activate() throws CardException, SignatureCardException, Exception {
-
- System.out.println("SELECT MF");
- CommandAPDU cmdAPDU = new CommandAPDU(0x00, 0xA4, 0x00, 0x0c, new byte[]{(byte) 0x3F, (byte) 0x00});
- System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes()));
- ResponseAPDU resp = channel.transmit(cmdAPDU);
- System.out.println(" -> " + toString(resp.getBytes()) + "\n");
-
- byte[] cin = getCIN();
-
- byte[] k_qsigNumVer = getKApplNumberVersion(AID_QSig);
-
- SecretKeySpec k_qsig;
- try {
- k_qsig = deriveApplicationKey(MK_QSig, cin, k_qsigNumVer[0], k_qsigNumVer[1]);
- System.out.println("K_QS (" + k_qsig.getAlgorithm() + ")"
- + toString(k_qsig.getEncoded()));
- } catch (Exception ex) {
- throw new SignatureCardException("failed to derive k_qs", ex);
- }
-
- 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()));
- resp = channel.transmit(cmdAPDU);
- System.out.println(" -> " + toString(resp.getBytes()) + "\n");
-
- openSecureChannel(k_qsig, cin);
- }
-
-
- /**
- * @precondition MF
- *
- * @return
- * @throws CardException
- * @throws SignatureCardException
- */
- byte[] getCIN() throws CardException, SignatureCardException {
- CommandAPDU cmdAPDU;
- ResponseAPDU resp;
-
- System.out.println("READ EF.GDO (SFI=02)");
- cmdAPDU = new CommandAPDU(0x00, 0xb0, 0x82, 0x00, 256);
- System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes()));
- resp = channel.transmit(cmdAPDU);
- System.out.println(" -> " + toString(resp.getBytes()) + "\n");
-
- if (resp.getSW() == 0x9000) {
- byte[] cin = new TLVSequence(resp.getData()).getValue(0x5a);
- System.out.println("CIN: " + toString(cin));
- return cin;
- } else {
- throw new SignatureCardException("Failed to read EF.GDO: 0x" + Integer.toHexString(resp.getSW()));
- }
- }
-
- /**
- * @precondition MF
- * @postcondition AID
- *
- * @param aid
- * @return
- * @throws CardException
- * @throws SignatureCardException
- */
- byte[] getKApplNumberVersion(byte[] aid) throws CardException, SignatureCardException {
-
- System.out.println("SELECT AID " + toString(aid));
- // P1=0x00 -> 67:00 (wrong length)
- CommandAPDU cmdAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x00, aid, 256);
- System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes()));
- ResponseAPDU 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(0x6f);
-
- TLVSequence fci = new TLVSequence(fciBytes);
- System.out.println("FCI AID " + toString(aid));
- 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));
- }
- return keyNumVer;
-
- } else {
- throw new SignatureCardException("Failed to read AID: 0x"
- + Integer.toHexString(resp.getSW()));
- }
- }
-
- void openSecureChannel(SecretKeySpec k_appl, byte[] cin) throws SignatureCardException, NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, CardException, NoSuchProviderException, GeneralSecurityException {
-// function openSecureChannelG3(card, crypto, iccsn, kappl, kid, algo) {
-
-// if (typeof(kid) == "undefined")
-// kid = 0x81;
-//
-// if (typeof(algo) == "undefined")
-// algo = 0x54;
-//
-// // Perform mutual authentication procedure
-// GPSystem.trace("Performing mutual authentication");
-//
-// var kenc = deriveKENC(crypto, kappl);
-// var kmac = deriveKMAC(crypto, kappl);
-
- SecretKeySpec k_enc = deriveKENC(k_appl);
- SecretKeySpec k_mac = deriveKMAC(k_appl);
-
-//
-// // Manage SE: Set K_Appl for Mutual Authentication with Session Key establishment
-// var bb = new ByteBuffer("8301", HEX);
-// bb.append(kid);
-// bb.append(0x80);
-// bb.append(0x01);
-// bb.append(algo);
-//
-// card.sendApdu(0x00, 0x22, 0x81, 0xA4, bb.toByteString(), [0x9000])
-//
-// var rndicc = card.sendApdu(0x00, 0x84, 0x00, 0x00, 0x08, [0x9000]);
-
- int dfSpecificKeyRef = 1;
- byte[] crt_at = new byte[]{
- (byte) 0x83, (byte) 0x01, (byte) (0x80 | (0x7f & dfSpecificKeyRef)),
- // algorithm id 0x54???
- (byte) 0x80, (byte) 0x01, (byte) 0x54
- };
-
- System.out.println("MSE SET AT for key agreement");
- CommandAPDU cmdAPDU = new CommandAPDU(0x00, 0x22, 0x81, 0xa4, crt_at);
- System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes()));
- ResponseAPDU resp = channel.transmit(cmdAPDU);
- System.out.println(" -> " + toString(resp.getBytes()) + "\n");
-
- System.out.println("GET CHALLENGE");
- 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();
-
- if (rnd_icc.length != 8) {
- throw new RuntimeException("invalid RND.ICC: " + toString(rnd_icc));
- }
- System.out.println("RND_ICC: " + toString(rnd_icc));
-
- if (cin.length != 10) {
- throw new RuntimeException("invalid CIN: " + toString(cin));
- }
-
- byte[] icc_id = Arrays.copyOfRange(cin, cin .length-8, cin.length);
- System.out.println("ICC_ID: " + toString(icc_id));
-
-// var rndifd = crypto.generateRandom(8);
-// var snifd = crypto.generateRandom(8);
-// var kifd = crypto.generateRandom(64); // 32 -> 64
-// var snicc = iccsn.bytes(2, 8);
-//
-
- Random rand = new Random(System.currentTimeMillis());
-
- byte[] rnd_ifd = new byte[8];
- rand.nextBytes(rnd_ifd);
- byte[] ifd_id = new byte[8];
- rand.nextBytes(ifd_id);
- byte[] kd_ifd = new byte[64];
- rand.nextBytes(kd_ifd);
-
-// var plain = rndifd.concat(snifd).concat(rndicc).concat(snicc).concat(kifd);
-// GPSystem.trace("Plain Block : " + plain);
-// print("Plain Block : " + plain);
-//
-// print("K_enc : " + kenc.getComponent(Key.DES));
-//
-// var cryptogram = crypto.encrypt(kenc, Crypto.DES_CBC, plain, new ByteString("0000000000000000", HEX));
-// GPSystem.trace("Cryptogram : " + cryptogram);
-// print("Cryptogram : " + cryptogram);
-
- Cipher tDES = Cipher.getInstance("3DES/CBC/NoPadding");
- tDES.init(Cipher.ENCRYPT_MODE, k_enc, new IvParameterSpec(ZEROS));
-
- 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));
-
-// 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));
- //
- // print("K_mac : " + kmac.getComponent(Key.DES));
- //
- // var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, cryptogram.pad(Crypto.ISO9797_METHOD_2));
- // GPSystem.trace("MAC : " + mac);
- // print("MAC : " + mac);
-
-
- byte[] mac = RetailCBCMac.retailMac(cryptogram, "DES", "DESede", k_mac, 8, 8);
- System.out.println("mac (" + mac.length +"byte): " + toString(mac));
-//
-//
-// var autresp = card.sendApdu(0x00, 0x82, 0x00, 0x00, cryptogram.concat(mac), 0); // 81 -> 00
-//
-// if (card.SW != 0x9000) {
-// GPSystem.trace("Mutual authenticate failed with " + card.SW.toString(16) + " \"" + card.SWMSG + "\"");
-// throw new GPError("MutualAuthentication", GPError.CRYPTO_FAILED, 0, "Card did not accept MAC");
-// }
-//
-// cryptogram = autresp.bytes(0, 96); // 64 -> 96
-// mac = autresp.bytes(96, 8); // 64 -> 96
-
- 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("MUTUAL AUTHENTICATE (" + c.length + "bytes): " + toString(c));
- cmdAPDU = new CommandAPDU(0x00, 0x82, 0x00, 0x81, c, 256); // 81->00
- System.out.println(" cmd apdu " + toString(cmdAPDU.getBytes()));
- resp = channel.transmit(cmdAPDU);
- System.out.println(" -> " + toString(resp.getBytes()) + "\n");
-
-//
-// if (!crypto.verify(kmac, Crypto.DES_MAC_EMV, cryptogram.pad(Crypto.ISO9797_METHOD_2), mac)) {
-// throw new GPError("MutualAuthentication", GPError.CRYPTO_FAILED, 0, "Card MAC did not verify correctly");
-// }
-
- System.out.println("ICC Response: " + resp.getData().length + " Bytes");
- System.arraycopy(resp.getData(), 0, cryptogram, 0, 96);
- System.arraycopy(resp.getData(), 96, mac, 0, 8);
-
- byte[] mac_ = RetailCBCMac.retailMac(cryptogram, "DES", "DESede", k_mac, 8, 8);
-
- if (!Arrays.equals(mac, mac_)) {
- throw new SignatureCardException("Failed to authenticate card, invalid MAC " + toString(mac));
- }
- System.out.println("icc MAC verified");
-
-
-//
-// plain = crypto.decrypt(kenc, Crypto.DES_CBC, cryptogram, new ByteString("0000000000000000", HEX));
-// GPSystem.trace("Plain Block : " + plain);
-//
-// if (!plain.bytes(0, 8).equals(rndicc)) {
-// throw new GPError("MutualAuthentication", GPError.CRYPTO_FAILED, 0, "Card response does not contain matching RND.ICC");
-// }
-//
-// if (!plain.bytes(16, 8).equals(rndifd)) {
-// throw new GPError("MutualAuthentication", GPError.CRYPTO_FAILED, 0, "Card response does not contain matching RND.IFD");
-// }
-
- tDES = Cipher.getInstance("3DES/CBC/NoPadding");
- tDES.init(Cipher.DECRYPT_MODE, k_enc, new IvParameterSpec(ZEROS));
-
- System.out.println("Decrypt cryptogram ("
- + cryptogram.length + " Bytes) " + toString(cryptogram));
-
- byte[] plain = tDES.doFinal(cryptogram);
-
- if (!Arrays.equals(Arrays.copyOfRange(plain, 0, 8), rnd_icc)) {
- throw new SignatureCardException("Failed to authenticate ICC, wrong RND.ICC "
- + toString(Arrays.copyOfRange(plain, 0, 8)));
- } else if (!Arrays.equals(Arrays.copyOfRange(plain, 16, 24), rnd_ifd)) {
- throw new SignatureCardException("Failed to authenticate ICC, wrong RND.IFD "
- + toString(Arrays.copyOfRange(plain, 16, 24)));
- }
-
- System.out.println("successfully verified RND.ICC/IFD");
-
-
-//
-// var kicc = plain.bytes(32, 64); // 32 -> 64
-// keyinp = kicc.xor(kifd);
-//
-
- // TDES session key negotiation according to E-Sign K [STARCOS,6.11]?
-
- byte[] kd_icc = Arrays.copyOfRange(plain, 32, 96);
- System.out.println("derive key input...");
- byte[] kinp = new byte[kd_ifd.length];
- for (int i = 0; i < kd_ifd.length; i++) {
- kinp[i] = (byte) (kd_icc[i] ^ kd_ifd[i]);
- }
-
- System.out.println("session key negotiation key (key seed): " + toString(kinp));
-
-// var hashin = keyinp.concat(new ByteString("00000001", HEX));
-// var hashres = crypto.digest(Crypto.SHA_256, hashin);
-// var kencval = hashres.bytes(0, 24);
-// var kencssc = hashres.bytes(24, 8);
-//
-// GPSystem.trace("Kenc : " + kencval);
-// GPSystem.trace("Kenc SSC : " + kencssc);
-// var kenc = new Key();
-// kenc.setComponent(Key.DES, kencval);
-//
-
- MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
- sha256.update(kinp);
- sha256.update(new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01});
- byte[] enc_ = sha256.digest();
-
- SecretKeySpec kenc = new SecretKeySpec(Arrays.copyOfRange(enc_, 0, 24), "3DES");
- byte[] kencssc = Arrays.copyOfRange(enc_, 24, 32);
-
- System.out.println("session key kenc: " + toString(kenc.getEncoded()));
- System.out.println("send sequence counter SSC_enc: " + toString(kencssc));
-
-// var hashin = keyinp.concat(new ByteString("00000002", HEX));
-// var hashres = crypto.digest(Crypto.SHA_256, hashin);
-// var kmacval = hashres.bytes(0, 24);
-// var kmacssc = hashres.bytes(24, 8);
-//
-// GPSystem.trace("Kmac : " + kmacval);
-// GPSystem.trace("Kmac SSC : " + kmacssc);
-// var kmac = new Key();
-// kmac.setComponent(Key.DES, kmacval);
-
- sha256.update(kinp);
- sha256.update(new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02});
- enc_ = sha256.digest();
-
- SecretKeySpec kmac = new SecretKeySpec(Arrays.copyOfRange(enc_, 0, 24), "3DES");
- byte[] kmacssc = Arrays.copyOfRange(enc_, 24, 32);
-
- System.out.println("session key kmac: " + toString(kmac.getEncoded()));
- System.out.println("send sequence counter SSC_mac: " + toString(kmacssc));
-
-//
-// var sc = new IsoSecureChannel(crypto);
-// sc.setEncKey(kenc);
-// sc.setMacKey(kmac);
-//
-// sc.setMACSendSequenceCounter(kmacssc);
-// sc.setEncryptionSendSequenceCounter(kencssc);
-// return sc;
-//}
-
- channel = new SecureChannel(channel, kenc, kmac, kencssc, kmacssc);
-
- }
-
- public static void main(String[] args) {
-
- try {
- Activation test = new Activation();
- test.setUp();
- test.activate();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-}
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();
}
}
diff --git a/smccTest/src/main/java/at/gv/egiz/smcc/activation/RetailCBCMac.java b/smccTest/src/main/java/at/gv/egiz/smcc/activation/RetailCBCMac.java
deleted file mode 100644
index 79f7be62..00000000
--- a/smccTest/src/main/java/at/gv/egiz/smcc/activation/RetailCBCMac.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package at.gv.egiz.smcc.activation;
-
-import iaik.utils.CryptoUtils;
-
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-public class RetailCBCMac {
-
- /**
- * Calculates a Retail CBC Mac from the given message.
- * <p>
- * The retail CBC Mac is calculated according to the following
- * algorithm:
- * <ul>
- * <li>
- * Pad the message to a multiple n of the CBC cipher block size with
- * a leading one bit followed by as many zero bits as necessary.
- * </li>
- * <li>
- * Create a CBC cipher key from the first <code>cbcCipherKeyLen</code>
- * bytes of the <code>csk</code> key and use it to calculate a
- * CBC Mac value from the first n-1 blocks of the padded message.
- * For CBC Mac calculation initialize the CBC Cipher with an
- * IV of all zero bytes.
- * </li>
- * <li>
- * XOR the last block of the padded message with the CBC mac value
- * and calculate the final retail MAC by encrypting the XOR result
- * with the given Cipher algorithm in ECB mode using no padding.
- * </li>
- * </ul>
- *
- * @param msg the message
- * @param cbcCipherAlg the name of the CBC Cipher algorithm to be used
- * @param cipherAlg the name of the final Cipher algorithm to be used
- * @param csk the secret key to be used
- * @param cbcCipherKeyLen the length of the CBC cipher key to be used
- * @param blockSize the block size of the CBC Cipher
- *
- * @return the retail CBC Mac value
- *
- * @throws NoSuchAlgorithmException if any of the requested Cipher algorithms
- * is not available
- * @throws NoSuchProviderException if the IAIK provider is not installed
- * @throws InvalidKeyException if the key cannot be used with the Ciphers
- * @throws GeneralSecurityException if the Cipher operation(s) fails
- */
- static byte[] retailMac(byte[] msg,
- String cbcCipherAlg,
- String cipherAlg,
- SecretKey csk,
- int cbcCipherKeyLen,
- int blockSize)
- throws NoSuchAlgorithmException,
- NoSuchProviderException,
- InvalidKeyException,
- GeneralSecurityException {
-
- if (msg == null) {
- throw new NullPointerException("Message m must not be null!");
- }
- if (csk == null) {
- throw new NullPointerException("Key csk must not be null!");
- }
-
- // calculate key for CBC cipher
- byte[] rawCsk = csk.getEncoded();
- int cskLen = rawCsk.length;
- SecretKey cbcCipherKey;
- if (cskLen == cbcCipherKeyLen) {
- cbcCipherKey = csk;
- } else if (cskLen < cbcCipherKeyLen) {
- throw new InvalidKeyException("Key too short!");
- } else {
- byte[] rawCbcCipherKey = new byte[blockSize];
- System.arraycopy(rawCsk, 0, rawCbcCipherKey, 0, blockSize);
- cbcCipherKey = new SecretKeySpec(rawCbcCipherKey, cbcCipherAlg);
- }
- // if necessary pad message with zeros
- byte[] paddedMsg = pad(msg, blockSize);
-
- // calculate CBC Mac for the first n-1 blocks
- int n = paddedMsg.length;
- int n_1 = n - blockSize;
- byte[] cbcMac = cbcMac(paddedMsg, 0, n_1, cbcCipherKey, cbcCipherAlg, blockSize);
-
- // calculate retail mac
- byte[] xor = new byte[blockSize];
- CryptoUtils.xorBlock(paddedMsg, n_1, cbcMac, 0, xor, 0, blockSize);
- Cipher cipher = Cipher.getInstance(cipherAlg+"/ECB/NoPadding", "IAIK");
- cipher.init(Cipher.ENCRYPT_MODE, csk);
- byte[] retailMac = cipher.doFinal(xor);
- return retailMac;
- }
-
- /**
- * Calculates a simple CBC Mac from the given (already) padded message.
- *
- * @param paddedMsg the (zero) padded message
- * @param off the start offset in the paddedMsg array
- * @param len the number of bytes to be processed, starting at <code>off</code>
- * @param key the Cipher key
- * @param cipherAlg the name of the CBC Cipher algorithm to be used
- * @param blockSize the block size of the CBC Cipher
- *
- * @return the CBC Mac value
- *
- * @throws NoSuchAlgorithmException if the requested Cipher algorithm
- * is not available
- * @throws NoSuchProviderException if the IAIK provider is not installed
- * @throws InvalidKeyException if the key cannot be used with the Ciphers
- * @throws GeneralSecurityException if the Cipher operation fails
- */
- static byte[] cbcMac(byte[] paddedMsg,
- int off,
- int len,
- SecretKey key,
- String cipherAlg,
- int blockSize)
- throws NoSuchAlgorithmException,
- NoSuchProviderException,
- InvalidKeyException,
- GeneralSecurityException {
-
- if (paddedMsg == null) {
- throw new NullPointerException("Message must not be null!");
- }
- if (key == null) {
- throw new NullPointerException("Key csk must not be null!");
- }
-
-
- Cipher cbcCipher = Cipher.getInstance(cipherAlg+"/CBC/NoPadding", "IAIK");
- byte[] iv = new byte[blockSize];
- cbcCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
- int finOff = off;
- if (len > blockSize) {
- finOff = len - blockSize;
- cbcCipher.update(paddedMsg, 0, finOff);
- }
- byte[] mac = cbcCipher.doFinal(paddedMsg, finOff, blockSize);
- return mac;
- }
-
- /**
- * Pads the given message to a multiple of the given blocksize with
- * a leading one bit followed by as many zero bits as necessary
- *
- * @param msg the message to be padded
- * @param blockSize the block size
- *
- * @return the padded message
- */
- static byte[] pad(byte[] msg, int blockSize) {
- int paddingLen;
- byte[] paddedMsg;
-
- int msgLen = msg.length;
- if (msgLen == 0) {
- paddingLen = blockSize;
- } else {
- paddingLen = blockSize - msgLen % blockSize;
- }
- if (paddingLen > 0) {
- paddedMsg = new byte[msgLen + paddingLen];
- System.arraycopy(msg, 0, paddedMsg, 0, msgLen);
- paddedMsg[msgLen] = (byte)0x80;
- } else {
- paddedMsg = msg;
- }
- return paddedMsg;
- }
-
-
-
-
-
-}
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
deleted file mode 100644
index 303b1b68..00000000
--- a/smccTest/src/main/java/at/gv/egiz/smcc/activation/SecureChannel.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package at.gv.egiz.smcc.activation;
-
-import java.nio.ByteBuffer;
-import javax.crypto.spec.SecretKeySpec;
-import javax.smartcardio.Card;
-import javax.smartcardio.CardChannel;
-import javax.smartcardio.CardException;
-import javax.smartcardio.CommandAPDU;
-import javax.smartcardio.ResponseAPDU;
-
-/**
- *
- * @author clemens
- */
-public class SecureChannel extends CardChannel {
-
- CardChannel basicChannel;
-
- SecretKeySpec kenc;
- SecretKeySpec kmac;
- byte[] kencssc;
- byte[] kmacssc;
-
- public SecureChannel(CardChannel basicChannel,
- SecretKeySpec kenc, SecretKeySpec kmac,
- byte[] kencssc, byte[] kmacssc) {
- this.basicChannel = basicChannel;
- this.kenc = kenc;
- this.kmac = kmac;
- this.kencssc = kencssc;
- this.kmacssc = kmacssc;
- }
-
-
- @Override
- public Card getCard() {
- return basicChannel.getCard();
- }
-
- @Override
- public int getChannelNumber() {
- return basicChannel.getChannelNumber();
- }
-
- @Override
- public ResponseAPDU transmit(CommandAPDU capdu) throws CardException {
- return basicChannel.transmit(capdu);
- }
-
- @Override
- public int transmit(ByteBuffer bb, ByteBuffer bb1) throws CardException {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
- public void close() throws CardException {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
-}
diff --git a/smccTest/src/test/java/at/gv/egiz/smcc/activation/TestRetailCBCMac.java b/smccTest/src/test/java/at/gv/egiz/smcc/activation/TestRetailCBCMac.java
deleted file mode 100644
index 495728c9..00000000
--- a/smccTest/src/test/java/at/gv/egiz/smcc/activation/TestRetailCBCMac.java
+++ /dev/null
@@ -1,358 +0,0 @@
-package at.gv.egiz.smcc.activation;
-
-import iaik.security.provider.IAIK;
-import iaik.utils.CryptoUtils;
-import iaik.utils.Util;
-
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.util.Arrays;
-import java.util.Random;
-
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import junit.framework.TestCase;
-
-public class TestRetailCBCMac extends TestCase {
-
-
- final static String[] PLAIN_DATA = {
- "5A 10 D3 0E FC F6 5D 7F 89 FF B6 69 E4 8C 1C 88 C9 D3 AB "+
- "74 3D B0 2C DB 00 00 00 23 00 78 71 11 6C 3C FC 5F 53 6C 49 A9 F3 42 E0 "+
- "E1 32 EE AE 2F 21 79 06 C0 6E EE 69 1B B0 10 B7 54 53 FA 31 EB 92 D1 51 "+
- "0D 90 E3 FC E2 F6 1C 1E 15 68 0D A5 AB CA 5B E8 45 23 8D 87 7C 5F 7B F5 "+
- "A1 D8 89 ED 30",
-
- "5C AB 2E 55 2C 1D BD F1 9C F9 F6 B9 28 73 5B EC 11 2A 2B "+
- "FC E5 C8 C6 86 00 00 00 23 00 78 71 11 59 D0 0C 8B 7B 45 A2 1F 02 62 5D "+
- "F3 18 F8 F2 46 A5 14 99 60 77 55 25 2C 3D AF 19 C9 CC C1 C8 9B EA 39 A3 "+
- "32 7C 45 19 87 B1 8A 98 CA D7 E5 90 A7 3D 70 BE 74 36 E3 09 C5 F9 00 57 "+
- "82 AF 64 B9 7D",
-
- "E4 A9 1F F1 5A AB BF 2F E8 3D C5 AA 70 BF A4 48 EE 32 88 "+
- "4B 5A 0A B2 E7 00 00 00 23 00 78 71 11 8A B1 B3 1F D0 40 33 D8 0A 9C 21 "+
- "5C CB 47 63 69 2C EC D4 46 92 C7 07 1D EF B5 6D 28 89 68 36 BA E1 7D A4 "+
- "60 03 5A 2C 0D 53 EF 43 2D BA 09 30 CD F7 4A 8C 70 18 ED 57 EA C9 63 E6 "+
- "43 B5 6C 97 94",
-
- "FD A8 CA 31 D7 41 EA 1D 62 47 71 A8 C9 2F D8 3E 3C 3A F1 "+
- "D2 60 41 8F 2A 00 00 00 23 00 78 71 11 45 0D B9 4F AF A1 4D 0C 9B 62 FE "+
- "B9 7C 3F C0 B0 B0 C2 67 44 3F 5F 2B B5 EC 8A 0D D9 D6 33 9B A0 EC 97 C2 "+
- "40 FA A4 56 67 46 02 58 B1 0A AB 27 FE 25 38 23 21 74 F6 34 3C 81 D4 1A "+
- "17 DB C2 A2 E9",
-
- "FB 5E 02 2A 0C A0 F0 09 7F FF 93 05 D1 3D 14 B4 14 3A DC "+
- "21 A3 AB DE C6 00 00 00 23 00 78 71 11 84 21 A6 CC 84 8B 0A 07 64 2F B2 "+
- "A1 05 7B 08 9A FB CE 3B B6 A1 36 A8 03 0D 7B EA 2D 1E 7A D7 E2 C1 2D E8 "+
- "DF 82 CE 3F 43 D5 F6 21 DB D2 F7 31 5B A8 F2 65 E2 F4 E4 7E 1E 94 F4 E6 "+
- "28 14 01 CA 18",
- };
-
- final static String[] CRYPTO_GRAM = {
- "E6 5E D9 34 14 4D 4B 86 B5 40 FB 2A 06 29 44 2D 5F 41 14 "+
- "E5 95 A3 6D 07 B0 C4 6A 14 35 8D FE 72 C6 18 37 96 15 20 4B CE E7 A9 A1 "+
- "FD C6 85 3D F5 AE EA E4 92 95 0B EB 95 74 CA ED 38 E8 4B E0 FC 4C 55 1B "+
- "DE DE AD B3 13 7E ED AB EC B3 C2 FC A2 BE 72 A6 BE 50 D4 79 89 D1 70 A4 "+
- "4A 15 EC A0 D7",
-
- "D8 91 7C 06 60 DC 9B 74 28 2A 44 68 96 AF EE 93 AC D2 CF "+
- "DB CE 19 F6 73 73 F5 61 B0 AB 20 DF 63 F3 C7 4C 47 86 BD E0 7A 9B 04 64 "+
- "F9 87 2D F3 A6 FB 3F E5 B8 80 C5 F1 29 A9 0A 56 4E 7F 96 BE 30 88 FD 81 "+
- "86 7D 13 56 6E 17 4B 2A 31 36 D3 DA 24 FD 66 7D 21 B2 9E C9 2D 63 46 EF "+
- "97 06 E1 DA 15",
-
- "5A 4E F8 99 EE ED 02 1A A2 C8 A9 6B DD FB D6 CE 2A F0 5A "+
- "05 57 6A 79 66 3C B3 B7 CA 00 98 52 EE 35 72 AE 65 17 D4 0F A7 B3 20 F5 "+
- "25 A7 A5 7A 47 79 EB 65 FD DE 63 68 A5 C0 04 EF 3D DA 21 5E DB B7 83 FD "+
- "EF FD 52 28 91 D3 67 F4 9E 69 57 1C 19 08 5F 67 98 86 6E 99 2F 19 A7 54 "+
- "B2 CE E8 F1 C0",
-
- "AB D2 A6 ED C1 AA 2C ED 12 67 7E 38 B2 CB 5C 4E 06 A0 E0 "+
- "5A FC 59 59 11 25 8B 92 07 12 81 D3 FE 7E B8 4B 35 CD F6 A2 CD 98 C7 EF "+
- "FC EA 75 94 2C 55 6F 35 B5 4E 83 F8 82 7B B0 85 DD B5 8E B1 04 B2 F0 71 "+
- "79 42 FA A4 81 68 64 83 FB F8 5E 75 B3 C6 C8 CA 17 9C 94 45 EC A9 8A ED "+
- "73 58 F9 9B 97",
-
- "AE E7 4C D8 AA 2E EA C4 6C D9 19 48 3C 19 12 D0 EA E8 70 "+
- "00 39 2F AF FD 77 36 3B 87 AF ED 11 9E 54 74 F6 4B DA 68 32 12 D7 B0 76 "+
- "73 87 BE C3 74 08 0E DB 33 1E 66 AE 9E 23 56 DD DC 0D 61 FF 8B 15 4A 36 "+
- "4E BD E7 9F E5 3C 15 43 4F CC B2 7F FC 4B DD D6 39 17 EB FD 3D D6 11 45 "+
- "AA DD F0 2E 61",
-
- };
-
- final static String[] RETAIL_MAC = {
- "27 D0 4D E8 17 20 46 E8",
-
- "C2 31 EF 5A 99 AB FA 5F",
-
- "09 6C 40 EE A6 12 FA 1C",
-
- "55 FA 62 93 86 56 D0 38",
-
- "9D 86 EB 57 A2 58 F8 C8",
-
- };
-
-
- final static String[] CSK = {
- "54 3D 49 BF 31 51 25 94 67 8A 64 4F 1C B9 54 3D 31 46 43 79 E5 B9 A7 A7",
- "76 23 EC 10 91 61 7C 75 EF EF BF 9D 7F 7F 9E FD 07 1A 0E 6E 51 0B D3 D0",
- "76 23 EC 10 91 61 7C 75 EF EF BF 9D 7F 7F 9E FD 07 1A 0E 6E 51 0B D3 D0",
- "54 3D 49 BF 31 51 25 94 67 8A 64 4F 1C B9 54 3D 31 46 43 79 E5 B9 A7 A72",
- "10 57 9E F4 9D 34 4F B3 43 D0 62 92 45 D9 EF 45 16 2F CD 4F 4A D5 38 08"
-
- };
-
-
-
- public TestRetailCBCMac() {
- super();
- }
-
- public TestRetailCBCMac(String name) {
- super(name);
- }
-
- /* (non-Javadoc)
- * @see iaik.AbstractTest#setUp()
- */
- public void setUp() throws Exception {
- super.setUp();
- IAIK.addAsProvider();
- }
-
-
-
- public void testRetailMac() {
- String cbcCipherAlg = "DES";
- String cipherAlg = "DESede";
- int cbcCipherKeyLen = 8;
- int blockSize = 8;
-
-
- for (int i = 0; i < PLAIN_DATA.length; i++) {
- byte[] plainData = Util.toByteArray(PLAIN_DATA[i].trim());
- byte[] cryptoGram = Util.toByteArray(CRYPTO_GRAM[i].trim());
- byte[] retailMac = Util.toByteArray(RETAIL_MAC[i].trim());
- byte[] rawCsk = Util.toByteArray(CSK[i].trim());
- byte[] calculatedMac = null;
- try {
- SecretKeySpec csk = new SecretKeySpec(rawCsk, cipherAlg);
- calculatedMac = retailMac(cryptoGram, cbcCipherAlg, cipherAlg, csk, cbcCipherKeyLen, blockSize);
- System.out.println("Expected Mac : " + Util.toString(retailMac));
- System.out.println("Calculated Mac: " + Util.toString(calculatedMac));
- } catch (Exception e) {
- e.printStackTrace();
- fail("Unexpetced error: " + e.toString());
- }
- assertTrue("Different Mac values!", Arrays.equals(retailMac, calculatedMac));
- }
- }
-
-// public void testRetailMacDESTripleDES() {
-// testRetailMac("DES", "DESede", 8, 8);
-// }
-
- public void testRetailMac(String cbcCipherAlg, String cipherAlg, int cbcCipherKeyLen, int blockSize) {
- try {
-
- Random rand = new Random();
- KeyGenerator kg = KeyGenerator.getInstance(cipherAlg, "IAIK");
- SecretKey key = kg.generateKey();
- int[] dataLen = { 0, 3, 8, 15, 16, 20, 24, 31, 32, 39, 40, 48, 510, 512, 1111, 1024, 2000, 2048, 4003, 4096 };
- for (int i = 0; i < dataLen.length; i++) {
- int len = dataLen[i];
- byte[] data = new byte[len];
- rand.nextBytes(data);
- System.out.println("\n Data (" + len + " bytes):" + Util.toString(data));
-
- byte[] mac = retailMac(data, cbcCipherAlg, "DESede", key, cbcCipherKeyLen, blockSize);
-
- System.out.println("MAC: " + Util.toString(mac));
- }
-
-
-
-
- } catch (Exception e) {
- fail("Unexpetced error: " + e.toString());
- }
- }
-
- /**
- * Calculates a Retail CBC Mac from the given message.
- * <p>
- * The retail CBC Mac is calculated according to the following
- * algorithm:
- * <ul>
- * <li>
- * Pad the message to a multiple n of the CBC cipher block size with
- * a leading one bit followed by as many zero bits as necessary.
- * </li>
- * <li>
- * Create a CBC cipher key from the first <code>cbcCipherKeyLen</code>
- * bytes of the <code>csk</code> key and use it to calculate a
- * CBC Mac value from the first n-1 blocks of the padded message.
- * For CBC Mac calculation initialize the CBC Cipher with an
- * IV of all zero bytes.
- * </li>
- * <li>
- * XOR the last block of the padded message with the CBC mac value
- * and calculate the final retail MAC by encrypting the XOR result
- * with the given Cipher algorithm in ECB mode using no padding.
- * </li>
- * </ul>
- *
- * @param msg the message
- * @param cbcCipherAlg the name of the CBC Cipher algorithm to be used
- * @param cipherAlg the name of the final Cipher algorithm to be used
- * @param csk the secret key to be used
- * @param cbcCipherKeyLen the length of the CBC cipher key to be used
- * @param blockSize the block size of the CBC Cipher
- *
- * @return the retail CBC Mac value
- *
- * @throws NoSuchAlgorithmException if any of the requested Cipher algorithms
- * is not available
- * @throws NoSuchProviderException if the IAIK provider is not installed
- * @throws InvalidKeyException if the key cannot be used with the Ciphers
- * @throws GeneralSecurityException if the Cipher operation(s) fails
- */
- static byte[] retailMac(byte[] msg,
- String cbcCipherAlg,
- String cipherAlg,
- SecretKey csk,
- int cbcCipherKeyLen,
- int blockSize)
- throws NoSuchAlgorithmException,
- NoSuchProviderException,
- InvalidKeyException,
- GeneralSecurityException {
-
- if (msg == null) {
- throw new NullPointerException("Message m must not be null!");
- }
- if (csk == null) {
- throw new NullPointerException("Key csk must not be null!");
- }
-
- // calculate key for CBC cipher
- byte[] rawCsk = csk.getEncoded();
- int cskLen = rawCsk.length;
- SecretKey cbcCipherKey;
- if (cskLen == cbcCipherKeyLen) {
- cbcCipherKey = csk;
- } else if (cskLen < cbcCipherKeyLen) {
- throw new InvalidKeyException("Key too short!");
- } else {
- byte[] rawCbcCipherKey = new byte[blockSize];
- System.arraycopy(rawCsk, 0, rawCbcCipherKey, 0, blockSize);
- cbcCipherKey = new SecretKeySpec(rawCbcCipherKey, cbcCipherAlg);
- }
- // if necessary pad message with zeros
- byte[] paddedMsg = pad(msg, blockSize);
-
- // calculate CBC Mac for the first n-1 blocks
- int n = paddedMsg.length;
- int n_1 = n - blockSize;
- byte[] cbcMac = cbcMac(paddedMsg, 0, n_1, cbcCipherKey, cbcCipherAlg, blockSize);
-
- // calculate retail mac
- byte[] xor = new byte[blockSize];
- CryptoUtils.xorBlock(paddedMsg, n_1, cbcMac, 0, xor, 0, blockSize);
- Cipher cipher = Cipher.getInstance(cipherAlg+"/ECB/NoPadding", "IAIK");
- cipher.init(Cipher.ENCRYPT_MODE, csk);
- byte[] retailMac = cipher.doFinal(xor);
- return retailMac;
- }
-
- /**
- * Calculates a simple CBC Mac from the given (already) padded message.
- *
- * @param paddedMsg the (zero) padded message
- * @param off the start offset in the paddedMsg array
- * @param len the number of bytes to be processed, starting at <code>off</code>
- * @param key the Cipher key
- * @param cipherAlg the name of the CBC Cipher algorithm to be used
- * @param blockSize the block size of the CBC Cipher
- *
- * @return the CBC Mac value
- *
- * @throws NoSuchAlgorithmException if the requested Cipher algorithm
- * is not available
- * @throws NoSuchProviderException if the IAIK provider is not installed
- * @throws InvalidKeyException if the key cannot be used with the Ciphers
- * @throws GeneralSecurityException if the Cipher operation fails
- */
- static byte[] cbcMac(byte[] paddedMsg,
- int off,
- int len,
- SecretKey key,
- String cipherAlg,
- int blockSize)
- throws NoSuchAlgorithmException,
- NoSuchProviderException,
- InvalidKeyException,
- GeneralSecurityException {
-
- if (paddedMsg == null) {
- throw new NullPointerException("Message must not be null!");
- }
- if (key == null) {
- throw new NullPointerException("Key csk must not be null!");
- }
-
-
- Cipher cbcCipher = Cipher.getInstance(cipherAlg+"/CBC/NoPadding", "IAIK");
- byte[] iv = new byte[blockSize];
- cbcCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
- int finOff = off;
- if (len > blockSize) {
- finOff = len - blockSize;
- cbcCipher.update(paddedMsg, 0, finOff);
- }
- byte[] mac = cbcCipher.doFinal(paddedMsg, finOff, blockSize);
- return mac;
- }
-
- /**
- * Pads the given message to a multiple of the given blocksize with
- * a leading one bit followed by as many zero bits as necessary
- *
- * @param msg the message to be padded
- * @param blockSize the block size
- *
- * @return the padded message
- */
- static byte[] pad(byte[] msg, int blockSize) {
- int paddingLen;
- byte[] paddedMsg;
-
- int msgLen = msg.length;
- if (msgLen == 0) {
- paddingLen = blockSize;
- } else {
- paddingLen = blockSize - msgLen % blockSize;
- }
- if (paddingLen > 0) {
- paddedMsg = new byte[msgLen + paddingLen];
- System.arraycopy(msg, 0, paddedMsg, 0, msgLen);
- paddedMsg[msgLen] = (byte)0x80;
- } else {
- paddedMsg = msg;
- }
- return paddedMsg;
- }
-
-
-
-
-
-}