/* * Copyright (c) 2006,2011-2014 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@ */ // // reqmaker - Requirement assembler // #ifndef _H_REQMAKER #define _H_REQMAKER #include namespace Security { namespace CodeSigning { // // A Requirement::Maker is a tool for creating a Requirement blob. // It's primarily an assember for the binary requirements (exprOp) language. // Initialize it, call put() methods to generate the exprOp program, then // call make() to get the assembled Requirement blob, malloc'ed for you. // The Maker is not reusable. // class Requirement::Maker { public: Maker(Kind k = exprForm); ~Maker() { free(mBuffer); } template T *alloc(size_t size) { return reinterpret_cast(alloc(size)); } template void put(const T &value) { *alloc >(sizeof(T)) = value; } void put(ExprOp op) { put(uint32_t(op)); } void put(MatchOperation op) { put(uint32_t(op)); } void put(const std::string &s) { putData(s.data(), s.size()); } void put(const char *s) { putData(s, strlen(s)); } void putData(const void *data, size_t length); void putData(CFStringRef s) { put(cfString(s)); } void anchor(int slot, SHA1::Digest digest); // given slot/digest void anchor(int slot, const void *cert, size_t length); // given slot/cert void anchor(); // made-by-Apple void anchorGeneric(); // anything drawn from the Apple anchor void trustedAnchor(); void trustedAnchor(int slot); void infoKey(const std::string &key, const std::string &value); void ident(const std::string &identHash); void cdhash(SHA1::Digest digest); void cdhash(CFDataRef digest); void copy(const void *data, size_t length) { memcpy(this->alloc(length), data, length); } void copy(const Requirement *req); // inline expand // // Keep labels into exprOp code, and allow for "shifting in" // prefix code as needed (exprOp is a prefix-code language). // struct Label { const Offset pos; Label(const Maker &maker) : pos((const Offset)maker.length()) { } }; void *insert(const Label &label, size_t length = sizeof(uint32_t)); template Endian &insert(const Label &label, size_t length = sizeof(T)) { return *reinterpret_cast*>(insert(label, length)); } // // Help with making operator chains (foo AND bar AND baz...). // Note that the empty case (no elements at all) must be resolved by the caller. // class Chain : public Label { public: Chain(Maker &myMaker, ExprOp op) : Label(myMaker), maker(myMaker), mJoiner(op), mCount(0) { } void add() const { if (mCount++) maker.insert(*this) = mJoiner; } Maker &maker; bool empty() const { return mCount == 0; } private: ExprOp mJoiner; mutable unsigned mCount; }; // // Over-all construction management // void kind(Kind k) { mBuffer->kind(k); } size_t length() const { return mPC; } Requirement *make(); Requirement *operator () () { return make(); } protected: void require(size_t size); void *alloc(size_t size); private: Requirement *mBuffer; Offset mSize; Offset mPC; }; } // CodeSigning } // Security #endif //_H_REQMAKER