blob: 5266c28029c878f96b7adc0bd96f6cf0a4e7e6b8 [file] [log] [blame]
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001// 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//! KeyParameter is used to express different characteristics of a key requested by the user
16//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
17//! and the methods to work with KeyParameter.
18
Hasini Gunasingheaf993662020-07-24 18:40:20 +000019use crate::error::Error as KeystoreError;
Janis Danisevskise24f3472020-08-12 17:58:49 -070020use crate::error::Rc;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000021pub use android_hardware_keymint::aidl::android::hardware::keymint::{
22 Algorithm, Algorithm::Algorithm as AlgorithmType, BlockMode,
23 BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
24 EcCurve::EcCurve as EcCurveType, HardwareAuthenticatorType,
25 HardwareAuthenticatorType::HardwareAuthenticatorType as HardwareAuthenticatorTypeType,
26 KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType, KeyPurpose,
27 KeyPurpose::KeyPurpose as KeyPurposeType, PaddingMode,
28 PaddingMode::PaddingMode as PaddingModeType, SecurityLevel,
29 SecurityLevel::SecurityLevel as SecurityLevelType, Tag, Tag::Tag as TagType,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000030};
Hasini Gunasingheaf993662020-07-24 18:40:20 +000031use anyhow::{Context, Result};
32use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
33use rusqlite::{Result as SqlResult, Row};
Hasini Gunasinghe12486362020-07-24 18:40:20 +000034
35/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
36pub struct KeyParameter {
37 key_parameter_value: KeyParameterValue,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000038 security_level: SecurityLevelType,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000039}
40
41/// KeyParameterValue holds a value corresponding to one of the Tags defined in
42/// the AIDL spec at hardware/interfaces/keymint
43#[derive(PartialEq, Debug)]
44pub enum KeyParameterValue {
45 /// Associated with Tag:INVALID
46 Invalid,
47 /// Set of purposes for which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +000048 KeyPurpose(KeyPurposeType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000049 /// Cryptographic algorithm with which the key is used
Hasini Gunasingheaf993662020-07-24 18:40:20 +000050 Algorithm(AlgorithmType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000051 /// Size of the key , in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +000052 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000053 /// Block cipher mode(s) with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +000054 BlockMode(BlockModeType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000055 /// Digest algorithms that may be used with the key to perform signing and verification
Hasini Gunasingheaf993662020-07-24 18:40:20 +000056 Digest(DigestType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000057 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Hasini Gunasingheaf993662020-07-24 18:40:20 +000058 PaddingMode(PaddingModeType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000059 /// Can the caller provide a nonce for nonce-requiring operations
60 CallerNonce,
61 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Hasini Gunasingheaf993662020-07-24 18:40:20 +000062 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000063 /// The elliptic curve
Hasini Gunasingheaf993662020-07-24 18:40:20 +000064 EcCurve(EcCurveType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000065 /// Value of the public exponent for an RSA key pair
Hasini Gunasingheaf993662020-07-24 18:40:20 +000066 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000067 /// An attestation certificate for the generated key should contain an application-scoped
68 /// and time-bounded device-unique ID
69 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000070 //TODO: find out about this
71 // /// Necessary system environment conditions for the generated key to be used
72 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000073 /// Only the boot loader can use the key
74 BootLoaderOnly,
75 /// When deleted, the key is guaranteed to be permanently deleted and unusable
76 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000077 /// The date and time at which the key becomes active
Hasini Gunasingheaf993662020-07-24 18:40:20 +000078 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000079 /// The date and time at which the key expires for signing and encryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000080 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000081 /// The date and time at which the key expires for verification and decryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000082 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000083 /// Minimum amount of time that elapses between allowed operations
Hasini Gunasingheaf993662020-07-24 18:40:20 +000084 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000085 /// Maximum number of times that a key may be used between system reboots
Hasini Gunasingheaf993662020-07-24 18:40:20 +000086 MaxUsesPerBoot(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000087 /// ID of the Android user that is permitted to use the key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000088 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000089 /// A key may only be used under a particular secure user authentication state
Hasini Gunasingheaf993662020-07-24 18:40:20 +000090 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000091 /// No authentication is required to use this key
92 NoAuthRequired,
93 /// The types of user authenticators that may be used to authorize this key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000094 HardwareAuthenticatorType(HardwareAuthenticatorTypeType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000095 /// The time in seconds for which the key is authorized for use, after user authentication
Hasini Gunasingheaf993662020-07-24 18:40:20 +000096 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000097 /// The key may be used after authentication timeout if device is still on-body
98 AllowWhileOnBody,
99 /// The key must be unusable except when the user has provided proof of physical presence
100 TrustedUserPresenceRequired,
101 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
102 /// unless the user provides confirmation of the data to be signed
103 TrustedConfirmationRequired,
104 /// The key may only be used when the device is unlocked
105 UnlockedDeviceRequired,
106 /// When provided to generateKey or importKey, this tag specifies data
107 /// that is necessary during all uses of the key
108 ApplicationID(Vec<u8>),
109 /// When provided to generateKey or importKey, this tag specifies data
110 /// that is necessary during all uses of the key
111 ApplicationData(Vec<u8>),
112 /// Specifies the date and time the key was created
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000113 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000114 /// Specifies where the key was created, if known
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000115 KeyOrigin(KeyOriginType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000116 /// The key used by verified boot to validate the operating system booted
117 RootOfTrust(Vec<u8>),
118 /// System OS version with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000119 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000120 /// Specifies the system security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000121 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000122 /// Specifies a unique, time-based identifier
123 UniqueID(Vec<u8>),
124 /// Used to deliver a "challenge" value to the attestKey() method
125 AttestationChallenge(Vec<u8>),
126 /// The set of applications which may use a key, used only with attestKey()
127 AttestationApplicationID(Vec<u8>),
128 /// Provides the device's brand name, to attestKey()
129 AttestationIdBrand(Vec<u8>),
130 /// Provides the device's device name, to attestKey()
131 AttestationIdDevice(Vec<u8>),
132 /// Provides the device's product name, to attestKey()
133 AttestationIdProduct(Vec<u8>),
134 /// Provides the device's serial number, to attestKey()
135 AttestationIdSerial(Vec<u8>),
136 /// Provides the IMEIs for all radios on the device, to attestKey()
137 AttestationIdIMEI(Vec<u8>),
138 /// Provides the MEIDs for all radios on the device, to attestKey()
139 AttestationIdMEID(Vec<u8>),
140 /// Provides the device's manufacturer name, to attestKey()
141 AttestationIdManufacturer(Vec<u8>),
142 /// Provides the device's model name, to attestKey()
143 AttestationIdModel(Vec<u8>),
144 /// Specifies the vendor image security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000145 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000146 /// Specifies the boot image (kernel) security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000147 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000148 /// Provides "associated data" for AES-GCM encryption or decryption
149 AssociatedData(Vec<u8>),
150 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
151 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
152 Nonce(Vec<u8>),
153 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000154 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000155 /// Specifies whether the device has been factory reset since the
156 /// last unique ID rotation. Used for key attestation
157 ResetSinceIdRotation,
158 /// Used to deliver a cryptographic token proving that the user
159 /// confirmed a signing request
160 ConfirmationToken(Vec<u8>),
161}
162
163impl KeyParameter {
164 /// Create an instance of KeyParameter, given the value and the security level.
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000165 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevelType) -> Self {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000166 KeyParameter { key_parameter_value, security_level }
167 }
168
169 /// Returns the tag given the KeyParameter instance.
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000170 pub fn get_tag(&self) -> TagType {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000171 match self.key_parameter_value {
172 KeyParameterValue::Invalid => Tag::INVALID,
173 KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
174 KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
175 KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
176 KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
177 KeyParameterValue::Digest(_) => Tag::DIGEST,
178 KeyParameterValue::PaddingMode(_) => Tag::PADDING,
179 KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
180 KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
181 KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
182 KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
183 KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000184 KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
185 KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
186 KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
187 KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
188 KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
189 KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
190 KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
191 KeyParameterValue::UserID(_) => Tag::USER_ID,
192 KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
193 KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
194 KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
195 KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
196 KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
197 KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
198 KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
199 KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
200 KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
201 KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
202 KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
203 KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
204 KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
205 KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
206 KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
207 KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
208 KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
209 KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
210 KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
211 KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
212 KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
213 KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
214 KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
215 KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
216 KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
217 KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
218 KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
219 KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
220 KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
221 KeyParameterValue::Nonce(_) => Tag::NONCE,
222 KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
223 KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
224 KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
225 }
226 }
227
228 /// Returns key parameter value.
229 pub fn key_parameter_value(&self) -> &KeyParameterValue {
230 &self.key_parameter_value
231 }
232
233 /// Returns the security level of a KeyParameter.
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000234 pub fn security_level(&self) -> &SecurityLevelType {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000235 &self.security_level
236 }
237}
238
239#[cfg(test)]
240mod basic_tests {
241 use crate::key_parameter::*;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000242
243 // Test basic functionality of KeyParameter.
244 #[test]
245 fn test_key_parameter() {
246 let key_parameter = KeyParameter::new(
247 KeyParameterValue::Algorithm(Algorithm::RSA),
248 SecurityLevel::STRONGBOX,
249 );
250
251 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
252
253 assert_eq!(
254 *key_parameter.key_parameter_value(),
255 KeyParameterValue::Algorithm(Algorithm::RSA)
256 );
257
258 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
259 }
260}
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000261
262/// This struct is defined to postpone converting rusqlite column value to the
263/// appropriate key parameter value until we know the corresponding tag value.
264/// Wraps the column index and a rusqlite row.
265pub struct SqlField<'a>(usize, &'a Row<'a>);
266
267impl<'a> SqlField<'a> {
268 /// Returns the column value from the row, when we know the expected type.
269 pub fn get<T: FromSql>(&self) -> SqlResult<T> {
270 self.1.get(self.0)
271 }
272}
273
274impl ToSql for KeyParameterValue {
275 /// Converts KeyParameterValue to be stored in rusqlite database.
276 /// Note that following variants of KeyParameterValue should not be stored:
277 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
278 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
279 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
280 /// conversion for all the variants, to keep error handling simple.
281 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
282 match self {
283 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
284 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(*k as u32)),
285 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(*a as u32)),
286 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
287 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(*b as u32)),
288 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(*d as u32)),
289 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(*p as u32)),
290 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
291 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
292 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(*e as u32)),
293 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
294 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
295 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
296 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
297 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
298 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
299 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
300 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
301 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
302 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
303 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
304 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
305 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(*h as u32)),
306 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
307 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
308 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
309 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
310 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
311 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
312 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
313 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
314 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(*k as u32)),
315 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
316 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
317 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
318 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
319 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
320 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
321 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
322 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
323 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
324 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
325 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
326 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
327 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
328 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
329 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
330 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
331 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
332 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
333 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
334 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
335 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
336 }
337 }
338}
339
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000340impl KeyParameter {
341 /// Construct a KeyParameter from the data from a rusqlite row.
342 /// Note that following variants of KeyParameterValue should not be stored:
343 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
344 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
345 /// This filtering is enforced at a higher level and here we support conversion for all the
346 /// variants.
347 pub fn new_from_sql(
348 tag_val: TagType,
349 data: &SqlField,
350 security_level_val: SecurityLevelType,
351 ) -> Result<Self> {
352 let key_param_value = match tag_val {
353 Tag::INVALID => KeyParameterValue::Invalid,
354 Tag::PURPOSE => {
355 let key_purpose: KeyPurposeType = data
356 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700357 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700358 .context("Failed to read sql data for tag: PURPOSE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000359 KeyParameterValue::KeyPurpose(key_purpose)
360 }
361 Tag::ALGORITHM => {
362 let algorithm: AlgorithmType = data
363 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700364 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700365 .context("Failed to read sql data for tag: ALGORITHM.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000366 KeyParameterValue::Algorithm(algorithm)
367 }
368 Tag::KEY_SIZE => {
369 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700370 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000371 KeyParameterValue::KeySize(key_size)
372 }
373 Tag::BLOCK_MODE => {
374 let block_mode: BlockModeType = data
375 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700376 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700377 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000378 KeyParameterValue::BlockMode(block_mode)
379 }
380 Tag::DIGEST => {
381 let digest: DigestType = data
382 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700383 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700384 .context("Failed to read sql data for tag: DIGEST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000385 KeyParameterValue::Digest(digest)
386 }
387 Tag::PADDING => {
388 let padding: PaddingModeType = data
389 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700390 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700391 .context("Failed to read sql data for tag: PADDING.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000392 KeyParameterValue::PaddingMode(padding)
393 }
394 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
395 Tag::MIN_MAC_LENGTH => {
396 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700397 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000398 KeyParameterValue::MinMacLength(min_mac_length)
399 }
400 Tag::EC_CURVE => {
401 let ec_curve: EcCurveType = data
402 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700403 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700404 .context("Failed to read sql data for tag: EC_CURVE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000405 KeyParameterValue::EcCurve(ec_curve)
406 }
407 Tag::RSA_PUBLIC_EXPONENT => {
408 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700409 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000410
411 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
412 }
413 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
414 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
415 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
416 Tag::ACTIVE_DATETIME => {
417 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700418 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000419 KeyParameterValue::ActiveDateTime(active_datetime)
420 }
421 Tag::ORIGINATION_EXPIRE_DATETIME => {
422 let origination_expire_datetime: i64 = data
423 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700424 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000425 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
426 }
427 Tag::USAGE_EXPIRE_DATETIME => {
428 let usage_expire_datetime: i64 = data
429 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700430 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000431 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
432 }
433 Tag::MIN_SECONDS_BETWEEN_OPS => {
434 let min_secs_between_ops: i32 = data
435 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700436 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000437 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
438 }
439 Tag::MAX_USES_PER_BOOT => {
440 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700441 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000442 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
443 }
444 Tag::USER_ID => {
445 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700446 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000447 KeyParameterValue::UserID(user_id)
448 }
449 Tag::USER_SECURE_ID => {
450 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700451 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000452 KeyParameterValue::UserSecureID(user_secure_id)
453 }
454 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
455 Tag::USER_AUTH_TYPE => {
456 let user_auth_type: HardwareAuthenticatorTypeType = data
457 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700458 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700459 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000460 KeyParameterValue::HardwareAuthenticatorType(user_auth_type)
461 }
462 Tag::AUTH_TIMEOUT => {
463 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700464 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000465 KeyParameterValue::AuthTimeout(auth_timeout)
466 }
467 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
468 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
469 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
470 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
471 Tag::APPLICATION_ID => {
472 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700473 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000474 KeyParameterValue::ApplicationID(app_id)
475 }
476 Tag::APPLICATION_DATA => {
477 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700478 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000479 KeyParameterValue::ApplicationData(app_data)
480 }
481 Tag::CREATION_DATETIME => {
482 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700483 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000484 KeyParameterValue::CreationDateTime(creation_datetime)
485 }
486 Tag::ORIGIN => {
487 let origin: KeyOriginType = data
488 .get()
Janis Danisevskise24f3472020-08-12 17:58:49 -0700489 .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700490 .context("Failed to read sql data for tag: ORIGIN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000491 KeyParameterValue::KeyOrigin(origin)
492 }
493 Tag::ROOT_OF_TRUST => {
494 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700495 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000496 KeyParameterValue::RootOfTrust(root_of_trust)
497 }
498 Tag::OS_VERSION => {
499 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700500 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000501 KeyParameterValue::OSVersion(os_version)
502 }
503 Tag::OS_PATCHLEVEL => {
504 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700505 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000506 KeyParameterValue::OSPatchLevel(os_patch_level)
507 }
508 Tag::UNIQUE_ID => {
509 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700510 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000511 KeyParameterValue::UniqueID(unique_id)
512 }
513 Tag::ATTESTATION_CHALLENGE => {
514 let attestation_challenge: Vec<u8> = data
515 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700516 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000517 KeyParameterValue::AttestationChallenge(attestation_challenge)
518 }
519 Tag::ATTESTATION_APPLICATION_ID => {
520 let attestation_app_id: Vec<u8> = data
521 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700522 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000523 KeyParameterValue::AttestationApplicationID(attestation_app_id)
524 }
525 Tag::ATTESTATION_ID_BRAND => {
526 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700527 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000528 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
529 }
530 Tag::ATTESTATION_ID_DEVICE => {
531 let attestation_id_device: Vec<u8> = data
532 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700533 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000534 KeyParameterValue::AttestationIdDevice(attestation_id_device)
535 }
536 Tag::ATTESTATION_ID_PRODUCT => {
537 let attestation_id_product: Vec<u8> = data
538 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700539 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000540 KeyParameterValue::AttestationIdProduct(attestation_id_product)
541 }
542 Tag::ATTESTATION_ID_SERIAL => {
543 let attestation_id_serial: Vec<u8> = data
544 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700545 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000546 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
547 }
548 Tag::ATTESTATION_ID_IMEI => {
549 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700550 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000551 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
552 }
553 Tag::ATTESTATION_ID_MEID => {
554 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700555 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000556 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
557 }
558 Tag::ATTESTATION_ID_MANUFACTURER => {
559 let attestation_id_manufacturer: Vec<u8> = data
560 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700561 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000562 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
563 }
564 Tag::ATTESTATION_ID_MODEL => {
565 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700566 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000567 KeyParameterValue::AttestationIdModel(attestation_id_model)
568 }
569 Tag::VENDOR_PATCHLEVEL => {
570 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700571 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000572 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
573 }
574 Tag::BOOT_PATCHLEVEL => {
575 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700576 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000577 KeyParameterValue::BootPatchLevel(boot_patch_level)
578 }
579 Tag::ASSOCIATED_DATA => {
580 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700581 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000582 KeyParameterValue::AssociatedData(associated_data)
583 }
584 Tag::NONCE => {
585 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700586 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000587 KeyParameterValue::Nonce(nonce)
588 }
589 Tag::MAC_LENGTH => {
590 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700591 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000592 KeyParameterValue::MacLength(mac_length)
593 }
594 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
595 Tag::CONFIRMATION_TOKEN => {
596 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700597 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000598 KeyParameterValue::ConfirmationToken(confirmation_token)
599 }
600 _ => {
Janis Danisevskise24f3472020-08-12 17:58:49 -0700601 return Err(KeystoreError::Rc(Rc::ValueCorrupted))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700602 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000603 }
604 };
605 Ok(KeyParameter::new(key_param_value, security_level_val))
606 }
607}
608
609/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
610/// data types and then tests 'to_sql' method for KeyParameters of those
611/// different data types. The five different data types for KeyParameter values are:
612/// i) enums of u32
613/// ii) u32
614/// iii) u64
615/// iv) Vec<u8>
616/// v) bool
617#[cfg(test)]
618mod storage_tests {
619 use crate::error::*;
620 use crate::key_parameter::*;
621 use anyhow::Result;
622 use rusqlite::types::ToSql;
623 use rusqlite::{params, Connection, NO_PARAMS};
624
625 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
626 /// from a database table row.
627 #[test]
628 fn test_new_from_sql_enum_i32() -> Result<()> {
629 let db = init_db()?;
630 insert_into_keyparameter(
631 &db,
632 1,
633 Tag::ALGORITHM,
634 &Algorithm::RSA,
635 SecurityLevel::STRONGBOX,
636 )?;
637 let key_param = query_from_keyparameter(&db)?;
638 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
639 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
640 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
641 Ok(())
642 }
643
644 /// Test initializing a KeyParameter (with key parameter value which is of i32)
645 /// from a database table row.
646 #[test]
647 fn test_new_from_sql_i32() -> Result<()> {
648 let db = init_db()?;
649 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE, &1024, SecurityLevel::STRONGBOX)?;
650 let key_param = query_from_keyparameter(&db)?;
651 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
652 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
653 Ok(())
654 }
655
656 /// Test initializing a KeyParameter (with key parameter value which is of i64)
657 /// from a database table row.
658 #[test]
659 fn test_new_from_sql_i64() -> Result<()> {
660 let db = init_db()?;
661 // max value for i64, just to test corner cases
662 insert_into_keyparameter(
663 &db,
664 1,
665 Tag::RSA_PUBLIC_EXPONENT,
666 &(i64::MAX),
667 SecurityLevel::STRONGBOX,
668 )?;
669 let key_param = query_from_keyparameter(&db)?;
670 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
671 assert_eq!(
672 *key_param.key_parameter_value(),
673 KeyParameterValue::RSAPublicExponent(i64::MAX)
674 );
675 Ok(())
676 }
677
678 /// Test initializing a KeyParameter (with key parameter value which is of bool)
679 /// from a database table row.
680 #[test]
681 fn test_new_from_sql_bool() -> Result<()> {
682 let db = init_db()?;
683 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE, &Null, SecurityLevel::STRONGBOX)?;
684 let key_param = query_from_keyparameter(&db)?;
685 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
686 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
687 Ok(())
688 }
689
690 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
691 /// from a database table row.
692 #[test]
693 fn test_new_from_sql_vec_u8() -> Result<()> {
694 let db = init_db()?;
695 let app_id = String::from("MyAppID");
696 let app_id_bytes = app_id.into_bytes();
697 insert_into_keyparameter(
698 &db,
699 1,
700 Tag::APPLICATION_ID,
701 &app_id_bytes,
702 SecurityLevel::STRONGBOX,
703 )?;
704 let key_param = query_from_keyparameter(&db)?;
705 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
706 assert_eq!(
707 *key_param.key_parameter_value(),
708 KeyParameterValue::ApplicationID(app_id_bytes)
709 );
710 Ok(())
711 }
712
713 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
714 /// in the database
715 #[test]
716 fn test_to_sql_enum_i32() -> Result<()> {
717 let db = init_db()?;
718 let kp = KeyParameter::new(
719 KeyParameterValue::Algorithm(Algorithm::RSA),
720 SecurityLevel::STRONGBOX,
721 );
722 store_keyparameter(&db, 1, &kp)?;
723 let key_param = query_from_keyparameter(&db)?;
724 assert_eq!(kp.get_tag(), key_param.get_tag());
725 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
726 assert_eq!(kp.security_level(), key_param.security_level());
727 Ok(())
728 }
729
730 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
731 #[test]
732 fn test_to_sql_i32() -> Result<()> {
733 let db = init_db()?;
734 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
735 store_keyparameter(&db, 1, &kp)?;
736 let key_param = query_from_keyparameter(&db)?;
737 assert_eq!(kp.get_tag(), key_param.get_tag());
738 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
739 assert_eq!(kp.security_level(), key_param.security_level());
740 Ok(())
741 }
742
743 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
744 #[test]
745 fn test_to_sql_i64() -> Result<()> {
746 let db = init_db()?;
747 // max value for i64, just to test corner cases
748 let kp = KeyParameter::new(
749 KeyParameterValue::RSAPublicExponent(i64::MAX),
750 SecurityLevel::STRONGBOX,
751 );
752 store_keyparameter(&db, 1, &kp)?;
753 let key_param = query_from_keyparameter(&db)?;
754 assert_eq!(kp.get_tag(), key_param.get_tag());
755 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
756 assert_eq!(kp.security_level(), key_param.security_level());
757 Ok(())
758 }
759
760 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
761 #[test]
762 fn test_to_sql_vec_u8() -> Result<()> {
763 let db = init_db()?;
764 let kp = KeyParameter::new(
765 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
766 SecurityLevel::STRONGBOX,
767 );
768 store_keyparameter(&db, 1, &kp)?;
769 let key_param = query_from_keyparameter(&db)?;
770 assert_eq!(kp.get_tag(), key_param.get_tag());
771 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
772 assert_eq!(kp.security_level(), key_param.security_level());
773 Ok(())
774 }
775
776 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
777 #[test]
778 fn test_to_sql_bool() -> Result<()> {
779 let db = init_db()?;
780 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
781 store_keyparameter(&db, 1, &kp)?;
782 let key_param = query_from_keyparameter(&db)?;
783 assert_eq!(kp.get_tag(), key_param.get_tag());
784 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
785 assert_eq!(kp.security_level(), key_param.security_level());
786 Ok(())
787 }
788
789 #[test]
790 /// Test Tag::Invalid
791 fn test_invalid_tag() -> Result<()> {
792 let db = init_db()?;
793 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
794 let key_param = query_from_keyparameter(&db)?;
795 assert_eq!(Tag::INVALID, key_param.get_tag());
796 Ok(())
797 }
798
799 #[test]
800 fn test_non_existing_enum_variant() -> Result<()> {
801 let db = init_db()?;
802 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
803 tests::check_result_contains_error_string(
804 query_from_keyparameter(&db),
805 "Failed to decode Tag enum from value.",
806 );
807 Ok(())
808 }
809
810 #[test]
811 fn test_invalid_conversion_from_sql() -> Result<()> {
812 let db = init_db()?;
813 insert_into_keyparameter(&db, 1, Tag::ALGORITHM, &Null, 1)?;
814 tests::check_result_contains_error_string(
815 query_from_keyparameter(&db),
816 "Failed to read sql data for tag: ALGORITHM.",
817 );
818 Ok(())
819 }
820
821 /// Helper method to init database table for key parameter
822 fn init_db() -> Result<Connection> {
823 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
824 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
825 .context("Failed to attach databases.")?;
826 db.execute(
827 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
828 keyentryid INTEGER,
829 tag INTEGER,
830 data ANY,
831 security_level INTEGER);",
832 NO_PARAMS,
833 )
834 .context("Failed to initialize \"keyparameter\" table.")?;
835 Ok(db)
836 }
837
838 /// Helper method to insert an entry into key parameter table, with individual parameters
839 fn insert_into_keyparameter<T: ToSql>(
840 db: &Connection,
841 key_id: i64,
842 tag: i32,
843 value: &T,
844 security_level: i32,
845 ) -> Result<()> {
846 db.execute(
847 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
848VALUES(?, ?, ?, ?);",
849 params![key_id, tag, *value, security_level],
850 )?;
851 Ok(())
852 }
853
854 /// Helper method to store a key parameter instance.
855 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
856 db.execute(
857 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
858VALUES(?, ?, ?, ?);",
859 params![key_id, kp.get_tag(), kp.key_parameter_value(), kp.security_level()],
860 )?;
861 Ok(())
862 }
863
864 /// Helper method to query a row from keyparameter table
865 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
866 let mut stmt = db.prepare(
867 "SELECT tag, data, security_level FROM
868persistent.keyparameter",
869 )?;
870 let mut rows = stmt.query(NO_PARAMS)?;
871 let row = rows.next()?.unwrap();
872 Ok(KeyParameter::new_from_sql(row.get(0)?, &SqlField(1, row), row.get(2)?)?)
873 }
874}