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 /** 31 * Uses the OEM lock HAL. 32 */ 33 class VendorLock extends OemLock { 34 private static final String TAG = "OemLock"; 35 36 private Context mContext; 37 private IOemLock mOemLock; 38 getOemLockHalService()39 static IOemLock getOemLockHalService() { 40 try { 41 return IOemLock.getService(/* retry */ true); 42 } catch (NoSuchElementException e) { 43 Slog.i(TAG, "OemLock HAL not present on device"); 44 return null; 45 } catch (RemoteException e) { 46 throw e.rethrowFromSystemServer(); 47 } 48 } 49 VendorLock(Context context, IOemLock oemLock)50 VendorLock(Context context, IOemLock oemLock) { 51 mContext = context; 52 mOemLock = oemLock; 53 } 54 55 @Override 56 @Nullable getLockName()57 String getLockName() { 58 final Integer[] requestStatus = new Integer[1]; 59 final String[] lockName = new String[1]; 60 61 try { 62 mOemLock.getName((status, name) -> { 63 requestStatus[0] = status; 64 lockName[0] = name; 65 }); 66 } catch (RemoteException e) { 67 Slog.e(TAG, "Failed to get name from HAL", e); 68 throw e.rethrowFromSystemServer(); 69 } 70 71 switch (requestStatus[0]) { 72 case OemLockStatus.OK: 73 // Success 74 return lockName[0]; 75 76 case OemLockStatus.FAILED: 77 Slog.e(TAG, "Failed to get OEM lock name."); 78 return null; 79 80 default: 81 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 82 return null; 83 } 84 } 85 86 @Override setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature)87 void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) { 88 try { 89 ArrayList<Byte> signatureBytes = toByteArrayList(signature); 90 switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, signatureBytes)) { 91 case OemLockSecureStatus.OK: 92 Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed); 93 return; 94 95 case OemLockSecureStatus.INVALID_SIGNATURE: 96 if (signatureBytes.isEmpty()) { 97 throw new IllegalArgumentException("Signature required for carrier unlock"); 98 } 99 throw new SecurityException( 100 "Invalid signature used in attempt to carrier unlock"); 101 102 default: 103 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 104 // Fallthrough 105 case OemLockSecureStatus.FAILED: 106 throw new RuntimeException("Failed to set carrier OEM unlock state"); 107 } 108 } catch (RemoteException e) { 109 Slog.e(TAG, "Failed to set carrier state with HAL", e); 110 throw e.rethrowFromSystemServer(); 111 } 112 } 113 114 @Override isOemUnlockAllowedByCarrier()115 boolean isOemUnlockAllowedByCarrier() { 116 final Integer[] requestStatus = new Integer[1]; 117 final Boolean[] allowedByCarrier = new Boolean[1]; 118 119 try { 120 mOemLock.isOemUnlockAllowedByCarrier((status, allowed) -> { 121 requestStatus[0] = status; 122 allowedByCarrier[0] = allowed; 123 }); 124 } catch (RemoteException e) { 125 Slog.e(TAG, "Failed to get carrier state from HAL"); 126 throw e.rethrowFromSystemServer(); 127 } 128 129 switch (requestStatus[0]) { 130 case OemLockStatus.OK: 131 // Success 132 return allowedByCarrier[0]; 133 134 default: 135 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 136 // Fallthrough 137 case OemLockStatus.FAILED: 138 throw new RuntimeException("Failed to get carrier OEM unlock state"); 139 } 140 } 141 142 @Override setOemUnlockAllowedByDevice(boolean allowedByDevice)143 void setOemUnlockAllowedByDevice(boolean allowedByDevice) { 144 try { 145 switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) { 146 case OemLockSecureStatus.OK: 147 Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice); 148 return; 149 150 default: 151 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 152 // Fallthrough 153 case OemLockSecureStatus.FAILED: 154 throw new RuntimeException("Failed to set device OEM unlock state"); 155 } 156 } catch (RemoteException e) { 157 Slog.e(TAG, "Failed to set device state with HAL", e); 158 throw e.rethrowFromSystemServer(); 159 } 160 } 161 162 @Override isOemUnlockAllowedByDevice()163 boolean isOemUnlockAllowedByDevice() { 164 final Integer[] requestStatus = new Integer[1]; 165 final Boolean[] allowedByDevice = new Boolean[1]; 166 167 try { 168 mOemLock.isOemUnlockAllowedByDevice((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