mGotResourceBase = false;
mTrust = NULL;
mCertChain = NULL;
+ mNotarizationChecked = false;
+ mStaplingChecked = false;
+ mNotarizationDate = NAN;
#if TARGET_OS_OSX
mEvalDetails = NULL;
#endif
return mCDHashes;
}
+//
+// Get a dictionary of untruncated cdhashes for all digest types in this signature.
+//
+CFDictionaryRef SecStaticCode::cdHashesFull()
+{
+ if (!mCDHashFullDict) {
+ CFRef<CFMutableDictionaryRef> cdDict = makeCFMutableDictionary();
+ for (auto const &it : mCodeDirectories) {
+ CodeDirectory::HashAlgorithm alg = it.first;
+ const CodeDirectory *cd = (const CodeDirectory *)CFDataGetBytePtr(it.second);
+ CFRef<CFDataRef> hash = cd->cdhash(false);
+ if (hash) {
+ CFDictionaryAddValue(cdDict, CFTempNumber(alg), hash);
+ }
+ }
+ mCDHashFullDict = cdDict.get();
+ }
+ return mCDHashFullDict;
+}
+
//
// Return the CMS signature blob; NULL if none found.
if (doit) {
if (mLimitedAsync == NULL) {
- mLimitedAsync = new LimitedAsync(diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey);
+ bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false :
+ (diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey);
+ mLimitedAsync = new LimitedAsync(runMultiThreaded);
}
try {
#if TARGET_OS_OSX
// full signature: Gin up full context and let DRMaker do its thing
validateDirectory(); // need the cert chain
+ CFRef<CFDateRef> secureTimestamp;
+ if (CFAbsoluteTime time = this->signingTimestamp()) {
+ secureTimestamp.take(CFDateCreate(NULL, time));
+ }
Requirement::Context context(this->certificates(),
this->infoDictionary(),
this->entitlements(),
this->codeDirectory(),
NULL,
kSecCodeSignatureNoHash,
- false
+ false,
+ secureTimestamp,
+ this->teamID()
);
return DRMaker(context).make();
#else
bool result = false;
assert(req);
validateDirectory();
- result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), codeDirectory()->identifier(), codeDirectory(), NULL, kSecCodeSignatureNoHash, mRep->appleInternalForcePlatform()), failure);
+ CFRef<CFDateRef> secureTimestamp;
+ if (CFAbsoluteTime time = this->signingTimestamp()) {
+ secureTimestamp.take(CFDateCreate(NULL, time));
+ }
+ result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(),
+ codeDirectory()->identifier(), codeDirectory(),
+ NULL, kSecCodeSignatureNoHash, mRep->appleInternalForcePlatform(),
+ secureTimestamp, teamID()),
+ failure);
return result;
}
CFDictionaryAddValue(dict, kSecCodeInfoSource, CFTempString(this->signatureSource()));
CFDictionaryAddValue(dict, kSecCodeInfoUnique, this->cdHash());
CFDictionaryAddValue(dict, kSecCodeInfoCdHashes, this->cdHashes());
+ CFDictionaryAddValue(dict, kSecCodeInfoCdHashesFull, this->cdHashesFull());
const CodeDirectory* cd = this->codeDirectory(false);
CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithm, CFTempNumber(cd->hashType));
CFRef<CFArrayRef> digests = makeCFArrayFrom(^CFTypeRef(CodeDirectory::HashAlgorithm type) { return CFTempNumber(type); }, hashAlgorithms());
}
}
+ if (flags & kSecCSCalculateCMSDigest) {
+ try {
+ CFDictionaryAddValue(dict, kSecCodeInfoCMSDigestHashType, CFTempNumber(cmsDigestHashType()));
+
+ CFRef<CFDataRef> cmsDigest = createCmsDigest();
+ if (cmsDigest) {
+ CFDictionaryAddValue(dict, kSecCodeInfoCMSDigest, cmsDigest.get());
+ }
+ } catch (...) { }
+ }
//
// kSecCSContentInformation adds more information about the physical layout
this->validateResources(flags);
// perform strict validation if desired
- if (flags & kSecCSStrictValidate)
+ if (flags & kSecCSStrictValidate) {
mRep->strictValidate(codeDirectory(), mTolerateErrors, mValidationFlags);
reportProgress();
+ } else if (flags & kSecCSStrictValidateStructure) {
+ mRep->strictValidateStructure(codeDirectory(), mTolerateErrors, mValidationFlags);
+ }
// allow monitor intervention
if (CFRef<CFTypeRef> veto = reportEvent(CFSTR("validated"), NULL)) {
{
static const std::string appleDeveloperRequirement = "(" + std::string(WWDRRequirement) + ") or (" + MACWWDRRequirement + ") or (" + developerID + ") or (" + distributionCertificate + ") or (" + iPhoneDistributionCert + ")";
SecPointer<SecRequirement> req = new SecRequirement(parseRequirement(appleDeveloperRequirement), true);
- Requirement::Context ctx(certs, NULL, NULL, "", NULL, NULL, kSecCodeSignatureNoHash, false);
+ Requirement::Context ctx(certs, NULL, NULL, "", NULL, NULL, kSecCodeSignatureNoHash, false, NULL, "");
return req->requirement()->validates(ctx);
}
+CFDataRef SecStaticCode::createCmsDigest()
+{
+ /*
+ * The CMS digest is a hash of the primary (first, most compatible) code directory,
+ * but its hash algorithm is fixed and not related to the code directory's
+ * hash algorithm.
+ */
+
+ auto it = codeDirectories()->begin();
+
+ if (it == codeDirectories()->end()) {
+ return NULL;
+ }
+
+ CodeDirectory const * const cd = reinterpret_cast<CodeDirectory const*>(CFDataGetBytePtr(it->second));
+
+ RefPointer<DynamicHash> hash = cd->hashFor(mCMSDigestHashType);
+ CFMutableDataRef data = CFDataCreateMutable(NULL, hash->digestLength());
+ CFDataSetLength(data, hash->digestLength());
+ hash->update(cd, cd->length());
+ hash->finish(CFDataGetMutableBytePtr(data));
+
+ return data;
+}
+
} // end namespace CodeSigning
} // end namespace Security