• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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