comparison nss/lib/pkcs7/p7local.c @ 0:1e5118fa0cb1

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