1/*
2 * Copyright (c) 2000-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//
26// ssblob - objects to represent persistent blobs used by SecurityServer
27//
28#ifndef _H_SSBLOB
29#define _H_SSBLOB
30
31#include <securityd_client/ssclient.h>
32#include <Security/cssm.h>
33#include <security_utilities/utilities.h>
34#include <security_cdsa_utilities/cssmacl.h>
35#include <security_utilities/memutils.h>
36#include <security_utilities/endian.h>
37
38
39namespace Security {
40namespace SecurityServer {
41
42using LowLevelMemoryUtilities::increment;
43
44
45//
46// A generic blob.
47// Note that Blob and its subclasses are meant to be Byte Order Corrected.
48// Make sure all non-byte fields are Endian<> qualified.
49//
50class Blob {
51public:
52	typedef Endian<uint32> uint32e;
53	typedef Endian<sint32> sint32e;
54
55protected:
56    template <class T>
57    T *at(off_t offset)		{ return LowLevelMemoryUtilities::increment<T>(this, offset); }
58    void *at(off_t offset)	{ return LowLevelMemoryUtilities::increment(this, (ptrdiff_t)offset); }
59
60    template <class T>
61    const T *at(off_t offset) const { return LowLevelMemoryUtilities::increment<T>(this, offset); }
62    const void *at(off_t offset) const { return LowLevelMemoryUtilities::increment(this, (ptrdiff_t)offset); }
63};
64
65
66//
67// The common features of our blobs
68//
69class CommonBlob : public Blob {
70public:
71    // initial fixed fields for versioning
72    uint32e magic;		// magic number
73    uint32e blobVersion; // version code
74	uint32 version() const { return blobVersion; }
75
76    static const uint32 magicNumber = 0xfade0711;
77
78    static const uint32 version_MacOS_10_0 = 0x00000100;	// MacOS 10.0.x
79    static const uint32 version_MacOS_10_1 = 0x00000101;	// MacOS 10.1.x and on
80    static const uint32 currentVersion = version_MacOS_10_0;
81
82public:
83    void initialize(uint32 version = currentVersion);
84	bool isValid() const;
85    void validate(CSSM_RETURN failureCode) const;
86
87	void *data()		{ return at(0); }
88	const void *data() const { return at(0); }
89};
90
91
92//
93// A Database blob
94//
95class DbBlob : public CommonBlob {
96public:
97    struct Signature {
98        uint8 bytes[16];
99
100        bool operator < (const Signature &sig) const
101        { return memcmp(bytes, sig.bytes, sizeof(bytes)) < 0; }
102        bool operator == (const Signature &sig) const
103        { return memcmp(bytes, sig.bytes, sizeof(bytes)) == 0; }
104    };
105
106    struct PrivateBlob : public Blob {
107	    typedef uint8 EncryptionKey[24];
108		typedef uint8 SigningKey[20];
109
110        EncryptionKey encryptionKey;	// master encryption key
111        SigningKey signingKey;		// master signing key
112
113        // private ACL blob follows, to the end
114        void *privateAclBlob()	{ return at(sizeof(PrivateBlob)); }
115    };
116
117public:
118    // position separators between variable-length fields (see below)
119    uint32e startCryptoBlob;	// end of public ACL; start of crypto blob
120    uint32e totalLength;		// end of crypto blob; end of entire blob
121
122    Signature randomSignature;	// randomizing database signature
123    uint32e sequence;			// database sequence number
124    DBParameters params;		// database settable parameters
125
126    uint8 salt[20];				// derivation salt
127    uint8 iv[8];				// encryption iv
128
129    uint8 blobSignature[20];	// HMAC/SHA1 of entire blob except itself
130
131    // variable length fields:
132    void *publicAclBlob()	{ return at(sizeof(DbBlob)); }
133    const void *publicAclBlob() const { return at(sizeof(DbBlob)); }
134    size_t publicAclBlobLength() const
135    { return startCryptoBlob - sizeof(DbBlob); }
136
137	void *cryptoBlob()			{ return at(startCryptoBlob); }
138    const void *cryptoBlob() const { return at(startCryptoBlob); }
139    size_t cryptoBlobLength() const { return totalLength - startCryptoBlob; }
140
141    uint32 length() const	{ return totalLength; }
142
143    DbBlob *copy(Allocator &alloc = Allocator::standard()) const
144    {
145        DbBlob *blob = alloc.malloc<DbBlob>(length());
146        memcpy(blob, this, length());
147        return blob;
148    }
149};
150
151
152//
153// A key blob
154//
155class KeyBlob : public CommonBlob {
156public:
157    uint32e startCryptoBlob;	// end of public ACL; start of crypto blob
158    uint32e totalLength;		// end of crypto blob; end of entire blob
159
160    uint8 iv[8];				// encryption iv
161
162    CssmKey::Header header;		// key header as-is
163    struct WrappedFields {
164        Endian<CSSM_KEYBLOB_TYPE> blobType;
165        Endian<CSSM_KEYBLOB_FORMAT> blobFormat;
166        Endian<CSSM_ALGORITHMS> wrapAlgorithm;
167        Endian<CSSM_ENCRYPT_MODE> wrapMode;
168    } wrappedHeader;
169
170    uint8 blobSignature[20];	// HMAC/SHA1 of entire blob except itself
171
172    // variable length fields:
173    void *publicAclBlob()	{ return at(sizeof(KeyBlob)); }
174    size_t publicAclBlobLength() const
175    { return startCryptoBlob - sizeof(KeyBlob); }
176
177    void *cryptoBlob()		{ return at(startCryptoBlob); }
178    size_t cryptoBlobLength() const { return totalLength - startCryptoBlob; }
179
180    uint32 length() const	{ return totalLength; }
181
182    // these bits are managed internally by the SecurityServer (and not passed to the CSPs)
183    static const uint32 managedAttributes =
184        CSSM_KEYATTR_ALWAYS_SENSITIVE |
185        CSSM_KEYATTR_NEVER_EXTRACTABLE |
186        CSSM_KEYATTR_PERMANENT |
187		CSSM_KEYATTR_SENSITIVE |
188		CSSM_KEYATTR_EXTRACTABLE;
189	static const uint32 forcedAttributes =
190		CSSM_KEYATTR_EXTRACTABLE;
191
192	/*
193	 * Public Key blobs can be stored unencrypted. A unique blobSignature
194	 * is used to indicate this state.
195	 */
196	bool isClearText();
197	void setClearTextSignature();
198
199public:
200    KeyBlob *copy(Allocator &alloc) const
201    {
202        KeyBlob *blob = alloc.malloc<KeyBlob>(length());
203        memcpy(blob, this, length());
204        return blob;
205    }
206};
207
208
209//
210// An auto-unlock record (database identity plus raw unlock key)
211//
212class UnlockBlob : public CommonBlob {
213public:
214	typedef uint8 MasterKey[24];
215	MasterKey masterKey;		// raw bits (triple-DES) - make your own CssmKey
216	DbBlob::Signature signature; // signature is index
217};
218
219
220} // end namespace SecurityServer
221} // end namespace Security
222
223
224#endif //_H_SSBLOB
225