Bug Summary

File:root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c
Warning:line 553, 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 -O2 -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-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -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 -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -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-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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 -Wno-character-conversion -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 -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-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 ri->cert = NULL((void*)0);
359 }
360
361 if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) {
362 NSSCMSKeyTransRecipientInfoEx *extra;
363 extra = &ri->ri.keyTransRecipientInfoEx;
364 if (extra->pubKey) {
365 SECKEY_DestroyPublicKey(extra->pubKey);
366 extra->pubKey = NULL((void*)0);
367 }
368 }
369 if (ri->cmsg && ri->cmsg->contentInfo.contentTypeTag == &fakeContent) {
370 NSS_CMSMessage_Destroy(ri->cmsg);
371 }
372
373 /* we're done. */
374}
375
376int
377NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri)
378{
379 unsigned long version;
380 SECItem *versionitem = NULL((void*)0);
381
382 switch (ri->recipientInfoType) {
383 case NSSCMSRecipientInfoID_KeyTrans:
384 /* ignore subIndex */
385 versionitem = &(ri->ri.keyTransRecipientInfo.version);
386 break;
387 case NSSCMSRecipientInfoID_KEK:
388 /* ignore subIndex */
389 versionitem = &(ri->ri.kekRecipientInfo.version);
390 break;
391 case NSSCMSRecipientInfoID_KeyAgree:
392 versionitem = &(ri->ri.keyAgreeRecipientInfo.version);
393 break;
394 }
395
396 PORT_Assert(versionitem)((versionitem) ? ((void)0) : PR_Assert("versionitem", "/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c"
, 396))
;
397 if (versionitem == NULL((void*)0))
398 return 0;
399
400 /* always take apart the SECItem */
401 if (SEC_ASN1DecodeIntegerSEC_ASN1DecodeInteger_Util(versionitem, &version) != SECSuccess)
402 return 0;
403 else
404 return (int)version;
405}
406
407SECStatus
408NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
409 SECOidTag bulkalgtag)
410{
411 CERTCertificate *cert;
412 SECOidTag certalgtag;
413 SECStatus rv = SECSuccess;
414 NSSCMSRecipientEncryptedKey *rek;
415 NSSCMSOriginatorIdentifierOrKey *oiok;
416 CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL((void*)0);
417 PLArenaPool *poolp;
418 NSSCMSKeyTransRecipientInfoEx *extra = NULL((void*)0);
419 PRBool usesSubjKeyID;
420 void *wincx = NULL((void*)0);
421
422 poolp = ri->cmsg->poolp;
423 cert = ri->cert;
424 usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
425 if (cert) {
426 spki = &cert->subjectPublicKeyInfo;
427 } else if (usesSubjKeyID) {
428 extra = &ri->ri.keyTransRecipientInfoEx;
429 /* sanity check */
430 PORT_Assert(extra->pubKey)((extra->pubKey) ? ((void)0) : PR_Assert("extra->pubKey"
, "/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c", 430
))
;
431 if (!extra->pubKey) {
432 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
433 return SECFailure;
434 }
435 spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(extra->pubKey);
436 } else {
437 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
438 return SECFailure;
439 }
440
441 /* XXX set ri->recipientInfoType to the proper value here */
442 /* or should we look if it's been set already ? */
443
444 certalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&spki->algorithm);
445 if (!NSS_SMIMEUtil_KeyEncodingAllowed(&spki->algorithm, cert, extra ? extra->pubKey : NULL((void*)0))) {
446 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_EXPORT_ALGORITHM);
447 rv = SECFailure;
448 goto loser;
449 }
450 switch (certalgtag) {
451 case SEC_OID_PKCS1_RSA_ENCRYPTION:
452 /* wrap the symkey */
453 if (cert) {
454 rv = NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey,
455 &ri->ri.keyTransRecipientInfo.encKey);
456 if (rv != SECSuccess)
457 break;
458 } else if (usesSubjKeyID) {
459 PORT_Assert(extra != NULL)((extra != ((void*)0)) ? ((void)0) : PR_Assert("extra != NULL"
, "/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c", 459
))
;
460 rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, extra->pubKey,
461 bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
462 if (rv != SECSuccess)
463 break;
464 }
465
466 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL((void*)0));
467 break;
468 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
469 rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
470 if (rek == NULL((void*)0)) {
471 rv = SECFailure;
472 break;
473 }
474
475 oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
476 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", 476
))
;
477
478 /* see RFC2630 12.3.1.1 */
479 if (SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
480 certalgtag, NULL((void*)0)) != SECSuccess) {
481 rv = SECFailure;
482 break;
483 }
484
485 /* this will generate a key pair, compute the shared secret, */
486 /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
487 /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
488 switch (certalgtag) {
489 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
490 if (ri->cmsg) {
491 wincx = ri->cmsg->pwfn_arg;
492 } else {
493 wincx = PK11_GetWindow(bulkkey);
494 }
495 rv = NSS_CMSUtil_EncryptSymKey_ESECDH(poolp, cert, bulkkey,
496 &rek->encKey,
497 PR_TRUE1,
498 &ri->ri.keyAgreeRecipientInfo.ukm,
499 &ri->ri.keyAgreeRecipientInfo.keyEncAlg,
500 &oiok->id.originatorPublicKey.publicKey,
501 wincx);
502 break;
503
504 default:
505 /* Not reached. Added to silence enum warnings. */
506 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/smime/cmsrecinfo.c"
, 506))
;
507 break;
508 }
509 break;
510 default:
511 /* other algorithms not supported yet */
512 /* NOTE that we do not support any KEK algorithm */
513 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
514 rv = SECFailure;
515 }
516loser:
517 if (freeSpki)
518 SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
519
520 return rv;
521}
522
523PK11SymKey *
524NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex,
525 CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag)
526{
527 PK11SymKey *bulkkey = NULL((void*)0);
528 SECAlgorithmID *algid;
529 SECOidTag encalgtag;
530 SECItem *enckey = NULL((void*)0), *ukm = NULL((void*)0), *parameters = NULL((void*)0);
531 NSSCMSOriginatorIdentifierOrKey *oiok = NULL((void*)0);
532 int error;
533 void *wincx = NULL((void*)0);
534
535 ri->cert = CERT_DupCertificate(cert);
536 /* mark the recipientInfo so we can find it later */
537
538 switch (ri->recipientInfoType) {
539 case NSSCMSRecipientInfoID_KeyTrans:
540 algid = &(ri->ri.keyTransRecipientInfo.keyEncAlg);
541 parameters = &(ri->ri.keyTransRecipientInfo.keyEncAlg.parameters);
542 enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */
543 break;
544 case NSSCMSRecipientInfoID_KeyAgree:
545 algid = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg);
546 parameters = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg.parameters);
547 enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey);
548 oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
549 ukm = &(ri->ri.keyAgreeRecipientInfo.ukm);
550 break;
551 case NSSCMSRecipientInfoID_KEK:
552 algid = &(ri->ri.kekRecipientInfo.keyEncAlg);
553 parameters = &(ri->ri.kekRecipientInfo.keyEncAlg.parameters);
Value stored to 'parameters' is never read
554 enckey = &(ri->ri.kekRecipientInfo.encKey);
555 /* not supported yet */
556 default:
557 error = SEC_ERROR_UNSUPPORTED_KEYALG;
558 goto loser;
559 break;
560 }
561 if (!NSS_SMIMEUtil_KeyDecodingAllowed(algid, privkey)) {
562 error = SEC_ERROR_BAD_EXPORT_ALGORITHM;
563 goto loser;
564 }
565 encalgtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid);
566 switch (encalgtag) {
567 case SEC_OID_PKCS1_RSA_ENCRYPTION:
568 /* RSA encryption algorithm: */
569 if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) {
570 error = SEC_ERROR_UNSUPPORTED_KEYALG;
571 goto loser;
572 }
573 /* get the symmetric (bulk) key by unwrapping it using our private key */
574 bulkkey = NSS_CMSUtil_DecryptSymKey_RSA(privkey, enckey, bulkalgtag);
575 break;
576 case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
577 /* RSA OAEP encryption algorithm: */
578 if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) {
579 error = SEC_ERROR_UNSUPPORTED_KEYALG;
580 goto loser;
581 }
582 /* get the symmetric (bulk) key by unwrapping it using our private key */
583 bulkkey = NSS_CMSUtil_DecryptSymKey_RSA_OAEP(privkey, parameters, enckey,
584 bulkalgtag);
585 break;
586 case SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME:
587 case SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME:
588 case SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME:
589 case SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME:
590 case SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME:
591 case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME:
592 case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME:
593 case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME:
594 case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME:
595 case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME:
596 if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyAgree) {
597 error = SEC_ERROR_UNSUPPORTED_KEYALG;
598 goto loser;
599 }
600 if (ri->cmsg) {
601 wincx = ri->cmsg->pwfn_arg;
602 }
603 bulkkey = NSS_CMSUtil_DecryptSymKey_ECDH(privkey, enckey, algid,
604 bulkalgtag, ukm, oiok, wincx);
605 break;
606 default:
607 error = SEC_ERROR_UNSUPPORTED_KEYALG;
608 goto loser;
609 }
610 /* XXXX continue here */
611 return bulkkey;
612
613loser:
614 PORT_SetErrorPORT_SetError_Util(error);
615 return NULL((void*)0);
616}
617
618SECStatus
619NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri,
620 CERTCertificate **retcert,
621 SECKEYPrivateKey **retkey)
622{
623 CERTCertificate *cert = NULL((void*)0);
624 NSSCMSRecipient **recipients = NULL((void*)0);
625 NSSCMSRecipientInfo *recipientInfos[2];
626 SECStatus rv = SECSuccess;
627 SECKEYPrivateKey *key = NULL((void*)0);
628
629 if (!ri)
630 return SECFailure;
631
632 if (!retcert && !retkey) {
633 /* nothing requested, nothing found, success */
634 return SECSuccess;
635 }
636
637 if (retcert) {
638 *retcert = NULL((void*)0);
639 }
640 if (retkey) {
641 *retkey = NULL((void*)0);
642 }
643
644 if (ri->cert) {
645 cert = CERT_DupCertificate(ri->cert);
646 if (!cert) {
647 rv = SECFailure;
648 }
649 }
650 if (SECSuccess == rv && !cert) {
651 /* we don't have the cert, we have to look for it */
652 /* first build an NSS_CMSRecipient */
653 recipientInfos[0] = ri;
654 recipientInfos[1] = NULL((void*)0);
655
656 recipients = nss_cms_recipient_list_create(recipientInfos);
657 if (recipients) {
658 /* now look for the cert and key */
659 if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients,
660 ri->cmsg->pwfn_arg)) {
661 cert = CERT_DupCertificate(recipients[0]->cert);
662 key = SECKEY_CopyPrivateKey(recipients[0]->privkey);
663 } else {
664 rv = SECFailure;
665 }
666
667 nss_cms_recipient_list_destroy(recipients);
668 } else {
669 rv = SECFailure;
670 }
671 } else if (SECSuccess == rv && cert && retkey) {
672 /* we have the cert, we just need the key now */
673 key = PK11_FindPrivateKeyFromCert(cert->slot, cert, ri->cmsg->pwfn_arg);
674 }
675 if (retcert) {
676 *retcert = cert;
677 } else {
678 if (cert) {
679 CERT_DestroyCertificate(cert);
680 }
681 }
682 if (retkey) {
683 *retkey = key;
684 } else {
685 if (key) {
686 SECKEY_DestroyPrivateKey(key);
687 }
688 }
689
690 return rv;
691}
692
693SECStatus
694NSS_CMSRecipientInfo_Encode(PLArenaPool *poolp,
695 const NSSCMSRecipientInfo *src,
696 SECItem *returned)
697{
698 extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];
699 SECStatus rv = SECFailure;
700 if (!src || !returned) {
701 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
702 } else if (SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(poolp, returned, src,
703 NSSCMSRecipientInfoTemplate)) {
704 rv = SECSuccess;
705 }
706 return rv;
707}