1 /* 2 * Copyright (C) 2017 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.server.oemlock; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.hardware.oemlock.V1_0.IOemLock; 22 import android.hardware.oemlock.V1_0.OemLockSecureStatus; 23 import android.hardware.oemlock.V1_0.OemLockStatus; 24 import android.os.RemoteException; 25 import android.util.Slog; 26 27 import java.util.ArrayList; 28 import java.util.NoSuchElementException; 29 30 /** Uses the OEM lock HAL. */ 31 class VendorLockHidl extends OemLock { 32 private static final String TAG = "OemLock"; 33 34 private Context mContext; 35 private IOemLock mOemLock; 36 getOemLockHalService()37 static IOemLock getOemLockHalService() { 38 try { 39 return IOemLock.getService(/* retry */ true); 40 } catch (NoSuchElementException e) { 41 Slog.i(TAG, "OemLock Hidl HAL not present on device"); 42 return null; 43 } catch (RemoteException e) { 44 throw e.rethrowFromSystemServer(); 45 } 46 } 47 VendorLockHidl(Context context)48 VendorLockHidl(Context context) { 49 mContext = context; 50 mOemLock = getOemLockHalService(); 51 } 52 53 @Override 54 @Nullable getLockName()55 String getLockName() { 56 final String[] lockName = new String[1]; 57 final Integer[] requestStatus = new Integer[1]; 58 59 try { 60 mOemLock.getName( 61 (status, name) -> { 62 requestStatus[0] = status; 63 lockName[0] = name; 64 }); 65 } catch (RemoteException e) { 66 Slog.e(TAG, "Failed to get name from HAL", e); 67 throw e.rethrowFromSystemServer(); 68 } 69 70 switch (requestStatus[0]) { 71 case OemLockStatus.OK: 72 // Success 73 return lockName[0]; 74 75 case OemLockStatus.FAILED: 76 Slog.e(TAG, "Failed to get OEM lock name."); 77 return null; 78 79 default: 80 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 81 return null; 82 } 83 } 84 85 @Override setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature)86 void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) { 87 try { 88 ArrayList<Byte> signatureBytes = toByteArrayList(signature); 89 switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, signatureBytes)) { 90 case OemLockSecureStatus.OK: 91 Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed); 92 return; 93 94 case OemLockSecureStatus.INVALID_SIGNATURE: 95 if (signatureBytes.isEmpty()) { 96 throw new IllegalArgumentException("Signature required for carrier unlock"); 97 } 98 throw new SecurityException( 99 "Invalid signature used in attempt to carrier unlock"); 100 101 default: 102 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 103 // Fallthrough 104 case OemLockSecureStatus.FAILED: 105 throw new RuntimeException("Failed to set carrier OEM unlock state"); 106 } 107 } catch (RemoteException e) { 108 Slog.e(TAG, "Failed to set carrier state with HAL", e); 109 throw e.rethrowFromSystemServer(); 110 } 111 } 112 113 @Override isOemUnlockAllowedByCarrier()114 boolean isOemUnlockAllowedByCarrier() { 115 final Boolean[] allowedByCarrier = new Boolean[1]; 116 final Integer[] requestStatus = new Integer[1]; 117 try { 118 mOemLock.isOemUnlockAllowedByCarrier( 119 (status, allowed) -> { 120 requestStatus[0] = status; 121 allowedByCarrier[0] = allowed; 122 }); 123 } catch (RemoteException e) { 124 Slog.e(TAG, "Failed to get carrier state from HAL"); 125 throw e.rethrowFromSystemServer(); 126 } 127 128 switch (requestStatus[0]) { 129 case OemLockStatus.OK: 130 // Success 131 return allowedByCarrier[0]; 132 133 default: 134 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 135 // Fallthrough 136 case OemLockStatus.FAILED: 137 throw new RuntimeException("Failed to get carrier OEM unlock state"); 138 } 139 } 140 141 @Override setOemUnlockAllowedByDevice(boolean allowedByDevice)142 void setOemUnlockAllowedByDevice(boolean allowedByDevice) { 143 try { 144 switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) { 145 case OemLockSecureStatus.OK: 146 Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice); 147 return; 148 149 default: 150 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 151 // Fallthrough 152 case OemLockSecureStatus.FAILED: 153 throw new RuntimeException("Failed to set device OEM unlock state"); 154 } 155 } catch (RemoteException e) { 156 Slog.e(TAG, "Failed to set device state with HAL", e); 157 throw e.rethrowFromSystemServer(); 158 } 159 } 160 161 @Override isOemUnlockAllowedByDevice()162 boolean isOemUnlockAllowedByDevice() { 163 final Boolean[] allowedByDevice = new Boolean[1]; 164 165 final Integer[] requestStatus = new Integer[1]; 166 try { 167 mOemLock.isOemUnlockAllowedByDevice( 168 (status, allowed) -> { 169 requestStatus[0] = status; 170 allowedByDevice[0] = allowed; 171 }); 172 } catch (RemoteException e) { 173 Slog.e(TAG, "Failed to get devie state from HAL"); 174 throw e.rethrowFromSystemServer(); 175 } 176 177 switch (requestStatus[0]) { 178 case OemLockStatus.OK: 179 // Success 180 return allowedByDevice[0]; 181 182 default: 183 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 184 // Fallthrough 185 case OemLockStatus.FAILED: 186 throw new RuntimeException("Failed to get device OEM unlock state"); 187 } 188 } 189 toByteArrayList(byte[] data)190 private ArrayList<Byte> toByteArrayList(byte[] data) { 191 if (data == null) { 192 return new ArrayList<Byte>(); 193 } 194 ArrayList<Byte> result = new ArrayList<Byte>(data.length); 195 for (final byte b : data) { 196 result.add(b); 197 } 198 return result; 199 } 200 } 201