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_inner_process.h"
17
18#include <stddef.h>
19#include <stdint.h>
20
21#include "device_security_defines.h"
22#include "utils_datetime.h"
23#include "utils_log.h"
24#include "utils_state_machine.h"
25#include "dslm_core_defines.h"
26#include "dslm_credential.h"
27#include "dslm_crypto.h"
28#include "dslm_messenger_wrapper.h"
29#include "dslm_msg_utils.h"
30#include "dslm_cred.h"
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36#define NONCE_ALIVE_TIME 60000
37
38int32_t CheckAndGenerateChallenge(DslmDeviceInfo *device)
39{
40    if (device == NULL) {
41        return ERR_INVALID_PARA;
42    }
43
44    uint64_t curr = GetMillisecondSinceBoot();
45    if ((curr <= device->nonceTimeStamp) || (curr - device->nonceTimeStamp > NONCE_ALIVE_TIME) || device->nonce == 0) {
46        SECURITY_LOG_INFO("update nonce for device %{public}x", device->machine.machineId);
47        RandomValue rand = {0};
48        GenerateRandom(&rand, RANDOM_MAX_LEN);
49        device->nonce = *(uint64_t *)&rand.value[0];
50        device->nonceTimeStamp = curr;
51    }
52
53    return SUCCESS;
54}
55
56int32_t SendDeviceInfoRequest(DslmDeviceInfo *device)
57{
58    if (device == NULL) {
59        return ERR_INVALID_PARA;
60    }
61
62    MessageBuff *buff = NULL;
63    int32_t ret = BuildDeviceSecInfoRequest(device->nonce, &buff);
64    if (ret != SUCCESS) {
65        return ERR_INVALID_PARA;
66    }
67    device->transNum++;
68#ifndef L0_MINI
69    // mini devices are not support yet
70    SendMsgToDevice(device->transNum, &device->identity, buff->buff, buff->length);
71#endif
72    SECURITY_LOG_DEBUG("buff is %s", (char *)buff->buff);
73    SECURITY_LOG_INFO("challenge is %{public}x***, transNum is %{public}u",
74        (uint32_t)device->nonce, (uint32_t)device->transNum);
75    FreeMessageBuff(buff);
76    return SUCCESS;
77}
78
79int32_t VerifyDeviceInfoResponse(DslmDeviceInfo *device, const MessageBuff *buff)
80{
81    if (device == NULL || buff == NULL) {
82        return ERR_INVALID_PARA;
83    }
84
85    DslmCredBuff *cred = NULL;
86    uint64_t nonce = 0;
87    uint32_t version = 0;
88    int32_t ret;
89
90    do {
91        // Parse the msg
92        ret = ParseDeviceSecInfoResponse(buff, &nonce, &version, &cred);
93        if (ret != SUCCESS) {
94            SECURITY_LOG_ERROR("ParseDeviceSecInfoResponse failed, ret is %{public}d", ret);
95            break;
96        }
97        device->version = version;
98        if (nonce != device->nonce || nonce == 0) {
99            ret = ERR_CHALLENGE_ERR;
100            SECURITY_LOG_ERROR("nonce not equal");
101            DestroyDslmCred(cred);
102            break;
103        }
104#ifdef L2_STANDARD
105        uint64_t curr = GetMillisecondSinceBoot();
106        if ((curr <= device->nonceTimeStamp) || (curr - device->nonceTimeStamp > NONCE_ALIVE_TIME)) {
107            ret = ERR_CHALLENGE_ERR;
108            SECURITY_LOG_ERROR("nonce expired");
109            DestroyDslmCred(cred);
110            break;
111        }
112#endif // L2_STANDARD
113        // process
114        ret = DefaultVerifyDslmCred(&device->identity, device->nonce, cred, &device->credInfo);
115        DestroyDslmCred(cred);
116    } while (0);
117
118    SECURITY_LOG_INFO("challenge is %{public}x***, ret is %{public}d", (uint32_t)nonce, ret);
119    return ret;
120}
121
122#ifdef __cplusplus
123}
124#endif
125