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