Merge "Move device tree compile rule in common places" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index adf6309..f5d2dda 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -99,6 +99,9 @@
"path": "packages/modules/Virtualization/rialto"
},
{
+ "path": "packages/modules/Virtualization/service_vm/requests"
+ },
+ {
"path": "packages/modules/Virtualization/vm"
},
{
diff --git a/apex/empty-payload-apk/Android.bp b/apex/empty-payload-apk/Android.bp
index 70e6754..8bd138f 100644
--- a/apex/empty-payload-apk/Android.bp
+++ b/apex/empty-payload-apk/Android.bp
@@ -9,8 +9,8 @@
apex_available: ["com.android.virt"],
sdk_version: "system_current",
jni_uses_platform_apis: true,
- min_sdk_version: "UpsideDownCake",
- target_sdk_version: "UpsideDownCake",
+ min_sdk_version: "34",
+ target_sdk_version: "34",
compile_multilib: "first",
stl: "none",
}
diff --git a/compos/benchmark/Android.bp b/compos/benchmark/Android.bp
index dc0c01c..93927a2 100644
--- a/compos/benchmark/Android.bp
+++ b/compos/benchmark/Android.bp
@@ -13,7 +13,7 @@
"androidx.test.ext.junit",
"MicrodroidDeviceTestHelper",
"MicrodroidTestHelper",
- "truth-prebuilt",
+ "truth",
],
sdk_version: "test_current",
use_embedded_native_libs: true,
diff --git a/libs/bssl/error/src/code.rs b/libs/bssl/error/src/code.rs
index 7fb36c4..9b661e9 100644
--- a/libs/bssl/error/src/code.rs
+++ b/libs/bssl/error/src/code.rs
@@ -91,6 +91,12 @@
InvalidNonce,
}
+impl From<CipherError> for ReasonCode {
+ fn from(e: CipherError) -> ReasonCode {
+ ReasonCode::Cipher(e)
+ }
+}
+
impl fmt::Display for CipherError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "An error occurred in a Cipher function: {self:?}")
diff --git a/libs/bssl/error/src/lib.rs b/libs/bssl/error/src/lib.rs
index 80398c0..3766c41 100644
--- a/libs/bssl/error/src/lib.rs
+++ b/libs/bssl/error/src/lib.rs
@@ -68,4 +68,5 @@
EVP_AEAD_CTX_seal,
HKDF,
HMAC,
+ RAND_bytes,
}
diff --git a/libs/bssl/src/aead.rs b/libs/bssl/src/aead.rs
index a7d03b9..e0c9fbb 100644
--- a/libs/bssl/src/aead.rs
+++ b/libs/bssl/src/aead.rs
@@ -23,8 +23,13 @@
};
use core::ptr::NonNull;
+/// BoringSSL spec recommends to use 12-byte nonces.
+///
+/// https://commondatastorage.googleapis.com/chromium-boringssl-docs/aead.h.html#EVP_aead_aes_256_gcm
+pub const AES_GCM_NONCE_LENGTH: usize = 12;
+
/// Magic value indicating that the default tag length for an AEAD should be used to
-/// initialize `AeadCtx`.
+/// initialize `AeadContext`.
const AEAD_DEFAULT_TAG_LENGTH: usize = EVP_AEAD_DEFAULT_TAG_LENGTH as usize;
/// Represents an AEAD algorithm.
@@ -60,12 +65,12 @@
}
/// Represents an AEAD algorithm configuration.
-pub struct AeadCtx {
+pub struct AeadContext {
ctx: NonNull<EVP_AEAD_CTX>,
aead: Aead,
}
-impl Drop for AeadCtx {
+impl Drop for AeadContext {
fn drop(&mut self) {
// SAFETY: It is safe because the pointer has been created with `EVP_AEAD_CTX_new`
// and isn't used after this.
@@ -73,8 +78,8 @@
}
}
-impl AeadCtx {
- /// Creates a new `AeadCtx` with the given `Aead` algorithm, `key` and `tag_len`.
+impl AeadContext {
+ /// Creates a new `AeadContext` with the given `Aead` algorithm, `key` and `tag_len`.
///
/// The default tag length will be used if `tag_len` is None.
pub fn new(aead: Aead, key: &[u8], tag_len: Option<usize>) -> Result<Self> {
@@ -153,7 +158,7 @@
out.get(0..out_len).ok_or(to_call_failed_error(ApiName::EVP_AEAD_CTX_open))
}
- /// Returns the `Aead` represented by this `AeadCtx`.
+ /// Returns the `Aead` represented by this `AeadContext`.
pub fn aead(&self) -> Aead {
self.aead
}
diff --git a/libs/bssl/src/lib.rs b/libs/bssl/src/lib.rs
index 898e16c..709e8ad 100644
--- a/libs/bssl/src/lib.rs
+++ b/libs/bssl/src/lib.rs
@@ -25,13 +25,15 @@
mod err;
mod hkdf;
mod hmac;
+mod rand;
mod util;
pub use bssl_avf_error::{ApiName, CipherError, Error, ReasonCode, Result};
-pub use aead::{Aead, AeadCtx};
+pub use aead::{Aead, AeadContext, AES_GCM_NONCE_LENGTH};
pub use cbb::CbbFixed;
pub use digest::Digester;
pub use ec_key::{EcKey, ZVec};
pub use hkdf::hkdf;
pub use hmac::hmac_sha256;
+pub use rand::rand_bytes;
diff --git a/libs/bssl/src/rand.rs b/libs/bssl/src/rand.rs
new file mode 100644
index 0000000..9343284
--- /dev/null
+++ b/libs/bssl/src/rand.rs
@@ -0,0 +1,26 @@
+// Copyright 2023, 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.
+
+//! Wrappers of the randon number generations functions in BoringSSL rand.h.
+
+use crate::util::check_int_result;
+use bssl_avf_error::{ApiName, Result};
+use bssl_ffi::RAND_bytes;
+
+/// Fills the given `dest` with random data.
+pub fn rand_bytes(dest: &mut [u8]) -> Result<()> {
+ // SAFETY: This function only writes to the given buffer within its bounds.
+ let ret = unsafe { RAND_bytes(dest.as_mut_ptr(), dest.len()) };
+ check_int_result(ret, ApiName::RAND_bytes)
+}
diff --git a/libs/bssl/tests/aead_test.rs b/libs/bssl/tests/aead_test.rs
index 8ac3f12..8bdb0e7 100644
--- a/libs/bssl/tests/aead_test.rs
+++ b/libs/bssl/tests/aead_test.rs
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use bssl_avf::{Aead, AeadCtx, ApiName, CipherError, Error, ReasonCode, Result};
+use bssl_avf::{Aead, AeadContext, ApiName, CipherError, Error, ReasonCode, Result};
/// The following vectors are generated randomly with:
/// `hexdump -vn32 -e'32/1 "0x%02x, " 1 "\n"' /dev/urandom`
@@ -38,7 +38,7 @@
let tag_len = None;
let ad = &[];
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let mut out = vec![0u8; ciphertext.len()];
let plaintext = aead_ctx.open(&ciphertext, &AES_256_GCM_NONCE1, ad, &mut out)?;
@@ -50,7 +50,7 @@
#[test]
fn aes_256_gcm_fails_to_encrypt_with_invalid_nonce() -> Result<()> {
let tag_len = None;
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let nonce = &[];
let ad = &[];
let mut out = vec![0u8; MESSAGE.len() + aead_ctx.aead().max_overhead()];
@@ -71,7 +71,7 @@
let tag_len = None;
let ad = &[];
- let aead_ctx2 = AeadCtx::new(Aead::aes_256_gcm(), &KEY2, tag_len)?;
+ let aead_ctx2 = AeadContext::new(Aead::aes_256_gcm(), &KEY2, tag_len)?;
let mut plaintext = vec![0u8; ciphertext.len()];
let err = aead_ctx2.open(&ciphertext, &AES_256_GCM_NONCE1, ad, &mut plaintext).unwrap_err();
@@ -88,7 +88,7 @@
let tag_len = None;
let ad2 = &[1];
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let mut plaintext = vec![0u8; ciphertext.len()];
let err = aead_ctx.open(&ciphertext, &AES_256_GCM_NONCE1, ad2, &mut plaintext).unwrap_err();
@@ -105,7 +105,7 @@
let tag_len = None;
let ad = &[];
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let mut plaintext = vec![0u8; ciphertext.len()];
let err = aead_ctx.open(&ciphertext, &AES_256_GCM_NONCE2, ad, &mut plaintext).unwrap_err();
@@ -123,7 +123,7 @@
let tag_len = None;
let ad = &[];
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let mut plaintext = vec![0u8; ciphertext.len()];
let err = aead_ctx.open(&ciphertext, &AES_256_GCM_NONCE1, ad, &mut plaintext).unwrap_err();
@@ -136,7 +136,7 @@
fn aes_256_gcm_encrypt(message: &[u8]) -> Result<Vec<u8>> {
let tag_len = None;
- let aead_ctx = AeadCtx::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), &KEY1, tag_len)?;
let mut out = vec![0u8; message.len() + aead_ctx.aead().max_overhead()];
assert_eq!(aead_ctx.aead().nonce_length(), AES_256_GCM_NONCE1.len());
diff --git a/rialto/tests/test.rs b/rialto/tests/test.rs
index 6a6dcf4..ee7ecb4 100644
--- a/rialto/tests/test.rs
+++ b/rialto/tests/test.rs
@@ -77,8 +77,9 @@
info!("Received response: {response:?}.");
match response {
- Response::GenerateEcdsaP256KeyPair(EcdsaP256KeyPair { maced_public_key, .. }) => {
- assert_array_has_nonzero(&maced_public_key[..]);
+ Response::GenerateEcdsaP256KeyPair(EcdsaP256KeyPair { maced_public_key, key_blob }) => {
+ assert_array_has_nonzero(&maced_public_key);
+ assert_array_has_nonzero(&key_blob);
Ok(maced_public_key)
}
_ => bail!("Incorrect response type: {response:?}"),
diff --git a/service_vm/requests/Android.bp b/service_vm/requests/Android.bp
index 4b9b46f..f85064a 100644
--- a/service_vm/requests/Android.bp
+++ b/service_vm/requests/Android.bp
@@ -3,7 +3,7 @@
}
rust_defaults {
- name: "libservice_vm_requests_defaults",
+ name: "libservice_vm_requests_nostd_defaults",
crate_name: "service_vm_requests",
defaults: ["avf_build_flags_rust"],
srcs: ["src/lib.rs"],
@@ -11,11 +11,6 @@
apex_available: [
"com.android.virt",
],
-}
-
-rust_library_rlib {
- name: "libservice_vm_requests_nostd",
- defaults: ["libservice_vm_requests_defaults"],
no_stdlibs: true,
stdlibs: [
"libcore.rust_sysroot",
@@ -32,3 +27,14 @@
"libzeroize_nostd",
],
}
+
+rust_library_rlib {
+ name: "libservice_vm_requests_nostd",
+ defaults: ["libservice_vm_requests_nostd_defaults"],
+}
+
+rust_test {
+ name: "libservice_vm_requests.test",
+ defaults: ["libservice_vm_requests_nostd_defaults"],
+ test_suites: ["general-tests"],
+}
diff --git a/service_vm/requests/TEST_MAPPING b/service_vm/requests/TEST_MAPPING
new file mode 100644
index 0000000..c95f9e3
--- /dev/null
+++ b/service_vm/requests/TEST_MAPPING
@@ -0,0 +1,9 @@
+// When adding or removing tests here, don't forget to amend _all_modules list in
+// wireless/android/busytown/ath_config/configs/prod/avf/tests.gcl
+{
+ "avf-presubmit" : [
+ {
+ "name" : "libservice_vm_requests.test"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/service_vm/requests/src/cbor.rs b/service_vm/requests/src/cbor.rs
new file mode 100644
index 0000000..36492e5
--- /dev/null
+++ b/service_vm/requests/src/cbor.rs
@@ -0,0 +1,37 @@
+// Copyright 2023, 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.
+
+//! Utility functions for CBOR serialization/deserialization.
+
+use alloc::vec::Vec;
+use coset::{CoseError, Result};
+use serde::{de::DeserializeOwned, Serialize};
+
+/// Serializes the given data to a CBOR-encoded byte vector.
+pub(crate) fn serialize<T: ?Sized + Serialize>(v: &T) -> Result<Vec<u8>> {
+ let mut data = Vec::new();
+ ciborium::into_writer(v, &mut data)?;
+ Ok(data)
+}
+
+/// Deserializes the given type from a CBOR-encoded byte slice, failing if any extra
+/// data remains after the type has been read.
+pub(crate) fn deserialize<T: DeserializeOwned>(mut data: &[u8]) -> Result<T> {
+ let res = ciborium::from_reader(&mut data)?;
+ if data.is_empty() {
+ Ok(res)
+ } else {
+ Err(CoseError::ExtraneousData)
+ }
+}
diff --git a/service_vm/requests/src/keyblob.rs b/service_vm/requests/src/keyblob.rs
new file mode 100644
index 0000000..a714edd
--- /dev/null
+++ b/service_vm/requests/src/keyblob.rs
@@ -0,0 +1,158 @@
+// Copyright 2023, 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.
+
+//! Handles the encryption and decryption of the key blob.
+
+use crate::cbor;
+use alloc::vec;
+use alloc::vec::Vec;
+use bssl_avf::{hkdf, rand_bytes, Aead, AeadContext, Digester, AES_GCM_NONCE_LENGTH};
+use core::result;
+use serde::{Deserialize, Serialize};
+use service_vm_comm::RequestProcessingError;
+// TODO(b/241428146): This will be used once the retrieval mechanism is available.
+#[cfg(test)]
+use zeroize::Zeroizing;
+
+type Result<T> = result::Result<T, RequestProcessingError>;
+
+/// The KEK (Key Encryption Key) info is used as information to derive the KEK using HKDF.
+const KEK_INFO: &[u8] = b"rialto keyblob kek";
+
+/// An all-zero nonce is utilized to encrypt the private key. This is because each key
+/// undergoes encryption using a distinct KEK, which is derived from a secret and a random
+/// salt. Since the uniqueness of the IV/key combination is already guaranteed by the uniqueness
+/// of the KEK, there is no need for an additional random nonce.
+const PRIVATE_KEY_NONCE: &[u8; AES_GCM_NONCE_LENGTH] = &[0; AES_GCM_NONCE_LENGTH];
+
+/// Since Rialto functions as both the sender and receiver of the message, no additional data is
+/// needed.
+const PRIVATE_KEY_AD: &[u8] = &[];
+
+// Encrypted key blob.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub(crate) enum EncryptedKeyBlob {
+ /// Version 1 key blob.
+ V1(EncryptedKeyBlobV1),
+}
+
+/// Encrypted key blob version 1.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub(crate) struct EncryptedKeyBlobV1 {
+ /// Salt used to derive the KEK.
+ kek_salt: [u8; 32],
+
+ /// Private key encrypted with AES-256-GCM.
+ encrypted_private_key: Vec<u8>,
+}
+
+impl EncryptedKeyBlob {
+ pub(crate) fn new(private_key: &[u8], kek_secret: &[u8]) -> Result<Self> {
+ EncryptedKeyBlobV1::new(private_key, kek_secret).map(Self::V1)
+ }
+
+ // TODO(b/241428146): Use this function to decrypt the retrieved keyblob once the retrieval
+ // mechanism is available.
+ #[cfg(test)]
+ pub(crate) fn decrypt_private_key(&self, kek_secret: &[u8]) -> Result<Zeroizing<Vec<u8>>> {
+ match self {
+ Self::V1(blob) => blob.decrypt_private_key(kek_secret),
+ }
+ }
+
+ // TODO(b/241428146): This function will be used once the retrieval mechanism is available.
+ #[cfg(test)]
+ pub(crate) fn from_cbor_slice(slice: &[u8]) -> coset::Result<Self> {
+ cbor::deserialize(slice)
+ }
+
+ pub(crate) fn to_cbor_vec(&self) -> coset::Result<Vec<u8>> {
+ cbor::serialize(&self)
+ }
+}
+
+impl EncryptedKeyBlobV1 {
+ fn new(private_key: &[u8], kek_secret: &[u8]) -> Result<Self> {
+ let mut kek_salt = [0u8; 32];
+ rand_bytes(&mut kek_salt)?;
+ let kek = hkdf::<32>(kek_secret, &kek_salt, KEK_INFO, Digester::sha512())?;
+
+ let tag_len = None;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), kek.as_slice(), tag_len)?;
+ let mut out = vec![0u8; private_key.len() + aead_ctx.aead().max_overhead()];
+ let ciphertext = aead_ctx.seal(private_key, PRIVATE_KEY_NONCE, PRIVATE_KEY_AD, &mut out)?;
+
+ Ok(Self { kek_salt, encrypted_private_key: ciphertext.to_vec() })
+ }
+
+ #[cfg(test)]
+ fn decrypt_private_key(&self, kek_secret: &[u8]) -> Result<Zeroizing<Vec<u8>>> {
+ let kek = hkdf::<32>(kek_secret, &self.kek_salt, KEK_INFO, Digester::sha512())?;
+ let mut out = Zeroizing::new(vec![0u8; self.encrypted_private_key.len()]);
+ let tag_len = None;
+ let aead_ctx = AeadContext::new(Aead::aes_256_gcm(), kek.as_slice(), tag_len)?;
+ let plaintext = aead_ctx.open(
+ &self.encrypted_private_key,
+ PRIVATE_KEY_NONCE,
+ PRIVATE_KEY_AD,
+ &mut out,
+ )?;
+ Ok(Zeroizing::new(plaintext.to_vec()))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use bssl_avf::{ApiName, CipherError, Error};
+
+ /// The test data are generated randomly with /dev/urandom.
+ const TEST_KEY: [u8; 32] = [
+ 0x76, 0xf7, 0xd5, 0x36, 0x1f, 0x78, 0x58, 0x2e, 0x55, 0x2f, 0x88, 0x9d, 0xa3, 0x3e, 0xba,
+ 0xfb, 0xc1, 0x2b, 0x17, 0x85, 0x24, 0xdc, 0x0e, 0xc4, 0xbf, 0x6d, 0x2e, 0xe8, 0xa8, 0x36,
+ 0x93, 0x62,
+ ];
+ const TEST_SECRET1: [u8; 32] = [
+ 0xac, 0xb1, 0x6b, 0xdf, 0x45, 0x30, 0x20, 0xa5, 0x60, 0x6d, 0x81, 0x07, 0x30, 0x68, 0x6e,
+ 0x01, 0x3d, 0x5e, 0x86, 0xd6, 0xc6, 0x17, 0xfa, 0xd6, 0xe0, 0xff, 0xd4, 0xf0, 0xb0, 0x7c,
+ 0x5c, 0x8f,
+ ];
+ const TEST_SECRET2: [u8; 32] = [
+ 0x04, 0x6e, 0xca, 0x30, 0x5e, 0x6c, 0x8f, 0xe5, 0x1a, 0x47, 0x12, 0xbc, 0x45, 0xd7, 0xa8,
+ 0x38, 0xfb, 0x06, 0xc6, 0x44, 0xa1, 0x21, 0x40, 0x0b, 0x48, 0x88, 0xe2, 0x31, 0x64, 0x42,
+ 0x9d, 0x1c,
+ ];
+
+ #[test]
+ fn decrypting_keyblob_succeeds_with_the_same_kek() -> Result<()> {
+ let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
+ let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+ let decrypted_key = encrypted_key_blob.decrypt_private_key(&TEST_SECRET1)?;
+
+ assert_eq!(TEST_KEY, decrypted_key.as_slice());
+ Ok(())
+ }
+
+ #[test]
+ fn decrypting_keyblob_fails_with_a_different_kek() -> Result<()> {
+ let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
+ let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+ let err = encrypted_key_blob.decrypt_private_key(&TEST_SECRET2).unwrap_err();
+
+ let expected_err: RequestProcessingError =
+ Error::CallFailed(ApiName::EVP_AEAD_CTX_open, CipherError::BadDecrypt.into()).into();
+ assert_eq!(expected_err, err);
+ Ok(())
+ }
+}
diff --git a/service_vm/requests/src/lib.rs b/service_vm/requests/src/lib.rs
index fc0c87d..6fa6e0b 100644
--- a/service_vm/requests/src/lib.rs
+++ b/service_vm/requests/src/lib.rs
@@ -19,6 +19,8 @@
extern crate alloc;
mod api;
+mod cbor;
+mod keyblob;
mod pub_key;
mod rkp;
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index f96b85d..2d80f13 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -15,7 +15,9 @@
//! This module contains functions related to the attestation of the
//! service VM via the RKP (Remote Key Provisioning) server.
-use super::pub_key::{build_maced_public_key, validate_public_key};
+use crate::cbor;
+use crate::keyblob::EncryptedKeyBlob;
+use crate::pub_key::{build_maced_public_key, validate_public_key};
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
@@ -36,7 +38,7 @@
0x82, 0x80, 0xFA, 0xD3, 0xA8, 0x0A, 0x9A, 0x4B, 0xF7, 0xA5, 0x7D, 0x7B, 0xE9, 0xC3, 0xAB, 0x13,
0x89, 0xDC, 0x7B, 0x46, 0xEE, 0x71, 0x22, 0xB4, 0x5F, 0x4C, 0x3F, 0xE2, 0x40, 0x04, 0x3B, 0x6C,
];
-const HMAC_KEY_INFO: &[u8] = b"rialto hmac key";
+const HMAC_KEY_INFO: &[u8] = b"rialto hmac wkey";
const HMAC_KEY_LENGTH: usize = 32;
pub(super) fn generate_ecdsa_p256_key_pair(
@@ -44,13 +46,12 @@
) -> Result<EcdsaP256KeyPair> {
let hmac_key = derive_hmac_key(dice_artifacts)?;
let ec_key = EcKey::new_p256()?;
+
let maced_public_key = build_maced_public_key(ec_key.cose_public_key()?, hmac_key.as_ref())?;
+ let key_blob =
+ EncryptedKeyBlob::new(ec_key.private_key()?.as_slice(), dice_artifacts.cdi_seal())?;
- // TODO(b/279425980): Encrypt the private key in a key blob.
- // Remove the printing of the private key.
- log::debug!("Private key: {:?}", ec_key.private_key()?.as_slice());
-
- let key_pair = EcdsaP256KeyPair { maced_public_key, key_blob: Vec::new() };
+ let key_pair = EcdsaP256KeyPair { maced_public_key, key_blob: key_blob.to_cbor_vec()? };
Ok(key_pair)
}
@@ -80,7 +81,7 @@
// TODO(b/299256925): Add device info in CBOR format here.
Value::Array(public_keys),
])?;
- let csr_payload = cbor_to_vec(&csr_payload)?;
+ let csr_payload = cbor::serialize(&csr_payload)?;
// Builds `SignedData`.
let signed_data_payload =
@@ -91,17 +92,15 @@
// Currently `UdsCerts` is left empty because it is only needed for Samsung devices.
// Check http://b/301574013#comment3 for more information.
let uds_certs = Value::Map(Vec::new());
- let dice_cert_chain = dice_artifacts
- .bcc()
- .map(read_to_value)
- .ok_or(RequestProcessingError::MissingDiceChain)??;
+ let dice_cert_chain = dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?;
+ let dice_cert_chain: Value = cbor::deserialize(dice_cert_chain)?;
let auth_req = cbor!([
Value::Integer(AUTH_REQ_SCHEMA_V1.into()),
uds_certs,
dice_cert_chain,
signed_data,
])?;
- cbor_to_vec(&auth_req)
+ Ok(cbor::serialize(&auth_req)?)
}
fn derive_hmac_key(dice_artifacts: &dyn DiceArtifacts) -> Result<Zeroizing<[u8; HMAC_KEY_LENGTH]>> {
@@ -123,7 +122,7 @@
let protected = HeaderBuilder::new().algorithm(signing_algorithm).build();
let signed_data = CoseSign1Builder::new()
.protected(protected)
- .payload(cbor_to_vec(payload)?)
+ .payload(cbor::serialize(payload)?)
.try_create_signature(&[], |message| sign_message(message, &cdi_leaf_priv))?
.build();
Ok(signed_data)
@@ -142,24 +141,3 @@
})?
.to_vec())
}
-
-fn cbor_to_vec(v: &Value) -> Result<Vec<u8>> {
- let mut data = Vec::new();
- ciborium::into_writer(v, &mut data).map_err(coset::CoseError::from)?;
- Ok(data)
-}
-
-/// Read a CBOR `Value` from a byte slice, failing if any extra data remains
-/// after the `Value` has been read.
-fn read_to_value(mut data: &[u8]) -> Result<Value> {
- let value = ciborium::from_reader(&mut data).map_err(|e| {
- error!("Failed to deserialize the data into CBOR value: {e}");
- RequestProcessingError::CborValueError
- })?;
- if data.is_empty() {
- Ok(value)
- } else {
- error!("CBOR input has extra data.");
- Err(RequestProcessingError::CborValueError)
- }
-}
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
index 80fdff7..657241c 100644
--- a/tests/benchmark/Android.bp
+++ b/tests/benchmark/Android.bp
@@ -14,7 +14,7 @@
"androidx.test.runner",
"androidx.test.ext.junit",
"com.android.microdroid.testservice-java",
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
"MicrodroidBenchmarkNativeLib",
diff --git a/tests/helper/Android.bp b/tests/helper/Android.bp
index 6f07efd..614c70c 100644
--- a/tests/helper/Android.bp
+++ b/tests/helper/Android.bp
@@ -17,7 +17,7 @@
"androidx.test.ext.junit",
"com.android.microdroid.testservice-java",
"MicrodroidTestHelper",
- "truth-prebuilt",
+ "truth",
],
sdk_version: "test_current",
}
diff --git a/tests/hostside/helper/Android.bp b/tests/hostside/helper/Android.bp
index e8b6f36..75553d0 100644
--- a/tests/hostside/helper/Android.bp
+++ b/tests/hostside/helper/Android.bp
@@ -9,7 +9,7 @@
"androidx.annotation_annotation",
"compatibility-tradefed",
"tradefed",
- "truth-prebuilt",
+ "truth",
],
static_libs: [
"MicrodroidTestHelper",
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 8e12114..692b1b8 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -190,7 +190,7 @@
long start = System.currentTimeMillis();
while ((System.currentTimeMillis() - start < timeoutMillis)
&& !matcher.matches(callable.call())) {
- Thread.sleep(500);
+ RunUtil.getDefault().sleep(500);
}
assertThat(callable.call(), matcher);
}
diff --git a/tests/no_avf/Android.bp b/tests/no_avf/Android.bp
index fd0d5e2..22d099e 100644
--- a/tests/no_avf/Android.bp
+++ b/tests/no_avf/Android.bp
@@ -13,9 +13,9 @@
"androidx.test.runner",
"androidx.test.ext.junit",
"compatibility-common-util-devicesidelib",
- "truth-prebuilt",
+ "truth",
],
sdk_version: "test_current",
compile_multilib: "both",
- min_sdk_version: "UpsideDownCake",
+ min_sdk_version: "34",
}
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 526f240..6e8216f 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -41,7 +41,7 @@
"androidx.test.ext.junit",
"authfs_test_apk_assets",
"cbor-java",
- "truth-prebuilt",
+ "truth",
"compatibility-common-util-devicesidelib",
"measure_io_as_jar",
],
diff --git a/tests/vmshareapp/Android.bp b/tests/vmshareapp/Android.bp
index 6c2c9e4..5f6dc57 100644
--- a/tests/vmshareapp/Android.bp
+++ b/tests/vmshareapp/Android.bp
@@ -12,5 +12,5 @@
// Defined in ../testapk/Android.bp
"MicrodroidPayloadInOtherAppNativeLib",
],
- min_sdk_version: "UpsideDownCake",
+ min_sdk_version: "34",
}