/* * Copyright 2024, 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 "SharedSecret.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace aidl::android::hardware::security::sharedsecret { ::ndk::ScopedAStatus SoftSharedSecret::getSharedSecretParameters( SharedSecretParameters* out_params) { std::lock_guard lock(mutex_); if (seed_.empty()) { seed_.resize(32, 0); } out_params->seed = seed_; if (nonce_.empty()) { nonce_.resize(32, 0); RAND_bytes(nonce_.data(), 32); } out_params->nonce = nonce_; LOG(INFO) << "Presented shared secret parameters with seed size " << out_params->seed.size() << " and nonce size " << out_params->nonce.size(); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus SoftSharedSecret::computeSharedSecret( const std::vector& params, std::vector* sharing_check) { std::lock_guard lock(mutex_); LOG(INFO) << "Computing shared secret"; // Reimplemented based on SoftKeymasterEnforcement, which does not expose // enough functionality to satisfy the GateKeeper interface keymaster::KeymasterKeyBlob key_agreement_key; if (key_agreement_key.Reset(32) == nullptr) { LOG(ERROR) << "key agreement key memory allocation failed"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED); } // Matching: // - kFakeAgreementKey in system/keymaster/km_openssl/soft_keymaster_enforcement.cpp // - Keys::kak in hardware/interfaces/security/keymint/aidl/default/ta/soft.rs std::memset(key_agreement_key.writable_data(), 0, 32); keymaster::KeymasterBlob label((uint8_t*)KEY_AGREEMENT_LABEL, strlen(KEY_AGREEMENT_LABEL)); if (label.data == nullptr) { LOG(ERROR) << "label memory allocation failed"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED); } static_assert(sizeof(keymaster_blob_t) == sizeof(keymaster::KeymasterBlob)); bool found_mine = false; std::vector context_blobs; for (const auto& param : params) { auto& seed_blob = context_blobs.emplace_back(); if (seed_blob.Reset(param.seed.size()) == nullptr) { LOG(ERROR) << "seed memory allocation failed"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED); } std::copy(param.seed.begin(), param.seed.end(), seed_blob.writable_data()); auto& nonce_blob = context_blobs.emplace_back(); if (nonce_blob.Reset(param.nonce.size()) == nullptr) { LOG(ERROR) << "Nonce memory allocation failed"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED); } std::copy(param.nonce.begin(), param.nonce.end(), nonce_blob.writable_data()); if (param.seed == seed_ && param.nonce == nonce_) { found_mine = true; } } if (!found_mine) { LOG(ERROR) << "Did not receive my own shared secret parameter back"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_INVALID_ARGUMENT); } auto context_blobs_ptr = reinterpret_cast(context_blobs.data()); if (hmac_key_.Reset(32) == nullptr) { LOG(ERROR) << "hmac key allocation failed"; return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED); } auto error = keymaster::ckdf(key_agreement_key, label, context_blobs_ptr, context_blobs.size(), &hmac_key_); if (error != KM_ERROR_OK) { LOG(ERROR) << "CKDF failed"; return keymint::km_utils::kmError2ScopedAStatus(error); } keymaster::HmacSha256 hmac_impl; if (!hmac_impl.Init(hmac_key_.key_material, hmac_key_.key_material_size)) { LOG(ERROR) << "hmac initialization failed"; return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } sharing_check->clear(); sharing_check->resize(32, 0); if (!hmac_impl.Sign((const uint8_t*)KEY_CHECK_LABEL, strlen(KEY_CHECK_LABEL), sharing_check->data(), sharing_check->size())) { return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } return ::ndk::ScopedAStatus::ok(); } keymaster::KeymasterKeyBlob SoftSharedSecret::HmacKey() const { std::lock_guard lock(mutex_); return hmac_key_; } } // namespace aidl::android::hardware::security::sharedsecret