2  * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 // signerutils - utilities for signature generation 
  27 #ifndef _H_SIGNERUTILS 
  28 #define _H_SIGNERUTILS 
  30 #include "CodeSigner.h" 
  32 #include "cdbuilder.h" 
  33 #include <security_utilities/utilities.h> 
  34 #include <security_utilities/blob.h> 
  35 #include <security_utilities/unix++.h> 
  36 #include <security_utilities/unixchild.h> 
  39 namespace CodeSigning 
{ 
  43 // A helper to deal with the magic merger logic of internal requirements 
  45 class InternalRequirements 
: public Requirements::Maker 
{ 
  47         InternalRequirements() : mReqs(NULL
) { } 
  48         ~InternalRequirements() { ::free((void *)mReqs
); } 
  49         void operator () (const Requirements 
*given
, const Requirements 
*defaulted
, const Requirement::Context 
&context
); 
  50         operator const Requirements 
* () const { return mReqs
; } 
  53         const Requirements 
*mReqs
; 
  58 // A DiskRep::Writer that assembles data in a SuperBlob (in memory) 
  60 class BlobWriter 
: public DiskRep::Writer
, public EmbeddedSignatureBlob::Maker 
{ 
  62         void component(CodeDirectory::SpecialSlot slot
, CFDataRef data
); 
  66 class DetachedBlobWriter 
: public BlobWriter 
{ 
  68         DetachedBlobWriter(SecCodeSigner::Signer 
&s
) : signer(s
) { } 
  70         SecCodeSigner::Signer 
&signer
; 
  77 // A multi-architecture editing assistant. 
  78 // ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture 
  79 // data structures. It must be subclassed to express a particular way to handle the signing 
  82 class ArchEditor 
: public DiskRep::Writer 
{ 
  84         ArchEditor(Universal 
&fat
, CodeDirectory::HashAlgorithm hashType
, uint32_t attrs
); 
  85         virtual ~ArchEditor(); 
  89         // One architecture's signing construction element. 
  90         // This also implements DispRep::Writer so generic writing code 
  91         // can work with both Mach-O and other files. 
  93         struct Arch 
: public BlobWriter 
{ 
  94                 Architecture architecture
;              // our architecture 
  95                 auto_ptr
<MachO
> source
;                 // Mach-O object to be signed 
  96                 CodeDirectory::Builder cdbuilder
; // builder for CodeDirectory 
  97                 InternalRequirements ireqs
;             // consolidated internal requirements 
  98                 size_t blobSize
;                                // calculated SuperBlob size 
 100                 Arch(const Architecture 
&arch
, CodeDirectory::HashAlgorithm hashType
) 
 101                         : architecture(arch
), cdbuilder(hashType
) { } 
 105         // Our callers access the architectural universe through a map 
 106         // from Architectures to Arch objects. 
 108         typedef std::map
<Architecture
, Arch 
*> ArchMap
; 
 109         typedef ArchMap::iterator Iterator
; 
 110         ArchMap::iterator 
begin()               { return architecture
.begin(); } 
 111         ArchMap::iterator 
end()                 { return architecture
.end(); } 
 112         unsigned count() const                  { return (unsigned)architecture
.size(); } 
 114         // methods needed for an actual implementation 
 115         virtual void allocate() = 0;                    // interpass allocations 
 116         virtual void reset(Arch 
&arch
) = 0;             // pass 2 prep 
 117         virtual void write(Arch 
&arch
, EmbeddedSignatureBlob 
*blob
) = 0; // takes ownership of blob 
 118         virtual void commit() = 0;                              // write/flush result 
 121         ArchMap architecture
; 
 126 // An ArchEditor that collects all architectures into a single SuperBlob, 
 127 // usually for writing a detached multi-architecture signature. 
 129 class BlobEditor 
: public ArchEditor 
{ 
 131         BlobEditor(Universal 
&fat
, SecCodeSigner::Signer 
&s
); 
 133         SecCodeSigner::Signer 
&signer
; 
 135         void component(CodeDirectory::SpecialSlot slot
, CFDataRef data
); 
 137         void reset(Arch 
&arch
) { } 
 138         void write(Arch 
&arch
, EmbeddedSignatureBlob 
*blob
); 
 142         DetachedSignatureBlob::Maker mMaker
; 
 143         EmbeddedSignatureBlob::Maker mGlobal
; 
 148 // An ArchEditor that writes its signatures into a (fat) binary file. 
 149 // We do this by forking a helper tool (codesign_allocate) and asking 
 150 // it to make a copy with suitable space "opened up" in the right spots. 
 152 class MachOEditor 
: public ArchEditor
, private UnixPlusPlus::Child 
{ 
 154         MachOEditor(DiskRep::Writer 
*w
, Universal 
&code
, CodeDirectory::HashAlgorithm hashType
, std::string srcPath
); 
 157         const RefPointer
<DiskRep::Writer
> writer
; 
 158         const std::string sourcePath
; 
 159         const std::string tempPath
; 
 161         void component(CodeDirectory::SpecialSlot slot
, CFDataRef data
); 
 163         void reset(Arch 
&arch
); 
 164         void write(Arch 
&arch
, EmbeddedSignatureBlob 
*blob
); 
 172         // controlling the temporary file copy 
 174         UnixPlusPlus::AutoFileDesc mFd
; 
 177         // finding and managing the helper tool 
 178         const char *mHelperPath
; 
 179         bool mHelperOverridden
; 
 184 // A Requirement::Context populated from a signing request. 
 185 // We use this to help generate the explicit Designated Requirement 
 186 // during signing ops, and thus this must be constructed BEFORE we 
 187 // actually have a signed object. 
 189 class PreSigningContext 
: public Requirement::Context 
{ 
 191         PreSigningContext(const SecCodeSigner::Signer 
&signer
); 
 194         CFRef
<CFArrayRef
> mCerts
;               // hold cert chain 
 198 } // end namespace CodeSigning 
 199 } // end namespace Security 
 201 #endif // !_H_SIGNERUTILS