X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..02b2aca600d4a0fe6fb259262bd6808ef889acde:/OSX/libsecurity_codesigning/lib/CodeSigner.cpp diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index ee8045f9..8cbc67f8 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace Security { @@ -58,6 +59,53 @@ public: else return false; } + + uint32_t parseRuntimeVersion(std::string& runtime) + { + uint32_t version = 0; + char* cursor = const_cast(runtime.c_str()); + char* end = cursor + runtime.length(); + char* nxt = NULL; + long component = 0; + int component_shift = 16; + + // x should convert to 0x00XX0000 + // x.y should convert to 0x00XXYY00 + // x.y.z should covert to 0x00XXYYZZ + // 0, 0.0, and 0.0.0 are rejected + // anything else should be rejected + while (cursor < end) { + nxt = NULL; + errno = 0; + component = strtol(cursor, &nxt, 10); + if (cursor == nxt || + (errno != 0) || + (component < 0 || component > UINT8_MAX)) { + secdebug("signer", "Runtime version: %s is invalid", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + version |= (component & 0xff) << component_shift; + component_shift -= 8; + + if (*nxt == '\0') { + break; + } + + if (*nxt != '.' || component_shift < 0 || (nxt + 1) == end) { + // Catch a trailing "." + secdebug("signer", "Runtime version: %s is invalid", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + cursor = nxt + 1; + } + + if (version == 0) { + secdebug("signer","Runtime version: %s is a version of zero", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + + return version; + } }; @@ -65,7 +113,7 @@ public: // Construct a SecCodeSigner // SecCodeSigner::SecCodeSigner(SecCSFlags flags) - : mOpFlags(flags), mLimitedAsync(NULL) + : mOpFlags(flags), mLimitedAsync(NULL), mRuntimeVersionOverride(0) { } @@ -73,7 +121,7 @@ SecCodeSigner::SecCodeSigner(SecCSFlags flags) // // Clean up a SecCodeSigner // -SecCodeSigner::~SecCodeSigner() throw() +SecCodeSigner::~SecCodeSigner() _NOEXCEPT try { delete mLimitedAsync; } catch (...) { @@ -122,8 +170,9 @@ std::string SecCodeSigner::getTeamIDFromSigner(CFArrayRef certs) // bool SecCodeSigner::valid() const { - if (mOpFlags & kSecCSRemoveSignature) + if (mOpFlags & (kSecCSRemoveSignature | kSecCSEditSignature)) { return true; + } return mSigner; } @@ -133,13 +182,20 @@ bool SecCodeSigner::valid() const // void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) { - code->setValidationFlags(flags); - if (code->isSigned() && (flags & kSecCSSignPreserveSignature)) + //Never preserve a linker signature. + if (code->isSigned() && + (flags & kSecCSSignPreserveSignature) && + !code->flag(kSecCodeSignatureLinkerSigned)) { return; + } + code->setValidationFlags(flags); Signer operation(*this, code); if ((flags | mOpFlags) & kSecCSRemoveSignature) { secinfo("signer", "%p will remove signature from %p", this, code); operation.remove(flags); + } else if ((flags | mOpFlags) & kSecCSEditSignature) { + secinfo("signer", "%p will edit signature of %p", this, code); + operation.edit(flags); } else { if (!valid()) MacOSError::throwMe(errSecCSInvalidObjectRef); @@ -181,6 +237,29 @@ void SecCodeSigner::returnDetachedSignature(BlobCore *blob, Signer &signer) SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) : CFDictionary(parameters, errSecCSBadDictionaryFormat) { + CFNumberRef editCpuType = get(kSecCodeSignerEditCpuType); + CFNumberRef editCpuSubtype = get(kSecCodeSignerEditCpuSubtype); + if (editCpuType != NULL && editCpuSubtype != NULL) { + state.mEditArch = Architecture(cfNumber(editCpuType), + cfNumber(editCpuSubtype)); + } + + state.mEditCMS = get(kSecCodeSignerEditCMS); + + state.mDryRun = getBool(kSecCodeSignerDryRun); + + state.mSDKRoot = get(kSecCodeSignerSDKRoot); + + state.mPreserveAFSC = getBool(kSecCodeSignerPreserveAFSC); + + if (state.mOpFlags & kSecCSEditSignature) { + return; + /* Everything below this point is irrelevant for + * Signature Editing, which does not create any + * parts of the signature, only replaces them. + */ + } + // the signer may be an identity or null state.mSigner = SecIdentityRef(get(kSecCodeSignerIdentity)); if (state.mSigner) @@ -204,7 +283,7 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) if (CFNumberRef cmsSize = get(CFSTR("cmssize"))) state.mCMSSize = cfNumber(cmsSize); else - state.mCMSSize = 9000; // likely big enough + state.mCMSSize = 18000; // big enough for now, not forever. // metadata preservation options if (CFNumberRef preserve = get(kSecCodeSignerPreserveMetadata)) { @@ -257,15 +336,11 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) MacOSError::throwMe(errSecCSInvalidObjectRef); } - state.mDryRun = getBool(kSecCodeSignerDryRun); - state.mResourceRules = get(kSecCodeSignerResourceRules); state.mApplicationData = get(kSecCodeSignerApplicationData); state.mEntitlementData = get(kSecCodeSignerEntitlements); - state.mSDKRoot = get(kSecCodeSignerSDKRoot); - if (CFBooleanRef timestampRequest = get(kSecCodeSignerRequireTimestamp)) { state.mWantTimeStamp = timestampRequest == kCFBooleanTrue; } else { // pick default @@ -280,6 +355,18 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) state.mTimestampAuthentication = get(kSecCodeSignerTimestampAuthentication); state.mTimestampService = get(kSecCodeSignerTimestampServer); state.mNoTimeStampCerts = getBool(kSecCodeSignerTimestampOmitCertificates); + + if (CFStringRef runtimeVersionOverride = get(kSecCodeSignerRuntimeVersion)) { + std::string runtime = cfString(runtimeVersionOverride); + if (runtime.empty()) { + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + state.mRuntimeVersionOverride = parseRuntimeVersion(runtime); + } + + // Don't add the adhoc flag, even if no signer identity was specified. + // Useful for editing in the CMS at a later point. + state.mOmitAdhocFlag = getBool(kSecCodeSignerOmitAdhocFlag); }