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