Steven Moreland | 6fe6954 | 2022-11-03 17:42:32 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2022 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 <aidl/android/hardware/secure_element/BnSecureElement.h> |
| 18 | |
| 19 | #include <android-base/hex.h> |
| 20 | #include <android-base/logging.h> |
| 21 | #include <android/binder_manager.h> |
| 22 | #include <android/binder_process.h> |
| 23 | |
| 24 | using aidl::android::hardware::secure_element::BnSecureElement; |
| 25 | using aidl::android::hardware::secure_element::ISecureElementCallback; |
| 26 | using aidl::android::hardware::secure_element::LogicalChannelResponse; |
| 27 | using android::base::HexString; |
| 28 | using ndk::ScopedAStatus; |
| 29 | |
| 30 | static const std::vector<uint8_t> kAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, |
| 31 | 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, |
| 32 | 0x43, 0x54, 0x53, 0x31}; |
| 33 | static const std::vector<uint8_t> kLongAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, |
| 34 | 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, |
| 35 | 0x43, 0x54, 0x53, 0x32}; |
| 36 | |
| 37 | class MySecureElement : public BnSecureElement { |
| 38 | public: |
| 39 | ScopedAStatus closeChannel(int8_t channelNumber) override { |
| 40 | LOG(INFO) << __func__ << " channel number: " << channelNumber; |
| 41 | return ScopedAStatus::ok(); |
| 42 | } |
| 43 | ScopedAStatus getAtr(std::vector<uint8_t>* _aidl_return) override { |
| 44 | LOG(INFO) << __func__; |
| 45 | _aidl_return->clear(); |
| 46 | return ScopedAStatus::ok(); |
| 47 | } |
| 48 | ScopedAStatus init(const std::shared_ptr<ISecureElementCallback>& clientCallback) override { |
| 49 | LOG(INFO) << __func__ << " callback: " << clientCallback.get(); |
| 50 | if (!clientCallback) { |
| 51 | return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); |
| 52 | } |
| 53 | mCb = clientCallback; |
| 54 | mCb->onStateChange(true, ""); |
| 55 | return ScopedAStatus::ok(); |
| 56 | } |
| 57 | ScopedAStatus isCardPresent(bool* _aidl_return) override { |
| 58 | LOG(INFO) << __func__; |
| 59 | *_aidl_return = true; |
| 60 | return ScopedAStatus::ok(); |
| 61 | } |
| 62 | ScopedAStatus openBasicChannel(const std::vector<uint8_t>& aid, int8_t p2, |
| 63 | std::vector<uint8_t>* _aidl_return) override { |
| 64 | LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size() |
| 65 | << ") p2 " << p2; |
| 66 | |
| 67 | // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU. |
| 68 | // The functionality here is enough to exercise the framework, but actual |
| 69 | // calls to the secure element will fail. This implementation does not model |
| 70 | // channel isolation or any other aspects important to implementing secure element. |
| 71 | *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY |
| 72 | return ScopedAStatus::ok(); |
| 73 | } |
| 74 | ScopedAStatus openLogicalChannel( |
| 75 | const std::vector<uint8_t>& aid, int8_t p2, |
| 76 | ::aidl::android::hardware::secure_element::LogicalChannelResponse* _aidl_return) |
| 77 | override { |
| 78 | LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size() |
| 79 | << ") p2 " << p2; |
| 80 | |
| 81 | if (aid != kAndroidTestAid && aid != kLongAndroidTestAid) { |
| 82 | return ScopedAStatus::fromServiceSpecificError(NO_SUCH_ELEMENT_ERROR); |
| 83 | } |
| 84 | |
| 85 | *_aidl_return = LogicalChannelResponse{.channelNumber = 1, .selectResponse = {}}; |
| 86 | |
| 87 | // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU. |
| 88 | // The functionality here is enough to exercise the framework, but actual |
| 89 | // calls to the secure element will fail. This implementation does not model |
| 90 | // channel isolation or any other aspects important to implementing secure element. |
| 91 | if (aid == kAndroidTestAid) { // DO NOT COPY |
| 92 | size_t size = 2050; // DO NOT COPY |
| 93 | _aidl_return->selectResponse.resize(size); // DO NOT COPY |
| 94 | _aidl_return->selectResponse[size - 1] = 0x00; // DO NOT COPY |
| 95 | _aidl_return->selectResponse[size - 2] = 0x90; // DO NOT COPY |
| 96 | } else { // DO NOT COPY |
| 97 | _aidl_return->selectResponse = {0x00, 0x00, 0x90, 0x00}; // DO NOT COPY |
| 98 | } // DO NOT COPY |
| 99 | |
| 100 | LOG(INFO) << __func__ << " sending response: " |
| 101 | << HexString(_aidl_return->selectResponse.data(), |
| 102 | _aidl_return->selectResponse.size()); |
| 103 | |
| 104 | return ScopedAStatus::ok(); |
| 105 | } |
| 106 | ScopedAStatus reset() override { |
| 107 | LOG(INFO) << __func__; |
| 108 | mCb->onStateChange(false, "reset"); |
| 109 | mCb->onStateChange(true, "reset"); |
| 110 | return ScopedAStatus::ok(); |
| 111 | } |
| 112 | ScopedAStatus transmit(const std::vector<uint8_t>& data, |
| 113 | std::vector<uint8_t>* _aidl_return) override { |
| 114 | LOG(INFO) << __func__ << " data: " << HexString(data.data(), data.size()) << " (" |
| 115 | << data.size() << ")"; |
| 116 | |
| 117 | // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU. |
| 118 | // The functionality here is enough to exercise the framework, but actual |
| 119 | // calls to the secure element will fail. This implementation does not model |
| 120 | // channel isolation or any other aspects important to implementing secure element. |
| 121 | |
| 122 | std::string hex = HexString(data.data(), data.size()); // DO NOT COPY |
| 123 | if (hex == "01a4040210a000000476416e64726f696443545331") { // DO NOT COPY |
| 124 | *_aidl_return = {0x00, 0x6A, 0x00}; // DO NOT COPY |
| 125 | } else if (data == std::vector<uint8_t>{0x00, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY |
| 126 | // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY |
| 127 | *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY |
| 128 | } else if (data == std::vector<uint8_t>{0x01, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY |
| 129 | // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY |
| 130 | *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY |
| 131 | } else if (data.size() == 5 || data.size() == 8) { // DO NOT COPY |
| 132 | // SEGMENTED_RESP_APDU - happens to use length 5 and 8 // DO NOT COPY |
| 133 | size_t size = (data[2] << 8 | data[3]) + 2; // DO NOT COPY |
| 134 | _aidl_return->resize(size); // DO NOT COPY |
| 135 | (*_aidl_return)[size - 1] = 0x00; // DO NOT COPY |
| 136 | (*_aidl_return)[size - 2] = 0x90; // DO NOT COPY |
| 137 | if (size >= 3) (*_aidl_return)[size - 3] = 0xFF; // DO NOT COPY |
| 138 | } else { // DO NOT COPY |
| 139 | *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY |
| 140 | } // DO NOT COPY |
| 141 | |
| 142 | return ScopedAStatus::ok(); |
| 143 | } |
| 144 | |
| 145 | private: |
| 146 | std::shared_ptr<ISecureElementCallback> mCb; |
| 147 | }; |
| 148 | |
| 149 | int main() { |
| 150 | ABinderProcess_setThreadPoolMaxThreadCount(0); |
| 151 | |
| 152 | auto se = ndk::SharedRefBase::make<MySecureElement>(); |
| 153 | const std::string name = std::string() + BnSecureElement::descriptor + "/eSE1"; |
| 154 | binder_status_t status = AServiceManager_addService(se->asBinder().get(), name.c_str()); |
| 155 | CHECK_EQ(status, STATUS_OK); |
| 156 | |
| 157 | ABinderProcess_joinThreadPool(); |
| 158 | return EXIT_FAILURE; // should not reach |
| 159 | } |