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#ifndef _H_REQMAKER 28#define _H_REQMAKER 29 30#include <security_codesigning/requirement.h> 31 32namespace Security { 33namespace CodeSigning { 34 35 36// 37// A Requirement::Maker is a tool for creating a Requirement blob. 38// It's primarily an assember for the binary requirements (exprOp) language. 39// Initialize it, call put() methods to generate the exprOp program, then 40// call make() to get the assembled Requirement blob, malloc'ed for you. 41// The Maker is not reusable. 42// 43class Requirement::Maker { 44public: 45 Maker(Kind k = exprForm); 46 ~Maker() { free(mBuffer); } 47 48 template <class T> 49 T *alloc(size_t size) { return reinterpret_cast<T *>(alloc(size)); } 50 51 template <class T> 52 void put(const T &value) { *alloc<Endian<T> >(sizeof(T)) = value; } 53 void put(ExprOp op) { put(uint32_t(op)); } 54 void put(MatchOperation op) { put(uint32_t(op)); } 55 void put(const std::string &s) { putData(s.data(), s.size()); } 56 void put(const char *s) { putData(s, strlen(s)); } 57 void putData(const void *data, size_t length); 58 void putData(CFStringRef s) { put(cfString(s)); } 59 60 void anchor(int slot, SHA1::Digest digest); // given slot/digest 61 void anchor(int slot, const void *cert, size_t length); // given slot/cert 62 void anchor(); // made-by-Apple 63 void anchorGeneric(); // anything drawn from the Apple anchor 64 65 void trustedAnchor(); 66 void trustedAnchor(int slot); 67 68 void infoKey(const std::string &key, const std::string &value); 69 void ident(const std::string &identHash); 70 void cdhash(SHA1::Digest digest); 71 void cdhash(CFDataRef digest); 72 73 void copy(const void *data, size_t length) 74 { memcpy(this->alloc(length), data, length); } 75 void copy(const Requirement *req); // inline expand 76 77 // 78 // Keep labels into exprOp code, and allow for "shifting in" 79 // prefix code as needed (exprOp is a prefix-code language). 80 // 81 struct Label { 82 const Offset pos; 83 Label(const Maker &maker) : pos((const Offset)maker.length()) { } 84 }; 85 void *insert(const Label &label, size_t length = sizeof(uint32_t)); 86 87 template <class T> 88 Endian<T> &insert(const Label &label, size_t length = sizeof(T)) 89 { return *reinterpret_cast<Endian<T>*>(insert(label, length)); } 90 91 // 92 // Help with making operator chains (foo AND bar AND baz...). 93 // Note that the empty case (no elements at all) must be resolved by the caller. 94 // 95 class Chain : public Label { 96 public: 97 Chain(Maker &myMaker, ExprOp op) 98 : Label(myMaker), maker(myMaker), mJoiner(op), mCount(0) { } 99 100 void add() const 101 { if (mCount++) maker.insert<ExprOp>(*this) = mJoiner; } 102 103 Maker &maker; 104 bool empty() const { return mCount == 0; } 105 106 private: 107 ExprOp mJoiner; 108 mutable unsigned mCount; 109 }; 110 111 112 // 113 // Over-all construction management 114 // 115 void kind(Kind k) { mBuffer->kind(k); } 116 size_t length() const { return mPC; } 117 Requirement *make(); 118 Requirement *operator () () { return make(); } 119 120protected: 121 void require(size_t size); 122 void *alloc(size_t size); 123 124private: 125 Requirement *mBuffer; 126 Offset mSize; 127 Offset mPC; 128}; 129 130 131} // CodeSigning 132} // Security 133 134#endif //_H_REQMAKER 135