diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 1e3eae79..8abbd04e 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -84,8 +84,8 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static final byte keyUsageKeyEncipher = (byte) 0x20; // 2nd- bit private static final byte keyUsageDataEncipher = (byte) 0x10; // 3rd- bit - private static final byte KEYMASTER_VERSION = 4; - private static final byte ATTESTATION_VERSION = 3; + private static final byte KEYMASTER_VERSION = 41; + private static final byte ATTESTATION_VERSION = 4; private static final byte[] pubExponent = {0x01, 0x00, 0x01}; private static final byte SERIAL_NUM = (byte) 0x01; private static final byte X509_VERSION = (byte) 0x02; @@ -462,14 +462,16 @@ private static void pushHWParams() { // Below are the allowed hardwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, + KMType.ATTESTATION_ID_MODEL, KMType.ATTESTATION_ID_MANUFACTURER, + KMType.ATTESTATION_ID_MEID, KMType.ATTESTATION_ID_IMEI, + KMType.ATTESTATION_ID_SERIAL, KMType.ATTESTATION_ID_PRODUCT, + KMType.ATTESTATION_ID_DEVICE, KMType.ATTESTATION_ID_BRAND, KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.APPLICATION_ID, - KMType.TRUSTED_CONFIRMATION_REQUIRED, - KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, - KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, - KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, - KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, - KMType.ALGORITHM, KMType.PURPOSE}; + KMType.ORIGIN, KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, + KMType.NO_AUTH_REQUIRED, KMType.USER_SECURE_ID, + KMType.RSA_PUBLIC_EXPONENT, KMType.ECCURVE, KMType.MIN_MAC_LENGTH, + KMType.CALLER_NONCE, KMType.PADDING, KMType.DIGEST, KMType.BLOCK_MODE, + KMType.KEYSIZE, KMType.ALGORITHM, KMType.PURPOSE}; byte index = 0; do { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 37e67d1c..1f242f38 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -78,8 +78,8 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static final byte keyUsageKeyEncipher = (byte) 0x20; // 2nd- bit private static final byte keyUsageDataEncipher = (byte) 0x10; // 3rd- bit - private static final byte KEYMASTER_VERSION = 4; - private static final byte ATTESTATION_VERSION = 3; + private static final byte KEYMASTER_VERSION = 41; + private static final byte ATTESTATION_VERSION = 4; private static final byte[] pubExponent = {0x01, 0x00, 0x01}; private static final byte SERIAL_NUM = (byte) 0x01; private static final byte X509_VERSION = (byte) 0x02; @@ -456,14 +456,16 @@ private static void pushHWParams() { // Below are the allowed hardwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, + KMType.ATTESTATION_ID_MODEL, KMType.ATTESTATION_ID_MANUFACTURER, + KMType.ATTESTATION_ID_MEID, KMType.ATTESTATION_ID_IMEI, + KMType.ATTESTATION_ID_SERIAL, KMType.ATTESTATION_ID_PRODUCT, + KMType.ATTESTATION_ID_DEVICE, KMType.ATTESTATION_ID_BRAND, KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.APPLICATION_ID, - KMType.TRUSTED_CONFIRMATION_REQUIRED, - KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, - KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, - KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, - KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, - KMType.ALGORITHM, KMType.PURPOSE}; + KMType.ORIGIN, KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, + KMType.NO_AUTH_REQUIRED, KMType.USER_SECURE_ID, + KMType.RSA_PUBLIC_EXPONENT, KMType.ECCURVE, KMType.MIN_MAC_LENGTH, + KMType.CALLER_NONCE, KMType.PADDING, KMType.DIGEST, KMType.BLOCK_MODE, + KMType.KEYSIZE, KMType.ALGORITHM, KMType.PURPOSE}; byte index = 0; do { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 6566dd55..0949177f 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1442,6 +1442,8 @@ private void processAttestKeyCmd(APDU apdu) { rsaCert = false; } KMAttestationCert cert = seProvider.getAttestationCert(rsaCert); + // Validate and add attestation ids. + addAttestationIds(cert); // Save attestation application id - must be present. tmpVariables[0] = KMKeyParameters.findTag( @@ -1485,7 +1487,6 @@ private void processAttestKeyCmd(APDU apdu) { KMKeyParameters.findTag(KMType.DATE_TAG, KMType.USAGE_EXPIRE_DATETIME, data[SW_PARAMETERS]); cert.notAfter(tmpVariables[2], repository.getCertExpiryTime(), scratchPad, (short) 0); - addAttestationIds(cert); addTags(KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getHardwareEnforced(), true, cert); addTags( KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getSoftwareEnforced(), false, cert); @@ -1512,7 +1513,25 @@ private void processAttestKeyCmd(APDU apdu) { sendOutgoing(apdu); } + private boolean isEmpty(byte[] buf, short offset, short len) { + boolean empty = true; + short index = 0; + while (index < len) { + if (buf[index] != 0) { + empty = false; + break; + } + index++; + } + return empty; + } + // -------------------------------- + // Only add the Attestation ids which are requested in the attestation parameters. + // If the requested attestation ids are not provisioned or deleted then + // throw CANNOT_ATTEST_IDS error. If there is mismatch in the attestation + // id values of both the requested parameters and the provisioned parameters + // then throw INVALID_TAG error. private void addAttestationIds(KMAttestationCert cert) { final short[] attTags = new short[]{ @@ -1527,10 +1546,30 @@ private void addAttestationIds(KMAttestationCert cert) { }; byte index = 0; short attIdTag; + short attIdTagValue; + short storedAttId; while (index < (short) attTags.length) { - attIdTag = repository.getAttId(mapToAttId(attTags[index])); - if (attIdTag != 0) { - attIdTag = KMByteTag.instance(attTags[index], attIdTag); + attIdTag = KMKeyParameters.findTag(KMType.BYTES_TAG, attTags[index], data[KEY_PARAMETERS]); + if (attIdTag != KMType.INVALID_VALUE) { + attIdTagValue = KMByteTag.cast(attIdTag).getValue(); + storedAttId = repository.getAttId(mapToAttId(attTags[index])); + // Return CANNOT_ATTEST_IDS if Attestation IDs are not provisioned or + // Attestation IDs are deleted. + if (storedAttId == 0 || + isEmpty(KMByteBlob.cast(storedAttId).getBuffer(), + KMByteBlob.cast(storedAttId).getStartOff(), + KMByteBlob.cast(storedAttId).length())) { + KMException.throwIt(KMError.CANNOT_ATTEST_IDS); + } + // Return INVALID_TAG if Attestation IDs does not match. + if ((KMByteBlob.cast(storedAttId).length() != KMByteBlob.cast(attIdTagValue).length()) || + (0 != Util.arrayCompare(KMByteBlob.cast(storedAttId).getBuffer(), + KMByteBlob.cast(storedAttId).getStartOff(), + KMByteBlob.cast(attIdTagValue).getBuffer(), + KMByteBlob.cast(attIdTagValue).getStartOff(), + KMByteBlob.cast(storedAttId).length()))) { + KMException.throwIt(KMError.INVALID_TAG); + } cert.extensionTag(attIdTag, true); } index++; diff --git a/ProvisioningTool/README.md b/ProvisioningTool/README.md index 0eeb4f8d..9d65e5d1 100644 --- a/ProvisioningTool/README.md +++ b/ProvisioningTool/README.md @@ -9,11 +9,13 @@ This tool can be built along with aosp build. It has dependency on [libjc_provision](Android.bp). #### Sample resources for quick testing -A sample json file is located in this directory with name [sample_json.txt](sample_json.txt) -for your reference. Also the required certificates and keys can be found -in [test_resources](test_resources) directory. Copy the certificates and the key into the -emulator/device filesystem in their respective paths mentioned in the -sample_json.txt. +Two sample json files are located in this directory with names +[sample_json_cf.txt](sample_json_cf.txt) and and [sample_json_gf.txt](sample_json_gf.txt) +for your reference. Use sample_json_cf.txt for cuttlefish target and use +sample_json_gf.txt for goldfish target. Also the required certificates and +keys can be found in [test_resources](test_resources) directory. Copy the +certificates and the key into the emulator/device filesystem in their respective +paths mentioned in the sample json file. #### Usage
diff --git a/ProvisioningTool/sample_json_cf.txt b/ProvisioningTool/sample_json_cf.txt
new file mode 100644
index 00000000..fd79e227
--- /dev/null
+++ b/ProvisioningTool/sample_json_cf.txt
@@ -0,0 +1,26 @@
+{
+   "attest_ids": {
+      "brand": "generic",
+      "device": "vsoc_x86_64",
+      "product": "aosp_cf_x86_64_phone",
+      "serial": "",
+      "imei": "000000000000000",
+      "meid": "000000000000000",
+      "manufacturer": "Google",
+      "model": "Cuttlefish x86_64 phone"
+   },
+   "shared_secret": "0000000000000000000000000000000000000000000000000000000000000000",
+   "set_boot_params": {
+      "boot_patch_level": 0,
+      "verified_boot_key": "0000000000000000000000000000000000000000000000000000000000000000",
+      "verified_boot_key_hash": "0000000000000000000000000000000000000000000000000000000000000000",
+      "boot_state": 2,
+      "device_locked": 1
+   },
+   "attest_key": "/data/vendor/batch_key.der",
+   "attest_cert_chain": [
+   "/data/vendor/batch_cert.der",
+   "/data/vendor/intermediate_cert.der",
+   "/data/vendor/ca_cert.der"
+   ]
+}
diff --git a/ProvisioningTool/sample_json.txt b/ProvisioningTool/sample_json_gf.txt
similarity index 68%
rename from ProvisioningTool/sample_json.txt
rename to ProvisioningTool/sample_json_gf.txt
index 7885b2aa..7825e693 100644
--- a/ProvisioningTool/sample_json.txt
+++ b/ProvisioningTool/sample_json_gf.txt
@@ -1,13 +1,13 @@
 {
    "attest_ids": {
-      "brand": "Google",
-      "device": "Pixel 3A",
-      "product": "Pixel",
-      "serial": "UGYJFDjFeRuBEH",
-      "imei": "987080543071019",
-      "meid": "27863510227963",
-      "manufacturer": "Foxconn",
-      "model": "HD1121"
+      "brand": "Android",
+      "device": "generic_x86_64",
+      "product": "aosp_x86_64",
+      "serial": "",
+      "imei": "000000000000000",
+      "meid": "000000000000000",
+      "manufacturer": "unknown",
+      "model": "AOSP on x86_64"
    },
    "shared_secret": "0000000000000000000000000000000000000000000000000000000000000000",
    "set_boot_params": {
@@ -15,7 +15,7 @@
       "verified_boot_key": "0000000000000000000000000000000000000000000000000000000000000000",
       "verified_boot_key_hash": "0000000000000000000000000000000000000000000000000000000000000000",
       "boot_state": 2,
-      "device_locked": 0
+      "device_locked": 1
    },
    "attest_key": "/data/vendor/batch_key.der",
    "attest_cert_chain": [