+ vector<Hashing::Byte> digest_vector(hasher->digestLength());
+ hasher->finish(digest_vector.data());
+ return CFDataCreate(NULL, digest_vector.data(),
+ digest_vector.size() * sizeof(Hashing::Byte));
+}
+
+
+//
+// Hash a file to multiple hash types and return a dictionary suitable to form a resource seal
+//
+CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithms types, bool strictCheck)
+{
+ UnixPlusPlus::AutoFileDesc fd(path);
+ fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass)
+ if (strictCheck)
+ if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME))
+ MacOSError::throwMe(errSecCSInvalidAssociatedFileData);
+ CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
+ CFMutableDictionaryRef resultRef = result;
+ CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) {
+ size_t length = hasher->digestLength();
+ vector<Hashing::Byte> digest_vector(length);
+ hasher->finish(digest_vector.data());
+ CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest_vector.data(), length));
+ });
+ return result.yield();
+}
+
+
+std::string ResourceBuilder::hashName(CodeDirectory::HashAlgorithm type)
+{
+ switch (type) {
+ case kSecCodeSignatureHashSHA1:
+ return "hash";
+ default:
+ char name[20];
+ snprintf(name, sizeof(name), "hash%d", int(type));
+ return name;
+ }