VirtualBox

Changeset 84379 in vbox for trunk/src


Ignore:
Timestamp:
May 19, 2020 7:40:54 PM (5 years ago)
Author:
vboxsync
Message:

IPRT/RTCrX509CertPaths: Hacked the code to accept trusted targets. Added option trust anchor checks. bugref:9699

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/crypto/x509-certpaths.cpp

    r82968 r84379  
    287287/** @name RTCRX509CERTPATHSINT_F_XXX - Certificate path build flags.
    288288 * @{ */
    289 #define RTCRX509CERTPATHSINT_F_VALID_TIME                    RT_BIT_32(0)
    290 #define RTCRX509CERTPATHSINT_F_ELIMINATE_UNTRUSTED_PATHS     RT_BIT_32(1)
    291 #define RTCRX509CERTPATHSINT_F_VALID_MASK                    UINT32_C(0x00000003)
     289#define RTCRX509CERTPATHSINT_F_VALID_TIME                   RT_BIT_32(0)
     290#define RTCRX509CERTPATHSINT_F_ELIMINATE_UNTRUSTED_PATHS    RT_BIT_32(1)
     291/** Whether checking the trust anchor signature (if self signed) and
     292 * that it is valid at the verification time, also require it to be a CA if not
     293 * leaf node. */
     294#define RTCRX509CERTPATHSINT_F_CHECK_TRUST_ANCHOR           RT_BIT_32(2)
     295#define RTCRX509CERTPATHSINT_F_VALID_MASK                   UINT32_C(0x00000007)
    292296/** @} */
    293297
     
    495499    else
    496500        pThis->fFlags &= ~RTCRX509CERTPATHSINT_F_VALID_TIME;
     501    return VINF_SUCCESS;
     502}
     503
     504
     505RTDECL(int) RTCrX509CertPathsSetTrustAnchorChecks(RTCRX509CERTPATHS hCertPaths, bool fEnable)
     506{
     507    PRTCRX509CERTPATHSINT pThis = hCertPaths;
     508    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     509    AssertReturn(pThis->u32Magic == RTCRX509CERTPATHSINT_MAGIC, VERR_INVALID_HANDLE);
     510
     511    if (fEnable)
     512        pThis->fFlags |= RTCRX509CERTPATHSINT_F_CHECK_TRUST_ANCHOR;
     513    else
     514        pThis->fFlags &= ~RTCRX509CERTPATHSINT_F_CHECK_TRUST_ANCHOR;
    497515    return VINF_SUCCESS;
    498516}
     
    611629            if (   pTmpNode->pCert == pCert
    612630                || RTCrX509Certificate_Compare(pTmpNode->pCert, pCert) == 0)
     631            {
     632                /* If target and the source it trusted, upgrade the source so we can successfully verify single node 'paths'. */
     633                if (   RTCRX509CERTPATHNODE_SRC_IS_TRUSTED(uSrc)
     634                    && pTmpNode == pParent
     635                    && pTmpNode->uSrc == RTCRX509CERTPATHNODE_SRC_TARGET)
     636                {
     637                    AssertReturnVoid(!pTmpNode->pParent);
     638                    pTmpNode->uSrc = uSrc;
     639                }
    613640                return;
     641            }
    614642            pTmpNode = pTmpNode->pParent;
    615643        }
     
    19391967
    19401968
    1941 
    19421969/**
    19431970 * Initializes the state.
     
    20142041        || pThis->v.pWorkingPublicKeyParameters->enmType == RTASN1TYPE_NULL)
    20152042        pThis->v.pWorkingPublicKeyParameters = NULL;
     2043}
     2044
     2045
     2046/**
     2047 * This does basic trust anchor checks (similar to 6.1.3.a) before starting on
     2048 * the RFC-5280 algorithm.
     2049 */
     2050static bool rtCrX509CpvMaybeCheckTrustAnchor(PRTCRX509CERTPATHSINT pThis, PRTCRX509CERTPATHNODE pTrustAnchor)
     2051{
     2052    /*
     2053     * This is optional (not part of RFC-5280) and we need a full certificate
     2054     * structure to do it.
     2055     */
     2056    if (!(pThis->fFlags & RTCRX509CERTPATHSINT_F_CHECK_TRUST_ANCHOR))
     2057        return true;
     2058
     2059    PCRTCRX509CERTIFICATE const pCert = pTrustAnchor->pCert;
     2060    if (!pCert)
     2061        return true;
     2062
     2063    /*
     2064     * Verify the certificate signature if self-signed.
     2065     */
     2066    if (RTCrX509Certificate_IsSelfSigned(pCert))
     2067    {
     2068        int rc = RTCrX509Certificate_VerifySignature(pCert, pThis->v.pWorkingPublicKeyAlgorithm,
     2069                                                     pThis->v.pWorkingPublicKeyParameters, pThis->v.pWorkingPublicKey,
     2070                                                     pThis->pErrInfo);
     2071        if (RT_FAILURE(rc))
     2072        {
     2073            pThis->rc = rc;
     2074            return false;
     2075        }
     2076    }
     2077
     2078    /*
     2079     * Verify that the certificate is valid at the specified time.
     2080     */
     2081    AssertCompile(sizeof(pThis->szTmp) >= 36 * 3);
     2082    if (   (pThis->fFlags & RTCRX509CERTPATHSINT_F_VALID_TIME)
     2083        && !RTCrX509Validity_IsValidAtTimeSpec(&pCert->TbsCertificate.Validity, &pThis->ValidTime))
     2084        return rtCrX509CpvFailed(pThis, VERR_CR_X509_CPV_NOT_VALID_AT_TIME,
     2085                                 "Certificate is not valid (ValidTime=%s Validity=[%s...%s])",
     2086                                 RTTimeSpecToString(&pThis->ValidTime, &pThis->szTmp[0], 36),
     2087                                 RTTimeToString(&pCert->TbsCertificate.Validity.NotBefore.Time, &pThis->szTmp[36], 36),
     2088                                 RTTimeToString(&pCert->TbsCertificate.Validity.NotAfter.Time,  &pThis->szTmp[2*36], 36) );
     2089
     2090    /*
     2091     * Verified that the certficiate is not revoked.
     2092     */
     2093    /** @todo rainy day. */
     2094
     2095    /*
     2096     * If non-leaf certificate CA must be set, if basic constraints are present.
     2097     */
     2098    if (pTrustAnchor->pParent)
     2099    {
     2100        if (RTAsn1Integer_UnsignedCompareWithU32(&pTrustAnchor->pCert->TbsCertificate.T0.Version, RTCRX509TBSCERTIFICATE_V3) != 0)
     2101            return rtCrX509CpvFailed(pThis, VERR_CR_X509_CPV_NOT_V3_CERT,
     2102                                     "Only version 3 TA certificates are supported (Version=%llu)",
     2103                                     pTrustAnchor->pCert->TbsCertificate.T0.Version.uValue);
     2104        PCRTCRX509BASICCONSTRAINTS pBasicConstraints = pTrustAnchor->pCert->TbsCertificate.T3.pBasicConstraints;
     2105        if (pBasicConstraints && !pBasicConstraints->CA.fValue)
     2106            return rtCrX509CpvFailed(pThis, VERR_CR_X509_CPV_NOT_CA_CERT,
     2107                                     "Trust anchor certificate is not marked as a CA");
     2108    }
     2109
     2110    return true;
    20162111}
    20172112
     
    25332628{
    25342629    /*
    2535      * Special case, target certificate is trusted.
    2536      */
    2537     if (!pTrustAnchor->pParent)
    2538         return rtCrX509CpvFailed(pThis, VERR_CR_X509_CERTPATHS_INTERNAL_ERROR, "Target certificate is trusted.");
    2539 
    2540     /*
    2541      * Normal processing.
     2630     * Init.
    25422631     */
    25432632    rtCrX509CpvInit(pThis, pTrustAnchor);
    25442633    if (RT_SUCCESS(pThis->rc))
    25452634    {
     2635        /*
     2636         * Maybe do some trust anchor checks.
     2637         */
     2638        if (!rtCrX509CpvMaybeCheckTrustAnchor(pThis, pTrustAnchor))
     2639        {
     2640            AssertStmt(RT_FAILURE_NP(pThis->rc), pThis->rc = VERR_CR_X509_CERTPATHS_INTERNAL_ERROR);
     2641            return false;
     2642        }
     2643
     2644        /*
     2645         * Special case, target certificate is trusted.
     2646         */
     2647        if (!pTrustAnchor->pParent)
     2648            return true; /* rtCrX509CpvWrapUp should not be needed here. */
     2649
     2650        /*
     2651         * Normal processing.
     2652         */
    25462653        PRTCRX509CERTPATHNODE   pNode = pTrustAnchor->pParent;
    25472654        uint32_t                iNode = pThis->v.iNode = 1; /* We count to cNode (inclusive).  Same a validation tree depth. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette