Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 35 additions & 0 deletions cryptoki/src/session/object_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,41 @@ impl Session {
}
}

/// Copy an object
/// A optional 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` - an optional reference to a slice of attributes, in the form of `Some(&[Attribute])`,
/// or set to `None`` if not needed.
///
/// # Returns
///
/// This function will return a new [ObjectHandle] that references the newly created object.
///
pub fn copy_object(&self, object: ObjectHandle, template: Option<&[Attribute]>) -> Result<ObjectHandle> {
let mut template: Vec<CK_ATTRIBUTE> = match template {
Some(template) => template.iter().map(|attr| attr.into()).collect(),
None => Vec::new(),
};

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::CreateObject)?;
}

Ok(ObjectHandle::new(object_handle))
}

/// Get the attribute info of an object: if the attribute is present and its size.
///
/// # Arguments
Expand Down
53 changes: 53 additions & 0 deletions cryptoki/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,59 @@ 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, None)?;
rw_session.destroy_object(copy)?;

// copy the object with a template
let copy = rw_session.copy_object(object, Some(&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, Some(&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