Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MCU client #179

Merged
merged 57 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
da9f1da
Initial commit, Zephyr Dockerfile + hello world
geky Nov 19, 2020
4d7c41c
Added a quick README
geky Nov 20, 2020
615ed4f
Pinned cmake to version 3.18.4
geky Dec 4, 2020
3ea4f03
Managed to get Zephyr's SLIP-based network working in Docker
geky Dec 4, 2020
ac6398c
Simple (ok broken) HTTP request using Zephyr's HTTP APIs
geky Feb 18, 2021
8208300
Properly fleshed out HTTP GET, mostly handling some Zephyr oddities
geky Mar 10, 2021
5fd4914
Added simple protobuf test
geky Mar 12, 2021
94af11f
Simple PAT request working
geky Apr 15, 2021
df9327d
Got mvp attestation working
geky Apr 16, 2021
18d7021
Cleanup, organized into files
geky Apr 17, 2021
9b57c61
Reversed base64 encode order to allow in-place encoding
geky Apr 21, 2021
c100627
Moved veracruz logic into vc.h/vc.c
geky Apr 23, 2021
897cdcd
More progress, handshake is getting a response
geky Apr 25, 2021
7d241da
Halfway through handshake, successful back-and-forth over POSTs
geky Apr 26, 2021
4a3c36e
Reverted attestation skip
geky Apr 26, 2021
16eb2aa
Added debugging, some other minor tweaks
geky Apr 26, 2021
5c995c5
Fixed len issue in base64 encoding
geky Apr 27, 2021
3021c5e
Successfully sent data to Veracruz server
geky Apr 27, 2021
3c9cb4a
Got skeleton of demo working, just need to work on presentation
geky Apr 28, 2021
010462f
Further modifications to make the demo presentable
geky Apr 29, 2021
a0b124b
Updated MVP demo, with emphasis on the M
geky Jul 13, 2021
374ebb2
Added runtime hash verification step required by new CA based proxy a…
geky Jul 16, 2021
f7c666b
Added CA cert to CA chain, now with correct authentication of cert chain
geky Jul 19, 2021
b7294f2
Consistent naming/repr of constants generated from policy file
geky Jul 19, 2021
c57100a
Removed outdated code (mostly attestation)
geky Jul 19, 2021
1575c24
Cleaned up xxd logging
geky Jul 19, 2021
53fb9a2
Added iteration of all known runtime hashes, not just SGX
geky Jul 19, 2021
1e1ebf7
Added audio event triangulation example for MCU clients
geky Jul 22, 2021
2fe5a10
Add 'veracruz-mcu-client/' from commit '53fb9a2de556e61663fceded72776…
geky Aug 12, 2021
ec7b6c0
Removed unnecessary files
geky Jul 22, 2021
729f2e6
Removed nanopb in order to fix submodule
geky Jul 22, 2021
2d54057
Fixed subtree submodule nanopb
geky Jul 22, 2021
a42d36d
Updated veracruz-mcu-client's transport_protoco.proto and removed lin…
geky Jul 22, 2021
19d3bf7
Updated license text
geky Jul 22, 2021
a690b99
Cleaned up a few more TODOs
geky Jul 22, 2021
249c182
Added MCU_CLIENT_INSTRUCTIONS.markdown and related test scripts
geky Jul 22, 2021
d6f3d36
MCU: Fix-upped the poll_for_result.py script and added it to the exam…
geky Jul 26, 2021
b73f323
MCU: Figured out the nuances of Zephyr modules and moved demo into it…
geky Jul 29, 2021
e0a692b
Added a small set of tests (through Shamir's secret sharing) and prog…
geky Jul 30, 2021
4da9598
Added `make run_with_memory_report` to find RAM/ROM usage
geky Jul 31, 2021
85e4ac4
Adopted internal base64_strnlen function due to portability issues
geky Jul 31, 2021
d31e5ca
Adopted Zephyr's cryptographically-safe RNG
geky Jul 31, 2021
957f665
MCU: Changed poll_for_result.py to take policy/identity as parameters
geky Aug 2, 2021
bb4fdaf
Better handling of lingering data in ssl-over-post stream
geky Aug 2, 2021
bebcf7d
MCU: Moved printfs behind VC_LOG and friends
geky Aug 3, 2021
63f5ac6
Tweaked run_md.sh to take a simpler argument for conditional execution
geky Aug 3, 2021
28b23b4
Removed run_markdown.sh, replaced with explicit scripts
geky Aug 3, 2021
1e5cca7
MCU: Cleaned up the Makefile
geky Aug 3, 2021
aa98bec
MCU: Cleaned up prj.confs
geky Aug 3, 2021
5b0e25d
MCU: Add rule to copy transport_protocol.proto from the crate instead…
geky Aug 3, 2021
3e87ed1
MCU: Added more detailed breakdown of memory usage
geky Aug 4, 2021
3068b63
MCU: Added license text and documentation
geky Aug 5, 2021
4865bb2
Added error handling to audio-event-triangulation
geky Aug 5, 2021
ae7895c
MCU: Fixed build failure in shamir-secret-sharing
geky Aug 5, 2021
d808d06
Removed some TODOs that aren't important, other TODOs moved to issues
geky Aug 5, 2021
3c75490
MCU: Increased vc send buffer to match mbedtls's SSL max content len
geky Aug 5, 2021
61a11df
Removed divide-by-zero in audio-event-triangulation demo
geky Aug 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
path = docker
url = https://github.com/veracruz-project/veracruz-docker-image.git
branch = main
[submodule "veracruz-mcu-client/nanopb"]
path = veracruz-mcu-client/nanopb
url = https://github.com/nanopb/nanopb
16 changes: 16 additions & 0 deletions sdk/rust-examples/audio-event-triangulation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "audio-event-triangulation"
version = "0.3.0"
authors = ["The Veracruz Development Team"]
edition = "2018"
description = "Triangulation via audio events"

[dependencies]
anyhow = "1.0.14"
thiserror = "1.0.26"

[profile.release]
opt-level = 3
lto = true
codegen-units = 1

26 changes: 26 additions & 0 deletions sdk/rust-examples/audio-event-triangulation/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Example Makefile
#
# AUTHORS
#
# The Veracruz Development Team.
#
# COPYRIGHT AND LICENSING
#
# See the `LICENSING.markdown` file in the Veracruz root directory for
# licensing and copyright information.

.PHONY: all doc clean fmt

all:
cargo build --target wasm32-wasi --release

doc:
cargo doc

fmt:
cargo fmt

clean:
cargo clean
rm -f Cargo.lock

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
dominic-mulligan-arm marked this conversation as resolved.
Show resolved Hide resolved
#
# Poll for audio event triangulation results
#
# AUTHORS
#
# The Veracruz Development Team.
#
# COPYRIGHT AND LICENSING
#
# See the `LICENSING.markdown` file in the Veracruz root directory for
# licensing and copyright information.

import argparse
import json
import re
import struct
import subprocess as sp
import sys
import time

# Convert pair of signed 32-bit latitude+longitude coordinates into
# a human readable representation
def dump_gps(location):
absy = abs(location[0])
absx = abs(location[1])
return '%d°%02d\'%02d.%02d"%c %d°%02d\'%02d.%02d"%c' % (
absy / (1024*1024),
(absy / (1024*1024/60)) % 60,
(absy / (1024*1024/60/60)) % 60,
(absy / (1024*1024/60/60/100)) % 100,
'N' if location[0] >= 0 else 'S',
absx / (1024*1024),
(absx / (1024*1024/60)) % 60,
(absx / (1024*1024/60/60)) % 60,
(absx / (1024*1024/60/60/100)) % 100,
'E' if location[1] >= 0 else 'W')

def main(args):
# grab server addresses from policy file
with open(args.policy) as f:
policy_json = json.load(f)

print('\033[0;32mstarting audio event triangulation service\033[m')
print('veracruz_server: %s' % policy_json['veracruz_server_url'])
print('proxy_attestation_server: %s' % policy_json['proxy_attestation_server_url'])
print('waiting for triangulation results...')

# poll until Veracruz returns a successful computation
while True:
try:
output = sp.check_output([
'vc-client',
args.policy,
'--identity', args.identity,
'--key', args.key,
'--program', 'audio-event-triangulation.wasm=' + args.program,
'--output', 'audio-event-triangulation.wasm=-'])
except sp.CalledProcessError:
time.sleep(5)
continue

# strip debug info
output = re.sub(rb'post.*?\n', b'', output)

# decode found coordinates
location = struct.unpack('<ii', output)
print()
print('\033[1;33maudio event detected!\033[0m')
print('\033[1;33mlocation:\033[0m %s' % dump_gps(location))
print('\033[1;33mtimestamp:\033[0m %u' % int(time.time()))
print()

break

if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Poll for audio event triangulation results')
parser.add_argument('policy',
help='Veracruz policy file (.json)')
parser.add_argument('--identity', required=True,
help='Identity of client (.pem)')
parser.add_argument('--key', required=True,
help='Private key of client (.pem)')
parser.add_argument('--program', required=True,
help='Path to audio event triangulation binary (.wasm)')
args = parser.parse_args()
main(args)
177 changes: 177 additions & 0 deletions sdk/rust-examples/audio-event-triangulation/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
//! An implementation of triangulation of audio event data
//!
//! This demo takes in audio events in the form of a timestamp,
//! GPS coordinates, and an analog rich audio sample, calculates the
//! best effort triangulated location, returning the estimated location
//!
//! ## Authors
//!
//! The Veracruz Development Team.
//!
//! ## Copyright
//!
//! See the file `LICENSING.markdown` in the Veracruz root directory for licensing
//! and copyright information.

use anyhow;
use std::{
convert::TryInto,
fs,
io,
};
use thiserror::Error;

/// An individual audio event
struct AudioEvent {
/// Timestamp of when even occured (currently unused)
#[allow(dead_code)]
timestamp: u32,
/// Location in 32-bit signed GPS coordinates
location: (i32, i32),
/// Samples in signed 16-bit PCM, bitrate is assumed to be
/// consistent for all samples
samples: Vec<i16>,
}

#[derive(Error, Debug)]
pub enum AudioEventError {
#[error("Unable to decode audio event")]
InvalidAudioEvent,
}

impl AudioEvent {
/// Compute the power of the audio event, larger+closer audio
/// events result in higher power
fn power(&self) -> f64 {
dominic-mulligan-arm marked this conversation as resolved.
Show resolved Hide resolved
// compute as avg per single sample, assumes common bitrate
let mut p: f64 = 0.0;
for x in self.samples.iter() {
p += x.abs() as f64;
}

p.checked_div(self.samples.len() as f64).unwrap_or(0)
}
}

/// Decode an audio event from raw little-endian bytes
///
/// This uses a simple fixed encoding scheme:
/// [ u32 timestamp ]
/// [ i32 device X GPS coord ]
/// [ i32 device Y GPS coord ]
/// [ i16 PCM audio window ]
/// [ i16 ]
/// [ i16 ]
/// [ ... ]
///
fn decode_audio_event(event: &[u8]) -> anyhow::Result<AudioEvent> {
if event.len() < 12 || event.len() % 2 != 0 {
Err(AudioEventError::InvalidAudioEvent)?;
}

Ok(AudioEvent{
timestamp: u32::from_le_bytes(event[0..4].try_into().unwrap()),
location: (
i32::from_le_bytes(event[4.. 8].try_into().unwrap()),
i32::from_le_bytes(event[8..12].try_into().unwrap())
),
samples: (12..event.len()).step_by(2)
.map(|i| i16::from_le_bytes(event[i..i+2].try_into().unwrap()))
.collect::<Vec<_>>()
})
}

/// Find the best effort triangulation of audio events
/// using measured signal power to estimate distance
///
/// Note! This is a fairly naive solution, using only 3 events
/// leaves us with farily low confidence. We also don't take
/// things like the curvature of the earth into account, so
/// this should only be used for demo purposes
///
fn triangulate(events: &[AudioEvent]) -> (i32, i32) {
// solving
// (x−x1)^2 + (y−y1)^2 = d1^2
// (x−x2)^2 + (y−y2)^2 = d2^2
// (x−x3)^2 + (y−y3)^2 = d3^2
//
// let
// a = (-2x1 + 2x2)
// b = (-2y1 + 2y2)
// c = d1^2-d2^2 - x1^2+x2^2 - y1^2+y2^2
// d = (-2x2 + 2x3)
// e = (-2y2 + 2y3)
// f = d2^2-d3^2 - x2^2+x3^2 - y2^2+y3^2
//
// gives us
// x = (ce - fb) / (ea - bd)
// y = (cd - af) / (bd - ae)
//
let (y1, x1) = events[0].location;
let (y2, x2) = events[1].location;
let (y3, x3) = events[2].location;
let (y1, x1) = (y1 as f64, x1 as f64);
let (y2, x2) = (y2 as f64, x2 as f64);
let (y3, x3) = (y3 as f64, x3 as f64);
let d1 = events[0].power();
let d2 = events[1].power();
let d3 = events[2].power();

let a = -2.0*x1 + 2.0*x2;
let b = -2.0*y1 + 2.0*y2;
let c = d1.powf(2.0)-d2.powf(2.0) - x1.powf(2.0)+x2.powf(2.0) - y1.powf(2.0)+y2.powf(2.0);
let d = -2.0*x2 + 2.0*x3;
let e = -2.0*y2 + 2.0*y3;
let f = d2.powf(2.0)-d3.powf(2.0) - x2.powf(2.0)+x3.powf(2.0) - y2.powf(2.0)+y3.powf(2.0);

let x = (c*e - f*b) / (e*a - b*d);
let y = (c*d - a*f) / (b*d - a*e);

(y as i32, x as i32)
}

/// Encode a pair of latitude/longitude GPS coordinates into
/// little-endian bytes
fn encode_location(location: (i32, i32)) -> Vec<u8> {
location.0.to_le_bytes().iter()
.chain(location.1.to_le_bytes().iter())
.map(|x| *x)
.collect::<Vec<_>>()
}

/// entry point
fn main() -> anyhow::Result<()> {
// read all inputs, note we don't know
// how many there are, so we keep trying until
// an input errors
let mut raw_events = Vec::new();
for i in 0.. {
let filename = format!("/input-{}", i);
let event = match fs::read(filename) {
Ok(event) => event,
Err(err) => {
match err.kind() {
io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied => break,
_ => Err(err)?,
}
}
};

raw_events.push(event);
}

// decode
let events = raw_events.iter()
.map(|raw_event| decode_audio_event(&raw_event[..]))
.collect::<Result<Vec<_>, _>>()?;

// triangulate
let location = triangulate(&events);

// encode
let raw_location = encode_location(location);

// write our output through libveracruz
fs::write("/output", &raw_location)?;
Ok(())
}
1 change: 1 addition & 0 deletions veracruz-mcu-client/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
20 changes: 20 additions & 0 deletions veracruz-mcu-client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# intermediary directories
build/
example/
test-data/
# this must be copied over from the transport-protocol crate
transport_protocol.proto
# these are all autogenerated
transport_protocol.pb.c
transport_protocol.pb.h
policy.c
policy.h
samples/audio-event-triangulation/clap.c
samples/audio-event-triangulation/clap.h
samples/shamir-secret-sharing/binary.h
samples/shamir-secret-sharing/binary.c
# output from reports
massif.out
rom_report.txt
static_ram_report.txt
dyn_ram_report.txt
3 changes: 3 additions & 0 deletions veracruz-mcu-client/.gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "nanopb"]
path = nanopb
url = https://github.com/nanopb/nanopb
Loading