1 /*
2  * Copyright (C) 2018 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 #include "HciEventManager.h"
17 
18 #include <android-base/logging.h>
19 #include <android-base/stringprintf.h>
20 #include <log/log.h>
21 #include <nativehelper/ScopedLocalRef.h>
22 
23 #include "JavaClassConstants.h"
24 #include "NfcJniUtil.h"
25 #include "nfc_config.h"
26 
27 const char* APP_NAME = "NfcNci";
28 uint8_t HciEventManager::sEsePipe;
29 std::vector<uint8_t> HciEventManager::sSimPipeIds;
30 static Mutex sSimPipeIdsMutex;
31 
32 using android::base::StringPrintf;
33 
HciEventManager()34 HciEventManager::HciEventManager() : mNativeData(nullptr) {}
35 
getInstance()36 HciEventManager& HciEventManager::getInstance() {
37   static HciEventManager sHciEventManager;
38   return sHciEventManager;
39 }
40 
initialize(nfc_jni_native_data * native)41 void HciEventManager::initialize(nfc_jni_native_data* native) {
42   mNativeData = native;
43   tNFA_STATUS nfaStat = NFA_HciRegister(const_cast<char*>(APP_NAME),
44                                         (tNFA_HCI_CBACK*)&nfaHciCallback, true);
45   if (nfaStat != NFA_STATUS_OK) {
46     LOG(ERROR) << "HCI registration failed; status=" << nfaStat;
47   }
48   sEsePipe = NfcConfig::getUnsigned(NAME_OFF_HOST_ESE_PIPE_ID, 0x16);
49   // Backward compatibility or For vendor supporting only single sim pipe ID
50   sSimPipeIdsMutex.lock();
51   if (!NfcConfig::hasKey(NAME_OFF_HOST_SIM_PIPE_IDS)) {
52     uint8_t simPipeId = NfcConfig::getUnsigned(NAME_OFF_HOST_SIM_PIPE_ID, 0x0A);
53     sSimPipeIds = {simPipeId};
54   } else {
55     sSimPipeIds = NfcConfig::getBytes(NAME_OFF_HOST_SIM_PIPE_IDS);
56   }
57   sSimPipeIdsMutex.unlock();
58 }
59 
notifyTransactionListenersOfAid(std::vector<uint8_t> aid,std::vector<uint8_t> data,std::string evtSrc)60 void HciEventManager::notifyTransactionListenersOfAid(std::vector<uint8_t> aid,
61                                                       std::vector<uint8_t> data,
62                                                       std::string evtSrc) {
63   if (aid.empty()) {
64     return;
65   }
66 
67   JNIEnv* e = NULL;
68   ScopedAttach attach(mNativeData->vm, &e);
69   CHECK(e);
70 
71   ScopedLocalRef<jobject> aidJavaArray(e, e->NewByteArray(aid.size()));
72   CHECK(aidJavaArray.get());
73   e->SetByteArrayRegion((jbyteArray)aidJavaArray.get(), 0, aid.size(),
74                         (jbyte*)&aid[0]);
75   CHECK(!e->ExceptionCheck());
76 
77   ScopedLocalRef<jobject> srcJavaString(e, e->NewStringUTF(evtSrc.c_str()));
78   CHECK(srcJavaString.get());
79 
80   if (data.size() > 0) {
81     ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(data.size()));
82     CHECK(dataJavaArray.get());
83     e->SetByteArrayRegion((jbyteArray)dataJavaArray.get(), 0, data.size(),
84                           (jbyte*)&data[0]);
85     CHECK(!e->ExceptionCheck());
86     e->CallVoidMethod(mNativeData->manager,
87                       android::gCachedNfcManagerNotifyTransactionListeners,
88                       aidJavaArray.get(), dataJavaArray.get(),
89                       srcJavaString.get());
90   } else {
91     e->CallVoidMethod(mNativeData->manager,
92                       android::gCachedNfcManagerNotifyTransactionListeners,
93                       aidJavaArray.get(), NULL, srcJavaString.get());
94   }
95 }
96 
97 /**
98  * BerTlv has the following format:
99  *
100  * byte1 byte2 byte3 byte4 byte5 byte6
101  * 00-7F   -    -     -     -     -
102  * 81    00-FF  -     -     -     -
103  * 82    0000-FFFF    -     -     -
104  * 83      000000-FFFFFF    -     -
105  * 84      00000000-FFFFFFFF      -
106  */
getDataFromBerTlv(std::vector<uint8_t> berTlv)107 std::vector<uint8_t> HciEventManager::getDataFromBerTlv(
108     std::vector<uint8_t> berTlv) {
109   if (berTlv.empty()) {
110     return std::vector<uint8_t>();
111   }
112   size_t lengthTag = berTlv[0];
113   LOG(DEBUG) << "decodeBerTlv: berTlv[0]=" << berTlv[0];
114 
115   /* As per ISO/IEC 7816, read the first byte to determine the length and
116    * the start index accordingly
117    */
118   if (lengthTag < 0x80 && berTlv.size() == (lengthTag + 1)) {
119     return std::vector<uint8_t>(berTlv.begin() + 1, berTlv.end());
120   } else if (lengthTag == 0x81 && berTlv.size() > 2) {
121     size_t length = berTlv[1];
122     if ((length + 2) == berTlv.size()) {
123       return std::vector<uint8_t>(berTlv.begin() + 2, berTlv.end());
124     }
125   } else if (lengthTag == 0x82 && berTlv.size() > 3) {
126     size_t length = ((berTlv[1] << 8) | berTlv[2]);
127     if ((length + 3) == berTlv.size()) {
128       return std::vector<uint8_t>(berTlv.begin() + 3, berTlv.end());
129     }
130   } else if (lengthTag == 0x83 && berTlv.size() > 4) {
131     size_t length = (berTlv[1] << 16) | (berTlv[2] << 8) | berTlv[3];
132     if ((length + 4) == berTlv.size()) {
133       return std::vector<uint8_t>(berTlv.begin() + 4, berTlv.end());
134     }
135   } else if (lengthTag == 0x84 && berTlv.size() > 5) {
136     size_t length =
137         (berTlv[1] << 24) | (berTlv[2] << 16) | (berTlv[3] << 8) | berTlv[4];
138     if ((length + 5) == berTlv.size()) {
139       return std::vector<uint8_t>(berTlv.begin() + 5, berTlv.end());
140     }
141   }
142   LOG(ERROR) << "Error in TLV length encoding!";
143   return std::vector<uint8_t>();
144 }
145 
nfaHciCallback(tNFA_HCI_EVT event,tNFA_HCI_EVT_DATA * eventData)146 void HciEventManager::nfaHciCallback(tNFA_HCI_EVT event,
147                                      tNFA_HCI_EVT_DATA* eventData) {
148   if (eventData == nullptr) {
149     return;
150   }
151 
152   LOG(DEBUG) << StringPrintf(
153       "event=%d code=%d pipe=%d len=%d", event, eventData->rcvd_evt.evt_code,
154       eventData->rcvd_evt.pipe, eventData->rcvd_evt.evt_len);
155 
156   std::string evtSrc;
157   if (eventData->rcvd_evt.pipe == sEsePipe) {
158     evtSrc = "eSE1";
159   } else {
160     sSimPipeIdsMutex.lock();
161     bool isSimPipeId = false;
162     for (size_t i = 0; i < (size_t)sSimPipeIds.size(); i++) {
163       if (eventData->rcvd_evt.pipe == sSimPipeIds[i]) {
164         evtSrc = "SIM" + std::to_string(i + 1);
165         isSimPipeId = true;
166         break;
167       }
168     }
169     sSimPipeIdsMutex.unlock();
170 
171     if (!isSimPipeId) {
172       LOG(WARNING) << "Incorrect Pipe Id";
173       return;
174     }
175   }
176 
177   // Check the event and check if it contains the AID
178   uint8_t* event_buff = eventData->rcvd_evt.p_evt_buf;
179   uint32_t event_buff_len = eventData->rcvd_evt.evt_len;
180   if (event != NFA_HCI_EVENT_RCVD_EVT ||
181       eventData->rcvd_evt.evt_code != NFA_HCI_EVT_TRANSACTION ||
182       event_buff_len <= 3 || event_buff == nullptr || event_buff[0] != 0x81) {
183     LOG(WARNING) << "Invalid event";
184     return;
185   }
186 
187   uint32_t aid_len = event_buff[1];
188   if (aid_len >= (event_buff_len - 1)) {
189     android_errorWriteLog(0x534e4554, "181346545");
190     LOG(ERROR) << StringPrintf("error: aidlen(%d) is too big", aid_len);
191     return;
192   }
193 
194   std::vector<uint8_t> aid(event_buff + 2, event_buff + aid_len + 2);
195   int32_t berTlvStart = aid_len + 2 + 1;
196   int32_t berTlvLen = event_buff_len - berTlvStart;
197   std::vector<uint8_t> data;
198   if (berTlvLen > 0 && event_buff[2 + aid_len] == 0x82) {
199     std::vector<uint8_t> berTlv(event_buff + berTlvStart,
200                                 event_buff + event_buff_len);
201     // BERTLV decoding here, to support extended data length for params.
202     data = getInstance().getDataFromBerTlv(berTlv);
203   }
204 
205   getInstance().notifyTransactionListenersOfAid(aid, data, evtSrc);
206 }
207 
finalize()208 void HciEventManager::finalize() { mNativeData = NULL; }
209