Merge "Verify Device ID attestation data in key management test."
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index bdb5d3b..4e878c5 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -29,6 +29,8 @@
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <!-- Needed to read the serial number during Device ID attestation tests -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 
     <application
         android:testOnly="true">
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
index 4050f69..bd51d86 100755
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
@@ -24,7 +24,9 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.keystore.cts.Attestation;
+import android.keystore.cts.AuthorizationList;
 import android.net.Uri;
+import android.os.Build;
 import android.security.AttestedKeyPair;
 import android.security.KeyChain;
 import android.security.KeyChainAliasCallback;
@@ -312,6 +314,22 @@
         }
     }
 
+    private void validateDeviceIdAttestationData(Certificate leaf,
+            String expectedSerial, String expectedImei, String expectedMeid)
+            throws CertificateParsingException {
+        Attestation attestationRecord = new Attestation((X509Certificate) leaf);
+        AuthorizationList teeAttestation = attestationRecord.getTeeEnforced();
+        assertNotNull(teeAttestation);
+        assertEquals(Build.BRAND, teeAttestation.getBrand());
+        assertEquals(Build.DEVICE, teeAttestation.getDevice());
+        assertEquals(Build.PRODUCT, teeAttestation.getProduct());
+        assertEquals(Build.MANUFACTURER, teeAttestation.getManufacturer());
+        assertEquals(Build.MODEL, teeAttestation.getModel());
+        assertEquals(expectedSerial, teeAttestation.getSerialNumber());
+        assertEquals(expectedImei, teeAttestation.getImei());
+        assertEquals(expectedMeid, teeAttestation.getMeid());
+    }
+
     private void validateAttestationRecord(List<Certificate> attestation,
             byte[] providedChallenge) throws CertificateParsingException {
         assertNotNull(attestation);
@@ -385,6 +403,7 @@
             verifySignatureOverData("SHA256withECDSA", keyPair);
             List<Certificate> attestation = generated.getAttestationRecord();
             validateAttestationRecord(attestation, attestationChallenge);
+            validateDeviceIdAttestationData(attestation.get(0), Build.getSerial(), null, null);
             validateSignatureChain(attestation, keyPair.getPublic());
         } finally {
             assertTrue(mDevicePolicyManager.removeKeyPair(getWho(), alias));
diff --git a/tests/security/src/android/keystore/cts/AuthorizationList.java b/tests/security/src/android/keystore/cts/AuthorizationList.java
index d488b26..460bbf7 100644
--- a/tests/security/src/android/keystore/cts/AuthorizationList.java
+++ b/tests/security/src/android/keystore/cts/AuthorizationList.java
@@ -35,6 +35,7 @@
 import com.android.org.bouncycastle.asn1.ASN1InputStream;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.security.cert.CertificateParsingException;
 import java.text.DateFormat;
 import java.util.Collection;
@@ -120,6 +121,14 @@
     private static final int KM_TAG_OS_VERSION = KM_UINT | 705;
     private static final int KM_TAG_OS_PATCHLEVEL = KM_UINT | 706;
     private static final int KM_TAG_ATTESTATION_APPLICATION_ID = KM_BYTES | 709;
+    private static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710;
+    private static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711;
+    private static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712;
+    private static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713;
+    private static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714;
+    private static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715;
+    private static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716;
+    private static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717;
 
     // Map for converting padding values to strings
     private static final ImmutableMap<Integer, String> paddingMap = ImmutableMap
@@ -175,6 +184,14 @@
     private Integer osVersion;
     private Integer osPatchLevel;
     private AttestationApplicationId attestationApplicationId;
+    private String brand;
+    private String device;
+    private String serialNumber;
+    private String imei;
+    private String meid;
+    private String product;
+    private String manufacturer;
+    private String model;
 
     public AuthorizationList(ASN1Encodable sequence) throws CertificateParsingException {
         if (!(sequence instanceof ASN1Sequence)) {
@@ -260,6 +277,30 @@
                     attestationApplicationId = new AttestationApplicationId(Asn1Utils
                             .getAsn1EncodableFromBytes(Asn1Utils.getByteArrayFromAsn1(value)));
                     break;
+                case KM_TAG_ATTESTATION_ID_BRAND & KEYMASTER_TAG_TYPE_MASK:
+                    brand = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_DEVICE & KEYMASTER_TAG_TYPE_MASK:
+                    device = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_PRODUCT & KEYMASTER_TAG_TYPE_MASK:
+                    product = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_SERIAL & KEYMASTER_TAG_TYPE_MASK:
+                    serialNumber = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_IMEI & KEYMASTER_TAG_TYPE_MASK:
+                    imei = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_MEID & KEYMASTER_TAG_TYPE_MASK:
+                    meid = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_MANUFACTURER & KEYMASTER_TAG_TYPE_MASK:
+                    manufacturer = getStringFromAsn1Value(value);
+                    break;
+                case KM_TAG_ATTESTATION_ID_MODEL & KEYMASTER_TAG_TYPE_MASK:
+                    model = getStringFromAsn1Value(value);
+                    break;
                 case KM_TAG_ALL_APPLICATIONS & KEYMASTER_TAG_TYPE_MASK:
                     allApplications = true;
                     break;
@@ -492,6 +533,46 @@
         return attestationApplicationId;
     }
 
+    public String getBrand() {
+        return brand;
+    }
+
+    public String getDevice() {
+        return device;
+    }
+
+    public String getSerialNumber() {
+        return serialNumber;
+    };
+
+    public String getImei() {
+        return imei;
+    };
+
+    public String getMeid() {
+        return meid;
+    };
+
+    public String getProduct() {
+        return product;
+    };
+
+    public String getManufacturer() {
+        return manufacturer;
+    };
+
+    public String getModel() {
+        return model;
+    };
+
+    private String getStringFromAsn1Value(ASN1Primitive value) throws CertificateParsingException {
+        try {
+            return Asn1Utils.getStringFromAsn1OctetStreamAssumingUTF8(value);
+        } catch (UnsupportedEncodingException e) {
+            throw new CertificateParsingException("Error parsing ASN.1 value", e);
+        }
+    }
+
     @Override
     public String toString() {
         StringBuilder s = new StringBuilder();
@@ -576,6 +657,13 @@
         if (attestationApplicationId != null) {
             s.append("\nAttestation Application Id:").append(attestationApplicationId);
         }
+
+        if (brand != null) {
+            s.append("\nBrand: ").append(brand);
+        }
+        if (device != null) {
+            s.append("\nDevice type: ").append(device);
+        }
         return s.toString();
     }
 }