• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.annotation.NonNull;
20 import android.os.ServiceManager;
21 import android.os.ServiceSpecificException;
22 import android.security.legacykeystore.ILegacyKeystore;
23 import android.util.Log;
24 
25 /**
26  * @hide This class allows legacy VPN access to its profiles that were stored in Keystore.
27  * The storage of unstructured blobs in Android Keystore is going away, because there is no
28  * architectural or security benefit of storing profiles in keystore over storing them
29  * in the file system. This class allows access to the blobs that still exist in keystore.
30  * And it stores new blob in a database that is still owned by Android Keystore.
31  */
32 public class LegacyVpnProfileStore {
33     private static final String TAG = "LegacyVpnProfileStore";
34 
35     public static final int SYSTEM_ERROR = ILegacyKeystore.ERROR_SYSTEM_ERROR;
36     public static final int PROFILE_NOT_FOUND = ILegacyKeystore.ERROR_ENTRY_NOT_FOUND;
37 
38     private static final String LEGACY_KEYSTORE_SERVICE_NAME = "android.security.legacykeystore";
39 
getService()40     private static ILegacyKeystore getService() {
41         return ILegacyKeystore.Stub.asInterface(
42                     ServiceManager.checkService(LEGACY_KEYSTORE_SERVICE_NAME));
43     }
44 
45     /**
46      * Stores the profile under the alias in the profile database. Existing profiles by the
47      * same name will be replaced.
48      * @param alias The name of the profile
49      * @param profile The profile.
50      * @return true if the profile was successfully added. False otherwise.
51      * @hide
52      */
put(@onNull String alias, @NonNull byte[] profile)53     public static boolean put(@NonNull String alias, @NonNull byte[] profile) {
54         try {
55             getService().put(alias, ILegacyKeystore.UID_SELF, profile);
56             return true;
57         } catch (Exception e) {
58             Log.e(TAG, "Failed to put vpn profile.", e);
59             return false;
60         }
61     }
62 
63     /**
64      * Retrieves a profile by the name alias from the profile database.
65      * @param alias Name of the profile to retrieve.
66      * @return The unstructured blob, that is the profile that was stored using
67      *         LegacyVpnProfileStore#put or with
68      *         android.security.Keystore.put(Credentials.VPN + alias).
69      *         Returns null if no profile was found.
70      * @hide
71      */
get(@onNull String alias)72     public static byte[] get(@NonNull String alias) {
73         try {
74             return getService().get(alias, ILegacyKeystore.UID_SELF);
75         } catch (ServiceSpecificException e) {
76             if (e.errorCode != PROFILE_NOT_FOUND) {
77                 Log.e(TAG, "Failed to get vpn profile.", e);
78             }
79         } catch (Exception e) {
80             Log.e(TAG, "Failed to get vpn profile.", e);
81         }
82         return null;
83     }
84 
85     /**
86      * Removes a profile by the name alias from the profile database.
87      * @param alias Name of the profile to be removed.
88      * @return True if a profile was removed. False if no such profile was found.
89      * @hide
90      */
remove(@onNull String alias)91     public static boolean remove(@NonNull String alias) {
92         try {
93             getService().remove(alias, ILegacyKeystore.UID_SELF);
94             return true;
95         } catch (ServiceSpecificException e) {
96             if (e.errorCode != PROFILE_NOT_FOUND) {
97                 Log.e(TAG, "Failed to remove vpn profile.", e);
98             }
99         } catch (Exception e) {
100             Log.e(TAG, "Failed to remove vpn profile.", e);
101         }
102         return false;
103     }
104 
105     /**
106      * Lists the vpn profiles stored in the database.
107      * @return An array of strings representing the aliases stored in the profile database.
108      *         The return value may be empty but never null.
109      * @hide
110      */
list(@onNull String prefix)111     public static @NonNull String[] list(@NonNull String prefix) {
112         try {
113             final String[] aliases = getService().list(prefix, ILegacyKeystore.UID_SELF);
114             for (int i = 0; i < aliases.length; ++i) {
115                 aliases[i] = aliases[i].substring(prefix.length());
116             }
117             return aliases;
118         } catch (Exception e) {
119             Log.e(TAG, "Failed to list vpn profiles.", e);
120         }
121         return new String[0];
122     }
123 }
124