• 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 com.android.server.locksettings;
18 
19 import android.security.keystore.KeyGenParameterSpec;
20 import android.security.keystore.KeyProperties;
21 import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
22 import android.security.keystore2.AndroidKeyStoreSpi;
23 import android.util.Slog;
24 
25 import com.android.internal.annotations.GuardedBy;
26 
27 import java.io.IOException;
28 import java.security.GeneralSecurityException;
29 import java.security.KeyStore;
30 
31 import javax.crypto.KeyGenerator;
32 import javax.crypto.SecretKey;
33 
34 /**
35  * This class loads and generates the key used for resume on reboot from android keystore.
36  */
37 public class RebootEscrowKeyStoreManager {
38     private static final String TAG = "RebootEscrowKeyStoreManager";
39 
40     /**
41      * The key alias in keystore. This key is used to wrap both escrow key and escrow data.
42      */
43     public static final String REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME =
44             "reboot_escrow_key_store_encryption_key";
45 
46     public static final int KEY_LENGTH = 256;
47 
48     /**
49      * Use keystore2 once it's installed.
50      */
51     private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeystore";
52 
53     /**
54      * The selinux namespace for resume_on_reboot_key
55      */
56     private static final int KEY_STORE_NAMESPACE = 120;
57 
58     /**
59      * Hold this lock when getting or generating the encryption key in keystore.
60      */
61     private final Object mKeyStoreLock = new Object();
62 
63     @GuardedBy("mKeyStoreLock")
getKeyStoreEncryptionKeyLocked()64     private SecretKey getKeyStoreEncryptionKeyLocked() {
65         try {
66             KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
67             KeyStore.LoadStoreParameter loadStoreParameter = null;
68             // Load from the specific namespace if keystore2 is enabled.
69             loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
70             keyStore.load(loadStoreParameter);
71             return (SecretKey) keyStore.getKey(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME,
72                     null);
73         } catch (IOException | GeneralSecurityException e) {
74             Slog.e(TAG, "Unable to get encryption key from keystore.", e);
75         }
76         return null;
77     }
78 
getKeyStoreEncryptionKey()79     protected SecretKey getKeyStoreEncryptionKey() {
80         synchronized (mKeyStoreLock) {
81             return getKeyStoreEncryptionKeyLocked();
82         }
83     }
84 
clearKeyStoreEncryptionKey()85     protected void clearKeyStoreEncryptionKey() {
86         synchronized (mKeyStoreLock) {
87             try {
88                 KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
89                 KeyStore.LoadStoreParameter loadStoreParameter = null;
90                 // Load from the specific namespace if keystore2 is enabled.
91                 loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
92                 keyStore.load(loadStoreParameter);
93                 keyStore.deleteEntry(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME);
94             } catch (IOException | GeneralSecurityException e) {
95                 Slog.e(TAG, "Unable to delete encryption key in keystore.", e);
96             }
97         }
98     }
99 
generateKeyStoreEncryptionKeyIfNeeded()100     protected SecretKey generateKeyStoreEncryptionKeyIfNeeded() {
101         synchronized (mKeyStoreLock) {
102             SecretKey kk = getKeyStoreEncryptionKeyLocked();
103             if (kk != null) {
104                 return kk;
105             }
106 
107             try {
108                 KeyGenerator generator = KeyGenerator.getInstance(
109                         KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStoreSpi.NAME);
110                 KeyGenParameterSpec.Builder parameterSpecBuilder = new KeyGenParameterSpec.Builder(
111                         REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME,
112                         KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
113                         .setKeySize(KEY_LENGTH)
114                         .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
115                         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE);
116                 // Generate the key with the correct namespace if keystore2 is enabled.
117                 parameterSpecBuilder.setNamespace(KEY_STORE_NAMESPACE);
118                 generator.init(parameterSpecBuilder.build());
119                 return generator.generateKey();
120             } catch (GeneralSecurityException e) {
121                 // Should never happen.
122                 Slog.e(TAG, "Unable to generate key from keystore.", e);
123             }
124             return null;
125         }
126     }
127 }
128