Bug Summary

File:root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c
Warning:line 589, column 13
Value stored to 'parameters' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cmsrecinfo.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/smime/smime_smime -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/smime/smime_smime -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -I /root/firefox-clang/security/nss/lib/smime -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/smime/smime_smime -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c /root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c
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
20PRBool
21nss_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 */
41static const SECOidData fakeContent;
42NSSCMSRecipientInfo *
43nss_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
239done:
240 PORT_ArenaUnmarkPORT_ArenaUnmark_Util(poolp, mark);
241 if (freeSpki)
242 SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
243 return ri;
244
245loser:
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 */
266PRBool
267NSS_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 */
288NSSCMSRecipientInfo *
289NSS_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
295NSSCMSRecipientInfo *
296NSS_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
302NSSCMSRecipientInfo *
303NSS_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
309NSSCMSRecipientInfo *
310NSS_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
318NSSCMSRecipientInfo *
319NSS_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);
338done:
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
348void
349NSS_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
372int
373NSS_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
403SECItem *
404NSS_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
424SECOidTag
425NSS_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
443SECStatus
444NSS_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 }
552loser:
553 if (freeSpki)
554 SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
555
556 return rv;
557}
558
559PK11SymKey *
560NSS_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
649loser:
650 PORT_SetErrorPORT_SetError_Util(error);
651 return NULL((void*)0);
652}
653
654SECStatus
655NSS_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
729SECStatus
730NSS_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}