From cda7a60a1348b1932fe08459d311ddf9e5e1f949 Mon Sep 17 00:00:00 2001 From: noproto Date: Thu, 26 Dec 2019 17:15:14 -0500 Subject: [PATCH] WB 0.1.0: Crypto interface, relocate log table --- src/application/Cargo.toml | 2 +- src/application/common/api/mod.rs | 21 ++++++++- src/application/common/api/service.rs | 37 +++++++++++++++ src/application/common/crypto.rs | 65 ++++++++++++++------------- src/application/common/db.rs | 4 +- src/library/Cargo.toml | 2 +- 6 files changed, 94 insertions(+), 37 deletions(-) create mode 100644 src/application/common/api/service.rs diff --git a/src/application/Cargo.toml b/src/application/Cargo.toml index 76e7b9a..4ad1faf 100644 --- a/src/application/Cargo.toml +++ b/src/application/Cargo.toml @@ -1,7 +1,7 @@ # General info [package] name = "whitebeam" -version = "0.0.9" +version = "0.1.0" authors = ["noproto"] edition = "2018" diff --git a/src/application/common/api/mod.rs b/src/application/common/api/mod.rs index c5d0536..2dd73f0 100644 --- a/src/application/common/api/mod.rs +++ b/src/application/common/api/mod.rs @@ -3,6 +3,7 @@ use warp::Filter; // Endpoints mod status; mod log; +mod service; pub fn serve() { // GET /status @@ -19,6 +20,24 @@ pub fn serve() { .and(warp::body::json()) .map(log::log_exec); - let routes = status_route.or(log_exec_route); + // GET /service/public_key + let service_public_key_route = warp::get2() + .and(warp::path("service")) + .and(warp::path("public_key")) + .and(warp::path::end()) + .map(service::public_key); + + // POST /service/encrypted {"pubkey":"..","nonce":"..","ciphertext":".."} + let service_encrypted_route = warp::post2() + .and(warp::path("service")) + .and(warp::path("encrypted")) + .and(warp::path::end()) + .and(warp::body::json()) + .map(service::encrypted); + + let routes = status_route + .or(log_exec_route) + .or(service_public_key_route) + .or(service_encrypted_route); warp::serve(routes).run(([0, 0, 0, 0], 11998)); } diff --git a/src/application/common/api/service.rs b/src/application/common/api/service.rs new file mode 100644 index 0000000..9dadd3c --- /dev/null +++ b/src/application/common/api/service.rs @@ -0,0 +1,37 @@ +// Database +use crate::common::db; +// Public key encryption and signatures +use crate::common::crypto; + +fn managed_initialize() -> String { + // TODO + String::from("OK") +} + +fn set_console_secret() -> String { + // TODO + String::from("OK") +} + +fn log_invalid_request() -> String { + // TODO + // Avoid providing a cryptographic oracle + String::from("OK") +} + +// GET /service/public_key +pub fn public_key() -> impl warp::Reply { + let client_public_key = crypto::get_client_public_key(); + return hex::encode(client_public_key); +} + +// GET /service/encrypted +pub fn encrypted(crypto_box_object: crypto::CryptoBox) -> impl warp::Reply { + let server_message = crypto::process_request(crypto_box_object); + match server_message.action.as_ref() { + "managed_initialize" => managed_initialize(), + "set_console_secret" => set_console_secret(), + "invalid" => log_invalid_request(), + _ => log_invalid_request() + } +} diff --git a/src/application/common/crypto.rs b/src/application/common/crypto.rs index 59cdd2d..fa96de3 100644 --- a/src/application/common/crypto.rs +++ b/src/application/common/crypto.rs @@ -67,10 +67,10 @@ Encoding #[derive(Serialize, Deserialize, Debug)] pub struct Message { - expires: u32, - version: String, - action: String, - parameters: Vec + pub expires: u32, + pub version: String, + pub action: String, + pub parameters: Vec } fn json_encode_message(action: String, parameters: Vec) -> String { @@ -95,9 +95,9 @@ fn json_decode_message(json: String) -> Message { #[derive(Serialize, Deserialize, Debug)] pub struct CryptoBox { - pubkey: String, - nonce: String, - ciphertext: String + pub pubkey: String, + pub nonce: String, + pub ciphertext: String } fn json_encode_crypto_box(pubkey: String, nonce: String, ciphertext: String) -> String { @@ -109,6 +109,7 @@ fn json_encode_crypto_box(pubkey: String, nonce: String, ciphertext: String) -> serde_json::to_string(&crypto_box_object).unwrap() } +#[allow(dead_code)] fn json_decode_crypto_box(json: String) -> CryptoBox { let crypto_box_object: CryptoBox = serde_json::from_str(&json).unwrap(); crypto_box_object @@ -138,6 +139,15 @@ fn decrypt_server_ciphertext(ciphertext: &[u8], nonce: Nonce) -> Vec { box_::open(ciphertext, &nonce, &server_public_key, &client_private_key).unwrap() } +/* +Handlers +*/ + +pub fn get_client_public_key() -> PublicKey { + let (client_public_key, _client_private_key) = get_client_public_private_key(); + client_public_key +} + pub fn generate_crypto_box_message(action: String, parameters: Vec) -> String { let (client_public_key, _client_private_key) = get_client_public_private_key(); let message = json_encode_message(action, parameters); @@ -146,34 +156,17 @@ pub fn generate_crypto_box_message(action: String, parameters: Vec) -> S json_encode_crypto_box(hex::encode(client_public_key), hex::encode(nonce), hex::encode(ciphertext)) } -/* -Handlers -*/ - -fn process_server_message(message: Message) { - let expiry = (SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs() as u32)-3600; - if message.expires < expiry { - // Message has expired - return - } - /* TODO: - match message.action.as_ref() { - "managed_initialize" => managed_initialize(), - "set_console_secret" => set_console_secret(), - _ => unknown_action(), +pub fn process_request(crypto_box_object: CryptoBox) -> Message { + let invalid_message = Message { + expires: 0, + version: String::from("0.0.0"), + action: String::from("invalid"), + parameters: Vec::new() }; - */ -} - -pub fn process_request(request: String) { let conn: rusqlite::Connection = db::db_open(); - let crypto_box_object = json_decode_crypto_box(request); // Ignore replayed messages if db::get_seen_nonce(&conn, &crypto_box_object.nonce) { - return + return invalid_message; } let nonce_array: [u8; NONCEBYTES] = nonce_array_from_slice(&hex::decode(crypto_box_object.nonce).unwrap()); let nonce = Nonce(nonce_array); @@ -186,5 +179,13 @@ pub fn process_request(request: String) { ).unwrap() ); let server_message = json_decode_message(plaintext); - process_server_message(server_message); + let expiry = (SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() as u32)-3600; + if server_message.expires < expiry { + // Message has expired + return invalid_message; + } + server_message } diff --git a/src/application/common/db.rs b/src/application/common/db.rs index c06d4f5..355165f 100644 --- a/src/application/common/db.rs +++ b/src/application/common/db.rs @@ -45,7 +45,7 @@ pub fn insert_config(conn: &Connection, config_param: &str, config_value: &str) pub fn insert_exec(conn: &Connection, exec: LogExecObject) { let _res = conn.execute( - "INSERT INTO logs (program, hash, uid, ts, success) + "INSERT INTO exec_logs (program, hash, uid, ts, success) VALUES (?1, ?2, ?3, ?4, ?5)", params![exec.program, exec.hash, exec.uid, exec.ts, exec.success], ); @@ -66,7 +66,7 @@ fn db_init(conn: &Connection) { rusqlite::NO_PARAMS, ); let _res = conn.execute( - "CREATE TABLE logs ( + "CREATE TABLE exec_logs ( id INTEGER PRIMARY KEY, program TEXT NOT NULL, hash TEXT NOT NULL, diff --git a/src/library/Cargo.toml b/src/library/Cargo.toml index 613e8ad..844f0b9 100644 --- a/src/library/Cargo.toml +++ b/src/library/Cargo.toml @@ -1,7 +1,7 @@ # General info [package] name = "libwhitebeam" -version = "0.0.9" +version = "0.1.0" authors = ["noproto"] edition = "2018"