OLD | NEW |
| (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 | |
OLD | NEW |