1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! IRemotelyProvisionedComponent HAL implementation.
16 
17 use crate::rkpvm;
18 use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
19     DeviceInfo::DeviceInfo,
20     IRemotelyProvisionedComponent::{
21         BnRemotelyProvisionedComponent, IRemotelyProvisionedComponent, STATUS_FAILED,
22         STATUS_INVALID_MAC, STATUS_REMOVED,
23     },
24     MacedPublicKey::MacedPublicKey,
25     ProtectedData::ProtectedData,
26     RpcHardwareInfo::{RpcHardwareInfo, CURVE_NONE, MIN_SUPPORTED_NUM_KEYS_IN_CSR},
27 };
28 use anyhow::Context;
29 use avflog::LogResult;
30 use binder::{
31     BinderFeatures, ExceptionCode, Interface, IntoBinderResult, Result as BinderResult, Status,
32     Strong,
33 };
34 use hypervisor_props::is_protected_vm_supported;
35 use rustutils::system_properties;
36 use service_vm_comm::{RequestProcessingError, Response};
37 
38 /// Constructs a binder object that implements `IRemotelyProvisionedComponent`.
new_binder() -> Strong<dyn IRemotelyProvisionedComponent>39 pub(crate) fn new_binder() -> Strong<dyn IRemotelyProvisionedComponent> {
40     BnRemotelyProvisionedComponent::new_binder(
41         AvfRemotelyProvisionedComponent {},
42         BinderFeatures::default(),
43     )
44 }
45 
46 struct AvfRemotelyProvisionedComponent {}
47 
48 impl Interface for AvfRemotelyProvisionedComponent {}
49 
50 #[allow(non_snake_case)]
51 impl IRemotelyProvisionedComponent for AvfRemotelyProvisionedComponent {
getHardwareInfo(&self) -> BinderResult<RpcHardwareInfo>52     fn getHardwareInfo(&self) -> BinderResult<RpcHardwareInfo> {
53         check_remote_attestation_is_supported()?;
54 
55         Ok(RpcHardwareInfo {
56             versionNumber: 3,
57             rpcAuthorName: String::from("Android Virtualization Framework"),
58             supportedEekCurve: CURVE_NONE,
59             uniqueId: Some(String::from("AVF Remote Provisioning 1")),
60             supportedNumKeysInCsr: MIN_SUPPORTED_NUM_KEYS_IN_CSR,
61         })
62     }
63 
generateEcdsaP256KeyPair( &self, testMode: bool, macedPublicKey: &mut MacedPublicKey, ) -> BinderResult<Vec<u8>>64     fn generateEcdsaP256KeyPair(
65         &self,
66         testMode: bool,
67         macedPublicKey: &mut MacedPublicKey,
68     ) -> BinderResult<Vec<u8>> {
69         check_remote_attestation_is_supported()?;
70 
71         if testMode {
72             return Err(Status::new_service_specific_error_str(
73                 STATUS_REMOVED,
74                 Some("generateEcdsaP256KeyPair does not support test mode in IRPC v3+ HAL."),
75             ))
76             .with_log();
77         }
78         let res = rkpvm::generate_ecdsa_p256_key_pair()
79             .context("Failed to generate ECDSA P-256 key pair")
80             .with_log()
81             .or_service_specific_exception(STATUS_FAILED)?;
82         match res {
83             Response::GenerateEcdsaP256KeyPair(key_pair) => {
84                 macedPublicKey.macedKey = key_pair.maced_public_key;
85                 Ok(key_pair.key_blob)
86             }
87             _ => Err(to_service_specific_error(res)),
88         }
89         .with_log()
90     }
91 
generateCertificateRequest( &self, _testMode: bool, _keysToSign: &[MacedPublicKey], _endpointEncryptionCertChain: &[u8], _challenge: &[u8], _deviceInfo: &mut DeviceInfo, _protectedData: &mut ProtectedData, ) -> BinderResult<Vec<u8>>92     fn generateCertificateRequest(
93         &self,
94         _testMode: bool,
95         _keysToSign: &[MacedPublicKey],
96         _endpointEncryptionCertChain: &[u8],
97         _challenge: &[u8],
98         _deviceInfo: &mut DeviceInfo,
99         _protectedData: &mut ProtectedData,
100     ) -> BinderResult<Vec<u8>> {
101         Err(Status::new_service_specific_error_str(
102             STATUS_REMOVED,
103             Some("This method was deprecated in v3 of the interface."),
104         ))
105         .with_log()
106     }
107 
generateCertificateRequestV2( &self, keysToSign: &[MacedPublicKey], challenge: &[u8], ) -> BinderResult<Vec<u8>>108     fn generateCertificateRequestV2(
109         &self,
110         keysToSign: &[MacedPublicKey],
111         challenge: &[u8],
112     ) -> BinderResult<Vec<u8>> {
113         check_remote_attestation_is_supported()?;
114 
115         const MAX_CHALLENGE_SIZE: usize = 64;
116         if challenge.len() > MAX_CHALLENGE_SIZE {
117             let message = format!(
118                 "Challenge is too big. Actual: {:?}. Maximum: {:?}.",
119                 challenge.len(),
120                 MAX_CHALLENGE_SIZE
121             );
122             return Err(Status::new_service_specific_error_str(STATUS_FAILED, Some(message)))
123                 .with_log();
124         }
125         let res = rkpvm::generate_certificate_request(keysToSign, challenge)
126             .context("Failed to generate certificate request")
127             .with_log()
128             .or_service_specific_exception(STATUS_FAILED)?;
129         match res {
130             Response::GenerateCertificateRequest(res) => Ok(res),
131             _ => Err(to_service_specific_error(res)),
132         }
133         .with_log()
134     }
135 }
136 
check_remote_attestation_is_supported() -> BinderResult<()>137 pub(crate) fn check_remote_attestation_is_supported() -> BinderResult<()> {
138     if !is_protected_vm_supported().unwrap_or(false) {
139         return Err(Status::new_exception_str(
140             ExceptionCode::UNSUPPORTED_OPERATION,
141             Some("Protected VM support is missing for this operation"),
142         ))
143         .with_log();
144     }
145     if !is_remote_attestation_supported() {
146         return Err(Status::new_exception_str(
147             ExceptionCode::UNSUPPORTED_OPERATION,
148             Some("Remote attestation is disabled"),
149         ))
150         .with_log();
151     }
152     Ok(())
153 }
154 
is_remote_attestation_supported() -> bool155 pub(crate) fn is_remote_attestation_supported() -> bool {
156     // Remote attestation is enabled by default.
157     system_properties::read_bool("avf.remote_attestation.enabled", true).unwrap_or(true)
158 }
159 
to_service_specific_error(response: Response) -> Status160 pub(crate) fn to_service_specific_error(response: Response) -> Status {
161     match response {
162         Response::Err(e) => match e {
163             RequestProcessingError::InvalidMac => {
164                 Status::new_service_specific_error_str(STATUS_INVALID_MAC, Some(format!("{e}")))
165             }
166             _ => Status::new_service_specific_error_str(
167                 STATUS_FAILED,
168                 Some(format!("Failed to process request: {e}.")),
169             ),
170         },
171         other => Status::new_service_specific_error_str(
172             STATUS_FAILED,
173             Some(format!("Incorrect response type: {other:?}")),
174         ),
175     }
176 }
177