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