]> git.saurik.com Git - apple/security.git/blob - libsecurity_sd_cspdl/lib/SDKey.cpp
Security-55471.tar.gz
[apple/security.git] / libsecurity_sd_cspdl / lib / SDKey.cpp
1 /*
2 * Copyright (c) 2004,2008 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 //
26 // SDKey - reference keys for the security server
27 //
28 #include "SDKey.h"
29
30 #include "SDCSPSession.h"
31 #include "SDCSPDLSession.h"
32 #include "SDDLSession.h"
33 #include <security_cdsa_utilities/KeySchema.h>
34 #include <security_cdsa_utilities/cssmdb.h>
35 #include <security_cdsa_plugin/cssmplugin.h>
36
37 using namespace CssmClient;
38 using namespace SecurityServer;
39
40 // Constructor for a Security Server generated key.
41 SDKey::SDKey(SDCSPSession &session, KeyHandle hKey, CssmKey &ioKey,
42 CSSM_DB_HANDLE inDBHandle, uint32 inKeyAttr,
43 const CssmData *inKeyLabel)
44 : ReferencedKey(session.mSDCSPDLSession),
45 mAllocator(session), mKeyHandle(hKey),
46 mClientSession(session.clientSession())
47 {
48 CssmKey::Header &header = ioKey.header();
49 #if 0
50 if (inKeyAttr & CSSM_KEYATTR_PERMANENT)
51 {
52 if (!inDBHandle)
53 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE);
54
55 // EncodeKey and store it in the db.
56 CssmDataContainer blob(mAllocator);
57 clientSession().encodeKey(keyHandle, blob);
58
59 assert(header.HeaderVersion == CSSM_KEYHEADER_VERSION);
60 switch (header.KeyClass)
61 {
62 case CSSM_KEYCLASS_PUBLIC_KEY:
63 mRecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY;
64 break;
65 case CSSM_KEYCLASS_PRIVATE_KEY:
66 mRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
67 break;
68 case CSSM_KEYCLASS_SESSION_KEY:
69 mRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
70 break;
71 default:
72 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
73 }
74
75 CssmData label;
76 if (inKeyLabel)
77 label = *inKeyLabel;
78
79 CssmData none;
80 // We store the keys real CSP guid on disk
81 CssmGuidData creatorGuid(header.CspId);
82 CssmDateData startDate(header.StartDate);
83 CssmDateData endDate(header.EndDate);
84
85 DbAttributes attributes(inDBHandle);
86 attributes.recordType(mRecordType);
87 attributes.add(KeySchema::KeyClass, mRecordType);
88 attributes.add(KeySchema::PrintName, label);
89 attributes.add(KeySchema::Alias, none);
90 attributes.add(KeySchema::Permanent,
91 header.attribute(CSSM_KEYATTR_PERMANENT));
92 attributes.add(KeySchema::Private,
93 header.attribute(CSSM_KEYATTR_PRIVATE));
94 attributes.add(KeySchema::Modifiable,
95 header.attribute(CSSM_KEYATTR_MODIFIABLE));
96 attributes.add(KeySchema::Label, label);
97 attributes.add(KeySchema::ApplicationTag, none);
98 attributes.add(KeySchema::KeyCreator, creatorGuid);
99 attributes.add(KeySchema::KeyType, header.AlgorithmId);
100 attributes.add(KeySchema::KeySizeInBits, header.LogicalKeySizeInBits);
101 // @@@ Get the real effective key size.
102 attributes.add(KeySchema::EffectiveKeySize, header.LogicalKeySizeInBits);
103 attributes.add(KeySchema::StartDate, startDate);
104 attributes.add(KeySchema::EndDate, endDate);
105 attributes.add(KeySchema::Sensitive,
106 header.attribute(CSSM_KEYATTR_SENSITIVE));
107 attributes.add(KeySchema::AlwaysSensitive,
108 header.attribute(CSSM_KEYATTR_ALWAYS_SENSITIVE));
109 attributes.add(KeySchema::Extractable,
110 header.attribute(CSSM_KEYATTR_EXTRACTABLE));
111 attributes.add(KeySchema::NeverExtractable,
112 header.attribute(CSSM_KEYATTR_NEVER_EXTRACTABLE));
113 attributes.add(KeySchema::Encrypt,
114 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_ENCRYPT));
115 attributes.add(KeySchema::Decrypt,
116 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DECRYPT));
117 attributes.add(KeySchema::Derive,
118 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DERIVE));
119 attributes.add(KeySchema::Sign,
120 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_SIGN));
121 attributes.add(KeySchema::Verify,
122 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_VERIFY));
123 attributes.add(KeySchema::SignRecover,
124 header.useFor(CSSM_KEYUSE_ANY
125 | CSSM_KEYUSE_SIGN_RECOVER));
126 attributes.add(KeySchema::VerifyRecover,
127 header.useFor(CSSM_KEYUSE_ANY
128 | CSSM_KEYUSE_VERIFY_RECOVER));
129 attributes.add(KeySchema::Wrap,
130 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_WRAP));
131 attributes.add(KeySchema::Unwrap,
132 header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_UNWRAP));
133
134 // @@@ Fixme
135 mUniqueId = inDBHandle->insert(mRecordType, &attributes, &blob,
136 true);
137 }
138
139 #endif
140 header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me.
141 makeReferenceKey(mAllocator, keyReference(), ioKey);
142 }
143
144 // Constructor for a key retrived from a Db.
145 SDKey::SDKey(SDDLSession &session, CssmKey &ioKey, KeyHandle hKey, CSSM_DB_HANDLE inDBHandle,
146 RecordHandle record, CSSM_DB_RECORDTYPE recordType,
147 CssmData &keyBlob)
148 : ReferencedKey(session.mSDCSPDLSession),
149 mAllocator(session.allocator()), mKeyHandle(hKey), mRecord(record),
150 mClientSession(session.clientSession())
151 {
152 CssmKey::Header &header = ioKey.header();
153 #if 0
154 memset(&header, 0, sizeof(header)); // Clear key header
155
156 if (!mUniqueId || !mUniqueId->database())
157 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
158
159 header.HeaderVersion = CSSM_KEYHEADER_VERSION;
160 switch (mRecordType)
161 {
162 case CSSM_DL_DB_RECORD_PUBLIC_KEY:
163 header.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
164 break;
165 case CSSM_DL_DB_RECORD_PRIVATE_KEY:
166 header.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
167 break;
168 case CSSM_DL_DB_RECORD_SYMMETRIC_KEY:
169 header.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
170 break;
171 default:
172 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
173 }
174
175 DbAttributes attributes(mUniqueId->database());
176 attributes.recordType(mRecordType);
177 attributes.add(KeySchema::KeyClass); // 0
178 attributes.add(KeySchema::Permanent); // 1
179 attributes.add(KeySchema::Private); // 2
180 attributes.add(KeySchema::Modifiable); // 3
181 attributes.add(KeySchema::KeyCreator); // 4
182 attributes.add(KeySchema::KeyType); // 5
183 attributes.add(KeySchema::KeySizeInBits); // 6
184 attributes.add(KeySchema::StartDate); // 7
185 attributes.add(KeySchema::EndDate); // 8
186 attributes.add(KeySchema::Sensitive); // 9
187 attributes.add(KeySchema::AlwaysSensitive); // 10
188 attributes.add(KeySchema::Extractable); // 11
189 attributes.add(KeySchema::NeverExtractable); // 12
190 attributes.add(KeySchema::Encrypt); // 13
191 attributes.add(KeySchema::Decrypt); // 14
192 attributes.add(KeySchema::Derive); // 15
193 attributes.add(KeySchema::Sign); // 16
194 attributes.add(KeySchema::Verify); // 17
195 attributes.add(KeySchema::SignRecover); // 18
196 attributes.add(KeySchema::VerifyRecover); // 19
197 attributes.add(KeySchema::Wrap); // 20
198 attributes.add(KeySchema::Unwrap); // 21
199
200 mUniqueId->get(&attributes, NULL);
201
202 // Assert that the mRecordType matches the KeyClass attribute.
203 if (mRecordType != uint32(attributes[0]))
204 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
205
206 header.AlgorithmId = attributes[5]; // KeyType
207 header.LogicalKeySizeInBits = attributes[6]; // KeySizeInBits
208
209 if (attributes[1]) header.setAttribute(CSSM_KEYATTR_PERMANENT);
210 if (attributes[2]) header.setAttribute(CSSM_KEYATTR_PRIVATE);
211 if (attributes[3]) header.setAttribute(CSSM_KEYATTR_MODIFIABLE);
212 if (attributes[9]) header.setAttribute(CSSM_KEYATTR_SENSITIVE);
213 if (attributes[11]) header.setAttribute(CSSM_KEYATTR_EXTRACTABLE);
214 if (attributes[10]) header.setAttribute(CSSM_KEYATTR_ALWAYS_SENSITIVE);
215 if (attributes[12]) header.setAttribute(CSSM_KEYATTR_NEVER_EXTRACTABLE);
216
217 if (attributes[13]) header.usage(CSSM_KEYUSE_ENCRYPT);
218 if (attributes[14]) header.usage(CSSM_KEYUSE_DECRYPT);
219 if (attributes[15]) header.usage(CSSM_KEYUSE_DERIVE);
220 if (attributes[16]) header.usage(CSSM_KEYUSE_SIGN);
221 if (attributes[17]) header.usage(CSSM_KEYUSE_VERIFY);
222 if (attributes[18]) header.usage(CSSM_KEYUSE_SIGN_RECOVER);
223 if (attributes[19]) header.usage(CSSM_KEYUSE_VERIFY_RECOVER);
224 if (attributes[20]) header.usage(CSSM_KEYUSE_WRAP);
225 if (attributes[21]) header.usage(CSSM_KEYUSE_UNWRAP);
226
227 // If all usages are allowed set usage to CSSM_KEYUSE_ANY
228 if (header.usage() == (CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT
229 | CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN
230 | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER
231 | CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP
232 | CSSM_KEYUSE_UNWRAP))
233 header.usage(CSSM_KEYUSE_ANY);
234
235 if (!attributes[7].size() || !attributes[8].size())
236 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
237
238 header.StartDate = attributes[7].at<CSSM_DATE>(0);
239 header.EndDate = attributes[8].at<CSSM_DATE>(0);
240
241 #endif
242 makeReferenceKey(mAllocator, keyReference(), ioKey);
243 header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me.
244 }
245
246 SDKey::~SDKey()
247 {
248 if (mKeyHandle != noKey)
249 clientSession().releaseKey(mKeyHandle);
250 }
251
252 void
253 SDKey::free(const AccessCredentials *accessCred, CssmKey &ioKey,
254 CSSM_BOOL deleteKey)
255 {
256 // @@@ We need a new freeKey(const AccessCredentials *accessCred, CSSM_HANDLE key, CSSM_BOOL deleteKey)
257 // In the client library
258 freeReferenceKey(mAllocator, ioKey);
259 if (deleteKey)
260 {
261 if (!mRecord || !mDatabase)
262 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
263
264 // @@@ Evaluate accessCred against Db acl.
265 // What should we do with accessCred? Reauthenticate
266 // mUniqueId->database()?
267 clientSession().deleteRecord(ClientSession::toIPCHandle(mDatabase), ClientSession::toIPCHandle(mRecord));
268 }
269
270 if (mKeyHandle != noKey)
271 {
272 clientSession().releaseKey(mKeyHandle);
273 mKeyHandle = noKey;
274 }
275 }
276
277 SecurityServer::ClientSession &
278 SDKey::clientSession()
279 {
280 return mClientSession;
281 }
282
283 KeyHandle SDKey::optionalKeyHandle() const
284 {
285 return mKeyHandle;
286 }
287
288 KeyHandle
289 SDKey::keyHandle()
290 {
291 if (mKeyHandle == noKey)
292 {
293 #if 0
294 // Deal with uninstantiated keys.
295 if (!mUniqueId || !mUniqueId->database())
296 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
297
298 CssmDataContainer blob(mAllocator);
299 mUniqueId->get(NULL, &blob);
300 CssmKey::Header dummyHeader; // @@@ Unused
301 mKeyHandle =
302 clientSession().decodeKey(mUniqueId->database().dbHandle(), blob,
303 dummyHeader);
304
305 // @@@ Check decoded header against returned header
306 #else
307 abort();
308 #endif
309 }
310
311 return mKeyHandle;
312 }
313
314 //
315 // ACL retrieval and change operations
316 //
317 void
318 SDKey::getOwner(CSSM_ACL_OWNER_PROTOTYPE &owner, Allocator &allocator)
319 {
320 clientSession().getKeyOwner(keyHandle(), AclOwnerPrototype::overlay(owner),
321 allocator);
322 }
323
324 void
325 SDKey::changeOwner(const AccessCredentials &accessCred,
326 const AclOwnerPrototype &newOwner)
327 {
328 clientSession().changeKeyOwner(keyHandle(), accessCred, newOwner);
329 }
330
331 void
332 SDKey::getAcl(const char *selectionTag, uint32 &numberOfAclInfos,
333 AclEntryInfo *&aclInfos, Allocator &allocator)
334 {
335 clientSession().getKeyAcl(keyHandle(), selectionTag, numberOfAclInfos,
336 aclInfos, allocator);
337 }
338
339 void
340 SDKey::changeAcl(const AccessCredentials &accessCred, const AclEdit &aclEdit)
341 {
342 clientSession().changeKeyAcl(keyHandle(), accessCred, aclEdit);
343 }