1/* 2 * Copyright (c) 2006 Apple Computer, 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 29namespace Security { 30namespace CodeSigning { 31 32 33// 34// Requirement::Makers 35// 36Requirement::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 46void 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 58void *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 75void 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 82void Requirement::Maker::anchor() 83{ 84 put(opAppleAnchor); 85} 86 87void Requirement::Maker::anchorGeneric() 88{ 89 put(opAppleGenericAnchor); 90} 91 92void Requirement::Maker::anchor(int slot, SHA1::Digest digest) 93{ 94 put(opAnchorHash); 95 put(slot); 96 putData(digest, SHA1::digestLength); 97} 98 99void 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 108void Requirement::Maker::trustedAnchor() 109{ 110 put(opTrustedCerts); 111} 112 113void Requirement::Maker::trustedAnchor(int slot) 114{ 115 put(opTrustedCert); 116 put(slot); 117} 118 119void Requirement::Maker::infoKey(const string &key, const string &value) 120{ 121 put(opInfoKeyValue); 122 put(key); 123 put(value); 124} 125 126void Requirement::Maker::ident(const string &identifier) 127{ 128 put(opIdent); 129 put(identifier); 130} 131 132void Requirement::Maker::cdhash(SHA1::Digest digest) 133{ 134 put(opCDHash); 135 putData(digest, SHA1::digestLength); 136} 137 138void Requirement::Maker::cdhash(CFDataRef digest) 139{ 140 put(opCDHash); 141 putData(CFDataGetBytePtr(digest), CFDataGetLength(digest)); 142} 143 144 145void Requirement::Maker::copy(const Requirement *req) 146{ 147 assert(req); 148 if (req->kind() != exprForm) // don't know how to embed this 149 MacOSError::throwMe(errSecCSReqUnsupported); 150 this->copy(req->at<const void>(sizeof(Requirement)), req->length() - sizeof(Requirement)); 151} 152 153 154void *Requirement::Maker::insert(const Label &label, size_t length) 155{ 156 require(length); 157 memmove(mBuffer->at<void>(label.pos + length), 158 mBuffer->at<void>(label.pos), mPC - label.pos); 159 mPC += length; 160 return mBuffer->at<void>(label.pos); 161} 162 163 164Requirement *Requirement::Maker::make() 165{ 166 mBuffer->length(mPC); 167 Requirement *result = mBuffer; 168 mBuffer = NULL; 169 return result; 170} 171 172 173} // CodeSigning 174} // Security 175