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 "dslm_msg_utils.h"
17
18 #include <securec.h>
19 #include <string.h>
20
21 #include "utils_base64.h"
22 #include "utils_hexstring.h"
23 #include "utils_json.h"
24 #include "utils_log.h"
25 #include "utils_mem.h"
26
27 #include "device_security_defines.h"
28 #include "dslm_core_defines.h"
29 #include "dslm_credential.h"
30
31 #define CHALLENGE_STRING_LENGTH 32
32
GenerateSecInfoResponseJson(uint64_t challenge,const DslmCredBuff * cred)33 static uint8_t *GenerateSecInfoResponseJson(uint64_t challenge, const DslmCredBuff *cred)
34 {
35 uint8_t *credBase64Str = NULL;
36 uint8_t *out = NULL;
37
38 JsonHandle head = CreateJson(NULL);
39 if (head == NULL) {
40 return NULL;
41 }
42
43 JsonHandle body = CreateJson(NULL);
44 if (body == NULL) {
45 DestroyJson(head);
46 return NULL;
47 }
48
49 AddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_RESPONSE);
50 AddFieldJsonToJson(head, FIELD_PAYLOAD, body);
51
52 AddFieldIntToJson(body, FIELD_VERSION, GetCurrentVersion());
53 AddFieldIntToJson(body, FIELD_CRED_TYPE, cred->type);
54
55 char challengeStr[CHALLENGE_STRING_LENGTH] = {0};
56 char *nonce = &challengeStr[0];
57 ByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH);
58 challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0;
59 AddFieldStringToJson(body, FIELD_CHALLENGE, nonce);
60
61 credBase64Str = Base64EncodeApp(cred->credVal, cred->credLen);
62 // it is ok when credBase64Str is NULL
63 AddFieldStringToJson(body, FIELD_CRED_INFO, (char *)credBase64Str);
64 out = (uint8_t *)ConvertJsonToString(head);
65
66 if (head != NULL) {
67 DestroyJson(head);
68 body = NULL; // no need to free body
69 }
70
71 if (body != NULL) {
72 DestroyJson(body);
73 }
74 if (credBase64Str != NULL) {
75 FREE(credBase64Str);
76 }
77 return out;
78 }
79
GenerateSecInfoRequestJson(uint64_t challenge)80 static uint8_t *GenerateSecInfoRequestJson(uint64_t challenge)
81 {
82 JsonHandle head = CreateJson(NULL);
83 if (head == NULL) {
84 return NULL;
85 }
86 JsonHandle body = CreateJson(NULL);
87 if (body == NULL) {
88 DestroyJson(head);
89 return NULL;
90 }
91
92 char challengeStr[CHALLENGE_STRING_LENGTH] = {0};
93 char *nonce = &challengeStr[0];
94 ByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH);
95 challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0;
96
97 AddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_REQUEST);
98 AddFieldJsonToJson(head, FIELD_PAYLOAD, body);
99 AddFieldIntToJson(body, FIELD_VERSION, GetCurrentVersion());
100
101 AddFieldStringToJson(body, FIELD_CHALLENGE, nonce);
102
103 CredType credTypeArray[MAX_CRED_ARRAY_SIZE] = {0};
104 int32_t arraySize = GetSupportedCredTypes(credTypeArray, MAX_CRED_ARRAY_SIZE);
105 AddFieldIntArrayToJson(body, FIELD_SUPPORT, (const int32_t *)credTypeArray, arraySize);
106
107 uint8_t *out = (uint8_t *)ConvertJsonToString(head);
108
109 if (head != NULL) {
110 DestroyJson(head);
111 body = NULL; // no need to free body
112 }
113
114 if (body != NULL) {
115 DestroyJson(body);
116 }
117 return out;
118 }
119
BuildDeviceSecInfoRequest(uint64_t challenge,MessageBuff ** msg)120 int32_t BuildDeviceSecInfoRequest(uint64_t challenge, MessageBuff **msg)
121 {
122 if ((msg == NULL) || (*msg != NULL)) {
123 return ERR_INVALID_PARA;
124 }
125
126 MessageBuff *out = MALLOC(sizeof(MessageBuff));
127 if (out == NULL) {
128 return ERR_NO_MEMORY;
129 }
130 memset_s(out, sizeof(MessageBuff), 0, sizeof(MessageBuff));
131
132 out->buff = GenerateSecInfoRequestJson(challenge);
133 if (out->buff == NULL) {
134 FREE(out);
135 return ERR_JSON_ERR;
136 }
137 out->length = strlen((char *)out->buff) + 1;
138 *msg = out;
139 return SUCCESS;
140 }
141
ParseDeviceSecInfoRequest(const MessageBuff * buff,RequestObject * obj)142 int32_t ParseDeviceSecInfoRequest(const MessageBuff *buff, RequestObject *obj)
143 {
144 if (buff == NULL || obj == NULL || buff->buff == NULL) {
145 return ERR_INVALID_PARA;
146 }
147 SECURITY_LOG_DEBUG("ParseDeviceSecInfoRequest msg is %s", (char *)buff->buff);
148
149 JsonHandle handle = CreateJson((const char *)buff->buff);
150 if (handle == NULL) {
151 return ERR_INVALID_PARA;
152 }
153
154 const char *nonceStr = GetJsonFieldString(handle, FIELD_CHALLENGE);
155 if (nonceStr == NULL) {
156 DestroyJson(handle);
157 return ERR_NO_CHALLENGE;
158 }
159
160 int32_t ret = HexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&obj->challenge, sizeof(obj->challenge));
161 if (ret != 0) {
162 DestroyJson(handle);
163 return ERR_NO_CHALLENGE;
164 }
165
166 obj->version = (uint32_t)GetJsonFieldInt(handle, FIELD_VERSION);
167 obj->arraySize = GetJsonFieldIntArray(handle, FIELD_SUPPORT, (int32_t *)obj->credArray, MAX_CRED_ARRAY_SIZE);
168
169 DestroyJson(handle);
170
171 return SUCCESS;
172 }
173
BuildDeviceSecInfoResponse(uint64_t challenge,const DslmCredBuff * cred,MessageBuff ** msg)174 int32_t BuildDeviceSecInfoResponse(uint64_t challenge, const DslmCredBuff *cred, MessageBuff **msg)
175 {
176 if ((cred == NULL) || (msg == NULL) || (*msg != NULL)) {
177 return ERR_INVALID_PARA;
178 }
179 MessageBuff *out = MALLOC(sizeof(MessageBuff));
180 if (out == NULL) {
181 return ERR_NO_MEMORY;
182 }
183
184 out->buff = (uint8_t *)GenerateSecInfoResponseJson(challenge, cred);
185 if (out->buff == NULL) {
186 FREE(out);
187 return ERR_JSON_ERR;
188 }
189 out->length = strlen((char *)out->buff) + 1;
190
191 *msg = out;
192 return SUCCESS;
193 }
194
ParseDeviceSecInfoResponse(const MessageBuff * msg,uint64_t * challenge,uint32_t * version,DslmCredBuff ** cred)195 int32_t ParseDeviceSecInfoResponse(const MessageBuff *msg, uint64_t *challenge, uint32_t *version, DslmCredBuff **cred)
196 {
197 if (msg == NULL || challenge == NULL || version == NULL || cred == NULL) {
198 return ERR_INVALID_PARA;
199 }
200
201 if (msg->buff == NULL || *cred != NULL) {
202 return ERR_INVALID_PARA;
203 }
204
205 JsonHandle handle = CreateJson((const char *)msg->buff);
206 if (handle == NULL) {
207 return ERR_INVALID_PARA;
208 }
209
210 const char *nonceStr = GetJsonFieldString(handle, FIELD_CHALLENGE);
211 if (nonceStr == NULL) {
212 DestroyJson(handle);
213 return ERR_NO_CHALLENGE;
214 }
215 uint64_t nonceNum = 0;
216 int32_t ret = HexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&nonceNum, sizeof(uint64_t));
217 if (ret != 0) {
218 DestroyJson(handle);
219 return ERR_NO_CHALLENGE;
220 }
221
222 uint32_t type = (uint32_t)GetJsonFieldInt(handle, FIELD_CRED_TYPE);
223 uint32_t verNum = (uint32_t)GetJsonFieldInt(handle, FIELD_VERSION);
224
225 const char *credStr = GetJsonFieldString(handle, FIELD_CRED_INFO);
226 if (credStr == NULL) {
227 DestroyJson(handle);
228 return ERR_NO_CRED;
229 }
230
231 uint8_t *credBuf = NULL;
232 uint32_t credLen = (uint32_t)Base64DecodeApp((uint8_t *)credStr, &credBuf);
233 if (credBuf == NULL) {
234 DestroyJson(handle);
235 return ERR_NO_CRED;
236 }
237
238 DslmCredBuff *out = CreateDslmCred((CredType)type, credLen, credBuf);
239 if (out == NULL) {
240 DestroyJson(handle);
241 FREE(credBuf);
242 return ERR_NO_MEMORY;
243 }
244
245 DestroyJson(handle);
246 FREE(credBuf);
247 *version = verNum;
248 *challenge = nonceNum;
249 *cred = out;
250 return SUCCESS;
251 }
252