]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_codesigning/lib/resources.cpp
Security-57337.60.2.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / resources.cpp
index 5695800eabce99099c96aecb947cc1d414247952..c1efa959ce5d039785e2ab77fb47c6bb24aa469f 100644 (file)
@@ -61,9 +61,8 @@ static string removeTrailingSlash(string path)
 // Construction and maintainance
 //
 ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &relBase,
-       CFDictionaryRef rulesDict, CodeDirectory::HashAlgorithm hashType, bool strict, const MacOSErrorSet& toleratedErrors)
-       : mHashType(hashType),
-         mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()),
+       CFDictionaryRef rulesDict, bool strict, const MacOSErrorSet& toleratedErrors)
+       : mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()),
          mCheckUnknownType(strict && toleratedErrors.find(errSecCSResourceNotSupported) == toleratedErrors.end())
 {
        assert(!root.empty());
@@ -274,11 +273,11 @@ ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const
 //
 // Hash a file and return a CFDataRef with the hash
 //
-CFDataRef ResourceBuilder::hashFile(const char *path) const
+CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithm type)
 {
        UnixPlusPlus::AutoFileDesc fd(path);
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
-       MakeHash<ResourceBuilder> hasher(this);
+       RefPointer<DynamicHash> hasher(CodeDirectory::hashFor(type));
        hashFileData(fd, hasher.get());
        Hashing::Byte digest[hasher->digestLength()];
        hasher->finish(digest);
@@ -286,6 +285,38 @@ CFDataRef ResourceBuilder::hashFile(const char *path) const
 }
 
 
+//
+// 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)
+{
+       UnixPlusPlus::AutoFileDesc fd(path);
+       fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
+       CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
+       CFMutableDictionaryRef resultRef = result;
+       CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) {
+               size_t length = hasher->digestLength();
+               Hashing::Byte digest[length];
+               hasher->finish(digest);
+               CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest, 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;
+       }
+}
+
+
 //
 // Regex matching objects
 //
@@ -333,29 +364,43 @@ std::string ResourceBuilder::escapeRE(const std::string &s)
 // Resource Seals
 //
 ResourceSeal::ResourceSeal(CFTypeRef it)
-       : mDict(NULL), mHash(NULL), mRequirement(NULL), mLink(NULL), mFlags(0)
+       : mDict(NULL), mRequirement(NULL), mLink(NULL), mFlags(0)
 {
        if (it == NULL)
                MacOSError::throwMe(errSecCSResourcesInvalid);
-       if (CFGetTypeID(it) == CFDataGetTypeID()) {
-               mHash = CFDataRef(it);
-       } else {
-               int optional = 0;
+       if (CFGetTypeID(it) == CFDataGetTypeID())       // old-style form with just a hash
+               mDict.take(cfmake<CFDictionaryRef>("{hash=%O}", it));
+       else if (CFGetTypeID(it) == CFDictionaryGetTypeID())
                mDict = CFDictionaryRef(it);
-               bool err;
-               if (CFDictionaryGetValue(mDict, CFSTR("requirement")))
-                       err = !cfscan(mDict, "{requirement=%SO,?optional=%B}", &mRequirement, &optional);
-               else if (CFDictionaryGetValue(mDict, CFSTR("symlink")))
-                       err = !cfscan(mDict, "{symlink=%SO,?optional=%B}", &mLink, &optional);
-               else
-                       err = !cfscan(mDict, "{hash=%XO,?optional=%B}", &mHash, &optional);
-               if (err)
-                       MacOSError::throwMe(errSecCSResourcesInvalid);
-               if (optional)
-                       mFlags |= ResourceBuilder::optional;
-               if (mRequirement)
-                       mFlags |= ResourceBuilder::nested;
-       }
+       else
+               MacOSError::throwMe(errSecCSResourcesInvalid);
+
+       int optional = 0;
+       bool err;
+       if (CFDictionaryGetValue(mDict, CFSTR("requirement")))
+               err = !cfscan(mDict, "{requirement=%SO,?optional=%B}", &mRequirement, &optional);
+       else if (CFDictionaryGetValue(mDict, CFSTR("symlink")))
+               err = !cfscan(mDict, "{symlink=%SO,?optional=%B}", &mLink, &optional);
+       else
+               err = !cfscan(mDict, "{?optional=%B}", &optional);
+       if (err)
+               MacOSError::throwMe(errSecCSResourcesInvalid);
+       if (optional)
+               mFlags |= ResourceBuilder::optional;
+       if (mRequirement)
+               mFlags |= ResourceBuilder::nested;
+}
+       
+       
+const Hashing::Byte *ResourceSeal::hash(CodeDirectory::HashAlgorithm type) const
+{
+       std::string name = ResourceBuilder::hashName(type);
+       CFTypeRef hash = CFDictionaryGetValue(mDict, CFTempString(name));
+       if (hash == NULL)       // pre-agility fallback
+               hash = CFDictionaryGetValue(mDict, CFSTR("hash"));
+       if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID())
+               MacOSError::throwMe(errSecCSResourcesInvalid);
+       return CFDataGetBytePtr(CFDataRef(hash));
 }