1 // Copyright 2022, 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 use crate::keymint::{
16     AttestationKey, HardwareAuthToken, KeyCharacteristics, KeyCreationResult, KeyFormat,
17     KeyMintHardwareInfo, KeyParam, KeyPurpose,
18 };
19 use crate::rpc;
20 use crate::secureclock::TimeStampToken;
21 use crate::sharedsecret::SharedSecretParameters;
22 use crate::{cbor, cbor_type_error, vec_try, AsCborValue, CborError};
23 use alloc::{
24     format,
25     string::{String, ToString},
26     vec::Vec,
27 };
28 use enumn::N;
29 use kmr_derive::AsCborValue;
30 
31 /// Key size in bits.
32 #[repr(transparent)]
33 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsCborValue)]
34 pub struct KeySizeInBits(pub u32);
35 
36 /// RSA exponent.
37 #[repr(transparent)]
38 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsCborValue)]
39 pub struct RsaExponent(pub u64);
40 
41 /// Default maximum supported size for CBOR-serialized messages.
42 pub const DEFAULT_MAX_SIZE: usize = 4096;
43 
44 /// Marker type indicating failure to convert into a wire type.  For `enum` wire types, the variant
45 /// names match the `enum` whose value failed to convert.
46 #[derive(Debug)]
47 pub enum ValueNotRecognized {
48     // Enum type names.
49     KeyPurpose,
50     Algorithm,
51     BlockMode,
52     Digest,
53     PaddingMode,
54     EcCurve,
55     ErrorCode,
56     HardwareAuthenticatorType,
57     KeyFormat,
58     KeyOrigin,
59     SecurityLevel,
60     Tag,
61     TagType,
62     KmVersion,
63     EekCurve,
64     Origin,
65     // Non-enum types.
66     Bool,
67     Blob,
68     DateTime,
69     Integer,
70     LongInteger,
71 }
72 
73 /// Trait that associates an enum value of the specified type with a type.
74 /// Values of the `enum` type `T` are used to identify particular message types.
75 /// A message type implements `Code<T>` to indicate which `enum` value it is
76 /// associated with.
77 ///
78 /// For example, an `enum WhichMsg { Hello, Goodbye }` could be used to distinguish
79 /// between `struct HelloMsg` and `struct GoodbyeMsg` instances, in which case the
80 /// latter types would both implement `Code<WhichMsg>` with `CODE` values of
81 /// `WhichMsg::Hello` and `WhichMsg::Goodbye` respectively.
82 pub trait Code<T> {
83     /// The enum value identifying this request/response.
84     const CODE: T;
85     /// Return the enum value associated with the underlying type of this item.
code(&self) -> T86     fn code(&self) -> T {
87         Self::CODE
88     }
89 }
90 
91 /// Internal equivalent of the `keymint::BeginResult` type; instead of the Binder object reference
92 /// there is an opaque `op_handle` value that the bottom half implementation uses to identify the
93 /// in-progress operation.  This field is included as an extra parameter in all of the per-operation
94 /// ...Request types.
95 #[derive(Debug, Default, AsCborValue)]
96 pub struct InternalBeginResult {
97     pub challenge: i64,
98     pub params: Vec<KeyParam>,
99     // Extra for internal use: returned by bottom half of KeyMint implementation, used on
100     // all subsequent operation methods to identify the operation.
101     pub op_handle: i64,
102 }
103 
104 // The following types encapsulate the arguments to each method into a corresponding ..Request
105 // struct, and the return value and out parameters into a corresponding ..Response struct.
106 // These are currently hand-generated, but they could be auto-generated from the AIDL spec.
107 
108 // IKeyMintDevice methods.
109 #[derive(Debug, AsCborValue)]
110 pub struct GetHardwareInfoRequest {}
111 #[derive(Debug, AsCborValue)]
112 pub struct GetHardwareInfoResponse {
113     pub ret: KeyMintHardwareInfo,
114 }
115 #[derive(Debug, AsCborValue)]
116 pub struct AddRngEntropyRequest {
117     pub data: Vec<u8>,
118 }
119 #[derive(Debug, AsCborValue)]
120 pub struct AddRngEntropyResponse {}
121 #[derive(Debug, AsCborValue)]
122 pub struct GenerateKeyRequest {
123     pub key_params: Vec<KeyParam>,
124     pub attestation_key: Option<AttestationKey>,
125 }
126 #[derive(Debug, AsCborValue)]
127 pub struct GenerateKeyResponse {
128     pub ret: KeyCreationResult,
129 }
130 #[derive(AsCborValue)]
131 pub struct ImportKeyRequest {
132     pub key_params: Vec<KeyParam>,
133     pub key_format: KeyFormat,
134     pub key_data: Vec<u8>,
135     pub attestation_key: Option<AttestationKey>,
136 }
137 #[derive(Debug, AsCborValue)]
138 pub struct ImportKeyResponse {
139     pub ret: KeyCreationResult,
140 }
141 #[derive(AsCborValue)]
142 pub struct ImportWrappedKeyRequest {
143     pub wrapped_key_data: Vec<u8>,
144     pub wrapping_key_blob: Vec<u8>,
145     pub masking_key: Vec<u8>,
146     pub unwrapping_params: Vec<KeyParam>,
147     pub password_sid: i64,
148     pub biometric_sid: i64,
149 }
150 #[derive(Debug, AsCborValue)]
151 pub struct ImportWrappedKeyResponse {
152     pub ret: KeyCreationResult,
153 }
154 #[derive(Debug, AsCborValue)]
155 pub struct UpgradeKeyRequest {
156     pub key_blob_to_upgrade: Vec<u8>,
157     pub upgrade_params: Vec<KeyParam>,
158 }
159 #[derive(Debug, AsCborValue)]
160 pub struct UpgradeKeyResponse {
161     pub ret: Vec<u8>,
162 }
163 #[derive(Debug, AsCborValue)]
164 pub struct DeleteKeyRequest {
165     pub key_blob: Vec<u8>,
166 }
167 #[derive(Debug, AsCborValue)]
168 pub struct DeleteKeyResponse {}
169 #[derive(Debug, AsCborValue)]
170 pub struct DeleteAllKeysRequest {}
171 #[derive(Debug, AsCborValue)]
172 pub struct DeleteAllKeysResponse {}
173 #[derive(Debug, AsCborValue)]
174 pub struct DestroyAttestationIdsRequest {}
175 #[derive(Debug, AsCborValue)]
176 pub struct DestroyAttestationIdsResponse {}
177 #[derive(Debug, AsCborValue)]
178 pub struct BeginRequest {
179     pub purpose: KeyPurpose,
180     pub key_blob: Vec<u8>,
181     pub params: Vec<KeyParam>,
182     pub auth_token: Option<HardwareAuthToken>,
183 }
184 #[derive(Debug, AsCborValue)]
185 pub struct BeginResponse {
186     pub ret: InternalBeginResult, // special case: no Binder ref here
187 }
188 #[derive(Debug, AsCborValue)]
189 pub struct EarlyBootEndedRequest {}
190 #[derive(Debug, AsCborValue)]
191 pub struct EarlyBootEndedResponse {}
192 #[derive(Debug, AsCborValue)]
193 pub struct ConvertStorageKeyToEphemeralRequest {
194     pub storage_key_blob: Vec<u8>,
195 }
196 #[derive(Debug, AsCborValue)]
197 pub struct ConvertStorageKeyToEphemeralResponse {
198     pub ret: Vec<u8>,
199 }
200 #[derive(Debug, AsCborValue)]
201 pub struct GetKeyCharacteristicsRequest {
202     pub key_blob: Vec<u8>,
203     pub app_id: Vec<u8>,
204     pub app_data: Vec<u8>,
205 }
206 #[derive(Debug, AsCborValue)]
207 pub struct GetKeyCharacteristicsResponse {
208     pub ret: Vec<KeyCharacteristics>,
209 }
210 
211 #[derive(Debug, AsCborValue)]
212 pub struct GetRootOfTrustChallengeRequest {}
213 
214 #[derive(Debug, AsCborValue)]
215 pub struct GetRootOfTrustChallengeResponse {
216     pub ret: [u8; 16],
217 }
218 
219 #[derive(Debug, AsCborValue)]
220 pub struct GetRootOfTrustRequest {
221     pub challenge: [u8; 16],
222 }
223 #[derive(Debug, AsCborValue)]
224 pub struct GetRootOfTrustResponse {
225     pub ret: Vec<u8>,
226 }
227 
228 #[derive(Debug, AsCborValue)]
229 pub struct SendRootOfTrustRequest {
230     pub root_of_trust: Vec<u8>,
231 }
232 
233 #[derive(Debug, AsCborValue)]
234 pub struct SendRootOfTrustResponse {}
235 
236 // IKeyMintOperation methods.  These ...Request structures include an extra `op_handle` field whose
237 // value was returned in the `InternalBeginResult` type and which identifies the operation in
238 // progress.
239 //
240 // `Debug` deliberately not derived to reduce the chances of inadvertent leakage of private info.
241 #[derive(Clone, AsCborValue)]
242 pub struct UpdateAadRequest {
243     pub op_handle: i64, // Extra for internal use, from `InternalBeginResult`.
244     pub input: Vec<u8>,
245     pub auth_token: Option<HardwareAuthToken>,
246     pub timestamp_token: Option<TimeStampToken>,
247 }
248 #[derive(AsCborValue)]
249 pub struct UpdateAadResponse {}
250 #[derive(Clone, AsCborValue)]
251 pub struct UpdateRequest {
252     pub op_handle: i64, // Extra for internal use, from `InternalBeginResult`.
253     pub input: Vec<u8>,
254     pub auth_token: Option<HardwareAuthToken>,
255     pub timestamp_token: Option<TimeStampToken>,
256 }
257 #[derive(AsCborValue)]
258 pub struct UpdateResponse {
259     pub ret: Vec<u8>,
260 }
261 #[derive(AsCborValue)]
262 pub struct FinishRequest {
263     pub op_handle: i64, // Extra for internal use, from `InternalBeginResult`.
264     pub input: Option<Vec<u8>>,
265     pub signature: Option<Vec<u8>>,
266     pub auth_token: Option<HardwareAuthToken>,
267     pub timestamp_token: Option<TimeStampToken>,
268     pub confirmation_token: Option<Vec<u8>>,
269 }
270 #[derive(AsCborValue)]
271 pub struct FinishResponse {
272     pub ret: Vec<u8>,
273 }
274 #[derive(Debug, AsCborValue)]
275 pub struct AbortRequest {
276     pub op_handle: i64, // Extra for internal use, from `InternalBeginResult`.
277 }
278 #[derive(Debug, AsCborValue)]
279 pub struct AbortResponse {}
280 
281 // IRemotelyProvisionedComponent methods.
282 
283 #[derive(Debug, AsCborValue)]
284 pub struct GetRpcHardwareInfoRequest {}
285 #[derive(Debug, AsCborValue)]
286 pub struct GetRpcHardwareInfoResponse {
287     pub ret: rpc::HardwareInfo,
288 }
289 #[derive(Debug, AsCborValue)]
290 pub struct GenerateEcdsaP256KeyPairRequest {
291     pub test_mode: bool,
292 }
293 #[derive(Debug, AsCborValue)]
294 pub struct GenerateEcdsaP256KeyPairResponse {
295     pub maced_public_key: rpc::MacedPublicKey,
296     pub ret: Vec<u8>,
297 }
298 #[derive(Debug, AsCborValue)]
299 pub struct GenerateCertificateRequestRequest {
300     pub test_mode: bool,
301     pub keys_to_sign: Vec<rpc::MacedPublicKey>,
302     pub endpoint_encryption_cert_chain: Vec<u8>,
303     pub challenge: Vec<u8>,
304 }
305 #[derive(Debug, AsCborValue)]
306 pub struct GenerateCertificateRequestResponse {
307     pub device_info: rpc::DeviceInfo,
308     pub protected_data: rpc::ProtectedData,
309     pub ret: Vec<u8>,
310 }
311 #[derive(Debug, AsCborValue)]
312 pub struct GenerateCertificateRequestV2Request {
313     pub keys_to_sign: Vec<rpc::MacedPublicKey>,
314     pub challenge: Vec<u8>,
315 }
316 #[derive(Debug, AsCborValue)]
317 pub struct GenerateCertificateRequestV2Response {
318     pub ret: Vec<u8>,
319 }
320 
321 // ISharedSecret methods.
322 #[derive(Debug, AsCborValue)]
323 pub struct GetSharedSecretParametersRequest {}
324 #[derive(Debug, AsCborValue)]
325 pub struct GetSharedSecretParametersResponse {
326     pub ret: SharedSecretParameters,
327 }
328 #[derive(Debug, AsCborValue)]
329 pub struct ComputeSharedSecretRequest {
330     pub params: Vec<SharedSecretParameters>,
331 }
332 #[derive(Debug, AsCborValue)]
333 pub struct ComputeSharedSecretResponse {
334     pub ret: Vec<u8>,
335 }
336 
337 // ISecureClock methods.
338 #[derive(Debug, AsCborValue)]
339 pub struct GenerateTimeStampRequest {
340     pub challenge: i64,
341 }
342 #[derive(Debug, AsCborValue)]
343 pub struct GenerateTimeStampResponse {
344     pub ret: TimeStampToken,
345 }
346 
347 // The following messages have no equivalent on a HAL interface, but are used internally
348 // between components.
349 
350 // HAL->TA at start of day.
351 #[derive(Debug, PartialEq, Eq, AsCborValue)]
352 pub struct SetHalInfoRequest {
353     pub os_version: u32,
354     pub os_patchlevel: u32,     // YYYYMM format
355     pub vendor_patchlevel: u32, // YYYYMMDD format
356 }
357 #[derive(Debug, AsCborValue)]
358 pub struct SetHalInfoResponse {}
359 
360 // HAL->TA at start of day.
361 #[derive(Debug, PartialEq, Eq, AsCborValue)]
362 pub struct SetHalVersionRequest {
363     pub aidl_version: u32,
364 }
365 #[derive(Debug, AsCborValue)]
366 pub struct SetHalVersionResponse {}
367 
368 // Boot loader->TA at start of day.
369 #[derive(Debug, AsCborValue)]
370 pub struct SetBootInfoRequest {
371     pub verified_boot_key: Vec<u8>,
372     pub device_boot_locked: bool,
373     pub verified_boot_state: i32,
374     pub verified_boot_hash: Vec<u8>,
375     pub boot_patchlevel: u32, // YYYYMMDD format
376 }
377 #[derive(Debug, AsCborValue)]
378 pub struct SetBootInfoResponse {}
379 
380 /// Attestation ID information.
381 #[derive(Clone, Debug, AsCborValue, PartialEq, Eq, Default)]
382 pub struct AttestationIdInfo {
383     // The following fields are byte vectors that typically hold UTF-8 string data.
384     pub brand: Vec<u8>,
385     pub device: Vec<u8>,
386     pub product: Vec<u8>,
387     pub serial: Vec<u8>,
388     pub imei: Vec<u8>,
389     pub imei2: Vec<u8>,
390     pub meid: Vec<u8>,
391     pub manufacturer: Vec<u8>,
392     pub model: Vec<u8>,
393 }
394 
395 // Provisioner->TA at device provisioning time.
396 #[derive(Debug, AsCborValue)]
397 pub struct SetAttestationIdsRequest {
398     pub ids: AttestationIdInfo,
399 }
400 #[derive(Debug, AsCborValue)]
401 pub struct SetAttestationIdsResponse {}
402 
403 // Result of an operation, as an error code and a response message (only present when
404 // `error_code` is zero).
405 #[derive(AsCborValue)]
406 pub struct PerformOpResponse {
407     pub error_code: i32,
408     pub rsp: Option<PerformOpRsp>,
409 }
410 
411 /// Declare a collection of related enums for a code and a pair of types.
412 ///
413 /// An invocation like:
414 /// ```ignore
415 /// declare_req_rsp_enums! { KeyMintOperation  => (PerformOpReq, PerformOpRsp) {
416 ///     DeviceGetHardwareInfo = 0x11 => (GetHardwareInfoRequest, GetHardwareInfoResponse),
417 ///     DeviceAddRngEntropy = 0x12 =>   (AddRngEntropyRequest, AddRngEntropyResponse),
418 /// } }
419 /// ```
420 /// will emit three `enum` types all of whose variant names are the same (taken from the leftmost
421 /// column), but whose contents are:
422 ///
423 /// - the numeric values (second column)
424 ///   ```ignore
425 ///   #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
426 ///   enum KeyMintOperation {
427 ///       DeviceGetHardwareInfo = 0x11,
428 ///       DeviceAddRngEntropy = 0x12,
429 ///   }
430 ///   ```
431 ///
432 /// - the types from the third column:
433 ///   ```ignore
434 ///   #[derive(Debug)]
435 ///   enum PerformOpReq {
436 ///       DeviceGetHardwareInfo(GetHardwareInfoRequest),
437 ///       DeviceAddRngEntropy(AddRngEntropyRequest),
438 ///   }
439 ///   ```
440 ///
441 /// - the types from the fourth column:
442 ///   ```ignore
443 ///   #[derive(Debug)]
444 ///   enum PerformOpRsp {
445 ///       DeviceGetHardwareInfo(GetHardwareInfoResponse),
446 ///       DeviceAddRngEntropy(AddRngEntropyResponse),
447 ///   }
448 //   ```
449 ///
450 /// Each of these enum types will also get an implementation of [`AsCborValue`]
451 macro_rules! declare_req_rsp_enums {
452     {
453         $cenum:ident => ($reqenum:ident, $rspenum:ident)
454         {
455             $( $cname:ident = $cvalue:expr => ($reqtyp:ty, $rsptyp:ty) , )*
456         }
457     } => {
458         declare_req_rsp_enums! { $cenum => ($reqenum, $rspenum)
459                                  ( concat!("&(\n",
460                                            $( "    [", stringify!($cname), ", {}],\n", )*
461                                            ")") )
462           {
463             $( $cname = $cvalue => ($reqtyp, $rsptyp), )*
464         } }
465     };
466     {
467         $cenum:ident => ($reqenum:ident, $rspenum:ident) ( $cddlfmt:expr )
468         {
469             $( $cname:ident = $cvalue:expr => ($reqtyp:ty, $rsptyp:ty) , )*
470         }
471     } => {
472 
473         #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, N)]
474         pub enum $cenum {
475             $( $cname = $cvalue, )*
476         }
477 
478         impl AsCborValue for $cenum {
479             /// Create an instance of the enum from a [`cbor::value::Value`], checking that the
480             /// value is valid.
481             fn from_cbor_value(value: $crate::cbor::value::Value) ->
482                 Result<Self, crate::CborError> {
483                 use core::convert::TryInto;
484                 // First get the int value as an `i32`.
485                 let v: i32 = match value {
486                     $crate::cbor::value::Value::Integer(i) => i.try_into().map_err(|_| {
487                         crate::CborError::OutOfRangeIntegerValue
488                     })?,
489                     v => return crate::cbor_type_error(&v, &"int"),
490                 };
491                 // Now check it is one of the defined enum values.
492                 Self::n(v).ok_or(crate::CborError::NonEnumValue)
493             }
494             /// Convert the enum value to a [`cbor::value::Value`] (without checking that the
495             /// contained enum value is valid).
496             fn to_cbor_value(self) -> Result<$crate::cbor::value::Value, crate::CborError> {
497                 Ok($crate::cbor::value::Value::Integer((self as i64).into()))
498             }
499             fn cddl_typename() -> Option<alloc::string::String> {
500                 use alloc::string::ToString;
501                 Some(stringify!($cenum).to_string())
502             }
503             fn cddl_schema() -> Option<alloc::string::String> {
504                 use alloc::string::ToString;
505                 Some( concat!("&(\n",
506                               $( "    ", stringify!($cname), ": ", stringify!($cvalue), ",\n", )*
507                               ")").to_string() )
508             }
509         }
510 
511         pub enum $reqenum {
512             $( $cname($reqtyp), )*
513         }
514 
515         impl $reqenum {
516             pub fn code(&self) -> $cenum {
517                 match self {
518                     $( Self::$cname(_) => $cenum::$cname, )*
519                 }
520             }
521         }
522 
523         pub enum $rspenum {
524             $( $cname($rsptyp), )*
525         }
526 
527         impl AsCborValue for $reqenum {
528             fn from_cbor_value(value: cbor::value::Value) -> Result<Self, CborError> {
529                 let mut a = match value {
530                     cbor::value::Value::Array(a) => a,
531                     _ => return crate::cbor_type_error(&value, "arr"),
532                 };
533                 if a.len() != 2 {
534                     return Err(CborError::UnexpectedItem("arr", "arr len 2"));
535                 }
536                 let ret_val = a.remove(1);
537                 let ret_type = <$cenum>::from_cbor_value(a.remove(0))?;
538                 match ret_type {
539                     $( $cenum::$cname => Ok(Self::$cname(<$reqtyp>::from_cbor_value(ret_val)?)), )*
540                 }
541             }
542             fn to_cbor_value(self) -> Result<cbor::value::Value, CborError> {
543                 Ok(cbor::value::Value::Array(match self {
544                     $( Self::$cname(val) => {
545                         vec_try![
546                             $cenum::$cname.to_cbor_value()?,
547                             val.to_cbor_value()?
548                         ]?
549                     }, )*
550                 }))
551             }
552 
553             fn cddl_typename() -> Option<String> {
554                 use alloc::string::ToString;
555                 Some(stringify!($reqenum).to_string())
556             }
557 
558             fn cddl_schema() -> Option<String> {
559                 Some(format!($cddlfmt,
560                              $( <$reqtyp>::cddl_ref(), )*
561                 ))
562             }
563         }
564 
565         impl AsCborValue for $rspenum {
566             fn from_cbor_value(value: cbor::value::Value) -> Result<Self, CborError> {
567                 let mut a = match value {
568                     cbor::value::Value::Array(a) => a,
569                     _ => return crate::cbor_type_error(&value, "arr"),
570                 };
571                 if a.len() != 2 {
572                     return Err(CborError::UnexpectedItem("arr", "arr len 2"));
573                 }
574                 let ret_val = a.remove(1);
575                 let ret_type = <$cenum>::from_cbor_value(a.remove(0))?;
576                 match ret_type {
577                     $( $cenum::$cname => Ok(Self::$cname(<$rsptyp>::from_cbor_value(ret_val)?)), )*
578                 }
579             }
580             fn to_cbor_value(self) -> Result<cbor::value::Value, CborError> {
581                 Ok(cbor::value::Value::Array(match self {
582                     $( Self::$cname(val) => {
583                         vec_try![
584                             $cenum::$cname.to_cbor_value()?,
585                             val.to_cbor_value()?
586                         ]?
587                     }, )*
588                 }))
589             }
590 
591             fn cddl_typename() -> Option<String> {
592                 use alloc::string::ToString;
593                 Some(stringify!($rspenum).to_string())
594             }
595 
596             fn cddl_schema() -> Option<String> {
597                 Some(format!($cddlfmt,
598                              $( <$rsptyp>::cddl_ref(), )*
599                 ))
600             }
601         }
602 
603         $(
604             impl Code<$cenum> for $reqtyp {
605                 const CODE: $cenum = $cenum::$cname;
606             }
607         )*
608 
609         $(
610             impl Code<$cenum> for $rsptyp {
611                 const CODE: $cenum = $cenum::$cname;
612             }
613         )*
614     };
615 }
616 
617 // Possible KeyMint operation requests, as:
618 // - an enum value with an explicit numeric value
619 // - a request enum which has an operation code associated to each variant
620 // - a response enum which has the same operation code associated to each variant.
621 declare_req_rsp_enums! { KeyMintOperation  =>    (PerformOpReq, PerformOpRsp) {
622     DeviceGetHardwareInfo = 0x11 =>                    (GetHardwareInfoRequest, GetHardwareInfoResponse),
623     DeviceAddRngEntropy = 0x12 =>                      (AddRngEntropyRequest, AddRngEntropyResponse),
624     DeviceGenerateKey = 0x13 =>                        (GenerateKeyRequest, GenerateKeyResponse),
625     DeviceImportKey = 0x14 =>                          (ImportKeyRequest, ImportKeyResponse),
626     DeviceImportWrappedKey = 0x15 =>                   (ImportWrappedKeyRequest, ImportWrappedKeyResponse),
627     DeviceUpgradeKey = 0x16 =>                         (UpgradeKeyRequest, UpgradeKeyResponse),
628     DeviceDeleteKey = 0x17 =>                          (DeleteKeyRequest, DeleteKeyResponse),
629     DeviceDeleteAllKeys = 0x18 =>                      (DeleteAllKeysRequest, DeleteAllKeysResponse),
630     DeviceDestroyAttestationIds = 0x19 =>              (DestroyAttestationIdsRequest, DestroyAttestationIdsResponse),
631     DeviceBegin = 0x1a =>                              (BeginRequest, BeginResponse),
632     // 0x1b used to be DeviceDeviceLocked, but it was never used and consequently was removed.
633     DeviceEarlyBootEnded = 0x1c =>                     (EarlyBootEndedRequest, EarlyBootEndedResponse),
634     DeviceConvertStorageKeyToEphemeral = 0x1d =>       (ConvertStorageKeyToEphemeralRequest, ConvertStorageKeyToEphemeralResponse),
635     DeviceGetKeyCharacteristics = 0x1e =>              (GetKeyCharacteristicsRequest, GetKeyCharacteristicsResponse),
636     OperationUpdateAad = 0x31 =>                       (UpdateAadRequest, UpdateAadResponse),
637     OperationUpdate = 0x32 =>                          (UpdateRequest, UpdateResponse),
638     OperationFinish = 0x33 =>                          (FinishRequest, FinishResponse),
639     OperationAbort = 0x34 =>                           (AbortRequest, AbortResponse),
640     RpcGetHardwareInfo = 0x41 =>                       (GetRpcHardwareInfoRequest, GetRpcHardwareInfoResponse),
641     RpcGenerateEcdsaP256KeyPair = 0x42 =>              (GenerateEcdsaP256KeyPairRequest, GenerateEcdsaP256KeyPairResponse),
642     RpcGenerateCertificateRequest = 0x43 =>            (GenerateCertificateRequestRequest, GenerateCertificateRequestResponse),
643     RpcGenerateCertificateV2Request = 0x44 =>          (GenerateCertificateRequestV2Request, GenerateCertificateRequestV2Response),
644     SharedSecretGetSharedSecretParameters = 0x51 =>    (GetSharedSecretParametersRequest, GetSharedSecretParametersResponse),
645     SharedSecretComputeSharedSecret = 0x52 =>          (ComputeSharedSecretRequest, ComputeSharedSecretResponse),
646     SecureClockGenerateTimeStamp = 0x61 =>             (GenerateTimeStampRequest, GenerateTimeStampResponse),
647     GetRootOfTrustChallenge = 0x71 =>                  (GetRootOfTrustChallengeRequest, GetRootOfTrustChallengeResponse),
648     GetRootOfTrust = 0x72 =>                           (GetRootOfTrustRequest, GetRootOfTrustResponse),
649     SendRootOfTrust = 0x73 =>                          (SendRootOfTrustRequest, SendRootOfTrustResponse),
650     SetHalInfo = 0x81 =>                               (SetHalInfoRequest, SetHalInfoResponse),
651     SetBootInfo = 0x82 =>                              (SetBootInfoRequest, SetBootInfoResponse),
652     SetAttestationIds = 0x83 =>                        (SetAttestationIdsRequest, SetAttestationIdsResponse),
653     SetHalVersion = 0x84 =>                            (SetHalVersionRequest, SetHalVersionResponse),
654 } }
655 
656 /// Indicate whether an operation is part of the `IRemotelyProvisionedComponent` HAL.
is_rpc_operation(code: KeyMintOperation) -> bool657 pub fn is_rpc_operation(code: KeyMintOperation) -> bool {
658     matches!(
659         code,
660         KeyMintOperation::RpcGetHardwareInfo
661             | KeyMintOperation::RpcGenerateEcdsaP256KeyPair
662             | KeyMintOperation::RpcGenerateCertificateRequest
663             | KeyMintOperation::RpcGenerateCertificateV2Request
664     )
665 }
666