]> git.saurik.com Git - apple/security.git/blob - AppleCSPDL/SSCSPSession.cpp
Security-29.tar.gz
[apple/security.git] / AppleCSPDL / SSCSPSession.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 // SSCSPSession.cpp - Security Server CSP session.
21 //
22 #include "SSCSPSession.h"
23
24 #include "CSPDLPlugin.h"
25 #include "SSDatabase.h"
26 #include "SSDLSession.h"
27 #include "SSKey.h"
28
29 #include <memory>
30
31 using namespace std;
32 using namespace SecurityServer;
33
34 //
35 // SSCSPSession -- Security Server CSP session
36 //
37 SSCSPSession::SSCSPSession(CSSM_MODULE_HANDLE handle,
38 CSPDLPlugin &plug,
39 const CSSM_VERSION &version,
40 uint32 subserviceId,
41 CSSM_SERVICE_TYPE subserviceType,
42 CSSM_ATTACH_FLAGS attachFlags,
43 const CSSM_UPCALLS &upcalls,
44 SSCSPDLSession &ssCSPDLSession)
45 : CSPFullPluginSession(handle, plug, version, subserviceId, subserviceType,
46 attachFlags, upcalls),
47 mSSCSPDLSession(ssCSPDLSession),
48 mSSFactory(plug.mSSFactory)
49 {
50 }
51
52 //
53 // Called at (CSSM) context create time. This is ignored; we do a full
54 // context setup later, at setupContext time.
55 //
56 CSPFullPluginSession::CSPContext *
57 SSCSPSession::contextCreate(CSSM_CC_HANDLE handle, const Context &context)
58 {
59 return NULL;
60 }
61
62
63 //
64 // Called by CSPFullPluginSession when an op is actually commencing.
65 // Context can safely assumed to be fully formed and stable for the
66 // duration of the op; thus we wait until now to set up our
67 // CSPContext as appropriate to the op.
68 //
69 void
70 SSCSPSession::setupContext(CSPContext * &cspCtx,
71 const Context &context,
72 bool encoding)
73 {
74 // note we skip this if this CSPContext is being reused
75 if (cspCtx == NULL)
76 {
77
78 if (mSSFactory.setup(*this, cspCtx, context, encoding))
79 return;
80
81 #if 0
82 if (mBSafe4Factory.setup(*this, cspCtx, context))
83 return;
84
85 if (mCryptKitFactory.setup(*this, cspCtx, context))
86 return;
87 #endif
88
89 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
90 }
91 }
92
93
94 //
95 // DL interaction
96 //
97 SSDatabase
98 SSCSPSession::getDatabase(const Context &context)
99 {
100 CSSM_DL_DB_HANDLE *aDLDbHandle = context.get<CSSM_DL_DB_HANDLE>(CSSM_ATTRIBUTE_DL_DB_HANDLE);
101 if (!aDLDbHandle)
102 return SSDatabase();
103
104 return findSession<SSDLSession>(aDLDbHandle->DLHandle).findDbHandle(aDLDbHandle->DBHandle);
105 }
106
107
108 //
109 // Reference Key management
110 //
111 void
112 SSCSPSession::makeReferenceKey(KeyHandle inKeyHandle, CssmKey &ioKey, SSDatabase &inSSDatabase,
113 uint32 inKeyAttr, const CssmData *inKeyLabel)
114 {
115 return mSSCSPDLSession.makeReferenceKey(*this, inKeyHandle, ioKey, inSSDatabase, inKeyAttr, inKeyLabel);
116 }
117
118 SSKey &
119 SSCSPSession::lookupKey(const CssmKey &inKey)
120 {
121 return mSSCSPDLSession.lookupKey(inKey);
122 }
123
124
125 //
126 // Key creating and handeling members
127 //
128 void
129 SSCSPSession::WrapKey(CSSM_CC_HANDLE CCHandle,
130 const Context &context,
131 const AccessCredentials &AccessCred,
132 const CssmKey &Key,
133 const CssmData *DescriptiveData,
134 CssmKey &WrappedKey,
135 CSSM_PRIVILEGE Privilege)
136 {
137 // @@@ Deal with permanent keys
138 const CssmKey *keyInContext =
139 context.get<const CssmKey>(CSSM_ATTRIBUTE_KEY);
140
141 KeyHandle contextKeyHandle = (keyInContext
142 ? lookupKey(*keyInContext).keyHandle()
143 : noKey);
144 clientSession().wrapKey(context, contextKeyHandle,
145 lookupKey(Key).keyHandle(), &AccessCred,
146 DescriptiveData, WrappedKey, *this);
147 }
148
149 void
150 SSCSPSession::UnwrapKey(CSSM_CC_HANDLE CCHandle,
151 const Context &context,
152 const CssmKey *PublicKey,
153 const CssmWrappedKey &WrappedKey,
154 uint32 KeyUsage,
155 uint32 KeyAttr,
156 const CssmData *KeyLabel,
157 const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
158 CssmKey &UnwrappedKey,
159 CssmData &DescriptiveData,
160 CSSM_PRIVILEGE Privilege)
161 {
162 SSDatabase database = getDatabase(context);
163 const AccessCredentials *cred = NULL;
164 const AclEntryInput *owner = NULL;
165 if (CredAndAclEntry)
166 {
167 cred = AccessCredentials::overlay(CredAndAclEntry->AccessCred);
168 owner = &AclEntryInput::overlay(CredAndAclEntry->InitialAclEntry);
169 }
170
171 KeyHandle publicKey = noKey;
172 if (PublicKey)
173 {
174 if (PublicKey->blobType() == CSSM_KEYBLOB_RAW)
175 {
176 // @@@ We need to unwrap the publicKey into the SecurityServer
177 // before continuing
178 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
179 }
180 else
181 publicKey = lookupKey(*PublicKey).keyHandle();
182 }
183
184 // @@@ Deal with permanent keys
185 const CssmKey *keyInContext =
186 context.get<const CssmKey>(CSSM_ATTRIBUTE_KEY);
187
188 KeyHandle contextKeyHandle =
189 keyInContext ? lookupKey(*keyInContext).keyHandle() : noKey;
190
191 KeyHandle unwrappedKeyHandle;
192 clientSession().unwrapKey(database.dbHandle(), context, contextKeyHandle,
193 publicKey, WrappedKey, KeyUsage, KeyAttr,
194 cred, owner, DescriptiveData, unwrappedKeyHandle,
195 UnwrappedKey.header(), *this);
196 makeReferenceKey(unwrappedKeyHandle, UnwrappedKey, database, KeyAttr,
197 KeyLabel);
198 }
199
200 void
201 SSCSPSession::DeriveKey(CSSM_CC_HANDLE ccHandle,
202 const Context &context,
203 CssmData &param,
204 uint32 keyUsage,
205 uint32 keyAttr,
206 const CssmData *keyLabel,
207 const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry,
208 CssmKey &derivedKey)
209 {
210 unimplemented();
211 }
212
213 void
214 SSCSPSession::GenerateKey(CSSM_CC_HANDLE ccHandle,
215 const Context &context,
216 uint32 keyUsage,
217 uint32 keyAttr,
218 const CssmData *keyLabel,
219 const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry,
220 CssmKey &key,
221 CSSM_PRIVILEGE privilege)
222 {
223 SSDatabase database = getDatabase(context);
224 const AccessCredentials *cred = NULL;
225 const AclEntryInput *owner = NULL;
226 if (credAndAclEntry)
227 {
228 cred = AccessCredentials::overlay(credAndAclEntry->AccessCred);
229 owner = &AclEntryInput::overlay(credAndAclEntry->InitialAclEntry);
230 }
231
232 KeyHandle keyHandle;
233 clientSession().generateKey(database.dbHandle(), context, keyUsage,
234 keyAttr, cred, owner, keyHandle, key.header());
235 makeReferenceKey(keyHandle, key, database, keyAttr, keyLabel);
236 }
237
238 void
239 SSCSPSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle,
240 const Context &context,
241 uint32 publicKeyUsage,
242 uint32 publicKeyAttr,
243 const CssmData *publicKeyLabel,
244 CssmKey &publicKey,
245 uint32 privateKeyUsage,
246 uint32 privateKeyAttr,
247 const CssmData *privateKeyLabel,
248 const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry,
249 CssmKey &privateKey,
250 CSSM_PRIVILEGE privilege)
251 {
252 SSDatabase database = getDatabase(context);
253 const AccessCredentials *cred = NULL;
254 const AclEntryInput *owner = NULL;
255 if (credAndAclEntry)
256 {
257 cred = AccessCredentials::overlay(credAndAclEntry->AccessCred);
258 owner = &AclEntryInput::overlay(credAndAclEntry->InitialAclEntry);
259 }
260
261 KeyHandle pubKeyHandle, privKeyHandle;
262 clientSession().generateKey(database.dbHandle(), context,
263 publicKeyUsage, publicKeyAttr,
264 privateKeyUsage, privateKeyAttr,
265 cred, owner,
266 pubKeyHandle, publicKey.header(),
267 privKeyHandle, privateKey.header());
268 makeReferenceKey(privKeyHandle, privateKey, database, privateKeyAttr,
269 privateKeyLabel);
270 // @@@ What if this throws, we need to free privateKey.
271 makeReferenceKey(pubKeyHandle, publicKey, database, publicKeyAttr,
272 publicKeyLabel);
273 }
274
275 void
276 SSCSPSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey,
277 CssmKey &PrivateKey)
278 {
279 unimplemented();
280 }
281
282 void
283 SSCSPSession::QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle,
284 const Context &Context,
285 const CssmKey &Key,
286 CSSM_KEY_SIZE &KeySize)
287 {
288 unimplemented();
289 }
290
291 void
292 SSCSPSession::FreeKey(const AccessCredentials *accessCred,
293 CssmKey &ioKey, CSSM_BOOL deleteKey)
294 {
295 if (ioKey.blobType() == CSSM_KEYBLOB_REFERENCE)
296 {
297 // @@@ Note that this means that detaching a session should free
298 // all keys ascociated with it or else...
299 // -- or else what?
300 // exactly!
301
302 // @@@ There are thread safety issues when deleting a key that is
303 // in use by another thread, but the answer to that is: Don't do
304 // that!
305
306 // Find the key in the map. Tell tell the key to free itself
307 // (when the auto_ptr deletes the key it removes itself from the map).
308 auto_ptr<SSKey> ssKey(&mSSCSPDLSession.find<SSKey>(ioKey));
309 ssKey->free(accessCred, ioKey, deleteKey);
310 }
311 else
312 {
313 CSPFullPluginSession::FreeKey(accessCred, ioKey, deleteKey);
314 }
315 }
316
317
318 //
319 // Generation stuff.
320 //
321 void
322 SSCSPSession::GenerateRandom(CSSM_CC_HANDLE ccHandle,
323 const Context &context,
324 CssmData &randomNumber)
325 {
326 checkOperation(context.type(), CSSM_ALGCLASS_RANDOMGEN);
327 // if (context.algorithm() != @@@) CssmError::throwMe(ALGORITHM_NOT_SUPPORTED);
328 uint32 needed = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE);
329
330 // @@@ What about the seed?
331 if (randomNumber.length())
332 {
333 if (randomNumber.length() < needed)
334 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
335 randomNumber.Length = needed;
336 clientSession().generateRandom(randomNumber);
337 }
338 else
339 {
340 randomNumber.Data = alloc<uint8>(needed);
341 try
342 {
343 randomNumber.Length = needed;
344 clientSession().generateRandom(randomNumber);
345 }
346 catch(...)
347 {
348 free(randomNumber.Data);
349 randomNumber.Data = NULL;
350 throw;
351 }
352 }
353 }
354
355 //
356 // Login/Logout and token operational maintainance. These mean little
357 // without support by the actual implementation, but we can help...
358 // @@@ Should this be in CSP[non-Full]PluginSession?
359 //
360 void
361 SSCSPSession::Login(const AccessCredentials &AccessCred,
362 const CssmData *LoginName,
363 const void *Reserved)
364 {
365 // @@@ Do a login to the securityServer making keys persistant until it
366 // goes away
367 unimplemented();
368 }
369
370 void
371 SSCSPSession::Logout()
372 {
373 unimplemented();
374 }
375
376 void
377 SSCSPSession::VerifyDevice(const CssmData &DeviceCert)
378 {
379 CssmError::throwMe(CSSMERR_CSP_DEVICE_VERIFY_FAILED);
380 }
381
382 void
383 SSCSPSession::GetOperationalStatistics(CSPOperationalStatistics &statistics)
384 {
385 unimplemented();
386 }
387
388
389 //
390 // Utterly miscellaneous, rarely used, strange functions
391 //
392 void
393 SSCSPSession::RetrieveCounter(CssmData &Counter)
394 {
395 unimplemented();
396 }
397
398 void
399 SSCSPSession::RetrieveUniqueId(CssmData &UniqueID)
400 {
401 unimplemented();
402 }
403
404 void
405 SSCSPSession::GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData)
406 {
407 unimplemented();
408 }
409
410
411 //
412 // ACL retrieval and change operations
413 //
414 void
415 SSCSPSession::GetKeyOwner(const CssmKey &Key,
416 CSSM_ACL_OWNER_PROTOTYPE &Owner)
417 {
418 lookupKey(Key).getOwner(Owner, *this);
419 }
420
421 void
422 SSCSPSession::ChangeKeyOwner(const AccessCredentials &AccessCred,
423 const CssmKey &Key,
424 const CSSM_ACL_OWNER_PROTOTYPE &NewOwner)
425 {
426 lookupKey(Key).changeOwner(AccessCred,
427 AclOwnerPrototype::overlay(NewOwner));
428 }
429
430 void
431 SSCSPSession::GetKeyAcl(const CssmKey &Key,
432 const CSSM_STRING *SelectionTag,
433 uint32 &NumberOfAclInfos,
434 CSSM_ACL_ENTRY_INFO_PTR &AclInfos)
435 {
436 lookupKey(Key).getAcl(reinterpret_cast<const char *>(SelectionTag),
437 NumberOfAclInfos,
438 reinterpret_cast<AclEntryInfo *&>(AclInfos), *this);
439 }
440
441 void
442 SSCSPSession::ChangeKeyAcl(const AccessCredentials &AccessCred,
443 const CSSM_ACL_EDIT &AclEdit,
444 const CssmKey &Key)
445 {
446 lookupKey(Key).changeAcl(AccessCred, AclEdit::overlay(AclEdit));
447 }
448
449 void
450 SSCSPSession::GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner)
451 {
452 unimplemented();
453 }
454
455 void
456 SSCSPSession::ChangeLoginOwner(const AccessCredentials &AccessCred,
457 const CSSM_ACL_OWNER_PROTOTYPE &NewOwner)
458 {
459 unimplemented();
460 }
461
462 void
463 SSCSPSession::GetLoginAcl(const CSSM_STRING *SelectionTag,
464 uint32 &NumberOfAclInfos,
465 CSSM_ACL_ENTRY_INFO_PTR &AclInfos)
466 {
467 unimplemented();
468 }
469
470 void
471 SSCSPSession::ChangeLoginAcl(const AccessCredentials &AccessCred,
472 const CSSM_ACL_EDIT &AclEdit)
473 {
474 unimplemented();
475 }
476
477
478
479 //
480 // Passthroughs (by default, unimplemented)
481 //
482 void
483 SSCSPSession::PassThrough(CSSM_CC_HANDLE CCHandle,
484 const Context &Context,
485 uint32 PassThroughId,
486 const void *InData,
487 void **OutData)
488 {
489 unimplemented();
490 }