• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.remoteprovisioner.unittest;
18 
19 import static android.hardware.security.keymint.SecurityLevel.TRUSTED_ENVIRONMENT;
20 
21 import static org.junit.Assert.assertNotEquals;
22 import static org.junit.Assert.assertNotNull;
23 
24 import android.content.Context;
25 import android.hardware.security.keymint.DeviceInfo;
26 import android.hardware.security.keymint.ProtectedData;
27 import android.os.Build;
28 import android.os.ServiceManager;
29 import android.security.IGenerateRkpKeyService.Status;
30 import android.security.remoteprovisioning.IRemoteProvisioning;
31 import android.security.remoteprovisioning.ImplInfo;
32 
33 import androidx.test.core.app.ApplicationProvider;
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import com.android.remoteprovisioner.CborUtils;
37 import com.android.remoteprovisioner.GeekResponse;
38 import com.android.remoteprovisioner.ProvisionerMetrics;
39 import com.android.remoteprovisioner.RemoteProvisioningException;
40 import com.android.remoteprovisioner.ServerInterface;
41 import com.android.remoteprovisioner.SettingsManager;
42 import com.android.remoteprovisioner.SystemInterface;
43 
44 import org.junit.After;
45 import org.junit.Before;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 
50 import java.util.List;
51 
52 import co.nstant.in.cbor.model.Map;
53 import co.nstant.in.cbor.model.UnicodeString;
54 
55 @RunWith(AndroidJUnit4.class)
56 public class KeyRegisteredTest {
57 
58     private static final String SERVICE = "android.security.remoteprovisioning";
59 
60     private static Context sContext;
61     private static IRemoteProvisioning sBinder;
62     private static int sCurve;
63 
64     @BeforeClass
init()65     public static void init() throws Exception {
66         sContext = ApplicationProvider.getApplicationContext();
67         sBinder =
68               IRemoteProvisioning.Stub.asInterface(ServiceManager.getService(SERVICE));
69         assertNotNull(sBinder);
70         ImplInfo[] info = sBinder.getImplementationInfo();
71         for (int i = 0; i < info.length; i++) {
72             if (info[i].secLevel == TRUSTED_ENVIRONMENT) {
73                 sCurve = info[i].supportedCurve;
74                 break;
75             }
76         }
77     }
78 
79     @Before
setUp()80     public void setUp() throws Exception {
81         sBinder.deleteAllKeys();
82     }
83 
84     @After
tearDown()85     public void tearDown() throws Exception {
86         sBinder.deleteAllKeys();
87     }
88 
requestCerts(int numKeys, int secLevel, byte[] geekChain, byte[] challenge, IRemoteProvisioning binder, Context context, ProvisionerMetrics metrics)89     private void requestCerts(int numKeys, int secLevel, byte[] geekChain, byte[] challenge,
90                               IRemoteProvisioning binder, Context context,
91                               ProvisionerMetrics metrics) throws Exception {
92         DeviceInfo deviceInfo = new DeviceInfo();
93         ProtectedData protectedData = new ProtectedData();
94         byte[] macedKeysToSign = SystemInterface.generateCsr(SettingsManager.isTestMode(), numKeys,
95                 secLevel, geekChain, challenge, protectedData, deviceInfo, binder, metrics);
96         String fingerprint = Build.FINGERPRINT;
97         // The backend should provision test certs if the build isn't a user build.
98         // Registration status only factors into user builds, so set a debug property that
99         // will instruct the underlying provisioning code to appear as a user build to the
100         // backend if it isn't.
101         if (!Build.TYPE.equals("user")) {
102             fingerprint = fingerprint.replace("userdebug", "user");
103             fingerprint = fingerprint.replace("eng", "user");
104         }
105         Map unverifiedDeviceInfo = new Map();
106         unverifiedDeviceInfo.put(new UnicodeString("fingerprint"),
107                                  new UnicodeString(fingerprint));
108         byte[] certificateRequest =
109                 CborUtils.buildCertificateRequest(deviceInfo.deviceInfo,
110                                                   challenge,
111                                                   protectedData.protectedData,
112                                                   macedKeysToSign,
113                                                   unverifiedDeviceInfo);
114         List<byte[]> certChains = ServerInterface.requestSignedCertificates(context,
115                         certificateRequest, challenge, metrics);
116     }
117 
118     @Test
testKeyRegisteredTee()119     public void testKeyRegisteredTee() throws Exception {
120         try {
121             ProvisionerMetrics metrics = ProvisionerMetrics.createScheduledAttemptMetrics(sContext);
122             int numTestKeys = 1;
123             sBinder.generateKeyPair(SettingsManager.isTestMode(), TRUSTED_ENVIRONMENT);
124             GeekResponse geek = ServerInterface.fetchGeek(sContext, metrics);
125             assertNotNull(geek);
126             requestCerts(numTestKeys, TRUSTED_ENVIRONMENT, geek.getGeekChain(sCurve),
127                          geek.getChallenge(), sBinder, sContext, metrics);
128         } catch (RemoteProvisioningException e) {
129             // Any exception will be a failure here, but specifically call out DEVICE_NOT_REGISTERED
130             // as a registration failure before throwing whatever other problem may have occurred.
131             assertNotEquals("Device isn't registered.",
132                     Status.DEVICE_NOT_REGISTERED, e.getErrorCode());
133             throw e;
134         }
135     }
136 }
137