blob: b0613da35d28860bdb352401d16dc48ab48c16e9 [file] [log] [blame]
Robert Berrybd086f12017-12-27 13:29:39 +00001/*
2 * Copyright (C) 2017 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
Robert Berry76cf0832017-12-15 23:01:22 +000017package com.android.server.locksettings.recoverablekeystore.storage;
18
19import android.content.Context;
20import android.database.sqlite.SQLiteDatabase;
21import android.database.sqlite.SQLiteOpenHelper;
Bo Zhu14d993d2018-02-03 21:38:48 -080022import android.util.Log;
Robert Berry76cf0832017-12-15 23:01:22 +000023
24import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
Bo Zhu584b923f2017-12-22 16:05:15 -080025import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -070026import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
Robert Berrybc088402017-12-18 13:10:41 +000027import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
Robert Berry76cf0832017-12-15 23:01:22 +000028
29/**
30 * Helper for creating the recoverable key database.
31 */
32class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
Bo Zhu14d993d2018-02-03 21:38:48 -080033 private static final String TAG = "RecoverableKeyStoreDbHp";
34
Bo Zhu7ebcd662019-01-04 17:00:58 -080035 static final int DATABASE_VERSION = 5;
Robert Berry76cf0832017-12-15 23:01:22 +000036 private static final String DATABASE_NAME = "recoverablekeystore.db";
37
Robert Berrybc088402017-12-18 13:10:41 +000038 private static final String SQL_CREATE_KEYS_ENTRY =
Robert Berry76cf0832017-12-15 23:01:22 +000039 "CREATE TABLE " + KeysEntry.TABLE_NAME + "( "
40 + KeysEntry._ID + " INTEGER PRIMARY KEY,"
Robert Berryb7c06ea2017-12-21 13:37:23 +000041 + KeysEntry.COLUMN_NAME_USER_ID + " INTEGER,"
Robert Berrybc088402017-12-18 13:10:41 +000042 + KeysEntry.COLUMN_NAME_UID + " INTEGER,"
43 + KeysEntry.COLUMN_NAME_ALIAS + " TEXT,"
Robert Berry76cf0832017-12-15 23:01:22 +000044 + KeysEntry.COLUMN_NAME_NONCE + " BLOB,"
45 + KeysEntry.COLUMN_NAME_WRAPPED_KEY + " BLOB,"
46 + KeysEntry.COLUMN_NAME_GENERATION_ID + " INTEGER,"
Robert Berrybc088402017-12-18 13:10:41 +000047 + KeysEntry.COLUMN_NAME_LAST_SYNCED_AT + " INTEGER,"
Dmitry Dementyevad884712017-12-20 12:38:36 -080048 + KeysEntry.COLUMN_NAME_RECOVERY_STATUS + " INTEGER,"
Bo Zhu7ebcd662019-01-04 17:00:58 -080049 + KeysEntry.COLUMN_NAME_KEY_METADATA + " BLOB,"
Robert Berrybc088402017-12-18 13:10:41 +000050 + "UNIQUE(" + KeysEntry.COLUMN_NAME_UID + ","
51 + KeysEntry.COLUMN_NAME_ALIAS + "))";
Robert Berry76cf0832017-12-15 23:01:22 +000052
Robert Berrybc088402017-12-18 13:10:41 +000053 private static final String SQL_CREATE_USER_METADATA_ENTRY =
54 "CREATE TABLE " + UserMetadataEntry.TABLE_NAME + "( "
55 + UserMetadataEntry._ID + " INTEGER PRIMARY KEY,"
56 + UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE,"
57 + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)";
58
Dmitry Dementyev77183ef2018-01-05 15:46:00 -080059 private static final String SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY =
Bo Zhu584b923f2017-12-22 16:05:15 -080060 "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
61 + RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY,"
62 + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER,"
63 + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER,"
Dmitry Dementyev77183ef2018-01-05 15:46:00 -080064 + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER,"
65 + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER,"
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -070066 + RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST + " TEXT,"
Bo Zhu584b923f2017-12-22 16:05:15 -080067 + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
Bo Zhu14d993d2018-02-03 21:38:48 -080068 + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
69 + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
Dmitry Dementyevbdfdf532017-12-27 11:58:45 -080070 + RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT,"
Dmitry Dementyev77183ef2018-01-05 15:46:00 -080071 + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER,"
Dmitry Dementyev7d8c78a2018-01-12 19:14:07 -080072 + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS + " BLOB,"
Bo Zhu5b81fa62017-12-21 14:36:11 -080073 + "UNIQUE("
Bo Zhu584b923f2017-12-22 16:05:15 -080074 + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + ","
75 + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + "))";
Bo Zhu5b81fa62017-12-21 14:36:11 -080076
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -070077 private static final String SQL_CREATE_ROOT_OF_TRUST_ENTRY =
78 "CREATE TABLE " + RootOfTrustEntry.TABLE_NAME + " ("
79 + RootOfTrustEntry._ID + " INTEGER PRIMARY KEY,"
80 + RootOfTrustEntry.COLUMN_NAME_USER_ID + " INTEGER,"
81 + RootOfTrustEntry.COLUMN_NAME_UID + " INTEGER,"
82 + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " TEST,"
83 + RootOfTrustEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
84 + RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
85 + "UNIQUE("
86 + RootOfTrustEntry.COLUMN_NAME_USER_ID + ","
87 + RootOfTrustEntry.COLUMN_NAME_UID + ","
88 + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + "))";
89
Robert Berrybc088402017-12-18 13:10:41 +000090 private static final String SQL_DELETE_KEYS_ENTRY =
Robert Berry76cf0832017-12-15 23:01:22 +000091 "DROP TABLE IF EXISTS " + KeysEntry.TABLE_NAME;
92
Robert Berrybc088402017-12-18 13:10:41 +000093 private static final String SQL_DELETE_USER_METADATA_ENTRY =
94 "DROP TABLE IF EXISTS " + UserMetadataEntry.TABLE_NAME;
95
Dmitry Dementyev77183ef2018-01-05 15:46:00 -080096 private static final String SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY =
Bo Zhu584b923f2017-12-22 16:05:15 -080097 "DROP TABLE IF EXISTS " + RecoveryServiceMetadataEntry.TABLE_NAME;
Bo Zhu5b81fa62017-12-21 14:36:11 -080098
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -070099 private static final String SQL_DELETE_ROOT_OF_TRUST_ENTRY =
100 "DROP TABLE IF EXISTS " + RootOfTrustEntry.TABLE_NAME;
101
Robert Berry76cf0832017-12-15 23:01:22 +0000102 RecoverableKeyStoreDbHelper(Context context) {
103 super(context, DATABASE_NAME, null, DATABASE_VERSION);
104 }
105
106 @Override
107 public void onCreate(SQLiteDatabase db) {
Robert Berrybc088402017-12-18 13:10:41 +0000108 db.execSQL(SQL_CREATE_KEYS_ENTRY);
109 db.execSQL(SQL_CREATE_USER_METADATA_ENTRY);
Dmitry Dementyev77183ef2018-01-05 15:46:00 -0800110 db.execSQL(SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY);
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700111 db.execSQL(SQL_CREATE_ROOT_OF_TRUST_ENTRY);
112 }
113
114 @Override
115 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
116 Log.e(TAG, "Recreating recoverablekeystore after unexpected version downgrade.");
117 dropAllKnownTables(db); // Wipe database.
118 onCreate(db);
Robert Berry76cf0832017-12-15 23:01:22 +0000119 }
120
121 @Override
122 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Bo Zhu14d993d2018-02-03 21:38:48 -0800123 if (oldVersion < 2) {
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700124 dropAllKnownTables(db); // Wipe database.
Bo Zhu14d993d2018-02-03 21:38:48 -0800125 onCreate(db);
126 return;
127 }
128
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700129 if (oldVersion < 3 && newVersion >= 3) {
Bo Zhu14d993d2018-02-03 21:38:48 -0800130 upgradeDbForVersion3(db);
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700131 oldVersion = 3;
Bo Zhu14d993d2018-02-03 21:38:48 -0800132 }
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700133
134 if (oldVersion < 4 && newVersion >= 4) {
135 upgradeDbForVersion4(db);
136 oldVersion = 4;
137 }
138
Bo Zhu7ebcd662019-01-04 17:00:58 -0800139 if (oldVersion < 5 && newVersion >= 5) {
140 upgradeDbForVersion5(db);
141 oldVersion = 5;
142 }
143
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700144 if (oldVersion != newVersion) {
145 Log.e(TAG, "Failed to update recoverablekeystore database to the most recent version");
146 }
147 }
148
149 private void dropAllKnownTables(SQLiteDatabase db) {
150 db.execSQL(SQL_DELETE_KEYS_ENTRY);
151 db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
152 db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
153 db.execSQL(SQL_DELETE_ROOT_OF_TRUST_ENTRY);
Bo Zhu14d993d2018-02-03 21:38:48 -0800154 }
155
156 private void upgradeDbForVersion3(SQLiteDatabase db) {
157 // Add the two columns for cert path and cert serial number
158 addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
159 RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, "BLOB", /*defaultStr=*/ null);
160 addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
161 RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, "INTEGER", /*defaultStr=*/
162 null);
163 }
164
Dmitry Dementyevf34fc7e2018-03-26 17:31:29 -0700165 private void upgradeDbForVersion4(SQLiteDatabase db) {
166 Log.d(TAG, "Updating recoverable keystore database to version 4");
167 // Add new table with two columns for cert path and cert serial number.
168 db.execSQL(SQL_CREATE_ROOT_OF_TRUST_ENTRY);
169 // adds column to store root of trust currently used by the recovery agent
170 addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME,
171 RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST, "TEXT",
172 /*defaultStr=*/ null);
173 }
174
Bo Zhu7ebcd662019-01-04 17:00:58 -0800175 private void upgradeDbForVersion5(SQLiteDatabase db) {
176 Log.d(TAG, "Updating recoverable keystore database to version 5");
177 // adds a column to store the metadata for application keys
178 addColumnToTable(db, KeysEntry.TABLE_NAME,
179 KeysEntry.COLUMN_NAME_KEY_METADATA, "BLOB", /*defaultStr=*/ null);
180 }
181
Bo Zhu14d993d2018-02-03 21:38:48 -0800182 private static void addColumnToTable(
183 SQLiteDatabase db, String tableName, String column, String columnType,
184 String defaultStr) {
185 Log.d(TAG, "Adding column " + column + " to " + tableName + ".");
186
187 String alterStr = "ALTER TABLE " + tableName + " ADD COLUMN " + column + " " + columnType;
188 if (defaultStr != null && !defaultStr.isEmpty()) {
189 alterStr += " DEFAULT " + defaultStr;
190 }
191
192 db.execSQL(alterStr + ";");
Robert Berry76cf0832017-12-15 23:01:22 +0000193 }
194}
Bo Zhu14d993d2018-02-03 21:38:48 -0800195