Skip to content

Commit

Permalink
Provide Key::read_to_vec (#6)
Browse files Browse the repository at this point in the history
* Add `Key::read_to_vec` for easier reading into a vec
* Don't rely on libc for KEYCTL constants
* Update tests
* Bump version

Co-authored-by: landhb <landhb@users.noreply.github.com>
  • Loading branch information
landhb and landhb authored Oct 10, 2022
1 parent 943547c commit 9759cdf
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "linux-keyutils"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
authors = ["landhb <landhb@users.noreply.github.com>"]
description = """
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum KeyError {
/// Operation not supported
OperationNotSupported,

/// Write to destination failed
WriteError,

/// Unknown - catch all, return this instead of panicing
Unknown(i32),
}
Expand Down
64 changes: 32 additions & 32 deletions src/ffi/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,69 +63,69 @@ pub enum DefaultKeyring {
#[repr(u32)]
pub enum KeyCtlOperation {
/// Ask for a keyring's ID
GetKeyRingId = libc::KEYCTL_GET_KEYRING_ID,
GetKeyRingId = 0,
/// Join or start named session keyring
JoinSessionKeyRing = libc::KEYCTL_JOIN_SESSION_KEYRING,
JoinSessionKeyRing = 1,
/// Update a key
Update = libc::KEYCTL_UPDATE,
Update = 2,
/// Revoke a key
Revoke = libc::KEYCTL_REVOKE,
Revoke = 3,
/// Set ownership of a key
Chown = libc::KEYCTL_CHOWN,
Chown = 4,
/// Set permissions of a key
SetPerm = libc::KEYCTL_SETPERM,
SetPerm = 5,
/// Describe a key
Describe = libc::KEYCTL_DESCRIBE,
Describe = 6,
/// Clear contents of a keyring
Clear = libc::KEYCTL_CLEAR,
Clear = 7,
/// Link a key into a keyring
Link = libc::KEYCTL_LINK,
Link = 8,
/// Unlink a key from a keyring
Unlink = libc::KEYCTL_UNLINK,
Unlink = 9,
/// Search for a key in a keyring
Search = libc::KEYCTL_SEARCH,
Search = 10,
/// Read a key or keyring's contents
Read = libc::KEYCTL_READ,
Read = 11,
/// Instantiate a partially constructed key
Instantiate = libc::KEYCTL_INSTANTIATE,
Instantiate = 12,
/// Negate a partially constructed key
Negate = libc::KEYCTL_NEGATE,
Negate = 13,
/// Set default request-key keyring
SetRequestKeyKeyring = libc::KEYCTL_SET_REQKEY_KEYRING,
SetRequestKeyKeyring = 14,
/// Set timeout on a key
SetTimeout = libc::KEYCTL_SET_TIMEOUT,
SetTimeout = 15,
/// Assume authority to instantiate key
AssumeAuthority = libc::KEYCTL_ASSUME_AUTHORITY,
AssumeAuthority = 16,
/// Get key security label
GetSecurityLabel = libc::KEYCTL_GET_SECURITY,
GetSecurityLabel = 17,
/// Set my session keyring on my parent process
SessionToParent = libc::KEYCTL_SESSION_TO_PARENT,
SessionToParent = 18,
/// Reject a partially constructed key
Reject = libc::KEYCTL_REJECT,
Reject = 19,
/// Instantiate a partially constructed key
InstantiageIov = libc::KEYCTL_INSTANTIATE_IOV,
InstantiageIov = 20,
/// Invalidate a key
Invalidate = libc::KEYCTL_INVALIDATE,
Invalidate = 21,
/// Get a user's persistent keyring
GetPersistent = libc::KEYCTL_GET_PERSISTENT,
GetPersistent = 22,
/// Compute Diffie-Hellman values
DiffieHellmanCompute = libc::KEYCTL_DH_COMPUTE,
DiffieHellmanCompute = 23,
/// Query public key parameters
PubkeyQuery = libc::KEYCTL_PKEY_QUERY,
PubkeyQuery = 24,
/// Encrypt a blob using a public key
PubkeyEncrypt = libc::KEYCTL_PKEY_ENCRYPT,
PubkeyEncrypt = 25,
/// Decrypt a blob using a public key
PubkeyDecrypt = libc::KEYCTL_PKEY_DECRYPT,
PubkeyDecrypt = 26,
/// Create a public key signature
PubkeySign = libc::KEYCTL_PKEY_SIGN,
PubkeySign = 27,
/// Verify a public key signature
PubkeyVerify = libc::KEYCTL_PKEY_VERIFY,
PubkeyVerify = 28,
/// Restrict keys allowed to link to a keyring
RestrictKeyring = libc::KEYCTL_RESTRICT_KEYRING,
RestrictKeyring = 29,
/// Move keys between keyrings
Move = libc::KEYCTL_MOVE,
Move = 30,
/// Find capabilities of keyrings subsystem
Capabilities = libc::KEYCTL_CAPABILITIES,
Capabilities = 31,
/// Watch a key or ring of keys for changes
WatchKey = 32,
}
Expand Down
45 changes: 44 additions & 1 deletion src/key.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::ffi::{self, KeyCtlOperation, KeySerialId};
use crate::utils::Vec;
use crate::{KeyError, KeyPermissions, Metadata};
use core::fmt;

Expand Down Expand Up @@ -57,7 +58,9 @@ impl Key {
Metadata::from_id(self.0)
}

/// Read the payload data of a key.
/// Read the payload data of a key into a provided mutable slice.
///
/// The returned usize is the number of bytes read into the slice.
///
/// The key must either grant the caller read permission, or grant
/// the caller search permission when searched for from the process
Expand All @@ -73,6 +76,30 @@ impl Key {
Ok(len)
}

/// Read the payload data of a key, returning a newly allocated vector.
///
/// The key must either grant the caller read permission, or grant
/// the caller search permission when searched for from the process
/// keyrings (i.e., the key is possessed).
pub fn read_to_vec(&self) -> Result<Vec<u8>, KeyError> {
// Ensure we have enough room to write up to the maximum for a UserKey
let mut buffer = Vec::with_capacity(65536);

// Obtain the key
let len = ffi::keyctl!(
KeyCtlOperation::Read,
self.0.as_raw_id() as libc::c_ulong,
buffer.as_mut_ptr() as _,
buffer.capacity() as _
)? as usize;

// Update length
unsafe {
buffer.set_len(len);
}
Ok(buffer)
}

/// Update a key's data payload.
///
/// The caller must have write permission on the key specified and the key
Expand Down Expand Up @@ -229,6 +256,22 @@ mod tests {
key.invalidate().unwrap()
}

#[test]
fn test_read_into_vec() {
let secret = "Test Data";

// Obtain the default User keyring
let ring = KeyRing::from_special_id(KeyRingIdentifier::Session, false).unwrap();

// Create the key
let key = ring.add_key("vec-read-key", secret).unwrap();

// Verify the payload
let payload = key.read_to_vec().unwrap();
assert_eq!(secret.as_bytes(), &payload);
key.invalidate().unwrap();
}

#[test]
fn test_user_keyring_add_key() {
let secret = "Test Data";
Expand Down

0 comments on commit 9759cdf

Please sign in to comment.