| @@ -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, |
| @@ -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 on | 827 | * 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); |
| @@ -90,12 +90,12 @@ void HITLS_X509_StoreCtxFree(HITLS_X509_StoreCtx *storeCtx) | |||
| 90 | 90 | ||
| 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 list | 94 | // 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 list | 154 | // 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 DN | 505 | // 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 paths | 527 | // 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 | |||
| 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 [Code Guarder][medium][likely] X509_CheckExt returns verification errors without pushing to error stack
Problem
New verification checks in Code
Suggested Fix
![]() ![]() | |||
| 979 | + } | ||
| 980 | + } | ||
| 981 | + } | ||
| 982 | + cur = BSL_LIST_GET_PREV(chain); | ||
| 983 | + curDepth--; | ||
| 984 | + } | ||
| 985 | + return HITLS_PKI_SUCCESS; | ||
| 986 | +} | ||
| 987 | + | ||
| 948 | int32_t HITLS_X509_CertVerify(HITLS_X509_StoreCtx *storeCtx, HITLS_X509_List *chain) | 988 | int32_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); |
| @@ -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 path | 684 | // 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 paths | 719 | // 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 paths | 729 | // 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 chain | 737 | // 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 paths | 756 | // 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 paths | 766 | // 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 paths | 785 | // 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 paths | 795 | // 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 paths | 815 | // 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 verified | 820 | // 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 paths | 826 | // 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 | + | ||
| 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 | + | ||
| 1076 | + (void)leafPath; | ||
| 1077 | + (void)interPath; | ||
| 1078 | + (void)rootPath; | ||
| 1079 | + (void)exp; | ||
| 1080 | + SKIP_TEST(); | ||
| 1081 | + | ||
| 1082 | +} | ||
| 1083 | +/* END_CASE */ | ||
| @@ -66,7 +66,7 @@ SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008:"../testdata/cert/chain/rsa-v3/ca1.der":".. | |||
| 66 | 66 | ||
| 67 | SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test crl have no cacrl vfy all | 67 | SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test crl have no cacrl vfy all |
| 68 | SDV_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 | 68 | SDV_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 | + |
| 70 | SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test revoke endcert | 70 | SDV_X509_BUILD_CERT_CHAIN_FUNC_TC008 test revoke endcert |
| 71 | SDV_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 | 71 | SDV_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 | |||
| 124 | SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001 prevent aftertime bypass by flag tampering | 124 | SDV_X509_CHECK_TIME_NEED_AFTER_TIME_FUNC_TC001 prevent aftertime bypass by flag tampering |
| 125 | SDV_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" | 125 | SDV_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 [Code Guarder][low][trusted] Added depth_suite certificate fixtures are unused by verification tests
Problem
Certificate files under Code
Suggested Fix
![]() ![]() | |||
| 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 [Code Guarder][low][trusted] Added pathlen certificate fixtures are unused by verification tests
Problem
Certificate files under Code
Suggested Fix
![]() ![]() | |||
| 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 | + | ||
| @@ -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----- | ||
| @@ -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----- | ||
| @@ -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----- | ||
| @@ -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----- | ||
| @@ -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----- | ||
| @@ -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() | ||


[Code Guarder][high][likely] BasicConstraints pathLenConstraint is not enforced in chain verification
highlikelyXpki/x509_verify/src/hitls_x509_verify.c:957-977Problem
HITLS_X509_CertExt::maxPathLenis populated during extension parsing butX509_CheckExtnever enforces it. A CA cert withpathLenConstraint=0can still be accepted while allowing another intermediate CA below it, violating RFC 5280 chain depth semantics for path length.Code
Suggested Fix