blob: e5a6d08cad8be56533a1ac2655ef28b91f0f1ca1 [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 Danisevskisc5b210b2020-09-11 13:27:37 -070020use crate::error::ResponseCode;
21
Shawn Willden708744a2020-12-11 13:05:27 +000022pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070023 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
24 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
Janis Danisevskis398e6be2020-12-17 09:29:25 -080025 KeyParameter::KeyParameter as KmKeyParameter,
26 KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
27 PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000028};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070029use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000030use anyhow::{Context, Result};
31use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
32use rusqlite::{Result as SqlResult, Row};
Hasini Gunasinghe12486362020-07-24 18:40:20 +000033
34/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070035#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000036pub struct KeyParameter {
37 key_parameter_value: KeyParameterValue,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070038 security_level: SecurityLevel,
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
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070043#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000044pub enum KeyParameterValue {
45 /// Associated with Tag:INVALID
46 Invalid,
47 /// Set of purposes for which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070048 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000049 /// Cryptographic algorithm with which the key is used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070050 Algorithm(Algorithm),
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
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070054 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000055 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070056 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000057 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070058 PaddingMode(PaddingMode),
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
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070064 EcCurve(EcCurve),
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
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070094 HardwareAuthenticatorType(HardwareAuthenticatorType),
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
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700115 KeyOrigin(KeyOrigin),
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.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700165 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> 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.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700170 pub fn get_tag(&self) -> Tag {
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.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700234 pub fn security_level(&self) -> &SecurityLevel {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000235 &self.security_level
236 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700237
238 /// An authorization is a KeyParameter with an associated security level that is used
239 /// to convey the key characteristics to keystore clients. This function consumes
240 /// an internal KeyParameter representation to produce the Authorization wire type.
241 pub fn into_authorization(self) -> Authorization {
242 Authorization {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700243 securityLevel: self.security_level,
244 keyParameter: self.key_parameter_value.convert_to_wire(),
Janis Danisevskis04b02832020-10-26 09:21:40 -0700245 }
246 }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000247}
248
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000249/// This struct is defined to postpone converting rusqlite column value to the
250/// appropriate key parameter value until we know the corresponding tag value.
251/// Wraps the column index and a rusqlite row.
252pub struct SqlField<'a>(usize, &'a Row<'a>);
253
254impl<'a> SqlField<'a> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700255 /// Creates a new SqlField with the given index and row.
256 pub fn new(index: usize, row: &'a Row<'a>) -> Self {
257 Self(index, row)
258 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000259 /// Returns the column value from the row, when we know the expected type.
260 pub fn get<T: FromSql>(&self) -> SqlResult<T> {
261 self.1.get(self.0)
262 }
263}
264
265impl ToSql for KeyParameterValue {
266 /// Converts KeyParameterValue to be stored in rusqlite database.
267 /// Note that following variants of KeyParameterValue should not be stored:
268 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
269 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
270 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
271 /// conversion for all the variants, to keep error handling simple.
272 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
273 match self {
274 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700275 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
276 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000277 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700278 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
279 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
280 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000281 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
282 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700283 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000284 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
285 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
286 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
287 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
288 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
289 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
290 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
291 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
292 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
293 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
294 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
295 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700296 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000297 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
298 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
299 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
300 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
301 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
302 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
303 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
304 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700305 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000306 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
307 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
308 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
309 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
310 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
311 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
312 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
313 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
314 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
315 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
316 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
317 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
318 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
319 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
320 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
321 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
322 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
323 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
324 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
325 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
326 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
327 }
328 }
329}
330
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000331impl KeyParameter {
332 /// Construct a KeyParameter from the data from a rusqlite row.
333 /// Note that following variants of KeyParameterValue should not be stored:
334 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
335 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
336 /// This filtering is enforced at a higher level and here we support conversion for all the
337 /// variants.
338 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700339 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000340 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700341 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000342 ) -> Result<Self> {
343 let key_param_value = match tag_val {
344 Tag::INVALID => KeyParameterValue::Invalid,
345 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700346 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000347 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700348 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700349 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700350 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000351 }
352 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700353 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000354 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700355 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700356 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700357 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000358 }
359 Tag::KEY_SIZE => {
360 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700361 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000362 KeyParameterValue::KeySize(key_size)
363 }
364 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700365 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000366 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700367 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700368 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700369 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000370 }
371 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700372 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000373 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700374 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700375 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700376 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000377 }
378 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700379 let padding: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000380 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700381 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700382 .context("Failed to read sql data for tag: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700383 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000384 }
385 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
386 Tag::MIN_MAC_LENGTH => {
387 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700388 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000389 KeyParameterValue::MinMacLength(min_mac_length)
390 }
391 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700392 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000393 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700394 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700395 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700396 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000397 }
398 Tag::RSA_PUBLIC_EXPONENT => {
399 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700400 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000401
402 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
403 }
404 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
405 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
406 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
407 Tag::ACTIVE_DATETIME => {
408 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700409 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000410 KeyParameterValue::ActiveDateTime(active_datetime)
411 }
412 Tag::ORIGINATION_EXPIRE_DATETIME => {
413 let origination_expire_datetime: i64 = data
414 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700415 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000416 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
417 }
418 Tag::USAGE_EXPIRE_DATETIME => {
419 let usage_expire_datetime: i64 = data
420 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700421 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000422 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
423 }
424 Tag::MIN_SECONDS_BETWEEN_OPS => {
425 let min_secs_between_ops: i32 = data
426 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700427 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000428 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
429 }
430 Tag::MAX_USES_PER_BOOT => {
431 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700432 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000433 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
434 }
435 Tag::USER_ID => {
436 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700437 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000438 KeyParameterValue::UserID(user_id)
439 }
440 Tag::USER_SECURE_ID => {
441 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700442 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000443 KeyParameterValue::UserSecureID(user_secure_id)
444 }
445 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
446 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700447 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000448 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700449 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700450 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700451 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
452 user_auth_type,
453 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000454 }
455 Tag::AUTH_TIMEOUT => {
456 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700457 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000458 KeyParameterValue::AuthTimeout(auth_timeout)
459 }
460 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
461 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
462 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
463 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
464 Tag::APPLICATION_ID => {
465 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700466 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000467 KeyParameterValue::ApplicationID(app_id)
468 }
469 Tag::APPLICATION_DATA => {
470 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700471 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000472 KeyParameterValue::ApplicationData(app_data)
473 }
474 Tag::CREATION_DATETIME => {
475 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700476 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000477 KeyParameterValue::CreationDateTime(creation_datetime)
478 }
479 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700480 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000481 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700482 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700483 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700484 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000485 }
486 Tag::ROOT_OF_TRUST => {
487 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700488 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000489 KeyParameterValue::RootOfTrust(root_of_trust)
490 }
491 Tag::OS_VERSION => {
492 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700493 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000494 KeyParameterValue::OSVersion(os_version)
495 }
496 Tag::OS_PATCHLEVEL => {
497 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700498 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000499 KeyParameterValue::OSPatchLevel(os_patch_level)
500 }
501 Tag::UNIQUE_ID => {
502 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700503 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000504 KeyParameterValue::UniqueID(unique_id)
505 }
506 Tag::ATTESTATION_CHALLENGE => {
507 let attestation_challenge: Vec<u8> = data
508 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700509 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000510 KeyParameterValue::AttestationChallenge(attestation_challenge)
511 }
512 Tag::ATTESTATION_APPLICATION_ID => {
513 let attestation_app_id: Vec<u8> = data
514 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700515 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000516 KeyParameterValue::AttestationApplicationID(attestation_app_id)
517 }
518 Tag::ATTESTATION_ID_BRAND => {
519 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700520 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000521 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
522 }
523 Tag::ATTESTATION_ID_DEVICE => {
524 let attestation_id_device: Vec<u8> = data
525 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700526 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000527 KeyParameterValue::AttestationIdDevice(attestation_id_device)
528 }
529 Tag::ATTESTATION_ID_PRODUCT => {
530 let attestation_id_product: Vec<u8> = data
531 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700532 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000533 KeyParameterValue::AttestationIdProduct(attestation_id_product)
534 }
535 Tag::ATTESTATION_ID_SERIAL => {
536 let attestation_id_serial: Vec<u8> = data
537 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700538 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000539 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
540 }
541 Tag::ATTESTATION_ID_IMEI => {
542 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700543 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000544 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
545 }
546 Tag::ATTESTATION_ID_MEID => {
547 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700548 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000549 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
550 }
551 Tag::ATTESTATION_ID_MANUFACTURER => {
552 let attestation_id_manufacturer: Vec<u8> = data
553 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700554 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000555 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
556 }
557 Tag::ATTESTATION_ID_MODEL => {
558 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700559 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000560 KeyParameterValue::AttestationIdModel(attestation_id_model)
561 }
562 Tag::VENDOR_PATCHLEVEL => {
563 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700564 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000565 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
566 }
567 Tag::BOOT_PATCHLEVEL => {
568 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700569 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000570 KeyParameterValue::BootPatchLevel(boot_patch_level)
571 }
572 Tag::ASSOCIATED_DATA => {
573 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700574 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000575 KeyParameterValue::AssociatedData(associated_data)
576 }
577 Tag::NONCE => {
578 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700579 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000580 KeyParameterValue::Nonce(nonce)
581 }
582 Tag::MAC_LENGTH => {
583 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700584 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000585 KeyParameterValue::MacLength(mac_length)
586 }
587 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
588 Tag::CONFIRMATION_TOKEN => {
589 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700590 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000591 KeyParameterValue::ConfirmationToken(confirmation_token)
592 }
593 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700594 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700595 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000596 }
597 };
598 Ok(KeyParameter::new(key_param_value, security_level_val))
599 }
600}
601
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000602/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700603/// This macro takes between three and four different pieces of information about each
604/// of the KeyParameterValue variants:
605/// 1. The KeyParameterValue variant name,
606/// 2. the tag name corresponding to the variant,
607/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
608/// stored when converted, and
609/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000610/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
611/// the two conversion methods: convert_to_wire() and convert_from_wire().
612/// ## Example
613/// ```
614/// implement_key_parameter_conversion_to_from_wire! {
615/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700616/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000617/// CallerNonce, CALLER_NONCE, boolValue;
618/// UserSecureID, USER_SECURE_ID, longInteger;
619/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000620/// }
621/// ```
622/// expands to:
623/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700624/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000625/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700626/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000627/// tag: Tag::INVALID,
628/// ..Default::default()
629/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700630/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000631/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700632/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000633/// ..Default::default()
634/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700635/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000636/// tag: Tag::CALLER_NONCE,
637/// boolValue: true,
638/// ..Default::default()
639/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700640/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000641/// tag: Tag::USER_SECURE_ID,
642/// longInteger: v,
643/// ..Default::default()
644/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700645/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000646/// tag: Tag::APPLICATION_ID,
647/// blob: v,
648/// ..Default::default()
649/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000650/// }
651/// }
652/// ```
653/// and
654/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700655/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000656/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700657/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000658/// tag: Tag::INVALID,
659/// ..
660/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700661/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000662/// tag: Tag::PURPOSE,
663/// integer: v,
664/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700665/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
666/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000667/// tag: Tag::CALLER_NONCE,
668/// boolValue: true,
669/// ..
670/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700671/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000672/// tag: Tag::USER_SECURE_ID,
673/// longInteger: v,
674/// ..
675/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700676/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000677/// tag: Tag::APPLICATION_ID,
678/// blob: v,
679/// ..
680/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000681/// _ => KeyParameterValue::Invalid,
682/// }
683/// }
684///
685macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700686 // There are three groups of rules in this macro.
687 // 1. The first group contains the rule which acts as the public interface. It takes the input
688 // given to this macro and prepares it to be given as input to the two groups of rules
689 // mentioned below.
690 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
691 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
692 //
693 // Input to this macro is first handled by the first macro rule (belonging to the first
694 // group above), which pre-processes the input such that rules in the other two groups
695 // generate the code for the two methods, when called recursively.
696 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
697 // four macro rules in the second two groups. These four rules intend to do the following
698 // tasks respectively:
699 // i) generates match arms related to Invalid KeyParameterValue variant.
700 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
701 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
702 // iv) generates the method definition including the match arms generated from the above
703 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000704
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700705 // This rule is applied on the input given to the macro invocations from outside the macro.
706 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
707 // pre-processes input to target the rules that generate convert_to_wire() method.
708 implement_key_parameter_conversion_to_from_wire! {@to
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800709 [], $($variant, $tag_name, $field_name;)*
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700710 }
711 // pre-processes input to target the rules that generate convert_from_wire() method.
712 implement_key_parameter_conversion_to_from_wire! {@from
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800713 [], $($variant, $tag_name, $field_name;)*
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700714 }
715 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000716
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700717 // Following four rules (belonging to the aforementioned second group) generate
718 // convert_to_wire() conversion method.
719 // -----------------------------------------------------------------------
720 // This rule handles Invalid variant.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800721 // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700722 // KeyParameterValue::Invalid => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800723 // tag: Tag::INVALID,
724 // value: KmKeyParameterValue::Invalid(0),
725 // },
726 (@to [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700727 implement_key_parameter_conversion_to_from_wire! {@to
728 [$($out)*
729 KeyParameterValue::Invalid => KmKeyParameter {
730 tag: Tag::INVALID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800731 value: KmKeyParameterValue::Invalid(0),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700732 },
733 ], $($in)*
734 }
735 };
736 // This rule handles all variants that correspond to bool values.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800737 // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700738 // a match arm like:
739 // KeyParameterValue::CallerNonce => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800740 // tag: Tag::CALLER_NONCE,
741 // value: KmKeyParameterValue::BoolValue(true),
742 // },
743 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700744 implement_key_parameter_conversion_to_from_wire! {@to
745 [$($out)*
746 KeyParameterValue::$variant => KmKeyParameter {
747 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800748 value: KmKeyParameterValue::BoolValue(true),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700749 },
750 ], $($in)*
751 }
752 };
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700753 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700754 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700755 // KmKeyParameter).
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800756 // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700757 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800758 // tag: Tag::CONFIRMATION_TOKEN,
759 // value: KmKeyParameterValue::$field(v),
760 // },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700761 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
762 implement_key_parameter_conversion_to_from_wire! {@to
763 [$($out)*
764 KeyParameterValue::$variant(v) => KmKeyParameter {
765 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800766 value: KmKeyParameterValue::$field(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700767 },
768 ], $($in)*
769 }
770 };
771 // After all the match arms are generated by the above three rules, this rule combines them
772 // into the convert_to_wire() method.
773 (@to [$($out:tt)*], ) => {
774 /// Conversion of key parameter to wire type
775 pub fn convert_to_wire(self) -> KmKeyParameter {
776 match self {
777 $($out)*
778 }
779 }
780 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000781
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700782 // Following four rules (belonging to the aforementioned third group) generate
783 // convert_from_wire() conversion method.
784 // ------------------------------------------------------------------------
785 // This rule handles Invalid variant.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800786 // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700787 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800788 (@from [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700789 implement_key_parameter_conversion_to_from_wire! {@from
790 [$($out)*
791 KmKeyParameter {
792 tag: Tag::INVALID,
793 ..
794 } => KeyParameterValue::Invalid,
795 ], $($in)*
796 }
797 };
798 // This rule handles all variants that correspond to bool values.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800799 // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700800 // KmKeyParameter {
801 // tag: Tag::CALLER_NONCE,
802 // boolValue: true,
803 // ..
804 // } => KeyParameterValue::CallerNonce,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800805 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700806 implement_key_parameter_conversion_to_from_wire! {@from
807 [$($out)*
808 KmKeyParameter {
809 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800810 value: KmKeyParameterValue::BoolValue(true),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700811 } => KeyParameterValue::$variant,
812 ], $($in)*
813 }
814 };
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700815 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700816 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700817 // KmKeyParameter).
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800818 // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700819 // like:
820 // KmKeyParameter {
821 // tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800822 // value: KmKeyParameterValue::Blob(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700823 // } => KeyParameterValue::ConfirmationToken(v),
824 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
825 implement_key_parameter_conversion_to_from_wire! {@from
826 [$($out)*
827 KmKeyParameter {
828 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800829 value: KmKeyParameterValue::$field(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700830 } => KeyParameterValue::$variant(v),
831 ], $($in)*
832 }
833 };
834 // After all the match arms are generated by the above three rules, this rule combines them
835 // into the convert_from_wire() method.
836 (@from [$($out:tt)*], ) => {
837 /// Conversion of key parameter from wire type
838 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
839 match aidl_kp {
840 $($out)*
841 _ => KeyParameterValue::Invalid,
842 }
843 }
844 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000845}
846
847impl KeyParameterValue {
848 // Invoke the macro that generates the code for key parameter conversion to/from wire type
849 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
850 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700851 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000852 implement_key_parameter_conversion_to_from_wire! {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800853 Invalid, INVALID, Invalid;
854 KeyPurpose, PURPOSE, KeyPurpose;
855 Algorithm, ALGORITHM, Algorithm;
856 KeySize, KEY_SIZE, Integer;
857 BlockMode, BLOCK_MODE, BlockMode;
858 Digest, DIGEST, Digest;
859 PaddingMode, PADDING, PaddingMode;
860 CallerNonce, CALLER_NONCE, BoolValue;
861 MinMacLength, MIN_MAC_LENGTH, Integer;
862 EcCurve, EC_CURVE, EcCurve;
863 RSAPublicExponent, RSA_PUBLIC_EXPONENT, LongInteger;
864 IncludeUniqueID, INCLUDE_UNIQUE_ID, BoolValue;
865 BootLoaderOnly, BOOTLOADER_ONLY, BoolValue;
866 RollbackResistance, ROLLBACK_RESISTANCE, BoolValue;
867 ActiveDateTime, ACTIVE_DATETIME, DateTime;
868 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, DateTime;
869 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, DateTime;
870 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, Integer;
871 MaxUsesPerBoot, MAX_USES_PER_BOOT, Integer;
872 UserID, USER_ID, Integer;
873 UserSecureID, USER_SECURE_ID, LongInteger;
874 NoAuthRequired, NO_AUTH_REQUIRED, BoolValue;
875 HardwareAuthenticatorType, USER_AUTH_TYPE, HardwareAuthenticatorType;
876 AuthTimeout, AUTH_TIMEOUT, Integer;
877 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, BoolValue;
878 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, BoolValue;
879 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, BoolValue;
880 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, BoolValue;
881 ApplicationID, APPLICATION_ID, Blob;
882 ApplicationData, APPLICATION_DATA, Blob;
883 CreationDateTime, CREATION_DATETIME, DateTime;
884 KeyOrigin, ORIGIN, Origin;
885 RootOfTrust, ROOT_OF_TRUST, Blob;
886 OSVersion, OS_VERSION, Integer;
887 OSPatchLevel, OS_PATCHLEVEL, Integer;
888 UniqueID, UNIQUE_ID, Blob;
889 AttestationChallenge, ATTESTATION_CHALLENGE, Blob;
890 AttestationApplicationID, ATTESTATION_APPLICATION_ID, Blob;
891 AttestationIdBrand, ATTESTATION_ID_BRAND, Blob;
892 AttestationIdDevice, ATTESTATION_ID_DEVICE, Blob;
893 AttestationIdProduct, ATTESTATION_ID_PRODUCT, Blob;
894 AttestationIdSerial, ATTESTATION_ID_SERIAL, Blob;
895 AttestationIdIMEI, ATTESTATION_ID_IMEI, Blob;
896 AttestationIdMEID, ATTESTATION_ID_MEID, Blob;
897 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, Blob;
898 AttestationIdModel, ATTESTATION_ID_MODEL, Blob;
899 VendorPatchLevel, VENDOR_PATCHLEVEL, Integer;
900 BootPatchLevel, BOOT_PATCHLEVEL, Integer;
901 AssociatedData, ASSOCIATED_DATA, Blob;
902 Nonce, NONCE, Blob;
903 MacLength, MAC_LENGTH, Integer;
904 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, BoolValue;
905 ConfirmationToken, CONFIRMATION_TOKEN, Blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000906 }
907}
908
909#[cfg(test)]
910mod basic_tests {
911 use crate::key_parameter::*;
912
913 // Test basic functionality of KeyParameter.
914 #[test]
915 fn test_key_parameter() {
916 let key_parameter = KeyParameter::new(
917 KeyParameterValue::Algorithm(Algorithm::RSA),
918 SecurityLevel::STRONGBOX,
919 );
920
921 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
922
923 assert_eq!(
924 *key_parameter.key_parameter_value(),
925 KeyParameterValue::Algorithm(Algorithm::RSA)
926 );
927
928 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
929 }
930}
931
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000932/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
933/// data types and then tests 'to_sql' method for KeyParameters of those
934/// different data types. The five different data types for KeyParameter values are:
935/// i) enums of u32
936/// ii) u32
937/// iii) u64
938/// iv) Vec<u8>
939/// v) bool
940#[cfg(test)]
941mod storage_tests {
942 use crate::error::*;
943 use crate::key_parameter::*;
944 use anyhow::Result;
945 use rusqlite::types::ToSql;
946 use rusqlite::{params, Connection, NO_PARAMS};
947
948 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
949 /// from a database table row.
950 #[test]
951 fn test_new_from_sql_enum_i32() -> Result<()> {
952 let db = init_db()?;
953 insert_into_keyparameter(
954 &db,
955 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700956 Tag::ALGORITHM.0,
957 &Algorithm::RSA.0,
958 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000959 )?;
960 let key_param = query_from_keyparameter(&db)?;
961 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
962 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
963 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
964 Ok(())
965 }
966
967 /// Test initializing a KeyParameter (with key parameter value which is of i32)
968 /// from a database table row.
969 #[test]
970 fn test_new_from_sql_i32() -> Result<()> {
971 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700972 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000973 let key_param = query_from_keyparameter(&db)?;
974 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
975 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
976 Ok(())
977 }
978
979 /// Test initializing a KeyParameter (with key parameter value which is of i64)
980 /// from a database table row.
981 #[test]
982 fn test_new_from_sql_i64() -> Result<()> {
983 let db = init_db()?;
984 // max value for i64, just to test corner cases
985 insert_into_keyparameter(
986 &db,
987 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700988 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000989 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700990 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000991 )?;
992 let key_param = query_from_keyparameter(&db)?;
993 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
994 assert_eq!(
995 *key_param.key_parameter_value(),
996 KeyParameterValue::RSAPublicExponent(i64::MAX)
997 );
998 Ok(())
999 }
1000
1001 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1002 /// from a database table row.
1003 #[test]
1004 fn test_new_from_sql_bool() -> Result<()> {
1005 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001006 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001007 let key_param = query_from_keyparameter(&db)?;
1008 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1009 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1010 Ok(())
1011 }
1012
1013 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1014 /// from a database table row.
1015 #[test]
1016 fn test_new_from_sql_vec_u8() -> Result<()> {
1017 let db = init_db()?;
1018 let app_id = String::from("MyAppID");
1019 let app_id_bytes = app_id.into_bytes();
1020 insert_into_keyparameter(
1021 &db,
1022 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001023 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001024 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001025 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001026 )?;
1027 let key_param = query_from_keyparameter(&db)?;
1028 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1029 assert_eq!(
1030 *key_param.key_parameter_value(),
1031 KeyParameterValue::ApplicationID(app_id_bytes)
1032 );
1033 Ok(())
1034 }
1035
1036 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1037 /// in the database
1038 #[test]
1039 fn test_to_sql_enum_i32() -> Result<()> {
1040 let db = init_db()?;
1041 let kp = KeyParameter::new(
1042 KeyParameterValue::Algorithm(Algorithm::RSA),
1043 SecurityLevel::STRONGBOX,
1044 );
1045 store_keyparameter(&db, 1, &kp)?;
1046 let key_param = query_from_keyparameter(&db)?;
1047 assert_eq!(kp.get_tag(), key_param.get_tag());
1048 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1049 assert_eq!(kp.security_level(), key_param.security_level());
1050 Ok(())
1051 }
1052
1053 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1054 #[test]
1055 fn test_to_sql_i32() -> Result<()> {
1056 let db = init_db()?;
1057 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1058 store_keyparameter(&db, 1, &kp)?;
1059 let key_param = query_from_keyparameter(&db)?;
1060 assert_eq!(kp.get_tag(), key_param.get_tag());
1061 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1062 assert_eq!(kp.security_level(), key_param.security_level());
1063 Ok(())
1064 }
1065
1066 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1067 #[test]
1068 fn test_to_sql_i64() -> Result<()> {
1069 let db = init_db()?;
1070 // max value for i64, just to test corner cases
1071 let kp = KeyParameter::new(
1072 KeyParameterValue::RSAPublicExponent(i64::MAX),
1073 SecurityLevel::STRONGBOX,
1074 );
1075 store_keyparameter(&db, 1, &kp)?;
1076 let key_param = query_from_keyparameter(&db)?;
1077 assert_eq!(kp.get_tag(), key_param.get_tag());
1078 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1079 assert_eq!(kp.security_level(), key_param.security_level());
1080 Ok(())
1081 }
1082
1083 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1084 #[test]
1085 fn test_to_sql_vec_u8() -> Result<()> {
1086 let db = init_db()?;
1087 let kp = KeyParameter::new(
1088 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1089 SecurityLevel::STRONGBOX,
1090 );
1091 store_keyparameter(&db, 1, &kp)?;
1092 let key_param = query_from_keyparameter(&db)?;
1093 assert_eq!(kp.get_tag(), key_param.get_tag());
1094 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1095 assert_eq!(kp.security_level(), key_param.security_level());
1096 Ok(())
1097 }
1098
1099 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1100 #[test]
1101 fn test_to_sql_bool() -> Result<()> {
1102 let db = init_db()?;
1103 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1104 store_keyparameter(&db, 1, &kp)?;
1105 let key_param = query_from_keyparameter(&db)?;
1106 assert_eq!(kp.get_tag(), key_param.get_tag());
1107 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1108 assert_eq!(kp.security_level(), key_param.security_level());
1109 Ok(())
1110 }
1111
1112 #[test]
1113 /// Test Tag::Invalid
1114 fn test_invalid_tag() -> Result<()> {
1115 let db = init_db()?;
1116 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1117 let key_param = query_from_keyparameter(&db)?;
1118 assert_eq!(Tag::INVALID, key_param.get_tag());
1119 Ok(())
1120 }
1121
1122 #[test]
1123 fn test_non_existing_enum_variant() -> Result<()> {
1124 let db = init_db()?;
1125 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1126 tests::check_result_contains_error_string(
1127 query_from_keyparameter(&db),
1128 "Failed to decode Tag enum from value.",
1129 );
1130 Ok(())
1131 }
1132
1133 #[test]
1134 fn test_invalid_conversion_from_sql() -> Result<()> {
1135 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001136 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001137 tests::check_result_contains_error_string(
1138 query_from_keyparameter(&db),
1139 "Failed to read sql data for tag: ALGORITHM.",
1140 );
1141 Ok(())
1142 }
1143
1144 /// Helper method to init database table for key parameter
1145 fn init_db() -> Result<Connection> {
1146 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1147 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1148 .context("Failed to attach databases.")?;
1149 db.execute(
1150 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1151 keyentryid INTEGER,
1152 tag INTEGER,
1153 data ANY,
1154 security_level INTEGER);",
1155 NO_PARAMS,
1156 )
1157 .context("Failed to initialize \"keyparameter\" table.")?;
1158 Ok(db)
1159 }
1160
1161 /// Helper method to insert an entry into key parameter table, with individual parameters
1162 fn insert_into_keyparameter<T: ToSql>(
1163 db: &Connection,
1164 key_id: i64,
1165 tag: i32,
1166 value: &T,
1167 security_level: i32,
1168 ) -> Result<()> {
1169 db.execute(
1170 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001171 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001172 params![key_id, tag, *value, security_level],
1173 )?;
1174 Ok(())
1175 }
1176
1177 /// Helper method to store a key parameter instance.
1178 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1179 db.execute(
1180 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001181 VALUES(?, ?, ?, ?);",
1182 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001183 )?;
1184 Ok(())
1185 }
1186
1187 /// Helper method to query a row from keyparameter table
1188 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001189 let mut stmt =
1190 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001191 let mut rows = stmt.query(NO_PARAMS)?;
1192 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001193 Ok(KeyParameter::new_from_sql(
1194 Tag(row.get(0)?),
1195 &SqlField(1, row),
1196 SecurityLevel(row.get(2)?),
1197 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001198 }
1199}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001200
1201/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001202/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001203/// key parameter.
1204/// i) bool
1205/// ii) integer
1206/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001207/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001208#[cfg(test)]
1209mod wire_tests {
1210 use crate::key_parameter::*;
1211 /// unit tests for to conversions
1212 #[test]
1213 fn test_convert_to_wire_invalid() {
1214 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1215 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1216 assert_eq!(Tag::INVALID, actual.tag);
1217 }
1218 #[test]
1219 fn test_convert_to_wire_bool() {
1220 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1221 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1222 assert_eq!(Tag::CALLER_NONCE, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001223 assert_eq!(KmKeyParameterValue::BoolValue(true), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001224 }
1225 #[test]
1226 fn test_convert_to_wire_integer() {
1227 let kp = KeyParameter::new(
1228 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1229 SecurityLevel::STRONGBOX,
1230 );
1231 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1232 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001233 assert_eq!(KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001234 }
1235 #[test]
1236 fn test_convert_to_wire_long_integer() {
1237 let kp =
1238 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1239 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1240 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001241 assert_eq!(KmKeyParameterValue::LongInteger(i64::MAX), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001242 }
1243 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001244 fn test_convert_to_wire_blob() {
1245 let kp = KeyParameter::new(
1246 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1247 SecurityLevel::STRONGBOX,
1248 );
1249 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1250 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001251 assert_eq!(
1252 KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
1253 actual.value
1254 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001255 }
1256
1257 /// unit tests for from conversion
1258 #[test]
1259 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001260 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001261 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1262 assert_eq!(KeyParameterValue::Invalid, actual);
1263 }
1264 #[test]
1265 fn test_convert_from_wire_bool() {
1266 let aidl_kp =
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001267 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001268 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1269 assert_eq!(KeyParameterValue::CallerNonce, actual);
1270 }
1271 #[test]
1272 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001273 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001274 tag: Tag::PURPOSE,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001275 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001276 };
1277 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1278 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1279 }
1280 #[test]
1281 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001282 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001283 tag: Tag::USER_SECURE_ID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001284 value: KmKeyParameterValue::LongInteger(i64::MAX),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001285 };
1286 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1287 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1288 }
1289 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001290 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001291 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001292 tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001293 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001294 };
1295 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1296 assert_eq!(
1297 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1298 actual
1299 );
1300 }
1301}