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",
132 hi.GetHeaderClassType(), hi.GetHeaderClassTypeName().c_str());
133 switch (hi.GetHeaderClassType()) {
134 case ObexHeaderDataType::BYTES: {
135 auto bytes = hi.GetBytes();
136 if (bytes) {
137 OBEX_LOG_INFO("BYTES:%{public}s", ToDebugString(bytes.get(), hi.GetHeaderDataSize(), false).c_str());
138 } else {
139 OBEX_LOG_INFO("BYTES: null");
140 }
141 break;
142 }
143 case ObexHeaderDataType::BYTE:
144 OBEX_LOG_INFO("BYTE:0x%02X", static_cast<const ObexOptionalByteHeader *>(&hi)->GetByte());
145 break;
146 case ObexHeaderDataType::WORD:
147 OBEX_LOG_INFO("WORD(dec):%{public}d", static_cast<const ObexOptionalWordHeader *>(&hi)->GetWord());
148 break;
149 case ObexHeaderDataType::UNICODE_TEXT:
150 OBEX_LOG_INFO("UNICODE_TEXT:%{public}s",
151 UnicodeToUtf8(static_cast<const ObexOptionalUnicodeHeader *>(&hi)->GetUnicodeText()).c_str());
152 break;
153 case ObexHeaderDataType::STRING:
154 OBEX_LOG_INFO("String:%{public}s", static_cast<const ObexOptionalStringHeader *>(&hi)->GetString().c_str());
155 break;
156 case ObexHeaderDataType::TLV: {
157 auto &tlvParamters = static_cast<const ObexOptionalTlvHeader *>(&hi)->GetTlvParamters();
158 if (tlvParamters != nullptr) {
159 int index = 0;
160 for (auto &pm : static_cast<const ObexOptionalTlvHeader *>(&hi)->GetTlvParamters()->GetTlvTriplets()) {
161 OBEX_LOG_INFO("----TlvHeader At:%{public}d, TAG:0x%02X, LEN:%{public}d",
162 index, pm->GetTagId(), pm->GetLen());
163 OBEX_LOG_INFO("--VAL:%{public}s",
164 ObexUtils::ToDebugString(pm->GetVal(), pm->GetLen(), false).c_str());
165 index++;
166 }
167 }
168 break;
169 }
170 default:
171 OBEX_LOG_ERROR("HdrType is illegal");
172 break;
173 }
174 OBEX_LOG_INFO("DATA HEX:\n%{public}s",
175 ObexUtils::ToDebugString(hi.GetBytes().get(), hi.GetHeaderDataSize(), true).c_str());
176 }
177
ObexHeaderDebug(const ObexHeader & header)178 void ObexUtils::ObexHeaderDebug(const ObexHeader &header)
179 {
180 OBEX_LOG_INFO("----------ObexHeader Debug Start----------");
181
182 OBEX_LOG_INFO("Code:0x%02X", header.GetFieldCode());
183 OBEX_LOG_INFO("PacketLength(dec):%{public}d", int(header.GetFieldPacketLength()));
184 if (header.GetFieldObexVersionNum() != nullptr) {
185 OBEX_LOG_INFO("ObexVersionNum:0x%02X", header.GetFieldObexVersionNum()[0]);
186 }
187 if (header.GetFieldFlags() != nullptr) {
188 OBEX_LOG_INFO("Flags:0x%02X", header.GetFieldFlags()[0]);
189 }
190 if (header.GetFieldMaxPacketLength() != nullptr) {
191 OBEX_LOG_INFO("MaxPacketLength(dec):%{public}d", int(header.GetFieldMaxPacketLength()[0]));
192 }
193 if (header.GetFieldConstants() != nullptr) {
194 OBEX_LOG_INFO("Constants:0x%02X", header.GetFieldConstants()[0]);
195 }
196
197 auto &headerList = header.GetOptionalHeaders();
198 OBEX_LOG_INFO("--------------------OptionalHeaders Start");
199
200 for (size_t i = 0; i < headerList.size(); i++) {
201 OBEX_LOG_INFO("----------Header At:%zu", i);
202 auto &headerItem = headerList.at(i);
203 ObexHeaderItemDebug(*headerItem);
204 }
205 OBEX_LOG_INFO("--------------------OptionalHeaders End");
206
207 auto obexPacket = header.Build();
208 OBEX_LOG_INFO(
209 "ALL HEX:\n%{public}s", ObexUtils::ToDebugString(obexPacket->GetBuffer(), obexPacket->GetSize(), true).c_str());
210
211 OBEX_LOG_INFO("----------ObexHeader Debug End----------");
212 }
213
BtAddr2String(const BtAddr & addr)214 std::string ObexUtils::BtAddr2String(const BtAddr &addr)
215 {
216 return RawAddress::ConvertToString(addr.addr).GetAddress();
217 }
218
MakeNonce(const uint32_t & privateKey)219 std::vector<uint8_t> ObexUtils::MakeNonce(const uint32_t &privateKey)
220 {
221 std::unique_lock<std::mutex> unilock(g_mutex);
222
223 struct timespec tp;
224 clock_gettime(CLOCK_REALTIME, &tp);
225 const int bufSize = 20;
226 char secBuf[bufSize] = {0};
227 (void)sprintf_s(secBuf, sizeof(secBuf), "%ld", tp.tv_sec);
228 std::string sec(secBuf);
229
230 char nsecBuf[bufSize] = {0};
231 (void)sprintf_s(nsecBuf, sizeof(nsecBuf), "%ld", tp.tv_nsec);
232 std::string nsec(nsecBuf);
233
234 std::string timeStamp = sec + nsec;
235
236 char key[bufSize] = {0};
237 (void)sprintf_s(key, sizeof(key), "%{public}d", int(privateKey));
238 std::string priKey(key);
239
240 std::string nonce = timeStamp + ":" + priKey;
241
242 stub::MessageDigest *digest = stub::MessageDigestFactory::GetInstance(stub::DIGEST_TYPE_MD5);
243
244 return digest->Digest((uint8_t *)nonce.data(), nonce.size());
245 }
246
MakeRequestDigest(const uint8_t * nonce,int sz,const std::string & password)247 std::vector<uint8_t> ObexUtils::MakeRequestDigest(const uint8_t *nonce, int sz, const std::string &password)
248 {
249 std::unique_lock<std::mutex> unilock(g_mutex);
250 const int bufSize = 256;
251 uint8_t nonceBuf[bufSize];
252 (void)memcpy_s(nonceBuf, sizeof(nonceBuf), nonce, sz);
253 nonceBuf[sz] = ':';
254 (void)memcpy_s(&nonceBuf[sz + 1], sizeof(nonceBuf) - sz - 1,
255 reinterpret_cast<uint8_t *>(const_cast<char *>(password.c_str())), password.size());
256
257 stub::MessageDigest *digest = stub::MessageDigestFactory::GetInstance(stub::DIGEST_TYPE_MD5);
258 std::vector<uint8_t> vc = digest->Digest((uint8_t *)nonceBuf, sz + password.size() + 1);
259
260 return vc;
261 }
262
UnicodeToUtf8(const std::u16string & str16)263 std::string ObexUtils::UnicodeToUtf8(const std::u16string &str16)
264 {
265 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
266 return convert.to_bytes(str16);
267 }
268
Utf8ToUnicode(const std::string & strUtf8)269 std::u16string ObexUtils::Utf8ToUnicode(const std::string &strUtf8)
270 {
271 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
272 return convert.from_bytes(strUtf8);
273 }
274 } // namespace bluetooth
275 } // namespace OHOS