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 //! Helper wrapper around PostProcessor interface.
16
17 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::Certificate::Certificate;
18 use android_security_postprocessor::aidl::android::security::postprocessor::{
19 CertificateChain::CertificateChain,
20 IKeystoreCertificatePostProcessor::IKeystoreCertificatePostProcessor,
21 };
22 use anyhow::{Context, Result};
23 use binder::{StatusCode, Strong};
24 use log::{error, info, warn};
25 use message_macro::source_location_msg;
26 use std::sync::atomic::{AtomicBool, Ordering};
27 use std::sync::mpsc;
28 use std::thread;
29 use std::time::Duration;
30
31 /// Errors occurred during the interaction with Certificate Processor
32 #[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
33 #[error("Binder transaction error {0:?}")]
34 pub struct Error(pub StatusCode);
35
36 static CERT_PROCESSOR_FAILURE: AtomicBool = AtomicBool::new(false);
37
send_certificate_chain_to_processor( attestation_chain: CertificateChain, ) -> Result<CertificateChain>38 fn send_certificate_chain_to_processor(
39 attestation_chain: CertificateChain,
40 ) -> Result<CertificateChain> {
41 let cert_processing_server: Strong<dyn IKeystoreCertificatePostProcessor> = wait_for_interface(
42 "rkp_cert_processor.service".to_string(),
43 )
44 .context(source_location_msg!("While trying to connect to the post processor service."))?;
45 cert_processing_server
46 .processKeystoreCertificates(&attestation_chain)
47 .context(source_location_msg!("While trying to post process certificates."))
48 }
49
50 /// Processes the keystore certificates after the certificate chain has been generated by Keystore.
51 /// More details about this function provided in IKeystoreCertificatePostProcessor.aidl
process_certificate_chain( mut certificates: Vec<Certificate>, attestation_certs: Vec<u8>, ) -> Vec<Certificate>52 pub fn process_certificate_chain(
53 mut certificates: Vec<Certificate>,
54 attestation_certs: Vec<u8>,
55 ) -> Vec<Certificate> {
56 // If no certificates are provided from keymint, return the original chain.
57 if certificates.is_empty() {
58 error!("No leaf certificate provided.");
59 return vec![Certificate { encodedCertificate: attestation_certs }];
60 }
61
62 if certificates.len() > 1 {
63 warn!("dropping {} unexpected extra certificates after the leaf", certificates.len() - 1);
64 }
65
66 let attestation_chain = CertificateChain {
67 leafCertificate: certificates[0].encodedCertificate.clone(),
68 remainingChain: attestation_certs.clone(),
69 };
70 let result = send_certificate_chain_to_processor(attestation_chain);
71 match result {
72 Ok(certificate_chain) => {
73 info!("Post processing successful. Replacing certificates.");
74 vec![
75 Certificate { encodedCertificate: certificate_chain.leafCertificate },
76 Certificate { encodedCertificate: certificate_chain.remainingChain },
77 ]
78 }
79 Err(err) => {
80 error!("Failed to replace certificates ({err:#?}), falling back to original chain.");
81 certificates.push(Certificate { encodedCertificate: attestation_certs });
82 certificates
83 }
84 }
85 }
86
wait_for_interface( service_name: String, ) -> Result<Strong<dyn IKeystoreCertificatePostProcessor>>87 fn wait_for_interface(
88 service_name: String,
89 ) -> Result<Strong<dyn IKeystoreCertificatePostProcessor>> {
90 if CERT_PROCESSOR_FAILURE.load(Ordering::Relaxed) {
91 return Err(Error(StatusCode::INVALID_OPERATION).into());
92 }
93 let (sender, receiver) = mpsc::channel();
94 let _t = thread::spawn(move || {
95 if let Err(e) = sender.send(binder::wait_for_interface(&service_name)) {
96 error!("failed to send result of wait_for_interface({service_name}), likely due to timeout: {e:?}");
97 }
98 });
99
100 match receiver.recv_timeout(Duration::from_secs(5)) {
101 Ok(service_binder) => Ok(service_binder?),
102 Err(e) => {
103 error!("Timed out while connecting to post processor service: {e:#?}");
104 // Cert processor has failed. Retry only after reboot.
105 CERT_PROCESSOR_FAILURE.store(true, Ordering::Relaxed);
106 Err(e.into())
107 }
108 }
109 }
110