Log keystore key attestation events using statsd. am: 9d2bd25cbd

Original change: https://googleplex-android-review.googlesource.com/c/platform/system/security/+/11972698

Change-Id: I5cc2032a293a28fd6e10728ac9e908aea02624c3
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/identity/Util.cpp b/identity/Util.cpp
index a962dc3..cd29017 100644
--- a/identity/Util.cpp
+++ b/identity/Util.cpp
@@ -110,7 +110,7 @@
         remaining -= numWritten;
     }
 
-    if (TEMP_FAILURE_RETRY(fsync(fd) == -1)) {
+    if (TEMP_FAILURE_RETRY(fsync(fd))) {
         PLOG(ERROR) << "Failed fsyncing temp file for '" << path << "'";
         close(fd);
         return false;
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 1b38643..4e5bc48 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -1001,21 +1001,102 @@
     return Status::ok();
 }
 
+bool isDeviceIdAttestationTag(Tag tag) {
+    switch (tag) {
+    case Tag::ATTESTATION_ID_BRAND:
+    case Tag::ATTESTATION_ID_DEVICE:
+    case Tag::ATTESTATION_ID_MANUFACTURER:
+    case Tag::ATTESTATION_ID_MODEL:
+    case Tag::ATTESTATION_ID_PRODUCT:
+    case Tag::ATTESTATION_ID_IMEI:
+    case Tag::ATTESTATION_ID_MEID:
+    case Tag::ATTESTATION_ID_SERIAL:
+        return true;
+    case Tag::INVALID:
+    case Tag::PURPOSE:
+    case Tag::ALGORITHM:
+    case Tag::KEY_SIZE:
+    case Tag::BLOCK_MODE:
+    case Tag::DIGEST:
+    case Tag::PADDING:
+    case Tag::CALLER_NONCE:
+    case Tag::MIN_MAC_LENGTH:
+    case Tag::EC_CURVE:
+    case Tag::RSA_PUBLIC_EXPONENT:
+    case Tag::INCLUDE_UNIQUE_ID:
+    case Tag::BLOB_USAGE_REQUIREMENTS:
+    case Tag::BOOTLOADER_ONLY:
+    case Tag::ROLLBACK_RESISTANCE:
+    case Tag::HARDWARE_TYPE:
+    case Tag::ACTIVE_DATETIME:
+    case Tag::ORIGINATION_EXPIRE_DATETIME:
+    case Tag::USAGE_EXPIRE_DATETIME:
+    case Tag::MIN_SECONDS_BETWEEN_OPS:
+    case Tag::MAX_USES_PER_BOOT:
+    case Tag::USER_ID:
+    case Tag::USER_SECURE_ID:
+    case Tag::NO_AUTH_REQUIRED:
+    case Tag::USER_AUTH_TYPE:
+    case Tag::AUTH_TIMEOUT:
+    case Tag::ALLOW_WHILE_ON_BODY:
+    case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
+    case Tag::TRUSTED_CONFIRMATION_REQUIRED:
+    case Tag::UNLOCKED_DEVICE_REQUIRED:
+    case Tag::APPLICATION_ID:
+    case Tag::APPLICATION_DATA:
+    case Tag::CREATION_DATETIME:
+    case Tag::ORIGIN:
+    case Tag::ROOT_OF_TRUST:
+    case Tag::OS_VERSION:
+    case Tag::OS_PATCHLEVEL:
+    case Tag::UNIQUE_ID:
+    case Tag::ATTESTATION_CHALLENGE:
+    case Tag::ATTESTATION_APPLICATION_ID:
+    case Tag::VENDOR_PATCHLEVEL:
+    case Tag::BOOT_PATCHLEVEL:
+    case Tag::ASSOCIATED_DATA:
+    case Tag::NONCE:
+    case Tag::MAC_LENGTH:
+    case Tag::RESET_SINCE_ID_ROTATION:
+    case Tag::CONFIRMATION_TOKEN:
+        return false;
+        // no default, all values must be present in the switch, in this way the compiler ensures
+        // that new values added in the Tag enum are also added here.
+    }
+}
+
+// These are attestation id tags that are not unique per device and don't require special permission
+// to be attested. Any addition to this list needs privacy review and approval (PWG).
+bool isDevicePropertyAttestationTag(Tag tag) {
+    switch (tag) {
+    case Tag::ATTESTATION_ID_BRAND:
+    case Tag::ATTESTATION_ID_DEVICE:
+    case Tag::ATTESTATION_ID_MANUFACTURER:
+    case Tag::ATTESTATION_ID_MODEL:
+    case Tag::ATTESTATION_ID_PRODUCT:
+        return true;
+    default:
+        return false;
+    }
+}
+
 bool isDeviceIdAttestationRequested(const KeymasterArguments& params) {
     const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
     for (size_t i = 0; i < paramsVec.size(); ++i) {
-        switch (paramsVec[i].tag) {
-        case Tag::ATTESTATION_ID_BRAND:
-        case Tag::ATTESTATION_ID_DEVICE:
-        case Tag::ATTESTATION_ID_MANUFACTURER:
-        case Tag::ATTESTATION_ID_MODEL:
-        case Tag::ATTESTATION_ID_PRODUCT:
-        case Tag::ATTESTATION_ID_IMEI:
-        case Tag::ATTESTATION_ID_MEID:
-        case Tag::ATTESTATION_ID_SERIAL:
+        if (isDeviceIdAttestationTag(paramsVec[i].tag)) {
             return true;
-        default:
-            continue;
+        }
+    }
+    return false;
+}
+
+// Device properties can be attested safely without special permission
+bool needsPermissionToAttestDeviceIds(const KeymasterArguments& params) {
+    const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
+    for (size_t i = 0; i < paramsVec.size(); ++i) {
+        if (isDeviceIdAttestationTag(paramsVec[i].tag) &&
+            !isDevicePropertyAttestationTag(paramsVec[i].tag)) {
+            return true;
         }
     }
     return false;
@@ -1031,7 +1112,7 @@
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
 
-    if (isDeviceIdAttestationRequested(params) && (get_app_id(callingUid) != AID_SYSTEM)) {
+    if (needsPermissionToAttestDeviceIds(params) && (get_app_id(callingUid) != AID_SYSTEM)) {
         return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
     }
 
@@ -1106,14 +1187,19 @@
     }
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
-    if (binder == nullptr) {
-        return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
-    }
-    if (!interface_cast<IPermissionController>(binder)->checkPermission(
-            String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
-            IPCThreadState::self()->getCallingPid(), callingUid)) {
-        return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
+
+    // Request special permission only for unique ids
+    if (needsPermissionToAttestDeviceIds(params)) {
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+        if (binder == nullptr) {
+            return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
+        }
+
+        if (!interface_cast<IPermissionController>(binder)->checkPermission(
+                String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
+                IPCThreadState::self()->getCallingPid(), callingUid)) {
+            return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
+        }
     }
 
     AuthorizationSet mutableParams = params.getParameters();