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