PageRenderTime 84ms CodeModel.GetById 14ms app.highlight 61ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/pkcs7/p7local.c

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