1 // Copyright 2024, 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 //! Main executable of VM attestation for end-to-end testing.
16
17 use anyhow::Result;
18 use avflog::LogResult;
19 use com_android_virt_vm_attestation_testservice::{
20 aidl::com::android::virt::vm_attestation::testservice::IAttestationService::{
21 AttestationStatus::AttestationStatus, BnAttestationService, IAttestationService,
22 SigningResult::SigningResult, PORT,
23 },
24 binder::{self, BinderFeatures, Interface, IntoBinderResult, Strong},
25 };
26 use log::{error, info};
27 use std::sync::{Arc, Mutex};
28 use vm_payload::{AttestationError, AttestationResult};
29
30 vm_payload::main!(main);
31
32 // Entry point of the Service VM client.
main()33 fn main() {
34 android_logger::init_once(
35 android_logger::Config::default()
36 .with_tag("service_vm_client")
37 .with_max_level(log::LevelFilter::Debug),
38 );
39 if let Err(e) = try_main() {
40 error!("failed with {:?}", e);
41 std::process::exit(1);
42 }
43 }
44
try_main() -> Result<()>45 fn try_main() -> Result<()> {
46 info!("Welcome to Service VM Client!");
47
48 vm_payload::run_single_vsock_service(AttestationService::new_binder(), PORT.try_into()?)
49 }
50
51 struct AttestationService {
52 res: Arc<Mutex<Option<AttestationResult>>>,
53 }
54
55 impl Interface for AttestationService {}
56
57 impl AttestationService {
new_binder() -> Strong<dyn IAttestationService>58 fn new_binder() -> Strong<dyn IAttestationService> {
59 let res = Arc::new(Mutex::new(None));
60 BnAttestationService::new_binder(AttestationService { res }, BinderFeatures::default())
61 }
62 }
63
64 #[allow(non_snake_case)]
65 impl IAttestationService for AttestationService {
requestAttestationForTesting(&self) -> binder::Result<()>66 fn requestAttestationForTesting(&self) -> binder::Result<()> {
67 const CHALLENGE: &[u8] = &[0xaa; 32];
68 let res = vm_payload::restricted::request_attestation_for_testing(CHALLENGE)
69 .with_log()
70 .or_service_specific_exception(-1)?;
71 *self.res.lock().unwrap() = Some(res);
72 Ok(())
73 }
74
signWithAttestationKey( &self, challenge: &[u8], message: &[u8], ) -> binder::Result<SigningResult>75 fn signWithAttestationKey(
76 &self,
77 challenge: &[u8],
78 message: &[u8],
79 ) -> binder::Result<SigningResult> {
80 let res: AttestationResult = match vm_payload::request_attestation(challenge) {
81 Ok(res) => res,
82 Err(e) => {
83 let status = to_attestation_status(e);
84 return Ok(SigningResult { certificateChain: vec![], signature: vec![], status });
85 }
86 };
87
88 let certificate_chain: Vec<u8> = res.certificate_chain().flatten().collect();
89 let status = AttestationStatus::OK;
90 let signature = res.sign_message(message);
91
92 Ok(SigningResult { certificateChain: certificate_chain, signature, status })
93 }
94
validateAttestationResult(&self) -> binder::Result<()>95 fn validateAttestationResult(&self) -> binder::Result<()> {
96 // TODO(b/191073073): Returns the attestation result to the host for validation.
97 log(self.res.lock().unwrap().as_ref().unwrap());
98 Ok(())
99 }
100 }
101
log(res: &AttestationResult)102 fn log(res: &AttestationResult) {
103 for (i, cert) in res.certificate_chain().enumerate() {
104 info!("Attestation result certificate {i} = {cert:?}");
105 }
106
107 let private_key = res.private_key();
108 info!("Attestation result privateKey = {private_key:?}");
109
110 let message = b"Hello from Service VM client";
111 info!("Signing message: {message:?}");
112 let signature = res.sign_message(message);
113 info!("Signature: {signature:?}");
114 }
115
to_attestation_status(e: AttestationError) -> AttestationStatus116 fn to_attestation_status(e: AttestationError) -> AttestationStatus {
117 match e {
118 AttestationError::InvalidChallenge => AttestationStatus::ERROR_INVALID_CHALLENGE,
119 AttestationError::AttestationFailed => AttestationStatus::ERROR_ATTESTATION_FAILED,
120 AttestationError::AttestationUnsupported => AttestationStatus::ERROR_UNSUPPORTED,
121 }
122 }
123