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