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 16#include "dslm_msg_utils.h" 17 18#include <string.h> 19 20#include "securec.h" 21 22#include "device_security_defines.h" 23#include "dslm_core_defines.h" 24#include "dslm_credential.h" 25#include "utils_base64.h" 26#include "utils_hexstring.h" 27#include "utils_json.h" 28#include "utils_log.h" 29#include "utils_mem.h" 30 31#define CHALLENGE_STRING_LENGTH 32 32 33static uint8_t *GenerateSecInfoResponseJson(uint64_t challenge, const DslmCredBuff *cred) 34{ 35 uint8_t *credBase64Str = NULL; 36 uint8_t *out = NULL; 37 38 DslmJsonHandle head = DslmCreateJson(NULL); 39 if (head == NULL) { 40 return NULL; 41 } 42 43 DslmJsonHandle body = DslmCreateJson(NULL); 44 if (body == NULL) { 45 DslmDestroyJson(head); 46 return NULL; 47 } 48 49 DslmAddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_RESPONSE); 50 DslmAddFieldJsonToJson(head, FIELD_PAYLOAD, body); 51 52 DslmAddFieldIntToJson(body, FIELD_VERSION, (int32_t)GetCurrentVersion()); 53 DslmAddFieldIntToJson(body, FIELD_CRED_TYPE, cred->type); 54 55 char challengeStr[CHALLENGE_STRING_LENGTH] = {0}; 56 char *nonce = &challengeStr[0]; 57 DslmByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH); 58 challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0; 59 DslmAddFieldStringToJson(body, FIELD_CHALLENGE, nonce); 60 61 credBase64Str = Base64EncodeApp(cred->credVal, cred->credLen); 62 // it is ok when credBase64Str is NULL 63 DslmAddFieldStringToJson(body, FIELD_CRED_INFO, (char *)credBase64Str); 64 out = (uint8_t *)DslmConvertJsonToString(head); 65 66 if (head != NULL) { 67 DslmDestroyJson(head); 68 body = NULL; // no need to free body 69 } 70 71 if (body != NULL) { 72 DslmDestroyJson(body); 73 } 74 if (credBase64Str != NULL) { 75 FREE(credBase64Str); 76 } 77 return out; 78} 79 80static uint8_t *GenerateSecInfoRequestJson(uint64_t challenge) 81{ 82 DslmJsonHandle head = DslmCreateJson(NULL); 83 if (head == NULL) { 84 return NULL; 85 } 86 DslmJsonHandle body = DslmCreateJson(NULL); 87 if (body == NULL) { 88 DslmDestroyJson(head); 89 return NULL; 90 } 91 92 char challengeStr[CHALLENGE_STRING_LENGTH] = {0}; 93 char *nonce = &challengeStr[0]; 94 DslmByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH); 95 challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0; 96 97 DslmAddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_REQUEST); 98 DslmAddFieldJsonToJson(head, FIELD_PAYLOAD, body); 99 DslmAddFieldIntToJson(body, FIELD_VERSION, (int32_t)GetCurrentVersion()); 100 101 DslmAddFieldStringToJson(body, FIELD_CHALLENGE, nonce); 102 103 CredType credTypeArray[MAX_CRED_ARRAY_SIZE] = {0}; 104 int32_t arraySize = GetSupportedCredTypes(credTypeArray, MAX_CRED_ARRAY_SIZE); 105 DslmAddFieldIntArrayToJson(body, FIELD_SUPPORT, (const int32_t *)credTypeArray, arraySize); 106 107 uint8_t *out = (uint8_t *)DslmConvertJsonToString(head); 108 109 if (head != NULL) { 110 DslmDestroyJson(head); 111 body = NULL; // no need to free body 112 } 113 114 if (body != NULL) { 115 DslmDestroyJson(body); 116 } 117 return out; 118} 119 120int32_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 (void)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 142int32_t ParseDeviceSecInfoRequest(const MessageBuff *msg, RequestObject *obj) 143{ 144 if (msg == NULL || obj == NULL || msg->buff == NULL) { 145 return ERR_INVALID_PARA; 146 } 147 SECURITY_LOG_DEBUG("ParseDeviceSecInfoRequest msg is %s", (char *)msg->buff); 148 149 DslmJsonHandle handle = DslmCreateJson((const char *)msg->buff); 150 if (handle == NULL) { 151 return ERR_INVALID_PARA; 152 } 153 154 const char *nonceStr = DslmGetJsonFieldString(handle, FIELD_CHALLENGE); 155 if (nonceStr == NULL) { 156 DslmDestroyJson(handle); 157 return ERR_NO_CHALLENGE; 158 } 159 160 int32_t ret = DslmHexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&obj->challenge, sizeof(obj->challenge)); 161 if (ret != 0) { 162 DslmDestroyJson(handle); 163 return ERR_NO_CHALLENGE; 164 } 165 166 obj->version = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_VERSION); 167 obj->arraySize = DslmGetJsonFieldIntArray(handle, FIELD_SUPPORT, (int32_t *)obj->credArray, MAX_CRED_ARRAY_SIZE); 168 169 DslmDestroyJson(handle); 170 171 return SUCCESS; 172} 173 174int32_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 = 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 195int32_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 DslmJsonHandle handle = DslmCreateJson((const char *)msg->buff); 206 if (handle == NULL) { 207 return ERR_INVALID_PARA; 208 } 209 210 const char *nonceStr = DslmGetJsonFieldString(handle, FIELD_CHALLENGE); 211 if (nonceStr == NULL) { 212 DslmDestroyJson(handle); 213 return ERR_NO_CHALLENGE; 214 } 215 uint64_t nonceNum = 0; 216 int32_t ret = DslmHexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&nonceNum, sizeof(uint64_t)); 217 if (ret != 0) { 218 DslmDestroyJson(handle); 219 return ERR_NO_CHALLENGE; 220 } 221 222 uint32_t type = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_CRED_TYPE); 223 uint32_t verNum = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_VERSION); 224 225 const char *credStr = DslmGetJsonFieldString(handle, FIELD_CRED_INFO); 226 if (credStr == NULL) { 227 DslmDestroyJson(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 DslmDestroyJson(handle); 235 return ERR_NO_CRED; 236 } 237 238 DslmCredBuff *out = CreateDslmCred((CredType)type, credLen, credBuf); 239 if (out == NULL) { 240 DslmDestroyJson(handle); 241 FREE(credBuf); 242 return ERR_NO_MEMORY; 243 } 244 245 DslmDestroyJson(handle); 246 FREE(credBuf); 247 *version = verNum; 248 *challenge = nonceNum; 249 *cred = out; 250 return SUCCESS; 251} 252