Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2009 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 android.security;
     18 
     19 import android.os.RemoteException;
     20 import android.os.ServiceManager;
     21 import android.util.Log;
     22 
     23 /**
     24  * @hide This should not be made public in its present form because it
     25  * assumes that private and secret key bytes are available and would
     26  * preclude the use of hardware crypto.
     27  */
     28 public class KeyStore {
     29     private static final String TAG = "KeyStore";
     30 
     31     // ResponseCodes
     32     public static final int NO_ERROR = 1;
     33     public static final int LOCKED = 2;
     34     public static final int UNINITIALIZED = 3;
     35     public static final int SYSTEM_ERROR = 4;
     36     public static final int PROTOCOL_ERROR = 5;
     37     public static final int PERMISSION_DENIED = 6;
     38     public static final int KEY_NOT_FOUND = 7;
     39     public static final int VALUE_CORRUPTED = 8;
     40     public static final int UNDEFINED_ACTION = 9;
     41     public static final int WRONG_PASSWORD = 10;
     42 
     43     // Used for UID field to indicate the calling UID.
     44     public static final int UID_SELF = -1;
     45 
     46     // Flags for "put" "import" and "generate"
     47     public static final int FLAG_NONE = 0;
     48     public static final int FLAG_ENCRYPTED = 1;
     49 
     50     // States
     51     public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
     52 
     53     private int mError = NO_ERROR;
     54 
     55     private final IKeystoreService mBinder;
     56 
     57     private KeyStore(IKeystoreService binder) {
     58         mBinder = binder;
     59     }
     60 
     61     public static KeyStore getInstance() {
     62         IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
     63                 .getService("android.security.keystore"));
     64         return new KeyStore(keystore);
     65     }
     66 
     67     public State state() {
     68         final int ret;
     69         try {
     70             ret = mBinder.test();
     71         } catch (RemoteException e) {
     72             Log.w(TAG, "Cannot connect to keystore", e);
     73             throw new AssertionError(e);
     74         }
     75 
     76         switch (ret) {
     77             case NO_ERROR: return State.UNLOCKED;
     78             case LOCKED: return State.LOCKED;
     79             case UNINITIALIZED: return State.UNINITIALIZED;
     80             default: throw new AssertionError(mError);
     81         }
     82     }
     83 
     84     public boolean isUnlocked() {
     85         return state() == State.UNLOCKED;
     86     }
     87 
     88     public byte[] get(String key) {
     89         try {
     90             return mBinder.get(key);
     91         } catch (RemoteException e) {
     92             Log.w(TAG, "Cannot connect to keystore", e);
     93             return null;
     94         }
     95     }
     96 
     97     public boolean put(String key, byte[] value, int uid, int flags) {
     98         try {
     99             return mBinder.insert(key, value, uid, flags) == NO_ERROR;
    100         } catch (RemoteException e) {
    101             Log.w(TAG, "Cannot connect to keystore", e);
    102             return false;
    103         }
    104     }
    105 
    106     public boolean delete(String key, int uid) {
    107         try {
    108             return mBinder.del(key, uid) == NO_ERROR;
    109         } catch (RemoteException e) {
    110             Log.w(TAG, "Cannot connect to keystore", e);
    111             return false;
    112         }
    113     }
    114 
    115     public boolean delete(String key) {
    116         return delete(key, UID_SELF);
    117     }
    118 
    119     public boolean contains(String key, int uid) {
    120         try {
    121             return mBinder.exist(key, uid) == NO_ERROR;
    122         } catch (RemoteException e) {
    123             Log.w(TAG, "Cannot connect to keystore", e);
    124             return false;
    125         }
    126     }
    127 
    128     public boolean contains(String key) {
    129         return contains(key, UID_SELF);
    130     }
    131 
    132     public String[] saw(String prefix, int uid) {
    133         try {
    134             return mBinder.saw(prefix, uid);
    135         } catch (RemoteException e) {
    136             Log.w(TAG, "Cannot connect to keystore", e);
    137             return null;
    138         }
    139     }
    140 
    141     public String[] saw(String prefix) {
    142         return saw(prefix, UID_SELF);
    143     }
    144 
    145     public boolean reset() {
    146         try {
    147             return mBinder.reset() == NO_ERROR;
    148         } catch (RemoteException e) {
    149             Log.w(TAG, "Cannot connect to keystore", e);
    150             return false;
    151         }
    152     }
    153 
    154     public boolean password(String password) {
    155         try {
    156             return mBinder.password(password) == NO_ERROR;
    157         } catch (RemoteException e) {
    158             Log.w(TAG, "Cannot connect to keystore", e);
    159             return false;
    160         }
    161     }
    162 
    163     public boolean lock() {
    164         try {
    165             return mBinder.lock() == NO_ERROR;
    166         } catch (RemoteException e) {
    167             Log.w(TAG, "Cannot connect to keystore", e);
    168             return false;
    169         }
    170     }
    171 
    172     public boolean unlock(String password) {
    173         try {
    174             mError = mBinder.unlock(password);
    175             return mError == NO_ERROR;
    176         } catch (RemoteException e) {
    177             Log.w(TAG, "Cannot connect to keystore", e);
    178             return false;
    179         }
    180     }
    181 
    182     public boolean isEmpty() {
    183         try {
    184             return mBinder.zero() == KEY_NOT_FOUND;
    185         } catch (RemoteException e) {
    186             Log.w(TAG, "Cannot connect to keystore", e);
    187             return false;
    188         }
    189     }
    190 
    191     public boolean generate(String key, int uid, int flags) {
    192         try {
    193             return mBinder.generate(key, uid, flags) == NO_ERROR;
    194         } catch (RemoteException e) {
    195             Log.w(TAG, "Cannot connect to keystore", e);
    196             return false;
    197         }
    198     }
    199 
    200     public boolean importKey(String keyName, byte[] key, int uid, int flags) {
    201         try {
    202             return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
    203         } catch (RemoteException e) {
    204             Log.w(TAG, "Cannot connect to keystore", e);
    205             return false;
    206         }
    207     }
    208 
    209     public byte[] getPubkey(String key) {
    210         try {
    211             return mBinder.get_pubkey(key);
    212         } catch (RemoteException e) {
    213             Log.w(TAG, "Cannot connect to keystore", e);
    214             return null;
    215         }
    216     }
    217 
    218     public boolean delKey(String key, int uid) {
    219         try {
    220             return mBinder.del_key(key, uid) == NO_ERROR;
    221         } catch (RemoteException e) {
    222             Log.w(TAG, "Cannot connect to keystore", e);
    223             return false;
    224         }
    225     }
    226 
    227     public boolean delKey(String key) {
    228         return delKey(key, UID_SELF);
    229     }
    230 
    231     public byte[] sign(String key, byte[] data) {
    232         try {
    233             return mBinder.sign(key, data);
    234         } catch (RemoteException e) {
    235             Log.w(TAG, "Cannot connect to keystore", e);
    236             return null;
    237         }
    238     }
    239 
    240     public boolean verify(String key, byte[] data, byte[] signature) {
    241         try {
    242             return mBinder.verify(key, data, signature) == NO_ERROR;
    243         } catch (RemoteException e) {
    244             Log.w(TAG, "Cannot connect to keystore", e);
    245             return false;
    246         }
    247     }
    248 
    249     public boolean grant(String key, int uid) {
    250         try {
    251             return mBinder.grant(key, uid) == NO_ERROR;
    252         } catch (RemoteException e) {
    253             Log.w(TAG, "Cannot connect to keystore", e);
    254             return false;
    255         }
    256     }
    257 
    258     public boolean ungrant(String key, int uid) {
    259         try {
    260             return mBinder.ungrant(key, uid) == NO_ERROR;
    261         } catch (RemoteException e) {
    262             Log.w(TAG, "Cannot connect to keystore", e);
    263             return false;
    264         }
    265     }
    266 
    267     /**
    268      * Returns the last modification time of the key in milliseconds since the
    269      * epoch. Will return -1L if the key could not be found or other error.
    270      */
    271     public long getmtime(String key) {
    272         try {
    273             final long millis = mBinder.getmtime(key);
    274             if (millis == -1L) {
    275                 return -1L;
    276             }
    277 
    278             return millis * 1000L;
    279         } catch (RemoteException e) {
    280             Log.w(TAG, "Cannot connect to keystore", e);
    281             return -1L;
    282         }
    283     }
    284 
    285     public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
    286         try {
    287             return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
    288         } catch (RemoteException e) {
    289             Log.w(TAG, "Cannot connect to keystore", e);
    290             return false;
    291         }
    292     }
    293 
    294     public boolean isHardwareBacked() {
    295         try {
    296             return mBinder.is_hardware_backed() == NO_ERROR;
    297         } catch (RemoteException e) {
    298             Log.w(TAG, "Cannot connect to keystore", e);
    299             return false;
    300         }
    301     }
    302 
    303     public boolean clearUid(int uid) {
    304         try {
    305             return mBinder.clear_uid(uid) == NO_ERROR;
    306         } catch (RemoteException e) {
    307             Log.w(TAG, "Cannot connect to keystore", e);
    308             return false;
    309         }
    310     }
    311 
    312     public int getLastError() {
    313         return mError;
    314     }
    315 }
    316