File: | root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c |
Warning: | line 589, column 13 Value stored to 'parameters' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | |
5 | /* |
6 | * CMS recipientInfo methods. |
7 | */ |
8 | |
9 | #include "cmslocal.h" |
10 | |
11 | #include "cert.h" |
12 | #include "keyhi.h" |
13 | #include "secasn1.h" |
14 | #include "secitem.h" |
15 | #include "secoid.h" |
16 | #include "pk11func.h" |
17 | #include "secerr.h" |
18 | #include "smime.h" |
19 | |
20 | PRBool |
21 | nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri) |
22 | { |
23 | if (ri->recipientInfoType == NSSCMSRecipientInfoID_KeyTrans) { |
24 | NSSCMSRecipientIdentifier *rid; |
25 | rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier; |
26 | if (rid->identifierType == NSSCMSRecipientID_SubjectKeyID) { |
27 | return PR_TRUE1; |
28 | } |
29 | } |
30 | return PR_FALSE0; |
31 | } |
32 | |
33 | /* |
34 | * NOTE: fakeContent marks CMSMessage structure which is only used as a carrier |
35 | * of pwfn_arg and arena pools. In an ideal world, NSSCMSMessage would not have |
36 | * been exported, and we would have added an ordinary enum to handle this |
37 | * check. Unfortunatly wo don't have that luxury so we are overloading the |
38 | * contentTypeTag field. NO code should every try to interpret this content tag |
39 | * as a real OID tag, or use any fields other than pwfn_arg or poolp of this |
40 | * CMSMessage for that matter */ |
41 | static const SECOidData fakeContent; |
42 | NSSCMSRecipientInfo * |
43 | nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, |
44 | NSSCMSRecipientIDSelector type, |
45 | CERTCertificate *cert, |
46 | SECKEYPublicKey *pubKey, |
47 | SECItem *subjKeyID, |
48 | void *pwfn_arg, |
49 | SECItem *DERinput) |
50 | { |
51 | NSSCMSRecipientInfo *ri; |
52 | void *mark; |
53 | SECOidTag certalgtag; |
54 | SECStatus rv = SECSuccess; |
55 | NSSCMSRecipientEncryptedKey *rek; |
56 | NSSCMSOriginatorIdentifierOrKey *oiok; |
57 | unsigned long version; |
58 | SECItem *dummy; |
59 | PLArenaPool *poolp; |
60 | CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL((void*)0); |
61 | NSSCMSRecipientIdentifier *rid; |
62 | extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[]; |
63 | |
64 | if (!cmsg) { |
65 | /* a CMSMessage wasn't supplied, create a fake one to hold the pwfunc |
66 | * and a private arena pool */ |
67 | cmsg = NSS_CMSMessage_Create(NULL((void*)0)); |
68 | cmsg->pwfn_arg = pwfn_arg; |
69 | /* mark it as a special cms message */ |
70 | cmsg->contentInfo.contentTypeTag = (SECOidData *)&fakeContent; |
71 | } |
72 | |
73 | poolp = cmsg->poolp; |
74 | |
75 | mark = PORT_ArenaMarkPORT_ArenaMark_Util(poolp); |
76 | |
77 | ri = (NSSCMSRecipientInfo *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(poolp, sizeof(NSSCMSRecipientInfo)); |
78 | if (ri == NULL((void*)0)) |
79 | goto loser; |
80 | |
81 | ri->cmsg = cmsg; |
82 | |
83 | if (DERinput) { |
84 | /* decode everything from DER */ |
85 | SECItem newinput; |
86 | rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &newinput, DERinput); |
87 | if (SECSuccess != rv) |
88 | goto loser; |
89 | rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput); |
90 | if (SECSuccess != rv) |
91 | goto loser; |
92 | } |
93 | |
94 | switch (type) { |
95 | case NSSCMSRecipientID_IssuerSN: { |
96 | ri->cert = CERT_DupCertificate(cert); |
97 | if (NULL((void*)0) == ri->cert) |
98 | goto loser; |
99 | spki = &(cert->subjectPublicKeyInfo); |
100 | break; |
101 | } |
102 | |
103 | case NSSCMSRecipientID_SubjectKeyID: { |
104 | PORT_Assert(pubKey)((pubKey)?((void)0):PR_Assert("pubKey","/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c" ,104)); |
105 | spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); |
106 | break; |
107 | } |
108 | |
109 | case NSSCMSRecipientID_BrandNew: |
110 | goto done; |
111 | break; |
112 | |
113 | default: |
114 | /* unkown type */ |
115 | goto loser; |
116 | break; |
117 | } |
118 | |
119 | certalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&(spki->algorithm)); |
120 | |
121 | rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier; |
122 | |
123 | // This switch must match the switch in NSS_CMSRecipient_IsSupported. |
124 | switch (certalgtag) { |
125 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
126 | ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans; |
127 | rid->identifierType = type; |
128 | if (type == NSSCMSRecipientID_IssuerSN) { |
129 | rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert); |
130 | if (rid->id.issuerAndSN == NULL((void*)0)) { |
131 | break; |
132 | } |
133 | } else if (type == NSSCMSRecipientID_SubjectKeyID) { |
134 | NSSCMSKeyTransRecipientInfoEx *riExtra; |
135 | |
136 | rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem)(SECItem *)PORT_ArenaAlloc_Util(poolp, sizeof(SECItem)); |
137 | if (rid->id.subjectKeyID == NULL((void*)0)) { |
138 | rv = SECFailure; |
139 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY); |
140 | break; |
141 | } |
142 | rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, rid->id.subjectKeyID, subjKeyID); |
143 | if (rv != SECSuccess || rid->id.subjectKeyID->data == NULL((void*)0)) { |
144 | rv = SECFailure; |
145 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY); |
146 | break; |
147 | } |
148 | riExtra = &ri->ri.keyTransRecipientInfoEx; |
149 | riExtra->version = 0; |
150 | riExtra->pubKey = SECKEY_CopyPublicKey(pubKey); |
151 | if (riExtra->pubKey == NULL((void*)0)) { |
152 | rv = SECFailure; |
153 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY); |
154 | break; |
155 | } |
156 | } else { |
157 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
158 | rv = SECFailure; |
159 | } |
160 | break; |
161 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
162 | PORT_Assert(type == NSSCMSRecipientID_IssuerSN)((type == NSSCMSRecipientID_IssuerSN)?((void)0):PR_Assert("type == NSSCMSRecipientID_IssuerSN" ,"/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c",162 )); |
163 | if (type != NSSCMSRecipientID_IssuerSN) { |
164 | rv = SECFailure; |
165 | break; |
166 | } |
167 | /* a key agreement op */ |
168 | ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree; |
169 | |
170 | /* we do not support the case where multiple recipients |
171 | * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys |
172 | * in this case, we would need to walk all the recipientInfos, take the |
173 | * ones that do KeyAgreement algorithms and join them, algorithm by algorithm |
174 | * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */ |
175 | |
176 | /* only epheremal-static Diffie-Hellman is supported for now |
177 | * this is the only form of key agreement that provides potential anonymity |
178 | * of the sender, plus we do not have to include certs in the message */ |
179 | |
180 | /* force single recipientEncryptedKey for now */ |
181 | if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL((void*)0)) { |
182 | rv = SECFailure; |
183 | break; |
184 | } |
185 | |
186 | /* hardcoded IssuerSN choice for now */ |
187 | rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN; |
188 | if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL((void*)0)) { |
189 | rv = SECFailure; |
190 | break; |
191 | } |
192 | |
193 | oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); |
194 | |
195 | /* see RFC2630 12.3.1.1 */ |
196 | oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey; |
197 | |
198 | rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys, |
199 | (void *)rek); |
200 | |
201 | break; |
202 | default: |
203 | /* other algorithms not supported yet */ |
204 | /* NOTE that we do not support any KEK algorithm */ |
205 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM); |
206 | rv = SECFailure; |
207 | break; |
208 | } |
209 | |
210 | if (rv == SECFailure) |
211 | goto loser; |
212 | |
213 | /* set version */ |
214 | switch (ri->recipientInfoType) { |
215 | case NSSCMSRecipientInfoID_KeyTrans: |
216 | if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == NSSCMSRecipientID_IssuerSN) |
217 | version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN0; |
218 | else |
219 | version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY2; |
220 | dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(poolp, &(ri->ri.keyTransRecipientInfo.version), version); |
221 | if (dummy == NULL((void*)0)) |
222 | goto loser; |
223 | break; |
224 | case NSSCMSRecipientInfoID_KeyAgree: |
225 | dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(poolp, &(ri->ri.keyAgreeRecipientInfo.version), |
226 | NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION3); |
227 | if (dummy == NULL((void*)0)) |
228 | goto loser; |
229 | break; |
230 | case NSSCMSRecipientInfoID_KEK: |
231 | /* NOTE: this cannot happen as long as we do not support any KEK algorithm */ |
232 | dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(poolp, &(ri->ri.kekRecipientInfo.version), |
233 | NSS_CMS_KEK_RECIPIENT_INFO_VERSION4); |
234 | if (dummy == NULL((void*)0)) |
235 | goto loser; |
236 | break; |
237 | } |
238 | |
239 | done: |
240 | PORT_ArenaUnmarkPORT_ArenaUnmark_Util(poolp, mark); |
241 | if (freeSpki) |
242 | SECKEY_DestroySubjectPublicKeyInfo(freeSpki); |
243 | return ri; |
244 | |
245 | loser: |
246 | if (ri && ri->cert) { |
247 | CERT_DestroyCertificate(ri->cert); |
248 | } |
249 | if (freeSpki) { |
250 | SECKEY_DestroySubjectPublicKeyInfo(freeSpki); |
251 | } |
252 | PORT_ArenaReleasePORT_ArenaRelease_Util(poolp, mark); |
253 | if (cmsg->contentInfo.contentTypeTag == &fakeContent) { |
254 | NSS_CMSMessage_Destroy(cmsg); |
255 | } |
256 | return NULL((void*)0); |
257 | } |
258 | |
259 | /* |
260 | * NSS_CMSRecipient_IsSupported - checks for a support certificate |
261 | * |
262 | * Use this function to confirm that the given certificate will be |
263 | * accepted by NSS_CMSRecipientInfo_Create, which means that the |
264 | * certificate can be used with a supported encryption algorithm. |
265 | */ |
266 | PRBool |
267 | NSS_CMSRecipient_IsSupported(CERTCertificate *cert) |
268 | { |
269 | CERTSubjectPublicKeyInfo *spki = &(cert->subjectPublicKeyInfo); |
270 | SECOidTag certalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&(spki->algorithm)); |
271 | |
272 | switch (certalgtag) { |
273 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
274 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
275 | return PR_TRUE1; |
276 | default: |
277 | return PR_FALSE0; |
278 | } |
279 | } |
280 | |
281 | /* |
282 | * NSS_CMSRecipientInfo_Create - create a recipientinfo |
283 | * |
284 | * we currently do not create KeyAgreement recipientinfos with multiple |
285 | * recipientEncryptedKeys the certificate is supposed to have been |
286 | * verified by the caller |
287 | */ |
288 | NSSCMSRecipientInfo * |
289 | NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert) |
290 | { |
291 | return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert, |
292 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
293 | } |
294 | |
295 | NSSCMSRecipientInfo * |
296 | NSS_CMSRecipientInfo_CreateNew(void *pwfn_arg) |
297 | { |
298 | return nss_cmsrecipientinfo_create(NULL((void*)0), NSSCMSRecipientID_BrandNew, NULL((void*)0), |
299 | NULL((void*)0), NULL((void*)0), pwfn_arg, NULL((void*)0)); |
300 | } |
301 | |
302 | NSSCMSRecipientInfo * |
303 | NSS_CMSRecipientInfo_CreateFromDER(SECItem *input, void *pwfn_arg) |
304 | { |
305 | return nss_cmsrecipientinfo_create(NULL((void*)0), NSSCMSRecipientID_BrandNew, NULL((void*)0), |
306 | NULL((void*)0), NULL((void*)0), pwfn_arg, input); |
307 | } |
308 | |
309 | NSSCMSRecipientInfo * |
310 | NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage *cmsg, |
311 | SECItem *subjKeyID, |
312 | SECKEYPublicKey *pubKey) |
313 | { |
314 | return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID, |
315 | NULL((void*)0), pubKey, subjKeyID, NULL((void*)0), NULL((void*)0)); |
316 | } |
317 | |
318 | NSSCMSRecipientInfo * |
319 | NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg, |
320 | CERTCertificate *cert) |
321 | { |
322 | SECKEYPublicKey *pubKey = NULL((void*)0); |
323 | SECItem subjKeyID = { siBuffer, NULL((void*)0), 0 }; |
324 | NSSCMSRecipientInfo *retVal = NULL((void*)0); |
325 | |
326 | if (!cmsg || !cert) { |
327 | return NULL((void*)0); |
328 | } |
329 | pubKey = CERT_ExtractPublicKey(cert); |
330 | if (!pubKey) { |
331 | goto done; |
332 | } |
333 | if (CERT_FindSubjectKeyIDExtension(cert, &subjKeyID) != SECSuccess || |
334 | subjKeyID.data == NULL((void*)0)) { |
335 | goto done; |
336 | } |
337 | retVal = NSS_CMSRecipientInfo_CreateWithSubjKeyID(cmsg, &subjKeyID, pubKey); |
338 | done: |
339 | if (pubKey) |
340 | SECKEY_DestroyPublicKey(pubKey); |
341 | |
342 | if (subjKeyID.data) |
343 | SECITEM_FreeItemSECITEM_FreeItem_Util(&subjKeyID, PR_FALSE0); |
344 | |
345 | return retVal; |
346 | } |
347 | |
348 | void |
349 | NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri) |
350 | { |
351 | if (!ri) { |
352 | return; |
353 | } |
354 | /* version was allocated on the pool, so no need to destroy it */ |
355 | /* issuerAndSN was allocated on the pool, so no need to destroy it */ |
356 | if (ri->cert != NULL((void*)0)) |
357 | CERT_DestroyCertificate(ri->cert); |
358 | |
359 | if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) { |
360 | NSSCMSKeyTransRecipientInfoEx *extra; |
361 | extra = &ri->ri.keyTransRecipientInfoEx; |
362 | if (extra->pubKey) |
363 | SECKEY_DestroyPublicKey(extra->pubKey); |
364 | } |
365 | if (ri->cmsg && ri->cmsg->contentInfo.contentTypeTag == &fakeContent) { |
366 | NSS_CMSMessage_Destroy(ri->cmsg); |
367 | } |
368 | |
369 | /* we're done. */ |
370 | } |
371 | |
372 | int |
373 | NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri) |
374 | { |
375 | unsigned long version; |
376 | SECItem *versionitem = NULL((void*)0); |
377 | |
378 | switch (ri->recipientInfoType) { |
379 | case NSSCMSRecipientInfoID_KeyTrans: |
380 | /* ignore subIndex */ |
381 | versionitem = &(ri->ri.keyTransRecipientInfo.version); |
382 | break; |
383 | case NSSCMSRecipientInfoID_KEK: |
384 | /* ignore subIndex */ |
385 | versionitem = &(ri->ri.kekRecipientInfo.version); |
386 | break; |
387 | case NSSCMSRecipientInfoID_KeyAgree: |
388 | versionitem = &(ri->ri.keyAgreeRecipientInfo.version); |
389 | break; |
390 | } |
391 | |
392 | PORT_Assert(versionitem)((versionitem)?((void)0):PR_Assert("versionitem","/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c" ,392)); |
393 | if (versionitem == NULL((void*)0)) |
394 | return 0; |
395 | |
396 | /* always take apart the SECItem */ |
397 | if (SEC_ASN1DecodeIntegerSEC_ASN1DecodeInteger_Util(versionitem, &version) != SECSuccess) |
398 | return 0; |
399 | else |
400 | return (int)version; |
401 | } |
402 | |
403 | SECItem * |
404 | NSS_CMSRecipientInfo_GetEncryptedKey(NSSCMSRecipientInfo *ri, int subIndex) |
405 | { |
406 | SECItem *enckey = NULL((void*)0); |
407 | |
408 | switch (ri->recipientInfoType) { |
409 | case NSSCMSRecipientInfoID_KeyTrans: |
410 | /* ignore subIndex */ |
411 | enckey = &(ri->ri.keyTransRecipientInfo.encKey); |
412 | break; |
413 | case NSSCMSRecipientInfoID_KEK: |
414 | /* ignore subIndex */ |
415 | enckey = &(ri->ri.kekRecipientInfo.encKey); |
416 | break; |
417 | case NSSCMSRecipientInfoID_KeyAgree: |
418 | enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); |
419 | break; |
420 | } |
421 | return enckey; |
422 | } |
423 | |
424 | SECOidTag |
425 | NSS_CMSRecipientInfo_GetKeyEncryptionAlgorithmTag(NSSCMSRecipientInfo *ri) |
426 | { |
427 | SECOidTag encalgtag = SEC_OID_UNKNOWN; /* an invalid encryption alg */ |
428 | |
429 | switch (ri->recipientInfoType) { |
430 | case NSSCMSRecipientInfoID_KeyTrans: |
431 | encalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&(ri->ri.keyTransRecipientInfo.keyEncAlg)); |
432 | break; |
433 | case NSSCMSRecipientInfoID_KeyAgree: |
434 | encalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg)); |
435 | break; |
436 | case NSSCMSRecipientInfoID_KEK: |
437 | encalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&(ri->ri.kekRecipientInfo.keyEncAlg)); |
438 | break; |
439 | } |
440 | return encalgtag; |
441 | } |
442 | |
443 | SECStatus |
444 | NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, |
445 | SECOidTag bulkalgtag) |
446 | { |
447 | CERTCertificate *cert; |
448 | SECOidTag certalgtag; |
449 | SECStatus rv = SECSuccess; |
450 | NSSCMSRecipientEncryptedKey *rek; |
451 | NSSCMSOriginatorIdentifierOrKey *oiok; |
452 | CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL((void*)0); |
453 | PLArenaPool *poolp; |
454 | NSSCMSKeyTransRecipientInfoEx *extra = NULL((void*)0); |
455 | PRBool usesSubjKeyID; |
456 | void *wincx = NULL((void*)0); |
457 | |
458 | poolp = ri->cmsg->poolp; |
459 | cert = ri->cert; |
460 | usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri); |
461 | if (cert) { |
462 | spki = &cert->subjectPublicKeyInfo; |
463 | } else if (usesSubjKeyID) { |
464 | extra = &ri->ri.keyTransRecipientInfoEx; |
465 | /* sanity check */ |
466 | PORT_Assert(extra->pubKey)((extra->pubKey)?((void)0):PR_Assert("extra->pubKey","/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c" ,466)); |
467 | if (!extra->pubKey) { |
468 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
469 | return SECFailure; |
470 | } |
471 | spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(extra->pubKey); |
472 | } else { |
473 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
474 | return SECFailure; |
475 | } |
476 | |
477 | /* XXX set ri->recipientInfoType to the proper value here */ |
478 | /* or should we look if it's been set already ? */ |
479 | |
480 | certalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&spki->algorithm); |
481 | if (!NSS_SMIMEUtil_KeyEncodingAllowed(&spki->algorithm, cert, extra ? extra->pubKey : NULL((void*)0))) { |
482 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_EXPORT_ALGORITHM); |
483 | rv = SECFailure; |
484 | goto loser; |
485 | } |
486 | switch (certalgtag) { |
487 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
488 | /* wrap the symkey */ |
489 | if (cert) { |
490 | rv = NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, |
491 | &ri->ri.keyTransRecipientInfo.encKey); |
492 | if (rv != SECSuccess) |
493 | break; |
494 | } else if (usesSubjKeyID) { |
495 | PORT_Assert(extra != NULL)((extra != ((void*)0))?((void)0):PR_Assert("extra != NULL","/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c" ,495)); |
496 | rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, extra->pubKey, |
497 | bulkkey, &ri->ri.keyTransRecipientInfo.encKey); |
498 | if (rv != SECSuccess) |
499 | break; |
500 | } |
501 | |
502 | rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL((void*)0)); |
503 | break; |
504 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
505 | rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0]; |
506 | if (rek == NULL((void*)0)) { |
507 | rv = SECFailure; |
508 | break; |
509 | } |
510 | |
511 | oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); |
512 | PORT_Assert(oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey)((oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey )?((void)0):PR_Assert("oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey" ,"/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c",512 )); |
513 | |
514 | /* see RFC2630 12.3.1.1 */ |
515 | if (SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier, |
516 | certalgtag, NULL((void*)0)) != SECSuccess) { |
517 | rv = SECFailure; |
518 | break; |
519 | } |
520 | |
521 | /* this will generate a key pair, compute the shared secret, */ |
522 | /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */ |
523 | /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */ |
524 | switch (certalgtag) { |
525 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
526 | if (ri->cmsg) { |
527 | wincx = ri->cmsg->pwfn_arg; |
528 | } else { |
529 | wincx = PK11_GetWindow(bulkkey); |
530 | } |
531 | rv = NSS_CMSUtil_EncryptSymKey_ESECDH(poolp, cert, bulkkey, |
532 | &rek->encKey, |
533 | PR_TRUE1, |
534 | &ri->ri.keyAgreeRecipientInfo.ukm, |
535 | &ri->ri.keyAgreeRecipientInfo.keyEncAlg, |
536 | &oiok->id.originatorPublicKey.publicKey, |
537 | wincx); |
538 | break; |
539 | |
540 | default: |
541 | /* Not reached. Added to silence enum warnings. */ |
542 | PORT_Assert(0)((0)?((void)0):PR_Assert("0","/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c" ,542)); |
543 | break; |
544 | } |
545 | break; |
546 | default: |
547 | /* other algorithms not supported yet */ |
548 | /* NOTE that we do not support any KEK algorithm */ |
549 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM); |
550 | rv = SECFailure; |
551 | } |
552 | loser: |
553 | if (freeSpki) |
554 | SECKEY_DestroySubjectPublicKeyInfo(freeSpki); |
555 | |
556 | return rv; |
557 | } |
558 | |
559 | PK11SymKey * |
560 | NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex, |
561 | CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag) |
562 | { |
563 | PK11SymKey *bulkkey = NULL((void*)0); |
564 | SECAlgorithmID *algid; |
565 | SECOidTag encalgtag; |
566 | SECItem *enckey = NULL((void*)0), *ukm = NULL((void*)0), *parameters = NULL((void*)0); |
567 | NSSCMSOriginatorIdentifierOrKey *oiok = NULL((void*)0); |
568 | int error; |
569 | void *wincx = NULL((void*)0); |
570 | |
571 | ri->cert = CERT_DupCertificate(cert); |
572 | /* mark the recipientInfo so we can find it later */ |
573 | |
574 | switch (ri->recipientInfoType) { |
575 | case NSSCMSRecipientInfoID_KeyTrans: |
576 | algid = &(ri->ri.keyTransRecipientInfo.keyEncAlg); |
577 | parameters = &(ri->ri.keyTransRecipientInfo.keyEncAlg.parameters); |
578 | enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */ |
579 | break; |
580 | case NSSCMSRecipientInfoID_KeyAgree: |
581 | algid = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg); |
582 | parameters = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg.parameters); |
583 | enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); |
584 | oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); |
585 | ukm = &(ri->ri.keyAgreeRecipientInfo.ukm); |
586 | break; |
587 | case NSSCMSRecipientInfoID_KEK: |
588 | algid = &(ri->ri.kekRecipientInfo.keyEncAlg); |
589 | parameters = &(ri->ri.kekRecipientInfo.keyEncAlg.parameters); |
Value stored to 'parameters' is never read | |
590 | enckey = &(ri->ri.kekRecipientInfo.encKey); |
591 | /* not supported yet */ |
592 | default: |
593 | error = SEC_ERROR_UNSUPPORTED_KEYALG; |
594 | goto loser; |
595 | break; |
596 | } |
597 | if (!NSS_SMIMEUtil_KeyDecodingAllowed(algid, privkey)) { |
598 | error = SEC_ERROR_BAD_EXPORT_ALGORITHM; |
599 | goto loser; |
600 | } |
601 | encalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid); |
602 | switch (encalgtag) { |
603 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
604 | /* RSA encryption algorithm: */ |
605 | if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) { |
606 | error = SEC_ERROR_UNSUPPORTED_KEYALG; |
607 | goto loser; |
608 | } |
609 | /* get the symmetric (bulk) key by unwrapping it using our private key */ |
610 | bulkkey = NSS_CMSUtil_DecryptSymKey_RSA(privkey, enckey, bulkalgtag); |
611 | break; |
612 | case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION: |
613 | /* RSA OAEP encryption algorithm: */ |
614 | if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) { |
615 | error = SEC_ERROR_UNSUPPORTED_KEYALG; |
616 | goto loser; |
617 | } |
618 | /* get the symmetric (bulk) key by unwrapping it using our private key */ |
619 | bulkkey = NSS_CMSUtil_DecryptSymKey_RSA_OAEP(privkey, parameters, enckey, |
620 | bulkalgtag); |
621 | break; |
622 | case SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME: |
623 | case SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME: |
624 | case SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME: |
625 | case SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME: |
626 | case SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME: |
627 | case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME: |
628 | case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME: |
629 | case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME: |
630 | case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME: |
631 | case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME: |
632 | if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyAgree) { |
633 | error = SEC_ERROR_UNSUPPORTED_KEYALG; |
634 | goto loser; |
635 | } |
636 | if (ri->cmsg) { |
637 | wincx = ri->cmsg->pwfn_arg; |
638 | } |
639 | bulkkey = NSS_CMSUtil_DecryptSymKey_ECDH(privkey, enckey, algid, |
640 | bulkalgtag, ukm, oiok, wincx); |
641 | break; |
642 | default: |
643 | error = SEC_ERROR_UNSUPPORTED_KEYALG; |
644 | goto loser; |
645 | } |
646 | /* XXXX continue here */ |
647 | return bulkkey; |
648 | |
649 | loser: |
650 | PORT_SetErrorPORT_SetError_Util(error); |
651 | return NULL((void*)0); |
652 | } |
653 | |
654 | SECStatus |
655 | NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri, |
656 | CERTCertificate **retcert, |
657 | SECKEYPrivateKey **retkey) |
658 | { |
659 | CERTCertificate *cert = NULL((void*)0); |
660 | NSSCMSRecipient **recipients = NULL((void*)0); |
661 | NSSCMSRecipientInfo *recipientInfos[2]; |
662 | SECStatus rv = SECSuccess; |
663 | SECKEYPrivateKey *key = NULL((void*)0); |
664 | |
665 | if (!ri) |
666 | return SECFailure; |
667 | |
668 | if (!retcert && !retkey) { |
669 | /* nothing requested, nothing found, success */ |
670 | return SECSuccess; |
671 | } |
672 | |
673 | if (retcert) { |
674 | *retcert = NULL((void*)0); |
675 | } |
676 | if (retkey) { |
677 | *retkey = NULL((void*)0); |
678 | } |
679 | |
680 | if (ri->cert) { |
681 | cert = CERT_DupCertificate(ri->cert); |
682 | if (!cert) { |
683 | rv = SECFailure; |
684 | } |
685 | } |
686 | if (SECSuccess == rv && !cert) { |
687 | /* we don't have the cert, we have to look for it */ |
688 | /* first build an NSS_CMSRecipient */ |
689 | recipientInfos[0] = ri; |
690 | recipientInfos[1] = NULL((void*)0); |
691 | |
692 | recipients = nss_cms_recipient_list_create(recipientInfos); |
693 | if (recipients) { |
694 | /* now look for the cert and key */ |
695 | if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients, |
696 | ri->cmsg->pwfn_arg)) { |
697 | cert = CERT_DupCertificate(recipients[0]->cert); |
698 | key = SECKEY_CopyPrivateKey(recipients[0]->privkey); |
699 | } else { |
700 | rv = SECFailure; |
701 | } |
702 | |
703 | nss_cms_recipient_list_destroy(recipients); |
704 | } else { |
705 | rv = SECFailure; |
706 | } |
707 | } else if (SECSuccess == rv && cert && retkey) { |
708 | /* we have the cert, we just need the key now */ |
709 | key = PK11_FindPrivateKeyFromCert(cert->slot, cert, ri->cmsg->pwfn_arg); |
710 | } |
711 | if (retcert) { |
712 | *retcert = cert; |
713 | } else { |
714 | if (cert) { |
715 | CERT_DestroyCertificate(cert); |
716 | } |
717 | } |
718 | if (retkey) { |
719 | *retkey = key; |
720 | } else { |
721 | if (key) { |
722 | SECKEY_DestroyPrivateKey(key); |
723 | } |
724 | } |
725 | |
726 | return rv; |
727 | } |
728 | |
729 | SECStatus |
730 | NSS_CMSRecipientInfo_Encode(PLArenaPool *poolp, |
731 | const NSSCMSRecipientInfo *src, |
732 | SECItem *returned) |
733 | { |
734 | extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[]; |
735 | SECStatus rv = SECFailure; |
736 | if (!src || !returned) { |
737 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); |
738 | } else if (SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(poolp, returned, src, |
739 | NSSCMSRecipientInfoTemplate)) { |
740 | rv = SECSuccess; |
741 | } |
742 | return rv; |
743 | } |