]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_codesigning/lib/signer.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_codesigning / lib / signer.cpp
diff --git a/libsecurity_codesigning/lib/signer.cpp b/libsecurity_codesigning/lib/signer.cpp
deleted file mode 100644 (file)
index c11ce0c..0000000
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-//
-// signer - Signing operation supervisor and controller
-//
-#include "signer.h"
-#include "resources.h"
-#include "signerutils.h"
-#include "SecCodeSigner.h"
-#include <Security/SecIdentity.h>
-#include <Security/CMSEncoder.h>
-#include <Security/CMSPrivate.h>
-#include <Security/CSCommonPriv.h>
-#include <CoreFoundation/CFBundlePriv.h>
-#include "resources.h"
-#include "machorep.h"
-#include "reqparser.h"
-#include "reqdumper.h"
-#include "csutilities.h"
-#include <security_utilities/unix++.h>
-#include <security_utilities/unixchild.h>
-#include <security_utilities/cfmunge.h>
-
-namespace Security {
-namespace CodeSigning {
-
-
-//
-// Sign some code.
-//
-void SecCodeSigner::Signer::sign(SecCSFlags flags)
-{
-       rep = code->diskRep()->base();
-       this->prepare(flags);
-
-       PreSigningContext context(*this);
-
-       /* If an explicit teamID was passed in it must be
-        the same as what came from the cert */
-       std::string teamIDFromCert = state.getTeamIDFromSigner(context.certs);
-
-       if (state.mPreserveMetadata & kSecCodeSignerPreserveTeamIdentifier) {
-               /* If preserving the team identifier, teamID is set previously when the
-                code object is still available */
-               if (!teamIDFromCert.empty() && teamID != teamIDFromCert)
-                       MacOSError::throwMe(errSecCSInvalidFlags);
-       } else {
-               if (teamIDFromCert.empty()) {
-                       /* state.mTeamID is an explicitly passed teamID */
-                       teamID = state.mTeamID;
-               } else if (state.mTeamID.empty() || (state.mTeamID == teamIDFromCert)) {
-                       /* If there was no explicit team ID set, or the explicit team ID matches
-                        what is in the cert, use the team ID from the certificate */
-                       teamID = teamIDFromCert;
-               } else {
-                       /* The caller passed in an explicit team ID that does not match what is
-                        in the signing cert, which is an invalid usage */
-                       MacOSError::throwMe(errSecCSInvalidFlags);
-               }
-       }
-
-       if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) {
-               signMachO(fat, context);
-       } else {
-               signArchitectureAgnostic(context);
-       }
-}
-
-
-//
-// Remove any existing code signature from code
-//
-void SecCodeSigner::Signer::remove(SecCSFlags flags)
-{
-       // can't remove a detached signature
-       if (state.mDetached)
-               MacOSError::throwMe(errSecCSNotSupported);
-
-       rep = code->diskRep();
-       if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) {
-               // architecture-sensitive removal
-               MachOEditor editor(rep->writer(), *fat, kSecCodeSignatureNoHash, rep->mainExecutablePath());
-               editor.allocate();              // create copy
-               editor.commit();                // commit change
-       } else {
-               // architecture-agnostic removal
-               RefPointer<DiskRep::Writer> writer = rep->writer();
-               writer->remove();
-               writer->flush();
-       }
-}
-
-
-//
-// Contemplate the object-to-be-signed and set up the Signer state accordingly.
-//
-void SecCodeSigner::Signer::prepare(SecCSFlags flags)
-{
-       // make sure the rep passes strict validation
-       if (strict)
-               rep->strictValidate(MacOSErrorSet());
-
-       // get the Info.plist out of the rep for some creative defaulting
-       CFRef<CFDictionaryRef> infoDict;
-       if (CFRef<CFDataRef> infoData = rep->component(cdInfoSlot))
-               infoDict.take(makeCFDictionaryFrom(infoData));
-       
-       uint32_t inherit = code->isSigned() ? state.mPreserveMetadata : 0;
-
-       // work out the canonical identifier
-       identifier = state.mIdentifier;
-       if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier))
-               identifier = code->identifier();
-       if (identifier.empty()) {
-               identifier = rep->recommendedIdentifier(state);
-               if (identifier.find('.') == string::npos)
-                       identifier = state.mIdentifierPrefix + identifier;
-               if (identifier.find('.') == string::npos && state.isAdhoc())
-                       identifier = identifier + "-" + uniqueName();
-               secdebug("signer", "using default identifier=%s", identifier.c_str());
-       } else
-               secdebug("signer", "using explicit identifier=%s", identifier.c_str());
-
-       teamID = state.mTeamID;
-       if (teamID.empty() && (inherit & kSecCodeSignerPreserveTeamIdentifier)) {
-               const char *c_id = code->teamID();
-               if (c_id)
-                       teamID = c_id;
-       }
-    
-       entitlements = state.mEntitlementData;
-       if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements))
-               entitlements = code->component(cdEntitlementSlot);
-       
-       // work out the CodeDirectory flags word
-       bool haveCdFlags = false;
-       if (!haveCdFlags && state.mCdFlagsGiven) {
-               cdFlags = state.mCdFlags;
-               secdebug("signer", "using explicit cdFlags=0x%x", cdFlags);
-               haveCdFlags = true;
-       }
-       if (!haveCdFlags) {
-               cdFlags = 0;
-               if (infoDict)
-                       if (CFTypeRef csflags = CFDictionaryGetValue(infoDict, CFSTR("CSFlags"))) {
-                               if (CFGetTypeID(csflags) == CFNumberGetTypeID()) {
-                                       cdFlags = cfNumber<uint32_t>(CFNumberRef(csflags));
-                                       secdebug("signer", "using numeric cdFlags=0x%x from Info.plist", cdFlags);
-                               } else if (CFGetTypeID(csflags) == CFStringGetTypeID()) {
-                                       cdFlags = cdTextFlags(cfString(CFStringRef(csflags)));
-                                       secdebug("signer", "using text cdFlags=0x%x from Info.plist", cdFlags);
-                               } else
-                                       MacOSError::throwMe(errSecCSBadDictionaryFormat);
-                               haveCdFlags = true;
-                       }
-       }
-       if (!haveCdFlags && (inherit & kSecCodeSignerPreserveFlags)) {
-               cdFlags = code->codeDirectory(false)->flags & ~kSecCodeSignatureAdhoc;
-               secdebug("signer", "using inherited cdFlags=0x%x", cdFlags);
-               haveCdFlags = true;
-       }
-       if (!haveCdFlags)
-               cdFlags = 0;
-       if (state.mSigner == SecIdentityRef(kCFNull))   // ad-hoc signing requested...
-               cdFlags |= kSecCodeSignatureAdhoc;      // ... so note that
-
-       // prepare the internal requirements input
-       if (state.mRequirements) {
-               if (CFGetTypeID(state.mRequirements) == CFDataGetTypeID()) {            // binary form
-                       const Requirements *rp = (const Requirements *)CFDataGetBytePtr(state.mRequirements.as<CFDataRef>());
-                       if (!rp->validateBlob())
-                               MacOSError::throwMe(errSecCSReqInvalid);
-                       requirements = rp->clone();
-               } else if (CFGetTypeID(state.mRequirements) == CFStringGetTypeID()) { // text form
-                       CFRef<CFMutableStringRef> reqText = CFStringCreateMutableCopy(NULL, 0, state.mRequirements.as<CFStringRef>());
-                       // substitute $ variable tokens
-                       CFRange range = { 0, CFStringGetLength(reqText) };
-                       CFStringFindAndReplace(reqText, CFSTR("$self.identifier"), CFTempString(identifier), range, 0);
-                       requirements = parseRequirements(cfString(reqText));
-               } else
-                       MacOSError::throwMe(errSecCSInvalidObjectRef);
-       } else if (inherit & kSecCodeSignerPreserveRequirements)
-               if (const Requirements *rp = code->internalRequirements())
-                       requirements = rp->clone();
-       
-       // prepare the resource directory, if any
-       string rpath = rep->resourcesRootPath();
-       if (!rpath.empty()) {
-               // explicitly given resource rules always win
-               CFCopyRef<CFDictionaryRef> resourceRules = state.mResourceRules;
-               
-               // inherited rules come next (overriding embedded ones!)
-               if (!resourceRules && (inherit & kSecCodeSignerPreserveResourceRules))
-                       if (CFDictionaryRef oldRules = code->resourceDictionary(false))
-                               resourceRules = oldRules;
-               
-               // embedded resource rules come next
-               if (!resourceRules && infoDict)
-                       if (CFTypeRef spec = CFDictionaryGetValue(infoDict, _kCFBundleResourceSpecificationKey)) {
-                               if (CFGetTypeID(spec) == CFStringGetTypeID())
-                                       if (CFRef<CFDataRef> data = cfLoadFile(rpath + "/" + cfString(CFStringRef(spec))))
-                                               if (CFDictionaryRef dict = makeCFDictionaryFrom(data))
-                                                       resourceRules.take(dict);
-                               if (!resourceRules)     // embedded rules present but unacceptable
-                                       MacOSError::throwMe(errSecCSResourceRulesInvalid);
-                       }
-               
-               // if we got one from anywhere (but the defaults), sanity-check it
-               if (resourceRules) {
-                       CFTypeRef rules = CFDictionaryGetValue(resourceRules, CFSTR("rules"));
-                       if (!rules || CFGetTypeID(rules) != CFDictionaryGetTypeID())
-                               MacOSError::throwMe(errSecCSResourceRulesInvalid);
-               }
-
-               // finally, ask the DiskRep for its default
-               if (!resourceRules)
-                       resourceRules.take(rep->defaultResourceRules(state));
-
-               // resource root can optionally be the canonical bundle path,
-               // but sealed resource paths are always relative to rpath
-               string root = rpath;
-               if (state.signingFlags() & kSecCSSignBundleRoot)
-                       root = cfStringRelease(rep->copyCanonicalPath());
-
-               // build the resource directory
-               buildResources(root, rpath, resourceRules);
-       }
-       
-       // screen and set the signing time
-       CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
-       if (state.mSigningTime == CFDateRef(kCFNull)) {
-               signingTime = 0;                // no time at all
-       } else if (!state.mSigningTime) {
-               signingTime = now;              // default
-       } else {
-               CFAbsoluteTime time = CFDateGetAbsoluteTime(state.mSigningTime);
-               if (time > now) // not allowed to post-date a signature
-                       MacOSError::throwMe(errSecCSBadDictionaryFormat);
-               signingTime = time;
-       }
-       
-       pagesize = state.mPageSize ? cfNumber<size_t>(state.mPageSize) : rep->pageSize(state);
-    
-    // Timestamping setup
-    CFRef<SecIdentityRef> mTSAuth;     // identity for client-side authentication to the Timestamp server
-}
-
-
-//
-// Collect the resource seal for a program.
-// This includes both sealed resources and information about nested code.
-//
-void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase, CFDictionaryRef rulesDict)
-{
-       typedef ResourceBuilder::Rule Rule;
-       
-       secdebug("codesign", "start building resource directory");
-       __block CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
-       
-       CFDictionaryRef rules = cfget<CFDictionaryRef>(rulesDict, "rules");
-       assert(rules);
-
-       CFDictionaryRef files2 = NULL;
-       if (!(state.signingFlags() & kSecCSSignV1)) {
-               CFCopyRef<CFDictionaryRef> rules2 = cfget<CFDictionaryRef>(rulesDict, "rules2");
-               if (!rules2) {
-                       // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules).
-                       // V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them.
-                       rules2 = cfmake<CFDictionaryRef>("{+%O"
-                               "'^[^/]+$' = {top=#T, weight=0}"                        // files directly in Contents
-                               "'^(Frameworks|SharedFrameworks|Plugins|Plug-ins|XPCServices|Helpers|MacOS)/' = {nested=#T, weight=0}" // exclude dynamic repositories
-                       "}", rules);
-               }
-               // build the modern (V2) resource seal
-               __block CFRef<CFMutableDictionaryRef> files = makeCFMutableDictionary();
-               ResourceBuilder resourceBuilder(root, relBase, rules2, digestAlgorithm(), strict, MacOSErrorSet());
-               ResourceBuilder &resources = resourceBuilder;   // (into block)
-               rep->adjustResources(resources);
-               resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const char *relpath, Rule *rule) {
-                       CFRef<CFMutableDictionaryRef> seal;
-                       if (ruleFlags & ResourceBuilder::nested) {
-                               seal.take(signNested(ent, relpath));
-                       } else if (ent->fts_info == FTS_SL) {
-                               char target[PATH_MAX];
-                               ssize_t len = ::readlink(ent->fts_accpath, target, sizeof(target)-1);
-                               if (len < 0)
-                                       UnixError::check(-1);
-                               target[len] = '\0';
-                               seal.take(cfmake<CFMutableDictionaryRef>("{symlink=%s}", target));
-                       } else {
-                               seal.take(cfmake<CFMutableDictionaryRef>("{hash=%O}",
-                                       CFRef<CFDataRef>(resources.hashFile(ent->fts_accpath)).get()));
-                       }
-                       if (ruleFlags & ResourceBuilder::optional)
-                               CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue);
-                       CFTypeRef hash;
-                       if ((hash = CFDictionaryGetValue(seal, CFSTR("hash"))) && CFDictionaryGetCount(seal) == 1) // simple form
-                               CFDictionaryAddValue(files, CFTempString(relpath).get(), hash);
-                       else
-                               CFDictionaryAddValue(files, CFTempString(relpath).get(), seal.get());
-               });
-               CFDictionaryAddValue(result, CFSTR("rules2"), resourceBuilder.rules());
-               files2 = files;
-               CFDictionaryAddValue(result, CFSTR("files2"), files2);
-       }
-       
-       CFDictionaryAddValue(result, CFSTR("rules"), rules);    // preserve V1 rules in any case
-       if (!(state.signingFlags() & kSecCSSignNoV1)) {
-               // build the legacy (V1) resource seal
-               __block CFRef<CFMutableDictionaryRef> files = makeCFMutableDictionary();
-               ResourceBuilder resourceBuilder(root, relBase, rules, digestAlgorithm(), strict, MacOSErrorSet());
-               ResourceBuilder &resources = resourceBuilder;
-               rep->adjustResources(resources);        // DiskRep-specific adjustments
-               resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const char *relpath, Rule *rule) {
-                       if (ent->fts_info == FTS_F) {
-                               CFRef<CFDataRef> hash;
-                               if (files2)     // try to get the hash from a previously-made version
-                                       if (CFTypeRef seal = CFDictionaryGetValue(files2, CFTempString(relpath))) {
-                                               if (CFGetTypeID(seal) == CFDataGetTypeID())
-                                                       hash = CFDataRef(seal);
-                                               else
-                                                       hash = CFDataRef(CFDictionaryGetValue(CFDictionaryRef(seal), CFSTR("hash")));
-                                       }
-                               if (!hash)
-                                       hash.take(resources.hashFile(ent->fts_accpath));
-                               if (ruleFlags == 0) {   // default case - plain hash
-                                       cfadd(files, "{%s=%O}", relpath, hash.get());
-                                       secdebug("csresource", "%s added simple (rule %p)", relpath, rule);
-                               } else {        // more complicated - use a sub-dictionary
-                                       cfadd(files, "{%s={hash=%O,optional=%B}}",
-                                               relpath, hash.get(), ruleFlags & ResourceBuilder::optional);
-                                       secdebug("csresource", "%s added complex (rule %p)", relpath, rule);
-                               }
-                       }
-               });
-               CFDictionaryAddValue(result, CFSTR("files"), files.get());
-       }
-       
-       resourceDirectory = result.get();
-       resourceDictData.take(makeCFData(resourceDirectory.get()));
-}
-
-
-//
-// Deal with one piece of nested code
-//
-CFMutableDictionaryRef SecCodeSigner::Signer::signNested(FTSENT *ent, const char *relpath)
-{
-       // sign nested code and collect nesting information
-       try {
-               SecPointer<SecStaticCode> code = new SecStaticCode(DiskRep::bestGuess(ent->fts_path));
-               if (state.signingFlags() & kSecCSSignNestedCode)
-                       this->state.sign(code, state.signingFlags());
-               std::string dr = Dumper::dump(code->designatedRequirement());
-               return cfmake<CFMutableDictionaryRef>("{requirement=%s,cdhash=%O}",
-                       Dumper::dump(code->designatedRequirement()).c_str(),
-                       code->cdHash());
-       } catch (const CommonError &err) {
-               CSError::throwMe(err.osStatus(), kSecCFErrorPath, CFTempURL(relpath, false, this->code->resourceBase()));
-       }
-}
-
-
-//
-// Sign a Mach-O binary, using liberal dollops of that special Mach-O magic sauce.
-// Note that this will deal just fine with non-fat Mach-O binaries, but it will
-// treat them as architectural binaries containing (only) one architecture - that
-// interpretation is courtesy of the Universal/MachO support classes.
-//
-void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context &context)
-{
-       // Mach-O executable at the core - perform multi-architecture signing
-       auto_ptr<ArchEditor> editor(state.mDetached
-               ? static_cast<ArchEditor *>(new BlobEditor(*fat, *this))
-               : new MachOEditor(rep->writer(), *fat, this->digestAlgorithm(), rep->mainExecutablePath()));
-       assert(editor->count() > 0);
-       if (!editor->attribute(writerNoGlobal)) // can store architecture-common components
-               populate(*editor);
-       
-       // pass 1: prepare signature blobs and calculate sizes
-       for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) {
-               MachOEditor::Arch &arch = *it->second;
-               arch.source.reset(fat->architecture(it->first));
-               arch.ireqs(requirements, rep->defaultRequirements(&arch.architecture, state), context);
-               if (editor->attribute(writerNoGlobal))  // can't store globally, add per-arch
-                       populate(arch);
-               populate(arch.cdbuilder, arch, arch.ireqs,
-                       arch.source->offset(), arch.source->signingExtent());
-       
-               // add identification blob (made from this architecture) only if we're making a detached signature
-               if (state.mDetached) {
-                       CFRef<CFDataRef> identification = MachORep::identificationFor(arch.source.get());
-                       arch.add(cdIdentificationSlot, BlobWrapper::alloc(
-                               CFDataGetBytePtr(identification), CFDataGetLength(identification)));
-               }
-               
-               // prepare SuperBlob size estimate
-               size_t cdSize = arch.cdbuilder.size(CodeDirectory::currentVersion);
-               arch.blobSize = arch.size(cdSize, state.mCMSSize, 0);
-       }
-       
-       editor->allocate();
-       
-       // pass 2: Finish and generate signatures, and write them
-       for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) {
-               MachOEditor::Arch &arch = *it->second;
-               editor->reset(arch);
-
-               // finish CodeDirectory (off new binary) and sign it
-               CodeDirectory *cd = arch.cdbuilder.build();
-               CFRef<CFDataRef> signature = signCodeDirectory(cd);
-               
-               // complete the SuperBlob
-               arch.add(cdCodeDirectorySlot, cd);      // takes ownership
-               arch.add(cdSignatureSlot, BlobWrapper::alloc(
-                       CFDataGetBytePtr(signature), CFDataGetLength(signature)));
-               if (!state.mDryRun) {
-                       EmbeddedSignatureBlob *blob = arch.make();
-                       editor->write(arch, blob);      // takes ownership of blob
-               }
-       }
-       
-       // done: write edit copy back over the original
-       if (!state.mDryRun)
-               editor->commit();
-}
-
-
-//
-// Sign a binary that has no notion of architecture.
-// That currently means anything that isn't Mach-O format.
-//
-void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context &context)
-{
-       // non-Mach-O executable - single-instance signing
-       RefPointer<DiskRep::Writer> writer = state.mDetached ?
-               (new DetachedBlobWriter(*this)) : rep->writer();
-       CodeDirectory::Builder builder(state.mDigestAlgorithm);
-       InternalRequirements ireqs;
-       ireqs(requirements, rep->defaultRequirements(NULL, state), context);
-       populate(*writer);
-       populate(builder, *writer, ireqs, rep->signingBase(), rep->signingLimit());
-       
-       // add identification blob (made from this architecture) only if we're making a detached signature
-       if (state.mDetached) {
-               CFRef<CFDataRef> identification = rep->identification();
-               writer->component(cdIdentificationSlot, identification);
-       }
-       
-       CodeDirectory *cd = builder.build();
-       CFRef<CFDataRef> signature = signCodeDirectory(cd);
-       if (!state.mDryRun) {
-               writer->codeDirectory(cd);
-               writer->signature(signature);
-               writer->flush();
-       }
-       ::free(cd);
-}
-
-
-//
-// Global populate - send components to destination buffers ONCE
-//
-void SecCodeSigner::Signer::populate(DiskRep::Writer &writer)
-{
-       if (resourceDirectory && !state.mDryRun)
-               writer.component(cdResourceDirSlot, resourceDictData);
-}
-
-
-//
-// Per-architecture populate - send components to per-architecture buffers
-// and populate the CodeDirectory for an architecture. In architecture-agnostic
-// signing operations, the non-architectural binary is considered one (arbitrary) architecture
-// for the purposes of this call.
-//
-void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer,
-       InternalRequirements &ireqs, size_t offset /* = 0 */, size_t length /* = 0 */)
-{
-       // fill the CodeDirectory
-       builder.executable(rep->mainExecutablePath(), pagesize, offset, length);
-       builder.flags(cdFlags);
-       builder.identifier(identifier);
-       builder.teamID(teamID);
-
-       if (CFRef<CFDataRef> data = rep->component(cdInfoSlot))
-               builder.specialSlot(cdInfoSlot, data);
-       if (ireqs) {
-               CFRef<CFDataRef> data = makeCFData(*ireqs);
-               writer.component(cdRequirementsSlot, data);
-               builder.specialSlot(cdRequirementsSlot, data);
-       }
-       if (resourceDirectory)
-               builder.specialSlot(cdResourceDirSlot, resourceDictData);
-#if NOT_YET
-       if (state.mApplicationData)
-               builder.specialSlot(cdApplicationSlot, state.mApplicationData);
-#endif
-       if (entitlements) {
-               writer.component(cdEntitlementSlot, entitlements);
-               builder.specialSlot(cdEntitlementSlot, entitlements);
-       }
-       
-       writer.addDiscretionary(builder);
-}
-
-#include <security_smime/tsaSupport.h>
-
-//
-// Generate the CMS signature for a (finished) CodeDirectory.
-//
-CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd)
-{
-       assert(state.mSigner);
-       CFRef<CFMutableDictionaryRef> defaultTSContext = NULL;
-    
-       // a null signer generates a null signature blob
-       if (state.mSigner == SecIdentityRef(kCFNull))
-               return CFDataCreate(NULL, NULL, 0);
-       
-       // generate CMS signature
-       CFRef<CMSEncoderRef> cms;
-       MacOSError::check(CMSEncoderCreate(&cms.aref()));
-       MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRoot));
-       CMSEncoderAddSigners(cms, state.mSigner);
-       MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true));
-       
-       if (signingTime) {
-               MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrSigningTime));
-               MacOSError::check(CMSEncoderSetSigningTime(cms, signingTime));
-       }
-       
-       MacOSError::check(CMSEncoderUpdateContent(cms, cd, cd->length()));
-    
-    // Set up to call Timestamp server if requested
-    
-    if (state.mWantTimeStamp)
-    {
-        CFRef<CFErrorRef> error = NULL;
-        defaultTSContext = SecCmsTSAGetDefaultContext(&error.aref());
-        if (error)
-            MacOSError::throwMe(errSecDataNotAvailable);
-            
-        if (state.mNoTimeStampCerts || state.mTimestampService) {
-            if (state.mTimestampService)
-                CFDictionarySetValue(defaultTSContext, kTSAContextKeyURL, state.mTimestampService);
-            if (state.mNoTimeStampCerts)
-                CFDictionarySetValue(defaultTSContext, kTSAContextKeyNoCerts, kCFBooleanTrue);
-       }
-            
-        CmsMessageSetTSAContext(cms, defaultTSContext);
-    }
-    
-       CFDataRef signature;
-       MacOSError::check(CMSEncoderCopyEncodedContent(cms, &signature));
-
-       return signature;
-}
-
-
-//
-// Parse a text of the form
-//     flag,...,flag
-// where each flag is the canonical name of a signable CodeDirectory flag.
-// No abbreviations are allowed, and internally set flags are not accepted.
-//
-uint32_t SecCodeSigner::Signer::cdTextFlags(std::string text)
-{
-       uint32_t flags = 0;
-       for (string::size_type comma = text.find(','); ; text = text.substr(comma+1), comma = text.find(',')) {
-               string word = (comma == string::npos) ? text : text.substr(0, comma);
-               const SecCodeDirectoryFlagTable *item;
-               for (item = kSecCodeDirectoryFlagTable; item->name; item++)
-                       if (item->signable && word == item->name) {
-                               flags |= item->value;
-                               break;
-                       }
-               if (!item->name)        // not found
-                       MacOSError::throwMe(errSecCSInvalidFlags);
-               if (comma == string::npos)      // last word
-                       break;
-       }
-       return flags;
-}
-
-
-//
-// Generate a unique string from our underlying DiskRep.
-// We could get 90%+ of the uniquing benefit by just generating
-// a random string here. Instead, we pick the (hex string encoding of)
-// the source rep's unique identifier blob. For universal binaries,
-// this is the canonical local architecture, which is a bit arbitrary.
-// This provides us with a consistent unique string for all architectures
-// of a fat binary, *and* (unlike a random string) is reproducible
-// for identical inputs, even upon resigning.
-//
-std::string SecCodeSigner::Signer::uniqueName() const
-{
-       CFRef<CFDataRef> identification = rep->identification();
-       const UInt8 *ident = CFDataGetBytePtr(identification);
-       const CFIndex length = CFDataGetLength(identification);
-       string result;
-       for (CFIndex n = 0; n < length; n++) {
-               char hex[3];
-               snprintf(hex, sizeof(hex), "%02x", ident[n]);
-               result += hex;
-       }
-       return result;
-}
-
-
-} // end namespace CodeSigning
-} // end namespace Security