mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge "KeyMint: default to Rust reference implementation" into main
This commit is contained in:
@@ -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"],
|
||||
|
||||
}
|
||||
|
||||
99
security/keymint/aidl/default/hal/lib.rs
Normal file
99
security/keymint/aidl/default/hal/lib.rs
Normal file
@@ -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,
|
||||
}
|
||||
}
|
||||
174
security/keymint/aidl/default/main.rs
Normal file
174
security/keymint/aidl/default/main.rs
Normal file
@@ -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<String> 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<Vec<u8>>,
|
||||
out_rx: mpsc::Receiver<Vec<u8>>,
|
||||
}
|
||||
|
||||
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<u8> = 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<Vec<u8>> {
|
||||
self.in_tx
|
||||
.send(req_data.to_vec())
|
||||
.expect("failed to send in request");
|
||||
Ok(self.out_rx.recv().expect("failed to receive response"))
|
||||
}
|
||||
}
|
||||
@@ -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 <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include <AndroidKeyMintDevice.h>
|
||||
#include <AndroidRemotelyProvisionedComponentDevice.h>
|
||||
#include <AndroidSecureClock.h>
|
||||
#include <AndroidSharedSecret.h>
|
||||
#include <keymaster/soft_keymaster_logger.h>
|
||||
|
||||
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 <typename T, class... Args>
|
||||
std::shared_ptr<T> addService(Args&&... args) {
|
||||
std::shared_ptr<T> ser = ndk::SharedRefBase::make<T>(std::forward<Args>(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<AndroidKeyMintDevice> keyMint =
|
||||
addService<AndroidKeyMintDevice>(SecurityLevel::SOFTWARE);
|
||||
// Add Secure Clock Service
|
||||
addService<AndroidSecureClock>(keyMint);
|
||||
// Add Shared Secret Service
|
||||
addService<AndroidSharedSecret>(keyMint);
|
||||
// Add Remotely Provisioned Component Service
|
||||
addService<AndroidRemotelyProvisionedComponentDevice>(keyMint);
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
||||
425
security/keymint/aidl/default/ta/attest.rs
Normal file
425
security/keymint/aidl/default/ta/attest.rs
Normal file
@@ -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<keymint::Certificate>,
|
||||
}
|
||||
|
||||
/// 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<KeyMaterial, Error> {
|
||||
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<Vec<keymint::Certificate>, Error> {
|
||||
Ok(match key_type.algo_hint {
|
||||
SigningAlgorithm::Rsa => self.rsa_info.chain.clone(),
|
||||
SigningAlgorithm::Ec => self.ec_info.chain.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
40
security/keymint/aidl/default/ta/clock.rs
Normal file
40
security/keymint/aidl/default/ta/clock.rs
Normal file
@@ -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())
|
||||
}
|
||||
}
|
||||
109
security/keymint/aidl/default/ta/lib.rs
Normal file
109
security/keymint/aidl/default/ta/lib.rs
Normal file
@@ -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<dyn kmr_ta::device::RetrieveKeyMaterial> = Box::new(soft::Keys);
|
||||
let rpc: Box<dyn kmr_ta::device::RetrieveRpcArtifacts> = 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,
|
||||
)
|
||||
}
|
||||
234
security/keymint/aidl/default/ta/rpc.rs
Normal file
234
security/keymint/aidl/default/ta/rpc.rs
Normal file
@@ -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<Vec<u8>, Error>;
|
||||
}
|
||||
|
||||
/// Common emulated implementation of RPC artifact retrieval.
|
||||
pub struct Artifacts<T: DeriveBytes> {
|
||||
derive: T,
|
||||
sign_algo: CsrSigningAlgorithm,
|
||||
// Invariant once populated: `self.dice_info.signing_algorithm` == `self.sign_algo`
|
||||
dice_info: RefCell<Option<DiceInfo>>,
|
||||
// Invariant once populated: `self.bcc_signing_key` is a variant that matches `self.sign_algo`
|
||||
bcc_signing_key: RefCell<Option<ec::Key>>,
|
||||
}
|
||||
|
||||
impl<T: DeriveBytes> RetrieveRpcArtifacts for Artifacts<T> {
|
||||
fn derive_bytes_from_hbk(
|
||||
&self,
|
||||
_hkdf: &dyn crypto::Hkdf,
|
||||
context: &[u8],
|
||||
output_len: usize,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
self.derive.derive_bytes(context, output_len)
|
||||
}
|
||||
|
||||
fn get_dice_info(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> {
|
||||
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<RpcV2Req>,
|
||||
) -> Result<Vec<u8>, 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<T: DeriveBytes> Artifacts<T> {
|
||||
/// 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)?))
|
||||
}
|
||||
}
|
||||
67
security/keymint/aidl/default/ta/soft.rs
Normal file
67
security/keymint/aidl/default/ta/soft.rs
Normal file
@@ -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<crypto::OpaqueOr<crypto::hmac::Key>, 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<crypto::OpaqueOr<crypto::aes::Key>, 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<crypto::hmac::Key, Error> {
|
||||
// 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<u8>,
|
||||
}
|
||||
|
||||
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<Vec<u8>, Error> {
|
||||
BoringHmac.hkdf(&[], &self.hbk, context, output_len)
|
||||
}
|
||||
}
|
||||
|
||||
/// RPC artifact retrieval using software fake key.
|
||||
pub type RpcArtifacts = crate::rpc::Artifacts<Derive>;
|
||||
Reference in New Issue
Block a user