diff --git a/cryptoki/src/session/object_management.rs b/cryptoki/src/session/object_management.rs index db811ed4..65f77d72 100644 --- a/cryptoki/src/session/object_management.rs +++ b/cryptoki/src/session/object_management.rs @@ -194,3 +194,22 @@ pub(super) fn get_attributes( // Convert from CK_ATTRIBUTE to Attribute template.into_iter().map(|attr| attr.try_into()).collect() } + +impl Session { + /// Sets the attributes of an object + pub fn update_attributes(&self, object: ObjectHandle, template: &[Attribute]) -> Result<()> { + let mut template: Vec = template.iter().map(|attr| attr.into()).collect(); + + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SetAttributeValue)( + self.handle(), + object.handle(), + template.as_mut_ptr(), + template.len().try_into()?, + )) + .into_result()?; + } + + Ok(()) + } +} diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index b4b72727..894ead85 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -826,3 +826,46 @@ fn aes_cbc_pad_encrypt() -> TestResult { assert_eq!(expected_cipher[..], cipher[..]); Ok(()) } + +#[test] +#[serial] +fn update_attributes_key() -> TestResult { + let (pkcs11, slot) = init_pins(); + // open a session + let session = pkcs11.open_rw_session(slot)?; + + // log in the session + session.login(UserType::User, Some(USER_PIN))?; + + // pub key template + let pub_key_template = vec![ + Attribute::Token(true), + Attribute::Private(true), + Attribute::PublicExponent(vec![0x01, 0x00, 0x01]), + Attribute::ModulusBits(1024.into()), + ]; + + // priv key template + let priv_key_template = vec![Attribute::Token(true), Attribute::Extractable(true)]; + + let (_public_key, private_key) = session.generate_key_pair( + &Mechanism::RsaPkcsKeyPairGen, + &pub_key_template, + &priv_key_template, + )?; + + let updated_attributes = vec![Attribute::Extractable(false)]; + + session.update_attributes(private_key, &updated_attributes)?; + + let mut attributes_result = + session.get_attributes(private_key, &[AttributeType::Extractable])?; + + if let Some(Attribute::Extractable(ext)) = attributes_result.pop() { + assert!(!ext); + } else { + panic!("Last attribute was not extractable"); + } + + Ok(()) +}