blob: 0d164f1ede79d9b75174e79e7613b9efe8061ef7 [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,
26 Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000027};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070028pub use android_system_keystore2::aidl::android::system::keystore2::SecurityLevel::SecurityLevel;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000029use anyhow::{Context, Result};
30use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
31use rusqlite::{Result as SqlResult, Row};
Hasini Gunasinghe12486362020-07-24 18:40:20 +000032
33/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070034#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000035pub struct KeyParameter {
36 key_parameter_value: KeyParameterValue,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070037 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000038}
39
40/// KeyParameterValue holds a value corresponding to one of the Tags defined in
41/// the AIDL spec at hardware/interfaces/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070042#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000043pub enum KeyParameterValue {
44 /// Associated with Tag:INVALID
45 Invalid,
46 /// Set of purposes for which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070047 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000048 /// Cryptographic algorithm with which the key is used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070049 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000050 /// Size of the key , in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +000051 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000052 /// Block cipher mode(s) with which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070053 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000054 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070055 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000056 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070057 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000058 /// Can the caller provide a nonce for nonce-requiring operations
59 CallerNonce,
60 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Hasini Gunasingheaf993662020-07-24 18:40:20 +000061 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000062 /// The elliptic curve
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070063 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000064 /// Value of the public exponent for an RSA key pair
Hasini Gunasingheaf993662020-07-24 18:40:20 +000065 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000066 /// An attestation certificate for the generated key should contain an application-scoped
67 /// and time-bounded device-unique ID
68 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000069 //TODO: find out about this
70 // /// Necessary system environment conditions for the generated key to be used
71 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000072 /// Only the boot loader can use the key
73 BootLoaderOnly,
74 /// When deleted, the key is guaranteed to be permanently deleted and unusable
75 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000076 /// The date and time at which the key becomes active
Hasini Gunasingheaf993662020-07-24 18:40:20 +000077 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000078 /// The date and time at which the key expires for signing and encryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000079 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000080 /// The date and time at which the key expires for verification and decryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000081 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000082 /// Minimum amount of time that elapses between allowed operations
Hasini Gunasingheaf993662020-07-24 18:40:20 +000083 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000084 /// Maximum number of times that a key may be used between system reboots
Hasini Gunasingheaf993662020-07-24 18:40:20 +000085 MaxUsesPerBoot(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000086 /// ID of the Android user that is permitted to use the key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000087 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000088 /// A key may only be used under a particular secure user authentication state
Hasini Gunasingheaf993662020-07-24 18:40:20 +000089 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000090 /// No authentication is required to use this key
91 NoAuthRequired,
92 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070093 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000094 /// The time in seconds for which the key is authorized for use, after user authentication
Hasini Gunasingheaf993662020-07-24 18:40:20 +000095 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000096 /// The key may be used after authentication timeout if device is still on-body
97 AllowWhileOnBody,
98 /// The key must be unusable except when the user has provided proof of physical presence
99 TrustedUserPresenceRequired,
100 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
101 /// unless the user provides confirmation of the data to be signed
102 TrustedConfirmationRequired,
103 /// The key may only be used when the device is unlocked
104 UnlockedDeviceRequired,
105 /// When provided to generateKey or importKey, this tag specifies data
106 /// that is necessary during all uses of the key
107 ApplicationID(Vec<u8>),
108 /// When provided to generateKey or importKey, this tag specifies data
109 /// that is necessary during all uses of the key
110 ApplicationData(Vec<u8>),
111 /// Specifies the date and time the key was created
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000112 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000113 /// Specifies where the key was created, if known
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700114 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000115 /// The key used by verified boot to validate the operating system booted
116 RootOfTrust(Vec<u8>),
117 /// System OS version with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000118 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000119 /// Specifies the system security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000120 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000121 /// Specifies a unique, time-based identifier
122 UniqueID(Vec<u8>),
123 /// Used to deliver a "challenge" value to the attestKey() method
124 AttestationChallenge(Vec<u8>),
125 /// The set of applications which may use a key, used only with attestKey()
126 AttestationApplicationID(Vec<u8>),
127 /// Provides the device's brand name, to attestKey()
128 AttestationIdBrand(Vec<u8>),
129 /// Provides the device's device name, to attestKey()
130 AttestationIdDevice(Vec<u8>),
131 /// Provides the device's product name, to attestKey()
132 AttestationIdProduct(Vec<u8>),
133 /// Provides the device's serial number, to attestKey()
134 AttestationIdSerial(Vec<u8>),
135 /// Provides the IMEIs for all radios on the device, to attestKey()
136 AttestationIdIMEI(Vec<u8>),
137 /// Provides the MEIDs for all radios on the device, to attestKey()
138 AttestationIdMEID(Vec<u8>),
139 /// Provides the device's manufacturer name, to attestKey()
140 AttestationIdManufacturer(Vec<u8>),
141 /// Provides the device's model name, to attestKey()
142 AttestationIdModel(Vec<u8>),
143 /// Specifies the vendor image security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000144 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000145 /// Specifies the boot image (kernel) security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000146 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000147 /// Provides "associated data" for AES-GCM encryption or decryption
148 AssociatedData(Vec<u8>),
149 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
150 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
151 Nonce(Vec<u8>),
152 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000153 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000154 /// Specifies whether the device has been factory reset since the
155 /// last unique ID rotation. Used for key attestation
156 ResetSinceIdRotation,
157 /// Used to deliver a cryptographic token proving that the user
158 /// confirmed a signing request
159 ConfirmationToken(Vec<u8>),
160}
161
162impl KeyParameter {
163 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700164 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000165 KeyParameter { key_parameter_value, security_level }
166 }
167
168 /// Returns the tag given the KeyParameter instance.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700169 pub fn get_tag(&self) -> Tag {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000170 match self.key_parameter_value {
171 KeyParameterValue::Invalid => Tag::INVALID,
172 KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
173 KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
174 KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
175 KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
176 KeyParameterValue::Digest(_) => Tag::DIGEST,
177 KeyParameterValue::PaddingMode(_) => Tag::PADDING,
178 KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
179 KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
180 KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
181 KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
182 KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000183 KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
184 KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
185 KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
186 KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
187 KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
188 KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
189 KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
190 KeyParameterValue::UserID(_) => Tag::USER_ID,
191 KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
192 KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
193 KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
194 KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
195 KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
196 KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
197 KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
198 KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
199 KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
200 KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
201 KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
202 KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
203 KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
204 KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
205 KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
206 KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
207 KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
208 KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
209 KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
210 KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
211 KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
212 KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
213 KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
214 KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
215 KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
216 KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
217 KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
218 KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
219 KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
220 KeyParameterValue::Nonce(_) => Tag::NONCE,
221 KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
222 KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
223 KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
224 }
225 }
226
227 /// Returns key parameter value.
228 pub fn key_parameter_value(&self) -> &KeyParameterValue {
229 &self.key_parameter_value
230 }
231
232 /// Returns the security level of a KeyParameter.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700233 pub fn security_level(&self) -> &SecurityLevel {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000234 &self.security_level
235 }
236}
237
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000238/// This struct is defined to postpone converting rusqlite column value to the
239/// appropriate key parameter value until we know the corresponding tag value.
240/// Wraps the column index and a rusqlite row.
241pub struct SqlField<'a>(usize, &'a Row<'a>);
242
243impl<'a> SqlField<'a> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700244 /// Creates a new SqlField with the given index and row.
245 pub fn new(index: usize, row: &'a Row<'a>) -> Self {
246 Self(index, row)
247 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000248 /// Returns the column value from the row, when we know the expected type.
249 pub fn get<T: FromSql>(&self) -> SqlResult<T> {
250 self.1.get(self.0)
251 }
252}
253
254impl ToSql for KeyParameterValue {
255 /// Converts KeyParameterValue to be stored in rusqlite database.
256 /// Note that following variants of KeyParameterValue should not be stored:
257 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
258 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
259 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
260 /// conversion for all the variants, to keep error handling simple.
261 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
262 match self {
263 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700264 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
265 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000266 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700267 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
268 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
269 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000270 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
271 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700272 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000273 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
274 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
275 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
276 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
277 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
278 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
279 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
280 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
281 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
282 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
283 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
284 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700285 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000286 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
287 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
288 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
289 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
290 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
291 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
292 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
293 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700294 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000295 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
296 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
297 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
298 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
299 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
300 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
301 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
302 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
303 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
304 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
305 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
306 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
307 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
308 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
309 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
310 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
311 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
312 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
313 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
314 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
315 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
316 }
317 }
318}
319
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000320impl KeyParameter {
321 /// Construct a KeyParameter from the data from a rusqlite row.
322 /// Note that following variants of KeyParameterValue should not be stored:
323 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
324 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
325 /// This filtering is enforced at a higher level and here we support conversion for all the
326 /// variants.
327 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700328 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000329 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700330 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000331 ) -> Result<Self> {
332 let key_param_value = match tag_val {
333 Tag::INVALID => KeyParameterValue::Invalid,
334 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700335 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000336 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700337 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700338 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700339 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000340 }
341 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700342 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000343 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700344 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700345 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700346 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000347 }
348 Tag::KEY_SIZE => {
349 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700350 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000351 KeyParameterValue::KeySize(key_size)
352 }
353 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700354 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000355 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700356 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700357 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700358 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000359 }
360 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700361 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000362 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700363 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700364 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700365 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000366 }
367 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700368 let padding: 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: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700372 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000373 }
374 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
375 Tag::MIN_MAC_LENGTH => {
376 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700377 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000378 KeyParameterValue::MinMacLength(min_mac_length)
379 }
380 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700381 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000382 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700383 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700384 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700385 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000386 }
387 Tag::RSA_PUBLIC_EXPONENT => {
388 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700389 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000390
391 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
392 }
393 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
394 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
395 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
396 Tag::ACTIVE_DATETIME => {
397 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700398 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000399 KeyParameterValue::ActiveDateTime(active_datetime)
400 }
401 Tag::ORIGINATION_EXPIRE_DATETIME => {
402 let origination_expire_datetime: i64 = data
403 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700404 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000405 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
406 }
407 Tag::USAGE_EXPIRE_DATETIME => {
408 let usage_expire_datetime: i64 = data
409 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700410 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000411 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
412 }
413 Tag::MIN_SECONDS_BETWEEN_OPS => {
414 let min_secs_between_ops: i32 = data
415 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700416 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000417 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
418 }
419 Tag::MAX_USES_PER_BOOT => {
420 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700421 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000422 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
423 }
424 Tag::USER_ID => {
425 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700426 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000427 KeyParameterValue::UserID(user_id)
428 }
429 Tag::USER_SECURE_ID => {
430 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700431 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000432 KeyParameterValue::UserSecureID(user_secure_id)
433 }
434 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
435 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700436 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000437 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700438 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700439 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700440 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
441 user_auth_type,
442 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000443 }
444 Tag::AUTH_TIMEOUT => {
445 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700446 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000447 KeyParameterValue::AuthTimeout(auth_timeout)
448 }
449 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
450 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
451 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
452 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
453 Tag::APPLICATION_ID => {
454 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700455 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000456 KeyParameterValue::ApplicationID(app_id)
457 }
458 Tag::APPLICATION_DATA => {
459 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700460 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000461 KeyParameterValue::ApplicationData(app_data)
462 }
463 Tag::CREATION_DATETIME => {
464 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700465 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000466 KeyParameterValue::CreationDateTime(creation_datetime)
467 }
468 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700469 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000470 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700471 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700472 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700473 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000474 }
475 Tag::ROOT_OF_TRUST => {
476 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700477 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000478 KeyParameterValue::RootOfTrust(root_of_trust)
479 }
480 Tag::OS_VERSION => {
481 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700482 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000483 KeyParameterValue::OSVersion(os_version)
484 }
485 Tag::OS_PATCHLEVEL => {
486 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700487 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000488 KeyParameterValue::OSPatchLevel(os_patch_level)
489 }
490 Tag::UNIQUE_ID => {
491 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700492 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000493 KeyParameterValue::UniqueID(unique_id)
494 }
495 Tag::ATTESTATION_CHALLENGE => {
496 let attestation_challenge: Vec<u8> = data
497 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700498 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000499 KeyParameterValue::AttestationChallenge(attestation_challenge)
500 }
501 Tag::ATTESTATION_APPLICATION_ID => {
502 let attestation_app_id: Vec<u8> = data
503 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700504 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000505 KeyParameterValue::AttestationApplicationID(attestation_app_id)
506 }
507 Tag::ATTESTATION_ID_BRAND => {
508 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700509 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000510 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
511 }
512 Tag::ATTESTATION_ID_DEVICE => {
513 let attestation_id_device: Vec<u8> = data
514 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700515 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000516 KeyParameterValue::AttestationIdDevice(attestation_id_device)
517 }
518 Tag::ATTESTATION_ID_PRODUCT => {
519 let attestation_id_product: Vec<u8> = data
520 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700521 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000522 KeyParameterValue::AttestationIdProduct(attestation_id_product)
523 }
524 Tag::ATTESTATION_ID_SERIAL => {
525 let attestation_id_serial: Vec<u8> = data
526 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700527 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000528 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
529 }
530 Tag::ATTESTATION_ID_IMEI => {
531 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700532 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000533 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
534 }
535 Tag::ATTESTATION_ID_MEID => {
536 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700537 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000538 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
539 }
540 Tag::ATTESTATION_ID_MANUFACTURER => {
541 let attestation_id_manufacturer: Vec<u8> = data
542 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700543 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000544 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
545 }
546 Tag::ATTESTATION_ID_MODEL => {
547 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700548 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000549 KeyParameterValue::AttestationIdModel(attestation_id_model)
550 }
551 Tag::VENDOR_PATCHLEVEL => {
552 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700553 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000554 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
555 }
556 Tag::BOOT_PATCHLEVEL => {
557 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700558 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000559 KeyParameterValue::BootPatchLevel(boot_patch_level)
560 }
561 Tag::ASSOCIATED_DATA => {
562 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700563 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000564 KeyParameterValue::AssociatedData(associated_data)
565 }
566 Tag::NONCE => {
567 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700568 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000569 KeyParameterValue::Nonce(nonce)
570 }
571 Tag::MAC_LENGTH => {
572 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700573 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000574 KeyParameterValue::MacLength(mac_length)
575 }
576 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
577 Tag::CONFIRMATION_TOKEN => {
578 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700579 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000580 KeyParameterValue::ConfirmationToken(confirmation_token)
581 }
582 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700583 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700584 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000585 }
586 };
587 Ok(KeyParameter::new(key_param_value, security_level_val))
588 }
589}
590
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000591/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700592/// This macro takes between three and four different pieces of information about each
593/// of the KeyParameterValue variants:
594/// 1. The KeyParameterValue variant name,
595/// 2. the tag name corresponding to the variant,
596/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
597/// stored when converted, and
598/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000599/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
600/// the two conversion methods: convert_to_wire() and convert_from_wire().
601/// ## Example
602/// ```
603/// implement_key_parameter_conversion_to_from_wire! {
604/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700605/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000606/// CallerNonce, CALLER_NONCE, boolValue;
607/// UserSecureID, USER_SECURE_ID, longInteger;
608/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000609/// }
610/// ```
611/// expands to:
612/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700613/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000614/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700615/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000616/// tag: Tag::INVALID,
617/// ..Default::default()
618/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700619/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000620/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700621/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000622/// ..Default::default()
623/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700624/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000625/// tag: Tag::CALLER_NONCE,
626/// boolValue: true,
627/// ..Default::default()
628/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700629/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000630/// tag: Tag::USER_SECURE_ID,
631/// longInteger: v,
632/// ..Default::default()
633/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700634/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000635/// tag: Tag::APPLICATION_ID,
636/// blob: v,
637/// ..Default::default()
638/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000639/// }
640/// }
641/// ```
642/// and
643/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700644/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000645/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700646/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000647/// tag: Tag::INVALID,
648/// ..
649/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700650/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000651/// tag: Tag::PURPOSE,
652/// integer: v,
653/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700654/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
655/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000656/// tag: Tag::CALLER_NONCE,
657/// boolValue: true,
658/// ..
659/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700660/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000661/// tag: Tag::USER_SECURE_ID,
662/// longInteger: v,
663/// ..
664/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700665/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000666/// tag: Tag::APPLICATION_ID,
667/// blob: v,
668/// ..
669/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000670/// _ => KeyParameterValue::Invalid,
671/// }
672/// }
673///
674macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700675 // There are three groups of rules in this macro.
676 // 1. The first group contains the rule which acts as the public interface. It takes the input
677 // given to this macro and prepares it to be given as input to the two groups of rules
678 // mentioned below.
679 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
680 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
681 //
682 // Input to this macro is first handled by the first macro rule (belonging to the first
683 // group above), which pre-processes the input such that rules in the other two groups
684 // generate the code for the two methods, when called recursively.
685 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
686 // four macro rules in the second two groups. These four rules intend to do the following
687 // tasks respectively:
688 // i) generates match arms related to Invalid KeyParameterValue variant.
689 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
690 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
691 // iv) generates the method definition including the match arms generated from the above
692 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000693
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700694 // This rule is applied on the input given to the macro invocations from outside the macro.
695 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
696 // pre-processes input to target the rules that generate convert_to_wire() method.
697 implement_key_parameter_conversion_to_from_wire! {@to
698 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
699 }
700 // pre-processes input to target the rules that generate convert_from_wire() method.
701 implement_key_parameter_conversion_to_from_wire! {@from
702 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
703 }
704 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000705
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700706 // Following four rules (belonging to the aforementioned second group) generate
707 // convert_to_wire() conversion method.
708 // -----------------------------------------------------------------------
709 // This rule handles Invalid variant.
710 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
711 // KeyParameterValue::Invalid => KmKeyParameter {
712 // tag: Tag::INVALID,
713 // ..Default::default()
714 // },
715 (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
716 implement_key_parameter_conversion_to_from_wire! {@to
717 [$($out)*
718 KeyParameterValue::Invalid => KmKeyParameter {
719 tag: Tag::INVALID,
720 ..Default::default()
721 },
722 ], $($in)*
723 }
724 };
725 // This rule handles all variants that correspond to bool values.
726 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
727 // a match arm like:
728 // KeyParameterValue::CallerNonce => KmKeyParameter {
729 // tag: Tag::CALLER_NONCE,
730 // boolValue: true,
731 // ..Default::default()
732 // },
733 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
734 implement_key_parameter_conversion_to_from_wire! {@to
735 [$($out)*
736 KeyParameterValue::$variant => KmKeyParameter {
737 tag: Tag::$tag_val,
738 boolValue: true,
739 ..Default::default()
740 },
741 ], $($in)*
742 }
743 };
744 // This rule handles all enum variants.
745 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
746 // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
747 // tag: Tag::PURPOSE,
748 // integer: v.0,
749 // ..Default::default(),
750 // },
751 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
752 implement_key_parameter_conversion_to_from_wire! {@to
753 [$($out)*
754 KeyParameterValue::$variant(v) => KmKeyParameter {
755 tag: Tag::$tag_val,
756 $field: v.0,
757 ..Default::default()
758 },
759 ], $($in)*
760 }
761 };
762 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700763 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700764 // KmKeyParameter).
765 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
766 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
767 // tag: Tag::CONFIRMATION_TOKEN,
768 // blob: v,
769 // ..Default::default(),
770 // },
771 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
772 implement_key_parameter_conversion_to_from_wire! {@to
773 [$($out)*
774 KeyParameterValue::$variant(v) => KmKeyParameter {
775 tag: Tag::$tag_val,
776 $field: v,
777 ..Default::default()
778 },
779 ], $($in)*
780 }
781 };
782 // After all the match arms are generated by the above three rules, this rule combines them
783 // into the convert_to_wire() method.
784 (@to [$($out:tt)*], ) => {
785 /// Conversion of key parameter to wire type
786 pub fn convert_to_wire(self) -> KmKeyParameter {
787 match self {
788 $($out)*
789 }
790 }
791 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000792
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700793 // Following four rules (belonging to the aforementioned third group) generate
794 // convert_from_wire() conversion method.
795 // ------------------------------------------------------------------------
796 // This rule handles Invalid variant.
797 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
798 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
799 (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
800 implement_key_parameter_conversion_to_from_wire! {@from
801 [$($out)*
802 KmKeyParameter {
803 tag: Tag::INVALID,
804 ..
805 } => KeyParameterValue::Invalid,
806 ], $($in)*
807 }
808 };
809 // This rule handles all variants that correspond to bool values.
810 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
811 // KmKeyParameter {
812 // tag: Tag::CALLER_NONCE,
813 // boolValue: true,
814 // ..
815 // } => KeyParameterValue::CallerNonce,
816 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
817 implement_key_parameter_conversion_to_from_wire! {@from
818 [$($out)*
819 KmKeyParameter {
820 tag: Tag::$tag_val,
821 boolValue: true,
822 ..
823 } => KeyParameterValue::$variant,
824 ], $($in)*
825 }
826 };
827 // This rule handles all enum variants.
828 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
829 // like:
830 // KmKeyParameter {
831 // tag: Tag::PURPOSE,
832 // integer: v,
833 // ..,
834 // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
835 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
836 implement_key_parameter_conversion_to_from_wire! {@from
837 [$($out)*
838 KmKeyParameter {
839 tag: Tag::$tag_val,
840 $field: v,
841 ..
842 } => KeyParameterValue::$variant($enum_type(v)),
843 ], $($in)*
844 }
845 };
846 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700847 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700848 // KmKeyParameter).
849 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
850 // like:
851 // KmKeyParameter {
852 // tag: Tag::CONFIRMATION_TOKEN,
853 // blob: v,
854 // ..,
855 // } => KeyParameterValue::ConfirmationToken(v),
856 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
857 implement_key_parameter_conversion_to_from_wire! {@from
858 [$($out)*
859 KmKeyParameter {
860 tag: Tag::$tag_val,
861 $field: v,
862 ..
863 } => KeyParameterValue::$variant(v),
864 ], $($in)*
865 }
866 };
867 // After all the match arms are generated by the above three rules, this rule combines them
868 // into the convert_from_wire() method.
869 (@from [$($out:tt)*], ) => {
870 /// Conversion of key parameter from wire type
871 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
872 match aidl_kp {
873 $($out)*
874 _ => KeyParameterValue::Invalid,
875 }
876 }
877 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000878}
879
880impl KeyParameterValue {
881 // Invoke the macro that generates the code for key parameter conversion to/from wire type
882 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
883 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700884 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000885 implement_key_parameter_conversion_to_from_wire! {
886 Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700887 KeyPurpose, PURPOSE, integer, KeyPurpose;
888 Algorithm, ALGORITHM, integer, Algorithm;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000889 KeySize, KEY_SIZE, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700890 BlockMode, BLOCK_MODE, integer, BlockMode;
891 Digest, DIGEST, integer, Digest;
892 PaddingMode, PADDING, integer, PaddingMode;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000893 CallerNonce, CALLER_NONCE, boolValue;
894 MinMacLength, MIN_MAC_LENGTH, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700895 EcCurve, EC_CURVE, integer, EcCurve;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000896 RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
897 IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
898 BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
899 RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700900 ActiveDateTime, ACTIVE_DATETIME, longInteger;
901 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
902 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000903 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
904 MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
905 UserID, USER_ID, integer;
906 UserSecureID, USER_SECURE_ID, longInteger;
907 NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700908 HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000909 AuthTimeout, AUTH_TIMEOUT, integer;
910 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
911 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
912 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
913 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
914 ApplicationID, APPLICATION_ID, blob;
915 ApplicationData, APPLICATION_DATA, blob;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700916 CreationDateTime, CREATION_DATETIME, longInteger;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700917 KeyOrigin, ORIGIN, integer, KeyOrigin;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000918 RootOfTrust, ROOT_OF_TRUST, blob;
919 OSVersion, OS_VERSION, integer;
920 OSPatchLevel, OS_PATCHLEVEL, integer;
921 UniqueID, UNIQUE_ID, blob;
922 AttestationChallenge, ATTESTATION_CHALLENGE, blob;
923 AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
924 AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
925 AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
926 AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
927 AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
928 AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
929 AttestationIdMEID, ATTESTATION_ID_MEID, blob;
930 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
931 AttestationIdModel, ATTESTATION_ID_MODEL, blob;
932 VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
933 BootPatchLevel, BOOT_PATCHLEVEL, integer;
934 AssociatedData, ASSOCIATED_DATA, blob;
935 Nonce, NONCE, blob;
936 MacLength, MAC_LENGTH, integer;
937 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
938 ConfirmationToken, CONFIRMATION_TOKEN, blob;
939 }
940}
941
942#[cfg(test)]
943mod basic_tests {
944 use crate::key_parameter::*;
945
946 // Test basic functionality of KeyParameter.
947 #[test]
948 fn test_key_parameter() {
949 let key_parameter = KeyParameter::new(
950 KeyParameterValue::Algorithm(Algorithm::RSA),
951 SecurityLevel::STRONGBOX,
952 );
953
954 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
955
956 assert_eq!(
957 *key_parameter.key_parameter_value(),
958 KeyParameterValue::Algorithm(Algorithm::RSA)
959 );
960
961 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
962 }
963}
964
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000965/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
966/// data types and then tests 'to_sql' method for KeyParameters of those
967/// different data types. The five different data types for KeyParameter values are:
968/// i) enums of u32
969/// ii) u32
970/// iii) u64
971/// iv) Vec<u8>
972/// v) bool
973#[cfg(test)]
974mod storage_tests {
975 use crate::error::*;
976 use crate::key_parameter::*;
977 use anyhow::Result;
978 use rusqlite::types::ToSql;
979 use rusqlite::{params, Connection, NO_PARAMS};
980
981 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
982 /// from a database table row.
983 #[test]
984 fn test_new_from_sql_enum_i32() -> Result<()> {
985 let db = init_db()?;
986 insert_into_keyparameter(
987 &db,
988 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700989 Tag::ALGORITHM.0,
990 &Algorithm::RSA.0,
991 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000992 )?;
993 let key_param = query_from_keyparameter(&db)?;
994 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
995 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
996 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
997 Ok(())
998 }
999
1000 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1001 /// from a database table row.
1002 #[test]
1003 fn test_new_from_sql_i32() -> Result<()> {
1004 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001005 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001006 let key_param = query_from_keyparameter(&db)?;
1007 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1008 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1009 Ok(())
1010 }
1011
1012 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1013 /// from a database table row.
1014 #[test]
1015 fn test_new_from_sql_i64() -> Result<()> {
1016 let db = init_db()?;
1017 // max value for i64, just to test corner cases
1018 insert_into_keyparameter(
1019 &db,
1020 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001021 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001022 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001023 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001024 )?;
1025 let key_param = query_from_keyparameter(&db)?;
1026 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1027 assert_eq!(
1028 *key_param.key_parameter_value(),
1029 KeyParameterValue::RSAPublicExponent(i64::MAX)
1030 );
1031 Ok(())
1032 }
1033
1034 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1035 /// from a database table row.
1036 #[test]
1037 fn test_new_from_sql_bool() -> Result<()> {
1038 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001039 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001040 let key_param = query_from_keyparameter(&db)?;
1041 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1042 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1043 Ok(())
1044 }
1045
1046 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1047 /// from a database table row.
1048 #[test]
1049 fn test_new_from_sql_vec_u8() -> Result<()> {
1050 let db = init_db()?;
1051 let app_id = String::from("MyAppID");
1052 let app_id_bytes = app_id.into_bytes();
1053 insert_into_keyparameter(
1054 &db,
1055 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001057 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001058 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001059 )?;
1060 let key_param = query_from_keyparameter(&db)?;
1061 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1062 assert_eq!(
1063 *key_param.key_parameter_value(),
1064 KeyParameterValue::ApplicationID(app_id_bytes)
1065 );
1066 Ok(())
1067 }
1068
1069 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1070 /// in the database
1071 #[test]
1072 fn test_to_sql_enum_i32() -> Result<()> {
1073 let db = init_db()?;
1074 let kp = KeyParameter::new(
1075 KeyParameterValue::Algorithm(Algorithm::RSA),
1076 SecurityLevel::STRONGBOX,
1077 );
1078 store_keyparameter(&db, 1, &kp)?;
1079 let key_param = query_from_keyparameter(&db)?;
1080 assert_eq!(kp.get_tag(), key_param.get_tag());
1081 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1082 assert_eq!(kp.security_level(), key_param.security_level());
1083 Ok(())
1084 }
1085
1086 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1087 #[test]
1088 fn test_to_sql_i32() -> Result<()> {
1089 let db = init_db()?;
1090 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
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 i64) in the database
1100 #[test]
1101 fn test_to_sql_i64() -> Result<()> {
1102 let db = init_db()?;
1103 // max value for i64, just to test corner cases
1104 let kp = KeyParameter::new(
1105 KeyParameterValue::RSAPublicExponent(i64::MAX),
1106 SecurityLevel::STRONGBOX,
1107 );
1108 store_keyparameter(&db, 1, &kp)?;
1109 let key_param = query_from_keyparameter(&db)?;
1110 assert_eq!(kp.get_tag(), key_param.get_tag());
1111 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1112 assert_eq!(kp.security_level(), key_param.security_level());
1113 Ok(())
1114 }
1115
1116 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1117 #[test]
1118 fn test_to_sql_vec_u8() -> Result<()> {
1119 let db = init_db()?;
1120 let kp = KeyParameter::new(
1121 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1122 SecurityLevel::STRONGBOX,
1123 );
1124 store_keyparameter(&db, 1, &kp)?;
1125 let key_param = query_from_keyparameter(&db)?;
1126 assert_eq!(kp.get_tag(), key_param.get_tag());
1127 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1128 assert_eq!(kp.security_level(), key_param.security_level());
1129 Ok(())
1130 }
1131
1132 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1133 #[test]
1134 fn test_to_sql_bool() -> Result<()> {
1135 let db = init_db()?;
1136 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1137 store_keyparameter(&db, 1, &kp)?;
1138 let key_param = query_from_keyparameter(&db)?;
1139 assert_eq!(kp.get_tag(), key_param.get_tag());
1140 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1141 assert_eq!(kp.security_level(), key_param.security_level());
1142 Ok(())
1143 }
1144
1145 #[test]
1146 /// Test Tag::Invalid
1147 fn test_invalid_tag() -> Result<()> {
1148 let db = init_db()?;
1149 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1150 let key_param = query_from_keyparameter(&db)?;
1151 assert_eq!(Tag::INVALID, key_param.get_tag());
1152 Ok(())
1153 }
1154
1155 #[test]
1156 fn test_non_existing_enum_variant() -> Result<()> {
1157 let db = init_db()?;
1158 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1159 tests::check_result_contains_error_string(
1160 query_from_keyparameter(&db),
1161 "Failed to decode Tag enum from value.",
1162 );
1163 Ok(())
1164 }
1165
1166 #[test]
1167 fn test_invalid_conversion_from_sql() -> Result<()> {
1168 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001169 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001170 tests::check_result_contains_error_string(
1171 query_from_keyparameter(&db),
1172 "Failed to read sql data for tag: ALGORITHM.",
1173 );
1174 Ok(())
1175 }
1176
1177 /// Helper method to init database table for key parameter
1178 fn init_db() -> Result<Connection> {
1179 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1180 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1181 .context("Failed to attach databases.")?;
1182 db.execute(
1183 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1184 keyentryid INTEGER,
1185 tag INTEGER,
1186 data ANY,
1187 security_level INTEGER);",
1188 NO_PARAMS,
1189 )
1190 .context("Failed to initialize \"keyparameter\" table.")?;
1191 Ok(db)
1192 }
1193
1194 /// Helper method to insert an entry into key parameter table, with individual parameters
1195 fn insert_into_keyparameter<T: ToSql>(
1196 db: &Connection,
1197 key_id: i64,
1198 tag: i32,
1199 value: &T,
1200 security_level: i32,
1201 ) -> Result<()> {
1202 db.execute(
1203 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001204 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001205 params![key_id, tag, *value, security_level],
1206 )?;
1207 Ok(())
1208 }
1209
1210 /// Helper method to store a key parameter instance.
1211 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1212 db.execute(
1213 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001214 VALUES(?, ?, ?, ?);",
1215 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001216 )?;
1217 Ok(())
1218 }
1219
1220 /// Helper method to query a row from keyparameter table
1221 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001222 let mut stmt =
1223 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001224 let mut rows = stmt.query(NO_PARAMS)?;
1225 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001226 Ok(KeyParameter::new_from_sql(
1227 Tag(row.get(0)?),
1228 &SqlField(1, row),
1229 SecurityLevel(row.get(2)?),
1230 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001231 }
1232}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001233
1234/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001235/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001236/// key parameter.
1237/// i) bool
1238/// ii) integer
1239/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001240/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001241#[cfg(test)]
1242mod wire_tests {
1243 use crate::key_parameter::*;
1244 /// unit tests for to conversions
1245 #[test]
1246 fn test_convert_to_wire_invalid() {
1247 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1248 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1249 assert_eq!(Tag::INVALID, actual.tag);
1250 }
1251 #[test]
1252 fn test_convert_to_wire_bool() {
1253 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1254 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1255 assert_eq!(Tag::CALLER_NONCE, actual.tag);
1256 assert_eq!(true, actual.boolValue);
1257 }
1258 #[test]
1259 fn test_convert_to_wire_integer() {
1260 let kp = KeyParameter::new(
1261 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1262 SecurityLevel::STRONGBOX,
1263 );
1264 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1265 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001266 assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001267 }
1268 #[test]
1269 fn test_convert_to_wire_long_integer() {
1270 let kp =
1271 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1272 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1273 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
1274 assert_eq!(i64::MAX, actual.longInteger);
1275 }
1276 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001277 fn test_convert_to_wire_blob() {
1278 let kp = KeyParameter::new(
1279 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1280 SecurityLevel::STRONGBOX,
1281 );
1282 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1283 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
1284 assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
1285 }
1286
1287 /// unit tests for from conversion
1288 #[test]
1289 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001290 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001291 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1292 assert_eq!(KeyParameterValue::Invalid, actual);
1293 }
1294 #[test]
1295 fn test_convert_from_wire_bool() {
1296 let aidl_kp =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001297 KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001298 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1299 assert_eq!(KeyParameterValue::CallerNonce, actual);
1300 }
1301 #[test]
1302 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001303 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001304 tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001305 integer: KeyPurpose::ENCRYPT.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001306 ..Default::default()
1307 };
1308 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1309 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1310 }
1311 #[test]
1312 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001313 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001314 tag: Tag::USER_SECURE_ID,
1315 longInteger: i64::MAX,
1316 ..Default::default()
1317 };
1318 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1319 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1320 }
1321 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001322 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001323 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001324 tag: Tag::CONFIRMATION_TOKEN,
1325 blob: String::from("ConfirmationToken").into_bytes(),
1326 ..Default::default()
1327 };
1328 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1329 assert_eq!(
1330 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1331 actual
1332 );
1333 }
1334}