diff options
author | Andrew Scull <ascull@google.com> | 2018-01-13 16:05:32 +0000 |
---|---|---|
committer | Andrew Scull <ascull@google.com> | 2018-01-13 16:06:18 +0000 |
commit | 6b7a43403b9ae0abd992c23bd9905d2ddc290184 (patch) | |
tree | dbfc8d21680aa14e01332a005388ef0fc60fa6c4 /citadel | |
parent | 9a759c4b89ce9d9d1acb1d8d751d47dc5db81e27 (diff) | |
download | android-6b7a43403b9ae0abd992c23bd9905d2ddc290184.tar.gz |
Prepare for citadeld running by default.
Sanity checks for citadel are now in citadeld and are run by
/vendor/bin/hw/citadel_test. The old manual tests can be run by first
killing citadeld:
kill $(pgrep citadeld) && test_citadel
Change-Id: I09b00617402643d68ae95b0f4ca879cf198ae05f
Diffstat (limited to 'citadel')
-rw-r--r-- | citadel/citadeld/Android.bp | 14 | ||||
-rw-r--r-- | citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl | 3 | ||||
-rw-r--r-- | citadel/citadeld/check.cpp | 137 | ||||
-rw-r--r-- | citadel/citadeld/check.h | 30 | ||||
-rw-r--r-- | citadel/citadeld/citadel_test.cpp | 66 | ||||
-rw-r--r-- | citadel/citadeld/main.cpp | 18 |
6 files changed, 262 insertions, 6 deletions
diff --git a/citadel/citadeld/Android.bp b/citadel/citadeld/Android.bp index 3c6bb4b..2552454 100644 --- a/citadel/citadeld/Android.bp +++ b/citadel/citadeld/Android.bp @@ -20,6 +20,9 @@ cc_defaults { "aidl/android/hardware/citadel/ICitadeld.aidl", ], defaults: ["nos_base_cc_defaults"], + header_libs: [ + "nos_headers", + ], shared_libs: [ "libbase", "libbinder", @@ -49,11 +52,13 @@ cc_binary { init_rc: ["citadeld.rc"], srcs: [ "main.cpp", + "check.cpp", ], defaults: ["citadeld_defaults"], shared_libs: [ "libnos", "libnos_client_citadel", + "libnos_transport", ], } @@ -68,7 +73,10 @@ cc_library { aidl: { export_aidl_headers: true, }, - header_libs: [ - "nos_headers", - ], +} + +cc_binary { + name: "citadel_test", + srcs: ["citadel_test.cpp"], + defaults: ["citadeld_defaults"], } diff --git a/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl b/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl index 2173c23..2ca6884 100644 --- a/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl +++ b/citadel/citadeld/aidl/android/hardware/citadel/ICitadeld.aidl @@ -27,4 +27,7 @@ interface ICitadeld { * @return Status code from the app. */ int callApp(int appId, int arg, in byte[] request, out byte[] response); + + /** Runs a series of checks to ensure the devices is present, connected and responsive. */ + boolean checkDevice(); } diff --git a/citadel/citadeld/check.cpp b/citadel/citadeld/check.cpp new file mode 100644 index 0000000..4a91949 --- /dev/null +++ b/citadel/citadeld/check.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 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 "check.h" + +#include <iomanip> +#include <sstream> + +#include <android-base/logging.h> + +#include <application.h> +#include <app_nugget.h> + +#include <nos/debug.h> +#include <nos/transport.h> + +/* TPM Register magic commands */ +#define RD4_TPM_DID_VID 0x83d40f00 +#define WR1_TPM_FW_VER 0x00d40f90 + +namespace android { +namespace citadeld { + +namespace { + +bool CheckDatagram(nos_device* const dev) { + int rv; + uint8_t buf[4]; + const uint8_t expected_tpm_did_vid[] = { 0xe0, 0x1a, 0x28, 0x00 }; + static_assert(sizeof(buf) >= sizeof(expected_tpm_did_vid), + "buf not large enough"); + + // Clear the version string pointer + LOG(INFO) << "Check: simple write"; + buf[0] = 0x00; + rv = dev->ops.write(dev->ctx, WR1_TPM_FW_VER, buf, 1); + if (rv != 0) { + LOG(ERROR) << " Failed with 0x" << std::hex << rv << " (" << std::dec << rv << ")"; + return false; + } + LOG(INFO) << " Passed"; + + // Read TPM_DID_VID + LOG(INFO) << "Check: simple read"; + uint32_t buflen = sizeof(expected_tpm_did_vid); + memset(buf, 0, buflen); + rv = dev->ops.read(dev->ctx, RD4_TPM_DID_VID, buf, buflen); + if (rv != 0) { + LOG(ERROR) << " Failed with 0x" << std::hex << rv << " (" << std::dec << rv << ")"; + return false; + } else { + std::ostringstream ss; + ss << "got:" << std::setfill('0') << std::setw(2) << std::hex; + for (uint32_t i = 0; i < buflen; ++i) { + ss << " " << buf[i]; + } + LOG(DEBUG) << ss.str(); + if (memcmp(buf, expected_tpm_did_vid, sizeof(expected_tpm_did_vid))) { + LOG(ERROR) << " Returned unexpected values"; + return false; + } + } + LOG(INFO) << " Passed"; + return true; +} + +bool CheckTransport(nos_device* const dev) { + LOG(INFO) << "Check: get version string"; + uint8_t buf[520]; + uint32_t replycount = sizeof(buf); + uint32_t retval = nos_call_application(dev, APP_ID_NUGGET, NUGGET_PARAM_VERSION, + buf, 0, + buf, &replycount); + if (retval != 0) { + LOG(ERROR) << " Failed with 0x" << std::hex << retval + << " (" << nos::StatusCodeString(retval) << ")"; + return false; + } + if (replycount < 4 || replycount > 512) { + LOG(ERROR) << " Returned " << replycount << " bytes, which seems wrong"; + return false; + } + LOG(INFO) << " Passed"; + return true; +} + +} // namespace + +bool CheckDevice(nos_device* const dev) +{ + if (dev == nullptr) { + LOG(ERROR) << "Checks require non-null device"; + return false; + } + + bool all_passed = true; + + LOG(INFO) << "----"; + LOG(INFO) << "Datagram checks begin..."; + if (!CheckDatagram(dev)) { + LOG(ERROR) << "Datagram checks failed"; + all_passed = false; + } else { + LOG(INFO) << "Datagram checks passed"; + } + + LOG(INFO) << "----"; + LOG(INFO) << "Transport checks begin..."; + if (!CheckTransport(dev)) { + LOG(ERROR) << "Transport checks failed"; + all_passed = false; + } else { + LOG(INFO) << "Transport checks passed"; + } + + // TODO: add more e.g. GPIO + + + LOG(INFO) << "----"; + return all_passed; +} + +} // namespace citadeld +} // namespace android diff --git a/citadel/citadeld/check.h b/citadel/citadeld/check.h new file mode 100644 index 0000000..554b31b --- /dev/null +++ b/citadel/citadeld/check.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 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 <nos/device.h> + +namespace android { +namespace citadeld { + +/** + * Run a series of checks that the device is functioning correctly. + * + * @param dev has been opened and ready for messages. + */ +bool CheckDevice(nos_device* dev); + +} // namespace citadeld +} // namespace android diff --git a/citadel/citadeld/citadel_test.cpp b/citadel/citadeld/citadel_test.cpp new file mode 100644 index 0000000..889656b --- /dev/null +++ b/citadel/citadeld/citadel_test.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 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 <iostream> + +#include <android-base/logging.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> + +#include <android/hardware/citadel/ICitadeld.h> + +#include <application.h> + +using ::android::defaultServiceManager; +using ::android::sp; +using ::android::ProcessState; + +using ::android::hardware::citadel::ICitadeld; + +/** + * This utility invokes the citadeld device checks and reports the results. + */ +int main(int argc, char** argv) { + (void) argc; + (void) argv; + + std::cout << "Checking citadel is present and responsive...\n"; + + // Ensure this process is using the vndbinder + ProcessState::initWithDriver("/dev/vndbinder"); + ::android::sp<::android::hardware::citadel::ICitadeld> _citadeld + = ICitadeld::asInterface(defaultServiceManager()->getService(ICitadeld::descriptor)); + if (_citadeld == nullptr) { + std::cerr << "Failed to connect to citadeld\n"; + return EXIT_FAILURE; + } + + // Invoke the checks + bool passed = false; + if (!_citadeld->checkDevice(&passed).isOk()) { + std::cerr << "Failed to run device checks via citadeld\n"; + return EXIT_FAILURE; + } + + // Report the outcome + if (passed) { + std::cout << "\nPASS PASS PASS\n\n"; + return EXIT_SUCCESS; + } else { + std::cerr << "\nFAIL FAIL FAIL (see citadeld logcat for details)\n\n"; + return EXIT_FAILURE; + } +} diff --git a/citadel/citadeld/main.cpp b/citadel/citadeld/main.cpp index 3a51566..59a54b0 100644 --- a/citadel/citadeld/main.cpp +++ b/citadel/citadeld/main.cpp @@ -24,6 +24,8 @@ #include <android/hardware/citadel/BnCitadeld.h> +#include "check.h" + using ::android::OK; using ::android::defaultServiceManager; using ::android::sp; @@ -35,7 +37,6 @@ using ::android::ProcessState; using ::android::binder::Status; using ::nos::NuggetClient; -using ::nos::NuggetClientInterface; using ::android::hardware::citadel::BnCitadeld; using ::android::hardware::citadel::ICitadeld; @@ -43,9 +44,9 @@ using ::android::hardware::citadel::ICitadeld; namespace { struct CitadelProxy : public BnCitadeld { - NuggetClientInterface& _client; + NuggetClient& _client; - CitadelProxy(NuggetClientInterface& client) : _client{client} {} + CitadelProxy(NuggetClient& client) : _client{client} {} ~CitadelProxy() override = default; Status callApp(const int32_t _appId, const int32_t _arg, const std::vector<uint8_t>& request, @@ -62,6 +63,17 @@ struct CitadelProxy : public BnCitadeld { *appStatus = _client.CallApp(appId, arg, request, response); return Status::ok(); } + + Status checkDevice(bool* const _aidl_return) override { + LOG(INFO) << "Running citadel device checks..."; + *_aidl_return = android::citadeld::CheckDevice(_client.Device()); + if (*_aidl_return) { + LOG(INFO) << "Citadel device check passed"; + } else { + LOG(ERROR) << "Citadel device check failed"; + } + return Status::ok(); + } }; } // namespace |