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_ohos_request.h"
17
18 #include <stdio.h>
19 #include <stdbool.h>
20 #include <string.h>
21
22 #include "securec.h"
23
24 #include "external_interface_adapter.h"
25 #include "utils_hexstring.h"
26 #include "utils_json.h"
27 #include "utils_log.h"
28 #include "utils_mem.h"
29
30 #define DSLM_CRED_CFG_FILE_POSITION "/system/etc/dslm_finger.cfg"
31 #define DSLM_CRED_STR_LEN_MAX 4096
32 #define CHALLENGE_STRING_LENGTH 32
33 #define UDID_STRING_LENGTH 65
34
35 #define DEVAUTH_JSON_KEY_CHALLENGE "challenge"
36 #define DEVAUTH_JSON_KEY_PK_INFO_LIST "pkInfoList"
37
TransToJsonStr(const char * challengeStr,const char * pkInfoListStr,char ** nonceStr)38 static int32_t TransToJsonStr(const char *challengeStr, const char *pkInfoListStr, char **nonceStr)
39 {
40 JsonHandle json = CreateJson(NULL);
41 if (json == NULL) {
42 return ERR_INVALID_PARA;
43 }
44
45 // add challenge
46 AddFieldStringToJson(json, DEVAUTH_JSON_KEY_CHALLENGE, challengeStr);
47
48 // add pkInfoList
49 AddFieldStringToJson(json, DEVAUTH_JSON_KEY_PK_INFO_LIST, pkInfoListStr);
50
51 // tran to json
52 *nonceStr = ConvertJsonToString(json);
53 if (*nonceStr == NULL) {
54 DestroyJson(json);
55 return ERR_JSON_ERR;
56 }
57 DestroyJson(json);
58 return SUCCESS;
59 }
60
GenerateDslmCertChain(const DeviceIdentify * device,const RequestObject * obj,char * credStr,uint8_t ** certChain,uint32_t * certChainLen)61 static int32_t GenerateDslmCertChain(const DeviceIdentify *device, const RequestObject *obj, char *credStr,
62 uint8_t **certChain, uint32_t *certChainLen)
63 {
64 char *pkInfoListStr = NULL;
65 char *nonceStr = NULL;
66 char challengeStr[CHALLENGE_STRING_LENGTH] = {0};
67 ByteToHexString((uint8_t *)&(obj->challenge), sizeof(obj->challenge), (uint8_t *)challengeStr,
68 CHALLENGE_STRING_LENGTH);
69 char udidStr[UDID_STRING_LENGTH] = {0};
70 if (memcpy_s(udidStr, UDID_STRING_LENGTH, device->identity, device->length) != EOK) {
71 return ERR_MEMORY_ERR;
72 }
73 int32_t ret = ERR_DEFAULT;
74 do {
75 ret = GetPkInfoListStr(true, udidStr, &pkInfoListStr);
76 if (ret != SUCCESS) {
77 SECURITY_LOG_ERROR("GetPkInfoListStr failed");
78 break;
79 }
80
81 ret = TransToJsonStr(challengeStr, pkInfoListStr, &nonceStr);
82 if (ret != SUCCESS) {
83 SECURITY_LOG_ERROR("TransToJsonStr failed");
84 break;
85 }
86 struct DslmInfoInCertChain saveInfo = {.credStr = credStr, .nonceStr = nonceStr, .udidStr = udidStr};
87 ret = DslmCredAttestAdapter(&saveInfo, certChain, certChainLen);
88 if (ret != SUCCESS) {
89 SECURITY_LOG_ERROR("DslmCredAttestAdapter failed");
90 break;
91 }
92 } while (0);
93
94 if (pkInfoListStr != NULL) {
95 FREE(pkInfoListStr);
96 }
97 if (nonceStr != NULL) {
98 FREE(nonceStr);
99 }
100 return ret;
101 }
102
SelectDslmCredType(const DeviceIdentify * device,const RequestObject * obj,uint32_t * type)103 static int32_t SelectDslmCredType(const DeviceIdentify *device, const RequestObject *obj, uint32_t *type)
104 {
105 (void)device;
106 (void)obj;
107 if (HksAttestIsReadyAdapter() != SUCCESS) {
108 *type = CRED_TYPE_SMALL;
109 } else {
110 *type = CRED_TYPE_STANDARD;
111 }
112 return SUCCESS;
113 }
114
RequestSmallDslmCred(uint8_t * data,uint32_t dataLen,DslmCredBuff ** credBuff)115 static int32_t RequestSmallDslmCred(uint8_t *data, uint32_t dataLen, DslmCredBuff **credBuff)
116 {
117 DslmCredBuff *out = CreateDslmCred(CRED_TYPE_SMALL, dataLen, data);
118 if (out == NULL) {
119 SECURITY_LOG_ERROR("CreateDslmCred failed");
120 return ERR_MEMORY_ERR;
121 }
122 *credBuff = out;
123 SECURITY_LOG_INFO("success");
124 return SUCCESS;
125 }
126
RequestStandardDslmCred(const DeviceIdentify * device,const RequestObject * obj,char * credStr,DslmCredBuff ** credBuff)127 static int32_t RequestStandardDslmCred(const DeviceIdentify *device, const RequestObject *obj, char *credStr,
128 DslmCredBuff **credBuff)
129 {
130 uint8_t *certChain = NULL;
131 uint32_t certChainLen = 0;
132 int32_t ret = GenerateDslmCertChain(device, obj, credStr, &certChain, &certChainLen);
133 if (ret != SUCCESS) {
134 SECURITY_LOG_ERROR("GenerateDslmCertChain failed");
135 return ret;
136 }
137 DslmCredBuff *out = CreateDslmCred(CRED_TYPE_STANDARD, certChainLen, certChain);
138 if (out == NULL) {
139 FREE(certChain);
140 SECURITY_LOG_ERROR("CreateDslmCred failed");
141 return ERR_MEMORY_ERR;
142 }
143 FREE(certChain);
144 *credBuff = out;
145 SECURITY_LOG_INFO("success");
146 return SUCCESS;
147 }
148
GetCredFromCurrentDevice(char * credStr,uint32_t maxLen)149 int32_t GetCredFromCurrentDevice(char *credStr, uint32_t maxLen)
150 {
151 if (credStr == NULL || maxLen == 0) {
152 return ERR_INVALID_PARA;
153 }
154 FILE *fp = NULL;
155 fp = fopen(DSLM_CRED_CFG_FILE_POSITION, "r");
156 if (fp == NULL) {
157 SECURITY_LOG_ERROR("fopen cred file failed");
158 return ERR_INVALID_PARA;
159 }
160 int32_t ret = fscanf_s(fp, "%s", credStr, maxLen);
161 if (ret <= 0) {
162 SECURITY_LOG_ERROR("fscanf_s cred file failed");
163 ret = ERR_INVALID_PARA;
164 } else {
165 ret = SUCCESS;
166 }
167 if (fclose(fp) != 0) {
168 SECURITY_LOG_ERROR("fclose cred file failed");
169 ret = ERR_INVALID_PARA;
170 }
171 return ret;
172 }
173
RequestOhosDslmCred(const DeviceIdentify * device,const RequestObject * obj,DslmCredBuff ** credBuff)174 int32_t RequestOhosDslmCred(const DeviceIdentify *device, const RequestObject *obj, DslmCredBuff **credBuff)
175 {
176 SECURITY_LOG_INFO("start");
177 uint32_t credType = 0;
178 char credStr[DSLM_CRED_STR_LEN_MAX] = {0};
179 int32_t ret = GetCredFromCurrentDevice(credStr, DSLM_CRED_STR_LEN_MAX);
180 if (ret != SUCCESS) {
181 SECURITY_LOG_ERROR("read cred data from file failed");
182 return ret;
183 }
184 ret = SelectDslmCredType(device, obj, &credType);
185 if (ret != SUCCESS) {
186 SECURITY_LOG_ERROR("SelectDslmCredType failed");
187 return ret;
188 }
189 switch (credType) {
190 case CRED_TYPE_SMALL:
191 return RequestSmallDslmCred((uint8_t *)credStr, strlen(credStr) + 1, credBuff);
192 case CRED_TYPE_STANDARD:
193 return RequestStandardDslmCred(device, obj, credStr, credBuff);
194 default:
195 SECURITY_LOG_ERROR("invalid cred type");
196 return ERR_INVALID_PARA;
197 }
198
199 return SUCCESS;
200 }
201