blob: 490ff01d7cdecfdcc66e7cf311ada672497f7fff [file] [log] [blame]
// 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.
//! IRemotelyProvisionedComponent HAL implementation.
use crate::rkpvm;
use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
DeviceInfo::DeviceInfo,
IRemotelyProvisionedComponent::{
BnRemotelyProvisionedComponent, IRemotelyProvisionedComponent, STATUS_FAILED,
STATUS_INVALID_MAC, STATUS_REMOVED,
},
MacedPublicKey::MacedPublicKey,
ProtectedData::ProtectedData,
RpcHardwareInfo::{RpcHardwareInfo, CURVE_NONE, MIN_SUPPORTED_NUM_KEYS_IN_CSR},
};
use anyhow::Context;
use avflog::LogResult;
use binder::{
BinderFeatures, ExceptionCode, Interface, IntoBinderResult, Result as BinderResult, Status,
Strong,
};
use hypervisor_props::is_protected_vm_supported;
use rustutils::system_properties;
use service_vm_comm::{RequestProcessingError, Response};
/// Constructs a binder object that implements `IRemotelyProvisionedComponent`.
pub(crate) fn new_binder() -> Strong<dyn IRemotelyProvisionedComponent> {
BnRemotelyProvisionedComponent::new_binder(
AvfRemotelyProvisionedComponent {},
BinderFeatures::default(),
)
}
struct AvfRemotelyProvisionedComponent {}
impl Interface for AvfRemotelyProvisionedComponent {}
#[allow(non_snake_case)]
impl IRemotelyProvisionedComponent for AvfRemotelyProvisionedComponent {
fn getHardwareInfo(&self) -> BinderResult<RpcHardwareInfo> {
check_remote_attestation_is_supported()?;
Ok(RpcHardwareInfo {
versionNumber: 3,
rpcAuthorName: String::from("Android Virtualization Framework"),
supportedEekCurve: CURVE_NONE,
uniqueId: Some(String::from("AVF Remote Provisioning 1")),
supportedNumKeysInCsr: MIN_SUPPORTED_NUM_KEYS_IN_CSR,
})
}
fn generateEcdsaP256KeyPair(
&self,
testMode: bool,
macedPublicKey: &mut MacedPublicKey,
) -> BinderResult<Vec<u8>> {
check_remote_attestation_is_supported()?;
if testMode {
return Err(Status::new_service_specific_error_str(
STATUS_REMOVED,
Some("generateEcdsaP256KeyPair does not support test mode in IRPC v3+ HAL."),
))
.with_log();
}
let res = rkpvm::generate_ecdsa_p256_key_pair()
.context("Failed to generate ECDSA P-256 key pair")
.with_log()
.or_service_specific_exception(STATUS_FAILED)?;
match res {
Response::GenerateEcdsaP256KeyPair(key_pair) => {
macedPublicKey.macedKey = key_pair.maced_public_key;
Ok(key_pair.key_blob)
}
_ => Err(to_service_specific_error(res)),
}
.with_log()
}
fn generateCertificateRequest(
&self,
_testMode: bool,
_keysToSign: &[MacedPublicKey],
_endpointEncryptionCertChain: &[u8],
_challenge: &[u8],
_deviceInfo: &mut DeviceInfo,
_protectedData: &mut ProtectedData,
) -> BinderResult<Vec<u8>> {
Err(Status::new_service_specific_error_str(
STATUS_REMOVED,
Some("This method was deprecated in v3 of the interface."),
))
.with_log()
}
fn generateCertificateRequestV2(
&self,
keysToSign: &[MacedPublicKey],
challenge: &[u8],
) -> BinderResult<Vec<u8>> {
check_remote_attestation_is_supported()?;
const MAX_CHALLENGE_SIZE: usize = 64;
if challenge.len() > MAX_CHALLENGE_SIZE {
let message = format!(
"Challenge is too big. Actual: {:?}. Maximum: {:?}.",
challenge.len(),
MAX_CHALLENGE_SIZE
);
return Err(Status::new_service_specific_error_str(STATUS_FAILED, Some(message)))
.with_log();
}
let res = rkpvm::generate_certificate_request(keysToSign, challenge)
.context("Failed to generate certificate request")
.with_log()
.or_service_specific_exception(STATUS_FAILED)?;
match res {
Response::GenerateCertificateRequest(res) => Ok(res),
_ => Err(to_service_specific_error(res)),
}
.with_log()
}
}
pub(crate) fn check_remote_attestation_is_supported() -> BinderResult<()> {
if !is_protected_vm_supported().unwrap_or(false) {
return Err(Status::new_exception_str(
ExceptionCode::UNSUPPORTED_OPERATION,
Some("Protected VM support is missing for this operation"),
))
.with_log();
}
if !is_remote_attestation_supported() {
return Err(Status::new_exception_str(
ExceptionCode::UNSUPPORTED_OPERATION,
Some("Remote attestation is disabled"),
))
.with_log();
}
Ok(())
}
pub(crate) fn is_remote_attestation_supported() -> bool {
// Remote attestation is enabled by default.
system_properties::read_bool("avf.remote_attestation.enabled", true).unwrap_or(true)
}
pub(crate) fn to_service_specific_error(response: Response) -> Status {
match response {
Response::Err(e) => match e {
RequestProcessingError::InvalidMac => {
Status::new_service_specific_error_str(STATUS_INVALID_MAC, Some(format!("{e}")))
}
_ => Status::new_service_specific_error_str(
STATUS_FAILED,
Some(format!("Failed to process request: {e}.")),
),
},
other => Status::new_service_specific_error_str(
STATUS_FAILED,
Some(format!("Incorrect response type: {other:?}")),
),
}
}