• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Static information about tag behaviour.
2 
3 use crate::{km_err, Error};
4 use kmr_wire::keymint::{Tag, TagType};
5 
6 #[cfg(test)]
7 mod tests;
8 
9 /// Indicate the allowed use of the tag as a key characteristic.
10 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
11 pub enum Characteristic {
12     /// Tag is a key characteristic that is enforced by KeyMint (at whatever security
13     /// level the KeyMint implementation is running at), and is visible to KeyMint
14     /// users (e.g. via GetKeyCharacteristics).
15     KeyMintEnforced,
16 
17     /// Tag is a key characteristic that is enforced by KeyMint (at whatever security
18     /// level the KeyMint implementation is running at), but is not exposed to KeyMint
19     /// users.  If a key has this tag associated with it, all operations on the key
20     /// must have this tag provided as an operation parameter.
21     KeyMintHidden,
22 
23     /// Tag is a key characteristic that is enforced by Keystore.
24     KeystoreEnforced,
25 
26     /// Tag is enforced by both KeyMint and Keystore, in different ways.
27     BothEnforced,
28 
29     /// Tag is not a key characteristic, either because it only acts as an operation
30     /// parameter or because it never appears on the API.
31     NotKeyCharacteristic,
32 }
33 
34 /// The set of characteristics that are necessarily enforced by Keystore.
35 pub const KEYSTORE_ENFORCED_CHARACTERISTICS: &[Tag] = &[
36     Tag::ActiveDatetime,
37     Tag::OriginationExpireDatetime,
38     Tag::UsageExpireDatetime,
39     Tag::UserId,
40     Tag::AllowWhileOnBody,
41     Tag::CreationDatetime,
42     Tag::MaxBootLevel,
43 ];
44 
45 /// The set of characteristics that are enforced by KeyMint.
46 pub const KEYMINT_ENFORCED_CHARACTERISTICS: &[Tag] = &[
47     Tag::UserSecureId,
48     Tag::Algorithm,
49     Tag::EcCurve,
50     Tag::UserAuthType,
51     Tag::Origin,
52     Tag::Purpose,
53     Tag::BlockMode,
54     Tag::Digest,
55     Tag::Padding,
56     Tag::RsaOaepMgfDigest,
57     Tag::KeySize,
58     Tag::MinMacLength,
59     Tag::MaxUsesPerBoot,
60     Tag::AuthTimeout,
61     Tag::OsVersion,
62     Tag::OsPatchlevel,
63     Tag::VendorPatchlevel,
64     Tag::BootPatchlevel,
65     Tag::RsaPublicExponent,
66     Tag::CallerNonce,
67     Tag::BootloaderOnly,
68     Tag::RollbackResistance,
69     Tag::EarlyBootOnly,
70     Tag::NoAuthRequired,
71     Tag::TrustedUserPresenceRequired,
72     Tag::TrustedConfirmationRequired,
73     Tag::StorageKey,
74 ];
75 
76 /// The set of characteristics that are automatically added by KeyMint on key generation.
77 pub const AUTO_ADDED_CHARACTERISTICS: &[Tag] =
78     &[Tag::Origin, Tag::OsVersion, Tag::OsPatchlevel, Tag::VendorPatchlevel, Tag::BootPatchlevel];
79 
80 /// Indicate the allowed use of the tag as a parameter for an operation.
81 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
82 pub enum OperationParam {
83     /// Tag acts as an operation parameter for key generation/import operations.
84     KeyGenImport,
85 
86     /// Tag is provided as an explicit argument for a cipher operation, and must
87     /// match one of the values for this tag in the key characteristics.
88     CipherExplicitArgOneOf,
89 
90     /// Tag is provided as a parameter for a cipher operation, and must
91     /// match one of the values for this tag in the key characteristics.
92     CipherParamOneOf,
93 
94     /// Tag is provided as a parameter for a cipher operation, and must
95     /// exactly match the (single) value for this tag in the key characteristics.
96     CipherParamExactMatch,
97 
98     /// Tag is provided as a parameter for a cipher operation, and is not a key
99     /// characteristic.
100     CipherParam,
101 
102     /// Tag is not an operation parameter; this *normally* means that it only acts
103     /// as a key characteristic (exception: ROOT_OF_TRUST is neither an operation
104     /// parameter nor a key characteristic).
105     NotOperationParam,
106 }
107 
108 /// Indicate whether the KeyMint user is allowed to specify this tag.
109 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
110 pub struct UserSpecifiable(pub bool);
111 
112 /// Indicate whether the KeyMint implementation auto-adds this tag as a characteristic to generated
113 /// or imported keys.
114 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
115 pub struct AutoAddedCharacteristic(pub bool);
116 
117 /// Indicate the lifetime of the value associated with the tag.
118 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
119 pub enum ValueLifetime {
120     /// Indicates that the value of the tag is communicated to KeyMint from the bootloader, and
121     /// fixed thereafter.
122     FixedAtBoot,
123     /// Indicates that the value of the tag is communicated to KeyMint from the HAL service, and
124     /// fixed thereafter.
125     FixedAtStartup,
126     /// Indicates that the value of the tag varies from key to key, or operation to operation.
127     Variable,
128 }
129 
130 /// Indicate whether a tag provided as an asymmetric key generation/import parameter is
131 /// required for the production of a certificate or attestation extension.
132 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
133 pub enum CertGenParam {
134     /// Tag not required as a parameter for certificate or extension generation (although its value
135     /// may appear in the extension as a key characteristic).
136     ///
137     /// Example: `Tag::KeySize` doesn't affect cert generation (but does appear in any attestation
138     /// extension).
139     NotRequired,
140     /// Tag must be specified as a parameter on key generation in order to get certificate
141     /// generation.
142     ///
143     /// Example: `Tag::CertificateNotBefore` must be specified to get a cert.
144     Required,
145     /// Tag must be specified as a parameter on key generation in order to get an attestation
146     /// extension in a generated certificate.
147     ///
148     /// Example: `Tag::AttestationChallenge` must be specified to get a cert with an attestation
149     /// extension.
150     RequiredForAttestation,
151     /// Tag need not be specified as a parameter on key generation, but if specified it does affect
152     /// the contents of the generated certificate (not extension).
153     ///
154     /// Example: `Tag::CertificateSerial` can be omitted, but if supplied it alters the cert.
155     Optional,
156     /// Tag need not be specified as a parameter on key generation, but if specified it does affect
157     /// the contents of the attestation extension.
158     ///
159     /// Example: `Tag::ResetSinceIdRotation` can be omitted, but if supplied (along with
160     /// `Tag::IncludeUniqueId`) then the attestation extension contents are altered.
161     OptionalForAttestation,
162     /// Special cases; see individual tags for information.
163     Special,
164 }
165 
166 /// Information about a tag's behaviour.
167 #[derive(Debug, Clone)]
168 pub struct Info {
169     /// Tag name as a string for debug purposes.
170     pub name: &'static str,
171     /// Indication of the type of the corresponding value.
172     pub tt: TagType,
173     /// Indicates whether the tag value appears in an attestation extension, and as what ASN.1
174     /// type.
175     pub ext_asn1_type: Option<&'static str>,
176     /// Indicates whether the KeyMint user can specify this tag.
177     pub user_can_specify: UserSpecifiable,
178     /// Indicates how this tag acts as a key characteristic.
179     pub characteristic: Characteristic,
180     /// Indicates how this tag acts as an operation parameter.
181     pub op_param: OperationParam,
182     /// Indicates whether KeyMint automatically adds this tag to keys as a key characteristic.
183     pub keymint_auto_adds: AutoAddedCharacteristic,
184     /// Indicates the lifetime of the value associated with this tag.
185     pub lifetime: ValueLifetime,
186     /// Indicates the role this tag plays in certificate generation for asymmetric keys.
187     pub cert_gen: CertGenParam,
188     /// Unique bit index for tracking this tag.
189     bit_index: usize,
190 }
191 
192 /// Global "map" of tags to information about their behaviour.
193 /// Encoded as an array to avoid allocation; lookup should only be slightly slower
194 /// for this few entries.
195 const INFO: [(Tag, Info); 60] = [
196     (
197         Tag::Purpose,
198         Info {
199             name: "PURPOSE",
200             tt: TagType::EnumRep,
201             ext_asn1_type: Some("SET OF INTEGER"),
202             user_can_specify: UserSpecifiable(true),
203             characteristic: Characteristic::KeyMintEnforced,
204             op_param: OperationParam::CipherExplicitArgOneOf,
205             keymint_auto_adds: AutoAddedCharacteristic(false),
206             lifetime: ValueLifetime::Variable,
207             cert_gen: CertGenParam::NotRequired,
208             bit_index: 0,
209         },
210     ),
211     (
212         Tag::Algorithm,
213         Info {
214             name: "ALGORITHM",
215             tt: TagType::Enum,
216             ext_asn1_type: Some("INTEGER"),
217             user_can_specify: UserSpecifiable(true),
218             characteristic: Characteristic::KeyMintEnforced,
219             op_param: OperationParam::NotOperationParam,
220             keymint_auto_adds: AutoAddedCharacteristic(false),
221             lifetime: ValueLifetime::Variable,
222             cert_gen: CertGenParam::NotRequired,
223             bit_index: 1,
224         },
225     ),
226     (
227         Tag::KeySize,
228         Info {
229             name: "KEY_SIZE",
230             tt: TagType::Uint,
231             ext_asn1_type: Some("INTEGER"),
232             user_can_specify: UserSpecifiable(true),
233             characteristic: Characteristic::KeyMintEnforced,
234             op_param: OperationParam::NotOperationParam,
235             keymint_auto_adds: AutoAddedCharacteristic(false),
236             lifetime: ValueLifetime::Variable,
237             cert_gen: CertGenParam::NotRequired,
238             bit_index: 2,
239         },
240     ),
241     (
242         Tag::BlockMode,
243         Info {
244             name: "BLOCK_MODE",
245             tt: TagType::EnumRep,
246             ext_asn1_type: None,
247             user_can_specify: UserSpecifiable(true),
248             characteristic: Characteristic::KeyMintEnforced,
249             op_param: OperationParam::CipherParamOneOf,
250             keymint_auto_adds: AutoAddedCharacteristic(false),
251             lifetime: ValueLifetime::Variable,
252             cert_gen: CertGenParam::NotRequired,
253             bit_index: 3,
254         },
255     ),
256     (
257         Tag::Digest,
258         Info {
259             name: "DIGEST",
260             tt: TagType::EnumRep,
261             ext_asn1_type: Some("SET OF INTEGER"),
262             user_can_specify: UserSpecifiable(true),
263             characteristic: Characteristic::KeyMintEnforced,
264             op_param: OperationParam::CipherParamOneOf,
265             keymint_auto_adds: AutoAddedCharacteristic(false),
266             lifetime: ValueLifetime::Variable,
267             cert_gen: CertGenParam::NotRequired,
268             bit_index: 4,
269         },
270     ),
271     (
272         Tag::Padding,
273         Info {
274             name: "PADDING",
275             tt: TagType::EnumRep,
276             ext_asn1_type: Some("SET OF INTEGER"),
277             user_can_specify: UserSpecifiable(true),
278             characteristic: Characteristic::KeyMintEnforced,
279             op_param: OperationParam::CipherParamOneOf,
280             keymint_auto_adds: AutoAddedCharacteristic(false),
281             lifetime: ValueLifetime::Variable,
282             cert_gen: CertGenParam::NotRequired,
283             bit_index: 5,
284         },
285     ),
286     (
287         Tag::CallerNonce,
288         Info {
289             name: "CALLER_NONCE",
290             tt: TagType::Bool,
291             ext_asn1_type: None,
292             user_can_specify: UserSpecifiable(true),
293             characteristic: Characteristic::KeyMintEnforced,
294             op_param: OperationParam::NotOperationParam,
295             keymint_auto_adds: AutoAddedCharacteristic(false),
296             lifetime: ValueLifetime::Variable,
297             cert_gen: CertGenParam::NotRequired,
298             bit_index: 6,
299         },
300     ),
301     (
302         Tag::MinMacLength,
303         Info {
304             name: "MIN_MAC_LENGTH",
305             tt: TagType::Uint,
306             ext_asn1_type: None,
307             user_can_specify: UserSpecifiable(true),
308             characteristic: Characteristic::KeyMintEnforced,
309             op_param: OperationParam::NotOperationParam,
310             keymint_auto_adds: AutoAddedCharacteristic(false),
311             lifetime: ValueLifetime::Variable,
312             cert_gen: CertGenParam::NotRequired,
313             bit_index: 7,
314         },
315     ),
316     (
317         Tag::EcCurve,
318         Info {
319             name: "EC_CURVE",
320             tt: TagType::Enum,
321             ext_asn1_type: Some("INTEGER"),
322             user_can_specify: UserSpecifiable(true),
323             characteristic: Characteristic::KeyMintEnforced,
324             op_param: OperationParam::NotOperationParam,
325             keymint_auto_adds: AutoAddedCharacteristic(false),
326             lifetime: ValueLifetime::Variable,
327             cert_gen: CertGenParam::NotRequired,
328             bit_index: 8,
329         },
330     ),
331     (
332         Tag::RsaPublicExponent,
333         Info {
334             name: "RSA_PUBLIC_EXPONENT",
335             tt: TagType::Ulong,
336             ext_asn1_type: Some("INTEGER"),
337             user_can_specify: UserSpecifiable(true),
338             characteristic: Characteristic::KeyMintEnforced,
339             op_param: OperationParam::NotOperationParam,
340             keymint_auto_adds: AutoAddedCharacteristic(false),
341             lifetime: ValueLifetime::Variable,
342             cert_gen: CertGenParam::NotRequired,
343             bit_index: 9,
344         },
345     ),
346     (
347         Tag::IncludeUniqueId,
348         Info {
349             name: "INCLUDE_UNIQUE_ID",
350             tt: TagType::Bool,
351             ext_asn1_type: None,
352             user_can_specify: UserSpecifiable(true),
353             characteristic: Characteristic::NotKeyCharacteristic,
354             op_param: OperationParam::KeyGenImport,
355             keymint_auto_adds: AutoAddedCharacteristic(false),
356             lifetime: ValueLifetime::Variable,
357             cert_gen: CertGenParam::OptionalForAttestation,
358             bit_index: 10,
359         },
360     ),
361     (
362         Tag::RsaOaepMgfDigest,
363         Info {
364             name: "RSA_OAEP_MGF_DIGEST",
365             tt: TagType::EnumRep,
366             ext_asn1_type: Some("SET OF INTEGER"),
367             user_can_specify: UserSpecifiable(true),
368             characteristic: Characteristic::KeyMintEnforced,
369             op_param: OperationParam::CipherParamOneOf,
370             keymint_auto_adds: AutoAddedCharacteristic(false),
371             lifetime: ValueLifetime::Variable,
372             cert_gen: CertGenParam::NotRequired,
373             bit_index: 11,
374         },
375     ),
376     (
377         Tag::BootloaderOnly,
378         Info {
379             name: "BOOTLOADER_ONLY",
380             tt: TagType::Bool,
381             ext_asn1_type: None,
382             user_can_specify: UserSpecifiable(false),
383             characteristic: Characteristic::KeyMintEnforced,
384             op_param: OperationParam::NotOperationParam,
385             keymint_auto_adds: AutoAddedCharacteristic(false),
386             lifetime: ValueLifetime::Variable,
387             cert_gen: CertGenParam::NotRequired,
388             bit_index: 12,
389         },
390     ),
391     (
392         Tag::RollbackResistance,
393         Info {
394             name: "ROLLBACK_RESISTANCE",
395             tt: TagType::Bool,
396             ext_asn1_type: Some("NULL"),
397             user_can_specify: UserSpecifiable(true),
398             characteristic: Characteristic::KeyMintEnforced,
399             op_param: OperationParam::NotOperationParam,
400             keymint_auto_adds: AutoAddedCharacteristic(false),
401             lifetime: ValueLifetime::Variable,
402             cert_gen: CertGenParam::NotRequired,
403             bit_index: 13,
404         },
405     ),
406     (
407         Tag::EarlyBootOnly,
408         Info {
409             name: "EARLY_BOOT_ONLY",
410             tt: TagType::Bool,
411             ext_asn1_type: Some("NULL"),
412             user_can_specify: UserSpecifiable(true),
413             characteristic: Characteristic::KeyMintEnforced,
414             op_param: OperationParam::NotOperationParam,
415             keymint_auto_adds: AutoAddedCharacteristic(false),
416             lifetime: ValueLifetime::Variable,
417             cert_gen: CertGenParam::NotRequired,
418             bit_index: 14,
419         },
420     ),
421     (
422         Tag::ActiveDatetime,
423         Info {
424             name: "ACTIVE_DATETIME",
425             tt: TagType::Date,
426             ext_asn1_type: Some("INTEGER"),
427             user_can_specify: UserSpecifiable(true),
428             characteristic: Characteristic::KeystoreEnforced,
429             op_param: OperationParam::NotOperationParam,
430             keymint_auto_adds: AutoAddedCharacteristic(false),
431             lifetime: ValueLifetime::Variable,
432             cert_gen: CertGenParam::NotRequired,
433             bit_index: 15,
434         },
435     ),
436     (
437         Tag::OriginationExpireDatetime,
438         Info {
439             name: "ORIGINATION_EXPIRE_DATETIME",
440             tt: TagType::Date,
441             ext_asn1_type: Some("INTEGER"),
442             user_can_specify: UserSpecifiable(true),
443             characteristic: Characteristic::KeystoreEnforced,
444             op_param: OperationParam::NotOperationParam,
445             keymint_auto_adds: AutoAddedCharacteristic(false),
446             lifetime: ValueLifetime::Variable,
447             cert_gen: CertGenParam::NotRequired,
448             bit_index: 16,
449         },
450     ),
451     (
452         Tag::UsageExpireDatetime,
453         Info {
454             name: "USAGE_EXPIRE_DATETIME",
455             tt: TagType::Date,
456             ext_asn1_type: Some("INTEGER"),
457             user_can_specify: UserSpecifiable(true),
458             characteristic: Characteristic::KeystoreEnforced,
459             op_param: OperationParam::NotOperationParam,
460             keymint_auto_adds: AutoAddedCharacteristic(false),
461             lifetime: ValueLifetime::Variable,
462             cert_gen: CertGenParam::NotRequired,
463             bit_index: 17,
464         },
465     ),
466     (
467         Tag::MaxUsesPerBoot,
468         Info {
469             name: "MAX_USES_PER_BOOT",
470             tt: TagType::Uint,
471             ext_asn1_type: None,
472             user_can_specify: UserSpecifiable(true),
473             characteristic: Characteristic::KeyMintEnforced,
474             op_param: OperationParam::NotOperationParam,
475             keymint_auto_adds: AutoAddedCharacteristic(false),
476             lifetime: ValueLifetime::Variable,
477             cert_gen: CertGenParam::NotRequired,
478             bit_index: 18,
479         },
480     ),
481     (
482         Tag::UsageCountLimit,
483         Info {
484             name: "USAGE_COUNT_LIMIT",
485             tt: TagType::Uint,
486             ext_asn1_type: Some("INTEGER"),
487             user_can_specify: UserSpecifiable(true),
488             characteristic: Characteristic::BothEnforced,
489             op_param: OperationParam::NotOperationParam,
490             keymint_auto_adds: AutoAddedCharacteristic(false),
491             lifetime: ValueLifetime::Variable,
492             cert_gen: CertGenParam::NotRequired,
493             bit_index: 19,
494         },
495     ),
496     (
497         Tag::UserId,
498         Info {
499             name: "USER_ID",
500             tt: TagType::Uint,
501             ext_asn1_type: None,
502             user_can_specify: UserSpecifiable(true),
503             characteristic: Characteristic::KeystoreEnforced,
504             op_param: OperationParam::NotOperationParam,
505             keymint_auto_adds: AutoAddedCharacteristic(false),
506             lifetime: ValueLifetime::Variable,
507             cert_gen: CertGenParam::NotRequired,
508             bit_index: 20,
509         },
510     ),
511     // Value must match userID or secureId in authToken param
512     (
513         Tag::UserSecureId,
514         Info {
515             name: "USER_SECURE_ID",
516             tt: TagType::UlongRep,
517             ext_asn1_type: None,
518             user_can_specify: UserSpecifiable(true),
519             characteristic: Characteristic::KeyMintEnforced,
520             op_param: OperationParam::CipherExplicitArgOneOf,
521             keymint_auto_adds: AutoAddedCharacteristic(false),
522             lifetime: ValueLifetime::Variable,
523             cert_gen: CertGenParam::NotRequired,
524             bit_index: 21,
525         },
526     ),
527     (
528         Tag::NoAuthRequired,
529         Info {
530             name: "NO_AUTH_REQUIRED",
531             tt: TagType::Bool,
532             ext_asn1_type: Some("NULL"),
533             user_can_specify: UserSpecifiable(true),
534             characteristic: Characteristic::KeyMintEnforced,
535             op_param: OperationParam::NotOperationParam,
536             keymint_auto_adds: AutoAddedCharacteristic(false),
537             lifetime: ValueLifetime::Variable,
538             cert_gen: CertGenParam::NotRequired,
539             bit_index: 22,
540         },
541     ),
542     (
543         Tag::UserAuthType,
544         Info {
545             name: "USER_AUTH_TYPE",
546             tt: TagType::Enum,
547             ext_asn1_type: Some("INTEGER"),
548             user_can_specify: UserSpecifiable(true),
549             characteristic: Characteristic::KeyMintEnforced,
550             op_param: OperationParam::CipherParamOneOf,
551             keymint_auto_adds: AutoAddedCharacteristic(false),
552             lifetime: ValueLifetime::Variable,
553             cert_gen: CertGenParam::NotRequired,
554             bit_index: 23,
555         },
556     ),
557     (
558         Tag::AuthTimeout,
559         Info {
560             name: "AUTH_TIMEOUT",
561             tt: TagType::Uint,
562             ext_asn1_type: Some("INTEGER"),
563             user_can_specify: UserSpecifiable(true),
564             characteristic: Characteristic::KeyMintEnforced,
565             op_param: OperationParam::NotOperationParam,
566             keymint_auto_adds: AutoAddedCharacteristic(false),
567             lifetime: ValueLifetime::Variable,
568             cert_gen: CertGenParam::NotRequired,
569             bit_index: 24,
570         },
571     ),
572     (
573         Tag::AllowWhileOnBody,
574         Info {
575             name: "ALLOW_WHILE_ON_BODY",
576             tt: TagType::Bool,
577             ext_asn1_type: Some("NULL"),
578             user_can_specify: UserSpecifiable(true),
579             characteristic: Characteristic::KeystoreEnforced,
580             op_param: OperationParam::NotOperationParam,
581             keymint_auto_adds: AutoAddedCharacteristic(false),
582             lifetime: ValueLifetime::Variable,
583             cert_gen: CertGenParam::NotRequired,
584             bit_index: 25,
585         },
586     ),
587     (
588         Tag::TrustedUserPresenceRequired,
589         Info {
590             name: "TRUSTED_USER_PRESENCE_REQUIRED",
591             tt: TagType::Bool,
592             ext_asn1_type: Some("NULL"),
593             user_can_specify: UserSpecifiable(true),
594             characteristic: Characteristic::KeyMintEnforced,
595             op_param: OperationParam::NotOperationParam,
596             keymint_auto_adds: AutoAddedCharacteristic(false),
597             lifetime: ValueLifetime::Variable,
598             cert_gen: CertGenParam::NotRequired,
599             bit_index: 26,
600         },
601     ),
602     (
603         Tag::TrustedConfirmationRequired,
604         Info {
605             name: "TRUSTED_CONFIRMATION_REQUIRED",
606             tt: TagType::Bool,
607             ext_asn1_type: Some("NULL"),
608             user_can_specify: UserSpecifiable(true),
609             characteristic: Characteristic::KeyMintEnforced,
610             op_param: OperationParam::NotOperationParam,
611             keymint_auto_adds: AutoAddedCharacteristic(false),
612             lifetime: ValueLifetime::Variable,
613             cert_gen: CertGenParam::NotRequired,
614             bit_index: 27,
615         },
616     ),
617     // Keystore enforces unlocked-by-specific user,  KeyMint unlocked-at-all (according to
618     // deviceLocked() invocations)
619     (
620         Tag::UnlockedDeviceRequired,
621         Info {
622             name: "UNLOCKED_DEVICE_REQUIRED",
623             tt: TagType::Bool,
624             ext_asn1_type: Some("NULL"),
625             user_can_specify: UserSpecifiable(true),
626             characteristic: Characteristic::BothEnforced,
627             op_param: OperationParam::NotOperationParam,
628             keymint_auto_adds: AutoAddedCharacteristic(false),
629             lifetime: ValueLifetime::Variable,
630             cert_gen: CertGenParam::NotRequired,
631             bit_index: 28,
632         },
633     ),
634     (
635         Tag::ApplicationId,
636         Info {
637             name: "APPLICATION_ID",
638             tt: TagType::Bytes,
639             ext_asn1_type: None,
640             user_can_specify: UserSpecifiable(true),
641             characteristic: Characteristic::KeyMintHidden,
642             op_param: OperationParam::CipherParamExactMatch,
643             keymint_auto_adds: AutoAddedCharacteristic(false),
644             lifetime: ValueLifetime::Variable,
645             cert_gen: CertGenParam::NotRequired,
646             bit_index: 29,
647         },
648     ),
649     (
650         Tag::ApplicationData,
651         Info {
652             name: "APPLICATION_DATA",
653             tt: TagType::Bytes,
654             ext_asn1_type: None,
655             user_can_specify: UserSpecifiable(true),
656             characteristic: Characteristic::KeyMintHidden,
657             op_param: OperationParam::CipherParamExactMatch,
658             keymint_auto_adds: AutoAddedCharacteristic(false),
659             lifetime: ValueLifetime::Variable,
660             cert_gen: CertGenParam::NotRequired,
661             bit_index: 30,
662         },
663     ),
664     (
665         Tag::CreationDatetime,
666         Info {
667             name: "CREATION_DATETIME",
668             tt: TagType::Date,
669             ext_asn1_type: Some("INTEGER"),
670             user_can_specify: UserSpecifiable(true),
671             characteristic: Characteristic::KeystoreEnforced,
672             op_param: OperationParam::NotOperationParam,
673             keymint_auto_adds: AutoAddedCharacteristic(false),
674             lifetime: ValueLifetime::Variable,
675             // If `Tag::IncludeUniqueId` is specified for attestation extension
676             // generation, then a value for `Tag::CreationDatetime` is needed for
677             // the calculation of the unique ID value.
678             cert_gen: CertGenParam::Special,
679             bit_index: 31,
680         },
681     ),
682     (
683         Tag::Origin,
684         Info {
685             name: "ORIGIN",
686             tt: TagType::Enum,
687             ext_asn1_type: Some("INTEGER"),
688             user_can_specify: UserSpecifiable(false),
689             characteristic: Characteristic::KeyMintEnforced,
690             op_param: OperationParam::NotOperationParam,
691             keymint_auto_adds: AutoAddedCharacteristic(true),
692             lifetime: ValueLifetime::Variable,
693             cert_gen: CertGenParam::NotRequired,
694             bit_index: 32,
695         },
696     ),
697     (
698         Tag::RootOfTrust,
699         Info {
700             name: "ROOT_OF_TRUST",
701             tt: TagType::Bytes,
702             ext_asn1_type: Some("RootOfTrust SEQUENCE"),
703             user_can_specify: UserSpecifiable(false),
704             // The root of trust is neither a key characteristic nor an operation parameter.
705             // The tag exists only to reserve a numeric value that can be used in the
706             // attestation extension record.
707             characteristic: Characteristic::NotKeyCharacteristic,
708             op_param: OperationParam::NotOperationParam,
709             keymint_auto_adds: AutoAddedCharacteristic(false),
710             lifetime: ValueLifetime::FixedAtBoot,
711             cert_gen: CertGenParam::NotRequired,
712             bit_index: 33,
713         },
714     ),
715     (
716         Tag::OsVersion,
717         Info {
718             name: "OS_VERSION",
719             tt: TagType::Uint,
720             ext_asn1_type: Some("INTEGER"),
721             user_can_specify: UserSpecifiable(false),
722             characteristic: Characteristic::KeyMintEnforced,
723             op_param: OperationParam::NotOperationParam,
724             keymint_auto_adds: AutoAddedCharacteristic(true),
725             lifetime: ValueLifetime::FixedAtBoot,
726             cert_gen: CertGenParam::NotRequired,
727             bit_index: 34,
728         },
729     ),
730     (
731         Tag::OsPatchlevel,
732         Info {
733             name: "OS_PATCHLEVEL",
734             tt: TagType::Uint,
735             ext_asn1_type: Some("INTEGER"),
736             user_can_specify: UserSpecifiable(false),
737             characteristic: Characteristic::KeyMintEnforced,
738             op_param: OperationParam::NotOperationParam,
739             keymint_auto_adds: AutoAddedCharacteristic(true),
740             lifetime: ValueLifetime::FixedAtBoot,
741             cert_gen: CertGenParam::NotRequired,
742             bit_index: 35,
743         },
744     ),
745     (
746         Tag::UniqueId,
747         Info {
748             name: "UNIQUE_ID",
749             tt: TagType::Bytes,
750             ext_asn1_type: Some("OCTET STRING"),
751             user_can_specify: UserSpecifiable(false),
752             // The unique ID is neither a key characteristic nor an operation parameter.
753             //
754             // The docs claim that tag exists only to reserve a numeric value that can be used in
755             // the attestation extension record created on key generation.
756             //
757             // However, the unique ID gets a field of its own in the top-level KeyDescription
758             // SEQUENCE; it does not appear in the AuthorizationList SEQUENCE, so this tag value
759             // should never be seen anywhere.
760             characteristic: Characteristic::NotKeyCharacteristic,
761             op_param: OperationParam::NotOperationParam,
762             keymint_auto_adds: AutoAddedCharacteristic(false),
763             lifetime: ValueLifetime::Variable,
764             cert_gen: CertGenParam::Special,
765             bit_index: 36,
766         },
767     ),
768     (
769         Tag::AttestationChallenge,
770         Info {
771             name: "ATTESTATION_CHALLENGE",
772             tt: TagType::Bytes,
773             ext_asn1_type: Some("OCTET STRING"),
774             user_can_specify: UserSpecifiable(true),
775             characteristic: Characteristic::NotKeyCharacteristic,
776             op_param: OperationParam::KeyGenImport,
777             keymint_auto_adds: AutoAddedCharacteristic(false),
778             lifetime: ValueLifetime::Variable,
779             cert_gen: CertGenParam::RequiredForAttestation,
780             bit_index: 37,
781         },
782     ),
783     (
784         Tag::AttestationApplicationId,
785         Info {
786             name: "ATTESTATION_APPLICATION_ID",
787             tt: TagType::Bytes,
788             ext_asn1_type: Some("OCTET STRING"),
789             user_can_specify: UserSpecifiable(true),
790             characteristic: Characteristic::NotKeyCharacteristic,
791             op_param: OperationParam::KeyGenImport,
792             keymint_auto_adds: AutoAddedCharacteristic(false),
793             lifetime: ValueLifetime::Variable,
794             cert_gen: CertGenParam::RequiredForAttestation,
795             bit_index: 38,
796         },
797     ),
798     (
799         Tag::AttestationIdBrand,
800         Info {
801             name: "ATTESTATION_ID_BRAND",
802             tt: TagType::Bytes,
803             ext_asn1_type: Some("OCTET STRING"),
804             user_can_specify: UserSpecifiable(true),
805             characteristic: Characteristic::NotKeyCharacteristic,
806             op_param: OperationParam::KeyGenImport,
807             keymint_auto_adds: AutoAddedCharacteristic(false),
808             lifetime: ValueLifetime::FixedAtBoot,
809             cert_gen: CertGenParam::OptionalForAttestation,
810             bit_index: 39,
811         },
812     ),
813     (
814         Tag::AttestationIdDevice,
815         Info {
816             name: "ATTESTATION_ID_DEVICE",
817             tt: TagType::Bytes,
818             ext_asn1_type: Some("OCTET STRING"),
819             user_can_specify: UserSpecifiable(true),
820             characteristic: Characteristic::NotKeyCharacteristic,
821             op_param: OperationParam::KeyGenImport,
822             keymint_auto_adds: AutoAddedCharacteristic(false),
823             lifetime: ValueLifetime::FixedAtBoot,
824             cert_gen: CertGenParam::OptionalForAttestation,
825             bit_index: 40,
826         },
827     ),
828     (
829         Tag::AttestationIdProduct,
830         Info {
831             name: "ATTESTATION_ID_PRODUCT",
832             tt: TagType::Bytes,
833             ext_asn1_type: Some("OCTET STRING"),
834             user_can_specify: UserSpecifiable(true),
835             characteristic: Characteristic::NotKeyCharacteristic,
836             op_param: OperationParam::KeyGenImport,
837             keymint_auto_adds: AutoAddedCharacteristic(false),
838             lifetime: ValueLifetime::FixedAtBoot,
839             cert_gen: CertGenParam::OptionalForAttestation,
840             bit_index: 41,
841         },
842     ),
843     (
844         Tag::AttestationIdSerial,
845         Info {
846             name: "ATTESTATION_ID_SERIAL",
847             tt: TagType::Bytes,
848             ext_asn1_type: Some("OCTET STRING"),
849             user_can_specify: UserSpecifiable(true),
850             characteristic: Characteristic::NotKeyCharacteristic,
851             op_param: OperationParam::KeyGenImport,
852             keymint_auto_adds: AutoAddedCharacteristic(false),
853             lifetime: ValueLifetime::FixedAtBoot,
854             cert_gen: CertGenParam::OptionalForAttestation,
855             bit_index: 42,
856         },
857     ),
858     (
859         Tag::AttestationIdImei,
860         Info {
861             name: "ATTESTATION_ID_IMEI",
862             tt: TagType::Bytes,
863             ext_asn1_type: Some("OCTET STRING"),
864             user_can_specify: UserSpecifiable(true),
865             characteristic: Characteristic::NotKeyCharacteristic,
866             op_param: OperationParam::KeyGenImport,
867             keymint_auto_adds: AutoAddedCharacteristic(false),
868             lifetime: ValueLifetime::FixedAtBoot,
869             cert_gen: CertGenParam::OptionalForAttestation,
870             bit_index: 43,
871         },
872     ),
873     (
874         Tag::AttestationIdSecondImei,
875         Info {
876             name: "ATTESTATION_ID_SECOND_IMEI",
877             tt: TagType::Bytes,
878             ext_asn1_type: Some("OCTET STRING"),
879             user_can_specify: UserSpecifiable(true),
880             characteristic: Characteristic::NotKeyCharacteristic,
881             op_param: OperationParam::KeyGenImport,
882             keymint_auto_adds: AutoAddedCharacteristic(false),
883             lifetime: ValueLifetime::FixedAtBoot,
884             cert_gen: CertGenParam::OptionalForAttestation,
885             bit_index: 44,
886         },
887     ),
888     (
889         Tag::AttestationIdMeid,
890         Info {
891             name: "ATTESTATION_ID_MEID",
892             tt: TagType::Bytes,
893             ext_asn1_type: Some("OCTET STRING"),
894             user_can_specify: UserSpecifiable(true),
895             characteristic: Characteristic::NotKeyCharacteristic,
896             op_param: OperationParam::KeyGenImport,
897             keymint_auto_adds: AutoAddedCharacteristic(false),
898             lifetime: ValueLifetime::FixedAtBoot,
899             cert_gen: CertGenParam::OptionalForAttestation,
900             bit_index: 45,
901         },
902     ),
903     (
904         Tag::AttestationIdManufacturer,
905         Info {
906             name: "ATTESTATION_ID_MANUFACTURER",
907             tt: TagType::Bytes,
908             ext_asn1_type: Some("OCTET STRING"),
909             user_can_specify: UserSpecifiable(true),
910             characteristic: Characteristic::NotKeyCharacteristic,
911             op_param: OperationParam::KeyGenImport,
912             keymint_auto_adds: AutoAddedCharacteristic(false),
913             lifetime: ValueLifetime::FixedAtBoot,
914             cert_gen: CertGenParam::OptionalForAttestation,
915             bit_index: 46,
916         },
917     ),
918     (
919         Tag::AttestationIdModel,
920         Info {
921             name: "ATTESTATION_ID_MODEL",
922             tt: TagType::Bytes,
923             ext_asn1_type: Some("OCTET STRING"),
924             user_can_specify: UserSpecifiable(true),
925             characteristic: Characteristic::NotKeyCharacteristic,
926             op_param: OperationParam::KeyGenImport,
927             keymint_auto_adds: AutoAddedCharacteristic(false),
928             lifetime: ValueLifetime::FixedAtBoot,
929             cert_gen: CertGenParam::OptionalForAttestation,
930             bit_index: 47,
931         },
932     ),
933     (
934         Tag::VendorPatchlevel,
935         Info {
936             name: "VENDOR_PATCHLEVEL",
937             tt: TagType::Uint,
938             ext_asn1_type: Some("INTEGER"),
939             user_can_specify: UserSpecifiable(false),
940             characteristic: Characteristic::KeyMintEnforced,
941             op_param: OperationParam::NotOperationParam,
942             keymint_auto_adds: AutoAddedCharacteristic(true),
943             lifetime: ValueLifetime::FixedAtStartup,
944             cert_gen: CertGenParam::NotRequired,
945             bit_index: 48,
946         },
947     ),
948     (
949         Tag::BootPatchlevel,
950         Info {
951             name: "BOOT_PATCHLEVEL",
952             tt: TagType::Uint,
953             ext_asn1_type: Some("INTEGER"),
954             user_can_specify: UserSpecifiable(false),
955             characteristic: Characteristic::KeyMintEnforced,
956             op_param: OperationParam::NotOperationParam,
957             keymint_auto_adds: AutoAddedCharacteristic(true),
958             lifetime: ValueLifetime::FixedAtBoot,
959             cert_gen: CertGenParam::NotRequired,
960             bit_index: 49,
961         },
962     ),
963     (
964         Tag::DeviceUniqueAttestation,
965         Info {
966             name: "DEVICE_UNIQUE_ATTESTATION",
967             tt: TagType::Bool,
968             ext_asn1_type: Some("NULL"),
969             user_can_specify: UserSpecifiable(true),
970             characteristic: Characteristic::NotKeyCharacteristic,
971             op_param: OperationParam::KeyGenImport,
972             keymint_auto_adds: AutoAddedCharacteristic(false),
973             lifetime: ValueLifetime::Variable,
974             // Device unique attestation does not affect the contents of the `tbsCertificate`,
975             // but it does change the chain used to sign the resulting certificate.
976             cert_gen: CertGenParam::Special,
977             bit_index: 50,
978         },
979     ),
980     // A key marked as a storage key cannot be used via most of the KeyMint API. Instead, it
981     // can be passed to `convertStorageKeyToEphemeral` to convert it to an ephemeral key.
982     (
983         Tag::StorageKey,
984         Info {
985             name: "STORAGE_KEY",
986             tt: TagType::Bool,
987             ext_asn1_type: None,
988             user_can_specify: UserSpecifiable(true),
989             characteristic: Characteristic::KeyMintEnforced,
990             op_param: OperationParam::NotOperationParam,
991             keymint_auto_adds: AutoAddedCharacteristic(false),
992             lifetime: ValueLifetime::Variable,
993             cert_gen: CertGenParam::NotRequired,
994             bit_index: 51,
995         },
996     ),
997     // Can only be user-specified if CALLER_NONCE set in key characteristics.
998     (
999         Tag::Nonce,
1000         Info {
1001             name: "NONCE",
1002             tt: TagType::Bytes,
1003             ext_asn1_type: None,
1004             user_can_specify: UserSpecifiable(true),
1005             characteristic: Characteristic::NotKeyCharacteristic,
1006             op_param: OperationParam::CipherParam,
1007             keymint_auto_adds: AutoAddedCharacteristic(false),
1008             lifetime: ValueLifetime::Variable,
1009             cert_gen: CertGenParam::NotRequired,
1010             bit_index: 52,
1011         },
1012     ),
1013     (
1014         Tag::MacLength,
1015         Info {
1016             name: "MAC_LENGTH",
1017             tt: TagType::Uint,
1018             ext_asn1_type: None,
1019             user_can_specify: UserSpecifiable(true),
1020             characteristic: Characteristic::NotKeyCharacteristic,
1021             op_param: OperationParam::CipherParam,
1022             keymint_auto_adds: AutoAddedCharacteristic(false),
1023             lifetime: ValueLifetime::Variable,
1024             cert_gen: CertGenParam::NotRequired,
1025             bit_index: 53,
1026         },
1027     ),
1028     (
1029         Tag::ResetSinceIdRotation,
1030         Info {
1031             name: "RESET_SINCE_ID_ROTATION",
1032             tt: TagType::Bool,
1033             ext_asn1_type: Some("part of UniqueID"),
1034             user_can_specify: UserSpecifiable(true),
1035             characteristic: Characteristic::NotKeyCharacteristic,
1036             op_param: OperationParam::KeyGenImport,
1037             keymint_auto_adds: AutoAddedCharacteristic(false),
1038             lifetime: ValueLifetime::Variable,
1039             cert_gen: CertGenParam::OptionalForAttestation,
1040             bit_index: 54,
1041         },
1042     ),
1043     // Default to 1 if not present
1044     (
1045         Tag::CertificateSerial,
1046         Info {
1047             name: "CERTIFICATE_SERIAL",
1048             tt: TagType::Bignum,
1049             ext_asn1_type: None,
1050             user_can_specify: UserSpecifiable(true),
1051             characteristic: Characteristic::NotKeyCharacteristic,
1052             op_param: OperationParam::KeyGenImport,
1053             keymint_auto_adds: AutoAddedCharacteristic(false),
1054             lifetime: ValueLifetime::Variable,
1055             cert_gen: CertGenParam::Optional,
1056             bit_index: 55,
1057         },
1058     ),
1059     // Default to "CN=Android Keystore Key" if not present
1060     (
1061         Tag::CertificateSubject,
1062         Info {
1063             name: "CERTIFICATE_SUBJECT",
1064             tt: TagType::Bytes,
1065             ext_asn1_type: None,
1066             user_can_specify: UserSpecifiable(true),
1067             characteristic: Characteristic::NotKeyCharacteristic,
1068             op_param: OperationParam::KeyGenImport,
1069             keymint_auto_adds: AutoAddedCharacteristic(false),
1070             lifetime: ValueLifetime::Variable,
1071             cert_gen: CertGenParam::Optional,
1072             bit_index: 56,
1073         },
1074     ),
1075     (
1076         Tag::CertificateNotBefore,
1077         Info {
1078             name: "CERTIFICATE_NOT_BEFORE",
1079             tt: TagType::Date,
1080             ext_asn1_type: None,
1081             user_can_specify: UserSpecifiable(true),
1082             characteristic: Characteristic::NotKeyCharacteristic,
1083             op_param: OperationParam::KeyGenImport,
1084             keymint_auto_adds: AutoAddedCharacteristic(false),
1085             lifetime: ValueLifetime::Variable,
1086             cert_gen: CertGenParam::Required,
1087             bit_index: 57,
1088         },
1089     ),
1090     (
1091         Tag::CertificateNotAfter,
1092         Info {
1093             name: "CERTIFICATE_NOT_AFTER",
1094             tt: TagType::Date,
1095             ext_asn1_type: None,
1096             user_can_specify: UserSpecifiable(true),
1097             characteristic: Characteristic::NotKeyCharacteristic,
1098             op_param: OperationParam::KeyGenImport,
1099             keymint_auto_adds: AutoAddedCharacteristic(false),
1100             lifetime: ValueLifetime::Variable,
1101             cert_gen: CertGenParam::Required,
1102             bit_index: 58,
1103         },
1104     ),
1105     (
1106         Tag::MaxBootLevel,
1107         Info {
1108             name: "MAX_BOOT_LEVEL",
1109             tt: TagType::Uint,
1110             ext_asn1_type: None,
1111             user_can_specify: UserSpecifiable(true),
1112             characteristic: Characteristic::KeystoreEnforced,
1113             op_param: OperationParam::NotOperationParam,
1114             keymint_auto_adds: AutoAddedCharacteristic(false),
1115             lifetime: ValueLifetime::Variable,
1116             cert_gen: CertGenParam::NotRequired,
1117             bit_index: 59,
1118         },
1119     ),
1120 ];
1121 
1122 /// Return behaviour information about the specified tag.
info(tag: Tag) -> Result<&'static Info, Error>1123 pub fn info(tag: Tag) -> Result<&'static Info, Error> {
1124     for (t, info) in &INFO {
1125         if tag == *t {
1126             return Ok(info);
1127         }
1128     }
1129     Err(km_err!(InvalidTag, "unknown tag {:?}", tag))
1130 }
1131 
1132 /// Indicate whether a tag is allowed to have multiple values.
1133 #[inline]
multivalued(tag: Tag) -> bool1134 pub fn multivalued(tag: Tag) -> bool {
1135     matches!(
1136         kmr_wire::keymint::tag_type(tag),
1137         TagType::EnumRep | TagType::UintRep | TagType::UlongRep
1138     )
1139 }
1140 
1141 /// Tracker for observed tag values.
1142 #[derive(Default)]
1143 pub struct DuplicateTagChecker(u64);
1144 
1145 impl DuplicateTagChecker {
1146     /// Add the given tag to the set of seen tags, failing if the tag
1147     /// has already been observed (and is not multivalued).
add(&mut self, tag: Tag) -> Result<(), Error>1148     pub fn add(&mut self, tag: Tag) -> Result<(), Error> {
1149         let bit_idx = info(tag)?.bit_index;
1150         let bit_mask = 0x01u64 << bit_idx;
1151         if !multivalued(tag) && (self.0 & bit_mask) != 0 {
1152             return Err(km_err!(InvalidKeyBlob, "duplicate value for {:?}", tag));
1153         }
1154         self.0 |= bit_mask;
1155         Ok(())
1156     }
1157 }
1158