1 /*
2  * Copyright (C) 2010 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.Environment;
20 import android.os.FileUtils;
21 import android.os.StrictMode;
22 
23 import libcore.io.IoUtils;
24 
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.security.NoSuchAlgorithmException;
29 import java.security.SecureRandom;
30 
31 import javax.crypto.KeyGenerator;
32 import javax.crypto.SecretKey;
33 
34 /**
35  *@hide
36  */
37 public class SystemKeyStore {
38 
39     private static final String SYSTEM_KEYSTORE_DIRECTORY = "misc/systemkeys";
40     private static final String KEY_FILE_EXTENSION = ".sks";
41     private static SystemKeyStore mInstance = new SystemKeyStore();
42 
SystemKeyStore()43     private SystemKeyStore() { }
44 
getInstance()45     public static SystemKeyStore getInstance() {
46         return mInstance;
47     }
48 
toHexString(byte[] keyData)49     public static String toHexString(byte[] keyData) {
50         if (keyData == null) {
51             return null;
52         }
53         int keyLen = keyData.length;
54         int expectedStringLen = keyData.length * 2;
55         StringBuilder sb = new StringBuilder(expectedStringLen);
56         for (int i = 0; i < keyData.length; i++) {
57             String hexStr = Integer.toString(keyData[i] & 0x00FF, 16);
58             if (hexStr.length() == 1) {
59                 hexStr = "0" + hexStr;
60             }
61             sb.append(hexStr);
62         }
63         return sb.toString();
64     }
65 
generateNewKeyHexString(int numBits, String algName, String keyName)66     public String generateNewKeyHexString(int numBits, String algName, String keyName)
67             throws NoSuchAlgorithmException {
68         return toHexString(generateNewKey(numBits, algName, keyName));
69     }
70 
generateNewKey(int numBits, String algName, String keyName)71     public byte[] generateNewKey(int numBits, String algName, String keyName)
72             throws NoSuchAlgorithmException {
73         StrictMode.noteDiskWrite();
74 
75         // Check if key with similar name exists. If so, return null.
76         File keyFile = getKeyFile(keyName);
77         if (keyFile.exists()) {
78             throw new IllegalArgumentException();
79         }
80 
81         KeyGenerator skg = KeyGenerator.getInstance(algName);
82         SecureRandom srng = SecureRandom.getInstance("SHA1PRNG");
83         skg.init(numBits, srng);
84 
85         SecretKey sk = skg.generateKey();
86         byte[] retKey = sk.getEncoded();
87 
88         try {
89             // Store the key
90             if (!keyFile.createNewFile()) {
91                 throw new IllegalArgumentException();
92             }
93 
94             FileOutputStream fos = new FileOutputStream(keyFile);
95             fos.write(retKey);
96             fos.flush();
97             FileUtils.sync(fos);
98             fos.close();
99             FileUtils.setPermissions(keyFile.getName(), (FileUtils.S_IRUSR | FileUtils.S_IWUSR),
100                 -1, -1);
101         } catch (IOException ioe) {
102             return null;
103         }
104         return retKey;
105     }
106 
getKeyFile(String keyName)107     private File getKeyFile(String keyName) {
108         StrictMode.noteDiskWrite();
109         File sysKeystoreDir = new File(Environment.getDataDirectory(),
110                 SYSTEM_KEYSTORE_DIRECTORY);
111         File keyFile = new File(sysKeystoreDir, keyName + KEY_FILE_EXTENSION);
112         return keyFile;
113     }
114 
retrieveKeyHexString(String keyName)115     public String retrieveKeyHexString(String keyName) throws IOException {
116         return toHexString(retrieveKey(keyName));
117     }
118 
retrieveKey(String keyName)119     public byte[] retrieveKey(String keyName) throws IOException {
120         StrictMode.noteDiskRead();
121         File keyFile = getKeyFile(keyName);
122         if (!keyFile.exists()) {
123             return null;
124         }
125         return IoUtils.readFileAsByteArray(keyFile.toString());
126     }
127 
deleteKey(String keyName)128     public void deleteKey(String keyName) {
129         StrictMode.noteDiskWrite();
130 
131         // Get the file first.
132         File keyFile = getKeyFile(keyName);
133         if (!keyFile.exists()) {
134             throw new IllegalArgumentException();
135         }
136 
137         keyFile.delete();
138     }
139 }
140