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

Side by Side Diff: nss/lib/pkcs7/p7common.c

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

Powered by Google App Engine
This is Rietveld 408576698