• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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