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

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

Powered by Google App Engine
This is Rietveld 408576698