12ee81decSopenharmony_ci/*
22ee81decSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
32ee81decSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42ee81decSopenharmony_ci * you may not use this file except in compliance with the License.
52ee81decSopenharmony_ci * You may obtain a copy of the License at
62ee81decSopenharmony_ci *
72ee81decSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
82ee81decSopenharmony_ci *
92ee81decSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102ee81decSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112ee81decSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122ee81decSopenharmony_ci * See the License for the specific language governing permissions and
132ee81decSopenharmony_ci * limitations under the License.
142ee81decSopenharmony_ci */
152ee81decSopenharmony_ci
162ee81decSopenharmony_ci#include "dslm_msg_utils.h"
172ee81decSopenharmony_ci
182ee81decSopenharmony_ci#include <string.h>
192ee81decSopenharmony_ci
202ee81decSopenharmony_ci#include "securec.h"
212ee81decSopenharmony_ci
222ee81decSopenharmony_ci#include "device_security_defines.h"
232ee81decSopenharmony_ci#include "dslm_core_defines.h"
242ee81decSopenharmony_ci#include "dslm_credential.h"
252ee81decSopenharmony_ci#include "utils_base64.h"
262ee81decSopenharmony_ci#include "utils_hexstring.h"
272ee81decSopenharmony_ci#include "utils_json.h"
282ee81decSopenharmony_ci#include "utils_log.h"
292ee81decSopenharmony_ci#include "utils_mem.h"
302ee81decSopenharmony_ci
312ee81decSopenharmony_ci#define CHALLENGE_STRING_LENGTH 32
322ee81decSopenharmony_ci
332ee81decSopenharmony_cistatic uint8_t *GenerateSecInfoResponseJson(uint64_t challenge, const DslmCredBuff *cred)
342ee81decSopenharmony_ci{
352ee81decSopenharmony_ci    uint8_t *credBase64Str = NULL;
362ee81decSopenharmony_ci    uint8_t *out = NULL;
372ee81decSopenharmony_ci
382ee81decSopenharmony_ci    DslmJsonHandle head = DslmCreateJson(NULL);
392ee81decSopenharmony_ci    if (head == NULL) {
402ee81decSopenharmony_ci        return NULL;
412ee81decSopenharmony_ci    }
422ee81decSopenharmony_ci
432ee81decSopenharmony_ci    DslmJsonHandle body = DslmCreateJson(NULL);
442ee81decSopenharmony_ci    if (body == NULL) {
452ee81decSopenharmony_ci        DslmDestroyJson(head);
462ee81decSopenharmony_ci        return NULL;
472ee81decSopenharmony_ci    }
482ee81decSopenharmony_ci
492ee81decSopenharmony_ci    DslmAddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_RESPONSE);
502ee81decSopenharmony_ci    DslmAddFieldJsonToJson(head, FIELD_PAYLOAD, body);
512ee81decSopenharmony_ci
522ee81decSopenharmony_ci    DslmAddFieldIntToJson(body, FIELD_VERSION, (int32_t)GetCurrentVersion());
532ee81decSopenharmony_ci    DslmAddFieldIntToJson(body, FIELD_CRED_TYPE, cred->type);
542ee81decSopenharmony_ci
552ee81decSopenharmony_ci    char challengeStr[CHALLENGE_STRING_LENGTH] = {0};
562ee81decSopenharmony_ci    char *nonce = &challengeStr[0];
572ee81decSopenharmony_ci    DslmByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH);
582ee81decSopenharmony_ci    challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0;
592ee81decSopenharmony_ci    DslmAddFieldStringToJson(body, FIELD_CHALLENGE, nonce);
602ee81decSopenharmony_ci
612ee81decSopenharmony_ci    credBase64Str = Base64EncodeApp(cred->credVal, cred->credLen);
622ee81decSopenharmony_ci    // it is ok when credBase64Str is NULL
632ee81decSopenharmony_ci    DslmAddFieldStringToJson(body, FIELD_CRED_INFO, (char *)credBase64Str);
642ee81decSopenharmony_ci    out = (uint8_t *)DslmConvertJsonToString(head);
652ee81decSopenharmony_ci
662ee81decSopenharmony_ci    if (head != NULL) {
672ee81decSopenharmony_ci        DslmDestroyJson(head);
682ee81decSopenharmony_ci        body = NULL; // no need to free body
692ee81decSopenharmony_ci    }
702ee81decSopenharmony_ci
712ee81decSopenharmony_ci    if (body != NULL) {
722ee81decSopenharmony_ci        DslmDestroyJson(body);
732ee81decSopenharmony_ci    }
742ee81decSopenharmony_ci    if (credBase64Str != NULL) {
752ee81decSopenharmony_ci        FREE(credBase64Str);
762ee81decSopenharmony_ci    }
772ee81decSopenharmony_ci    return out;
782ee81decSopenharmony_ci}
792ee81decSopenharmony_ci
802ee81decSopenharmony_cistatic uint8_t *GenerateSecInfoRequestJson(uint64_t challenge)
812ee81decSopenharmony_ci{
822ee81decSopenharmony_ci    DslmJsonHandle head = DslmCreateJson(NULL);
832ee81decSopenharmony_ci    if (head == NULL) {
842ee81decSopenharmony_ci        return NULL;
852ee81decSopenharmony_ci    }
862ee81decSopenharmony_ci    DslmJsonHandle body = DslmCreateJson(NULL);
872ee81decSopenharmony_ci    if (body == NULL) {
882ee81decSopenharmony_ci        DslmDestroyJson(head);
892ee81decSopenharmony_ci        return NULL;
902ee81decSopenharmony_ci    }
912ee81decSopenharmony_ci
922ee81decSopenharmony_ci    char challengeStr[CHALLENGE_STRING_LENGTH] = {0};
932ee81decSopenharmony_ci    char *nonce = &challengeStr[0];
942ee81decSopenharmony_ci    DslmByteToHexString((uint8_t *)&challenge, sizeof(challenge), (uint8_t *)nonce, CHALLENGE_STRING_LENGTH);
952ee81decSopenharmony_ci    challengeStr[CHALLENGE_STRING_LENGTH - 1] = 0;
962ee81decSopenharmony_ci
972ee81decSopenharmony_ci    DslmAddFieldIntToJson(head, FIELD_MESSAGE, MSG_TYPE_DSLM_CRED_REQUEST);
982ee81decSopenharmony_ci    DslmAddFieldJsonToJson(head, FIELD_PAYLOAD, body);
992ee81decSopenharmony_ci    DslmAddFieldIntToJson(body, FIELD_VERSION, (int32_t)GetCurrentVersion());
1002ee81decSopenharmony_ci
1012ee81decSopenharmony_ci    DslmAddFieldStringToJson(body, FIELD_CHALLENGE, nonce);
1022ee81decSopenharmony_ci
1032ee81decSopenharmony_ci    CredType credTypeArray[MAX_CRED_ARRAY_SIZE] = {0};
1042ee81decSopenharmony_ci    int32_t arraySize = GetSupportedCredTypes(credTypeArray, MAX_CRED_ARRAY_SIZE);
1052ee81decSopenharmony_ci    DslmAddFieldIntArrayToJson(body, FIELD_SUPPORT, (const int32_t *)credTypeArray, arraySize);
1062ee81decSopenharmony_ci
1072ee81decSopenharmony_ci    uint8_t *out = (uint8_t *)DslmConvertJsonToString(head);
1082ee81decSopenharmony_ci
1092ee81decSopenharmony_ci    if (head != NULL) {
1102ee81decSopenharmony_ci        DslmDestroyJson(head);
1112ee81decSopenharmony_ci        body = NULL; // no need to free body
1122ee81decSopenharmony_ci    }
1132ee81decSopenharmony_ci
1142ee81decSopenharmony_ci    if (body != NULL) {
1152ee81decSopenharmony_ci        DslmDestroyJson(body);
1162ee81decSopenharmony_ci    }
1172ee81decSopenharmony_ci    return out;
1182ee81decSopenharmony_ci}
1192ee81decSopenharmony_ci
1202ee81decSopenharmony_ciint32_t BuildDeviceSecInfoRequest(uint64_t challenge, MessageBuff **msg)
1212ee81decSopenharmony_ci{
1222ee81decSopenharmony_ci    if ((msg == NULL) || (*msg != NULL)) {
1232ee81decSopenharmony_ci        return ERR_INVALID_PARA;
1242ee81decSopenharmony_ci    }
1252ee81decSopenharmony_ci
1262ee81decSopenharmony_ci    MessageBuff *out = MALLOC(sizeof(MessageBuff));
1272ee81decSopenharmony_ci    if (out == NULL) {
1282ee81decSopenharmony_ci        return ERR_NO_MEMORY;
1292ee81decSopenharmony_ci    }
1302ee81decSopenharmony_ci    (void)memset_s(out, sizeof(MessageBuff), 0, sizeof(MessageBuff));
1312ee81decSopenharmony_ci
1322ee81decSopenharmony_ci    out->buff = GenerateSecInfoRequestJson(challenge);
1332ee81decSopenharmony_ci    if (out->buff == NULL) {
1342ee81decSopenharmony_ci        FREE(out);
1352ee81decSopenharmony_ci        return ERR_JSON_ERR;
1362ee81decSopenharmony_ci    }
1372ee81decSopenharmony_ci    out->length = strlen((char *)out->buff) + 1;
1382ee81decSopenharmony_ci    *msg = out;
1392ee81decSopenharmony_ci    return SUCCESS;
1402ee81decSopenharmony_ci}
1412ee81decSopenharmony_ci
1422ee81decSopenharmony_ciint32_t ParseDeviceSecInfoRequest(const MessageBuff *msg, RequestObject *obj)
1432ee81decSopenharmony_ci{
1442ee81decSopenharmony_ci    if (msg == NULL || obj == NULL || msg->buff == NULL) {
1452ee81decSopenharmony_ci        return ERR_INVALID_PARA;
1462ee81decSopenharmony_ci    }
1472ee81decSopenharmony_ci    SECURITY_LOG_DEBUG("ParseDeviceSecInfoRequest msg is %s", (char *)msg->buff);
1482ee81decSopenharmony_ci
1492ee81decSopenharmony_ci    DslmJsonHandle handle = DslmCreateJson((const char *)msg->buff);
1502ee81decSopenharmony_ci    if (handle == NULL) {
1512ee81decSopenharmony_ci        return ERR_INVALID_PARA;
1522ee81decSopenharmony_ci    }
1532ee81decSopenharmony_ci
1542ee81decSopenharmony_ci    const char *nonceStr = DslmGetJsonFieldString(handle, FIELD_CHALLENGE);
1552ee81decSopenharmony_ci    if (nonceStr == NULL) {
1562ee81decSopenharmony_ci        DslmDestroyJson(handle);
1572ee81decSopenharmony_ci        return ERR_NO_CHALLENGE;
1582ee81decSopenharmony_ci    }
1592ee81decSopenharmony_ci
1602ee81decSopenharmony_ci    int32_t ret = DslmHexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&obj->challenge, sizeof(obj->challenge));
1612ee81decSopenharmony_ci    if (ret != 0) {
1622ee81decSopenharmony_ci        DslmDestroyJson(handle);
1632ee81decSopenharmony_ci        return ERR_NO_CHALLENGE;
1642ee81decSopenharmony_ci    }
1652ee81decSopenharmony_ci
1662ee81decSopenharmony_ci    obj->version = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_VERSION);
1672ee81decSopenharmony_ci    obj->arraySize = DslmGetJsonFieldIntArray(handle, FIELD_SUPPORT, (int32_t *)obj->credArray, MAX_CRED_ARRAY_SIZE);
1682ee81decSopenharmony_ci
1692ee81decSopenharmony_ci    DslmDestroyJson(handle);
1702ee81decSopenharmony_ci
1712ee81decSopenharmony_ci    return SUCCESS;
1722ee81decSopenharmony_ci}
1732ee81decSopenharmony_ci
1742ee81decSopenharmony_ciint32_t BuildDeviceSecInfoResponse(uint64_t challenge, const DslmCredBuff *cred, MessageBuff **msg)
1752ee81decSopenharmony_ci{
1762ee81decSopenharmony_ci    if ((cred == NULL) || (msg == NULL) || (*msg != NULL)) {
1772ee81decSopenharmony_ci        return ERR_INVALID_PARA;
1782ee81decSopenharmony_ci    }
1792ee81decSopenharmony_ci    MessageBuff *out = MALLOC(sizeof(MessageBuff));
1802ee81decSopenharmony_ci    if (out == NULL) {
1812ee81decSopenharmony_ci        return ERR_NO_MEMORY;
1822ee81decSopenharmony_ci    }
1832ee81decSopenharmony_ci
1842ee81decSopenharmony_ci    out->buff = GenerateSecInfoResponseJson(challenge, cred);
1852ee81decSopenharmony_ci    if (out->buff == NULL) {
1862ee81decSopenharmony_ci        FREE(out);
1872ee81decSopenharmony_ci        return ERR_JSON_ERR;
1882ee81decSopenharmony_ci    }
1892ee81decSopenharmony_ci    out->length = strlen((char *)out->buff) + 1;
1902ee81decSopenharmony_ci
1912ee81decSopenharmony_ci    *msg = out;
1922ee81decSopenharmony_ci    return SUCCESS;
1932ee81decSopenharmony_ci}
1942ee81decSopenharmony_ci
1952ee81decSopenharmony_ciint32_t ParseDeviceSecInfoResponse(const MessageBuff *msg, uint64_t *challenge, uint32_t *version, DslmCredBuff **cred)
1962ee81decSopenharmony_ci{
1972ee81decSopenharmony_ci    if (msg == NULL || challenge == NULL || version == NULL || cred == NULL) {
1982ee81decSopenharmony_ci        return ERR_INVALID_PARA;
1992ee81decSopenharmony_ci    }
2002ee81decSopenharmony_ci
2012ee81decSopenharmony_ci    if (msg->buff == NULL || *cred != NULL) {
2022ee81decSopenharmony_ci        return ERR_INVALID_PARA;
2032ee81decSopenharmony_ci    }
2042ee81decSopenharmony_ci
2052ee81decSopenharmony_ci    DslmJsonHandle handle = DslmCreateJson((const char *)msg->buff);
2062ee81decSopenharmony_ci    if (handle == NULL) {
2072ee81decSopenharmony_ci        return ERR_INVALID_PARA;
2082ee81decSopenharmony_ci    }
2092ee81decSopenharmony_ci
2102ee81decSopenharmony_ci    const char *nonceStr = DslmGetJsonFieldString(handle, FIELD_CHALLENGE);
2112ee81decSopenharmony_ci    if (nonceStr == NULL) {
2122ee81decSopenharmony_ci        DslmDestroyJson(handle);
2132ee81decSopenharmony_ci        return ERR_NO_CHALLENGE;
2142ee81decSopenharmony_ci    }
2152ee81decSopenharmony_ci    uint64_t nonceNum = 0;
2162ee81decSopenharmony_ci    int32_t ret = DslmHexStringToByte(nonceStr, strlen(nonceStr), (uint8_t *)&nonceNum, sizeof(uint64_t));
2172ee81decSopenharmony_ci    if (ret != 0) {
2182ee81decSopenharmony_ci        DslmDestroyJson(handle);
2192ee81decSopenharmony_ci        return ERR_NO_CHALLENGE;
2202ee81decSopenharmony_ci    }
2212ee81decSopenharmony_ci
2222ee81decSopenharmony_ci    uint32_t type = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_CRED_TYPE);
2232ee81decSopenharmony_ci    uint32_t verNum = (uint32_t)DslmGetJsonFieldInt(handle, FIELD_VERSION);
2242ee81decSopenharmony_ci
2252ee81decSopenharmony_ci    const char *credStr = DslmGetJsonFieldString(handle, FIELD_CRED_INFO);
2262ee81decSopenharmony_ci    if (credStr == NULL) {
2272ee81decSopenharmony_ci        DslmDestroyJson(handle);
2282ee81decSopenharmony_ci        return ERR_NO_CRED;
2292ee81decSopenharmony_ci    }
2302ee81decSopenharmony_ci
2312ee81decSopenharmony_ci    uint8_t *credBuf = NULL;
2322ee81decSopenharmony_ci    uint32_t credLen = (uint32_t)Base64DecodeApp((uint8_t *)credStr, &credBuf);
2332ee81decSopenharmony_ci    if (credBuf == NULL) {
2342ee81decSopenharmony_ci        DslmDestroyJson(handle);
2352ee81decSopenharmony_ci        return ERR_NO_CRED;
2362ee81decSopenharmony_ci    }
2372ee81decSopenharmony_ci
2382ee81decSopenharmony_ci    DslmCredBuff *out = CreateDslmCred((CredType)type, credLen, credBuf);
2392ee81decSopenharmony_ci    if (out == NULL) {
2402ee81decSopenharmony_ci        DslmDestroyJson(handle);
2412ee81decSopenharmony_ci        FREE(credBuf);
2422ee81decSopenharmony_ci        return ERR_NO_MEMORY;
2432ee81decSopenharmony_ci    }
2442ee81decSopenharmony_ci
2452ee81decSopenharmony_ci    DslmDestroyJson(handle);
2462ee81decSopenharmony_ci    FREE(credBuf);
2472ee81decSopenharmony_ci    *version = verNum;
2482ee81decSopenharmony_ci    *challenge = nonceNum;
2492ee81decSopenharmony_ci    *cred = out;
2502ee81decSopenharmony_ci    return SUCCESS;
2512ee81decSopenharmony_ci}
252