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.keystore2;
18 
19 import android.annotation.NonNull;
20 import android.hardware.biometrics.BiometricManager;
21 import android.hardware.security.keymint.KeyParameter;
22 import android.hardware.security.keymint.KeyParameterValue;
23 import android.hardware.security.keymint.SecurityLevel;
24 import android.hardware.security.keymint.Tag;
25 import android.security.GateKeeper;
26 import android.security.keymaster.KeymasterDefs;
27 import android.security.keystore.KeyProperties;
28 import android.security.keystore.UserAuthArgs;
29 import android.system.keystore2.Authorization;
30 
31 import java.math.BigInteger;
32 import java.security.ProviderException;
33 import java.util.ArrayList;
34 import java.util.Date;
35 import java.util.List;
36 import java.util.function.Consumer;
37 
38 /**
39  * @hide
40  */
41 public abstract class KeyStore2ParameterUtils {
42 
43     /**
44      * This function constructs a {@link KeyParameter} expressing a boolean value.
45      * @param tag Must be KeyMint tag with the associated type BOOL.
46      * @return An instance of {@link KeyParameter}.
47      * @hide
48      */
makeBool(int tag)49     static @NonNull KeyParameter makeBool(int tag) {
50         int type = KeymasterDefs.getTagType(tag);
51         if (type != KeymasterDefs.KM_BOOL) {
52             throw new IllegalArgumentException("Not a boolean tag: " + tag);
53         }
54         KeyParameter p = new KeyParameter();
55         p.tag = tag;
56         p.value = KeyParameterValue.boolValue(true);
57         return p;
58     }
59 
60     /**
61      * This function constructs a {@link KeyParameter} expressing an enum value.
62      * @param tag Must be KeyMint tag with the associated type ENUM or ENUM_REP.
63      * @param v A 32bit integer.
64      * @return An instance of {@link KeyParameter}.
65      * @hide
66      */
makeEnum(int tag, int v)67     static @NonNull KeyParameter makeEnum(int tag, int v) {
68         KeyParameter kp = new KeyParameter();
69         kp.tag = tag;
70         switch (tag) {
71             case Tag.PURPOSE:
72                 kp.value = KeyParameterValue.keyPurpose(v);
73                 break;
74             case Tag.ALGORITHM:
75                 kp.value = KeyParameterValue.algorithm(v);
76                 break;
77             case Tag.BLOCK_MODE:
78                 kp.value = KeyParameterValue.blockMode(v);
79                 break;
80             case Tag.DIGEST:
81                 kp.value = KeyParameterValue.digest(v);
82                 break;
83             case Tag.EC_CURVE:
84                 kp.value = KeyParameterValue.ecCurve(v);
85                 break;
86             case Tag.ORIGIN:
87                 kp.value = KeyParameterValue.origin(v);
88                 break;
89             case Tag.PADDING:
90                 kp.value = KeyParameterValue.paddingMode(v);
91                 break;
92             case Tag.USER_AUTH_TYPE:
93                 kp.value = KeyParameterValue.hardwareAuthenticatorType(v);
94                 break;
95             case Tag.HARDWARE_TYPE:
96                 kp.value = KeyParameterValue.securityLevel(v);
97                 break;
98             default:
99                 throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag);
100         }
101         return kp;
102     }
103 
104     /**
105      * This function constructs a {@link KeyParameter} expressing an integer value.
106      * @param tag Must be KeyMint tag with the associated type UINT or UINT_REP.
107      * @param v A 32bit integer.
108      * @return An instance of {@link KeyParameter}.
109      * @hide
110      */
makeInt(int tag, int v)111     static @NonNull KeyParameter makeInt(int tag, int v) {
112         int type = KeymasterDefs.getTagType(tag);
113         if (type != KeymasterDefs.KM_UINT && type != KeymasterDefs.KM_UINT_REP) {
114             throw new IllegalArgumentException("Not an int or repeatable int tag: " + tag);
115         }
116         KeyParameter p = new KeyParameter();
117         p.tag = tag;
118         p.value = KeyParameterValue.integer(v);
119         return p;
120     }
121 
122     /**
123      * This function constructs a {@link KeyParameter} expressing a long integer value.
124      * @param tag Must be KeyMint tag with the associated type ULONG or ULONG_REP.
125      * @param v A 64bit integer.
126      * @return An instance of {@link KeyParameter}.
127      * @hide
128      */
makeLong(int tag, long v)129     static @NonNull KeyParameter makeLong(int tag, long v) {
130         int type = KeymasterDefs.getTagType(tag);
131         if (type != KeymasterDefs.KM_ULONG && type != KeymasterDefs.KM_ULONG_REP) {
132             throw new IllegalArgumentException("Not a long or repeatable long tag: " + tag);
133         }
134         KeyParameter p = new KeyParameter();
135         p.tag = tag;
136         p.value = KeyParameterValue.longInteger(v);
137         return p;
138     }
139 
140     /**
141      * This function constructs a {@link KeyParameter} expressing a blob.
142      * @param tag Must be KeyMint tag with the associated type BYTES.
143      * @param b A byte array to be stored in the new key parameter.
144      * @return An instance of {@link KeyParameter}.
145      * @hide
146      */
makeBytes(int tag, @NonNull byte[] b)147     static @NonNull KeyParameter makeBytes(int tag, @NonNull byte[] b) {
148         if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) {
149             throw new IllegalArgumentException("Not a bytes tag: " + tag);
150         }
151         KeyParameter p = new KeyParameter();
152         p.tag = tag;
153         p.value = KeyParameterValue.blob(b);
154         return p;
155     }
156 
157     /**
158      * This function constructs a {@link KeyParameter} expressing a Bignum.
159      * @param tag Must be KeyMint tag with the associated type BIGNUM.
160      * @param b A BitInteger to be stored in the new key parameter.
161      * @return An instance of {@link KeyParameter}.
162      * @hide
163      */
makeBignum(int tag, @NonNull BigInteger b)164     static @NonNull KeyParameter makeBignum(int tag, @NonNull BigInteger b) {
165         if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BIGNUM) {
166             throw new IllegalArgumentException("Not a bignum tag: " + tag);
167         }
168         KeyParameter p = new KeyParameter();
169         p.tag = tag;
170         p.value = KeyParameterValue.blob(b.toByteArray());
171         return p;
172     }
173 
174     /**
175      * This function constructs a {@link KeyParameter} expressing date.
176      * @param tag Must be KeyMint tag with the associated type DATE.
177      * @param date A date
178      * @return An instance of {@link KeyParameter}.
179      * @hide
180      */
makeDate(int tag, @NonNull Date date)181     static @NonNull KeyParameter makeDate(int tag, @NonNull Date date) {
182         if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
183             throw new IllegalArgumentException("Not a date tag: " + tag);
184         }
185         KeyParameter p = new KeyParameter();
186         p.tag = tag;
187         p.value = KeyParameterValue.dateTime(date.getTime());
188         return p;
189     }
190     /**
191      * Returns true if the given security level is TEE or Strongbox.
192      *
193      * @param securityLevel the security level to query
194      * @return truw if the given security level is TEE or Strongbox.
195      */
isSecureHardware(@ecurityLevel int securityLevel)196     static boolean isSecureHardware(@SecurityLevel int securityLevel) {
197         return securityLevel == SecurityLevel.TRUSTED_ENVIRONMENT
198                 || securityLevel == SecurityLevel.STRONGBOX;
199     }
200 
getUnsignedInt(@onNull Authorization param)201     static long getUnsignedInt(@NonNull Authorization param) {
202         if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_UINT) {
203             throw new IllegalArgumentException("Not an int tag: " + param.keyParameter.tag);
204         }
205         // KM_UINT is 32 bits wide so we must suppress sign extension.
206         return ((long) param.keyParameter.value.getInteger()) & 0xffffffffL;
207     }
208 
getDate(@onNull Authorization param)209     static @NonNull Date getDate(@NonNull Authorization param) {
210         if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_DATE) {
211             throw new IllegalArgumentException("Not a date tag: " + param.keyParameter.tag);
212         }
213         if (param.keyParameter.value.getDateTime() < 0) {
214             throw new IllegalArgumentException("Date Value too large: "
215                     + param.keyParameter.value.getDateTime());
216         }
217         return new Date(param.keyParameter.value.getDateTime());
218     }
219 
forEachSetFlag(int flags, Consumer<Integer> consumer)220     static void forEachSetFlag(int flags, Consumer<Integer> consumer) {
221         int offset = 0;
222         while (flags != 0) {
223             if ((flags & 1) == 1) {
224                 consumer.accept(1 << offset);
225             }
226             offset += 1;
227             flags >>>= 1;
228         }
229     }
230 
getRootSid()231     private static long getRootSid() {
232         long rootSid = GateKeeper.getSecureUserId();
233         if (rootSid == 0) {
234             throw new IllegalStateException("Secure lock screen must be enabled"
235                     + " to create keys requiring user authentication");
236         }
237         return rootSid;
238     }
239 
addSids(@onNull List<KeyParameter> params, @NonNull UserAuthArgs spec)240     private static void addSids(@NonNull List<KeyParameter> params, @NonNull UserAuthArgs spec) {
241         // If both biometric and credential are accepted, then just use the root sid from gatekeeper
242         if (spec.getUserAuthenticationType() == (KeyProperties.AUTH_BIOMETRIC_STRONG
243                 | KeyProperties.AUTH_DEVICE_CREDENTIAL)) {
244             if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
245                 params.add(makeLong(
246                         KeymasterDefs.KM_TAG_USER_SECURE_ID,
247                         spec.getBoundToSpecificSecureUserId()
248                 ));
249             } else {
250                 // The key is authorized for use for the specified amount of time after the user has
251                 // authenticated. Whatever unlocks the secure lock screen should authorize this key.
252                 params.add(makeLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, getRootSid()));
253             }
254         } else {
255             List<Long> sids = new ArrayList<>();
256             if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_BIOMETRIC_STRONG) != 0) {
257                 final BiometricManager bm = android.app.AppGlobals.getInitialApplication()
258                         .getSystemService(BiometricManager.class);
259 
260                 // TODO: Restore permission check in getAuthenticatorIds once the ID is no longer
261                 //       needed here.
262 
263                 final long[] biometricSids = bm.getAuthenticatorIds();
264 
265                 if (biometricSids.length == 0) {
266                     throw new IllegalStateException(
267                             "At least one biometric must be enrolled to create keys requiring user"
268                                     + " authentication for every use");
269                 }
270 
271                 if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
272                     sids.add(spec.getBoundToSpecificSecureUserId());
273                 } else if (spec.isInvalidatedByBiometricEnrollment()) {
274                     // The biometric-only SIDs will change on biometric enrollment or removal of all
275                     // enrolled templates, invalidating the key.
276                     for (long sid : biometricSids) {
277                         sids.add(sid);
278                     }
279                 } else {
280                     // The root SID will *not* change on fingerprint enrollment, or removal of all
281                     // enrolled fingerprints, allowing the key to remain valid.
282                     sids.add(getRootSid());
283                 }
284             } else if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_DEVICE_CREDENTIAL)
285                     != 0) {
286                 sids.add(getRootSid());
287             } else {
288                 throw new IllegalStateException("Invalid or no authentication type specified.");
289             }
290 
291             for (int i = 0; i < sids.size(); i++) {
292                 params.add(makeLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, sids.get(i)));
293             }
294         }
295     }
296 
297     /**
298      * Adds keymaster arguments to express the key's authorization policy supported by user
299      * authentication.
300      *
301      * @param args The arguments sent to keymaster that need to be populated from the spec
302      * @param spec The user authentication relevant portions of the spec passed in from the caller.
303      *        This spec will be translated into the relevant keymaster tags to be loaded into args.
304      * @throws IllegalStateException if user authentication is required but the system is in a wrong
305      *         state (e.g., secure lock screen not set up) for generating or importing keys that
306      *         require user authentication.
307      */
addUserAuthArgs(@onNull List<KeyParameter> args, @NonNull UserAuthArgs spec)308     static void addUserAuthArgs(@NonNull List<KeyParameter> args,
309             @NonNull UserAuthArgs spec) {
310 
311         if (spec.isUserConfirmationRequired()) {
312             args.add(KeyStore2ParameterUtils.makeBool(
313                     KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED));
314         }
315         if (spec.isUserPresenceRequired()) {
316             args.add(KeyStore2ParameterUtils.makeBool(
317                     KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED));
318         }
319         if (spec.isUnlockedDeviceRequired()) {
320             args.add(KeyStore2ParameterUtils.makeBool(
321                     KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED));
322         }
323         if (!spec.isUserAuthenticationRequired()) {
324             args.add(KeyStore2ParameterUtils.makeBool(
325                     KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED));
326         } else {
327             if (spec.getUserAuthenticationValidityDurationSeconds() == 0) {
328                 // Every use of this key needs to be authorized by the user.
329                 addSids(args, spec);
330                 args.add(KeyStore2ParameterUtils.makeEnum(
331                         KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType()
332                 ));
333 
334                 if (spec.isUserAuthenticationValidWhileOnBody()) {
335                     throw new ProviderException(
336                             "Key validity extension while device is on-body is not "
337                                     + "supported for keys requiring fingerprint authentication");
338                 }
339             } else {
340                 addSids(args, spec);
341                 args.add(KeyStore2ParameterUtils.makeEnum(
342                         KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType()
343                 ));
344                 args.add(KeyStore2ParameterUtils.makeInt(
345                         KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
346                         spec.getUserAuthenticationValidityDurationSeconds()
347                 ));
348                 if (spec.isUserAuthenticationValidWhileOnBody()) {
349                     args.add(KeyStore2ParameterUtils.makeBool(
350                             KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY
351                     ));
352                 }
353             }
354         }
355     }
356 }
357