Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: mozilla/security/nss/lib/pkcs7/p7create.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/security/nss/lib/pkcs7/p7common.c ('k') | mozilla/security/nss/lib/pkcs7/p7decode.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 * PKCS7 creation.
7 *
8 * $Id: p7create.c,v 1.11 2012/04/25 14:50:06 gerv%gerv.net Exp $
9 */
10
11 #include "p7local.h"
12
13 #include "cert.h"
14 #include "secasn1.h"
15 #include "secitem.h"
16 #include "secoid.h"
17 #include "pk11func.h"
18 #include "prtime.h"
19 #include "secerr.h"
20 #include "secder.h"
21 #include "secpkcs5.h"
22
23 const int NSS_PBE_DEFAULT_ITERATION_COUNT = 2000; /* used in p12e.c too */
24
25 static SECStatus
26 sec_pkcs7_init_content_info (SEC_PKCS7ContentInfo *cinfo, PRArenaPool *poolp,
27 SECOidTag kind, PRBool detached)
28 {
29 void *thing;
30 int version;
31 SECItem *versionp;
32 SECStatus rv;
33
34 PORT_Assert (cinfo != NULL && poolp != NULL);
35 if (cinfo == NULL || poolp == NULL)
36 return SECFailure;
37
38 cinfo->contentTypeTag = SECOID_FindOIDByTag (kind);
39 PORT_Assert (cinfo->contentTypeTag
40 && cinfo->contentTypeTag->offset == kind);
41
42 rv = SECITEM_CopyItem (poolp, &(cinfo->contentType),
43 &(cinfo->contentTypeTag->oid));
44 if (rv != SECSuccess)
45 return rv;
46
47 if (detached)
48 return SECSuccess;
49
50 switch (kind) {
51 default:
52 case SEC_OID_PKCS7_DATA:
53 thing = PORT_ArenaZAlloc (poolp, sizeof(SECItem));
54 cinfo->content.data = (SECItem*)thing;
55 versionp = NULL;
56 version = -1;
57 break;
58 case SEC_OID_PKCS7_DIGESTED_DATA:
59 thing = PORT_ArenaZAlloc (poolp, sizeof(SEC_PKCS7DigestedData));
60 cinfo->content.digestedData = (SEC_PKCS7DigestedData*)thing;
61 versionp = &(cinfo->content.digestedData->version);
62 version = SEC_PKCS7_DIGESTED_DATA_VERSION;
63 break;
64 case SEC_OID_PKCS7_ENCRYPTED_DATA:
65 thing = PORT_ArenaZAlloc (poolp, sizeof(SEC_PKCS7EncryptedData));
66 cinfo->content.encryptedData = (SEC_PKCS7EncryptedData*)thing;
67 versionp = &(cinfo->content.encryptedData->version);
68 version = SEC_PKCS7_ENCRYPTED_DATA_VERSION;
69 break;
70 case SEC_OID_PKCS7_ENVELOPED_DATA:
71 thing = PORT_ArenaZAlloc (poolp, sizeof(SEC_PKCS7EnvelopedData));
72 cinfo->content.envelopedData =
73 (SEC_PKCS7EnvelopedData*)thing;
74 versionp = &(cinfo->content.envelopedData->version);
75 version = SEC_PKCS7_ENVELOPED_DATA_VERSION;
76 break;
77 case SEC_OID_PKCS7_SIGNED_DATA:
78 thing = PORT_ArenaZAlloc (poolp, sizeof(SEC_PKCS7SignedData));
79 cinfo->content.signedData =
80 (SEC_PKCS7SignedData*)thing;
81 versionp = &(cinfo->content.signedData->version);
82 version = SEC_PKCS7_SIGNED_DATA_VERSION;
83 break;
84 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
85 thing = PORT_ArenaZAlloc(poolp,sizeof(SEC_PKCS7SignedAndEnvelopedData));
86 cinfo->content.signedAndEnvelopedData =
87 (SEC_PKCS7SignedAndEnvelopedData*)thing;
88 versionp = &(cinfo->content.signedAndEnvelopedData->version);
89 version = SEC_PKCS7_SIGNED_AND_ENVELOPED_DATA_VERSION;
90 break;
91 }
92
93 if (thing == NULL)
94 return SECFailure;
95
96 if (versionp != NULL) {
97 SECItem *dummy;
98
99 PORT_Assert (version >= 0);
100 dummy = SEC_ASN1EncodeInteger (poolp, versionp, version);
101 if (dummy == NULL)
102 return SECFailure;
103 PORT_Assert (dummy == versionp);
104 }
105
106 return SECSuccess;
107 }
108
109
110 static SEC_PKCS7ContentInfo *
111 sec_pkcs7_create_content_info (SECOidTag kind, PRBool detached,
112 SECKEYGetPasswordKey pwfn, void *pwfn_arg)
113 {
114 SEC_PKCS7ContentInfo *cinfo;
115 PRArenaPool *poolp;
116 SECStatus rv;
117
118 poolp = PORT_NewArena (1024); /* XXX what is right value? */
119 if (poolp == NULL)
120 return NULL;
121
122 cinfo = (SEC_PKCS7ContentInfo*)PORT_ArenaZAlloc (poolp, sizeof(*cinfo));
123 if (cinfo == NULL) {
124 PORT_FreeArena (poolp, PR_FALSE);
125 return NULL;
126 }
127
128 cinfo->poolp = poolp;
129 cinfo->pwfn = pwfn;
130 cinfo->pwfn_arg = pwfn_arg;
131 cinfo->created = PR_TRUE;
132 cinfo->refCount = 1;
133
134 rv = sec_pkcs7_init_content_info (cinfo, poolp, kind, detached);
135 if (rv != SECSuccess) {
136 PORT_FreeArena (poolp, PR_FALSE);
137 return NULL;
138 }
139
140 return cinfo;
141 }
142
143
144 /*
145 * Add a signer to a PKCS7 thing, verifying the signature cert first.
146 * Any error returns SECFailure.
147 *
148 * XXX Right now this only adds the *first* signer. It fails if you try
149 * to add a second one -- this needs to be fixed.
150 */
151 static SECStatus
152 sec_pkcs7_add_signer (SEC_PKCS7ContentInfo *cinfo,
153 CERTCertificate * cert,
154 SECCertUsage certusage,
155 CERTCertDBHandle * certdb,
156 SECOidTag digestalgtag,
157 SECItem * digestdata)
158 {
159 SEC_PKCS7SignerInfo *signerinfo, **signerinfos, ***signerinfosp;
160 SECAlgorithmID *digestalg, **digestalgs, ***digestalgsp;
161 SECItem *digest, **digests, ***digestsp;
162 SECItem * dummy;
163 void * mark;
164 SECStatus rv;
165 SECOidTag kind;
166
167 kind = SEC_PKCS7ContentType (cinfo);
168 switch (kind) {
169 case SEC_OID_PKCS7_SIGNED_DATA:
170 {
171 SEC_PKCS7SignedData *sdp;
172
173 sdp = cinfo->content.signedData;
174 digestalgsp = &(sdp->digestAlgorithms);
175 digestsp = &(sdp->digests);
176 signerinfosp = &(sdp->signerInfos);
177 }
178 break;
179 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
180 {
181 SEC_PKCS7SignedAndEnvelopedData *saedp;
182
183 saedp = cinfo->content.signedAndEnvelopedData;
184 digestalgsp = &(saedp->digestAlgorithms);
185 digestsp = &(saedp->digests);
186 signerinfosp = &(saedp->signerInfos);
187 }
188 break;
189 default:
190 return SECFailure; /* XXX set an error? */
191 }
192
193 /*
194 * XXX I think that CERT_VerifyCert should do this if *it* is passed
195 * a NULL database.
196 */
197 if (certdb == NULL) {
198 certdb = CERT_GetDefaultCertDB();
199 if (certdb == NULL)
200 return SECFailure; /* XXX set an error? */
201 }
202
203 if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage, PR_Now(),
204 cinfo->pwfn_arg, NULL) != SECSuccess)
205 {
206 /* XXX Did CERT_VerifyCert set an error? */
207 return SECFailure;
208 }
209
210 /*
211 * XXX This is the check that we do not already have a signer.
212 * This is not what we really want -- we want to allow this
213 * and *add* the new signer.
214 */
215 PORT_Assert (*signerinfosp == NULL
216 && *digestalgsp == NULL && *digestsp == NULL);
217 if (*signerinfosp != NULL || *digestalgsp != NULL || *digestsp != NULL)
218 return SECFailure;
219
220 mark = PORT_ArenaMark (cinfo->poolp);
221
222 signerinfo = (SEC_PKCS7SignerInfo*)PORT_ArenaZAlloc (cinfo->poolp,
223 sizeof(SEC_PKCS7SignerInfo));
224 if (signerinfo == NULL) {
225 PORT_ArenaRelease (cinfo->poolp, mark);
226 return SECFailure;
227 }
228
229 dummy = SEC_ASN1EncodeInteger (cinfo->poolp, &signerinfo->version,
230 SEC_PKCS7_SIGNER_INFO_VERSION);
231 if (dummy == NULL) {
232 PORT_ArenaRelease (cinfo->poolp, mark);
233 return SECFailure;
234 }
235 PORT_Assert (dummy == &signerinfo->version);
236
237 signerinfo->cert = CERT_DupCertificate (cert);
238 if (signerinfo->cert == NULL) {
239 PORT_ArenaRelease (cinfo->poolp, mark);
240 return SECFailure;
241 }
242
243 signerinfo->issuerAndSN = CERT_GetCertIssuerAndSN (cinfo->poolp, cert);
244 if (signerinfo->issuerAndSN == NULL) {
245 PORT_ArenaRelease (cinfo->poolp, mark);
246 return SECFailure;
247 }
248
249 rv = SECOID_SetAlgorithmID (cinfo->poolp, &signerinfo->digestAlg,
250 digestalgtag, NULL);
251 if (rv != SECSuccess) {
252 PORT_ArenaRelease (cinfo->poolp, mark);
253 return SECFailure;
254 }
255
256 /*
257 * Okay, now signerinfo is all set. We just need to put it and its
258 * companions (another copy of the digest algorithm, and the digest
259 * itself if given) into the main structure.
260 *
261 * XXX If we are handling more than one signer, the following code
262 * needs to look through the digest algorithms already specified
263 * and see if the same one is there already. If it is, it does not
264 * need to be added again. Also, if it is there *and* the digest
265 * is not null, then the digest given should match the digest already
266 * specified -- if not, that is an error. Finally, the new signerinfo
267 * should be *added* to the set already found.
268 */
269
270 signerinfos = (SEC_PKCS7SignerInfo**)PORT_ArenaAlloc (cinfo->poolp,
271 2 * sizeof(SEC_PKCS7SignerInfo *));
272 if (signerinfos == NULL) {
273 PORT_ArenaRelease (cinfo->poolp, mark);
274 return SECFailure;
275 }
276 signerinfos[0] = signerinfo;
277 signerinfos[1] = NULL;
278
279 digestalg = PORT_ArenaZAlloc (cinfo->poolp, sizeof(SECAlgorithmID));
280 digestalgs = PORT_ArenaAlloc (cinfo->poolp, 2 * sizeof(SECAlgorithmID *));
281 if (digestalg == NULL || digestalgs == NULL) {
282 PORT_ArenaRelease (cinfo->poolp, mark);
283 return SECFailure;
284 }
285 rv = SECOID_SetAlgorithmID (cinfo->poolp, digestalg, digestalgtag, NULL);
286 if (rv != SECSuccess) {
287 PORT_ArenaRelease (cinfo->poolp, mark);
288 return SECFailure;
289 }
290 digestalgs[0] = digestalg;
291 digestalgs[1] = NULL;
292
293 if (digestdata != NULL) {
294 digest = (SECItem*)PORT_ArenaAlloc (cinfo->poolp, sizeof(SECItem));
295 digests = (SECItem**)PORT_ArenaAlloc (cinfo->poolp,
296 2 * sizeof(SECItem *));
297 if (digest == NULL || digests == NULL) {
298 PORT_ArenaRelease (cinfo->poolp, mark);
299 return SECFailure;
300 }
301 rv = SECITEM_CopyItem (cinfo->poolp, digest, digestdata);
302 if (rv != SECSuccess) {
303 PORT_ArenaRelease (cinfo->poolp, mark);
304 return SECFailure;
305 }
306 digests[0] = digest;
307 digests[1] = NULL;
308 } else {
309 digests = NULL;
310 }
311
312 *signerinfosp = signerinfos;
313 *digestalgsp = digestalgs;
314 *digestsp = digests;
315
316 PORT_ArenaUnmark(cinfo->poolp, mark);
317 return SECSuccess;
318 }
319
320
321 /*
322 * Helper function for creating an empty signedData.
323 */
324 static SEC_PKCS7ContentInfo *
325 sec_pkcs7_create_signed_data (SECKEYGetPasswordKey pwfn, void *pwfn_arg)
326 {
327 SEC_PKCS7ContentInfo *cinfo;
328 SEC_PKCS7SignedData *sigd;
329 SECStatus rv;
330
331 cinfo = sec_pkcs7_create_content_info (SEC_OID_PKCS7_SIGNED_DATA, PR_FALSE,
332 pwfn, pwfn_arg);
333 if (cinfo == NULL)
334 return NULL;
335
336 sigd = cinfo->content.signedData;
337 PORT_Assert (sigd != NULL);
338
339 /*
340 * XXX Might we want to allow content types other than data?
341 * If so, via what interface?
342 */
343 rv = sec_pkcs7_init_content_info (&(sigd->contentInfo), cinfo->poolp,
344 SEC_OID_PKCS7_DATA, PR_TRUE);
345 if (rv != SECSuccess) {
346 SEC_PKCS7DestroyContentInfo (cinfo);
347 return NULL;
348 }
349
350 return cinfo;
351 }
352
353
354 /*
355 * Start a PKCS7 signing context.
356 *
357 * "cert" is the cert that will be used to sign the data. It will be
358 * checked for validity.
359 *
360 * "certusage" describes the signing usage (e.g. certUsageEmailSigner)
361 * XXX Maybe SECCertUsage should be split so that our caller just says
362 * "email" and *we* add the "signing" part -- otherwise our caller
363 * could be lying about the usage; we do not want to allow encryption
364 * certs for signing or vice versa.
365 *
366 * "certdb" is the cert database to use for verifying the cert.
367 * It can be NULL if a default database is available (like in the client).
368 *
369 * "digestalg" names the digest algorithm (e.g. SEC_OID_SHA1).
370 *
371 * "digest" is the actual digest of the data. It must be provided in
372 * the case of detached data or NULL if the content will be included.
373 *
374 * The return value can be passed to functions which add things to
375 * it like attributes, then eventually to SEC_PKCS7Encode() or to
376 * SEC_PKCS7EncoderStart() to create the encoded data, and finally to
377 * SEC_PKCS7DestroyContentInfo().
378 *
379 * An error results in a return value of NULL and an error set.
380 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
381 */
382 SEC_PKCS7ContentInfo *
383 SEC_PKCS7CreateSignedData (CERTCertificate *cert,
384 SECCertUsage certusage,
385 CERTCertDBHandle *certdb,
386 SECOidTag digestalg,
387 SECItem *digest,
388 SECKEYGetPasswordKey pwfn, void *pwfn_arg)
389 {
390 SEC_PKCS7ContentInfo *cinfo;
391 SECStatus rv;
392
393 cinfo = sec_pkcs7_create_signed_data (pwfn, pwfn_arg);
394 if (cinfo == NULL)
395 return NULL;
396
397 rv = sec_pkcs7_add_signer (cinfo, cert, certusage, certdb,
398 digestalg, digest);
399 if (rv != SECSuccess) {
400 SEC_PKCS7DestroyContentInfo (cinfo);
401 return NULL;
402 }
403
404 return cinfo;
405 }
406
407
408 static SEC_PKCS7Attribute *
409 sec_pkcs7_create_attribute (PRArenaPool *poolp, SECOidTag oidtag,
410 SECItem *value, PRBool encoded)
411 {
412 SEC_PKCS7Attribute *attr;
413 SECItem **values;
414 void *mark;
415
416 PORT_Assert (poolp != NULL);
417 mark = PORT_ArenaMark (poolp);
418
419 attr = (SEC_PKCS7Attribute*)PORT_ArenaAlloc (poolp,
420 sizeof(SEC_PKCS7Attribute));
421 if (attr == NULL)
422 goto loser;
423
424 attr->typeTag = SECOID_FindOIDByTag (oidtag);
425 if (attr->typeTag == NULL)
426 goto loser;
427
428 if (SECITEM_CopyItem (poolp, &(attr->type),
429 &(attr->typeTag->oid)) != SECSuccess)
430 goto loser;
431
432 values = (SECItem**)PORT_ArenaAlloc (poolp, 2 * sizeof(SECItem *));
433 if (values == NULL)
434 goto loser;
435
436 if (value != NULL) {
437 SECItem *copy;
438
439 copy = (SECItem*)PORT_ArenaAlloc (poolp, sizeof(SECItem));
440 if (copy == NULL)
441 goto loser;
442
443 if (SECITEM_CopyItem (poolp, copy, value) != SECSuccess)
444 goto loser;
445
446 value = copy;
447 }
448
449 values[0] = value;
450 values[1] = NULL;
451 attr->values = values;
452 attr->encoded = encoded;
453
454 PORT_ArenaUnmark (poolp, mark);
455 return attr;
456
457 loser:
458 PORT_Assert (mark != NULL);
459 PORT_ArenaRelease (poolp, mark);
460 return NULL;
461 }
462
463
464 static SECStatus
465 sec_pkcs7_add_attribute (SEC_PKCS7ContentInfo *cinfo,
466 SEC_PKCS7Attribute ***attrsp,
467 SEC_PKCS7Attribute *attr)
468 {
469 SEC_PKCS7Attribute **attrs;
470 SECItem *ct_value;
471 void *mark;
472
473 PORT_Assert (SEC_PKCS7ContentType (cinfo) == SEC_OID_PKCS7_SIGNED_DATA);
474 if (SEC_PKCS7ContentType (cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
475 return SECFailure;
476
477 attrs = *attrsp;
478 if (attrs != NULL) {
479 int count;
480
481 /*
482 * We already have some attributes, and just need to add this
483 * new one.
484 */
485
486 /*
487 * We should already have the *required* attributes, which were
488 * created/added at the same time the first attribute was added.
489 */
490 PORT_Assert (sec_PKCS7FindAttribute (attrs,
491 SEC_OID_PKCS9_CONTENT_TYPE,
492 PR_FALSE) != NULL);
493 PORT_Assert (sec_PKCS7FindAttribute (attrs,
494 SEC_OID_PKCS9_MESSAGE_DIGEST,
495 PR_FALSE) != NULL);
496
497 for (count = 0; attrs[count] != NULL; count++)
498 ;
499 attrs = (SEC_PKCS7Attribute**)PORT_ArenaGrow (cinfo->poolp, attrs,
500 (count + 1) * sizeof(SEC_PKCS7Attribute *),
501 (count + 2) * sizeof(SEC_PKCS7Attribute *));
502 if (attrs == NULL)
503 return SECFailure;
504
505 attrs[count] = attr;
506 attrs[count+1] = NULL;
507 *attrsp = attrs;
508
509 return SECSuccess;
510 }
511
512 /*
513 * This is the first time an attribute is going in.
514 * We need to create and add the required attributes, and then
515 * we will also add in the one our caller gave us.
516 */
517
518 /*
519 * There are 2 required attributes, plus the one our caller wants
520 * to add, plus we always end with a NULL one. Thus, four slots.
521 */
522 attrs = (SEC_PKCS7Attribute**)PORT_ArenaAlloc (cinfo->poolp,
523 4 * sizeof(SEC_PKCS7Attribute *));
524 if (attrs == NULL)
525 return SECFailure;
526
527 mark = PORT_ArenaMark (cinfo->poolp);
528
529 /*
530 * First required attribute is the content type of the data
531 * being signed.
532 */
533 ct_value = &(cinfo->content.signedData->contentInfo.contentType);
534 attrs[0] = sec_pkcs7_create_attribute (cinfo->poolp,
535 SEC_OID_PKCS9_CONTENT_TYPE,
536 ct_value, PR_FALSE);
537 /*
538 * Second required attribute is the message digest of the data
539 * being signed; we leave the value NULL for now (just create
540 * the place for it to go), and the encoder will fill it in later.
541 */
542 attrs[1] = sec_pkcs7_create_attribute (cinfo->poolp,
543 SEC_OID_PKCS9_MESSAGE_DIGEST,
544 NULL, PR_FALSE);
545 if (attrs[0] == NULL || attrs[1] == NULL) {
546 PORT_ArenaRelease (cinfo->poolp, mark);
547 return SECFailure;
548 }
549
550 attrs[2] = attr;
551 attrs[3] = NULL;
552 *attrsp = attrs;
553
554 PORT_ArenaUnmark (cinfo->poolp, mark);
555 return SECSuccess;
556 }
557
558
559 /*
560 * Add the signing time to the authenticated (i.e. signed) attributes
561 * of "cinfo". This is expected to be included in outgoing signed
562 * messages for email (S/MIME) but is likely useful in other situations.
563 *
564 * This should only be added once; a second call will either do
565 * nothing or replace an old signing time with a newer one.
566 *
567 * XXX This will probably just shove the current time into "cinfo"
568 * but it will not actually get signed until the entire item is
569 * processed for encoding. Is this (expected to be small) delay okay?
570 *
571 * "cinfo" should be of type signedData (the only kind of pkcs7 data
572 * that is allowed authenticated attributes); SECFailure will be returned
573 * if it is not.
574 */
575 SECStatus
576 SEC_PKCS7AddSigningTime (SEC_PKCS7ContentInfo *cinfo)
577 {
578 SEC_PKCS7SignerInfo **signerinfos;
579 SEC_PKCS7Attribute *attr;
580 SECItem stime;
581 SECStatus rv;
582 int si;
583
584 PORT_Assert (SEC_PKCS7ContentType (cinfo) == SEC_OID_PKCS7_SIGNED_DATA);
585 if (SEC_PKCS7ContentType (cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
586 return SECFailure;
587
588 signerinfos = cinfo->content.signedData->signerInfos;
589
590 /* There has to be a signer, or it makes no sense. */
591 if (signerinfos == NULL || signerinfos[0] == NULL)
592 return SECFailure;
593
594 rv = DER_EncodeTimeChoice(NULL, &stime, PR_Now());
595 if (rv != SECSuccess)
596 return rv;
597
598 attr = sec_pkcs7_create_attribute (cinfo->poolp,
599 SEC_OID_PKCS9_SIGNING_TIME,
600 &stime, PR_FALSE);
601 SECITEM_FreeItem (&stime, PR_FALSE);
602
603 if (attr == NULL)
604 return SECFailure;
605
606 rv = SECSuccess;
607 for (si = 0; signerinfos[si] != NULL; si++) {
608 SEC_PKCS7Attribute *oattr;
609
610 oattr = sec_PKCS7FindAttribute (signerinfos[si]->authAttr,
611 SEC_OID_PKCS9_SIGNING_TIME, PR_FALSE);
612 PORT_Assert (oattr == NULL);
613 if (oattr != NULL)
614 continue; /* XXX or would it be better to replace it? */
615
616 rv = sec_pkcs7_add_attribute (cinfo, &(signerinfos[si]->authAttr),
617 attr);
618 if (rv != SECSuccess)
619 break; /* could try to continue, but may as well give up now */
620 }
621
622 return rv;
623 }
624
625
626 /*
627 * Add the specified attribute to the authenticated (i.e. signed) attributes
628 * of "cinfo" -- "oidtag" describes the attribute and "value" is the
629 * value to be associated with it. NOTE! "value" must already be encoded;
630 * no interpretation of "oidtag" is done. Also, it is assumed that this
631 * signedData has only one signer -- if we ever need to add attributes
632 * when there is more than one signature, we need a way to specify *which*
633 * signature should get the attribute.
634 *
635 * XXX Technically, a signed attribute can have multiple values; if/when
636 * we ever need to support an attribute which takes multiple values, we
637 * either need to change this interface or create an AddSignedAttributeValue
638 * which can be called subsequently, and would then append a value.
639 *
640 * "cinfo" should be of type signedData (the only kind of pkcs7 data
641 * that is allowed authenticated attributes); SECFailure will be returned
642 * if it is not.
643 */
644 SECStatus
645 SEC_PKCS7AddSignedAttribute (SEC_PKCS7ContentInfo *cinfo,
646 SECOidTag oidtag,
647 SECItem *value)
648 {
649 SEC_PKCS7SignerInfo **signerinfos;
650 SEC_PKCS7Attribute *attr;
651
652 PORT_Assert (SEC_PKCS7ContentType (cinfo) == SEC_OID_PKCS7_SIGNED_DATA);
653 if (SEC_PKCS7ContentType (cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
654 return SECFailure;
655
656 signerinfos = cinfo->content.signedData->signerInfos;
657
658 /*
659 * No signature or more than one means no deal.
660 */
661 if (signerinfos == NULL || signerinfos[0] == NULL || signerinfos[1] != NULL)
662 return SECFailure;
663
664 attr = sec_pkcs7_create_attribute (cinfo->poolp, oidtag, value, PR_TRUE);
665 if (attr == NULL)
666 return SECFailure;
667
668 return sec_pkcs7_add_attribute (cinfo, &(signerinfos[0]->authAttr), attr);
669 }
670
671
672 /*
673 * Mark that the signer certificates and their issuing chain should
674 * be included in the encoded data. This is expected to be used
675 * in outgoing signed messages for email (S/MIME).
676 *
677 * "certdb" is the cert database to use for finding the chain.
678 * It can be NULL, meaning use the default database.
679 *
680 * "cinfo" should be of type signedData or signedAndEnvelopedData;
681 * SECFailure will be returned if it is not.
682 */
683 SECStatus
684 SEC_PKCS7IncludeCertChain (SEC_PKCS7ContentInfo *cinfo,
685 CERTCertDBHandle *certdb)
686 {
687 SECOidTag kind;
688 SEC_PKCS7SignerInfo *signerinfo, **signerinfos;
689
690 kind = SEC_PKCS7ContentType (cinfo);
691 switch (kind) {
692 case SEC_OID_PKCS7_SIGNED_DATA:
693 signerinfos = cinfo->content.signedData->signerInfos;
694 break;
695 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
696 signerinfos = cinfo->content.signedAndEnvelopedData->signerInfos;
697 break;
698 default:
699 return SECFailure; /* XXX set an error? */
700 }
701
702 if (signerinfos == NULL) /* no signer, no certs? */
703 return SECFailure; /* XXX set an error? */
704
705 if (certdb == NULL) {
706 certdb = CERT_GetDefaultCertDB();
707 if (certdb == NULL) {
708 PORT_SetError (SEC_ERROR_BAD_DATABASE);
709 return SECFailure;
710 }
711 }
712
713 /* XXX Should it be an error if we find no signerinfo or no certs? */
714 while ((signerinfo = *signerinfos++) != NULL) {
715 if (signerinfo->cert != NULL)
716 /* get the cert chain. don't send the root to avoid contamination
717 * of old clients with a new root that they don't trust
718 */
719 signerinfo->certList = CERT_CertChainFromCert (signerinfo->cert,
720 certUsageEmailSigner,
721 PR_FALSE);
722 }
723
724 return SECSuccess;
725 }
726
727
728 /*
729 * Helper function to add a certificate chain for inclusion in the
730 * bag of certificates in a signedData.
731 */
732 static SECStatus
733 sec_pkcs7_add_cert_chain (SEC_PKCS7ContentInfo *cinfo,
734 CERTCertificate *cert,
735 CERTCertDBHandle *certdb)
736 {
737 SECOidTag kind;
738 CERTCertificateList *certlist, **certlists, ***certlistsp;
739 int count;
740
741 kind = SEC_PKCS7ContentType (cinfo);
742 switch (kind) {
743 case SEC_OID_PKCS7_SIGNED_DATA:
744 {
745 SEC_PKCS7SignedData *sdp;
746
747 sdp = cinfo->content.signedData;
748 certlistsp = &(sdp->certLists);
749 }
750 break;
751 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
752 {
753 SEC_PKCS7SignedAndEnvelopedData *saedp;
754
755 saedp = cinfo->content.signedAndEnvelopedData;
756 certlistsp = &(saedp->certLists);
757 }
758 break;
759 default:
760 return SECFailure; /* XXX set an error? */
761 }
762
763 if (certdb == NULL) {
764 certdb = CERT_GetDefaultCertDB();
765 if (certdb == NULL) {
766 PORT_SetError (SEC_ERROR_BAD_DATABASE);
767 return SECFailure;
768 }
769 }
770
771 certlist = CERT_CertChainFromCert (cert, certUsageEmailSigner, PR_FALSE);
772 if (certlist == NULL)
773 return SECFailure;
774
775 certlists = *certlistsp;
776 if (certlists == NULL) {
777 count = 0;
778 certlists = (CERTCertificateList**)PORT_ArenaAlloc (cinfo->poolp,
779 2 * sizeof(CERTCertificateList *));
780 } else {
781 for (count = 0; certlists[count] != NULL; count++)
782 ;
783 PORT_Assert (count); /* should be at least one already */
784 certlists = (CERTCertificateList**)PORT_ArenaGrow (cinfo->poolp,
785 certlists,
786 (count + 1) * sizeof(CERTCertificateList *),
787 (count + 2) * sizeof(CERTCertificateList *));
788 }
789
790 if (certlists == NULL) {
791 CERT_DestroyCertificateList (certlist);
792 return SECFailure;
793 }
794
795 certlists[count] = certlist;
796 certlists[count + 1] = NULL;
797
798 *certlistsp = certlists;
799
800 return SECSuccess;
801 }
802
803
804 /*
805 * Helper function to add a certificate for inclusion in the bag of
806 * certificates in a signedData.
807 */
808 static SECStatus
809 sec_pkcs7_add_certificate (SEC_PKCS7ContentInfo *cinfo,
810 CERTCertificate *cert)
811 {
812 SECOidTag kind;
813 CERTCertificate **certs, ***certsp;
814 int count;
815
816 kind = SEC_PKCS7ContentType (cinfo);
817 switch (kind) {
818 case SEC_OID_PKCS7_SIGNED_DATA:
819 {
820 SEC_PKCS7SignedData *sdp;
821
822 sdp = cinfo->content.signedData;
823 certsp = &(sdp->certs);
824 }
825 break;
826 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
827 {
828 SEC_PKCS7SignedAndEnvelopedData *saedp;
829
830 saedp = cinfo->content.signedAndEnvelopedData;
831 certsp = &(saedp->certs);
832 }
833 break;
834 default:
835 return SECFailure; /* XXX set an error? */
836 }
837
838 cert = CERT_DupCertificate (cert);
839 if (cert == NULL)
840 return SECFailure;
841
842 certs = *certsp;
843 if (certs == NULL) {
844 count = 0;
845 certs = (CERTCertificate**)PORT_ArenaAlloc (cinfo->poolp,
846 2 * sizeof(CERTCertificate *));
847 } else {
848 for (count = 0; certs[count] != NULL; count++)
849 ;
850 PORT_Assert (count); /* should be at least one already */
851 certs = (CERTCertificate**)PORT_ArenaGrow (cinfo->poolp, certs,
852 (count + 1) * sizeof(CERTCertificate *),
853 (count + 2) * sizeof(CERTCertificate *));
854 }
855
856 if (certs == NULL) {
857 CERT_DestroyCertificate (cert);
858 return SECFailure;
859 }
860
861 certs[count] = cert;
862 certs[count + 1] = NULL;
863
864 *certsp = certs;
865
866 return SECSuccess;
867 }
868
869
870 /*
871 * Create a PKCS7 certs-only container.
872 *
873 * "cert" is the (first) cert that will be included.
874 *
875 * "include_chain" specifies whether the entire chain for "cert" should
876 * be included.
877 *
878 * "certdb" is the cert database to use for finding the chain.
879 * It can be NULL in when "include_chain" is false, or when meaning
880 * use the default database.
881 *
882 * More certs and chains can be added via AddCertificate and AddCertChain.
883 *
884 * An error results in a return value of NULL and an error set.
885 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
886 */
887 SEC_PKCS7ContentInfo *
888 SEC_PKCS7CreateCertsOnly (CERTCertificate *cert,
889 PRBool include_chain,
890 CERTCertDBHandle *certdb)
891 {
892 SEC_PKCS7ContentInfo *cinfo;
893 SECStatus rv;
894
895 cinfo = sec_pkcs7_create_signed_data (NULL, NULL);
896 if (cinfo == NULL)
897 return NULL;
898
899 if (include_chain)
900 rv = sec_pkcs7_add_cert_chain (cinfo, cert, certdb);
901 else
902 rv = sec_pkcs7_add_certificate (cinfo, cert);
903
904 if (rv != SECSuccess) {
905 SEC_PKCS7DestroyContentInfo (cinfo);
906 return NULL;
907 }
908
909 return cinfo;
910 }
911
912
913 /*
914 * Add "cert" and its entire chain to the set of certs included in "cinfo".
915 *
916 * "certdb" is the cert database to use for finding the chain.
917 * It can be NULL, meaning use the default database.
918 *
919 * "cinfo" should be of type signedData or signedAndEnvelopedData;
920 * SECFailure will be returned if it is not.
921 */
922 SECStatus
923 SEC_PKCS7AddCertChain (SEC_PKCS7ContentInfo *cinfo,
924 CERTCertificate *cert,
925 CERTCertDBHandle *certdb)
926 {
927 SECOidTag kind;
928
929 kind = SEC_PKCS7ContentType (cinfo);
930 if (kind != SEC_OID_PKCS7_SIGNED_DATA
931 && kind != SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA)
932 return SECFailure; /* XXX set an error? */
933
934 return sec_pkcs7_add_cert_chain (cinfo, cert, certdb);
935 }
936
937
938 /*
939 * Add "cert" to the set of certs included in "cinfo".
940 *
941 * "cinfo" should be of type signedData or signedAndEnvelopedData;
942 * SECFailure will be returned if it is not.
943 */
944 SECStatus
945 SEC_PKCS7AddCertificate (SEC_PKCS7ContentInfo *cinfo, CERTCertificate *cert)
946 {
947 SECOidTag kind;
948
949 kind = SEC_PKCS7ContentType (cinfo);
950 if (kind != SEC_OID_PKCS7_SIGNED_DATA
951 && kind != SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA)
952 return SECFailure; /* XXX set an error? */
953
954 return sec_pkcs7_add_certificate (cinfo, cert);
955 }
956
957
958 static SECStatus
959 sec_pkcs7_init_encrypted_content_info (SEC_PKCS7EncryptedContentInfo *enccinfo,
960 PRArenaPool *poolp,
961 SECOidTag kind, PRBool detached,
962 SECOidTag encalg, int keysize)
963 {
964 SECStatus rv;
965
966 PORT_Assert (enccinfo != NULL && poolp != NULL);
967 if (enccinfo == NULL || poolp == NULL)
968 return SECFailure;
969
970 /*
971 * XXX Some day we may want to allow for other kinds. That needs
972 * more work and modifications to the creation interface, etc.
973 * For now, allow but notice callers who pass in other kinds.
974 * They are responsible for creating the inner type and encoding,
975 * if it is other than DATA.
976 */
977 PORT_Assert (kind == SEC_OID_PKCS7_DATA);
978
979 enccinfo->contentTypeTag = SECOID_FindOIDByTag (kind);
980 PORT_Assert (enccinfo->contentTypeTag
981 && enccinfo->contentTypeTag->offset == kind);
982
983 rv = SECITEM_CopyItem (poolp, &(enccinfo->contentType),
984 &(enccinfo->contentTypeTag->oid));
985 if (rv != SECSuccess)
986 return rv;
987
988 /* Save keysize and algorithm for later. */
989 enccinfo->keysize = keysize;
990 enccinfo->encalg = encalg;
991
992 return SECSuccess;
993 }
994
995
996 /*
997 * Add a recipient to a PKCS7 thing, verifying their cert first.
998 * Any error returns SECFailure.
999 */
1000 static SECStatus
1001 sec_pkcs7_add_recipient (SEC_PKCS7ContentInfo *cinfo,
1002 CERTCertificate *cert,
1003 SECCertUsage certusage,
1004 CERTCertDBHandle *certdb)
1005 {
1006 SECOidTag kind;
1007 SEC_PKCS7RecipientInfo *recipientinfo, **recipientinfos, ***recipientinfosp;
1008 SECItem *dummy;
1009 void *mark;
1010 int count;
1011
1012 kind = SEC_PKCS7ContentType (cinfo);
1013 switch (kind) {
1014 case SEC_OID_PKCS7_ENVELOPED_DATA:
1015 {
1016 SEC_PKCS7EnvelopedData *edp;
1017
1018 edp = cinfo->content.envelopedData;
1019 recipientinfosp = &(edp->recipientInfos);
1020 }
1021 break;
1022 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1023 {
1024 SEC_PKCS7SignedAndEnvelopedData *saedp;
1025
1026 saedp = cinfo->content.signedAndEnvelopedData;
1027 recipientinfosp = &(saedp->recipientInfos);
1028 }
1029 break;
1030 default:
1031 return SECFailure; /* XXX set an error? */
1032 }
1033
1034 /*
1035 * XXX I think that CERT_VerifyCert should do this if *it* is passed
1036 * a NULL database.
1037 */
1038 if (certdb == NULL) {
1039 certdb = CERT_GetDefaultCertDB();
1040 if (certdb == NULL)
1041 return SECFailure; /* XXX set an error? */
1042 }
1043
1044 if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage, PR_Now(),
1045 cinfo->pwfn_arg, NULL) != SECSuccess)
1046 {
1047 /* XXX Did CERT_VerifyCert set an error? */
1048 return SECFailure;
1049 }
1050
1051 mark = PORT_ArenaMark (cinfo->poolp);
1052
1053 recipientinfo = (SEC_PKCS7RecipientInfo*)PORT_ArenaZAlloc (cinfo->poolp,
1054 sizeof(SEC_PKCS7RecipientInfo));
1055 if (recipientinfo == NULL) {
1056 PORT_ArenaRelease (cinfo->poolp, mark);
1057 return SECFailure;
1058 }
1059
1060 dummy = SEC_ASN1EncodeInteger (cinfo->poolp, &recipientinfo->version,
1061 SEC_PKCS7_RECIPIENT_INFO_VERSION);
1062 if (dummy == NULL) {
1063 PORT_ArenaRelease (cinfo->poolp, mark);
1064 return SECFailure;
1065 }
1066 PORT_Assert (dummy == &recipientinfo->version);
1067
1068 recipientinfo->cert = CERT_DupCertificate (cert);
1069 if (recipientinfo->cert == NULL) {
1070 PORT_ArenaRelease (cinfo->poolp, mark);
1071 return SECFailure;
1072 }
1073
1074 recipientinfo->issuerAndSN = CERT_GetCertIssuerAndSN (cinfo->poolp, cert);
1075 if (recipientinfo->issuerAndSN == NULL) {
1076 PORT_ArenaRelease (cinfo->poolp, mark);
1077 return SECFailure;
1078 }
1079
1080 /*
1081 * Okay, now recipientinfo is all set. We just need to put it into
1082 * the main structure.
1083 *
1084 * If this is the first recipient, allocate a new recipientinfos array;
1085 * otherwise, reallocate the array, making room for the new entry.
1086 */
1087 recipientinfos = *recipientinfosp;
1088 if (recipientinfos == NULL) {
1089 count = 0;
1090 recipientinfos = (SEC_PKCS7RecipientInfo **)PORT_ArenaAlloc (
1091 cinfo->poolp,
1092 2 * sizeof(SEC_PKCS7RecipientInfo *));
1093 } else {
1094 for (count = 0; recipientinfos[count] != NULL; count++)
1095 ;
1096 PORT_Assert (count); /* should be at least one already */
1097 recipientinfos = (SEC_PKCS7RecipientInfo **)PORT_ArenaGrow (
1098 cinfo->poolp, recipientinfos,
1099 (count + 1) * sizeof(SEC_PKCS7RecipientInfo *),
1100 (count + 2) * sizeof(SEC_PKCS7RecipientInfo *));
1101 }
1102
1103 if (recipientinfos == NULL) {
1104 PORT_ArenaRelease (cinfo->poolp, mark);
1105 return SECFailure;
1106 }
1107
1108 recipientinfos[count] = recipientinfo;
1109 recipientinfos[count + 1] = NULL;
1110
1111 *recipientinfosp = recipientinfos;
1112
1113 PORT_ArenaUnmark (cinfo->poolp, mark);
1114 return SECSuccess;
1115 }
1116
1117
1118 /*
1119 * Start a PKCS7 enveloping context.
1120 *
1121 * "cert" is the cert for the recipient. It will be checked for validity.
1122 *
1123 * "certusage" describes the encryption usage (e.g. certUsageEmailRecipient)
1124 * XXX Maybe SECCertUsage should be split so that our caller just says
1125 * "email" and *we* add the "recipient" part -- otherwise our caller
1126 * could be lying about the usage; we do not want to allow encryption
1127 * certs for signing or vice versa.
1128 *
1129 * "certdb" is the cert database to use for verifying the cert.
1130 * It can be NULL if a default database is available (like in the client).
1131 *
1132 * "encalg" specifies the bulk encryption algorithm to use (e.g. SEC_OID_RC2).
1133 *
1134 * "keysize" specifies the bulk encryption key size, in bits.
1135 *
1136 * The return value can be passed to functions which add things to
1137 * it like more recipients, then eventually to SEC_PKCS7Encode() or to
1138 * SEC_PKCS7EncoderStart() to create the encoded data, and finally to
1139 * SEC_PKCS7DestroyContentInfo().
1140 *
1141 * An error results in a return value of NULL and an error set.
1142 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
1143 */
1144 extern SEC_PKCS7ContentInfo *
1145 SEC_PKCS7CreateEnvelopedData (CERTCertificate *cert,
1146 SECCertUsage certusage,
1147 CERTCertDBHandle *certdb,
1148 SECOidTag encalg,
1149 int keysize,
1150 SECKEYGetPasswordKey pwfn, void *pwfn_arg)
1151 {
1152 SEC_PKCS7ContentInfo *cinfo;
1153 SEC_PKCS7EnvelopedData *envd;
1154 SECStatus rv;
1155
1156 cinfo = sec_pkcs7_create_content_info (SEC_OID_PKCS7_ENVELOPED_DATA,
1157 PR_FALSE, pwfn, pwfn_arg);
1158 if (cinfo == NULL)
1159 return NULL;
1160
1161 rv = sec_pkcs7_add_recipient (cinfo, cert, certusage, certdb);
1162 if (rv != SECSuccess) {
1163 SEC_PKCS7DestroyContentInfo (cinfo);
1164 return NULL;
1165 }
1166
1167 envd = cinfo->content.envelopedData;
1168 PORT_Assert (envd != NULL);
1169
1170 /*
1171 * XXX Might we want to allow content types other than data?
1172 * If so, via what interface?
1173 */
1174 rv = sec_pkcs7_init_encrypted_content_info (&(envd->encContentInfo),
1175 cinfo->poolp,
1176 SEC_OID_PKCS7_DATA, PR_FALSE,
1177 encalg, keysize);
1178 if (rv != SECSuccess) {
1179 SEC_PKCS7DestroyContentInfo (cinfo);
1180 return NULL;
1181 }
1182
1183 /* XXX Anything more to do here? */
1184
1185 return cinfo;
1186 }
1187
1188
1189 /*
1190 * Add another recipient to an encrypted message.
1191 *
1192 * "cinfo" should be of type envelopedData or signedAndEnvelopedData;
1193 * SECFailure will be returned if it is not.
1194 *
1195 * "cert" is the cert for the recipient. It will be checked for validity.
1196 *
1197 * "certusage" describes the encryption usage (e.g. certUsageEmailRecipient)
1198 * XXX Maybe SECCertUsage should be split so that our caller just says
1199 * "email" and *we* add the "recipient" part -- otherwise our caller
1200 * could be lying about the usage; we do not want to allow encryption
1201 * certs for signing or vice versa.
1202 *
1203 * "certdb" is the cert database to use for verifying the cert.
1204 * It can be NULL if a default database is available (like in the client).
1205 */
1206 SECStatus
1207 SEC_PKCS7AddRecipient (SEC_PKCS7ContentInfo *cinfo,
1208 CERTCertificate *cert,
1209 SECCertUsage certusage,
1210 CERTCertDBHandle *certdb)
1211 {
1212 return sec_pkcs7_add_recipient (cinfo, cert, certusage, certdb);
1213 }
1214
1215
1216 /*
1217 * Create an empty PKCS7 data content info.
1218 *
1219 * An error results in a return value of NULL and an error set.
1220 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
1221 */
1222 SEC_PKCS7ContentInfo *
1223 SEC_PKCS7CreateData (void)
1224 {
1225 return sec_pkcs7_create_content_info (SEC_OID_PKCS7_DATA, PR_FALSE,
1226 NULL, NULL);
1227 }
1228
1229
1230 /*
1231 * Create an empty PKCS7 encrypted content info.
1232 *
1233 * "algorithm" specifies the bulk encryption algorithm to use.
1234 *
1235 * An error results in a return value of NULL and an error set.
1236 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
1237 */
1238 SEC_PKCS7ContentInfo *
1239 SEC_PKCS7CreateEncryptedData (SECOidTag algorithm, int keysize,
1240 SECKEYGetPasswordKey pwfn, void *pwfn_arg)
1241 {
1242 SEC_PKCS7ContentInfo *cinfo;
1243 SECAlgorithmID *algid;
1244 SEC_PKCS7EncryptedData *enc_data;
1245 SECStatus rv;
1246
1247 cinfo = sec_pkcs7_create_content_info (SEC_OID_PKCS7_ENCRYPTED_DATA,
1248 PR_FALSE, pwfn, pwfn_arg);
1249 if (cinfo == NULL)
1250 return NULL;
1251
1252 enc_data = cinfo->content.encryptedData;
1253 algid = &(enc_data->encContentInfo.contentEncAlg);
1254
1255 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm)) {
1256 rv = SECOID_SetAlgorithmID (cinfo->poolp, algid, algorithm, NULL);
1257 } else {
1258 /* Assume password-based-encryption.
1259 * Note: we can't generate pkcs5v2 from this interface.
1260 * PK11_CreateBPEAlgorithmID generates pkcs5v2 by accepting
1261 * non-PBE oids and assuming that they are pkcs5v2 oids, but
1262 * NSS_CMSEncryptedData_Create accepts non-PBE oids as regular
1263 * CMS encrypted data, so we can't tell SEC_PKCS7CreateEncryptedtedData
1264 * to create pkcs5v2 PBEs */
1265 SECAlgorithmID *pbe_algid;
1266 pbe_algid = PK11_CreatePBEAlgorithmID(algorithm,
1267 NSS_PBE_DEFAULT_ITERATION_COUNT,
1268 NULL);
1269 if (pbe_algid == NULL) {
1270 rv = SECFailure;
1271 } else {
1272 rv = SECOID_CopyAlgorithmID (cinfo->poolp, algid, pbe_algid);
1273 SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE);
1274 }
1275 }
1276
1277 if (rv != SECSuccess) {
1278 SEC_PKCS7DestroyContentInfo (cinfo);
1279 return NULL;
1280 }
1281
1282 rv = sec_pkcs7_init_encrypted_content_info (&(enc_data->encContentInfo),
1283 cinfo->poolp,
1284 SEC_OID_PKCS7_DATA, PR_FALSE,
1285 algorithm, keysize);
1286 if (rv != SECSuccess) {
1287 SEC_PKCS7DestroyContentInfo (cinfo);
1288 return NULL;
1289 }
1290
1291 return cinfo;
1292 }
1293
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/pkcs7/p7common.c ('k') | mozilla/security/nss/lib/pkcs7/p7decode.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698