VirtualBox

Changeset 74721 in vbox for trunk


Ignore:
Timestamp:
Oct 9, 2018 4:04:49 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/ldr: More Mach-O signing hacking. bugref:9232

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/crypto/applecodesign.h

    r74692 r74721  
    4747
    4848
    49 /** @name Apple code signing magic values for identifying blobs
     49/** @name RTCRAPLCS_MAGIC_XXX - Apple code signing magic values for identifying blobs
    5050 * @note No byte order conversion required.
    5151 * @{ */
     
    6767/** @} */
    6868
    69 /** @name Apple code signing slots.
     69/** @name RTCRAPLCS_SLOT_XXX - Apple code signing slots.
    7070 * @note No byte order conversion required.
    7171 * @{ */
     
    8787/** @} */
    8888
    89 /** @name Apple code signing hash types
     89/** @name RTCRAPLCS_HASHTYPE_XXX - Apple code signing hash types
    9090 * @note Byte sized field, so no byte order concerns.
    9191 * @{ */
     
    119119typedef struct RTCRAPLCSBLOBSLOT
    120120{
    121     /** Slot type, RTCRAPLCSSLOT_XXX.
     121    /** Slot type, RTCRAPLCS_SLOT_XXX.
    122122     * (Big endian, but so are the constants too). */
    123123    uint32_t            uType;
     
    156156{
    157157    /** 0x00: Header (uMagic = RTCRAPLCS_MAGIC_CODEDIRECTORY). */
    158     RTCRAPLCSHDR   Hdr;
     158    RTCRAPLCSHDR    Hdr;
    159159    /** 0x08: The version number (RTCRAPLCS_VER_XXX).
    160160     * @note Big endian, host order constants. */
     
    186186    uint32_t        offScatter;
    187187    /** 0x30: Offset of team identifier (optional).  Big endian.
    188      * @since RTCRAPLCS_VER_SUPPORTS_SCATTER */
     188     * @since RTCRAPLCS_VER_SUPPORTS_TEAM */
    189189    uint32_t        offTeam;
    190190} RTCRAPLCSCODEDIRECTORY;
  • trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp

    r74707 r74721  
    238238    /** Array of segments parallel to the one in KLDRMOD. */
    239239    RTLDRMODMACHOSEG        aSegments[1];
    240 } RTLDRMODMACHO, *PRTLDRMODMACHO;
    241 
     240} RTLDRMODMACHO;
     241/** Pointer instance data for an Mach-O module. */
     242typedef RTLDRMODMACHO *PRTLDRMODMACHO;
     243
     244/**
     245 * Code directory data.
     246 */
     247typedef struct RTLDRMACHCODEDIR
     248{
     249    PCRTCRAPLCSCODEDIRECTORY    pCodeDir;
     250    /** The slot type. */
     251    uint32_t                    uSlot;
     252    /** The naturalized size. */
     253    uint32_t                    cb;
     254} RTLDRMACHCODEDIR;
     255/** Pointer to code directory data. */
     256typedef RTLDRMACHCODEDIR *PRTLDRMACHCODEDIR;
     257
     258/**
     259 * Decoded apple Mach-O signature data.
     260 * @note The raw signature data lives in RTLDRMODMACHO::PtrCodeSignature.
     261 */
     262typedef struct RTLDRMACHOSIGNATURE
     263{
     264    /** Number of code directory slots. */
     265    uint32_t                    cCodeDirs;
     266    /** Code directories. */
     267    RTLDRMACHCODEDIR            aCodeDirs[6];
     268
     269    /** The index of the PKCS#7 slot. */
     270    uint32_t                    idxPkcs7;
     271    /** The size of the PKCS#7 data. */
     272    uint32_t                    cbPkcs7;
     273    /** Pointer to the PKCS#7 data. */
     274    uint8_t const              *pbPkcs7;
     275    /** Parsed PKCS#7 data. */
     276    RTCRPKCS7CONTENTINFO        ContentInfo;
     277    /** Pointer to the decoded SignedData inside the ContentInfo member. */
     278    PRTCRPKCS7SIGNEDDATA        pSignedData;
     279} RTLDRMACHOSIGNATURE;
     280/** Pointer to decoded apple code signing data. */
     281typedef RTLDRMACHOSIGNATURE *PRTLDRMACHOSIGNATURE;
    242282
    243283
     
    39654005
    39664006
     4007#ifndef IPRT_WITHOUT_LDR_VERIFY
     4008
     4009/**
     4010 * Decodes the signature blob at RTLDRMODMACHO::PtrCodeSignature.
     4011 *
     4012 * @returns IPRT status code.
     4013 * @param   pThis               The Mach-O module instance.
     4014 * @param   ppSignature         Where to return the decoded signature data.
     4015 * @param   pErrInfo            Where to supply extra error details. Optional.
     4016 */
     4017static int rtldrMachO_VerifySignatureDecode(PRTLDRMODMACHO pThis, PRTLDRMACHOSIGNATURE *ppSignature, PRTERRINFO pErrInfo)
     4018{
     4019    Assert(pThis->PtrCodeSignature.pSuper != NULL);
     4020
     4021    /*
     4022     * Allocate and init decoded signature data structure.
     4023     */
     4024    PRTLDRMACHOSIGNATURE pSignature = (PRTLDRMACHOSIGNATURE)RTMemTmpAllocZ(sizeof(*pSignature));
     4025    *ppSignature = pSignature;
     4026    if (!pSignature)
     4027        return VERR_NO_TMP_MEMORY;
     4028    pSignature->idxPkcs7 = UINT32_MAX;
     4029
     4030    /*
     4031     * Parse the slots, validating the slot headers.
     4032     */
     4033    PCRTCRAPLCSSUPERBLOB pSuper     = pThis->PtrCodeSignature.pSuper;
     4034    uint32_t const       cSlots     = RT_BE2H_U32(pSuper->cSlots);
     4035    uint32_t const       offFirst   = RT_UOFFSETOF_DYN(RTCRAPLCSSUPERBLOB, aSlots[cSlots]);
     4036    uint32_t const       cbBlob     = RT_BE2H_U32(pSuper->Hdr.cb);
     4037    for (uint32_t iSlot = 0; iSlot < cSlots; iSlot++)
     4038    {
     4039        uint32_t const offData = RT_BE2H_U32(pSuper->aSlots[iSlot].offData);
     4040        if (   offData < offFirst
     4041            || offData > cbBlob - sizeof(RTCRAPLCSHDR)
     4042            || !(offData & 3))
     4043            return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4044                                 "Slot #%u has an invalid data offset: %#x (min %#x, max %#x-4)",
     4045                                 iSlot, offData, offFirst, cbBlob);
     4046        uint32_t const cbMaxData = cbBlob - offData;
     4047
     4048        /*
     4049         * Code directories.
     4050         */
     4051        if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
     4052            || (   pSuper->aSlots[iSlot].uType >= RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES
     4053                && pSuper->aSlots[iSlot].uType < RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_END))
     4054        {
     4055            if (pSignature->cCodeDirs >= RT_ELEMENTS(pSignature->aCodeDirs))
     4056                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4057                                     "Slot #%u: Too many code directory slots (%u found thus far)",
     4058                                     iSlot, pSignature->cCodeDirs + 1);
     4059            if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
     4060                && pSignature->cCodeDirs > 0)
     4061                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4062                                     "Slot #%u: Already have primary code directory in slot #%u",
     4063                                     iSlot, pSignature->aCodeDirs[0].uSlot);
     4064            if (   pSuper->aSlots[iSlot].uType != RTCRAPLCS_SLOT_CODEDIRECTORY /* lazy bird */
     4065                && pSignature->cCodeDirs == 0)
     4066                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4067                                     "Slot #%u: Expected alternative code directory after the primary one", iSlot);
     4068            if (cbMaxData < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, uUnused))
     4069                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4070                                     "Slot #%u: Insufficient data vailable for code directory (max %#x)", iSlot, cbMaxData);
     4071
     4072            PCRTCRAPLCSCODEDIRECTORY pCodeDir = (PCRTCRAPLCSCODEDIRECTORY)&pThis->PtrCodeSignature.pb[offData];
     4073            if (pCodeDir->Hdr.uMagic != RTCRAPLCS_MAGIC_CODEDIRECTORY)
     4074                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4075                                     "Slot #%u: Invalid code directory magic: %#x", iSlot, RT_BE2H_U32(pCodeDir->Hdr.uMagic));
     4076            uint32_t const cb = RT_BE2H_U32(pCodeDir->Hdr.cb);
     4077            if (cb > cbMaxData || cb < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter))
     4078                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4079                                     "Slot #%u: Code directory size is out of bound: %#x (min %#x, max %#x)",
     4080                                     iSlot, cb, RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter), cbMaxData);
     4081/** @todo validate all the fields we wish to use here. */
     4082
     4083            pSignature->aCodeDirs[pSignature->cCodeDirs].pCodeDir = pCodeDir;
     4084            pSignature->aCodeDirs[pSignature->cCodeDirs].uSlot    = iSlot;
     4085            pSignature->aCodeDirs[pSignature->cCodeDirs].cb       = cb;
     4086            pSignature->cCodeDirs++;
     4087        }
     4088        /*
     4089         * PKCS#7/CMS signature.
     4090         */
     4091        else if (pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_SIGNATURE)
     4092        {
     4093            if (pSignature->idxPkcs7 != UINT32_MAX)
     4094                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4095                                     "Slot #%u: Already have PKCS#7 data in slot %#u", iSlot, pSignature->idxPkcs7);
     4096            PCRTCRAPLCSHDR pHdr = (PCRTCRAPLCSHDR)&pThis->PtrCodeSignature.pb[offData];
     4097            if (pHdr->uMagic != RTCRAPLCS_MAGIC_BLOBWRAPPER)
     4098                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4099                                     "Slot #%u: Invalid PKCS#7 wrapper magic: %#x", iSlot, RT_BE2H_U32(pHdr->uMagic));
     4100            uint32_t const cb = RT_BE2H_U32(pHdr->cb);
     4101            if (cb > cbMaxData || cb < sizeof(*pHdr) + 2U)
     4102                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
     4103                                     "Slot #%u: Invalid PKCS#7 size is out of bound: %#x (min %#x, max %#x)",
     4104                                     iSlot, cb, sizeof(*pHdr) + 2, cbMaxData);
     4105            pSignature->idxPkcs7 = iSlot;
     4106            pSignature->pbPkcs7  = (uint8_t const *)(pHdr + 1);
     4107            pSignature->cbPkcs7  = cb - sizeof(*pHdr);
     4108        }
     4109    }
     4110
     4111    /*
     4112     * Check that we've got at least one code directory and one PKCS#7 signature.
     4113     */
     4114    if (pSignature->cCodeDirs == 0)
     4115        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, "No code directory slot in the code signature");
     4116    if (pSignature->idxPkcs7 == UINT32_MAX)
     4117        return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, "No PKCS#7 slot in the code signature");
     4118
     4119    /*
     4120     * Decode the PKCS#7 signature.
     4121     */
     4122    RTASN1CURSORPRIMARY PrimaryCursor;
     4123    RTAsn1CursorInitPrimary(&PrimaryCursor, pSignature->pbPkcs7, pSignature->cbPkcs7,
     4124                            pErrInfo, &g_RTAsn1DefaultAllocator, 0, "Mach-O-BLOB");
     4125    int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pSignature->ContentInfo, "CI");
     4126    if (RT_SUCCESS(rc))
     4127    {
     4128        if (RTCrPkcs7ContentInfo_IsSignedData(&pSignature->ContentInfo))
     4129        {
     4130            pSignature->pSignedData = pSignature->ContentInfo.u.pSignedData;
     4131
     4132            /*
     4133             * Check that the signedData stuff adds up.
     4134             */
     4135            if (!strcmp(pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCR_PKCS7_DATA_OID))
     4136            {
     4137                rc = RTCrPkcs7SignedData_CheckSanity(pSignature->pSignedData,
     4138                                                     RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE /** @todo consider not piggy-backing on auth-code */
     4139                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH
     4140                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT,
     4141                                                     pErrInfo, "SD");
     4142                if (RT_SUCCESS(rc))
     4143                    return VINF_SUCCESS;
     4144            }
     4145            else
     4146                rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID,
     4147                                   "Unexpected pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)",
     4148                                   pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCR_PKCS7_DATA_OID);
     4149        }
     4150        else
     4151            rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/
     4152                               "PKCS#7 is not 'signedData': %s", pSignature->ContentInfo.ContentType.szObjId);
     4153    }
     4154    return rc;
     4155}
     4156
     4157/**
     4158 * Destroys the decoded signature data structure.
     4159 *
     4160 * @param   pSignature      The decoded signature data.  Can be NULL.
     4161 */
     4162static void rtldrMachO_VerifySignatureDestroy(PRTLDRMACHOSIGNATURE pSignature)
     4163{
     4164    if (pSignature)
     4165    {
     4166        RTCrPkcs7ContentInfo_Delete(&pSignature->ContentInfo);
     4167        RTMemTmpFree(pSignature);
     4168    }
     4169}
     4170
     4171
     4172/**
     4173 * Verifies the code directory hashes embedded in the PKCS\#7 data.
     4174 *
     4175 * @returns IPRT status code.
     4176 * @param   pSignature      The decoded signature data.
     4177 * @param   pErrInfo        Where to supply extra error details. Optional.
     4178 */
     4179static int rtldrMachO_VerifySignatureValidatePkcs7Hashes(PRTLDRMACHOSIGNATURE pSignature, PRTERRINFO pErrInfo)
     4180{
     4181    RT_NOREF(pSignature, pErrInfo);
     4182    return VERR_NOT_IMPLEMENTED;
     4183}
     4184
     4185
     4186/**
     4187 * Verifies the page hashes of the given code directory.
     4188 *
     4189 * @returns IPRT status code.
     4190 * @param   pThis           The Mach-O module instance.
     4191 * @param   pEntry          The data entry for the code directory to validate.
     4192 * @param   pErrInfo        Where to supply extra error details. Optional.
     4193 */
     4194static int rtldrMachO_VerifySignatureValidateCodeDir(PRTLDRMODMACHO pThis, PRTLDRMACHCODEDIR pEntry, PRTERRINFO pErrInfo)
     4195{
     4196    RT_NOREF(pThis, pEntry, pErrInfo);
     4197    return VERR_NOT_IMPLEMENTED;
     4198}
     4199
     4200
     4201/**
     4202 * Verifies the page hashes of all the code directories
     4203 *
     4204 * @returns IPRT status code.
     4205 * @param   pThis           The Mach-O module instance.
     4206 * @param   pSignature      The decoded signature data.
     4207 * @param   pErrInfo        Where to supply extra error details. Optional.
     4208 */
     4209static int rtldrMachO_VerifySignatureValidateCodeDirs(PRTLDRMODMACHO pThis, PRTLDRMACHOSIGNATURE pSignature, PRTERRINFO pErrInfo)
     4210{
     4211    int rc = VERR_INTERNAL_ERROR_3;
     4212    for (uint32_t i = 0; i < pSignature->cCodeDirs; i++)
     4213    {
     4214        rc = rtldrMachO_VerifySignatureValidateCodeDir(pThis, &pSignature->aCodeDirs[i], pErrInfo);
     4215        if (RT_FAILURE(rc))
     4216            break;
     4217    }
     4218    return rc;
     4219}
     4220
     4221#endif /* !IPRT_WITHOUT_LDR_VERIFY*/
     4222
    39674223/**
    39684224 * @interface_method_impl{RTLDROPS,pfnVerifySignature}
     
    39734229#ifndef IPRT_WITHOUT_LDR_VERIFY
    39744230    PRTLDRMODMACHO pThis = RT_FROM_MEMBER(pMod, RTLDRMODMACHO, Core);
    3975 
    39764231    int rc = rtldrMachO_LoadSignatureBlob(pThis);
    39774232    if (RT_SUCCESS(rc))
    39784233    {
    3979         RT_NOREF(pfnCallback, pvUser, pErrInfo);
    3980 #if 0
    3981         int rc = rtldrPE_VerifySignatureImagePrecoditions(pModPe, pErrInfo);
     4234        PRTLDRMACHOSIGNATURE pSignature = NULL;
     4235        rc = rtldrMachO_VerifySignatureDecode(pThis, &pSignature, pErrInfo);
    39824236        if (RT_SUCCESS(rc))
    39834237        {
    3984             PRTLDRPESIGNATURE pSignature = NULL;
    3985             rc = rtldrPE_VerifySignatureRead(pModPe, &pSignature, pErrInfo);
     4238            rc = rtldrMachO_VerifySignatureValidatePkcs7Hashes(pSignature, pErrInfo);
    39864239            if (RT_SUCCESS(rc))
    39874240            {
    3988                 rc = rtldrPE_VerifySignatureDecode(pModPe, pSignature, pErrInfo);
    3989                 if (RT_SUCCESS(rc))
    3990                     rc = rtldrPE_VerifySignatureValidateHash(pModPe, pSignature, pErrInfo);
     4241                rc = rtldrMachO_VerifySignatureValidateCodeDirs(pThis, pSignature, pErrInfo);
    39914242                if (RT_SUCCESS(rc))
    39924243                {
    3993                     rc = pfnCallback(&pModPe->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA,
     4244                    /*
     4245                     * Finally, let the caller verify the certificate chain for the PKCS#7 bit.
     4246                     */
     4247                    rc = pfnCallback(&pThis->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA,
    39944248                                     &pSignature->ContentInfo, sizeof(pSignature->ContentInfo),
    39954249                                     pErrInfo, pvUser);
    39964250                }
    3997                 rtldrPE_VerifySignatureDestroy(pModPe, pSignature);
    39984251            }
    39994252        }
    4000 #endif
     4253        rtldrMachO_VerifySignatureDestroy(pSignature);
    40014254    }
    40024255    return rc;
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r74707 r74721  
    25892589                                   pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);
    25902590        }
     2591        else
     2592            rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, /** @todo error code*/
     2593                               "PKCS#7 is not 'signedData': %s", pSignature->ContentInfo.ContentType.szObjId);
    25912594    }
    25922595    return rc;
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