- Timestamp:
- Oct 9, 2018 4:04:49 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/crypto/applecodesign.h
r74692 r74721 47 47 48 48 49 /** @name Apple code signing magic values for identifying blobs49 /** @name RTCRAPLCS_MAGIC_XXX - Apple code signing magic values for identifying blobs 50 50 * @note No byte order conversion required. 51 51 * @{ */ … … 67 67 /** @} */ 68 68 69 /** @name Apple code signing slots.69 /** @name RTCRAPLCS_SLOT_XXX - Apple code signing slots. 70 70 * @note No byte order conversion required. 71 71 * @{ */ … … 87 87 /** @} */ 88 88 89 /** @name Apple code signing hash types89 /** @name RTCRAPLCS_HASHTYPE_XXX - Apple code signing hash types 90 90 * @note Byte sized field, so no byte order concerns. 91 91 * @{ */ … … 119 119 typedef struct RTCRAPLCSBLOBSLOT 120 120 { 121 /** Slot type, RTCRAPLCS SLOT_XXX.121 /** Slot type, RTCRAPLCS_SLOT_XXX. 122 122 * (Big endian, but so are the constants too). */ 123 123 uint32_t uType; … … 156 156 { 157 157 /** 0x00: Header (uMagic = RTCRAPLCS_MAGIC_CODEDIRECTORY). */ 158 RTCRAPLCSHDR Hdr;158 RTCRAPLCSHDR Hdr; 159 159 /** 0x08: The version number (RTCRAPLCS_VER_XXX). 160 160 * @note Big endian, host order constants. */ … … 186 186 uint32_t offScatter; 187 187 /** 0x30: Offset of team identifier (optional). Big endian. 188 * @since RTCRAPLCS_VER_SUPPORTS_ SCATTER*/188 * @since RTCRAPLCS_VER_SUPPORTS_TEAM */ 189 189 uint32_t offTeam; 190 190 } RTCRAPLCSCODEDIRECTORY; -
trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp
r74707 r74721 238 238 /** Array of segments parallel to the one in KLDRMOD. */ 239 239 RTLDRMODMACHOSEG aSegments[1]; 240 } RTLDRMODMACHO, *PRTLDRMODMACHO; 241 240 } RTLDRMODMACHO; 241 /** Pointer instance data for an Mach-O module. */ 242 typedef RTLDRMODMACHO *PRTLDRMODMACHO; 243 244 /** 245 * Code directory data. 246 */ 247 typedef 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. */ 256 typedef RTLDRMACHCODEDIR *PRTLDRMACHCODEDIR; 257 258 /** 259 * Decoded apple Mach-O signature data. 260 * @note The raw signature data lives in RTLDRMODMACHO::PtrCodeSignature. 261 */ 262 typedef 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. */ 281 typedef RTLDRMACHOSIGNATURE *PRTLDRMACHOSIGNATURE; 242 282 243 283 … … 3965 4005 3966 4006 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 */ 4017 static 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 */ 4162 static 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 */ 4179 static 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 */ 4194 static 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 */ 4209 static 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 3967 4223 /** 3968 4224 * @interface_method_impl{RTLDROPS,pfnVerifySignature} … … 3973 4229 #ifndef IPRT_WITHOUT_LDR_VERIFY 3974 4230 PRTLDRMODMACHO pThis = RT_FROM_MEMBER(pMod, RTLDRMODMACHO, Core); 3975 3976 4231 int rc = rtldrMachO_LoadSignatureBlob(pThis); 3977 4232 if (RT_SUCCESS(rc)) 3978 4233 { 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); 3982 4236 if (RT_SUCCESS(rc)) 3983 4237 { 3984 PRTLDRPESIGNATURE pSignature = NULL; 3985 rc = rtldrPE_VerifySignatureRead(pModPe, &pSignature, pErrInfo); 4238 rc = rtldrMachO_VerifySignatureValidatePkcs7Hashes(pSignature, pErrInfo); 3986 4239 if (RT_SUCCESS(rc)) 3987 4240 { 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); 3991 4242 if (RT_SUCCESS(rc)) 3992 4243 { 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, 3994 4248 &pSignature->ContentInfo, sizeof(pSignature->ContentInfo), 3995 4249 pErrInfo, pvUser); 3996 4250 } 3997 rtldrPE_VerifySignatureDestroy(pModPe, pSignature);3998 4251 } 3999 4252 } 4000 #endif 4253 rtldrMachO_VerifySignatureDestroy(pSignature); 4001 4254 } 4002 4255 return rc; -
trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
r74707 r74721 2589 2589 pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 2590 2590 } 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); 2591 2594 } 2592 2595 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.