blob: 086a162b55349f1f5f67ea70d7314cdd87c9d959 [file] [log] [blame]
Alan Stokes337874a2021-06-16 16:49:32 +01001// Copyright 2021, 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//! Provides a binder service for key generation & verification for CompOs. We assume we have
16//! access to Keystore in the VM, but not persistent storage; instead the host stores the key
17//! on our behalf via this service.
18
19use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
20 Algorithm::Algorithm, Digest::Digest, KeyParameter::KeyParameter,
21 KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
22 SecurityLevel::SecurityLevel, Tag::Tag,
23};
24use android_system_keystore2::aidl::android::system::keystore2::{
25 Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
26 IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor,
27};
Victor Hsieh23f73592021-08-06 18:08:24 -070028use android_system_keystore2::binder::{wait_for_interface, Strong};
Alan Stokes337874a2021-06-16 16:49:32 +010029use anyhow::{anyhow, Context, Result};
Victor Hsieh23f73592021-08-06 18:08:24 -070030use compos_aidl_interface::aidl::com::android::compos::CompOsKeyData::CompOsKeyData;
Alan Stokes337874a2021-06-16 16:49:32 +010031use ring::rand::{SecureRandom, SystemRandom};
32use ring::signature;
33use scopeguard::ScopeGuard;
Alan Stokes337874a2021-06-16 16:49:32 +010034
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070035/// Keystore2 namespace ID, used for access control to keys. In a VM we can use the generic ID
36/// allocated for payloads. See microdroid's keystore2_key_contexts.
37const KEYSTORE_NAMESPACE: i64 = 140;
Alan Stokesb15c93f2021-07-15 16:21:50 +010038
Alan Stokes337874a2021-06-16 16:49:32 +010039const KEYSTORE_SERVICE_NAME: &str = "android.system.keystore2.IKeystoreService/default";
Alan Stokes337874a2021-06-16 16:49:32 +010040const PURPOSE_SIGN: KeyParameter =
41 KeyParameter { tag: Tag::PURPOSE, value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN) };
42const ALGORITHM: KeyParameter =
43 KeyParameter { tag: Tag::ALGORITHM, value: KeyParameterValue::Algorithm(Algorithm::RSA) };
44const PADDING: KeyParameter = KeyParameter {
45 tag: Tag::PADDING,
46 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
47};
48const DIGEST: KeyParameter =
49 KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) };
50const KEY_SIZE: KeyParameter =
51 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) };
52const EXPONENT: KeyParameter =
53 KeyParameter { tag: Tag::RSA_PUBLIC_EXPONENT, value: KeyParameterValue::LongInteger(65537) };
54const NO_AUTH_REQUIRED: KeyParameter =
55 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) };
56
Alan Stokesb15c93f2021-07-15 16:21:50 +010057const BLOB_KEY_DESCRIPTOR: KeyDescriptor =
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070058 KeyDescriptor { domain: Domain::BLOB, nspace: KEYSTORE_NAMESPACE, alias: None, blob: None };
Alan Stokes337874a2021-06-16 16:49:32 +010059
Victor Hsieha64194b2021-08-06 17:43:36 -070060/// An internal service for CompOS key management.
Alan Stokes7ec4e7f2021-07-21 11:29:10 +010061#[derive(Clone)]
Victor Hsieha64194b2021-08-06 17:43:36 -070062pub struct CompOsKeyService {
Alan Stokes337874a2021-06-16 16:49:32 +010063 random: SystemRandom,
Alan Stokes337874a2021-06-16 16:49:32 +010064 security_level: Strong<dyn IKeystoreSecurityLevel>,
65}
66
Alan Stokes7ec4e7f2021-07-21 11:29:10 +010067impl CompOsKeyService {
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070068 pub fn new() -> Result<Self> {
Victor Hsieha64194b2021-08-06 17:43:36 -070069 let keystore_service = wait_for_interface::<dyn IKeystoreService>(KEYSTORE_SERVICE_NAME)
70 .context("No Keystore service")?;
71
72 Ok(CompOsKeyService {
Victor Hsieha64194b2021-08-06 17:43:36 -070073 random: SystemRandom::new(),
74 security_level: keystore_service
75 .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
76 .context("Getting SecurityLevel failed")?,
77 })
78 }
79
Alan Stokes183d7d32021-12-08 16:10:45 +000080 pub fn generate(&self) -> Result<CompOsKeyData> {
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070081 let key_descriptor = BLOB_KEY_DESCRIPTOR;
Alan Stokes337874a2021-06-16 16:49:32 +010082 let key_parameters =
83 [PURPOSE_SIGN, ALGORITHM, PADDING, DIGEST, KEY_SIZE, EXPONENT, NO_AUTH_REQUIRED];
84 let attestation_key = None;
85 let flags = 0;
86 let entropy = [];
87
88 let key_metadata = self
Alan Stokes4a489d42021-06-28 10:12:05 +010089 .security_level
Alan Stokesb15c93f2021-07-15 16:21:50 +010090 .generateKey(&key_descriptor, attestation_key, &key_parameters, flags, &entropy)
Alan Stokes337874a2021-06-16 16:49:32 +010091 .context("Generating key failed")?;
92
93 if let (Some(certificate), Some(blob)) = (key_metadata.certificate, key_metadata.key.blob) {
94 Ok(CompOsKeyData { certificate, keyBlob: blob })
95 } else {
96 Err(anyhow!("Missing cert or blob"))
97 }
98 }
99
Alan Stokes183d7d32021-12-08 16:10:45 +0000100 pub fn verify(&self, key_blob: &[u8], public_key: &[u8]) -> Result<()> {
Alan Stokes337874a2021-06-16 16:49:32 +0100101 let mut data = [0u8; 32];
102 self.random.fill(&mut data).context("No random data")?;
103
Alan Stokes46a1dff2021-12-14 10:56:05 +0000104 let signature = self.new_signer(key_blob).sign(&data)?;
Alan Stokes337874a2021-06-16 16:49:32 +0100105
106 let public_key =
107 signature::UnparsedPublicKey::new(&signature::RSA_PKCS1_2048_8192_SHA256, public_key);
108 public_key.verify(&data, &signature).context("Signature verification failed")?;
109
110 Ok(())
111 }
112
Alan Stokes46a1dff2021-12-14 10:56:05 +0000113 pub fn new_signer(&self, key_blob: &[u8]) -> Signer {
114 Signer { key_blob: key_blob.to_vec(), security_level: self.security_level.clone() }
115 }
116}
117
118pub struct Signer {
119 key_blob: Vec<u8>,
120 security_level: Strong<dyn IKeystoreSecurityLevel>,
121}
122
123impl Signer {
124 pub fn sign(self, data: &[u8]) -> Result<Vec<u8>> {
125 let key_descriptor = KeyDescriptor { blob: Some(self.key_blob), ..BLOB_KEY_DESCRIPTOR };
Alan Stokes337874a2021-06-16 16:49:32 +0100126 let operation_parameters = [PURPOSE_SIGN, ALGORITHM, PADDING, DIGEST];
127 let forced = false;
128
129 let response = self
Alan Stokes4a489d42021-06-28 10:12:05 +0100130 .security_level
Alan Stokes337874a2021-06-16 16:49:32 +0100131 .createOperation(&key_descriptor, &operation_parameters, forced)
132 .context("Creating key failed")?;
133 let operation = scopeguard::guard(
134 response.iOperation.ok_or_else(|| anyhow!("No operation created"))?,
135 |op| op.abort().unwrap_or_default(),
136 );
137
138 if response.operationChallenge.is_some() {
139 return Err(anyhow!("Key requires user authorization"));
140 }
141
Chris Wailes68c39f82021-07-27 16:03:44 -0700142 let signature = operation.finish(Some(data), None).context("Signing failed")?;
Alan Stokes337874a2021-06-16 16:49:32 +0100143 // Operation has finished, we're no longer responsible for aborting it
144 ScopeGuard::into_inner(operation);
145
146 signature.ok_or_else(|| anyhow!("No signature returned"))
147 }
148}