已关闭
fix(pki): harden X509 verification for certificate version #1657
balabala-123创建于 7月7日关闭于 7月15日
fix(pki): harden X509 verification for certificate version #1657
已关闭
balabala-123创建于 7月7日关闭于 7月15日
17 个文件变更+549-32
Minclude/pki/hitls_pki_errno.h+3-0
@@ -40,6 +40,9 @@ typedef enum {
40 HITLS_X509_ERR_VFY_AKI_SKI_NOT_MATCH,40 HITLS_X509_ERR_VFY_AKI_SKI_NOT_MATCH,
41 HITLS_X509_ERR_VFY_ERR_SM2_USER_ID,41 HITLS_X509_ERR_VFY_ERR_SM2_USER_ID,
42 HITLS_X509_ERR_KU_IS_NONE,42 HITLS_X509_ERR_KU_IS_NONE,
43+ HITLS_X509_ERR_VFY_INVALID_CA,
44+ HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION,
45+ HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS,
43 46 
44 HITLS_X509_ERR_CERT_NOT_CA = 0x04010001,47 HITLS_X509_ERR_CERT_NOT_CA = 0x04010001,
45 HITLS_X509_ERR_CERT_EXIST,48 HITLS_X509_ERR_CERT_EXIST,
Mpki/x509_cert/src/hitls_x509_cert.c+1-12
@@ -817,18 +817,6 @@ int32_t HITLS_X509_CheckIssued(HITLS_X509_Cert *issue, HITLS_X509_Cert *subject,
817 }817 }
818 }818 }
819 819 
820- /**
821- * If the basic constraints extension is not present in a version 3 certificate,
822- * or the extension is present but the cA boolean is not asserted,
823- * then the certified public key MUST NOT be used to verify certificate signatures.
824- */
825- HITLS_X509_CertExt *certExt = (HITLS_X509_CertExt *)issue->tbs.ext.extData;
826- if (issue->tbs.version == HITLS_X509_VERSION_3 && ((certExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 ||
827- !certExt->isCa)) {
828- BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_CERT_NOT_CA);
829- return HITLS_X509_ERR_CERT_NOT_CA;
830- }
831- 
832 ret = HITLS_X509_CheckAlg(issue->tbs.ealPubKey, &subject->tbs.signAlgId);820 ret = HITLS_X509_CheckAlg(issue->tbs.ealPubKey, &subject->tbs.signAlgId);
833 if (ret != HITLS_PKI_SUCCESS) {821 if (ret != HITLS_PKI_SUCCESS) {
834 BSL_ERR_PUSH_ERROR(ret);822 BSL_ERR_PUSH_ERROR(ret);
@@ -839,6 +827,7 @@ int32_t HITLS_X509_CheckIssued(HITLS_X509_Cert *issue, HITLS_X509_Cert *subject,
839 * in certificates that contain public keys that are used to validate digital signatures on827 * in certificates that contain public keys that are used to validate digital signatures on
840 * other public key certificates or CRLs.828 * other public key certificates or CRLs.
841 */829 */
830+ HITLS_X509_CertExt *certExt = (HITLS_X509_CertExt *)issue->tbs.ext.extData;
842 if ((certExt->extFlags & HITLS_X509_EXT_FLAG_KUSAGE) != 0) {831 if ((certExt->extFlags & HITLS_X509_EXT_FLAG_KUSAGE) != 0) {
843 if (((certExt->keyUsage & HITLS_X509_EXT_KU_KEY_CERT_SIGN)) == 0) {832 if (((certExt->keyUsage & HITLS_X509_EXT_KU_KEY_CERT_SIGN)) == 0) {
844 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_KU_NO_CERTSIGN);833 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_KU_NO_CERTSIGN);
Mpki/x509_verify/src/hitls_x509_verify.c+50-5
@@ -90,12 +90,12 @@ void HITLS_X509_StoreCtxFree(HITLS_X509_StoreCtx *storeCtx)
90#endif90#endif
91 BSL_LIST_FREE(storeCtx->store, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);91 BSL_LIST_FREE(storeCtx->store, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
92 BSL_LIST_FREE(storeCtx->crl, (BSL_LIST_PFUNC_FREE)HITLS_X509_CrlFree);92 BSL_LIST_FREE(storeCtx->crl, (BSL_LIST_PFUNC_FREE)HITLS_X509_CrlFree);
93- 93+ 
94 // Free CA paths list94 // Free CA paths list
95 if (storeCtx->caPaths != NULL) {95 if (storeCtx->caPaths != NULL) {
96 BSL_LIST_FREE(storeCtx->caPaths, (BSL_LIST_PFUNC_FREE)BSL_SAL_Free);96 BSL_LIST_FREE(storeCtx->caPaths, (BSL_LIST_PFUNC_FREE)BSL_SAL_Free);
97 }97 }
98- 98+ 
99 BSL_SAL_ReferencesFree(&storeCtx->references);99 BSL_SAL_ReferencesFree(&storeCtx->references);
100 BSL_SAL_Free(storeCtx);100 BSL_SAL_Free(storeCtx);
101}101}
@@ -150,7 +150,7 @@ HITLS_X509_StoreCtx *HITLS_X509_StoreCtxNew(void)
150 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);150 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
151 return NULL;151 return NULL;
152 }152 }
153- 153+ 
154 // Initialize CA paths list154 // Initialize CA paths list
155 ctx->caPaths = BSL_LIST_New(sizeof(char *));155 ctx->caPaths = BSL_LIST_New(sizeof(char *));
156 if (ctx->caPaths == NULL) {156 if (ctx->caPaths == NULL) {
@@ -501,7 +501,7 @@ static int32_t HITLS_X509_GetCertBySubjectDer(HITLS_X509_StoreCtx *storeCtx, con
501 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);501 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);
502 return HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND;502 return HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND;
503 }503 }
504- 504+ 
505 // Calculate hash from canon-encoded subject DN505 // Calculate hash from canon-encoded subject DN
506 uint32_t hash = 0;506 uint32_t hash = 0;
507 uint8_t digest[CRYPT_SHA1_DIGESTSIZE];507 uint8_t digest[CRYPT_SHA1_DIGESTSIZE];
@@ -523,7 +523,7 @@ static int32_t HITLS_X509_GetCertBySubjectDer(HITLS_X509_StoreCtx *storeCtx, con
523 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);523 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);
524 return HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND;524 return HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND;
525 }525 }
526- 526+ 
527 // Try to load certificate using hash-based file lookup from CA paths527 // Try to load certificate using hash-based file lookup from CA paths
528 char *caPath = BSL_LIST_GET_FIRST(storeCtx->caPaths);528 char *caPath = BSL_LIST_GET_FIRST(storeCtx->caPaths);
529 while (caPath != NULL) {529 while (caPath != NULL) {
@@ -945,6 +945,46 @@ static int32_t X509_GetVerifyCertChain(HITLS_X509_StoreCtx *storeCtx, HITLS_X509
945 return HITLS_PKI_SUCCESS;945 return HITLS_PKI_SUCCESS;
946}946}
947 947 
948+int32_t X509_CheckExt(HITLS_X509_List *chain)
949+{
950+ int32_t rootDepth = BSL_LIST_COUNT(chain) - 1;
951+ int32_t curDepth = rootDepth;
952+ HITLS_X509_Cert *cur = BSL_LIST_GET_LAST(chain);
953+ 
954+ while (cur != NULL) {
955+ HITLS_X509_CertExt *curExt = (HITLS_X509_CertExt *)cur->tbs.ext.extData;
956+ 
957+ if (curDepth > 0) { // CA certificates (root and intermediate)
958+ /** RFC 5280 Section 6.1.4:
959+ * (k) If certificate i is a version 3 certificate, verify that the basicConstraints extension is
960+ * present and that cA is set to TRUE. (If certificate i is a version 1 or version 2 certificate,
961+ * then the application MUST either verify that certificate i is a CA certificate through
962+ * out-of-band means or reject the certificate. Conforming implementations may choose to reject
963+ * all version 1 and version 2 intermediate certificates.)
964+ */
965+ if (curDepth == rootDepth) {
B
Bbaoyi849307月8日

[Code Guarder][high][likely] BasicConstraints pathLenConstraint is not enforced in chain verification

  • Severity: high
  • Confidence: likely
  • Reviewers: X
  • Location: pki/x509_verify/src/hitls_x509_verify.c:957-977

Problem HITLS_X509_CertExt::maxPathLen is populated during extension parsing but X509_CheckExt never enforces it. A CA cert with pathLenConstraint=0 can still be accepted while allowing another intermediate CA below it, violating RFC 5280 chain depth semantics for path length.

Code

if (curDepth == rootDepth) {
    if (((cur->tbs.version == HITLS_X509_VERSION_3) &&
         ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa))) {
        return HITLS_X509_ERR_VFY_INVALID_CA;
    }
} else {
    if (cur->tbs.version != HITLS_X509_VERSION_3) {
        return HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION;
    }
    if ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa) {
        return HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS;
    }
}

Suggested Fix

if (cur->tbs.version == HITLS_X509_VERSION_3 && curExt->maxPathLen >= 0) {
    int32_t caBelow = curDepth - 1; // number of CA certs below current cert
    if (caBelow > curExt->maxPathLen) {
        BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INVALID_CA);
        return HITLS_X509_ERR_VFY_INVALID_CA;
    }
}
likedislike
balabala-123
7月14日 评论:
966+ if (((cur->tbs.version == HITLS_X509_VERSION_3) &&
967+ ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa))) {
968+ BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INVALID_CA);
969+ return HITLS_X509_ERR_VFY_INVALID_CA;
970+ }
971+ } else {
972+ if (cur->tbs.version != HITLS_X509_VERSION_3) {
973+ BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION);
974+ return HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION;
975+ }
976+ if ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa) {
977+ BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS);
978+ return HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS;
B
Bbaoyi849307月8日

[Code Guarder][medium][likely] X509_CheckExt returns verification errors without pushing to error stack

  • Severity: medium
  • Confidence: likely
  • Reviewers: O
  • Location: pki/x509_verify/src/hitls_x509_verify.c:968-975

Problem New verification checks in X509_CheckExt return distinct HITLS_X509_ERR_* values, but do not call BSL_ERR_PUSH_ERROR. This drops structured error context for callers that rely on the error stack for diagnostics/logging, unlike adjacent verification paths that always push before returning.

Code

if (curDepth == rootDepth) {
    if (((cur->tbs.version == HITLS_X509_VERSION_3) &&
         ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa))) {
        return HITLS_X509_ERR_VFY_INVALID_CA;
    }
} else {
    if (cur->tbs.version != HITLS_X509_VERSION_3) {
        return HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION;
    }
    if ((curExt->extFlags & HITLS_X509_EXT_FLAG_BCONS) == 0 || !curExt->isCa) {
        return HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS;
    }
}

Suggested Fix

BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INVALID_CA);
return HITLS_X509_ERR_VFY_INVALID_CA;
...
BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION);
return HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION;
...
BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS);
return HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS;
likedislike
balabala-123
7月14日 评论:
979+ }
980+ }
981+ }
982+ cur = BSL_LIST_GET_PREV(chain);
983+ curDepth--;
984+ }
985+ return HITLS_PKI_SUCCESS;
986+}
987+ 
948int32_t HITLS_X509_CertVerify(HITLS_X509_StoreCtx *storeCtx, HITLS_X509_List *chain)988int32_t HITLS_X509_CertVerify(HITLS_X509_StoreCtx *storeCtx, HITLS_X509_List *chain)
949{989{
950 if (storeCtx == NULL || chain == NULL) {990 if (storeCtx == NULL || chain == NULL) {
@@ -965,6 +1005,11 @@ int32_t HITLS_X509_CertVerify(HITLS_X509_StoreCtx *storeCtx, HITLS_X509_List *ch
965 BSL_LIST_FREE(tmpChain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);1005 BSL_LIST_FREE(tmpChain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
966 return ret;1006 return ret;
967 }1007 }
1008+ ret = X509_CheckExt(tmpChain);
1009+ if (ret != HITLS_PKI_SUCCESS) {
1010+ BSL_LIST_FREE(tmpChain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
1011+ return ret;
1012+ }
968 ret = HITLS_X509_VerifyCrl(storeCtx, tmpChain);1013 ret = HITLS_X509_VerifyCrl(storeCtx, tmpChain);
969 if (ret != HITLS_PKI_SUCCESS) {1014 if (ret != HITLS_PKI_SUCCESS) {
970 BSL_LIST_FREE(tmpChain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);1015 BSL_LIST_FREE(tmpChain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
Mtestcode/sdv/testcase/pki/verify/test_suite_sdv_x509_vfy.c+69-14
@@ -287,7 +287,7 @@ void SDV_X509_BUILD_CERT_CHAIN_FUNC_TC001(char *rootPath, char *caPath, char *ce
287 287 
288 ASSERT_TRUE(HITLS_AddCertToStoreTest(cert, store, &entity) != HITLS_PKI_SUCCESS);288 ASSERT_TRUE(HITLS_AddCertToStoreTest(cert, store, &entity) != HITLS_PKI_SUCCESS);
289 ASSERT_EQ(HITLS_AddCrlToStoreTest(crlPath, store, &crl), HITLS_PKI_SUCCESS);289 ASSERT_EQ(HITLS_AddCrlToStoreTest(crlPath, store, &crl), HITLS_PKI_SUCCESS);
290- 290+ 
291 ASSERT_EQ(BSL_LIST_COUNT(store->crl), 1);291 ASSERT_EQ(BSL_LIST_COUNT(store->crl), 1);
292 if (withIntCa) {292 if (withIntCa) {
293 ASSERT_EQ(BSL_LIST_COUNT(store->store), 2);293 ASSERT_EQ(BSL_LIST_COUNT(store->store), 2);
@@ -680,7 +680,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_FUNC_TC001(void)
680 TestMemInit();680 TestMemInit();
681 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();681 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
682 ASSERT_NE(storeCtx, NULL);682 ASSERT_NE(storeCtx, NULL);
683- 683+ 
684 // Test adding additional CA path684 // Test adding additional CA path
685 const char *testPath1 = "/usr/local/ssl/certs";685 const char *testPath1 = "/usr/local/ssl/certs";
686 int32_t ret =686 int32_t ret =
@@ -689,7 +689,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_FUNC_TC001(void)
689 689 
690 ret = HITLS_X509_StoreCtxCtrl(NULL, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)testPath1, strlen(testPath1));690 ret = HITLS_X509_StoreCtxCtrl(NULL, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)testPath1, strlen(testPath1));
691 ASSERT_EQ(ret, HITLS_X509_ERR_INVALID_PARAM);691 ASSERT_EQ(ret, HITLS_X509_ERR_INVALID_PARAM);
692- 692+ 
693 ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH,693 ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH,
694 NULL, strlen(testPath1));694 NULL, strlen(testPath1));
695 ASSERT_EQ(ret, HITLS_X509_ERR_INVALID_PARAM);695 ASSERT_EQ(ret, HITLS_X509_ERR_INVALID_PARAM);
@@ -715,7 +715,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC001(void)
715 HITLS_X509_List *chain = NULL;715 HITLS_X509_List *chain = NULL;
716 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();716 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
717 ASSERT_NE(storeCtx, NULL);717 ASSERT_NE(storeCtx, NULL);
718- 718+ 
719 // Add additional CA paths719 // Add additional CA paths
720 const char *caPath = "../testdata/tls/certificate/pem/rsa_sha256";720 const char *caPath = "../testdata/tls/certificate/pem/rsa_sha256";
721 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));721 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));
@@ -725,7 +725,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC001(void)
725 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";725 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";
726 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);726 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);
727 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);727 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
728- 728+ 
729 // Build certificate chain with on-demand CA loading from multiple paths729 // Build certificate chain with on-demand CA loading from multiple paths
730 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);730 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);
731 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);731 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
@@ -733,7 +733,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC001(void)
733 733 
734 uint32_t chainLength = BSL_LIST_COUNT(chain);734 uint32_t chainLength = BSL_LIST_COUNT(chain);
735 ASSERT_TRUE(chainLength >= 1);735 ASSERT_TRUE(chainLength >= 1);
736- 736+ 
737 // Verify the certificate chain737 // Verify the certificate chain
738 ret = HITLS_X509_CertVerify(storeCtx, chain);738 ret = HITLS_X509_CertVerify(storeCtx, chain);
739 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);739 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
@@ -752,7 +752,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC002(void)
752 HITLS_X509_List *chain = NULL;752 HITLS_X509_List *chain = NULL;
753 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();753 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
754 ASSERT_NE(storeCtx, NULL);754 ASSERT_NE(storeCtx, NULL);
755- 755+ 
756 // Add additional CA paths756 // Add additional CA paths
757 const char *caPath = "../testdata/tls/certificate/pem/ed25519";757 const char *caPath = "../testdata/tls/certificate/pem/ed25519";
758 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));758 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));
@@ -762,7 +762,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC002(void)
762 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";762 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";
763 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);763 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);
764 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);764 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
765- 765+ 
766 // Build certificate chain with on-demand CA loading from multiple paths766 // Build certificate chain with on-demand CA loading from multiple paths
767 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);767 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);
768 ASSERT_EQ(ret, HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);768 ASSERT_EQ(ret, HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND);
@@ -781,7 +781,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC003(void)
781 HITLS_X509_List *chain = NULL;781 HITLS_X509_List *chain = NULL;
782 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();782 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
783 ASSERT_NE(storeCtx, NULL);783 ASSERT_NE(storeCtx, NULL);
784- 784+ 
785 // Add additional CA paths785 // Add additional CA paths
786 const char *caPath = "../testdata/tls/certificate/pem/test_dir";786 const char *caPath = "../testdata/tls/certificate/pem/test_dir";
787 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));787 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));
@@ -791,7 +791,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC003(void)
791 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";791 const char *certToVerify = "../testdata/tls/certificate/pem/rsa_sha256/client.pem";
792 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);792 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);
793 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);793 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
794- 794+ 
795 // Build certificate chain with on-demand CA loading from multiple paths795 // Build certificate chain with on-demand CA loading from multiple paths
796 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);796 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);
797 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);797 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
@@ -811,7 +811,7 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC004(void)
811 HITLS_X509_List *chain = NULL;811 HITLS_X509_List *chain = NULL;
812 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();812 HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
813 ASSERT_NE(storeCtx, NULL);813 ASSERT_NE(storeCtx, NULL);
814- 814+ 
815 // Add additional CA paths815 // Add additional CA paths
816 const char *caPath = "../testdata/tls/certificate/pem/test_dir";816 const char *caPath = "../testdata/tls/certificate/pem/test_dir";
817 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));817 int32_t ret = HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_ADD_CA_PATH, (void *)caPath, strlen(caPath));
@@ -819,10 +819,10 @@ void SDV_X509_STORE_LOAD_CA_PATH_CHAIN_BUILD_TC004(void)
819 819 
820 // Load the certificate to be verified820 // Load the certificate to be verified
821 const char *certToVerify = "../testdata/tls/certificate/pem/ecdsa_sha256/client.pem";821 const char *certToVerify = "../testdata/tls/certificate/pem/ecdsa_sha256/client.pem";
822- 822+ 
823 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);823 ret = HITLS_X509_CertParseFile(BSL_FORMAT_PEM, certToVerify, &cert);
824 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);824 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
825- 825+ 
826 // Build certificate chain with on-demand CA loading from multiple paths826 // Build certificate chain with on-demand CA loading from multiple paths
827 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);827 ret = HITLS_X509_CertChainBuild(storeCtx, true, cert, &chain);
828 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);828 ASSERT_EQ(ret, HITLS_PKI_SUCCESS);
@@ -856,7 +856,7 @@ void SDV_X509_VFY_AKI_SKI_CRITICAL_PASS_TC007(void)
856 "../testdata/cert/chain/akiski_suite/aki_leaf_critical.pem", &leaf), HITLS_PKI_SUCCESS);856 "../testdata/cert/chain/akiski_suite/aki_leaf_critical.pem", &leaf), HITLS_PKI_SUCCESS);
857 HITLS_X509_List *chain = BSL_LIST_New(sizeof(HITLS_X509_Cert *));857 HITLS_X509_List *chain = BSL_LIST_New(sizeof(HITLS_X509_Cert *));
858 ASSERT_NE(chain, NULL);858 ASSERT_NE(chain, NULL);
859- 859+ 
860 ASSERT_EQ(X509_AddCertToChainTest(chain, leaf), HITLS_PKI_SUCCESS);860 ASSERT_EQ(X509_AddCertToChainTest(chain, leaf), HITLS_PKI_SUCCESS);
861 ASSERT_EQ(X509_AddCertToChainTest(chain, inter), HITLS_PKI_SUCCESS);861 ASSERT_EQ(X509_AddCertToChainTest(chain, inter), HITLS_PKI_SUCCESS);
862 ASSERT_EQ(X509_AddCertToChainTest(chain, root), HITLS_PKI_SUCCESS);862 ASSERT_EQ(X509_AddCertToChainTest(chain, root), HITLS_PKI_SUCCESS);
@@ -1026,3 +1026,58 @@ EXIT:
1026 BSL_LIST_FREE(chain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);1026 BSL_LIST_FREE(chain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
1027}1027}
1028/* END_CASE */1028/* END_CASE */
1029+ 
1030+/**
1031+ * @test SDV_X509_VFY_V1_INTER_CA_TC001
1032+ * @title v1/v2 non-trust-anchor intermediate CAs must be rejected; v1 trust anchors must be accepted.
1033+ * @brief
1034+ * TC1: v1 intermediate (no extensions) in chain → HITLS_X509_ERR_VFY_INVALID_CA
1035+ * TC2: v2 intermediate (no extensions) in chain → HITLS_X509_ERR_VFY_INVALID_CA
1036+ * TC3: v1 self-signed root (no extensions) as trust anchor → HITLS_PKI_SUCCESS
1037+ * @expect
1038+ * TC1/TC2: HITLS_X509_ERR_VFY_INVALID_CA
1039+ * TC3: HITLS_PKI_SUCCESS
1040+ */
1041+/* BEGIN_CASE */
1042+void SDV_X509_VFY_V1_INTER_CA_TC001(char *leafPath, char *interPath, char *rootPath, int exp)
1043+{
1044+#ifdef HITLS_PKI_X509_VFY
1045+ TestMemInit();
1046+ HITLS_X509_Cert *root = NULL;
1047+ HITLS_X509_Cert *inter = NULL;
1048+ HITLS_X509_Cert *leaf = NULL;
1049+ 
1050+ HITLS_X509_StoreCtx *storeCtx = HITLS_X509_StoreCtxNew();
1051+ HITLS_X509_List *chain = BSL_LIST_New(sizeof(HITLS_X509_Cert *));
1052+ ASSERT_TRUE(storeCtx != NULL && chain != NULL);
1053+ 
1054+ ASSERT_EQ(HITLS_X509_CertParseFile(BSL_FORMAT_UNKNOWN, leafPath, &leaf), HITLS_PKI_SUCCESS);
1055+ ASSERT_EQ(HITLS_X509_CertParseFile(BSL_FORMAT_UNKNOWN, rootPath, &root), HITLS_PKI_SUCCESS);
1056+ 
1057+ ASSERT_EQ(X509_AddCertToChainTest(chain, leaf), HITLS_PKI_SUCCESS);
1058+ if (strlen(interPath) > 0) {
1059+ ASSERT_EQ(HITLS_X509_CertParseFile(BSL_FORMAT_UNKNOWN, interPath, &inter), HITLS_PKI_SUCCESS);
1060+ ASSERT_EQ(X509_AddCertToChainTest(chain, inter), HITLS_PKI_SUCCESS);
1061+ }
1062+ ASSERT_EQ(X509_AddCertToChainTest(chain, root), HITLS_PKI_SUCCESS);
1063+ 
1064+ ASSERT_EQ(HITLS_X509_StoreCtxCtrl(storeCtx, HITLS_X509_STORECTX_DEEP_COPY_SET_CA, root, sizeof(HITLS_X509_Cert)), 0);
1065+ 
1066+ ASSERT_EQ(HITLS_X509_CertVerify(storeCtx, chain), exp);
1067+EXIT:
1068+ HITLS_X509_StoreCtxFree(storeCtx);
1069+ if (chain != NULL) {
1070+ BSL_LIST_FREE(chain, (BSL_LIST_PFUNC_FREE)HITLS_X509_CertFree);
1071+ }
1072+ HITLS_X509_CertFree(leaf);
1073+ HITLS_X509_CertFree(inter);
1074+ HITLS_X509_CertFree(root);
1075+#else
1076+ (void)leafPath;
1077+ (void)interPath;
1078+ (void)rootPath;
1079+ (void)exp;
1080+ SKIP_TEST();
1081+#endif
1082+}
1083+/* END_CASE */
Mtestcode/sdv/testcase/pki/verify/test_suite_sdv_x509_vfy.data+16-1
@@ -66,7 +66,7 @@ SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":"..
66 66 
67SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test crl have no cacrl vfy all67SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test crl have no cacrl vfy all
68SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":"../testdata/cert/chain/rsa-v3/inter.der":"../testdata/cert/chain/rsa-v3/end.der":"":"../testdata/cert/chain/rsa-v3/crl_v2.old.der":HITLS_X509_VFY_FLAG_CRL_ALL:HITLS_X509_ERR_CRL_NOT_FOUND68SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":"../testdata/cert/chain/rsa-v3/inter.der":"../testdata/cert/chain/rsa-v3/end.der":"":"../testdata/cert/chain/rsa-v3/crl_v2.old.der":HITLS_X509_VFY_FLAG_CRL_ALL:HITLS_X509_ERR_CRL_NOT_FOUND
69- 69+ 
70SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test revoke endcert70SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test revoke endcert
71SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":"../testdata/cert/chain/rsa-v3/inter.der":"../testdata/cert/chain/rsa-v3/end.der":"":"../testdata/cert/chain/rsa-v3/crl_v1.der":HITLS_X509_VFY_FLAG_CRL_DEV:HITLS_X509_ERR_VFY_CERT_REVOKED71SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":"../testdata/cert/chain/rsa-v3/inter.der":"../testdata/cert/chain/rsa-v3/end.der":"":"../testdata/cert/chain/rsa-v3/crl_v1.der":HITLS_X509_VFY_FLAG_CRL_DEV:HITLS_X509_ERR_VFY_CERT_REVOKED
72 72 
@@ -124,3 +124,18 @@ SDV_X509_CERT_VERIFY_BY_PUBKEY_FUNC_TC001:"../testdata/cert/chain/verify/rsa_cer
124SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001 prevent aftertime bypass by flag tampering124SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001 prevent aftertime bypass by flag tampering
125SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001:"../testdata/cert/chain/verify/aftertime_ca.der":"../testdata/cert/chain/verify/aftertime_cert.der":"../testdata/cert/chain/verify/aftertime_crl.der"125SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001:"../testdata/cert/chain/verify/aftertime_ca.der":"../testdata/cert/chain/verify/aftertime_cert.der":"../testdata/cert/chain/verify/aftertime_crl.der"
126 126 
127+SDV_X509_VFY_V1_INTER_CA_TC001: TC1 v1 intermediate without extensions rejected
B
Bbaoyi849307月8日

[Code Guarder][low][trusted] Added depth_suite certificate fixtures are unused by verification tests

  • Severity: low
  • Confidence: trusted
  • Reviewers: O
  • Location: testcode/sdv/testcase/pki/verify/test_suite_sdv_x509_vfy.data:127-140

Problem Certificate files under testcode/testdata/cert/chain/bcExt/depth_suite/ are added in the PR but no .data entry binds them to a runnable test case, so these artifacts are dead code/test data and unvalidated.

Code

SDV_X509_VFY_V1_INTER_CA_TC001: TC1 v1 intermediate without extensions rejected
SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/v1_inter/v3_leaf.der":"../testdata/cert/chain/v1_inter/v1_inter.der":"../testdata/cert/chain/v1_inter/v3_root.der":HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION
...
SDV_X509_VFY_V1_INTER_CA_TC001: TC5 v3 intermediate BasicConstraints CA=false
SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/bcExt/bc_leaf_ca_false.pem":"../testdata/cert/chain/bcExt/bc_inter_ca_false.pem":"../testdata/cert/chain/bcExt/bc_root_general.pem":HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS

Suggested Fix

Add depth_suite entries to this .data file and corresponding test cases, or remove the unused depth_suite PEM files:
../testdata/cert/chain/bcExt/depth_suite/depth_root.pem
../testdata/cert/chain/bcExt/depth_suite/depth_inter1.pem
../testdata/cert/chain/bcExt/depth_suite/depth_inter2.pem
../testdata/cert/chain/bcExt/depth_suite/depth_leaf_lvl1.pem
../testdata/cert/chain/bcExt/depth_suite/depth_leaf_lvl2.pem
likedislike
balabala-123
7月14日 评论:
128+SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/v1_inter/v3_leaf.der":"../testdata/cert/chain/v1_inter/v1_inter.der":"../testdata/cert/chain/v1_inter/v3_root.der":HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION
129+ 
130+SDV_X509_VFY_V1_INTER_CA_TC001: TC2 v2 intermediate without extensions rejected
131+SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/v1_inter/v3_leaf.der":"../testdata/cert/chain/v1_inter/v2_inter.der":"../testdata/cert/chain/v1_inter/v3_root.der":HITLS_X509_ERR_VFY_INTERCA_INVALID_VERSION
132+ 
133+SDV_X509_VFY_V1_INTER_CA_TC001: TC3 v1 trust anchor without extensions accepted
134+SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/v1_inter/v3_leaf_b.der":"":"../testdata/cert/chain/v1_inter/v1_root.der":HITLS_PKI_SUCCESS
135+ 
136+SDV_X509_VFY_V1_INTER_CA_TC001: TC4 v3 intermediate missing BasicConstraints
B
Bbaoyi849307月8日

[Code Guarder][low][trusted] Added pathlen certificate fixtures are unused by verification tests

  • Severity: low
  • Confidence: trusted
  • Reviewers: O
  • Location: testcode/sdv/testcase/pki/verify/test_suite_sdv_x509_vfy.data:127-140

Problem Certificate files under testcode/testdata/cert/chain/bcExt/pathlen_* are added but not referenced by any SDV data-driven verification case, so intended pathLenConstraint behavior is untested despite new assets being introduced.

Code

SDV_X509_VFY_V1_INTER_CA_TC001: TC4 v3 intermediate missing BasicConstraints
SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/bcExt/bc_leaf_missing_bc.pem":"../testdata/cert/chain/bcExt/bc_inter_missing_bc.pem":"../testdata/cert/chain/bcExt/bc_root_general.pem":HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS
SDV_X509_VFY_V1_INTER_CA_TC001: TC5 v3 intermediate BasicConstraints CA=false
SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/bcExt/bc_leaf_ca_false.pem":"../testdata/cert/chain/bcExt/bc_inter_ca_false.pem":"../testdata/cert/chain/bcExt/bc_root_general.pem":HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS

Suggested Fix

Add .data entries and tests that consume:
../testdata/cert/chain/bcExt/pathlen_inter_lvl1.pem
../testdata/cert/chain/bcExt/pathlen_inter_lvl2.pem
../testdata/cert/chain/bcExt/pathlen_leaf_pl_exceed.pem
../testdata/cert/chain/bcExt/pathlen_multi_inter1.pem
../testdata/cert/chain/bcExt/pathlen_multi_inter2.pem
../testdata/cert/chain/bcExt/pathlen_multi_inter3.pem
../testdata/cert/chain/bcExt/pathlen_multi_leaf.pem
../testdata/cert/chain/bcExt/pathlen_multi_root.pem
../testdata/cert/chain/bcExt/pathlen_root_pl1.pem
likedislike
balabala-123
7月14日 评论:
137+SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/bcExt/bc_leaf_missing_bc.pem":"../testdata/cert/chain/bcExt/bc_inter_missing_bc.pem":"../testdata/cert/chain/bcExt/bc_root_general.pem":HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS
138+ 
139+SDV_X509_VFY_V1_INTER_CA_TC001: TC5 v3 intermediate BasicConstraints CA=false
140+SDV_X509_VFY_V1_INTER_CA_TC001:"../testdata/cert/chain/bcExt/bc_leaf_ca_false.pem":"../testdata/cert/chain/bcExt/bc_inter_ca_false.pem":"../testdata/cert/chain/bcExt/bc_root_general.pem":HITLS_X509_ERR_VFY_INTERCA_INVALID_BCONS
141+ 
Atestcode/testdata/cert/chain/bcExt/bc_inter_ca_false.pem+22-0
@@ -0,0 +1,22 @@
1+-----BEGIN CERTIFICATE-----
2+MIIDkDCCAnigAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQ04x
3+DTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRM
4+UzEYMBYGA1UEAwwPYmMtcm9vdC1nZW5lcmFsMB4XDTI1MTAzMTA3NDgxNVoXDTMw
5+MTAzMDA3NDgxNVowWzELMAkGA1UEBhMCQ04xDTALBgNVBAgMBFRlc3QxDTALBgNV
6+BAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRMUzEaMBgGA1UEAwwRYmMtaW50ZXIt
7+Y2EtZmFsc2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFTxZhmXsK
8+bzy/TfeOgC8tGY4ErQ8FATR3vVMQ9szf/VwsdtTAtFGW8EjIuAkGHxnOUo4rLXNJ
9+pp5bfzcDoFk6Dww1g3wsfez74iB1uQhV5+atNm0zMfwmrHgZxCQueGlc73CjQCuO
10+4Hk11B30c4oSnAhnLgIWfbJlGU12vpwA5jPjEUOkOf1B/RIzU9z+fxXliw/YvTQ2
11+uccm2x1pnlUP/RBZZZArJuOREzIRTmZkdswGrVdWVRxKkX2ryDNaCYH7X4ZVQqGN
12+8h3I2T1pMUWvY5LDCz4cEfja5PneDgOk4Xi4rCzDK8/ejbBnn7oa2fYBiVOZvijm
13+XOjpuPpE8P5/AgMBAAGjYDBeMB0GA1UdDgQWBBQRtcaLwK7Jbi6J554QstILPhfz
14+YDAfBgNVHSMEGDAWgBTbGxXyCMiE22QDaW71vbQCZXuD2jAMBgNVHRMBAf8EAjAA
15+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEADo7Io4wqY9VRag/+
16+5/9DlbQjsUiFlThl33fueS4nXswdM/+pAYXQBowrbMbbZz2JpLKTo0cXvYvOxt6G
17+ZM6SKU3ASny93oBgwvAJphpkUGusRGuE8yoelvFrJL/cnKzrv3BjZqkf6HNF/bs8
18+9qY8rlMBpDbKgjDZvLh8SnhXM32BmHpEHhbdDv8E8VoP8PUObxWyqW4fROV//V+F
19+v/Y6sf0qhEhBYL2W0H7O/WrQw8trTaFSxm8wm/I55grOsyFUJEZVpjS1eVs5DvaF
20+pDVJ3BrRwVs8IueB0ghDa63kvPAWsigAAqAcvpgceXHpkkGLHhB8r4JqgdRqEbUa
21+FfXuxg==
22+-----END CERTIFICATE-----
Atestcode/testdata/cert/chain/bcExt/bc_inter_missing_bc.pem+21-0
@@ -0,0 +1,21 @@
1+-----BEGIN CERTIFICATE-----
2+MIIDfzCCAmegAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQ04x
3+DTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRM
4+UzEYMBYGA1UEAwwPYmMtcm9vdC1nZW5lcmFsMB4XDTI1MTAzMTA3NDY0M1oXDTMw
5+MTAzMDA3NDY0M1owWDELMAkGA1UEBhMCQ04xDTALBgNVBAgMBFRlc3QxDTALBgNV
6+BAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRMUzEXMBUGA1UEAwwOYmMtaW50ZXIt
7+bm8tYmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ9DFXkxq/nt9H
8+bdGqjF5DHP6DK9t0sbI7z5utzxf2BO/KIkVCtLdvlK70vQAcltJK3z5B8iBTOGbF
9+LBvJQ2tCbgg4CoGo0FEN6Jgnr5iKx/QVLNIvQ4MKhvJygpAtT0DAAav+dunL5KtH
10+ru0eLvDk6Npx22WSnvhlJBsAof3F+RgBTO3KueZOUHx0OX+a6SCie+rNxLcw0lm0
11+jabMoPbQbCe7s8/NW9YFKHb04WvOv1vZKWllfs+ltx2go7bMRR3JQmHURkA/LFR9
12+GIMxquvbXMpMSEPbjobZGkUsbT+WhLdn5AhjZJ/Ci3lSiOqQvTVXAspdSoXnnzB/
13+IQ56KcJBAgMBAAGjUjBQMB0GA1UdDgQWBBTkTKwBsOTBbyh2Qk1MRyO87FW9azAf
14+BgNVHSMEGDAWgBTbGxXyCMiE22QDaW71vbQCZXuD2jAOBgNVHQ8BAf8EBAMCAQYw
15+DQYJKoZIhvcNAQELBQADggEBAMIfee0MMx4id0tAtWeJHUaXE5UJktiPinEFugvu
16+vmBG1Dglej7fZOoWxDT+fLWicabB4HHZ/3yDJYG7bunf/sHZmnGoMEBv4IqHypwy
17+w3U5RWq+oiJxkdskGMgbbtrtmrgCT84Wm6oKZGsOg5SAK7eBNuF2ygS0f9MaqFCa
18+DjPw/shI5EqmDEhKOchaqjyoMKr3vjIgMhzIXbzft9ZA9/TKakyKHQkQW4ESiJ71
19+9S0Jr78cVduq+kd4zf91eQYxMQmVMGrapzHN6wz2T+l7bodZ7kymhn4xJUSh+g64
20+icPng6JqQ6q+WLhtTnhPztwUsN8CwKj0fmJUA6Q4H3f+qz0=
21+-----END CERTIFICATE-----
Atestcode/testdata/cert/chain/bcExt/bc_leaf_ca_false.pem+22-0
@@ -0,0 +1,22 @@
1+-----BEGIN CERTIFICATE-----
2+MIIDujCCAqKgAwIBAgICIAIwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCQ04x
3+DTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRM
4+UzEaMBgGA1UEAwwRYmMtaW50ZXItY2EtZmFsc2UwHhcNMjUxMDMxMDc0ODI5WhcN
5+MjgwMjAzMDc0ODI5WjBkMQswCQYDVQQGEwJDTjENMAsGA1UECAwEVGVzdDENMAsG
6+A1UEBwwEVGVzdDESMBAGA1UECgwJb3BlbkhpVExTMSMwIQYDVQQDDBpiYy1sZWFm
7+LWlzc3VlZC1ieS1jYS1mYWxzZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
8+ggEBAKwg12I/mXixKE9Z/GfOt+fHO6o0pyVcj/NowjImHubltcIfidtXpM+5IGPY
9+RMLQlrD8UYQG/cC5WQOHranCF+3gkdBtoHLDxvSuzS6E7+R78tfnKTa2qiCcwIhw
10+2c1+pPMv7CMdBYftHCe0Bfe1TWe9MzfJM4moisHXuXpgMhmVXttI6fGenEo1aAeS
11+YQGfI6O+ep2xBXKhWrL1vOIPmh/3HQIWiVlg/PvBl7kFIXBztlD160H2hGwxAkcj
12+mxUKav7gWm27fwj9GEQdaWIjLl6d5cXSAQlIneu2lcBPILZ0bTt2UNtQKs8KiI3t
13+jaWAkrusHb/3P8gVuhyNUpGLF9kCAwEAAaN/MH0wHQYDVR0OBBYEFPVremUhVSYS
14+R0spKcF9pH4awEY4MB8GA1UdIwQYMBaAFBG1xovArsluLonnnhCy0gs+F/NgMAwG
15+A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMC
16+BggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAcRMTzMU/AcVZaXFV7gg4o5Kb
17+xgdj9qURK4mBJUPQlez0EeCHNCynsT+ErEKFMnGfRK4X2T15B7e1HM3xu7NVSVrv
18+OPVxU2LD8WHjjZID5UO8fwuYDOrwamuEZIEusEOKUyY+cWN2M/tjbMwo6gWemoJh
19+GJW3KgBA2VH0StElvE386rppENiIiUgySwruqoilNTLDgR0/Tgjn5R5bH+5g1Sfd
20+pdFFSV9DIqtXVW4gRqz/BdB+WQujDKKswhOC7O+5LGFxGhuRwT5S0nBupvP6aTPX
21+Xh6boHEQtDLaNRgE29Q55OD0Tjke9xKGA2cn476ZY9tY1HqtNis4Jk/w7dJBmQ==
22+-----END CERTIFICATE-----
Atestcode/testdata/cert/chain/bcExt/bc_leaf_missing_bc.pem+22-0
@@ -0,0 +1,22 @@
1+-----BEGIN CERTIFICATE-----
2+MIIDtDCCApygAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCQ04x
3+DTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRM
4+UzEXMBUGA1UEAwwOYmMtaW50ZXItbm8tYmMwHhcNMjUxMDMxMDc0NzI0WhcNMjgw
5+MjAzMDc0NzI0WjBhMQswCQYDVQQGEwJDTjENMAsGA1UECAwEVGVzdDENMAsGA1UE
6+BwwEVGVzdDESMBAGA1UECgwJb3BlbkhpVExTMSAwHgYDVQQDDBdiYy1sZWFmLWlz
7+c3VlZC1ieS1uby1iYzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANPV
8+5T5eV3v5WoWsmJ3XZX4o90TeHw8M/fqAdKVF5FkJI1fSQrCdQX5ZvY7ATfl7NLuK
9+7ihWYfFjm2JfdLrwUgEDbvkvxlqopiMrFzAo1z+rlR+UUC3fLDSiA1zCYaffQOIE
10+QwND5OCam3MdgqVC9K0B1kVR9mp7eNiikmWRMsQN7apwDiweguasrbua5Avp4WBF
11+Az6SY4bNUllWNN29O7bwxPNneoxTNYqm1Mvrtk5hROrnhT0iVzbnOlzqW7ahoVbC
12+8CZT5dBrA8Oh6wYO1sjd/gkbhfF11G0T5AfADyP3boiNHajojg/qW13JxbB9gn+C
13+gAkxdxDvLZcQqFGXhpMCAwEAAaN/MH0wHQYDVR0OBBYEFD44tR/uyAIjyI7EINfx
14+LnmZY+QjMB8GA1UdIwQYMBaAFORMrAGw5MFvKHZCTUxHI7zsVb1rMAwGA1UdEwEB
15+/wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEF
16+BQcDATANBgkqhkiG9w0BAQsFAAOCAQEAep1u6QkK3rXosPXwxLP7VHa3riI6dn9b
17+B5BeiLXUdLb2Htp8/UcVI+jip8Y0H8M6+qhHILlPJKtwIpFBL1zOMffyy2r+jaIX
18+tuQ4witNAUFeVZhjRWXgqYyICFCeRkY60BeceqrVW0JMA9cW2pUt1vH9WqQWzqaB
19+Ln1mX3T/pwA7zh9rEmsDXeXq3yPncI0tbDqvL6PaGe4NL9sZftYstcQYYWO5Fhz5
20+M9Em/Go+qRuTu2W/bdFrIpe1UdKjD8lqTAajwS8JKdnj9kZy+kUXxM7DnA4o5tEy
21+6+sDsA+cLNkwu0BLNXl8rRYhNWqWKKy0/g4pETRyxsUEM2fe8tYBCg==
22+-----END CERTIFICATE-----
Atestcode/testdata/cert/chain/bcExt/bc_root_general.pem+22-0
@@ -0,0 +1,22 @@
1+-----BEGIN CERTIFICATE-----
2+MIIDlDCCAnygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQ04x
3+DTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRM
4+UzEYMBYGA1UEAwwPYmMtcm9vdC1nZW5lcmFsMB4XDTI1MTAzMTA3NDYzMloXDTM1
5+MTAyOTA3NDYzMlowWTELMAkGA1UEBhMCQ04xDTALBgNVBAgMBFRlc3QxDTALBgNV
6+BAcMBFRlc3QxEjAQBgNVBAoMCW9wZW5IaVRMUzEYMBYGA1UEAwwPYmMtcm9vdC1n
7+ZW5lcmFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw3GO9L9pk31E
8+aQ8FbObU2tECxJS94Lk9IR9Uvwzv+LZNrgc3z05LcaqGqku/Pm89U54i8dA7dTJ2
9+LiQOsL2DFl4N+QcDKIoSuiREOjQmahgXIHENyiMHGHh0J29ySQnVaMC+tR62rCZ6
10+2OVverWHydLkJbCWNoJM8OvHYzyvEyXTHBw4rf8IvnN0ygzJ5I0pkQ3Um7HxorgY
11+8H75vrXfGb6xgP53tvf1Trt04c+gJ8VpC4MgVS/nFJeAF/L66LIIIhF3sPHo4XO/
12+2kQkYEYB106oKZvfB/OINwcOl4Tn6iT2Q5wBT9n6y5msY4VT/mXYbdEuI3tqN1Ac
13+IDWt0zii0QIDAQABo2YwZDAdBgNVHQ4EFgQU2xsV8gjIhNtkA2lu9b20AmV7g9ow
14+HwYDVR0jBBgwFoAU2xsV8gjIhNtkA2lu9b20AmV7g9owEgYDVR0TAQH/BAgwBgEB
15+/wIBBDAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAAN0ks7KZbhp
16+xqJjfQFmMxgx6JGqV6teIUNNbKUQyuywT2c2+0129TdzAKUKG5Ra7oHrx0kxpEFZ
17+WUqNsG1jXzLvNJo3MueKIDvRkjRSu0rlOTpC5EnylZQbpzYKaxyfa+Z8PDjIO36z
18+AengbMS4dJmWfiUVT3cvrqRvAnXHZC75lhRrxHqFBfId2hCBR1sSrwmBdvSrZ6oJ
19++eZV1EkVJpDd3E1zHFUmr2zL5QI4Agw//kJ0IJzyBMltMwAPIlrkJedIrpU7nIgo
20+HA3lU0gVXjQV0i5DzMOAdk+xhT5ssVdB4QH4+lBvwdXTSq+hTo/0wXnduw1lttkB
21+abJmlaMLDZk=
22+-----END CERTIFICATE-----
Atestcode/testdata/cert/chain/v1_inter/gen_certs.py+301-0
@@ -0,0 +1,301 @@
1+#!/usr/bin/env python3
2+# -*- coding: utf-8 -*-
3+# This file is part of the openHiTLS project.
4+#
5+# openHiTLS is licensed under the Mulan PSL v2.
6+# You can use this software according to the terms and conditions of the Mulan PSL v2.
7+# You may obtain a copy of Mulan PSL v2 at:
8+#
9+# http://license.coscl.org.cn/MulanPSL2
10+#
11+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+# See the Mulan PSL v2 for more details.
15+"""
16+Generate test certificates for v1/v2 intermediate CA rejection tests (Problem 2 fix).
17+ 
18+Tests that v1/v2 non-trust-anchor intermediate CAs are rejected, while v1 trust anchors are accepted.
19+ 
20+Strategy for v1/v2 certs WITHOUT extensions:
21+ 1. Build a TBS without any extensions using the cryptography library
22+ 2. Sign to get a v3 cert (the library always outputs v3)
23+ 3. Patch the version byte in the TBS DER from 0x02 (v3) to 0x00 (v1) or 0x01 (v2)
24+ 4. Re-sign the patched TBS with the issuer's private key
25+ 5. Assemble the final Certificate SEQUENCE
26+ 
27+Output files:
28+ v3_root.der - v3 root CA (trust anchor, with BC:CA=TRUE, KU:keyCertSign)
29+ v1_inter.der - v1 intermediate WITHOUT extensions, signed by root (TC1)
30+ v2_inter.der - v2 intermediate WITHOUT extensions, signed by root (TC2)
31+ v3_leaf.der - v3 leaf cert, signed by intermediate's key (for TC1/TC2 chain)
32+ v1_root.der - v1 self-signed root WITHOUT extensions (TC3 trust anchor)
33+ v3_leaf_b.der - v3 leaf cert, signed by v1 root's key (for TC3 chain)
34+"""
35+ 
36+import os
37+import datetime
38+from cryptography import x509
39+from cryptography.x509.oid import NameOID
40+from cryptography.hazmat.primitives import hashes, serialization
41+from cryptography.hazmat.primitives.asymmetric import rsa, padding
42+ 
43+ 
44+def gen_key():
45+ return rsa.generate_private_key(public_exponent=65537, key_size=2048)
46+ 
47+ 
48+def make_root_cn():
49+ return x509.Name([
50+ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
51+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "V1InterTest"),
52+ x509.NameAttribute(NameOID.COMMON_NAME, "V1InterTest Root CA"),
53+ ])
54+ 
55+ 
56+def make_inter_cn():
57+ return x509.Name([
58+ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
59+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "V1InterTest"),
60+ x509.NameAttribute(NameOID.COMMON_NAME, "V1InterTest Intermediate"),
61+ ])
62+ 
63+ 
64+def make_leaf_cn():
65+ return x509.Name([
66+ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
67+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "V1InterTest"),
68+ x509.NameAttribute(NameOID.COMMON_NAME, "V1InterTest Leaf"),
69+ ])
70+ 
71+ 
72+def make_root_b_cn():
73+ return x509.Name([
74+ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
75+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "V1InterTest"),
76+ x509.NameAttribute(NameOID.COMMON_NAME, "V1InterTest SelfRoot"),
77+ ])
78+ 
79+ 
80+def build_ca_tbs(subject, issuer, pub_key, path_length):
81+ return (
82+ x509.CertificateBuilder()
83+ .subject_name(subject)
84+ .issuer_name(issuer)
85+ .public_key(pub_key)
86+ .serial_number(x509.random_serial_number())
87+ .not_valid_before(datetime.datetime(2024, 1, 1))
88+ .not_valid_after(datetime.datetime(2050, 12, 31))
89+ .add_extension(
90+ x509.BasicConstraints(ca=True, path_length=path_length),
91+ critical=True,
92+ )
93+ .add_extension(
94+ x509.KeyUsage(
95+ digital_signature=True, key_cert_sign=True, crl_sign=True,
96+ content_commitment=False, key_encipherment=False,
97+ data_encipherment=False, key_agreement=False,
98+ encipher_only=False, decipher_only=False,
99+ ),
100+ critical=True,
101+ )
102+ )
103+ 
104+ 
105+def build_leaf_tbs(subject, issuer, pub_key):
106+ return (
107+ x509.CertificateBuilder()
108+ .subject_name(subject)
109+ .issuer_name(issuer)
110+ .public_key(pub_key)
111+ .serial_number(x509.random_serial_number())
112+ .not_valid_before(datetime.datetime(2024, 1, 1))
113+ .not_valid_after(datetime.datetime(2050, 12, 31))
114+ .add_extension(
115+ x509.BasicConstraints(ca=False, path_length=None),
116+ critical=True,
117+ )
118+ .add_extension(
119+ x509.KeyUsage(
120+ digital_signature=True, key_encipherment=True,
121+ content_commitment=False, key_agreement=False,
122+ key_cert_sign=False, crl_sign=False,
123+ data_encipherment=False, encipher_only=False, decipher_only=False,
124+ ),
125+ critical=True,
126+ )
127+ )
128+ 
129+ 
130+def build_no_ext_tbs(subject, issuer, pub_key):
131+ """Build a TBS without any extensions. Used for v1/v2 certs."""
132+ return (
133+ x509.CertificateBuilder()
134+ .subject_name(subject)
135+ .issuer_name(issuer)
136+ .public_key(pub_key)
137+ .serial_number(x509.random_serial_number())
138+ .not_valid_before(datetime.datetime(2024, 1, 1))
139+ .not_valid_after(datetime.datetime(2050, 12, 31))
140+ )
141+ 
142+ 
143+def to_der(cert):
144+ return cert.public_bytes(serialization.Encoding.DER)
145+ 
146+ 
147+def patch_version_in_der(der_bytes, new_version):
148+ der = bytearray(der_bytes)
149+ pattern = bytes([0xA0, 0x03, 0x02, 0x01])
150+ idx = der.find(pattern)
151+ if idx < 0:
152+ raise ValueError("version field pattern not found in DER")
153+ der[idx + 4] = new_version
154+ return bytes(der)
155+ 
156+ 
157+def extract_tbs_der(cert_der):
158+ if cert_der[0] != 0x30:
159+ raise ValueError("expected SEQUENCE tag")
160+ idx = 1
161+ if cert_der[1] & 0x80:
162+ idx += 1 + (cert_der[1] & 0x7F)
163+ else:
164+ idx += 1
165+ tbs_start = idx
166+ if cert_der[idx] != 0x30:
167+ raise ValueError("expected TBS SEQUENCE tag")
168+ idx += 1
169+ if cert_der[idx] & 0x80:
170+ num_len_bytes = cert_der[idx] & 0x7F
171+ idx += 1
172+ tbs_content_len = int.from_bytes(cert_der[idx:idx + num_len_bytes], 'big')
173+ idx += num_len_bytes
174+ else:
175+ tbs_content_len = cert_der[idx]
176+ idx += 1
177+ tbs_end = idx + tbs_content_len
178+ return cert_der[tbs_start:tbs_end]
179+ 
180+ 
181+def extract_sig_alg_and_value(cert_der):
182+ idx = 1
183+ if cert_der[1] & 0x80:
184+ idx += 1 + (cert_der[1] & 0x7F)
185+ else:
186+ idx += 1
187+ if cert_der[idx] != 0x30:
188+ raise ValueError("expected TBS SEQUENCE")
189+ idx += 1
190+ if cert_der[idx] & 0x80:
191+ num_len_bytes = cert_der[idx] & 0x7F
192+ tbs_len = int.from_bytes(cert_der[idx + 1:idx + 1 + num_len_bytes], 'big')
193+ idx += 1 + num_len_bytes + tbs_len
194+ else:
195+ tbs_len = cert_der[idx]
196+ idx += 1 + tbs_len
197+ sig_alg_start = idx
198+ if cert_der[idx] != 0x30:
199+ raise ValueError("expected sigAlg SEQUENCE")
200+ idx += 1
201+ if cert_der[idx] & 0x80:
202+ num_len_bytes = cert_der[idx] & 0x7F
203+ sig_alg_len = int.from_bytes(cert_der[idx + 1:idx + 1 + num_len_bytes], 'big')
204+ idx += 1 + num_len_bytes + sig_alg_len
205+ else:
206+ sig_alg_len = cert_der[idx]
207+ idx += 1 + sig_alg_len
208+ sig_alg_end = idx
209+ sig_val_start = idx
210+ sig_val_end = len(cert_der)
211+ return cert_der[sig_alg_start:sig_alg_end], cert_der[sig_val_start:sig_val_end]
212+ 
213+ 
214+def _encode_length(length):
215+ if length < 0x80:
216+ return bytes([length])
217+ elif length < 0x100:
218+ return bytes([0x81, length])
219+ elif length < 0x10000:
220+ return bytes([0x82, (length >> 8) & 0xFF, length & 0xFF])
221+ else:
222+ return bytes([0x83, (length >> 16) & 0xFF, (length >> 8) & 0xFF, length & 0xFF])
223+ 
224+ 
225+def build_versioned_cert_no_ext(tbs_builder, signing_key, version):
226+ """Build a certificate without extensions, with a specific version (0=v1, 1=v2).
227+ 
228+ 1. Sign a v3 TBS (without extensions) to get a valid cert structure
229+ 2. Extract TBS DER
230+ 3. Patch version byte to desired value
231+ 4. Re-sign patched TBS
232+ 5. Assemble final certificate
233+ """
234+ v3_cert = tbs_builder.sign(signing_key, hashes.SHA256())
235+ v3_der = to_der(v3_cert)
236+ 
237+ tbs_der = extract_tbs_der(v3_der)
238+ patched_tbs = patch_version_in_der(tbs_der, version)
239+ 
240+ sig_alg_der, _ = extract_sig_alg_and_value(v3_der)
241+ 
242+ new_signature = signing_key.sign(patched_tbs, padding.PKCS1v15(), hashes.SHA256())
243+ sig_content = b'\x00' + new_signature
244+ sig_value_der = b'\x03' + _encode_length(len(sig_content)) + sig_content
245+ 
246+ inner = patched_tbs + sig_alg_der + sig_value_der
247+ cert_der = b'\x30' + _encode_length(len(inner)) + inner
248+ return cert_der
249+ 
250+ 
251+def save(der_bytes, filename, out_dir):
252+ path = os.path.join(out_dir, filename)
253+ with open(path, "wb") as f:
254+ f.write(der_bytes)
255+ print(f" wrote {filename} ({len(der_bytes)} bytes)")
256+ 
257+ 
258+def main():
259+ out_dir = os.path.dirname(os.path.abspath(__file__))
260+ 
261+ print("Generating keys...")
262+ root_key = gen_key()
263+ inter_key = gen_key()
264+ leaf_key = gen_key()
265+ root_b_key = gen_key()
266+ 
267+ root_name = make_root_cn()
268+ inter_name = make_inter_cn()
269+ leaf_name = make_leaf_cn()
270+ root_b_name = make_root_b_cn()
271+ 
272+ print("Generating certificates...")
273+ 
274+ # v3 root CA (trust anchor for TC1/TC2, with BC:CA=TRUE, KU:keyCertSign)
275+ a_root = build_ca_tbs(root_name, root_name, root_key.public_key(), 2).sign(root_key, hashes.SHA256())
276+ save(to_der(a_root), "v3_root.der", out_dir)
277+ 
278+ # v1 intermediate WITHOUT extensions, signed by root (TC1)
279+ tbs_inter_no_ext = build_no_ext_tbs(inter_name, root_name, inter_key.public_key())
280+ save(build_versioned_cert_no_ext(tbs_inter_no_ext, root_key, 0x00), "v1_inter.der", out_dir)
281+ 
282+ # v2 intermediate WITHOUT extensions, signed by root (TC2)
283+ save(build_versioned_cert_no_ext(tbs_inter_no_ext, root_key, 0x01), "v2_inter.der", out_dir)
284+ 
285+ # v3 leaf signed by intermediate's key (for TC1/TC2 chain)
286+ a_leaf = build_leaf_tbs(leaf_name, inter_name, leaf_key.public_key()).sign(inter_key, hashes.SHA256())
287+ save(to_der(a_leaf), "v3_leaf.der", out_dir)
288+ 
289+ # v1 self-signed root WITHOUT extensions (TC3 trust anchor)
290+ tbs_root_b_no_ext = build_no_ext_tbs(root_b_name, root_b_name, root_b_key.public_key())
291+ save(build_versioned_cert_no_ext(tbs_root_b_no_ext, root_b_key, 0x00), "v1_root.der", out_dir)
292+ 
293+ # v3 leaf signed by v1 root's key (for TC3 chain)
294+ b_leaf = build_leaf_tbs(leaf_name, root_b_name, leaf_key.public_key()).sign(root_b_key, hashes.SHA256())
295+ save(to_der(b_leaf), "v3_leaf_b.der", out_dir)
296+ 
297+ print("Done.")
298+ 
299+ 
300+if __name__ == "__main__":
301+ main()
Atestcode/testdata/cert/chain/v1_inter/v1_inter.der+0-0
Binary files do not support preview
Atestcode/testdata/cert/chain/v1_inter/v1_root.der+0-0
Binary files do not support preview
Atestcode/testdata/cert/chain/v1_inter/v2_inter.der+0-0
Binary files do not support preview
Atestcode/testdata/cert/chain/v1_inter/v3_leaf.der+0-0
Binary files do not support preview
Atestcode/testdata/cert/chain/v1_inter/v3_leaf_b.der+0-0
Binary files do not support preview
Atestcode/testdata/cert/chain/v1_inter/v3_root.der+0-0
Binary files do not support preview