1 /*
2 * Copyright (C) 2021 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
16 #include "obex_utils.h"
17 #include <algorithm>
18 #include <codecvt>
19 #include <cstring>
20 #include <endian.h>
21 #include <iomanip>
22 #include <locale>
23 #include <sstream>
24 #include "log.h"
25 #include "raw_address.h"
26 #include "securec.h"
27 #include "stub/message_digest.h"
28
29 namespace OHOS {
30 namespace bluetooth {
31 int ObexUtils::g_bigEndian = -1;
32
SysIsBigEndian()33 bool ObexUtils::SysIsBigEndian()
34 {
35
36 if (g_bigEndian == -1) {
37 union {
38 int aInt;
39 char bChar;
40 } tempUnion;
41 tempUnion.aInt = 1;
42 if (tempUnion.bChar == 1) {
43 g_bigEndian = 0;
44 } else {
45 g_bigEndian = 1;
46 }
47 }
48 return g_bigEndian == 1;
49 }
50
51 std::mutex ObexUtils::g_mutex;
52
DataReverse(uint8_t * data,const uint16_t & len,const uint8_t & unitLen)53 void ObexUtils::DataReverse(uint8_t *data, const uint16_t &len, const uint8_t &unitLen)
54 {
55 if (unitLen < 1) {
56 OBEX_LOG_ERROR("LittleToBigEndian: unitLen is incorrect");
57 return;
58 }
59 if (unitLen == 1) {
60 return;
61 }
62 for (uint16_t pos = 0; pos < len; pos += unitLen) {
63 for (uint16_t subPos = 0; subPos < unitLen / 0x02; subPos++) {
64 uint8_t temp = data[pos + subPos];
65 data[pos + subPos] = data[pos + (unitLen - subPos - 1)];
66 data[pos + (unitLen - subPos - 1)] = temp;
67 }
68 }
69 }
70
SetBufData16(uint8_t * bigEndData,uint16_t pos,const uint16_t & value)71 void ObexUtils::SetBufData16(uint8_t *bigEndData, uint16_t pos, const uint16_t &value)
72 {
73 *(reinterpret_cast<uint16_t *>(&bigEndData[pos])) = htobe16(value);
74 }
75
SetBufData32(uint8_t * bigEndData,uint16_t pos,const uint32_t & value)76 void ObexUtils::SetBufData32(uint8_t *bigEndData, uint16_t pos, const uint32_t &value)
77 {
78 *(reinterpret_cast<uint32_t *>(&bigEndData[pos])) = htobe32(value);
79 }
80
SetBufData64(uint8_t * bigEndData,uint16_t pos,const uint64_t & value)81 void ObexUtils::SetBufData64(uint8_t *bigEndData, uint16_t pos, const uint64_t &value)
82 {
83 *(reinterpret_cast<uint64_t *>(&bigEndData[pos])) = htobe64(value);
84 }
85
GetBufData16(const uint8_t * bigEndData,uint16_t pos)86 uint16_t ObexUtils::GetBufData16(const uint8_t *bigEndData, uint16_t pos)
87 {
88 return be16toh(*(reinterpret_cast<uint16_t *>(const_cast<uint8_t *>(&bigEndData[pos]))));
89 }
90
GetBufData32(const uint8_t * bigEndData,uint16_t pos)91 uint32_t ObexUtils::GetBufData32(const uint8_t *bigEndData, uint16_t pos)
92 {
93 return be32toh(*(reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(&bigEndData[pos]))));
94 }
95
GetBufData64(const uint8_t * bigEndData,uint16_t pos)96 uint64_t ObexUtils::GetBufData64(const uint8_t *bigEndData, uint16_t pos)
97 {
98 return be64toh(*(reinterpret_cast<uint64_t *>(const_cast<uint8_t *>(&bigEndData[pos]))));
99 }
100
ToDebugString(Packet & obexPacket)101 std::string ObexUtils::ToDebugString(Packet &obexPacket)
102 {
103 Buffer *tmpBuffer = PacketContinuousPayload(&obexPacket);
104 uint8_t *packetBuf = (uint8_t *)BufferPtr(tmpBuffer);
105 size_t packetBufSize = BufferGetSize(tmpBuffer);
106 return ToDebugString(packetBuf, packetBufSize, true);
107 }
108
ToDebugString(const uint8_t * v,const size_t & s,bool wrap)109 std::string ObexUtils::ToDebugString(const uint8_t *v, const size_t &s, bool wrap)
110 {
111 std::stringstream ss;
112 ss << std::uppercase << std::hex << std::setfill('0');
113 for (size_t i = 0; i < s; i++) {
114 if (wrap && i > 0 && i % DEBUG_MAX_COL_COUNT == 0) {
115 ss << std::endl;
116 }
117 if (i == DEBUG_MAX_DATA_LEN) {
118 ss << "......";
119 break;
120 }
121 ss << std::hex << std::setw(DEBUG_COL_ITEM_LEN) << static_cast<int>(v[i]) << " ";
122 }
123 return ss.str();
124 }
125
ObexHeaderItemDebug(const ObexOptionalHeader & hi)126 void ObexUtils::ObexHeaderItemDebug(const ObexOptionalHeader &hi)
127 {
128 OBEX_LOG_INFO("HeaderId:0x%02X", hi.GetHeaderId());
129 OBEX_LOG_INFO("DataSize(dec):%{public}d, AllSize(dec):%{public}d",
130 int(hi.GetHeaderDataSize()), int(hi.GetHeaderTotalSize()));
131 OBEX_LOG_INFO("DataType:0x%02hhX, DataTypeName:%{public}s", hi.GetHeaderClassType(), hi.GetHeaderClassTypeName().c_str());
132 switch (hi.GetHeaderClassType()) {
133 case ObexHeaderDataType::BYTES: {
134 auto bytes = hi.GetBytes();
135 if (bytes) {
136 OBEX_LOG_INFO("BYTES:%{public}s", ToDebugString(bytes.get(), hi.GetHeaderDataSize(), false).c_str());
137 } else {
138 OBEX_LOG_INFO("BYTES: null");
139 }
140 break;
141 }
142 case ObexHeaderDataType::BYTE:
143 OBEX_LOG_INFO("BYTE:0x%02X", static_cast<const ObexOptionalByteHeader *>(&hi)->GetByte());
144 break;
145 case ObexHeaderDataType::WORD:
146 OBEX_LOG_INFO("WORD(dec):%{public}d", static_cast<const ObexOptionalWordHeader *>(&hi)->GetWord());
147 break;
148 case ObexHeaderDataType::UNICODE_TEXT:
149 OBEX_LOG_INFO("UNICODE_TEXT:%{public}s",
150 UnicodeToUtf8(static_cast<const ObexOptionalUnicodeHeader *>(&hi)->GetUnicodeText()).c_str());
151 break;
152 case ObexHeaderDataType::STRING:
153 OBEX_LOG_INFO("String:%{public}s", static_cast<const ObexOptionalStringHeader *>(&hi)->GetString().c_str());
154 break;
155 case ObexHeaderDataType::TLV: {
156 auto &tlvParamters = static_cast<const ObexOptionalTlvHeader *>(&hi)->GetTlvParamters();
157 if (tlvParamters != nullptr) {
158 int index = 0;
159 for (auto &pm : static_cast<const ObexOptionalTlvHeader *>(&hi)->GetTlvParamters()->GetTlvTriplets()) {
160 OBEX_LOG_INFO("----TlvHeader At:%{public}d, TAG:0x%02X, LEN:%{public}d", index, pm->GetTagId(), pm->GetLen());
161 OBEX_LOG_INFO("--VAL:%{public}s", ObexUtils::ToDebugString(pm->GetVal(), pm->GetLen(), false).c_str());
162 index++;
163 }
164 }
165 break;
166 }
167 default:
168 OBEX_LOG_ERROR("HdrType is illegal");
169 break;
170 }
171 OBEX_LOG_INFO("DATA HEX:\n%{public}s", ObexUtils::ToDebugString(hi.GetBytes().get(), hi.GetHeaderDataSize(), true).c_str());
172 }
173
ObexHeaderDebug(const ObexHeader & header)174 void ObexUtils::ObexHeaderDebug(const ObexHeader &header)
175 {
176 OBEX_LOG_INFO("----------ObexHeader Debug Start----------");
177
178 OBEX_LOG_INFO("Code:0x%02X", header.GetFieldCode());
179 OBEX_LOG_INFO("PacketLength(dec):%{public}d", int(header.GetFieldPacketLength()));
180 if (header.GetFieldObexVersionNum() != nullptr) {
181 OBEX_LOG_INFO("ObexVersionNum:0x%02X", header.GetFieldObexVersionNum()[0]);
182 }
183 if (header.GetFieldFlags() != nullptr) {
184 OBEX_LOG_INFO("Flags:0x%02X", header.GetFieldFlags()[0]);
185 }
186 if (header.GetFieldMaxPacketLength() != nullptr) {
187 OBEX_LOG_INFO("MaxPacketLength(dec):%{public}d", int(header.GetFieldMaxPacketLength()[0]));
188 }
189 if (header.GetFieldConstants() != nullptr) {
190 OBEX_LOG_INFO("Constants:0x%02X", header.GetFieldConstants()[0]);
191 }
192
193 auto &headerList = header.GetOptionalHeaders();
194 OBEX_LOG_INFO("--------------------OptionalHeaders Start");
195
196 for (size_t i = 0; i < headerList.size(); i++) {
197 OBEX_LOG_INFO("----------Header At:%zu", i);
198 auto &headerItem = headerList.at(i);
199 ObexHeaderItemDebug(*headerItem);
200 }
201 OBEX_LOG_INFO("--------------------OptionalHeaders End");
202
203 auto obexPacket = header.Build();
204 OBEX_LOG_INFO(
205 "ALL HEX:\n%{public}s", ObexUtils::ToDebugString(obexPacket->GetBuffer(), obexPacket->GetSize(), true).c_str());
206
207 OBEX_LOG_INFO("----------ObexHeader Debug End----------");
208 }
209
BtAddr2String(const BtAddr & addr)210 std::string ObexUtils::BtAddr2String(const BtAddr &addr)
211 {
212 return RawAddress::ConvertToString(addr.addr).GetAddress();
213 }
214
MakeNonce(const uint32_t & privateKey)215 std::vector<uint8_t> ObexUtils::MakeNonce(const uint32_t &privateKey)
216 {
217 std::unique_lock<std::mutex> unilock(g_mutex);
218
219 struct timespec tp;
220 clock_gettime(CLOCK_REALTIME, &tp);
221 const int bufSize = 20;
222 char secBuf[bufSize] = {0};
223 (void)sprintf_s(secBuf, sizeof(secBuf), "%ld", tp.tv_sec);
224 std::string sec(secBuf);
225
226 char nsecBuf[bufSize] = {0};
227 (void)sprintf_s(nsecBuf, sizeof(nsecBuf), "%ld", tp.tv_nsec);
228 std::string nsec(nsecBuf);
229
230 std::string timeStamp = sec + nsec;
231
232 char key[bufSize] = {0};
233 (void)sprintf_s(key, sizeof(key), "%{public}d", int(privateKey));
234 std::string priKey(key);
235
236 std::string nonce = timeStamp + ":" + priKey;
237
238 stub::MessageDigest *digest = stub::MessageDigestFactory::GetInstance(stub::DIGEST_TYPE_MD5);
239
240 return digest->Digest((uint8_t *)nonce.data(), nonce.size());
241 }
242
MakeRequestDigest(const uint8_t * nonce,int sz,const std::string & password)243 std::vector<uint8_t> ObexUtils::MakeRequestDigest(const uint8_t *nonce, int sz, const std::string &password)
244 {
245 std::unique_lock<std::mutex> unilock(g_mutex);
246 const int bufSize = 256;
247 uint8_t nonceBuf[bufSize];
248 (void)memcpy_s(nonceBuf, sizeof(nonceBuf), nonce, sz);
249 nonceBuf[sz] = ':';
250 (void)memcpy_s(&nonceBuf[sz + 1], sizeof(nonceBuf) - sz - 1,
251 reinterpret_cast<uint8_t *>(const_cast<char *>(password.c_str())), password.size());
252
253 stub::MessageDigest *digest = stub::MessageDigestFactory::GetInstance(stub::DIGEST_TYPE_MD5);
254 std::vector<uint8_t> vc = digest->Digest((uint8_t *)nonceBuf, sz + password.size() + 1);
255
256 return vc;
257 }
258
UnicodeToUtf8(const std::u16string & str16)259 std::string ObexUtils::UnicodeToUtf8(const std::u16string &str16)
260 {
261 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
262 return convert.to_bytes(str16);
263 }
264
Utf8ToUnicode(const std::string & strUtf8)265 std::u16string ObexUtils::Utf8ToUnicode(const std::string &strUtf8)
266 {
267 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
268 return convert.from_bytes(strUtf8);
269 }
270 } // namespace bluetooth
271 } // namespace OHOS