2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // SSCSPSession.cpp - Security Server CSP session.
22 #include "SSCSPSession.h"
24 #include "CSPDLPlugin.h"
25 #include "SSDatabase.h"
26 #include "SSDLSession.h"
32 using namespace SecurityServer
;
35 // SSCSPSession -- Security Server CSP session
37 SSCSPSession::SSCSPSession(CSSM_MODULE_HANDLE handle
,
39 const CSSM_VERSION
&version
,
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
),
51 mClientSession(CssmAllocator::standard(), *this)
56 // Called at (CSSM) context create time. This is ignored; we do a full
57 // context setup later, at setupContext time.
59 CSPFullPluginSession::CSPContext
*
60 SSCSPSession::contextCreate(CSSM_CC_HANDLE handle
, const Context
&context
)
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.
73 SSCSPSession::setupContext(CSPContext
* &cspCtx
,
74 const Context
&context
,
77 // note we skip this if this CSPContext is being reused
81 if (mSSFactory
.setup(*this, cspCtx
, context
, encoding
))
85 if (mBSafe4Factory
.setup(*this, cspCtx
, context
))
88 if (mCryptKitFactory
.setup(*this, cspCtx
, context
))
92 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
101 SSCSPSession::getDatabase(const Context
&context
)
103 CSSM_DL_DB_HANDLE
*aDLDbHandle
= context
.get
<CSSM_DL_DB_HANDLE
>(CSSM_ATTRIBUTE_DL_DB_HANDLE
);
107 return findSession
<SSDLSession
>(aDLDbHandle
->DLHandle
).findDbHandle(aDLDbHandle
->DBHandle
);
112 // Reference Key management
115 SSCSPSession::makeReferenceKey(KeyHandle inKeyHandle
, CssmKey
&ioKey
, SSDatabase
&inSSDatabase
,
116 uint32 inKeyAttr
, const CssmData
*inKeyLabel
)
118 return mSSCSPDLSession
.makeReferenceKey(*this, inKeyHandle
, ioKey
, inSSDatabase
, inKeyAttr
, inKeyLabel
);
122 SSCSPSession::lookupKey(const CssmKey
&inKey
)
124 return mSSCSPDLSession
.lookupKey(inKey
);
129 // Key creating and handeling members
132 SSCSPSession::WrapKey(CSSM_CC_HANDLE CCHandle
,
133 const Context
&context
,
134 const AccessCredentials
&AccessCred
,
136 const CssmData
*DescriptiveData
,
138 CSSM_PRIVILEGE Privilege
)
140 // @@@ Deal with permanent keys
141 const CssmKey
*keyInContext
=
142 context
.get
<const CssmKey
>(CSSM_ATTRIBUTE_KEY
);
144 KeyHandle contextKeyHandle
= (keyInContext
145 ? lookupKey(*keyInContext
).keyHandle()
147 clientSession().wrapKey(context
, contextKeyHandle
,
148 lookupKey(Key
).keyHandle(), &AccessCred
,
149 DescriptiveData
, WrappedKey
, *this);
153 SSCSPSession::UnwrapKey(CSSM_CC_HANDLE CCHandle
,
154 const Context
&context
,
155 const CssmKey
*PublicKey
,
156 const CssmWrappedKey
&WrappedKey
,
159 const CssmData
*KeyLabel
,
160 const CSSM_RESOURCE_CONTROL_CONTEXT
*CredAndAclEntry
,
161 CssmKey
&UnwrappedKey
,
162 CssmData
&DescriptiveData
,
163 CSSM_PRIVILEGE Privilege
)
165 SSDatabase database
= getDatabase(context
);
166 validateKeyAttr(KeyAttr
);
167 const AccessCredentials
*cred
= NULL
;
168 const AclEntryInput
*owner
= NULL
;
171 cred
= AccessCredentials::overlay(CredAndAclEntry
->AccessCred
);
172 owner
= &AclEntryInput::overlay(CredAndAclEntry
->InitialAclEntry
);
175 KeyHandle publicKey
= noKey
;
178 if (PublicKey
->blobType() == CSSM_KEYBLOB_RAW
)
180 // @@@ We need to unwrap the publicKey into the SecurityServer
182 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
185 publicKey
= lookupKey(*PublicKey
).keyHandle();
188 // @@@ Deal with permanent keys
189 const CssmKey
*keyInContext
=
190 context
.get
<const CssmKey
>(CSSM_ATTRIBUTE_KEY
);
192 KeyHandle contextKeyHandle
=
193 keyInContext
? lookupKey(*keyInContext
).keyHandle() : noKey
;
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
,
205 SSCSPSession::DeriveKey(CSSM_CC_HANDLE ccHandle
,
206 const Context
&context
,
210 const CssmData
*keyLabel
,
211 const CSSM_RESOURCE_CONTROL_CONTEXT
*credAndAclEntry
,
214 SSDatabase database
= getDatabase(context
);
215 validateKeyAttr(keyAttr
);
216 const AccessCredentials
*cred
= NULL
;
217 const AclEntryInput
*owner
= NULL
;
220 cred
= AccessCredentials::overlay(credAndAclEntry
->AccessCred
);
221 owner
= &AclEntryInput::overlay(credAndAclEntry
->InitialAclEntry
);
224 /* optional BaseKey */
225 const CssmKey
*keyInContext
=
226 context
.get
<const CssmKey
>(CSSM_ATTRIBUTE_KEY
);
227 KeyHandle contextKeyHandle
=
228 keyInContext
? lookupKey(*keyInContext
).keyHandle() : noKey
;
230 clientSession().deriveKey(database
.dbHandle(), context
, contextKeyHandle
, keyUsage
,
231 keyAttr
, param
, cred
, owner
, keyHandle
, derivedKey
.header());
232 makeReferenceKey(keyHandle
, derivedKey
, database
, keyAttr
, keyLabel
);
236 SSCSPSession::GenerateKey(CSSM_CC_HANDLE ccHandle
,
237 const Context
&context
,
240 const CssmData
*keyLabel
,
241 const CSSM_RESOURCE_CONTROL_CONTEXT
*credAndAclEntry
,
243 CSSM_PRIVILEGE privilege
)
245 SSDatabase database
= getDatabase(context
);
246 validateKeyAttr(keyAttr
);
247 const AccessCredentials
*cred
= NULL
;
248 const AclEntryInput
*owner
= NULL
;
251 cred
= AccessCredentials::overlay(credAndAclEntry
->AccessCred
);
252 owner
= &AclEntryInput::overlay(credAndAclEntry
->InitialAclEntry
);
256 clientSession().generateKey(database
.dbHandle(), context
, keyUsage
,
257 keyAttr
, cred
, owner
, keyHandle
, key
.header());
258 makeReferenceKey(keyHandle
, key
, database
, keyAttr
, keyLabel
);
262 SSCSPSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle
,
263 const Context
&context
,
264 uint32 publicKeyUsage
,
265 uint32 publicKeyAttr
,
266 const CssmData
*publicKeyLabel
,
268 uint32 privateKeyUsage
,
269 uint32 privateKeyAttr
,
270 const CssmData
*privateKeyLabel
,
271 const CSSM_RESOURCE_CONTROL_CONTEXT
*credAndAclEntry
,
273 CSSM_PRIVILEGE privilege
)
275 SSDatabase database
= getDatabase(context
);
276 validateKeyAttr(publicKeyAttr
);
277 validateKeyAttr(privateKeyAttr
);
278 const AccessCredentials
*cred
= NULL
;
279 const AclEntryInput
*owner
= NULL
;
282 cred
= AccessCredentials::overlay(credAndAclEntry
->AccessCred
);
283 owner
= &AclEntryInput::overlay(credAndAclEntry
->InitialAclEntry
);
286 KeyHandle pubKeyHandle
, privKeyHandle
;
287 clientSession().generateKey(database
.dbHandle(), context
,
288 publicKeyUsage
, publicKeyAttr
,
289 privateKeyUsage
, privateKeyAttr
,
291 pubKeyHandle
, publicKey
.header(),
292 privKeyHandle
, privateKey
.header());
293 makeReferenceKey(privKeyHandle
, privateKey
, database
, privateKeyAttr
,
295 // @@@ What if this throws, we need to free privateKey.
296 makeReferenceKey(pubKeyHandle
, publicKey
, database
, publicKeyAttr
,
301 SSCSPSession::ObtainPrivateKeyFromPublicKey(const CssmKey
&PublicKey
,
308 SSCSPSession::QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle
,
309 const Context
&Context
,
311 CSSM_KEY_SIZE
&KeySize
)
317 SSCSPSession::FreeKey(const AccessCredentials
*accessCred
,
318 CssmKey
&ioKey
, CSSM_BOOL deleteKey
)
320 if (ioKey
.blobType() == CSSM_KEYBLOB_REFERENCE
)
322 // @@@ Note that this means that detaching a session should free
323 // all keys ascociated with it or else...
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
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
);
338 CSPFullPluginSession::FreeKey(accessCred
, ioKey
, deleteKey
);
347 SSCSPSession::GenerateRandom(CSSM_CC_HANDLE ccHandle
,
348 const Context
&context
,
349 CssmData
&randomNumber
)
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
);
355 // @@@ What about the seed?
356 if (randomNumber
.length())
358 if (randomNumber
.length() < needed
)
359 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
360 randomNumber
.Length
= needed
;
361 clientSession().generateRandom(randomNumber
);
365 randomNumber
.Data
= alloc
<uint8
>(needed
);
368 randomNumber
.Length
= needed
;
369 clientSession().generateRandom(randomNumber
);
373 free(randomNumber
.Data
);
374 randomNumber
.Data
= NULL
;
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?
386 SSCSPSession::Login(const AccessCredentials
&AccessCred
,
387 const CssmData
*LoginName
,
388 const void *Reserved
)
390 // @@@ Do a login to the securityServer making keys persistant until it
396 SSCSPSession::Logout()
402 SSCSPSession::VerifyDevice(const CssmData
&DeviceCert
)
404 CssmError::throwMe(CSSMERR_CSP_DEVICE_VERIFY_FAILED
);
408 SSCSPSession::GetOperationalStatistics(CSPOperationalStatistics
&statistics
)
415 // Utterly miscellaneous, rarely used, strange functions
418 SSCSPSession::RetrieveCounter(CssmData
&Counter
)
424 SSCSPSession::RetrieveUniqueId(CssmData
&UniqueID
)
430 SSCSPSession::GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm
, CssmData
&TimeData
)
437 // ACL retrieval and change operations
440 SSCSPSession::GetKeyOwner(const CssmKey
&Key
,
441 CSSM_ACL_OWNER_PROTOTYPE
&Owner
)
443 lookupKey(Key
).getOwner(Owner
, *this);
447 SSCSPSession::ChangeKeyOwner(const AccessCredentials
&AccessCred
,
449 const CSSM_ACL_OWNER_PROTOTYPE
&NewOwner
)
451 lookupKey(Key
).changeOwner(AccessCred
,
452 AclOwnerPrototype::overlay(NewOwner
));
456 SSCSPSession::GetKeyAcl(const CssmKey
&Key
,
457 const CSSM_STRING
*SelectionTag
,
458 uint32
&NumberOfAclInfos
,
459 CSSM_ACL_ENTRY_INFO_PTR
&AclInfos
)
461 lookupKey(Key
).getAcl(reinterpret_cast<const char *>(SelectionTag
),
463 reinterpret_cast<AclEntryInfo
*&>(AclInfos
), *this);
467 SSCSPSession::ChangeKeyAcl(const AccessCredentials
&AccessCred
,
468 const CSSM_ACL_EDIT
&AclEdit
,
471 lookupKey(Key
).changeAcl(AccessCred
, AclEdit::overlay(AclEdit
));
475 SSCSPSession::GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE
&Owner
)
481 SSCSPSession::ChangeLoginOwner(const AccessCredentials
&AccessCred
,
482 const CSSM_ACL_OWNER_PROTOTYPE
&NewOwner
)
488 SSCSPSession::GetLoginAcl(const CSSM_STRING
*SelectionTag
,
489 uint32
&NumberOfAclInfos
,
490 CSSM_ACL_ENTRY_INFO_PTR
&AclInfos
)
496 SSCSPSession::ChangeLoginAcl(const AccessCredentials
&AccessCred
,
497 const CSSM_ACL_EDIT
&AclEdit
)
505 // Passthroughs (by default, unimplemented)
508 SSCSPSession::PassThrough(CSSM_CC_HANDLE CCHandle
,
509 const Context
&Context
,
510 uint32 PassThroughId
,
517 /* Validate requested key attr flags for newly generated keys */
518 void SSCSPSession::validateKeyAttr(uint32 reqKeyAttr
)
520 if(reqKeyAttr
& (CSSM_KEYATTR_RETURN_DATA
)) {
521 /* CSPDL only supports reference keys */
522 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK
);
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
);
529 /* There may be more, but we'll leave it to SS and CSP to decide */