blob: 5355d93d2ef4301c152766a9c625b95f2c4de1f6 [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
Hasini Gunasingheaf993662020-07-24 18:40:20 +000022pub use android_hardware_keymint::aidl::android::hardware::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070023 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
24 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
25 KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
Janis Danisevskis04b02832020-10-26 09:21:40 -070026 SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000027};
Janis Danisevskis04b02832020-10-26 09:21:40 -070028use android_system_keystore2::aidl::android::system::keystore2::{
29 Authorization::Authorization, SecurityLevel::SecurityLevel as KsSecurityLevel,
30};
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.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070036#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000037pub struct KeyParameter {
38 key_parameter_value: KeyParameterValue,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070039 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000040}
41
42/// KeyParameterValue holds a value corresponding to one of the Tags defined in
43/// the AIDL spec at hardware/interfaces/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070044#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000045pub enum KeyParameterValue {
46 /// Associated with Tag:INVALID
47 Invalid,
48 /// Set of purposes for which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070049 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000050 /// Cryptographic algorithm with which the key is used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070051 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000052 /// Size of the key , in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +000053 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000054 /// Block cipher mode(s) with which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070055 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000056 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070057 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000058 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070059 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000060 /// Can the caller provide a nonce for nonce-requiring operations
61 CallerNonce,
62 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Hasini Gunasingheaf993662020-07-24 18:40:20 +000063 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000064 /// The elliptic curve
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070065 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000066 /// Value of the public exponent for an RSA key pair
Hasini Gunasingheaf993662020-07-24 18:40:20 +000067 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000068 /// An attestation certificate for the generated key should contain an application-scoped
69 /// and time-bounded device-unique ID
70 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000071 //TODO: find out about this
72 // /// Necessary system environment conditions for the generated key to be used
73 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000074 /// Only the boot loader can use the key
75 BootLoaderOnly,
76 /// When deleted, the key is guaranteed to be permanently deleted and unusable
77 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000078 /// The date and time at which the key becomes active
Hasini Gunasingheaf993662020-07-24 18:40:20 +000079 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000080 /// The date and time at which the key expires for signing and encryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000081 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000082 /// The date and time at which the key expires for verification and decryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000083 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000084 /// Minimum amount of time that elapses between allowed operations
Hasini Gunasingheaf993662020-07-24 18:40:20 +000085 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000086 /// Maximum number of times that a key may be used between system reboots
Hasini Gunasingheaf993662020-07-24 18:40:20 +000087 MaxUsesPerBoot(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000088 /// ID of the Android user that is permitted to use the key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000089 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000090 /// A key may only be used under a particular secure user authentication state
Hasini Gunasingheaf993662020-07-24 18:40:20 +000091 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000092 /// No authentication is required to use this key
93 NoAuthRequired,
94 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070095 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000096 /// The time in seconds for which the key is authorized for use, after user authentication
Hasini Gunasingheaf993662020-07-24 18:40:20 +000097 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000098 /// The key may be used after authentication timeout if device is still on-body
99 AllowWhileOnBody,
100 /// The key must be unusable except when the user has provided proof of physical presence
101 TrustedUserPresenceRequired,
102 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
103 /// unless the user provides confirmation of the data to be signed
104 TrustedConfirmationRequired,
105 /// The key may only be used when the device is unlocked
106 UnlockedDeviceRequired,
107 /// When provided to generateKey or importKey, this tag specifies data
108 /// that is necessary during all uses of the key
109 ApplicationID(Vec<u8>),
110 /// When provided to generateKey or importKey, this tag specifies data
111 /// that is necessary during all uses of the key
112 ApplicationData(Vec<u8>),
113 /// Specifies the date and time the key was created
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000114 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000115 /// Specifies where the key was created, if known
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700116 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000117 /// The key used by verified boot to validate the operating system booted
118 RootOfTrust(Vec<u8>),
119 /// System OS version with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000120 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000121 /// Specifies the system security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000122 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000123 /// Specifies a unique, time-based identifier
124 UniqueID(Vec<u8>),
125 /// Used to deliver a "challenge" value to the attestKey() method
126 AttestationChallenge(Vec<u8>),
127 /// The set of applications which may use a key, used only with attestKey()
128 AttestationApplicationID(Vec<u8>),
129 /// Provides the device's brand name, to attestKey()
130 AttestationIdBrand(Vec<u8>),
131 /// Provides the device's device name, to attestKey()
132 AttestationIdDevice(Vec<u8>),
133 /// Provides the device's product name, to attestKey()
134 AttestationIdProduct(Vec<u8>),
135 /// Provides the device's serial number, to attestKey()
136 AttestationIdSerial(Vec<u8>),
137 /// Provides the IMEIs for all radios on the device, to attestKey()
138 AttestationIdIMEI(Vec<u8>),
139 /// Provides the MEIDs for all radios on the device, to attestKey()
140 AttestationIdMEID(Vec<u8>),
141 /// Provides the device's manufacturer name, to attestKey()
142 AttestationIdManufacturer(Vec<u8>),
143 /// Provides the device's model name, to attestKey()
144 AttestationIdModel(Vec<u8>),
145 /// Specifies the vendor image security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000146 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000147 /// Specifies the boot image (kernel) security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000148 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000149 /// Provides "associated data" for AES-GCM encryption or decryption
150 AssociatedData(Vec<u8>),
151 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
152 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
153 Nonce(Vec<u8>),
154 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000155 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000156 /// Specifies whether the device has been factory reset since the
157 /// last unique ID rotation. Used for key attestation
158 ResetSinceIdRotation,
159 /// Used to deliver a cryptographic token proving that the user
160 /// confirmed a signing request
161 ConfirmationToken(Vec<u8>),
162}
163
164impl KeyParameter {
165 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700166 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000167 KeyParameter { key_parameter_value, security_level }
168 }
169
170 /// Returns the tag given the KeyParameter instance.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700171 pub fn get_tag(&self) -> Tag {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000172 match self.key_parameter_value {
173 KeyParameterValue::Invalid => Tag::INVALID,
174 KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
175 KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
176 KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
177 KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
178 KeyParameterValue::Digest(_) => Tag::DIGEST,
179 KeyParameterValue::PaddingMode(_) => Tag::PADDING,
180 KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
181 KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
182 KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
183 KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
184 KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000185 KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
186 KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
187 KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
188 KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
189 KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
190 KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
191 KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
192 KeyParameterValue::UserID(_) => Tag::USER_ID,
193 KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
194 KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
195 KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
196 KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
197 KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
198 KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
199 KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
200 KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
201 KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
202 KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
203 KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
204 KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
205 KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
206 KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
207 KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
208 KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
209 KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
210 KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
211 KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
212 KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
213 KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
214 KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
215 KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
216 KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
217 KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
218 KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
219 KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
220 KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
221 KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
222 KeyParameterValue::Nonce(_) => Tag::NONCE,
223 KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
224 KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
225 KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
226 }
227 }
228
229 /// Returns key parameter value.
230 pub fn key_parameter_value(&self) -> &KeyParameterValue {
231 &self.key_parameter_value
232 }
233
234 /// Returns the security level of a KeyParameter.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700235 pub fn security_level(&self) -> &SecurityLevel {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000236 &self.security_level
237 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700238
239 /// An authorization is a KeyParameter with an associated security level that is used
240 /// to convey the key characteristics to keystore clients. This function consumes
241 /// an internal KeyParameter representation to produce the Authorization wire type.
242 pub fn into_authorization(self) -> Authorization {
243 Authorization {
244 securityLevel: KsSecurityLevel(self.security_level.0),
245 keyParameter: crate::utils::keyparam_km_to_ks(
246 &self.key_parameter_value.convert_to_wire(),
247 ),
248 }
249 }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000250}
251
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000252/// This struct is defined to postpone converting rusqlite column value to the
253/// appropriate key parameter value until we know the corresponding tag value.
254/// Wraps the column index and a rusqlite row.
255pub struct SqlField<'a>(usize, &'a Row<'a>);
256
257impl<'a> SqlField<'a> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700258 /// Creates a new SqlField with the given index and row.
259 pub fn new(index: usize, row: &'a Row<'a>) -> Self {
260 Self(index, row)
261 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000262 /// Returns the column value from the row, when we know the expected type.
263 pub fn get<T: FromSql>(&self) -> SqlResult<T> {
264 self.1.get(self.0)
265 }
266}
267
268impl ToSql for KeyParameterValue {
269 /// Converts KeyParameterValue to be stored in rusqlite database.
270 /// Note that following variants of KeyParameterValue should not be stored:
271 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
272 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
273 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
274 /// conversion for all the variants, to keep error handling simple.
275 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
276 match self {
277 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700278 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
279 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000280 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700281 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
282 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
283 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000284 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
285 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700286 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000287 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
288 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
289 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
290 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
291 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
292 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
293 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
294 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
295 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
296 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
297 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
298 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700299 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000300 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
301 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
302 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
303 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
304 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
305 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
306 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
307 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700308 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000309 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
310 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
311 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
312 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
313 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
314 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
315 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
316 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
317 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
318 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
319 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
320 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
321 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
322 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
323 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
324 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
325 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
326 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
327 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
328 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
329 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
330 }
331 }
332}
333
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000334impl KeyParameter {
335 /// Construct a KeyParameter from the data from a rusqlite row.
336 /// Note that following variants of KeyParameterValue should not be stored:
337 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
338 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
339 /// This filtering is enforced at a higher level and here we support conversion for all the
340 /// variants.
341 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700342 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000343 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700344 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000345 ) -> Result<Self> {
346 let key_param_value = match tag_val {
347 Tag::INVALID => KeyParameterValue::Invalid,
348 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700349 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000350 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700351 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700352 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700353 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000354 }
355 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700356 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000357 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700358 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700359 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700360 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000361 }
362 Tag::KEY_SIZE => {
363 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700364 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000365 KeyParameterValue::KeySize(key_size)
366 }
367 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700368 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000369 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700370 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700371 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700372 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000373 }
374 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700375 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000376 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700377 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700378 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700379 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000380 }
381 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700382 let padding: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000383 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700384 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700385 .context("Failed to read sql data for tag: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700386 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000387 }
388 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
389 Tag::MIN_MAC_LENGTH => {
390 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700391 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000392 KeyParameterValue::MinMacLength(min_mac_length)
393 }
394 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700395 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000396 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700397 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700398 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700399 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000400 }
401 Tag::RSA_PUBLIC_EXPONENT => {
402 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700403 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000404
405 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
406 }
407 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
408 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
409 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
410 Tag::ACTIVE_DATETIME => {
411 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700412 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000413 KeyParameterValue::ActiveDateTime(active_datetime)
414 }
415 Tag::ORIGINATION_EXPIRE_DATETIME => {
416 let origination_expire_datetime: i64 = data
417 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700418 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000419 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
420 }
421 Tag::USAGE_EXPIRE_DATETIME => {
422 let usage_expire_datetime: i64 = data
423 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700424 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000425 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
426 }
427 Tag::MIN_SECONDS_BETWEEN_OPS => {
428 let min_secs_between_ops: i32 = data
429 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700430 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000431 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
432 }
433 Tag::MAX_USES_PER_BOOT => {
434 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700435 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000436 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
437 }
438 Tag::USER_ID => {
439 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700440 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000441 KeyParameterValue::UserID(user_id)
442 }
443 Tag::USER_SECURE_ID => {
444 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700445 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000446 KeyParameterValue::UserSecureID(user_secure_id)
447 }
448 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
449 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700450 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000451 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700452 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700453 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700454 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
455 user_auth_type,
456 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000457 }
458 Tag::AUTH_TIMEOUT => {
459 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700460 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000461 KeyParameterValue::AuthTimeout(auth_timeout)
462 }
463 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
464 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
465 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
466 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
467 Tag::APPLICATION_ID => {
468 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700469 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000470 KeyParameterValue::ApplicationID(app_id)
471 }
472 Tag::APPLICATION_DATA => {
473 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700474 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000475 KeyParameterValue::ApplicationData(app_data)
476 }
477 Tag::CREATION_DATETIME => {
478 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700479 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000480 KeyParameterValue::CreationDateTime(creation_datetime)
481 }
482 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700483 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000484 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700485 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700486 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700487 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000488 }
489 Tag::ROOT_OF_TRUST => {
490 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700491 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000492 KeyParameterValue::RootOfTrust(root_of_trust)
493 }
494 Tag::OS_VERSION => {
495 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700496 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000497 KeyParameterValue::OSVersion(os_version)
498 }
499 Tag::OS_PATCHLEVEL => {
500 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700501 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000502 KeyParameterValue::OSPatchLevel(os_patch_level)
503 }
504 Tag::UNIQUE_ID => {
505 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700506 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000507 KeyParameterValue::UniqueID(unique_id)
508 }
509 Tag::ATTESTATION_CHALLENGE => {
510 let attestation_challenge: Vec<u8> = data
511 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700512 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000513 KeyParameterValue::AttestationChallenge(attestation_challenge)
514 }
515 Tag::ATTESTATION_APPLICATION_ID => {
516 let attestation_app_id: Vec<u8> = data
517 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700518 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000519 KeyParameterValue::AttestationApplicationID(attestation_app_id)
520 }
521 Tag::ATTESTATION_ID_BRAND => {
522 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700523 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000524 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
525 }
526 Tag::ATTESTATION_ID_DEVICE => {
527 let attestation_id_device: Vec<u8> = data
528 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700529 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000530 KeyParameterValue::AttestationIdDevice(attestation_id_device)
531 }
532 Tag::ATTESTATION_ID_PRODUCT => {
533 let attestation_id_product: Vec<u8> = data
534 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700535 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000536 KeyParameterValue::AttestationIdProduct(attestation_id_product)
537 }
538 Tag::ATTESTATION_ID_SERIAL => {
539 let attestation_id_serial: Vec<u8> = data
540 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700541 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000542 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
543 }
544 Tag::ATTESTATION_ID_IMEI => {
545 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700546 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000547 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
548 }
549 Tag::ATTESTATION_ID_MEID => {
550 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700551 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000552 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
553 }
554 Tag::ATTESTATION_ID_MANUFACTURER => {
555 let attestation_id_manufacturer: Vec<u8> = data
556 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700557 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000558 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
559 }
560 Tag::ATTESTATION_ID_MODEL => {
561 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700562 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000563 KeyParameterValue::AttestationIdModel(attestation_id_model)
564 }
565 Tag::VENDOR_PATCHLEVEL => {
566 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700567 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000568 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
569 }
570 Tag::BOOT_PATCHLEVEL => {
571 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700572 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000573 KeyParameterValue::BootPatchLevel(boot_patch_level)
574 }
575 Tag::ASSOCIATED_DATA => {
576 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700577 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000578 KeyParameterValue::AssociatedData(associated_data)
579 }
580 Tag::NONCE => {
581 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700582 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000583 KeyParameterValue::Nonce(nonce)
584 }
585 Tag::MAC_LENGTH => {
586 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700587 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000588 KeyParameterValue::MacLength(mac_length)
589 }
590 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
591 Tag::CONFIRMATION_TOKEN => {
592 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700593 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000594 KeyParameterValue::ConfirmationToken(confirmation_token)
595 }
596 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700597 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700598 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000599 }
600 };
601 Ok(KeyParameter::new(key_param_value, security_level_val))
602 }
603}
604
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000605/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700606/// This macro takes between three and four different pieces of information about each
607/// of the KeyParameterValue variants:
608/// 1. The KeyParameterValue variant name,
609/// 2. the tag name corresponding to the variant,
610/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
611/// stored when converted, and
612/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000613/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
614/// the two conversion methods: convert_to_wire() and convert_from_wire().
615/// ## Example
616/// ```
617/// implement_key_parameter_conversion_to_from_wire! {
618/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700619/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000620/// CallerNonce, CALLER_NONCE, boolValue;
621/// UserSecureID, USER_SECURE_ID, longInteger;
622/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000623/// }
624/// ```
625/// expands to:
626/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700627/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000628/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700629/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000630/// tag: Tag::INVALID,
631/// ..Default::default()
632/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700633/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000634/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700635/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000636/// ..Default::default()
637/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700638/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000639/// tag: Tag::CALLER_NONCE,
640/// boolValue: true,
641/// ..Default::default()
642/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700643/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000644/// tag: Tag::USER_SECURE_ID,
645/// longInteger: v,
646/// ..Default::default()
647/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700648/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000649/// tag: Tag::APPLICATION_ID,
650/// blob: v,
651/// ..Default::default()
652/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000653/// }
654/// }
655/// ```
656/// and
657/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700658/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000659/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700660/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000661/// tag: Tag::INVALID,
662/// ..
663/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700664/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000665/// tag: Tag::PURPOSE,
666/// integer: v,
667/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700668/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
669/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000670/// tag: Tag::CALLER_NONCE,
671/// boolValue: true,
672/// ..
673/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700674/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000675/// tag: Tag::USER_SECURE_ID,
676/// longInteger: v,
677/// ..
678/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700679/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000680/// tag: Tag::APPLICATION_ID,
681/// blob: v,
682/// ..
683/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000684/// _ => KeyParameterValue::Invalid,
685/// }
686/// }
687///
688macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700689 // There are three groups of rules in this macro.
690 // 1. The first group contains the rule which acts as the public interface. It takes the input
691 // given to this macro and prepares it to be given as input to the two groups of rules
692 // mentioned below.
693 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
694 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
695 //
696 // Input to this macro is first handled by the first macro rule (belonging to the first
697 // group above), which pre-processes the input such that rules in the other two groups
698 // generate the code for the two methods, when called recursively.
699 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
700 // four macro rules in the second two groups. These four rules intend to do the following
701 // tasks respectively:
702 // i) generates match arms related to Invalid KeyParameterValue variant.
703 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
704 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
705 // iv) generates the method definition including the match arms generated from the above
706 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000707
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700708 // This rule is applied on the input given to the macro invocations from outside the macro.
709 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
710 // pre-processes input to target the rules that generate convert_to_wire() method.
711 implement_key_parameter_conversion_to_from_wire! {@to
712 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
713 }
714 // pre-processes input to target the rules that generate convert_from_wire() method.
715 implement_key_parameter_conversion_to_from_wire! {@from
716 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
717 }
718 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000719
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700720 // Following four rules (belonging to the aforementioned second group) generate
721 // convert_to_wire() conversion method.
722 // -----------------------------------------------------------------------
723 // This rule handles Invalid variant.
724 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
725 // KeyParameterValue::Invalid => KmKeyParameter {
726 // tag: Tag::INVALID,
727 // ..Default::default()
728 // },
729 (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
730 implement_key_parameter_conversion_to_from_wire! {@to
731 [$($out)*
732 KeyParameterValue::Invalid => KmKeyParameter {
733 tag: Tag::INVALID,
734 ..Default::default()
735 },
736 ], $($in)*
737 }
738 };
739 // This rule handles all variants that correspond to bool values.
740 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
741 // a match arm like:
742 // KeyParameterValue::CallerNonce => KmKeyParameter {
743 // tag: Tag::CALLER_NONCE,
744 // boolValue: true,
745 // ..Default::default()
746 // },
747 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
748 implement_key_parameter_conversion_to_from_wire! {@to
749 [$($out)*
750 KeyParameterValue::$variant => KmKeyParameter {
751 tag: Tag::$tag_val,
752 boolValue: true,
753 ..Default::default()
754 },
755 ], $($in)*
756 }
757 };
758 // This rule handles all enum variants.
759 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
760 // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
761 // tag: Tag::PURPOSE,
762 // integer: v.0,
763 // ..Default::default(),
764 // },
765 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
766 implement_key_parameter_conversion_to_from_wire! {@to
767 [$($out)*
768 KeyParameterValue::$variant(v) => KmKeyParameter {
769 tag: Tag::$tag_val,
770 $field: v.0,
771 ..Default::default()
772 },
773 ], $($in)*
774 }
775 };
776 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700777 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700778 // KmKeyParameter).
779 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
780 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
781 // tag: Tag::CONFIRMATION_TOKEN,
782 // blob: v,
783 // ..Default::default(),
784 // },
785 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
786 implement_key_parameter_conversion_to_from_wire! {@to
787 [$($out)*
788 KeyParameterValue::$variant(v) => KmKeyParameter {
789 tag: Tag::$tag_val,
790 $field: v,
791 ..Default::default()
792 },
793 ], $($in)*
794 }
795 };
796 // After all the match arms are generated by the above three rules, this rule combines them
797 // into the convert_to_wire() method.
798 (@to [$($out:tt)*], ) => {
799 /// Conversion of key parameter to wire type
800 pub fn convert_to_wire(self) -> KmKeyParameter {
801 match self {
802 $($out)*
803 }
804 }
805 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000806
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700807 // Following four rules (belonging to the aforementioned third group) generate
808 // convert_from_wire() conversion method.
809 // ------------------------------------------------------------------------
810 // This rule handles Invalid variant.
811 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
812 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
813 (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
814 implement_key_parameter_conversion_to_from_wire! {@from
815 [$($out)*
816 KmKeyParameter {
817 tag: Tag::INVALID,
818 ..
819 } => KeyParameterValue::Invalid,
820 ], $($in)*
821 }
822 };
823 // This rule handles all variants that correspond to bool values.
824 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
825 // KmKeyParameter {
826 // tag: Tag::CALLER_NONCE,
827 // boolValue: true,
828 // ..
829 // } => KeyParameterValue::CallerNonce,
830 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
831 implement_key_parameter_conversion_to_from_wire! {@from
832 [$($out)*
833 KmKeyParameter {
834 tag: Tag::$tag_val,
835 boolValue: true,
836 ..
837 } => KeyParameterValue::$variant,
838 ], $($in)*
839 }
840 };
841 // This rule handles all enum variants.
842 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
843 // like:
844 // KmKeyParameter {
845 // tag: Tag::PURPOSE,
846 // integer: v,
847 // ..,
848 // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
849 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
850 implement_key_parameter_conversion_to_from_wire! {@from
851 [$($out)*
852 KmKeyParameter {
853 tag: Tag::$tag_val,
854 $field: v,
855 ..
856 } => KeyParameterValue::$variant($enum_type(v)),
857 ], $($in)*
858 }
859 };
860 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700861 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700862 // KmKeyParameter).
863 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
864 // like:
865 // KmKeyParameter {
866 // tag: Tag::CONFIRMATION_TOKEN,
867 // blob: v,
868 // ..,
869 // } => KeyParameterValue::ConfirmationToken(v),
870 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
871 implement_key_parameter_conversion_to_from_wire! {@from
872 [$($out)*
873 KmKeyParameter {
874 tag: Tag::$tag_val,
875 $field: v,
876 ..
877 } => KeyParameterValue::$variant(v),
878 ], $($in)*
879 }
880 };
881 // After all the match arms are generated by the above three rules, this rule combines them
882 // into the convert_from_wire() method.
883 (@from [$($out:tt)*], ) => {
884 /// Conversion of key parameter from wire type
885 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
886 match aidl_kp {
887 $($out)*
888 _ => KeyParameterValue::Invalid,
889 }
890 }
891 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000892}
893
894impl KeyParameterValue {
895 // Invoke the macro that generates the code for key parameter conversion to/from wire type
896 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
897 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700898 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000899 implement_key_parameter_conversion_to_from_wire! {
900 Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700901 KeyPurpose, PURPOSE, integer, KeyPurpose;
902 Algorithm, ALGORITHM, integer, Algorithm;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000903 KeySize, KEY_SIZE, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700904 BlockMode, BLOCK_MODE, integer, BlockMode;
905 Digest, DIGEST, integer, Digest;
906 PaddingMode, PADDING, integer, PaddingMode;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000907 CallerNonce, CALLER_NONCE, boolValue;
908 MinMacLength, MIN_MAC_LENGTH, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700909 EcCurve, EC_CURVE, integer, EcCurve;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000910 RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
911 IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
912 BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
913 RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700914 ActiveDateTime, ACTIVE_DATETIME, longInteger;
915 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
916 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000917 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
918 MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
919 UserID, USER_ID, integer;
920 UserSecureID, USER_SECURE_ID, longInteger;
921 NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700922 HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000923 AuthTimeout, AUTH_TIMEOUT, integer;
924 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
925 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
926 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
927 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
928 ApplicationID, APPLICATION_ID, blob;
929 ApplicationData, APPLICATION_DATA, blob;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700930 CreationDateTime, CREATION_DATETIME, longInteger;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700931 KeyOrigin, ORIGIN, integer, KeyOrigin;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000932 RootOfTrust, ROOT_OF_TRUST, blob;
933 OSVersion, OS_VERSION, integer;
934 OSPatchLevel, OS_PATCHLEVEL, integer;
935 UniqueID, UNIQUE_ID, blob;
936 AttestationChallenge, ATTESTATION_CHALLENGE, blob;
937 AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
938 AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
939 AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
940 AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
941 AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
942 AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
943 AttestationIdMEID, ATTESTATION_ID_MEID, blob;
944 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
945 AttestationIdModel, ATTESTATION_ID_MODEL, blob;
946 VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
947 BootPatchLevel, BOOT_PATCHLEVEL, integer;
948 AssociatedData, ASSOCIATED_DATA, blob;
949 Nonce, NONCE, blob;
950 MacLength, MAC_LENGTH, integer;
951 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
952 ConfirmationToken, CONFIRMATION_TOKEN, blob;
953 }
954}
955
956#[cfg(test)]
957mod basic_tests {
958 use crate::key_parameter::*;
959
960 // Test basic functionality of KeyParameter.
961 #[test]
962 fn test_key_parameter() {
963 let key_parameter = KeyParameter::new(
964 KeyParameterValue::Algorithm(Algorithm::RSA),
965 SecurityLevel::STRONGBOX,
966 );
967
968 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
969
970 assert_eq!(
971 *key_parameter.key_parameter_value(),
972 KeyParameterValue::Algorithm(Algorithm::RSA)
973 );
974
975 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
976 }
977}
978
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000979/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
980/// data types and then tests 'to_sql' method for KeyParameters of those
981/// different data types. The five different data types for KeyParameter values are:
982/// i) enums of u32
983/// ii) u32
984/// iii) u64
985/// iv) Vec<u8>
986/// v) bool
987#[cfg(test)]
988mod storage_tests {
989 use crate::error::*;
990 use crate::key_parameter::*;
991 use anyhow::Result;
992 use rusqlite::types::ToSql;
993 use rusqlite::{params, Connection, NO_PARAMS};
994
995 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
996 /// from a database table row.
997 #[test]
998 fn test_new_from_sql_enum_i32() -> Result<()> {
999 let db = init_db()?;
1000 insert_into_keyparameter(
1001 &db,
1002 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001003 Tag::ALGORITHM.0,
1004 &Algorithm::RSA.0,
1005 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001006 )?;
1007 let key_param = query_from_keyparameter(&db)?;
1008 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1009 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1010 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1011 Ok(())
1012 }
1013
1014 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1015 /// from a database table row.
1016 #[test]
1017 fn test_new_from_sql_i32() -> Result<()> {
1018 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001019 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001020 let key_param = query_from_keyparameter(&db)?;
1021 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1022 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1023 Ok(())
1024 }
1025
1026 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1027 /// from a database table row.
1028 #[test]
1029 fn test_new_from_sql_i64() -> Result<()> {
1030 let db = init_db()?;
1031 // max value for i64, just to test corner cases
1032 insert_into_keyparameter(
1033 &db,
1034 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001035 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001036 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001037 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001038 )?;
1039 let key_param = query_from_keyparameter(&db)?;
1040 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1041 assert_eq!(
1042 *key_param.key_parameter_value(),
1043 KeyParameterValue::RSAPublicExponent(i64::MAX)
1044 );
1045 Ok(())
1046 }
1047
1048 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1049 /// from a database table row.
1050 #[test]
1051 fn test_new_from_sql_bool() -> Result<()> {
1052 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001053 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001054 let key_param = query_from_keyparameter(&db)?;
1055 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1056 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1057 Ok(())
1058 }
1059
1060 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1061 /// from a database table row.
1062 #[test]
1063 fn test_new_from_sql_vec_u8() -> Result<()> {
1064 let db = init_db()?;
1065 let app_id = String::from("MyAppID");
1066 let app_id_bytes = app_id.into_bytes();
1067 insert_into_keyparameter(
1068 &db,
1069 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001070 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001071 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001072 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001073 )?;
1074 let key_param = query_from_keyparameter(&db)?;
1075 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1076 assert_eq!(
1077 *key_param.key_parameter_value(),
1078 KeyParameterValue::ApplicationID(app_id_bytes)
1079 );
1080 Ok(())
1081 }
1082
1083 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1084 /// in the database
1085 #[test]
1086 fn test_to_sql_enum_i32() -> Result<()> {
1087 let db = init_db()?;
1088 let kp = KeyParameter::new(
1089 KeyParameterValue::Algorithm(Algorithm::RSA),
1090 SecurityLevel::STRONGBOX,
1091 );
1092 store_keyparameter(&db, 1, &kp)?;
1093 let key_param = query_from_keyparameter(&db)?;
1094 assert_eq!(kp.get_tag(), key_param.get_tag());
1095 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1096 assert_eq!(kp.security_level(), key_param.security_level());
1097 Ok(())
1098 }
1099
1100 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1101 #[test]
1102 fn test_to_sql_i32() -> Result<()> {
1103 let db = init_db()?;
1104 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1105 store_keyparameter(&db, 1, &kp)?;
1106 let key_param = query_from_keyparameter(&db)?;
1107 assert_eq!(kp.get_tag(), key_param.get_tag());
1108 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1109 assert_eq!(kp.security_level(), key_param.security_level());
1110 Ok(())
1111 }
1112
1113 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1114 #[test]
1115 fn test_to_sql_i64() -> Result<()> {
1116 let db = init_db()?;
1117 // max value for i64, just to test corner cases
1118 let kp = KeyParameter::new(
1119 KeyParameterValue::RSAPublicExponent(i64::MAX),
1120 SecurityLevel::STRONGBOX,
1121 );
1122 store_keyparameter(&db, 1, &kp)?;
1123 let key_param = query_from_keyparameter(&db)?;
1124 assert_eq!(kp.get_tag(), key_param.get_tag());
1125 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1126 assert_eq!(kp.security_level(), key_param.security_level());
1127 Ok(())
1128 }
1129
1130 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1131 #[test]
1132 fn test_to_sql_vec_u8() -> Result<()> {
1133 let db = init_db()?;
1134 let kp = KeyParameter::new(
1135 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1136 SecurityLevel::STRONGBOX,
1137 );
1138 store_keyparameter(&db, 1, &kp)?;
1139 let key_param = query_from_keyparameter(&db)?;
1140 assert_eq!(kp.get_tag(), key_param.get_tag());
1141 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1142 assert_eq!(kp.security_level(), key_param.security_level());
1143 Ok(())
1144 }
1145
1146 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1147 #[test]
1148 fn test_to_sql_bool() -> Result<()> {
1149 let db = init_db()?;
1150 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1151 store_keyparameter(&db, 1, &kp)?;
1152 let key_param = query_from_keyparameter(&db)?;
1153 assert_eq!(kp.get_tag(), key_param.get_tag());
1154 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1155 assert_eq!(kp.security_level(), key_param.security_level());
1156 Ok(())
1157 }
1158
1159 #[test]
1160 /// Test Tag::Invalid
1161 fn test_invalid_tag() -> Result<()> {
1162 let db = init_db()?;
1163 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1164 let key_param = query_from_keyparameter(&db)?;
1165 assert_eq!(Tag::INVALID, key_param.get_tag());
1166 Ok(())
1167 }
1168
1169 #[test]
1170 fn test_non_existing_enum_variant() -> Result<()> {
1171 let db = init_db()?;
1172 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1173 tests::check_result_contains_error_string(
1174 query_from_keyparameter(&db),
1175 "Failed to decode Tag enum from value.",
1176 );
1177 Ok(())
1178 }
1179
1180 #[test]
1181 fn test_invalid_conversion_from_sql() -> Result<()> {
1182 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001183 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001184 tests::check_result_contains_error_string(
1185 query_from_keyparameter(&db),
1186 "Failed to read sql data for tag: ALGORITHM.",
1187 );
1188 Ok(())
1189 }
1190
1191 /// Helper method to init database table for key parameter
1192 fn init_db() -> Result<Connection> {
1193 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1194 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1195 .context("Failed to attach databases.")?;
1196 db.execute(
1197 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1198 keyentryid INTEGER,
1199 tag INTEGER,
1200 data ANY,
1201 security_level INTEGER);",
1202 NO_PARAMS,
1203 )
1204 .context("Failed to initialize \"keyparameter\" table.")?;
1205 Ok(db)
1206 }
1207
1208 /// Helper method to insert an entry into key parameter table, with individual parameters
1209 fn insert_into_keyparameter<T: ToSql>(
1210 db: &Connection,
1211 key_id: i64,
1212 tag: i32,
1213 value: &T,
1214 security_level: i32,
1215 ) -> Result<()> {
1216 db.execute(
1217 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001218 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001219 params![key_id, tag, *value, security_level],
1220 )?;
1221 Ok(())
1222 }
1223
1224 /// Helper method to store a key parameter instance.
1225 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1226 db.execute(
1227 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001228 VALUES(?, ?, ?, ?);",
1229 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001230 )?;
1231 Ok(())
1232 }
1233
1234 /// Helper method to query a row from keyparameter table
1235 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001236 let mut stmt =
1237 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001238 let mut rows = stmt.query(NO_PARAMS)?;
1239 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001240 Ok(KeyParameter::new_from_sql(
1241 Tag(row.get(0)?),
1242 &SqlField(1, row),
1243 SecurityLevel(row.get(2)?),
1244 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001245 }
1246}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001247
1248/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001249/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001250/// key parameter.
1251/// i) bool
1252/// ii) integer
1253/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001254/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001255#[cfg(test)]
1256mod wire_tests {
1257 use crate::key_parameter::*;
1258 /// unit tests for to conversions
1259 #[test]
1260 fn test_convert_to_wire_invalid() {
1261 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1262 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1263 assert_eq!(Tag::INVALID, actual.tag);
1264 }
1265 #[test]
1266 fn test_convert_to_wire_bool() {
1267 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1268 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1269 assert_eq!(Tag::CALLER_NONCE, actual.tag);
1270 assert_eq!(true, actual.boolValue);
1271 }
1272 #[test]
1273 fn test_convert_to_wire_integer() {
1274 let kp = KeyParameter::new(
1275 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1276 SecurityLevel::STRONGBOX,
1277 );
1278 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1279 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001280 assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001281 }
1282 #[test]
1283 fn test_convert_to_wire_long_integer() {
1284 let kp =
1285 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1286 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1287 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
1288 assert_eq!(i64::MAX, actual.longInteger);
1289 }
1290 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001291 fn test_convert_to_wire_blob() {
1292 let kp = KeyParameter::new(
1293 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1294 SecurityLevel::STRONGBOX,
1295 );
1296 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1297 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
1298 assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
1299 }
1300
1301 /// unit tests for from conversion
1302 #[test]
1303 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001304 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001305 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1306 assert_eq!(KeyParameterValue::Invalid, actual);
1307 }
1308 #[test]
1309 fn test_convert_from_wire_bool() {
1310 let aidl_kp =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001311 KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001312 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1313 assert_eq!(KeyParameterValue::CallerNonce, actual);
1314 }
1315 #[test]
1316 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001317 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001318 tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001319 integer: KeyPurpose::ENCRYPT.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001320 ..Default::default()
1321 };
1322 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1323 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1324 }
1325 #[test]
1326 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001327 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001328 tag: Tag::USER_SECURE_ID,
1329 longInteger: i64::MAX,
1330 ..Default::default()
1331 };
1332 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1333 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1334 }
1335 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001336 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001337 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001338 tag: Tag::CONFIRMATION_TOKEN,
1339 blob: String::from("ConfirmationToken").into_bytes(),
1340 ..Default::default()
1341 };
1342 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1343 assert_eq!(
1344 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1345 actual
1346 );
1347 }
1348}