Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.
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 numberDiff line numberDiff line change
Expand Up@@ -59,24 +59,9 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeLis
private static final byte INS_PROVISION_OEM_ROOT_PUBLIC_KEY_CMD = INS_KEYMINT_PROVIDER_APDU_START + 10;
private static final byte INS_OEM_UNLOCK_PROVISIONING_CMD = INS_KEYMINT_PROVIDER_APDU_START + 11;


private static final byte INS_KEYMINT_PROVIDER_APDU_END = 0x1F;
public static final byte BOOT_KEY_MAX_SIZE = 32;
public static final byte BOOT_HASH_MAX_SIZE = 32;

// Provision reporting status
private static final byte NOT_PROVISIONED = 0x00;
private static final byte PROVISION_STATUS_ATTESTATION_KEY = 0x01; // unused in keymint
private static final byte PROVISION_STATUS_ATTESTATION_CERT_CHAIN = 0x02; // unused in keymint
private static final byte PROVISION_STATUS_ATTESTATION_CERT_PARAMS = 0x04; // unused in keymint
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_KEYPAIR = 0x40;
private static final byte PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = (byte) 0x80;
private static final byte PROVISION_STATUS_SE_LOCKED = 0x01;
private static final byte PROVISION_STATUS_OEM_PUBLIC_KEY = 0x02;

public static final short SHARED_SECRET_KEY_SIZE = 32;

// Package version.
Expand DownExpand Up@@ -206,7 +191,7 @@ private boolean isCommandAllowed(short apduIns) {
break;

case INS_SE_FACTORY_PROVISIONING_LOCK_CMD:
if(!isSeFactoryProvisioningComplete()) {
if(isSeFactoryProvisioningLocked() || !isSeFactoryProvisioningComplete()) {
result = false;
}
break;
Expand All@@ -216,7 +201,7 @@ private boolean isCommandAllowed(short apduIns) {
// 1. All the necessary provisioning commands are succcessfully executed
// 2. SE provision is locked
// 3. OEM Root Public is provisioned.
if (!(isProvisioningComplete() && isSeFactoryProvisioningLocked())) {
if (kmDataStore.isProvisionLocked() || !(isProvisioningComplete() && isSeFactoryProvisioningLocked())) {
result = false;
}
break;
Expand All@@ -243,44 +228,48 @@ private boolean isCommandAllowed(short apduIns) {
}

private boolean isSeFactoryProvisioningLocked() {
short dInex = repository.allocReclaimableMemory((short)1);
byte data[] = repository.getHeap();
short dInex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
short pStatus = Util.getShort(data, dInex);
boolean result = false;
if ((0 != (data[dInex] & PROVISION_STATUS_SE_LOCKED))) {
if ((0 != (pStatus & PROVISION_STATUS_SE_LOCKED))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private boolean isSeFactoryProvisioningComplete() {
short dIndex = repository.allocReclaimableMemory((short)1);
short dIndex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dIndex);
short pStatus = Util.getShort(data, dIndex);
boolean result = false;
if ((0 != (data[dIndex] & INS_PROVISION_RKP_DEVICE_UNIQUE_KEYPAIR_CMD))
&& (0 != ((data[dIndex] & INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD)))) {
result = true;
if ((0 != (pStatus & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != ((pStatus & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN)))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private void processOEMUnlockProvisionCmd(APDU apdu) {
handleOEMLockUnlockCmd(OEM_UNLOCK_PROVISION_VERIFICATION_LABEL, apdu);
authenticateOEM(OEM_UNLOCK_PROVISION_VERIFICATION_LABEL, apdu);
kmDataStore.setProvisionLock(false);
kmDataStore.unlockProvision(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
}

private void processOEMLockProvisionCmd(APDU apdu) {
handleOEMLockUnlockCmd(OEM_LOCK_PROVISION_VERIFICATION_LABEL, apdu);
authenticateOEM(OEM_LOCK_PROVISION_VERIFICATION_LABEL, apdu);
// Enable the lock bit in provision status.
kmDataStore.setProvisionLock(true);
kmDataStore.setProvisionStatus(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
}

private void handleOEMLockUnlockCmd(byte[] plainMsg, APDU apdu) {
private void authenticateOEM(byte[] plainMsg, APDU apdu) {

tmpVariables[0] = KMArray.instance((short) 1);
KMArray.cast(tmpVariables[0]).add((short) 0, KMByteBlob.exp());
Expand DownExpand Up@@ -519,7 +508,7 @@ private void processGetProvisionStatusCmd(APDU apdu) {
kmDataStore.getProvisionStatus(scratchpad, (short) 0);
short resp = KMArray.instance((short) 2);
KMArray.cast(resp).add((short) 0, buildErrorStatus(KMError.OK));
KMArray.cast(resp).add((short) 1, KMInteger.uint_8(scratchpad[0]));
KMArray.cast(resp).add((short) 1, KMInteger.instance(scratchpad, (short)0, (short)2));
sendOutgoing(apdu, resp);
}

Expand DownExpand Up@@ -586,53 +575,30 @@ private void processSetBootParamsCmd(APDU apdu) {
enumVal = KMEnum.cast(bootParam).getVal();
kmDataStore.setDeviceLocked(enumVal == KMType.DEVICE_LOCKED_TRUE);


// Clear the Computed SharedHmac and Hmac nonce from persistent memory.
Util.arrayFillNonAtomic(scratchPad, (short) 0, KMKeymintDataStore.COMPUTED_HMAC_KEY_SIZE, (byte) 0);
kmDataStore.createComputedHmacKey(scratchPad, (short) 0, KMKeymintDataStore.COMPUTED_HMAC_KEY_SIZE);

super.reboot();
sendError(apdu, KMError.OK);
}

private boolean isProvisioningComplete() {
short dInex = repository.allocReclaimableMemory((short)1);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
boolean result = false;
if (kmDataStore.isProvisionLocked() || ((0 != (data[dInex] & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != (data[dInex] & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN))
&& (0 != (data[dInex] & PROVISION_STATUS_PRESHARED_SECRET))
&& (0 != (data[dInex] & PROVISION_STATUS_ATTEST_IDS)))) {
result = true;
}
repository.reclaimMemory((short)1);
return result;
}

private boolean isOemProvisionComplete() {
short dInex = repository.allocReclaimableMemory((short)1);
byte data[] = repository.getHeap();
short dInex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
short pStatus = Util.getShort(data, dInex);
boolean result = false;
if ((0 != (data[dInex] & PROVISION_STATUS_OEM_PUBLIC_KEY))
&& (0 != (data[dInex] & PROVISION_STATUS_SE_LOCKED))) {
if (kmDataStore.isProvisionLocked() || ((0 != (pStatus & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != (pStatus & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN))
&& (0 != (pStatus & PROVISION_STATUS_PRESHARED_SECRET))
&& (0 != (pStatus & PROVISION_STATUS_ATTEST_IDS)))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private void processLockProvisioningCmd(APDU apdu) {
if (isProvisioningComplete()) {
kmDataStore.setProvisionLocked();
kmDataStore.setProvisionStatus(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
} else {
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
}
}

@Override
public void onCleanup() {
}
Expand DownExpand Up@@ -704,5 +670,5 @@ private short validateApdu(APDU apdu) {
}
return apduBuffer[ISO7816.OFFSET_INS];
}
}

}
Original file line numberDiff line numberDiff line change
Expand Up@@ -698,7 +698,6 @@ KMDeviceUniqueKeyPair createRkpDeviceUniqueKeyPair(KMDeviceUniqueKeyPair key,
short messageDigest256(byte[] inBuff, short inOffset, short inLength, byte[] outBuff,
short outOffset);


/**
* This function generates a HMAC key from the provided key buffers.
*
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,17 +54,17 @@ public class KMJCardSimApplet extends KMKeymasterApplet {
public static final byte BOOT_HASH_MAX_SIZE = 32;

// Provision reporting status
private static final byte NOT_PROVISIONED = 0x00;
private static final byte PROVISION_STATUS_ATTESTATION_KEY = 0x01; // unused in keymint
private static final byte PROVISION_STATUS_ATTESTATION_CERT_CHAIN = 0x02; // unused in keymint
private static final byte PROVISION_STATUS_ATTESTATION_CERT_PARAMS = 0x04; // unused in keymint
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_KEYPAIR = 0x40;
private static final byte PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = (byte) 0x80;
private static final byte PROVISION_STATUS_SE_LOCKED = 0x01;
private static final byte PROVISION_STATUS_OEM_PUBLIC_KEY = 0x02;
private static final short NOT_PROVISIONED = 0x0000;
private static final short PROVISION_STATUS_ATTESTATION_KEY = 0x0001;
private static final short PROVISION_STATUS_ATTESTATION_CERT_CHAIN = 0x0002;
private static final short PROVISION_STATUS_ATTESTATION_CERT_PARAMS = 0x0004;
private static final short PROVISION_STATUS_ATTEST_IDS = 0x0008;
private static final short PROVISION_STATUS_PRESHARED_SECRET = 0x0010;
private static final short PROVISION_STATUS_PROVISIONING_LOCKED = 0x0020;
private static final short PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR = 0x0040;
private static final short PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = 0x0080;
private static final short PROVISION_STATUS_SE_LOCKED = 0x0100;
private static final short PROVISION_STATUS_OEM_PUBLIC_KEY = 0x0200;

public static final short SHARED_SECRET_KEY_SIZE = 32;

Expand DownExpand Up@@ -194,7 +194,7 @@ private boolean isCommandAllowed(short apduIns) {
break;

case INS_SE_FACTORY_PROVISIONING_LOCK_CMD:
if(!isSeFactoryProvisioningComplete()) {
if(isSeFactoryProvisioningLocked() || !isSeFactoryProvisioningComplete()) {
result = false;
}
break;
Expand All@@ -204,7 +204,7 @@ private boolean isCommandAllowed(short apduIns) {
// 1. All the necessary provisioning commands are succcessfully executed
// 2. SE provision is locked
// 3. OEM Root Public is provisioned.
if (!(isProvisioningComplete() && isSeFactoryProvisioningLocked())) {
if (kmDataStore.isProvisionLocked() || !(isProvisioningComplete() && isSeFactoryProvisioningLocked())) {
result = false;
}
break;
Expand All@@ -231,44 +231,48 @@ private boolean isCommandAllowed(short apduIns) {
}

private boolean isSeFactoryProvisioningLocked() {
short dInex = repository.allocReclaimableMemory((short)1);
short dInex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
short pStatus = Util.getShort(data, dInex);
boolean result = false;
if ((0 != (data[dInex] & PROVISION_STATUS_SE_LOCKED))) {
if ((0 != (pStatus & PROVISION_STATUS_SE_LOCKED))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private boolean isSeFactoryProvisioningComplete() {
short dIndex = repository.allocReclaimableMemory((short)1);
short dIndex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dIndex);
short pStatus = Util.getShort(data, dIndex);
boolean result = false;
if ((0 != (data[dIndex] & INS_PROVISION_RKP_DEVICE_UNIQUE_KEYPAIR_CMD))
&& (0 != ((data[dIndex] & INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD)))) {
result = true;
if ((0 != (pStatus & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != ((pStatus & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN)))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private void processOEMUnlockProvisionCmd(APDU apdu) {
handleOEMLockUnlockCmd(OEM_UNLOCK_PROVISION_VERIFICATION_LABEL, apdu);
authenticateOEM(OEM_UNLOCK_PROVISION_VERIFICATION_LABEL, apdu);
kmDataStore.setProvisionLock(false);
kmDataStore.unlockProvision(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
}

private void processOEMLockProvisionCmd(APDU apdu) {
handleOEMLockUnlockCmd(OEM_LOCK_PROVISION_VERIFICATION_LABEL, apdu);
authenticateOEM(OEM_LOCK_PROVISION_VERIFICATION_LABEL, apdu);
// Enable the lock bit in provision status.
kmDataStore.setProvisionLock(true);
kmDataStore.setProvisionStatus(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
}

private void handleOEMLockUnlockCmd(byte[] plainMsg, APDU apdu) {
private void authenticateOEM(byte[] plainMsg, APDU apdu) {

tmpVariables[0] = KMArray.instance((short) 1);
KMArray.cast(tmpVariables[0]).add((short) 0, KMByteBlob.exp());
Expand DownExpand Up@@ -507,7 +511,7 @@ private void processGetProvisionStatusCmd(APDU apdu) {
kmDataStore.getProvisionStatus(scratchpad, (short) 0);
short resp = KMArray.instance((short) 2);
KMArray.cast(resp).add((short) 0, buildErrorStatus(KMError.OK));
KMArray.cast(resp).add((short) 1, KMInteger.uint_8(scratchpad[0]));
KMArray.cast(resp).add((short) 1, KMInteger.instance(scratchpad, (short)0, (short)2));
sendOutgoing(apdu, resp);
}

Expand DownExpand Up@@ -583,43 +587,21 @@ private void processSetBootParamsCmd(APDU apdu) {
}

private boolean isProvisioningComplete() {
short dInex = repository.allocReclaimableMemory((short)1);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
boolean result = false;
if (kmDataStore.isProvisionLocked() || ((0 != (data[dInex] & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != (data[dInex] & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN))
&& (0 != (data[dInex] & PROVISION_STATUS_PRESHARED_SECRET))
&& (0 != (data[dInex] & PROVISION_STATUS_ATTEST_IDS)))) {
result = true;
}
repository.reclaimMemory((short)1);
return result;
}

private boolean isOemProvisionComplete() {
short dInex = repository.allocReclaimableMemory((short)1);
short dInex = repository.allocReclaimableMemory((short)2);
byte data[] = repository.getHeap();
kmDataStore.getProvisionStatus(data, dInex);
short pStatus = Util.getShort(data, dInex);
boolean result = false;
if ((0 != (data[dInex] & PROVISION_STATUS_OEM_PUBLIC_KEY))
&& (0 != (data[dInex] & PROVISION_STATUS_SE_LOCKED))) {
if (kmDataStore.isProvisionLocked() || ((0 != (pStatus & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR))
&& (0 != (pStatus & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN))
&& (0 != (pStatus & PROVISION_STATUS_PRESHARED_SECRET))
&& (0 != (pStatus & PROVISION_STATUS_ATTEST_IDS)))) {
result = true;
}
repository.reclaimMemory((short)1);
repository.reclaimMemory((short)2);
return result;
}

private void processLockProvisioningCmd(APDU apdu) {
if (isProvisioningComplete()) {
kmDataStore.setProvisionLocked();
kmDataStore.setProvisionStatus(PROVISION_STATUS_PROVISIONING_LOCKED);
sendError(apdu, KMError.OK);
} else {
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
}
}

private short validateApdu(APDU apdu) {
// Read the apdu header and buffer.
byte[] apduBuffer = apdu.getBuffer();
Expand Down
13 changes: 13 additions & 0 deletions Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,19 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe
// Minimum HMAC length in bits
public static final short MIN_HMAC_LENGTH_BITS = 64;

// Provision reporting status
public static final short NOT_PROVISIONED = 0x0000;
public static final short PROVISION_STATUS_ATTESTATION_KEY = 0x0001;
public static final short PROVISION_STATUS_ATTESTATION_CERT_CHAIN = 0x0002;
public static final short PROVISION_STATUS_ATTESTATION_CERT_PARAMS = 0x0004;
public static final short PROVISION_STATUS_ATTEST_IDS = 0x0008;
public static final short PROVISION_STATUS_PRESHARED_SECRET = 0x0010;
public static final short PROVISION_STATUS_PROVISIONING_LOCKED = 0x0020;
public static final short PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR = 0x0040;
public static final short PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = 0x0080;
public static final short PROVISION_STATUS_SE_LOCKED = 0x0100;
public static final short PROVISION_STATUS_OEM_PUBLIC_KEY = 0x0200;

protected static RemotelyProvisionedComponentDevice rkp;
protected static KMEncoder encoder;
protected static KMDecoder decoder;
Expand Down
Loading