Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions cryptoki/src/session/object_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,42 @@ impl Session {
}
}

/// Copy an object
///
/// A template can be provided to change some attributes of the new object, when allowed.
///
/// # Arguments
///
/// * `object` - The [ObjectHandle] used to reference the object to copy
/// * `template` - new values for any attributes of the object that can ordinarily be modified
/// check out [PKCS#11 documentation](https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/cs01/pkcs11-spec-v3.1-cs01.html#_Toc111203284) for details
///
/// # Returns
///
/// This function will return a new [ObjectHandle] that references the newly created object.
///
pub fn copy_object(
&self,
object: ObjectHandle,
template: &[Attribute],
) -> Result<ObjectHandle> {
let mut template: Vec<CK_ATTRIBUTE> = template.iter().map(|attr| attr.into()).collect();
let mut object_handle = 0;

unsafe {
Rv::from(get_pkcs11!(self.client(), C_CopyObject)(
self.handle(),
object.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
&mut object_handle as CK_OBJECT_HANDLE_PTR,
))
.into_result(Function::CopyObject)?;
}

Ok(ObjectHandle::new(object_handle))
}

/// Get the attribute info of an object: if the attribute is present and its size.
///
/// # Arguments
Expand Down
50 changes: 50 additions & 0 deletions cryptoki/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,56 @@ fn ro_rw_session_test() -> TestResult {
Ok(())
}

#[test]
#[serial]
fn session_copy_object() -> TestResult {
let aes128_template = [
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Encrypt(true),
Attribute::Token(false),
Attribute::Private(true),
Attribute::Sensitive(true),
Attribute::Extractable(false),
Attribute::ValueLen(16.into()),
Attribute::Label("original".as_bytes().to_vec()),
];

let copy_template = vec![Attribute::Label("copy".as_bytes().to_vec())];

let insecure_copy_template = vec![Attribute::Extractable(true)];

let (pkcs11, slot) = init_pins();

// open a session
let rw_session = pkcs11.open_rw_session(slot)?;

// log in the session
rw_session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;

// create a key object
let object = rw_session.generate_key(&Mechanism::AesKeyGen, &aes128_template)?;

// copy the object without a template
let copy = rw_session.copy_object(object, &[])?;
rw_session.destroy_object(copy)?;

// copy the object with a template
let copy = rw_session.copy_object(object, &copy_template)?;
rw_session.destroy_object(copy)?;

// try the copy with the insecure template. It should fail. Returning CKR_OK is considered a failure.
rw_session
.copy_object(object, &insecure_copy_template)
.unwrap_err();

// delete keys
rw_session.destroy_object(object)?;
rw_session.logout()?;

Ok(())
}

#[test]
#[serial]
fn aes_cbc_encrypt() -> TestResult {
Expand Down