Mercurial > trustbridge > nss-cmake-static
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, ¶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 * | |
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 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 */ |