• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019, The Android Open Source Project, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *   http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.google.android.attestation;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 
21 import com.google.android.attestation.AuthorizationList.UserAuthType;
22 import com.google.android.attestation.ParsedAttestationRecord.SecurityLevel;
23 import java.io.ByteArrayInputStream;
24 import java.io.IOException;
25 import java.security.cert.CertificateException;
26 import java.security.cert.CertificateFactory;
27 import java.security.cert.X509Certificate;
28 import java.util.Set;
29 import org.bouncycastle.asn1.ASN1Sequence;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.JUnit4;
33 
34 /** Test for {@link ParsedAttestationRecord}. */
35 @RunWith(JUnit4.class)
36 public class ParsedAttestationRecordTest {
37 
38   // Certificate generated by TestDPC with RSA Algorithm and StrongBox Security Level
39   private static final String CERT =
40       "-----BEGIN CERTIFICATE-----\n"
41           + "MIIGCDCCBHCgAwIBAgIBATANBgkqhkiG9w0BAQsFADApMRkwFwYDVQQFExAyZGM1OGIyZDFhMjQx"
42           + "MzI2MQwwCgYDVQQMDANURUUwIBcNNzAwMTAxMDAwMDAwWhgPMjEwNjAyMDcwNjI4MTVaMB8xHTAb"
43           + "BgNVBAMMFEFuZHJvaWQgS2V5c3RvcmUgS2V5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC"
44           + "AQEApNVcnyN40MANMbbo2nMGNq2NNysDSjfLm0W3i6wPKf0ffCYkhWM4dCmQKKf50uAZTBeTit4c"
45           + "NwXeZn3qellMlOsIN3Qc384rfN/8cikrRvUAgibz0Jy7STykjwa7x6tKwqITxbO8HqAhKo8/BQXU"
46           + "xzrOdIg5ciy+UM7Vgh7a7ogen0KL2iGgrsalb1ti7Vlzb6vIJ4WzIC3TGD2sCkoPahghwqFDZZCo"
47           + "/FzaLoNY0jAUX2mL+kf8aUaoxz7xA9FTvgara+1pLBR1s4c8xPS2HdZipcVXWfey0wujv1VAKs4+"
48           + "tXjKlHkYBHBBceEjxUtEmrapSQEdpHPv7Xh9Uanq4QIDAQABo4ICwTCCAr0wDgYDVR0PAQH/BAQD"
49           + "AgeAMIICqQYKKwYBBAHWeQIBEQSCApkwggKVAgEDCgEBAgEECgEBBANhYmMEADCCAc2/hT0IAgYB"
50           + "ZOYGEYe/hUWCAbsEggG3MIIBszGCAYswDAQHYW5kcm9pZAIBHTAZBBRjb20uYW5kcm9pZC5rZXlj"
51           + "aGFpbgIBHTAZBBRjb20uYW5kcm9pZC5zZXR0aW5ncwIBHTAZBBRjb20ucXRpLmRpYWdzZXJ2aWNl"
52           + "cwIBHTAaBBVjb20uYW5kcm9pZC5keW5zeXN0ZW0CAR0wHQQYY29tLmFuZHJvaWQuaW5wdXRkZXZp"
53           + "Y2VzAgEdMB8EGmNvbS5hbmRyb2lkLmxvY2FsdHJhbnNwb3J0AgEdMB8EGmNvbS5hbmRyb2lkLmxv"
54           + "Y2F0aW9uLmZ1c2VkAgEdMB8EGmNvbS5hbmRyb2lkLnNlcnZlci50ZWxlY29tAgEdMCAEG2NvbS5h"
55           + "bmRyb2lkLndhbGxwYXBlcmJhY2t1cAIBHTAhBBxjb20uZ29vZ2xlLlNTUmVzdGFydERldGVjdG9y"
56           + "AgEdMCIEHWNvbS5nb29nbGUuYW5kcm9pZC5oaWRkZW5tZW51AgEBMCMEHmNvbS5hbmRyb2lkLnBy"
57           + "b3ZpZGVycy5zZXR0aW5ncwIBHTEiBCAwGqPLCBE0UBxF8UIqvGbCQiT9Xe1f3I8X5pcXb9hmqjCB"
58           + "rqEIMQYCAQICAQOiAwIBAaMEAgIIAKUFMQMCAQSmCDEGAgEDAgEFv4FIBQIDAQABv4N3AgUAv4U+"
59           + "AwIBAL+FQEwwSgQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQAKAQIEIHKNsSdP"
60           + "HxzxVx3kOAsEilVKxKOA529TVQg1KQhKk3gBv4VBAwIBAL+FQgUCAwMUs7+FTgUCAwMUs7+FTwUC"
61           + "AwMUszANBgkqhkiG9w0BAQsFAAOCAYEAJMIuzdNUdfrE6sIdmsnMn/scSG2odbphj8FkX9JGdF2S"
62           + "OT599HuDY9qhvkru2Dza4sLKK3f4ViBhuR9lpfeprKvstxbtBO7jkLYfVn0ZRzHRHVEyiW5IVKh+"
63           + "qOXVJ9S1lMShOTlsaYJytLKIlcrRAZBEXZiNbzTuVh1CH6X9Ni1dog14snm+lcOeORdL9fht2CHa"
64           + "u/caRnpWiZbjoAoJp0O89uBrRkXPpln51+3jPY6AFny30grNAvKguauDcPPhNV1yR+ylSsQi2gm3"
65           + "Rs4pgtlxFLMfZLgT0cbkl+9zk/QUqlpBP8ftUBsOI0ARr8xhFN3cvq9kXGLtJ9hEP9PRaflAFREk"
66           + "DK3IBIbVcAFZBFoAQOdE9zy0+F5bQrznPGaZg4Dzhcx33qMDUTgHtWoy+k3ePGQMEtmoTTLgQywW"
67           + "OIkXEoFqqGi9GKJXUT1KYi5NsigaYqu7FoN4Qsvs61pMUEfZSPP2AFwkA8uNFbmb9uxcxaGHCA8i"
68           + "3i9VM6yOLIrP\n"
69           + "-----END CERTIFICATE-----";
70 
71   private static final int EXPECTED_ATTESTATION_VERSION = 3;
72   private static final SecurityLevel EXPECTED_ATTESTATION_SECURITY_LEVEL =
73       SecurityLevel.TRUSTED_ENVIRONMENT;
74   private static final int EXPECTED_KEYMASTER_VERSION = 4;
75   private static final SecurityLevel EXPECTED_KEYMASTER_SECURITY_LEVEL =
76       SecurityLevel.TRUSTED_ENVIRONMENT;
77   private static final byte[] EXPECTED_ATTESTATION_CHALLENGE = "abc".getBytes(UTF_8);
78   private static final byte[] EXPECTED_UNIQUE_ID = "".getBytes(UTF_8);
79 
getAttestationRecord(String certStr)80   private static X509Certificate getAttestationRecord(String certStr) throws CertificateException {
81     CertificateFactory factory = CertificateFactory.getInstance("X509");
82     X509Certificate cert =
83         (X509Certificate)
84             factory.generateCertificate(new ByteArrayInputStream(certStr.getBytes(UTF_8)));
85     cert.checkValidity();
86     return cert;
87   }
88 
89   @Test
testParseAttestationRecord()90   public void testParseAttestationRecord() throws CertificateException, IOException {
91     X509Certificate x509Certificate = getAttestationRecord(CERT);
92     ParsedAttestationRecord attestationRecord =
93         ParsedAttestationRecord.createParsedAttestationRecord(x509Certificate);
94 
95     assertThat(attestationRecord.attestationVersion).isEqualTo(EXPECTED_ATTESTATION_VERSION);
96     assertThat(attestationRecord.attestationSecurityLevel)
97         .isEqualTo(EXPECTED_ATTESTATION_SECURITY_LEVEL);
98     assertThat(attestationRecord.keymasterVersion).isEqualTo(EXPECTED_KEYMASTER_VERSION);
99     assertThat(attestationRecord.keymasterSecurityLevel)
100         .isEqualTo(EXPECTED_KEYMASTER_SECURITY_LEVEL);
101     assertThat(attestationRecord.attestationChallenge).isEqualTo(EXPECTED_ATTESTATION_CHALLENGE);
102     assertThat(attestationRecord.uniqueId).isEqualTo(EXPECTED_UNIQUE_ID);
103     assertThat(attestationRecord.softwareEnforced).isNotNull();
104     assertThat(attestationRecord.teeEnforced).isNotNull();
105   }
106 
107   @Test
testCreateAndParseAttestationRecord()108   public void testCreateAndParseAttestationRecord() {
109     AuthorizationList.Builder teeEnforcedBuilder = AuthorizationList.builder();
110     teeEnforcedBuilder.userAuthType = Set.of(UserAuthType.FINGERPRINT);
111     teeEnforcedBuilder.attestationIdBrand = "free food".getBytes(UTF_8);
112     ParsedAttestationRecord expected =
113         ParsedAttestationRecord.create(
114             /* attestationVersion= */ 2,
115             /* attestationSecurityLevel= */ SecurityLevel.TRUSTED_ENVIRONMENT,
116             /* keymasterVersion= */ 4,
117             /* keymasterSecurityLevel= */ SecurityLevel.SOFTWARE,
118             /* attestationChallenge= */ "abc".getBytes(UTF_8),
119             /* uniqueId= */ "foodplease".getBytes(UTF_8),
120             /* softwareEnforced= */ AuthorizationList.builder().build(),
121             /* teeEnforced= */ AuthorizationList.builder()
122                 .setUserAuthType(Set.of(UserAuthType.FINGERPRINT))
123                 .setAttestationIdBrand("free food".getBytes(UTF_8)).build());
124     ASN1Sequence seq = expected.toAsn1Sequence();
125     ParsedAttestationRecord actual = ParsedAttestationRecord.create(seq);
126     assertThat(actual.attestationVersion).isEqualTo(expected.attestationVersion);
127     assertThat(actual.attestationSecurityLevel).isEqualTo(expected.attestationSecurityLevel);
128     assertThat(actual.keymasterVersion).isEqualTo(expected.keymasterVersion);
129     assertThat(actual.keymasterSecurityLevel).isEqualTo(expected.keymasterSecurityLevel);
130     assertThat(actual.attestationChallenge).isEqualTo(expected.attestationChallenge);
131     assertThat(actual.uniqueId).isEqualTo(expected.uniqueId);
132     assertThat(actual.teeEnforced.userAuthType).isEqualTo(expected.teeEnforced.userAuthType);
133     assertThat(actual.teeEnforced.attestationIdBrand)
134         .isEqualTo(expected.teeEnforced.attestationIdBrand);
135   }
136 }
137