xref: /aosp_15_r20/system/security/keystore2/postprocessor_client/src/lib.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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