| /* |
| * Copyright 2015 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. |
| */ |
| |
| #include "trusty_keymaster_context.h" |
| #include "secure_storage.h" |
| |
| extern "C" { |
| #include <lib/hwkey/hwkey.h> |
| #include <lib/rng/trusty_rng.h> |
| } |
| |
| #include <keymaster/android_keymaster_utils.h> |
| #include <keymaster/ec_key_factory.h> |
| #include <keymaster/logger.h> |
| #include <keymaster/rsa_key_factory.h> |
| #ifndef DISABLE_ATAP_SUPPORT |
| #include <libatap/libatap.h> |
| #endif |
| |
| #include "aes_key.h" |
| #include "auth_encrypted_key_blob.h" |
| #include "hmac_key.h" |
| #include "ocb_utils.h" |
| #include "openssl_err.h" |
| #include "test_attestation_keys.h" |
| |
| |
| /** |
| * Defining KEYMASTER_DEBUG will do the following: |
| * |
| * - Allow configure() to succeed without root of trust from bootloader |
| * - Allow attestation keys and certificates to be overwritten once set |
| */ |
| //#define KEYMASTER_DEBUG |
| |
| #ifdef KEYMASTER_DEBUG |
| #warning "Compiling with fake Keymaster Root of Trust values! DO NOT SHIP THIS!" |
| #endif |
| |
| namespace keymaster { |
| |
| namespace { |
| static const int kAesKeySize = 16; |
| static const int kCallsBetweenRngReseeds = 32; |
| static const int kRngReseedSize = 64; |
| static const uint8_t kMasterKeyDerivationData[kAesKeySize] = "KeymasterMaster"; |
| |
| bool UpgradeIntegerTag(keymaster_tag_t tag, uint32_t value, AuthorizationSet* set, |
| bool* set_changed) { |
| int index = set->find(tag); |
| if (index == -1) { |
| keymaster_key_param_t param; |
| param.tag = tag; |
| param.integer = value; |
| set->push_back(param); |
| *set_changed = true; |
| return true; |
| } |
| |
| if (set->params[index].integer > value) { |
| return false; |
| } |
| |
| if (set->params[index].integer != value) { |
| set->params[index].integer = value; |
| *set_changed = true; |
| } |
| return true; |
| } |
| |
| } // anonymous namespace |
| |
| TrustyKeymasterContext::TrustyKeymasterContext() |
| : enforcement_policy_(this), rng_initialized_(false), calls_since_reseed_(0) { |
| LOG_D("Creating TrustyKeymaster", 0); |
| rsa_factory_.reset(new RsaKeyFactory(this)); |
| ec_factory_.reset(new EcKeyFactory(this)); |
| aes_factory_.reset(new AesKeyFactory(this)); |
| hmac_factory_.reset(new HmacKeyFactory(this)); |
| verified_boot_key_.Reinitialize("Unbound", 7); |
| } |
| |
| KeyFactory* TrustyKeymasterContext::GetKeyFactory(keymaster_algorithm_t algorithm) const { |
| switch (algorithm) { |
| case KM_ALGORITHM_RSA: |
| return rsa_factory_.get(); |
| case KM_ALGORITHM_EC: |
| return ec_factory_.get(); |
| case KM_ALGORITHM_AES: |
| return aes_factory_.get(); |
| case KM_ALGORITHM_HMAC: |
| return hmac_factory_.get(); |
| default: |
| return nullptr; |
| } |
| } |
| |
| static keymaster_algorithm_t supported_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, |
| KM_ALGORITHM_AES, KM_ALGORITHM_HMAC}; |
| |
| keymaster_algorithm_t* |
| TrustyKeymasterContext::GetSupportedAlgorithms(size_t* algorithms_count) const { |
| *algorithms_count = array_length(supported_algorithms); |
| return supported_algorithms; |
| } |
| |
| OperationFactory* TrustyKeymasterContext::GetOperationFactory(keymaster_algorithm_t algorithm, |
| keymaster_purpose_t purpose) const { |
| KeyFactory* key_factory = GetKeyFactory(algorithm); |
| if (!key_factory) |
| return nullptr; |
| return key_factory->GetOperationFactory(purpose); |
| } |
| |
| static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error err) { |
| switch (err) { |
| case AuthorizationSet::OK: |
| return KM_ERROR_OK; |
| case AuthorizationSet::ALLOCATION_FAILURE: |
| return KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| case AuthorizationSet::MALFORMED_DATA: |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| return KM_ERROR_OK; |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::SetAuthorizations(const AuthorizationSet& key_description, |
| keymaster_key_origin_t origin, |
| AuthorizationSet* hw_enforced, |
| AuthorizationSet* sw_enforced) const { |
| sw_enforced->Clear(); |
| hw_enforced->Clear(); |
| |
| for (auto& entry : key_description) { |
| |
| switch (entry.tag) { |
| case KM_TAG_INVALID: |
| case KM_TAG_BOOTLOADER_ONLY: |
| case KM_TAG_NONCE: |
| case KM_TAG_AUTH_TOKEN: |
| case KM_TAG_MAC_LENGTH: |
| case KM_TAG_ASSOCIATED_DATA: |
| case KM_TAG_UNIQUE_ID: |
| return KM_ERROR_INVALID_KEY_BLOB; |
| |
| case KM_TAG_ROLLBACK_RESISTANT: |
| case KM_TAG_APPLICATION_ID: |
| case KM_TAG_APPLICATION_DATA: |
| case KM_TAG_ALL_APPLICATIONS: |
| case KM_TAG_ROOT_OF_TRUST: |
| case KM_TAG_ORIGIN: |
| case KM_TAG_RESET_SINCE_ID_ROTATION: |
| case KM_TAG_ALLOW_WHILE_ON_BODY: |
| case KM_TAG_ATTESTATION_CHALLENGE: |
| case KM_TAG_OS_VERSION: |
| case KM_TAG_OS_PATCHLEVEL: |
| // Ignore these. |
| break; |
| |
| case KM_TAG_PURPOSE: |
| case KM_TAG_ALGORITHM: |
| case KM_TAG_KEY_SIZE: |
| case KM_TAG_RSA_PUBLIC_EXPONENT: |
| case KM_TAG_BLOB_USAGE_REQUIREMENTS: |
| case KM_TAG_DIGEST: |
| case KM_TAG_PADDING: |
| case KM_TAG_BLOCK_MODE: |
| case KM_TAG_MIN_SECONDS_BETWEEN_OPS: |
| case KM_TAG_MAX_USES_PER_BOOT: |
| case KM_TAG_USER_SECURE_ID: |
| case KM_TAG_NO_AUTH_REQUIRED: |
| case KM_TAG_AUTH_TIMEOUT: |
| case KM_TAG_CALLER_NONCE: |
| case KM_TAG_MIN_MAC_LENGTH: |
| case KM_TAG_KDF: |
| case KM_TAG_EC_CURVE: |
| case KM_TAG_ECIES_SINGLE_HASH_MODE: |
| hw_enforced->push_back(entry); |
| break; |
| |
| case KM_TAG_USER_AUTH_TYPE: |
| if (entry.enumerated == HW_AUTH_PASSWORD) |
| hw_enforced->push_back(entry); |
| else |
| sw_enforced->push_back(entry); |
| break; |
| |
| case KM_TAG_ACTIVE_DATETIME: |
| case KM_TAG_ORIGINATION_EXPIRE_DATETIME: |
| case KM_TAG_USAGE_EXPIRE_DATETIME: |
| case KM_TAG_USER_ID: |
| case KM_TAG_ALL_USERS: |
| case KM_TAG_CREATION_DATETIME: |
| case KM_TAG_INCLUDE_UNIQUE_ID: |
| case KM_TAG_EXPORTABLE: |
| |
| sw_enforced->push_back(entry); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| hw_enforced->push_back(TAG_ORIGIN, origin); |
| // these values will be 0 if not set by bootloader |
| hw_enforced->push_back(TAG_OS_VERSION, boot_os_version_); |
| hw_enforced->push_back(TAG_OS_PATCHLEVEL, boot_os_patchlevel_); |
| |
| if (sw_enforced->is_valid() != AuthorizationSet::OK) |
| return TranslateAuthorizationSetError(sw_enforced->is_valid()); |
| if (hw_enforced->is_valid() != AuthorizationSet::OK) |
| return TranslateAuthorizationSetError(hw_enforced->is_valid()); |
| return KM_ERROR_OK; |
| } |
| |
| keymaster_error_t |
| TrustyKeymasterContext::BuildHiddenAuthorizations(const AuthorizationSet& input_set, |
| AuthorizationSet* hidden) const { |
| keymaster_blob_t entry; |
| if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry)) |
| hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length); |
| if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry)) |
| hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length); |
| |
| // Copy verified boot key, verified boot state, and device lock state to hidden |
| // authorization set for binding to key. |
| keymaster_key_param_t root_of_trust; |
| root_of_trust.tag = KM_TAG_ROOT_OF_TRUST; |
| root_of_trust.blob.data = verified_boot_key_.begin(); |
| root_of_trust.blob.data_length = verified_boot_key_.buffer_size(); |
| hidden->push_back(root_of_trust); |
| |
| root_of_trust.blob.data = reinterpret_cast<const uint8_t*>(&verified_boot_state_); |
| root_of_trust.blob.data_length = sizeof(verified_boot_state_); |
| hidden->push_back(root_of_trust); |
| |
| root_of_trust.blob.data = reinterpret_cast<const uint8_t*>(&device_locked_); |
| root_of_trust.blob.data_length = sizeof(device_locked_); |
| hidden->push_back(root_of_trust); |
| |
| return TranslateAuthorizationSetError(hidden->is_valid()); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::CreateAuthEncryptedKeyBlob( |
| const AuthorizationSet& key_description, const KeymasterKeyBlob& key_material, |
| const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced, |
| KeymasterKeyBlob* blob) const { |
| AuthorizationSet hidden; |
| keymaster_error_t error = BuildHiddenAuthorizations(key_description, &hidden); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| KeymasterKeyBlob master_key; |
| error = DeriveMasterKey(&master_key); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| Buffer nonce(OCB_NONCE_LENGTH); |
| Buffer tag(OCB_TAG_LENGTH); |
| if (!nonce.peek_write() || !tag.peek_write()) |
| return KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| |
| error = GenerateRandom(nonce.peek_write(), OCB_NONCE_LENGTH); |
| if (error != KM_ERROR_OK) |
| return error; |
| nonce.advance_write(OCB_NONCE_LENGTH); |
| |
| KeymasterKeyBlob encrypted_key; |
| error = OcbEncryptKey(hw_enforced, sw_enforced, hidden, master_key, key_material, nonce, |
| &encrypted_key, &tag); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| return SerializeAuthEncryptedBlob(encrypted_key, hw_enforced, sw_enforced, nonce, tag, blob); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description, |
| keymaster_key_origin_t origin, |
| const KeymasterKeyBlob& key_material, |
| KeymasterKeyBlob* blob, |
| AuthorizationSet* hw_enforced, |
| AuthorizationSet* sw_enforced) const { |
| keymaster_error_t error = SetAuthorizations(key_description, origin, hw_enforced, sw_enforced); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| return CreateAuthEncryptedKeyBlob(key_description, key_material, *hw_enforced, *sw_enforced, |
| blob); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade, |
| const AuthorizationSet& upgrade_params, |
| KeymasterKeyBlob* upgraded_key) const { |
| KeymasterKeyBlob key_material; |
| AuthorizationSet hw_enforced; |
| AuthorizationSet sw_enforced; |
| keymaster_error_t error = |
| ParseKeyBlob(key_to_upgrade, upgrade_params, &key_material, &hw_enforced, &sw_enforced); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| bool set_changed = false; |
| |
| if (boot_os_version_ == 0) { |
| // We need to allow "upgrading" OS version to zero, to support upgrading from proper |
| // numbered releases to unnumbered development and preview releases. |
| |
| int key_os_version_pos = sw_enforced.find(TAG_OS_VERSION); |
| if (key_os_version_pos != -1) { |
| uint32_t key_os_version = sw_enforced[key_os_version_pos].integer; |
| if (key_os_version != 0) { |
| sw_enforced[key_os_version_pos].integer = boot_os_version_; |
| set_changed = true; |
| } |
| } |
| } |
| |
| if (!UpgradeIntegerTag(TAG_OS_VERSION, boot_os_version_, &hw_enforced, &set_changed) || |
| !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, boot_os_patchlevel_, &hw_enforced, &set_changed)) { |
| // One of the version fields would have been a downgrade. Not allowed. |
| return KM_ERROR_INVALID_ARGUMENT; |
| } |
| |
| if (!set_changed) { |
| // Don't need an upgrade. |
| return KM_ERROR_OK; |
| } |
| |
| return CreateAuthEncryptedKeyBlob(upgrade_params, key_material, hw_enforced, sw_enforced, |
| upgraded_key); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blob, |
| const AuthorizationSet& additional_params, |
| KeymasterKeyBlob* key_material, |
| AuthorizationSet* hw_enforced, |
| AuthorizationSet* sw_enforced) const { |
| Buffer nonce, tag; |
| KeymasterKeyBlob encrypted_key_material; |
| keymaster_error_t error = DeserializeAuthEncryptedBlob(blob, &encrypted_key_material, |
| hw_enforced, sw_enforced, &nonce, &tag); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| if (nonce.available_read() != OCB_NONCE_LENGTH || tag.available_read() != OCB_TAG_LENGTH) |
| return KM_ERROR_INVALID_KEY_BLOB; |
| |
| KeymasterKeyBlob master_key; |
| error = DeriveMasterKey(&master_key); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| AuthorizationSet hidden; |
| error = BuildHiddenAuthorizations(additional_params, &hidden); |
| if (error != KM_ERROR_OK) |
| return error; |
| |
| return OcbDecryptKey(*hw_enforced, *sw_enforced, hidden, master_key, encrypted_key_material, |
| nonce, tag, key_material); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const { |
| if (trusty_rng_add_entropy(buf, length) != 0) |
| return KM_ERROR_UNKNOWN_ERROR; |
| return KM_ERROR_OK; |
| } |
| |
| bool TrustyKeymasterContext::SeedRngIfNeeded() const { |
| if (ShouldReseedRng()) |
| const_cast<TrustyKeymasterContext*>(this)->ReseedRng(); |
| return rng_initialized_; |
| } |
| |
| bool TrustyKeymasterContext::ShouldReseedRng() const { |
| if (!rng_initialized_) { |
| LOG_I("RNG not initalized, reseed", 0); |
| return true; |
| } |
| |
| if (++calls_since_reseed_ % kCallsBetweenRngReseeds == 0) { |
| LOG_I("Periodic reseed", 0); |
| return true; |
| } |
| return false; |
| } |
| |
| bool TrustyKeymasterContext::ReseedRng() { |
| UniquePtr<uint8_t[]> rand_seed(new uint8_t[kRngReseedSize]); |
| memset(rand_seed.get(), 0, kRngReseedSize); |
| if (trusty_rng_hw_rand(rand_seed.get(), kRngReseedSize) != 0) { |
| LOG_E("Failed to get bytes from HW RNG", 0); |
| return false; |
| } |
| LOG_I("Reseeding with %d bytes from HW RNG", kRngReseedSize); |
| trusty_rng_add_entropy(rand_seed.get(), kRngReseedSize); |
| |
| rng_initialized_ = true; |
| return true; |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::GenerateRandom(uint8_t* buf, size_t length) const { |
| if (!SeedRngIfNeeded() || trusty_rng_secure_rand(buf, length) != 0) |
| return KM_ERROR_UNKNOWN_ERROR; |
| return KM_ERROR_OK; |
| } |
| |
| // Gee wouldn't it be nice if the crypto service headers defined this. |
| enum DerivationParams { |
| DERIVATION_DATA_PARAM = 0, |
| OUTPUT_BUFFER_PARAM = 1, |
| }; |
| |
| keymaster_error_t TrustyKeymasterContext::DeriveMasterKey(KeymasterKeyBlob* master_key) const { |
| LOG_D("Deriving master key", 0); |
| |
| long rc = hwkey_open(); |
| if (rc < 0) { |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| |
| hwkey_session_t session = (hwkey_session_t)rc; |
| |
| if (!master_key->Reset(kAesKeySize)) { |
| LOG_S("Could not allocate memory for master key buffer", 0); |
| return KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| } |
| |
| uint32_t kdf_version = HWKEY_KDF_VERSION_1; |
| rc = hwkey_derive(session, &kdf_version, kMasterKeyDerivationData, master_key->writable_data(), |
| kAesKeySize); |
| |
| if (rc < 0) { |
| LOG_S("Error deriving master key: %d", rc); |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| |
| hwkey_close(session); |
| LOG_I("Key derivation complete", 0); |
| return KM_ERROR_OK; |
| } |
| |
| bool TrustyKeymasterContext::InitializeAuthTokenKey() { |
| if (GenerateRandom(auth_token_key_, kAuthTokenKeySize) != KM_ERROR_OK) |
| return false; |
| auth_token_key_initialized_ = true; |
| return auth_token_key_initialized_; |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::GetAuthTokenKey(keymaster_key_blob_t* key) const { |
| if (!auth_token_key_initialized_ && |
| !const_cast<TrustyKeymasterContext*>(this)->InitializeAuthTokenKey()) |
| return KM_ERROR_UNKNOWN_ERROR; |
| |
| key->key_material = auth_token_key_; |
| key->key_material_size = kAuthTokenKeySize; |
| return KM_ERROR_OK; |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::SetSystemVersion(uint32_t os_version, |
| uint32_t os_patchlevel) { |
| #ifndef KEYMASTER_DEBUG |
| if (!boot_params_set_ || boot_os_version_ != os_version || |
| boot_os_patchlevel_ != os_patchlevel) { |
| return KM_ERROR_INVALID_ARGUMENT; |
| } |
| #else |
| Buffer fake_root_of_trust("000111222333444555666777888999000", 32); |
| Buffer verified_boot_hash_none; |
| if (!boot_params_set_) { |
| /* Sets bootloader parameters to what is expected on a 'good' device, will pass |
| * attestation CTS tests. FOR DEBUGGING ONLY. |
| */ |
| SetBootParams(os_version, os_patchlevel, fake_root_of_trust, KM_VERIFIED_BOOT_VERIFIED, |
| true, verified_boot_hash_none); |
| } |
| #endif |
| |
| return KM_ERROR_OK; |
| } |
| |
| void TrustyKeymasterContext::GetSystemVersion(uint32_t* os_version, uint32_t* os_patchlevel) const { |
| *os_version = boot_os_version_; |
| *os_patchlevel = boot_os_patchlevel_; |
| } |
| |
| keymaster_error_t |
| TrustyKeymasterContext::GetVerifiedBootParams(keymaster_blob_t* verified_boot_key, |
| keymaster_verified_boot_t* verified_boot_state, |
| bool* device_locked) const { |
| verified_boot_key->data = verified_boot_key_.begin(); |
| verified_boot_key->data_length = verified_boot_key_.buffer_size(); |
| *verified_boot_state = verified_boot_state_; |
| *device_locked = device_locked_; |
| return KM_ERROR_OK; |
| } |
| |
| EVP_PKEY* TrustyKeymasterContext::AttestationKey(keymaster_algorithm_t algorithm, |
| keymaster_error_t* error) const { |
| |
| uint8_t* key = nullptr; |
| size_t key_size = 0; |
| int evp_key_type; |
| UniquePtr<uint8_t[]> key_deleter; |
| AttestationKeySlot key_slot; |
| |
| switch (algorithm) { |
| case KM_ALGORITHM_RSA: |
| evp_key_type = EVP_PKEY_RSA; |
| key_slot = AttestationKeySlot::kRsa; |
| break; |
| |
| case KM_ALGORITHM_EC: |
| evp_key_type = EVP_PKEY_EC; |
| key_slot = AttestationKeySlot::kEcdsa; |
| break; |
| |
| default: |
| *error = KM_ERROR_UNSUPPORTED_ALGORITHM; |
| return nullptr; |
| } |
| |
| *error = ReadKeyFromStorage(key_slot, &key, &key_size); |
| if (*error == KM_ERROR_OK) { |
| key_deleter.reset(key); |
| } else { |
| LOG_I("Failed to read attestation key from RPMB, falling back to test key", 0); |
| *error = GetSoftwareAttestationKey(algorithm, &key, &key_size); |
| } |
| if (*error != KM_ERROR_OK) |
| return nullptr; |
| const uint8_t* const_key = key; |
| EVP_PKEY* pkey = d2i_PrivateKey(evp_key_type, nullptr, &const_key, key_size); |
| if (!pkey) |
| *error = TranslateLastOpenSslError(); |
| |
| return pkey; |
| } |
| |
| keymaster_cert_chain_t* TrustyKeymasterContext::AttestationChain(keymaster_algorithm_t algorithm, |
| keymaster_error_t* error) const { |
| |
| UniquePtr<keymaster_cert_chain_t, CertificateChainDelete> chain(new keymaster_cert_chain_t); |
| if (!chain.get()) { |
| *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| return nullptr; |
| } |
| AttestationKeySlot key_slot; |
| switch (algorithm) { |
| case KM_ALGORITHM_RSA: |
| key_slot = AttestationKeySlot::kRsa; |
| break; |
| case KM_ALGORITHM_EC: |
| key_slot = AttestationKeySlot::kEcdsa; |
| break; |
| default: |
| *error = KM_ERROR_UNSUPPORTED_ALGORITHM; |
| return nullptr; |
| } |
| memset(chain.get(), 0, sizeof(keymaster_cert_chain_t)); |
| |
| *error = ReadCertChainFromStorage(key_slot, chain.get()); |
| if (*error != KM_ERROR_OK) { |
| LOG_I("Failed to read attestation chain from RPMB, falling back to test chain", 0); |
| *error = GetSoftwareAttestationChain(algorithm, chain.get()); |
| } |
| if (*error != KM_ERROR_OK) |
| return nullptr; |
| return chain.release(); |
| } |
| |
| keymaster_error_t |
| TrustyKeymasterContext::SetBootParams(uint32_t os_version, uint32_t os_patchlevel, |
| const Buffer& verified_boot_key, |
| keymaster_verified_boot_t verified_boot_state, |
| bool device_locked, const Buffer& verified_boot_hash) { |
| if (boot_params_set_) |
| return KM_ERROR_ROOT_OF_TRUST_ALREADY_SET; |
| boot_params_set_ = true; |
| boot_os_version_ = os_version; |
| boot_os_patchlevel_ = os_patchlevel; |
| verified_boot_hash_.Reinitialize(verified_boot_hash); |
| |
| // If no verified boot key hash is passed, then verified boot state is considered |
| // unverified and unlocked. |
| if (verified_boot_key.buffer_size()) { |
| verified_boot_key_.Reinitialize(verified_boot_key); |
| verified_boot_state_ = verified_boot_state; |
| device_locked_ = device_locked; |
| } |
| return KM_ERROR_OK; |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::SetAttestKey(keymaster_algorithm_t algorithm, |
| const uint8_t* key, uint32_t key_size) { |
| AttestationKeySlot key_slot; |
| switch (algorithm) { |
| case KM_ALGORITHM_RSA: |
| key_slot = AttestationKeySlot::kRsa; |
| break; |
| case KM_ALGORITHM_EC: |
| key_slot = AttestationKeySlot::kEcdsa; |
| break; |
| default: |
| return KM_ERROR_UNSUPPORTED_ALGORITHM; |
| } |
| if (key_size == 0) { |
| return KM_ERROR_INVALID_INPUT_LENGTH; |
| } |
| bool exists; |
| keymaster_error_t error = AttestationKeyExists(key_slot, &exists); |
| if (error != KM_ERROR_OK) { |
| return error; |
| } |
| #ifndef KEYMASTER_DEBUG |
| if (exists) { |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| #endif |
| return WriteKeyToStorage(key_slot, key, key_size); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::AppendAttestCertChain(keymaster_algorithm_t algorithm, |
| const uint8_t* cert, |
| uint32_t cert_size) { |
| AttestationKeySlot key_slot; |
| switch (algorithm) { |
| case KM_ALGORITHM_RSA: |
| key_slot = AttestationKeySlot::kRsa; |
| break; |
| case KM_ALGORITHM_EC: |
| key_slot = AttestationKeySlot::kEcdsa; |
| break; |
| default: |
| return KM_ERROR_UNSUPPORTED_ALGORITHM; |
| } |
| if (cert_size == 0) { |
| return KM_ERROR_INVALID_INPUT_LENGTH; |
| } |
| uint32_t cert_chain_length; |
| keymaster_error_t error = ReadCertChainLength(key_slot, &cert_chain_length); |
| if (error != KM_ERROR_OK) { |
| cert_chain_length = 0; |
| } |
| if (cert_chain_length >= kMaxCertChainLength) { |
| #ifndef KEYMASTER_DEBUG |
| return KM_ERROR_UNKNOWN_ERROR; |
| #else |
| // If debug flag is enabled, reset cert_chain_length when it hits max |
| cert_chain_length = 0; |
| #endif |
| } |
| return WriteCertToStorage(key_slot, cert, cert_size, cert_chain_length); |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::AtapGetCaRequest(const Buffer& operation_start, |
| Buffer* ca_request) { |
| #ifdef DISABLE_ATAP_SUPPORT |
| // Not implemented. |
| return KM_ERROR_UNKNOWN_ERROR; |
| #else |
| uint8_t* output; |
| uint32_t output_size; |
| AtapResult result = |
| atap_get_ca_request(atap_ops_provider_.atap_ops(), operation_start.begin(), |
| operation_start.available_read(), &output, &output_size); |
| if (result != ATAP_RESULT_OK) { |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| if (!ca_request->Reinitialize(output, output_size)) { |
| atap_free(output); |
| return KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| } |
| atap_free(output); |
| return KM_ERROR_OK; |
| #endif |
| } |
| |
| keymaster_error_t TrustyKeymasterContext::AtapSetCaResponse(const Buffer& ca_response) { |
| #ifdef DISABLE_ATAP_SUPPORT |
| // Not implemented. |
| return KM_ERROR_UNKNOWN_ERROR; |
| #else |
| AtapResult result = atap_set_ca_response(atap_ops_provider_.atap_ops(), ca_response.begin(), |
| ca_response.available_read()); |
| if (result != ATAP_RESULT_OK) { |
| return KM_ERROR_UNKNOWN_ERROR; |
| } |
| return KM_ERROR_OK; |
| #endif |
| } |
| |
| } // namespace keymaster |