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 <stdbool.h>
19 #include <stdio.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 DslmJsonHandle json = DslmCreateJson(NULL);
41 if (json == NULL) {
42 return ERR_INVALID_PARA;
43 }
44
45 // add challenge
46 DslmAddFieldStringToJson(json, DEVAUTH_JSON_KEY_CHALLENGE, challengeStr);
47
48 // add pkInfoList
49 DslmAddFieldStringToJson(json, DEVAUTH_JSON_KEY_PK_INFO_LIST, pkInfoListStr);
50
51 // tran to json
52 *nonceStr = DslmConvertJsonToString(json);
53 if (*nonceStr == NULL) {
54 DslmDestroyJson(json);
55 return ERR_JSON_ERR;
56 }
57 DslmDestroyJson(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 DslmByteToHexString((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 #ifdef L0_MINI
109 *type = CRED_TYPE_MINI;
110 #else
111 *type = CRED_TYPE_SMALL;
112 #endif
113 } else {
114 *type = CRED_TYPE_STANDARD;
115 }
116 return SUCCESS;
117 }
118
RequestLiteDslmCred(uint32_t credType,uint8_t * data,uint32_t dataLen,DslmCredBuff ** credBuff)119 static int32_t RequestLiteDslmCred(uint32_t credType, uint8_t *data, uint32_t dataLen, DslmCredBuff **credBuff)
120 {
121 DslmCredBuff *out = CreateDslmCred(credType, dataLen, data);
122 if (out == NULL) {
123 SECURITY_LOG_ERROR("CreateDslmCred failed");
124 return ERR_MEMORY_ERR;
125 }
126 *credBuff = out;
127 SECURITY_LOG_INFO("success");
128 return SUCCESS;
129 }
130
RequestStandardDslmCred(const DeviceIdentify * device,const RequestObject * obj,char * credStr,DslmCredBuff ** credBuff)131 static int32_t RequestStandardDslmCred(const DeviceIdentify *device, const RequestObject *obj, char *credStr,
132 DslmCredBuff **credBuff)
133 {
134 uint8_t *certChain = NULL;
135 uint32_t certChainLen = 0;
136 int32_t ret = GenerateDslmCertChain(device, obj, credStr, &certChain, &certChainLen);
137 if (ret != SUCCESS) {
138 SECURITY_LOG_ERROR("GenerateDslmCertChain failed");
139 return ret;
140 }
141 DslmCredBuff *out = CreateDslmCred(CRED_TYPE_STANDARD, certChainLen, certChain);
142 if (out == NULL) {
143 FREE(certChain);
144 SECURITY_LOG_ERROR("CreateDslmCred failed");
145 return ERR_MEMORY_ERR;
146 }
147 FREE(certChain);
148 *credBuff = out;
149 SECURITY_LOG_INFO("success");
150 return SUCCESS;
151 }
152
153 #ifndef L0_MINI
GetCredFromCurrentDevice(char * credStr,uint32_t maxLen)154 int32_t GetCredFromCurrentDevice(char *credStr, uint32_t maxLen)
155 {
156 if (credStr == NULL || maxLen == 0) {
157 return ERR_INVALID_PARA;
158 }
159 FILE *fp = NULL;
160 fp = fopen(DSLM_CRED_CFG_FILE_POSITION, "r");
161 if (fp == NULL) {
162 SECURITY_LOG_ERROR("fopen cred file failed");
163 return ERR_INVALID_PARA;
164 }
165
166 int32_t ret = fscanf_s(fp, "%s", credStr, maxLen);
167 if (ret <= 0) {
168 SECURITY_LOG_ERROR("fscanf_s cred file failed");
169 ret = ERR_INVALID_PARA;
170 } else {
171 ret = SUCCESS;
172 }
173
174 if (fclose(fp) != 0) {
175 SECURITY_LOG_ERROR("fclose cred file failed");
176 ret = ERR_INVALID_PARA;
177 }
178 return ret;
179 }
180 #else
GetCredFromCurrentDevice(char * credStr,uint32_t maxLen)181 int32_t GetCredFromCurrentDevice(char *credStr, uint32_t maxLen)
182 {
183 if (credStr == NULL || maxLen == 0) {
184 return ERR_INVALID_PARA;
185 }
186 const char cred[] =
187 "eyJ0eXAiOiAiRFNMIn0=."
188 "eyJ0eXBlIjogImRlYnVnIiwgIm1hbnVmYWN0dXJlIjogIk9IT1MiLCAiYnJhbmQiOiAiT0hPUyIsICJtb2RlbCI6ICJPSE9TIiwgInNvZnR3YX"
189 "JlVmVyc2lvbiI6ICIzLjAuMCIsICJzZWN1cml0eUxldmVsIjogIlNMMSIsICJzaWduVGltZSI6ICIyMDIyMDgyMjExNTcyMCIsICJ2ZXJzaW9u"
190 "IjogIjEuMC4xIn0=.MGQCMFxmouOZBmCbs4d0RvTdWOYwSsXyDwwbaNXNMadroqmACGdXMYyC0J0/uza9BBkR/"
191 "gIwB5Zumkm4EhfvHocEWj4gW+aDcanBMIA73onLZBYqVOseXaMjz9O//"
192 "HOXN7Y6r0T0."
193 "W3sidXNlclB1YmxpY0tleSI6ICJNSG93RkFZSEtvWkl6ajBDQVFZSkt5UURBd0lJQVFFTEEySUFCR3VNaFVGRm5sUGtVd013dDhpQ3JPRUdEL0"
194 "xRaU1FMmZ6TE0rc2RaRXhJOWQxN0RsWGhJU2YrWnRzeFROVDR0NDNDSW1YbTltenJMOTVtOCtKWEJZSGgza0lTZElnZHAxdVRmbEZIVjBYZm1p"
195 "YngrMlRMTG5QY3VXMFBWTXhKODZnPT0iLCAic2lnbmF0dXJlIjogIk1HUUNNQ0Z4VGxldjhXVjZkNktueFpya3pRbGY3SE85Tm1Ua3NXeTV4aF"
196 "VOcjlMamlMcnU3dEY1emYrMEJZeG52WXgybVFJd2NhenVtd0dsaGxORHgrZHJ0Z0JzSHFLckdqcWRENDNTbDkzR3B3NE83Uk5RUzJQdng4SmtK"
197 "YnRFVWVyZHYvNVMifSwgeyJ1c2VyUHVibGljS2V5IjogIk1Ib3dGQVlIS29aSXpqMENBUVlKS3lRREF3SUlBUUVMQTJJQUJFQkFGWTkrM0RaTH"
198 "M4TnRaRHVsZHRwQmp1alB2d2llUDlUdk1PWFZrNWZ2SkhFUXY2WERlbEdPNGRnUVozNlVKQ2lVd1UyL3JLckNrenFvS0ttaXNNa0Y2aFFnblZF"
199 "Z3l3a3haV24zaHFjengzcDdzamF2S3lSYnRXVW5XdmtTV2c9PSIsICJzaWduYXR1cmUiOiAiTUdRQ01GU2JHMzdMc0dzRkpLZ1lDVUR0S3BtQ3"
200 "FVRHc1ck1MVkhjQ3ZtaDVhcVhrQmQ2RzlzUDZGd0RqbmdYeEtsQ1RMZ0l3ZHV4dEg0YUQ5RjN3T0tQNnZJM1FvcVNneWJIMkZjdytFY3o2Mk03"
201 "T0RtN0p3RWRmZXowSkJ1Y0dKM0hKZXVVVyJ9LCB7InVzZXJQdWJsaWNLZXkiOiAiTUhvd0ZBWUhLb1pJemowQ0FRWUpLeVFEQXdJSUFRRUxBMk"
202 "lBQkRFMHNPMUVWcXViUHMxbDNadmpBTE5xRkcrUlBIei9NK3RPeUN6cTJuNUFNRnUrMWxsUEFhVEdYYzQwTy9uTGluei84emZaNHREQWlUb3NB"
203 "UmlKK20zckVWTUZrQitmbnh5SEFDc2UrYWpHdmZxZ2F2ajlGTXNIYjJMRVpQZmkrdz09IiwgInNpZ25hdHVyZSI6ICJNR01DTUV0dDc1VG0wUm"
204 "dtYlkvb2Vpb0Y3cHc2K28vZEJmWTFCVVR0RHlVbjFyWjltTW1NWGxyQ0ovaGFTc25oSG12d2h3SXZmYTBTZ0gzWENBbURUWm0xMnpTUHc4b1lI"
205 "L3QvNXF0S0tHdlpFZWJmSldIQVE5MFpnblhUdWNOR0FQY05BOEk9In1d";
206 int32_t ret = sscanf_s(cred, "%s", credStr, maxLen);
207 if (ret <= 0) {
208 SECURITY_LOG_ERROR("sscanf_s cred file failed, ret = %d", ret);
209 ret = ERR_INVALID_PARA;
210 } else {
211 ret = SUCCESS;
212 }
213 return ret;
214 }
215 #endif
216
RequestOhosDslmCred(const DeviceIdentify * device,const RequestObject * obj,DslmCredBuff ** credBuff)217 int32_t RequestOhosDslmCred(const DeviceIdentify *device, const RequestObject *obj, DslmCredBuff **credBuff)
218 {
219 SECURITY_LOG_INFO("start");
220 uint32_t credType = 0;
221 char credStr[DSLM_CRED_STR_LEN_MAX] = {0};
222 int32_t ret = GetCredFromCurrentDevice(credStr, DSLM_CRED_STR_LEN_MAX);
223 if (ret != SUCCESS) {
224 SECURITY_LOG_ERROR("read cred data from file failed");
225 return ret;
226 }
227 ret = SelectDslmCredType(device, obj, &credType);
228 if (ret != SUCCESS) {
229 SECURITY_LOG_ERROR("SelectDslmCredType failed");
230 return ret;
231 }
232 switch (credType) {
233 case CRED_TYPE_STANDARD:
234 return RequestStandardDslmCred(device, obj, credStr, credBuff);
235 case CRED_TYPE_SMALL:
236 case CRED_TYPE_MINI:
237 return RequestLiteDslmCred(credType, (uint8_t *)credStr, strlen(credStr) + 1, credBuff);
238 default:
239 SECURITY_LOG_ERROR("invalid cred type");
240 return ERR_INVALID_PARA;
241 }
242
243 return SUCCESS;
244 }
245