Keystore 2.0: Add safe crypto wrapper

 * Adds safe wrappers for AES_gcm_decrypt and AES_gcm_encrypt.
 * Adds AES256 key generation.
 * Adds ZVec, a simple fixed size owned vector type that locks
   the backing memory in place with mlock and zeroes the buffer
   before freeing it.

Test: keystore2_test
Bug: 173545997
Change-Id: Id7e30d50b024da1fa8aa58a07cd9bb7a861f81f0
diff --git a/keystore2/src/crypto/zvec.rs b/keystore2/src/crypto/zvec.rs
new file mode 100644
index 0000000..52addfc
--- /dev/null
+++ b/keystore2/src/crypto/zvec.rs
@@ -0,0 +1,102 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![allow(dead_code)]
+
+use crate::error::Error;
+use nix::sys::mman::{mlock, munlock};
+use std::convert::TryFrom;
+use std::fmt;
+use std::ops::{Deref, DerefMut};
+use std::ptr::write_volatile;
+
+/// A fixed size u8 vector that is zeroed when dropped. Also the data is
+/// pinned in memory with mlock.
+#[derive(Default, Eq, PartialEq)]
+pub struct ZVec(Box<[u8]>);
+
+impl ZVec {
+    /// Create a ZVec with the given size.
+    pub fn new(size: usize) -> Result<Self, Error> {
+        let v: Vec<u8> = vec![0; size];
+        let b = v.into_boxed_slice();
+        if size > 0 {
+            unsafe { mlock(b.as_ptr() as *const std::ffi::c_void, b.len()) }?;
+        }
+        Ok(Self(b))
+    }
+}
+
+impl Drop for ZVec {
+    fn drop(&mut self) {
+        for i in 0..self.0.len() {
+            unsafe { write_volatile(self.0.as_mut_ptr().add(i), 0) };
+        }
+        if !self.0.is_empty() {
+            if let Err(e) =
+                unsafe { munlock(self.0.as_ptr() as *const std::ffi::c_void, self.0.len()) }
+            {
+                log::error!("In ZVec::drop: `munlock` failed: {:?}.", e);
+            }
+        }
+    }
+}
+
+impl Deref for ZVec {
+    type Target = [u8];
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for ZVec {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl fmt::Debug for ZVec {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.0.is_empty() {
+            write!(f, "Zvec empty")
+        } else {
+            write!(f, "Zvec size: {} [ Sensitive information redacted ]", self.0.len())
+        }
+    }
+}
+
+impl TryFrom<&[u8]> for ZVec {
+    type Error = Error;
+
+    fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
+        let mut z = ZVec::new(v.len())?;
+        if !v.is_empty() {
+            z.clone_from_slice(v);
+        }
+        Ok(z)
+    }
+}
+
+impl TryFrom<Vec<u8>> for ZVec {
+    type Error = Error;
+
+    fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
+        let b = v.into_boxed_slice();
+        if !b.is_empty() {
+            unsafe { mlock(b.as_ptr() as *const std::ffi::c_void, b.len()) }?;
+        }
+        Ok(Self(b))
+    }
+}