1 /*
2  * Copyright (c) 2022-2023 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 "hks_verifier.h"
17 
18 #include <openssl/asn1.h>
19 #include <openssl/bio.h>
20 #include <openssl/crypto.h>
21 #include <openssl/evp.h>
22 #include <openssl/obj_mac.h>
23 #include <openssl/ossl_typ.h>
24 #include <openssl/pem.h>
25 #include <openssl/x509.h>
26 #include <stddef.h>
27 
28 #include "hks_log.h"
29 #include "hks_mem.h"
30 #include "hks_param.h"
31 #include "hks_template.h"
32 #include "hks_type.h"
33 #include "securec.h"
34 
35 #define OPENSSL_SUCCESS 1
36 #define OPENSSL_ERROR 0
37 #define KEY_DESCRIPTION_OID "1.3.6.1.4.1.2011.2.376.1.3"
38 
39 #define TLV_VERSION_NEED_SIZE 3
40 
41 #define ASN_1_TAG_TYPE_SEQ 0x30
42 #define ASN_1_MIN_VAL_1_EXTRA_LEN_BYTE 0x80
43 #define ASN_1_TAG_TYPE_1_BYTE_LEN 0x81
44 #define ASN_1_TAG_TYPE_2_BYTE_LEN 0x82
45 #define ASN_1_MIN_HEADER_LEN 0x3
46 #define APPLICATION_ID_RAW_OID_LEN 16
47 #define APPLICATION_ID_HEADER_LEN 2
48 
49 struct HksCertInfo {
50     uint8_t *data;
51     size_t length;
52     enum HksCertFormat format;
53     X509 *x509;
54 };
55 
56 #define HKS_ASN1_DECODE_BYTE(ptr, value) \
57 do { \
58     (value) = (uint32_t)((ptr)[0]); \
59     (ptr)++; \
60 } while (0)
61 
62 #define HKS_ASN1_DECODE_TWO_BYTE(ptr, value) \
63 do { \
64     (value) = (uint32_t)((ptr)[0] & 0xff) << 8; \
65     (ptr)++; \
66     (value) |= (uint32_t)((ptr)[0] & 0xff); \
67     (ptr)++; \
68 } while (0)
69 
70 static uint8_t g_challengeOid[] = {
71     0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x01, 0x04
72 };
73 static uint8_t g_udidOid[] = {
74     0x06, 0x0e, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x02, 0x04, 0x0a
75 };
76 static uint8_t g_snOid[] = {
77     0x06, 0x0e, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x02, 0x04, 0x03
78 };
79 static uint8_t g_secInfoOid[] = {
80     0x06, 0x0e, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x02, 0x02, 0x05
81 };
82 static uint8_t g_versionInfoOid[] = {
83     0x06, 0x0e, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x02, 0x02, 0x04
84 };
85 static uint8_t g_deviceIdOid[] = {
86     0x06, 0x0e, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x02, 0x04, 0x05
87 };
88 static uint8_t g_appIdOid[] = {
89     0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8f, 0x5b, 0x02, 0x82, 0x78, 0x02, 0x01, 0x03
90 };
91 
92 static const struct HksParam g_oidParams[] = {
93     {
94         .tag = HKS_TAG_ATTESTATION_CHALLENGE,
95         .blob = {
96             .size = sizeof(g_challengeOid),
97             .data = g_challengeOid
98         }
99     }, {
100         .tag = HKS_TAG_ATTESTATION_ID_UDID,
101         .blob = {
102             .size = sizeof(g_udidOid),
103             .data = g_udidOid
104         }
105     }, {
106         .tag = HKS_TAG_ATTESTATION_ID_SERIAL,
107         .blob = {
108             .size = sizeof(g_snOid),
109             .data = g_snOid
110         }
111     }, {
112         .tag = HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO,
113         .blob = {
114             .size = sizeof(g_secInfoOid),
115             .data = g_secInfoOid
116         }
117     }, {
118         .tag = HKS_TAG_ATTESTATION_ID_VERSION_INFO,
119         .blob = {
120             .size = sizeof(g_versionInfoOid),
121             .data = g_versionInfoOid
122         }
123     }, {
124         .tag = HKS_TAG_ATTESTATION_ID_DEVICE,
125         .blob = {
126             .size = sizeof(g_deviceIdOid),
127             .data = g_deviceIdOid
128         }
129     }, {
130         .tag = HKS_TAG_ATTESTATION_APPLICATION_ID,
131         .blob = {
132             .size = sizeof(g_appIdOid),
133             .data = g_appIdOid
134         }
135     },
136 };
137 
CopyBlobBuffer(const uint8_t * buffer,uint32_t len,struct HksBlob * blob)138 static int32_t CopyBlobBuffer(const uint8_t *buffer, uint32_t len, struct HksBlob *blob)
139 {
140     if ((blob->data == NULL) || (blob->size < len)) {
141         HKS_LOG_E("construct paramSet out blob: invalid blob");
142         return HKS_ERROR_INVALID_ARGUMENT;
143     }
144     if (memcpy_s(blob->data, blob->size, buffer, len) != EOK) {
145         HKS_LOG_E("construct paramSet out blob buffer failed");
146         return HKS_ERROR_INSUFFICIENT_MEMORY;
147     }
148     blob->size = len;
149     return HKS_SUCCESS;
150 }
151 
GetX509FormatCert(const struct HksCertInfo * cert)152 static X509 *GetX509FormatCert(const struct HksCertInfo *cert)
153 {
154     X509 *x509 = NULL;
155 
156     BIO *bio = BIO_new_mem_buf(cert->data, cert->length);
157     HKS_IF_NULL_RETURN(bio, x509)
158 
159     if (cert->format == HKS_CERT_DER) {
160         x509 = d2i_X509_bio(bio, NULL);
161     } else if (cert->format == HKS_CERT_PEM) {
162         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
163     }
164 
165     BIO_free(bio);
166     return x509;
167 }
168 
TranslateToX509Format(struct HksCertInfo * certs,uint32_t certNum)169 static int32_t TranslateToX509Format(struct HksCertInfo *certs, uint32_t certNum)
170 {
171     for (uint32_t i = 0; i < certNum; ++i) {
172         X509 *x509 = GetX509FormatCert(&certs[i]);
173         /* if failed, x509 need to be freed by caller function */
174         HKS_IF_NULL_LOGE_RETURN(x509, HKS_ERROR_VERIFICATION_FAILED, "load cert chain to x509 failed")
175 
176         certs[i].x509 = x509;
177     }
178     return HKS_SUCCESS;
179 }
180 
VerifySignature(const struct HksCertInfo * cert,const struct HksCertInfo * issuerCert)181 static int32_t VerifySignature(const struct HksCertInfo *cert, const struct HksCertInfo *issuerCert)
182 {
183     EVP_PKEY *pubKey = X509_get_pubkey(issuerCert->x509);
184     HKS_IF_NULL_LOGE_RETURN(pubKey, HKS_ERROR_VERIFICATION_FAILED, "get public key from device cert failed")
185 
186     int32_t resOpenssl = X509_verify(cert->x509, pubKey);
187     if (resOpenssl != OPENSSL_SUCCESS) {
188         HKS_LOG_E("verify signature failed");
189     }
190 
191     EVP_PKEY_free(pubKey);
192     return (resOpenssl == OPENSSL_SUCCESS) ? HKS_SUCCESS : HKS_ERROR_VERIFICATION_FAILED;
193 }
194 
VerifyCertChain(const struct HksCertInfo * certs,uint32_t certNum)195 static int32_t VerifyCertChain(const struct HksCertInfo *certs, uint32_t certNum)
196 {
197     int32_t ret = HKS_ERROR_VERIFICATION_FAILED;
198     X509_STORE *store = X509_STORE_new();
199     X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new();
200     if ((store == NULL) || (verifyCtx == NULL)) {
201         HKS_LOG_E("verify cert chain init failed");
202         goto EXIT;
203     }
204 
205     for (uint32_t i = certNum - 1; i > 1; i--) { /* add root ca cert and device ca cert */
206         if (X509_STORE_add_cert(store, certs[i].x509) != OPENSSL_SUCCESS) {
207             HKS_LOG_E("add cert to store failed");
208             goto EXIT;
209         }
210     }
211 
212     int32_t resOpenssl = X509_STORE_CTX_init(verifyCtx, store, certs[1].x509, NULL); /* cert 1: add device cert */
213     if (resOpenssl != OPENSSL_SUCCESS) {
214         HKS_LOG_E("init verify ctx failed");
215         goto EXIT;
216     }
217 
218     resOpenssl = X509_verify_cert(verifyCtx);
219     if (resOpenssl != OPENSSL_SUCCESS) {
220         HKS_LOG_E("verify cert failed");
221         goto EXIT;
222     }
223 
224     ret = VerifySignature(&certs[certNum - 1], &certs[certNum - 1]); /* root ca cert need to be verified by itself */
225     HKS_IF_NOT_SUCC_LOGE(ret, "verify root cert failed")
226 
227 EXIT:
228     if (verifyCtx != NULL) {
229         X509_STORE_CTX_free(verifyCtx);
230     }
231     if (store != NULL) {
232         X509_STORE_free(store);
233     }
234     return ret;
235 }
236 
VerifyAttestationCertChain(struct HksCertInfo * certs,uint32_t certNum)237 static int32_t VerifyAttestationCertChain(struct HksCertInfo *certs, uint32_t certNum)
238 {
239     int32_t ret = TranslateToX509Format(certs, certNum);
240     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "translate to x509 format failed")
241 
242     ret = VerifyCertChain(certs, certNum);
243     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "verify attestation cert chain verify cert chain failed")
244 
245     /* use device cert's pubkey to verify the attestation cert */
246     ret = VerifySignature(&certs[0], &certs[1]); /* 0:attestation cert, 1:device cert */
247     HKS_IF_NOT_SUCC_LOGE(ret, "verify attestation cert chain signature failed")
248 
249     return ret;
250 }
251 
EncodeTlvAndGetLength(uint8_t ** buf,uint32_t * outLength,uint32_t inLen)252 static int32_t EncodeTlvAndGetLength(uint8_t **buf, uint32_t *outLength, uint32_t inLen)
253 {
254     uint32_t length = 0; /* length of the payload */
255 
256     uint32_t tmp;
257     HKS_ASN1_DECODE_BYTE(*buf, tmp); /* get type */
258     if ((*buf)[0] < ASN_1_MIN_VAL_1_EXTRA_LEN_BYTE) {
259         /* Current byte tells the length */
260         HKS_ASN1_DECODE_BYTE(*buf, length);
261     } else {
262         /* now bit 8 is set */
263         uint32_t b;
264         HKS_ASN1_DECODE_BYTE(*buf, b);
265 
266         switch (b) {
267             case ASN_1_TAG_TYPE_1_BYTE_LEN: /* 1 byte length */
268                 HKS_ASN1_DECODE_BYTE(*buf, length);
269                 break;
270             case ASN_1_TAG_TYPE_2_BYTE_LEN: /* 2 byte length */
271                 if (inLen < (ASN_1_MIN_HEADER_LEN + 1)) {
272                     HKS_LOG_E("invalid data to decode two bytes");
273                     return HKS_ERROR_INVALID_ARGUMENT;
274                 }
275                 HKS_ASN1_DECODE_TWO_BYTE(*buf, length);
276                 break;
277             default:
278                 HKS_LOG_E("Object length does not make sense");
279                 return HKS_ERROR_INVALID_ARGUMENT;
280         }
281     }
282     *outLength = length;
283     return HKS_SUCCESS;
284 }
285 
ExtractTlvLength(const uint8_t * in,uint32_t inLen,uint32_t * headSize,uint32_t * outLen)286 static int32_t ExtractTlvLength(const uint8_t *in, uint32_t inLen, uint32_t *headSize, uint32_t *outLen)
287 {
288     if ((in == NULL) || (inLen < ASN_1_MIN_HEADER_LEN) || (outLen == NULL)) {
289         HKS_LOG_E("invalid tlv data");
290         return HKS_ERROR_INVALID_ARGUMENT;
291     }
292 
293     uint8_t *buf = (uint8_t *)in;
294     uint32_t length = 0; /* length of the payload */
295 
296     int32_t ret = EncodeTlvAndGetLength(&buf, &length, inLen);
297     HKS_IF_NOT_SUCC_RETURN(ret, ret)
298 
299     *headSize = buf - in;
300     if (*headSize > inLen) {
301         HKS_LOG_E("the data is too small, extract failed");
302         return HKS_ERROR_BUFFER_TOO_SMALL;
303     }
304     /* Check that tag length can fit into buffer */
305     if (length > (inLen - *headSize)) {
306         HKS_LOG_E("data buffer is not big enough to hold %" LOG_PUBLIC "u bytes.", length);
307         return HKS_ERROR_INVALID_ARGUMENT;
308     }
309     *outLen = length;
310     return HKS_SUCCESS;
311 }
312 
ExtractTlvData(const uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t * outLen)313 static int32_t ExtractTlvData(const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen)
314 {
315     if ((in == NULL) || (inLen < ASN_1_MIN_HEADER_LEN) || (out == NULL) || (outLen == NULL)) {
316         HKS_LOG_E("invalid tlv data");
317         return HKS_ERROR_INVALID_ARGUMENT;
318     }
319 
320     uint8_t *buf = (uint8_t *)in;
321     uint32_t length = 0; /* length of the payload */
322 
323     int32_t ret = EncodeTlvAndGetLength(&buf, &length, inLen);
324     HKS_IF_NOT_SUCC_RETURN(ret, ret)
325 
326     uint32_t headSize = buf - in;
327     if (headSize > inLen) {
328         HKS_LOG_E("the data is too small, extract failed");
329         return HKS_ERROR_BUFFER_TOO_SMALL;
330     }
331     /* Check that tag length can fit into buffer */
332     if (length > (inLen - headSize)) {
333         HKS_LOG_E("data buffer is not big enough to hold %" LOG_PUBLIC "u bytes.", length);
334         return HKS_ERROR_INVALID_ARGUMENT;
335     }
336     if (memcpy_s(out, *outLen, buf, length) != EOK) {
337         HKS_LOG_E("extract tlv data memcpy_s failed");
338         return HKS_ERROR_INSUFFICIENT_MEMORY;
339     }
340     *outLen = length;
341     return HKS_SUCCESS;
342 }
343 
ExtractTlvDataAndHeadSize(const uint8_t * in,uint32_t inLen,uint8_t ** out,uint32_t * outLen,uint32_t * size)344 static int32_t ExtractTlvDataAndHeadSize(const uint8_t *in, uint32_t inLen,
345     uint8_t **out, uint32_t *outLen, uint32_t *size)
346 {
347     uint32_t headOffset = 0;
348     int32_t ret = ExtractTlvLength(in, inLen, &headOffset, outLen);
349     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "ExtractTlvLength fail!")
350     if (size != NULL) {
351         *size = headOffset;
352     }
353 
354     *out = (uint8_t *)HksMalloc(*outLen);
355     HKS_IF_NULL_LOGE_RETURN(*out, HKS_ERROR_MALLOC_FAIL, "malloc fail!")
356 
357     ret = ExtractTlvData(in, inLen, *out, outLen);
358     if (ret != HKS_SUCCESS) {
359         HKS_FREE(*out);
360         HKS_LOG_E("ExtractTlvData fail!");
361     }
362     return ret;
363 }
364 
GetObjByOid(int32_t nid,const char * oid,const char * sn,const char * ln)365 static ASN1_OBJECT *GetObjByOid(int32_t nid, const char *oid, const char *sn, const char *ln)
366 {
367     int32_t len;
368     ASN1_OBJECT *obj = NULL;
369     uint8_t *buf = NULL;
370     do {
371         len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
372         if (len <= 0) {
373             HKS_LOG_E("get a2d_ASN1_OBJECT fail, len1 = %" LOG_PUBLIC "d", len);
374             return NULL;
375         }
376 
377         buf = (uint8_t *)HksMalloc(len);
378         HKS_IF_NULL_LOGE_RETURN(buf, NULL, "openssl malloc fail")
379 
380         len = a2d_ASN1_OBJECT(buf, len, oid, -1);
381         if (len <= 0) {
382             HKS_LOG_E("get a2d_ASN1_OBJECT fail, len2 = %" LOG_PUBLIC "d", len);
383             break;
384         }
385 
386         obj = ASN1_OBJECT_create(nid, buf, len, sn, ln);
387         HKS_IF_NULL_LOGE_BREAK(obj, "ASN1_OBJECT_create fail")
388     } while (0);
389     HKS_FREE(buf);
390     return obj;
391 }
392 
GetKeyDescriptionSeqValue(const struct HksCertInfo * cert,uint8_t ** data,uint32_t * len)393 static int32_t GetKeyDescriptionSeqValue(const struct HksCertInfo *cert, uint8_t **data, uint32_t *len)
394 {
395     int32_t ret = HKS_ERROR_VERIFICATION_FAILED;
396     ASN1_OBJECT *obj = GetObjByOid(NID_undef, KEY_DESCRIPTION_OID, "KeyDescription", "KEY DESCRIPTION OID");
397     HKS_IF_NULL_LOGE_RETURN(obj, ret, "get obj by oid failed")
398 
399     int32_t idx = X509_get_ext_by_OBJ(cert->x509, obj, -1);
400     if (idx < 0) {
401         HKS_LOG_E("get ext idx by Obj failed");
402         goto EXIT;
403     }
404 
405     X509_EXTENSION *ext = X509_get_ext(cert->x509, idx);
406     if (ext == NULL) {
407         HKS_LOG_E("X509 get ext by idx failed");
408         goto EXIT;
409     }
410 
411     ASN1_OCTET_STRING *octetStr = X509_EXTENSION_get_data(ext);
412     if (octetStr == NULL) {
413         HKS_LOG_E("X509 extension get data by ext failed");
414         goto EXIT;
415     }
416 
417     // gain the Extension data of attest cert
418     ret = ExtractTlvDataAndHeadSize(octetStr->data, octetStr->length, data, len, NULL);
419     if (ret != HKS_SUCCESS) {
420         HKS_LOG_E("gain the extension data failed");
421         goto EXIT;
422     }
423 
424     if (*len >= MAX_ATTEST_EXTENSION_BUF_LEN) {
425         (void)memset_s(*data, *len, 0, *len);
426         HKS_FREE(*data);
427         HKS_LOG_E("the length of extension data is too long");
428         ret = HKS_ERROR_INSUFFICIENT_MEMORY;
429     }
430 
431 EXIT:
432     ASN1_OBJECT_free(obj);
433     return ret;
434 }
435 
ConstructParamSetOut(enum HksTag tag,uint8_t * data,uint32_t len,struct HksParamSet * paramSetOut)436 static int32_t ConstructParamSetOut(enum HksTag tag, uint8_t *data, uint32_t len, struct HksParamSet *paramSetOut)
437 {
438     int32_t ret;
439     for (uint32_t i = 0; i < paramSetOut->paramsCnt; i++) {
440         if ((paramSetOut->params[i].tag == tag) && (GetTagType(tag) == HKS_TAG_TYPE_BYTES)) {
441             if (tag == HKS_TAG_ATTESTATION_APPLICATION_ID) {
442                 // APPLICATION_ID_RAW_OID_LEN + APPLICATION_ID_HEADER_LEN + sizeof(appId)
443                 uint32_t appIdOffsetSize = APPLICATION_ID_RAW_OID_LEN + APPLICATION_ID_HEADER_LEN;
444                 ret = CopyBlobBuffer(data + appIdOffsetSize, len - appIdOffsetSize, &(paramSetOut->params[i].blob));
445                 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "CopyBlobBuffer failed")
446             } else {
447                 ret = CopyBlobBuffer(data, len, &(paramSetOut->params[i].blob));
448                 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "CopyBlobBuffer failed")
449             }
450             return HKS_SUCCESS;
451         }
452     }
453     return HKS_SUCCESS;
454 }
455 
GetClaimDataParamSet(uint8_t * data,uint32_t len,struct HksParamSet * paramSetOut)456 static int32_t GetClaimDataParamSet(uint8_t *data, uint32_t len, struct HksParamSet *paramSetOut)
457 {
458     for (uint32_t i = 0; i < sizeof(g_oidParams) / sizeof(g_oidParams[0]); i++) {
459         uint32_t offset = TLV_VERSION_NEED_SIZE;
460         uint8_t *claimData = NULL;
461         uint32_t claimSize = 0;
462         uint32_t headSize = 0;
463 
464         if ((offset > len) || ((len - offset) < g_oidParams[i].blob.size)) {
465             HKS_LOG_E("input param invalid, fail");
466             return HKS_ERROR_INVALID_ARGUMENT;
467         }
468 
469         if (HksMemCmp(g_oidParams[i].blob.data, data + offset, g_oidParams[i].blob.size) == 0) {
470             offset += g_oidParams[i].blob.size;
471             int32_t ret = ExtractTlvDataAndHeadSize(data + offset, len - offset, &claimData, &claimSize, &headSize);
472             HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_INVALID_ARGUMENT, "get cliam count fail")
473 
474             if (claimSize >= MAX_ATTEST_CLAIM_BUF_LEN) {
475                 HKS_LOG_E("the length of claim is too long");
476                 HKS_FREE(claimData);
477                 return HKS_ERROR_INSUFFICIENT_MEMORY;
478             }
479 
480             ret = ConstructParamSetOut(g_oidParams[i].tag, claimData, claimSize, paramSetOut);
481             if (ret != HKS_SUCCESS) {
482                 HKS_LOG_E("ConstructParamSetOut fail");
483                 HKS_FREE(claimData);
484                 return HKS_ERROR_INVALID_ARGUMENT;
485             }
486             HKS_FREE(claimData);
487             return HKS_SUCCESS;
488         }
489     }
490 
491     return HKS_SUCCESS;
492 }
493 
FillAttestExtendParamSet(uint8_t * data,uint32_t length,uint8_t version,struct HksParamSet * paramSetOut)494 static int32_t FillAttestExtendParamSet(uint8_t *data, uint32_t length,
495     uint8_t version, struct HksParamSet *paramSetOut)
496 {
497     if ((data == NULL) || (length < ASN_1_MIN_HEADER_LEN)) {
498         HKS_LOG_E("invalid argument data");
499         return HKS_ERROR_INVALID_ARGUMENT;
500     }
501     int32_t ret;
502     uint32_t headSize;
503     uint32_t leftSize = length;
504     uint8_t *tmp = data;
505 
506     for (headSize = 0; leftSize >= ASN_1_MIN_HEADER_LEN;) {
507         uint8_t *value = NULL;
508         uint32_t valueLength;
509         ret = ExtractTlvDataAndHeadSize(tmp, leftSize, &value, &valueLength, &headSize);
510         if (ret != HKS_SUCCESS || valueLength > (leftSize - headSize)
511             || leftSize < ASN_1_MIN_HEADER_LEN) {
512             HKS_FREE(value);
513             HKS_LOG_E("get claim count fail, the length of claim or the value of leftSize can be wrong, too");
514             return HKS_ERROR_INVALID_ARGUMENT;
515         }
516 
517         if (valueLength >= MAX_ATTEST_CLAIM_BUF_LEN) {
518             HKS_LOG_E("the length of claim is too long");
519             HKS_FREE(value);
520             return HKS_ERROR_INSUFFICIENT_MEMORY;
521         }
522 
523         ret = GetClaimDataParamSet(value, valueLength, paramSetOut);
524         if (ret != HKS_SUCCESS) {
525             HKS_LOG_E("GetClaimDataParamSet failed, ret = %" LOG_PUBLIC "d", ret);
526             HKS_FREE(value);
527             return ret;
528         }
529         HKS_FREE(value);
530         tmp += (valueLength + headSize);
531         leftSize -= (valueLength + headSize);
532     }
533     return HKS_SUCCESS;
534 }
535 
FillAttestExtendInfo(uint8_t * data,uint32_t length,struct HksParamSet * paramSetOut)536 static int32_t FillAttestExtendInfo(uint8_t *data, uint32_t length, struct HksParamSet *paramSetOut)
537 {
538     if ((data == NULL) || (length < ASN_1_MIN_HEADER_LEN) || (length <= TLV_VERSION_NEED_SIZE)) {
539         HKS_LOG_E("invalid argument data");
540         return HKS_ERROR_INVALID_ARGUMENT;
541     }
542 
543     uint8_t *version = NULL;
544     uint32_t len;
545     int32_t ret = ExtractTlvDataAndHeadSize(data, length, &version, &len, NULL);
546     if (ret != HKS_SUCCESS || len != sizeof(uint8_t)) {
547         HKS_FREE(version);
548         HKS_LOG_E("get version fail or length is not equal to sizeof(uint8_t)");
549         return HKS_ERROR_INVALID_ARGUMENT;
550     }
551 
552     ret = FillAttestExtendParamSet(data + TLV_VERSION_NEED_SIZE, length - TLV_VERSION_NEED_SIZE,
553         *version, paramSetOut);
554     HKS_IF_NOT_SUCC_LOGE(ret, "fill attest extend paramSet fail")
555 
556     HKS_FREE(version);
557     return ret;
558 }
559 
GetParamSetOutInfo(const struct HksCertInfo * certs,struct HksParamSet * paramSetOut)560 static int32_t GetParamSetOutInfo(const struct HksCertInfo *certs, struct HksParamSet *paramSetOut)
561 {
562     uint8_t *keyDescription = NULL;
563     uint32_t keyDescLen;
564 
565     int32_t ret = GetKeyDescriptionSeqValue(&certs[0], &keyDescription, &keyDescLen);
566     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "GetKeyDescriptionSeqValue failed")
567 
568     ret = FillAttestExtendInfo(keyDescription, keyDescLen, paramSetOut);
569     HKS_IF_NOT_SUCC_LOGE(ret, "fill attest extend info fail")
570 
571     (void)memset_s(keyDescription, keyDescLen, 0, keyDescLen);
572     HKS_FREE(keyDescription);
573     return ret;
574 }
575 
InitCertChainInfo(const struct HksCertChain * certChain,struct HksCertInfo ** certs)576 static int32_t InitCertChainInfo(const struct HksCertChain *certChain, struct HksCertInfo **certs)
577 {
578     int32_t ret = HKS_SUCCESS;
579 
580     uint32_t certsInfoLen = sizeof(struct HksCertInfo) * certChain->certsCount; /* only 4 cert */
581     struct HksCertInfo *certsInfo = (struct HksCertInfo *)HksMalloc(certsInfoLen);
582     HKS_IF_NULL_RETURN(certsInfo, HKS_ERROR_MALLOC_FAIL)
583 
584     (void)memset_s(certsInfo, certsInfoLen, 0, certsInfoLen);
585 
586     for (uint32_t i = 0; i < certChain->certsCount; ++i) {
587         struct HksCertInfo *cert = &(certsInfo[i]);
588         cert->data = certChain->certs[i].data;
589         cert->length = certChain->certs[i].size;
590 
591         if (cert->data[0] == '-') {
592             cert->format = HKS_CERT_PEM;
593         } else if (cert->data[0] == ASN_1_TAG_TYPE_SEQ) {
594             cert->format = HKS_CERT_DER;
595         } else {
596             HKS_LOG_E("validate cert chain invalid cert format");
597             ret = HKS_ERROR_VERIFICATION_FAILED;
598             break;
599         }
600     }
601 
602     if (ret != HKS_SUCCESS) {
603         HKS_FREE(certsInfo);
604         return ret;
605     }
606     *certs = certsInfo;
607     return HKS_SUCCESS;
608 }
609 
FreeCertChainInfo(struct HksCertInfo ** certs,uint32_t certNum)610 static void FreeCertChainInfo(struct HksCertInfo **certs, uint32_t certNum)
611 {
612     if (*certs != NULL) {
613         for (uint32_t i = 0; i < certNum; ++i) {
614             if ((*certs)[i].x509 != NULL) {
615                 X509_free((*certs)[i].x509);
616             }
617         }
618         HKS_FREE(*certs);
619     }
620 }
621 
CheckCertChainParams(const struct HksCertChain * certChain)622 static int32_t CheckCertChainParams(const struct HksCertChain *certChain)
623 {
624     /* certChain has been checked not null */
625     if ((certChain->certs == NULL) || (certChain->certsCount != HKS_DEFAULT_CERT_CHAIN_CNT)) {
626         HKS_LOG_E("validate cert chain chain invalid certChain or count");
627         return HKS_ERROR_INVALID_ARGUMENT;
628     }
629 
630     for (uint32_t i = 0; i < certChain->certsCount; ++i) {
631         if (CheckBlob(&certChain->certs[i]) != HKS_SUCCESS) {
632             HKS_LOG_E("certChain entry[%" LOG_PUBLIC "u] invalid", i);
633             return HKS_ERROR_INVALID_ARGUMENT;
634         }
635     }
636     return HKS_SUCCESS;
637 }
638 
CheckValidateCertChainParams(const struct HksCertChain * certChain,struct HksParamSet * paramSetOut)639 static int32_t CheckValidateCertChainParams(const struct HksCertChain *certChain, struct HksParamSet *paramSetOut)
640 {
641     int32_t ret = CheckCertChainParams(certChain);
642     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "certChain invalid, ret = %" LOG_PUBLIC "d", ret)
643 
644     /* paramSetOut has been checked not null */
645     ret = HksCheckParamSet(paramSetOut, paramSetOut->paramSetSize);
646     HKS_IF_NOT_SUCC_LOGE(ret, "paramSetOut invalid, ret = %" LOG_PUBLIC "d", ret)
647     return ret;
648 }
649 
HksClientValidateCertChain(const struct HksCertChain * certChain,struct HksParamSet * paramSetOut)650 int32_t HksClientValidateCertChain(const struct HksCertChain *certChain, struct HksParamSet *paramSetOut)
651 {
652     int32_t ret = CheckValidateCertChainParams(certChain, paramSetOut);
653     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "certChain params check failed, ret = %" LOG_PUBLIC "d", ret)
654 
655     struct HksCertInfo *certsInfo = NULL;
656     ret = InitCertChainInfo(certChain, &certsInfo);
657     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get cert chain info failed")
658     ret = VerifyAttestationCertChain(certsInfo, certChain->certsCount);
659     if (ret != HKS_SUCCESS) {
660         FreeCertChainInfo(&certsInfo, certChain->certsCount);
661         HKS_LOG_E("VerifyAttestationCertChain failed, ret = %" LOG_PUBLIC "d", ret);
662         return ret;
663     }
664 
665     ret = GetParamSetOutInfo(certsInfo, paramSetOut);
666     HKS_IF_NOT_SUCC_LOGE(ret, "VerifyAttestationCertChain failed, ret = %" LOG_PUBLIC "d", ret)
667 
668     FreeCertChainInfo(&certsInfo, certChain->certsCount);
669     return ret;
670 }
671