Improve memory handling with SecureMessaging
This commit is contained in:
parent
f693a7290e
commit
ec84edb737
@ -31,7 +31,7 @@ public final class CmacKey {
|
||||
protected final byte[] k1;
|
||||
protected final byte[] k2;
|
||||
|
||||
protected CmacKey(final byte aesKeyLength) {
|
||||
protected CmacKey(final short aesKeyLength) {
|
||||
key = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
|
||||
(short)(aesKeyLength * 8),
|
||||
false);
|
||||
@ -51,6 +51,10 @@ public final class CmacKey {
|
||||
Util.arrayFillNonAtomic(k2, (short)0, (short)k2.length, (byte)0);
|
||||
}
|
||||
|
||||
protected final short getSize() {
|
||||
return key.getSize();
|
||||
}
|
||||
|
||||
protected final void setKey(final byte[] buf, final short bufOff) {
|
||||
key.setKey(buf, bufOff);
|
||||
|
||||
|
@ -51,8 +51,13 @@ public final class CmacSignature {
|
||||
}
|
||||
|
||||
protected final void clear() {
|
||||
if(key != null) {
|
||||
if(key.isInitialized()) {
|
||||
key.clearKey();
|
||||
}
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
|
||||
private final byte blockLen() {
|
||||
return bytes[BYTE_OFFSET_BLOCK_LEN];
|
||||
|
@ -27,6 +27,14 @@ import javacardx.crypto.*;
|
||||
|
||||
public final class Common {
|
||||
|
||||
protected static final short aesKeyLength(final ECParams params) {
|
||||
if(params.nb_bits < (short)512) {
|
||||
return (short)16;
|
||||
} else {
|
||||
return (short)32;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final short writeLength(final byte[] buf, short off, final short len) {
|
||||
if(len > 0xff) {
|
||||
buf[off] = (byte)0x82;
|
||||
|
@ -29,7 +29,6 @@ public final class SecureMessaging {
|
||||
|
||||
public static final short MAC_LENGTH = (short)(Constants.AES_BLOCK_SIZE / (short)2);
|
||||
|
||||
|
||||
protected static final byte[] PADDING_BLOCK = {
|
||||
(byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00,
|
||||
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
||||
@ -37,62 +36,101 @@ public final class SecureMessaging {
|
||||
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
|
||||
};
|
||||
|
||||
private final byte[] iv;
|
||||
private final byte[] mac_chaining;
|
||||
private static final byte[] CRT_PREFIX = {
|
||||
(byte)0xA6, (byte)0x0D,
|
||||
(byte)0x90, (byte)0x02, (byte)0x11, (byte)0x00,
|
||||
(byte)0x95, (byte)0x01, (byte)0x3C,
|
||||
(byte)0x80, (byte)0x01, (byte)0x88,
|
||||
(byte)0x81, (byte)0x01
|
||||
};
|
||||
|
||||
private final Cipher cipher;
|
||||
|
||||
private final CmacSignature macer;
|
||||
private AESKey senc;
|
||||
private CmacKey smac;
|
||||
private CmacKey srmac;
|
||||
private final MessageDigest digest;
|
||||
private final KeyAgreement key_agreement;
|
||||
|
||||
protected final PGPKey static_key;
|
||||
|
||||
private final Cipher cipher;
|
||||
private AESKey senc;
|
||||
private final byte[] iv;
|
||||
|
||||
private final CmacSignature macer;
|
||||
private final byte[] mac_chaining;
|
||||
private CmacKey sreceiptmac;
|
||||
private CmacKey smac;
|
||||
private CmacKey srmac;
|
||||
|
||||
|
||||
protected SecureMessaging(final Transients transients) {
|
||||
digest = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
|
||||
key_agreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false);
|
||||
|
||||
static_key = new PGPKey(true);
|
||||
|
||||
cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||
|
||||
macer = new CmacSignature();
|
||||
|
||||
senc = null;
|
||||
iv = JCSystem.makeTransientByteArray(Constants.AES_BLOCK_SIZE,
|
||||
JCSystem.CLEAR_ON_DESELECT);
|
||||
|
||||
macer = new CmacSignature();
|
||||
mac_chaining = JCSystem.makeTransientByteArray(Constants.AES_BLOCK_SIZE,
|
||||
JCSystem.CLEAR_ON_DESELECT);
|
||||
|
||||
senc = null;
|
||||
sreceiptmac = null;
|
||||
smac = null;
|
||||
srmac = null;
|
||||
|
||||
static_key = new PGPKey(true);
|
||||
|
||||
reset(transients);
|
||||
}
|
||||
|
||||
|
||||
protected final void clearSession(final Transients transients) {
|
||||
if(senc != null) {
|
||||
if((senc != null) && senc.isInitialized()) {
|
||||
senc.clearKey();
|
||||
senc = null;
|
||||
}
|
||||
if(smac != null) {
|
||||
smac.clearKey();
|
||||
smac = null;
|
||||
}
|
||||
if(srmac != null) {
|
||||
srmac.clearKey();
|
||||
srmac = null;
|
||||
}
|
||||
macer.clear();
|
||||
transients.setSecureMessagingEncryptionCounter((short)0);
|
||||
Util.arrayFillNonAtomic(iv, (short)0, (short)iv.length, (byte)0);
|
||||
|
||||
macer.clear();
|
||||
Util.arrayFillNonAtomic(mac_chaining, (short)0, (short)mac_chaining.length, (byte)0);
|
||||
if((sreceiptmac != null) && senc.isInitialized()) {
|
||||
sreceiptmac.clearKey();
|
||||
}
|
||||
if((smac != null) && smac.isInitialized()) {
|
||||
smac.clearKey();
|
||||
}
|
||||
if((srmac != null) && srmac.isInitialized()) {
|
||||
srmac.clearKey();
|
||||
}
|
||||
|
||||
transients.setSecureMessagingEncryptionCounter((short)0);
|
||||
}
|
||||
|
||||
protected final void reset(final Transients transients) {
|
||||
clearSession(transients);
|
||||
sreceiptmac = null;
|
||||
senc = null;
|
||||
smac = null;
|
||||
srmac = null;
|
||||
static_key.reset();
|
||||
}
|
||||
|
||||
private final void initSession(final short keyLength,
|
||||
final byte[] buf, final short off) {
|
||||
if((sreceiptmac == null) ||
|
||||
(sreceiptmac.getSize() != (short)(keyLength * 8))) {
|
||||
senc = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
|
||||
(short)(keyLength * 8),
|
||||
false);
|
||||
|
||||
sreceiptmac = new CmacKey(keyLength);
|
||||
smac = new CmacKey(keyLength);
|
||||
srmac = new CmacKey(keyLength);
|
||||
}
|
||||
|
||||
sreceiptmac.setKey(buf, off);
|
||||
senc.setKey(buf, (short)(off + keyLength));
|
||||
smac.setKey(buf, (short)(off + (short)(2 * keyLength)));
|
||||
srmac.setKey(buf, (short)(off + (short)(3 * keyLength)));
|
||||
}
|
||||
|
||||
protected final boolean isInitialized() {
|
||||
return static_key.isInitialized();
|
||||
}
|
||||
@ -104,38 +142,27 @@ public final class SecureMessaging {
|
||||
&& (srmac != null) && srmac.isInitialized();
|
||||
}
|
||||
|
||||
private static final byte aesKeyLength(final ECParams params) {
|
||||
if(params.nb_bits < (short)512) {
|
||||
return (byte)16;
|
||||
} else {
|
||||
return (byte)32;
|
||||
}
|
||||
}
|
||||
|
||||
private final short scp11b(final ECParams params,
|
||||
private final short scp11b(final ECCurves curves,
|
||||
final byte[] buf, final short len) {
|
||||
|
||||
final byte[] crt = new byte[]{ (byte)0xA6, (byte)0x0D,
|
||||
(byte)0x90, (byte)0x02, (byte)0x11, (byte)0x00,
|
||||
(byte)0x95, (byte)0x01, (byte)0x3C,
|
||||
(byte)0x80, (byte)0x01, (byte)0x88,
|
||||
(byte)0x81, (byte)0x01 };
|
||||
final ECParams params = static_key.ecParams(curves);
|
||||
|
||||
if(len <= (short)((short)crt.length + 4)) {
|
||||
if(len <= (short)((short)CRT_PREFIX.length + 4)) {
|
||||
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Util.arrayCompare(crt, (short)0,
|
||||
if(Util.arrayCompare(CRT_PREFIX, (short)0,
|
||||
buf, (short)0,
|
||||
(short)crt.length) != (byte)0) {
|
||||
(short)CRT_PREFIX.length) != (byte)0) {
|
||||
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
short off = (short)crt.length;
|
||||
short off = (short)CRT_PREFIX.length;
|
||||
|
||||
if(buf[off] != aesKeyLength(params)) {
|
||||
if(buf[off] != Common.aesKeyLength(params)) {
|
||||
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
@ -147,7 +174,7 @@ public final class SecureMessaging {
|
||||
}
|
||||
off += 2;
|
||||
|
||||
final short keylen = Common.readLength(buf, off, len);
|
||||
short keylen = Common.readLength(buf, off, len);
|
||||
|
||||
off = Common.skipLength(buf, off, len);
|
||||
|
||||
@ -161,17 +188,17 @@ public final class SecureMessaging {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final ECPrivateKey eskcard = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE,
|
||||
ECPrivateKey eskcard = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE,
|
||||
params.nb_bits,
|
||||
false);
|
||||
final ECPublicKey epkcard = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,
|
||||
ECPublicKey epkcard = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,
|
||||
params.nb_bits,
|
||||
false);
|
||||
|
||||
params.setParams(eskcard);
|
||||
params.setParams(epkcard);
|
||||
|
||||
final KeyPair ekcard = new KeyPair(epkcard, eskcard);
|
||||
KeyPair ekcard = new KeyPair(epkcard, eskcard);
|
||||
|
||||
ekcard.genKeyPair();
|
||||
|
||||
@ -181,17 +208,16 @@ public final class SecureMessaging {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final KeyAgreement ka = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false);
|
||||
|
||||
ka.init(eskcard);
|
||||
key_agreement.init(eskcard);
|
||||
|
||||
short msglen = 0;
|
||||
|
||||
msglen += ka.generateSecret(buf, off, keylen, buf, len);
|
||||
msglen += key_agreement.generateSecret(buf, off, keylen, buf, len);
|
||||
eskcard.clearKey();
|
||||
eskcard = null;
|
||||
|
||||
static_key.initKeyAgreement(ka);
|
||||
msglen += ka.generateSecret(buf, off, keylen, buf, (short)(len + msglen));
|
||||
static_key.initKeyAgreement(key_agreement);
|
||||
msglen += key_agreement.generateSecret(buf, off, keylen, buf, (short)(len + msglen));
|
||||
|
||||
Util.setShort(buf, (short)(len + msglen), (short)0);
|
||||
msglen += 2;
|
||||
@ -200,52 +226,26 @@ public final class SecureMessaging {
|
||||
off = (short)(len + msglen);
|
||||
msglen += 2;
|
||||
|
||||
buf[(short)(len + msglen)] = crt[(short)8];
|
||||
buf[(short)(len + msglen)] = CRT_PREFIX[(short)8];
|
||||
++msglen;
|
||||
buf[(short)(len + msglen)] = crt[(short)11];
|
||||
buf[(short)(len + msglen)] = CRT_PREFIX[(short)11];
|
||||
++msglen;
|
||||
buf[(short)(len + msglen)] = buf[crt.length];
|
||||
buf[(short)(len + msglen)] = buf[CRT_PREFIX.length];
|
||||
++msglen;
|
||||
|
||||
short keydata_len = 0;
|
||||
keylen = 0;
|
||||
|
||||
final MessageDigest digest = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
|
||||
|
||||
while(keydata_len < (short)(4 * buf[crt.length])) {
|
||||
while(keylen < (short)(4 * buf[CRT_PREFIX.length])) {
|
||||
Util.setShort(buf, off, counter);
|
||||
++counter;
|
||||
|
||||
keydata_len += digest.doFinal(buf, len, msglen,
|
||||
buf, (short)(len + msglen + keydata_len));
|
||||
keylen += digest.doFinal(buf, len, msglen,
|
||||
buf, (short)(len + msglen + keylen));
|
||||
}
|
||||
|
||||
final CmacKey sreceiptmac = new CmacKey(aesKeyLength(params));
|
||||
sreceiptmac.setKey(buf, (short)(len + msglen));
|
||||
initSession(Common.aesKeyLength(params), buf, (short)(len + msglen));
|
||||
|
||||
if(senc != null) {
|
||||
senc.clearKey();
|
||||
senc = null;
|
||||
}
|
||||
senc = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
|
||||
(short)(aesKeyLength(params) * 8),
|
||||
false);
|
||||
senc.setKey(buf, (short)(len + msglen + aesKeyLength(params)));
|
||||
|
||||
if(smac != null) {
|
||||
smac.clearKey();
|
||||
smac = null;
|
||||
}
|
||||
smac = new CmacKey(aesKeyLength(params));
|
||||
smac.setKey(buf, (short)(len + msglen + 2 * aesKeyLength(params)));
|
||||
|
||||
if(srmac != null) {
|
||||
srmac.clearKey();
|
||||
srmac = null;
|
||||
}
|
||||
srmac = new CmacKey(aesKeyLength(params));
|
||||
srmac.setKey(buf, (short)(len + msglen + 3 * aesKeyLength(params)));
|
||||
|
||||
Util.arrayFillNonAtomic(buf, len, (short)(msglen + keydata_len), (byte)0);
|
||||
Util.arrayFillNonAtomic(buf, len, (short)(msglen + keylen), (byte)0);
|
||||
|
||||
off = len;
|
||||
Util.setShort(buf, off, (short)0x5F49);
|
||||
@ -255,6 +255,9 @@ public final class SecureMessaging {
|
||||
msglen = off;
|
||||
|
||||
epkcard.clearKey();
|
||||
epkcard = null;
|
||||
|
||||
ekcard = null;
|
||||
|
||||
buf[off++] = (byte)0x86;
|
||||
buf[off++] = (byte)Constants.AES_BLOCK_SIZE;
|
||||
@ -262,7 +265,6 @@ public final class SecureMessaging {
|
||||
macer.init(sreceiptmac);
|
||||
macer.sign(buf, (short)0, msglen,
|
||||
buf, off, Constants.AES_BLOCK_SIZE);
|
||||
sreceiptmac.clearKey();
|
||||
macer.clear();
|
||||
|
||||
Util.arrayCopy(buf, off, mac_chaining, (short)0, Constants.AES_BLOCK_SIZE);
|
||||
@ -284,11 +286,7 @@ public final class SecureMessaging {
|
||||
clearSession(transients);
|
||||
|
||||
if(isInitialized() && static_key.isEc()) {
|
||||
final ECParams params = static_key.ecParams(ec);
|
||||
|
||||
if(params != null) {
|
||||
return scp11b(params, buf, len);
|
||||
}
|
||||
return scp11b(ec, buf, len);
|
||||
}
|
||||
|
||||
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
|
||||
|
Loading…
Reference in New Issue
Block a user