blob: 6e82c24a6e9b28d11043aa22bd7c6a7a18bd8ca3 [file] [log] [blame]
Andrew Scull5d7027d2017-04-12 11:46:27 +01001/*
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
17package com.android.server.oemlock;
18
19import android.Manifest;
20import android.annotation.Nullable;
21import android.app.ActivityManager;
22import android.content.Context;
23import android.content.pm.PackageManager;
24import android.hardware.oemlock.V1_0.IOemLock;
25import android.os.Binder;
26import android.os.Bundle;
27import android.os.IBinder;
28import android.os.SystemProperties;
29import android.os.UserHandle;
30import android.os.UserManager;
31import android.os.UserManagerInternal;
32import android.os.UserManagerInternal.UserRestrictionsListener;
33import android.service.oemlock.IOemLockService;
34import android.util.Slog;
35
36import com.android.server.LocalServices;
Andrew Scull1a5b76c2018-01-19 16:56:22 +000037import com.android.server.PersistentDataBlockManagerInternal;
Andrew Scull5d7027d2017-04-12 11:46:27 +010038import com.android.server.SystemService;
39import com.android.server.pm.UserRestrictionsUtils;
40
41/**
42 * Service for managing the OEM lock state of the device.
43 *
44 * The OemLock HAL will be used if it is available, otherwise the persistent data block will be
45 * used.
46 */
47public class OemLockService extends SystemService {
48 private static final String TAG = "OemLock";
49
50 private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
51 private static final String FLASH_LOCK_UNLOCKED = "0";
52
53 private Context mContext;
54 private OemLock mOemLock;
55
56 public static boolean isHalPresent() {
57 return VendorLock.getOemLockHalService() != null;
58 }
59
60 /** Select the OEM lock implementation */
61 private static OemLock getOemLock(Context context) {
62 final IOemLock oemLockHal = VendorLock.getOemLockHalService();
63 if (oemLockHal != null) {
64 Slog.i(TAG, "Using vendor lock via the HAL");
65 return new VendorLock(context, oemLockHal);
66 } else {
67 Slog.i(TAG, "Using persistent data block based lock");
68 return new PersistentDataBlockLock(context);
69 }
70 }
71
72 public OemLockService(Context context) {
73 this(context, getOemLock(context));
74 }
75
76 OemLockService(Context context, OemLock oemLock) {
77 super(context);
78 mContext = context;
79 mOemLock = oemLock;
80
81 LocalServices.getService(UserManagerInternal.class)
82 .addUserRestrictionsListener(mUserRestrictionsListener);
83 }
84
85 @Override
86 public void onStart() {
87 publishBinderService(Context.OEM_LOCK_SERVICE, mService);
88 }
89
90 private final UserRestrictionsListener mUserRestrictionsListener =
91 new UserRestrictionsListener() {
92 @Override
93 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
94 Bundle prevRestrictions) {
95 // The admin can prevent OEM unlock with the DISALLOW_FACTORY_RESET user restriction
96 if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
97 UserManager.DISALLOW_FACTORY_RESET)) {
98 final boolean unlockAllowedByAdmin =
99 !newRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET);
100 if (!unlockAllowedByAdmin) {
101 mOemLock.setOemUnlockAllowedByDevice(false);
Rubin Xu2257fda2017-10-06 12:07:32 +0100102 setPersistentDataBlockOemUnlockAllowedBit(false);
Andrew Scull5d7027d2017-04-12 11:46:27 +0100103 }
104 }
105 }
106 };
107
108 /**
109 * Implements the binder interface for the service.
110 *
111 * This checks for the relevant permissions before forwarding the call to the OEM lock
112 * implementation being used on this device.
113 */
114 private final IBinder mService = new IOemLockService.Stub() {
115 @Override
Andrew Scull23a1a5f2018-11-27 16:45:58 +0000116 @Nullable
117 public String getLockName() {
118 enforceManageCarrierOemUnlockPermission();
119
120 final long token = Binder.clearCallingIdentity();
121 try {
122 return mOemLock.getLockName();
123 } finally {
124 Binder.restoreCallingIdentity(token);
125 }
126 }
127
128 @Override
Andrew Scull5d7027d2017-04-12 11:46:27 +0100129 public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
130 enforceManageCarrierOemUnlockPermission();
131 enforceUserIsAdmin();
132
133 final long token = Binder.clearCallingIdentity();
134 try {
135 mOemLock.setOemUnlockAllowedByCarrier(allowed, signature);
136 } finally {
137 Binder.restoreCallingIdentity(token);
138 }
139 }
140
141 @Override
142 public boolean isOemUnlockAllowedByCarrier() {
143 enforceManageCarrierOemUnlockPermission();
144
145 final long token = Binder.clearCallingIdentity();
146 try {
147 return mOemLock.isOemUnlockAllowedByCarrier();
148 } finally {
149 Binder.restoreCallingIdentity(token);
150 }
151 }
152
153 // The user has the final say so if they allow unlock, then the device allows the bootloader
154 // to OEM unlock it.
155 @Override
156 public void setOemUnlockAllowedByUser(boolean allowedByUser) {
157 if (ActivityManager.isUserAMonkey()) {
158 // Prevent a monkey from changing this
159 return;
160 }
161
162 enforceManageUserOemUnlockPermission();
163 enforceUserIsAdmin();
164
165 final long token = Binder.clearCallingIdentity();
166 try {
Andrew Scull85be6902017-09-07 14:03:21 +0100167 if (!isOemUnlockAllowedByAdmin()) {
168 throw new SecurityException("Admin does not allow OEM unlock");
169 }
170
171 if (!mOemLock.isOemUnlockAllowedByCarrier()) {
172 throw new SecurityException("Carrier does not allow OEM unlock");
Andrew Scull5d7027d2017-04-12 11:46:27 +0100173 }
174
175 mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
Rubin Xu2257fda2017-10-06 12:07:32 +0100176 setPersistentDataBlockOemUnlockAllowedBit(allowedByUser);
Andrew Scull5d7027d2017-04-12 11:46:27 +0100177 } finally {
178 Binder.restoreCallingIdentity(token);
179 }
180 }
181
182 @Override
183 public boolean isOemUnlockAllowedByUser() {
184 enforceManageUserOemUnlockPermission();
185
186 final long token = Binder.clearCallingIdentity();
187 try {
188 return mOemLock.isOemUnlockAllowedByDevice();
189 } finally {
190 Binder.restoreCallingIdentity(token);
191 }
192 }
193
Wei Wangade05382017-12-20 15:56:46 -0800194 /** Currently MasterClearConfirm will call isOemUnlockAllowed()
195 * to sync PersistentDataBlockOemUnlockAllowedBit which
196 * is needed before factory reset
197 * TODO: Figure out better place to run sync e.g. adding new API
198 */
Andrew Scull5d7027d2017-04-12 11:46:27 +0100199 @Override
Andrew Scull5d7027d2017-04-12 11:46:27 +0100200 public boolean isOemUnlockAllowed() {
201 enforceOemUnlockReadPermission();
202
203 final long token = Binder.clearCallingIdentity();
204 try {
Wei Wangade05382017-12-20 15:56:46 -0800205 boolean allowed = mOemLock.isOemUnlockAllowedByCarrier()
206 && mOemLock.isOemUnlockAllowedByDevice();
207 setPersistentDataBlockOemUnlockAllowedBit(allowed);
208 return allowed;
Andrew Scull5d7027d2017-04-12 11:46:27 +0100209 } finally {
210 Binder.restoreCallingIdentity(token);
211 }
212 }
213
214 @Override
215 public boolean isDeviceOemUnlocked() {
216 enforceOemUnlockReadPermission();
217
218 String locked = SystemProperties.get(FLASH_LOCK_PROP);
219 switch (locked) {
220 case FLASH_LOCK_UNLOCKED:
221 return true;
222 default:
223 return false;
224 }
225 }
226 };
227
Rubin Xu2257fda2017-10-06 12:07:32 +0100228 /**
229 * Always synchronize the OemUnlockAllowed bit to the FRP partition, which
230 * is used to erase FRP information on a unlockable device.
231 */
232 private void setPersistentDataBlockOemUnlockAllowedBit(boolean allowed) {
Andrew Scull1a5b76c2018-01-19 16:56:22 +0000233 final PersistentDataBlockManagerInternal pdbmi
234 = LocalServices.getService(PersistentDataBlockManagerInternal.class);
Rubin Xu2257fda2017-10-06 12:07:32 +0100235 // if mOemLock is PersistentDataBlockLock, then the bit should have already been set
Andrew Scull1a5b76c2018-01-19 16:56:22 +0000236 if (pdbmi != null && !(mOemLock instanceof PersistentDataBlockLock)) {
Rubin Xu2257fda2017-10-06 12:07:32 +0100237 Slog.i(TAG, "Update OEM Unlock bit in pst partition to " + allowed);
Andrew Scull1a5b76c2018-01-19 16:56:22 +0000238 pdbmi.forceOemUnlockEnabled(allowed);
Rubin Xu2257fda2017-10-06 12:07:32 +0100239 }
240 }
241
Andrew Scull5d7027d2017-04-12 11:46:27 +0100242 private boolean isOemUnlockAllowedByAdmin() {
243 return !UserManager.get(mContext)
244 .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
245 }
246
247 private void enforceManageCarrierOemUnlockPermission() {
248 mContext.enforceCallingOrSelfPermission(
249 Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
250 "Can't manage OEM unlock allowed by carrier");
251 }
252
253 private void enforceManageUserOemUnlockPermission() {
254 mContext.enforceCallingOrSelfPermission(
255 Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
256 "Can't manage OEM unlock allowed by user");
257 }
258
259 private void enforceOemUnlockReadPermission() {
260 if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
261 == PackageManager.PERMISSION_DENIED
262 && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
263 == PackageManager.PERMISSION_DENIED) {
264 throw new SecurityException("Can't access OEM unlock state. Requires "
265 + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
266 }
267 }
268
269 private void enforceUserIsAdmin() {
270 final int userId = UserHandle.getCallingUserId();
271 final long token = Binder.clearCallingIdentity();
272 try {
273 if (!UserManager.get(mContext).isUserAdmin(userId)) {
274 throw new SecurityException("Must be an admin user");
275 }
276 } finally {
277 Binder.restoreCallingIdentity(token);
278 }
279 }
280}