1use std::collections::HashMap;
5use std::fmt::Debug;
6use std::sync::LazyLock;
7
8use crate::attribute::{AttrType, Attribute};
9use crate::error::{Error, Result};
10use crate::mechanism::{Mechanism, Mechanisms};
11use crate::misc::{sizeof, void_ptr};
12use crate::pkcs11::*;
13
14#[cfg(feature = "nssdb")]
15use crate::pkcs11::vendor::nss::*;
16
17use super::certs::{TrustObject, X509Factory};
18use super::key::{
19 GenericSecretKeyFactory, GenericSecretKeyMechanism, KeyFactory,
20 PubKeyFactory, SecretKeyFactory,
21};
22use super::Object;
23
24#[cfg(feature = "nssdb")]
25use super::certs::NSSTrustObject;
26
27use bitflags::bitflags;
28
29pub fn incomplete(e: Error) -> Error {
31 if e.attr_not_found() {
32 Error::ck_rv(CKR_TEMPLATE_INCOMPLETE)
33 } else {
34 e
35 }
36}
37
38bitflags! {
39 #[derive(Debug, Clone, Copy)]
41 pub struct OAFlags: u32 {
42 const Ignored = 0x00000001;
44
45 const Sensitive = 0x00000002;
48
49 const Defval = 0x00000004;
52
53 const RequiredOnCreate = 0x00000008;
56
57 const RequiredOnGenerate = 0x00000010;
60
61 const AlwaysRequired = 0x00000020;
66
67 const SettableOnlyOnCreate = 0x00000080;
71
72 const NeverSettable = 0x00000100;
76
77 const Unchangeable = 0x00000400;
80
81 const ChangeToFalse = 0x00000C00;
83
84 const ChangeToTrue = 0x00001400;
86
87 const ChangeOnCopy = 0x00002400;
89
90 const Ephemeral = 0x00008000;
93 }
94}
95
96#[derive(Debug, Clone)]
101pub struct ObjectAttr {
102 pub(crate) attribute: Attribute,
104 flags: OAFlags,
107}
108
109impl ObjectAttr {
110 pub fn new(a: Attribute, f: OAFlags) -> ObjectAttr {
112 ObjectAttr {
113 attribute: a,
114 flags: f,
115 }
116 }
117
118 pub fn get_type(&self) -> CK_ULONG {
120 self.attribute.get_type()
121 }
122
123 pub fn is(&self, val: OAFlags) -> bool {
125 if val.is_empty() {
126 return false;
127 }
128 self.flags.contains(val)
129 }
130
131 pub fn has_default(&self) -> bool {
133 self.flags.contains(OAFlags::Defval)
134 }
135}
136
137#[macro_export]
139macro_rules! attr_element {
140 ($id:expr; $flags:expr; $from_type:expr; val $defval:expr) => {
141 $crate::object::factory::ObjectAttr::new(
142 $from_type($id, $defval),
143 $flags,
144 )
145 };
146}
147pub use attr_element;
148
149#[derive(Debug)]
156pub struct ObjectFactoryData {
157 class: CK_OBJECT_CLASS,
159 attributes: Vec<ObjectAttr>,
161 sensitive: Vec<CK_ATTRIBUTE_TYPE>,
163 ephemeral: Vec<CK_ATTRIBUTE_TYPE>,
165 finalized: bool,
168}
169
170impl ObjectFactoryData {
171 pub fn new(class: CK_OBJECT_CLASS) -> ObjectFactoryData {
172 ObjectFactoryData {
173 class: class,
174 attributes: Vec::new(),
175 sensitive: Vec::new(),
176 ephemeral: Vec::new(),
177 finalized: false,
178 }
179 }
180
181 pub fn get_class(&self) -> CK_OBJECT_CLASS {
183 self.class
184 }
185
186 pub fn get_attributes(&self) -> &Vec<ObjectAttr> {
188 &self.attributes
189 }
190
191 pub fn get_attributes_mut(&mut self) -> &mut Vec<ObjectAttr> {
197 if self.finalized {
198 panic!("Attempted modification after finalization");
199 }
200 &mut self.attributes
201 }
202
203 pub fn get_sensitive(&self) -> &Vec<CK_ATTRIBUTE_TYPE> {
207 &self.sensitive
208 }
209
210 pub fn get_ephemeral(&self) -> &Vec<CK_ATTRIBUTE_TYPE> {
214 &self.ephemeral
215 }
216
217 pub fn finalize(&mut self) {
220 for a in &self.attributes {
221 if a.is(OAFlags::Sensitive) {
222 self.sensitive.push(a.get_type());
223 }
224 if a.is(OAFlags::Ephemeral) {
225 self.ephemeral.push(a.get_type());
226 }
227 }
228 self.finalized = true;
229 }
230}
231
232pub trait ObjectFactory: Debug + Send + Sync {
241 fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
246 return Err(CKR_GENERAL_ERROR)?;
247 }
248
249 fn builtin_create(&self, _id: CK_ULONG) -> Result<Object> {
253 return Err(CKR_GENERAL_ERROR)?;
254 }
255
256 fn copy(&self, obj: &Object, template: &[CK_ATTRIBUTE]) -> Result<Object> {
260 self.default_copy(obj, template)
261 }
262
263 fn add_common_object_attrs(&mut self) {
265 let attrs = self.get_data_mut().get_attributes_mut();
266 attrs.push(attr_element!(
267 CKA_CLASS; OAFlags::RequiredOnCreate;
268 Attribute::from_ulong; val 0));
269 attrs.push(attr_element!(
270 CKA_UNIQUE_ID; OAFlags::NeverSettable | OAFlags::Unchangeable;
271 Attribute::from_string; val String::new()));
272 }
273
274 fn add_common_storage_attrs(&mut self, private: bool) {
276 self.add_common_object_attrs();
277 let attrs = self.get_data_mut().get_attributes_mut();
278 attrs.push(attr_element!(
279 CKA_TOKEN; OAFlags::Defval | OAFlags::ChangeOnCopy;
280 Attribute::from_bool; val false));
281 attrs.push(attr_element!(
282 CKA_PRIVATE; OAFlags::Defval | OAFlags::ChangeOnCopy;
283 Attribute::from_bool; val private));
284 attrs.push(attr_element!(
285 CKA_MODIFIABLE; OAFlags::Defval | OAFlags::ChangeOnCopy;
286 Attribute::from_bool; val true));
287 attrs.push(attr_element!(
288 CKA_LABEL; OAFlags::empty(); Attribute::from_string;
289 val String::new()));
290 attrs.push(attr_element!(
291 CKA_COPYABLE; OAFlags::Defval | OAFlags::ChangeToFalse;
292 Attribute::from_bool; val true));
293 attrs.push(attr_element!(
294 CKA_DESTROYABLE; OAFlags::Defval; Attribute::from_bool;
295 val true));
296 }
297
298 fn internal_object_create(
313 &self,
314 template: &[CK_ATTRIBUTE],
315 unacceptable_flags: OAFlags,
316 required_flags: OAFlags,
317 ) -> Result<Object> {
318 let data = self.get_data();
319 let mut obj = Object::new(data.get_class());
320
321 let attributes = data.get_attributes();
322 for ck_attr in template {
323 match attributes.iter().find(|a| a.get_type() == ck_attr.type_) {
324 Some(attr) => {
325 if attr.is(unacceptable_flags) {
326 return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
327 }
328 match obj.get_attr(ck_attr.type_) {
330 Some(oa) => {
331 if oa.get_type() != CKA_CLASS
332 || (oa.get_type() == CKA_CLASS
333 && ck_attr.to_ulong()? != oa.to_ulong()?)
334 {
335 return Err(CKR_TEMPLATE_INCONSISTENT)?;
336 }
337 }
338 None => (),
339 }
340 if !attr.is(OAFlags::Ignored) {
341 obj.attributes.push(Attribute::from_ck_attr(ck_attr)?);
342 }
343 }
344 None => {
345 return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
346 }
347 }
348 }
349 for attr in attributes {
350 match obj.get_attr(attr.get_type()) {
351 Some(_) => (),
352 None => {
353 if attr.has_default() {
354 obj.attributes.push(attr.attribute.clone());
355 } else if attr.is(required_flags)
356 || attr.is(OAFlags::AlwaysRequired)
357 {
358 return Err(CKR_TEMPLATE_INCOMPLETE)?;
359 }
360 }
361 }
362 }
363 Ok(obj)
364 }
365
366 fn default_object_create(
367 &self,
368 template: &[CK_ATTRIBUTE],
369 ) -> Result<Object> {
370 let mut obj = self.internal_object_create(
371 template,
372 OAFlags::NeverSettable,
373 OAFlags::RequiredOnCreate,
374 )?;
375 obj.generate_unique();
376 Ok(obj)
377 }
378
379 #[allow(dead_code)]
382 fn set_attribute_default(
383 &self,
384 attr: CK_ATTRIBUTE_TYPE,
385 obj: &mut Object,
386 ) -> Result<()> {
387 let attributes = self.get_data().get_attributes();
388 match attributes.iter().find(|a| a.get_type() == attr) {
389 Some(defattr) => {
390 if defattr.has_default() {
391 obj.set_attr(defattr.attribute.clone())?;
392 }
393 }
394 None => (),
395 }
396 Ok(())
397 }
398
399 fn default_copy(
402 &self,
403 origin: &Object,
404 template: &[CK_ATTRIBUTE],
405 ) -> Result<Object> {
406 let attributes = self.get_data().get_attributes();
407 for ck_attr in template {
408 match attributes.iter().find(|a| a.get_type() == ck_attr.type_) {
409 Some(attr) => {
410 if attr.is(OAFlags::Unchangeable) {
411 if attr
412 .is(OAFlags::ChangeToFalse | OAFlags::ChangeToTrue)
413 {
414 let val =
415 match origin.get_attr_as_bool(ck_attr.type_) {
416 Ok(a) => a,
417 Err(_) => false,
418 };
419 if val && !attr.is(OAFlags::ChangeToFalse) {
420 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
421 }
422 if !val && !attr.is(OAFlags::ChangeToTrue) {
423 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
424 }
425 }
426 if !attr.is(OAFlags::ChangeOnCopy) {
427 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
428 }
429 }
430 }
431 None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
432 }
433 }
434
435 let mut obj = origin.blind_copy()?;
436 for ck_attr in template {
437 let _ = obj.set_attr(Attribute::from_ck_attr(ck_attr)?)?;
438 }
439
440 match obj.get_attr_as_bool(CKA_EXTRACTABLE) {
442 Ok(e) => {
443 let mut val = !e;
444 match obj.get_attr_as_bool(CKA_NEVER_EXTRACTABLE) {
445 Ok(ne) => val &= ne,
446 Err(_) => match origin.get_attr_as_bool(CKA_EXTRACTABLE) {
447 Ok(oe) => val &= !oe,
448 Err(_) => val = false,
449 },
450 }
451 let _ = obj.set_attr(Attribute::from_bool(
452 CKA_NEVER_EXTRACTABLE,
453 val,
454 ))?;
455 }
456 Err(_) => (),
457 }
458 match obj.get_attr_as_bool(CKA_SENSITIVE) {
459 Ok(b) => {
460 let mut val = b;
461 match origin.get_attr_as_bool(CKA_ALWAYS_SENSITIVE) {
462 Ok(ob) => val &= ob,
463 Err(_) => match origin.get_attr_as_bool(CKA_SENSITIVE) {
464 Ok(os) => val &= os,
465 Err(_) => val = false,
466 },
467 }
468 let _ = obj.set_attr(Attribute::from_bool(
469 CKA_ALWAYS_SENSITIVE,
470 val,
471 ))?;
472 }
473 Err(_) => (),
474 }
475
476 Ok(obj)
477 }
478
479 fn check_set_attributes(&self, template: &[CK_ATTRIBUTE]) -> Result<()> {
484 let attrs = self.get_data().get_attributes();
485 for ck_attr in template {
486 match attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
487 None => return Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
488 Some(attr) => {
489 if attr.is(OAFlags::NeverSettable) {
490 return Err(CKR_ACTION_PROHIBITED)?;
491 }
492 if attr.is(OAFlags::Unchangeable) {
493 if attr.attribute.get_attrtype() == AttrType::BoolType {
494 let val = ck_attr.to_bool()?;
495 if val {
496 if !attr.is(OAFlags::ChangeToTrue) {
497 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
498 }
499 } else {
500 if !attr.is(OAFlags::ChangeToFalse) {
501 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
502 }
503 }
504 } else {
505 return Err(CKR_ATTRIBUTE_READ_ONLY)?;
506 }
507 }
508 }
509 }
510 }
511 Ok(())
512 }
513
514 fn set_object_attributes(
520 &self,
521 obj: &mut Object,
522 template: &[CK_ATTRIBUTE],
523 ) -> Result<()> {
524 if !obj.is_modifiable() {
525 return Err(CKR_ACTION_PROHIBITED)?;
526 }
527
528 self.check_set_attributes(template)?;
530
531 for ck_attr in template {
533 obj.set_attr(Attribute::from_ck_attr(ck_attr)?)?;
534 }
535
536 Ok(())
537 }
538
539 fn get_data(&self) -> &ObjectFactoryData;
541
542 fn get_data_mut(&mut self) -> &mut ObjectFactoryData;
544
545 fn as_key_factory(&self) -> Result<&dyn KeyFactory> {
548 Err(CKR_GENERAL_ERROR)?
549 }
550
551 fn as_public_key_factory(&self) -> Result<&dyn PubKeyFactory> {
556 Err(CKR_GENERAL_ERROR)?
557 }
558
559 fn as_secret_key_factory(&self) -> Result<&dyn SecretKeyFactory> {
563 Err(CKR_GENERAL_ERROR)?
564 }
565}
566
567#[derive(Debug)]
573struct DataFactory {
574 data: ObjectFactoryData,
575}
576
577impl DataFactory {
578 fn new() -> DataFactory {
580 let mut factory: DataFactory = DataFactory {
581 data: ObjectFactoryData::new(CKO_DATA),
582 };
583
584 factory.add_common_storage_attrs(false);
585
586 let attributes = factory.data.get_attributes_mut();
587
588 attributes.push(attr_element!(
589 CKA_APPLICATION; OAFlags::Defval; Attribute::from_string;
590 val String::new()));
591 attributes.push(attr_element!(
592 CKA_OBJECT_ID; OAFlags::empty(); Attribute::from_bytes;
593 val Vec::new()));
594 attributes.push(attr_element!(
595 CKA_VALUE; OAFlags::Defval; Attribute::from_bytes;
596 val Vec::new()));
597
598 factory.data.finalize();
599
600 factory
601 }
602}
603
604impl ObjectFactory for DataFactory {
605 fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
609 self.default_object_create(template)
610 }
611
612 fn copy(
613 &self,
614 origin: &Object,
615 template: &[CK_ATTRIBUTE],
616 ) -> Result<Object> {
617 self.default_copy(origin, template)
618 }
619
620 fn get_data(&self) -> &ObjectFactoryData {
621 &self.data
622 }
623
624 fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
625 &mut self.data
626 }
627}
628
629#[cfg(feature = "profiles")]
632#[derive(Debug)]
633pub struct ProfileFactory {
634 data: ObjectFactoryData,
635}
636
637#[cfg(feature = "profiles")]
638impl ProfileFactory {
639 fn new() -> ProfileFactory {
641 let mut factory: ProfileFactory = ProfileFactory {
642 data: ObjectFactoryData::new(CKO_PROFILE),
643 };
644
645 factory.add_common_object_attrs();
646
647 let attributes = factory.data.get_attributes_mut();
648
649 attributes.push(attr_element!(
650 CKA_PROFILE_ID; OAFlags::RequiredOnCreate; Attribute::from_ulong;
651 val CK_UNAVAILABLE_INFORMATION));
652
653 factory.data.finalize();
654
655 factory
656 }
657}
658
659#[cfg(feature = "profiles")]
660impl ObjectFactory for ProfileFactory {
661 fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
662 Err(CKR_TEMPLATE_INCOMPLETE)?
663 }
664
665 fn builtin_create(&self, profile_id: CK_PROFILE_ID) -> Result<Object> {
666 let mut pid = profile_id;
667 let attr = CK_ATTRIBUTE {
668 type_: CKA_PROFILE_ID,
669 pValue: void_ptr!(&mut pid),
670 ulValueLen: sizeof!(CK_PROFILE_ID),
671 };
672 let mut obj = self.internal_object_create(
673 &[attr],
674 OAFlags::empty(),
675 OAFlags::RequiredOnCreate,
676 )?;
677 obj.generate_stable_unique(profile_id);
678 Ok(obj)
679 }
680
681 fn copy(
682 &self,
683 _origin: &Object,
684 _template: &[CK_ATTRIBUTE],
685 ) -> Result<Object> {
686 Err(CKR_ACTION_PROHIBITED)?
687 }
688
689 fn get_data(&self) -> &ObjectFactoryData {
690 &self.data
691 }
692
693 fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
694 &mut self.data
695 }
696}
697
698#[derive(Debug)]
701pub struct MechanismFactory {
702 data: ObjectFactoryData,
703}
704
705impl MechanismFactory {
706 fn new() -> MechanismFactory {
708 let mut factory: MechanismFactory = MechanismFactory {
709 data: ObjectFactoryData::new(CKO_MECHANISM),
710 };
711
712 factory.add_common_object_attrs();
713
714 let attributes = factory.data.get_attributes_mut();
715
716 attributes.push(attr_element!(
717 CKA_MECHANISM_TYPE; OAFlags::RequiredOnCreate; Attribute::from_ulong;
718 val CK_UNAVAILABLE_INFORMATION));
719
720 factory.data.finalize();
721
722 factory
723 }
724}
725
726impl ObjectFactory for MechanismFactory {
727 fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
728 Err(CKR_TEMPLATE_INCOMPLETE)?
729 }
730
731 fn builtin_create(
732 &self,
733 mechanism_type: CK_MECHANISM_TYPE,
734 ) -> Result<Object> {
735 let mut mt = mechanism_type;
736 let attr = CK_ATTRIBUTE {
737 type_: CKA_MECHANISM_TYPE,
738 pValue: void_ptr!(&mut mt),
739 ulValueLen: sizeof!(CK_MECHANISM_TYPE),
740 };
741 let mut obj = self.internal_object_create(
742 &[attr],
743 OAFlags::empty(),
744 OAFlags::RequiredOnCreate,
745 )?;
746 obj.generate_stable_unique(mechanism_type);
747 Ok(obj)
748 }
749
750 fn copy(
751 &self,
752 _origin: &Object,
753 _template: &[CK_ATTRIBUTE],
754 ) -> Result<Object> {
755 Err(CKR_ACTION_PROHIBITED)?
756 }
757
758 fn get_data(&self) -> &ObjectFactoryData {
759 &self.data
760 }
761
762 fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
763 &mut self.data
764 }
765}
766
767#[derive(Debug, Eq, Hash, PartialEq)]
773pub struct ObjectType {
774 class: CK_ULONG,
775 type_: CK_ULONG,
776}
777
778impl ObjectType {
779 pub fn new(class: CK_ULONG, type_: CK_ULONG) -> ObjectType {
781 ObjectType {
782 class: class,
783 type_: type_,
784 }
785 }
786}
787
788#[derive(Debug)]
795pub struct ObjectFactories {
796 factories: HashMap<ObjectType, &'static Box<dyn ObjectFactory>>,
797}
798
799impl ObjectFactories {
800 pub fn new() -> ObjectFactories {
802 ObjectFactories {
803 factories: HashMap::new(),
804 }
805 }
806
807 pub fn add_factory(
809 &mut self,
810 otype: ObjectType,
811 templ: &'static Box<dyn ObjectFactory>,
812 ) {
813 self.factories.insert(otype, templ);
814 }
815
816 pub fn get_factory(
818 &self,
819 otype: ObjectType,
820 ) -> Result<&Box<dyn ObjectFactory>> {
821 match self.factories.get(&otype) {
822 Some(b) => Ok(b),
823 None => Err(CKR_ATTRIBUTE_VALUE_INVALID)?,
824 }
825 }
826
827 pub fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
830 let class = match template.iter().find(|a| a.type_ == CKA_CLASS) {
831 Some(c) => c.to_ulong()?,
832 None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
833 };
834 let type_ = match class {
835 CKO_DATA | CKO_TRUST | CKO_PROFILE | CKO_MECHANISM => 0,
836 #[cfg(feature = "nssdb")]
837 CKO_NSS_TRUST => 0,
838 CKO_CERTIFICATE => {
839 match template.iter().find(|a| a.type_ == CKA_CERTIFICATE_TYPE)
840 {
841 Some(c) => c.to_ulong()?,
842 None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
843 }
844 }
845 CKO_PUBLIC_KEY => {
846 match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
847 Some(k) => k.to_ulong()?,
848 None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
849 }
850 }
851 CKO_PRIVATE_KEY => {
852 match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
853 Some(k) => k.to_ulong()?,
854 None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
855 }
856 }
857 CKO_SECRET_KEY | CKO_OTP_KEY => {
858 match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
859 Some(k) => k.to_ulong()?,
860 None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
861 }
862 }
863 _ => return Err(CKR_TEMPLATE_INCONSISTENT)?,
870 };
871 self.get_factory(ObjectType::new(class, type_))?
872 .create(template)
873 }
874
875 pub fn get_object_factory(
877 &self,
878 obj: &Object,
879 ) -> Result<&Box<dyn ObjectFactory>> {
880 let class = obj.get_attr_as_ulong(CKA_CLASS)?;
881 let type_ = match class {
882 CKO_CERTIFICATE => obj.get_attr_as_ulong(CKA_CERTIFICATE_TYPE)?,
883 CKO_PUBLIC_KEY | CKO_PRIVATE_KEY | CKO_SECRET_KEY | CKO_OTP_KEY => {
884 obj.get_attr_as_ulong(CKA_KEY_TYPE)?
885 }
886 _ => 0,
887 };
888 self.get_factory(ObjectType::new(class, type_))
889 }
890
891 fn get_template_attribute(
892 oa: &Attribute,
893 ck_attr: &mut CK_ATTRIBUTE,
894 result: &mut CK_RV,
895 ) -> Result<()> {
896 let stored_attrs = oa.to_template()?;
897 let stored_count = stored_attrs.len();
898 let ck_attr_size = std::mem::size_of::<CK_ATTRIBUTE>();
899 let expected_len = CK_ULONG::try_from(stored_count * ck_attr_size)?;
900
901 if ck_attr.pValue.is_null() {
903 ck_attr.ulValueLen = expected_len;
904 return Ok(());
905 }
906
907 let val_len = usize::try_from(ck_attr.ulValueLen)?;
909 if val_len % ck_attr_size != 0 {
910 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
911 if *result == CKR_OK {
912 *result = CKR_TEMPLATE_INCONSISTENT;
913 }
914 return Ok(());
915 }
916
917 let app_count = val_len / ck_attr_size;
918 if app_count != stored_count {
919 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
920 if *result == CKR_OK {
921 *result = CKR_TEMPLATE_INCONSISTENT;
922 }
923 return Ok(());
924 }
925
926 if app_count == 0 {
927 ck_attr.ulValueLen = 0;
928 return Ok(());
929 }
930
931 let app_attrs: &mut [CK_ATTRIBUTE] = unsafe {
932 std::slice::from_raw_parts_mut(
933 ck_attr.pValue as *mut CK_ATTRIBUTE,
934 app_count,
935 )
936 };
937
938 let unavail_count = app_attrs
939 .iter()
940 .filter(|a| a.type_ == CK_UNAVAILABLE_INFORMATION)
941 .count();
942
943 if unavail_count != 0 && unavail_count != app_count {
944 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
945 if *result == CKR_OK {
946 *result = CKR_TEMPLATE_INCONSISTENT;
947 }
948 return Ok(());
949 }
950
951 if unavail_count == app_count {
953 if app_attrs
954 .iter()
955 .any(|a| !a.pValue.is_null() || a.ulValueLen != 0)
956 {
957 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
958 if *result == CKR_OK {
959 *result = CKR_TEMPLATE_INCONSISTENT;
960 }
961 return Ok(());
962 }
963
964 for i in 0..app_count {
965 app_attrs[i].type_ = stored_attrs[i].get_type();
966 app_attrs[i].ulValueLen =
967 CK_ULONG::try_from(stored_attrs[i].get_value().len())?;
968 app_attrs[i].pValue = std::ptr::null_mut();
969 }
970 ck_attr.ulValueLen = expected_len;
971 return Ok(());
972 }
973
974 for (idx, a) in app_attrs.iter().enumerate() {
976 if app_attrs[idx + 1..]
977 .iter()
978 .any(|other| other.type_ == a.type_)
979 {
980 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
981 if *result == CKR_OK {
982 *result = CKR_TEMPLATE_INCONSISTENT;
983 }
984 return Ok(());
985 }
986 }
987
988 for inner in app_attrs.iter_mut() {
989 match stored_attrs.iter().find(|sa| sa.get_type() == inner.type_) {
990 Some(sa) => {
991 let attr_val = sa.get_value();
992 let attr_len = CK_ULONG::try_from(attr_val.len())?;
993 if inner.pValue.is_null() {
994 inner.ulValueLen = attr_len;
995 } else if inner.ulValueLen == CK_UNAVAILABLE_INFORMATION {
996 if *result == CKR_OK {
997 *result = CKR_TEMPLATE_INCONSISTENT;
998 }
999 } else if inner.ulValueLen < attr_len {
1000 inner.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1001 if *result == CKR_OK {
1002 *result = CKR_BUFFER_TOO_SMALL;
1003 }
1004 } else {
1005 inner.ulValueLen = attr_len;
1006 unsafe {
1007 std::ptr::copy_nonoverlapping(
1008 attr_val.as_ptr(),
1009 inner.pValue as *mut u8,
1010 attr_val.len(),
1011 );
1012 }
1013 }
1014 }
1015 None => {
1016 inner.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1017 if *result == CKR_OK {
1018 *result = CKR_TEMPLATE_INCONSISTENT;
1019 }
1020 }
1021 }
1022 }
1023
1024 ck_attr.ulValueLen = expected_len;
1025 Ok(())
1026 }
1027
1028 pub fn check_sensitive(
1033 &self,
1034 obj: &Object,
1035 template: &[CK_ATTRIBUTE],
1036 ) -> Result<()> {
1037 let objtype_attrs =
1038 self.get_object_factory(obj)?.get_data().get_attributes();
1039 for ck_attr in template {
1040 match objtype_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
1041 None => return Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
1042 Some(attr) => {
1043 if attr.is(OAFlags::Sensitive) {
1044 return Err(CKR_ATTRIBUTE_SENSITIVE)?;
1045 }
1046 }
1047 }
1048 }
1049 Ok(())
1050 }
1051
1052 pub fn get_object_attributes(
1059 &self,
1060 obj: &Object,
1061 template: &mut [CK_ATTRIBUTE],
1062 ) -> Result<()> {
1063 let sensitive = obj.is_sensitive() || !obj.is_extractable();
1064 let mut result = CKR_OK;
1065
1066 let factory_attrs =
1067 self.get_object_factory(obj)?.get_data().get_attributes();
1068 let obj_attrs = obj.get_attributes();
1069
1070 for ck_attr in template.iter_mut() {
1071 let valid: bool;
1072
1073 match factory_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
1075 Some(fa) => {
1076 if sensitive && fa.is(OAFlags::Sensitive) {
1077 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1078 if result == CKR_OK {
1079 result = CKR_ATTRIBUTE_SENSITIVE;
1080 }
1081 valid = false;
1082 } else {
1083 valid = true;
1084 }
1085 }
1086 None => {
1087 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1089 if result == CKR_OK {
1090 result = CKR_ATTRIBUTE_TYPE_INVALID;
1091 }
1092 valid = false;
1093 }
1094 }
1095
1096 if !valid {
1097 continue;
1102 }
1103
1104 match obj_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
1105 Some(oa) => {
1106 if oa.get_attrtype() == AttrType::TemplateType {
1107 Self::get_template_attribute(oa, ck_attr, &mut result)?;
1108 continue;
1109 }
1110 let attr_val = oa.get_value();
1111 let attr_len = CK_ULONG::try_from(attr_val.len())?;
1112 if ck_attr.pValue.is_null() {
1113 ck_attr.ulValueLen = attr_len;
1114 } else if ck_attr.ulValueLen == CK_UNAVAILABLE_INFORMATION {
1115 if result == CKR_OK {
1116 result = CKR_TEMPLATE_INCONSISTENT;
1117 }
1118 } else {
1119 if ck_attr.ulValueLen < attr_len {
1120 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1121 if result == CKR_OK {
1122 result = CKR_BUFFER_TOO_SMALL;
1123 }
1124 } else {
1125 ck_attr.ulValueLen = attr_len;
1126 unsafe {
1127 std::ptr::copy_nonoverlapping(
1128 attr_val.as_ptr(),
1129 ck_attr.pValue as *mut _,
1130 attr_val.len(),
1131 );
1132 }
1133 }
1134 }
1135 }
1136 None => {
1137 ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
1139 if result == CKR_OK {
1140 result = CKR_ATTRIBUTE_TYPE_INVALID;
1141 }
1142 }
1143 }
1144 }
1145 if result == CKR_OK {
1146 Ok(())
1147 } else {
1148 Err(result)?
1149 }
1150 }
1151
1152 pub fn copy(
1155 &self,
1156 obj: &Object,
1157 template: &[CK_ATTRIBUTE],
1158 ) -> Result<Object> {
1159 if !obj.is_copyable() {
1160 return Err(CKR_ACTION_PROHIBITED)?;
1161 }
1162 self.get_object_factory(obj)?.copy(obj, template)
1163 }
1164
1165 pub fn get_obj_factory_from_key_template(
1168 &self,
1169 template: &[CK_ATTRIBUTE],
1170 ) -> Result<&Box<dyn ObjectFactory>> {
1171 let class = match template.iter().position(|x| x.type_ == CKA_CLASS) {
1172 Some(idx) => template[idx].to_ulong()?,
1173 None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
1174 };
1175 let key_type =
1176 match template.iter().position(|x| x.type_ == CKA_KEY_TYPE) {
1177 Some(idx) => template[idx].to_ulong()?,
1178 None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
1179 };
1180 self.get_factory(ObjectType::new(class, key_type))
1181 }
1182
1183 pub fn derive_key_from_template(
1186 &self,
1187 key: &Object,
1188 template: &[CK_ATTRIBUTE],
1189 ) -> Result<Object> {
1190 let factory = self.get_obj_factory_from_key_template(template)?;
1191 factory.as_key_factory()?.key_derive(template, key)
1192 }
1193}
1194
1195static DATA_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1197 LazyLock::new(|| Box::new(DataFactory::new()));
1198
1199static X509_CERT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1201 LazyLock::new(|| Box::new(X509Factory::new()));
1202
1203static TRUST_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1205 LazyLock::new(|| Box::new(TrustObject::new()));
1206
1207#[cfg(feature = "nssdb")]
1209static NSS_TRUST_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1210 LazyLock::new(|| Box::new(NSSTrustObject::new()));
1211
1212#[cfg(feature = "profiles")]
1214static PROFILE_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1215 LazyLock::new(|| Box::new(ProfileFactory::new()));
1216
1217static MECHANISM_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1219 LazyLock::new(|| Box::new(MechanismFactory::new()));
1220
1221static GENERIC_SECRET: LazyLock<Box<dyn Mechanism>> = LazyLock::new(|| {
1223 Box::new(GenericSecretKeyMechanism::new(CKK_GENERIC_SECRET))
1224});
1225
1226pub(crate) static GENERIC_SECRET_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
1228 LazyLock::new(|| Box::new(GenericSecretKeyFactory::new()));
1229
1230pub fn register(mechs: &mut Mechanisms, ot: &mut ObjectFactories) {
1233 mechs.add_mechanism(CKM_GENERIC_SECRET_KEY_GEN, &(*GENERIC_SECRET));
1234
1235 ot.add_factory(ObjectType::new(CKO_DATA, 0), &(*DATA_OBJECT_FACTORY));
1236 ot.add_factory(
1237 ObjectType::new(CKO_CERTIFICATE, CKC_X_509),
1238 &(*X509_CERT_FACTORY),
1239 );
1240 ot.add_factory(
1241 ObjectType::new(CKO_SECRET_KEY, CKK_GENERIC_SECRET),
1242 &(*GENERIC_SECRET_FACTORY),
1243 );
1244 ot.add_factory(ObjectType::new(CKO_TRUST, 0), &(*TRUST_OBJECT_FACTORY));
1245 #[cfg(feature = "nssdb")]
1246 ot.add_factory(
1247 ObjectType::new(CKO_NSS_TRUST, 0),
1248 &(*NSS_TRUST_OBJECT_FACTORY),
1249 );
1250 #[cfg(feature = "profiles")]
1251 ot.add_factory(ObjectType::new(CKO_PROFILE, 0), &(*PROFILE_FACTORY));
1252 ot.add_factory(ObjectType::new(CKO_MECHANISM, 0), &(*MECHANISM_FACTORY));
1253}
1254
1255#[cfg(test)]
1256mod tests {
1257 use super::*;
1258 use crate::attribute::serialize_template;
1259
1260 #[test]
1261 fn test_get_template_attribute_lifecycle() {
1262 let mut of = ObjectFactories::new();
1263 of.add_factory(
1264 ObjectType::new(CKO_SECRET_KEY, CKK_GENERIC_SECRET),
1265 &(*GENERIC_SECRET_FACTORY),
1266 );
1267
1268 let mut obj = Object::new(CKO_SECRET_KEY);
1269 obj.set_attr(Attribute::from_ulong(CKA_KEY_TYPE, CKK_GENERIC_SECRET))
1270 .unwrap();
1271 obj.set_attr(Attribute::from_bool(CKA_EXTRACTABLE, true))
1272 .unwrap();
1273 obj.set_attr(Attribute::from_bool(CKA_SENSITIVE, false))
1274 .unwrap();
1275
1276 let inner_attrs = vec![
1277 Attribute::from_bool(CKA_ENCRYPT, true),
1278 Attribute::from_ulong(CKA_VALUE_LEN, 32),
1279 ];
1280 let serialized = serialize_template(&inner_attrs).unwrap();
1281 obj.set_attr(Attribute::from_template_bytes(
1282 CKA_DERIVE_TEMPLATE,
1283 serialized,
1284 ))
1285 .unwrap();
1286
1287 let ck_attr_size = std::mem::size_of::<CK_ATTRIBUTE>();
1288
1289 let mut query = [CK_ATTRIBUTE {
1291 type_: CKA_DERIVE_TEMPLATE,
1292 pValue: std::ptr::null_mut(),
1293 ulValueLen: 0,
1294 }];
1295 assert!(of.get_object_attributes(&obj, &mut query).is_ok());
1296 assert_eq!(query[0].ulValueLen, (2 * ck_attr_size) as CK_ULONG);
1297
1298 let mut disc_attrs = [
1300 CK_ATTRIBUTE {
1301 type_: CK_UNAVAILABLE_INFORMATION,
1302 pValue: std::ptr::null_mut(),
1303 ulValueLen: 0,
1304 },
1305 CK_ATTRIBUTE {
1306 type_: CK_UNAVAILABLE_INFORMATION,
1307 pValue: std::ptr::null_mut(),
1308 ulValueLen: 0,
1309 },
1310 ];
1311 let mut query = [CK_ATTRIBUTE {
1312 type_: CKA_DERIVE_TEMPLATE,
1313 pValue: disc_attrs.as_mut_ptr() as *mut std::ffi::c_void,
1314 ulValueLen: (2 * ck_attr_size) as CK_ULONG,
1315 }];
1316 assert!(of.get_object_attributes(&obj, &mut query).is_ok());
1317 assert_eq!(disc_attrs[0].type_, CKA_ENCRYPT);
1318 assert_eq!(disc_attrs[0].ulValueLen, 1);
1319 assert!(disc_attrs[0].pValue.is_null());
1320 assert_eq!(disc_attrs[1].type_, CKA_VALUE_LEN);
1321 assert_eq!(disc_attrs[1].ulValueLen, sizeof!(CK_ULONG));
1322 assert!(disc_attrs[1].pValue.is_null());
1323
1324 let mut dummy = 0u8;
1326 disc_attrs[0].pValue = &mut dummy as *mut _ as *mut std::ffi::c_void;
1327 disc_attrs[0].type_ = CK_UNAVAILABLE_INFORMATION;
1328 disc_attrs[1].type_ = CK_UNAVAILABLE_INFORMATION;
1329 let mut query = [CK_ATTRIBUTE {
1330 type_: CKA_DERIVE_TEMPLATE,
1331 pValue: disc_attrs.as_mut_ptr() as *mut std::ffi::c_void,
1332 ulValueLen: (2 * ck_attr_size) as CK_ULONG,
1333 }];
1334 assert_eq!(
1335 of.get_object_attributes(&obj, &mut query).unwrap_err().rv(),
1336 CKR_TEMPLATE_INCONSISTENT
1337 );
1338
1339 disc_attrs[0].pValue = std::ptr::null_mut();
1341 disc_attrs[0].type_ = CKA_ENCRYPT;
1342 disc_attrs[1].type_ = CK_UNAVAILABLE_INFORMATION;
1343 let mut query = [CK_ATTRIBUTE {
1344 type_: CKA_DERIVE_TEMPLATE,
1345 pValue: disc_attrs.as_mut_ptr() as *mut std::ffi::c_void,
1346 ulValueLen: (2 * ck_attr_size) as CK_ULONG,
1347 }];
1348 assert_eq!(
1349 of.get_object_attributes(&obj, &mut query).unwrap_err().rv(),
1350 CKR_TEMPLATE_INCONSISTENT
1351 );
1352
1353 let mut enc_val: CK_BBOOL = CK_FALSE;
1355 let mut vlen_val: CK_ULONG = 0;
1356 let mut val_attrs = [
1357 CK_ATTRIBUTE {
1358 type_: CKA_ENCRYPT,
1359 pValue: &mut enc_val as *mut _ as *mut std::ffi::c_void,
1360 ulValueLen: sizeof!(CK_BBOOL),
1361 },
1362 CK_ATTRIBUTE {
1363 type_: CKA_VALUE_LEN,
1364 pValue: &mut vlen_val as *mut _ as *mut std::ffi::c_void,
1365 ulValueLen: sizeof!(CK_ULONG),
1366 },
1367 ];
1368 let mut query = [CK_ATTRIBUTE {
1369 type_: CKA_DERIVE_TEMPLATE,
1370 pValue: val_attrs.as_mut_ptr() as *mut std::ffi::c_void,
1371 ulValueLen: (2 * ck_attr_size) as CK_ULONG,
1372 }];
1373 assert!(of.get_object_attributes(&obj, &mut query).is_ok());
1374 assert_eq!(enc_val, CK_TRUE);
1375 assert_eq!(vlen_val, 32);
1376
1377 val_attrs[0].ulValueLen = 0;
1379 let mut query = [CK_ATTRIBUTE {
1380 type_: CKA_DERIVE_TEMPLATE,
1381 pValue: val_attrs.as_mut_ptr() as *mut std::ffi::c_void,
1382 ulValueLen: (2 * ck_attr_size) as CK_ULONG,
1383 }];
1384 assert_eq!(
1385 of.get_object_attributes(&obj, &mut query).unwrap_err().rv(),
1386 CKR_BUFFER_TOO_SMALL
1387 );
1388 assert_eq!(val_attrs[0].ulValueLen, CK_UNAVAILABLE_INFORMATION);
1389 }
1390}