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