Support writing/reading 2nd IMEI in storage

Bug: 265381212
Test: Ran `com.android.trusty.rust.keymint.test`
Change-Id: Ib1696a9af3d7e70689e45f07504e748b9c67139d
Signed-off-by: Donnie Pollitz <donpollitz@google.com>
diff --git a/ipc_manager.rs b/ipc_manager.rs
index 75f2bd5..98cd2f9 100644
--- a/ipc_manager.rs
+++ b/ipc_manager.rs
@@ -21,9 +21,10 @@
     crypto, km_err,
     wire::legacy::{
         self, ConfigureBootPatchlevelResponse, GetAuthTokenKeyResponse, GetDeviceInfoResponse,
-        GetVersion2Response, GetVersionResponse, SetAttestationIdsResponse,
-        SetAttestationKeyResponse, SetBootParamsResponse, TrustyMessageId, TrustyPerformOpReq,
-        TrustyPerformOpRsp, TrustyPerformSecureOpReq, TrustyPerformSecureOpRsp,
+        GetVersion2Response, GetVersionResponse, SetAttestationIdsKM3Response,
+        SetAttestationIdsResponse, SetAttestationKeyResponse, SetBootParamsResponse,
+        TrustyMessageId, TrustyPerformOpReq, TrustyPerformOpRsp, TrustyPerformSecureOpReq,
+        TrustyPerformSecureOpRsp,
     },
     Error,
 };
@@ -332,9 +333,24 @@
                     &req.meid,
                     &req.manufacturer,
                     &req.model,
+                    None,
                 )?;
                 Ok(TrustyPerformOpRsp::SetAttestationIds(SetAttestationIdsResponse {}))
             }
+            TrustyPerformOpReq::SetAttestationIdsKM3(req) => {
+                secure_storage_manager::provision_attestation_id_file(
+                    &req.base.brand,
+                    &req.base.product,
+                    &req.base.device,
+                    &req.base.serial,
+                    &req.base.imei,
+                    &req.base.meid,
+                    &req.base.manufacturer,
+                    &req.base.model,
+                    Some(&req.second_imei),
+                )?;
+                Ok(TrustyPerformOpRsp::SetAttestationIdsKM3(SetAttestationIdsKM3Response {}))
+            }
             // TODO: Check if we need to support other provisioning messages:
             // (AppendAttestationCertChain, ClearAttestationCertChain, SetWrappedAttestationKey)
             _ => Err(km_err!(Unimplemented, "received command {:?} not supported", cmd_code)),
@@ -432,6 +448,7 @@
                     &req.meid,
                     &req.manufacturer,
                     &req.model,
+                    None,
                 )?;
                 Ok(TrustyPerformSecureOpRsp::SetAttestationIds(SetAttestationIdsResponse {}))
             }
diff --git a/keymaster_attributes.rs b/keymaster_attributes.rs
index be8ecbc..e23fa28 100644
--- a/keymaster_attributes.rs
+++ b/keymaster_attributes.rs
@@ -255,6 +255,7 @@
     meid: ::protobuf::SingularField<::std::vec::Vec<u8>>,
     manufacturer: ::protobuf::SingularField<::std::vec::Vec<u8>>,
     model: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    second_imei: ::protobuf::SingularField<::std::vec::Vec<u8>>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -558,6 +559,42 @@
     pub fn take_model(&mut self) -> ::std::vec::Vec<u8> {
         self.model.take().unwrap_or_else(|| ::std::vec::Vec::new())
     }
+
+    // optional bytes second_imei = 9;
+
+
+    pub fn get_second_imei(&self) -> &[u8] {
+        match self.second_imei.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_second_imei(&mut self) {
+        self.second_imei.clear();
+    }
+
+    pub fn has_second_imei(&self) -> bool {
+        self.second_imei.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_second_imei(&mut self, v: ::std::vec::Vec<u8>) {
+        self.second_imei = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_second_imei(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.second_imei.is_none() {
+            self.second_imei.set_default();
+        }
+        self.second_imei.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_second_imei(&mut self) -> ::std::vec::Vec<u8> {
+        self.second_imei.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
 }
 
 impl ::protobuf::Message for AttestationIds {
@@ -593,6 +630,9 @@
                 8 => {
                     ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.model)?;
                 },
+                9 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.second_imei)?;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -629,6 +669,9 @@
         if let Some(ref v) = self.model.as_ref() {
             my_size += ::protobuf::rt::bytes_size(8, &v);
         }
+        if let Some(ref v) = self.second_imei.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(9, &v);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -659,6 +702,9 @@
         if let Some(ref v) = self.model.as_ref() {
             os.write_bytes(8, &v)?;
         }
+        if let Some(ref v) = self.second_imei.as_ref() {
+            os.write_bytes(9, &v)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -737,6 +783,11 @@
                 |m: &AttestationIds| { &m.model },
                 |m: &mut AttestationIds| { &mut m.model },
             ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "second_imei",
+                |m: &AttestationIds| { &m.second_imei },
+                |m: &mut AttestationIds| { &mut m.second_imei },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<AttestationIds>(
                 "AttestationIds",
                 fields,
@@ -761,6 +812,7 @@
         self.meid.clear();
         self.manufacturer.clear();
         self.model.clear();
+        self.second_imei.clear();
         self.unknown_fields.clear();
     }
 }
@@ -1171,7 +1223,7 @@
     \n\x1akeymaster_attributes.proto\x1a\x0cnanopb.proto\"V\n\x13KeymasterAt\
     tributes\x12\x19\n\x04uuid\x18\x01\x20\x01(\x0cR\x04uuidB\x05\x92?\x02\
     \x08\x20\x12$\n\nproduct_id\x18\x02\x20\x01(\x0cR\tproductIdB\x05\x92?\
-    \x02\x08\x10\"\x8a\x02\n\x0eAttestationIds\x12\x1b\n\x05brand\x18\x01\
+    \x02\x08\x10\"\xb2\x02\n\x0eAttestationIds\x12\x1b\n\x05brand\x18\x01\
     \x20\x01(\x0cR\x05brandB\x05\x92?\x02\x08@\x12\x1d\n\x06device\x18\x02\
     \x20\x01(\x0cR\x06deviceB\x05\x92?\x02\x08@\x12\x1f\n\x07product\x18\x03\
     \x20\x01(\x0cR\x07productB\x05\x92?\x02\x08@\x12\x1d\n\x06serial\x18\x04\
@@ -1179,12 +1231,13 @@
     \x20\x01(\x0cR\x04imeiB\x05\x92?\x02\x08@\x12\x19\n\x04meid\x18\x06\x20\
     \x01(\x0cR\x04meidB\x05\x92?\x02\x08@\x12)\n\x0cmanufacturer\x18\x07\x20\
     \x01(\x0cR\x0cmanufacturerB\x05\x92?\x02\x08@\x12\x1b\n\x05model\x18\x08\
-    \x20\x01(\x0cR\x05modelB\x05\x92?\x02\x08@\"Y\n\x0eAttestationKey\x12\
+    \x20\x01(\x0cR\x05modelB\x05\x92?\x02\x08@\x12&\n\x0bsecond_imei\x18\t\
+    \x20\x01(\x0cR\nsecondImeiB\x05\x92?\x02\x08@\"Y\n\x0eAttestationKey\x12\
     \x18\n\x03key\x18\x01\x20\x01(\x0cR\x03keyB\x06\x92?\x03\x08\x80\x10\x12\
     -\n\x05certs\x18\x02\x20\x03(\x0b2\x10.AttestationCertR\x05certsB\x05\
     \x92?\x02\x10\x03\"3\n\x0fAttestationCert\x12\x20\n\x07content\x18\x01\
-    \x20\x02(\x0cR\x07contentB\x06\x92?\x03\x08\x80\x10J\xb0\x17\n\x06\x12\
-    \x04%\0@\x02\n\xa6\x0c\n\x01\x0c\x12\x03%\0\x122\xcc\x04\n\x20Copyright\
+    \x20\x02(\x0cR\x07contentB\x06\x92?\x03\x08\x80\x10J\x94\x18\n\x06\x12\
+    \x04%\0A\x02\n\xa6\x0c\n\x01\x0c\x12\x03%\0\x122\xcc\x04\n\x20Copyright\
     \x20(C)\x202018\x20The\x20Android\x20Open\x20Source\x20Project\n\n\x20Li\
     censed\x20under\x20the\x20Apache\x20License,\x20Version\x202.0\x20(the\
     \x20\"License\");\n\x20you\x20may\x20not\x20use\x20this\x20file\x20excep\
@@ -1217,31 +1270,31 @@
     b/nanopb.\n\x20Please\x20check\x20the\x20nanopb\x20version\x20in\x20trus\
     ty\x20tree\x20at\x20external/nanopb-c\x20to\x20make\n\x20sure\x20you\x20\
     are\x20using\x20the\x20same\x20nanopb\x20version.\n\n\t\n\x02\x03\0\x12\
-    \x03'\x07\x15\n\n\n\x02\x04\0\x12\x04)\0,\x01\n\n\n\x03\x04\0\x01\x12\
-    \x03)\x08\x1b\n\x0b\n\x04\x04\0\x02\0\x12\x03*\x021\n\x0c\n\x05\x04\0\
-    \x02\0\x04\x12\x03*\x02\n\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03*\x0b\x10\n\
-    \x0c\n\x05\x04\0\x02\0\x01\x12\x03*\x11\x15\n\x0c\n\x05\x04\0\x02\0\x03\
-    \x12\x03*\x18\x19\n\x0c\n\x05\x04\0\x02\0\x08\x12\x03*\x1a0\n\x0f\n\x08\
-    \x04\0\x02\0\x08\xf2\x07\x01\x12\x03*\x1b/\n\x0b\n\x04\x04\0\x02\x01\x12\
-    \x03+\x027\n\x0c\n\x05\x04\0\x02\x01\x04\x12\x03+\x02\n\n\x0c\n\x05\x04\
-    \0\x02\x01\x05\x12\x03+\x0b\x10\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03+\
-    \x11\x1b\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03+\x1e\x1f\n\x0c\n\x05\x04\
-    \0\x02\x01\x08\x12\x03+\x206\n\x0f\n\x08\x04\0\x02\x01\x08\xf2\x07\x01\
-    \x12\x03+!5\n\n\n\x02\x04\x01\x12\x04.\07\x01\n\n\n\x03\x04\x01\x01\x12\
-    \x03.\x08\x16\n\x0b\n\x04\x04\x01\x02\0\x12\x03/\x044\n\x0c\n\x05\x04\
-    \x01\x02\0\x04\x12\x03/\x04\x0c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03/\r\
-    \x12\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03/\x13\x18\n\x0c\n\x05\x04\x01\
-    \x02\0\x03\x12\x03/\x1b\x1c\n\x0c\n\x05\x04\x01\x02\0\x08\x12\x03/\x1d3\
-    \n\x0f\n\x08\x04\x01\x02\0\x08\xf2\x07\x01\x12\x03/\x1e2\n\x0b\n\x04\x04\
-    \x01\x02\x01\x12\x030\x045\n\x0c\n\x05\x04\x01\x02\x01\x04\x12\x030\x04\
-    \x0c\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x030\r\x12\n\x0c\n\x05\x04\x01\
-    \x02\x01\x01\x12\x030\x13\x19\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x030\
-    \x1c\x1d\n\x0c\n\x05\x04\x01\x02\x01\x08\x12\x030\x1e4\n\x0f\n\x08\x04\
-    \x01\x02\x01\x08\xf2\x07\x01\x12\x030\x1f3\n\x0b\n\x04\x04\x01\x02\x02\
-    \x12\x031\x046\n\x0c\n\x05\x04\x01\x02\x02\x04\x12\x031\x04\x0c\n\x0c\n\
-    \x05\x04\x01\x02\x02\x05\x12\x031\r\x12\n\x0c\n\x05\x04\x01\x02\x02\x01\
-    \x12\x031\x13\x1a\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x031\x1d\x1e\n\x0c\
-    \n\x05\x04\x01\x02\x02\x08\x12\x031\x1f5\n\x0f\n\x08\x04\x01\x02\x02\x08\
+    \x03'\0\x16\n\n\n\x02\x04\0\x12\x04)\0,\x01\n\n\n\x03\x04\0\x01\x12\x03)\
+    \x08\x1b\n\x0b\n\x04\x04\0\x02\0\x12\x03*\x021\n\x0c\n\x05\x04\0\x02\0\
+    \x04\x12\x03*\x02\n\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03*\x0b\x10\n\x0c\n\
+    \x05\x04\0\x02\0\x01\x12\x03*\x11\x15\n\x0c\n\x05\x04\0\x02\0\x03\x12\
+    \x03*\x18\x19\n\x0c\n\x05\x04\0\x02\0\x08\x12\x03*\x1a0\n\x0f\n\x08\x04\
+    \0\x02\0\x08\xf2\x07\x01\x12\x03*\x1b/\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
+    +\x027\n\x0c\n\x05\x04\0\x02\x01\x04\x12\x03+\x02\n\n\x0c\n\x05\x04\0\
+    \x02\x01\x05\x12\x03+\x0b\x10\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03+\x11\
+    \x1b\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03+\x1e\x1f\n\x0c\n\x05\x04\0\
+    \x02\x01\x08\x12\x03+\x206\n\x0f\n\x08\x04\0\x02\x01\x08\xf2\x07\x01\x12\
+    \x03+!5\n\n\n\x02\x04\x01\x12\x04.\08\x01\n\n\n\x03\x04\x01\x01\x12\x03.\
+    \x08\x16\n\x0b\n\x04\x04\x01\x02\0\x12\x03/\x044\n\x0c\n\x05\x04\x01\x02\
+    \0\x04\x12\x03/\x04\x0c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03/\r\x12\n\
+    \x0c\n\x05\x04\x01\x02\0\x01\x12\x03/\x13\x18\n\x0c\n\x05\x04\x01\x02\0\
+    \x03\x12\x03/\x1b\x1c\n\x0c\n\x05\x04\x01\x02\0\x08\x12\x03/\x1d3\n\x0f\
+    \n\x08\x04\x01\x02\0\x08\xf2\x07\x01\x12\x03/\x1e2\n\x0b\n\x04\x04\x01\
+    \x02\x01\x12\x030\x045\n\x0c\n\x05\x04\x01\x02\x01\x04\x12\x030\x04\x0c\
+    \n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x030\r\x12\n\x0c\n\x05\x04\x01\x02\
+    \x01\x01\x12\x030\x13\x19\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x030\x1c\
+    \x1d\n\x0c\n\x05\x04\x01\x02\x01\x08\x12\x030\x1e4\n\x0f\n\x08\x04\x01\
+    \x02\x01\x08\xf2\x07\x01\x12\x030\x1f3\n\x0b\n\x04\x04\x01\x02\x02\x12\
+    \x031\x046\n\x0c\n\x05\x04\x01\x02\x02\x04\x12\x031\x04\x0c\n\x0c\n\x05\
+    \x04\x01\x02\x02\x05\x12\x031\r\x12\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\
+    \x031\x13\x1a\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x031\x1d\x1e\n\x0c\n\
+    \x05\x04\x01\x02\x02\x08\x12\x031\x1f5\n\x0f\n\x08\x04\x01\x02\x02\x08\
     \xf2\x07\x01\x12\x031\x204\n\x0b\n\x04\x04\x01\x02\x03\x12\x032\x045\n\
     \x0c\n\x05\x04\x01\x02\x03\x04\x12\x032\x04\x0c\n\x0c\n\x05\x04\x01\x02\
     \x03\x05\x12\x032\r\x12\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x032\x13\x19\
@@ -1266,23 +1319,27 @@
     \x01\x02\x07\x05\x12\x036\r\x12\n\x0c\n\x05\x04\x01\x02\x07\x01\x12\x036\
     \x13\x18\n\x0c\n\x05\x04\x01\x02\x07\x03\x12\x036\x1b\x1c\n\x0c\n\x05\
     \x04\x01\x02\x07\x08\x12\x036\x1d3\n\x0f\n\x08\x04\x01\x02\x07\x08\xf2\
-    \x07\x01\x12\x036\x1e2\n\n\n\x02\x04\x02\x12\x049\0<\x01\n\n\n\x03\x04\
-    \x02\x01\x12\x039\x08\x16\n\x0b\n\x04\x04\x02\x02\0\x12\x03:\x022\n\x0c\
-    \n\x05\x04\x02\x02\0\x04\x12\x03:\x02\n\n\x0c\n\x05\x04\x02\x02\0\x05\
-    \x12\x03:\x0b\x10\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03:\x11\x14\n\x0c\n\
-    \x05\x04\x02\x02\0\x03\x12\x03:\x17\x18\n\x0c\n\x05\x04\x02\x02\0\x08\
-    \x12\x03:\x191\n\x0f\n\x08\x04\x02\x02\0\x08\xf2\x07\x01\x12\x03:\x1a0\n\
-    \x0b\n\x04\x04\x02\x02\x01\x12\x03;\x02<\n\x0c\n\x05\x04\x02\x02\x01\x04\
-    \x12\x03;\x02\n\n\x0c\n\x05\x04\x02\x02\x01\x06\x12\x03;\x0b\x1a\n\x0c\n\
-    \x05\x04\x02\x02\x01\x01\x12\x03;\x1b\x20\n\x0c\n\x05\x04\x02\x02\x01\
-    \x03\x12\x03;#$\n\x0c\n\x05\x04\x02\x02\x01\x08\x12\x03;%;\n\x0f\n\x08\
-    \x04\x02\x02\x01\x08\xf2\x07\x02\x12\x03;&:\n\n\n\x02\x04\x03\x12\x04>\0\
-    @\x01\n\n\n\x03\x04\x03\x01\x12\x03>\x08\x17\n\x0b\n\x04\x04\x03\x02\0\
-    \x12\x03?\x026\n\x0c\n\x05\x04\x03\x02\0\x04\x12\x03?\x02\n\n\x0c\n\x05\
-    \x04\x03\x02\0\x05\x12\x03?\x0b\x10\n\x0c\n\x05\x04\x03\x02\0\x01\x12\
-    \x03?\x11\x18\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03?\x1b\x1c\n\x0c\n\x05\
-    \x04\x03\x02\0\x08\x12\x03?\x1d5\n\x0f\n\x08\x04\x03\x02\0\x08\xf2\x07\
-    \x01\x12\x03?\x1e4\
+    \x07\x01\x12\x036\x1e2\n\x0b\n\x04\x04\x01\x02\x08\x12\x037\x04:\n\x0c\n\
+    \x05\x04\x01\x02\x08\x04\x12\x037\x04\x0c\n\x0c\n\x05\x04\x01\x02\x08\
+    \x05\x12\x037\r\x12\n\x0c\n\x05\x04\x01\x02\x08\x01\x12\x037\x13\x1e\n\
+    \x0c\n\x05\x04\x01\x02\x08\x03\x12\x037!\"\n\x0c\n\x05\x04\x01\x02\x08\
+    \x08\x12\x037#9\n\x0f\n\x08\x04\x01\x02\x08\x08\xf2\x07\x01\x12\x037$8\n\
+    \n\n\x02\x04\x02\x12\x04:\0=\x01\n\n\n\x03\x04\x02\x01\x12\x03:\x08\x16\
+    \n\x0b\n\x04\x04\x02\x02\0\x12\x03;\x022\n\x0c\n\x05\x04\x02\x02\0\x04\
+    \x12\x03;\x02\n\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03;\x0b\x10\n\x0c\n\
+    \x05\x04\x02\x02\0\x01\x12\x03;\x11\x14\n\x0c\n\x05\x04\x02\x02\0\x03\
+    \x12\x03;\x17\x18\n\x0c\n\x05\x04\x02\x02\0\x08\x12\x03;\x191\n\x0f\n\
+    \x08\x04\x02\x02\0\x08\xf2\x07\x01\x12\x03;\x1a0\n\x0b\n\x04\x04\x02\x02\
+    \x01\x12\x03<\x02<\n\x0c\n\x05\x04\x02\x02\x01\x04\x12\x03<\x02\n\n\x0c\
+    \n\x05\x04\x02\x02\x01\x06\x12\x03<\x0b\x1a\n\x0c\n\x05\x04\x02\x02\x01\
+    \x01\x12\x03<\x1b\x20\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03<#$\n\x0c\n\
+    \x05\x04\x02\x02\x01\x08\x12\x03<%;\n\x0f\n\x08\x04\x02\x02\x01\x08\xf2\
+    \x07\x02\x12\x03<&:\n\n\n\x02\x04\x03\x12\x04?\0A\x01\n\n\n\x03\x04\x03\
+    \x01\x12\x03?\x08\x17\n\x0b\n\x04\x04\x03\x02\0\x12\x03@\x026\n\x0c\n\
+    \x05\x04\x03\x02\0\x04\x12\x03@\x02\n\n\x0c\n\x05\x04\x03\x02\0\x05\x12\
+    \x03@\x0b\x10\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03@\x11\x18\n\x0c\n\x05\
+    \x04\x03\x02\0\x03\x12\x03@\x1b\x1c\n\x0c\n\x05\x04\x03\x02\0\x08\x12\
+    \x03@\x1d5\n\x0f\n\x08\x04\x03\x02\0\x08\xf2\x07\x01\x12\x03@\x1e4\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
diff --git a/secure_storage_manager.rs b/secure_storage_manager.rs
index 0418f33..bebf6ee 100644
--- a/secure_storage_manager.rs
+++ b/secure_storage_manager.rs
@@ -140,6 +140,7 @@
     meid: &[u8],
     manufacturer: &[u8],
     model: &[u8],
+    maybe_imei2: Option<&[u8]>,
 ) -> Result<(), Error> {
     let mut file = create_attestation_id_file()?;
 
@@ -169,6 +170,12 @@
     if model.len() > 0 {
         attestation_ids.set_model(try_to_vec(model)?);
     }
+    match maybe_imei2 {
+        Some(imei2) if imei2.len() > 0 => {
+            attestation_ids.set_second_imei(try_to_vec(imei2)?);
+        }
+        _ => (),
+    }
 
     let serialized_buffer = attestation_ids.write_to_bytes().map_err(|e| {
         km_err!(SecureHwCommunicationFailed, "couldn't serialize attestationIds: {:?}", e)
@@ -245,9 +252,14 @@
     let manufacturer = attestation_ids_pb.take_manufacturer();
     let model = attestation_ids_pb.take_model();
 
-    // Pixel devices are provisioned with two consecutive IMEI values, but only the first is stored
-    // in the data.
-    let imei2 = kmr_common::tag::increment_imei(&imei);
+    // Pixel devices are provisioned with two consecutive IMEI values, in earlier devices only the
+    // first one was stored.  Use the storage imei if it exists, otherwise generate it based on the
+    // first imei.
+    let imei2 = if attestation_ids_pb.has_second_imei() {
+        attestation_ids_pb.take_second_imei()
+    } else {
+        kmr_common::tag::increment_imei(&imei)
+    };
 
     Ok(AttestationIdInfo { brand, device, product, serial, imei, imei2, meid, manufacturer, model })
 }
@@ -394,6 +406,7 @@
         expect_eq!(lhs.meid, rhs.meid, "meid doesn't match");
         expect_eq!(lhs.manufacturer, rhs.manufacturer, "manufacturer doesn't match");
         expect_eq!(lhs.model, rhs.model, "model doesn't match");
+        expect_eq!(lhs.imei2, rhs.imei2, "imei2 doesn't match");
     }
 
     fn read_certificates_test(algorithm: SigningAlgorithm) {
@@ -518,6 +531,7 @@
         expect_eq!(attestation_ids.meid.len(), 0, "meid should be empty");
         expect_eq!(attestation_ids.manufacturer.len(), 0, "manufacturer should be empty");
         expect_eq!(attestation_ids.model.len(), 0, "model should be empty");
+        expect_eq!(attestation_ids.imei2.len(), 0, "imei2 should be empty");
     }
 
     #[test]
@@ -553,6 +567,7 @@
         expect_eq!(attestation_ids_info.meid.len(), 0, "shouldn't have a meid");
         expect_eq!(attestation_ids_info.manufacturer.len(), 0, "shouldn't have a manufacturer");
         expect_eq!(attestation_ids_info.model.len(), 0, "shouldn't have a model");
+        expect_eq!(attestation_ids_info.imei2.len(), 0, "shouldn't have a model");
 
         // Now using a raw protobuf
         let raw_protobuf = [10, 9, 110, 101, 119, 32, 98, 114, 97, 110, 100];
@@ -575,6 +590,106 @@
     }
 
     #[test]
+    fn test_provision_attestation_id_file() {
+        let brand = b"unknown brand";
+        let product = b"";
+        let device = b"my brand new device";
+        let serial = vec![b'9'; 64];
+        let imei = b" ";
+        let meid = b"\0";
+        let manufacturer = b"manufacturer #$%%^";
+        let model = b"working one";
+        let imei2 = b"0";
+
+        assert!(provision_attestation_id_file(
+            brand,
+            product,
+            device,
+            &serial,
+            imei,
+            meid,
+            manufacturer,
+            model,
+            Some(imei2)
+        )
+        .is_ok());
+
+        let attestation_ids_info =
+            read_attestation_ids().expect("Couldn't read attestation IDs from storage");
+
+        delete_attestation_id_file();
+        expect_eq!(
+            check_attestation_id_file_exists(),
+            false,
+            "Couldn't delete attestation IDs file"
+        );
+
+        expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
+        expect_eq!(attestation_ids_info.device, device.to_vec(), "device doesn't match");
+        expect_eq!(attestation_ids_info.product, product.to_vec(), "product doesn't match");
+        expect_eq!(attestation_ids_info.serial, serial, "serial doesn't match");
+        expect_eq!(attestation_ids_info.imei, imei.to_vec(), "imei doesn't match");
+        expect_eq!(attestation_ids_info.meid, meid.to_vec(), "meid doesn't match");
+        expect_eq!(
+            attestation_ids_info.manufacturer,
+            manufacturer.to_vec(),
+            "manufacturer doesn't match"
+        );
+        expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
+        expect_eq!(attestation_ids_info.imei2, imei2.to_vec(), "imei2 doesn't match");
+    }
+
+    #[test]
+    fn test_provision_attestation_id_file_imei2_none() {
+        let brand = b"unknown brand";
+        let product = b"";
+        let device = b"my brand new device";
+        let serial = vec![b'9'; 64];
+        let imei = b"000000123456782";
+        let meid = b"\0";
+        let manufacturer = b"manufacturer #$%%^";
+        let model = b"working one";
+        let expected_imei2 = b"123456790";
+
+        assert!(provision_attestation_id_file(
+            brand,
+            product,
+            device,
+            &serial,
+            imei,
+            meid,
+            manufacturer,
+            model,
+            None
+        )
+        .is_ok());
+
+        let attestation_ids_info =
+            read_attestation_ids().expect("Couldn't read attestation IDs from storage");
+
+        delete_attestation_id_file();
+        expect_eq!(
+            check_attestation_id_file_exists(),
+            false,
+            "Couldn't delete attestation IDs file"
+        );
+
+        expect_eq!(attestation_ids_info.brand, brand.to_vec(), "brand doesn't match");
+        expect_eq!(attestation_ids_info.device, device.to_vec(), "device doesn't match");
+        expect_eq!(attestation_ids_info.product, product.to_vec(), "product doesn't match");
+        expect_eq!(attestation_ids_info.serial, serial, "serial doesn't match");
+        expect_eq!(attestation_ids_info.imei, imei.to_vec(), "imei doesn't match");
+        expect_eq!(attestation_ids_info.meid, meid.to_vec(), "meid doesn't match");
+        expect_eq!(
+            attestation_ids_info.manufacturer,
+            manufacturer.to_vec(),
+            "manufacturer doesn't match"
+        );
+        expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
+        expect_eq!(attestation_ids_info.imei2, expected_imei2.to_vec(), "imei2 doesn't match");
+    }
+
+    #[test]
     fn all_attestation_id_fields() {
         let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");
         let mut attestation_ids = keymaster_attributes::AttestationIds::new();
@@ -586,6 +701,7 @@
         let meid = b"\0";
         let manufacturer = b"manufacturer #$%%^";
         let model = b"working one";
+        let imei2 = b"0";
 
         attestation_ids.set_brand(brand.to_vec());
         attestation_ids.set_device(device.to_vec());
@@ -595,6 +711,7 @@
         attestation_ids.set_meid(meid.to_vec());
         attestation_ids.set_manufacturer(manufacturer.to_vec());
         attestation_ids.set_model(model.to_vec());
+        attestation_ids.set_second_imei(imei2.to_vec());
 
         let serialized_buffer =
             attestation_ids.write_to_bytes().expect("Couldn't serialize attestationIds");
@@ -624,6 +741,7 @@
             "manufacturer doesn't match"
         );
         expect_eq!(attestation_ids_info.model, model.to_vec(), "model doesn't match");
+        expect_eq!(attestation_ids_info.imei2, imei2.to_vec(), "imei2 doesn't match");
 
         // Now trying the same from a raw protobuf
         let raw_protobuf = [
@@ -634,6 +752,7 @@
             57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
             42, 1, 32, 50, 1, 0, 58, 18, 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114,
             32, 35, 36, 37, 37, 94, 66, 11, 119, 111, 114, 107, 105, 110, 103, 32, 111, 110, 101,
+            74, 1, 48,
         ];
 
         let mut file = create_attestation_id_file().expect("Couldn't create attestation id file");