]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * crypto.h - public data structures and prototypes for the crypto library | |
3 | * | |
4 | * The contents of this file are subject to the Mozilla Public | |
5 | * License Version 1.1 (the "License"); you may not use this file | |
6 | * except in compliance with the License. You may obtain a copy of | |
7 | * the License at http://www.mozilla.org/MPL/ | |
8 | * | |
9 | * Software distributed under the License is distributed on an "AS | |
10 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
11 | * implied. See the License for the specific language governing | |
12 | * rights and limitations under the License. | |
13 | * | |
14 | * The Original Code is the Netscape security libraries. | |
15 | * | |
16 | * The Initial Developer of the Original Code is Netscape | |
17 | * Communications Corporation. Portions created by Netscape are | |
18 | * Copyright (C) 1994-2000 Netscape Communications Corporation. All | |
19 | * Rights Reserved. | |
20 | * | |
21 | * Contributor(s): | |
22 | * | |
23 | * Alternatively, the contents of this file may be used under the | |
24 | * terms of the GNU General Public License Version 2 or later (the | |
25 | * "GPL"), in which case the provisions of the GPL are applicable | |
26 | * instead of those above. If you wish to allow use of your | |
27 | * version of this file only under the terms of the GPL and not to | |
28 | * allow others to use your version of this file under the MPL, | |
29 | * indicate your decision by deleting the provisions above and | |
30 | * replace them with the notice and other provisions required by | |
31 | * the GPL. If you do not delete the provisions above, a recipient | |
32 | * may use your version of this file under either the MPL or the | |
33 | * GPL. | |
34 | */ | |
35 | ||
36 | #include "cryptohi.h" | |
37 | ||
38 | #include "secoid.h" | |
39 | #include "cmspriv.h" | |
40 | #include <security_asn1/secerr.h> | |
41 | #include <Security/cssmapi.h> | |
42 | #include <Security/cssmapi.h> | |
43 | #include <Security/SecKeyPriv.h> | |
44 | #include <Security/cssmapple.h> | |
45 | ||
46 | static CSSM_CSP_HANDLE gCsp = 0; | |
47 | static char gCssmInitialized = 0; | |
48 | ||
49 | /* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */ | |
50 | static CSSM_API_MEMORY_FUNCS memFuncs = | |
51 | { | |
52 | (CSSM_MALLOC)malloc, | |
53 | (CSSM_FREE)free, | |
54 | (CSSM_REALLOC)realloc, | |
55 | (CSSM_CALLOC)calloc, | |
56 | NULL | |
57 | }; | |
58 | ||
59 | /* | |
60 | * | |
61 | * SecCspHandleForAlgorithm | |
62 | * @@@ This function should get more parameters like keysize and operation required and use mds. | |
63 | * | |
64 | */ | |
65 | CSSM_CSP_HANDLE | |
66 | SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm) | |
67 | { | |
68 | ||
69 | if (!gCsp) | |
70 | { | |
71 | CSSM_VERSION version = { 2, 0 }; | |
72 | CSSM_RETURN rv; | |
73 | ||
74 | if (!gCssmInitialized) | |
75 | { | |
76 | CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } }; | |
77 | CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; | |
78 | ||
79 | rv = CSSM_Init (&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL); | |
80 | if (rv) | |
81 | goto loser; | |
82 | gCssmInitialized = 1; | |
83 | } | |
84 | ||
85 | rv = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); | |
86 | if (rv) | |
87 | goto loser; | |
88 | rv = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &memFuncs, 0, CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &gCsp); | |
89 | } | |
90 | ||
91 | loser: | |
92 | return gCsp; | |
93 | } | |
94 | ||
95 | CSSM_ALGORITHMS | |
96 | SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag) | |
97 | { | |
98 | const SECOidData *oidData = SECOID_FindOIDByTag(algTag); | |
99 | return oidData ? oidData->cssmAlgorithm : CSSM_ALGID_NONE; | |
100 | } | |
101 | ||
102 | static SECStatus SEC_CssmRtnToSECStatus(CSSM_RETURN rv) | |
103 | { | |
104 | CSSM_RETURN crtn = CSSM_ERRCODE(rv); | |
105 | switch(crtn) { | |
106 | case CSSM_ERRCODE_USER_CANCELED: | |
107 | case CSSM_ERRCODE_OPERATION_AUTH_DENIED: | |
108 | case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: | |
109 | return SEC_ERROR_USER_CANCELLED; | |
110 | case CSSM_ERRCODE_NO_USER_INTERACTION: | |
111 | return SEC_ERROR_NO_USER_INTERACTION; | |
112 | case CSSMERR_CSP_KEY_USAGE_INCORRECT: | |
113 | return SEC_ERROR_INADEQUATE_KEY_USAGE; | |
114 | default: | |
115 | fprintf(stderr, "CSSM_SignData returned: %08X\n", (uint32_t)rv); | |
116 | return SEC_ERROR_LIBRARY_FAILURE; | |
117 | } | |
118 | } | |
119 | ||
120 | SECStatus | |
121 | SEC_SignData(SECItem *result, unsigned char *buf, int len, | |
122 | SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) | |
123 | { | |
124 | const CSSM_ACCESS_CREDENTIALS *accessCred; | |
125 | CSSM_ALGORITHMS algorithm; | |
126 | CSSM_CC_HANDLE cc = 0; | |
127 | CSSM_CSP_HANDLE csp; | |
128 | OSStatus rv; | |
129 | CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; | |
130 | CSSM_DATA sig = {}; | |
131 | const CSSM_KEY *key; | |
132 | ||
133 | algorithm = SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag)); | |
134 | if (!algorithm) | |
135 | { | |
136 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
137 | rv = SECFailure; | |
138 | goto loser; | |
139 | } | |
140 | ||
141 | rv = SecKeyGetCSPHandle(pk, &csp); | |
142 | if (rv) { | |
143 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
144 | goto loser; | |
145 | } | |
146 | rv = SecKeyGetCSSMKey(pk, &key); | |
147 | if (rv) { | |
148 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
149 | goto loser; | |
150 | } | |
151 | rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); | |
152 | if (rv) { | |
153 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
154 | goto loser; | |
155 | } | |
156 | ||
157 | rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, accessCred, key, &cc); | |
158 | if (rv) { | |
159 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
160 | goto loser; | |
161 | } | |
162 | ||
163 | rv = CSSM_SignData(cc, &dataBuf, 1, CSSM_ALGID_NONE, &sig); | |
164 | if (rv) { | |
165 | SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); | |
166 | PORT_SetError(code); | |
167 | goto loser; | |
168 | } | |
169 | ||
170 | result->Length = sig.Length; | |
171 | result->Data = sig.Data; | |
172 | ||
173 | loser: | |
174 | if (cc) | |
175 | CSSM_DeleteContext(cc); | |
176 | ||
177 | return rv; | |
178 | } | |
179 | ||
180 | SECStatus | |
181 | SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest) | |
182 | { | |
183 | const CSSM_ACCESS_CREDENTIALS *accessCred; | |
184 | CSSM_ALGORITHMS digalg, sigalg; | |
185 | CSSM_CC_HANDLE cc = 0; | |
186 | CSSM_CSP_HANDLE csp; | |
187 | const CSSM_KEY *key; | |
188 | CSSM_DATA sig = {}; | |
189 | OSStatus rv; | |
190 | ||
191 | digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); | |
192 | sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); | |
193 | if (!digalg || !sigalg) | |
194 | { | |
195 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
196 | rv = SECFailure; | |
197 | goto loser; | |
198 | } | |
199 | ||
200 | rv = SecKeyGetCSPHandle(pk, &csp); | |
201 | if (rv) { | |
202 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
203 | goto loser; | |
204 | } | |
205 | rv = SecKeyGetCSSMKey(pk, &key); | |
206 | if (rv) { | |
207 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
208 | goto loser; | |
209 | } | |
210 | rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); | |
211 | if (rv) { | |
212 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
213 | goto loser; | |
214 | } | |
215 | ||
216 | rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, accessCred, key, &cc); | |
217 | if (rv) { | |
218 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
219 | goto loser; | |
220 | } | |
221 | ||
222 | rv = CSSM_SignData(cc, digest, 1, digalg, &sig); | |
223 | if (rv) { | |
224 | SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); | |
225 | PORT_SetError(code); | |
226 | goto loser; | |
227 | } | |
228 | ||
229 | result->Length = sig.Length; | |
230 | result->Data = sig.Data; | |
231 | ||
232 | loser: | |
233 | if (cc) | |
234 | CSSM_DeleteContext(cc); | |
235 | ||
236 | return rv; | |
237 | } | |
238 | ||
239 | SECStatus | |
240 | VFY_VerifyData(unsigned char *buf, int len, | |
241 | SecPublicKeyRef pk, SECItem *sig, | |
242 | SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) | |
243 | { | |
244 | SECOidTag algTag; | |
245 | CSSM_ALGORITHMS algorithm; | |
246 | CSSM_CC_HANDLE cc = 0; | |
247 | CSSM_CSP_HANDLE csp; | |
248 | OSStatus rv = SECFailure; | |
249 | CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; | |
250 | const CSSM_KEY *key; | |
251 | ||
252 | algTag = SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag); | |
253 | algorithm = SECOID_FindyCssmAlgorithmByTag(algTag); | |
254 | if (!algorithm) | |
255 | { | |
256 | rv = algTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; | |
257 | goto loser; | |
258 | } | |
259 | ||
260 | rv = SecKeyGetCSPHandle(pk, &csp); | |
261 | if (rv) | |
262 | goto loser; | |
263 | rv = SecKeyGetCSSMKey(pk, &key); | |
264 | if (rv) | |
265 | goto loser; | |
266 | ||
267 | rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, NULL, key, &cc); | |
268 | if (rv) | |
269 | goto loser; | |
270 | ||
271 | rv = CSSM_VerifyData(cc, &dataBuf, 1, CSSM_ALGID_NONE, sig); | |
272 | ||
273 | loser: | |
274 | if (cc) | |
275 | CSSM_DeleteContext(cc); | |
276 | ||
277 | return rv; | |
278 | } | |
279 | ||
280 | SECStatus | |
281 | VFY_VerifyDigest(SECItem *digest, SecPublicKeyRef pk, | |
282 | SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) | |
283 | { | |
284 | CSSM_ALGORITHMS sigalg, digalg; | |
285 | CSSM_CC_HANDLE cc = 0; | |
286 | CSSM_CSP_HANDLE csp; | |
287 | const CSSM_KEY *key; | |
288 | OSStatus rv; | |
289 | ||
290 | digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); | |
291 | sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); | |
292 | if (!digalg || !sigalg) | |
293 | { | |
294 | rv = digAlgTag == SEC_OID_UNKNOWN || sigAlgTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; | |
295 | goto loser; | |
296 | } | |
297 | ||
298 | rv = SecKeyGetCSPHandle(pk, &csp); | |
299 | if (rv) | |
300 | goto loser; | |
301 | rv = SecKeyGetCSSMKey(pk, &key); | |
302 | if (rv) | |
303 | goto loser; | |
304 | ||
305 | rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, NULL, key, &cc); | |
306 | if (rv) | |
307 | goto loser; | |
308 | ||
309 | rv = CSSM_VerifyData(cc, digest, 1, digalg, sig); | |
310 | ||
311 | loser: | |
312 | if (cc) | |
313 | CSSM_DeleteContext(cc); | |
314 | ||
315 | return rv; | |
316 | } | |
317 | ||
318 | SECStatus | |
319 | WRAP_PubWrapSymKey(SecPublicKeyRef publickey, | |
320 | SecSymmetricKeyRef bulkkey, | |
321 | CSSM_DATA_PTR encKey) | |
322 | { | |
323 | CSSM_WRAP_KEY wrappedKey = {}; | |
324 | //CSSM_WRAP_KEY wrappedPk = {} | |
325 | //CSSM_KEY upk = {}; | |
326 | CSSM_CC_HANDLE cc = 0; | |
327 | CSSM_CSP_HANDLE pkCsp, bkCsp; | |
328 | const CSSM_KEY *pk, *bk, *pubkey; | |
329 | OSStatus rv; | |
330 | CSSM_ACCESS_CREDENTIALS accessCred = {}; | |
331 | ||
332 | rv = SecKeyGetCSPHandle(publickey, &pkCsp); | |
333 | if (rv) | |
334 | goto loser; | |
335 | rv = SecKeyGetCSSMKey(publickey, &pk); | |
336 | if (rv) | |
337 | goto loser; | |
338 | ||
339 | rv = SecKeyGetCSPHandle(bulkkey, &bkCsp); | |
340 | if (rv) | |
341 | goto loser; | |
342 | rv = SecKeyGetCSSMKey(bulkkey, &bk); | |
343 | if (rv) | |
344 | goto loser; | |
345 | ||
346 | #if 1 | |
347 | pubkey = pk; | |
348 | #else | |
349 | /* We need to get the publickey out of it's pkCsp and into the bkCsp so we can operate with it. */ | |
350 | ||
351 | /* Make a NULL wrap symmetric context to extract the public key from pkCsp. */ | |
352 | rv = CSSM_CSP_CreateSymmetricContext(pkCsp, | |
353 | CSSM_ALGID_NONE, | |
354 | CSSM_MODE_NONE, | |
355 | NULL, /* accessCred */ | |
356 | NULL, /* key */ | |
357 | NULL, /* iv */ | |
358 | CSSM_PADDING_NONE, | |
359 | NULL, /* reserved */ | |
360 | &cc); | |
361 | if (rv) | |
362 | goto loser; | |
363 | rv = CSSM_WrapKey(cc, | |
364 | NULL /* accessCred */, | |
365 | pk, | |
366 | NULL /* descriptiveData */, | |
367 | &wrappedPk); | |
368 | CSSM_DeleteContext(cc); | |
369 | cc = 0; | |
370 | ||
371 | /* Make a NULL unwrap symmetric context to import the public key into bkCsp. */ | |
372 | rv = CSSM_CSP_CreateSymmetricContext(bkCsp, | |
373 | CSSM_ALGID_NONE, | |
374 | CSSM_MODE_NONE, | |
375 | NULL, /* accessCred */ | |
376 | NULL, /* key */ | |
377 | NULL, /* iv */ | |
378 | CSSM_PADDING_NONE, | |
379 | NULL, /* reserved */ | |
380 | &cc); | |
381 | if (rv) | |
382 | goto loser; | |
383 | rv = CSSM_UnwrapKey(cc, NULL, &wrappedPk, usage, attr, NULL /* label */, NULL /* rcc */, &upk, NULL /* descriptiveData */); | |
384 | CSSM_DeleteContext(cc); | |
385 | cc = 0; | |
386 | ||
387 | pubkey = &upk; | |
388 | #endif | |
389 | ||
390 | rv = CSSM_CSP_CreateAsymmetricContext(bkCsp, | |
391 | pubkey->KeyHeader.AlgorithmId, | |
392 | &accessCred, | |
393 | pubkey, | |
394 | CSSM_PADDING_PKCS1, | |
395 | &cc); | |
396 | if (rv) | |
397 | goto loser; | |
398 | ||
399 | { | |
400 | /* Set the wrapped key format to indicate we want just the raw bits encrypted. */ | |
401 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, sizeof(uint32) }; | |
402 | contextAttribute.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; | |
403 | rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); | |
404 | if (rv) | |
405 | goto loser; | |
406 | } | |
407 | ||
408 | { | |
409 | /* Set the mode to CSSM_ALGMODE_PKCS1_EME_V15. */ | |
410 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_MODE, sizeof(uint32) }; | |
411 | contextAttribute.Attribute.Uint32 = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ | |
412 | rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); | |
413 | if (rv) | |
414 | goto loser; | |
415 | } | |
416 | ||
417 | { | |
418 | // @@@ Stick in an empty initVector to work around a csp bug. | |
419 | CSSM_DATA initVector = {}; | |
420 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; | |
421 | contextAttribute.Attribute.Data = &initVector; | |
422 | rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); | |
423 | if (rv) | |
424 | goto loser; | |
425 | } | |
426 | ||
427 | rv = CSSM_WrapKey(cc, | |
428 | &accessCred, | |
429 | bk, | |
430 | NULL, /* descriptiveData */ | |
431 | &wrappedKey); | |
432 | if (rv) | |
433 | goto loser; | |
434 | ||
435 | // @@@ Fix leaks! | |
436 | if (encKey->Length < wrappedKey.KeyData.Length) | |
437 | abort(); | |
438 | encKey->Length = wrappedKey.KeyData.Length; | |
439 | memcpy(encKey->Data, wrappedKey.KeyData.Data, encKey->Length); | |
440 | CSSM_FreeKey(bkCsp, NULL /* credentials */, &wrappedKey, FALSE); | |
441 | ||
442 | loser: | |
443 | if (cc) | |
444 | CSSM_DeleteContext(cc); | |
445 | ||
446 | return rv; | |
447 | } | |
448 | ||
449 | SecSymmetricKeyRef | |
450 | WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) | |
451 | { | |
452 | SecSymmetricKeyRef bulkkey = NULL; | |
453 | CSSM_WRAP_KEY wrappedKey = {}; | |
454 | CSSM_CC_HANDLE cc = 0; | |
455 | CSSM_CSP_HANDLE pkCsp; | |
456 | const CSSM_KEY *pk; | |
457 | CSSM_KEY unwrappedKey = {}; | |
458 | const CSSM_ACCESS_CREDENTIALS *accessCred; | |
459 | CSSM_DATA descriptiveData = {}; | |
460 | CSSM_ALGORITHMS bulkalg; | |
461 | OSStatus rv; | |
462 | ||
463 | rv = SecKeyGetCSPHandle(privkey, &pkCsp); | |
464 | if (rv) | |
465 | goto loser; | |
466 | rv = SecKeyGetCSSMKey(privkey, &pk); | |
467 | if (rv) | |
468 | goto loser; | |
469 | rv = SecKeyGetCredentials(privkey, | |
470 | CSSM_ACL_AUTHORIZATION_DECRYPT, /* @@@ Should be UNWRAP */ | |
471 | kSecCredentialTypeDefault, | |
472 | &accessCred); | |
473 | if (rv) | |
474 | goto loser; | |
475 | ||
476 | bulkalg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); | |
477 | if (!bulkalg) | |
478 | { | |
479 | rv = SEC_ERROR_INVALID_ALGORITHM; | |
480 | goto loser; | |
481 | } | |
482 | ||
483 | rv = CSSM_CSP_CreateAsymmetricContext(pkCsp, | |
484 | pk->KeyHeader.AlgorithmId, | |
485 | accessCred, | |
486 | pk, | |
487 | CSSM_PADDING_PKCS1, | |
488 | &cc); | |
489 | if (rv) | |
490 | goto loser; | |
491 | ||
492 | { | |
493 | // @@@ Stick in an empty initvector to work around a csp bug. | |
494 | CSSM_DATA initVector = {}; | |
495 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; | |
496 | contextAttribute.Attribute.Data = &initVector; | |
497 | rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); | |
498 | if (rv) | |
499 | goto loser; | |
500 | } | |
501 | ||
502 | wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; | |
503 | wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; | |
504 | wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; | |
505 | wrappedKey.KeyHeader.AlgorithmId = bulkalg; | |
506 | wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; | |
507 | wrappedKey.KeyHeader.WrapAlgorithmId = pk->KeyHeader.AlgorithmId; | |
508 | wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ | |
509 | wrappedKey.KeyData = *encKey; | |
510 | ||
511 | rv = CSSM_UnwrapKey(cc, | |
512 | NULL, /* publicKey */ | |
513 | &wrappedKey, | |
514 | CSSM_KEYUSE_DECRYPT, | |
515 | CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */, | |
516 | NULL, /* keyLabel */ | |
517 | NULL, /* rcc */ | |
518 | &unwrappedKey, | |
519 | &descriptiveData); | |
520 | if (rv) { | |
521 | SECErrorCodes code; | |
522 | if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED | |
523 | || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED | |
524 | || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED) | |
525 | code = SEC_ERROR_USER_CANCELLED; | |
526 | else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION | |
527 | || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) | |
528 | code = SEC_ERROR_INADEQUATE_KEY_USAGE; | |
529 | else | |
530 | { | |
531 | fprintf(stderr, "CSSM_UnwrapKey returned: %08X\n", (uint32_t)rv); | |
532 | code = SEC_ERROR_LIBRARY_FAILURE; | |
533 | } | |
534 | ||
535 | PORT_SetError(code); | |
536 | goto loser; | |
537 | } | |
538 | ||
539 | // @@@ Export this key from the csp/dl and import it to the standard csp | |
540 | rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &bulkkey); | |
541 | if (rv) | |
542 | goto loser; | |
543 | ||
544 | loser: | |
545 | if (rv) | |
546 | PORT_SetError(rv); | |
547 | ||
548 | if (cc) | |
549 | CSSM_DeleteContext(cc); | |
550 | ||
551 | return bulkkey; | |
552 | } |