Home | History | Annotate | Download | only in oemlock
      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 
     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);
    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         public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
    117             enforceManageCarrierOemUnlockPermission();
    118             enforceUserIsAdmin();
    119 
    120             final long token = Binder.clearCallingIdentity();
    121             try {
    122                 mOemLock.setOemUnlockAllowedByCarrier(allowed, signature);
    123             } finally {
    124                 Binder.restoreCallingIdentity(token);
    125             }
    126         }
    127 
    128         @Override
    129         public boolean isOemUnlockAllowedByCarrier() {
    130             enforceManageCarrierOemUnlockPermission();
    131 
    132             final long token = Binder.clearCallingIdentity();
    133             try {
    134               return mOemLock.isOemUnlockAllowedByCarrier();
    135             } finally {
    136                 Binder.restoreCallingIdentity(token);
    137             }
    138         }
    139 
    140         // The user has the final say so if they allow unlock, then the device allows the bootloader
    141         // to OEM unlock it.
    142         @Override
    143         public void setOemUnlockAllowedByUser(boolean allowedByUser) {
    144             if (ActivityManager.isUserAMonkey()) {
    145                 // Prevent a monkey from changing this
    146                 return;
    147             }
    148 
    149             enforceManageUserOemUnlockPermission();
    150             enforceUserIsAdmin();
    151 
    152             final long token = Binder.clearCallingIdentity();
    153             try {
    154                 if (!isOemUnlockAllowedByAdmin()) {
    155                     throw new SecurityException("Admin does not allow OEM unlock");
    156                 }
    157 
    158                 if (!mOemLock.isOemUnlockAllowedByCarrier()) {
    159                     throw new SecurityException("Carrier does not allow OEM unlock");
    160                 }
    161 
    162                 mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
    163                 setPersistentDataBlockOemUnlockAllowedBit(allowedByUser);
    164             } finally {
    165                 Binder.restoreCallingIdentity(token);
    166             }
    167         }
    168 
    169         @Override
    170         public boolean isOemUnlockAllowedByUser() {
    171             enforceManageUserOemUnlockPermission();
    172 
    173             final long token = Binder.clearCallingIdentity();
    174             try {
    175                 return mOemLock.isOemUnlockAllowedByDevice();
    176             } finally {
    177                 Binder.restoreCallingIdentity(token);
    178             }
    179         }
    180 
    181         /** Currently MasterClearConfirm will call isOemUnlockAllowed()
    182          * to sync PersistentDataBlockOemUnlockAllowedBit which
    183          * is needed before factory reset
    184          * TODO: Figure out better place to run sync e.g. adding new API
    185          */
    186         @Override
    187         public boolean isOemUnlockAllowed() {
    188             enforceOemUnlockReadPermission();
    189 
    190             final long token = Binder.clearCallingIdentity();
    191             try {
    192                 boolean allowed = mOemLock.isOemUnlockAllowedByCarrier()
    193                         && mOemLock.isOemUnlockAllowedByDevice();
    194                 setPersistentDataBlockOemUnlockAllowedBit(allowed);
    195                 return allowed;
    196             } finally {
    197                 Binder.restoreCallingIdentity(token);
    198             }
    199         }
    200 
    201         @Override
    202         public boolean isDeviceOemUnlocked() {
    203             enforceOemUnlockReadPermission();
    204 
    205             String locked = SystemProperties.get(FLASH_LOCK_PROP);
    206             switch (locked) {
    207                 case FLASH_LOCK_UNLOCKED:
    208                     return true;
    209                 default:
    210                     return false;
    211             }
    212         }
    213     };
    214 
    215     /**
    216      * Always synchronize the OemUnlockAllowed bit to the FRP partition, which
    217      * is used to erase FRP information on a unlockable device.
    218      */
    219     private void setPersistentDataBlockOemUnlockAllowedBit(boolean allowed) {
    220         final PersistentDataBlockManagerInternal pdbmi
    221                 = LocalServices.getService(PersistentDataBlockManagerInternal.class);
    222         // if mOemLock is PersistentDataBlockLock, then the bit should have already been set
    223         if (pdbmi != null && !(mOemLock instanceof PersistentDataBlockLock)) {
    224             Slog.i(TAG, "Update OEM Unlock bit in pst partition to " + allowed);
    225             pdbmi.forceOemUnlockEnabled(allowed);
    226         }
    227     }
    228 
    229     private boolean isOemUnlockAllowedByAdmin() {
    230         return !UserManager.get(mContext)
    231                 .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
    232     }
    233 
    234     private void enforceManageCarrierOemUnlockPermission() {
    235         mContext.enforceCallingOrSelfPermission(
    236                 Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
    237                 "Can't manage OEM unlock allowed by carrier");
    238     }
    239 
    240     private void enforceManageUserOemUnlockPermission() {
    241         mContext.enforceCallingOrSelfPermission(
    242                 Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
    243                 "Can't manage OEM unlock allowed by user");
    244     }
    245 
    246     private void enforceOemUnlockReadPermission() {
    247         if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
    248                 == PackageManager.PERMISSION_DENIED
    249                 && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
    250                 == PackageManager.PERMISSION_DENIED) {
    251             throw new SecurityException("Can't access OEM unlock state. Requires "
    252                     + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
    253         }
    254     }
    255 
    256     private void enforceUserIsAdmin() {
    257         final int userId = UserHandle.getCallingUserId();
    258         final long token = Binder.clearCallingIdentity();
    259         try {
    260             if (!UserManager.get(mContext).isUserAdmin(userId)) {
    261                 throw new SecurityException("Must be an admin user");
    262             }
    263         } finally {
    264             Binder.restoreCallingIdentity(token);
    265         }
    266     }
    267 }
    268