]>
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 | ||
b1ab9ed8 | 102 | SECStatus |
d8f41ccd | 103 | SEC_SignData(SecAsn1Item *result, unsigned char *buf, int len, |
b1ab9ed8 A |
104 | SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) |
105 | { | |
106 | const CSSM_ACCESS_CREDENTIALS *accessCred; | |
107 | CSSM_ALGORITHMS algorithm; | |
108 | CSSM_CC_HANDLE cc = 0; | |
109 | CSSM_CSP_HANDLE csp; | |
110 | OSStatus rv; | |
d8f41ccd A |
111 | SecAsn1Item dataBuf = { (uint32)len, (uint8_t *)buf }; |
112 | SecAsn1Item sig = {}; | |
b1ab9ed8 A |
113 | const CSSM_KEY *key; |
114 | ||
115 | algorithm = SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag)); | |
116 | if (!algorithm) | |
117 | { | |
118 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
119 | rv = SECFailure; | |
120 | goto loser; | |
121 | } | |
122 | ||
123 | rv = SecKeyGetCSPHandle(pk, &csp); | |
124 | if (rv) { | |
125 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
126 | goto loser; | |
127 | } | |
128 | rv = SecKeyGetCSSMKey(pk, &key); | |
129 | if (rv) { | |
130 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
131 | goto loser; | |
132 | } | |
133 | rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); | |
134 | if (rv) { | |
135 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
136 | goto loser; | |
137 | } | |
138 | ||
139 | rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, accessCred, key, &cc); | |
140 | if (rv) { | |
141 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
142 | goto loser; | |
143 | } | |
144 | ||
145 | rv = CSSM_SignData(cc, &dataBuf, 1, CSSM_ALGID_NONE, &sig); | |
146 | if (rv) { | |
d8f41ccd A |
147 | SECErrorCodes code; |
148 | if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED | |
149 | || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) | |
150 | code = SEC_ERROR_USER_CANCELLED; | |
151 | else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION | |
152 | || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) | |
153 | code = SEC_ERROR_INADEQUATE_KEY_USAGE; | |
154 | else | |
155 | code = SEC_ERROR_LIBRARY_FAILURE; | |
156 | ||
b1ab9ed8 A |
157 | PORT_SetError(code); |
158 | goto loser; | |
159 | } | |
160 | ||
161 | result->Length = sig.Length; | |
162 | result->Data = sig.Data; | |
163 | ||
164 | loser: | |
165 | if (cc) | |
166 | CSSM_DeleteContext(cc); | |
167 | ||
168 | return rv; | |
169 | } | |
170 | ||
171 | SECStatus | |
d8f41ccd | 172 | SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SecAsn1Item *result, SecAsn1Item *digest) |
b1ab9ed8 A |
173 | { |
174 | const CSSM_ACCESS_CREDENTIALS *accessCred; | |
175 | CSSM_ALGORITHMS digalg, sigalg; | |
176 | CSSM_CC_HANDLE cc = 0; | |
177 | CSSM_CSP_HANDLE csp; | |
178 | const CSSM_KEY *key; | |
d8f41ccd | 179 | SecAsn1Item sig = {}; |
b1ab9ed8 A |
180 | OSStatus rv; |
181 | ||
182 | digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); | |
183 | sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); | |
184 | if (!digalg || !sigalg) | |
185 | { | |
186 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
187 | rv = SECFailure; | |
188 | goto loser; | |
189 | } | |
190 | ||
191 | rv = SecKeyGetCSPHandle(pk, &csp); | |
192 | if (rv) { | |
193 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
194 | goto loser; | |
195 | } | |
196 | rv = SecKeyGetCSSMKey(pk, &key); | |
197 | if (rv) { | |
198 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
199 | goto loser; | |
200 | } | |
201 | rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); | |
202 | if (rv) { | |
203 | PORT_SetError(SEC_ERROR_BAD_KEY); | |
204 | goto loser; | |
205 | } | |
206 | ||
207 | rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, accessCred, key, &cc); | |
208 | if (rv) { | |
209 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
210 | goto loser; | |
211 | } | |
212 | ||
213 | rv = CSSM_SignData(cc, digest, 1, digalg, &sig); | |
214 | if (rv) { | |
d8f41ccd A |
215 | SECErrorCodes code; |
216 | if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED | |
217 | || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) | |
218 | code = SEC_ERROR_USER_CANCELLED; | |
219 | else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION | |
220 | || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) | |
221 | code = SEC_ERROR_INADEQUATE_KEY_USAGE; | |
222 | else | |
223 | code = SEC_ERROR_LIBRARY_FAILURE; | |
224 | ||
b1ab9ed8 A |
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, | |
d8f41ccd | 241 | SecPublicKeyRef pk, SecAsn1Item *sig, |
b1ab9ed8 A |
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; | |
d8f41ccd | 249 | SecAsn1Item dataBuf = { (uint32)len, (uint8_t *)buf }; |
b1ab9ed8 A |
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 | |
d8f41ccd A |
281 | VFY_VerifyDigest(SecAsn1Item *digest, SecPublicKeyRef pk, |
282 | SecAsn1Item *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) | |
b1ab9ed8 A |
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, | |
d8f41ccd | 321 | SecAsn1Item * encKey) |
b1ab9ed8 A |
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. | |
d8f41ccd A |
419 | SecAsn1Item initVector = {}; |
420 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(SecAsn1Item *) }; | |
b1ab9ed8 A |
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 | |
d8f41ccd | 450 | WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag) |
b1ab9ed8 A |
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; | |
d8f41ccd | 459 | SecAsn1Item descriptiveData = {}; |
b1ab9ed8 A |
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. | |
d8f41ccd A |
494 | SecAsn1Item initVector = {}; |
495 | CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(SecAsn1Item *) }; | |
b1ab9ed8 A |
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 | |
d8f41ccd | 523 | || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) |
b1ab9ed8 A |
524 | code = SEC_ERROR_USER_CANCELLED; |
525 | else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION | |
526 | || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) | |
527 | code = SEC_ERROR_INADEQUATE_KEY_USAGE; | |
528 | else | |
b1ab9ed8 | 529 | code = SEC_ERROR_LIBRARY_FAILURE; |
b1ab9ed8 A |
530 | |
531 | PORT_SetError(code); | |
532 | goto loser; | |
533 | } | |
534 | ||
535 | // @@@ Export this key from the csp/dl and import it to the standard csp | |
d8f41ccd | 536 | rv = SecKeyCreate(&unwrappedKey, &bulkkey); |
b1ab9ed8 A |
537 | if (rv) |
538 | goto loser; | |
539 | ||
540 | loser: | |
541 | if (rv) | |
542 | PORT_SetError(rv); | |
543 | ||
544 | if (cc) | |
545 | CSSM_DeleteContext(cc); | |
546 | ||
547 | return bulkkey; | |
548 | } |