blob: 56c03aa0b0ffec3e47894998632537041115dc7d [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,
Janis Danisevskis398e6be2020-12-17 09:29:25 -080026 KeyParameter::KeyParameter as KmKeyParameter,
27 KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
28 PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000029};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070030use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000031use anyhow::{Context, Result};
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080032use rusqlite::types::{Null, ToSql, ToSqlOutput};
33use rusqlite::Result as SqlResult;
Hasini Gunasinghe12486362020-07-24 18:40:20 +000034
35/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070036#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000037pub struct KeyParameter {
38 key_parameter_value: KeyParameterValue,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070039 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000040}
41
42/// KeyParameterValue holds a value corresponding to one of the Tags defined in
43/// the AIDL spec at hardware/interfaces/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070044#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +000045pub enum KeyParameterValue {
46 /// Associated with Tag:INVALID
47 Invalid,
48 /// Set of purposes for which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070049 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000050 /// Cryptographic algorithm with which the key is used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070051 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000052 /// Size of the key , in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +000053 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000054 /// Block cipher mode(s) with which the key may be used
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070055 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000056 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070057 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000058 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070059 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000060 /// Can the caller provide a nonce for nonce-requiring operations
61 CallerNonce,
62 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Hasini Gunasingheaf993662020-07-24 18:40:20 +000063 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000064 /// The elliptic curve
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070065 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000066 /// Value of the public exponent for an RSA key pair
Hasini Gunasingheaf993662020-07-24 18:40:20 +000067 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000068 /// An attestation certificate for the generated key should contain an application-scoped
69 /// and time-bounded device-unique ID
70 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +000071 //TODO: find out about this
72 // /// Necessary system environment conditions for the generated key to be used
73 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000074 /// Only the boot loader can use the key
75 BootLoaderOnly,
76 /// When deleted, the key is guaranteed to be permanently deleted and unusable
77 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +000078 /// The date and time at which the key becomes active
Hasini Gunasingheaf993662020-07-24 18:40:20 +000079 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000080 /// The date and time at which the key expires for signing and encryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000081 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000082 /// The date and time at which the key expires for verification and decryption
Hasini Gunasingheaf993662020-07-24 18:40:20 +000083 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000084 /// Minimum amount of time that elapses between allowed operations
Hasini Gunasingheaf993662020-07-24 18:40:20 +000085 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000086 /// Maximum number of times that a key may be used between system reboots
Hasini Gunasingheaf993662020-07-24 18:40:20 +000087 MaxUsesPerBoot(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000088 /// ID of the Android user that is permitted to use the key
Hasini Gunasingheaf993662020-07-24 18:40:20 +000089 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000090 /// A key may only be used under a particular secure user authentication state
Hasini Gunasingheaf993662020-07-24 18:40:20 +000091 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000092 /// No authentication is required to use this key
93 NoAuthRequired,
94 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070095 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000096 /// The time in seconds for which the key is authorized for use, after user authentication
Hasini Gunasingheaf993662020-07-24 18:40:20 +000097 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +000098 /// The key may be used after authentication timeout if device is still on-body
99 AllowWhileOnBody,
100 /// The key must be unusable except when the user has provided proof of physical presence
101 TrustedUserPresenceRequired,
102 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
103 /// unless the user provides confirmation of the data to be signed
104 TrustedConfirmationRequired,
105 /// The key may only be used when the device is unlocked
106 UnlockedDeviceRequired,
107 /// When provided to generateKey or importKey, this tag specifies data
108 /// that is necessary during all uses of the key
109 ApplicationID(Vec<u8>),
110 /// When provided to generateKey or importKey, this tag specifies data
111 /// that is necessary during all uses of the key
112 ApplicationData(Vec<u8>),
113 /// Specifies the date and time the key was created
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000114 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000115 /// Specifies where the key was created, if known
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700116 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000117 /// The key used by verified boot to validate the operating system booted
118 RootOfTrust(Vec<u8>),
119 /// System OS version with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000120 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000121 /// Specifies the system security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000122 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000123 /// Specifies a unique, time-based identifier
124 UniqueID(Vec<u8>),
125 /// Used to deliver a "challenge" value to the attestKey() method
126 AttestationChallenge(Vec<u8>),
127 /// The set of applications which may use a key, used only with attestKey()
128 AttestationApplicationID(Vec<u8>),
129 /// Provides the device's brand name, to attestKey()
130 AttestationIdBrand(Vec<u8>),
131 /// Provides the device's device name, to attestKey()
132 AttestationIdDevice(Vec<u8>),
133 /// Provides the device's product name, to attestKey()
134 AttestationIdProduct(Vec<u8>),
135 /// Provides the device's serial number, to attestKey()
136 AttestationIdSerial(Vec<u8>),
137 /// Provides the IMEIs for all radios on the device, to attestKey()
138 AttestationIdIMEI(Vec<u8>),
139 /// Provides the MEIDs for all radios on the device, to attestKey()
140 AttestationIdMEID(Vec<u8>),
141 /// Provides the device's manufacturer name, to attestKey()
142 AttestationIdManufacturer(Vec<u8>),
143 /// Provides the device's model name, to attestKey()
144 AttestationIdModel(Vec<u8>),
145 /// Specifies the vendor image security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000146 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000147 /// Specifies the boot image (kernel) security patch level with which the key may be used
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000148 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000149 /// Provides "associated data" for AES-GCM encryption or decryption
150 AssociatedData(Vec<u8>),
151 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
152 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
153 Nonce(Vec<u8>),
154 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000155 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000156 /// Specifies whether the device has been factory reset since the
157 /// last unique ID rotation. Used for key attestation
158 ResetSinceIdRotation,
159 /// Used to deliver a cryptographic token proving that the user
160 /// confirmed a signing request
161 ConfirmationToken(Vec<u8>),
162}
163
164impl KeyParameter {
165 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700166 pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000167 KeyParameter { key_parameter_value, security_level }
168 }
169
170 /// Returns the tag given the KeyParameter instance.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700171 pub fn get_tag(&self) -> Tag {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000172 match self.key_parameter_value {
173 KeyParameterValue::Invalid => Tag::INVALID,
174 KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
175 KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
176 KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
177 KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
178 KeyParameterValue::Digest(_) => Tag::DIGEST,
179 KeyParameterValue::PaddingMode(_) => Tag::PADDING,
180 KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
181 KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
182 KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
183 KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
184 KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000185 KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
186 KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
187 KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
188 KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
189 KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
190 KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
191 KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
192 KeyParameterValue::UserID(_) => Tag::USER_ID,
193 KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
194 KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
195 KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
196 KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
197 KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
198 KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
199 KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
200 KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
201 KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
202 KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
203 KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
204 KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
205 KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
206 KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
207 KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
208 KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
209 KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
210 KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
211 KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
212 KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
213 KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
214 KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
215 KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
216 KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
217 KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
218 KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
219 KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
220 KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
221 KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
222 KeyParameterValue::Nonce(_) => Tag::NONCE,
223 KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
224 KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
225 KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
226 }
227 }
228
229 /// Returns key parameter value.
230 pub fn key_parameter_value(&self) -> &KeyParameterValue {
231 &self.key_parameter_value
232 }
233
234 /// Returns the security level of a KeyParameter.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700235 pub fn security_level(&self) -> &SecurityLevel {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000236 &self.security_level
237 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700238
239 /// An authorization is a KeyParameter with an associated security level that is used
240 /// to convey the key characteristics to keystore clients. This function consumes
241 /// an internal KeyParameter representation to produce the Authorization wire type.
242 pub fn into_authorization(self) -> Authorization {
243 Authorization {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700244 securityLevel: self.security_level,
245 keyParameter: self.key_parameter_value.convert_to_wire(),
Janis Danisevskis04b02832020-10-26 09:21:40 -0700246 }
247 }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000248}
249
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000250impl ToSql for KeyParameterValue {
251 /// Converts KeyParameterValue to be stored in rusqlite database.
252 /// Note that following variants of KeyParameterValue should not be stored:
253 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
254 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
255 /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
256 /// conversion for all the variants, to keep error handling simple.
257 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
258 match self {
259 KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700260 KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
261 KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000262 KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700263 KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
264 KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
265 KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000266 KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
267 KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700268 KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000269 KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
270 KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
271 KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
272 KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
273 KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
274 KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
275 KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
276 KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
277 KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
278 KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
279 KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
280 KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700281 KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000282 KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
283 KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
284 KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
285 KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
286 KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
287 KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
288 KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
289 KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700290 KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000291 KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
292 KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
293 KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
294 KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
295 KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
296 KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
297 KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
298 KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
299 KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
300 KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
301 KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
302 KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
303 KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
304 KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
305 KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
306 KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
307 KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
308 KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
309 KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
310 KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
311 KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
312 }
313 }
314}
315
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000316impl KeyParameter {
317 /// Construct a KeyParameter from the data from a rusqlite row.
318 /// Note that following variants of KeyParameterValue should not be stored:
319 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
320 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
321 /// This filtering is enforced at a higher level and here we support conversion for all the
322 /// variants.
323 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700324 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000325 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700326 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000327 ) -> Result<Self> {
328 let key_param_value = match tag_val {
329 Tag::INVALID => KeyParameterValue::Invalid,
330 Tag::PURPOSE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700331 let key_purpose: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000332 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700333 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700334 .context("Failed to read sql data for tag: PURPOSE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700335 KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000336 }
337 Tag::ALGORITHM => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700338 let algorithm: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000339 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700340 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700341 .context("Failed to read sql data for tag: ALGORITHM.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700342 KeyParameterValue::Algorithm(Algorithm(algorithm))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000343 }
344 Tag::KEY_SIZE => {
345 let key_size: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700346 data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000347 KeyParameterValue::KeySize(key_size)
348 }
349 Tag::BLOCK_MODE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700350 let block_mode: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000351 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700352 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700353 .context("Failed to read sql data for tag: BLOCK_MODE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700354 KeyParameterValue::BlockMode(BlockMode(block_mode))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000355 }
356 Tag::DIGEST => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700357 let digest: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000358 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700359 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700360 .context("Failed to read sql data for tag: DIGEST.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700361 KeyParameterValue::Digest(Digest(digest))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000362 }
363 Tag::PADDING => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700364 let padding: 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: PADDING.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700368 KeyParameterValue::PaddingMode(PaddingMode(padding))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000369 }
370 Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
371 Tag::MIN_MAC_LENGTH => {
372 let min_mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700373 data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000374 KeyParameterValue::MinMacLength(min_mac_length)
375 }
376 Tag::EC_CURVE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700377 let ec_curve: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000378 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700379 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700380 .context("Failed to read sql data for tag: EC_CURVE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700381 KeyParameterValue::EcCurve(EcCurve(ec_curve))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000382 }
383 Tag::RSA_PUBLIC_EXPONENT => {
384 let rsa_pub_exponent: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700385 data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000386
387 KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
388 }
389 Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
390 Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
391 Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
392 Tag::ACTIVE_DATETIME => {
393 let active_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700394 data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000395 KeyParameterValue::ActiveDateTime(active_datetime)
396 }
397 Tag::ORIGINATION_EXPIRE_DATETIME => {
398 let origination_expire_datetime: i64 = data
399 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700400 .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000401 KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
402 }
403 Tag::USAGE_EXPIRE_DATETIME => {
404 let usage_expire_datetime: i64 = data
405 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700406 .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000407 KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
408 }
409 Tag::MIN_SECONDS_BETWEEN_OPS => {
410 let min_secs_between_ops: i32 = data
411 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700412 .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000413 KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
414 }
415 Tag::MAX_USES_PER_BOOT => {
416 let max_uses_per_boot: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700417 data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000418 KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
419 }
420 Tag::USER_ID => {
421 let user_id: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700422 data.get().context("Failed to read sql data for tag: USER_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000423 KeyParameterValue::UserID(user_id)
424 }
425 Tag::USER_SECURE_ID => {
426 let user_secure_id: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700427 data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000428 KeyParameterValue::UserSecureID(user_secure_id)
429 }
430 Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
431 Tag::USER_AUTH_TYPE => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700432 let user_auth_type: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000433 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700434 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700435 .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700436 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
437 user_auth_type,
438 ))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000439 }
440 Tag::AUTH_TIMEOUT => {
441 let auth_timeout: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700442 data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000443 KeyParameterValue::AuthTimeout(auth_timeout)
444 }
445 Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
446 Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
447 Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
448 Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
449 Tag::APPLICATION_ID => {
450 let app_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700451 data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000452 KeyParameterValue::ApplicationID(app_id)
453 }
454 Tag::APPLICATION_DATA => {
455 let app_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700456 data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000457 KeyParameterValue::ApplicationData(app_data)
458 }
459 Tag::CREATION_DATETIME => {
460 let creation_datetime: i64 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700461 data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000462 KeyParameterValue::CreationDateTime(creation_datetime)
463 }
464 Tag::ORIGIN => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700465 let origin: i32 = data
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000466 .get()
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700467 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700468 .context("Failed to read sql data for tag: ORIGIN.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700469 KeyParameterValue::KeyOrigin(KeyOrigin(origin))
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000470 }
471 Tag::ROOT_OF_TRUST => {
472 let root_of_trust: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700473 data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000474 KeyParameterValue::RootOfTrust(root_of_trust)
475 }
476 Tag::OS_VERSION => {
477 let os_version: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700478 data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000479 KeyParameterValue::OSVersion(os_version)
480 }
481 Tag::OS_PATCHLEVEL => {
482 let os_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700483 data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000484 KeyParameterValue::OSPatchLevel(os_patch_level)
485 }
486 Tag::UNIQUE_ID => {
487 let unique_id: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700488 data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000489 KeyParameterValue::UniqueID(unique_id)
490 }
491 Tag::ATTESTATION_CHALLENGE => {
492 let attestation_challenge: Vec<u8> = data
493 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700494 .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000495 KeyParameterValue::AttestationChallenge(attestation_challenge)
496 }
497 Tag::ATTESTATION_APPLICATION_ID => {
498 let attestation_app_id: Vec<u8> = data
499 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700500 .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000501 KeyParameterValue::AttestationApplicationID(attestation_app_id)
502 }
503 Tag::ATTESTATION_ID_BRAND => {
504 let attestation_id_brand: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700505 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000506 KeyParameterValue::AttestationIdBrand(attestation_id_brand)
507 }
508 Tag::ATTESTATION_ID_DEVICE => {
509 let attestation_id_device: Vec<u8> = data
510 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700511 .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000512 KeyParameterValue::AttestationIdDevice(attestation_id_device)
513 }
514 Tag::ATTESTATION_ID_PRODUCT => {
515 let attestation_id_product: Vec<u8> = data
516 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700517 .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000518 KeyParameterValue::AttestationIdProduct(attestation_id_product)
519 }
520 Tag::ATTESTATION_ID_SERIAL => {
521 let attestation_id_serial: Vec<u8> = data
522 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700523 .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000524 KeyParameterValue::AttestationIdSerial(attestation_id_serial)
525 }
526 Tag::ATTESTATION_ID_IMEI => {
527 let attestation_id_imei: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700528 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000529 KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
530 }
531 Tag::ATTESTATION_ID_MEID => {
532 let attestation_id_meid: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700533 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000534 KeyParameterValue::AttestationIdMEID(attestation_id_meid)
535 }
536 Tag::ATTESTATION_ID_MANUFACTURER => {
537 let attestation_id_manufacturer: Vec<u8> = data
538 .get()
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700539 .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000540 KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
541 }
542 Tag::ATTESTATION_ID_MODEL => {
543 let attestation_id_model: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700544 data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000545 KeyParameterValue::AttestationIdModel(attestation_id_model)
546 }
547 Tag::VENDOR_PATCHLEVEL => {
548 let vendor_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700549 data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000550 KeyParameterValue::VendorPatchLevel(vendor_patch_level)
551 }
552 Tag::BOOT_PATCHLEVEL => {
553 let boot_patch_level: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700554 data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000555 KeyParameterValue::BootPatchLevel(boot_patch_level)
556 }
557 Tag::ASSOCIATED_DATA => {
558 let associated_data: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700559 data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000560 KeyParameterValue::AssociatedData(associated_data)
561 }
562 Tag::NONCE => {
563 let nonce: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700564 data.get().context("Failed to read sql data for tag: NONCE.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000565 KeyParameterValue::Nonce(nonce)
566 }
567 Tag::MAC_LENGTH => {
568 let mac_length: i32 =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700569 data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000570 KeyParameterValue::MacLength(mac_length)
571 }
572 Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
573 Tag::CONFIRMATION_TOKEN => {
574 let confirmation_token: Vec<u8> =
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700575 data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000576 KeyParameterValue::ConfirmationToken(confirmation_token)
577 }
578 _ => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700579 return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
Joel Galenson5c0ec0d2020-09-02 14:24:30 -0700580 .context("Failed to decode Tag enum from value.")?
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000581 }
582 };
583 Ok(KeyParameter::new(key_param_value, security_level_val))
584 }
585}
586
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000587/// Macro rules for converting key parameter to/from wire type.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700588/// This macro takes between three and four different pieces of information about each
589/// of the KeyParameterValue variants:
590/// 1. The KeyParameterValue variant name,
591/// 2. the tag name corresponding to the variant,
592/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
593/// stored when converted, and
594/// 4. an optional enum type name when the nested value is of enum type.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000595/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
596/// the two conversion methods: convert_to_wire() and convert_from_wire().
597/// ## Example
598/// ```
599/// implement_key_parameter_conversion_to_from_wire! {
600/// Invalid, INVALID, na;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700601/// KeyPurpose, PURPOSE, integer, KeyPurpose;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000602/// CallerNonce, CALLER_NONCE, boolValue;
603/// UserSecureID, USER_SECURE_ID, longInteger;
604/// ApplicationID, APPLICATION_ID, blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000605/// }
606/// ```
607/// expands to:
608/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700609/// pub fn convert_to_wire(self) -> KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000610/// match self {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700611/// KeyParameterValue::Invalid => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000612/// tag: Tag::INVALID,
613/// ..Default::default()
614/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700615/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000616/// tag: Tag::PURPOSE,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700617/// integer: v.0,
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000618/// ..Default::default()
619/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700620/// KeyParameterValue::CallerNonce => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000621/// tag: Tag::CALLER_NONCE,
622/// boolValue: true,
623/// ..Default::default()
624/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700625/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000626/// tag: Tag::USER_SECURE_ID,
627/// longInteger: v,
628/// ..Default::default()
629/// },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700630/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000631/// tag: Tag::APPLICATION_ID,
632/// blob: v,
633/// ..Default::default()
634/// },
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000635/// }
636/// }
637/// ```
638/// and
639/// ```
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700640/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000641/// match aidl_kp {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700642/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000643/// tag: Tag::INVALID,
644/// ..
645/// } => KeyParameterValue::Invalid,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700646/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000647/// tag: Tag::PURPOSE,
648/// integer: v,
649/// ..
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700650/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
651/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000652/// tag: Tag::CALLER_NONCE,
653/// boolValue: true,
654/// ..
655/// } => KeyParameterValue::CallerNonce,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700656/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000657/// tag: Tag::USER_SECURE_ID,
658/// longInteger: v,
659/// ..
660/// } => KeyParameterValue::UserSecureID(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700661/// KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000662/// tag: Tag::APPLICATION_ID,
663/// blob: v,
664/// ..
665/// } => KeyParameterValue::ApplicationID(v),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000666/// _ => KeyParameterValue::Invalid,
667/// }
668/// }
669///
670macro_rules! implement_key_parameter_conversion_to_from_wire {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700671 // There are three groups of rules in this macro.
672 // 1. The first group contains the rule which acts as the public interface. It takes the input
673 // given to this macro and prepares it to be given as input to the two groups of rules
674 // mentioned below.
675 // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
676 // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
677 //
678 // Input to this macro is first handled by the first macro rule (belonging to the first
679 // group above), which pre-processes the input such that rules in the other two groups
680 // generate the code for the two methods, when called recursively.
681 // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
682 // four macro rules in the second two groups. These four rules intend to do the following
683 // tasks respectively:
684 // i) generates match arms related to Invalid KeyParameterValue variant.
685 // ii) generates match arms related to boolValue field in KmKeyParameter struct.
686 // iii) generates match arms related to all the other fields in KmKeyParameter struct.
687 // iv) generates the method definition including the match arms generated from the above
688 // three recursive macro rules.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000689
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700690 // This rule is applied on the input given to the macro invocations from outside the macro.
691 ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
692 // pre-processes input to target the rules that generate convert_to_wire() method.
693 implement_key_parameter_conversion_to_from_wire! {@to
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800694 [], $($variant, $tag_name, $field_name;)*
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700695 }
696 // pre-processes input to target the rules that generate convert_from_wire() method.
697 implement_key_parameter_conversion_to_from_wire! {@from
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800698 [], $($variant, $tag_name, $field_name;)*
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700699 }
700 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000701
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700702 // Following four rules (belonging to the aforementioned second group) generate
703 // convert_to_wire() conversion method.
704 // -----------------------------------------------------------------------
705 // This rule handles Invalid variant.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800706 // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700707 // KeyParameterValue::Invalid => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800708 // tag: Tag::INVALID,
709 // value: KmKeyParameterValue::Invalid(0),
710 // },
711 (@to [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700712 implement_key_parameter_conversion_to_from_wire! {@to
713 [$($out)*
714 KeyParameterValue::Invalid => KmKeyParameter {
715 tag: Tag::INVALID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800716 value: KmKeyParameterValue::Invalid(0),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700717 },
718 ], $($in)*
719 }
720 };
721 // This rule handles all variants that correspond to bool values.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800722 // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700723 // a match arm like:
724 // KeyParameterValue::CallerNonce => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800725 // tag: Tag::CALLER_NONCE,
726 // value: KmKeyParameterValue::BoolValue(true),
727 // },
728 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700729 implement_key_parameter_conversion_to_from_wire! {@to
730 [$($out)*
731 KeyParameterValue::$variant => KmKeyParameter {
732 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800733 value: KmKeyParameterValue::BoolValue(true),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700734 },
735 ], $($in)*
736 }
737 };
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700738 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700739 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700740 // KmKeyParameter).
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800741 // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700742 // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800743 // tag: Tag::CONFIRMATION_TOKEN,
744 // value: KmKeyParameterValue::$field(v),
745 // },
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700746 (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
747 implement_key_parameter_conversion_to_from_wire! {@to
748 [$($out)*
749 KeyParameterValue::$variant(v) => KmKeyParameter {
750 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800751 value: KmKeyParameterValue::$field(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700752 },
753 ], $($in)*
754 }
755 };
756 // After all the match arms are generated by the above three rules, this rule combines them
757 // into the convert_to_wire() method.
758 (@to [$($out:tt)*], ) => {
759 /// Conversion of key parameter to wire type
760 pub fn convert_to_wire(self) -> KmKeyParameter {
761 match self {
762 $($out)*
763 }
764 }
765 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000766
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700767 // Following four rules (belonging to the aforementioned third group) generate
768 // convert_from_wire() conversion method.
769 // ------------------------------------------------------------------------
770 // This rule handles Invalid variant.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800771 // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700772 // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800773 (@from [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700774 implement_key_parameter_conversion_to_from_wire! {@from
775 [$($out)*
776 KmKeyParameter {
777 tag: Tag::INVALID,
778 ..
779 } => KeyParameterValue::Invalid,
780 ], $($in)*
781 }
782 };
783 // This rule handles all variants that correspond to bool values.
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800784 // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates a match arm like:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700785 // KmKeyParameter {
786 // tag: Tag::CALLER_NONCE,
787 // boolValue: true,
788 // ..
789 // } => KeyParameterValue::CallerNonce,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800790 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700791 implement_key_parameter_conversion_to_from_wire! {@from
792 [$($out)*
793 KmKeyParameter {
794 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800795 value: KmKeyParameterValue::BoolValue(true),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700796 } => KeyParameterValue::$variant,
797 ], $($in)*
798 }
799 };
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700800 // This rule handles all variants that are neither invalid nor bool values nor enums
Janis Danisevskis85d47932020-10-23 16:12:59 -0700801 // (i.e. all variants which correspond to integer, longInteger, and blob fields in
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700802 // KmKeyParameter).
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800803 // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700804 // like:
805 // KmKeyParameter {
806 // tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800807 // value: KmKeyParameterValue::Blob(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700808 // } => KeyParameterValue::ConfirmationToken(v),
809 (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
810 implement_key_parameter_conversion_to_from_wire! {@from
811 [$($out)*
812 KmKeyParameter {
813 tag: Tag::$tag_val,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800814 value: KmKeyParameterValue::$field(v),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700815 } => KeyParameterValue::$variant(v),
816 ], $($in)*
817 }
818 };
819 // After all the match arms are generated by the above three rules, this rule combines them
820 // into the convert_from_wire() method.
821 (@from [$($out:tt)*], ) => {
822 /// Conversion of key parameter from wire type
823 pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
824 match aidl_kp {
825 $($out)*
826 _ => KeyParameterValue::Invalid,
827 }
828 }
829 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000830}
831
832impl KeyParameterValue {
833 // Invoke the macro that generates the code for key parameter conversion to/from wire type
834 // with all possible variants of KeyParameterValue. Each line corresponding to a variant
835 // contains: variant identifier, tag value, and the related field name (i.e.
Janis Danisevskis85d47932020-10-23 16:12:59 -0700836 // boolValue/integer/longInteger/blob) in the KmKeyParameter.
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000837 implement_key_parameter_conversion_to_from_wire! {
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800838 Invalid, INVALID, Invalid;
839 KeyPurpose, PURPOSE, KeyPurpose;
840 Algorithm, ALGORITHM, Algorithm;
841 KeySize, KEY_SIZE, Integer;
842 BlockMode, BLOCK_MODE, BlockMode;
843 Digest, DIGEST, Digest;
844 PaddingMode, PADDING, PaddingMode;
845 CallerNonce, CALLER_NONCE, BoolValue;
846 MinMacLength, MIN_MAC_LENGTH, Integer;
847 EcCurve, EC_CURVE, EcCurve;
848 RSAPublicExponent, RSA_PUBLIC_EXPONENT, LongInteger;
849 IncludeUniqueID, INCLUDE_UNIQUE_ID, BoolValue;
850 BootLoaderOnly, BOOTLOADER_ONLY, BoolValue;
851 RollbackResistance, ROLLBACK_RESISTANCE, BoolValue;
852 ActiveDateTime, ACTIVE_DATETIME, DateTime;
853 OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, DateTime;
854 UsageExpireDateTime, USAGE_EXPIRE_DATETIME, DateTime;
855 MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, Integer;
856 MaxUsesPerBoot, MAX_USES_PER_BOOT, Integer;
857 UserID, USER_ID, Integer;
858 UserSecureID, USER_SECURE_ID, LongInteger;
859 NoAuthRequired, NO_AUTH_REQUIRED, BoolValue;
860 HardwareAuthenticatorType, USER_AUTH_TYPE, HardwareAuthenticatorType;
861 AuthTimeout, AUTH_TIMEOUT, Integer;
862 AllowWhileOnBody, ALLOW_WHILE_ON_BODY, BoolValue;
863 TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, BoolValue;
864 TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, BoolValue;
865 UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, BoolValue;
866 ApplicationID, APPLICATION_ID, Blob;
867 ApplicationData, APPLICATION_DATA, Blob;
868 CreationDateTime, CREATION_DATETIME, DateTime;
869 KeyOrigin, ORIGIN, Origin;
870 RootOfTrust, ROOT_OF_TRUST, Blob;
871 OSVersion, OS_VERSION, Integer;
872 OSPatchLevel, OS_PATCHLEVEL, Integer;
873 UniqueID, UNIQUE_ID, Blob;
874 AttestationChallenge, ATTESTATION_CHALLENGE, Blob;
875 AttestationApplicationID, ATTESTATION_APPLICATION_ID, Blob;
876 AttestationIdBrand, ATTESTATION_ID_BRAND, Blob;
877 AttestationIdDevice, ATTESTATION_ID_DEVICE, Blob;
878 AttestationIdProduct, ATTESTATION_ID_PRODUCT, Blob;
879 AttestationIdSerial, ATTESTATION_ID_SERIAL, Blob;
880 AttestationIdIMEI, ATTESTATION_ID_IMEI, Blob;
881 AttestationIdMEID, ATTESTATION_ID_MEID, Blob;
882 AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, Blob;
883 AttestationIdModel, ATTESTATION_ID_MODEL, Blob;
884 VendorPatchLevel, VENDOR_PATCHLEVEL, Integer;
885 BootPatchLevel, BOOT_PATCHLEVEL, Integer;
886 AssociatedData, ASSOCIATED_DATA, Blob;
887 Nonce, NONCE, Blob;
888 MacLength, MAC_LENGTH, Integer;
889 ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, BoolValue;
890 ConfirmationToken, CONFIRMATION_TOKEN, Blob;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +0000891 }
892}
893
894#[cfg(test)]
895mod basic_tests {
896 use crate::key_parameter::*;
897
898 // Test basic functionality of KeyParameter.
899 #[test]
900 fn test_key_parameter() {
901 let key_parameter = KeyParameter::new(
902 KeyParameterValue::Algorithm(Algorithm::RSA),
903 SecurityLevel::STRONGBOX,
904 );
905
906 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
907
908 assert_eq!(
909 *key_parameter.key_parameter_value(),
910 KeyParameterValue::Algorithm(Algorithm::RSA)
911 );
912
913 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
914 }
915}
916
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000917/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
918/// data types and then tests 'to_sql' method for KeyParameters of those
919/// different data types. The five different data types for KeyParameter values are:
920/// i) enums of u32
921/// ii) u32
922/// iii) u64
923/// iv) Vec<u8>
924/// v) bool
925#[cfg(test)]
926mod storage_tests {
927 use crate::error::*;
928 use crate::key_parameter::*;
929 use anyhow::Result;
930 use rusqlite::types::ToSql;
931 use rusqlite::{params, Connection, NO_PARAMS};
932
933 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
934 /// from a database table row.
935 #[test]
936 fn test_new_from_sql_enum_i32() -> Result<()> {
937 let db = init_db()?;
938 insert_into_keyparameter(
939 &db,
940 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700941 Tag::ALGORITHM.0,
942 &Algorithm::RSA.0,
943 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000944 )?;
945 let key_param = query_from_keyparameter(&db)?;
946 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
947 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
948 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
949 Ok(())
950 }
951
952 /// Test initializing a KeyParameter (with key parameter value which is of i32)
953 /// from a database table row.
954 #[test]
955 fn test_new_from_sql_i32() -> Result<()> {
956 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700957 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000958 let key_param = query_from_keyparameter(&db)?;
959 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
960 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
961 Ok(())
962 }
963
964 /// Test initializing a KeyParameter (with key parameter value which is of i64)
965 /// from a database table row.
966 #[test]
967 fn test_new_from_sql_i64() -> Result<()> {
968 let db = init_db()?;
969 // max value for i64, just to test corner cases
970 insert_into_keyparameter(
971 &db,
972 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700973 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000974 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700975 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000976 )?;
977 let key_param = query_from_keyparameter(&db)?;
978 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
979 assert_eq!(
980 *key_param.key_parameter_value(),
981 KeyParameterValue::RSAPublicExponent(i64::MAX)
982 );
983 Ok(())
984 }
985
986 /// Test initializing a KeyParameter (with key parameter value which is of bool)
987 /// from a database table row.
988 #[test]
989 fn test_new_from_sql_bool() -> Result<()> {
990 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700991 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000992 let key_param = query_from_keyparameter(&db)?;
993 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
994 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
995 Ok(())
996 }
997
998 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
999 /// from a database table row.
1000 #[test]
1001 fn test_new_from_sql_vec_u8() -> Result<()> {
1002 let db = init_db()?;
1003 let app_id = String::from("MyAppID");
1004 let app_id_bytes = app_id.into_bytes();
1005 insert_into_keyparameter(
1006 &db,
1007 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001008 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001009 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001010 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001011 )?;
1012 let key_param = query_from_keyparameter(&db)?;
1013 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1014 assert_eq!(
1015 *key_param.key_parameter_value(),
1016 KeyParameterValue::ApplicationID(app_id_bytes)
1017 );
1018 Ok(())
1019 }
1020
1021 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1022 /// in the database
1023 #[test]
1024 fn test_to_sql_enum_i32() -> Result<()> {
1025 let db = init_db()?;
1026 let kp = KeyParameter::new(
1027 KeyParameterValue::Algorithm(Algorithm::RSA),
1028 SecurityLevel::STRONGBOX,
1029 );
1030 store_keyparameter(&db, 1, &kp)?;
1031 let key_param = query_from_keyparameter(&db)?;
1032 assert_eq!(kp.get_tag(), key_param.get_tag());
1033 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1034 assert_eq!(kp.security_level(), key_param.security_level());
1035 Ok(())
1036 }
1037
1038 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1039 #[test]
1040 fn test_to_sql_i32() -> Result<()> {
1041 let db = init_db()?;
1042 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1043 store_keyparameter(&db, 1, &kp)?;
1044 let key_param = query_from_keyparameter(&db)?;
1045 assert_eq!(kp.get_tag(), key_param.get_tag());
1046 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1047 assert_eq!(kp.security_level(), key_param.security_level());
1048 Ok(())
1049 }
1050
1051 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1052 #[test]
1053 fn test_to_sql_i64() -> Result<()> {
1054 let db = init_db()?;
1055 // max value for i64, just to test corner cases
1056 let kp = KeyParameter::new(
1057 KeyParameterValue::RSAPublicExponent(i64::MAX),
1058 SecurityLevel::STRONGBOX,
1059 );
1060 store_keyparameter(&db, 1, &kp)?;
1061 let key_param = query_from_keyparameter(&db)?;
1062 assert_eq!(kp.get_tag(), key_param.get_tag());
1063 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1064 assert_eq!(kp.security_level(), key_param.security_level());
1065 Ok(())
1066 }
1067
1068 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1069 #[test]
1070 fn test_to_sql_vec_u8() -> Result<()> {
1071 let db = init_db()?;
1072 let kp = KeyParameter::new(
1073 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1074 SecurityLevel::STRONGBOX,
1075 );
1076 store_keyparameter(&db, 1, &kp)?;
1077 let key_param = query_from_keyparameter(&db)?;
1078 assert_eq!(kp.get_tag(), key_param.get_tag());
1079 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1080 assert_eq!(kp.security_level(), key_param.security_level());
1081 Ok(())
1082 }
1083
1084 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1085 #[test]
1086 fn test_to_sql_bool() -> Result<()> {
1087 let db = init_db()?;
1088 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1089 store_keyparameter(&db, 1, &kp)?;
1090 let key_param = query_from_keyparameter(&db)?;
1091 assert_eq!(kp.get_tag(), key_param.get_tag());
1092 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1093 assert_eq!(kp.security_level(), key_param.security_level());
1094 Ok(())
1095 }
1096
1097 #[test]
1098 /// Test Tag::Invalid
1099 fn test_invalid_tag() -> Result<()> {
1100 let db = init_db()?;
1101 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1102 let key_param = query_from_keyparameter(&db)?;
1103 assert_eq!(Tag::INVALID, key_param.get_tag());
1104 Ok(())
1105 }
1106
1107 #[test]
1108 fn test_non_existing_enum_variant() -> Result<()> {
1109 let db = init_db()?;
1110 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
1111 tests::check_result_contains_error_string(
1112 query_from_keyparameter(&db),
1113 "Failed to decode Tag enum from value.",
1114 );
1115 Ok(())
1116 }
1117
1118 #[test]
1119 fn test_invalid_conversion_from_sql() -> Result<()> {
1120 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001121 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001122 tests::check_result_contains_error_string(
1123 query_from_keyparameter(&db),
1124 "Failed to read sql data for tag: ALGORITHM.",
1125 );
1126 Ok(())
1127 }
1128
1129 /// Helper method to init database table for key parameter
1130 fn init_db() -> Result<Connection> {
1131 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1132 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1133 .context("Failed to attach databases.")?;
1134 db.execute(
1135 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1136 keyentryid INTEGER,
1137 tag INTEGER,
1138 data ANY,
1139 security_level INTEGER);",
1140 NO_PARAMS,
1141 )
1142 .context("Failed to initialize \"keyparameter\" table.")?;
1143 Ok(db)
1144 }
1145
1146 /// Helper method to insert an entry into key parameter table, with individual parameters
1147 fn insert_into_keyparameter<T: ToSql>(
1148 db: &Connection,
1149 key_id: i64,
1150 tag: i32,
1151 value: &T,
1152 security_level: i32,
1153 ) -> Result<()> {
1154 db.execute(
1155 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001156 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001157 params![key_id, tag, *value, security_level],
1158 )?;
1159 Ok(())
1160 }
1161
1162 /// Helper method to store a key parameter instance.
1163 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1164 db.execute(
1165 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001166 VALUES(?, ?, ?, ?);",
1167 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001168 )?;
1169 Ok(())
1170 }
1171
1172 /// Helper method to query a row from keyparameter table
1173 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001174 let mut stmt =
1175 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001176 let mut rows = stmt.query(NO_PARAMS)?;
1177 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001178 Ok(KeyParameter::new_from_sql(
1179 Tag(row.get(0)?),
Janis Danisevskis4522c2b2020-11-27 18:04:58 -08001180 &SqlField::new(1, row),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001181 SecurityLevel(row.get(2)?),
1182 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001183 }
1184}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001185
1186/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001187/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001188/// key parameter.
1189/// i) bool
1190/// ii) integer
1191/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001192/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001193#[cfg(test)]
1194mod wire_tests {
1195 use crate::key_parameter::*;
1196 /// unit tests for to conversions
1197 #[test]
1198 fn test_convert_to_wire_invalid() {
1199 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
1200 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1201 assert_eq!(Tag::INVALID, actual.tag);
1202 }
1203 #[test]
1204 fn test_convert_to_wire_bool() {
1205 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1206 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1207 assert_eq!(Tag::CALLER_NONCE, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001208 assert_eq!(KmKeyParameterValue::BoolValue(true), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001209 }
1210 #[test]
1211 fn test_convert_to_wire_integer() {
1212 let kp = KeyParameter::new(
1213 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1214 SecurityLevel::STRONGBOX,
1215 );
1216 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1217 assert_eq!(Tag::PURPOSE, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001218 assert_eq!(KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001219 }
1220 #[test]
1221 fn test_convert_to_wire_long_integer() {
1222 let kp =
1223 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
1224 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1225 assert_eq!(Tag::USER_SECURE_ID, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001226 assert_eq!(KmKeyParameterValue::LongInteger(i64::MAX), actual.value);
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001227 }
1228 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001229 fn test_convert_to_wire_blob() {
1230 let kp = KeyParameter::new(
1231 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1232 SecurityLevel::STRONGBOX,
1233 );
1234 let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
1235 assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001236 assert_eq!(
1237 KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
1238 actual.value
1239 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001240 }
1241
1242 /// unit tests for from conversion
1243 #[test]
1244 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001245 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001246 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1247 assert_eq!(KeyParameterValue::Invalid, actual);
1248 }
1249 #[test]
1250 fn test_convert_from_wire_bool() {
1251 let aidl_kp =
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001252 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001253 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1254 assert_eq!(KeyParameterValue::CallerNonce, actual);
1255 }
1256 #[test]
1257 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001258 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001259 tag: Tag::PURPOSE,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001260 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001261 };
1262 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1263 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
1264 }
1265 #[test]
1266 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001267 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001268 tag: Tag::USER_SECURE_ID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001269 value: KmKeyParameterValue::LongInteger(i64::MAX),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001270 };
1271 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1272 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
1273 }
1274 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001275 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001276 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001277 tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001278 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001279 };
1280 let actual = KeyParameterValue::convert_from_wire(aidl_kp);
1281 assert_eq!(
1282 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1283 actual
1284 );
1285 }
1286}