Documentation cleanup #5
4 changed files with 76 additions and 35 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue