[client] Unused dependencies, certificate documentation and minor improvements
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Armin Friedl 2020-02-08 22:12:04 +01:00
parent 7515462433
commit e7fbb4e47c
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
4 changed files with 76 additions and 35 deletions

2
Cargo.lock generated
View file

@ -88,9 +88,7 @@ dependencies = [
"exec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "exec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View file

@ -12,8 +12,6 @@ log = "0.4"
env_logger="0.7" env_logger="0.7"
structopt = "0.3" structopt = "0.3"
# Communication # Communication
serde = { version = "1.0", features = ["derive"]}
serde_yaml = "0.8"
serde_cbor = "0.10.2" serde_cbor = "0.10.2"
# Executing subcommand # Executing subcommand
exec = "0.3.1" exec = "0.3.1"

View file

@ -1,9 +1,12 @@
//! # Coffer client
//!
//! Retrieve a secret shard from a `coffer-server`. Secrets in the shard are set
//! as environment variables for the spawned subcommand `cmd`.
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use env_logger; use env_logger;
use structopt::StructOpt;
use std:: { use std:: {
net::TcpStream, net::TcpStream,
error::Error, error::Error,
@ -12,9 +15,14 @@ use std:: {
convert::{TryInto, TryFrom} convert::{TryInto, TryFrom}
}; };
use coffer_common::certificate::Certificate; use coffer_common::{
use coffer_common::coffer::{CofferShard, CofferValue}; coffer::{CofferShard, CofferValue},
certificate::Certificate
};
use structopt::StructOpt;
/// Client for setting up the environment from coffer server secrets
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
struct Args { struct Args {
/// Address of the coffer server /// Address of the coffer server
@ -75,6 +83,8 @@ fn main() -> Result<(), Box<dyn Error>> {
Err("Could not spawn sub-command".into()) Err("Could not spawn sub-command".into())
} }
/// Replaces the `coffer-client` process image with
/// the subcommand `cmd` with `args`
fn reap_coffer(cmd: &str, args: &[String]) { fn reap_coffer(cmd: &str, args: &[String]) {
let mut cmd = exec::Command::new(cmd); let mut cmd = exec::Command::new(cmd);

View file

@ -1,12 +1,20 @@
//! Common certificate handling and encryption //! A keypair contianer providing functionality for signing, encryption and
//! decryption
//!
//! # Base libraries
//! The cryptographic operations exposed by this module are based on the
//! [NaCl](http://nacl.cr.yp.to/) fork [libsodium](https://libsodium.org) as
//! exposed by the rust bindings [sodiumoxide](https://crates.io/crates/sodiumoxide).
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use std::path::Path; use std::{
use std::io::BufReader; path::Path,
use std::fs::File; io::BufReader,
use std::fmt::{Debug, Formatter}; fs::File,
ops::Deref
};
use quick_error::quick_error; use quick_error::quick_error;
@ -25,22 +33,51 @@ quick_error! {
Io(err: std::io::Error) { Io(err: std::io::Error) {
from() from()
} }
SecKey SecKey {
from(CertificateInner)
}
Crypto Crypto
} }
} }
/// A secure container for certificates /// A secure container for a keypair
/// ///
/// # Certificate /// Secure means a best effort approach to:
/// - Prevent swapping memory to disk
/// - Zeroing out memory upon dropping
/// - Prevent other processes and buffer overflows to access the secure memory
/// area
/// ///
/// A certificate consists of a public and a private key in a secure memory /// These guarantees are currently *not* reliable. If you threat model contains
/// area. With a certificate data sealed and opened. /// targeted attacks against coffer memory, additional precautions have to be
/// taken.
pub struct Certificate { pub struct Certificate {
inner: SecKey<CertificateInner> inner: SecKey<CertificateInner>
} }
// The SecKeyReadGuard prevents convenience methods for handing out references
// to private/public keys (reference outlives SecKeyReadGuard). Hence below
// macros are shortcut projections that can be used after a read guard is
// created
// Get the public key
macro_rules! pk {
($cert:ident) => {
&$cert.inner.read().public_key
};
}
// Get the private key
macro_rules! sk {
($cert:ident) => {
&$cert.inner.read().private_key
};
}
// Certificate and its inner SecKey own their
// raw pointer without any thread local behaviour
unsafe impl Send for Certificate {} unsafe impl Send for Certificate {}
// After initialization, certificate is read-only
unsafe impl Sync for Certificate {} unsafe impl Sync for Certificate {}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -49,13 +86,8 @@ struct CertificateInner {
private_key: box_::SecretKey private_key: box_::SecretKey
} }
impl Debug for CertificateInner {
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
write!(fmt, "<Certificate Hidden>")
}
}
impl Certificate { impl Certificate {
/// Initialize with a generated keypair
pub fn new() -> Result<Certificate, CertificateError> { pub fn new() -> Result<Certificate, CertificateError> {
debug!{"Generating new certificate"} debug!{"Generating new certificate"}
let (public_key, private_key) = box_::gen_keypair(); let (public_key, private_key) = box_::gen_keypair();
@ -66,6 +98,7 @@ impl Certificate {
Ok(Certificate{inner}) Ok(Certificate{inner})
} }
/// Initialize from a serialized certificate in [cbor](https://cbor.io/) format
pub fn new_from_cbor<T: AsRef<Path>>(path: T) -> Result<Certificate, CertificateError> { pub fn new_from_cbor<T: AsRef<Path>>(path: T) -> Result<Certificate, CertificateError> {
debug!{"Reading certificate from {}", path.as_ref().display()} debug!{"Reading certificate from {}", path.as_ref().display()}
let f = File::open(path)?; let f = File::open(path)?;
@ -76,33 +109,35 @@ impl Certificate {
Ok(Certificate{inner}) Ok(Certificate{inner})
} }
/// Serialize a certificate to a file in [cbor](https://cbor.io/) format
#[cfg(feature = "export")] #[cfg(feature = "export")]
pub fn to_cbor(&self) -> Result<Vec<u8>, CertificateError> { pub fn to_cbor(&self) -> Result<Vec<u8>, CertificateError> {
let inner_cert = &*self.inner.read(); let read_guard = self.inner.read();
let cbor = serde_cbor::to_vec(inner_cert)?;
let cbor = serde_cbor::to_vec(read_guard.deref())?;
Ok(cbor) Ok(cbor)
} }
/// Clone the bytes of the public key
pub fn public_key(&self) -> Vec<u8> { pub fn public_key(&self) -> Vec<u8> {
self.inner.read().public_key.as_ref().to_owned() pk!(self).as_ref().to_owned()
} }
/// Clone the bytes of the private key
#[cfg(feature = "export")] #[cfg(feature = "export")]
pub fn secret_key(&self) -> Vec<u8> { pub fn secret_key(&self) -> Vec<u8> {
self.inner.read().private_key.as_ref().to_owned() sk!(self).as_ref().to_owned()
} }
/// Open a [sealed box](https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes)
pub fn open(&self, c: &[u8]) -> Result<Vec<u8>, CertificateError> { pub fn open(&self, c: &[u8]) -> Result<Vec<u8>, CertificateError> {
let pk = &self.inner.read().public_key; sealedbox::open(c, pk!{self}, sk!{self})
let sk = &self.inner.read().private_key;
sealedbox::open(c, pk, sk)
.map_err(|_| CertificateError::Crypto) .map_err(|_| CertificateError::Crypto)
} }
/// Seal a message in a [sealed box](https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes)
pub fn seal(&self, message: &[u8]) -> Result<Vec<u8>, CertificateError> { pub fn seal(&self, message: &[u8]) -> Result<Vec<u8>, CertificateError> {
let pk = &self.inner.read().public_key; Ok(sealedbox::seal(message, pk!{self}))
Ok(sealedbox::seal(message, pk))
} }
} }