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_trust_anchor.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_crl_common.h"
24 #include "napi_cert_defines.h"
25 #include "napi_cert_utils.h"
26 #include "napi_object.h"
27 #include "napi_x509_certificate.h"
28 #include "utils.h"
29 
30 namespace OHOS {
31 namespace CertFramework {
32 
GetCACert(napi_env env,napi_value arg,HcfX509Certificate * & out)33 static bool GetCACert(napi_env env, napi_value arg, HcfX509Certificate *&out)
34 {
35     napi_value obj = GetProp(env, arg, CERT_CHAIN_TRUSTANCHOR_TAG_CACERT.c_str());
36     if (obj == nullptr) {
37         return true;
38     }
39     NapiX509Certificate *napiX509Cert = nullptr;
40     napi_unwrap(env, obj, reinterpret_cast<void **>(&napiX509Cert));
41     if (napiX509Cert == nullptr) {
42         LOGE("napiX509Cert is null!");
43         return false;
44     }
45 
46     out = napiX509Cert->GetX509Cert();
47     if (out == nullptr) {
48         LOGE("out is null!");
49         return false;
50     }
51     return true;
52 }
53 
GetCASubject(napi_env env,napi_value arg,CfBlob * & out)54 static bool GetCASubject(napi_env env, napi_value arg, CfBlob *&out)
55 {
56     napi_value obj = GetProp(env, arg, CERT_CHAIN_TRUSTANCHOR_TAG_CASUBJECT.c_str());
57     if (obj == nullptr) {
58         return true;
59     }
60     out = CertGetBlobFromUint8ArrJSParams(env, obj);
61     if (out == nullptr) {
62         LOGE("out is null!");
63         return false;
64     }
65     return true;
66 }
67 
GetNameConstraints(napi_env env,napi_value arg,CfBlob * & out)68 static bool GetNameConstraints(napi_env env, napi_value arg, CfBlob *&out)
69 {
70     napi_value obj = GetProp(env, arg, CERT_MATCH_TAG_NAME_CONSTRAINTS.c_str());
71     if (obj == nullptr) {
72         return true;
73     }
74     out = CertGetBlobFromUint8ArrJSParams(env, obj);
75     if (out == nullptr) {
76         LOGE("out is null!");
77         return false;
78     }
79     return true;
80 }
81 
GetCAPubKey(napi_env env,napi_value arg,CfBlob * & out)82 static bool GetCAPubKey(napi_env env, napi_value arg, CfBlob *&out)
83 {
84     napi_value obj = GetProp(env, arg, CERT_CHAIN_TRUSTANCHOR_TAG_CAPUBKEY.c_str());
85     if (obj == nullptr) {
86         return true;
87     }
88     out = CertGetBlobFromUint8ArrJSParams(env, obj);
89     if (out == nullptr) {
90         LOGE("out is null!");
91         return false;
92     }
93     return true;
94 }
95 
BuildX509TrustAnchorJS(napi_env env,const HcfX509TrustAnchor * trustAnchor)96 napi_value BuildX509TrustAnchorJS(napi_env env, const HcfX509TrustAnchor *trustAnchor)
97 {
98     if (trustAnchor == nullptr) {
99         LOGE("input param invalid!");
100         return nullptr;
101     }
102     napi_value instance = nullptr;
103     napi_create_object(env, &instance);
104     if (trustAnchor->CAPubKey != nullptr) {
105         napi_value CAPubKey = ConvertBlobToUint8ArrNapiValue(env, trustAnchor->CAPubKey);
106         if (CAPubKey == nullptr) {
107             LOGE("CA pub key convert failed!");
108             return nullptr;
109         }
110         napi_set_named_property(env, instance, CERT_CHAIN_TRUSTANCHOR_TAG_CAPUBKEY.c_str(), CAPubKey);
111     }
112 
113     if (trustAnchor->CASubject != nullptr) {
114         napi_value CASubject = ConvertBlobToUint8ArrNapiValue(env, trustAnchor->CASubject);
115         if (CASubject == nullptr) {
116             LOGE("CA subject convert failed!");
117             return nullptr;
118         }
119         napi_set_named_property(env, instance, CERT_CHAIN_TRUSTANCHOR_TAG_CASUBJECT.c_str(), CASubject);
120     }
121 
122     if (trustAnchor->CACert != nullptr) {
123         napi_value CACert = ConvertCertToNapiValue(env, trustAnchor->CACert);
124         if (CACert == nullptr) {
125             LOGE("CA cert convert failed!");
126             return nullptr;
127         }
128         napi_set_named_property(env, instance, CERT_CHAIN_TRUSTANCHOR_TAG_CACERT.c_str(), CACert);
129     }
130 
131     if (trustAnchor->nameConstraints != nullptr) {
132         napi_value nameConstraints = ConvertBlobToUint8ArrNapiValue(env, trustAnchor->nameConstraints);
133         if (nameConstraints == nullptr) {
134             LOGE("Name constraints convert failed!");
135             return nullptr;
136         }
137         napi_set_named_property(env, instance, CERT_MATCH_TAG_NAME_CONSTRAINTS.c_str(), nameConstraints);
138     }
139 
140     return instance;
141 }
142 
BuildX509TrustAnchorObj(napi_env env,napi_value arg,HcfX509TrustAnchor * & trustAnchor)143 bool BuildX509TrustAnchorObj(napi_env env, napi_value arg, HcfX509TrustAnchor *&trustAnchor)
144 {
145     napi_valuetype type;
146     napi_typeof(env, arg, &type);
147     if (type != napi_object) {
148         LOGE("wrong argument type. expect string type. [Type]: %d", type);
149         return false;
150     }
151     trustAnchor = static_cast<HcfX509TrustAnchor *>(CfMalloc(sizeof(HcfX509TrustAnchor), 0));
152     if (trustAnchor == nullptr) {
153         LOGE("Failed to allocate data memory!");
154         return false;
155     }
156 
157     if (!GetCAPubKey(env, arg, trustAnchor->CAPubKey)) {
158         FreeX509TrustAnchorObj(trustAnchor);
159         return false;
160     }
161     if (!GetCACert(env, arg, trustAnchor->CACert)) {
162         FreeX509TrustAnchorObj(trustAnchor);
163         return false;
164     }
165     if (!GetCASubject(env, arg, trustAnchor->CASubject)) {
166         FreeX509TrustAnchorObj(trustAnchor);
167         return false;
168     }
169     if (!GetNameConstraints(env, arg, trustAnchor->nameConstraints)) {
170         FreeX509TrustAnchorObj(trustAnchor);
171         return false;
172     }
173     return true;
174 }
175 
176 /* [freeCertFlag] : if building a obj for RETURN failed, the cert object need to free manually. */
FreeX509TrustAnchorObj(HcfX509TrustAnchor * & trustAnchor,bool freeCertFlag)177 void FreeX509TrustAnchorObj(HcfX509TrustAnchor *&trustAnchor, bool freeCertFlag)
178 {
179     if (trustAnchor == nullptr) {
180         return;
181     }
182     CfBlobFree(&trustAnchor->CAPubKey);
183     CfBlobFree(&trustAnchor->CASubject);
184     CfBlobFree(&trustAnchor->nameConstraints);
185     if (freeCertFlag) {
186         CfObjDestroy(trustAnchor->CACert);
187     }
188     trustAnchor->CACert = nullptr;
189 
190     CF_FREE_PTR(trustAnchor);
191 }
192 
193 } // namespace CertFramework
194 } // namespace OHOS
195