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.Manifest;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.hardware.oemlock.V1_0.IOemLock;
25 import android.os.Binder;
26 import android.os.Bundle;
27 import android.os.IBinder;
28 import android.os.SystemProperties;
29 import android.os.UserHandle;
30 import android.os.UserManager;
31 import android.os.UserManagerInternal;
32 import android.os.UserManagerInternal.UserRestrictionsListener;
33 import android.service.oemlock.IOemLockService;
34 import android.util.Slog;
35 
36 import com.android.server.LocalServices;
37 import com.android.server.PersistentDataBlockManagerInternal;
38 import com.android.server.SystemService;
39 import 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  */
47 public 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 
isHalPresent()56     public static boolean isHalPresent() {
57         return VendorLock.getOemLockHalService() != null;
58     }
59 
60     /** Select the OEM lock implementation */
getOemLock(Context context)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 
OemLockService(Context context)72     public OemLockService(Context context) {
73         this(context, getOemLock(context));
74     }
75 
OemLockService(Context context, OemLock oemLock)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
onStart()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);
102                     setPersistentDataBlockOemUnlockAllowedBit(false);
103                 }
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
116         @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
129         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 {
167                 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");
173                 }
174 
175                 mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
176                 setPersistentDataBlockOemUnlockAllowedBit(allowedByUser);
177             } 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 
194         /** 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          */
199         @Override
200         public boolean isOemUnlockAllowed() {
201             enforceOemUnlockReadPermission();
202 
203             final long token = Binder.clearCallingIdentity();
204             try {
205                 boolean allowed = mOemLock.isOemUnlockAllowedByCarrier()
206                         && mOemLock.isOemUnlockAllowedByDevice();
207                 setPersistentDataBlockOemUnlockAllowedBit(allowed);
208                 return allowed;
209             } 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 
228     /**
229      * Always synchronize the OemUnlockAllowed bit to the FRP partition, which
230      * is used to erase FRP information on a unlockable device.
231      */
setPersistentDataBlockOemUnlockAllowedBit(boolean allowed)232     private void setPersistentDataBlockOemUnlockAllowedBit(boolean allowed) {
233         final PersistentDataBlockManagerInternal pdbmi
234                 = LocalServices.getService(PersistentDataBlockManagerInternal.class);
235         // if mOemLock is PersistentDataBlockLock, then the bit should have already been set
236         if (pdbmi != null && !(mOemLock instanceof PersistentDataBlockLock)) {
237             Slog.i(TAG, "Update OEM Unlock bit in pst partition to " + allowed);
238             pdbmi.forceOemUnlockEnabled(allowed);
239         }
240     }
241 
isOemUnlockAllowedByAdmin()242     private boolean isOemUnlockAllowedByAdmin() {
243         return !UserManager.get(mContext)
244                 .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
245     }
246 
enforceManageCarrierOemUnlockPermission()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 
enforceManageUserOemUnlockPermission()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 
enforceOemUnlockReadPermission()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 
enforceUserIsAdmin()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 }
281