1 /*
2 * Copyright (c) 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 "cj_x509_certchain.h"
17
18 CfResult parseAnchor(CjX509TrustAnchor *trustAnchors, uint32_t trustAnchorCnt, HcfX509TrustAnchorArray &ret);
19
20 HcfCertCRLCollectionArray *parseCRLCollections(HcfCertCrlCollection **certCRLCollections, uint32_t certCRLCollectionCnt,
21 HcfCertCRLCollectionArray &ret);
22
23 HcfRevocationCheckParam *parseRevocation(const CjRevocationCheckParam *checkParam,
24 HcfRevocationCheckParam &revocationCheckParam,
25 HcfRevChkOpArray &revChkOption);
26
27 HcfKuArray *parseKeyUsage(const CjX509CertChainValidateParams *params, HcfKuArray &keyUsage);
28
29 void updateCertMatchParameters(HcfX509CertChainBuildParameters &hcfParams, const CjX509CertMatchParams *matchParams);
30
31 void updateValidateParameters(const CjX509CertChainValidateParams &validParams,
32 HcfX509CertChainBuildParameters &hcfParams);
33
34 SubAltNameArray *parseSubAltName(const CjX509CertMatchParams &matchParams, SubAltNameArray &subjectAlternativeNames);
35
FfiCertCjX509CertChainNewInstanceBlob(const CfEncodingBlob * blob,CjX509CertChain * returnObj)36 int32_t FfiCertCjX509CertChainNewInstanceBlob(const CfEncodingBlob *blob, CjX509CertChain *returnObj)
37 {
38 auto chain = static_cast<HcfCertChain *>(malloc(sizeof(HcfCertChain)));
39 if (chain == nullptr) {
40 return CF_ERR_MALLOC;
41 }
42 const auto errCode = HcfCertChainCreate(blob, nullptr, &chain);
43 if (errCode != CF_SUCCESS) {
44 free(chain);
45 return errCode;
46 }
47 returnObj->chain = chain;
48 return CF_SUCCESS;
49 }
50
FfiCertCjX509CertChainNewInstanceArray(const HcfX509CertificateArray * inCerts,CjX509CertChain * returnObj)51 int32_t FfiCertCjX509CertChainNewInstanceArray(const HcfX509CertificateArray *inCerts, CjX509CertChain *returnObj)
52 {
53 auto chain = static_cast<HcfCertChain *>(malloc(sizeof(HcfCertChain)));
54 if (chain == nullptr) {
55 return CF_ERR_MALLOC;
56 }
57 const auto errCode = HcfCertChainCreate(nullptr, inCerts, &chain);
58 if (errCode != CF_SUCCESS) {
59 free(chain);
60 return errCode;
61 }
62 returnObj->chain = chain;
63 return CF_SUCCESS;
64 }
65
FfiCertCjX509CertChainDeleteInstance(CjX509CertChain self)66 void FfiCertCjX509CertChainDeleteInstance(CjX509CertChain self)
67 {
68 CfObjDestroy(self.chain);
69 }
70
FfiCertCjX509CertChainGetCertList(const CjX509CertChain self,HcfX509CertificateArray * out)71 CfResult FfiCertCjX509CertChainGetCertList(const CjX509CertChain self, HcfX509CertificateArray *out)
72 {
73 return self.chain->getCertList(self.chain, out);
74 }
75
FfiCertCjX509CertChainValidate(const CjX509CertChain self,const CjX509CertChainValidateParams * params,CjX509CertChainValidateResult * result)76 CfResult FfiCertCjX509CertChainValidate(const CjX509CertChain self,
77 const CjX509CertChainValidateParams *params,
78 CjX509CertChainValidateResult *result)
79 {
80 HcfX509TrustAnchorArray anchors;
81 CfResult errCode = parseAnchor(params->trustAnchors, params->trustAnchorCnt, anchors);
82 if (errCode != CF_SUCCESS) {
83 return errCode;
84 }
85
86 HcfCertCRLCollectionArray certCRLCollections;
87 HcfCertCRLCollectionArray *certCRLCollectionsPtr = parseCRLCollections(
88 params->certCRLCollections, params->certCRLCollectionCnt,
89 certCRLCollections);
90
91 HcfRevocationCheckParam revocationCheckParam;
92 HcfRevChkOpArray revChkOption;
93 HcfRevocationCheckParam *revocationCheckParamPtr = parseRevocation(params->revocationCheckParam,
94 revocationCheckParam,
95 revChkOption);
96
97 HcfKuArray keyUsage;
98 HcfKuArray *keyUsagePtr = parseKeyUsage(params, keyUsage);
99
100 auto hcfParams = HcfX509CertChainValidateParams{
101 .date = params->date,
102 .trustAnchors = &anchors,
103 .certCRLCollections = certCRLCollectionsPtr,
104 .revocationCheckParam = revocationCheckParamPtr,
105 .policy = params->policy,
106 .sslHostname = params->sslHostname,
107 .keyUsage = keyUsagePtr,
108 };
109
110 HcfX509CertChainValidateResult hcfResult;
111 errCode = self.chain->validate(self.chain, &hcfParams, &hcfResult);
112
113 for (uint32_t i = 0; i < anchors.count; ++i) {
114 free(anchors.data[i]);
115 }
116 free(anchors.data);
117
118 if (errCode == CF_SUCCESS) {
119 result->trustAnchor.CAPubKey = hcfResult.trustAnchor->CAPubKey;
120 result->trustAnchor.CACert = hcfResult.trustAnchor->CACert;
121 result->trustAnchor.CASubject = hcfResult.trustAnchor->CASubject;
122 result->trustAnchor.nameConstraints = hcfResult.trustAnchor->nameConstraints;
123 result->entityCert = hcfResult.entityCert;
124 }
125 return errCode;
126 }
127
FfiCertCjX509CertChainToString(const CjX509CertChain self,CfBlob * out)128 CfResult FfiCertCjX509CertChainToString(const CjX509CertChain self, CfBlob *out)
129 {
130 return self.chain->toString(self.chain, out);
131 }
132
FfiCertCjX509CertChainHashCode(const CjX509CertChain self,CfBlob * out)133 CfResult FfiCertCjX509CertChainHashCode(const CjX509CertChain self, CfBlob *out)
134 {
135 return self.chain->hashCode(self.chain, out);
136 }
137
FfiCertBuildX509CertChain(const CjX509CertMatchParams & matchParams,const CjX509CertChainValidateParams & validParams,int32_t maxLength,CjX509CertChain * returnObj)138 CfResult FfiCertBuildX509CertChain(const CjX509CertMatchParams &matchParams,
139 const CjX509CertChainValidateParams &validParams,
140 int32_t maxLength, CjX509CertChain *returnObj)
141 {
142 HcfCertificate *certPtr = nullptr;
143 if (matchParams.x509Cert != nullptr) {
144 certPtr = &matchParams.x509Cert->base;
145 }
146
147 SubAltNameArray subjectAlternativeNames;
148 SubAltNameArray *subjectAlternativeNamesPtr = parseSubAltName(matchParams, subjectAlternativeNames);
149
150 HcfX509TrustAnchorArray anchors;
151 CfResult errCode = parseAnchor(validParams.trustAnchors, validParams.trustAnchorCnt, anchors);
152 if (errCode != CF_SUCCESS) {
153 return errCode;
154 }
155
156 HcfCertCRLCollectionArray certCRLCollections;
157 HcfCertCRLCollectionArray *certCRLCollectionsPtr = parseCRLCollections(
158 validParams.certCRLCollections, validParams.certCRLCollectionCnt,
159 certCRLCollections);
160
161 HcfRevocationCheckParam revocationCheckParam;
162 HcfRevChkOpArray revChkOption;
163 HcfRevocationCheckParam *revocationCheckParamPtr = parseRevocation(validParams.revocationCheckParam,
164 revocationCheckParam,
165 revChkOption);
166
167 HcfKuArray keyUsage;
168 HcfKuArray *keyUsagePtr = parseKeyUsage(&validParams, keyUsage);
169
170 HcfX509CertChainBuildParameters hcfParams = {};
171 updateCertMatchParameters(hcfParams, &matchParams);
172 hcfParams.certMatchParameters.x509Cert = certPtr;
173 hcfParams.certMatchParameters.subjectAlternativeNames = subjectAlternativeNamesPtr;
174 hcfParams.maxlength = maxLength;
175 updateValidateParameters(validParams, hcfParams);
176 hcfParams.validateParameters.trustAnchors = &anchors;
177 hcfParams.validateParameters.certCRLCollections = certCRLCollectionsPtr;
178 hcfParams.validateParameters.revocationCheckParam = revocationCheckParamPtr;
179 hcfParams.validateParameters.keyUsage = keyUsagePtr;
180
181 HcfX509CertChainBuildResult *buildResult = nullptr;
182 errCode = HcfCertChainBuildResultCreate(&hcfParams, &buildResult);
183 if (errCode != CF_SUCCESS) {
184 return errCode;
185 }
186 returnObj->chain = buildResult->certChain;
187 // release buildResult here
188 // buildResult->certChain is allocated by CfMalloc and will be released by cangjie
189 free(buildResult);
190 return CF_SUCCESS;
191 }
192
parseSubAltName(const CjX509CertMatchParams & matchParams,SubAltNameArray & subjectAlternativeNames)193 SubAltNameArray *parseSubAltName(const CjX509CertMatchParams &matchParams, SubAltNameArray &subjectAlternativeNames)
194 {
195 SubAltNameArray *subjectAlternativeNamesPtr = nullptr;
196 if (matchParams.subjectAlternativeNameCnt > 0) {
197 subjectAlternativeNames = SubAltNameArray{
198 .data = matchParams.subjectAlternativeNames,
199 .count = matchParams.subjectAlternativeNameCnt
200 };
201 subjectAlternativeNamesPtr = &subjectAlternativeNames;
202 }
203 return subjectAlternativeNamesPtr;
204 }
205
updateValidateParameters(const CjX509CertChainValidateParams & validParams,HcfX509CertChainBuildParameters & hcfParams)206 void updateValidateParameters(const CjX509CertChainValidateParams &validParams,
207 HcfX509CertChainBuildParameters &hcfParams)
208 {
209 hcfParams.validateParameters = {
210 .date = validParams.date,
211 .policy = validParams.policy,
212 .sslHostname = validParams.sslHostname,
213 };
214 }
215
updateCertMatchParameters(HcfX509CertChainBuildParameters & hcfParams,const CjX509CertMatchParams * matchParams)216 void updateCertMatchParameters(HcfX509CertChainBuildParameters &hcfParams, const CjX509CertMatchParams *matchParams)
217 {
218 hcfParams.certMatchParameters.validDate = matchParams->validDate;
219 hcfParams.certMatchParameters.issuer = matchParams->issuer;
220 hcfParams.certMatchParameters.keyUsage = matchParams->keyUsage;
221 hcfParams.certMatchParameters.serialNumber = matchParams->serialNumber;
222 hcfParams.certMatchParameters.subject = matchParams->subject;
223 hcfParams.certMatchParameters.publicKey = matchParams->publicKey;
224 hcfParams.certMatchParameters.publicKeyAlgID = matchParams->publicKeyAlgID;
225 hcfParams.certMatchParameters.matchAllSubjectAltNames = matchParams->matchAllSubjectAltNames;
226 hcfParams.certMatchParameters.authorityKeyIdentifier = matchParams->authorityKeyIdentifier;
227 hcfParams.certMatchParameters.minPathLenConstraint = matchParams->minPathLenConstraint;
228 hcfParams.certMatchParameters.extendedKeyUsage = matchParams->extendedKeyUsage;
229 hcfParams.certMatchParameters.nameConstraints = matchParams->nameConstraints;
230 hcfParams.certMatchParameters.certPolicy = matchParams->certPolicy;
231 hcfParams.certMatchParameters.privateKeyValid = matchParams->privateKeyValid;
232 hcfParams.certMatchParameters.subjectKeyIdentifier = matchParams->subjectKeyIdentifier;
233 }
234
FfiCertCreateTrustAnchorWithKeyStore(const CfBlob * keyStore,const CfBlob * pwd,CjX509TrustAnchorArray * returnObj)235 CfResult FfiCertCreateTrustAnchorWithKeyStore(const CfBlob *keyStore, const CfBlob *pwd,
236 CjX509TrustAnchorArray *returnObj)
237 {
238 HcfX509TrustAnchorArray *anchorArray = nullptr;
239 const auto errCode = HcfCreateTrustAnchorWithKeyStore(keyStore, pwd, &anchorArray);
240 if (errCode != CF_SUCCESS) {
241 return errCode;
242 }
243 returnObj->count = anchorArray->count;
244 returnObj->data = static_cast<CjX509TrustAnchor **>(malloc(sizeof(CjX509TrustAnchor *) * anchorArray->count));
245 if (returnObj->data == nullptr) {
246 free(anchorArray->data);
247 return CF_ERR_MALLOC;
248 }
249 for (uint32_t i = 0; i < anchorArray->count; ++i) {
250 const auto anchor = static_cast<CjX509TrustAnchor *>(malloc(sizeof(CjX509TrustAnchor)));
251 if (anchor == nullptr) {
252 for (uint32_t j = 0; j < i; j++) {
253 free(returnObj->data[j]);
254 }
255 free(anchorArray->data);
256 return CF_ERR_MALLOC;
257 }
258 anchor->CAPubKey = anchorArray->data[i]->CAPubKey;
259 anchor->CACert = anchorArray->data[i]->CACert;
260 anchor->CASubject = anchorArray->data[i]->CASubject;
261 anchor->nameConstraints = anchorArray->data[i]->nameConstraints;
262 returnObj->data[i] = anchor;
263 }
264 free(anchorArray->data);
265 return CF_SUCCESS;
266 }
267
parseCRLCollections(HcfCertCrlCollection ** certCRLCollections,uint32_t certCRLCollectionCnt,HcfCertCRLCollectionArray & ret)268 HcfCertCRLCollectionArray *parseCRLCollections(HcfCertCrlCollection **certCRLCollections,
269 uint32_t certCRLCollectionCnt,
270 HcfCertCRLCollectionArray &ret)
271 {
272 HcfCertCRLCollectionArray *certCRLCollectionsPtr = nullptr;
273 if (certCRLCollectionCnt != 0) {
274 ret.data = certCRLCollections;
275 ret.count = certCRLCollectionCnt;
276 certCRLCollectionsPtr = &ret;
277 }
278 return certCRLCollectionsPtr;
279 }
280
parseAnchor(CjX509TrustAnchor * trustAnchors,uint32_t trustAnchorCnt,HcfX509TrustAnchorArray & ret)281 CfResult parseAnchor(CjX509TrustAnchor *trustAnchors, uint32_t trustAnchorCnt, HcfX509TrustAnchorArray &ret)
282 {
283 ret = HcfX509TrustAnchorArray{
284 .data = static_cast<HcfX509TrustAnchor **>(malloc(sizeof(HcfX509TrustAnchor *) * (trustAnchorCnt))),
285 .count = trustAnchorCnt,
286 };
287 if (ret.data == nullptr) {
288 return CF_ERR_MALLOC;
289 }
290 for (uint32_t i = 0; i < trustAnchorCnt; ++i) {
291 const auto item = static_cast<HcfX509TrustAnchor *>(malloc(sizeof(HcfX509TrustAnchor)));
292 if (item == nullptr) {
293 for (uint32_t j = 0; j < i; j++) {
294 free(ret.data[j]);
295 }
296 free(ret.data);
297 return CF_ERR_MALLOC;
298 }
299 item->CAPubKey = trustAnchors[i].CAPubKey;
300 item->CACert = trustAnchors[i].CACert;
301 item->CASubject = trustAnchors[i].CASubject;
302 item->nameConstraints = trustAnchors[i].nameConstraints;
303 ret.data[i] = item;
304 }
305 return CF_SUCCESS;
306 }
307
parseKeyUsage(const CjX509CertChainValidateParams * params,HcfKuArray & keyUsage)308 HcfKuArray *parseKeyUsage(const CjX509CertChainValidateParams *params, HcfKuArray &keyUsage)
309 {
310 HcfKuArray *keyUsagePtr = nullptr;
311 if (params->keyUsageCnt != 0) {
312 keyUsage = HcfKuArray{
313 .data = params->keyUsage,
314 .count = params->keyUsageCnt,
315 };
316 keyUsagePtr = &keyUsage;
317 }
318 return keyUsagePtr;
319 }
320
parseRevocation(const CjRevocationCheckParam * checkParam,HcfRevocationCheckParam & revocationCheckParam,HcfRevChkOpArray & revChkOption)321 HcfRevocationCheckParam *parseRevocation(const CjRevocationCheckParam *checkParam,
322 HcfRevocationCheckParam &revocationCheckParam,
323 HcfRevChkOpArray &revChkOption)
324 {
325 HcfRevocationCheckParam *revocationCheckParamPtr = nullptr;
326 HcfRevChkOpArray *revChkOptionPtr = nullptr;
327 if (checkParam) {
328 if (checkParam->optionCnt != 0) {
329 revChkOption = HcfRevChkOpArray{
330 .data = checkParam->options,
331 .count = checkParam->optionCnt,
332 };
333 revChkOptionPtr = &revChkOption;
334 }
335 revocationCheckParam = HcfRevocationCheckParam{
336 .ocspRequestExtension = checkParam->ocspRequestExtension,
337 .ocspResponderURI = checkParam->ocspResponderURI,
338 .ocspResponderCert = checkParam->ocspResponderCert,
339 .ocspResponses = checkParam->ocspResponses,
340 .crlDownloadURI = checkParam->crlDownloadURI,
341 .options = revChkOptionPtr,
342 .ocspDigest = checkParam->ocspDigest,
343 };
344 revocationCheckParamPtr = &revocationCheckParam;
345 }
346 return revocationCheckParamPtr;
347 }
348