Skip to content
Merged
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 @@ -20,7 +20,7 @@
import org.globalplatform.upgrade.UpgradeManager;

import com.android.javacard.seprovider.KMAndroidSEProvider;
import com.android.javacard.seprovider.KMDeviceUniqueKey;
import com.android.javacard.seprovider.KMDeviceUniqueKeyPair;
import com.android.javacard.seprovider.KMError;
import com.android.javacard.seprovider.KMException;
import com.android.javacard.seprovider.KMType;
Expand All @@ -35,7 +35,7 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeLis
// Magic number version
private static final byte KM_MAGIC_NUMBER = (byte) 0x82;
// MSB byte is for Major version and LSB byte is for Minor version.
private static final short CURRENT_PACKAGE_VERSION = 0x0009; // 0.9
private static final short CURRENT_PACKAGE_VERSION = 0x0100;

private static final byte KM_BEGIN_STATE = 0x00;
private static final byte ILLEGAL_STATE = KM_BEGIN_STATE + 1;
Expand All @@ -49,9 +49,9 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeLis
private static final byte INS_LOCK_PROVISIONING_CMD = INS_KEYMINT_PROVIDER_APDU_START + 3;
private static final byte INS_GET_PROVISION_STATUS_CMD = INS_KEYMINT_PROVIDER_APDU_START + 4;
private static final byte INS_SET_BOOT_PARAMS_CMD = INS_KEYMINT_PROVIDER_APDU_START + 5;
private static final byte INS_PROVISION_DEVICE_UNIQUE_KEY_CMD =
private static final byte INS_PROVISION_RKP_UNIQUE_DEVICE_KEYPAIR_CMD =
INS_KEYMINT_PROVIDER_APDU_START + 6;
private static final byte INS_PROVISION_ADDITIONAL_CERT_CHAIN_CMD =
private static final byte INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD =
INS_KEYMINT_PROVIDER_APDU_START + 7;
private static final byte INS_SET_BOOT_ENDED_CMD =
INS_KEYMINT_PROVIDER_APDU_START + 8;
Expand All @@ -68,7 +68,7 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeLis
private static final byte PROVISION_STATUS_ATTEST_IDS = 0x08;
private static final byte PROVISION_STATUS_PRESHARED_SECRET = 0x10;
private static final byte PROVISION_STATUS_PROVISIONING_LOCKED = 0x20;
private static final byte PROVISION_STATUS_DEVICE_UNIQUE_KEY = 0x40;
private static final byte PROVISION_STATUS_UNIQUE_DEVICE_KEYPAIR = 0x40;
private static final byte PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = (byte) 0x80;

public static final short SHARED_SECRET_KEY_SIZE = 32;
Expand Down Expand Up @@ -159,11 +159,11 @@ public void process(APDU apdu) {
processSetBootParamsCmd(apdu);
break;

case INS_PROVISION_DEVICE_UNIQUE_KEY_CMD:
processProvisionDeviceUniqueKey(apdu);
case INS_PROVISION_RKP_UNIQUE_DEVICE_KEYPAIR_CMD:
processProvisionDeviceUniqueKeyPair(apdu);
break;

case INS_PROVISION_ADDITIONAL_CERT_CHAIN_CMD:
case INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD:
processProvisionAdditionalCertChain(apdu);
break;

Expand All @@ -189,7 +189,7 @@ public void process(APDU apdu) {
}
}

private static void processProvisionDeviceUniqueKey(APDU apdu) {
private static void processProvisionDeviceUniqueKeyPair(APDU apdu) {
// Re-purpose the apdu buffer as scratch pad.
byte[] scratchPad = apdu.getBuffer();
short arr = KMArray.instance((short) 1);
Expand All @@ -201,13 +201,13 @@ private static void processProvisionDeviceUniqueKey(APDU apdu) {
short pubKeyLen = KMCoseKey.cast(coseKey).getEcdsa256PublicKey(scratchPad, (short) 0);
short privKeyLen = KMCoseKey.cast(coseKey).getPrivateKey(scratchPad, pubKeyLen);
//Store the Device unique Key.
kmDataStore.createDeviceUniqueKey(scratchPad, (short) 0, pubKeyLen, scratchPad,
kmDataStore.createDeviceUniqueKeyPair(scratchPad, (short) 0, pubKeyLen, scratchPad,
pubKeyLen, privKeyLen);
short bcc = generateBcc(false, scratchPad);
short len = KMKeymasterApplet.encodeToApduBuffer(bcc, scratchPad, (short) 0,
MAX_COSE_BUF_SIZE);
kmDataStore.persistBootCertificateChain(scratchPad, (short) 0, len);
kmDataStore.setProvisionStatus(PROVISION_STATUS_DEVICE_UNIQUE_KEY);
kmDataStore.setProvisionStatus(PROVISION_STATUS_UNIQUE_DEVICE_KEYPAIR);
sendError(apdu, KMError.OK);
}

Expand Down Expand Up @@ -244,7 +244,7 @@ private static void processProvisionAdditionalCertChain(APDU apdu) {
srcBuffer, null);
// Compare the DK_Pub.
short pubKeyLen = KMCoseKey.cast(leafCoseKey).getEcdsa256PublicKey(srcBuffer, (short) 0);
KMDeviceUniqueKey uniqueKey = kmDataStore.getDeviceUniqueKey(false);
KMDeviceUniqueKeyPair uniqueKey = kmDataStore.getDeviceUniqueKeyPair(false);
if (uniqueKey == null) {
KMException.throwIt(KMError.STATUS_FAILED);
}
Expand Down Expand Up @@ -408,7 +408,7 @@ private boolean isProvisioningComplete() {
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
boolean result = false;
if ((0 != (data[dInex] & PROVISION_STATUS_DEVICE_UNIQUE_KEY))
if ((0 != (data[dInex] & PROVISION_STATUS_UNIQUE_DEVICE_KEYPAIR))
&& (0 != (data[dInex] & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN))
&& (0 != (data[dInex] & PROVISION_STATUS_PRESHARED_SECRET))) {
result = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ public boolean ecVerify256(byte[] pubKey, short pubKeyOffset, short pubKeyLen,
}

@Override
public short ecSign256(KMDeviceUniqueKey ecPrivKey, byte[] inputDataBuf,
public short ecSign256(KMDeviceUniqueKeyPair ecPrivKey, byte[] inputDataBuf,
short inputDataStart, short inputDataLength, byte[] outputDataBuf,
short outputDataStart) {
Signature.OneShot signer = null;
Expand All @@ -1108,7 +1108,7 @@ public short ecSign256(KMDeviceUniqueKey ecPrivKey, byte[] inputDataBuf,
}

@Override
public KMDeviceUniqueKey createDeviceUniqueKey(KMDeviceUniqueKey key,
public KMDeviceUniqueKeyPair createDeviceUniqueKeyPair(KMDeviceUniqueKeyPair key,
byte[] pubKey, short pubKeyOff, short pubKeyLen, byte[] privKey,
short privKeyOff, short privKeyLen) {
if (key == null) {
Expand All @@ -1118,7 +1118,7 @@ public KMDeviceUniqueKey createDeviceUniqueKey(KMDeviceUniqueKey key,
}
((KMECDeviceUniqueKey) key).setS(privKey, privKeyOff, privKeyLen);
((KMECDeviceUniqueKey) key).setW(pubKey, pubKeyOff, pubKeyLen);
return (KMDeviceUniqueKey) key;
return (KMDeviceUniqueKeyPair) key;
}

@Override
Expand Down Expand Up @@ -1182,7 +1182,7 @@ public void onSave(Element element, byte interfaceType, Object object) {
case KMDataStoreConstants.INTERFACE_TYPE_ATTESTATION_KEY:
KMECPrivateKey.onSave(element, (KMECPrivateKey) object);
break;
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR:
KMECDeviceUniqueKey.onSave(element, (KMECDeviceUniqueKey) object);
break;
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
Expand All @@ -1208,7 +1208,7 @@ public Object onResore(Element element) {
return KMHmacKey.onRestore((HMACKey) element.readObject());
case KMDataStoreConstants.INTERFACE_TYPE_ATTESTATION_KEY:
return KMECPrivateKey.onRestore((KeyPair) element.readObject());
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR:
return KMECDeviceUniqueKey.onRestore((KeyPair) element.readObject());
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
return KMHmacKey.onRestore((HMACKey) element.readObject());
Expand All @@ -1234,7 +1234,7 @@ public short getBackupPrimitiveByteCount(byte interfaceType) {
case KMDataStoreConstants.INTERFACE_TYPE_ATTESTATION_KEY:
primitiveCount += KMECPrivateKey.getBackupPrimitiveByteCount();
break;
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR:
primitiveCount += KMECDeviceUniqueKey.getBackupPrimitiveByteCount();
break;
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
Expand All @@ -1257,7 +1257,7 @@ public short getBackupObjectCount(byte interfaceType) {
return KMHmacKey.getBackupObjectCount();
case KMDataStoreConstants.INTERFACE_TYPE_ATTESTATION_KEY:
return KMECPrivateKey.getBackupObjectCount();
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY:
case KMDataStoreConstants.INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR:
return KMECDeviceUniqueKey.getBackupObjectCount();
case KMDataStoreConstants.INTERFACE_TYPE_RKP_MAC_KEY:
return KMHmacKey.getBackupObjectCount();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class KMDataStoreConstants {
// INTERFACE Types
public static final byte INTERFACE_TYPE_COMPUTED_HMAC_KEY = 0x01;
public static final byte INTERFACE_TYPE_ATTESTATION_KEY = 0x02;
public static final byte INTERFACE_TYPE_DEVICE_UNIQUE_KEY = 0x03;
public static final byte INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR = 0x03;
public static final byte INTERFACE_TYPE_MASTER_KEY = 0x04;
public static final byte INTERFACE_TYPE_PRE_SHARED_KEY = 0x05;
public static final byte INTERFACE_TYPE_RKP_MAC_KEY = 0x06;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import javacard.security.ECPublicKey;
import javacard.security.KeyPair;

public class KMECDeviceUniqueKey implements KMDeviceUniqueKey {
public class KMECDeviceUniqueKey implements KMDeviceUniqueKeyPair {

private KeyPair ecKeyPair;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ boolean ecVerify256(
* @return length of the decrypted data.
*/
short ecSign256(
KMDeviceUniqueKey ecPrivKey,
KMDeviceUniqueKeyPair ecPrivKey,
byte[] inputDataBuf,
short inputDataStart,
short inputDataLength,
Expand Down Expand Up @@ -626,7 +626,7 @@ KMOperation initAsymmetricOperation(
* @param privKeyLen private key buffer length.
* @return instance of KMDeviceUniqueKey.
*/
KMDeviceUniqueKey createDeviceUniqueKey(KMDeviceUniqueKey key,
KMDeviceUniqueKeyPair createDeviceUniqueKeyPair(KMDeviceUniqueKeyPair key,
byte[] pubKey, short pubKeyOff, short pubKeyLen,
byte[] privKey, short privKeyOff, short privKeyLen);

Expand Down
113 changes: 34 additions & 79 deletions Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.android.javacard.keymaster;

import com.android.javacard.seprovider.KMAttestationCert;
import com.android.javacard.seprovider.KMDeviceUniqueKey;
import com.android.javacard.seprovider.KMDeviceUniqueKeyPair;
import com.android.javacard.seprovider.KMException;
import com.android.javacard.seprovider.KMHmacKey;
import com.android.javacard.seprovider.KMSEProvider;
Expand Down Expand Up @@ -1221,35 +1221,31 @@ private KMAttestationCert makeCommonCert(byte[] scratchPad) {
}


private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyParam,
short attChallenge, short issuer, short hwParameters, short swParameters, byte[] scratchPad) {
private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyParam, short attChallenge, short issuer,
short hwParameters, short swParameters, byte[] scratchPad) {
KMAttestationCert cert = makeCommonCert(scratchPad);

// App Id and App Data,
short appId = KMType.INVALID_VALUE;
short appData = KMType.INVALID_VALUE;
if(attKeyParam != KMType.INVALID_VALUE) {
appId =
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, attKeyParam);
if (attKeyParam != KMType.INVALID_VALUE) {
appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, attKeyParam);
if (appId != KMTag.INVALID_VALUE) {
appId = KMByteTag.cast(appId).getValue();
}
appData =
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, attKeyParam);
appData = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, attKeyParam);
if (appData != KMTag.INVALID_VALUE) {
appData = KMByteTag.cast(appData).getValue();
}
}
//TODO remove following line
short origBlob = data[KEY_BLOB];
short pubKey = data[PUB_KEY];
short privKey = data[SECRET];
short keyBlob = parseEncryptedKeyBlob(attKeyBlob, appId, appData, scratchPad);
short attestationKeySecret = KMArray.cast(keyBlob).get(KEY_BLOB_SECRET);
short attestParam = KMArray.cast(keyBlob).get(KEY_BLOB_PARAMS);
attestParam = KMKeyCharacteristics.cast(attestParam).getStrongboxEnforced();
short attKeyPurpose =
KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, attestParam);
short attKeyPurpose = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, attestParam);
// If the attest key's purpose is not "attest key" then error.
if (!KMEnumArrayTag.cast(attKeyPurpose).contains(KMType.ATTEST_KEY)) {
KMException.throwIt(KMError.INCOMPATIBLE_PURPOSE);
Expand All @@ -1260,45 +1256,43 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara
}
short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, attestParam);

if(KMEnumTag.cast(alg).getValue() == KMType.RSA) {
if (KMEnumTag.cast(alg).getValue() == KMType.RSA) {
short attestationKeyPublic = KMArray.cast(keyBlob).get(KEY_BLOB_PUB_KEY);
cert.rsaAttestKey(attestationKeySecret, attestationKeyPublic, KMType.ATTESTATION_CERT);
}else{
} else {
cert.ecAttestKey(attestationKeySecret, KMType.ATTESTATION_CERT);
}
cert.attestationChallenge(attChallenge);
cert.issuer(issuer);
//TODO remove following line
data[PUB_KEY] = pubKey;
data[SECRET] = privKey;
data[KEY_BLOB] = origBlob;
cert.publicKey(data[PUB_KEY]);

// Save attestation application id - must be present.
short attAppId =
KMKeyParameters.findTag( KMType.BYTES_TAG, KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]);
if (attAppId == KMType.INVALID_VALUE) {
KMException.throwIt(KMError.ATTESTATION_APPLICATION_ID_MISSING);
}
cert.extensionTag(attAppId, false);
// unique id byte blob - uses application id and temporal month count of creation time.
setUniqueId(cert, scratchPad);
// Add Attestation Ids if present
addAttestationIds(cert, scratchPad);

// Add Tags
addTags(hwParameters, true, cert);
addTags(swParameters, false, cert);
// Add Device Boot locked status
cert.deviceLocked(kmDataStore.isDeviceBootLocked());
// VB data
cert.verifiedBootHash(getVerifiedBootHash(scratchPad));
cert.verifiedBootKey(getBootKey(scratchPad));
cert.verifiedBootState((byte)kmDataStore.getBootState());

//TODO remove the following line
short attAppId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]);
if (attAppId == KMType.INVALID_VALUE) {
KMException.throwIt(KMError.ATTESTATION_APPLICATION_ID_MISSING);
}
cert.extensionTag(attAppId, false);
// unique id byte blob - uses application id and temporal month count of
// creation time.
setUniqueId(cert, scratchPad);
// Add Attestation Ids if present
addAttestationIds(cert, scratchPad);

// Add Tags
addTags(hwParameters, true, cert);
addTags(swParameters, false, cert);
// Add Device Boot locked status
cert.deviceLocked(kmDataStore.isDeviceBootLocked());
// VB data
cert.verifiedBootHash(getVerifiedBootHash(scratchPad));
cert.verifiedBootKey(getBootKey(scratchPad));
cert.verifiedBootState((byte) kmDataStore.getBootState());

// TODO remove the following line
makeKeyCharacteristics(scratchPad);
data[SECRET] = privKey;
data[KEY_BLOB] = origBlob;

return cert;
}

Expand Down Expand Up @@ -3455,45 +3449,6 @@ private void generateAttestation(short attKeyBlob, short attKeyParam, byte[] sc
// Initialize the certificate as array of blob
data[CERTIFICATE] = KMArray.instance((short)1);
KMArray.cast(data[CERTIFICATE]).add((short)0, certData);

/*
boolean rsaCert = KMEnumTag.cast(alg).getValue() == KMType.EC;
short appId = KMType.INVALID_VALUE;
short appData = KMType.INVALID_VALUE;
if(attKeyParam != KMType.INVALID_VALUE) {
appId =
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, attKeyParam);
if (appId != KMTag.INVALID_VALUE) {
appId = KMByteTag.cast(appId).getValue();
}
appData =
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, attKeyParam);
if (appData != KMTag.INVALID_VALUE) {
appData = KMByteTag.cast(appData).getValue();
}
}

KMAttestationCert cert = makeCert(attKeyBlob, appId, appData, scratchPad);
if(cert == null) {// No certificate
data[CERTIFICATE] = KMArray.instance((short)0);
return;
}

// Allocate memory
short certData = KMByteBlob.instance(MAX_CERT_SIZE);
cert.buffer(KMByteBlob.cast(certData).getBuffer(),
KMByteBlob.cast(certData).getStartOff(),
KMByteBlob.cast(certData).length());
// Build the certificate - this will sign the cert
cert.build();
// Adjust the start and length of the certificate in the blob
KMByteBlob.cast(certData).setStartOff(cert.getCertStart());
KMByteBlob.cast(certData).setLength(cert.getCertLength());

// Initialize the certificate as array of blob
data[CERTIFICATE] = KMArray.instance((short)1);
KMArray.cast(data[CERTIFICATE]).add((short)0, certData);
*/
}

/**
Expand Down Expand Up @@ -4100,7 +4055,7 @@ public static short generateBcc(boolean testMode, byte[] scratchPad) {
if (!testMode && kmDataStore.isProvisionLocked()) {
KMException.throwIt(KMError.STATUS_FAILED);
}
KMDeviceUniqueKey deviceUniqueKey = kmDataStore.getDeviceUniqueKey(testMode);
KMDeviceUniqueKeyPair deviceUniqueKey = kmDataStore.getDeviceUniqueKeyPair(testMode);
short temp = deviceUniqueKey.getPublicKey(scratchPad, (short) 0);
short coseKey =
KMCose.constructCoseKey(
Expand Down
Loading