1 /*
2 * Copyright (C) 2025 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 "credential_message.h"
16
17 using namespace Hdc;
18
CredentialMessage(const std::string & messageStr)19 CredentialMessage::CredentialMessage(const std::string& messageStr)
20 {
21 Init(messageStr);
22 }
23
Init(const std::string & messageStr)24 void CredentialMessage::Init(const std::string& messageStr)
25 {
26 if (messageStr.empty() || messageStr.length() < MESSAGE_BODY_POS) {
27 WRITE_LOG(LOG_FATAL, "messageStr is too short!");
28 return;
29 }
30
31 int versionInt = messageStr[MESSAGE_VERSION_POS] - '0';
32 if ((versionInt >= METHOD_VERSION_V1 && versionInt <= METHOD_VERSION_MAX) ? false : true) {
33 WRITE_LOG(LOG_FATAL, "Invalid message version %d.", versionInt);
34 return;
35 }
36
37 messageVersion = versionInt;
38
39 std::string messageMethodStr = messageStr.substr(MESSAGE_METHOD_POS, MESSAGE_METHOD_LEN);
40 messageMethodType = StripLeadingZeros(messageMethodStr);
41
42 std::string messageLengthStr = messageStr.substr(MESSAGE_LENGTH_POS, MESSAGE_LENGTH_LEN);
43 char* end = nullptr;
44 size_t bodyLength = static_cast<size_t>(strtol(messageLengthStr.c_str(), &end, 10));
45 if (end == nullptr || *end != '\0' || bodyLength > MESSAGE_STR_MAX_LEN) {
46 WRITE_LOG(LOG_FATAL, "Invalid message body length %s.", messageLengthStr.c_str());
47 return;
48 }
49
50 if (messageStr.length() < MESSAGE_BODY_POS + bodyLength) {
51 WRITE_LOG(LOG_FATAL, "messageStr is too short.");
52 return;
53 }
54
55 messageBodyLen = static_cast<int>(bodyLength);
56 messageBody = messageStr.substr(MESSAGE_BODY_POS, bodyLength);
57 }
~CredentialMessage()58 CredentialMessage::~CredentialMessage()
59 {
60 if (!messageBody.empty()) {
61 memset_s(&messageBody[0], messageBody.size(), 0, messageBody.size());
62 }
63 }
64
SetMessageVersion(int version)65 void CredentialMessage::SetMessageVersion(int version)
66 {
67 if (version >= METHOD_VERSION_V1 && version <= METHOD_VERSION_MAX) {
68 messageVersion = version;
69 } else {
70 WRITE_LOG(LOG_FATAL, "Invalid message version %d.", version);
71 }
72 }
73
SetMessageBody(const std::string & body)74 void CredentialMessage::SetMessageBody(const std::string& body)
75 {
76 if (body.size() > MESSAGE_STR_MAX_LEN) {
77 WRITE_LOG(LOG_FATAL, "Message body length exceeds maximum allowed length.");
78 return;
79 }
80 messageBody = body;
81 messageBodyLen = static_cast<int>(messageBody.size());
82 }
83
Construct() const84 std::string CredentialMessage::Construct() const
85 {
86 size_t totalLength = 0;
87 totalLength += 1;
88 totalLength += MESSAGE_METHOD_LEN;
89 totalLength += MESSAGE_LENGTH_LEN;
90 totalLength += messageBody.size();
91
92 std::string messageMethodTypeStr = IntToStringWithPadding(messageMethodType, MESSAGE_METHOD_LEN);
93 if (messageMethodTypeStr.size() != MESSAGE_METHOD_LEN) {
94 WRITE_LOG(LOG_FATAL, "messageMethod length Error!");
95 return "";
96 }
97
98 std::string messageBodyLenStr = IntToStringWithPadding(messageBodyLen, MESSAGE_LENGTH_LEN);
99 if (messageBodyLenStr.empty() || (messageBodyLenStr.size() > MESSAGE_LENGTH_LEN)) {
100 WRITE_LOG(LOG_FATAL, "messageBodyLen length must be:%d,now is:%s",
101 MESSAGE_LENGTH_LEN, messageBodyLenStr.c_str());
102 return "";
103 }
104
105 std::string result;
106 result.reserve(totalLength);
107 result.push_back('0' + messageVersion);
108 result.append(messageMethodTypeStr);
109 result.append(messageBodyLenStr);
110 result.append(messageBody);
111
112 if (result.size() != totalLength) {
113 WRITE_LOG(LOG_FATAL, "size mismatch. Expected: %zu, Actual: %zu", totalLength, result.size());
114 return "";
115 }
116
117 return result;
118 }
119
IsNumeric(const std::string & str)120 bool IsNumeric(const std::string& str)
121 {
122 if (str.empty()) {
123 return false;
124 }
125 for (char ch : str) {
126 if (!std::isdigit(ch)) {
127 return false;
128 }
129 }
130 return true;
131 }
132
StripLeadingZeros(const std::string & input)133 int StripLeadingZeros(const std::string& input)
134 {
135 if (input.empty() || input == "0") {
136 return 0;
137 }
138 size_t firstNonZero = input.find_first_not_of('0');
139 if (firstNonZero == std::string::npos) {
140 return 0;
141 }
142
143 std::string numberStr = input.substr(firstNonZero);
144 if (!IsNumeric(numberStr)) {
145 WRITE_LOG(LOG_FATAL, "StripLeadingZeros: invalid numeric string.");
146 return -1;
147 }
148
149 char* end = nullptr;
150 long value = strtol(numberStr.c_str(), &end, 10);
151 return static_cast<int>(value);
152 }
153
String2Uint8(const std::string & str,size_t len)154 std::vector<uint8_t> String2Uint8(const std::string& str, size_t len)
155 {
156 std::vector<uint8_t> byteData(len);
157 for (size_t i = 0; i < len; i++) {
158 byteData[i] = static_cast<uint8_t>(str[i]);
159 }
160 return byteData;
161 }
162
IntToStringWithPadding(int length,int maxLen)163 std::string IntToStringWithPadding(int length, int maxLen)
164 {
165 std::string str = std::to_string(length);
166 if (str.length() > static_cast<size_t>(maxLen)) {
167 return "";
168 }
169 return std::string(static_cast<size_t>(maxLen) - str.length(), '0') + str;
170 }