[wlan][rsn] Make nonce generator thread safe

This is a preparation for moving the nonce generator into the
station and spawn exactly one such generator per station per
system boot up.
Sharing a single instance of such a generator between multiple,
potentially concurrent handshakes requires it to be thread safe.

Test=wlan_rsn_lib_test_rustc

NET-1338

Change-Id: I9c929e9378862579d608c0dd095c5562c5217214
diff --git a/lib/rust/crates/wlan-rsn/src/crypto_utils/nonce.rs b/lib/rust/crates/wlan-rsn/src/crypto_utils/nonce.rs
index f8d7f89..a29efcd 100644
--- a/lib/rust/crates/wlan-rsn/src/crypto_utils/nonce.rs
+++ b/lib/rust/crates/wlan-rsn/src/crypto_utils/nonce.rs
@@ -7,36 +7,45 @@
 use failure;
 use num::bigint::{BigUint, RandBigInt};
 use rand::OsRng;
+use std::sync::Mutex;
 use time;
 
-#[derive(Debug, PartialEq)]
+// Thread-safe nonce generator.
+// According to IEEE Std 802.11-2016, 12.7.5 each STA should be configured with an initial, random
+// counter at system boot up time.
+#[derive(Debug)]
 pub struct NonceReader {
-    key_counter: BigUint,
+    key_counter: Mutex<BigUint>,
 }
 
 impl NonceReader {
-    pub fn new(sta_addr: [u8; 6]) -> Result<NonceReader, failure::Error> {
+    pub fn new(sta_addr: &[u8]) -> Result<NonceReader, failure::Error> {
         // Write time and STA's address to buffer for PRF-256.
         // IEEE Std 802.11-2016, 12.7.5 recommends using a time in NTP format.
         // Fuchsia has no support for NTP yet; instead use a regular timestamp.
         // TODO(NET-430): Use time in NTP format once Fuchsia added support.
         let mut buf = BytesMut::with_capacity(14);
         buf.put_u64_le(time::precise_time_ns());
-        buf.put_slice(&sta_addr[..]);
+        buf.put_slice(sta_addr);
         let k = OsRng::new()?.gen_biguint(256).to_bytes_le();
         let init = prf(&k[..], "Init Counter", &buf[..], 256)?;
         Ok(NonceReader {
-            key_counter: BigUint::from_bytes_le(&init[..]),
+            key_counter: Mutex::new(BigUint::from_bytes_le(&init[..])),
         })
     }
 
-    pub fn next(&mut self) -> Vec<u8> {
-        self.key_counter += 1u8;
+    pub fn next(&mut self) -> Result<Vec<u8>, failure::Error> {
+        match self.key_counter.lock() {
+            Err(_) => bail!("NonceReader lock is poisoned"),
+            Ok(mut counter) => {
+                *counter += 1u8;
 
-        // Expand nonce if it's less than 32 bytes.
-        let mut result = self.key_counter.to_bytes_le();
-        result.resize(32, 0);
-        result
+                // Expand nonce if it's less than 32 bytes.
+                let mut result = (*counter).to_bytes_le();
+                result.resize(32, 0);
+                Ok(result)
+            },
+        }
     }
 }
 
@@ -47,10 +56,10 @@
     #[test]
     fn test_next_nonce() {
         let addr: [u8; 6] = [1, 2, 3, 4, 5, 6];
-        let mut rdr = NonceReader::new(addr).expect("error creating NonceReader");
-        let mut previous_nonce = rdr.next();
+        let mut rdr = NonceReader::new(&addr[..]).expect("error creating NonceReader");
+        let mut previous_nonce = rdr.next().expect("error generating nonce");
         for _ in 0..300 {
-            let nonce = rdr.next();
+            let nonce = rdr.next().expect("error generating nonce");
             let nonce_int = BigUint::from_bytes_le(&nonce[..]);
             let previous_nonce_int = BigUint::from_bytes_le(&previous_nonce[..]);
             assert_eq!(nonce_int.gt(&previous_nonce_int), true);
diff --git a/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/supplicant.rs b/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/supplicant.rs
index 403ed74..cc100f2 100644
--- a/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/supplicant.rs
+++ b/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/supplicant.rs
@@ -29,7 +29,7 @@
         -> Result<(eapol::KeyFrame, Ptk), failure::Error>
     {
         let anonce = &msg1.get().key_nonce;
-        let snonce = shared.nonce_rdr.next();
+        let snonce = shared.nonce_rdr.next()?;
         let rsne = &shared.cfg.s_rsne;
         let akm = &rsne.akm_suites[0];
         let cipher = &rsne.pairwise_cipher_suites[0];
@@ -239,7 +239,7 @@
     }
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug)]
 struct SharedState {
     anonce: [u8; 32],
     pmk: Vec<u8>,
@@ -249,6 +249,18 @@
     nonce_rdr: NonceReader,
 }
 
+impl PartialEq for SharedState {
+    fn eq(&self, other: &SharedState) -> bool {
+        // Exclude nonce generator from comparison. This code will soon change once the nonce
+        // generator moved further up the stack.
+        self.anonce == other.anonce &&
+            self.pmk == other.pmk &&
+            self.kek == other.kek &&
+            self.kck == other.kck &&
+            self.cfg == other.cfg
+    }
+}
+
 #[derive(Debug, PartialEq)]
 pub struct Supplicant {
     shared: SharedState,
@@ -257,7 +269,7 @@
 
 impl Supplicant {
     pub fn new(cfg: fourway::Config, pmk: Vec<u8>) -> Result<Self, failure::Error> {
-        let nonce_rdr = NonceReader::new(cfg.s_addr)?;
+        let nonce_rdr = NonceReader::new(&cfg.s_addr[..])?;
         Ok(Supplicant {
             state: Some(State::PtkInit(PtkInitState {})),
             shared: SharedState {
diff --git a/lib/rust/crates/wlan-rsn/src/rsna/test_util.rs b/lib/rust/crates/wlan-rsn/src/rsna/test_util.rs
index 3de12a7..17d819e 100644
--- a/lib/rust/crates/wlan-rsn/src/rsna/test_util.rs
+++ b/lib/rust/crates/wlan-rsn/src/rsna/test_util.rs
@@ -130,7 +130,8 @@
 }
 
 pub fn get_nonce() -> Vec<u8> {
-    NonceReader::new(S_ADDR).expect("error creating NonceReader").next()
+    NonceReader::new(&S_ADDR[..]).expect("error creating NonceReader")
+        .next().expect("error generating nonce")
 }
 
 pub fn get_akm() -> akm::Akm {