blob: 7f2dc56d9045f601d07e164f661c9dd8aca182a3 [file] [log] [blame]
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! KeyParameter is used to express different characteristics of a key requested by the user
16//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
17//! and the methods to work with KeyParameter.
18
Hasini Gunasingheaf993662020-07-24 18:40:20 +000019use crate::error::Error as KeystoreError;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070020use crate::error::ResponseCode;
21
Shawn Willden708744a2020-12-11 13:05:27 +000022pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070023 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
24 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
25 KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
Janis Danisevskis04b02832020-10-26 09:21:40 -070026 SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000027};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070028use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
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 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700236
237 /// An authorization is a KeyParameter with an associated security level that is used
238 /// to convey the key characteristics to keystore clients. This function consumes
239 /// an internal KeyParameter representation to produce the Authorization wire type.
240 pub fn into_authorization(self) -> Authorization {
241 Authorization {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700242 securityLevel: self.security_level,
243 keyParameter: self.key_parameter_value.convert_to_wire(),
Janis Danisevskis04b02832020-10-26 09:21:40 -0700244 }
245 }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000246}
247
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000248/// This struct is defined to postpone converting rusqlite column value to the
249/// appropriate key parameter value until we know the corresponding tag value.
250/// Wraps the column index and a rusqlite row.
251pub struct SqlField<'a>(usize, &'a Row<'a>);
252
253impl<'a> SqlField<'a> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700254 /// Creates a new SqlField with the given index and row.
255 pub fn new(index: usize, row: &'a Row<'a>) -> Self {
256 Self(index, row)
257 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000258 /// Returns the column value from the row, when we know the expected type.
259 pub fn get<T: FromSql>(&self) -> SqlResult<T> {
260 self.1.get(self.0)
261 }
262}
263
264impl ToSql for KeyParameterValue {
265 /// Converts KeyParameterValue to be stored in rusqlite database.
266 /// Note that following variants of KeyParameterValue should not be stored:
267 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
268 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
269 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
270 /// conversion for all the variants, to keep error handling simple.
271 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
272 match self {
273 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700274 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
275 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000276 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700277 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
278 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
279 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000280 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
281 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700282 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000283 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
284 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
285 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
286 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
287 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
288 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
289 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
290 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
291 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
292 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
293 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
294 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700295 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000296 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
297 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
298 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
299 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
300 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
301 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
302 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
303 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700304 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000305 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
306 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
307 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
308 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
309 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
310 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
311 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
312 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
313 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
314 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
315 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
316 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
317 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
318 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
319 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
320 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
321 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
322 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
323 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
324 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
325 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
326 }
327 }
328}
329
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000330impl KeyParameter {
331 /// Construct a KeyParameter from the data from a rusqlite row.
332 /// Note that following variants of KeyParameterValue should not be stored:
333 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
334 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
335 /// This filtering is enforced at a higher level and here we support conversion for all the
336 /// variants.
337 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700338 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000339 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700340 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000341 ) -> Result<Self> {
342 let key_param_value = match tag_val {
343 Tag::INVALID => KeyParameterValue::Invalid,
344 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700345 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000346 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700347 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700348 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700349 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000350 }
351 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700352 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000353 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700354 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700355 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700356 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000357 }
358 Tag::KEY_SIZE => {
359 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700360 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000361 KeyParameterValue::KeySize(key_size)
362 }
363 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700364 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000365 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700366 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700367 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700368 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000369 }
370 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700371 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000372 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700373 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700374 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700375 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000376 }
377 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700378 let padding: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000379 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700380 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700381 .context("Failed to read sql data for tag: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700382 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000383 }
384 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
385 Tag::MIN_MAC_LENGTH => {
386 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700387 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000388 KeyParameterValue::MinMacLength(min_mac_length)
389 }
390 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700391 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000392 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700393 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700394 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700395 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000396 }
397 Tag::RSA_PUBLIC_EXPONENT => {
398 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700399 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000400
401 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
402 }
403 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
404 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
405 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
406 Tag::ACTIVE_DATETIME => {
407 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700408 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000409 KeyParameterValue::ActiveDateTime(active_datetime)
410 }
411 Tag::ORIGINATION_EXPIRE_DATETIME => {
412 let origination_expire_datetime: i64 = data
413 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700414 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000415 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
416 }
417 Tag::USAGE_EXPIRE_DATETIME => {
418 let usage_expire_datetime: i64 = data
419 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700420 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000421 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
422 }
423 Tag::MIN_SECONDS_BETWEEN_OPS => {
424 let min_secs_between_ops: i32 = data
425 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700426 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000427 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
428 }
429 Tag::MAX_USES_PER_BOOT => {
430 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700431 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000432 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
433 }
434 Tag::USER_ID => {
435 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700436 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000437 KeyParameterValue::UserID(user_id)
438 }
439 Tag::USER_SECURE_ID => {
440 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700441 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000442 KeyParameterValue::UserSecureID(user_secure_id)
443 }
444 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
445 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700446 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000447 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700448 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700449 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700450 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
451 user_auth_type,
452 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000453 }
454 Tag::AUTH_TIMEOUT => {
455 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700456 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000457 KeyParameterValue::AuthTimeout(auth_timeout)
458 }
459 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
460 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
461 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
462 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
463 Tag::APPLICATION_ID => {
464 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700465 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000466 KeyParameterValue::ApplicationID(app_id)
467 }
468 Tag::APPLICATION_DATA => {
469 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700470 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000471 KeyParameterValue::ApplicationData(app_data)
472 }
473 Tag::CREATION_DATETIME => {
474 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700475 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000476 KeyParameterValue::CreationDateTime(creation_datetime)
477 }
478 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700479 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000480 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700481 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700482 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700483 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000484 }
485 Tag::ROOT_OF_TRUST => {
486 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700487 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000488 KeyParameterValue::RootOfTrust(root_of_trust)
489 }
490 Tag::OS_VERSION => {
491 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700492 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000493 KeyParameterValue::OSVersion(os_version)
494 }
495 Tag::OS_PATCHLEVEL => {
496 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700497 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000498 KeyParameterValue::OSPatchLevel(os_patch_level)
499 }
500 Tag::UNIQUE_ID => {
501 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700502 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000503 KeyParameterValue::UniqueID(unique_id)
504 }
505 Tag::ATTESTATION_CHALLENGE => {
506 let attestation_challenge: Vec<u8> = data
507 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700508 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000509 KeyParameterValue::AttestationChallenge(attestation_challenge)
510 }
511 Tag::ATTESTATION_APPLICATION_ID => {
512 let attestation_app_id: Vec<u8> = data
513 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700514 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000515 KeyParameterValue::AttestationApplicationID(attestation_app_id)
516 }
517 Tag::ATTESTATION_ID_BRAND => {
518 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700519 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000520 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
521 }
522 Tag::ATTESTATION_ID_DEVICE => {
523 let attestation_id_device: Vec<u8> = data
524 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700525 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000526 KeyParameterValue::AttestationIdDevice(attestation_id_device)
527 }
528 Tag::ATTESTATION_ID_PRODUCT => {
529 let attestation_id_product: Vec<u8> = data
530 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700531 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000532 KeyParameterValue::AttestationIdProduct(attestation_id_product)
533 }
534 Tag::ATTESTATION_ID_SERIAL => {
535 let attestation_id_serial: Vec<u8> = data
536 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700537 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000538 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
539 }
540 Tag::ATTESTATION_ID_IMEI => {
541 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700542 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000543 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
544 }
545 Tag::ATTESTATION_ID_MEID => {
546 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700547 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000548 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
549 }
550 Tag::ATTESTATION_ID_MANUFACTURER => {
551 let attestation_id_manufacturer: Vec<u8> = data
552 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700553 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000554 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
555 }
556 Tag::ATTESTATION_ID_MODEL => {
557 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700558 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000559 KeyParameterValue::AttestationIdModel(attestation_id_model)
560 }
561 Tag::VENDOR_PATCHLEVEL => {
562 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700563 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000564 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
565 }
566 Tag::BOOT_PATCHLEVEL => {
567 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700568 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000569 KeyParameterValue::BootPatchLevel(boot_patch_level)
570 }
571 Tag::ASSOCIATED_DATA => {
572 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700573 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000574 KeyParameterValue::AssociatedData(associated_data)
575 }
576 Tag::NONCE => {
577 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700578 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000579 KeyParameterValue::Nonce(nonce)
580 }
581 Tag::MAC_LENGTH => {
582 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700583 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000584 KeyParameterValue::MacLength(mac_length)
585 }
586 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
587 Tag::CONFIRMATION_TOKEN => {
588 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700589 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000590 KeyParameterValue::ConfirmationToken(confirmation_token)
591 }
592 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700593 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700594 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000595 }
596 };
597 Ok(KeyParameter::new(key_param_value, security_level_val))
598 }
599}
600
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000601/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700602/// This macro takes between three and four different pieces of information about each
603/// of the KeyParameterValue variants:
604/// 1. The KeyParameterValue variant name,
605/// 2. the tag name corresponding to the variant,
606/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
607/// stored when converted, and
608/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000609/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
610/// the two conversion methods: convert_to_wire() and convert_from_wire().
611/// ## Example
612/// ```
613/// implement_key_parameter_conversion_to_from_wire! {
614/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700615/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000616/// CallerNonce, CALLER_NONCE, boolValue;
617/// UserSecureID, USER_SECURE_ID, longInteger;
618/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000619/// }
620/// ```
621/// expands to:
622/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700623/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000624/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700625/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000626/// tag: Tag::INVALID,
627/// ..Default::default()
628/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700629/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000630/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700631/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000632/// ..Default::default()
633/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700634/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000635/// tag: Tag::CALLER_NONCE,
636/// boolValue: true,
637/// ..Default::default()
638/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700639/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000640/// tag: Tag::USER_SECURE_ID,
641/// longInteger: v,
642/// ..Default::default()
643/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700644/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000645/// tag: Tag::APPLICATION_ID,
646/// blob: v,
647/// ..Default::default()
648/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000649/// }
650/// }
651/// ```
652/// and
653/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700654/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000655/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700656/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000657/// tag: Tag::INVALID,
658/// ..
659/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700660/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000661/// tag: Tag::PURPOSE,
662/// integer: v,
663/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700664/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
665/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000666/// tag: Tag::CALLER_NONCE,
667/// boolValue: true,
668/// ..
669/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700670/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000671/// tag: Tag::USER_SECURE_ID,
672/// longInteger: v,
673/// ..
674/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700675/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000676/// tag: Tag::APPLICATION_ID,
677/// blob: v,
678/// ..
679/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000680/// _ => KeyParameterValue::Invalid,
681/// }
682/// }
683///
684macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700685 // There are three groups of rules in this macro.
686 // 1. The first group contains the rule which acts as the public interface. It takes the input
687 // given to this macro and prepares it to be given as input to the two groups of rules
688 // mentioned below.
689 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
690 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
691 //
692 // Input to this macro is first handled by the first macro rule (belonging to the first
693 // group above), which pre-processes the input such that rules in the other two groups
694 // generate the code for the two methods, when called recursively.
695 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
696 // four macro rules in the second two groups. These four rules intend to do the following
697 // tasks respectively:
698 // i) generates match arms related to Invalid KeyParameterValue variant.
699 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
700 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
701 // iv) generates the method definition including the match arms generated from the above
702 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000703
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700704 // This rule is applied on the input given to the macro invocations from outside the macro.
705 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
706 // pre-processes input to target the rules that generate convert_to_wire() method.
707 implement_key_parameter_conversion_to_from_wire! {@to
708 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
709 }
710 // pre-processes input to target the rules that generate convert_from_wire() method.
711 implement_key_parameter_conversion_to_from_wire! {@from
712 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
713 }
714 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000715
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700716 // Following four rules (belonging to the aforementioned second group) generate
717 // convert_to_wire() conversion method.
718 // -----------------------------------------------------------------------
719 // This rule handles Invalid variant.
720 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
721 // KeyParameterValue::Invalid => KmKeyParameter {
722 // tag: Tag::INVALID,
723 // ..Default::default()
724 // },
725 (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
726 implement_key_parameter_conversion_to_from_wire! {@to
727 [$($out)*
728 KeyParameterValue::Invalid => KmKeyParameter {
729 tag: Tag::INVALID,
730 ..Default::default()
731 },
732 ], $($in)*
733 }
734 };
735 // This rule handles all variants that correspond to bool values.
736 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
737 // a match arm like:
738 // KeyParameterValue::CallerNonce => KmKeyParameter {
739 // tag: Tag::CALLER_NONCE,
740 // boolValue: true,
741 // ..Default::default()
742 // },
743 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
744 implement_key_parameter_conversion_to_from_wire! {@to
745 [$($out)*
746 KeyParameterValue::$variant => KmKeyParameter {
747 tag: Tag::$tag_val,
748 boolValue: true,
749 ..Default::default()
750 },
751 ], $($in)*
752 }
753 };
754 // This rule handles all enum variants.
755 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
756 // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
757 // tag: Tag::PURPOSE,
758 // integer: v.0,
759 // ..Default::default(),
760 // },
761 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
762 implement_key_parameter_conversion_to_from_wire! {@to
763 [$($out)*
764 KeyParameterValue::$variant(v) => KmKeyParameter {
765 tag: Tag::$tag_val,
766 $field: v.0,
767 ..Default::default()
768 },
769 ], $($in)*
770 }
771 };
772 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700773 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700774 // KmKeyParameter).
775 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
776 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
777 // tag: Tag::CONFIRMATION_TOKEN,
778 // blob: v,
779 // ..Default::default(),
780 // },
781 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
782 implement_key_parameter_conversion_to_from_wire! {@to
783 [$($out)*
784 KeyParameterValue::$variant(v) => KmKeyParameter {
785 tag: Tag::$tag_val,
786 $field: v,
787 ..Default::default()
788 },
789 ], $($in)*
790 }
791 };
792 // After all the match arms are generated by the above three rules, this rule combines them
793 // into the convert_to_wire() method.
794 (@to [$($out:tt)*], ) => {
795 /// Conversion of key parameter to wire type
796 pub fn convert_to_wire(self) -> KmKeyParameter {
797 match self {
798 $($out)*
799 }
800 }
801 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000802
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700803 // Following four rules (belonging to the aforementioned third group) generate
804 // convert_from_wire() conversion method.
805 // ------------------------------------------------------------------------
806 // This rule handles Invalid variant.
807 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
808 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
809 (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
810 implement_key_parameter_conversion_to_from_wire! {@from
811 [$($out)*
812 KmKeyParameter {
813 tag: Tag::INVALID,
814 ..
815 } => KeyParameterValue::Invalid,
816 ], $($in)*
817 }
818 };
819 // This rule handles all variants that correspond to bool values.
820 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
821 // KmKeyParameter {
822 // tag: Tag::CALLER_NONCE,
823 // boolValue: true,
824 // ..
825 // } => KeyParameterValue::CallerNonce,
826 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
827 implement_key_parameter_conversion_to_from_wire! {@from
828 [$($out)*
829 KmKeyParameter {
830 tag: Tag::$tag_val,
831 boolValue: true,
832 ..
833 } => KeyParameterValue::$variant,
834 ], $($in)*
835 }
836 };
837 // This rule handles all enum variants.
838 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
839 // like:
840 // KmKeyParameter {
841 // tag: Tag::PURPOSE,
842 // integer: v,
843 // ..,
844 // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
845 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
846 implement_key_parameter_conversion_to_from_wire! {@from
847 [$($out)*
848 KmKeyParameter {
849 tag: Tag::$tag_val,
850 $field: v,
851 ..
852 } => KeyParameterValue::$variant($enum_type(v)),
853 ], $($in)*
854 }
855 };
856 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700857 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700858 // KmKeyParameter).
859 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
860 // like:
861 // KmKeyParameter {
862 // tag: Tag::CONFIRMATION_TOKEN,
863 // blob: v,
864 // ..,
865 // } => KeyParameterValue::ConfirmationToken(v),
866 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
867 implement_key_parameter_conversion_to_from_wire! {@from
868 [$($out)*
869 KmKeyParameter {
870 tag: Tag::$tag_val,
871 $field: v,
872 ..
873 } => KeyParameterValue::$variant(v),
874 ], $($in)*
875 }
876 };
877 // After all the match arms are generated by the above three rules, this rule combines them
878 // into the convert_from_wire() method.
879 (@from [$($out:tt)*], ) => {
880 /// Conversion of key parameter from wire type
881 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
882 match aidl_kp {
883 $($out)*
884 _ => KeyParameterValue::Invalid,
885 }
886 }
887 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000888}
889
890impl KeyParameterValue {
891 // Invoke the macro that generates the code for key parameter conversion to/from wire type
892 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
893 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700894 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000895 implement_key_parameter_conversion_to_from_wire! {
896 Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700897 KeyPurpose, PURPOSE, integer, KeyPurpose;
898 Algorithm, ALGORITHM, integer, Algorithm;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000899 KeySize, KEY_SIZE, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700900 BlockMode, BLOCK_MODE, integer, BlockMode;
901 Digest, DIGEST, integer, Digest;
902 PaddingMode, PADDING, integer, PaddingMode;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000903 CallerNonce, CALLER_NONCE, boolValue;
904 MinMacLength, MIN_MAC_LENGTH, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700905 EcCurve, EC_CURVE, integer, EcCurve;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000906 RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
907 IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
908 BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
909 RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700910 ActiveDateTime, ACTIVE_DATETIME, longInteger;
911 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
912 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000913 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
914 MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
915 UserID, USER_ID, integer;
916 UserSecureID, USER_SECURE_ID, longInteger;
917 NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700918 HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000919 AuthTimeout, AUTH_TIMEOUT, integer;
920 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
921 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
922 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
923 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
924 ApplicationID, APPLICATION_ID, blob;
925 ApplicationData, APPLICATION_DATA, blob;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700926 CreationDateTime, CREATION_DATETIME, longInteger;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700927 KeyOrigin, ORIGIN, integer, KeyOrigin;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000928 RootOfTrust, ROOT_OF_TRUST, blob;
929 OSVersion, OS_VERSION, integer;
930 OSPatchLevel, OS_PATCHLEVEL, integer;
931 UniqueID, UNIQUE_ID, blob;
932 AttestationChallenge, ATTESTATION_CHALLENGE, blob;
933 AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
934 AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
935 AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
936 AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
937 AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
938 AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
939 AttestationIdMEID, ATTESTATION_ID_MEID, blob;
940 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
941 AttestationIdModel, ATTESTATION_ID_MODEL, blob;
942 VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
943 BootPatchLevel, BOOT_PATCHLEVEL, integer;
944 AssociatedData, ASSOCIATED_DATA, blob;
945 Nonce, NONCE, blob;
946 MacLength, MAC_LENGTH, integer;
947 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
948 ConfirmationToken, CONFIRMATION_TOKEN, blob;
949 }
950}
951
952#[cfg(test)]
953mod basic_tests {
954 use crate::key_parameter::*;
955
956 // Test basic functionality of KeyParameter.
957 #[test]
958 fn test_key_parameter() {
959 let key_parameter = KeyParameter::new(
960 KeyParameterValue::Algorithm(Algorithm::RSA),
961 SecurityLevel::STRONGBOX,
962 );
963
964 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
965
966 assert_eq!(
967 *key_parameter.key_parameter_value(),
968 KeyParameterValue::Algorithm(Algorithm::RSA)
969 );
970
971 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
972 }
973}
974
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000975/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
976/// data types and then tests 'to_sql' method for KeyParameters of those
977/// different data types. The five different data types for KeyParameter values are:
978/// i) enums of u32
979/// ii) u32
980/// iii) u64
981/// iv) Vec<u8>
982/// v) bool
983#[cfg(test)]
984mod storage_tests {
985 use crate::error::*;
986 use crate::key_parameter::*;
987 use anyhow::Result;
988 use rusqlite::types::ToSql;
989 use rusqlite::{params, Connection, NO_PARAMS};
990
991 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
992 /// from a database table row.
993 #[test]
994 fn test_new_from_sql_enum_i32() -> Result<()> {
995 let db = init_db()?;
996 insert_into_keyparameter(
997 &db,
998 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700999 Tag::ALGORITHM.0,
1000 &Algorithm::RSA.0,
1001 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001002 )?;
1003 let key_param = query_from_keyparameter(&db)?;
1004 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1005 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1006 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1007 Ok(())
1008 }
1009
1010 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1011 /// from a database table row.
1012 #[test]
1013 fn test_new_from_sql_i32() -> Result<()> {
1014 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001015 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001016 let key_param = query_from_keyparameter(&db)?;
1017 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1018 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1019 Ok(())
1020 }
1021
1022 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1023 /// from a database table row.
1024 #[test]
1025 fn test_new_from_sql_i64() -> Result<()> {
1026 let db = init_db()?;
1027 // max value for i64, just to test corner cases
1028 insert_into_keyparameter(
1029 &db,
1030 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001031 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001032 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001033 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001034 )?;
1035 let key_param = query_from_keyparameter(&db)?;
1036 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1037 assert_eq!(
1038 *key_param.key_parameter_value(),
1039 KeyParameterValue::RSAPublicExponent(i64::MAX)
1040 );
1041 Ok(())
1042 }
1043
1044 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1045 /// from a database table row.
1046 #[test]
1047 fn test_new_from_sql_bool() -> Result<()> {
1048 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001049 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001050 let key_param = query_from_keyparameter(&db)?;
1051 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1052 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1053 Ok(())
1054 }
1055
1056 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1057 /// from a database table row.
1058 #[test]
1059 fn test_new_from_sql_vec_u8() -> Result<()> {
1060 let db = init_db()?;
1061 let app_id = String::from("MyAppID");
1062 let app_id_bytes = app_id.into_bytes();
1063 insert_into_keyparameter(
1064 &db,
1065 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001066 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001067 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001068 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001069 )?;
1070 let key_param = query_from_keyparameter(&db)?;
1071 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1072 assert_eq!(
1073 *key_param.key_parameter_value(),
1074 KeyParameterValue::ApplicationID(app_id_bytes)
1075 );
1076 Ok(())
1077 }
1078
1079 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1080 /// in the database
1081 #[test]
1082 fn test_to_sql_enum_i32() -> Result<()> {
1083 let db = init_db()?;
1084 let kp = KeyParameter::new(
1085 KeyParameterValue::Algorithm(Algorithm::RSA),
1086 SecurityLevel::STRONGBOX,
1087 );
1088 store_keyparameter(&db, 1, &kp)?;
1089 let key_param = query_from_keyparameter(&db)?;
1090 assert_eq!(kp.get_tag(), key_param.get_tag());
1091 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1092 assert_eq!(kp.security_level(), key_param.security_level());
1093 Ok(())
1094 }
1095
1096 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1097 #[test]
1098 fn test_to_sql_i32() -> Result<()> {
1099 let db = init_db()?;
1100 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1101 store_keyparameter(&db, 1, &kp)?;
1102 let key_param = query_from_keyparameter(&db)?;
1103 assert_eq!(kp.get_tag(), key_param.get_tag());
1104 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1105 assert_eq!(kp.security_level(), key_param.security_level());
1106 Ok(())
1107 }
1108
1109 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1110 #[test]
1111 fn test_to_sql_i64() -> Result<()> {
1112 let db = init_db()?;
1113 // max value for i64, just to test corner cases
1114 let kp = KeyParameter::new(
1115 KeyParameterValue::RSAPublicExponent(i64::MAX),
1116 SecurityLevel::STRONGBOX,
1117 );
1118 store_keyparameter(&db, 1, &kp)?;
1119 let key_param = query_from_keyparameter(&db)?;
1120 assert_eq!(kp.get_tag(), key_param.get_tag());
1121 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1122 assert_eq!(kp.security_level(), key_param.security_level());
1123 Ok(())
1124 }
1125
1126 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1127 #[test]
1128 fn test_to_sql_vec_u8() -> Result<()> {
1129 let db = init_db()?;
1130 let kp = KeyParameter::new(
1131 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1132 SecurityLevel::STRONGBOX,
1133 );
1134 store_keyparameter(&db, 1, &kp)?;
1135 let key_param = query_from_keyparameter(&db)?;
1136 assert_eq!(kp.get_tag(), key_param.get_tag());
1137 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1138 assert_eq!(kp.security_level(), key_param.security_level());
1139 Ok(())
1140 }
1141
1142 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1143 #[test]
1144 fn test_to_sql_bool() -> Result<()> {
1145 let db = init_db()?;
1146 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1147 store_keyparameter(&db, 1, &kp)?;
1148 let key_param = query_from_keyparameter(&db)?;
1149 assert_eq!(kp.get_tag(), key_param.get_tag());
1150 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1151 assert_eq!(kp.security_level(), key_param.security_level());
1152 Ok(())
1153 }
1154
1155 #[test]
1156 /// Test Tag::Invalid
1157 fn test_invalid_tag() -> Result<()> {
1158 let db = init_db()?;
1159 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1160 let key_param = query_from_keyparameter(&db)?;
1161 assert_eq!(Tag::INVALID, key_param.get_tag());
1162 Ok(())
1163 }
1164
1165 #[test]
1166 fn test_non_existing_enum_variant() -> Result<()> {
1167 let db = init_db()?;
1168 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1169 tests::check_result_contains_error_string(
1170 query_from_keyparameter(&db),
1171 "Failed to decode Tag enum from value.",
1172 );
1173 Ok(())
1174 }
1175
1176 #[test]
1177 fn test_invalid_conversion_from_sql() -> Result<()> {
1178 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001179 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001180 tests::check_result_contains_error_string(
1181 query_from_keyparameter(&db),
1182 "Failed to read sql data for tag: ALGORITHM.",
1183 );
1184 Ok(())
1185 }
1186
1187 /// Helper method to init database table for key parameter
1188 fn init_db() -> Result<Connection> {
1189 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1190 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1191 .context("Failed to attach databases.")?;
1192 db.execute(
1193 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1194 keyentryid INTEGER,
1195 tag INTEGER,
1196 data ANY,
1197 security_level INTEGER);",
1198 NO_PARAMS,
1199 )
1200 .context("Failed to initialize \"keyparameter\" table.")?;
1201 Ok(db)
1202 }
1203
1204 /// Helper method to insert an entry into key parameter table, with individual parameters
1205 fn insert_into_keyparameter<T: ToSql>(
1206 db: &Connection,
1207 key_id: i64,
1208 tag: i32,
1209 value: &T,
1210 security_level: i32,
1211 ) -> Result<()> {
1212 db.execute(
1213 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001214 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001215 params![key_id, tag, *value, security_level],
1216 )?;
1217 Ok(())
1218 }
1219
1220 /// Helper method to store a key parameter instance.
1221 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1222 db.execute(
1223 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001224 VALUES(?, ?, ?, ?);",
1225 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001226 )?;
1227 Ok(())
1228 }
1229
1230 /// Helper method to query a row from keyparameter table
1231 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001232 let mut stmt =
1233 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001234 let mut rows = stmt.query(NO_PARAMS)?;
1235 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001236 Ok(KeyParameter::new_from_sql(
1237 Tag(row.get(0)?),
1238 &SqlField(1, row),
1239 SecurityLevel(row.get(2)?),
1240 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001241 }
1242}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001243
1244/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001245/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001246/// key parameter.
1247/// i) bool
1248/// ii) integer
1249/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001250/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001251#[cfg(test)]
1252mod wire_tests {
1253 use crate::key_parameter::*;
1254 /// unit tests for to conversions
1255 #[test]
1256 fn test_convert_to_wire_invalid() {
1257 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1258 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1259 assert_eq!(Tag::INVALID, actual.tag);
1260 }
1261 #[test]
1262 fn test_convert_to_wire_bool() {
1263 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1264 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1265 assert_eq!(Tag::CALLER_NONCE, actual.tag);
1266 assert_eq!(true, actual.boolValue);
1267 }
1268 #[test]
1269 fn test_convert_to_wire_integer() {
1270 let kp = KeyParameter::new(
1271 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1272 SecurityLevel::STRONGBOX,
1273 );
1274 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1275 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001276 assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001277 }
1278 #[test]
1279 fn test_convert_to_wire_long_integer() {
1280 let kp =
1281 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1282 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1283 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
1284 assert_eq!(i64::MAX, actual.longInteger);
1285 }
1286 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001287 fn test_convert_to_wire_blob() {
1288 let kp = KeyParameter::new(
1289 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1290 SecurityLevel::STRONGBOX,
1291 );
1292 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1293 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
1294 assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
1295 }
1296
1297 /// unit tests for from conversion
1298 #[test]
1299 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001300 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001301 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1302 assert_eq!(KeyParameterValue::Invalid, actual);
1303 }
1304 #[test]
1305 fn test_convert_from_wire_bool() {
1306 let aidl_kp =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001307 KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001308 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1309 assert_eq!(KeyParameterValue::CallerNonce, actual);
1310 }
1311 #[test]
1312 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001313 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001314 tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001315 integer: KeyPurpose::ENCRYPT.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001316 ..Default::default()
1317 };
1318 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1319 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1320 }
1321 #[test]
1322 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001323 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001324 tag: Tag::USER_SECURE_ID,
1325 longInteger: i64::MAX,
1326 ..Default::default()
1327 };
1328 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1329 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1330 }
1331 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001332 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001333 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001334 tag: Tag::CONFIRMATION_TOKEN,
1335 blob: String::from("ConfirmationToken").into_bytes(),
1336 ..Default::default()
1337 };
1338 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1339 assert_eq!(
1340 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1341 actual
1342 );
1343 }
1344}