-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
137 lines (121 loc) · 4.42 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#![no_std]
pub mod tiva;
pub mod driverlib;
use core::{slice, array::from_fn};
use driverlib::{get_temp_samples, get_tick_timer};
use p256_cortex_m4::{SecretKey, Signature, PublicKey};
use rand_chacha::rand_core::{CryptoRng, RngCore};
use sha2::{Digest, Sha256};
pub use tiva::board::Board;
/// Sets up the Tiva development board. This includes setting up all the
/// peripherals we use for eCTF, including EEPROM, UART, and GPIO.
/// See wrapper.c for more information.
pub fn setup_board() -> Board {
let board = Board::new();
driverlib::init_system();
board
}
/// Converts an array of u8 to an array of u32
pub fn bytes_to_words(bytes: &[u8], words: &mut [u32]) {
assert!(bytes.len() %4 == 0 && words.len() *4 == bytes.len());
if bytes.len() % 4 == 0 && words.len() *4 == bytes.len() {
for i in 0..words.len() {
words[i] = u32::from_ne_bytes(bytes[i * 4..(i + 1) * 4].try_into().unwrap());
}
}
}
/// Converts an array of u32 to an array of u8
pub fn words_to_bytes(words: &[u32], bytes: &mut [u8]) {
assert!(bytes.len() %4 == 0 && words.len() *4 == bytes.len());
if bytes.len() % 4 == 0 && words.len() *4 == bytes.len() {
for i in 0..words.len() {
let word_bytes = words[i].to_ne_bytes();
bytes[i * 4] = word_bytes[0];
bytes[i * 4 + 1] = word_bytes[1];
bytes[i * 4 + 2] = word_bytes[2];
bytes[i * 4 + 3] = word_bytes[3];
}
}
}
/// Pass directly to hprintln if we are not in debug mode. Otherwise, do
/// nothing.
#[macro_export]
macro_rules! log {
($($arg:tt)*) => {
if cfg!(debug_assertions) {
use cortex_m_semihosting::hprintln;
hprintln!($($arg)*).unwrap();
}
}
}
/// Reads all of SRAM and hashes it to get a 32-byte entropy value.
pub fn get_ram_entropy() -> [u8; 32] {
let memory: &[u8];
unsafe {
// maybe is secure?
memory = slice::from_raw_parts(0x20000000 as *const u8, 0x00008000);
}
sha256(memory)
}
/// Gets 1024 samples from the temperature sensor and hashes them to get a
/// 32-byte entropy value.
pub fn get_temp_entropy() -> [u8; 32] {
let mut samples = [0u32; 8];
let mut samples_lsb;
let mut hash = Sha256::new();
for _ in 0..1024 {
get_temp_samples(&mut samples);
samples_lsb = samples.map(|x| x as u8);
hash.update(samples_lsb);
}
hash.finalize().into()
}
/// Gets 128 samples from the tick timer and hashes them to get a 32-byte
/// entropy value.
pub fn get_timer_entropy() -> [u8; 32] {
let mut hash = Sha256::new();
for _ in 0..128 {
hash.update(get_tick_timer().to_ne_bytes())
}
hash.finalize().into()
}
/// Combines the entropy from the RAM, temperature sensor, and tick timer to
/// get a 32-byte entropy value.
pub fn get_combined_entropy() -> [u8; 32] {
let ram_entropy = get_ram_entropy();
let temp_entropy = get_temp_entropy();
let timer_entropy = get_timer_entropy();
from_fn(|i| ram_entropy[i] ^ temp_entropy[i] ^ timer_entropy[i])
}
/// Hashes a message using SHA-256.
/// https://github.com/ycrypto/p256-cortex-m4/blob/290b275c08ef8964eda308ea56c888c1cf0fa06a/src/lib.rs#L27-L33
pub fn sha256(message: &[u8]) -> [u8; 32] {
let mut hash = Sha256::new();
hash.update(message);
let data = hash.finalize();
data.into()
}
/// Signs a message using the ECDSA algorithm.
pub trait Signer {
fn sign(&self, message: &[u8], rng: impl CryptoRng + RngCore) -> Signature;
}
/// Implementation of signature generation using the ECDSA algorithm.
impl Signer for SecretKey {
// https://github.com/ycrypto/p256-cortex-m4/blob/290b275c08ef8964eda308ea56c888c1cf0fa06a/src/cortex_m4.rs#L187-L190
fn sign(&self, message: &[u8], rng: impl CryptoRng + RngCore) -> Signature {
let prehashed_message = sha256(message);
self.sign_prehashed(prehashed_message.as_ref(), rng)
}
}
/// Verifies a signature using the ECDSA algorithm.
pub trait Verifier {
fn verify(&self, message: &[u8], signature: &Signature) -> bool;
}
/// Implementation of signature validation using the ECDSA algorithm.
impl Verifier for PublicKey {
// https://github.com/ycrypto/p256-cortex-m4/blob/290b275c08ef8964eda308ea56c888c1cf0fa06a/src/cortex_m4.rs#L302-L305
fn verify(&self, message: &[u8], signature: &Signature) -> bool {
let prehashed_message = sha256(message);
self.verify_prehashed(prehashed_message.as_ref(), signature)
}
}