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 "x509_crl_entry_openssl.h"
17 
18 #include "securec.h"
19 
20 #include <openssl/bio.h>
21 #include <openssl/x509.h>
22 #include <openssl/x509v3.h>
23 
24 #include "certificate_openssl_common.h"
25 #include "cf_log.h"
26 #include "cf_memory.h"
27 #include "config.h"
28 #include "utils.h"
29 #include "x509_crl.h"
30 #include "x509_crl_entry.h"
31 #include "x509_crl_openssl.h"
32 
33 typedef struct {
34     HcfX509CrlEntry base;
35     X509_REVOKED *rev;
36     CfBlob *certIssuer;
37 } HcfX509CRLEntryOpensslImpl;
38 
GetClass(void)39 static const char *GetClass(void)
40 {
41     return "HcfX509CRLEntryOpensslImpl.HcfX509CrlEntry";
42 }
43 
GetSelfRev(const HcfX509CrlEntry * self)44 static X509_REVOKED *GetSelfRev(const HcfX509CrlEntry *self)
45 {
46     if (!CfIsClassMatch((CfObjectBase *)self, GetClass())) {
47         LOGE("Input wrong class type!");
48         return NULL;
49     }
50     return ((HcfX509CRLEntryOpensslImpl *)self)->rev;
51 }
52 
GetEncoded(HcfX509CrlEntry * self,CfEncodingBlob * encodedOut)53 static CfResult GetEncoded(HcfX509CrlEntry *self, CfEncodingBlob *encodedOut)
54 {
55     if ((self == NULL) || (encodedOut == NULL)) {
56         LOGE("Invalid params for calling GetEncoded!");
57         return CF_INVALID_PARAMS;
58     }
59     X509_REVOKED *rev = GetSelfRev(self);
60     if (rev == NULL) {
61         LOGE("Rev is null!");
62         return CF_INVALID_PARAMS;
63     }
64     unsigned char *out = NULL;
65     int32_t length = i2d_X509_REVOKED(rev, &out);
66     if (length <= 0) {
67         LOGE("Do i2d_X509_REVOKED fail!");
68         CfPrintOpensslError();
69         return CF_ERR_CRYPTO_OPERATION;
70     }
71     encodedOut->data = (uint8_t *)CfMalloc(length, 0);
72     if (encodedOut->data == NULL) {
73         LOGE("Failed to malloc for encodedOut!");
74         OPENSSL_free(out);
75         return CF_ERR_MALLOC;
76     }
77     (void)memcpy_s(encodedOut->data, length, out, length);
78     encodedOut->len = length;
79     encodedOut->encodingFormat = CF_FORMAT_DER;
80     OPENSSL_free(out);
81     return CF_SUCCESS;
82 }
83 
GetSerialNumber(HcfX509CrlEntry * self,CfBlob * out)84 static CfResult GetSerialNumber(HcfX509CrlEntry *self, CfBlob *out)
85 {
86     if (self == NULL) {
87         LOGE("Invalid params for calling GetSerialNumber!");
88         return CF_INVALID_PARAMS;
89     }
90     X509_REVOKED *rev = GetSelfRev(self);
91     if (rev == NULL) {
92         LOGE("Rev is null!");
93         return CF_INVALID_PARAMS;
94     }
95     const ASN1_INTEGER *serialNumber = X509_REVOKED_get0_serialNumber(rev);
96     if (serialNumber == NULL) {
97         LOGE("Get serial number fail!");
98         CfPrintOpensslError();
99         return CF_ERR_CRYPTO_OPERATION;
100     }
101 
102     unsigned char *serialNumBytes = NULL;
103     int serialNumLen = i2d_ASN1_INTEGER((ASN1_INTEGER *)serialNumber, &serialNumBytes);
104     if (serialNumLen <= SERIAL_NUMBER_HEDER_SIZE) {
105         CfPrintOpensslError();
106         LOGE("get serial num len failed!");
107         return CF_ERR_CRYPTO_OPERATION;
108     }
109 
110     out->data = (uint8_t *)CfMalloc(serialNumLen - SERIAL_NUMBER_HEDER_SIZE, 0);
111     if (out->data == NULL) {
112         OPENSSL_free(serialNumBytes);
113         LOGE("Failed to malloc serial num");
114         return CF_ERR_MALLOC;
115     }
116     out->size = (uint32_t)(serialNumLen - SERIAL_NUMBER_HEDER_SIZE);
117     (void)memcpy_s(out->data, out->size, serialNumBytes + SERIAL_NUMBER_HEDER_SIZE, out->size);
118     OPENSSL_free(serialNumBytes);
119     return CF_SUCCESS;
120 }
121 
GetCertIssuer(HcfX509CrlEntry * self,CfBlob * encodedOut)122 static CfResult GetCertIssuer(HcfX509CrlEntry *self, CfBlob *encodedOut)
123 {
124     if ((self == NULL) || (encodedOut == NULL)) {
125         LOGE("Invalid params for calling GetCertIssuer!");
126         return CF_INVALID_PARAMS;
127     }
128     if (!CfIsClassMatch((CfObjectBase *)self, GetClass())) {
129         LOGE("Input wrong class type!");
130         return CF_INVALID_PARAMS;
131     }
132     CfBlob *certIssuer = ((HcfX509CRLEntryOpensslImpl *)self)->certIssuer;
133     if (!CfIsBlobValid(certIssuer)) {
134         LOGE("Get certIssuer fail! No certIssuer in CRL entry.");
135         return CF_NOT_SUPPORT;
136     }
137     uint32_t length = certIssuer->size;
138     encodedOut->data = (uint8_t *)CfMalloc(length, 0);
139     if (encodedOut->data == NULL) {
140         LOGE("Failed to malloc for encodedOut!");
141         return CF_ERR_MALLOC;
142     }
143     (void)memcpy_s(encodedOut->data, length, certIssuer->data, length);
144     encodedOut->size = length;
145     return CF_SUCCESS;
146 }
147 
GetRevocationDate(HcfX509CrlEntry * self,CfBlob * out)148 static CfResult GetRevocationDate(HcfX509CrlEntry *self, CfBlob *out)
149 {
150     if ((self == NULL) || (out == NULL)) {
151         LOGE("invalid params for calling GetRevocationDate!");
152         return CF_INVALID_PARAMS;
153     }
154     X509_REVOKED *rev = GetSelfRev(self);
155     if (rev == NULL) {
156         LOGE("Rev is null!");
157         return CF_INVALID_PARAMS;
158     }
159     const ASN1_TIME *time = X509_REVOKED_get0_revocationDate(rev);
160     if (time == NULL) {
161         LOGE("Get revocation date fail!");
162         CfPrintOpensslError();
163         return CF_ERR_CRYPTO_OPERATION;
164     }
165     const char *revTime = (const char *)(time->data);
166     if ((revTime == NULL) || (strlen(revTime) > HCF_MAX_STR_LEN)) {
167         LOGE("Get revocation date from ASN1_TIME fail!");
168         return CF_ERR_CRYPTO_OPERATION;
169     }
170     uint32_t length = strlen(revTime) + 1;
171     out->data = (uint8_t *)CfMalloc(length, 0);
172     if (out->data == NULL) {
173         LOGE("Failed to malloc for revTime!");
174         return CF_ERR_MALLOC;
175     }
176     (void)memcpy_s(out->data, length, revTime, length);
177     out->size = length;
178     return CF_SUCCESS;
179 }
180 
GetExtensions(HcfX509CrlEntry * self,CfBlob * outBlob)181 static CfResult GetExtensions(HcfX509CrlEntry *self, CfBlob *outBlob)
182 {
183     if ((self == NULL) || (outBlob == NULL)) {
184         LOGE("Invalid params!");
185         return CF_INVALID_PARAMS;
186     }
187 
188     X509_REVOKED *rev = GetSelfRev(self);
189     if (rev == NULL) {
190         LOGE("Rev is null!");
191         return CF_INVALID_PARAMS;
192     }
193 
194     X509_EXTENSIONS *exts = (X509_EXTENSIONS *)X509_REVOKED_get0_extensions(rev);
195     CfResult ret = CopyExtensionsToBlob(exts, outBlob);
196     if (ret != CF_SUCCESS) {
197         CfPrintOpensslError();
198     }
199     return ret;
200 }
201 
HasExtensions(HcfX509CrlEntry * self,bool * out)202 static CfResult HasExtensions(HcfX509CrlEntry *self, bool *out)
203 {
204     if (self == NULL || out == NULL) {
205         LOGE("Invalid params!");
206         return CF_INVALID_PARAMS;
207     }
208 
209     X509_REVOKED *rev = GetSelfRev(self);
210     if (rev == NULL) {
211         LOGE("Rev is null!");
212         return CF_INVALID_PARAMS;
213     }
214 
215     X509_EXTENSIONS *exts = (X509_EXTENSIONS *)X509_REVOKED_get0_extensions(rev);
216     if (exts == NULL) {
217         *out = false;
218     } else {
219         *out = (sk_X509_EXTENSION_num(exts) > 0);
220     }
221 
222     return CF_SUCCESS;
223 }
224 
ToString(HcfX509CrlEntry * self,CfBlob * outBlob)225 static CfResult ToString(HcfX509CrlEntry *self, CfBlob *outBlob)
226 {
227     if ((self == NULL) || (outBlob == NULL)) {
228         LOGE("Invalid params!");
229         return CF_INVALID_PARAMS;
230     }
231     X509_REVOKED *rev = GetSelfRev(self);
232     if (rev == NULL) {
233         LOGE("Rev is null!");
234         return CF_INVALID_PARAMS;
235     }
236 
237     BIO *out = BIO_new(BIO_s_mem());
238     if (out == NULL) {
239         LOGE("BIO_new error");
240         return CF_ERR_MALLOC;
241     }
242     BIO_printf(out, "    Serial Number: ");
243     i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(rev));
244     BIO_printf(out, "\n        Revocation Date: ");
245     ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(rev));
246     BIO_printf(out, "\n");
247     int len = X509V3_extensions_print(out, "CRL entry extensions", X509_REVOKED_get0_extensions(rev), 0, 8);
248     if (len <= 0) {
249         LOGE("X509V3_extensions_print error");
250         BIO_free(out);
251         return CF_ERR_CRYPTO_OPERATION;
252     }
253     BUF_MEM *bufMem = NULL;
254     if (BIO_get_mem_ptr(out, &bufMem) > 0 && bufMem != NULL) {
255         CfResult res = DeepCopyDataToOut(bufMem->data, bufMem->length, outBlob);
256         BIO_free(out);
257         return res;
258     }
259     BIO_free(out);
260     LOGE("BIO_get_mem_ptr error");
261     return CF_ERR_CRYPTO_OPERATION;
262 }
263 
HashCode(HcfX509CrlEntry * self,CfBlob * outBlob)264 static CfResult HashCode(HcfX509CrlEntry *self, CfBlob *outBlob)
265 {
266     if ((self == NULL) || (outBlob == NULL)) {
267         LOGE("Invalid params!");
268         return CF_INVALID_PARAMS;
269     }
270     X509_REVOKED *rev = GetSelfRev(self);
271     if (rev == NULL) {
272         LOGE("Rev is null!");
273         return CF_INVALID_PARAMS;
274     }
275 
276     unsigned char *buf = NULL;
277     int len = i2d_X509_REVOKED(rev, &buf);
278     if (len < 0 || buf == NULL) {
279         LOGE("i2d_X509_REVOKED error");
280         return CF_ERR_CRYPTO_OPERATION;
281     }
282 
283     outBlob->data = (uint8_t *)CfMalloc(SHA256_DIGEST_LENGTH, 0);
284     if (outBlob->data == NULL) {
285         LOGE("CfMalloc error");
286         OPENSSL_free(buf);
287         return CF_ERR_MALLOC;
288     }
289     if (SHA256(buf, len, (unsigned char *)outBlob->data) == NULL) {
290         LOGE("Compute sha256 error");
291         OPENSSL_free(buf);
292         CfFree(outBlob->data);
293         return CF_ERR_CRYPTO_OPERATION;
294     }
295     outBlob->size = SHA256_DIGEST_LENGTH;
296     OPENSSL_free(buf);
297     return CF_SUCCESS;
298 }
299 
GetExtensionsObject(HcfX509CrlEntry * self,CfBlob * outBlob)300 static CfResult GetExtensionsObject(HcfX509CrlEntry *self, CfBlob *outBlob)
301 {
302     if ((self == NULL) || (outBlob == NULL)) {
303         LOGE("Invalid params!");
304         return CF_INVALID_PARAMS;
305     }
306 
307     X509_REVOKED *rev = GetSelfRev(self);
308     if (rev == NULL) {
309         LOGE("Rev is null!");
310         return CF_INVALID_PARAMS;
311     }
312     int len = i2d_X509_EXTENSIONS(X509_REVOKED_get0_extensions(rev), &outBlob->data);
313     if (len < 0) {
314         LOGE("i2d_X509_EXTENSIONS error");
315         return CF_ERR_CRYPTO_OPERATION;
316     }
317     outBlob->size = len;
318     return CF_SUCCESS;
319 }
320 
DeepCopyCertIssuer(HcfX509CRLEntryOpensslImpl * returnCRLEntry,CfBlob * certIssuer)321 static CfResult DeepCopyCertIssuer(HcfX509CRLEntryOpensslImpl *returnCRLEntry, CfBlob *certIssuer)
322 {
323     returnCRLEntry->certIssuer = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
324     if (returnCRLEntry->certIssuer == NULL) {
325         LOGE("Failed to malloc certIssuer!");
326         return CF_ERR_MALLOC;
327     }
328     returnCRLEntry->certIssuer->size = certIssuer->size;
329     returnCRLEntry->certIssuer->data = (uint8_t *)CfMalloc(certIssuer->size, 0);
330     if (returnCRLEntry->certIssuer->data == NULL) {
331         LOGE("Failed to malloc certIssuer data!");
332         return CF_ERR_MALLOC;
333     }
334     (void)memcpy_s(returnCRLEntry->certIssuer->data, certIssuer->size, certIssuer->data, certIssuer->size);
335     return CF_SUCCESS;
336 }
337 
Destroy(CfObjectBase * self)338 static void Destroy(CfObjectBase *self)
339 {
340     if (self == NULL) {
341         LOGE("Invalid params!");
342         return;
343     }
344     if (!CfIsClassMatch((CfObjectBase *)self, GetClass())) {
345         LOGE("Input wrong class type!");
346         return;
347     }
348     HcfX509CRLEntryOpensslImpl *realCrlEntry = (HcfX509CRLEntryOpensslImpl *)self;
349     if (realCrlEntry->rev != NULL) {
350         X509_REVOKED_free(realCrlEntry->rev);
351         realCrlEntry->rev = NULL;
352     }
353     if (realCrlEntry->certIssuer != NULL) {
354         CfFree(realCrlEntry->certIssuer->data);
355         realCrlEntry->certIssuer->data = NULL;
356         CfFree(realCrlEntry->certIssuer);
357         realCrlEntry->certIssuer = NULL;
358     }
359     CfFree(realCrlEntry);
360 }
361 
HcfCX509CRLEntryCreate(X509_REVOKED * rev,HcfX509CrlEntry ** crlEntryOut,CfBlob * certIssuer)362 CfResult HcfCX509CRLEntryCreate(X509_REVOKED *rev, HcfX509CrlEntry **crlEntryOut, CfBlob *certIssuer)
363 {
364     if ((rev == NULL) || (crlEntryOut == NULL) || certIssuer == NULL) {
365         LOGE("Invalid params!");
366         return CF_INVALID_PARAMS;
367     }
368     HcfX509CRLEntryOpensslImpl *returnCRLEntry = (HcfX509CRLEntryOpensslImpl *)CfMalloc(
369         sizeof(HcfX509CRLEntryOpensslImpl), 0);
370     if (returnCRLEntry == NULL) {
371         LOGE("Failed to malloc for x509 entry instance!");
372         return CF_ERR_MALLOC;
373     }
374 
375     X509_REVOKED *tmp = X509_REVOKED_dup(rev);
376     if (tmp == NULL) {
377         CfFree(returnCRLEntry);
378         LOGE("Failed to dup x509 revoked");
379         return CF_ERR_MALLOC;
380     }
381     returnCRLEntry->rev = tmp;
382     returnCRLEntry->certIssuer = NULL;
383     returnCRLEntry->base.base.getClass = GetClass;
384     returnCRLEntry->base.base.destroy = Destroy;
385     returnCRLEntry->base.getEncoded = GetEncoded;
386     returnCRLEntry->base.getSerialNumber = GetSerialNumber;
387     returnCRLEntry->base.getCertIssuer = GetCertIssuer;
388     returnCRLEntry->base.getRevocationDate = GetRevocationDate;
389     returnCRLEntry->base.getExtensions = GetExtensions;
390     returnCRLEntry->base.hasExtensions = HasExtensions;
391     returnCRLEntry->base.toString = ToString;
392     returnCRLEntry->base.hashCode = HashCode;
393     returnCRLEntry->base.getExtensionsObject = GetExtensionsObject;
394     if (DeepCopyCertIssuer(returnCRLEntry, certIssuer) != CF_SUCCESS) {
395         LOGI("No cert issuer find or deep copy cert issuer fail!");
396     }
397     *crlEntryOut = (HcfX509CrlEntry *)returnCRLEntry;
398     return CF_SUCCESS;
399 }
400