Add compatibility wrapper

This implements the Keymint 1 spec by wrapping the legacy Keymaster
implementation.

Test: atest keystore2_km_compat_test
Test: atest keystore2_certificate_test
Test: Manually verify that keystore2 can find a legacy implementation.
Change-Id: Ia56c25eed0f97a7e6194954a655ceb62259b3273
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
new file mode 100644
index 0000000..b6a6baf
--- /dev/null
+++ b/keystore2/src/km_compat/lib.rs
@@ -0,0 +1,310 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// TODO: Once this is stable, remove this and document everything public.
+#![allow(missing_docs)]
+
+extern "C" {
+    fn addKeyMintDeviceService() -> i32;
+}
+
+pub fn add_keymint_device_service() -> i32 {
+    unsafe { addKeyMintDeviceService() }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+        Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, ByteArray::ByteArray,
+        Certificate::Certificate, Digest::Digest, ErrorCode::ErrorCode,
+        HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
+        KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+        KeyParameterArray::KeyParameterArray, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+        SecurityLevel::SecurityLevel, Tag::Tag,
+    };
+    use android_hardware_security_keymint::binder;
+    use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
+
+    fn get_device() -> Box<dyn IKeyMintDevice> {
+        add_keymint_device_service();
+        let compat_service: Box<dyn IKeystoreCompatService> =
+            binder::get_interface("android.security.compat").unwrap();
+        compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap()
+    }
+
+    #[test]
+    fn test_get_hardware_info() {
+        let legacy = get_device();
+        let hinfo = legacy.getHardwareInfo().unwrap();
+        assert_eq!(hinfo.versionNumber, 0);
+        assert_ne!(hinfo.securityLevel, SecurityLevel::SOFTWARE);
+        assert_eq!(hinfo.keyMintName, "RemoteKeymaster");
+        assert_eq!(hinfo.keyMintAuthorName, "Google");
+    }
+
+    #[test]
+    fn test_verify_authorization() {
+        use android_hardware_security_keymint::aidl::android::hardware::security::keymint::HardwareAuthToken::HardwareAuthToken;
+        let legacy = get_device();
+        let result = legacy.verifyAuthorization(0, &HardwareAuthToken::default());
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
+    }
+
+    #[test]
+    fn test_add_rng_entropy() {
+        let legacy = get_device();
+        let result = legacy.addRngEntropy(&[42; 16]);
+        assert!(result.is_ok(), "{:?}", result);
+    }
+
+    // TODO: If I only need the key itself, don't return the other things.
+    fn generate_key(
+        legacy: &dyn IKeyMintDevice,
+        kps: Vec<KeyParameter>,
+    ) -> (ByteArray, KeyCharacteristics, Vec<Certificate>) {
+        let mut blob = ByteArray { data: vec![] };
+        let mut characteristics = KeyCharacteristics::default();
+        let mut cert_chain = vec![];
+        let result = legacy.generateKey(&kps, &mut blob, &mut characteristics, &mut cert_chain);
+        assert!(result.is_ok(), "{:?}", result);
+        assert_ne!(blob.data.len(), 0);
+        (blob, characteristics, cert_chain)
+    }
+
+    fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
+        let mut kps = vec![
+            KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::RSA.0, ..Default::default() },
+            KeyParameter { tag: Tag::KEY_SIZE, integer: 2048, ..Default::default() },
+            KeyParameter {
+                tag: Tag::RSA_PUBLIC_EXPONENT,
+                longInteger: 65537,
+                ..Default::default()
+            },
+            KeyParameter { tag: Tag::DIGEST, integer: Digest::SHA_2_256.0, ..Default::default() },
+            KeyParameter {
+                tag: Tag::PADDING,
+                integer: PaddingMode::RSA_PSS.0,
+                ..Default::default()
+            },
+            KeyParameter { tag: Tag::NO_AUTH_REQUIRED, boolValue: true, ..Default::default() },
+            KeyParameter { tag: Tag::PURPOSE, integer: KeyPurpose::SIGN.0, ..Default::default() },
+        ];
+        if encrypt {
+            kps.push(KeyParameter {
+                tag: Tag::PURPOSE,
+                integer: KeyPurpose::ENCRYPT.0,
+                ..Default::default()
+            });
+        }
+        if attest {
+            kps.push(KeyParameter {
+                tag: Tag::ATTESTATION_CHALLENGE,
+                blob: vec![42; 8],
+                ..Default::default()
+            });
+            kps.push(KeyParameter {
+                tag: Tag::ATTESTATION_APPLICATION_ID,
+                blob: vec![42; 8],
+                ..Default::default()
+            });
+        }
+        let (blob, _, cert_chain) = generate_key(legacy, kps);
+        if attest {
+            // TODO: Will this always be greater than 1?
+            assert!(cert_chain.len() > 1);
+        } else {
+            assert_eq!(cert_chain.len(), 1);
+        }
+        blob.data
+    }
+
+    #[test]
+    fn test_generate_key_no_encrypt() {
+        let legacy = get_device();
+        generate_rsa_key(legacy.as_ref(), false, false);
+    }
+
+    #[test]
+    fn test_generate_key_encrypt() {
+        let legacy = get_device();
+        generate_rsa_key(legacy.as_ref(), true, false);
+    }
+
+    #[test]
+    fn test_generate_key_attested() {
+        let legacy = get_device();
+        generate_rsa_key(legacy.as_ref(), false, true);
+    }
+
+    #[test]
+    fn test_import_key() {
+        let legacy = get_device();
+        let kps =
+            [KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::AES.0, ..Default::default() }];
+        let kf = KeyFormat::RAW;
+        let kd = [0; 16];
+        let mut blob = ByteArray { data: vec![] };
+        let mut characteristics = KeyCharacteristics::default();
+        let mut cert_chain = vec![];
+        let result =
+            legacy.importKey(&kps, kf, &kd, &mut blob, &mut characteristics, &mut cert_chain);
+        assert!(result.is_ok(), "{:?}", result);
+        assert_ne!(blob.data.len(), 0);
+        assert_eq!(cert_chain.len(), 0);
+    }
+
+    #[test]
+    fn test_import_wrapped_key() {
+        let legacy = get_device();
+        let mut blob = ByteArray { data: vec![] };
+        let mut characteristics = KeyCharacteristics::default();
+        let result =
+            legacy.importWrappedKey(&[], &[], &[], &[], 0, 0, &mut blob, &mut characteristics);
+        // TODO: This test seems to fail on cuttlefish.  How should I test it?
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_upgrade_key() {
+        let legacy = get_device();
+        let blob = generate_rsa_key(legacy.as_ref(), false, false);
+        let result = legacy.upgradeKey(&blob, &[]);
+        // TODO: This test seems to fail on cuttlefish.  How should I test it?
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_delete_key() {
+        let legacy = get_device();
+        let blob = generate_rsa_key(legacy.as_ref(), false, false);
+        let result = legacy.deleteKey(&blob);
+        assert!(result.is_ok(), "{:?}", result);
+    }
+
+    #[test]
+    fn test_delete_all_keys() {
+        let legacy = get_device();
+        let result = legacy.deleteAllKeys();
+        assert!(result.is_ok(), "{:?}", result);
+    }
+
+    #[test]
+    fn test_destroy_attestation_ids() {
+        let legacy = get_device();
+        let result = legacy.destroyAttestationIds();
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
+    }
+
+    fn generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8> {
+        let kps = vec![
+            KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::AES.0, ..Default::default() },
+            KeyParameter { tag: Tag::KEY_SIZE, integer: 128, ..Default::default() },
+            KeyParameter { tag: Tag::BLOCK_MODE, integer: BlockMode::CBC.0, ..Default::default() },
+            KeyParameter { tag: Tag::PADDING, integer: PaddingMode::NONE.0, ..Default::default() },
+            KeyParameter { tag: Tag::NO_AUTH_REQUIRED, boolValue: true, ..Default::default() },
+            KeyParameter {
+                tag: Tag::PURPOSE,
+                integer: KeyPurpose::ENCRYPT.0,
+                ..Default::default()
+            },
+            KeyParameter {
+                tag: Tag::PURPOSE,
+                integer: KeyPurpose::DECRYPT.0,
+                ..Default::default()
+            },
+        ];
+        let (blob, _, cert_chain) = generate_key(legacy, kps);
+        assert_eq!(cert_chain.len(), 0);
+        blob.data
+    }
+
+    fn begin(
+        legacy: &dyn IKeyMintDevice,
+        blob: &[u8],
+        purpose: KeyPurpose,
+        extra_params: Option<Vec<KeyParameter>>,
+    ) -> BeginResult {
+        let mut kps = vec![
+            KeyParameter { tag: Tag::BLOCK_MODE, integer: BlockMode::CBC.0, ..Default::default() },
+            KeyParameter { tag: Tag::PADDING, integer: PaddingMode::NONE.0, ..Default::default() },
+        ];
+        if let Some(mut extras) = extra_params {
+            kps.append(&mut extras);
+        }
+        let result = legacy.begin(purpose, &blob, &kps, &HardwareAuthToken::default());
+        assert!(result.is_ok(), "{:?}", result);
+        result.unwrap()
+    }
+
+    #[test]
+    fn test_begin_abort() {
+        let legacy = get_device();
+        let blob = generate_aes_key(legacy.as_ref());
+        let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
+        let operation = begin_result.operation.unwrap();
+        let result = operation.abort();
+        assert!(result.is_ok(), "{:?}", result);
+        let result = operation.abort();
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_begin_update_finish() {
+        let legacy = get_device();
+        let blob = generate_aes_key(legacy.as_ref());
+
+        let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
+        let operation = begin_result.operation.unwrap();
+        let params = KeyParameterArray {
+            params: vec![KeyParameter {
+                tag: Tag::ASSOCIATED_DATA,
+                blob: b"foobar".to_vec(),
+                ..Default::default()
+            }],
+        };
+        let message = [42; 128];
+        let mut out_params = None;
+        let result =
+            operation.finish(Some(&params), Some(&message), None, None, None, &mut out_params);
+        assert!(result.is_ok(), "{:?}", result);
+        let ciphertext = result.unwrap();
+        assert!(!ciphertext.is_empty());
+        assert!(out_params.is_some());
+
+        let begin_result =
+            begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
+        let operation = begin_result.operation.unwrap();
+        let mut out_params = None;
+        let mut output = None;
+        let result = operation.update(
+            Some(&params),
+            Some(&ciphertext),
+            None,
+            None,
+            &mut out_params,
+            &mut output,
+        );
+        assert!(result.is_ok(), "{:?}", result);
+        assert_eq!(result.unwrap(), message.len() as i32);
+        assert!(output.is_some());
+        assert_eq!(output.unwrap().data, message.to_vec());
+        let result = operation.finish(Some(&params), None, None, None, None, &mut out_params);
+        assert!(result.is_ok(), "{:?}", result);
+        assert!(out_params.is_some());
+    }
+}