public static CodeDirectoryBlob CreateCodeDirectoryBlob(int codeLength, string ident, string teamID) { HashType hashType = HashType.SHA1; int pageSize = 4096; CodeDirectoryBlob codeDirectory = new CodeDirectoryBlob(); codeDirectory.CodeLimit = (uint)codeLength; codeDirectory.HashType = hashType; codeDirectory.HashSize = (byte)HashAlgorithmHelper.GetHashLength(hashType); codeDirectory.PageSize = pageSize; codeDirectory.Ident = ident; codeDirectory.TeamID = teamID; // We put empty hashes as placeholder to ensure that the blob length will not change later. for (int index = 0; index < SpecialHashCount; index++) { codeDirectory.SpecialHashes.Add(new byte[codeDirectory.HashSize]); } int codeHashEntries = (int)Math.Ceiling((double)codeLength / pageSize); for (int index = 0; index < codeHashEntries; index++) { codeDirectory.CodeHashes.Add(new byte[codeDirectory.HashSize]); } return(codeDirectory); }
private static byte[] GenerateHashesPList(byte[] codeDirectoryBytes, byte[] alternativeCodeDirectory1Bytes) { PListFile plist = new PListFile(); DictionaryNode rootNode = new DictionaryNode(); ArrayNode hashesNode = new ArrayNode(); hashesNode.Add(new DataNode(HashAlgorithmHelper.ComputeHash(HashType.SHA1, codeDirectoryBytes))); hashesNode.Add(new DataNode(HashAlgorithmHelper.ComputeHash(HashType.SHA256Truncated, alternativeCodeDirectory1Bytes))); rootNode.Add("cdhashes", hashesNode); plist.RootNode = rootNode; return(plist.GetBytes(PListFormat.Xml)); }
public static void UpdateHashes(CodeDirectoryBlob codeDirectory, byte[] codeToHash, byte[] infoFileBytes, CodeRequirementsBlob codeRequirements, byte[] codeResourcesBytes, EntitlementsBlob entitlements) { codeDirectory.CodeHashes = HashAlgorithmHelper.ComputeHashes(codeDirectory.HashType, codeDirectory.PageSize, codeToHash); codeDirectory.SpecialHashes = new List <byte[]>(); codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, infoFileBytes))); codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeRequirements.GetBytes()))); codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeResourcesBytes))); if (SpecialHashCount >= CodeDirectoryBlob.ApplicationSpecificHashOffset) { codeDirectory.SpecialHashes.Insert(0, new byte[HashAlgorithmHelper.GetHashLength(codeDirectory.HashType)]); if (SpecialHashCount >= CodeDirectoryBlob.EntitlementsHashOffset) { codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, entitlements.GetBytes()))); } } }
public static bool ValidateSpecialHashes(MachObjectFile file, byte[] infoFileBytes, byte[] codeResourcesBytes) { byte[] codeSignatureBytes = file.GetCodeSignatureBytes(); if (CodeSignatureSuperBlob.IsCodeSignatureSuperBlob(codeSignatureBytes, 0)) { CodeSignatureSuperBlob codeSignature = new CodeSignatureSuperBlob(codeSignatureBytes, 0); CodeDirectoryBlob codeDirectory = codeSignature.GetEntry(CodeSignatureEntryType.CodeDirectory) as CodeDirectoryBlob; byte[] infoFileHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, infoFileBytes); if (!ByteUtils.AreByteArraysEqual(infoFileHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.InfoFileHashOffset])) { return(false); } byte[] codeResourcesHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeResourcesBytes); if (!ByteUtils.AreByteArraysEqual(codeResourcesHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.CodeResourcesFileHashOffset])) { return(false); } CodeRequirementsBlob codeRequirements = codeSignature.GetEntry(CodeSignatureEntryType.Requirements) as CodeRequirementsBlob; byte[] codeRequirementsBytes = codeRequirements.GetBytes(); byte[] codeRequirementsHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeRequirementsBytes); if (!ByteUtils.AreByteArraysEqual(codeRequirementsHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.RequirementsHashOffset])) { return(false); } if (codeDirectory.SpecialHashes.Count >= CodeDirectoryBlob.EntitlementsHashOffset) { CodeSignatureGenericBlob entitlements = codeSignature.GetEntry(CodeSignatureEntryType.Entitlements) as CodeSignatureGenericBlob; byte[] entitlementsBytes = entitlements.GetBytes(); byte[] entitlementsHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, entitlementsBytes); if (!ByteUtils.AreByteArraysEqual(entitlementsHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.EntitlementsHashOffset])) { return(false); } } return(true); } return(false); }
public static bool ValidateExecutableHash(MachObjectFile file) { byte[] codeSignatureBytes = file.GetCodeSignatureBytes(); if (CodeSignatureSuperBlob.IsCodeSignatureSuperBlob(codeSignatureBytes, 0)) { CodeSignatureSuperBlob codeSignature = new CodeSignatureSuperBlob(codeSignatureBytes, 0); CodeDirectoryBlob codeDirectory = codeSignature.GetEntry(CodeSignatureEntryType.CodeDirectory) as CodeDirectoryBlob; byte[] signedFileData = ByteReader.ReadBytes(file.GetBytes(), 0, (int)codeDirectory.CodeLimit); List <byte[]> hashes = HashAlgorithmHelper.ComputeHashes(codeDirectory.HashType, codeDirectory.PageSize, signedFileData); if (hashes.Count != codeDirectory.CodeHashes.Count) { return(false); } for (int index = 0; index < hashes.Count; index++) { if (!ByteUtils.AreByteArraysEqual(hashes[index], codeDirectory.CodeHashes[index])) { return(false); } } return(true); } return(false); }