+//
+// Fetch an array of all available CodeDirectories.
+// Returns false if unsigned (no classic CD slot), true otherwise.
+//
+bool SecStaticCode::loadCodeDirectories(CodeDirectoryMap& cdMap) const
+{
+ __block CodeDirectoryMap candidates;
+ auto add = ^bool (CodeDirectory::SpecialSlot slot){
+ CFRef<CFDataRef> cdData = diskRep()->component(slot);
+ if (!cdData)
+ return false;
+ const CodeDirectory* cd = reinterpret_cast<const CodeDirectory*>(CFDataGetBytePtr(cdData));
+ if (!cd->validateBlob(CFDataGetLength(cdData)))
+ MacOSError::throwMe(errSecCSSignatureFailed); // no recovery - any suspect CD fails
+ cd->checkIntegrity();
+ auto result = candidates.insert(make_pair(cd->hashType, cdData.get()));
+ if (!result.second)
+ MacOSError::throwMe(errSecCSSignatureFailed); // duplicate hashType, go to heck
+ mHashAlgorithms.insert(cd->hashType);
+ if (slot == cdCodeDirectorySlot)
+ mBaseDir = cdData;
+ return true;
+ };
+ if (!add(cdCodeDirectorySlot))
+ return false; // no classic slot CodeDirectory -> unsigned
+ for (CodeDirectory::SpecialSlot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; slot++)
+ if (!add(slot)) // no CodeDirectory at this slot -> end of alternates
+ break;
+ if (candidates.empty())
+ MacOSError::throwMe(errSecCSSignatureFailed); // no viable CodeDirectory in sight
+ cdMap.swap(candidates);
+ return true;
+}
+
+