Home | History | Annotate | Download | only in keystore
      1 /*
      2  * Copyright (C) 2016 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 #define LOG_TAG "keystore"
     18 
     19 #include "permissions.h"
     20 
     21 #include <cutils/log.h>
     22 #include <cutils/sockets.h>
     23 #include <private/android_filesystem_config.h>
     24 
     25 #include <selinux/android.h>
     26 
     27 #include "keystore_utils.h"
     28 
     29 /* perm_labels associcated with keystore_key SELinux class verbs. */
     30 const char* perm_labels[] = {
     31     "get_state",
     32     "get",
     33     "insert",
     34     "delete",
     35     "exist",
     36     "list",
     37     "reset",
     38     "password",
     39     "lock",
     40     "unlock",
     41     "is_empty",
     42     "sign",
     43     "verify",
     44     "grant",
     45     "duplicate",
     46     "clear_uid",
     47     "add_auth",
     48     "user_changed",
     49     "gen_unique_id",
     50 };
     51 
     52 struct user_euid {
     53     uid_t uid;
     54     uid_t euid;
     55 };
     56 
     57 user_euid user_euids[] = {
     58     {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
     59     {AID_WIFI, AID_KEYSTORE}, {AID_KEYSTORE, AID_WIFI}
     60 };
     61 
     62 struct user_perm {
     63     uid_t uid;
     64     perm_t perms;
     65 };
     66 
     67 static user_perm user_perms[] = {
     68     {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0))},
     69     {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
     70     {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
     71     {AID_ROOT, static_cast<perm_t>(P_GET)},
     72 };
     73 
     74 static const perm_t DEFAULT_PERMS = static_cast<perm_t>(
     75     P_GET_STATE | P_GET | P_INSERT | P_DELETE | P_EXIST | P_LIST | P_SIGN | P_VERIFY |
     76     P_GEN_UNIQUE_ID /* Only privileged apps can do this, but enforcement is done by SELinux */);
     77 
     78 struct audit_data {
     79     pid_t pid;
     80     uid_t uid;
     81 };
     82 
     83 const char* get_perm_label(perm_t perm) {
     84     unsigned int index = ffs(perm);
     85     if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
     86         return perm_labels[index - 1];
     87     } else {
     88         ALOGE("Keystore: Failed to retrieve permission label.\n");
     89         abort();
     90     }
     91 }
     92 
     93 static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) {
     94     struct audit_data* ad = reinterpret_cast<struct audit_data*>(data);
     95     if (!ad) {
     96         ALOGE("No keystore audit data");
     97         return 0;
     98     }
     99 
    100     snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
    101     return 0;
    102 }
    103 
    104 static char* tctx;
    105 
    106 int configure_selinux() {
    107     union selinux_callback cb;
    108     cb.func_audit = audit_callback;
    109     selinux_set_callback(SELINUX_CB_AUDIT, cb);
    110     cb.func_log = selinux_log_callback;
    111     selinux_set_callback(SELINUX_CB_LOG, cb);
    112     if (getcon(&tctx) != 0) {
    113         ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
    114         return -1;
    115     }
    116 
    117     return 0;
    118 }
    119 
    120 static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
    121     audit_data ad;
    122     char* sctx = NULL;
    123     const char* selinux_class = "keystore_key";
    124     const char* str_perm = get_perm_label(perm);
    125 
    126     if (!str_perm) {
    127         return false;
    128     }
    129 
    130     if (getpidcon(spid, &sctx) != 0) {
    131         ALOGE("SELinux: Failed to get source pid context.\n");
    132         return false;
    133     }
    134 
    135     ad.pid = spid;
    136     ad.uid = uid;
    137 
    138     bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
    139                                         reinterpret_cast<void*>(&ad)) == 0;
    140     freecon(sctx);
    141     return allowed;
    142 }
    143 
    144 /**
    145  * Returns the UID that the callingUid should act as. This is here for
    146  * legacy support of the WiFi and VPN systems and should be removed
    147  * when WiFi can operate in its own namespace.
    148  */
    149 uid_t get_keystore_euid(uid_t uid) {
    150     for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
    151         struct user_euid user = user_euids[i];
    152         if (user.uid == uid) {
    153             return user.euid;
    154         }
    155     }
    156 
    157     return uid;
    158 }
    159 
    160 bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
    161     // All system users are equivalent for multi-user support.
    162     if (get_app_id(uid) == AID_SYSTEM) {
    163         uid = AID_SYSTEM;
    164     }
    165 
    166     for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
    167         struct user_perm user = user_perms[i];
    168         if (user.uid == uid) {
    169             return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
    170         }
    171     }
    172 
    173     return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
    174 }
    175 
    176 /**
    177  * Returns true if the callingUid is allowed to interact in the targetUid's
    178  * namespace.
    179  */
    180 bool is_granted_to(uid_t callingUid, uid_t targetUid) {
    181     if (callingUid == targetUid) {
    182         return true;
    183     }
    184     for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
    185         struct user_euid user = user_euids[i];
    186         if (user.euid == callingUid && user.uid == targetUid) {
    187             return true;
    188         }
    189     }
    190 
    191     return false;
    192 }
    193