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

Side by Side Diff: mozilla/security/nss/lib/pkcs7/p7local.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/p7local.h ('k') | mozilla/security/nss/lib/pkcs7/pkcs7t.h » ('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 * Support routines for PKCS7 implementation, none of which are exported.
7 * This file should only contain things that are needed by both the
8 * encoding/creation side *and* the decoding/decryption side. Anything
9 * else should be static routines in the appropriate file.
10 *
11 * $Id: p7local.c,v 1.16 2012/04/25 14:50:06 gerv%gerv.net Exp $
12 */
13
14 #include "p7local.h"
15
16 #include "cryptohi.h"
17 #include "secasn1.h"
18 #include "secoid.h"
19 #include "secitem.h"
20 #include "pk11func.h"
21 #include "secpkcs5.h"
22 #include "secerr.h"
23
24 /*
25 * -------------------------------------------------------------------
26 * Cipher stuff.
27 */
28
29 typedef SECStatus (*sec_pkcs7_cipher_function) (void *,
30 unsigned char *,
31 unsigned *,
32 unsigned int,
33 const unsigned char *,
34 unsigned int);
35 typedef SECStatus (*sec_pkcs7_cipher_destroy) (void *, PRBool);
36
37 #define BLOCK_SIZE 4096
38
39 struct sec_pkcs7_cipher_object {
40 void *cx;
41 sec_pkcs7_cipher_function doit;
42 sec_pkcs7_cipher_destroy destroy;
43 PRBool encrypt;
44 int block_size;
45 int pad_size;
46 int pending_count;
47 unsigned char pending_buf[BLOCK_SIZE];
48 };
49
50 SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
51 SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
52 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
53 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
54 SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
55
56 /*
57 * Create a cipher object to do decryption, based on the given bulk
58 * encryption key and algorithm identifier (which may include an iv).
59 *
60 * XXX This interface, or one similar, would be really nice available
61 * in general... I tried to keep the pkcs7-specific stuff (mostly
62 * having to do with padding) out of here.
63 *
64 * XXX Once both are working, it might be nice to combine this and the
65 * function below (for starting up encryption) into one routine, and just
66 * have two simple cover functions which call it.
67 */
68 sec_PKCS7CipherObject *
69 sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid)
70 {
71 sec_PKCS7CipherObject *result;
72 SECOidTag algtag;
73 void *ciphercx;
74 CK_MECHANISM_TYPE cryptoMechType;
75 PK11SlotInfo *slot;
76 SECItem *param = NULL;
77
78 result = (struct sec_pkcs7_cipher_object*)
79 PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
80 if (result == NULL)
81 return NULL;
82
83 ciphercx = NULL;
84 algtag = SECOID_GetAlgorithmTag (algid);
85
86 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
87 SECItem *pwitem;
88
89 pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
90 if (!pwitem) {
91 PORT_Free(result);
92 return NULL;
93 }
94
95 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
96 if (cryptoMechType == CKM_INVALID_MECHANISM) {
97 PORT_Free(result);
98 SECITEM_FreeItem(param,PR_TRUE);
99 return NULL;
100 }
101 } else {
102 cryptoMechType = PK11_AlgtagToMechanism(algtag);
103 param = PK11_ParamFromAlgid(algid);
104 if (param == NULL) {
105 PORT_Free(result);
106 return NULL;
107 }
108 }
109
110 result->pad_size = PK11_GetBlockSize(cryptoMechType, param);
111 slot = PK11_GetSlotFromKey(key);
112 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
113 PK11_FreeSlot(slot);
114 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
115 key, param);
116 SECITEM_FreeItem(param,PR_TRUE);
117 if (ciphercx == NULL) {
118 PORT_Free (result);
119 return NULL;
120 }
121
122 result->cx = ciphercx;
123 result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp;
124 result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext;
125 result->encrypt = PR_FALSE;
126 result->pending_count = 0;
127
128 return result;
129 }
130
131 /*
132 * Create a cipher object to do encryption, based on the given bulk
133 * encryption key and algorithm tag. Fill in the algorithm identifier
134 * (which may include an iv) appropriately.
135 *
136 * XXX This interface, or one similar, would be really nice available
137 * in general... I tried to keep the pkcs7-specific stuff (mostly
138 * having to do with padding) out of here.
139 *
140 * XXX Once both are working, it might be nice to combine this and the
141 * function above (for starting up decryption) into one routine, and just
142 * have two simple cover functions which call it.
143 */
144 sec_PKCS7CipherObject *
145 sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key,
146 SECOidTag algtag, SECAlgorithmID *algid)
147 {
148 sec_PKCS7CipherObject *result;
149 void *ciphercx;
150 SECStatus rv;
151 CK_MECHANISM_TYPE cryptoMechType;
152 PK11SlotInfo *slot;
153 SECItem *param = NULL;
154 PRBool needToEncodeAlgid = PR_FALSE;
155
156 result = (struct sec_pkcs7_cipher_object*)
157 PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
158 if (result == NULL)
159 return NULL;
160
161 ciphercx = NULL;
162 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
163 SECItem *pwitem;
164
165 pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
166 if (!pwitem) {
167 PORT_Free(result);
168 return NULL;
169 }
170
171 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
172 if (cryptoMechType == CKM_INVALID_MECHANISM) {
173 PORT_Free(result);
174 SECITEM_FreeItem(param,PR_TRUE);
175 return NULL;
176 }
177 } else {
178 cryptoMechType = PK11_AlgtagToMechanism(algtag);
179 param = PK11_GenerateNewParam(cryptoMechType, key);
180 if (param == NULL) {
181 PORT_Free(result);
182 return NULL;
183 }
184 needToEncodeAlgid = PR_TRUE;
185 }
186
187 result->pad_size = PK11_GetBlockSize(cryptoMechType,param);
188 slot = PK11_GetSlotFromKey(key);
189 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
190 PK11_FreeSlot(slot);
191 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
192 key, param);
193 if (ciphercx == NULL) {
194 PORT_Free (result);
195 SECITEM_FreeItem(param,PR_TRUE);
196 return NULL;
197 }
198
199 /*
200 * These are placed after the CreateContextBySymKey() because some
201 * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
202 * Don't move it from here.
203 */
204 if (needToEncodeAlgid) {
205 rv = PK11_ParamToAlgid(algtag,param,poolp,algid);
206 if(rv != SECSuccess) {
207 PORT_Free (result);
208 SECITEM_FreeItem(param,PR_TRUE);
209 return NULL;
210 }
211 }
212 SECITEM_FreeItem(param,PR_TRUE);
213
214 result->cx = ciphercx;
215 result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp;
216 result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext;
217 result->encrypt = PR_TRUE;
218 result->pending_count = 0;
219
220 return result;
221 }
222
223
224 /*
225 * Destroy the cipher object.
226 */
227 static void
228 sec_pkcs7_destroy_cipher (sec_PKCS7CipherObject *obj)
229 {
230 (* obj->destroy) (obj->cx, PR_TRUE);
231 PORT_Free (obj);
232 }
233
234 void
235 sec_PKCS7DestroyDecryptObject (sec_PKCS7CipherObject *obj)
236 {
237 PORT_Assert (obj != NULL);
238 if (obj == NULL)
239 return;
240 PORT_Assert (! obj->encrypt);
241 sec_pkcs7_destroy_cipher (obj);
242 }
243
244 void
245 sec_PKCS7DestroyEncryptObject (sec_PKCS7CipherObject *obj)
246 {
247 PORT_Assert (obj != NULL);
248 if (obj == NULL)
249 return;
250 PORT_Assert (obj->encrypt);
251 sec_pkcs7_destroy_cipher (obj);
252 }
253
254
255 /*
256 * XXX I think all of the following lengths should be longs instead
257 * of ints, but our current crypto interface uses ints, so I did too.
258 */
259
260
261 /*
262 * What will be the output length of the next call to decrypt?
263 * Result can be used to perform memory allocations. Note that the amount
264 * is exactly accurate only when not doing a block cipher or when final
265 * is false, otherwise it is an upper bound on the amount because until
266 * we see the data we do not know how many padding bytes there are
267 * (always between 1 and bsize).
268 *
269 * Note that this can return zero, which does not mean that the decrypt
270 * operation can be skipped! (It simply means that there are not enough
271 * bytes to make up an entire block; the bytes will be reserved until
272 * there are enough to encrypt/decrypt at least one block.) However,
273 * if zero is returned it *does* mean that no output buffer need be
274 * passed in to the subsequent decrypt operation, as no output bytes
275 * will be stored.
276 */
277 unsigned int
278 sec_PKCS7DecryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len,
279 PRBool final)
280 {
281 int blocks, block_size;
282
283 PORT_Assert (! obj->encrypt);
284
285 block_size = obj->block_size;
286
287 /*
288 * If this is not a block cipher, then we always have the same
289 * number of output bytes as we had input bytes.
290 */
291 if (block_size == 0)
292 return input_len;
293
294 /*
295 * On the final call, we will always use up all of the pending
296 * bytes plus all of the input bytes, *but*, there will be padding
297 * at the end and we cannot predict how many bytes of padding we
298 * will end up removing. The amount given here is actually known
299 * to be at least 1 byte too long (because we know we will have
300 * at least 1 byte of padding), but seemed clearer/better to me.
301 */
302 if (final)
303 return obj->pending_count + input_len;
304
305 /*
306 * Okay, this amount is exactly what we will output on the
307 * next cipher operation. We will always hang onto the last
308 * 1 - block_size bytes for non-final operations. That is,
309 * we will do as many complete blocks as we can *except* the
310 * last block (complete or partial). (This is because until
311 * we know we are at the end, we cannot know when to interpret
312 * and removing the padding byte(s), which are guaranteed to
313 * be there.)
314 */
315 blocks = (obj->pending_count + input_len - 1) / block_size;
316 return blocks * block_size;
317 }
318
319 /*
320 * What will be the output length of the next call to encrypt?
321 * Result can be used to perform memory allocations.
322 *
323 * Note that this can return zero, which does not mean that the encrypt
324 * operation can be skipped! (It simply means that there are not enough
325 * bytes to make up an entire block; the bytes will be reserved until
326 * there are enough to encrypt/decrypt at least one block.) However,
327 * if zero is returned it *does* mean that no output buffer need be
328 * passed in to the subsequent encrypt operation, as no output bytes
329 * will be stored.
330 */
331 unsigned int
332 sec_PKCS7EncryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len,
333 PRBool final)
334 {
335 int blocks, block_size;
336 int pad_size;
337
338 PORT_Assert (obj->encrypt);
339
340 block_size = obj->block_size;
341 pad_size = obj->pad_size;
342
343 /*
344 * If this is not a block cipher, then we always have the same
345 * number of output bytes as we had input bytes.
346 */
347 if (block_size == 0)
348 return input_len;
349
350 /*
351 * On the final call, we only send out what we need for
352 * remaining bytes plus the padding. (There is always padding,
353 * so even if we have an exact number of blocks as input, we
354 * will add another full block that is just padding.)
355 */
356 if (final) {
357 if (pad_size == 0) {
358 return obj->pending_count + input_len;
359 } else {
360 blocks = (obj->pending_count + input_len) / pad_size;
361 blocks++;
362 return blocks*pad_size;
363 }
364 }
365
366 /*
367 * Now, count the number of complete blocks of data we have.
368 */
369 blocks = (obj->pending_count + input_len) / block_size;
370
371
372 return blocks * block_size;
373 }
374
375
376 /*
377 * Decrypt a given length of input buffer (starting at "input" and
378 * containing "input_len" bytes), placing the decrypted bytes in
379 * "output" and storing the output length in "*output_len_p".
380 * "obj" is the return value from sec_PKCS7CreateDecryptObject.
381 * When "final" is true, this is the last of the data to be decrypted.
382 *
383 * This is much more complicated than it sounds when the cipher is
384 * a block-type, meaning that the decryption function will only
385 * operate on whole blocks. But our caller is operating stream-wise,
386 * and can pass in any number of bytes. So we need to keep track
387 * of block boundaries. We save excess bytes between calls in "obj".
388 * We also need to determine which bytes are padding, and remove
389 * them from the output. We can only do this step when we know we
390 * have the final block of data. PKCS #7 specifies that the padding
391 * used for a block cipher is a string of bytes, each of whose value is
392 * the same as the length of the padding, and that all data is padded.
393 * (Even data that starts out with an exact multiple of blocks gets
394 * added to it another block, all of which is padding.)
395 */
396 SECStatus
397 sec_PKCS7Decrypt (sec_PKCS7CipherObject *obj, unsigned char *output,
398 unsigned int *output_len_p, unsigned int max_output_len,
399 const unsigned char *input, unsigned int input_len,
400 PRBool final)
401 {
402 int blocks, bsize, pcount, padsize;
403 unsigned int max_needed, ifraglen, ofraglen, output_len;
404 unsigned char *pbuf;
405 SECStatus rv;
406
407 PORT_Assert (! obj->encrypt);
408
409 /*
410 * Check that we have enough room for the output. Our caller should
411 * already handle this; failure is really an internal error (i.e. bug).
412 */
413 max_needed = sec_PKCS7DecryptLength (obj, input_len, final);
414 PORT_Assert (max_output_len >= max_needed);
415 if (max_output_len < max_needed) {
416 /* PORT_SetError (XXX); */
417 return SECFailure;
418 }
419
420 /*
421 * hardware encryption does not like small decryption sizes here, so we
422 * allow both blocking and padding.
423 */
424 bsize = obj->block_size;
425 padsize = obj->pad_size;
426
427 /*
428 * When no blocking or padding work to do, we can simply call the
429 * cipher function and we are done.
430 */
431 if (bsize == 0) {
432 return (* obj->doit) (obj->cx, output, output_len_p, max_output_len,
433 input, input_len);
434 }
435
436 pcount = obj->pending_count;
437 pbuf = obj->pending_buf;
438
439 output_len = 0;
440
441 if (pcount) {
442 /*
443 * Try to fill in an entire block, starting with the bytes
444 * we already have saved away.
445 */
446 while (input_len && pcount < bsize) {
447 pbuf[pcount++] = *input++;
448 input_len--;
449 }
450 /*
451 * If we have at most a whole block and this is not our last call,
452 * then we are done for now. (We do not try to decrypt a lone
453 * single block because we cannot interpret the padding bytes
454 * until we know we are handling the very last block of all input.)
455 */
456 if (input_len == 0 && !final) {
457 obj->pending_count = pcount;
458 if (output_len_p)
459 *output_len_p = 0;
460 return SECSuccess;
461 }
462 /*
463 * Given the logic above, we expect to have a full block by now.
464 * If we do not, there is something wrong, either with our own
465 * logic or with (length of) the data given to us.
466 */
467 PORT_Assert ((padsize == 0) || (pcount % padsize) == 0);
468 if ((padsize != 0) && (pcount % padsize) != 0) {
469 PORT_Assert (final);
470 PORT_SetError (SEC_ERROR_BAD_DATA);
471 return SECFailure;
472 }
473 /*
474 * Decrypt the block.
475 */
476 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
477 pbuf, pcount);
478 if (rv != SECSuccess)
479 return rv;
480
481 /*
482 * For now anyway, all of our ciphers have the same number of
483 * bytes of output as they do input. If this ever becomes untrue,
484 * then sec_PKCS7DecryptLength needs to be made smarter!
485 */
486 PORT_Assert (ofraglen == pcount);
487
488 /*
489 * Account for the bytes now in output.
490 */
491 max_output_len -= ofraglen;
492 output_len += ofraglen;
493 output += ofraglen;
494 }
495
496 /*
497 * If this is our last call, we expect to have an exact number of
498 * blocks left to be decrypted; we will decrypt them all.
499 *
500 * If not our last call, we always save between 1 and bsize bytes
501 * until next time. (We must do this because we cannot be sure
502 * that none of the decrypted bytes are padding bytes until we
503 * have at least another whole block of data. You cannot tell by
504 * looking -- the data could be anything -- you can only tell by
505 * context, knowing you are looking at the last block.) We could
506 * decrypt a whole block now but it is easier if we just treat it
507 * the same way we treat partial block bytes.
508 */
509 if (final) {
510 if (padsize) {
511 blocks = input_len / padsize;
512 ifraglen = blocks * padsize;
513 } else ifraglen = input_len;
514 PORT_Assert (ifraglen == input_len);
515
516 if (ifraglen != input_len) {
517 PORT_SetError (SEC_ERROR_BAD_DATA);
518 return SECFailure;
519 }
520 } else {
521 blocks = (input_len - 1) / bsize;
522 ifraglen = blocks * bsize;
523 PORT_Assert (ifraglen < input_len);
524
525 pcount = input_len - ifraglen;
526 PORT_Memcpy (pbuf, input + ifraglen, pcount);
527 obj->pending_count = pcount;
528 }
529
530 if (ifraglen) {
531 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
532 input, ifraglen);
533 if (rv != SECSuccess)
534 return rv;
535
536 /*
537 * For now anyway, all of our ciphers have the same number of
538 * bytes of output as they do input. If this ever becomes untrue,
539 * then sec_PKCS7DecryptLength needs to be made smarter!
540 */
541 PORT_Assert (ifraglen == ofraglen);
542 if (ifraglen != ofraglen) {
543 PORT_SetError (SEC_ERROR_BAD_DATA);
544 return SECFailure;
545 }
546
547 output_len += ofraglen;
548 } else {
549 ofraglen = 0;
550 }
551
552 /*
553 * If we just did our very last block, "remove" the padding by
554 * adjusting the output length.
555 */
556 if (final && (padsize != 0)) {
557 unsigned int padlen = *(output + ofraglen - 1);
558 if (padlen == 0 || padlen > padsize) {
559 PORT_SetError (SEC_ERROR_BAD_DATA);
560 return SECFailure;
561 }
562 output_len -= padlen;
563 }
564
565 PORT_Assert (output_len_p != NULL || output_len == 0);
566 if (output_len_p != NULL)
567 *output_len_p = output_len;
568
569 return SECSuccess;
570 }
571
572 /*
573 * Encrypt a given length of input buffer (starting at "input" and
574 * containing "input_len" bytes), placing the encrypted bytes in
575 * "output" and storing the output length in "*output_len_p".
576 * "obj" is the return value from sec_PKCS7CreateEncryptObject.
577 * When "final" is true, this is the last of the data to be encrypted.
578 *
579 * This is much more complicated than it sounds when the cipher is
580 * a block-type, meaning that the encryption function will only
581 * operate on whole blocks. But our caller is operating stream-wise,
582 * and can pass in any number of bytes. So we need to keep track
583 * of block boundaries. We save excess bytes between calls in "obj".
584 * We also need to add padding bytes at the end. PKCS #7 specifies
585 * that the padding used for a block cipher is a string of bytes,
586 * each of whose value is the same as the length of the padding,
587 * and that all data is padded. (Even data that starts out with
588 * an exact multiple of blocks gets added to it another block,
589 * all of which is padding.)
590 *
591 * XXX I would kind of like to combine this with the function above
592 * which does decryption, since they have a lot in common. But the
593 * tricky parts about padding and filling blocks would be much
594 * harder to read that way, so I left them separate. At least for
595 * now until it is clear that they are right.
596 */
597 SECStatus
598 sec_PKCS7Encrypt (sec_PKCS7CipherObject *obj, unsigned char *output,
599 unsigned int *output_len_p, unsigned int max_output_len,
600 const unsigned char *input, unsigned int input_len,
601 PRBool final)
602 {
603 int blocks, bsize, padlen, pcount, padsize;
604 unsigned int max_needed, ifraglen, ofraglen, output_len;
605 unsigned char *pbuf;
606 SECStatus rv;
607
608 PORT_Assert (obj->encrypt);
609
610 /*
611 * Check that we have enough room for the output. Our caller should
612 * already handle this; failure is really an internal error (i.e. bug).
613 */
614 max_needed = sec_PKCS7EncryptLength (obj, input_len, final);
615 PORT_Assert (max_output_len >= max_needed);
616 if (max_output_len < max_needed) {
617 /* PORT_SetError (XXX); */
618 return SECFailure;
619 }
620
621 bsize = obj->block_size;
622 padsize = obj->pad_size;
623
624 /*
625 * When no blocking and padding work to do, we can simply call the
626 * cipher function and we are done.
627 */
628 if (bsize == 0) {
629 return (* obj->doit) (obj->cx, output, output_len_p, max_output_len,
630 input, input_len);
631 }
632
633 pcount = obj->pending_count;
634 pbuf = obj->pending_buf;
635
636 output_len = 0;
637
638 if (pcount) {
639 /*
640 * Try to fill in an entire block, starting with the bytes
641 * we already have saved away.
642 */
643 while (input_len && pcount < bsize) {
644 pbuf[pcount++] = *input++;
645 input_len--;
646 }
647 /*
648 * If we do not have a full block and we know we will be
649 * called again, then we are done for now.
650 */
651 if (pcount < bsize && !final) {
652 obj->pending_count = pcount;
653 if (output_len_p != NULL)
654 *output_len_p = 0;
655 return SECSuccess;
656 }
657 /*
658 * If we have a whole block available, encrypt it.
659 */
660 if ((padsize == 0) || (pcount % padsize) == 0) {
661 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
662 pbuf, pcount);
663 if (rv != SECSuccess)
664 return rv;
665
666 /*
667 * For now anyway, all of our ciphers have the same number of
668 * bytes of output as they do input. If this ever becomes untrue,
669 * then sec_PKCS7EncryptLength needs to be made smarter!
670 */
671 PORT_Assert (ofraglen == pcount);
672
673 /*
674 * Account for the bytes now in output.
675 */
676 max_output_len -= ofraglen;
677 output_len += ofraglen;
678 output += ofraglen;
679
680 pcount = 0;
681 }
682 }
683
684 if (input_len) {
685 PORT_Assert (pcount == 0);
686
687 blocks = input_len / bsize;
688 ifraglen = blocks * bsize;
689
690 if (ifraglen) {
691 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
692 input, ifraglen);
693 if (rv != SECSuccess)
694 return rv;
695
696 /*
697 * For now anyway, all of our ciphers have the same number of
698 * bytes of output as they do input. If this ever becomes untrue,
699 * then sec_PKCS7EncryptLength needs to be made smarter!
700 */
701 PORT_Assert (ifraglen == ofraglen);
702
703 max_output_len -= ofraglen;
704 output_len += ofraglen;
705 output += ofraglen;
706 }
707
708 pcount = input_len - ifraglen;
709 PORT_Assert (pcount < bsize);
710 if (pcount)
711 PORT_Memcpy (pbuf, input + ifraglen, pcount);
712 }
713
714 if (final) {
715 padlen = padsize - (pcount % padsize);
716 PORT_Memset (pbuf + pcount, padlen, padlen);
717 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
718 pbuf, pcount+padlen);
719 if (rv != SECSuccess)
720 return rv;
721
722 /*
723 * For now anyway, all of our ciphers have the same number of
724 * bytes of output as they do input. If this ever becomes untrue,
725 * then sec_PKCS7EncryptLength needs to be made smarter!
726 */
727 PORT_Assert (ofraglen == (pcount+padlen));
728 output_len += ofraglen;
729 } else {
730 obj->pending_count = pcount;
731 }
732
733 PORT_Assert (output_len_p != NULL || output_len == 0);
734 if (output_len_p != NULL)
735 *output_len_p = output_len;
736
737 return SECSuccess;
738 }
739
740 /*
741 * End of cipher stuff.
742 * -------------------------------------------------------------------
743 */
744
745
746 /*
747 * -------------------------------------------------------------------
748 * XXX The following Attribute stuff really belongs elsewhere.
749 * The Attribute type is *not* part of pkcs7 but rather X.501.
750 * But for now, since PKCS7 is the only customer of attributes,
751 * we define them here. Once there is a use outside of PKCS7,
752 * then change the attribute types and functions from internal
753 * to external naming convention, and move them elsewhere!
754 */
755
756 /*
757 * Look through a set of attributes and find one that matches the
758 * specified object ID. If "only" is true, then make sure that
759 * there is not more than one attribute of the same type. Otherwise,
760 * just return the first one found. (XXX Does anybody really want
761 * that first-found behavior? It was like that when I found it...)
762 */
763 SEC_PKCS7Attribute *
764 sec_PKCS7FindAttribute (SEC_PKCS7Attribute **attrs, SECOidTag oidtag,
765 PRBool only)
766 {
767 SECOidData *oid;
768 SEC_PKCS7Attribute *attr1, *attr2;
769
770 if (attrs == NULL)
771 return NULL;
772
773 oid = SECOID_FindOIDByTag(oidtag);
774 if (oid == NULL)
775 return NULL;
776
777 while ((attr1 = *attrs++) != NULL) {
778 if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data,
779 oid->oid.data,
780 oid->oid.len) == 0)
781 break;
782 }
783
784 if (attr1 == NULL)
785 return NULL;
786
787 if (!only)
788 return attr1;
789
790 while ((attr2 = *attrs++) != NULL) {
791 if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data,
792 oid->oid.data,
793 oid->oid.len) == 0)
794 break;
795 }
796
797 if (attr2 != NULL)
798 return NULL;
799
800 return attr1;
801 }
802
803
804 /*
805 * Return the single attribute value, doing some sanity checking first:
806 * - Multiple values are *not* expected.
807 * - Empty values are *not* expected.
808 */
809 SECItem *
810 sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr)
811 {
812 SECItem *value;
813
814 if (attr == NULL)
815 return NULL;
816
817 value = attr->values[0];
818
819 if (value == NULL || value->data == NULL || value->len == 0)
820 return NULL;
821
822 if (attr->values[1] != NULL)
823 return NULL;
824
825 return value;
826 }
827
828 static const SEC_ASN1Template *
829 sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding)
830 {
831 const SEC_ASN1Template *theTemplate;
832
833 SEC_PKCS7Attribute *attribute;
834 SECOidData *oiddata;
835 PRBool encoded;
836
837 PORT_Assert (src_or_dest != NULL);
838 if (src_or_dest == NULL)
839 return NULL;
840
841 attribute = (SEC_PKCS7Attribute*)src_or_dest;
842
843 if (encoding && attribute->encoded)
844 return SEC_ASN1_GET(SEC_AnyTemplate);
845
846 oiddata = attribute->typeTag;
847 if (oiddata == NULL) {
848 oiddata = SECOID_FindOID(&attribute->type);
849 attribute->typeTag = oiddata;
850 }
851
852 if (oiddata == NULL) {
853 encoded = PR_TRUE;
854 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
855 } else {
856 switch (oiddata->offset) {
857 default:
858 encoded = PR_TRUE;
859 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
860 break;
861 case SEC_OID_PKCS9_EMAIL_ADDRESS:
862 case SEC_OID_RFC1274_MAIL:
863 case SEC_OID_PKCS9_UNSTRUCTURED_NAME:
864 encoded = PR_FALSE;
865 theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate);
866 break;
867 case SEC_OID_PKCS9_CONTENT_TYPE:
868 encoded = PR_FALSE;
869 theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate);
870 break;
871 case SEC_OID_PKCS9_MESSAGE_DIGEST:
872 encoded = PR_FALSE;
873 theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate);
874 break;
875 case SEC_OID_PKCS9_SIGNING_TIME:
876 encoded = PR_FALSE;
877 theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate);
878 break;
879 /* XXX Want other types here, too */
880 }
881 }
882
883 if (encoding) {
884 /*
885 * If we are encoding and we think we have an already-encoded value,
886 * then the code which initialized this attribute should have set
887 * the "encoded" property to true (and we would have returned early,
888 * up above). No devastating error, but that code should be fixed.
889 * (It could indicate that the resulting encoded bytes are wrong.)
890 */
891 PORT_Assert (!encoded);
892 } else {
893 /*
894 * We are decoding; record whether the resulting value is
895 * still encoded or not.
896 */
897 attribute->encoded = encoded;
898 }
899 return theTemplate;
900 }
901
902 static const SEC_ASN1TemplateChooserPtr sec_attr_chooser
903 = sec_attr_choose_attr_value_template;
904
905 static const SEC_ASN1Template sec_pkcs7_attribute_template[] = {
906 { SEC_ASN1_SEQUENCE,
907 0, NULL, sizeof(SEC_PKCS7Attribute) },
908 { SEC_ASN1_OBJECT_ID,
909 offsetof(SEC_PKCS7Attribute,type) },
910 { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF,
911 offsetof(SEC_PKCS7Attribute,values),
912 &sec_attr_chooser },
913 { 0 }
914 };
915
916 static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = {
917 { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template },
918 };
919
920 /*
921 * If you are wondering why this routine does not reorder the attributes
922 * first, and might be tempted to make it do so, see the comment by the
923 * call to ReorderAttributes in p7encode.c. (Or, see who else calls this
924 * and think long and hard about the implications of making it always
925 * do the reordering.)
926 */
927 SECItem *
928 sec_PKCS7EncodeAttributes (PRArenaPool *poolp, SECItem *dest, void *src)
929 {
930 return SEC_ASN1EncodeItem (poolp, dest, src,
931 sec_pkcs7_set_of_attribute_template);
932 }
933
934 /*
935 * Make sure that the order of the attributes guarantees valid DER
936 * (which must be in lexigraphically ascending order for a SET OF);
937 * if reordering is necessary it will be done in place (in attrs).
938 */
939 SECStatus
940 sec_PKCS7ReorderAttributes (SEC_PKCS7Attribute **attrs)
941 {
942 PRArenaPool *poolp;
943 int num_attrs, i, pass, besti;
944 unsigned int j;
945 SECItem **enc_attrs;
946 SEC_PKCS7Attribute **new_attrs;
947
948 /*
949 * I think we should not be called with NULL. But if we are,
950 * call it a success anyway, because the order *is* okay.
951 */
952 PORT_Assert (attrs != NULL);
953 if (attrs == NULL)
954 return SECSuccess;
955
956 /*
957 * Count how many attributes we are dealing with here.
958 */
959 num_attrs = 0;
960 while (attrs[num_attrs] != NULL)
961 num_attrs++;
962
963 /*
964 * Again, I think we should have some attributes here.
965 * But if we do not, or if there is only one, then call it
966 * a success because it also already has a fine order.
967 */
968 PORT_Assert (num_attrs);
969 if (num_attrs == 0 || num_attrs == 1)
970 return SECSuccess;
971
972 /*
973 * Allocate an arena for us to work with, so it is easy to
974 * clean up all of the memory (fairly small pieces, really).
975 */
976 poolp = PORT_NewArena (1024); /* XXX what is right value? */
977 if (poolp == NULL)
978 return SECFailure; /* no memory; nothing we can do... */
979
980 /*
981 * Allocate arrays to hold the individual encodings which we will use
982 * for comparisons and the reordered attributes as they are sorted.
983 */
984 enc_attrs=(SECItem**)PORT_ArenaZAlloc(poolp, num_attrs*sizeof(SECItem *));
985 new_attrs = (SEC_PKCS7Attribute**)PORT_ArenaZAlloc (poolp,
986 num_attrs * sizeof(SEC_PKCS7Attribute *));
987 if (enc_attrs == NULL || new_attrs == NULL) {
988 PORT_FreeArena (poolp, PR_FALSE);
989 return SECFailure;
990 }
991
992 /*
993 * DER encode each individual attribute.
994 */
995 for (i = 0; i < num_attrs; i++) {
996 enc_attrs[i] = SEC_ASN1EncodeItem (poolp, NULL, attrs[i],
997 sec_pkcs7_attribute_template);
998 if (enc_attrs[i] == NULL) {
999 PORT_FreeArena (poolp, PR_FALSE);
1000 return SECFailure;
1001 }
1002 }
1003
1004 /*
1005 * Now compare and sort them; this is not the most efficient sorting
1006 * method, but it is just fine for the problem at hand, because the
1007 * number of attributes is (always) going to be small.
1008 */
1009 for (pass = 0; pass < num_attrs; pass++) {
1010 /*
1011 * Find the first not-yet-accepted attribute. (Once one is
1012 * sorted into the other array, it is cleared from enc_attrs.)
1013 */
1014 for (i = 0; i < num_attrs; i++) {
1015 if (enc_attrs[i] != NULL)
1016 break;
1017 }
1018 PORT_Assert (i < num_attrs);
1019 besti = i;
1020
1021 /*
1022 * Find the lowest (lexigraphically) encoding. One that is
1023 * shorter than all the rest is known to be "less" because each
1024 * attribute is of the same type (a SEQUENCE) and so thus the
1025 * first octet of each is the same, and the second octet is
1026 * the length (or the length of the length with the high bit
1027 * set, followed by the length, which also works out to always
1028 * order the shorter first). Two (or more) that have the
1029 * same length need to be compared byte by byte until a mismatch
1030 * is found.
1031 */
1032 for (i = besti + 1; i < num_attrs; i++) {
1033 if (enc_attrs[i] == NULL) /* slot already handled */
1034 continue;
1035
1036 if (enc_attrs[i]->len != enc_attrs[besti]->len) {
1037 if (enc_attrs[i]->len < enc_attrs[besti]->len)
1038 besti = i;
1039 continue;
1040 }
1041
1042 for (j = 0; j < enc_attrs[i]->len; j++) {
1043 if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) {
1044 besti = i;
1045 break;
1046 }
1047 }
1048
1049 /*
1050 * For this not to be true, we would have to have encountered
1051 * two *identical* attributes, which I think we should not see.
1052 * So assert if it happens, but even if it does, let it go
1053 * through; the ordering of the two does not matter.
1054 */
1055 PORT_Assert (j < enc_attrs[i]->len);
1056 }
1057
1058 /*
1059 * Now we have found the next-lowest one; copy it over and
1060 * remove it from enc_attrs.
1061 */
1062 new_attrs[pass] = attrs[besti];
1063 enc_attrs[besti] = NULL;
1064 }
1065
1066 /*
1067 * Now new_attrs has the attributes in the order we want;
1068 * copy them back into the attrs array we started with.
1069 */
1070 for (i = 0; i < num_attrs; i++)
1071 attrs[i] = new_attrs[i];
1072
1073 PORT_FreeArena (poolp, PR_FALSE);
1074 return SECSuccess;
1075 }
1076
1077 /*
1078 * End of attribute stuff.
1079 * -------------------------------------------------------------------
1080 */
1081
1082
1083 /*
1084 * Templates and stuff. Keep these at the end of the file.
1085 */
1086
1087 /* forward declaration */
1088 static const SEC_ASN1Template *
1089 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding);
1090
1091 static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser
1092 = sec_pkcs7_choose_content_template;
1093
1094 const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = {
1095 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1096 0, NULL, sizeof(SEC_PKCS7ContentInfo) },
1097 { SEC_ASN1_OBJECT_ID,
1098 offsetof(SEC_PKCS7ContentInfo,contentType) },
1099 { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM
1100 | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1101 offsetof(SEC_PKCS7ContentInfo,content),
1102 &sec_pkcs7_chooser },
1103 { 0 }
1104 };
1105
1106 /* XXX These names should change from external to internal convention. */
1107
1108 static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = {
1109 { SEC_ASN1_SEQUENCE,
1110 0, NULL, sizeof(SEC_PKCS7SignerInfo) },
1111 { SEC_ASN1_INTEGER,
1112 offsetof(SEC_PKCS7SignerInfo,version) },
1113 { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
1114 offsetof(SEC_PKCS7SignerInfo,issuerAndSN),
1115 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
1116 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1117 offsetof(SEC_PKCS7SignerInfo,digestAlg),
1118 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1119 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1120 offsetof(SEC_PKCS7SignerInfo,authAttr),
1121 sec_pkcs7_set_of_attribute_template },
1122 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1123 offsetof(SEC_PKCS7SignerInfo,digestEncAlg),
1124 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1125 { SEC_ASN1_OCTET_STRING,
1126 offsetof(SEC_PKCS7SignerInfo,encDigest) },
1127 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1128 offsetof(SEC_PKCS7SignerInfo,unAuthAttr),
1129 sec_pkcs7_set_of_attribute_template },
1130 { 0 }
1131 };
1132
1133 static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = {
1134 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1135 0, NULL, sizeof(SEC_PKCS7SignedData) },
1136 { SEC_ASN1_INTEGER,
1137 offsetof(SEC_PKCS7SignedData,version) },
1138 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1139 offsetof(SEC_PKCS7SignedData,digestAlgorithms),
1140 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1141 { SEC_ASN1_INLINE,
1142 offsetof(SEC_PKCS7SignedData,contentInfo),
1143 sec_PKCS7ContentInfoTemplate },
1144 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1145 SEC_ASN1_XTRN | 0,
1146 offsetof(SEC_PKCS7SignedData,rawCerts),
1147 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
1148 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1149 SEC_ASN1_XTRN | 1,
1150 offsetof(SEC_PKCS7SignedData,crls),
1151 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
1152 { SEC_ASN1_SET_OF,
1153 offsetof(SEC_PKCS7SignedData,signerInfos),
1154 SEC_PKCS7SignerInfoTemplate },
1155 { 0 }
1156 };
1157
1158 static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = {
1159 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate }
1160 };
1161
1162 static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = {
1163 { SEC_ASN1_SEQUENCE,
1164 0, NULL, sizeof(SEC_PKCS7RecipientInfo) },
1165 { SEC_ASN1_INTEGER,
1166 offsetof(SEC_PKCS7RecipientInfo,version) },
1167 { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
1168 offsetof(SEC_PKCS7RecipientInfo,issuerAndSN),
1169 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
1170 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1171 offsetof(SEC_PKCS7RecipientInfo,keyEncAlg),
1172 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1173 { SEC_ASN1_OCTET_STRING,
1174 offsetof(SEC_PKCS7RecipientInfo,encKey) },
1175 { 0 }
1176 };
1177
1178 static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = {
1179 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1180 0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) },
1181 { SEC_ASN1_OBJECT_ID,
1182 offsetof(SEC_PKCS7EncryptedContentInfo,contentType) },
1183 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1184 offsetof(SEC_PKCS7EncryptedContentInfo,contentEncAlg),
1185 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1186 { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC |
1187 SEC_ASN1_XTRN | 0,
1188 offsetof(SEC_PKCS7EncryptedContentInfo,encContent),
1189 SEC_ASN1_SUB(SEC_OctetStringTemplate) },
1190 { 0 }
1191 };
1192
1193 static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = {
1194 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1195 0, NULL, sizeof(SEC_PKCS7EnvelopedData) },
1196 { SEC_ASN1_INTEGER,
1197 offsetof(SEC_PKCS7EnvelopedData,version) },
1198 { SEC_ASN1_SET_OF,
1199 offsetof(SEC_PKCS7EnvelopedData,recipientInfos),
1200 SEC_PKCS7RecipientInfoTemplate },
1201 { SEC_ASN1_INLINE,
1202 offsetof(SEC_PKCS7EnvelopedData,encContentInfo),
1203 SEC_PKCS7EncryptedContentInfoTemplate },
1204 { 0 }
1205 };
1206
1207 static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = {
1208 { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate }
1209 };
1210
1211 static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = {
1212 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1213 0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) },
1214 { SEC_ASN1_INTEGER,
1215 offsetof(SEC_PKCS7SignedAndEnvelopedData,version) },
1216 { SEC_ASN1_SET_OF,
1217 offsetof(SEC_PKCS7SignedAndEnvelopedData,recipientInfos),
1218 SEC_PKCS7RecipientInfoTemplate },
1219 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1220 offsetof(SEC_PKCS7SignedAndEnvelopedData,digestAlgorithms),
1221 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1222 { SEC_ASN1_INLINE,
1223 offsetof(SEC_PKCS7SignedAndEnvelopedData,encContentInfo),
1224 SEC_PKCS7EncryptedContentInfoTemplate },
1225 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1226 SEC_ASN1_XTRN | 0,
1227 offsetof(SEC_PKCS7SignedAndEnvelopedData,rawCerts),
1228 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
1229 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1230 SEC_ASN1_XTRN | 1,
1231 offsetof(SEC_PKCS7SignedAndEnvelopedData,crls),
1232 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
1233 { SEC_ASN1_SET_OF,
1234 offsetof(SEC_PKCS7SignedAndEnvelopedData,signerInfos),
1235 SEC_PKCS7SignerInfoTemplate },
1236 { 0 }
1237 };
1238
1239 static const SEC_ASN1Template
1240 SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = {
1241 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate }
1242 };
1243
1244 static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = {
1245 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1246 0, NULL, sizeof(SEC_PKCS7DigestedData) },
1247 { SEC_ASN1_INTEGER,
1248 offsetof(SEC_PKCS7DigestedData,version) },
1249 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1250 offsetof(SEC_PKCS7DigestedData,digestAlg),
1251 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1252 { SEC_ASN1_INLINE,
1253 offsetof(SEC_PKCS7DigestedData,contentInfo),
1254 sec_PKCS7ContentInfoTemplate },
1255 { SEC_ASN1_OCTET_STRING,
1256 offsetof(SEC_PKCS7DigestedData,digest) },
1257 { 0 }
1258 };
1259
1260 static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = {
1261 { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate }
1262 };
1263
1264 static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = {
1265 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1266 0, NULL, sizeof(SEC_PKCS7EncryptedData) },
1267 { SEC_ASN1_INTEGER,
1268 offsetof(SEC_PKCS7EncryptedData,version) },
1269 { SEC_ASN1_INLINE,
1270 offsetof(SEC_PKCS7EncryptedData,encContentInfo),
1271 SEC_PKCS7EncryptedContentInfoTemplate },
1272 { 0 }
1273 };
1274
1275 static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = {
1276 { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate }
1277 };
1278
1279 static const SEC_ASN1Template *
1280 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding)
1281 {
1282 const SEC_ASN1Template *theTemplate;
1283 SEC_PKCS7ContentInfo *cinfo;
1284 SECOidTag kind;
1285
1286 PORT_Assert (src_or_dest != NULL);
1287 if (src_or_dest == NULL)
1288 return NULL;
1289
1290 cinfo = (SEC_PKCS7ContentInfo*)src_or_dest;
1291 kind = SEC_PKCS7ContentType (cinfo);
1292 switch (kind) {
1293 default:
1294 theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
1295 break;
1296 case SEC_OID_PKCS7_DATA:
1297 theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate);
1298 break;
1299 case SEC_OID_PKCS7_SIGNED_DATA:
1300 theTemplate = SEC_PointerToPKCS7SignedDataTemplate;
1301 break;
1302 case SEC_OID_PKCS7_ENVELOPED_DATA:
1303 theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate;
1304 break;
1305 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1306 theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate;
1307 break;
1308 case SEC_OID_PKCS7_DIGESTED_DATA:
1309 theTemplate = SEC_PointerToPKCS7DigestedDataTemplate;
1310 break;
1311 case SEC_OID_PKCS7_ENCRYPTED_DATA:
1312 theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate;
1313 break;
1314 }
1315 return theTemplate;
1316 }
1317
1318 /*
1319 * End of templates. Do not add stuff after this; put new code
1320 * up above the start of the template definitions.
1321 */
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/pkcs7/p7local.h ('k') | mozilla/security/nss/lib/pkcs7/pkcs7t.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698