forked from brl/citadel-tools
implemented some extra functionality
This commit is contained in:
parent
533ed4b8be
commit
e493e5180d
@ -21,7 +21,7 @@ use sodiumoxide::crypto::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Result,Error};
|
use crate::{Result,Error,KeyPair};
|
||||||
|
|
||||||
#[derive(Serialize,Deserialize,Debug)]
|
#[derive(Serialize,Deserialize,Debug)]
|
||||||
pub struct KeyRing {
|
pub struct KeyRing {
|
||||||
@ -38,7 +38,7 @@ impl KeyRing {
|
|||||||
|
|
||||||
pub fn load<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<KeyRing> {
|
pub fn load<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<KeyRing> {
|
||||||
let mut sbox = SecretBox::new(path.as_ref());
|
let mut sbox = SecretBox::new(path.as_ref());
|
||||||
sbox.read()?;
|
sbox.read().map_err(|e| format_err!("Error reading keyring file: {}", e))?;
|
||||||
let mut bytes = sbox.open(passphrase)?;
|
let mut bytes = sbox.open(passphrase)?;
|
||||||
let keyring = toml::from_slice::<KeyRing>(&bytes)?;
|
let keyring = toml::from_slice::<KeyRing>(&bytes)?;
|
||||||
bytes.iter_mut().for_each(|b| *b = 0);
|
bytes.iter_mut().for_each(|b| *b = 0);
|
||||||
@ -51,7 +51,7 @@ impl KeyRing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cryptsetup_passphrase() -> Result<String> {
|
fn get_cryptsetup_passphrase() -> Result<String> {
|
||||||
let key = KernelKey::request_key("user", "cryptsetup")?;
|
let key = KeyRing::get_key("cryptsetup")?;
|
||||||
info!("Got key {}", key.0);
|
info!("Got key {}", key.0);
|
||||||
let buf = key.read()?;
|
let buf = key.read()?;
|
||||||
match buf.split(|b| *b == 0).map(|bs| String::from_utf8_lossy(bs).to_string()).last() {
|
match buf.split(|b| *b == 0).map(|bs| String::from_utf8_lossy(bs).to_string()).last() {
|
||||||
@ -60,14 +60,38 @@ impl KeyRing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_key(name: &str) -> Result<KernelKey> {
|
||||||
|
if let Ok(key) = KernelKey::user_keyring().search(name) {
|
||||||
|
debug!("Found {} key in user keyring: (keyid: {:08x})", name, key.0);
|
||||||
|
if let Err(e) = key.read() {
|
||||||
|
info!("err tho on read: {}", e);
|
||||||
|
} else {
|
||||||
|
return Ok(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Ok(key) = KernelKey::request_key("user", name) {
|
||||||
|
info!("Found {} key with request_key", name);
|
||||||
|
return Ok(key);
|
||||||
|
}
|
||||||
|
return Err(format_err!("kernel key '{}' not found", name))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_keys_to_kernel(&self) -> Result<()> {
|
pub fn add_keys_to_kernel(&self) -> Result<()> {
|
||||||
for (k,v) in self.keypairs.iter() {
|
for (k,v) in self.keypairs.iter() {
|
||||||
info!("Adding {} to kernel keystore", k.as_str());
|
info!("Adding {} to kernel keystore", k.as_str());
|
||||||
let _key = KernelKey::add_key("user", k.as_str(), v.as_bytes(), KEY_SPEC_USER_KEYRING)?;
|
let bytes = hex::decode(v)?;
|
||||||
|
let key = KernelKey::add_key("user", k.as_str(), &bytes, KEY_SPEC_USER_KEYRING)?;
|
||||||
|
key.set_perm(0x3f030000)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_kernel_keypair(name: &str) -> Result<KeyPair> {
|
||||||
|
let key = KeyRing::get_key(name)?;
|
||||||
|
let data = key.read()?;
|
||||||
|
KeyPair::from_bytes(&data)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write<P: AsRef<Path>>(&self, path: P, passphrase: &str) -> Result<()> {
|
pub fn write<P: AsRef<Path>>(&self, path: P, passphrase: &str) -> Result<()> {
|
||||||
let salt = pwhash::gen_salt();
|
let salt = pwhash::gen_salt();
|
||||||
let nonce = secretbox::gen_nonce();
|
let nonce = secretbox::gen_nonce();
|
||||||
@ -143,13 +167,23 @@ impl SecretBox {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const KEYCTL_GET_KEYRING_ID : c_int = 0; // ask for a keyring's ID
|
||||||
|
const KEYCTL_SETPERM : c_int = 5; // set perms on a key
|
||||||
|
const KEYCTL_DESCRIBE : c_int = 6; // describe a key
|
||||||
|
const KEYCTL_SEARCH : c_int = 10; // search for a key in a keyring
|
||||||
const KEYCTL_READ : c_int = 11; // read a key or keyring's contents
|
const KEYCTL_READ : c_int = 11; // read a key or keyring's contents
|
||||||
|
|
||||||
const KEY_SPEC_USER_KEYRING : c_int = -4; // - key ID for UID-specific keyring
|
const KEY_SPEC_USER_KEYRING : c_int = -4; // - key ID for UID-specific keyring
|
||||||
|
|
||||||
|
|
||||||
pub struct KernelKey(int32_t);
|
pub struct KernelKey(int32_t);
|
||||||
|
|
||||||
impl KernelKey {
|
impl KernelKey {
|
||||||
|
|
||||||
|
pub fn user_keyring() -> KernelKey {
|
||||||
|
KernelKey(KEY_SPEC_USER_KEYRING)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_key(key_type: &str, description: &str) -> Result<KernelKey> {
|
pub fn request_key(key_type: &str, description: &str) -> Result<KernelKey> {
|
||||||
let key_type = CString::new(key_type).unwrap();
|
let key_type = CString::new(key_type).unwrap();
|
||||||
let description = CString::new(description).unwrap();
|
let description = CString::new(description).unwrap();
|
||||||
@ -164,11 +198,40 @@ impl KernelKey {
|
|||||||
Ok(KernelKey(serial as i32))
|
Ok(KernelKey(serial as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_keyring_id(&self, create: bool) -> Result<KernelKey> {
|
||||||
|
let serial = keyctl2(KEYCTL_GET_KEYRING_ID, self.id(), create as u64)?;
|
||||||
|
Ok(KernelKey(serial as i32))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_perm(&self, perm: u32) -> Result<()> {
|
||||||
|
keyctl2(KEYCTL_SETPERM, self.id(), perm as u64)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn describe(&self) -> Result<String> {
|
||||||
|
let mut size = 0;
|
||||||
|
loop {
|
||||||
|
size = match self.buffer_request(KEYCTL_DESCRIBE, size) {
|
||||||
|
BufferResult::Err(err) => return Err(format_err!("Error calling KEYCTL_DESCRIBE on key: {}", err)),
|
||||||
|
BufferResult::Ok(vec) => return Ok(String::from_utf8(vec).expect("KEYCTL_DESCRIBE returned bad utf8")),
|
||||||
|
BufferResult::TooSmall(sz) => sz,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn search(&self, description: &str) -> Result<KernelKey> {
|
||||||
|
let key_type = CString::new("user").unwrap();
|
||||||
|
let description = CString::new(description).unwrap();
|
||||||
|
|
||||||
|
let serial = keyctl4(KEYCTL_SEARCH, self.id(), key_type.as_ptr() as u64, description.as_ptr() as u64, 0)?;
|
||||||
|
Ok(KernelKey(serial as i32))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read(&self) -> Result<Vec<u8>> {
|
pub fn read(&self) -> Result<Vec<u8>> {
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
loop {
|
loop {
|
||||||
size = match self.buffer_request(KEYCTL_READ, size) {
|
size = match self.buffer_request(KEYCTL_READ, size) {
|
||||||
BufferResult::Err(err) => return Err(err),
|
BufferResult::Err(err) => return Err(format_err!("Error reading key: {}", err)),
|
||||||
BufferResult::Ok(buffer) => return Ok(buffer),
|
BufferResult::Ok(buffer) => return Ok(buffer),
|
||||||
BufferResult::TooSmall(sz) => sz + 1,
|
BufferResult::TooSmall(sz) => sz + 1,
|
||||||
}
|
}
|
||||||
@ -212,14 +275,22 @@ enum BufferResult {
|
|||||||
|
|
||||||
|
|
||||||
fn keyctl1(command: c_int, arg2: c_ulong) -> Result<c_long> {
|
fn keyctl1(command: c_int, arg2: c_ulong) -> Result<c_long> {
|
||||||
_keyctl(command, arg2, 0, 0, 0)
|
sys_keyctl(command, arg2, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keyctl2(command: c_int, arg2: c_ulong, arg3: c_ulong) -> Result<c_long> {
|
||||||
|
sys_keyctl(command, arg2, arg3, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyctl3(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong) -> Result<c_long> {
|
fn keyctl3(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong) -> Result<c_long> {
|
||||||
_keyctl(command, arg2, arg3, arg4, 0)
|
sys_keyctl(command, arg2, arg3, arg4, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _keyctl(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
fn keyctl4(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
||||||
|
sys_keyctl(command, arg2, arg3, arg4, arg5)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sys_keyctl(command: c_int, arg2: c_ulong, arg3: c_ulong, arg4: c_ulong, arg5: c_ulong) -> Result<c_long> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = libc::syscall(libc::SYS_keyctl, command, arg2, arg3, arg4, arg5);
|
let r = libc::syscall(libc::SYS_keyctl, command, arg2, arg3, arg4, arg5);
|
||||||
if r == -1 {
|
if r == -1 {
|
||||||
|
Loading…
Reference in New Issue
Block a user