1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <android-base/logging.h> 18#include <hidl/HidlTransportSupport.h> 19#include <utils/StrongPointer.h> 20 21#include <application.h> 22#include <nos/AppClient.h> 23#include <nos/CitadeldProxyClient.h> 24#include <nos/debug.h> 25 26#include <KeymasterDevice.h> 27#include <Keymaster.client.h> 28 29#ifdef ENABLE_QCOM_OTF_PROVISIONING 30#include <KeymasterKeyProvision.h> 31#endif 32#include <nugget/app/keymaster/keymaster.pb.h> 33#include "../proto_utils.h" 34 35using ::android::OK; 36using ::android::sp; 37using ::android::status_t; 38using ::android::hardware::configureRpcThreadpool; 39using ::android::hardware::joinRpcThreadpool; 40 41using ::android::hardware::keymaster::KeymasterDevice; 42using ::android::hardware::keymaster::translate_error_code; 43 44using ::nos::CitadeldProxyClient; 45using ::nos::AppClient; 46using ::nugget::app::keymaster::ProvisionPresharedSecretRequest; 47using ::nugget::app::keymaster::ProvisionPresharedSecretResponse; 48using ::nugget::app::keymaster::PresharedSecretStatus; 49using ErrorCodeNos = ::nugget::app::keymaster::ErrorCode; 50using ::android::hardware::keymaster::V4_0::ErrorCode; 51 52using KeymasterClient = ::nugget::app::keymaster::Keymaster; 53 54#ifdef ENABLE_QCOM_OTF_PROVISIONING 55// TODO(ngm): move this code into the HAL implementation. 56static bool alreadyProvisioned(KeymasterClient *keymasterClient) { 57 ProvisionPresharedSecretRequest request; 58 ProvisionPresharedSecretResponse response; 59 request.set_get_status(true); 60 61 const uint32_t status = keymasterClient->ProvisionPresharedSecret( 62 request, &response); 63 if (status != APP_SUCCESS) { 64 LOG(ERROR) << "KM ProvisionPresharedSecret() failed with status: " 65 << ::nos::StatusCodeString(status); 66 return false; 67 } 68 const ErrorCode error_code = translate_error_code(response.error_code()); 69 if (error_code != ErrorCode::OK) { 70 LOG(ERROR) << "ProvisionPresharedSecret() response error code: " 71 << toString(error_code); 72 return false; 73 } 74 if (response.status() == PresharedSecretStatus::ALREADY_SET) { 75 LOG(INFO) << "Preshared key previously established"; 76 return true; 77 } 78 79 return false; 80} 81 82// TODO(ngm): move this code into the HAL implementation. 83static bool maybeProvision(KeymasterClient *keymasterClient) { 84 if (alreadyProvisioned(keymasterClient)) { 85 return true; 86 } 87 88 // Attempt to provision the preshared-secret. 89 keymasterdevice::KeymasterKeyProvision qc_km_provisioning; 90 int result = qc_km_provisioning.KeyMasterProvisionInit(); 91 if (result) { 92 LOG(ERROR) << "KeyMasterProvisionInit error: " << result; 93 return false; 94 } 95 std::vector<uint8_t> preshared_secret(32); 96 result = qc_km_provisioning.GetPreSharedSecret( 97 preshared_secret.data(), preshared_secret.size()); 98 if (result != KM_ERROR_OK) { 99 LOG(ERROR) << "GetPreSharedSecret error: " << result; 100 return false; 101 } 102 103 ProvisionPresharedSecretRequest request; 104 ProvisionPresharedSecretResponse response; 105 request.set_get_status(false); 106 request.set_preshared_secret(preshared_secret.data(), 107 preshared_secret.size()); 108 const uint32_t status = keymasterClient->ProvisionPresharedSecret( 109 request, &response); 110 if (status != APP_SUCCESS) { 111 LOG(ERROR) << "KM ProvisionPresharedSecret() failed with status: " 112 << ::nos::StatusCodeString(status); 113 return false; 114 } 115 if (response.error_code() != ErrorCodeNos::OK) { 116 LOG(ERROR) << "KM ProvisionPresharedSecret() failed with code: " 117 << response.error_code(); 118 return false; 119 } 120 121 return true; 122} 123#else 124static bool maybeProvision(KeymasterClient *) { 125 return true; 126} 127#endif 128 129int main() { 130 LOG(INFO) << "Keymaster HAL service starting"; 131 132 // Connect to citadeld 133 CitadeldProxyClient citadeldProxy; 134 citadeldProxy.Open(); 135 if (!citadeldProxy.IsOpen()) { 136 LOG(FATAL) << "Failed to open citadeld client"; 137 } 138 139 // This thread will become the only thread of the daemon 140 constexpr bool thisThreadWillJoinPool = true; 141 configureRpcThreadpool(1, thisThreadWillJoinPool); 142 143 // Start the HAL service 144 KeymasterClient keymasterClient{citadeldProxy}; 145 sp<KeymasterDevice> keymaster = new KeymasterDevice{keymasterClient}; 146 147 if (maybeProvision(&keymasterClient)) { 148 const status_t status = keymaster->registerAsService("strongbox"); 149 if (status != OK) { 150 LOG(FATAL) << "Failed to register Keymaster as a service (status: " 151 << status << ")"; 152 } 153 } else { 154 LOG(ERROR) << "Skipping Keymaster registration, as provisioning failed"; 155 // Leave the service running to avoid being restarted. 156 } 157 158 joinRpcThreadpool(); 159 return -1; // Should never be reached 160} 161