blob: d606b6a9f2e6cd4a9f9e87c61c0f615c7bb0fa52 [file] [log] [blame]
Max Bires148c08e2020-10-13 13:41:41 -07001// Copyright 2020, 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//! This is the implementation for the remote provisioning AIDL interface between
16//! the network providers for remote provisioning and the system. This interface
17//! allows the caller to prompt the Remote Provisioning HAL to generate keys and
18//! CBOR blobs that can be ferried to a provisioning server that will return
19//! certificate chains signed by some root authority and stored in a keystore SQLite
20//! DB.
21
Max Biresb2e1d032021-02-08 21:35:05 -080022use std::collections::HashMap;
Max Bires148c08e2020-10-13 13:41:41 -070023
Max Biresb2e1d032021-02-08 21:35:05 -080024use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
25 IRemotelyProvisionedComponent::IRemotelyProvisionedComponent, MacedPublicKey::MacedPublicKey,
26 ProtectedData::ProtectedData, SecurityLevel::SecurityLevel,
27};
Max Bires148c08e2020-10-13 13:41:41 -070028use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
29 AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
30 IRemoteProvisioning::IRemoteProvisioning,
31};
Stephen Crane221bbb52020-12-16 15:52:10 -080032use android_security_remoteprovisioning::binder::Strong;
Max Biresb2e1d032021-02-08 21:35:05 -080033use anyhow::{Context, Result};
Max Bires148c08e2020-10-13 13:41:41 -070034
Max Biresb2e1d032021-02-08 21:35:05 -080035use crate::error::{self, map_or_log_err, map_rem_prov_error};
36use crate::globals::{get_keymint_device, get_remotely_provisioned_component, DB};
37use crate::utils::Asp;
Max Bires148c08e2020-10-13 13:41:41 -070038
39/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -080040#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -070041pub struct RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -080042 device_by_sec_level: HashMap<SecurityLevel, Asp>,
Max Bires148c08e2020-10-13 13:41:41 -070043}
44
45impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -080046 fn get_dev_by_sec_level(
47 &self,
48 sec_level: &SecurityLevel,
49 ) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
50 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
51 dev.get_interface().context("In get_dev_by_sec_level.")
52 } else {
53 Err(error::Error::sys()).context(concat!(
54 "In get_dev_by_sec_level: Remote instance for requested security level",
55 " not found."
56 ))
57 }
58 }
59
Max Bires148c08e2020-10-13 13:41:41 -070060 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -080061 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -080062 let mut result: Self = Default::default();
63 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
64 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
65 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
66 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
67 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
68 }
69 Ok(BnRemoteProvisioning::new_binder(result))
Max Bires148c08e2020-10-13 13:41:41 -070070 }
71
72 /// Populates the AttestationPoolStatus parcelable with information about how many
73 /// certs will be expiring by the date provided in `expired_by` along with how many
74 /// keys have not yet been assigned.
75 pub fn get_pool_status(
76 &self,
77 expired_by: i64,
78 sec_level: SecurityLevel,
79 ) -> Result<AttestationPoolStatus> {
80 let (_, _, uuid) = get_keymint_device(&sec_level)?;
81 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
82 let mut db = db.borrow_mut();
Max Biresb2e1d032021-02-08 21:35:05 -080083 // delete_expired_attestation_keys is always safe to call, and will remove anything
84 // older than the date at the time of calling. No work should be done on the
85 // attestation keys unless the pool status is checked first, so this call should be
86 // enough to routinely clean out expired keys.
87 db.delete_expired_attestation_keys()?;
Max Bires148c08e2020-10-13 13:41:41 -070088 Ok(db.get_attestation_pool_status(expired_by, &uuid)?)
89 })
90 }
91
92 /// Generates a CBOR blob which will be assembled by the calling code into a larger
93 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
94 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
95 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
96 /// be used to encrypt the sensitive contents being transmitted to the server, and the
97 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
98 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
99 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
100 pub fn generate_csr(
101 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800102 test_mode: bool,
103 num_csr: i32,
104 eek: &[u8],
105 challenge: &[u8],
106 sec_level: SecurityLevel,
107 protected_data: &mut ProtectedData,
Max Bires148c08e2020-10-13 13:41:41 -0700108 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800109 let dev = self.get_dev_by_sec_level(&sec_level)?;
110 let (_, _, uuid) = get_keymint_device(&sec_level)?;
111 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
112 let mut db = db.borrow_mut();
113 Ok(db
114 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
115 .iter()
116 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
117 .collect())
118 })?;
119 let mut mac = Vec::<u8>::with_capacity(32);
120 map_rem_prov_error(dev.generateCertificateRequest(
121 test_mode,
122 &keys_to_sign,
123 eek,
124 challenge,
125 &mut mac,
126 protected_data,
127 ))
128 .context("In generate_csr: Failed to generate csr")?;
129 Ok(mac)
Max Bires148c08e2020-10-13 13:41:41 -0700130 }
131
132 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
133 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
134 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
135 /// as a convenience from the caller to avoid having to parse the certificates semantically
136 /// here.
137 pub fn provision_cert_chain(
138 &self,
139 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800140 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700141 certs: &[u8],
142 expiration_date: i64,
143 sec_level: SecurityLevel,
144 ) -> Result<()> {
145 DB.with::<_, Result<()>>(|db| {
146 let mut db = db.borrow_mut();
147 let (_, _, uuid) = get_keymint_device(&sec_level)?;
148 Ok(db.store_signed_attestation_certificate_chain(
149 public_key,
Max Biresb2e1d032021-02-08 21:35:05 -0800150 batch_cert,
Max Bires148c08e2020-10-13 13:41:41 -0700151 certs, /* DER encoded certificate chain */
152 expiration_date,
153 &uuid,
154 )?)
155 })
156 }
157
158 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
159 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
160 /// for testing in order to differentiate them from private keys. If the call is successful,
161 /// the key pair is then added to the database.
Max Biresb2e1d032021-02-08 21:35:05 -0800162 pub fn generate_key_pair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> Result<()> {
163 let (_, _, uuid) = get_keymint_device(&sec_level)?;
164 let dev = self.get_dev_by_sec_level(&sec_level)?;
165 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
166 let priv_key =
167 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
168 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
169 // TODO(b/180392379): This is a brittle hack that relies on the consistent formatting of
170 // the returned CBOR blob in order to extract the public key.
171 let data = &maced_key.macedKey;
172 if data.len() < 85 {
173 return Err(error::Error::sys()).context(concat!(
174 "In generate_key_pair: CBOR blob returned from",
175 "RemotelyProvisionedComponent is definitely malformatted or empty."
176 ));
177 }
178 let mut raw_key: Vec<u8> = vec![0; 64];
179 raw_key[0..32].clone_from_slice(&data[18..18 + 32]);
180 raw_key[32..64].clone_from_slice(&data[53..53 + 32]);
181 DB.with::<_, Result<()>>(|db| {
182 let mut db = db.borrow_mut();
183 Ok(db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)?)
184 })
185 }
186
187 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
188 /// all levels in an array to the caller.
189 pub fn get_security_levels(&self) -> Result<Vec<SecurityLevel>> {
190 Ok(self.device_by_sec_level.keys().cloned().collect())
Max Bires148c08e2020-10-13 13:41:41 -0700191 }
192}
193
194impl binder::Interface for RemoteProvisioningService {}
195
196// Implementation of IRemoteProvisioning. See AIDL spec at
197// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
198impl IRemoteProvisioning for RemoteProvisioningService {
199 fn getPoolStatus(
200 &self,
201 expired_by: i64,
202 sec_level: SecurityLevel,
203 ) -> binder::public_api::Result<AttestationPoolStatus> {
204 map_or_log_err(self.get_pool_status(expired_by, sec_level), Ok)
205 }
206
207 fn generateCsr(
208 &self,
209 test_mode: bool,
210 num_csr: i32,
211 eek: &[u8],
212 challenge: &[u8],
213 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800214 protected_data: &mut ProtectedData,
Max Bires148c08e2020-10-13 13:41:41 -0700215 ) -> binder::public_api::Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800216 map_or_log_err(
217 self.generate_csr(test_mode, num_csr, eek, challenge, sec_level, protected_data),
218 Ok,
219 )
Max Bires148c08e2020-10-13 13:41:41 -0700220 }
221
222 fn provisionCertChain(
223 &self,
224 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800225 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700226 certs: &[u8],
227 expiration_date: i64,
228 sec_level: SecurityLevel,
229 ) -> binder::public_api::Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800230 map_or_log_err(
231 self.provision_cert_chain(public_key, batch_cert, certs, expiration_date, sec_level),
232 Ok,
233 )
Max Bires148c08e2020-10-13 13:41:41 -0700234 }
235
236 fn generateKeyPair(
237 &self,
238 is_test_mode: bool,
239 sec_level: SecurityLevel,
240 ) -> binder::public_api::Result<()> {
241 map_or_log_err(self.generate_key_pair(is_test_mode, sec_level), Ok)
242 }
Max Biresb2e1d032021-02-08 21:35:05 -0800243
244 fn getSecurityLevels(&self) -> binder::public_api::Result<Vec<SecurityLevel>> {
245 map_or_log_err(self.get_security_levels(), Ok)
246 }
Max Bires148c08e2020-10-13 13:41:41 -0700247}