implement AES CBC-MAC with a software fallback
This commit is contained in:
parent
9cab2f993a
commit
e04f4c7bc7
|
@ -22,9 +22,13 @@ public class SecureChannel {
|
||||||
public static final byte PAIR_P1_FIRST_STEP = 0x00;
|
public static final byte PAIR_P1_FIRST_STEP = 0x00;
|
||||||
public static final byte PAIR_P1_LAST_STEP = 0x01;
|
public static final byte PAIR_P1_LAST_STEP = 0x01;
|
||||||
|
|
||||||
|
public static final short MAX_MAC_APDU_SIZE = (short) 256;
|
||||||
|
|
||||||
private AESKey scEncKey;
|
private AESKey scEncKey;
|
||||||
private AESKey scMacKey;
|
private AESKey scMacKey;
|
||||||
private Cipher scCipher;
|
private Cipher scCipher;
|
||||||
|
private Cipher scMacCipher;
|
||||||
|
private byte[] macCipherBuf;
|
||||||
private Signature scMac;
|
private Signature scMac;
|
||||||
private KeyPair scKeypair;
|
private KeyPair scKeypair;
|
||||||
private byte[] secret;
|
private byte[] secret;
|
||||||
|
@ -46,7 +50,12 @@ public class SecureChannel {
|
||||||
public SecureChannel(byte pairingLimit, byte[] aPairingSecret, short off) {
|
public SecureChannel(byte pairingLimit, byte[] aPairingSecret, short off) {
|
||||||
scCipher = Cipher.getInstance(Cipher.ALG_AES_CBC_ISO9797_M2,false);
|
scCipher = Cipher.getInstance(Cipher.ALG_AES_CBC_ISO9797_M2,false);
|
||||||
|
|
||||||
scMac = Signature.getInstance(Signature.ALG_AES_MAC_128_NOPAD, false);
|
try {
|
||||||
|
scMac = Signature.getInstance(Signature.ALG_AES_MAC_128_NOPAD, false);
|
||||||
|
} catch (CryptoException e) {
|
||||||
|
scMacCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||||
|
macCipherBuf = JCSystem.makeTransientByteArray(MAX_MAC_APDU_SIZE, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
}
|
||||||
|
|
||||||
scEncKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
|
scEncKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
|
||||||
scMacKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
|
scMacKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
|
||||||
|
@ -56,7 +65,7 @@ public class SecureChannel {
|
||||||
SECP256k1.setCurveParameters((ECKey) scKeypair.getPublic());
|
SECP256k1.setCurveParameters((ECKey) scKeypair.getPublic());
|
||||||
scKeypair.genKeyPair();
|
scKeypair.genKeyPair();
|
||||||
|
|
||||||
secret = JCSystem.makeTransientByteArray((byte)(SC_SECRET_LENGTH * 2), JCSystem.CLEAR_ON_DESELECT);
|
secret = JCSystem.makeTransientByteArray((short)(SC_SECRET_LENGTH * 2), JCSystem.CLEAR_ON_DESELECT);
|
||||||
pairingSecret = new byte[SC_SECRET_LENGTH];
|
pairingSecret = new byte[SC_SECRET_LENGTH];
|
||||||
pairingKeys = new byte[(short)(PAIRING_KEY_LENGTH * pairingLimit)];
|
pairingKeys = new byte[(short)(PAIRING_KEY_LENGTH * pairingLimit)];
|
||||||
|
|
||||||
|
@ -261,11 +270,19 @@ public class SecureChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean verifyAESMAC(byte[] apduBuffer, short apduLen) {
|
public boolean verifyAESMAC(byte[] apduBuffer, short apduLen) {
|
||||||
scMac.init(scMacKey, Signature.MODE_VERIFY);
|
if (scMac == null) {
|
||||||
scMac.update(apduBuffer, (short) 0, ISO7816.OFFSET_CDATA);
|
scMacCipher.init(scMacKey, Cipher.MODE_ENCRYPT);
|
||||||
scMac.update(secret, SC_BLOCK_SIZE, (short) (SC_BLOCK_SIZE - ISO7816.OFFSET_CDATA));
|
short encLen = scMacCipher.update(apduBuffer, (short) 0, ISO7816.OFFSET_CDATA, macCipherBuf, (short) 0);
|
||||||
|
encLen += scMacCipher.update(secret, SC_BLOCK_SIZE, (short) (SC_BLOCK_SIZE - ISO7816.OFFSET_CDATA), macCipherBuf, encLen);
|
||||||
|
encLen += scMacCipher.doFinal(apduBuffer, (short) (ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), (short) (apduLen - SC_BLOCK_SIZE), macCipherBuf, encLen);
|
||||||
|
return Util.arrayCompare(apduBuffer, ISO7816.OFFSET_CDATA, macCipherBuf, (short)(encLen - SC_BLOCK_SIZE), SC_BLOCK_SIZE) == 0;
|
||||||
|
} else {
|
||||||
|
scMac.init(scMacKey, Signature.MODE_VERIFY);
|
||||||
|
scMac.update(apduBuffer, (short) 0, ISO7816.OFFSET_CDATA);
|
||||||
|
scMac.update(secret, SC_BLOCK_SIZE, (short) (SC_BLOCK_SIZE - ISO7816.OFFSET_CDATA));
|
||||||
|
|
||||||
return scMac.verify(apduBuffer, (short) (ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), (short) (apduLen - SC_BLOCK_SIZE), apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
return scMac.verify(apduBuffer, (short) (ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), (short) (apduLen - SC_BLOCK_SIZE), apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -296,10 +313,18 @@ public class SecureChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computeAESMAC(short len, byte[] apduBuffer) {
|
public void computeAESMAC(short len, byte[] apduBuffer) {
|
||||||
scMac.init(scMacKey, Signature.MODE_SIGN);
|
if (scMac == null) {
|
||||||
scMac.update(apduBuffer, (short) 0, (short) 1);
|
scMacCipher.init(scMacKey, Cipher.MODE_ENCRYPT);
|
||||||
scMac.update(secret, SC_BLOCK_SIZE, (short)(SC_BLOCK_SIZE - 1));
|
short encLen = scMacCipher.update(apduBuffer, (short) 0, (short) 1, macCipherBuf, (short) 0);
|
||||||
scMac.sign(apduBuffer, (short)(ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), len, apduBuffer, ISO7816.OFFSET_CDATA);
|
encLen += scMacCipher.update(secret, SC_BLOCK_SIZE, (short) (SC_BLOCK_SIZE - 1), macCipherBuf, encLen);
|
||||||
|
encLen += scMacCipher.doFinal(apduBuffer, (short) (ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), len, macCipherBuf, encLen);
|
||||||
|
Util.arrayCopyNonAtomic(macCipherBuf, (short)(encLen - SC_BLOCK_SIZE), apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
||||||
|
} else {
|
||||||
|
scMac.init(scMacKey, Signature.MODE_SIGN);
|
||||||
|
scMac.update(apduBuffer, (short) 0, (short) 1);
|
||||||
|
scMac.update(secret, SC_BLOCK_SIZE, (short) (SC_BLOCK_SIZE - 1));
|
||||||
|
scMac.sign(apduBuffer, (short) (ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), len, apduBuffer, ISO7816.OFFSET_CDATA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue