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