]> git.saurik.com Git - apple/security.git/blob - SecurityServer/key.cpp
Security-28.tar.gz
[apple/security.git] / SecurityServer / key.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // key - representation of SecurityServer key objects
21 //
22 #include "key.h"
23 #include "server.h"
24 #include "xdatabase.h"
25 #include <Security/acl_any.h>
26
27
28 //
29 // Create a Key object from a database-encoded blob.
30 // Note that this doesn't decode the blob (yet).
31 //
32 Key::Key(Database &db, const KeyBlob *blob)
33 : SecurityServerAcl(keyAcl, CssmAllocator::standard())
34 {
35 // perform basic validation on the incoming blob
36 assert(blob);
37 blob->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB);
38 switch (blob->version) {
39 #if defined(COMPAT_OSX_10_0)
40 case blob->version_MacOS_10_0:
41 break;
42 #endif
43 case blob->version_MacOS_10_1:
44 break;
45 default:
46 CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB);
47 }
48
49 // set it up
50 mDatabase = &db;
51 mBlob = blob->copy(CssmAllocator::standard());
52 mAttributes = 0;
53 mValidBlob = true;
54 mValidKey = false;
55 mValidUID = false;
56 debug("SSkey", "%p created from blob version %lx", this, blob->version);
57 }
58
59
60 //
61 // Create a Key from an explicit CssmKey.
62 //
63 Key::Key(Database *db, const CssmKey &newKey, uint32 moreAttributes,
64 const AclEntryPrototype *owner)
65 : SecurityServerAcl(keyAcl, CssmAllocator::standard())
66 {
67 if (moreAttributes & CSSM_KEYATTR_PERMANENT) {
68 // better have a database to make it permanent in...
69 if (!db)
70 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
71 } else {
72 // non-permanent; ignore database
73 db = NULL;
74 }
75
76 mDatabase = db;
77 mValidKey = true;
78 mBlob = NULL;
79 mValidBlob = false;
80 mValidUID = false;
81 setup(newKey, moreAttributes);
82
83 // establish initial ACL
84 if (owner)
85 cssmSetInitial(*owner);
86 else
87 cssmSetInitial(new AnyAclSubject());
88 debug("SSkey", "%p created from key alg=%ld use=0x%lx attr=0x%lx",
89 this, mKey.algorithm(), mKey.usage(), mAttributes);
90 }
91
92
93 //
94 // Set up the CssmKey part of this Key according to instructions.
95 //
96 void Key::setup(const CssmKey &newKey, uint32 moreAttributes)
97 {
98 CssmKey::Header &header = mKey.header();
99
100 // copy key header
101 header = newKey.header();
102 mAttributes = header.attributes() | moreAttributes;
103
104 // apply initial values of derived attributes (these are all in managedAttributes)
105 if (!(mAttributes & CSSM_KEYATTR_EXTRACTABLE))
106 mAttributes |= CSSM_KEYATTR_NEVER_EXTRACTABLE;
107 if (mAttributes & CSSM_KEYATTR_SENSITIVE)
108 mAttributes |= CSSM_KEYATTR_ALWAYS_SENSITIVE;
109
110 // verify internal/external attribute separation
111 assert(!(header.attributes() & managedAttributes));
112
113 // copy key data field @@@ crud - replace after MM reorg
114 mKey.KeyData = CssmData(memcpy(malloc(newKey.length()), newKey.data(), newKey.length()), newKey.length());
115 }
116
117
118 Key::~Key()
119 {
120 CssmAllocator::standard().free(mBlob);
121 if (mValidKey)
122 Server::csp()->freeKey(mKey);
123 debug("SSkey", "%p destroyed", this);
124 }
125
126
127 //
128 // Retrieve the actual CssmKey value for the key object.
129 // This will decode its blob if needed (and appropriate).
130 //
131 CssmKey &Key::keyValue()
132 {
133 decode();
134 return mKey;
135 }
136
137
138 //
139 // Ensure that a key is fully decoded.
140 // This makes the mKey key value available for use, as well as its ACL.
141 //
142 void Key::decode()
143 {
144 if (!mValidKey) {
145 assert(mDatabase); // have to have a database (to decode the blob)
146 assert(mValidBlob); // must have a blob to decode
147
148 // decode the key
149 void *publicAcl, *privateAcl;
150 database()->decodeKey(mBlob, mKey, publicAcl, privateAcl);
151 importBlob(publicAcl, privateAcl);
152 // publicAcl points into the blob; privateAcl was allocated for us
153 CssmAllocator::standard().free(privateAcl);
154
155 // extract managed attribute bits
156 mAttributes = mKey.attributes() & managedAttributes;
157 mKey.clearAttribute(managedAttributes);
158
159 // key is valid now
160 mValidKey = true;
161 }
162 }
163
164
165 //
166 // Retrieve the header (only) of a key.
167 // This is taking the clear header from the blob *without* verifying it.
168 //
169 CssmKey::Header &Key::keyHeader()
170 {
171 if (mValidKey) {
172 return mKey.header();
173 } else {
174 assert(mValidBlob);
175 return mBlob->header;
176 }
177 }
178
179
180 //
181 // Return a key's handle and header in external form
182 //
183 void Key::returnKey(Handle &h, CssmKey::Header &hdr)
184 {
185 // return handle
186 h = handle();
187
188 // return header with external attributes merged
189 hdr = keyHeader();
190 hdr.setAttribute(mAttributes);
191 }
192
193
194 //
195 // Encode a key into a blob.
196 // We'll have to ask our Database to do this - we don't have its keys.
197 // Note that this returns memory we own and keep.
198 //
199 KeyBlob *Key::blob()
200 {
201 if (mDatabase == NULL) // can't encode independent keys
202 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
203 if (!mValidBlob) {
204 assert(mValidKey); // must have valid key to encode
205 //@@@ release mBlob memory here
206
207 // export Key ACL to blob form
208 CssmData pubAcl, privAcl;
209 exportBlob(pubAcl, privAcl);
210
211 // assemble external key form
212 CssmKey externalKey = mKey;
213 externalKey.setAttribute(mAttributes);
214
215 // encode the key and replace blob
216 KeyBlob *newBlob = database()->encodeKey(externalKey, pubAcl, privAcl);
217 CssmAllocator::standard().free(mBlob);
218 mBlob = newBlob;
219 mValidBlob = true;
220
221 // clean up and go
222 database()->allocator.free(pubAcl);
223 database()->allocator.free(privAcl);
224 }
225 return mBlob;
226 }
227
228
229 //
230 // Return the UID of a key (the hash of its bits)
231 //
232 KeyUID &Key::uid()
233 {
234 if (!mValidUID) {
235 //@@@ calculate UID here
236 memset(&mUID, 0, sizeof(mUID));
237 mValidUID = true;
238 }
239 return mUID;
240 }
241
242
243 //
244 // Intercept ACL change requests and reset blob validity
245 //
246 void Key::instantiateAcl()
247 {
248 decode();
249 }
250
251 void Key::noticeAclChange()
252 {
253 mValidBlob = false;
254 }
255
256 const Database *Key::relatedDatabase() const
257 { return database(); }