/ OSX / libsecurity_codesigning / lib / reqmaker.cpp
reqmaker.cpp
  1  /*
  2   * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved.
  3   * 
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  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
 11   * file.
 12   * 
 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.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  //
 25  // reqmaker - Requirement assembler
 26  //
 27  #include "reqmaker.h"
 28  
 29  namespace Security {
 30  namespace CodeSigning {
 31  
 32  
 33  //
 34  // Requirement::Makers
 35  //
 36  Requirement::Maker::Maker(Kind k)
 37  	: mSize(1024)
 38  {
 39  	mBuffer = (Requirement *)malloc(mSize);
 40  	mBuffer->initialize();
 41  	mBuffer->kind(k);
 42  	mPC = sizeof(Requirement);
 43  }
 44  
 45  // need at least (size) bytes in the creation buffer
 46  void Requirement::Maker::require(size_t size)
 47  {
 48  	if (mPC + size > mSize) {
 49  		mSize *= 2;
 50  		if (mPC + size > mSize)
 51  			mSize = (Offset)(mPC + size);
 52  		if (!(mBuffer = (Requirement *)realloc(mBuffer, mSize)))
 53  			UnixError::throwMe(ENOMEM);
 54  	}
 55  }
 56  
 57  // allocate (size) bytes at end of buffer and return pointer to that
 58  void *Requirement::Maker::alloc(size_t size)
 59  {
 60  	// round size up to preserve alignment
 61  	size_t usedSize = LowLevelMemoryUtilities::alignUp(size, baseAlignment);
 62  	require(usedSize);
 63  	void *data = mBuffer->at<void>(mPC);
 64  	mPC += usedSize;
 65  	
 66  	// clear any padding (avoid random bytes in code image)
 67  	const uint32_t zero = 0;
 68  	memcpy(mBuffer->at<void>(mPC - usedSize + size), &zero, usedSize - size);
 69  	
 70  	// all done
 71  	return data;
 72  }
 73  
 74  // put contiguous data blob
 75  void Requirement::Maker::putData(const void *data, size_t length)
 76  {
 77  	put(uint32_t(length));
 78  	memcpy(alloc(length), data, length);
 79  }
 80  
 81  // Specialized Maker put operations
 82  void Requirement::Maker::anchor()
 83  {
 84  	put(opAppleAnchor);
 85  }
 86  
 87  void Requirement::Maker::anchorGeneric()
 88  {
 89  	put(opAppleGenericAnchor);
 90  }
 91  
 92  void Requirement::Maker::anchor(int slot, SHA1::Digest digest)
 93  {
 94  	put(opAnchorHash);
 95  	put(slot);
 96  	putData(digest, SHA1::digestLength);
 97  }
 98  
 99  void Requirement::Maker::anchor(int slot, const void *cert, size_t length)
100  {
101  	SHA1 hasher;
102  	hasher(cert, length);
103  	SHA1::Digest digest;
104  	hasher.finish(digest);
105  	anchor(slot, digest);
106  }
107  
108  void Requirement::Maker::trustedAnchor()
109  {
110  	put(opTrustedCerts);
111  }
112  
113  void Requirement::Maker::trustedAnchor(int slot)
114  {
115  	put(opTrustedCert);
116  	put(slot);
117  }
118  
119  void Requirement::Maker::infoKey(const string &key, const string &value)
120  {
121  	put(opInfoKeyValue);
122  	put(key);
123  	put(value);
124  }
125  
126  void Requirement::Maker::ident(const string &identifier)
127  {
128  	put(opIdent);
129  	put(identifier);
130  }
131  
132  void Requirement::Maker::cdhash(SHA1::Digest digest)
133  {
134  	put(opCDHash);
135  	putData(digest, SHA1::digestLength);
136  }
137  
138  void Requirement::Maker::cdhash(CFDataRef digest)
139  {
140  	put(opCDHash);
141  	putData(CFDataGetBytePtr(digest), CFDataGetLength(digest));
142  }
143  	
144  void Requirement::Maker::platform(int platformIdentifier)
145  {
146  	put(opPlatform);
147  	put(platformIdentifier);
148  }
149  
150  
151  void Requirement::Maker::copy(const Requirement *req)
152  {
153  	assert(req);
154  	if (req->kind() != exprForm)		// don't know how to embed this
155  		MacOSError::throwMe(errSecCSReqUnsupported);
156  	this->copy(req->at<const void>(sizeof(Requirement)), req->length() - sizeof(Requirement));
157  }
158  
159  
160  void *Requirement::Maker::insert(const Label &label, size_t length)
161  {
162  	require(length);
163  	memmove(mBuffer->at<void>(label.pos + length),
164  		mBuffer->at<void>(label.pos), mPC - label.pos);
165  	mPC += length;
166  	return mBuffer->at<void>(label.pos);
167  }
168  
169  
170  Requirement *Requirement::Maker::make()
171  {
172  	mBuffer->length(mPC);
173  	Requirement *result = mBuffer;
174  	mBuffer = NULL;
175  	return result;
176  }
177  
178  
179  }	// CodeSigning
180  }	// Security