1 /*
2  * Copyright (c) 2023-2024 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 "napi_x509_cert_match_parameters.h"
17 
18 #include "cf_log.h"
19 #include "cf_memory.h"
20 #include "cf_type.h"
21 #include "napi/native_api.h"
22 #include "napi/native_common.h"
23 #include "napi_cert_defines.h"
24 #include "napi_cert_utils.h"
25 #include "napi_object.h"
26 #include "napi_x509_certificate.h"
27 #include "utils.h"
28 
29 namespace OHOS {
30 namespace CertFramework {
31 
GetValidDate(napi_env env,napi_value arg,CfBlob * & out)32 static bool GetValidDate(napi_env env, napi_value arg, CfBlob *&out)
33 {
34     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_VALID_DATE.c_str());
35     if (obj == nullptr) {
36         return true;
37     }
38 
39     out = CertGetBlobFromStringJSParams(env, obj);
40     if (out == nullptr) {
41         LOGE("out is nullptr");
42         return false;
43     }
44     return true;
45 }
46 
GetIssuer(napi_env env,napi_value arg,CfBlob * & out)47 static bool GetIssuer(napi_env env, napi_value arg, CfBlob *&out)
48 {
49     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_ISSUER.c_str());
50     if (obj == nullptr) {
51         return true;
52     }
53     out = CertGetBlobFromUint8ArrJSParams(env, obj);
54     if (out == nullptr) {
55         LOGE("out is nullptr");
56         return false;
57     }
58     return true;
59 }
60 
GetKeyUsage(napi_env env,napi_value arg,CfBlob * & out)61 static bool GetKeyUsage(napi_env env, napi_value arg, CfBlob *&out)
62 {
63     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_KEY_USAGE.c_str());
64     if (obj == nullptr) {
65         return true;
66     }
67     out = CertGetBlobFromArrBoolJSParams(env, obj);
68     if (out == nullptr) {
69         LOGE("out is nullptr");
70         return false;
71     }
72     return true;
73 }
74 
GetSerialNumber(napi_env env,napi_value arg,CfBlob * & out)75 static bool GetSerialNumber(napi_env env, napi_value arg, CfBlob *&out)
76 {
77     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_SERIAL_NUMBER.c_str());
78     if (obj == nullptr) {
79         return true;
80     }
81     CfBlob outBlob = { 0, nullptr };
82     bool flag = CertGetSerialNumberFromBigIntJSParams(env, obj, outBlob);
83     if (!flag || outBlob.data == nullptr || outBlob.size == 0) {
84         LOGE("out is nullptr");
85         return false;
86     }
87     out = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
88     if (out == nullptr) {
89         LOGE("Failed to allocate newBlob memory!");
90         CfBlobDataFree(&outBlob);
91         return false;
92     }
93     out->data = outBlob.data;
94     out->size = outBlob.size;
95     return true;
96 }
97 
GetSubject(napi_env env,napi_value arg,CfBlob * & out)98 static bool GetSubject(napi_env env, napi_value arg, CfBlob *&out)
99 {
100     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_SUBJECT.c_str());
101     if (obj == nullptr) {
102         return true;
103     }
104     out = CertGetBlobFromUint8ArrJSParams(env, obj);
105     if (out == nullptr) {
106         LOGE("out is nullptr");
107         return false;
108     }
109     return true;
110 }
111 
GetPublicKey(napi_env env,napi_value arg,CfBlob * & out)112 static bool GetPublicKey(napi_env env, napi_value arg, CfBlob *&out)
113 {
114     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_PUBLIC_KEY.c_str());
115     if (obj == nullptr) {
116         return true;
117     }
118     out = CertGetBlobFromNapiValue(env, obj);
119     if (out == nullptr) {
120         LOGE("out is nullptr");
121         return false;
122     }
123     return true;
124 }
125 
GetPublicKeyAlgId(napi_env env,napi_value arg,CfBlob * & out)126 static bool GetPublicKeyAlgId(napi_env env, napi_value arg, CfBlob *&out)
127 {
128     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_PUBLIC_KEY_ALGID.c_str());
129     if (obj == nullptr) {
130         return true;
131     }
132     out = CertGetBlobFromStringJSParams(env, obj);
133     if (out == nullptr) {
134         LOGE("out is nullptr");
135         return false;
136     }
137     return true;
138 }
139 
GetX509Cert(napi_env env,napi_value arg,HcfCertificate * & out)140 static bool GetX509Cert(napi_env env, napi_value arg, HcfCertificate *&out)
141 {
142     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_X509CERT.c_str());
143     if (obj == nullptr) {
144         return true;
145     }
146     NapiX509Certificate *napiX509Cert = nullptr;
147     napi_unwrap(env, obj, reinterpret_cast<void **>(&napiX509Cert));
148     if (napiX509Cert == nullptr) {
149         LOGE("napiX509Cert is null!");
150         return false;
151     }
152 
153     HcfX509Certificate *cert = napiX509Cert->GetX509Cert();
154     if (cert == nullptr) {
155         LOGE("cert is null!");
156         return false;
157     }
158     out = &(cert->base);
159     return true;
160 }
161 
GetSubjectAltNamesArray(napi_env env,napi_value arg,SubAltNameArray * & out)162 static bool GetSubjectAltNamesArray(napi_env env, napi_value arg, SubAltNameArray *&out)
163 {
164     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_SUBJECT_ALT_NAMES.c_str());
165     if (obj == nullptr) {
166         return true;
167     }
168     out = CertGetSANArrFromArrUarrJSParams(env, obj);
169     if (out == nullptr) {
170         LOGE("Failed to get subject alternative name array!");
171         return false;
172     }
173     return true;
174 }
175 
GetMatchAllSubjectAltNames(napi_env env,napi_value arg,bool & out)176 static bool GetMatchAllSubjectAltNames(napi_env env, napi_value arg, bool &out)
177 {
178     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_MATCH_ALL_SUBJECT.c_str());
179     if (obj == nullptr) {
180         return true;
181     }
182 
183     napi_valuetype valueType;
184     napi_typeof(env, obj, &valueType);
185     if (valueType != napi_boolean) {
186         LOGE("Get %s obj is not bool!", CERT_MATCH_TAG_MATCH_ALL_SUBJECT.c_str());
187         return false;
188     }
189 
190     napi_status status = napi_get_value_bool(env, obj, &out);
191     if (status != napi_ok) {
192         LOGE("Failed to get value bool!");
193         return false;
194     }
195     return true;
196 }
197 
GetAuthorityKeyIdentifier(napi_env env,napi_value arg,CfBlob * & out)198 static bool GetAuthorityKeyIdentifier(napi_env env, napi_value arg, CfBlob *&out)
199 {
200     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_AUTH_KEY_ID.c_str());
201     if (obj == nullptr) {
202         return true;
203     }
204     out = CertGetBlobFromUint8ArrJSParams(env, obj);
205     if (out == nullptr) {
206         LOGE("Out is nullptr");
207         return false;
208     }
209     return true;
210 }
211 
GetMinPathLenConstraint(napi_env env,napi_value arg,int32_t & out)212 static bool GetMinPathLenConstraint(napi_env env, napi_value arg, int32_t &out)
213 {
214     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_MIN_PATH_LEN.c_str());
215     if (obj == nullptr) {
216         out = -1; // default value
217         return true;
218     }
219     napi_status status = napi_get_value_int32(env, obj, &out);
220     if (status != napi_ok) {
221         LOGE("Failed to get value int32!");
222         return false;
223     }
224     return true;
225 }
226 
GetExtendedKeyUsage(napi_env env,napi_value arg,CfArray * & out)227 static bool GetExtendedKeyUsage(napi_env env, napi_value arg, CfArray *&out)
228 {
229     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_EXTENDED_KEY_USAGE.c_str());
230     if (obj == nullptr) {
231         return true;
232     }
233     out = CertGetArrFromArrUarrJSParams(env, obj);
234     if (out == nullptr) {
235         LOGE("Out is nullptr");
236         return false;
237     }
238     return true;
239 }
240 
GetNameConstraints(napi_env env,napi_value arg,CfBlob * & out)241 static bool GetNameConstraints(napi_env env, napi_value arg, CfBlob *&out)
242 {
243     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_NAME_CONSTRAINTS.c_str());
244     if (obj == nullptr) {
245         return true;
246     }
247     out = CertGetBlobFromUint8ArrJSParams(env, obj);
248     if (out == nullptr) {
249         LOGE("Out is nullptr");
250         return false;
251     }
252     return true;
253 }
254 
GetCertPolicy(napi_env env,napi_value arg,CfArray * & out)255 static bool GetCertPolicy(napi_env env, napi_value arg, CfArray *&out)
256 {
257     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_CERT_POLICY.c_str());
258     if (obj == nullptr) {
259         return true;
260     }
261     out = CertGetArrFromArrUarrJSParams(env, obj);
262     if (out == nullptr) {
263         LOGE("Out is nullptr");
264         return false;
265     }
266     return true;
267 }
268 
GetPrivateKeyValid(napi_env env,napi_value arg,CfBlob * & out)269 static bool GetPrivateKeyValid(napi_env env, napi_value arg, CfBlob *&out)
270 {
271     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_PRIVATE_KEY_VALID.c_str());
272     if (obj == nullptr) {
273         return true;
274     }
275 
276     out = CertGetBlobFromStringJSParams(env, obj);
277     if (out == nullptr) {
278         LOGE("Out is nullptr");
279         return false;
280     }
281     return true;
282 }
283 
GetSubjectKeyIdentifier(napi_env env,napi_value arg,CfBlob * & out)284 static bool GetSubjectKeyIdentifier(napi_env env, napi_value arg, CfBlob *&out)
285 {
286     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_SUBJECT_KEY_IDENTIFIER.c_str());
287     if (obj == nullptr) {
288         return true;
289     }
290     out = CertGetBlobFromUint8ArrJSParams(env, obj);
291     if (out == nullptr) {
292         LOGE("Out is nullptr.");
293         return false;
294     }
295     return true;
296 }
297 
BuildX509CertMatchParamsV1(napi_env env,napi_value arg,HcfX509CertMatchParams * & matchParams)298 bool BuildX509CertMatchParamsV1(napi_env env, napi_value arg, HcfX509CertMatchParams *&matchParams)
299 {
300     napi_valuetype type;
301     napi_typeof(env, arg, &type);
302     if (type != napi_object) {
303         LOGE("Wrong argument type. expect object type. [Type]: %d", type);
304         return false;
305     }
306     if (!GetValidDate(env, arg, matchParams->validDate)) {
307         return false;
308     }
309     if (!GetIssuer(env, arg, matchParams->issuer)) {
310         return false;
311     }
312     if (!GetKeyUsage(env, arg, matchParams->keyUsage)) {
313         return false;
314     }
315     if (!GetSerialNumber(env, arg, matchParams->serialNumber)) {
316         return false;
317     }
318     if (!GetSubject(env, arg, matchParams->subject)) {
319         return false;
320     }
321     if (!GetPublicKey(env, arg, matchParams->publicKey)) {
322         return false;
323     }
324     if (!GetPublicKeyAlgId(env, arg, matchParams->publicKeyAlgID)) {
325         return false;
326     }
327     if (!GetX509Cert(env, arg, matchParams->x509Cert)) {
328         return false;
329     }
330     return true;
331 }
332 
BuildX509CertMatchParamsV2(napi_env env,napi_value arg,HcfX509CertMatchParams * & matchParams)333 bool BuildX509CertMatchParamsV2(napi_env env, napi_value arg, HcfX509CertMatchParams *&matchParams)
334 {
335     napi_valuetype type;
336     napi_typeof(env, arg, &type);
337     if (type != napi_object) {
338         LOGE("Wrong argument type. expect object type. [Type]: %d", type);
339         return false;
340     }
341     if (!GetSubjectAltNamesArray(env, arg, matchParams->subjectAlternativeNames)) {
342         return false;
343     }
344     if (!GetMatchAllSubjectAltNames(env, arg, matchParams->matchAllSubjectAltNames)) {
345         return false;
346     }
347     if (!GetAuthorityKeyIdentifier(env, arg, matchParams->authorityKeyIdentifier)) {
348         return false;
349     }
350     if (!GetMinPathLenConstraint(env, arg, matchParams->minPathLenConstraint)) {
351         return false;
352     }
353     if (!GetExtendedKeyUsage(env, arg, matchParams->extendedKeyUsage)) {
354         return false;
355     }
356     if (!GetNameConstraints(env, arg, matchParams->nameConstraints)) {
357         return false;
358     }
359     if (!GetCertPolicy(env, arg, matchParams->certPolicy)) {
360         return false;
361     }
362     if (!GetPrivateKeyValid(env, arg, matchParams->privateKeyValid)) {
363         return false;
364     }
365     if (!GetSubjectKeyIdentifier(env, arg, matchParams->subjectKeyIdentifier)) {
366         return false;
367     }
368     return true;
369 }
370 
BuildX509CertMatchParams(napi_env env,napi_value arg,HcfX509CertMatchParams * & matchParams)371 bool BuildX509CertMatchParams(napi_env env, napi_value arg, HcfX509CertMatchParams *&matchParams)
372 {
373     napi_valuetype type;
374     napi_typeof(env, arg, &type);
375     if (type != napi_object) {
376         LOGE("wrong argument type. expect object type. [Type]: %d", type);
377         return false;
378     }
379     if (!BuildX509CertMatchParamsV1(env, arg, matchParams)) {
380         return false;
381     }
382     if (!BuildX509CertMatchParamsV2(env, arg, matchParams)) {
383         return false;
384     }
385 
386     return true;
387 }
388 
FreeX509CertMatchParams(HcfX509CertMatchParams * & matchParams)389 void FreeX509CertMatchParams(HcfX509CertMatchParams *&matchParams)
390 {
391     if (matchParams == nullptr) {
392         return;
393     }
394 
395     matchParams->x509Cert = nullptr;
396     CfBlobFree(&matchParams->validDate);
397     CfBlobFree(&matchParams->issuer);
398     CfBlobFree(&matchParams->keyUsage);
399     CfBlobFree(&matchParams->serialNumber);
400     CfBlobFree(&matchParams->subject);
401     CfBlobFree(&matchParams->publicKey);
402     CfBlobFree(&matchParams->publicKeyAlgID);
403     CfBlobFree(&matchParams->authorityKeyIdentifier);
404     CfBlobFree(&matchParams->nameConstraints);
405     CfBlobFree(&matchParams->privateKeyValid);
406     CfBlobFree(&matchParams->subjectKeyIdentifier);
407     CfArrayDataClearAndFree(matchParams->certPolicy);
408     CfArrayDataClearAndFree(matchParams->extendedKeyUsage);
409     CfFree(matchParams->certPolicy);
410     CfFree(matchParams->extendedKeyUsage);
411     if (matchParams->subjectAlternativeNames != nullptr) {
412         for (uint32_t i = 0; i < matchParams->subjectAlternativeNames->count; ++i) {
413             if (matchParams->subjectAlternativeNames->data != nullptr) {
414                 CF_FREE_BLOB(matchParams->subjectAlternativeNames->data[i].name);
415             }
416         }
417         CfFree(matchParams->subjectAlternativeNames->data);
418         CfFree(matchParams->subjectAlternativeNames);
419     }
420 
421     CF_FREE_PTR(matchParams);
422 }
423 
424 } // namespace CertFramework
425 } // namespace OHOS
426