Implementing RetrieveCertSigningInfo and RetrieveAttestationIds traits

Implementing RetrieveCertSigningInfo and RetrieveAttestationIds traits
purely in Rust. For this we now depend on the protobuf crate.

Bug: 253906012, 253926844
Test: Build.py, run keymint TA unittests
Change-Id: I72fc1a5e282f3d3b0e8e8b599ecb287dfad5bbe9
diff --git a/eckey.key b/eckey.key
new file mode 100644
index 0000000..a2f245f
--- /dev/null
+++ b/eckey.key
Binary files differ
diff --git a/keymaster_attributes.rs b/keymaster_attributes.rs
new file mode 100644
index 0000000..be8ecbc
--- /dev/null
+++ b/keymaster_attributes.rs
@@ -0,0 +1,1298 @@
+// This file is generated by rust-protobuf 2.27.1. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `keymaster_attributes.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_27_1;
+
+#[derive(PartialEq,Clone,Default)]
+pub struct KeymasterAttributes {
+    // message fields
+    uuid: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    product_id: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a KeymasterAttributes {
+    fn default() -> &'a KeymasterAttributes {
+        <KeymasterAttributes as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl KeymasterAttributes {
+    pub fn new() -> KeymasterAttributes {
+        ::std::default::Default::default()
+    }
+
+    // optional bytes uuid = 1;
+
+
+    pub fn get_uuid(&self) -> &[u8] {
+        match self.uuid.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_uuid(&mut self) {
+        self.uuid.clear();
+    }
+
+    pub fn has_uuid(&self) -> bool {
+        self.uuid.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_uuid(&mut self, v: ::std::vec::Vec<u8>) {
+        self.uuid = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_uuid(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.uuid.is_none() {
+            self.uuid.set_default();
+        }
+        self.uuid.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_uuid(&mut self) -> ::std::vec::Vec<u8> {
+        self.uuid.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes product_id = 2;
+
+
+    pub fn get_product_id(&self) -> &[u8] {
+        match self.product_id.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_product_id(&mut self) {
+        self.product_id.clear();
+    }
+
+    pub fn has_product_id(&self) -> bool {
+        self.product_id.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_product_id(&mut self, v: ::std::vec::Vec<u8>) {
+        self.product_id = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_product_id(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.product_id.is_none() {
+            self.product_id.set_default();
+        }
+        self.product_id.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_product_id(&mut self) -> ::std::vec::Vec<u8> {
+        self.product_id.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+}
+
+impl ::protobuf::Message for KeymasterAttributes {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.uuid)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.product_id)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if let Some(ref v) = self.uuid.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(1, &v);
+        }
+        if let Some(ref v) = self.product_id.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(2, &v);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if let Some(ref v) = self.uuid.as_ref() {
+            os.write_bytes(1, &v)?;
+        }
+        if let Some(ref v) = self.product_id.as_ref() {
+            os.write_bytes(2, &v)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> KeymasterAttributes {
+        KeymasterAttributes::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "uuid",
+                |m: &KeymasterAttributes| { &m.uuid },
+                |m: &mut KeymasterAttributes| { &mut m.uuid },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "product_id",
+                |m: &KeymasterAttributes| { &m.product_id },
+                |m: &mut KeymasterAttributes| { &mut m.product_id },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<KeymasterAttributes>(
+                "KeymasterAttributes",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static KeymasterAttributes {
+        static instance: ::protobuf::rt::LazyV2<KeymasterAttributes> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(KeymasterAttributes::new)
+    }
+}
+
+impl ::protobuf::Clear for KeymasterAttributes {
+    fn clear(&mut self) {
+        self.uuid.clear();
+        self.product_id.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for KeymasterAttributes {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for KeymasterAttributes {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct AttestationIds {
+    // message fields
+    brand: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    device: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    product: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    serial: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    imei: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    meid: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    manufacturer: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    model: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a AttestationIds {
+    fn default() -> &'a AttestationIds {
+        <AttestationIds as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl AttestationIds {
+    pub fn new() -> AttestationIds {
+        ::std::default::Default::default()
+    }
+
+    // optional bytes brand = 1;
+
+
+    pub fn get_brand(&self) -> &[u8] {
+        match self.brand.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_brand(&mut self) {
+        self.brand.clear();
+    }
+
+    pub fn has_brand(&self) -> bool {
+        self.brand.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_brand(&mut self, v: ::std::vec::Vec<u8>) {
+        self.brand = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_brand(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.brand.is_none() {
+            self.brand.set_default();
+        }
+        self.brand.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_brand(&mut self) -> ::std::vec::Vec<u8> {
+        self.brand.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes device = 2;
+
+
+    pub fn get_device(&self) -> &[u8] {
+        match self.device.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_device(&mut self) {
+        self.device.clear();
+    }
+
+    pub fn has_device(&self) -> bool {
+        self.device.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_device(&mut self, v: ::std::vec::Vec<u8>) {
+        self.device = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_device(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.device.is_none() {
+            self.device.set_default();
+        }
+        self.device.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_device(&mut self) -> ::std::vec::Vec<u8> {
+        self.device.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes product = 3;
+
+
+    pub fn get_product(&self) -> &[u8] {
+        match self.product.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_product(&mut self) {
+        self.product.clear();
+    }
+
+    pub fn has_product(&self) -> bool {
+        self.product.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_product(&mut self, v: ::std::vec::Vec<u8>) {
+        self.product = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_product(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.product.is_none() {
+            self.product.set_default();
+        }
+        self.product.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_product(&mut self) -> ::std::vec::Vec<u8> {
+        self.product.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes serial = 4;
+
+
+    pub fn get_serial(&self) -> &[u8] {
+        match self.serial.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_serial(&mut self) {
+        self.serial.clear();
+    }
+
+    pub fn has_serial(&self) -> bool {
+        self.serial.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_serial(&mut self, v: ::std::vec::Vec<u8>) {
+        self.serial = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_serial(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.serial.is_none() {
+            self.serial.set_default();
+        }
+        self.serial.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_serial(&mut self) -> ::std::vec::Vec<u8> {
+        self.serial.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes imei = 5;
+
+
+    pub fn get_imei(&self) -> &[u8] {
+        match self.imei.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_imei(&mut self) {
+        self.imei.clear();
+    }
+
+    pub fn has_imei(&self) -> bool {
+        self.imei.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_imei(&mut self, v: ::std::vec::Vec<u8>) {
+        self.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_imei(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.imei.is_none() {
+            self.imei.set_default();
+        }
+        self.imei.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_imei(&mut self) -> ::std::vec::Vec<u8> {
+        self.imei.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes meid = 6;
+
+
+    pub fn get_meid(&self) -> &[u8] {
+        match self.meid.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_meid(&mut self) {
+        self.meid.clear();
+    }
+
+    pub fn has_meid(&self) -> bool {
+        self.meid.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_meid(&mut self, v: ::std::vec::Vec<u8>) {
+        self.meid = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_meid(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.meid.is_none() {
+            self.meid.set_default();
+        }
+        self.meid.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_meid(&mut self) -> ::std::vec::Vec<u8> {
+        self.meid.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes manufacturer = 7;
+
+
+    pub fn get_manufacturer(&self) -> &[u8] {
+        match self.manufacturer.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_manufacturer(&mut self) {
+        self.manufacturer.clear();
+    }
+
+    pub fn has_manufacturer(&self) -> bool {
+        self.manufacturer.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_manufacturer(&mut self, v: ::std::vec::Vec<u8>) {
+        self.manufacturer = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_manufacturer(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.manufacturer.is_none() {
+            self.manufacturer.set_default();
+        }
+        self.manufacturer.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_manufacturer(&mut self) -> ::std::vec::Vec<u8> {
+        self.manufacturer.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // optional bytes model = 8;
+
+
+    pub fn get_model(&self) -> &[u8] {
+        match self.model.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_model(&mut self) {
+        self.model.clear();
+    }
+
+    pub fn has_model(&self) -> bool {
+        self.model.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_model(&mut self, v: ::std::vec::Vec<u8>) {
+        self.model = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_model(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.model.is_none() {
+            self.model.set_default();
+        }
+        self.model.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_model(&mut self) -> ::std::vec::Vec<u8> {
+        self.model.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+}
+
+impl ::protobuf::Message for AttestationIds {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.brand)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.device)?;
+                },
+                3 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.product)?;
+                },
+                4 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.serial)?;
+                },
+                5 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.imei)?;
+                },
+                6 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.meid)?;
+                },
+                7 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.manufacturer)?;
+                },
+                8 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.model)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if let Some(ref v) = self.brand.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(1, &v);
+        }
+        if let Some(ref v) = self.device.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(2, &v);
+        }
+        if let Some(ref v) = self.product.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(3, &v);
+        }
+        if let Some(ref v) = self.serial.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(4, &v);
+        }
+        if let Some(ref v) = self.imei.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(5, &v);
+        }
+        if let Some(ref v) = self.meid.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(6, &v);
+        }
+        if let Some(ref v) = self.manufacturer.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(7, &v);
+        }
+        if let Some(ref v) = self.model.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(8, &v);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if let Some(ref v) = self.brand.as_ref() {
+            os.write_bytes(1, &v)?;
+        }
+        if let Some(ref v) = self.device.as_ref() {
+            os.write_bytes(2, &v)?;
+        }
+        if let Some(ref v) = self.product.as_ref() {
+            os.write_bytes(3, &v)?;
+        }
+        if let Some(ref v) = self.serial.as_ref() {
+            os.write_bytes(4, &v)?;
+        }
+        if let Some(ref v) = self.imei.as_ref() {
+            os.write_bytes(5, &v)?;
+        }
+        if let Some(ref v) = self.meid.as_ref() {
+            os.write_bytes(6, &v)?;
+        }
+        if let Some(ref v) = self.manufacturer.as_ref() {
+            os.write_bytes(7, &v)?;
+        }
+        if let Some(ref v) = self.model.as_ref() {
+            os.write_bytes(8, &v)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> AttestationIds {
+        AttestationIds::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "brand",
+                |m: &AttestationIds| { &m.brand },
+                |m: &mut AttestationIds| { &mut m.brand },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "device",
+                |m: &AttestationIds| { &m.device },
+                |m: &mut AttestationIds| { &mut m.device },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "product",
+                |m: &AttestationIds| { &m.product },
+                |m: &mut AttestationIds| { &mut m.product },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "serial",
+                |m: &AttestationIds| { &m.serial },
+                |m: &mut AttestationIds| { &mut m.serial },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "imei",
+                |m: &AttestationIds| { &m.imei },
+                |m: &mut AttestationIds| { &mut m.imei },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "meid",
+                |m: &AttestationIds| { &m.meid },
+                |m: &mut AttestationIds| { &mut m.meid },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "manufacturer",
+                |m: &AttestationIds| { &m.manufacturer },
+                |m: &mut AttestationIds| { &mut m.manufacturer },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "model",
+                |m: &AttestationIds| { &m.model },
+                |m: &mut AttestationIds| { &mut m.model },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<AttestationIds>(
+                "AttestationIds",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static AttestationIds {
+        static instance: ::protobuf::rt::LazyV2<AttestationIds> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(AttestationIds::new)
+    }
+}
+
+impl ::protobuf::Clear for AttestationIds {
+    fn clear(&mut self) {
+        self.brand.clear();
+        self.device.clear();
+        self.product.clear();
+        self.serial.clear();
+        self.imei.clear();
+        self.meid.clear();
+        self.manufacturer.clear();
+        self.model.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for AttestationIds {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for AttestationIds {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct AttestationKey {
+    // message fields
+    key: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    pub certs: ::protobuf::RepeatedField<AttestationCert>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a AttestationKey {
+    fn default() -> &'a AttestationKey {
+        <AttestationKey as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl AttestationKey {
+    pub fn new() -> AttestationKey {
+        ::std::default::Default::default()
+    }
+
+    // optional bytes key = 1;
+
+
+    pub fn get_key(&self) -> &[u8] {
+        match self.key.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_key(&mut self) {
+        self.key.clear();
+    }
+
+    pub fn has_key(&self) -> bool {
+        self.key.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_key(&mut self, v: ::std::vec::Vec<u8>) {
+        self.key = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_key(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.key.is_none() {
+            self.key.set_default();
+        }
+        self.key.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_key(&mut self) -> ::std::vec::Vec<u8> {
+        self.key.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+
+    // repeated .AttestationCert certs = 2;
+
+
+    pub fn get_certs(&self) -> &[AttestationCert] {
+        &self.certs
+    }
+    pub fn clear_certs(&mut self) {
+        self.certs.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_certs(&mut self, v: ::protobuf::RepeatedField<AttestationCert>) {
+        self.certs = v;
+    }
+
+    // Mutable pointer to the field.
+    pub fn mut_certs(&mut self) -> &mut ::protobuf::RepeatedField<AttestationCert> {
+        &mut self.certs
+    }
+
+    // Take field
+    pub fn take_certs(&mut self) -> ::protobuf::RepeatedField<AttestationCert> {
+        ::std::mem::replace(&mut self.certs, ::protobuf::RepeatedField::new())
+    }
+}
+
+impl ::protobuf::Message for AttestationKey {
+    fn is_initialized(&self) -> bool {
+        for v in &self.certs {
+            if !v.is_initialized() {
+                return false;
+            }
+        };
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.key)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.certs)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if let Some(ref v) = self.key.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(1, &v);
+        }
+        for value in &self.certs {
+            let len = value.compute_size();
+            my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
+        };
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if let Some(ref v) = self.key.as_ref() {
+            os.write_bytes(1, &v)?;
+        }
+        for v in &self.certs {
+            os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?;
+            os.write_raw_varint32(v.get_cached_size())?;
+            v.write_to_with_cached_sizes(os)?;
+        };
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> AttestationKey {
+        AttestationKey::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "key",
+                |m: &AttestationKey| { &m.key },
+                |m: &mut AttestationKey| { &mut m.key },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<AttestationCert>>(
+                "certs",
+                |m: &AttestationKey| { &m.certs },
+                |m: &mut AttestationKey| { &mut m.certs },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<AttestationKey>(
+                "AttestationKey",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static AttestationKey {
+        static instance: ::protobuf::rt::LazyV2<AttestationKey> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(AttestationKey::new)
+    }
+}
+
+impl ::protobuf::Clear for AttestationKey {
+    fn clear(&mut self) {
+        self.key.clear();
+        self.certs.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for AttestationKey {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for AttestationKey {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct AttestationCert {
+    // message fields
+    content: ::protobuf::SingularField<::std::vec::Vec<u8>>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a AttestationCert {
+    fn default() -> &'a AttestationCert {
+        <AttestationCert as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl AttestationCert {
+    pub fn new() -> AttestationCert {
+        ::std::default::Default::default()
+    }
+
+    // required bytes content = 1;
+
+
+    pub fn get_content(&self) -> &[u8] {
+        match self.content.as_ref() {
+            Some(v) => &v,
+            None => &[],
+        }
+    }
+    pub fn clear_content(&mut self) {
+        self.content.clear();
+    }
+
+    pub fn has_content(&self) -> bool {
+        self.content.is_some()
+    }
+
+    // Param is passed by value, moved
+    pub fn set_content(&mut self, v: ::std::vec::Vec<u8>) {
+        self.content = ::protobuf::SingularField::some(v);
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_content(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if self.content.is_none() {
+            self.content.set_default();
+        }
+        self.content.as_mut().unwrap()
+    }
+
+    // Take field
+    pub fn take_content(&mut self) -> ::std::vec::Vec<u8> {
+        self.content.take().unwrap_or_else(|| ::std::vec::Vec::new())
+    }
+}
+
+impl ::protobuf::Message for AttestationCert {
+    fn is_initialized(&self) -> bool {
+        if self.content.is_none() {
+            return false;
+        }
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.content)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if let Some(ref v) = self.content.as_ref() {
+            my_size += ::protobuf::rt::bytes_size(1, &v);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if let Some(ref v) = self.content.as_ref() {
+            os.write_bytes(1, &v)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> AttestationCert {
+        AttestationCert::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "content",
+                |m: &AttestationCert| { &m.content },
+                |m: &mut AttestationCert| { &mut m.content },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<AttestationCert>(
+                "AttestationCert",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static AttestationCert {
+        static instance: ::protobuf::rt::LazyV2<AttestationCert> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(AttestationCert::new)
+    }
+}
+
+impl ::protobuf::Clear for AttestationCert {
+    fn clear(&mut self) {
+        self.content.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for AttestationCert {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for AttestationCert {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \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\
+    \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\
+    \x20\x01(\x0cR\x06serialB\x05\x92?\x02\x08@\x12\x19\n\x04imei\x18\x05\
+    \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\
+    \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(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\
+    t\x20in\x20compliance\x20with\x20the\x20License.\n\x20You\x20may\x20obta\
+    in\x20a\x20copy\x20of\x20the\x20License\x20at\n\n\x20\x20\x20\x20\x20\
+    \x20http://www.apache.org/licenses/LICENSE-2.0\n\n\x20Unless\x20required\
+    \x20by\x20applicable\x20law\x20or\x20agreed\x20to\x20in\x20writing,\x20s\
+    oftware\n\x20distributed\x20under\x20the\x20License\x20is\x20distributed\
+    \x20on\x20an\x20\"AS\x20IS\"\x20BASIS,\n\x20WITHOUT\x20WARRANTIES\x20OR\
+    \x20CONDITIONS\x20OF\x20ANY\x20KIND,\x20either\x20express\x20or\x20impli\
+    ed.\n\x20See\x20the\x20License\x20for\x20the\x20specific\x20language\x20\
+    governing\x20permissions\x20and\n\x20limitations\x20under\x20the\x20Lice\
+    nse.\n2\xcc\x07\x20We\x20check\x20in\x20the\x20prebuilt\x20nanopb\x20pro\
+    tobuf\x20file\x20under\x20the\x20current\x20folder\n\x20because\x20the\
+    \x20compile\x20tool\x20chain\x20using\x20trusty/user/base/make/compile_p\
+    roto.mk\n\x20might\x20not\x20work\x20under\x20certain\x20environment\x20\
+    with\x20lower\x20version\x20of\x20python\n\x20protobuf\x20installed.\x20\
+    You\x20need\x20to\x20generate\x20and\x20check\x20in\x20the\x20new\x20pro\
+    tobuf\x20file\n\x20if\x20you\x20change\x20this\x20file\x20in\x20order\
+    \x20for\x20the\x20change\x20to\x20take\x20effect!\n\n\x20To\x20generate\
+    \x20the\x20file\x20using\x20the\x20tool\x20chain\x20in\x20trusty\x20tree\
+    ,\x20add\x20the\x20following\n\x20command\x20to\x20rules.mk:\n\n\x20PB_G\
+    EN_DIR\x20:=\x20[Your\x20generation\x20folder]\n\x20include\x20trusty/us\
+    er/base/make/compile_proto.mk\n\x20$(eval\x20$(call\x20compile_proto,$(K\
+    EYMASTER_DIR)/keymaster_attributes.proto,$(PB_GEN_DIR)))\n\n\x20The\x20g\
+    enerated\x20.pb.c\x20and\x20.pb.h\x20file\x20would\x20be\x20under\x20PB_\
+    GEN_DIR,\x20include\x20them\n\x20to\x20the\x20source\x20path.\n\n\x20To\
+    \x20generate\x20the\x20file\x20using\x20your\x20own\x20tool\x20chain,\
+    \x20please\x20follow\x20the\x20guide\x20at\n\x20https://github.com/nanop\
+    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\
+    \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\
+    \n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x032\x1c\x1d\n\x0c\n\x05\x04\x01\
+    \x02\x03\x08\x12\x032\x1e4\n\x0f\n\x08\x04\x01\x02\x03\x08\xf2\x07\x01\
+    \x12\x032\x1f3\n\x0b\n\x04\x04\x01\x02\x04\x12\x033\x043\n\x0c\n\x05\x04\
+    \x01\x02\x04\x04\x12\x033\x04\x0c\n\x0c\n\x05\x04\x01\x02\x04\x05\x12\
+    \x033\r\x12\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x033\x13\x17\n\x0c\n\x05\
+    \x04\x01\x02\x04\x03\x12\x033\x1a\x1b\n\x0c\n\x05\x04\x01\x02\x04\x08\
+    \x12\x033\x1c2\n\x0f\n\x08\x04\x01\x02\x04\x08\xf2\x07\x01\x12\x033\x1d1\
+    \n\x0b\n\x04\x04\x01\x02\x05\x12\x034\x043\n\x0c\n\x05\x04\x01\x02\x05\
+    \x04\x12\x034\x04\x0c\n\x0c\n\x05\x04\x01\x02\x05\x05\x12\x034\r\x12\n\
+    \x0c\n\x05\x04\x01\x02\x05\x01\x12\x034\x13\x17\n\x0c\n\x05\x04\x01\x02\
+    \x05\x03\x12\x034\x1a\x1b\n\x0c\n\x05\x04\x01\x02\x05\x08\x12\x034\x1c2\
+    \n\x0f\n\x08\x04\x01\x02\x05\x08\xf2\x07\x01\x12\x034\x1d1\n\x0b\n\x04\
+    \x04\x01\x02\x06\x12\x035\x04;\n\x0c\n\x05\x04\x01\x02\x06\x04\x12\x035\
+    \x04\x0c\n\x0c\n\x05\x04\x01\x02\x06\x05\x12\x035\r\x12\n\x0c\n\x05\x04\
+    \x01\x02\x06\x01\x12\x035\x13\x1f\n\x0c\n\x05\x04\x01\x02\x06\x03\x12\
+    \x035\"#\n\x0c\n\x05\x04\x01\x02\x06\x08\x12\x035$:\n\x0f\n\x08\x04\x01\
+    \x02\x06\x08\xf2\x07\x01\x12\x035%9\n\x0b\n\x04\x04\x01\x02\x07\x12\x036\
+    \x044\n\x0c\n\x05\x04\x01\x02\x07\x04\x12\x036\x04\x0c\n\x0c\n\x05\x04\
+    \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\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}
diff --git a/lib.rs b/lib.rs
index 94980ba..e93003d 100644
--- a/lib.rs
+++ b/lib.rs
@@ -20,9 +20,12 @@
 
 use kmr_ta;
 
+mod keymaster_attributes;
 mod keys;
+mod secure_storage_manager;
 
 pub use keys::TrustyKeys;
+pub use secure_storage_manager::{AttestationIds, CertSignInfo};
 
 // TODO: maintain the bootloader status and update it as the bootloader informs
 // Trusty when it is done.
diff --git a/main.rs b/main.rs
index fd6ec4b..3648a06 100644
--- a/main.rs
+++ b/main.rs
@@ -15,6 +15,7 @@
  */
 use alloc::vec::Vec;
 use core::cell::RefCell;
+use keymint::{AttestationIds, CertSignInfo, TrustyKeys};
 use kmr_common::crypto;
 use kmr_crypto_boring::{
     aes::BoringAes, aes_cmac::BoringAesCmac, des::BoringDes, ec::BoringEc, eq::BoringEq,
@@ -126,12 +127,14 @@
         ckdf: &BoringAesCmac,
         hkdf: &BoringHmac,
     };
-
+    let sign_info = CertSignInfo;
+    let mut att_ids = AttestationIds;
+    let trusty_keys = TrustyKeys;
     // TODO: replace no-ops with actual implementations
     let dev = kmr_ta::device::Implementation {
-        keys: &kmr_ta::device::NoOpRetrieveKeyMaterial,
-        sign_info: &kmr_ta::device::NoOpRetrieveCertSigningInfo,
-        attest_ids: None,
+        keys: &trusty_keys,
+        sign_info: &sign_info,
+        attest_ids: Some(&mut att_ids),
         sdd_mgr: None,
         bootloader: &kmr_ta::device::BootloaderDone,
         sk_wrapper: None,
diff --git a/rsakey.key b/rsakey.key
new file mode 100644
index 0000000..f39d187
--- /dev/null
+++ b/rsakey.key
Binary files differ
diff --git a/rules.mk b/rules.mk
index 28353f4..17796ac 100644
--- a/rules.mk
+++ b/rules.mk
@@ -30,6 +30,8 @@
 	trusty/user/base/lib/keymint-rust/common \
 	trusty/user/base/lib/keymint-rust/ta \
 	trusty/user/base/lib/log-rust \
+	trusty/user/base/lib/protobuf-rust \
+	trusty/user/base/lib/storage/rust \
 	trusty/user/base/lib/tipc/rust \
 	trusty/user/base/lib/trusty-log \
 	trusty/user/base/lib/trusty-std \
diff --git a/secure_storage_manager.rs b/secure_storage_manager.rs
new file mode 100644
index 0000000..a1e3bb5
--- /dev/null
+++ b/secure_storage_manager.rs
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+//! Module used to interact with keymint secure storage data.
+use alloc::{format, string::String, vec::Vec};
+use kmr_common::{
+    crypto::{self, KeyMaterial},
+    km_err, vec_try, vec_try_with_capacity,
+    wire::keymint::{self, ErrorCode},
+    wire::AttestationIdInfo,
+    Error,
+};
+use kmr_ta::device::{
+    RetrieveAttestationIds, RetrieveCertSigningInfo, SigningAlgorithm, SigningKeyType,
+};
+use storage::{OpenMode, Port, SecureFile, Session};
+
+use protobuf::{self, Message};
+
+use crate::keymaster_attributes;
+
+const KM_ATTESTATION_ID_FILENAME: &'static str = "AttestationIds";
+
+const KM_ATTESTATION_KEY_CERT_PREFIX: &'static str = "AttestKeyCert";
+
+fn get_key_slot_file_name(algorithm: SigningAlgorithm) -> String {
+    let suffix = match algorithm {
+        SigningAlgorithm::Ec => "ec",
+        SigningAlgorithm::Rsa => "rsa",
+    };
+    format!("{}.{}", KM_ATTESTATION_KEY_CERT_PREFIX, suffix)
+}
+
+pub(crate) fn delete_attestation_ids() -> Result<(), Error> {
+    let mut session = Session::new(Port::TamperProof, true)
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Failed to connect to storage port"))?;
+    session
+        .remove(KM_ATTESTATION_ID_FILENAME)
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Couldn't delete atestation IDs file"))?;
+    Ok(())
+}
+
+fn get_file_contents(file_name: &str) -> Result<Vec<u8>, Error> {
+    let mut session = Session::new(Port::TamperProof, true)
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Failed to connect to storage port"))?;
+    let file = session
+        .open_file(file_name, OpenMode::Open)
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Couldn't open {}", file_name))?;
+    let size = session
+        .get_size(&file)
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Couldn't get {} size", file_name))?;
+    let mut buffer = vec_try![0; size]?;
+    let content = session
+        .read_all(&file, buffer.as_mut_slice())
+        .map_err(|_| km_err!(SecureHwCommunicationFailed, "Couldn't read {}", file_name))?;
+    let total_size = content.len();
+    buffer.resize(total_size, 0);
+    Ok(buffer)
+}
+
+pub(crate) fn read_attestation_ids() -> Result<AttestationIdInfo, Error> {
+    let content = get_file_contents(KM_ATTESTATION_ID_FILENAME)?;
+    let mut attestation_ids_pb: keymaster_attributes::AttestationIds =
+        Message::parse_from_bytes(content.as_slice())
+            .map_err(|_| km_err!(UnknownError, "Couldn't parse attestation IDs proto"))?;
+
+    let brand = attestation_ids_pb.take_brand();
+    let device = attestation_ids_pb.take_device();
+    let product = attestation_ids_pb.take_product();
+    let serial = attestation_ids_pb.take_serial();
+    let imei = attestation_ids_pb.take_imei();
+    let meid = attestation_ids_pb.take_meid();
+    let manufacturer = attestation_ids_pb.take_manufacturer();
+    let model = attestation_ids_pb.take_model();
+
+    Ok(AttestationIdInfo { brand, device, product, serial, imei, meid, manufacturer, model })
+}
+
+fn read_attestation_key_content(
+    key_type: SigningKeyType,
+) -> Result<keymaster_attributes::AttestationKey, Error> {
+    let file_name = get_key_slot_file_name(key_type.algo_hint);
+    let content = get_file_contents(&file_name)?;
+
+    let pb = Message::parse_from_bytes(content.as_slice())
+        .map_err(|_| km_err!(UnknownError, "Couldn't parse attestation key proto"))?;
+    Ok(pb)
+}
+
+pub(crate) fn read_attestation_key(key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
+    let mut attestation_key_pb: keymaster_attributes::AttestationKey =
+        read_attestation_key_content(key_type)?;
+
+    if !(attestation_key_pb.has_key()) {
+        return Err(km_err!(UnknownError, "Attestation Key file found but it had no key"));
+    }
+    let key_buffer = attestation_key_pb.take_key();
+    let key = match key_type.algo_hint {
+        SigningAlgorithm::Ec => crypto::ec::import_pkcs8_key(key_buffer.as_slice())?,
+        SigningAlgorithm::Rsa => {
+            let (key_material, key_size, exponent) =
+                crypto::rsa::import_pkcs8_key(key_buffer.as_slice())?;
+            key_material
+        }
+    };
+    // TODO: Do we need to support KEYMASTER_SOFT_ATTESTATION_FALLBACK flow?
+    Ok(key)
+}
+
+pub(crate) fn get_cert_chain(key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
+    let mut attestation_certs_pb: keymaster_attributes::AttestationKey =
+        read_attestation_key_content(key_type)?;
+    let certs = attestation_certs_pb.take_certs();
+
+    let num_certs = certs.len();
+    if (num_certs == 0) {
+        return Err(km_err!(UnknownError, "Attestation Key file found but it had no certs"));
+    }
+    let mut certificates = vec_try_with_capacity!(num_certs)?;
+    for mut cert in certs {
+        let certificate = keymint::Certificate { encoded_certificate: cert.take_content() };
+        certificates.push(certificate);
+    }
+    // TODO: Do we need to support KEYMASTER_SOFT_ATTESTATION_FALLBACK flow?
+    Ok(certificates)
+}
+
+pub struct AttestationIds;
+
+impl RetrieveAttestationIds for AttestationIds {
+    fn get(&self) -> Result<AttestationIdInfo, Error> {
+        read_attestation_ids()
+    }
+
+    /// Destroy all attestation IDs associated with the device.
+    fn destroy_all(&mut self) -> Result<(), Error> {
+        delete_attestation_ids()
+    }
+}
+
+pub struct CertSignInfo;
+
+impl RetrieveCertSigningInfo for CertSignInfo {
+    fn signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
+        read_attestation_key(key_type)
+    }
+
+    fn cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
+        get_cert_chain(key_type)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use alloc::vec;
+    use core::iter::zip;
+    use kmr_common::wire::AttestationIdInfo;
+    use kmr_ta::device::{SigningAlgorithm, SigningKey, SigningKeyType};
+    use log::info;
+    use protobuf::RepeatedField;
+    use test::{expect, expect_eq, expect_ne};
+
+    // Generated by:
+    // openssl genpkey -out rsakey2.key -outform DER -algorithm RSA -pkeyopt rsa_keygen_bits:2048
+    // openssl pkcs8 -topk8 -in rsakey2.key -outform der -nocrypt -out rsakey.key
+    const RSA_KEY: &'static [u8] = include_bytes!("rsakey.key");
+    // Generated by:
+    // openssl ecparam -name prime256v1 -genkey -outform der -out eckey2.key
+    // openssl pkcs8 -topk8 -in eckey2.key -outform der -nocrypt -out eckey.key
+    const EC_KEY: &'static [u8] = include_bytes!("eckey.key");
+
+    fn create_file(file_name: &str) -> (Session, SecureFile) {
+        let mut session =
+            Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
+        let file = session
+            .open_file(file_name, OpenMode::Create)
+            .expect("Couldn't create attestation file.");
+        (session, file)
+    }
+
+    fn create_attestation_id_file() -> (Session, SecureFile) {
+        create_file(KM_ATTESTATION_ID_FILENAME)
+    }
+
+    fn create_attestation_key_file(algorithm: SigningAlgorithm) -> (Session, SecureFile) {
+        let file_name = get_key_slot_file_name(algorithm);
+        create_file(&file_name)
+    }
+
+    fn delete_key_file(algorithm: SigningAlgorithm) {
+        let file_name = get_key_slot_file_name(algorithm);
+        let mut session =
+            Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
+        session.remove(&file_name).expect("Couldn't delete attestation file.");
+    }
+
+    fn delete_attestation_id_file() {
+        let mut session =
+            Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
+        session.remove(KM_ATTESTATION_ID_FILENAME).expect("Couldn't delete attestation IDs file.");
+    }
+
+    fn check_attestation_id_file_exists() -> bool {
+        let mut session =
+            Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
+        session.open_file(KM_ATTESTATION_ID_FILENAME, OpenMode::Open).is_ok()
+    }
+
+    fn compare_attestation_ids(lhs: &AttestationIdInfo, rhs: &AttestationIdInfo) {
+        expect_eq!(lhs.brand, rhs.brand, "brand doesn't match");
+        expect_eq!(lhs.device, rhs.device, "device doesn't match");
+        expect_eq!(lhs.product, rhs.product, "product doesn't match");
+        expect_eq!(lhs.serial, rhs.serial, "serial doesn't match");
+        expect_eq!(lhs.imei, rhs.imei, "imei doesn't match");
+        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");
+    }
+
+    fn read_certificates_test(algorithm: SigningAlgorithm) {
+        let (mut session, mut file) = create_attestation_key_file(algorithm);
+        let mut key_cert = keymaster_attributes::AttestationKey::new();
+        let certs_data = [[b'a'; 2048], [b'\0'; 2048], [b'c'; 2048]];
+
+        let mut certs = protobuf::RepeatedField::<keymaster_attributes::AttestationCert>::new();
+
+        for cert_data in certs_data.iter() {
+            let mut cert = keymaster_attributes::AttestationCert::new();
+            cert.set_content(cert_data.to_vec());
+            certs.push(cert);
+        }
+
+        key_cert.set_certs(certs);
+
+        let serialized_buffer = key_cert.write_to_bytes().expect("Couldn't serialize certs");
+
+        session.write_all(&mut file, &serialized_buffer).unwrap();
+
+        file.close();
+        session.close();
+
+        let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
+        let certs = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
+        delete_key_file(algorithm);
+
+        expect_eq!(certs.len(), 3, "Didn't recover all certificates");
+        for (cert, cert_data) in zip(certs.iter(), certs_data.iter()) {
+            expect_eq!(cert.encoded_certificate, cert_data.to_vec(), "Wrong certificate retrieved");
+        }
+
+        // Trying now using just a raw protobuf with same data
+        let field_header = [18, 131, 16, 10, 128, 16];
+        let mut raw_protobuf = Vec::new();
+        for cert_data in certs_data.iter() {
+            raw_protobuf.extend_from_slice(&field_header);
+            raw_protobuf.extend_from_slice(cert_data);
+        }
+        let (mut session, mut file) = create_attestation_key_file(algorithm);
+        session.write_all(&mut file, &raw_protobuf).unwrap();
+
+        file.close();
+        session.close();
+        let certs_comp = get_cert_chain(key_type).expect("Couldn't get certificates from storage");
+
+        expect_eq!(certs, certs_comp, "Retrieved certificates didn't match");
+
+        delete_key_file(algorithm);
+    }
+
+    #[test]
+    fn read_ec_rsa_certificates() {
+        read_certificates_test(SigningAlgorithm::Rsa);
+        read_certificates_test(SigningAlgorithm::Ec);
+    }
+
+    fn read_key_test(algorithm: SigningAlgorithm) {
+        let (mut session, mut file) = create_attestation_key_file(algorithm);
+
+        let mut key_cert = keymaster_attributes::AttestationKey::new();
+
+        let test_key = match algorithm {
+            SigningAlgorithm::Rsa => RSA_KEY,
+            SigningAlgorithm::Ec => EC_KEY,
+        };
+
+        key_cert.set_key(test_key.to_vec());
+
+        let serialized_buffer = key_cert.write_to_bytes().expect("Couldn't serialize key");
+        session.write_all(&mut file, &serialized_buffer).unwrap();
+        file.close();
+        session.close();
+
+        let key_type = SigningKeyType { which: SigningKey::Batch, algo_hint: algorithm };
+        let att_key = read_attestation_key(key_type).expect("Couldn't read key from storage");
+
+        delete_key_file(algorithm);
+
+        // Trying now using just a raw protobuf with same data
+        let key_header = match algorithm {
+            SigningAlgorithm::Rsa => [10, 191, 9],
+            SigningAlgorithm::Ec => [10, 138, 1],
+        };
+        let mut raw_protobuf = Vec::new();
+        raw_protobuf.extend_from_slice(&key_header);
+        raw_protobuf.extend_from_slice(&test_key);
+
+        let (mut session, mut file) = create_attestation_key_file(algorithm);
+        session.write_all(&mut file, &raw_protobuf).unwrap();
+        file.close();
+        session.close();
+
+        let att_key_comp = read_attestation_key(key_type).expect("Couldn't read key from storage");
+
+        expect_eq!(att_key, att_key_comp);
+
+        delete_key_file(algorithm);
+    }
+
+    #[test]
+    fn read_ec_rsa_key() {
+        read_key_test(SigningAlgorithm::Rsa);
+        read_key_test(SigningAlgorithm::Ec);
+    }
+
+    #[test]
+    fn single_attestation_id_field() {
+        let (mut session, mut file) = create_attestation_id_file();
+
+        let mut attestation_ids = keymaster_attributes::AttestationIds::new();
+        let brand = b"new brand";
+
+        attestation_ids.set_brand(brand.to_vec());
+
+        let serialized_buffer =
+            attestation_ids.write_to_bytes().expect("Couldn't serialize attestationIds");
+
+        session.write_all(&mut file, &serialized_buffer).unwrap();
+
+        file.close();
+        session.close();
+
+        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.len(), 0, "shouldn't have a device");
+        expect_eq!(attestation_ids_info.product.len(), 0, "shouldn't have a product");
+        expect_eq!(attestation_ids_info.serial.len(), 0, "shouldn't have a serial");
+        expect_eq!(attestation_ids_info.imei.len(), 0, "shouldn't have a imei");
+        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");
+
+        // Now using a raw protobuf
+        let raw_protobuf = [10, 9, 110, 101, 119, 32, 98, 114, 97, 110, 100];
+        let (mut session, mut file) = create_attestation_id_file();
+        session.write_all(&mut file, &raw_protobuf).unwrap();
+        file.close();
+        session.close();
+        let attestation_ids_comp = read_attestation_ids()
+            .expect("Couldn't read comparison set of attestation IDs from storage");
+
+        compare_attestation_ids(&attestation_ids_info, &attestation_ids_comp);
+
+        delete_attestation_id_file();
+        expect_eq!(
+            check_attestation_id_file_exists(),
+            false,
+            "Couldn't delete attestation IDs file"
+        );
+    }
+
+    #[test]
+    fn all_attestation_id_fields() {
+        let (mut session, mut file) = create_attestation_id_file();
+
+        let mut attestation_ids = keymaster_attributes::AttestationIds::new();
+        let brand = b"unknown brand";
+        let device = b"my brand new device";
+        let product = b"";
+        let serial = vec![b'9'; 64];
+        let imei = b" ";
+        let meid = b"\0";
+        let manufacturer = b"manufacturer #$%%^";
+        let model = b"working one";
+
+        attestation_ids.set_brand(brand.to_vec());
+        attestation_ids.set_device(device.to_vec());
+        attestation_ids.set_product(product.to_vec());
+        attestation_ids.set_serial(serial.clone());
+        attestation_ids.set_imei(imei.to_vec());
+        attestation_ids.set_meid(meid.to_vec());
+        attestation_ids.set_manufacturer(manufacturer.to_vec());
+        attestation_ids.set_model(model.to_vec());
+
+        let serialized_buffer =
+            attestation_ids.write_to_bytes().expect("Couldn't serialize attestationIds");
+
+        session.write_all(&mut file, &serialized_buffer).unwrap();
+
+        file.close();
+        session.close();
+
+        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");
+
+        // Now trying the same from a raw protobuf
+        let raw_protobuf = [
+            10, 13, 117, 110, 107, 110, 111, 119, 110, 32, 98, 114, 97, 110, 100, 18, 19, 109, 121,
+            32, 98, 114, 97, 110, 100, 32, 110, 101, 119, 32, 100, 101, 118, 105, 99, 101, 26, 0,
+            34, 64, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+            57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+            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,
+        ];
+
+        let (mut session, mut file) = create_attestation_id_file();
+        session.write_all(&mut file, &raw_protobuf).unwrap();
+        file.close();
+        session.close();
+
+        let attestation_ids_comp = read_attestation_ids()
+            .expect("Couldn't read comparison set of attestation IDs from storage");
+
+        compare_attestation_ids(&attestation_ids_info, &attestation_ids_comp);
+
+        delete_attestation_id_file();
+        expect_eq!(
+            check_attestation_id_file_exists(),
+            false,
+            "Couldn't delete attestation IDs file"
+        );
+    }
+
+    #[test]
+    fn delete_attestation_ids_file() {
+        let (mut session, mut file) = create_attestation_id_file();
+        let raw_protobuf = [10, 9, 110, 101, 119, 32, 98, 114, 97, 110, 100];
+        session.write_all(&mut file, &raw_protobuf).unwrap();
+        file.close();
+        session.close();
+        expect!(check_attestation_id_file_exists(), "Couldn't create attestation IDs file");
+        expect!(delete_attestation_ids().is_ok(), "Couldn't delete attestation IDs file");
+        expect_eq!(
+            check_attestation_id_file_exists(),
+            false,
+            "Attestation IDs file was not deleted"
+        );
+    }
+
+    #[test]
+    fn protobuf_lib_version() {
+        // We are generating the protobuf rust files out of tree because we cannot do it in-tree yet
+        // Because the version of the tool used to autogenerate the files has to match the protobuf
+        // library version, we check it here.
+        expect_eq!("2.27.1", protobuf::VERSION, "autogenerated files version mistmatch");
+    }
+}