1 // Copyright 2020, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
16 //! data types and then tests 'to_sql' method for KeyParameters of those
17 //! different data types. The five different data types for KeyParameter values are:
18 //! i) enums of u32
19 //! ii) u32
20 //! iii) u64
21 //! iv) Vec<u8>
22 //! v) bool
23
24 use crate::error::*;
25 use crate::key_parameter::*;
26 use anyhow::Result;
27 use rusqlite::types::ToSql;
28 use rusqlite::{params, Connection};
29
30 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
31 /// from a database table row.
32 #[test]
test_new_from_sql_enum_i32() -> Result<()>33 fn test_new_from_sql_enum_i32() -> Result<()> {
34 let db = init_db()?;
35 insert_into_keyparameter(
36 &db,
37 1,
38 Tag::ALGORITHM.0,
39 &Algorithm::RSA.0,
40 SecurityLevel::STRONGBOX.0,
41 )?;
42 let key_param = query_from_keyparameter(&db)?;
43 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
44 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
45 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
46 Ok(())
47 }
48
49 /// Test initializing a KeyParameter (with key parameter value which is of i32)
50 /// from a database table row.
51 #[test]
test_new_from_sql_i32() -> Result<()>52 fn test_new_from_sql_i32() -> Result<()> {
53 let db = init_db()?;
54 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
55 let key_param = query_from_keyparameter(&db)?;
56 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
57 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
58 Ok(())
59 }
60
61 /// Test initializing a KeyParameter (with key parameter value which is of i64)
62 /// from a database table row.
63 #[test]
test_new_from_sql_i64() -> Result<()>64 fn test_new_from_sql_i64() -> Result<()> {
65 let db = init_db()?;
66 // max value for i64, just to test corner cases
67 insert_into_keyparameter(
68 &db,
69 1,
70 Tag::RSA_PUBLIC_EXPONENT.0,
71 &(i64::MAX),
72 SecurityLevel::STRONGBOX.0,
73 )?;
74 let key_param = query_from_keyparameter(&db)?;
75 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
76 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::RSAPublicExponent(i64::MAX));
77 Ok(())
78 }
79
80 /// Test initializing a KeyParameter (with key parameter value which is of bool)
81 /// from a database table row.
82 #[test]
test_new_from_sql_bool() -> Result<()>83 fn test_new_from_sql_bool() -> Result<()> {
84 let db = init_db()?;
85 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
86 let key_param = query_from_keyparameter(&db)?;
87 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
88 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
89 Ok(())
90 }
91
92 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
93 /// from a database table row.
94 #[test]
test_new_from_sql_vec_u8() -> Result<()>95 fn test_new_from_sql_vec_u8() -> Result<()> {
96 let db = init_db()?;
97 let app_id = String::from("MyAppID");
98 let app_id_bytes = app_id.into_bytes();
99 insert_into_keyparameter(
100 &db,
101 1,
102 Tag::APPLICATION_ID.0,
103 &app_id_bytes,
104 SecurityLevel::STRONGBOX.0,
105 )?;
106 let key_param = query_from_keyparameter(&db)?;
107 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
108 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::ApplicationID(app_id_bytes));
109 Ok(())
110 }
111
112 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
113 /// in the database
114 #[test]
test_to_sql_enum_i32() -> Result<()>115 fn test_to_sql_enum_i32() -> Result<()> {
116 let db = init_db()?;
117 let kp =
118 KeyParameter::new(KeyParameterValue::Algorithm(Algorithm::RSA), SecurityLevel::STRONGBOX);
119 store_keyparameter(&db, 1, &kp)?;
120 let key_param = query_from_keyparameter(&db)?;
121 assert_eq!(kp.get_tag(), key_param.get_tag());
122 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
123 assert_eq!(kp.security_level(), key_param.security_level());
124 Ok(())
125 }
126
127 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
128 #[test]
test_to_sql_i32() -> Result<()>129 fn test_to_sql_i32() -> Result<()> {
130 let db = init_db()?;
131 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
132 store_keyparameter(&db, 1, &kp)?;
133 let key_param = query_from_keyparameter(&db)?;
134 assert_eq!(kp.get_tag(), key_param.get_tag());
135 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
136 assert_eq!(kp.security_level(), key_param.security_level());
137 Ok(())
138 }
139
140 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
141 #[test]
test_to_sql_i64() -> Result<()>142 fn test_to_sql_i64() -> Result<()> {
143 let db = init_db()?;
144 // max value for i64, just to test corner cases
145 let kp =
146 KeyParameter::new(KeyParameterValue::RSAPublicExponent(i64::MAX), SecurityLevel::STRONGBOX);
147 store_keyparameter(&db, 1, &kp)?;
148 let key_param = query_from_keyparameter(&db)?;
149 assert_eq!(kp.get_tag(), key_param.get_tag());
150 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
151 assert_eq!(kp.security_level(), key_param.security_level());
152 Ok(())
153 }
154
155 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
156 #[test]
test_to_sql_vec_u8() -> Result<()>157 fn test_to_sql_vec_u8() -> Result<()> {
158 let db = init_db()?;
159 let kp = KeyParameter::new(
160 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
161 SecurityLevel::STRONGBOX,
162 );
163 store_keyparameter(&db, 1, &kp)?;
164 let key_param = query_from_keyparameter(&db)?;
165 assert_eq!(kp.get_tag(), key_param.get_tag());
166 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
167 assert_eq!(kp.security_level(), key_param.security_level());
168 Ok(())
169 }
170
171 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
172 #[test]
test_to_sql_bool() -> Result<()>173 fn test_to_sql_bool() -> Result<()> {
174 let db = init_db()?;
175 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
176 store_keyparameter(&db, 1, &kp)?;
177 let key_param = query_from_keyparameter(&db)?;
178 assert_eq!(kp.get_tag(), key_param.get_tag());
179 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
180 assert_eq!(kp.security_level(), key_param.security_level());
181 Ok(())
182 }
183
184 #[test]
185 /// Test Tag::Invalid
test_invalid_tag() -> Result<()>186 fn test_invalid_tag() -> Result<()> {
187 let db = init_db()?;
188 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
189 let key_param = query_from_keyparameter(&db)?;
190 assert_eq!(Tag::INVALID, key_param.get_tag());
191 Ok(())
192 }
193
194 #[test]
test_non_existing_enum_variant() -> Result<()>195 fn test_non_existing_enum_variant() -> Result<()> {
196 let db = init_db()?;
197 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
198 let key_param = query_from_keyparameter(&db)?;
199 assert_eq!(Tag::INVALID, key_param.get_tag());
200 Ok(())
201 }
202
203 #[test]
test_invalid_conversion_from_sql() -> Result<()>204 fn test_invalid_conversion_from_sql() -> Result<()> {
205 let db = init_db()?;
206 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
207 tests::check_result_contains_error_string(
208 query_from_keyparameter(&db),
209 "Failed to read sql data for tag: ALGORITHM.",
210 );
211 Ok(())
212 }
213
214 /// Helper method to init database table for key parameter
init_db() -> Result<Connection>215 fn init_db() -> Result<Connection> {
216 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
217 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
218 .context("Failed to attach databases.")?;
219 db.execute(
220 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
221 keyentryid INTEGER,
222 tag INTEGER,
223 data ANY,
224 security_level INTEGER);",
225 [],
226 )
227 .context("Failed to initialize \"keyparameter\" table.")?;
228 Ok(db)
229 }
230
231 /// Helper method to insert an entry into key parameter table, with individual parameters
insert_into_keyparameter<T: ToSql>( db: &Connection, key_id: i64, tag: i32, value: &T, security_level: i32, ) -> Result<()>232 fn insert_into_keyparameter<T: ToSql>(
233 db: &Connection,
234 key_id: i64,
235 tag: i32,
236 value: &T,
237 security_level: i32,
238 ) -> Result<()> {
239 db.execute(
240 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
241 VALUES(?, ?, ?, ?);",
242 params![key_id, tag, *value, security_level],
243 )?;
244 Ok(())
245 }
246
247 /// Helper method to store a key parameter instance.
store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()>248 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
249 db.execute(
250 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
251 VALUES(?, ?, ?, ?);",
252 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
253 )?;
254 Ok(())
255 }
256
257 /// Helper method to query a row from keyparameter table
query_from_keyparameter(db: &Connection) -> Result<KeyParameter>258 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
259 let mut stmt = db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
260 let mut rows = stmt.query([])?;
261 let row = rows.next()?.unwrap();
262 KeyParameter::new_from_sql(Tag(row.get(0)?), &SqlField::new(1, row), SecurityLevel(row.get(2)?))
263 }
264