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         @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      */
    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 
    242     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 }
    281