1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "mifare_classic_tag.h"
16 #include "loghelper.h"
17 #include "nfca_tag.h"
18
19 namespace OHOS {
20 namespace NFC {
21 namespace KITS {
22 const char MifareClassicTag::MC_KEY_DEFAULT[MC_KEY_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
23 // MIFARE Application Directory (MAD)
24 const char MifareClassicTag::MC_KEY_MAD[MC_KEY_LEN] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
25 const char MifareClassicTag::MC_KEY_NFC_FORUM[MC_KEY_LEN] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
26
MifareClassicTag(std::weak_ptr<TagInfo> tag)27 MifareClassicTag::MifareClassicTag(std::weak_ptr<TagInfo> tag)
28 : BasicTagSession(tag, KITS::TagTechnology::NFC_MIFARE_CLASSIC_TECH)
29 {
30 isEmulated_ = false;
31 mifareTagType_ = EmType::TYPE_UNKNOWN;
32 std::shared_ptr<NfcATag> nfcA = NfcATag::GetTag(tag);
33 if (nfcA == nullptr) {
34 ErrorLog("MifareClassicTag, not support NfcA.");
35 return;
36 }
37
38 DebugLog("MifareClassicTag, sak %{public}x", nfcA->GetSak());
39 mifareTagType_ = EmType::TYPE_CLASSIC;
40 SetSizeBySak(nfcA->GetSak());
41 }
42
SetSizeBySak(int sak)43 void MifareClassicTag::SetSizeBySak(int sak)
44 {
45 switch (sak) {
46 case SAK01:
47 case SAK08:
48 case SAK88:
49 size_ = MC_SIZE_1K;
50 break;
51 case SAK09:
52 size_ = MC_SIZE_MINI;
53 break;
54 case SAK10:
55 size_ = MC_SIZE_2K;
56 mifareTagType_ = EmType::TYPE_PLUS;
57 break;
58 case SAK11:
59 size_ = MC_SIZE_4K;
60 mifareTagType_ = EmType::TYPE_PLUS;
61 break;
62 case SAK18:
63 size_ = MC_SIZE_4K;
64 break;
65 case SAK19:
66 size_ = MC_SIZE_2K;
67 break;
68 case SAK28:
69 size_ = MC_SIZE_1K;
70 isEmulated_ = true;
71 break;
72 case SAK38:
73 size_ = MC_SIZE_4K;
74 isEmulated_ = true;
75 break;
76 case SAK98:
77 case SAKB8:
78 size_ = MC_SIZE_4K;
79 mifareTagType_ = EmType::TYPE_PRO;
80 break;
81 default:
82 ErrorLog("[MifareClassicTag::SetSizeBySak] err! sak %{public}x", sak);
83 break;
84 }
85 }
86
GetTag(std::weak_ptr<TagInfo> tag)87 std::shared_ptr<MifareClassicTag> MifareClassicTag::GetTag(std::weak_ptr<TagInfo> tag)
88 {
89 if (tag.expired() || !tag.lock()->IsTechSupported(KITS::TagTechnology::NFC_A_TECH) ||
90 !tag.lock()->IsTechSupported(KITS::TagTechnology::NFC_MIFARE_CLASSIC_TECH)) {
91 ErrorLog("MifareClassicTag::GetTag error, no mathced technology.");
92 return nullptr;
93 }
94
95 return std::make_shared<MifareClassicTag>(tag);
96 }
97
AuthenticateSector(int sectorIndex,const std::string & key,bool bIsKeyA)98 int MifareClassicTag::AuthenticateSector(int sectorIndex, const std::string& key, bool bIsKeyA)
99 {
100 if ((sectorIndex < 0 || sectorIndex >= MC_MAX_SECTOR_COUNT)) {
101 ErrorLog("AuthenticateSector, sectorIndex %{public}d invalid", sectorIndex);
102 return ErrorCode::ERR_TAG_PARAMETERS;
103 }
104 if (!IsConnected()) {
105 ErrorLog("AuthenticateSector, tag is not connected");
106 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
107 }
108 std::string hexCmd = "";
109 if (bIsKeyA) {
110 hexCmd += NfcSdkCommon::UnsignedCharToHexString(AUTHENTICATION_WITH_KEY_A);
111 } else {
112 hexCmd += NfcSdkCommon::UnsignedCharToHexString(AUTHENTICATION_WITH_KEY_B);
113 }
114 hexCmd += NfcSdkCommon::UnsignedCharToHexString(
115 static_cast<unsigned char>(GetBlockIndexFromSector(sectorIndex)));
116
117 // Takes the last 4 bytes of the tag as part of command
118 std::string tagUid = GetTagUid();
119 static const int uidLast4Bytes = 4;
120 uint32_t uidBytes = NfcSdkCommon::GetHexStrBytesLen(tagUid);
121 if (uidBytes < uidLast4Bytes) {
122 ErrorLog("AuthenticateSector, uidBytes invalid.");
123 return ErrorCode::ERR_TAG_PARAMETERS;
124 }
125 hexCmd += tagUid.substr((uidBytes - uidLast4Bytes) * HEX_BYTE_LEN, uidLast4Bytes * HEX_BYTE_LEN);
126
127 // Take the last 6 bytes of the tag as part of command
128 static const int expectedKeySize = 6;
129 uint32_t keyBytes = NfcSdkCommon::GetHexStrBytesLen(key);
130 if (keyBytes != expectedKeySize) {
131 ErrorLog("AuthenticateSector, key invalid.");
132 return ErrorCode::ERR_TAG_PARAMETERS;
133 }
134 hexCmd += key.substr(0, expectedKeySize * HEX_BYTE_LEN);
135
136 std::string hexRespData;
137 return SendCommand(hexCmd, false, hexRespData);
138 }
139
ReadSingleBlock(uint32_t blockIndex,std::string & hexRespData)140 int MifareClassicTag::ReadSingleBlock(uint32_t blockIndex, std::string &hexRespData)
141 {
142 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
143 ErrorLog("ReadSingleBlock, blockIndex = %{public}d invalid", blockIndex);
144 return ErrorCode::ERR_TAG_PARAMETERS;
145 }
146 if (!IsConnected()) {
147 ErrorLog("ReadSingleBlock, tag is not connected");
148 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
149 }
150 std::string hexCmd = "";
151 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_READ);
152 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
153
154 return SendCommand(hexCmd, false, hexRespData);
155 }
156
WriteSingleBlock(uint32_t blockIndex,const std::string & hexData)157 int MifareClassicTag::WriteSingleBlock(uint32_t blockIndex, const std::string& hexData)
158 {
159 if (!IsConnected()) {
160 ErrorLog("WriteSingleBlock, connect tag first!");
161 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
162 }
163 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
164 ErrorLog("WriteSingleBlock, blockIndex = %{public}d invalid", blockIndex);
165 return ErrorCode::ERR_TAG_PARAMETERS;
166 }
167 if (KITS::NfcSdkCommon::GetHexStrBytesLen(hexData) != MC_BLOCK_SIZE) {
168 ErrorLog("WriteSingleBlock, dataLen = %{public}d invalid", KITS::NfcSdkCommon::GetHexStrBytesLen(hexData));
169 return ErrorCode::ERR_TAG_PARAMETERS;
170 }
171 std::string hexCmd = "";
172 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_WRITE);
173 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
174 hexCmd += hexData;
175
176 std::string hexRespData;
177 return SendCommand(hexCmd, false, hexRespData);
178 }
179
IncrementBlock(uint32_t blockIndex,int value)180 int MifareClassicTag::IncrementBlock(uint32_t blockIndex, int value)
181 {
182 if (!IsConnected()) {
183 ErrorLog("IncrementBlock, connect tag first!");
184 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
185 }
186 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
187 ErrorLog("IncrementBlock, blockIndex = %{public}d invalid", blockIndex);
188 return ErrorCode::ERR_TAG_PARAMETERS;
189 }
190 if (value < 0) {
191 ErrorLog("IncrementBlock, value < 0 invalid");
192 return ErrorCode::ERR_TAG_PARAMETERS;
193 }
194 std::string hexCmd = "";
195 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_INCREMENT);
196 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
197 hexCmd += NfcSdkCommon::IntToHexString(value);
198
199 std::string hexRespData;
200 return SendCommand(hexCmd, false, hexRespData);
201 }
202
DecrementBlock(uint32_t blockIndex,int value)203 int MifareClassicTag::DecrementBlock(uint32_t blockIndex, int value)
204 {
205 if (!IsConnected()) {
206 ErrorLog("DecrementBlock, connect tag first!");
207 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
208 }
209 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
210 ErrorLog("DecrementBlock, blockIndex = %{public}d invalid", blockIndex);
211 return ErrorCode::ERR_TAG_PARAMETERS;
212 }
213 if (value < 0) {
214 ErrorLog("DecrementBlock, value < 0 invalid");
215 return ErrorCode::ERR_TAG_PARAMETERS;
216 }
217 std::string hexCmd = "";
218 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_DECREMENT);
219 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
220 hexCmd += NfcSdkCommon::IntToHexString(value);
221
222 std::string hexRespData;
223 return SendCommand(hexCmd, false, hexRespData);
224 }
225
TransferToBlock(uint32_t blockIndex)226 int MifareClassicTag::TransferToBlock(uint32_t blockIndex)
227 {
228 if (!IsConnected()) {
229 ErrorLog("TransferToBlock, connect tag first!");
230 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
231 }
232 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
233 ErrorLog("TransferToBlock, blockIndex = %{public}d invalid", blockIndex);
234 return ErrorCode::ERR_TAG_PARAMETERS;
235 }
236 std::string hexCmd = "";
237 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_TRANSFER);
238 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
239
240 std::string hexRespData;
241 return SendCommand(hexCmd, false, hexRespData);
242 }
243
RestoreFromBlock(uint32_t blockIndex)244 int MifareClassicTag::RestoreFromBlock(uint32_t blockIndex)
245 {
246 if (!IsConnected()) {
247 ErrorLog("RestoreFromBlock, connect tag first!");
248 return ErrorCode::ERR_TAG_STATE_DISCONNECTED;
249 }
250 if (blockIndex >= MC_MAX_BLOCK_INDEX) {
251 ErrorLog("RestoreFromBlock, blockIndex = %{public}d invalid", blockIndex);
252 return ErrorCode::ERR_TAG_PARAMETERS;
253 }
254 std::string hexCmd = "";
255 hexCmd += NfcSdkCommon::UnsignedCharToHexString(MIFARE_RESTORE);
256 hexCmd += NfcSdkCommon::UnsignedCharToHexString(static_cast<unsigned char>(blockIndex & 0xFF));
257
258 std::string hexRespData;
259 return SendCommand(hexCmd, false, hexRespData);
260 }
261
GetSectorCount() const262 int MifareClassicTag::GetSectorCount() const
263 {
264 size_t count = 0;
265 switch (size_) {
266 case MC_SIZE_1K:
267 count = MC_SECTOR_COUNT_OF_SIZE_1K;
268 break;
269 case MC_SIZE_2K:
270 count = MC_SECTOR_COUNT_OF_SIZE_2K;
271 break;
272 case MC_SIZE_4K:
273 count = MC_MAX_SECTOR_COUNT;
274 break;
275 case MC_SIZE_MINI:
276 count = MC_SECTOR_COUNT_OF_SIZE_MINI;
277 break;
278 default:
279 break;
280 }
281 return count;
282 }
283
GetBlockCountInSector(int sectorIndex) const284 int MifareClassicTag::GetBlockCountInSector(int sectorIndex) const
285 {
286 if (sectorIndex >= 0 && sectorIndex < MC_SECTOR_COUNT_OF_SIZE_2K) {
287 return MC_BLOCK_COUNT;
288 } else if (sectorIndex >= MC_SECTOR_COUNT_OF_SIZE_2K && sectorIndex < MC_MAX_SECTOR_COUNT) {
289 return MC_BLOCK_COUNT_OF_4K;
290 }
291 ErrorLog("GetBlockCountInSector, error sectorIndex %{public}d", sectorIndex);
292 return MC_ERROR_VALUE;
293 }
294
GetMifareTagType() const295 MifareClassicTag::EmType MifareClassicTag::GetMifareTagType() const
296 {
297 return mifareTagType_;
298 }
299
GetSize() const300 int MifareClassicTag::GetSize() const
301 {
302 return size_;
303 }
304
IsEmulated() const305 bool MifareClassicTag::IsEmulated() const
306 {
307 return isEmulated_;
308 }
309
GetBlockIndexFromSector(int sectorIndex) const310 int MifareClassicTag::GetBlockIndexFromSector(int sectorIndex) const
311 {
312 if (sectorIndex >= 0 && sectorIndex < MC_SECTOR_COUNT_OF_SIZE_2K) {
313 return sectorIndex * MC_BLOCK_COUNT;
314 }
315 if (sectorIndex >= MC_SECTOR_COUNT_OF_SIZE_2K && sectorIndex < MC_MAX_SECTOR_COUNT) {
316 return MC_SECTOR_COUNT_OF_SIZE_2K * MC_BLOCK_COUNT +
317 (sectorIndex - MC_SECTOR_COUNT_OF_SIZE_2K) * MC_BLOCK_COUNT_OF_4K;
318 }
319 ErrorLog("GetBlockIndexFromSector, error sectorIndex %{public}d", sectorIndex);
320 return MC_ERROR_VALUE;
321 }
322
GetSectorIndexFromBlock(int blockIndex) const323 int MifareClassicTag::GetSectorIndexFromBlock(int blockIndex) const
324 {
325 if (blockIndex < 0 || blockIndex >= MC_MAX_BLOCK_INDEX) {
326 ErrorLog("GetSectorIndexFromBlock, error blockIndex %{public}d", blockIndex);
327 return MC_ERROR_VALUE;
328 }
329 if (blockIndex < MC_SECTOR_COUNT_OF_SIZE_2K * MC_BLOCK_COUNT) {
330 return blockIndex / MC_BLOCK_COUNT;
331 } else {
332 return MC_SECTOR_COUNT_OF_SIZE_2K + (blockIndex - MC_SECTOR_COUNT_OF_SIZE_2K * MC_BLOCK_COUNT) / MC_BLOCK_SIZE;
333 }
334 }
335 } // namespace KITS
336 } // namespace NFC
337 } // namespace OHOS
338