blob: 7ec1d95b876f6acfbf4339c9346b90db45bee515 [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
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080019use crate::db_utils::SqlField;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000020use crate::error::Error as KeystoreError;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070021use crate::error::ResponseCode;
22
Shawn Willden708744a2020-12-11 13:05:27 +000023pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070024 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
25 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
26 KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
Janis Danisevskis04b02832020-10-26 09:21:40 -070027 SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000028};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070029use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000030use anyhow::{Context, Result};
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080031use rusqlite::types::{Null, ToSql, ToSqlOutput};
32use rusqlite::Result as SqlResult;
Hasini Gunasinghe12486362020-07-24 18:40:20 +000033
34/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070035#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000036pub struct KeyParameter {
37 key_parameter_value: KeyParameterValue,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070038 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000039}
40
41/// KeyParameterValue holds a value corresponding to one of the Tags defined in
42/// the AIDL spec at hardware/interfaces/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070043#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000044pub enum KeyParameterValue {
45 /// Associated with Tag:INVALID
46 Invalid,
47 /// Set of purposes for which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070048 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000049 /// Cryptographic algorithm with which the key is used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070050 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000051 /// Size of the key , in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +000052 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000053 /// Block cipher mode(s) with which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070054 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000055 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070056 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000057 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070058 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000059 /// Can the caller provide a nonce for nonce-requiring operations
60 CallerNonce,
61 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Hasini Gunasingheaf993662020-07-24 18:40:20 +000062 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000063 /// The elliptic curve
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070064 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000065 /// Value of the public exponent for an RSA key pair
Hasini Gunasingheaf993662020-07-24 18:40:20 +000066 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000067 /// An attestation certificate for the generated key should contain an application-scoped
68 /// and time-bounded device-unique ID
69 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000070 //TODO: find out about this
71 // /// Necessary system environment conditions for the generated key to be used
72 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000073 /// Only the boot loader can use the key
74 BootLoaderOnly,
75 /// When deleted, the key is guaranteed to be permanently deleted and unusable
76 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000077 /// The date and time at which the key becomes active
Hasini Gunasingheaf993662020-07-24 18:40:20 +000078 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000079 /// The date and time at which the key expires for signing and encryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000080 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000081 /// The date and time at which the key expires for verification and decryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000082 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000083 /// Minimum amount of time that elapses between allowed operations
Hasini Gunasingheaf993662020-07-24 18:40:20 +000084 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000085 /// Maximum number of times that a key may be used between system reboots
Hasini Gunasingheaf993662020-07-24 18:40:20 +000086 MaxUsesPerBoot(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000087 /// ID of the Android user that is permitted to use the key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000088 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000089 /// A key may only be used under a particular secure user authentication state
Hasini Gunasingheaf993662020-07-24 18:40:20 +000090 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000091 /// No authentication is required to use this key
92 NoAuthRequired,
93 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070094 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000095 /// The time in seconds for which the key is authorized for use, after user authentication
Hasini Gunasingheaf993662020-07-24 18:40:20 +000096 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000097 /// The key may be used after authentication timeout if device is still on-body
98 AllowWhileOnBody,
99 /// The key must be unusable except when the user has provided proof of physical presence
100 TrustedUserPresenceRequired,
101 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
102 /// unless the user provides confirmation of the data to be signed
103 TrustedConfirmationRequired,
104 /// The key may only be used when the device is unlocked
105 UnlockedDeviceRequired,
106 /// When provided to generateKey or importKey, this tag specifies data
107 /// that is necessary during all uses of the key
108 ApplicationID(Vec<u8>),
109 /// When provided to generateKey or importKey, this tag specifies data
110 /// that is necessary during all uses of the key
111 ApplicationData(Vec<u8>),
112 /// Specifies the date and time the key was created
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000113 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000114 /// Specifies where the key was created, if known
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700115 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000116 /// The key used by verified boot to validate the operating system booted
117 RootOfTrust(Vec<u8>),
118 /// System OS version with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000119 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000120 /// Specifies the system security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000121 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000122 /// Specifies a unique, time-based identifier
123 UniqueID(Vec<u8>),
124 /// Used to deliver a "challenge" value to the attestKey() method
125 AttestationChallenge(Vec<u8>),
126 /// The set of applications which may use a key, used only with attestKey()
127 AttestationApplicationID(Vec<u8>),
128 /// Provides the device's brand name, to attestKey()
129 AttestationIdBrand(Vec<u8>),
130 /// Provides the device's device name, to attestKey()
131 AttestationIdDevice(Vec<u8>),
132 /// Provides the device's product name, to attestKey()
133 AttestationIdProduct(Vec<u8>),
134 /// Provides the device's serial number, to attestKey()
135 AttestationIdSerial(Vec<u8>),
136 /// Provides the IMEIs for all radios on the device, to attestKey()
137 AttestationIdIMEI(Vec<u8>),
138 /// Provides the MEIDs for all radios on the device, to attestKey()
139 AttestationIdMEID(Vec<u8>),
140 /// Provides the device's manufacturer name, to attestKey()
141 AttestationIdManufacturer(Vec<u8>),
142 /// Provides the device's model name, to attestKey()
143 AttestationIdModel(Vec<u8>),
144 /// Specifies the vendor image security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000145 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000146 /// Specifies the boot image (kernel) security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000147 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000148 /// Provides "associated data" for AES-GCM encryption or decryption
149 AssociatedData(Vec<u8>),
150 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
151 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
152 Nonce(Vec<u8>),
153 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000154 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000155 /// Specifies whether the device has been factory reset since the
156 /// last unique ID rotation. Used for key attestation
157 ResetSinceIdRotation,
158 /// Used to deliver a cryptographic token proving that the user
159 /// confirmed a signing request
160 ConfirmationToken(Vec<u8>),
161}
162
163impl KeyParameter {
164 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700165 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000166 KeyParameter { key_parameter_value, security_level }
167 }
168
169 /// Returns the tag given the KeyParameter instance.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700170 pub fn get_tag(&self) -> Tag {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000171 match self.key_parameter_value {
172 KeyParameterValue::Invalid => Tag::INVALID,
173 KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
174 KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
175 KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
176 KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
177 KeyParameterValue::Digest(_) => Tag::DIGEST,
178 KeyParameterValue::PaddingMode(_) => Tag::PADDING,
179 KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
180 KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
181 KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
182 KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
183 KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000184 KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
185 KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
186 KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
187 KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
188 KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
189 KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
190 KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
191 KeyParameterValue::UserID(_) => Tag::USER_ID,
192 KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
193 KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
194 KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
195 KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
196 KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
197 KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
198 KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
199 KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
200 KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
201 KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
202 KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
203 KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
204 KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
205 KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
206 KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
207 KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
208 KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
209 KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
210 KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
211 KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
212 KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
213 KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
214 KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
215 KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
216 KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
217 KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
218 KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
219 KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
220 KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
221 KeyParameterValue::Nonce(_) => Tag::NONCE,
222 KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
223 KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
224 KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
225 }
226 }
227
228 /// Returns key parameter value.
229 pub fn key_parameter_value(&self) -> &KeyParameterValue {
230 &self.key_parameter_value
231 }
232
233 /// Returns the security level of a KeyParameter.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700234 pub fn security_level(&self) -> &SecurityLevel {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000235 &self.security_level
236 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700237
238 /// An authorization is a KeyParameter with an associated security level that is used
239 /// to convey the key characteristics to keystore clients. This function consumes
240 /// an internal KeyParameter representation to produce the Authorization wire type.
241 pub fn into_authorization(self) -> Authorization {
242 Authorization {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700243 securityLevel: self.security_level,
244 keyParameter: self.key_parameter_value.convert_to_wire(),
Janis Danisevskis04b02832020-10-26 09:21:40 -0700245 }
246 }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000247}
248
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000249impl ToSql for KeyParameterValue {
250 /// Converts KeyParameterValue to be stored in rusqlite database.
251 /// Note that following variants of KeyParameterValue should not be stored:
252 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
253 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
254 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
255 /// conversion for all the variants, to keep error handling simple.
256 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
257 match self {
258 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700259 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
260 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000261 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700262 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
263 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
264 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000265 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
266 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700267 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000268 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
269 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
270 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
271 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
272 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
273 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
274 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
275 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
276 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
277 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
278 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
279 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700280 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000281 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
282 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
283 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
284 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
285 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
286 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
287 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
288 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700289 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000290 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
291 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
292 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
293 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
294 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
295 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
296 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
297 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
298 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
299 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
300 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
301 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
302 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
303 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
304 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
305 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
306 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
307 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
308 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
309 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
310 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
311 }
312 }
313}
314
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000315impl KeyParameter {
316 /// Construct a KeyParameter from the data from a rusqlite row.
317 /// Note that following variants of KeyParameterValue should not be stored:
318 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
319 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
320 /// This filtering is enforced at a higher level and here we support conversion for all the
321 /// variants.
322 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700323 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000324 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700325 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000326 ) -> Result<Self> {
327 let key_param_value = match tag_val {
328 Tag::INVALID => KeyParameterValue::Invalid,
329 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700330 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000331 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700332 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700333 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700334 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000335 }
336 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700337 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000338 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700339 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700340 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700341 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000342 }
343 Tag::KEY_SIZE => {
344 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700345 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000346 KeyParameterValue::KeySize(key_size)
347 }
348 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700349 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000350 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700351 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700352 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700353 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000354 }
355 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700356 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000357 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700358 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700359 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700360 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000361 }
362 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700363 let padding: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000364 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700365 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700366 .context("Failed to read sql data for tag: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700367 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000368 }
369 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
370 Tag::MIN_MAC_LENGTH => {
371 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700372 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000373 KeyParameterValue::MinMacLength(min_mac_length)
374 }
375 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700376 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000377 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700378 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700379 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700380 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000381 }
382 Tag::RSA_PUBLIC_EXPONENT => {
383 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700384 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000385
386 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
387 }
388 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
389 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
390 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
391 Tag::ACTIVE_DATETIME => {
392 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700393 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000394 KeyParameterValue::ActiveDateTime(active_datetime)
395 }
396 Tag::ORIGINATION_EXPIRE_DATETIME => {
397 let origination_expire_datetime: i64 = data
398 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700399 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000400 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
401 }
402 Tag::USAGE_EXPIRE_DATETIME => {
403 let usage_expire_datetime: i64 = data
404 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700405 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000406 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
407 }
408 Tag::MIN_SECONDS_BETWEEN_OPS => {
409 let min_secs_between_ops: i32 = data
410 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700411 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000412 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
413 }
414 Tag::MAX_USES_PER_BOOT => {
415 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700416 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000417 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
418 }
419 Tag::USER_ID => {
420 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700421 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000422 KeyParameterValue::UserID(user_id)
423 }
424 Tag::USER_SECURE_ID => {
425 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700426 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000427 KeyParameterValue::UserSecureID(user_secure_id)
428 }
429 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
430 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700431 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000432 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700433 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700434 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700435 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
436 user_auth_type,
437 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000438 }
439 Tag::AUTH_TIMEOUT => {
440 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700441 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000442 KeyParameterValue::AuthTimeout(auth_timeout)
443 }
444 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
445 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
446 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
447 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
448 Tag::APPLICATION_ID => {
449 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700450 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000451 KeyParameterValue::ApplicationID(app_id)
452 }
453 Tag::APPLICATION_DATA => {
454 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700455 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000456 KeyParameterValue::ApplicationData(app_data)
457 }
458 Tag::CREATION_DATETIME => {
459 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700460 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000461 KeyParameterValue::CreationDateTime(creation_datetime)
462 }
463 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700464 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000465 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700466 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700467 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700468 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000469 }
470 Tag::ROOT_OF_TRUST => {
471 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700472 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000473 KeyParameterValue::RootOfTrust(root_of_trust)
474 }
475 Tag::OS_VERSION => {
476 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700477 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000478 KeyParameterValue::OSVersion(os_version)
479 }
480 Tag::OS_PATCHLEVEL => {
481 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700482 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000483 KeyParameterValue::OSPatchLevel(os_patch_level)
484 }
485 Tag::UNIQUE_ID => {
486 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700487 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000488 KeyParameterValue::UniqueID(unique_id)
489 }
490 Tag::ATTESTATION_CHALLENGE => {
491 let attestation_challenge: Vec<u8> = data
492 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700493 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000494 KeyParameterValue::AttestationChallenge(attestation_challenge)
495 }
496 Tag::ATTESTATION_APPLICATION_ID => {
497 let attestation_app_id: Vec<u8> = data
498 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700499 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000500 KeyParameterValue::AttestationApplicationID(attestation_app_id)
501 }
502 Tag::ATTESTATION_ID_BRAND => {
503 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700504 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000505 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
506 }
507 Tag::ATTESTATION_ID_DEVICE => {
508 let attestation_id_device: Vec<u8> = data
509 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700510 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000511 KeyParameterValue::AttestationIdDevice(attestation_id_device)
512 }
513 Tag::ATTESTATION_ID_PRODUCT => {
514 let attestation_id_product: Vec<u8> = data
515 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700516 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000517 KeyParameterValue::AttestationIdProduct(attestation_id_product)
518 }
519 Tag::ATTESTATION_ID_SERIAL => {
520 let attestation_id_serial: Vec<u8> = data
521 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700522 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000523 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
524 }
525 Tag::ATTESTATION_ID_IMEI => {
526 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700527 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000528 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
529 }
530 Tag::ATTESTATION_ID_MEID => {
531 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700532 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000533 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
534 }
535 Tag::ATTESTATION_ID_MANUFACTURER => {
536 let attestation_id_manufacturer: Vec<u8> = data
537 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700538 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000539 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
540 }
541 Tag::ATTESTATION_ID_MODEL => {
542 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700543 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000544 KeyParameterValue::AttestationIdModel(attestation_id_model)
545 }
546 Tag::VENDOR_PATCHLEVEL => {
547 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700548 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000549 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
550 }
551 Tag::BOOT_PATCHLEVEL => {
552 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700553 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000554 KeyParameterValue::BootPatchLevel(boot_patch_level)
555 }
556 Tag::ASSOCIATED_DATA => {
557 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700558 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000559 KeyParameterValue::AssociatedData(associated_data)
560 }
561 Tag::NONCE => {
562 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700563 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000564 KeyParameterValue::Nonce(nonce)
565 }
566 Tag::MAC_LENGTH => {
567 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700568 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000569 KeyParameterValue::MacLength(mac_length)
570 }
571 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
572 Tag::CONFIRMATION_TOKEN => {
573 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700574 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000575 KeyParameterValue::ConfirmationToken(confirmation_token)
576 }
577 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700578 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700579 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000580 }
581 };
582 Ok(KeyParameter::new(key_param_value, security_level_val))
583 }
584}
585
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000586/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700587/// This macro takes between three and four different pieces of information about each
588/// of the KeyParameterValue variants:
589/// 1. The KeyParameterValue variant name,
590/// 2. the tag name corresponding to the variant,
591/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
592/// stored when converted, and
593/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000594/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
595/// the two conversion methods: convert_to_wire() and convert_from_wire().
596/// ## Example
597/// ```
598/// implement_key_parameter_conversion_to_from_wire! {
599/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700600/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000601/// CallerNonce, CALLER_NONCE, boolValue;
602/// UserSecureID, USER_SECURE_ID, longInteger;
603/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000604/// }
605/// ```
606/// expands to:
607/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700608/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000609/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700610/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000611/// tag: Tag::INVALID,
612/// ..Default::default()
613/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700614/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000615/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700616/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000617/// ..Default::default()
618/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700619/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000620/// tag: Tag::CALLER_NONCE,
621/// boolValue: true,
622/// ..Default::default()
623/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700624/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000625/// tag: Tag::USER_SECURE_ID,
626/// longInteger: v,
627/// ..Default::default()
628/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700629/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000630/// tag: Tag::APPLICATION_ID,
631/// blob: v,
632/// ..Default::default()
633/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000634/// }
635/// }
636/// ```
637/// and
638/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700639/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000640/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700641/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000642/// tag: Tag::INVALID,
643/// ..
644/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700645/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000646/// tag: Tag::PURPOSE,
647/// integer: v,
648/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700649/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
650/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000651/// tag: Tag::CALLER_NONCE,
652/// boolValue: true,
653/// ..
654/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700655/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000656/// tag: Tag::USER_SECURE_ID,
657/// longInteger: v,
658/// ..
659/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700660/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000661/// tag: Tag::APPLICATION_ID,
662/// blob: v,
663/// ..
664/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000665/// _ => KeyParameterValue::Invalid,
666/// }
667/// }
668///
669macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700670 // There are three groups of rules in this macro.
671 // 1. The first group contains the rule which acts as the public interface. It takes the input
672 // given to this macro and prepares it to be given as input to the two groups of rules
673 // mentioned below.
674 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
675 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
676 //
677 // Input to this macro is first handled by the first macro rule (belonging to the first
678 // group above), which pre-processes the input such that rules in the other two groups
679 // generate the code for the two methods, when called recursively.
680 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
681 // four macro rules in the second two groups. These four rules intend to do the following
682 // tasks respectively:
683 // i) generates match arms related to Invalid KeyParameterValue variant.
684 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
685 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
686 // iv) generates the method definition including the match arms generated from the above
687 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000688
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700689 // This rule is applied on the input given to the macro invocations from outside the macro.
690 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
691 // pre-processes input to target the rules that generate convert_to_wire() method.
692 implement_key_parameter_conversion_to_from_wire! {@to
693 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
694 }
695 // pre-processes input to target the rules that generate convert_from_wire() method.
696 implement_key_parameter_conversion_to_from_wire! {@from
697 [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
698 }
699 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000700
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700701 // Following four rules (belonging to the aforementioned second group) generate
702 // convert_to_wire() conversion method.
703 // -----------------------------------------------------------------------
704 // This rule handles Invalid variant.
705 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
706 // KeyParameterValue::Invalid => KmKeyParameter {
707 // tag: Tag::INVALID,
708 // ..Default::default()
709 // },
710 (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
711 implement_key_parameter_conversion_to_from_wire! {@to
712 [$($out)*
713 KeyParameterValue::Invalid => KmKeyParameter {
714 tag: Tag::INVALID,
715 ..Default::default()
716 },
717 ], $($in)*
718 }
719 };
720 // This rule handles all variants that correspond to bool values.
721 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
722 // a match arm like:
723 // KeyParameterValue::CallerNonce => KmKeyParameter {
724 // tag: Tag::CALLER_NONCE,
725 // boolValue: true,
726 // ..Default::default()
727 // },
728 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
729 implement_key_parameter_conversion_to_from_wire! {@to
730 [$($out)*
731 KeyParameterValue::$variant => KmKeyParameter {
732 tag: Tag::$tag_val,
733 boolValue: true,
734 ..Default::default()
735 },
736 ], $($in)*
737 }
738 };
739 // This rule handles all enum variants.
740 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
741 // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
742 // tag: Tag::PURPOSE,
743 // integer: v.0,
744 // ..Default::default(),
745 // },
746 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
747 implement_key_parameter_conversion_to_from_wire! {@to
748 [$($out)*
749 KeyParameterValue::$variant(v) => KmKeyParameter {
750 tag: Tag::$tag_val,
751 $field: v.0,
752 ..Default::default()
753 },
754 ], $($in)*
755 }
756 };
757 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700758 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700759 // KmKeyParameter).
760 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
761 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
762 // tag: Tag::CONFIRMATION_TOKEN,
763 // blob: v,
764 // ..Default::default(),
765 // },
766 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
767 implement_key_parameter_conversion_to_from_wire! {@to
768 [$($out)*
769 KeyParameterValue::$variant(v) => KmKeyParameter {
770 tag: Tag::$tag_val,
771 $field: v,
772 ..Default::default()
773 },
774 ], $($in)*
775 }
776 };
777 // After all the match arms are generated by the above three rules, this rule combines them
778 // into the convert_to_wire() method.
779 (@to [$($out:tt)*], ) => {
780 /// Conversion of key parameter to wire type
781 pub fn convert_to_wire(self) -> KmKeyParameter {
782 match self {
783 $($out)*
784 }
785 }
786 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000787
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700788 // Following four rules (belonging to the aforementioned third group) generate
789 // convert_from_wire() conversion method.
790 // ------------------------------------------------------------------------
791 // This rule handles Invalid variant.
792 // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
793 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
794 (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
795 implement_key_parameter_conversion_to_from_wire! {@from
796 [$($out)*
797 KmKeyParameter {
798 tag: Tag::INVALID,
799 ..
800 } => KeyParameterValue::Invalid,
801 ], $($in)*
802 }
803 };
804 // This rule handles all variants that correspond to bool values.
805 // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
806 // KmKeyParameter {
807 // tag: Tag::CALLER_NONCE,
808 // boolValue: true,
809 // ..
810 // } => KeyParameterValue::CallerNonce,
811 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
812 implement_key_parameter_conversion_to_from_wire! {@from
813 [$($out)*
814 KmKeyParameter {
815 tag: Tag::$tag_val,
816 boolValue: true,
817 ..
818 } => KeyParameterValue::$variant,
819 ], $($in)*
820 }
821 };
822 // This rule handles all enum variants.
823 // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
824 // like:
825 // KmKeyParameter {
826 // tag: Tag::PURPOSE,
827 // integer: v,
828 // ..,
829 // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
830 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
831 implement_key_parameter_conversion_to_from_wire! {@from
832 [$($out)*
833 KmKeyParameter {
834 tag: Tag::$tag_val,
835 $field: v,
836 ..
837 } => KeyParameterValue::$variant($enum_type(v)),
838 ], $($in)*
839 }
840 };
841 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700842 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700843 // KmKeyParameter).
844 // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
845 // like:
846 // KmKeyParameter {
847 // tag: Tag::CONFIRMATION_TOKEN,
848 // blob: v,
849 // ..,
850 // } => KeyParameterValue::ConfirmationToken(v),
851 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
852 implement_key_parameter_conversion_to_from_wire! {@from
853 [$($out)*
854 KmKeyParameter {
855 tag: Tag::$tag_val,
856 $field: v,
857 ..
858 } => KeyParameterValue::$variant(v),
859 ], $($in)*
860 }
861 };
862 // After all the match arms are generated by the above three rules, this rule combines them
863 // into the convert_from_wire() method.
864 (@from [$($out:tt)*], ) => {
865 /// Conversion of key parameter from wire type
866 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
867 match aidl_kp {
868 $($out)*
869 _ => KeyParameterValue::Invalid,
870 }
871 }
872 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000873}
874
875impl KeyParameterValue {
876 // Invoke the macro that generates the code for key parameter conversion to/from wire type
877 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
878 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700879 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000880 implement_key_parameter_conversion_to_from_wire! {
881 Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700882 KeyPurpose, PURPOSE, integer, KeyPurpose;
883 Algorithm, ALGORITHM, integer, Algorithm;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000884 KeySize, KEY_SIZE, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700885 BlockMode, BLOCK_MODE, integer, BlockMode;
886 Digest, DIGEST, integer, Digest;
887 PaddingMode, PADDING, integer, PaddingMode;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000888 CallerNonce, CALLER_NONCE, boolValue;
889 MinMacLength, MIN_MAC_LENGTH, integer;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700890 EcCurve, EC_CURVE, integer, EcCurve;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000891 RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
892 IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
893 BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
894 RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700895 ActiveDateTime, ACTIVE_DATETIME, longInteger;
896 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
897 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000898 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
899 MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
900 UserID, USER_ID, integer;
901 UserSecureID, USER_SECURE_ID, longInteger;
902 NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700903 HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000904 AuthTimeout, AUTH_TIMEOUT, integer;
905 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
906 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
907 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
908 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
909 ApplicationID, APPLICATION_ID, blob;
910 ApplicationData, APPLICATION_DATA, blob;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700911 CreationDateTime, CREATION_DATETIME, longInteger;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700912 KeyOrigin, ORIGIN, integer, KeyOrigin;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000913 RootOfTrust, ROOT_OF_TRUST, blob;
914 OSVersion, OS_VERSION, integer;
915 OSPatchLevel, OS_PATCHLEVEL, integer;
916 UniqueID, UNIQUE_ID, blob;
917 AttestationChallenge, ATTESTATION_CHALLENGE, blob;
918 AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
919 AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
920 AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
921 AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
922 AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
923 AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
924 AttestationIdMEID, ATTESTATION_ID_MEID, blob;
925 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
926 AttestationIdModel, ATTESTATION_ID_MODEL, blob;
927 VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
928 BootPatchLevel, BOOT_PATCHLEVEL, integer;
929 AssociatedData, ASSOCIATED_DATA, blob;
930 Nonce, NONCE, blob;
931 MacLength, MAC_LENGTH, integer;
932 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
933 ConfirmationToken, CONFIRMATION_TOKEN, blob;
934 }
935}
936
937#[cfg(test)]
938mod basic_tests {
939 use crate::key_parameter::*;
940
941 // Test basic functionality of KeyParameter.
942 #[test]
943 fn test_key_parameter() {
944 let key_parameter = KeyParameter::new(
945 KeyParameterValue::Algorithm(Algorithm::RSA),
946 SecurityLevel::STRONGBOX,
947 );
948
949 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
950
951 assert_eq!(
952 *key_parameter.key_parameter_value(),
953 KeyParameterValue::Algorithm(Algorithm::RSA)
954 );
955
956 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
957 }
958}
959
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000960/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
961/// data types and then tests 'to_sql' method for KeyParameters of those
962/// different data types. The five different data types for KeyParameter values are:
963/// i) enums of u32
964/// ii) u32
965/// iii) u64
966/// iv) Vec<u8>
967/// v) bool
968#[cfg(test)]
969mod storage_tests {
970 use crate::error::*;
971 use crate::key_parameter::*;
972 use anyhow::Result;
973 use rusqlite::types::ToSql;
974 use rusqlite::{params, Connection, NO_PARAMS};
975
976 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
977 /// from a database table row.
978 #[test]
979 fn test_new_from_sql_enum_i32() -> Result<()> {
980 let db = init_db()?;
981 insert_into_keyparameter(
982 &db,
983 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700984 Tag::ALGORITHM.0,
985 &Algorithm::RSA.0,
986 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000987 )?;
988 let key_param = query_from_keyparameter(&db)?;
989 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
990 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
991 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
992 Ok(())
993 }
994
995 /// Test initializing a KeyParameter (with key parameter value which is of i32)
996 /// from a database table row.
997 #[test]
998 fn test_new_from_sql_i32() -> Result<()> {
999 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001000 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001001 let key_param = query_from_keyparameter(&db)?;
1002 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1003 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1004 Ok(())
1005 }
1006
1007 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1008 /// from a database table row.
1009 #[test]
1010 fn test_new_from_sql_i64() -> Result<()> {
1011 let db = init_db()?;
1012 // max value for i64, just to test corner cases
1013 insert_into_keyparameter(
1014 &db,
1015 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001016 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001017 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001018 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001019 )?;
1020 let key_param = query_from_keyparameter(&db)?;
1021 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1022 assert_eq!(
1023 *key_param.key_parameter_value(),
1024 KeyParameterValue::RSAPublicExponent(i64::MAX)
1025 );
1026 Ok(())
1027 }
1028
1029 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1030 /// from a database table row.
1031 #[test]
1032 fn test_new_from_sql_bool() -> Result<()> {
1033 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001034 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001035 let key_param = query_from_keyparameter(&db)?;
1036 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1037 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1038 Ok(())
1039 }
1040
1041 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1042 /// from a database table row.
1043 #[test]
1044 fn test_new_from_sql_vec_u8() -> Result<()> {
1045 let db = init_db()?;
1046 let app_id = String::from("MyAppID");
1047 let app_id_bytes = app_id.into_bytes();
1048 insert_into_keyparameter(
1049 &db,
1050 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001051 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001052 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001053 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001054 )?;
1055 let key_param = query_from_keyparameter(&db)?;
1056 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1057 assert_eq!(
1058 *key_param.key_parameter_value(),
1059 KeyParameterValue::ApplicationID(app_id_bytes)
1060 );
1061 Ok(())
1062 }
1063
1064 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1065 /// in the database
1066 #[test]
1067 fn test_to_sql_enum_i32() -> Result<()> {
1068 let db = init_db()?;
1069 let kp = KeyParameter::new(
1070 KeyParameterValue::Algorithm(Algorithm::RSA),
1071 SecurityLevel::STRONGBOX,
1072 );
1073 store_keyparameter(&db, 1, &kp)?;
1074 let key_param = query_from_keyparameter(&db)?;
1075 assert_eq!(kp.get_tag(), key_param.get_tag());
1076 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1077 assert_eq!(kp.security_level(), key_param.security_level());
1078 Ok(())
1079 }
1080
1081 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1082 #[test]
1083 fn test_to_sql_i32() -> Result<()> {
1084 let db = init_db()?;
1085 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1086 store_keyparameter(&db, 1, &kp)?;
1087 let key_param = query_from_keyparameter(&db)?;
1088 assert_eq!(kp.get_tag(), key_param.get_tag());
1089 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1090 assert_eq!(kp.security_level(), key_param.security_level());
1091 Ok(())
1092 }
1093
1094 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1095 #[test]
1096 fn test_to_sql_i64() -> Result<()> {
1097 let db = init_db()?;
1098 // max value for i64, just to test corner cases
1099 let kp = KeyParameter::new(
1100 KeyParameterValue::RSAPublicExponent(i64::MAX),
1101 SecurityLevel::STRONGBOX,
1102 );
1103 store_keyparameter(&db, 1, &kp)?;
1104 let key_param = query_from_keyparameter(&db)?;
1105 assert_eq!(kp.get_tag(), key_param.get_tag());
1106 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1107 assert_eq!(kp.security_level(), key_param.security_level());
1108 Ok(())
1109 }
1110
1111 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1112 #[test]
1113 fn test_to_sql_vec_u8() -> Result<()> {
1114 let db = init_db()?;
1115 let kp = KeyParameter::new(
1116 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
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 i32) in the database
1128 #[test]
1129 fn test_to_sql_bool() -> Result<()> {
1130 let db = init_db()?;
1131 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1132 store_keyparameter(&db, 1, &kp)?;
1133 let key_param = query_from_keyparameter(&db)?;
1134 assert_eq!(kp.get_tag(), key_param.get_tag());
1135 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1136 assert_eq!(kp.security_level(), key_param.security_level());
1137 Ok(())
1138 }
1139
1140 #[test]
1141 /// Test Tag::Invalid
1142 fn test_invalid_tag() -> Result<()> {
1143 let db = init_db()?;
1144 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1145 let key_param = query_from_keyparameter(&db)?;
1146 assert_eq!(Tag::INVALID, key_param.get_tag());
1147 Ok(())
1148 }
1149
1150 #[test]
1151 fn test_non_existing_enum_variant() -> Result<()> {
1152 let db = init_db()?;
1153 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1154 tests::check_result_contains_error_string(
1155 query_from_keyparameter(&db),
1156 "Failed to decode Tag enum from value.",
1157 );
1158 Ok(())
1159 }
1160
1161 #[test]
1162 fn test_invalid_conversion_from_sql() -> Result<()> {
1163 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001164 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001165 tests::check_result_contains_error_string(
1166 query_from_keyparameter(&db),
1167 "Failed to read sql data for tag: ALGORITHM.",
1168 );
1169 Ok(())
1170 }
1171
1172 /// Helper method to init database table for key parameter
1173 fn init_db() -> Result<Connection> {
1174 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1175 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1176 .context("Failed to attach databases.")?;
1177 db.execute(
1178 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1179 keyentryid INTEGER,
1180 tag INTEGER,
1181 data ANY,
1182 security_level INTEGER);",
1183 NO_PARAMS,
1184 )
1185 .context("Failed to initialize \"keyparameter\" table.")?;
1186 Ok(db)
1187 }
1188
1189 /// Helper method to insert an entry into key parameter table, with individual parameters
1190 fn insert_into_keyparameter<T: ToSql>(
1191 db: &Connection,
1192 key_id: i64,
1193 tag: i32,
1194 value: &T,
1195 security_level: i32,
1196 ) -> Result<()> {
1197 db.execute(
1198 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001199 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001200 params![key_id, tag, *value, security_level],
1201 )?;
1202 Ok(())
1203 }
1204
1205 /// Helper method to store a key parameter instance.
1206 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1207 db.execute(
1208 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001209 VALUES(?, ?, ?, ?);",
1210 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001211 )?;
1212 Ok(())
1213 }
1214
1215 /// Helper method to query a row from keyparameter table
1216 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001217 let mut stmt =
1218 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001219 let mut rows = stmt.query(NO_PARAMS)?;
1220 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001221 Ok(KeyParameter::new_from_sql(
1222 Tag(row.get(0)?),
Janis Danisevskis4522c2b2020-11-27 18:04:58 -08001223 &SqlField::new(1, row),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001224 SecurityLevel(row.get(2)?),
1225 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001226 }
1227}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001228
1229/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001230/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001231/// key parameter.
1232/// i) bool
1233/// ii) integer
1234/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001235/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001236#[cfg(test)]
1237mod wire_tests {
1238 use crate::key_parameter::*;
1239 /// unit tests for to conversions
1240 #[test]
1241 fn test_convert_to_wire_invalid() {
1242 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1243 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1244 assert_eq!(Tag::INVALID, actual.tag);
1245 }
1246 #[test]
1247 fn test_convert_to_wire_bool() {
1248 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1249 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1250 assert_eq!(Tag::CALLER_NONCE, actual.tag);
1251 assert_eq!(true, actual.boolValue);
1252 }
1253 #[test]
1254 fn test_convert_to_wire_integer() {
1255 let kp = KeyParameter::new(
1256 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1257 SecurityLevel::STRONGBOX,
1258 );
1259 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1260 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001261 assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001262 }
1263 #[test]
1264 fn test_convert_to_wire_long_integer() {
1265 let kp =
1266 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1267 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1268 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
1269 assert_eq!(i64::MAX, actual.longInteger);
1270 }
1271 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001272 fn test_convert_to_wire_blob() {
1273 let kp = KeyParameter::new(
1274 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1275 SecurityLevel::STRONGBOX,
1276 );
1277 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1278 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
1279 assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
1280 }
1281
1282 /// unit tests for from conversion
1283 #[test]
1284 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001285 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001286 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1287 assert_eq!(KeyParameterValue::Invalid, actual);
1288 }
1289 #[test]
1290 fn test_convert_from_wire_bool() {
1291 let aidl_kp =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001292 KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001293 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1294 assert_eq!(KeyParameterValue::CallerNonce, actual);
1295 }
1296 #[test]
1297 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001298 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001299 tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001300 integer: KeyPurpose::ENCRYPT.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001301 ..Default::default()
1302 };
1303 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1304 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1305 }
1306 #[test]
1307 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001308 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001309 tag: Tag::USER_SECURE_ID,
1310 longInteger: i64::MAX,
1311 ..Default::default()
1312 };
1313 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1314 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1315 }
1316 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001317 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001318 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001319 tag: Tag::CONFIRMATION_TOKEN,
1320 blob: String::from("ConfirmationToken").into_bytes(),
1321 ..Default::default()
1322 };
1323 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1324 assert_eq!(
1325 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1326 actual
1327 );
1328 }
1329}