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

Side by Side Diff: mozilla/security/nss/lib/pkcs7/p7common.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/certread.c ('k') | mozilla/security/nss/lib/pkcs7/p7create.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 implementation -- the exported parts that are used whether
7 * creating or decoding.
8 *
9 * $Id: p7common.c,v 1.9 2012/04/25 14:50:06 gerv%gerv.net Exp $
10 */
11
12 #include "p7local.h"
13
14 #include "cert.h"
15 #include "secitem.h"
16 #include "secoid.h"
17 #include "pk11func.h"
18
19 /*
20 * Find out (saving pointer to lookup result for future reference)
21 * and return the inner content type.
22 */
23 SECOidTag
24 SEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo)
25 {
26 if (cinfo->contentTypeTag == NULL)
27 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
28
29 if (cinfo->contentTypeTag == NULL)
30 return SEC_OID_UNKNOWN;
31
32 return cinfo->contentTypeTag->offset;
33 }
34
35
36 /*
37 * Destroy a PKCS7 contentInfo and all of its sub-pieces.
38 */
39 void
40 SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo)
41 {
42 SECOidTag kind;
43 CERTCertificate **certs;
44 CERTCertificateList **certlists;
45 SEC_PKCS7SignerInfo **signerinfos;
46 SEC_PKCS7RecipientInfo **recipientinfos;
47
48 PORT_Assert (cinfo->refCount > 0);
49 if (cinfo->refCount <= 0)
50 return;
51
52 cinfo->refCount--;
53 if (cinfo->refCount > 0)
54 return;
55
56 certs = NULL;
57 certlists = NULL;
58 recipientinfos = NULL;
59 signerinfos = NULL;
60
61 kind = SEC_PKCS7ContentType (cinfo);
62 switch (kind) {
63 case SEC_OID_PKCS7_ENVELOPED_DATA:
64 {
65 SEC_PKCS7EnvelopedData *edp;
66
67 edp = cinfo->content.envelopedData;
68 if (edp != NULL) {
69 recipientinfos = edp->recipientInfos;
70 }
71 }
72 break;
73 case SEC_OID_PKCS7_SIGNED_DATA:
74 {
75 SEC_PKCS7SignedData *sdp;
76
77 sdp = cinfo->content.signedData;
78 if (sdp != NULL) {
79 certs = sdp->certs;
80 certlists = sdp->certLists;
81 signerinfos = sdp->signerInfos;
82 }
83 }
84 break;
85 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
86 {
87 SEC_PKCS7SignedAndEnvelopedData *saedp;
88
89 saedp = cinfo->content.signedAndEnvelopedData;
90 if (saedp != NULL) {
91 certs = saedp->certs;
92 certlists = saedp->certLists;
93 recipientinfos = saedp->recipientInfos;
94 signerinfos = saedp->signerInfos;
95 if (saedp->sigKey != NULL)
96 PK11_FreeSymKey (saedp->sigKey);
97 }
98 }
99 break;
100 default:
101 /* XXX Anything else that needs to be "manually" freed/destroyed? */
102 break;
103 }
104
105 if (certs != NULL) {
106 CERTCertificate *cert;
107
108 while ((cert = *certs++) != NULL) {
109 CERT_DestroyCertificate (cert);
110 }
111 }
112
113 if (certlists != NULL) {
114 CERTCertificateList *certlist;
115
116 while ((certlist = *certlists++) != NULL) {
117 CERT_DestroyCertificateList (certlist);
118 }
119 }
120
121 if (recipientinfos != NULL) {
122 SEC_PKCS7RecipientInfo *ri;
123
124 while ((ri = *recipientinfos++) != NULL) {
125 if (ri->cert != NULL)
126 CERT_DestroyCertificate (ri->cert);
127 }
128 }
129
130 if (signerinfos != NULL) {
131 SEC_PKCS7SignerInfo *si;
132
133 while ((si = *signerinfos++) != NULL) {
134 if (si->cert != NULL)
135 CERT_DestroyCertificate (si->cert);
136 if (si->certList != NULL)
137 CERT_DestroyCertificateList (si->certList);
138 }
139 }
140
141 if (cinfo->poolp != NULL) {
142 PORT_FreeArena (cinfo->poolp, PR_FALSE); /* XXX clear it? */
143 }
144 }
145
146
147 /*
148 * Return a copy of the given contentInfo. The copy may be virtual
149 * or may be real -- either way, the result needs to be passed to
150 * SEC_PKCS7DestroyContentInfo later (as does the original).
151 */
152 SEC_PKCS7ContentInfo *
153 SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo)
154 {
155 if (cinfo == NULL)
156 return NULL;
157
158 PORT_Assert (cinfo->refCount > 0);
159
160 if (cinfo->created) {
161 /*
162 * Want to do a real copy of these; otherwise subsequent
163 * changes made to either copy are likely to be a surprise.
164 * XXX I suspect that this will not actually be called for yet,
165 * which is why the assert, so to notice if it is...
166 */
167 PORT_Assert (0);
168 /*
169 * XXX Create a new pool here, and copy everything from
170 * within. For cert stuff, need to call the appropriate
171 * copy functions, etc.
172 */
173 }
174
175 cinfo->refCount++;
176 return cinfo;
177 }
178
179
180 /*
181 * Return a pointer to the actual content. In the case of those types
182 * which are encrypted, this returns the *plain* content.
183 * XXX Needs revisiting if/when we handle nested encrypted types.
184 */
185 SECItem *
186 SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo)
187 {
188 SECOidTag kind;
189
190 kind = SEC_PKCS7ContentType (cinfo);
191 switch (kind) {
192 case SEC_OID_PKCS7_DATA:
193 return cinfo->content.data;
194 case SEC_OID_PKCS7_DIGESTED_DATA:
195 {
196 SEC_PKCS7DigestedData *digd;
197
198 digd = cinfo->content.digestedData;
199 if (digd == NULL)
200 break;
201 return SEC_PKCS7GetContent (&(digd->contentInfo));
202 }
203 case SEC_OID_PKCS7_ENCRYPTED_DATA:
204 {
205 SEC_PKCS7EncryptedData *encd;
206
207 encd = cinfo->content.encryptedData;
208 if (encd == NULL)
209 break;
210 return &(encd->encContentInfo.plainContent);
211 }
212 case SEC_OID_PKCS7_ENVELOPED_DATA:
213 {
214 SEC_PKCS7EnvelopedData *envd;
215
216 envd = cinfo->content.envelopedData;
217 if (envd == NULL)
218 break;
219 return &(envd->encContentInfo.plainContent);
220 }
221 case SEC_OID_PKCS7_SIGNED_DATA:
222 {
223 SEC_PKCS7SignedData *sigd;
224
225 sigd = cinfo->content.signedData;
226 if (sigd == NULL)
227 break;
228 return SEC_PKCS7GetContent (&(sigd->contentInfo));
229 }
230 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
231 {
232 SEC_PKCS7SignedAndEnvelopedData *saed;
233
234 saed = cinfo->content.signedAndEnvelopedData;
235 if (saed == NULL)
236 break;
237 return &(saed->encContentInfo.plainContent);
238 }
239 default:
240 PORT_Assert(0);
241 break;
242 }
243
244 return NULL;
245 }
246
247
248 /*
249 * XXX Fix the placement and formatting of the
250 * following routines (i.e. make them consistent with the rest of
251 * the pkcs7 code -- I think some/many belong in other files and
252 * they all need a formatting/style rehaul)
253 */
254
255 /* retrieve the algorithm identifier for encrypted data.
256 * the identifier returned is a copy of the algorithm identifier
257 * in the content info and needs to be freed after being used.
258 *
259 * cinfo is the content info for which to retrieve the
260 * encryption algorithm.
261 *
262 * if the content info is not encrypted data or an error
263 * occurs NULL is returned.
264 */
265 SECAlgorithmID *
266 SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo)
267 {
268 SECAlgorithmID *alg = 0;
269 switch (SEC_PKCS7ContentType(cinfo))
270 {
271 case SEC_OID_PKCS7_ENCRYPTED_DATA:
272 alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg;
273 break;
274 case SEC_OID_PKCS7_ENVELOPED_DATA:
275 alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg;
276 break;
277 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
278 alg = &cinfo->content.signedAndEnvelopedData
279 ->encContentInfo.contentEncAlg;
280 break;
281 default:
282 alg = 0;
283 break;
284 }
285
286 return alg;
287 }
288
289 /* set the content of the content info. For data content infos,
290 * the data is set. For encrytped content infos, the plainContent
291 * is set, and is expected to be encrypted later.
292 *
293 * cinfo is the content info where the data will be set
294 *
295 * buf is a buffer of the data to set
296 *
297 * len is the length of the data being set.
298 *
299 * in the event of an error, SECFailure is returned. SECSuccess
300 * indicates the content was successfully set.
301 */
302 SECStatus
303 SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo,
304 const char *buf,
305 unsigned long len)
306 {
307 SECOidTag cinfo_type;
308 SECStatus rv;
309 SECItem content;
310 SECOidData *contentTypeTag = NULL;
311
312 content.type = siBuffer;
313 content.data = (unsigned char *)buf;
314 content.len = len;
315
316 cinfo_type = SEC_PKCS7ContentType(cinfo);
317
318 /* set inner content */
319 switch(cinfo_type)
320 {
321 case SEC_OID_PKCS7_SIGNED_DATA:
322 if(content.len > 0) {
323 /* we "leak" the old content here, but as it's all in the pool * /
324 /* it does not really matter */
325
326 /* create content item if necessary */
327 if (cinfo->content.signedData->contentInfo.content.data == NULL)
328 cinfo->content.signedData->contentInfo.content.data = SECITE M_AllocItem(cinfo->poolp, NULL, 0);
329 rv = SECITEM_CopyItem(cinfo->poolp,
330 cinfo->content.signedData->contentInfo.content.data,
331 &content);
332 } else {
333 cinfo->content.signedData->contentInfo.content.data->data = NULL ;
334 cinfo->content.signedData->contentInfo.content.data->len = 0;
335 rv = SECSuccess;
336 }
337 if(rv == SECFailure)
338 goto loser;
339
340 break;
341 case SEC_OID_PKCS7_ENCRYPTED_DATA:
342 /* XXX this forces the inner content type to be "data" */
343 /* do we really want to override without asking or reason? */
344 contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA);
345 if(contentTypeTag == NULL)
346 goto loser;
347 rv = SECITEM_CopyItem(cinfo->poolp,
348 &(cinfo->content.encryptedData->encContentInfo.contentType),
349 &(contentTypeTag->oid));
350 if(rv == SECFailure)
351 goto loser;
352 if(content.len > 0) {
353 rv = SECITEM_CopyItem(cinfo->poolp,
354 &(cinfo->content.encryptedData->encContentInfo.plainCont ent),
355 &content);
356 } else {
357 cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL;
358 cinfo->content.encryptedData->encContentInfo.encContent.data = N ULL;
359 cinfo->content.encryptedData->encContentInfo.plainContent.len = 0;
360 cinfo->content.encryptedData->encContentInfo.encContent.len = 0;
361 rv = SECSuccess;
362 }
363 if(rv == SECFailure)
364 goto loser;
365 break;
366 case SEC_OID_PKCS7_DATA:
367 cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp,
368 sizeof(SECItem));
369 if(cinfo->content.data == NULL)
370 goto loser;
371 if(content.len > 0) {
372 rv = SECITEM_CopyItem(cinfo->poolp,
373 cinfo->content.data, &content);
374 } else {
375 /* handle case with NULL content */
376 rv = SECSuccess;
377 }
378 if(rv == SECFailure)
379 goto loser;
380 break;
381 default:
382 goto loser;
383 }
384
385 return SECSuccess;
386
387 loser:
388
389 return SECFailure;
390 }
391
392 /* the content of an encrypted data content info is encrypted.
393 * it is assumed that for encrypted data, that the data has already
394 * been set and is in the "plainContent" field of the content info.
395 *
396 * cinfo is the content info to encrypt
397 *
398 * key is the key with which to perform the encryption. if the
399 * algorithm is a password based encryption algorithm, the
400 * key is actually a password which will be processed per
401 * PKCS #5.
402 *
403 * in the event of an error, SECFailure is returned. SECSuccess
404 * indicates a success.
405 */
406 SECStatus
407 SEC_PKCS7EncryptContents(PRArenaPool *poolp,
408 SEC_PKCS7ContentInfo *cinfo,
409 SECItem *key,
410 void *wincx)
411 {
412 SECAlgorithmID *algid = NULL;
413 SECItem * result = NULL;
414 SECItem * src;
415 SECItem * dest;
416 SECItem * blocked_data = NULL;
417 void * mark;
418 void * cx;
419 PK11SymKey * eKey = NULL;
420 PK11SlotInfo * slot = NULL;
421
422 CK_MECHANISM_TYPE cryptoMechType;
423 int bs;
424 SECStatus rv = SECFailure;
425 SECItem *c_param = NULL;
426
427 if((cinfo == NULL) || (key == NULL))
428 return SECFailure;
429
430 if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
431 return SECFailure;
432
433 algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
434 if(algid == NULL)
435 return SECFailure;
436
437 if(poolp == NULL)
438 poolp = cinfo->poolp;
439
440 mark = PORT_ArenaMark(poolp);
441
442 src = &cinfo->content.encryptedData->encContentInfo.plainContent;
443 dest = &cinfo->content.encryptedData->encContentInfo.encContent;
444 dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
445 dest->len = (src->len + 64);
446 if(dest->data == NULL) {
447 rv = SECFailure;
448 goto loser;
449 }
450
451 slot = PK11_GetInternalKeySlot();
452 if(slot == NULL) {
453 rv = SECFailure;
454 goto loser;
455 }
456
457 eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
458 if(eKey == NULL) {
459 rv = SECFailure;
460 goto loser;
461 }
462
463 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
464 if (cryptoMechType == CKM_INVALID_MECHANISM) {
465 rv = SECFailure;
466 goto loser;
467 }
468
469 /* block according to PKCS 8 */
470 bs = PK11_GetBlockSize(cryptoMechType, c_param);
471 rv = SECSuccess;
472 if(bs) {
473 char pad_char;
474 pad_char = (char)(bs - (src->len % bs));
475 if(src->len % bs) {
476 rv = SECSuccess;
477 blocked_data = PK11_BlockData(src, bs);
478 if(blocked_data) {
479 PORT_Memset((blocked_data->data + blocked_data->len
480 - (int)pad_char),
481 pad_char, (int)pad_char);
482 } else {
483 rv = SECFailure;
484 goto loser;
485 }
486 } else {
487 blocked_data = SECITEM_DupItem(src);
488 if(blocked_data) {
489 blocked_data->data = (unsigned char*)PORT_Realloc(
490 blocked_data->data,
491 blocked_data->len + bs);
492 if(blocked_data->data) {
493 blocked_data->len += bs;
494 PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
495 } else {
496 rv = SECFailure;
497 goto loser;
498 }
499 } else {
500 rv = SECFailure;
501 goto loser;
502 }
503 }
504 } else {
505 blocked_data = SECITEM_DupItem(src);
506 if(!blocked_data) {
507 rv = SECFailure;
508 goto loser;
509 }
510 }
511
512 cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
513 eKey, c_param);
514 if(cx == NULL) {
515 rv = SECFailure;
516 goto loser;
517 }
518
519 rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len),
520 (int)(src->len + 64), blocked_data->data,
521 (int)blocked_data->len);
522 PK11_DestroyContext((PK11Context*)cx, PR_TRUE);
523
524 loser:
525 /* let success fall through */
526 if(blocked_data != NULL)
527 SECITEM_ZfreeItem(blocked_data, PR_TRUE);
528
529 if(result != NULL)
530 SECITEM_ZfreeItem(result, PR_TRUE);
531
532 if(rv == SECFailure)
533 PORT_ArenaRelease(poolp, mark);
534 else
535 PORT_ArenaUnmark(poolp, mark);
536
537 if(eKey != NULL)
538 PK11_FreeSymKey(eKey);
539
540 if(slot != NULL)
541 PK11_FreeSlot(slot);
542
543 if(c_param != NULL)
544 SECITEM_ZfreeItem(c_param, PR_TRUE);
545
546 return rv;
547 }
548
549 /* the content of an encrypted data content info is decrypted.
550 * it is assumed that for encrypted data, that the data has already
551 * been set and is in the "encContent" field of the content info.
552 *
553 * cinfo is the content info to decrypt
554 *
555 * key is the key with which to perform the decryption. if the
556 * algorithm is a password based encryption algorithm, the
557 * key is actually a password which will be processed per
558 * PKCS #5.
559 *
560 * in the event of an error, SECFailure is returned. SECSuccess
561 * indicates a success.
562 */
563 SECStatus
564 SEC_PKCS7DecryptContents(PRArenaPool *poolp,
565 SEC_PKCS7ContentInfo *cinfo,
566 SECItem *key,
567 void *wincx)
568 {
569 SECAlgorithmID *algid = NULL;
570 SECStatus rv = SECFailure;
571 SECItem *result = NULL, *dest, *src;
572 void *mark;
573
574 PK11SymKey *eKey = NULL;
575 PK11SlotInfo *slot = NULL;
576 CK_MECHANISM_TYPE cryptoMechType;
577 void *cx;
578 SECItem *c_param = NULL;
579 int bs;
580
581 if((cinfo == NULL) || (key == NULL))
582 return SECFailure;
583
584 if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
585 return SECFailure;
586
587 algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
588 if(algid == NULL)
589 return SECFailure;
590
591 if(poolp == NULL)
592 poolp = cinfo->poolp;
593
594 mark = PORT_ArenaMark(poolp);
595
596 src = &cinfo->content.encryptedData->encContentInfo.encContent;
597 dest = &cinfo->content.encryptedData->encContentInfo.plainContent;
598 dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
599 dest->len = (src->len + 64);
600 if(dest->data == NULL) {
601 rv = SECFailure;
602 goto loser;
603 }
604
605 slot = PK11_GetInternalKeySlot();
606 if(slot == NULL) {
607 rv = SECFailure;
608 goto loser;
609 }
610
611 eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
612 if(eKey == NULL) {
613 rv = SECFailure;
614 goto loser;
615 }
616
617 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
618 if (cryptoMechType == CKM_INVALID_MECHANISM) {
619 rv = SECFailure;
620 goto loser;
621 }
622
623 cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
624 eKey, c_param);
625 if(cx == NULL) {
626 rv = SECFailure;
627 goto loser;
628 }
629
630 rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len),
631 (int)(src->len + 64), src->data, (int)src->len);
632 PK11_DestroyContext((PK11Context *)cx, PR_TRUE);
633
634 bs = PK11_GetBlockSize(cryptoMechType, c_param);
635 if(bs) {
636 /* check for proper badding in block algorithms. this assumes
637 * RC2 cbc or a DES cbc variant. and the padding is thus defined
638 */
639 if(((int)dest->data[dest->len-1] <= bs) &&
640 ((int)dest->data[dest->len-1] > 0)) {
641 dest->len -= (int)dest->data[dest->len-1];
642 } else {
643 rv = SECFailure;
644 /* set an error ? */
645 }
646 }
647
648 loser:
649 /* let success fall through */
650 if(result != NULL)
651 SECITEM_ZfreeItem(result, PR_TRUE);
652
653 if(rv == SECFailure)
654 PORT_ArenaRelease(poolp, mark);
655 else
656 PORT_ArenaUnmark(poolp, mark);
657
658 if(eKey != NULL)
659 PK11_FreeSymKey(eKey);
660
661 if(slot != NULL)
662 PK11_FreeSlot(slot);
663
664 if(c_param != NULL)
665 SECITEM_ZfreeItem(c_param, PR_TRUE);
666
667 return rv;
668 }
669
670 SECItem **
671 SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo)
672 {
673 switch(SEC_PKCS7ContentType(cinfo))
674 {
675 case SEC_OID_PKCS7_SIGNED_DATA:
676 return cinfo->content.signedData->rawCerts;
677 break;
678 default:
679 return NULL;
680 break;
681 }
682 }
683
684
685 int
686 SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo)
687 {
688 if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA)
689 return cinfo->content.envelopedData->encContentInfo.keysize;
690 else
691 return 0;
692 }
693
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/pkcs7/certread.c ('k') | mozilla/security/nss/lib/pkcs7/p7create.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698