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
33 extern "C" {
34 #endif
35 
36 #define NONCE_ALIVE_TIME 60000
37 
CheckAndGenerateChallenge(DslmDeviceInfo * device)38 int32_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 
SendDeviceInfoRequest(DslmDeviceInfo * device)56 int32_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 
VerifyDeviceInfoResponse(DslmDeviceInfo * device,const MessageBuff * buff)79 int32_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