summaryrefslogtreecommitdiff
path: root/src/bin/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/server.rs')
-rw-r--r--src/bin/server.rs170
1 files changed, 130 insertions, 40 deletions
diff --git a/src/bin/server.rs b/src/bin/server.rs
index f62e4c2..ef1f46c 100644
--- a/src/bin/server.rs
+++ b/src/bin/server.rs
@@ -2,72 +2,77 @@
//! Roughtime server
//!
+extern crate byteorder;
extern crate core;
extern crate ring;
-extern crate untrusted;
extern crate roughenough;
+extern crate time;
+extern crate untrusted;
+
+use std::io;
-use core::ptr;
+use std::net::UdpSocket;
+use std::time::Duration;
use untrusted::Input;
+
use roughenough::{RtMessage, Tag, Error};
use roughenough::hex::*;
+use roughenough::{CERTIFICATE_CONTEXT, SIGNED_RESPONSE_CONTEXT, TREE_LEAF_TWEAK};
-use ring::{digest, rand};
+use ring::{digest, error, rand};
use ring::rand::SecureRandom;
use ring::signature::Ed25519KeyPair;
-/// Zero all bytes in dst
-#[inline]
-pub fn zero(dst: &mut [u8]) {
- unsafe {
- ptr::write_bytes(dst.as_mut_ptr(), 0u8, dst.len());
- }
-}
-
-fn main() {
- // Read long-term key
- let long_term_key = {
- let mut seed = [b'x'; 32];
-
- let lt_key = Ed25519KeyPair::from_seed_unchecked(Input::from(&seed)).unwrap();
- println!("Long-term public key: {}", lt_key.public_key_bytes().to_hex());
-
- lt_key
- };
+use byteorder::{LittleEndian, WriteBytesExt};
- // Create DELE
- let ephemeral_key = {
- let rng = rand::SystemRandom::new();
- let mut seed = [0u8; 32];
- rng.fill(&mut seed).unwrap();
+fn get_long_term_key() -> Result<Ed25519KeyPair, error::Unspecified> {
+ // TODO: read from config
+ let seed = [b'x'; 32];
+ Ed25519KeyPair::from_seed_unchecked(Input::from(&seed))
+}
- let eph_key = Ed25519KeyPair::from_seed_unchecked(Input::from(&seed)).unwrap();
- println!("Ephemeral public key: {}", eph_key.public_key_bytes().to_hex());
+fn make_ephemeral_key() -> Result<Ed25519KeyPair, error::Unspecified> {
+ let rng = rand::SystemRandom::new();
+ let mut seed = [0u8; 32];
+ rng.fill(&mut seed).unwrap();
- eph_key
- };
+ Ed25519KeyPair::from_seed_unchecked(Input::from(&seed))
+}
+fn make_dele_bytes(ephemeral_key: &Ed25519KeyPair) -> Result<Vec<u8>, Error> {
let zeros = [0u8; 8];
let max = [0xff; 8];
let mut dele_msg = RtMessage::new(3);
- dele_msg.add_field(Tag::PUBK, &ephemeral_key.public_key_bytes()).unwrap();
- dele_msg.add_field(Tag::MINT, &zeros).unwrap();
- dele_msg.add_field(Tag::MAXT, &max).unwrap();
+ dele_msg.add_field(Tag::PUBK, &ephemeral_key.public_key_bytes())?;
+ dele_msg.add_field(Tag::MINT, &zeros)?;
+ dele_msg.add_field(Tag::MAXT, &max)?;
- let dele_bytes = dele_msg.encode().unwrap();
+ dele_msg.encode()
+}
+
+fn make_cert(long_term_key: &Ed25519KeyPair, ephemeral_key: &Ed25519KeyPair) -> RtMessage {
+ // Make DELE and sign it with long-term key
+ let dele_bytes = make_dele_bytes(&ephemeral_key).unwrap();
+ let dele_sig = {
+ let mut sha_ctx = digest::Context::new(&digest::SHA512);
+ sha_ctx.update(CERTIFICATE_CONTEXT.as_bytes());
+ sha_ctx.update(&dele_bytes);
+ let digest = sha_ctx.finish();
- println!("{}", dele_bytes.to_hex());
+ long_term_key.sign(digest.as_ref())
+ };
- // Sign it with long-term key
// Create CERT
+ let mut cert_msg = RtMessage::new(2);
+ cert_msg.add_field(Tag::SIG, dele_sig.as_ref()).unwrap();
+ cert_msg.add_field(Tag::DELE, &dele_bytes).unwrap();
- // Wipe long-term key
+ cert_msg
+}
- // loop:
- // read request
- // validate request or goto loop
+fn make_response(ephemeral_key: &Ed25519KeyPair, cert_bytes: &[u8], request: &[u8]) -> RtMessage {
// create SREP
// sign SREP
// create response:
@@ -76,6 +81,91 @@ fn main() {
// - SREP
// - CERT (pre-created)
// - INDX (always 0)
+
+ let path = [0u8; 0];
+ let zeros = [0u8; 4];
+
+ let mut radi: Vec<u8> = Vec::with_capacity(4);
+ let mut midp: Vec<u8> = Vec::with_capacity(8);
+
+ // TODO: populate
+ let mut nonce = vec![0u8; 64];
+
+ // one second (in microseconds)
+ radi.write_u32::<LittleEndian>(1000000).unwrap();
+
+ // current epoch time in microseconds
+ let now = (time::get_time().sec as u64) * 1000;
+ midp.write_u64::<LittleEndian>(now).unwrap();
+
+ // Signed response SREP
+ let srep_bytes = {
+ // hash request nonce
+ let mut ctx = digest::Context::new(&digest::SHA512);
+ ctx.update(&TREE_LEAF_TWEAK);
+ ctx.update(&nonce);
+ let digest = ctx.finish();
+
+ let mut srep_msg = RtMessage::new(3);
+ srep_msg.add_field(Tag::RADI, &radi).unwrap();
+ srep_msg.add_field(Tag::MIDP, &midp).unwrap();
+ srep_msg.add_field(Tag::ROOT, digest.as_ref()).unwrap();
+
+ srep_msg.encode().unwrap()
+ };
+
+ // signature on SREP
+ let signature = {
+ let mut sha_ctx = digest::Context::new(&digest::SHA512);
+ sha_ctx.update(SIGNED_RESPONSE_CONTEXT.as_bytes());
+ sha_ctx.update(&srep_bytes);
+ let digest = sha_ctx.finish();
+
+ ephemeral_key.sign(digest.as_ref())
+ };
+
+ let mut response = RtMessage::new(5);
+ response.add_field(Tag::SIG, signature.as_ref()).unwrap();
+ response.add_field(Tag::PATH, &path).unwrap();
+ response.add_field(Tag::SREP, &srep_bytes).unwrap();
+ response.add_field(Tag::CERT, cert_bytes).unwrap();
+ response.add_field(Tag::INDX, &zeros).unwrap();
+
+ response
+}
+
+fn main() {
+ let lt_key = get_long_term_key().expect("failed to obtain long-term key");
+ let ephemeral_key = make_ephemeral_key().expect("failed to create ephemeral key");
+
+ println!("Long-term public key: {}", lt_key.public_key_bytes().to_hex());
+ println!("Ephemeral public key: {}", ephemeral_key.public_key_bytes().to_hex());
+
+ let cert_msg = make_cert(&lt_key, &ephemeral_key);
+ let cert_bytes = cert_msg.encode().unwrap();
+
+ let mut socket = UdpSocket::bind("127.0.0.1:8686").expect("failed to bind to socket");
+ socket.set_read_timeout(Some(Duration::from_secs(1))).expect("could not set read timeout");
+
+ let mut buf = [0u8; 65536];
+ let mut loops = 0u64;
+
+ loop {
+ match socket.recv_from(&mut buf) {
+ Ok((num_bytes, src_addr)) => {
+ println!("{} bytes from {}", num_bytes, src_addr);
+ let resp = make_response(&ephemeral_key, &cert_bytes, &buf[..num_bytes]);
+ println!("response {:?}", resp.encode().unwrap().to_hex());
+ },
+ Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => loops += 1,
+ Err(ref e) => println!("Error {:?}: {:?}", e.kind(), e)
+ }
+ }
+
+
+ // loop:
+ // read request
+ // validate request or goto loop
// send response
}