Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,18 +158,7 @@ public static void install(byte[] bArray, short bOffset, byte bLength) {
}
new KMAndroidSEApplet(kmDevice).register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}

private boolean isProvisionLocked() {
short offset = repositoryInst.alloc((short) 1);
short len = kmDataStore.getData(KMDataStoreConstants.PROVISIONED_LOCKED,
repositoryInst.getHeap(), offset);
if (len == 0) {
return false;
}
return ((byte[]) repositoryInst.getHeap())[offset] == 0x01;
}



@Override
public void process(APDU apdu) {
try {
Expand All @@ -184,7 +173,7 @@ public void process(APDU apdu) {
kmDeviceInst.powerReset();
}

if (isProvisionLocked()) {
if (seProvisionInst.isProvisionLocked()) {
switch (apduIns) {
case INS_SET_BOOT_PARAMS_CMD:
processSetBootParamsCmd(apdu);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
import com.android.javacard.kmdevice.KMError;
import com.android.javacard.kmdevice.KMException;
import com.android.javacard.kmdevice.KMRkpDataStore;
import com.android.javacard.kmdevice.KMRkpMacKey;
import com.android.javacard.kmdevice.KMPreSharedKey;
import com.android.javacard.kmdevice.KMSEProvider;
import com.android.javacard.kmdevice.KMComputedHmacKey;
import com.android.javacard.kmdevice.KMDataStoreConstants;
import com.android.javacard.kmdevice.KMType;

Expand All @@ -36,6 +38,7 @@ public class KMRkpDataStoreImpl implements KMRkpDataStore {
private KMDeviceUniqueKey deviceUniqueKey;
private KMDeviceUniqueKey testDeviceUniqueKey;
private KMSEProvider seProvider;
private KMRkpMacKey rkpMacKey;


public KMRkpDataStoreImpl(KMSEProvider provider) {
Expand Down Expand Up @@ -67,6 +70,9 @@ public void storeData(byte storeDataIndex, byte[] data, short offset, short leng
case KMDataStoreConstants.BOOT_CERT_CHAIN:
persistBootCertificateChain(data, offset, length);
break;
case KMDataStoreConstants.RKP_MAC_KEY:
persistRkpMacKey(data, offset, length);
break;
}
}

Expand Down Expand Up @@ -100,6 +106,13 @@ private void persistBootCertificateChain(byte[] buf, short offset, short len) {
Util.arrayCopy(buf, offset, bcc, (short) 2, len);
}

private void persistRkpMacKey(byte[] keydata, short offset, short length) {
if (rkpMacKey == null) {
rkpMacKey = seProvider.createRkpMacKey(rkpMacKey, keydata, offset, length);
} else {
seProvider.createRkpMacKey(rkpMacKey, keydata, offset, length);
}
}

@Override
public void createDeviceUniqueKey(boolean testMode, byte[] pubKey, short pubKeyOff,
Expand Down Expand Up @@ -154,27 +167,33 @@ public void onSave(Element ele) {
ele.write(bcc);
// Key Object
seProvider.onSave(ele, KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY, deviceUniqueKey);
seProvider.onSave(ele, KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY, rkpMacKey);
}

@Override
public void onRestore(Element ele, short oldVersion, short currentVersion) {
additionalCertData = (byte[]) ele.readObject();
bcc = (byte[]) ele.readObject();
deviceUniqueKey = (KMDeviceUniqueKey) seProvider.onResore(ele);
rkpMacKey = (KMRkpMacKey) seProvider.onResore(ele);
}

@Override
public short getBackupPrimitiveByteCount() {
return seProvider.getBackupPrimitiveByteCount(
KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY);
return (short)(seProvider.getBackupPrimitiveByteCount(
KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY) +
seProvider.getBackupPrimitiveByteCount(
KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY));
}

@Override
public short getBackupObjectCount() {
// AdditionalCertificateChain - 1
// BCC - 1
return (short) (2 + seProvider.getBackupObjectCount(
KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY));
KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY) +
seProvider.getBackupObjectCount(
KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY));
}

@Override
Expand All @@ -189,5 +208,10 @@ public byte[] getData(byte dataStoreId) {
}
return null;
}

@Override
public KMRkpMacKey getRkpMacacKey() {
return rkpMacKey;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.android.javacard.kmdevice.KMMasterKey;
import com.android.javacard.kmdevice.KMOperation;
import com.android.javacard.kmdevice.KMPreSharedKey;
import com.android.javacard.kmdevice.KMRkpMacKey;
import com.android.javacard.kmdevice.KMSEProvider;

import javacard.framework.ISO7816;
Expand Down Expand Up @@ -516,43 +517,45 @@ public HMACKey cmacKdf(KMPreSharedKey preSharedKey, byte[] label, short labelSta
final byte n = 2; // hardcoded
// [L] 256 bits - hardcoded 32 bits as per
// reference impl in keymaster.
final byte[] L = {
0, 0, 1, 0
};
// byte
final byte[] zero = {
0
};
short zeroIndex = 0;
short LIndex = 1;
short bufIndex = 5;
short keyIndex = 9;
//1st byte in tempArray is reserved for zero
//next 4 bytes in tempArray is reserved for L
tmpArray[0] = 0;
tmpArray[1] = 0;
tmpArray[2] = 0;
tmpArray[3] = 1;
tmpArray[4] = 0;

// [i] counter - 32 bits
short iBufLen = 4;
short keyOutLen = n * 16;
//Convert Hmackey to AES Key as the algorithm is ALG_AES_CMAC_128.
KMHmacKey hmacKey = ((KMHmacKey) preSharedKey);
hmacKey.getKey(tmpArray, (short) 0);
aesKeys[KEYSIZE_256_OFFSET].setKey(tmpArray, (short) 0);
hmacKey.getKey(tmpArray, keyIndex);
aesKeys[KEYSIZE_256_OFFSET].setKey(tmpArray, (short) keyIndex);
//Initialize the key derivation function.
kdf.init(aesKeys[KEYSIZE_256_OFFSET], Signature.MODE_SIGN);
//Clear the tmpArray buffer.
Util.arrayFillNonAtomic(tmpArray, (short) 0, (short) 256, (byte) 0);

Util.arrayFillNonAtomic(tmpArray, (short) 0, iBufLen, (byte) 0);
Util.arrayFillNonAtomic(tmpArray, (short) iBufLen, keyOutLen, (byte) 0);
Util.arrayFillNonAtomic(tmpArray, keyIndex, (short) 256, (byte) 0);

byte i = 1;
short pos = 0;
while (i <= n) {
tmpArray[3] = i;
tmpArray[(short)(bufIndex + 3)] = i;
// 4 bytes of iBuf with counter in it
kdf.update(tmpArray, (short) 0, (short) iBufLen);
kdf.update(label, labelStart, (short) labelLen); // label
kdf.update(zero, (short) 0, (short) 1); // 1 byte of 0x00
kdf.update(tmpArray, bufIndex, iBufLen);
kdf.update(label, labelStart, labelLen); // label
kdf.update(tmpArray, zeroIndex, (short) 1); // 1 byte of 0x00
kdf.update(context, contextStart, contextLength); // context
// 4 bytes of L - signature of 16 bytes
pos = kdf.sign(L, (short) 0, (short) 4, tmpArray,
(short) (iBufLen + pos));
pos = kdf.sign(tmpArray, LIndex, (short) 4, tmpArray,
(short) (keyIndex + pos));
i++;
}
return createHMACKey(tmpArray, (short) iBufLen, (short) keyOutLen);
return createHMACKey(tmpArray, keyIndex, keyOutLen);
} finally {
clean();
}
Expand All @@ -570,6 +573,16 @@ public short hmacSign(byte[] keyBuf, short keyStart, short keyLength,
HMACKey key = createHMACKey(keyBuf, keyStart, keyLength);
return hmacSign(key, data, dataStart, dataLength, mac, macStart);
}

@Override
public short hmacSign(Object key,
byte[] data, short dataStart, short dataLength, byte[] mac, short macStart) {
if(!(key instanceof KMHmacKey)) {
KMException.throwIt(KMError.INVALID_ARGUMENT);
}
KMHmacKey hmacKey = (KMHmacKey) key;
return hmacSign(hmacKey.getKey(), data, dataStart, dataLength, mac, macStart);
}

@Override
public short hmacKDF(KMMasterKey masterkey, byte[] data, short dataStart,
Expand All @@ -587,8 +600,11 @@ public short hmacKDF(KMMasterKey masterkey, byte[] data, short dataStart,
}

@Override
public boolean hmacVerify(KMComputedHmacKey key, byte[] data, short dataStart,
public boolean hmacVerify(Object key, byte[] data, short dataStart,
short dataLength, byte[] mac, short macStart, short macLength) {
if(!(key instanceof KMHmacKey)) {
KMException.throwIt(KMError.INVALID_ARGUMENT);
}
KMHmacKey hmacKey = (KMHmacKey) key;
hmacSignature.init(hmacKey.getKey(), Signature.MODE_VERIFY);
return hmacSignature.verify(data, dataStart, dataLength, mac, macStart,
Expand Down Expand Up @@ -918,6 +934,18 @@ public KMComputedHmacKey createComputedHmacKey(KMComputedHmacKey computedHmacKey
return (KMComputedHmacKey) computedHmacKey;
}

@Override
public KMRkpMacKey createRkpMacKey(KMRkpMacKey rkpMacKey, byte[] keyData,
short offset, short length) {
if (rkpMacKey == null) {
HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short) (length * 8),
false);
rkpMacKey = new KMHmacKey(key);
}
((KMHmacKey) rkpMacKey).setKey(keyData, offset, length);
return rkpMacKey;
}

@Override
public short ecSign256(byte[] secret, short secretStart, short secretLength,
byte[] inputDataBuf, short inputDataStart, short inputDataLength,
Expand Down Expand Up @@ -1048,22 +1076,22 @@ private short hkdfExpand(byte[] prk, short prkOff, short prkLen, byte[] info, sh
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
HMACKey hmacKey = createHMACKey(prk, prkOff, prkLen);
Util.arrayFill(tmpArray, (short) 0, (short) 32, (byte) 0);
byte[] cnt = {(byte) 0};
//first byte in tmpArray will be used for count.
Util.arrayFill(tmpArray, (short) 0, (short) 33, (byte) 0);
short bytesCopied = 0;
short len = 0;
for (short i = 0; i < n; i++) {
cnt[0]++;
tmpArray[0]++;
hmacSignature.init(hmacKey, Signature.MODE_SIGN);
if (i != 0) {
hmacSignature.update(tmpArray, (short) 0, (short) 32);
hmacSignature.update(tmpArray, (short) 1, (short) 32);
}
hmacSignature.update(info, infoOff, infoLen);
len = hmacSignature.sign(cnt, (short) 0, (short) 1, tmpArray, (short) 0);
len = hmacSignature.sign(tmpArray, (short) 0, (short) 1, tmpArray, (short) 1);
if ((short) (bytesCopied + len) > outLen) {
len = (short) (outLen - bytesCopied);
}
Util.arrayCopyNonAtomic(tmpArray, (short) 0, out, (short) (outOff + bytesCopied), len);
Util.arrayCopyNonAtomic(tmpArray, (short) 1, out, (short) (outOff + bytesCopied), len);
bytesCopied += len;
}
return outLen;
Expand Down Expand Up @@ -1212,6 +1240,8 @@ public short getBackupPrimitiveByteCount(byte interfaceType) {
return KMECPrivateKey.getBackupPrimitiveByteCount();
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
return KMECDeviceUniqueKey.getBackupPrimitiveByteCount();
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
return KMHmacKey.getBackupPrimitiveByteCount();
default:
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
Expand All @@ -1231,6 +1261,8 @@ public short getBackupObjectCount(byte interfaceType) {
return KMECPrivateKey.getBackupObjectCount();
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
return KMECDeviceUniqueKey.getBackupObjectCount();
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
return KMHmacKey.getBackupObjectCount();
default:
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@

import com.android.javacard.kmdevice.KMComputedHmacKey;
import com.android.javacard.kmdevice.KMPreSharedKey;
import com.android.javacard.kmdevice.KMRkpMacKey;

import javacard.security.HMACKey;

public class KMHmacKey implements KMPreSharedKey, KMComputedHmacKey {
public class KMHmacKey implements KMPreSharedKey, KMComputedHmacKey, KMRkpMacKey {

private HMACKey hmacKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,18 @@ public void processLockProvisioningCmd(APDU apdu) {
kmDeviceInst.sendError(apdu, KMError.OK);
}

public boolean isProvisionLocked() {
short offset = kmRepositroyInst.allocReclaimableMemory((short) 1);
short len = kmStoreDataInst.getData(KMDataStoreConstants.PROVISIONED_LOCKED,
kmRepositroyInst.getHeap(), offset);
if (len == 0) {
return false;
}
boolean res = ((byte[]) kmRepositroyInst.getHeap())[offset] == 0x01;
kmRepositroyInst.reclaimMemory((short)1);
return res;
}

public void processProvisionDeviceUniqueKey(APDU apdu) {
kmDeviceInst.sendError(apdu, KMError.CMD_NOT_ALLOWED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,9 @@ public class KMPoolManager {
// Hmac signer pool which is used to support TRUSTED_CONFIRMATION_REQUIRED tag.
private Object[] hmacSignOperationPool;

final byte[] CIPHER_ALGS = {
Cipher.ALG_AES_BLOCK_128_CBC_NOPAD,
Cipher.ALG_AES_BLOCK_128_ECB_NOPAD,
Cipher.ALG_DES_CBC_NOPAD,
Cipher.ALG_DES_ECB_NOPAD,
Cipher.ALG_AES_CTR,
Cipher.ALG_RSA_PKCS1,
KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1,
KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA256,
Cipher.ALG_RSA_NOPAD,
AEADCipher.ALG_AES_GCM};

final byte[] SIG_ALGS = {
Signature.ALG_RSA_SHA_256_PKCS1,
Signature.ALG_RSA_SHA_256_PKCS1_PSS,
Signature.ALG_ECDSA_SHA_256,
Signature.ALG_HMAC_SHA_256,
KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD,
KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST,
KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST};

final byte[] KEY_AGREE_ALGS = {KeyAgreement.ALG_EC_SVDP_DH_PLAIN};

private static byte[] CIPHER_ALGS;
private static byte[] SIG_ALGS;
private static byte[] KEY_AGREE_ALGS;

private static KMPoolManager poolManager;

Expand All @@ -76,6 +56,7 @@ public static KMPoolManager getInstance() {
}

private KMPoolManager() {
initStatics();
cipherPool = new Object[(short) (CIPHER_ALGS.length * 4)];
// Extra 4 algorithms are used to support TRUSTED_CONFIRMATION_REQUIRED feature.
signerPool = new Object[(short) ((SIG_ALGS.length * 4) + 4)];
Expand All @@ -90,6 +71,29 @@ private KMPoolManager() {
initializeKeyAgreementPool();
}

private void initStatics() {
CIPHER_ALGS = new byte[]{
Cipher.ALG_AES_BLOCK_128_CBC_NOPAD,
Cipher.ALG_AES_BLOCK_128_ECB_NOPAD,
Cipher.ALG_DES_CBC_NOPAD,
Cipher.ALG_DES_ECB_NOPAD,
Cipher.ALG_AES_CTR,
Cipher.ALG_RSA_PKCS1,
KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1,
KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA256,
Cipher.ALG_RSA_NOPAD,
AEADCipher.ALG_AES_GCM};
SIG_ALGS = new byte[]{
Signature.ALG_RSA_SHA_256_PKCS1,
Signature.ALG_RSA_SHA_256_PKCS1_PSS,
Signature.ALG_ECDSA_SHA_256,
Signature.ALG_HMAC_SHA_256,
KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD,
KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST,
KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST};
KEY_AGREE_ALGS = new byte[]{KeyAgreement.ALG_EC_SVDP_DH_PLAIN};
}

private void initializeOperationPool() {
short index = 0;
while (index < MAX_OPERATION_INSTANCES) {
Expand Down
Loading