blob: 8825fc99edfe101a6a568047f8315af160c1227d [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;
609/// ActiveDateTime, ACTIVE_DATETIME, dateTime;
610/// }
611/// ```
612/// expands to:
613/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700614/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000615/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700616/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000617/// tag: Tag::INVALID,
618/// ..Default::default()
619/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700620/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000621/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700622/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000623/// ..Default::default()
624/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700625/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000626/// tag: Tag::CALLER_NONCE,
627/// boolValue: true,
628/// ..Default::default()
629/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700630/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000631/// tag: Tag::USER_SECURE_ID,
632/// longInteger: v,
633/// ..Default::default()
634/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700635/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000636/// tag: Tag::APPLICATION_ID,
637/// blob: v,
638/// ..Default::default()
639/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700640/// KeyParameterValue::ActiveDateTime(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000641/// tag: Tag::ACTIVE_DATETIME,
642/// dateTime: v,
643/// ..Default::default()
644/// },
645/// }
646/// }
647/// ```
648/// and
649/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700650/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000651/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700652/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000653/// tag: Tag::INVALID,
654/// ..
655/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700656/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000657/// tag: Tag::PURPOSE,
658/// integer: v,
659/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700660/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
661/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000662/// tag: Tag::CALLER_NONCE,
663/// boolValue: true,
664/// ..
665/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700666/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000667/// tag: Tag::USER_SECURE_ID,
668/// longInteger: v,
669/// ..
670/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700671/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000672/// tag: Tag::APPLICATION_ID,
673/// blob: v,
674/// ..
675/// } => KeyParameterValue::ApplicationID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700676/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000677/// tag: Tag::ACTIVE_DATETIME,
678/// dateTime: v,
679/// ..
680/// } => KeyParameterValue::ActiveDateTime(v),
681/// _ => KeyParameterValue::Invalid,
682/// }
683/// }
684///
685macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700686 // There are three groups of rules in this macro.
687 // 1. The first group contains the rule which acts as the public interface. It takes the input
688 // given to this macro and prepares it to be given as input to the two groups of rules
689 // mentioned below.
690 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
691 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
692 //
693 // Input to this macro is first handled by the first macro rule (belonging to the first
694 // group above), which pre-processes the input such that rules in the other two groups
695 // generate the code for the two methods, when called recursively.
696 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
697 // four macro rules in the second two groups. These four rules intend to do the following
698 // tasks respectively:
699 // i) generates match arms related to Invalid KeyParameterValue variant.
700 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
701 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
702 // iv) generates the method definition including the match arms generated from the above
703 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000704
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700705 // This rule is applied on the input given to the macro invocations from outside the macro.
706 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
707 // pre-processes input to target the rules that generate convert_to_wire() method.
708 implement_key_parameter_conversion_to_from_wire! {@to
709 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
710 }
711 // pre-processes input to target the rules that generate convert_from_wire() method.
712 implement_key_parameter_conversion_to_from_wire! {@from
713 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
714 }
715 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000716
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700717 // Following four rules (belonging to the aforementioned second group) generate
718 // convert_to_wire() conversion method.
719 // -----------------------------------------------------------------------
720 // This rule handles Invalid variant.
721 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
722 // KeyParameterValue::Invalid => KmKeyParameter {
723 // tag: Tag::INVALID,
724 // ..Default::default()
725 // },
726 (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
727 implement_key_parameter_conversion_to_from_wire! {@to
728 [$($out)*
729 KeyParameterValue::Invalid => KmKeyParameter {
730 tag: Tag::INVALID,
731 ..Default::default()
732 },
733 ], $($in)*
734 }
735 };
736 // This rule handles all variants that correspond to bool values.
737 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
738 // a match arm like:
739 // KeyParameterValue::CallerNonce => KmKeyParameter {
740 // tag: Tag::CALLER_NONCE,
741 // boolValue: true,
742 // ..Default::default()
743 // },
744 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
745 implement_key_parameter_conversion_to_from_wire! {@to
746 [$($out)*
747 KeyParameterValue::$variant => KmKeyParameter {
748 tag: Tag::$tag_val,
749 boolValue: true,
750 ..Default::default()
751 },
752 ], $($in)*
753 }
754 };
755 // This rule handles all enum variants.
756 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
757 // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
758 // tag: Tag::PURPOSE,
759 // integer: v.0,
760 // ..Default::default(),
761 // },
762 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
763 implement_key_parameter_conversion_to_from_wire! {@to
764 [$($out)*
765 KeyParameterValue::$variant(v) => KmKeyParameter {
766 tag: Tag::$tag_val,
767 $field: v.0,
768 ..Default::default()
769 },
770 ], $($in)*
771 }
772 };
773 // This rule handles all variants that are neither invalid nor bool values nor enums
774 // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
775 // KmKeyParameter).
776 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
777 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
778 // tag: Tag::CONFIRMATION_TOKEN,
779 // blob: v,
780 // ..Default::default(),
781 // },
782 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
783 implement_key_parameter_conversion_to_from_wire! {@to
784 [$($out)*
785 KeyParameterValue::$variant(v) => KmKeyParameter {
786 tag: Tag::$tag_val,
787 $field: v,
788 ..Default::default()
789 },
790 ], $($in)*
791 }
792 };
793 // After all the match arms are generated by the above three rules, this rule combines them
794 // into the convert_to_wire() method.
795 (@to [$($out:tt)*], ) => {
796 /// Conversion of key parameter to wire type
797 pub fn convert_to_wire(self) -> KmKeyParameter {
798 match self {
799 $($out)*
800 }
801 }
802 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000803
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700804 // Following four rules (belonging to the aforementioned third group) generate
805 // convert_from_wire() conversion method.
806 // ------------------------------------------------------------------------
807 // This rule handles Invalid variant.
808 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
809 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
810 (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
811 implement_key_parameter_conversion_to_from_wire! {@from
812 [$($out)*
813 KmKeyParameter {
814 tag: Tag::INVALID,
815 ..
816 } => KeyParameterValue::Invalid,
817 ], $($in)*
818 }
819 };
820 // This rule handles all variants that correspond to bool values.
821 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
822 // KmKeyParameter {
823 // tag: Tag::CALLER_NONCE,
824 // boolValue: true,
825 // ..
826 // } => KeyParameterValue::CallerNonce,
827 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
828 implement_key_parameter_conversion_to_from_wire! {@from
829 [$($out)*
830 KmKeyParameter {
831 tag: Tag::$tag_val,
832 boolValue: true,
833 ..
834 } => KeyParameterValue::$variant,
835 ], $($in)*
836 }
837 };
838 // This rule handles all enum variants.
839 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
840 // like:
841 // KmKeyParameter {
842 // tag: Tag::PURPOSE,
843 // integer: v,
844 // ..,
845 // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
846 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
847 implement_key_parameter_conversion_to_from_wire! {@from
848 [$($out)*
849 KmKeyParameter {
850 tag: Tag::$tag_val,
851 $field: v,
852 ..
853 } => KeyParameterValue::$variant($enum_type(v)),
854 ], $($in)*
855 }
856 };
857 // This rule handles all variants that are neither invalid nor bool values nor enums
858 // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
859 // KmKeyParameter).
860 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
861 // like:
862 // KmKeyParameter {
863 // tag: Tag::CONFIRMATION_TOKEN,
864 // blob: v,
865 // ..,
866 // } => KeyParameterValue::ConfirmationToken(v),
867 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
868 implement_key_parameter_conversion_to_from_wire! {@from
869 [$($out)*
870 KmKeyParameter {
871 tag: Tag::$tag_val,
872 $field: v,
873 ..
874 } => KeyParameterValue::$variant(v),
875 ], $($in)*
876 }
877 };
878 // After all the match arms are generated by the above three rules, this rule combines them
879 // into the convert_from_wire() method.
880 (@from [$($out:tt)*], ) => {
881 /// Conversion of key parameter from wire type
882 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
883 match aidl_kp {
884 $($out)*
885 _ => KeyParameterValue::Invalid,
886 }
887 }
888 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000889}
890
891impl KeyParameterValue {
892 // Invoke the macro that generates the code for key parameter conversion to/from wire type
893 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
894 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700895 // boolValue/integer/longInteger/dateTime/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000896 implement_key_parameter_conversion_to_from_wire! {
897 Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700898 KeyPurpose, PURPOSE, integer, KeyPurpose;
899 Algorithm, ALGORITHM, integer, Algorithm;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000900 KeySize, KEY_SIZE, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700901 BlockMode, BLOCK_MODE, integer, BlockMode;
902 Digest, DIGEST, integer, Digest;
903 PaddingMode, PADDING, integer, PaddingMode;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000904 CallerNonce, CALLER_NONCE, boolValue;
905 MinMacLength, MIN_MAC_LENGTH, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700906 EcCurve, EC_CURVE, integer, EcCurve;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000907 RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
908 IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
909 BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
910 RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
911 ActiveDateTime, ACTIVE_DATETIME, dateTime;
912 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, dateTime;
913 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, dateTime;
914 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
915 MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
916 UserID, USER_ID, integer;
917 UserSecureID, USER_SECURE_ID, longInteger;
918 NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700919 HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000920 AuthTimeout, AUTH_TIMEOUT, integer;
921 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
922 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
923 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
924 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
925 ApplicationID, APPLICATION_ID, blob;
926 ApplicationData, APPLICATION_DATA, blob;
927 CreationDateTime, CREATION_DATETIME, dateTime;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700928 KeyOrigin, ORIGIN, integer, KeyOrigin;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000929 RootOfTrust, ROOT_OF_TRUST, blob;
930 OSVersion, OS_VERSION, integer;
931 OSPatchLevel, OS_PATCHLEVEL, integer;
932 UniqueID, UNIQUE_ID, blob;
933 AttestationChallenge, ATTESTATION_CHALLENGE, blob;
934 AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
935 AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
936 AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
937 AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
938 AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
939 AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
940 AttestationIdMEID, ATTESTATION_ID_MEID, blob;
941 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
942 AttestationIdModel, ATTESTATION_ID_MODEL, blob;
943 VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
944 BootPatchLevel, BOOT_PATCHLEVEL, integer;
945 AssociatedData, ASSOCIATED_DATA, blob;
946 Nonce, NONCE, blob;
947 MacLength, MAC_LENGTH, integer;
948 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
949 ConfirmationToken, CONFIRMATION_TOKEN, blob;
950 }
951}
952
953#[cfg(test)]
954mod basic_tests {
955 use crate::key_parameter::*;
956
957 // Test basic functionality of KeyParameter.
958 #[test]
959 fn test_key_parameter() {
960 let key_parameter = KeyParameter::new(
961 KeyParameterValue::Algorithm(Algorithm::RSA),
962 SecurityLevel::STRONGBOX,
963 );
964
965 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
966
967 assert_eq!(
968 *key_parameter.key_parameter_value(),
969 KeyParameterValue::Algorithm(Algorithm::RSA)
970 );
971
972 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
973 }
974}
975
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000976/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
977/// data types and then tests 'to_sql' method for KeyParameters of those
978/// different data types. The five different data types for KeyParameter values are:
979/// i) enums of u32
980/// ii) u32
981/// iii) u64
982/// iv) Vec<u8>
983/// v) bool
984#[cfg(test)]
985mod storage_tests {
986 use crate::error::*;
987 use crate::key_parameter::*;
988 use anyhow::Result;
989 use rusqlite::types::ToSql;
990 use rusqlite::{params, Connection, NO_PARAMS};
991
992 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
993 /// from a database table row.
994 #[test]
995 fn test_new_from_sql_enum_i32() -> Result<()> {
996 let db = init_db()?;
997 insert_into_keyparameter(
998 &db,
999 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001000 Tag::ALGORITHM.0,
1001 &Algorithm::RSA.0,
1002 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001003 )?;
1004 let key_param = query_from_keyparameter(&db)?;
1005 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1006 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1007 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1008 Ok(())
1009 }
1010
1011 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1012 /// from a database table row.
1013 #[test]
1014 fn test_new_from_sql_i32() -> Result<()> {
1015 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001016 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001017 let key_param = query_from_keyparameter(&db)?;
1018 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1019 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1020 Ok(())
1021 }
1022
1023 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1024 /// from a database table row.
1025 #[test]
1026 fn test_new_from_sql_i64() -> Result<()> {
1027 let db = init_db()?;
1028 // max value for i64, just to test corner cases
1029 insert_into_keyparameter(
1030 &db,
1031 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001032 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001033 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001034 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001035 )?;
1036 let key_param = query_from_keyparameter(&db)?;
1037 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1038 assert_eq!(
1039 *key_param.key_parameter_value(),
1040 KeyParameterValue::RSAPublicExponent(i64::MAX)
1041 );
1042 Ok(())
1043 }
1044
1045 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1046 /// from a database table row.
1047 #[test]
1048 fn test_new_from_sql_bool() -> Result<()> {
1049 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001050 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001051 let key_param = query_from_keyparameter(&db)?;
1052 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1053 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1054 Ok(())
1055 }
1056
1057 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1058 /// from a database table row.
1059 #[test]
1060 fn test_new_from_sql_vec_u8() -> Result<()> {
1061 let db = init_db()?;
1062 let app_id = String::from("MyAppID");
1063 let app_id_bytes = app_id.into_bytes();
1064 insert_into_keyparameter(
1065 &db,
1066 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001067 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001068 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001069 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001070 )?;
1071 let key_param = query_from_keyparameter(&db)?;
1072 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1073 assert_eq!(
1074 *key_param.key_parameter_value(),
1075 KeyParameterValue::ApplicationID(app_id_bytes)
1076 );
1077 Ok(())
1078 }
1079
1080 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1081 /// in the database
1082 #[test]
1083 fn test_to_sql_enum_i32() -> Result<()> {
1084 let db = init_db()?;
1085 let kp = KeyParameter::new(
1086 KeyParameterValue::Algorithm(Algorithm::RSA),
1087 SecurityLevel::STRONGBOX,
1088 );
1089 store_keyparameter(&db, 1, &kp)?;
1090 let key_param = query_from_keyparameter(&db)?;
1091 assert_eq!(kp.get_tag(), key_param.get_tag());
1092 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1093 assert_eq!(kp.security_level(), key_param.security_level());
1094 Ok(())
1095 }
1096
1097 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1098 #[test]
1099 fn test_to_sql_i32() -> Result<()> {
1100 let db = init_db()?;
1101 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1102 store_keyparameter(&db, 1, &kp)?;
1103 let key_param = query_from_keyparameter(&db)?;
1104 assert_eq!(kp.get_tag(), key_param.get_tag());
1105 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1106 assert_eq!(kp.security_level(), key_param.security_level());
1107 Ok(())
1108 }
1109
1110 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1111 #[test]
1112 fn test_to_sql_i64() -> Result<()> {
1113 let db = init_db()?;
1114 // max value for i64, just to test corner cases
1115 let kp = KeyParameter::new(
1116 KeyParameterValue::RSAPublicExponent(i64::MAX),
1117 SecurityLevel::STRONGBOX,
1118 );
1119 store_keyparameter(&db, 1, &kp)?;
1120 let key_param = query_from_keyparameter(&db)?;
1121 assert_eq!(kp.get_tag(), key_param.get_tag());
1122 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1123 assert_eq!(kp.security_level(), key_param.security_level());
1124 Ok(())
1125 }
1126
1127 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1128 #[test]
1129 fn test_to_sql_vec_u8() -> Result<()> {
1130 let db = init_db()?;
1131 let kp = KeyParameter::new(
1132 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1133 SecurityLevel::STRONGBOX,
1134 );
1135 store_keyparameter(&db, 1, &kp)?;
1136 let key_param = query_from_keyparameter(&db)?;
1137 assert_eq!(kp.get_tag(), key_param.get_tag());
1138 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1139 assert_eq!(kp.security_level(), key_param.security_level());
1140 Ok(())
1141 }
1142
1143 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1144 #[test]
1145 fn test_to_sql_bool() -> Result<()> {
1146 let db = init_db()?;
1147 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1148 store_keyparameter(&db, 1, &kp)?;
1149 let key_param = query_from_keyparameter(&db)?;
1150 assert_eq!(kp.get_tag(), key_param.get_tag());
1151 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1152 assert_eq!(kp.security_level(), key_param.security_level());
1153 Ok(())
1154 }
1155
1156 #[test]
1157 /// Test Tag::Invalid
1158 fn test_invalid_tag() -> Result<()> {
1159 let db = init_db()?;
1160 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1161 let key_param = query_from_keyparameter(&db)?;
1162 assert_eq!(Tag::INVALID, key_param.get_tag());
1163 Ok(())
1164 }
1165
1166 #[test]
1167 fn test_non_existing_enum_variant() -> Result<()> {
1168 let db = init_db()?;
1169 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1170 tests::check_result_contains_error_string(
1171 query_from_keyparameter(&db),
1172 "Failed to decode Tag enum from value.",
1173 );
1174 Ok(())
1175 }
1176
1177 #[test]
1178 fn test_invalid_conversion_from_sql() -> Result<()> {
1179 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001180 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001181 tests::check_result_contains_error_string(
1182 query_from_keyparameter(&db),
1183 "Failed to read sql data for tag: ALGORITHM.",
1184 );
1185 Ok(())
1186 }
1187
1188 /// Helper method to init database table for key parameter
1189 fn init_db() -> Result<Connection> {
1190 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1191 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1192 .context("Failed to attach databases.")?;
1193 db.execute(
1194 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1195 keyentryid INTEGER,
1196 tag INTEGER,
1197 data ANY,
1198 security_level INTEGER);",
1199 NO_PARAMS,
1200 )
1201 .context("Failed to initialize \"keyparameter\" table.")?;
1202 Ok(db)
1203 }
1204
1205 /// Helper method to insert an entry into key parameter table, with individual parameters
1206 fn insert_into_keyparameter<T: ToSql>(
1207 db: &Connection,
1208 key_id: i64,
1209 tag: i32,
1210 value: &T,
1211 security_level: i32,
1212 ) -> Result<()> {
1213 db.execute(
1214 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001215 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001216 params![key_id, tag, *value, security_level],
1217 )?;
1218 Ok(())
1219 }
1220
1221 /// Helper method to store a key parameter instance.
1222 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1223 db.execute(
1224 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001225 VALUES(?, ?, ?, ?);",
1226 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001227 )?;
1228 Ok(())
1229 }
1230
1231 /// Helper method to query a row from keyparameter table
1232 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001233 let mut stmt =
1234 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001235 let mut rows = stmt.query(NO_PARAMS)?;
1236 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001237 Ok(KeyParameter::new_from_sql(
1238 Tag(row.get(0)?),
1239 &SqlField(1, row),
1240 SecurityLevel(row.get(2)?),
1241 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001242 }
1243}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001244
1245/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001246/// KeyParameter, for the five different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001247/// key parameter.
1248/// i) bool
1249/// ii) integer
1250/// iii) longInteger
1251/// iv) dateTime
1252/// v) blob
1253#[cfg(test)]
1254mod wire_tests {
1255 use crate::key_parameter::*;
1256 /// unit tests for to conversions
1257 #[test]
1258 fn test_convert_to_wire_invalid() {
1259 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1260 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1261 assert_eq!(Tag::INVALID, actual.tag);
1262 }
1263 #[test]
1264 fn test_convert_to_wire_bool() {
1265 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1266 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1267 assert_eq!(Tag::CALLER_NONCE, actual.tag);
1268 assert_eq!(true, actual.boolValue);
1269 }
1270 #[test]
1271 fn test_convert_to_wire_integer() {
1272 let kp = KeyParameter::new(
1273 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1274 SecurityLevel::STRONGBOX,
1275 );
1276 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1277 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001278 assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001279 }
1280 #[test]
1281 fn test_convert_to_wire_long_integer() {
1282 let kp =
1283 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1284 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1285 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
1286 assert_eq!(i64::MAX, actual.longInteger);
1287 }
1288 #[test]
1289 fn test_convert_to_wire_date_time() {
1290 let kp = KeyParameter::new(
1291 KeyParameterValue::ActiveDateTime(i64::MAX),
1292 SecurityLevel::STRONGBOX,
1293 );
1294 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1295 assert_eq!(Tag::ACTIVE_DATETIME, actual.tag);
1296 assert_eq!(i64::MAX, actual.dateTime);
1297 }
1298 #[test]
1299 fn test_convert_to_wire_blob() {
1300 let kp = KeyParameter::new(
1301 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1302 SecurityLevel::STRONGBOX,
1303 );
1304 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1305 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
1306 assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
1307 }
1308
1309 /// unit tests for from conversion
1310 #[test]
1311 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001312 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001313 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1314 assert_eq!(KeyParameterValue::Invalid, actual);
1315 }
1316 #[test]
1317 fn test_convert_from_wire_bool() {
1318 let aidl_kp =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001319 KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001320 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1321 assert_eq!(KeyParameterValue::CallerNonce, actual);
1322 }
1323 #[test]
1324 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001325 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001326 tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001327 integer: KeyPurpose::ENCRYPT.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001328 ..Default::default()
1329 };
1330 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1331 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1332 }
1333 #[test]
1334 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001335 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001336 tag: Tag::USER_SECURE_ID,
1337 longInteger: i64::MAX,
1338 ..Default::default()
1339 };
1340 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1341 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1342 }
1343 #[test]
1344 fn test_convert_from_wire_date_time() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001345 let aidl_kp =
1346 KmKeyParameter { tag: Tag::ACTIVE_DATETIME, dateTime: i64::MAX, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001347 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1348 assert_eq!(KeyParameterValue::ActiveDateTime(i64::MAX), actual);
1349 }
1350 #[test]
1351 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001352 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001353 tag: Tag::CONFIRMATION_TOKEN,
1354 blob: String::from("ConfirmationToken").into_bytes(),
1355 ..Default::default()
1356 };
1357 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1358 assert_eq!(
1359 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1360 actual
1361 );
1362 }
1363}