Fix GCM IV length

Earlier versions of Keystore generated and stored a 16 byte IV, but used
only the first 12 bytes. Simply generate and store a 12 byte IV, while
processing the longer IVs as before.

Bug: 163866361
Test: keystore2_test
Change-Id: I6b30ad3f41515ce224f282fe555a03580ee7c214
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index 3523a9d..db23d1f 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -30,7 +30,7 @@
 pub use zvec::ZVec;
 
 /// Length of the expected initialization vector.
-pub const IV_LENGTH: usize = 16;
+pub const GCM_IV_LENGTH: usize = 12;
 /// Length of the expected AEAD TAG.
 pub const TAG_LENGTH: usize = 16;
 /// Length of an AES 256 key in bytes.
@@ -40,9 +40,9 @@
 /// Length of the expected salt for key from password generation.
 pub const SALT_LENGTH: usize = 16;
 
-// This is the number of bytes of the GCM IV that is expected to be initialized
-// with random bytes.
-const GCM_IV_LENGTH: usize = 12;
+/// Older versions of keystore produced IVs with four extra
+/// ignored zero bytes at the end; recognise and trim those.
+pub const LEGACY_IV_LENGTH: usize = 16;
 
 /// Generate an AES256 key, essentially 32 random bytes from the underlying
 /// boringssl library discretely stuffed into a ZVec.
@@ -80,10 +80,13 @@
 /// freed. Input key is taken as a slice for flexibility, but it is recommended that it is held
 /// in a ZVec as well.
 pub fn aes_gcm_decrypt(data: &[u8], iv: &[u8], tag: &[u8], key: &[u8]) -> Result<ZVec, Error> {
-    if iv.len() != IV_LENGTH {
-        return Err(Error::InvalidIvLength);
-    }
-
+    // Old versions of aes_gcm_encrypt produced 16 byte IVs, but the last four bytes were ignored
+    // so trim these to the correct size.
+    let iv = match iv.len() {
+        GCM_IV_LENGTH => iv,
+        LEGACY_IV_LENGTH => &iv[..GCM_IV_LENGTH],
+        _ => return Err(Error::InvalidIvLength),
+    };
     if tag.len() != TAG_LENGTH {
         return Err(Error::InvalidAeadTagLength);
     }
@@ -96,8 +99,8 @@
     let mut result = ZVec::new(data.len())?;
 
     // Safety: The first two arguments must point to buffers with a size given by the third
-    // argument. The key must have a size of 16 or 32 bytes which we check above.
-    // The iv and tag arguments must be 16 bytes, which we also check above.
+    // argument. We pass the length of the key buffer along with the key.
+    // The `iv` buffer must be 12 bytes and the `tag` buffer 16, which we check above.
     match unsafe {
         AES_gcm_decrypt(
             data.as_ptr(),
@@ -118,10 +121,9 @@
 /// This function accepts 128 and 256-bit keys and uses AES128 and AES256 respectively based on
 /// the key length. The function generates an initialization vector. The return value is a tuple
 /// of `(ciphertext, iv, tag)`.
-pub fn aes_gcm_encrypt(data: &[u8], key: &[u8]) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), Error> {
-    let mut iv = vec![0; IV_LENGTH];
-    // Safety: iv is longer than GCM_IV_LENGTH, which is 12 while IV_LENGTH is 16.
-    // The iv needs to be 16 bytes long, but the last 4 bytes remain zeroed.
+pub fn aes_gcm_encrypt(plaintext: &[u8], key: &[u8]) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), Error> {
+    let mut iv = vec![0; GCM_IV_LENGTH];
+    // Safety: iv is GCM_IV_LENGTH bytes long.
     if !unsafe { randomBytes(iv.as_mut_ptr(), GCM_IV_LENGTH) } {
         return Err(Error::RandomNumberGenerationFailed);
     }
@@ -131,21 +133,25 @@
         _ => return Err(Error::InvalidKeyLength),
     }
 
-    let mut result: Vec<u8> = vec![0; data.len()];
+    let mut ciphertext: Vec<u8> = vec![0; plaintext.len()];
     let mut tag: Vec<u8> = vec![0; TAG_LENGTH];
-    match unsafe {
+    // Safety: The first two arguments must point to buffers with a size given by the third
+    // argument. We pass the length of the key buffer along with the key.
+    // The `iv` buffer must be 12 bytes and the `tag` buffer 16, which we check above.
+    if unsafe {
         AES_gcm_encrypt(
-            data.as_ptr(),
-            result.as_mut_ptr(),
-            data.len(),
+            plaintext.as_ptr(),
+            ciphertext.as_mut_ptr(),
+            plaintext.len(),
             key.as_ptr(),
             key.len(),
             iv.as_ptr(),
             tag.as_mut_ptr(),
         )
     } {
-        true => Ok((result, iv, tag)),
-        false => Err(Error::EncryptionFailed),
+        Ok((ciphertext, iv, tag))
+    } else {
+        Err(Error::EncryptionFailed)
     }
 }
 
diff --git a/keystore2/src/legacy_blob.rs b/keystore2/src/legacy_blob.rs
index e631356..29d46ad 100644
--- a/keystore2/src/legacy_blob.rs
+++ b/keystore2/src/legacy_blob.rs
@@ -206,7 +206,7 @@
 }
 
 impl LegacyBlobLoader {
-    const IV_SIZE: usize = keystore2_crypto::IV_LENGTH;
+    const IV_SIZE: usize = keystore2_crypto::LEGACY_IV_LENGTH;
     const GCM_TAG_LENGTH: usize = keystore2_crypto::TAG_LENGTH;
     const SALT_SIZE: usize = keystore2_crypto::SALT_LENGTH;