From 30196cf77c3cc26d82dc5443b0890cdb4e7e4444 Mon Sep 17 00:00:00 2001 From: David Drysdale Date: Sat, 2 Dec 2023 19:24:15 +0000 Subject: [PATCH] KeyMint: default to Rust reference implementation Copy code that can be re-used from the Cuttlefish KeyMint implementation, specifically from the following directories under device/google/cuttlefish: - HAL-side code from guest/hals/keymint/rust/ - TA-side code from host/commands/secure_env/rust/ Create a corresponding pair of libkmr_{hal,ta}_nonsecure libraries here. The only changes to the copied code are: - Convert `pub(crate)` to `pub` in `attest.rs`. - Add some missing doc comments. - Add comment noting need for SELinux permission to read ro.serialno. - Add comment noting need for clock to be in sync with Gatekeeper. (A subsequent CL aosp/2852598 adjusts Cuttlefish so that it uses the copied modules here, and can remove the original copies.) In addition to the moved code, the default implementation also needs a new implementation of a monotonic clock, added here in clock.rs using `std::time::Instant`. With the new nonsecure HAL and TA libraries in place, implement the default KeyMint HAL service using the former, and spin up a single thread running a nonsecure TA using the latter. Communicate between the two via a pair of mpsc::channel()s. Test: VtsAidlKeyMintTargetTest with normal Cuttlefish (all pass) Test: VtsAidlKeyMintTargetTest with default/nonsecure impl (auth tests fail, but this is expected as Gatekeeper hasn't moved) Bug: 314513765 Change-Id: Ia450e9a8f2dc530f79e8d74d7ce65f7d67ea129f --- security/keymint/aidl/default/Android.bp | 70 ++-- security/keymint/aidl/default/hal/lib.rs | 99 +++++ security/keymint/aidl/default/main.rs | 174 +++++++++ security/keymint/aidl/default/service.cpp | 63 --- security/keymint/aidl/default/ta/attest.rs | 425 +++++++++++++++++++++ security/keymint/aidl/default/ta/clock.rs | 40 ++ security/keymint/aidl/default/ta/lib.rs | 109 ++++++ security/keymint/aidl/default/ta/rpc.rs | 234 ++++++++++++ security/keymint/aidl/default/ta/soft.rs | 67 ++++ 9 files changed, 1196 insertions(+), 85 deletions(-) create mode 100644 security/keymint/aidl/default/hal/lib.rs create mode 100644 security/keymint/aidl/default/main.rs delete mode 100644 security/keymint/aidl/default/service.cpp create mode 100644 security/keymint/aidl/default/ta/attest.rs create mode 100644 security/keymint/aidl/default/ta/clock.rs create mode 100644 security/keymint/aidl/default/ta/lib.rs create mode 100644 security/keymint/aidl/default/ta/rpc.rs create mode 100644 security/keymint/aidl/default/ta/soft.rs diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp index 953630ba85..d815ff7347 100644 --- a/security/keymint/aidl/default/Android.bp +++ b/security/keymint/aidl/default/Android.bp @@ -7,39 +7,29 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } -cc_binary { +rust_binary { name: "android.hardware.security.keymint-service", relative_install_path: "hw", + vendor: true, init_rc: ["android.hardware.security.keymint-service.rc"], vintf_fragments: [ "android.hardware.security.keymint-service.xml", "android.hardware.security.sharedsecret-service.xml", "android.hardware.security.secureclock-service.xml", ], - vendor: true, - cflags: [ - "-Wall", - "-Wextra", - ], defaults: [ - "keymint_use_latest_hal_aidl_ndk_shared", - ], - shared_libs: [ - "android.hardware.security.rkp-V3-ndk", - "android.hardware.security.sharedsecret-V1-ndk", - "android.hardware.security.secureclock-V1-ndk", - "libbase", - "libbinder_ndk", - "libcppbor_external", - "libcrypto", - "libkeymaster_portable", - "libkeymint", - "liblog", - "libpuresoftkeymasterdevice", - "libutils", + "keymint_use_latest_hal_aidl_rust", ], srcs: [ - "service.cpp", + "main.rs", + ], + rustlibs: [ + "libandroid_logger", + "libbinder_rs", + "liblog_rust", + "libkmr_hal", + "libkmr_hal_nonsecure", + "libkmr_ta_nonsecure", ], required: [ "android.hardware.hardware_keystore.xml", @@ -52,3 +42,39 @@ prebuilt_etc { vendor: true, src: "android.hardware.hardware_keystore.xml", } + +rust_library { + name: "libkmr_hal_nonsecure", + crate_name: "kmr_hal_nonsecure", + vendor_available: true, + lints: "android", + rustlibs: [ + "libbinder_rs", + "libhex", + "liblibc", + "liblog_rust", + "libkmr_hal", + "libkmr_wire", + ], + srcs: ["hal/lib.rs"], + +} + +rust_library { + name: "libkmr_ta_nonsecure", + crate_name: "kmr_ta_nonsecure", + vendor_available: true, + host_supported: true, + lints: "android", + rustlibs: [ + "libhex", + "liblibc", + "liblog_rust", + "libkmr_common", + "libkmr_crypto_boring", + "libkmr_ta", + "libkmr_wire", + ], + srcs: ["ta/lib.rs"], + +} diff --git a/security/keymint/aidl/default/hal/lib.rs b/security/keymint/aidl/default/hal/lib.rs new file mode 100644 index 0000000000..621f07793b --- /dev/null +++ b/security/keymint/aidl/default/hal/lib.rs @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! KeyMint helper functions that are only suitable for non-secure environments +//! such as Cuttlefish. + +use kmr_hal::env::get_property; +use log::error; + +/// Populate attestation ID information based on properties (where available). +/// Retrieving the serial number requires SELinux permission. +pub fn attestation_id_info() -> kmr_wire::AttestationIdInfo { + let prop = |name| { + get_property(name) + .unwrap_or_else(|_| format!("{} unavailable", name)) + .as_bytes() + .to_vec() + }; + kmr_wire::AttestationIdInfo { + brand: prop("ro.product.brand"), + device: prop("ro.product.device"), + product: prop("ro.product.name"), + serial: prop("ro.serialno"), + manufacturer: prop("ro.product.manufacturer"), + model: prop("ro.product.model"), + // Currently modem_simulator always returns one fixed value. See `handleGetIMEI` in + // device/google/cuttlefish/host/commands/modem_simulator/misc_service.cpp for more details. + // TODO(b/263188546): Use device-specific IMEI values when available. + imei: b"867400022047199".to_vec(), + imei2: b"867400022047199".to_vec(), + meid: vec![], + } +} + +/// Get boot information based on system properties. +pub fn get_boot_info() -> kmr_wire::SetBootInfoRequest { + // No access to a verified boot key. + let verified_boot_key = vec![0; 32]; + let vbmeta_digest = get_property("ro.boot.vbmeta.digest").unwrap_or_else(|_| "00".repeat(32)); + let verified_boot_hash = hex::decode(&vbmeta_digest).unwrap_or_else(|_e| { + error!("failed to parse hex data in '{}'", vbmeta_digest); + vec![0; 32] + }); + let device_boot_locked = match get_property("ro.boot.vbmeta.device_state") + .unwrap_or_else(|_| "no-prop".to_string()) + .as_str() + { + "locked" => true, + "unlocked" => false, + v => { + error!("Unknown device_state '{}', treating as unlocked", v); + false + } + }; + let verified_boot_state = match get_property("ro.boot.verifiedbootstate") + .unwrap_or_else(|_| "no-prop".to_string()) + .as_str() + { + "green" => 0, // Verified + "yellow" => 1, // SelfSigned + "orange" => 2, // Unverified, + "red" => 3, // Failed, + v => { + error!("Unknown boot state '{}', treating as Unverified", v); + 2 + } + }; + + // Attempt to get the boot patchlevel from a system property. This requires an SELinux + // permission, so fall back to re-using the OS patchlevel if this can't be done. + let boot_patchlevel_prop = get_property("ro.vendor.boot_security_patch").unwrap_or_else(|e| { + error!("Failed to retrieve boot patchlevel: {:?}", e); + get_property(kmr_hal::env::OS_PATCHLEVEL_PROPERTY) + .unwrap_or_else(|_| "1970-09-19".to_string()) + }); + let boot_patchlevel = + kmr_hal::env::extract_patchlevel(&boot_patchlevel_prop).unwrap_or(19700919); + + kmr_wire::SetBootInfoRequest { + verified_boot_key, + device_boot_locked, + verified_boot_state, + verified_boot_hash, + boot_patchlevel, + } +} diff --git a/security/keymint/aidl/default/main.rs b/security/keymint/aidl/default/main.rs new file mode 100644 index 0000000000..ea432d1a26 --- /dev/null +++ b/security/keymint/aidl/default/main.rs @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! Default implementation of the KeyMint HAL and related HALs. +//! +//! This implementation of the HAL is only intended to allow testing and policy compliance. A real +//! implementation **must be implemented in a secure environment**. + +use kmr_hal::SerializedChannel; +use kmr_hal_nonsecure::{attestation_id_info, get_boot_info}; +use log::{debug, error, info}; +use std::ops::DerefMut; +use std::sync::{mpsc, Arc, Mutex}; + +/// Name of KeyMint binder device instance. +static SERVICE_INSTANCE: &str = "default"; + +static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice"; +static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent"; +static CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock"; +static SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret"; + +/// Local error type for failures in the HAL service. +#[derive(Debug, Clone)] +struct HalServiceError(String); + +impl From for HalServiceError { + fn from(s: String) -> Self { + Self(s) + } +} + +fn main() { + if let Err(e) = inner_main() { + panic!("HAL service failed: {:?}", e); + } +} + +fn inner_main() -> Result<(), HalServiceError> { + // Initialize Android logging. + android_logger::init_once( + android_logger::Config::default() + .with_tag("keymint-hal-nonsecure") + .with_max_level(log::LevelFilter::Info) + .with_log_buffer(android_logger::LogId::System), + ); + // Redirect panic messages to logcat. + std::panic::set_hook(Box::new(|panic_info| { + error!("{}", panic_info); + })); + + info!("Insecure KeyMint HAL service is starting."); + + info!("Starting thread pool now."); + binder::ProcessState::start_thread_pool(); + + // Create a TA in-process, which acts as a local channel for communication. + let channel = Arc::new(Mutex::new(LocalTa::new())); + + let km_service = kmr_hal::keymint::Device::new_as_binder(channel.clone()); + let service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE); + binder::add_service(&service_name, km_service.as_binder()).map_err(|e| { + HalServiceError(format!( + "Failed to register service {} because of {:?}.", + service_name, e + )) + })?; + + let rpc_service = kmr_hal::rpc::Device::new_as_binder(channel.clone()); + let service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE); + binder::add_service(&service_name, rpc_service.as_binder()).map_err(|e| { + HalServiceError(format!( + "Failed to register service {} because of {:?}.", + service_name, e + )) + })?; + + let clock_service = kmr_hal::secureclock::Device::new_as_binder(channel.clone()); + let service_name = format!("{}/{}", CLOCK_SERVICE_NAME, SERVICE_INSTANCE); + binder::add_service(&service_name, clock_service.as_binder()).map_err(|e| { + HalServiceError(format!( + "Failed to register service {} because of {:?}.", + service_name, e + )) + })?; + + let secret_service = kmr_hal::sharedsecret::Device::new_as_binder(channel.clone()); + let service_name = format!("{}/{}", SECRET_SERVICE_NAME, SERVICE_INSTANCE); + binder::add_service(&service_name, secret_service.as_binder()).map_err(|e| { + HalServiceError(format!( + "Failed to register service {} because of {:?}.", + service_name, e + )) + })?; + + info!("Successfully registered KeyMint HAL services."); + + // Let the TA know information about the boot environment. In a real device this + // is communicated directly from the bootloader to the TA, but here we retrieve + // the information from system properties and send from the HAL service. + let boot_req = get_boot_info(); + debug!("boot/HAL->TA: boot info is {:?}", boot_req); + kmr_hal::send_boot_info(channel.lock().unwrap().deref_mut(), boot_req) + .map_err(|e| HalServiceError(format!("Failed to send boot info: {:?}", e)))?; + + // Let the TA know information about the userspace environment. + if let Err(e) = kmr_hal::send_hal_info(channel.lock().unwrap().deref_mut()) { + error!("Failed to send HAL info: {:?}", e); + } + + // Let the TA know about attestation IDs. (In a real device these would be pre-provisioned into + // the TA.) + let attest_ids = attestation_id_info(); + if let Err(e) = kmr_hal::send_attest_ids(channel.lock().unwrap().deref_mut(), attest_ids) { + error!("Failed to send attestation ID info: {:?}", e); + } + + info!("Successfully registered KeyMint HAL services."); + binder::ProcessState::join_thread_pool(); + info!("KeyMint HAL service is terminating."); // should not reach here + Ok(()) +} + +/// Implementation of the KeyMint TA that runs locally in-process (and which is therefore +/// insecure). +#[derive(Debug)] +pub struct LocalTa { + in_tx: mpsc::Sender>, + out_rx: mpsc::Receiver>, +} + +impl LocalTa { + /// Create a new instance. + pub fn new() -> Self { + // Create a pair of channels to communicate with the TA thread. + let (in_tx, in_rx) = mpsc::channel(); + let (out_tx, out_rx) = mpsc::channel(); + + // The TA code expects to run single threaded, so spawn a thread to run it in. + std::thread::spawn(move || { + let mut ta = kmr_ta_nonsecure::build_ta(); + loop { + let req_data: Vec = in_rx.recv().expect("failed to receive next req"); + let rsp_data = ta.process(&req_data); + out_tx.send(rsp_data).expect("failed to send out rsp"); + } + }); + Self { in_tx, out_rx } + } +} + +impl SerializedChannel for LocalTa { + const MAX_SIZE: usize = usize::MAX; + + fn execute(&mut self, req_data: &[u8]) -> binder::Result> { + self.in_tx + .send(req_data.to_vec()) + .expect("failed to send in request"); + Ok(self.out_rx.recv().expect("failed to receive response")) + } +} diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp deleted file mode 100644 index 10cbf07e30..0000000000 --- a/security/keymint/aidl/default/service.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "android.hardware.security.keymint-service" - -#include -#include -#include - -#include -#include -#include -#include -#include - -using aidl::android::hardware::security::keymint::AndroidKeyMintDevice; -using aidl::android::hardware::security::keymint::AndroidRemotelyProvisionedComponentDevice; -using aidl::android::hardware::security::keymint::SecurityLevel; -using aidl::android::hardware::security::secureclock::AndroidSecureClock; -using aidl::android::hardware::security::sharedsecret::AndroidSharedSecret; - -template -std::shared_ptr addService(Args&&... args) { - std::shared_ptr ser = ndk::SharedRefBase::make(std::forward(args)...); - auto instanceName = std::string(T::descriptor) + "/default"; - LOG(INFO) << "adding keymint service instance: " << instanceName; - binder_status_t status = - AServiceManager_addService(ser->asBinder().get(), instanceName.c_str()); - CHECK_EQ(status, STATUS_OK); - return ser; -} - -int main() { - // The global logger object required by keymaster's logging macros in keymaster/logger.h. - keymaster::SoftKeymasterLogger km_logger; - // Zero threads seems like a useless pool, but below we'll join this thread to it, increasing - // the pool size to 1. - ABinderProcess_setThreadPoolMaxThreadCount(0); - // Add Keymint Service - std::shared_ptr keyMint = - addService(SecurityLevel::SOFTWARE); - // Add Secure Clock Service - addService(keyMint); - // Add Shared Secret Service - addService(keyMint); - // Add Remotely Provisioned Component Service - addService(keyMint); - ABinderProcess_joinThreadPool(); - return EXIT_FAILURE; // should not reach -} diff --git a/security/keymint/aidl/default/ta/attest.rs b/security/keymint/aidl/default/ta/attest.rs new file mode 100644 index 0000000000..1ce20662db --- /dev/null +++ b/security/keymint/aidl/default/ta/attest.rs @@ -0,0 +1,425 @@ +// +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Attestation keys and certificates. +//! +//! Hard-coded keys and certs copied from system/keymaster/context/soft_attestation_cert.cpp + +use kmr_common::{ + crypto::ec, crypto::rsa, crypto::CurveType, crypto::KeyMaterial, wire::keymint, + wire::keymint::EcCurve, Error, +}; +use kmr_ta::device::{RetrieveCertSigningInfo, SigningAlgorithm, SigningKeyType}; + +/// RSA attestation private key in PKCS#1 format. +/// +/// Decoded contents (using [der2ascii](https://github.com/google/der-ascii)): +/// +/// ``` +/// SEQUENCE { +/// INTEGER { 0 } +/// INTEGER { `00c08323dc56881bb8302069f5b08561c6eebe7f05e2f5a842048abe8b47be76feaef25cf29b2afa3200141601429989a15fcfc6815eb363583c2fd2f20be4983283dd814b16d7e185417ae54abc296a3a6db5c004083b68c556c1f02339916419864d50b74d40aeca484c77356c895a0c275abfac499d5d7d2362f29c5e02e871` } +/// INTEGER { 65537 } +/// INTEGER { `00be860b0b99a802a6fb1a59438a7bb715065b09a36dc6e9cacc6bf3c02c34d7d79e94c6606428d88c7b7f6577c1cdea64074abe8e7286df1f0811dc9728260868de95d32efc96b6d084ff271a5f60defcc703e7a38e6e29ba9a3c5fc2c28076b6a896af1d34d78828ce9bddb1f34f9c9404430781298e201316725bbdbc993a41` } +/// INTEGER { `00e1c6d927646c0916ec36826d594983740c21f1b074c4a1a59867c669795c85d3dc464c5b929e94bfb34e0dcc5014b10f13341ab7fdd5f60414d2a326cad41cc5` } +/// INTEGER { `00da485997785cd5630fb0fd8c5254f98e538e18983aae9e6b7e6a5a7b5d343755b9218ebd40320d28387d789f76fa218bcc2d8b68a5f6418fbbeca5179ab3afbd` } +/// INTEGER { `50fefc32649559616ed6534e154509329d93a3d810dbe5bdb982292cf78bd8badb8020ae8d57f4b71d05386ffe9e9db271ca3477a34999db76f8e5ece9c0d49d` } +/// INTEGER { `15b74cf27cceff8bb36bf04d9d8346b09a2f70d2f4439b0f26ac7e03f7e9d1f77d4b915fd29b2823f03acb5d5200e0857ff2a803e93eee96d6235ce95442bc21` } +/// INTEGER { `0090a745da8970b2cd649660324228c5f82856ffd665ba9a85c8d60f1b8bee717ecd2c72eae01dad86ba7654d4cf45adb5f1f2b31d9f8122cfa5f1a5570f9b2d25` } +/// } +/// ``` +const RSA_ATTEST_KEY: &str = concat!( + "3082025d02010002818100c08323dc56881bb8302069f5b08561c6eebe7f05e2", + "f5a842048abe8b47be76feaef25cf29b2afa3200141601429989a15fcfc6815e", + "b363583c2fd2f20be4983283dd814b16d7e185417ae54abc296a3a6db5c00408", + "3b68c556c1f02339916419864d50b74d40aeca484c77356c895a0c275abfac49", + "9d5d7d2362f29c5e02e871020301000102818100be860b0b99a802a6fb1a5943", + "8a7bb715065b09a36dc6e9cacc6bf3c02c34d7d79e94c6606428d88c7b7f6577", + "c1cdea64074abe8e7286df1f0811dc9728260868de95d32efc96b6d084ff271a", + "5f60defcc703e7a38e6e29ba9a3c5fc2c28076b6a896af1d34d78828ce9bddb1", + "f34f9c9404430781298e201316725bbdbc993a41024100e1c6d927646c0916ec", + "36826d594983740c21f1b074c4a1a59867c669795c85d3dc464c5b929e94bfb3", + "4e0dcc5014b10f13341ab7fdd5f60414d2a326cad41cc5024100da485997785c", + "d5630fb0fd8c5254f98e538e18983aae9e6b7e6a5a7b5d343755b9218ebd4032", + "0d28387d789f76fa218bcc2d8b68a5f6418fbbeca5179ab3afbd024050fefc32", + "649559616ed6534e154509329d93a3d810dbe5bdb982292cf78bd8badb8020ae", + "8d57f4b71d05386ffe9e9db271ca3477a34999db76f8e5ece9c0d49d024015b7", + "4cf27cceff8bb36bf04d9d8346b09a2f70d2f4439b0f26ac7e03f7e9d1f77d4b", + "915fd29b2823f03acb5d5200e0857ff2a803e93eee96d6235ce95442bc210241", + "0090a745da8970b2cd649660324228c5f82856ffd665ba9a85c8d60f1b8bee71", + "7ecd2c72eae01dad86ba7654d4cf45adb5f1f2b31d9f8122cfa5f1a5570f9b2d", + "25", +); + +/// Attestation certificate corresponding to [`RSA_ATTEST_KEY`], signed by the key in +/// [`RSA_ATTEST_ROOT_CERT`]. +/// +/// Decoded contents: +/// +/// ``` +/// Certificate: +/// Data: +/// Version: 3 (0x2) +/// Serial Number: 4096 (0x1000) +/// Signature Algorithm: SHA256-RSA +/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California +/// Validity: +/// Not Before: 2016-01-04 12:40:53 +0000 UTC +/// Not After : 2035-12-30 12:40:53 +0000 UTC +/// Subject: C=US, O=Google, Inc., OU=Android, ST=California, CN=Android Software Attestation Key +/// Subject Public Key Info: +/// Public Key Algorithm: rsaEncryption +/// Public Key: (1024 bit) +/// Modulus: +/// c0:83:23:dc:56:88:1b:b8:30:20:69:f5:b0:85:61: +/// c6:ee:be:7f:05:e2:f5:a8:42:04:8a:be:8b:47:be: +/// 76:fe:ae:f2:5c:f2:9b:2a:fa:32:00:14:16:01:42: +/// 99:89:a1:5f:cf:c6:81:5e:b3:63:58:3c:2f:d2:f2: +/// 0b:e4:98:32:83:dd:81:4b:16:d7:e1:85:41:7a:e5: +/// 4a:bc:29:6a:3a:6d:b5:c0:04:08:3b:68:c5:56:c1: +/// f0:23:39:91:64:19:86:4d:50:b7:4d:40:ae:ca:48: +/// 4c:77:35:6c:89:5a:0c:27:5a:bf:ac:49:9d:5d:7d: +/// 23:62:f2:9c:5e:02:e8:71: +/// Exponent: 65537 (0x10001) +/// X509v3 extensions: +/// X509v3 Authority Key Identifier: +/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e +/// X509v3 Subject Key Identifier: +/// keyid:d40c101bf8cd63b9f73952b50e135ca6d7999386 +/// X509v3 Key Usage: critical +/// Digital Signature, Certificate Signing +/// X509v3 Basic Constraints: critical +/// CA:true, pathlen:0 +/// Signature Algorithm: SHA256-RSA +/// 9e:2d:48:5f:8c:67:33:dc:1a:85:ad:99:d7:50:23:ea:14:ec: +/// 43:b0:e1:9d:ea:c2:23:46:1e:72:b5:19:dc:60:22:e4:a5:68: +/// 31:6c:0b:55:c4:e6:9c:a2:2d:9f:3a:4f:93:6b:31:8b:16:78: +/// 16:0d:88:cb:d9:8b:cc:80:9d:84:f0:c2:27:e3:6b:38:f1:fd: +/// d1:e7:17:72:31:59:35:7d:96:f3:c5:7f:ab:9d:8f:96:61:26: +/// 4f:b2:be:81:bb:0d:49:04:22:8a:ce:9f:f7:f5:42:2e:25:44: +/// fa:21:07:12:5a:83:b5:55:ad:18:82:f8:40:14:9b:9c:20:63: +/// 04:7f: +/// ``` +const RSA_ATTEST_CERT: &str = concat!( + "308202b63082021fa00302010202021000300d06092a864886f70d01010b0500", + "3063310b30090603550406130255533113301106035504080c0a43616c69666f", + "726e69613116301406035504070c0d4d6f756e7461696e205669657731153013", + "060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e", + "64726f6964301e170d3136303130343132343035335a170d3335313233303132", + "343035335a3076310b30090603550406130255533113301106035504080c0a43", + "616c69666f726e696131153013060355040a0c0c476f6f676c652c20496e632e", + "3110300e060355040b0c07416e64726f69643129302706035504030c20416e64", + "726f696420536f667477617265204174746573746174696f6e204b657930819f", + "300d06092a864886f70d010101050003818d0030818902818100c08323dc5688", + "1bb8302069f5b08561c6eebe7f05e2f5a842048abe8b47be76feaef25cf29b2a", + "fa3200141601429989a15fcfc6815eb363583c2fd2f20be4983283dd814b16d7", + "e185417ae54abc296a3a6db5c004083b68c556c1f02339916419864d50b74d40", + "aeca484c77356c895a0c275abfac499d5d7d2362f29c5e02e8710203010001a3", + "663064301d0603551d0e04160414d40c101bf8cd63b9f73952b50e135ca6d799", + "9386301f0603551d2304183016801429faf1accc4dd24c96402775b6b0e932e5", + "07fe2e30120603551d130101ff040830060101ff020100300e0603551d0f0101", + "ff040403020284300d06092a864886f70d01010b0500038181009e2d485f8c67", + "33dc1a85ad99d75023ea14ec43b0e19deac223461e72b519dc6022e4a568316c", + "0b55c4e69ca22d9f3a4f936b318b1678160d88cbd98bcc809d84f0c227e36b38", + "f1fdd1e717723159357d96f3c57fab9d8f9661264fb2be81bb0d4904228ace9f", + "f7f5422e2544fa2107125a83b555ad1882f840149b9c2063047f", +); + +/// Attestation self-signed root certificate holding the key that signed [`RSA_ATTEST_CERT`]. +/// +/// Decoded contents: +/// +/// ``` +/// Certificate: +/// Data: +/// Version: 3 (0x2) +/// Serial Number: 18416584322103887884 (0xff94d9dd9f07c80c) +/// Signature Algorithm: SHA256-RSA +/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California +/// Validity: +/// Not Before: 2016-01-04 12:31:08 +0000 UTC +/// Not After : 2035-12-30 12:31:08 +0000 UTC +/// Subject: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California +/// Subject Public Key Info: +/// Public Key Algorithm: rsaEncryption +/// Public Key: (1024 bit) +/// Modulus: +/// a2:6b:ad:eb:6e:2e:44:61:ef:d5:0e:82:e6:b7:94: +/// d1:75:23:1f:77:9b:63:91:63:ff:f7:aa:ff:0b:72: +/// 47:4e:c0:2c:43:ec:33:7c:d7:ac:ed:40:3e:8c:28: +/// a0:66:d5:f7:87:0b:33:97:de:0e:b8:4e:13:40:ab: +/// af:a5:27:bf:95:69:a0:31:db:06:52:65:f8:44:59: +/// 57:61:f0:bb:f2:17:4b:b7:41:80:64:c0:28:0e:8f: +/// 52:77:8e:db:d2:47:b6:45:e9:19:c8:e9:8b:c3:db: +/// c2:91:3f:d7:d7:50:c4:1d:35:66:f9:57:e4:97:96: +/// 0b:09:ac:ce:92:35:85:9b: +/// Exponent: 65537 (0x10001) +/// X509v3 extensions: +/// X509v3 Authority Key Identifier: +/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e +/// X509v3 Subject Key Identifier: +/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e +/// X509v3 Key Usage: critical +/// Digital Signature, Certificate Signing +/// X509v3 Basic Constraints: critical +/// CA:true +/// Signature Algorithm: SHA256-RSA +/// 4f:72:f3:36:59:8d:0e:c1:b9:74:5b:31:59:f6:f0:8d:25:49: +/// 30:9e:a3:1c:1c:29:d2:45:2d:20:b9:4d:5f:64:b4:e8:80:c7: +/// 78:7a:9c:39:de:a8:b3:f5:bf:2f:70:5f:47:10:5c:c5:e6:eb: +/// 4d:06:99:61:d2:ae:9a:07:ff:f7:7c:b8:ab:eb:9c:0f:24:07: +/// 5e:b1:7f:ba:79:71:fd:4d:5b:9e:df:14:a9:fe:df:ed:7c:c0: +/// 88:5d:f8:dd:9b:64:32:56:d5:35:9a:e2:13:f9:8f:ce:c1:7c: +/// dc:ef:a4:aa:b2:55:c3:83:a9:2e:fb:5c:f6:62:f5:27:52:17: +/// be:63: +/// ``` +const RSA_ATTEST_ROOT_CERT: &str = concat!( + "308202a730820210a003020102020900ff94d9dd9f07c80c300d06092a864886", + "f70d01010b05003063310b30090603550406130255533113301106035504080c", + "0a43616c69666f726e69613116301406035504070c0d4d6f756e7461696e2056", + "69657731153013060355040a0c0c476f6f676c652c20496e632e3110300e0603", + "55040b0c07416e64726f6964301e170d3136303130343132333130385a170d33", + "35313233303132333130385a3063310b30090603550406130255533113301106", + "035504080c0a43616c69666f726e69613116301406035504070c0d4d6f756e74", + "61696e205669657731153013060355040a0c0c476f6f676c652c20496e632e31", + "10300e060355040b0c07416e64726f696430819f300d06092a864886f70d0101", + "01050003818d0030818902818100a26badeb6e2e4461efd50e82e6b794d17523", + "1f779b639163fff7aaff0b72474ec02c43ec337cd7aced403e8c28a066d5f787", + "0b3397de0eb84e1340abafa527bf9569a031db065265f844595761f0bbf2174b", + "b7418064c0280e8f52778edbd247b645e919c8e98bc3dbc2913fd7d750c41d35", + "66f957e497960b09acce9235859b0203010001a3633061301d0603551d0e0416", + "041429faf1accc4dd24c96402775b6b0e932e507fe2e301f0603551d23041830", + "16801429faf1accc4dd24c96402775b6b0e932e507fe2e300f0603551d130101", + "ff040530030101ff300e0603551d0f0101ff040403020284300d06092a864886", + "f70d01010b0500038181004f72f336598d0ec1b9745b3159f6f08d2549309ea3", + "1c1c29d2452d20b94d5f64b4e880c7787a9c39dea8b3f5bf2f705f47105cc5e6", + "eb4d069961d2ae9a07fff77cb8abeb9c0f24075eb17fba7971fd4d5b9edf14a9", + "fedfed7cc0885df8dd9b643256d5359ae213f98fcec17cdcefa4aab255c383a9", + "2efb5cf662f5275217be63", +); + +/// EC attestation private key in `ECPrivateKey` format. +/// +/// Decoded contents (using [der2ascii](https://github.com/google/der-ascii)): +/// +/// ``` +/// SEQUENCE { +/// INTEGER { 1 } +/// OCTET_STRING { `21e086432a15198459cf363a50fc14c9daadf935f527c2dfd71e4d6dbc42e544` } +/// [0] { +/// # secp256r1 +/// OBJECT_IDENTIFIER { 1.2.840.10045.3.1.7 } +/// } +/// [1] { +/// BIT_STRING { `00` `04eb9e79f8426359accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174974a2afea5b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014` } +/// } +/// } +/// ``` +const EC_ATTEST_KEY: &str = concat!( + "3077020101042021e086432a15198459cf363a50fc14c9daadf935f527c2dfd7", + "1e4d6dbc42e544a00a06082a8648ce3d030107a14403420004eb9e79f8426359", + "accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174974a2afea5", + "b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014", +); + +/// Attestation certificate corresponding to [`EC_ATTEST_KEY`], signed by the key in +/// [`EC_ATTEST_ROOT_CERT`]. +/// +/// Decoded contents: +/// +/// ``` +/// Certificate: +/// Data: +/// Version: 3 (0x2) +/// Serial Number: 4097 (0x1001) +/// Signature Algorithm: ECDSA-SHA256 +/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root +/// Validity: +/// Not Before: 2016-01-11 00:46:09 +0000 UTC +/// Not After : 2026-01-08 00:46:09 +0000 UTC +/// Subject: C=US, O=Google, Inc., OU=Android, ST=California, CN=Android Keystore Software Attestation Intermediate +/// Subject Public Key Info: +/// Public Key Algorithm: id-ecPublicKey +/// Public Key: (256 bit) +/// pub: +/// 04:eb:9e:79:f8:42:63:59:ac:cb:2a:91:4c:89:86: +/// cc:70:ad:90:66:93:82:a9:73:26:13:fe:ac:cb:f8: +/// 21:27:4c:21:74:97:4a:2a:fe:a5:b9:4d:7f:66:d4: +/// e0:65:10:66:35:bc:53:b7:a0:a3:a6:71:58:3e:db: +/// 3e:11:ae:10:14: +/// ASN1 OID: prime256v1 +/// X509v3 extensions: +/// X509v3 Authority Key Identifier: +/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf +/// X509v3 Subject Key Identifier: +/// keyid:3ffcacd61ab13a9e8120b8d5251cc565bb1e91a9 +/// X509v3 Key Usage: critical +/// Digital Signature, Certificate Signing +/// X509v3 Basic Constraints: critical +/// CA:true, pathlen:0 +/// Signature Algorithm: ECDSA-SHA256 +/// 30:45:02:20:4b:8a:9b:7b:ee:82:bc:c0:33:87:ae:2f:c0:89: +/// 98:b4:dd:c3:8d:ab:27:2a:45:9f:69:0c:c7:c3:92:d4:0f:8e: +/// 02:21:00:ee:da:01:5d:b6:f4:32:e9:d4:84:3b:62:4c:94:04: +/// ef:3a:7c:cc:bd:5e:fb:22:bb:e7:fe:b9:77:3f:59:3f:fb: +/// ``` +const EC_ATTEST_CERT: &str = concat!( + "308202783082021ea00302010202021001300a06082a8648ce3d040302308198", + "310b30090603550406130255533113301106035504080c0a43616c69666f726e", + "69613116301406035504070c0d4d6f756e7461696e2056696577311530130603", + "55040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e6472", + "6f69643133303106035504030c2a416e64726f6964204b657973746f72652053", + "6f667477617265204174746573746174696f6e20526f6f74301e170d31363031", + "31313030343630395a170d3236303130383030343630395a308188310b300906", + "03550406130255533113301106035504080c0a43616c69666f726e6961311530", + "13060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c0741", + "6e64726f6964313b303906035504030c32416e64726f6964204b657973746f72", + "6520536f667477617265204174746573746174696f6e20496e7465726d656469", + "6174653059301306072a8648ce3d020106082a8648ce3d03010703420004eb9e", + "79f8426359accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174", + "974a2afea5b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014a366", + "3064301d0603551d0e041604143ffcacd61ab13a9e8120b8d5251cc565bb1e91", + "a9301f0603551d23041830168014c8ade9774c45c3a3cf0d1610e479433a215a", + "30cf30120603551d130101ff040830060101ff020100300e0603551d0f0101ff", + "040403020284300a06082a8648ce3d040302034800304502204b8a9b7bee82bc", + "c03387ae2fc08998b4ddc38dab272a459f690cc7c392d40f8e022100eeda015d", + "b6f432e9d4843b624c9404ef3a7cccbd5efb22bbe7feb9773f593ffb", +); + +/// Attestation self-signed root certificate holding the key that signed [`EC_ATTEST_CERT`]. +/// +/// Decoded contents: +/// +/// ``` +/// Certificate: +/// Data: +/// Version: 3 (0x2) +/// Serial Number: 11674912229752527703 (0xa2059ed10e435b57) +/// Signature Algorithm: ECDSA-SHA256 +/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root +/// Validity: +/// Not Before: 2016-01-11 00:43:50 +0000 UTC +/// Not After : 2036-01-06 00:43:50 +0000 UTC +/// Subject: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root +/// Subject Public Key Info: +/// Public Key Algorithm: id-ecPublicKey +/// Public Key: (256 bit) +/// pub: +/// 04:ee:5d:5e:c7:e1:c0:db:6d:03:a6:7e:e6:b6:1b: +/// ec:4d:6a:5d:6a:68:2e:0f:ff:7f:49:0e:7d:77:1f: +/// 44:22:6d:bd:b1:af:fa:16:cb:c7:ad:c5:77:d2:56: +/// 9c:aa:b7:b0:2d:54:01:5d:3e:43:2b:2a:8e:d7:4e: +/// ec:48:75:41:a4: +/// ASN1 OID: prime256v1 +/// X509v3 extensions: +/// X509v3 Authority Key Identifier: +/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf +/// X509v3 Subject Key Identifier: +/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf +/// X509v3 Key Usage: critical +/// Digital Signature, Certificate Signing +/// X509v3 Basic Constraints: critical +/// CA:true +/// Signature Algorithm: ECDSA-SHA256 +/// 30:44:02:20:35:21:a3:ef:8b:34:46:1e:9c:d5:60:f3:1d:58: +/// 89:20:6a:dc:a3:65:41:f6:0d:9e:ce:8a:19:8c:66:48:60:7b: +/// 02:20:4d:0b:f3:51:d9:30:7c:7d:5b:da:35:34:1d:a8:47:1b: +/// 63:a5:85:65:3c:ad:4f:24:a7:e7:4d:af:41:7d:f1:bf: +/// ``` +const EC_ATTEST_ROOT_CERT: &str = concat!( + "3082028b30820232a003020102020900a2059ed10e435b57300a06082a8648ce", + "3d040302308198310b30090603550406130255533113301106035504080c0a43", + "616c69666f726e69613116301406035504070c0d4d6f756e7461696e20566965", + "7731153013060355040a0c0c476f6f676c652c20496e632e3110300e06035504", + "0b0c07416e64726f69643133303106035504030c2a416e64726f6964204b6579", + "73746f726520536f667477617265204174746573746174696f6e20526f6f7430", + "1e170d3136303131313030343335305a170d3336303130363030343335305a30", + "8198310b30090603550406130255533113301106035504080c0a43616c69666f", + "726e69613116301406035504070c0d4d6f756e7461696e205669657731153013", + "060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e", + "64726f69643133303106035504030c2a416e64726f6964204b657973746f7265", + "20536f667477617265204174746573746174696f6e20526f6f74305930130607", + "2a8648ce3d020106082a8648ce3d03010703420004ee5d5ec7e1c0db6d03a67e", + "e6b61bec4d6a5d6a682e0fff7f490e7d771f44226dbdb1affa16cbc7adc577d2", + "569caab7b02d54015d3e432b2a8ed74eec487541a4a3633061301d0603551d0e", + "04160414c8ade9774c45c3a3cf0d1610e479433a215a30cf301f0603551d2304", + "1830168014c8ade9774c45c3a3cf0d1610e479433a215a30cf300f0603551d13", + "0101ff040530030101ff300e0603551d0f0101ff040403020284300a06082a86", + "48ce3d040302034700304402203521a3ef8b34461e9cd560f31d5889206adca3", + "6541f60d9ece8a198c6648607b02204d0bf351d9307c7d5bda35341da8471b63", + "a585653cad4f24a7e74daf417df1bf", +); + +/// Per-algorithm attestation certificate signing information. +pub struct CertSignAlgoInfo { + key: KeyMaterial, + chain: Vec, +} + +/// Certificate signing information for all asymmetric key types. +pub struct CertSignInfo { + rsa_info: CertSignAlgoInfo, + ec_info: CertSignAlgoInfo, +} + +impl CertSignInfo { + /// Create a new cert signing impl. + pub fn new() -> Self { + CertSignInfo { + rsa_info: CertSignAlgoInfo { + key: KeyMaterial::Rsa(rsa::Key(hex::decode(RSA_ATTEST_KEY).unwrap()).into()), + chain: vec![ + keymint::Certificate { + encoded_certificate: hex::decode(RSA_ATTEST_CERT).unwrap(), + }, + keymint::Certificate { + encoded_certificate: hex::decode(RSA_ATTEST_ROOT_CERT).unwrap(), + }, + ], + }, + ec_info: CertSignAlgoInfo { + key: KeyMaterial::Ec( + EcCurve::P256, + CurveType::Nist, + ec::Key::P256(ec::NistKey(hex::decode(EC_ATTEST_KEY).unwrap())).into(), + ), + chain: vec![ + keymint::Certificate { + encoded_certificate: hex::decode(EC_ATTEST_CERT).unwrap(), + }, + keymint::Certificate { + encoded_certificate: hex::decode(EC_ATTEST_ROOT_CERT).unwrap(), + }, + ], + }, + } + } +} + +impl RetrieveCertSigningInfo for CertSignInfo { + fn signing_key(&self, key_type: SigningKeyType) -> Result { + Ok(match key_type.algo_hint { + SigningAlgorithm::Rsa => self.rsa_info.key.clone(), + SigningAlgorithm::Ec => self.ec_info.key.clone(), + }) + } + + fn cert_chain(&self, key_type: SigningKeyType) -> Result, Error> { + Ok(match key_type.algo_hint { + SigningAlgorithm::Rsa => self.rsa_info.chain.clone(), + SigningAlgorithm::Ec => self.ec_info.chain.clone(), + }) + } +} diff --git a/security/keymint/aidl/default/ta/clock.rs b/security/keymint/aidl/default/ta/clock.rs new file mode 100644 index 0000000000..ad8509abd3 --- /dev/null +++ b/security/keymint/aidl/default/ta/clock.rs @@ -0,0 +1,40 @@ +// +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Monotonic clock implementation. + +use kmr_common::crypto; +use std::time::Instant; + +/// Monotonic clock. +pub struct StdClock { + start: Instant, +} + +impl StdClock { + /// Create new clock instance, holding time since construction. + pub fn new() -> Self { + Self { + start: Instant::now(), + } + } +} + +impl crypto::MonotonicClock for StdClock { + fn now(&self) -> crypto::MillisecondsSinceEpoch { + let duration = self.start.elapsed(); + crypto::MillisecondsSinceEpoch(duration.as_millis().try_into().unwrap()) + } +} diff --git a/security/keymint/aidl/default/ta/lib.rs b/security/keymint/aidl/default/ta/lib.rs new file mode 100644 index 0000000000..fe8ad95cd5 --- /dev/null +++ b/security/keymint/aidl/default/ta/lib.rs @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! Local in-process implementation of the KeyMint TA. This is insecure and should +//! only be used for testing purposes. + +// This crate is `std` using, but some of the code uses macros from a `no_std` world. +extern crate alloc; + +use kmr_common::crypto; +use kmr_crypto_boring::{ + aes::BoringAes, aes_cmac::BoringAesCmac, des::BoringDes, ec::BoringEc, eq::BoringEq, + hmac::BoringHmac, rng::BoringRng, rsa::BoringRsa, sha256::BoringSha256, +}; +use kmr_ta::device::{ + BootloaderDone, CsrSigningAlgorithm, Implementation, TrustedPresenceUnsupported, +}; +use kmr_ta::{HardwareInfo, KeyMintTa, RpcInfo, RpcInfoV3}; +use kmr_wire::keymint::SecurityLevel; +use kmr_wire::rpc::MINIMUM_SUPPORTED_KEYS_IN_CSR; +use log::info; + +pub mod attest; +pub mod clock; +pub mod rpc; +pub mod soft; + +/// Build a set of crypto trait implementations based around BoringSSL and the standard library +/// clock. +pub fn boringssl_crypto_impls() -> crypto::Implementation { + let rng = BoringRng; + let clock = clock::StdClock::new(); + let rsa = BoringRsa::default(); + let ec = BoringEc::default(); + crypto::Implementation { + rng: Box::new(rng), + clock: Some(Box::new(clock)), + compare: Box::new(BoringEq), + aes: Box::new(BoringAes), + des: Box::new(BoringDes), + hmac: Box::new(BoringHmac), + rsa: Box::new(rsa), + ec: Box::new(ec), + ckdf: Box::new(BoringAesCmac), + hkdf: Box::new(BoringHmac), + sha256: Box::new(BoringSha256), + } +} + +/// Build a [`kmr_ta::KeyMintTa`] instance for nonsecure use. +pub fn build_ta() -> kmr_ta::KeyMintTa { + info!("Building NON-SECURE KeyMint Rust TA"); + let hw_info = HardwareInfo { + version_number: 1, + security_level: SecurityLevel::TrustedEnvironment, + impl_name: "Rust reference implementation", + author_name: "Google", + unique_id: "NON-SECURE KeyMint TA", + }; + let rpc_sign_algo = CsrSigningAlgorithm::EdDSA; + let rpc_info_v3 = RpcInfoV3 { + author_name: "Google", + unique_id: "NON-SECURE KeyMint TA", + fused: false, + supported_num_of_keys_in_csr: MINIMUM_SUPPORTED_KEYS_IN_CSR, + }; + + let sign_info = attest::CertSignInfo::new(); + let keys: Box = Box::new(soft::Keys); + let rpc: Box = Box::new(soft::RpcArtifacts::new( + soft::Derive::default(), + rpc_sign_algo, + )); + let dev = Implementation { + keys, + sign_info: Box::new(sign_info), + // HAL populates attestation IDs from properties. + attest_ids: None, + sdd_mgr: None, + // `BOOTLOADER_ONLY` keys not supported. + bootloader: Box::new(BootloaderDone), + // `STORAGE_KEY` keys not supported. + sk_wrapper: None, + // `TRUSTED_USER_PRESENCE_REQUIRED` keys not supported + tup: Box::new(TrustedPresenceUnsupported), + // No support for converting previous implementation's keyblobs. + legacy_key: None, + rpc, + }; + KeyMintTa::new( + hw_info, + RpcInfo::V3(rpc_info_v3), + boringssl_crypto_impls(), + dev, + ) +} diff --git a/security/keymint/aidl/default/ta/rpc.rs b/security/keymint/aidl/default/ta/rpc.rs new file mode 100644 index 0000000000..39da50e14c --- /dev/null +++ b/security/keymint/aidl/default/ta/rpc.rs @@ -0,0 +1,234 @@ +// +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Emulated implementation of device traits for `IRemotelyProvisionedComponent`. + +use core::cell::RefCell; +use kmr_common::crypto::{ec, ec::CoseKeyPurpose, Ec, KeyMaterial}; +use kmr_common::{crypto, explicit, rpc_err, vec_try, Error}; +use kmr_crypto_boring::{ec::BoringEc, hmac::BoringHmac, rng::BoringRng}; +use kmr_ta::device::{ + CsrSigningAlgorithm, DiceInfo, PubDiceArtifacts, RetrieveRpcArtifacts, RpcV2Req, +}; +use kmr_wire::coset::{iana, CoseSign1Builder, HeaderBuilder}; +use kmr_wire::keymint::{Digest, EcCurve}; +use kmr_wire::{cbor::value::Value, coset::AsCborValue, rpc, CborError}; + +/// Trait to encapsulate deterministic derivation of secret data. +pub trait DeriveBytes { + /// Derive `output_len` bytes of data from `context`, deterministically. + fn derive_bytes(&self, context: &[u8], output_len: usize) -> Result, Error>; +} + +/// Common emulated implementation of RPC artifact retrieval. +pub struct Artifacts { + derive: T, + sign_algo: CsrSigningAlgorithm, + // Invariant once populated: `self.dice_info.signing_algorithm` == `self.sign_algo` + dice_info: RefCell>, + // Invariant once populated: `self.bcc_signing_key` is a variant that matches `self.sign_algo` + bcc_signing_key: RefCell>, +} + +impl RetrieveRpcArtifacts for Artifacts { + fn derive_bytes_from_hbk( + &self, + _hkdf: &dyn crypto::Hkdf, + context: &[u8], + output_len: usize, + ) -> Result, Error> { + self.derive.derive_bytes(context, output_len) + } + + fn get_dice_info(&self, _test_mode: rpc::TestMode) -> Result { + if self.dice_info.borrow().is_none() { + let (dice_info, priv_key) = self.generate_dice_artifacts(rpc::TestMode(false))?; + *self.dice_info.borrow_mut() = Some(dice_info); + *self.bcc_signing_key.borrow_mut() = Some(priv_key); + } + + Ok(self + .dice_info + .borrow() + .as_ref() + .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? + .clone()) + } + + fn sign_data( + &self, + ec: &dyn crypto::Ec, + data: &[u8], + _rpc_v2: Option, + ) -> Result, Error> { + // DICE artifacts should have been initialized via `get_dice_info()` by the time this + // method is called. + let private_key = self + .bcc_signing_key + .borrow() + .as_ref() + .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? + .clone(); + + let mut op = ec.begin_sign(private_key.into(), self.signing_digest())?; + op.update(data)?; + let sig = op.finish()?; + crypto::ec::to_cose_signature(self.signing_curve(), sig) + } +} + +impl Artifacts { + /// Constructor. + pub fn new(derive: T, sign_algo: CsrSigningAlgorithm) -> Self { + Self { + derive, + sign_algo, + dice_info: RefCell::new(None), + bcc_signing_key: RefCell::new(None), + } + } + + /// Indicate the curve used in signing. + fn signing_curve(&self) -> EcCurve { + match self.sign_algo { + CsrSigningAlgorithm::ES256 => EcCurve::P256, + CsrSigningAlgorithm::ES384 => EcCurve::P384, + CsrSigningAlgorithm::EdDSA => EcCurve::Curve25519, + } + } + + /// Indicate the digest used in signing. + fn signing_digest(&self) -> Digest { + match self.sign_algo { + CsrSigningAlgorithm::ES256 => Digest::Sha256, + CsrSigningAlgorithm::ES384 => Digest::Sha384, + CsrSigningAlgorithm::EdDSA => Digest::None, + } + } + + /// Indicate the COSE algorithm value associated with signing. + fn signing_cose_algo(&self) -> iana::Algorithm { + match self.sign_algo { + CsrSigningAlgorithm::ES256 => iana::Algorithm::ES256, + CsrSigningAlgorithm::ES384 => iana::Algorithm::ES384, + CsrSigningAlgorithm::EdDSA => iana::Algorithm::EdDSA, + } + } + + fn generate_dice_artifacts( + &self, + _test_mode: rpc::TestMode, + ) -> Result<(DiceInfo, ec::Key), Error> { + let ec = BoringEc::default(); + + let key_material = match self.sign_algo { + CsrSigningAlgorithm::EdDSA => { + let secret = self.derive_bytes_from_hbk(&BoringHmac, b"Device Key Seed", 32)?; + ec::import_raw_ed25519_key(&secret) + } + // TODO: generate the *same* key after reboot, by use of the TPM. + CsrSigningAlgorithm::ES256 => { + ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P256, &[]) + } + CsrSigningAlgorithm::ES384 => { + ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P384, &[]) + } + }?; + let (pub_cose_key, private_key) = match key_material { + KeyMaterial::Ec(curve, curve_type, key) => ( + key.public_cose_key( + &ec, + curve, + curve_type, + CoseKeyPurpose::Sign, + None, /* no key ID */ + rpc::TestMode(false), + )?, + key, + ), + _ => { + return Err(rpc_err!( + Failed, + "expected the Ec variant of KeyMaterial for the cdi leaf key." + )) + } + }; + + let cose_key_cbor = pub_cose_key.to_cbor_value().map_err(CborError::from)?; + let cose_key_cbor_data = kmr_ta::rkp::serialize_cbor(&cose_key_cbor)?; + + // Construct `DiceChainEntryPayload` + let dice_chain_entry_payload = Value::Map(vec_try![ + // Issuer + ( + Value::Integer(1.into()), + Value::Text(String::from("Issuer")) + ), + // Subject + ( + Value::Integer(2.into()), + Value::Text(String::from("Subject")) + ), + // Subject public key + ( + Value::Integer((-4670552).into()), + Value::Bytes(cose_key_cbor_data) + ), + // Key Usage field contains a CBOR byte string of the bits which correspond + // to `keyCertSign` as per RFC 5280 Section 4.2.1.3 (in little-endian byte order) + ( + Value::Integer((-4670553).into()), + Value::Bytes(vec_try![0x20]?) + ), + ]?); + let dice_chain_entry_payload_data = kmr_ta::rkp::serialize_cbor(&dice_chain_entry_payload)?; + + // Construct `DiceChainEntry` + let protected = HeaderBuilder::new() + .algorithm(self.signing_cose_algo()) + .build(); + let dice_chain_entry = CoseSign1Builder::new() + .protected(protected) + .payload(dice_chain_entry_payload_data) + .try_create_signature(&[], |input| { + let mut op = ec.begin_sign(private_key.clone(), self.signing_digest())?; + op.update(input)?; + let sig = op.finish()?; + crypto::ec::to_cose_signature(self.signing_curve(), sig) + })? + .build(); + let dice_chain_entry_cbor = dice_chain_entry.to_cbor_value().map_err(CborError::from)?; + + // Construct `DiceCertChain` + let dice_cert_chain = Value::Array(vec_try![cose_key_cbor, dice_chain_entry_cbor]?); + let dice_cert_chain_data = kmr_ta::rkp::serialize_cbor(&dice_cert_chain)?; + + // Construct `UdsCerts` as an empty CBOR map + let uds_certs_data = kmr_ta::rkp::serialize_cbor(&Value::Map(Vec::new()))?; + + let pub_dice_artifacts = PubDiceArtifacts { + dice_cert_chain: dice_cert_chain_data, + uds_certs: uds_certs_data, + }; + + let dice_info = DiceInfo { + pub_dice_artifacts, + signing_algorithm: self.sign_algo, + rpc_v2_test_cdi_priv: None, + }; + + Ok((dice_info, explicit!(private_key)?)) + } +} diff --git a/security/keymint/aidl/default/ta/soft.rs b/security/keymint/aidl/default/ta/soft.rs new file mode 100644 index 0000000000..5bbe0608d9 --- /dev/null +++ b/security/keymint/aidl/default/ta/soft.rs @@ -0,0 +1,67 @@ +// +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Software-only trait implementations using fake keys. + +use kmr_common::{ + crypto, + crypto::{Hkdf, Rng}, + Error, +}; +use kmr_crypto_boring::{hmac::BoringHmac, rng::BoringRng}; +use kmr_ta::device::RetrieveKeyMaterial; + +/// Root key retrieval using hard-coded fake keys. +pub struct Keys; + +impl RetrieveKeyMaterial for Keys { + fn root_kek(&self, _context: &[u8]) -> Result, Error> { + // Matches `MASTER_KEY` in system/keymaster/key_blob_utils/software_keyblobs.cpp + Ok(crypto::hmac::Key::new([0; 16].to_vec()).into()) + } + fn kak(&self) -> Result, Error> { + // Matches `kFakeKeyAgreementKey` in + // system/keymaster/km_openssl/soft_keymaster_enforcement.cpp. + Ok(crypto::aes::Key::Aes256([0; 32]).into()) + } + fn unique_id_hbk(&self, _ckdf: &dyn crypto::Ckdf) -> Result { + // Matches value used in system/keymaster/contexts/pure_soft_keymaster_context.cpp. + crypto::hmac::Key::new_from(b"MustBeRandomBits") + } +} + +/// Implementation of key derivation using a random fake key. +pub struct Derive { + hbk: Vec, +} + +impl Default for Derive { + fn default() -> Self { + // Use random data as an emulation of a hardware-backed key. + let mut hbk = vec![0; 32]; + let mut rng = BoringRng; + rng.fill_bytes(&mut hbk); + Self { hbk } + } +} + +impl crate::rpc::DeriveBytes for Derive { + fn derive_bytes(&self, context: &[u8], output_len: usize) -> Result, Error> { + BoringHmac.hkdf(&[], &self.hbk, context, output_len) + } +} + +/// RPC artifact retrieval using software fake key. +pub type RpcArtifacts = crate::rpc::Artifacts;