/** Decode the content of the octet string value if known. */
static int rtCrSpcSerializedObject_DecodeMore(PRTASN1CURSOR pCursor, uint32_t fFlags,
                                              PRTCRSPCSERIALIZEDOBJECT pThis, const char *pszErrorTag)

{
    RT_NOREF_PV(fFlags); RT_NOREF_PV(pszErrorTag);

    int rc;
    RTASN1CURSOR SubCursor;
    if (RTUuidCompareStr(pThis->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR) == 0)
    {
        rc = RTAsn1MemAllocZ(&pThis->SerializedData.EncapsulatedAllocation, (void **)&pThis->u.pData, sizeof(*pThis->u.pData));
        if (RT_SUCCESS(rc))
        {
            pThis->SerializedData.pEncapsulated = (PRTASN1CORE)pThis->u.pData;
            pThis->enmType = RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES;

            rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->SerializedData.Asn1Core, &SubCursor, "SerializedData");
            if (RT_SUCCESS(rc))
                rc = RTCrSpcSerializedObjectAttributes_DecodeAsn1(&SubCursor, 0, pThis->u.pData, "SD");
        }
    }
    else
        return VINF_SUCCESS;
    if (RT_SUCCESS(rc))
        rc = RTAsn1CursorCheckEnd(&SubCursor);
    return rc;
}
RTDECL(int) RTAsn1ObjId_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pThis, const char *pszErrorTag)
{
    int rc = RTAsn1CursorReadHdr(pCursor, &pThis->Asn1Core, pszErrorTag);
    if (RT_SUCCESS(rc))
    {
        rc = RTAsn1CursorMatchTagClassFlags(pCursor, &pThis->Asn1Core, ASN1_TAG_OID,
                                            ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE, fFlags, pszErrorTag, "OID");
        if (RT_SUCCESS(rc))
        {
            /*
             * Validate and count things first.
             */
            uint8_t cComponents = 0; /* gcc maybe-crap */
            uint8_t cchObjId = 0;    /* ditto */
            rc = rtAsn1ObjId_PreParse(pCursor->pbCur, pThis->Asn1Core.cb, pCursor, pszErrorTag, &cComponents, &cchObjId);
            if (RT_SUCCESS(rc))
            {
                /*
                 * Allocate memory for the components array, either out of the
                 * string buffer or off the heap.
                 */
                pThis->cComponents = cComponents;
                RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation);
#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
                if (cComponents * sizeof(uint32_t) <= sizeof(pThis->szObjId) - cchObjId - 1)
                    pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)];
                else
#endif
                    rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents,
                                         cComponents * sizeof(pThis->pauComponents[0]));
                if (RT_SUCCESS(rc))
                {
                    uint32_t *pauComponents = (uint32_t *)pThis->pauComponents;

                    /*
                     * Deal with the two first components first since they are
                     * encoded in a weird way to save a byte.
                     */
                    uint8_t const  *pbContent = pCursor->pbCur;
                    uint32_t        cbContent = pThis->Asn1Core.cb;
                    uint32_t        uValue;
                    rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRC(rc);
                    if (RT_SUCCESS(rc))
                    {
                        pbContent += rc;
                        cbContent -= rc;

                        if (uValue < 80)
                        {
                            pauComponents[0] = uValue / 40;
                            pauComponents[1] = uValue % 40;
                        }
                        else
                        {
                            pauComponents[0] = 2;
                            pauComponents[1] = uValue - 2*40;
                        }

                        char  *pszObjId    = &pThis->szObjId[0];
                        *pszObjId++        = g_achDigits[pauComponents[0]];
                        size_t cbObjIdLeft = cchObjId + 1 - 1;

                        rc = rtAsn1ObjId_InternalFormatComponent(pauComponents[1], &pszObjId, &cbObjIdLeft); AssertRC(rc);
                        if (RT_SUCCESS(rc))
                        {
                            /*
                             * The other components are encoded in less complicated manner.
                             */
                            for (uint32_t i = 2; i < cComponents; i++)
                            {
                                rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue);
                                AssertRCBreak(rc);
                                pbContent += rc;
                                cbContent -= rc;
                                pauComponents[i] = uValue;
                                rc = rtAsn1ObjId_InternalFormatComponent(uValue, &pszObjId, &cbObjIdLeft);
                                AssertRCBreak(rc);
                            }
                            if (RT_SUCCESS(rc))
                            {
                                Assert(cbObjIdLeft == 1);
                                *pszObjId = '\0';

                                RTAsn1CursorSkip(pCursor, pThis->Asn1Core.cb);
                                pThis->Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT;
                                pThis->Asn1Core.pOps = &g_RTAsn1ObjId_Vtable;
                                return VINF_SUCCESS;
                            }
                        }
                    }
                }
            }
        }
    }
    RT_ZERO(*pThis);
    return rc;
}
static int rtCrPkcs7ContentInfo_DecodeExtra(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRPKCS7CONTENTINFO pThis,
                                            const char *pszErrorTag)
{
    pThis->u.pCore = NULL;

    /*
     * Figure the type.
     */
    RTCRPKCS7CONTENTINFOCHOICE  enmChoice;
    size_t                      cbContent = 0;
    if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
    {
        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA;
        cbContent = sizeof(*pThis->u.pSignedData);
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRSPCINDIRECTDATACONTENT_OID) == 0)
    {
        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT;
        cbContent = sizeof(*pThis->u.pIndirectDataContent);
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRTSPTSTINFO_OID) == 0)
    {
        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO;
        cbContent = sizeof(*pThis->u.pTstInfo);
    }
    else
    {
        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN;
        cbContent = 0;
    }

    int rc = VINF_SUCCESS;
    if (enmChoice != RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN)
    {
        /*
         * Detect CMS octet string and open the content cursor.
         * Current we don't have work with any contet which is octet string,
         * they're all sequences, which make detection so much simpler.
         */
        PRTASN1OCTETSTRING  pOctetString = &pThis->Content;
        RTASN1CURSOR        ContentCursor;
        rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content");
        if (   RT_SUCCESS(rc)
            && RTAsn1CursorIsNextEx(&ContentCursor, ASN1_TAG_OCTET_STRING, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL))
        {
            rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated,
                                 sizeof(*pOctetString));
            if (RT_SUCCESS(rc))
            {
                pThis->pCmsContent = pOctetString = (PRTASN1OCTETSTRING)pThis->Content.pEncapsulated;
                rc = RTAsn1OctetString_DecodeAsn1(&ContentCursor, 0, pOctetString, "CmsContent");
                if (RT_SUCCESS(rc))
                    rc = RTAsn1CursorCheckEnd(&ContentCursor);
                if (RT_SUCCESS(rc))
                    rc = RTAsn1CursorInitSubFromCore(pCursor, &pOctetString->Asn1Core, &ContentCursor, "CmsContent");
            }
        }
        if (RT_SUCCESS(rc))
        {
            /*
             * Allocate memory for the decoded content.
             */
            rc = RTAsn1MemAllocZ(&pOctetString->EncapsulatedAllocation, (void **)&pOctetString->pEncapsulated, cbContent);
            if (RT_SUCCESS(rc))
            {
                pThis->u.pCore = pOctetString->pEncapsulated;

                /*
                 * Decode it.
                 */
                switch (enmChoice)
                {
                    case RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA:
                        rc = RTCrPkcs7SignedData_DecodeAsn1(&ContentCursor, 0, pThis->u.pSignedData, "SignedData");
                        break;
                    case RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT:
                        rc = RTCrSpcIndirectDataContent_DecodeAsn1(&ContentCursor, 0, pThis->u.pIndirectDataContent,
                                                                   "IndirectDataContent");
                        break;
                    case RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO:
                        rc = RTCrTspTstInfo_DecodeAsn1(&ContentCursor, 0, pThis->u.pTstInfo, "TstInfo");
                        break;
                    default:
                        AssertFailed();
                        rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE;
                        break;
                }
                if (RT_SUCCESS(rc))
                    rc = RTAsn1CursorCheckEnd(&ContentCursor);
                if (RT_SUCCESS(rc))
                    return VINF_SUCCESS;

                RTAsn1MemFree(&pOctetString->EncapsulatedAllocation, pOctetString->pEncapsulated);
                pOctetString->pEncapsulated = NULL;
                pThis->u.pCore = NULL;
            }
        }
    }
    return rc;
}
Exemple #4
0
/*
 * One X.509 Extension.
 */
RTDECL(int) RTCrX509Extension_ExtnValue_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags,
                                                   PRTCRX509EXTENSION pThis, const char *pszErrorTag)
{
    pThis->enmValue = RTCRX509EXTENSIONVALUE_UNKNOWN;

    /*
     * Decode the encapsulated extension bytes if know the format.
     */
    RTASN1CURSOR ValueCursor;
    int rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->ExtnValue.Asn1Core, &ValueCursor, "ExtnValue");
    if (RT_FAILURE(rc))
        return rc;
    pCursor = &ValueCursor;

    if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_AUTHORITY_KEY_IDENTIFIER_OID) == 0)
    {
        /* 4.2.1.1 Authority Key Identifier */
        PRTCRX509AUTHORITYKEYIDENTIFIER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_AUTHORITY_KEY_IDENTIFIER;
            rc = RTCrX509AuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "AuthorityKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_OLD_AUTHORITY_KEY_IDENTIFIER_OID) == 0)
    {
        /* Old and obsolete version of the above, still found in microsoft certificates. */
        PRTCRX509OLDAUTHORITYKEYIDENTIFIER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_OLD_AUTHORITY_KEY_IDENTIFIER;
            rc = RTCrX509OldAuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "OldAuthorityKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_KEY_IDENTIFIER_OID) == 0)
    {
        /* 4.2.1.2 Subject Key Identifier */
        PRTASN1OCTETSTRING pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_OCTET_STRING;
            rc = RTAsn1CursorGetOctetString(&ValueCursor, 0, pThat, "SubjectKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.3 Key Usage */
        PRTASN1BITSTRING pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_BIT_STRING;
            rc = RTAsn1CursorGetBitStringEx(&ValueCursor, 0, 9, pThat, "KeyUsage");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_CERTIFICATE_POLICIES_OID) == 0)
    {
        /* 4.2.1.4 Certificate Policies */
        PRTCRX509CERTIFICATEPOLICIES pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_CERTIFICATE_POLICIES;
            rc = RTCrX509CertificatePolicies_DecodeAsn1(&ValueCursor, 0, pThat, "CertPolicies");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_MAPPINGS_OID) == 0)
    {
        /* 4.2.1.5 Policy Mappings */
        PRTCRX509POLICYMAPPINGS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_MAPPINGS;
            rc = RTCrX509PolicyMappings_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyMapppings");
        }
    }
    else if (   RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_ALT_NAME_OID) == 0
             || RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_ISSUER_ALT_NAME_OID) == 0)
    {
        /* 4.2.1.6 Subject Alternative Name  /  4.2.1.7 Issuer Alternative Name */
        PRTCRX509GENERALNAMES pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_GENERAL_NAMES;
            rc = RTCrX509GeneralNames_DecodeAsn1(&ValueCursor, 0, pThat, "AltName");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_BASIC_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.9 Basic Constraints */
        PRTCRX509BASICCONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_BASIC_CONSTRAINTS;
            rc = RTCrX509BasicConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "BasicConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_NAME_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.10 Name Constraints */
        PRTCRX509NAMECONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_NAME_CONSTRAINTS;
            rc = RTCrX509NameConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "NameConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.11 Policy Constraints */
        PRTCRX509POLICYCONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_CONSTRAINTS;
            rc = RTCrX509PolicyConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.12 Extended Key Usage */
        PRTASN1SEQOFOBJIDS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_SEQ_OF_OBJ_IDS;
            rc = RTAsn1SeqOfObjIds_DecodeAsn1(&ValueCursor, 0, pThat, "ExKeyUsage");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.14 Inhibit anyPolicy */
        PRTASN1INTEGER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_INTEGER;
            rc = RTAsn1CursorGetInteger(&ValueCursor, 0, pThat, "InhibitAnyPolicy");
        }
    }
    else
        return VINF_SUCCESS;

    if (RT_SUCCESS(rc))
        rc = RTAsn1CursorCheckEnd(&ValueCursor);

    if (RT_SUCCESS(rc))
        return VINF_SUCCESS;
    return rc;
}