security/nss/lib/pkcs7/p7local.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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/. */
     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  */
    12 #include "p7local.h"
    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"
    22 /*
    23  * -------------------------------------------------------------------
    24  * Cipher stuff.
    25  */
    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);
    35 #define BLOCK_SIZE 4096
    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 };
    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)
    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;
    76     result = (struct sec_pkcs7_cipher_object*)
    77       PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
    78     if (result == NULL)
    79 	return NULL;
    81     ciphercx = NULL;
    82     algtag = SECOID_GetAlgorithmTag (algid);
    84     if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
    85 	SECItem *pwitem;
    87 	pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
    88 	if (!pwitem) {
    89 	    PORT_Free(result);
    90 	    return NULL;
    91 	}
    93 	cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
    94 	if (cryptoMechType == CKM_INVALID_MECHANISM) {
    95 	    PORT_Free(result);
    96 	    SECITEM_FreeItem(param,PR_TRUE);
    97 	    return NULL;
    98 	}
    99     } else {
   100 	cryptoMechType = PK11_AlgtagToMechanism(algtag);
   101 	param = PK11_ParamFromAlgid(algid);
   102 	if (param == NULL) {
   103 	    PORT_Free(result);
   104 	    return NULL;
   105 	}
   106     }
   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     }
   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;
   126     return result;
   127 }
   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;
   154     result = (struct sec_pkcs7_cipher_object*)
   155 	      PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
   156     if (result == NULL)
   157 	return NULL;
   159     ciphercx = NULL;
   160     if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
   161 	SECItem *pwitem;
   163 	pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
   164 	if (!pwitem) {
   165 	    PORT_Free(result);
   166 	    return NULL;
   167 	}
   169 	cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
   170 	if (cryptoMechType == CKM_INVALID_MECHANISM) {
   171 	    PORT_Free(result);
   172 	    SECITEM_FreeItem(param,PR_TRUE);
   173 	    return NULL;
   174 	}
   175     } else {
   176 	cryptoMechType = PK11_AlgtagToMechanism(algtag);
   177 	param = PK11_GenerateNewParam(cryptoMechType, key);
   178 	if (param == NULL) {
   179 	    PORT_Free(result);
   180 	    return NULL;
   181 	}
   182 	needToEncodeAlgid = PR_TRUE;
   183     }
   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     }
   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);
   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;
   218     return result;
   219 }
   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 }
   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 }
   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 }
   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  */
   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;
   281     PORT_Assert (! obj->encrypt);
   283     block_size = obj->block_size;
   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;
   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;
   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 }
   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;
   336     PORT_Assert (obj->encrypt);
   338     block_size = obj->block_size;
   339     pad_size = obj->pad_size;
   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;
   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     }
   364     /*
   365      * Now, count the number of complete blocks of data we have.
   366      */
   367     blocks = (obj->pending_count + input_len) / block_size;
   370     return blocks * block_size;
   371 }
   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;
   405     PORT_Assert (! obj->encrypt);
   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     }
   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;
   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     }
   434     pcount = obj->pending_count;
   435     pbuf = obj->pending_buf;
   437     output_len = 0;
   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;
   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);
   486 	/*
   487 	 * Account for the bytes now in output.
   488 	 */
   489 	max_output_len -= ofraglen;
   490 	output_len += ofraglen;
   491 	output += ofraglen;
   492     }
   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);
   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);
   523 	pcount = input_len - ifraglen;
   524 	PORT_Memcpy (pbuf, input + ifraglen, pcount);
   525 	obj->pending_count = pcount;
   526     }
   528     if (ifraglen) {
   529 	rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
   530 			    input, ifraglen);
   531 	if (rv != SECSuccess)
   532 	    return rv;
   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 	}
   545 	output_len += ofraglen;
   546     } else {
   547 	ofraglen = 0;
   548     }
   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     }
   563     PORT_Assert (output_len_p != NULL || output_len == 0);
   564     if (output_len_p != NULL)
   565 	*output_len_p = output_len;
   567     return SECSuccess;
   568 }
   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;
   606     PORT_Assert (obj->encrypt);
   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     }
   619     bsize = obj->block_size;
   620     padsize = obj->pad_size;
   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     }
   631     pcount = obj->pending_count;
   632     pbuf = obj->pending_buf;
   634     output_len = 0;
   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;
   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);
   671 	    /*
   672 	     * Account for the bytes now in output.
   673 	     */
   674 	    max_output_len -= ofraglen;
   675 	    output_len += ofraglen;
   676 	    output += ofraglen;
   678 	    pcount = 0;
   679 	}
   680     }
   682     if (input_len) {
   683 	PORT_Assert (pcount == 0);
   685 	blocks = input_len / bsize;
   686 	ifraglen = blocks * bsize;
   688 	if (ifraglen) {
   689 	    rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
   690 				input, ifraglen);
   691 	    if (rv != SECSuccess)
   692 		return rv;
   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);
   701 	    max_output_len -= ofraglen;
   702 	    output_len += ofraglen;
   703 	    output += ofraglen;
   704 	}
   706 	pcount = input_len - ifraglen;
   707 	PORT_Assert (pcount < bsize);
   708 	if (pcount)
   709 	    PORT_Memcpy (pbuf, input + ifraglen, pcount);
   710     }
   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;
   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     }
   731     PORT_Assert (output_len_p != NULL || output_len == 0);
   732     if (output_len_p != NULL)
   733 	*output_len_p = output_len;
   735     return SECSuccess;
   736 }
   738 /*
   739  * End of cipher stuff.
   740  * -------------------------------------------------------------------
   741  */
   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  */
   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;
   768     if (attrs == NULL)
   769 	return NULL;
   771     oid = SECOID_FindOIDByTag(oidtag);
   772     if (oid == NULL)
   773 	return NULL;
   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     }
   782     if (attr1 == NULL)
   783 	return NULL;
   785     if (!only)
   786 	return attr1;
   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     }
   795     if (attr2 != NULL)
   796 	return NULL;
   798     return attr1;
   799 }
   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;
   812     if (attr == NULL)
   813 	return NULL;
   815     value = attr->values[0];
   817     if (value == NULL || value->data == NULL || value->len == 0)
   818 	return NULL;
   820     if (attr->values[1] != NULL)
   821 	return NULL;
   823     return value;
   824 }
   826 static const SEC_ASN1Template *
   827 sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding)
   828 {
   829     const SEC_ASN1Template *theTemplate;
   831     SEC_PKCS7Attribute *attribute;
   832     SECOidData *oiddata;
   833     PRBool encoded;
   835     PORT_Assert (src_or_dest != NULL);
   836     if (src_or_dest == NULL)
   837 	return NULL;
   839     attribute = (SEC_PKCS7Attribute*)src_or_dest;
   841     if (encoding && attribute->encoded)
   842 	return SEC_ASN1_GET(SEC_AnyTemplate);
   844     oiddata = attribute->typeTag;
   845     if (oiddata == NULL) {
   846 	oiddata = SECOID_FindOID(&attribute->type);
   847 	attribute->typeTag = oiddata;
   848     }
   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     }
   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 }
   900 static const SEC_ASN1TemplateChooserPtr sec_attr_chooser
   901 	= sec_attr_choose_attr_value_template;
   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 };
   914 static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = {
   915     { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template },
   916 };
   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 }
   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;
   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;
   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++;
   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;
   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... */
   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     }
   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 	}
  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;
  1016 	PORT_Assert (i < num_attrs);
  1017 	besti = i;
  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;
  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;
  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;
  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);
  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;
  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];
  1071     PORT_FreeArena (poolp, PR_FALSE);
  1072     return SECSuccess;
  1075 /*
  1076  * End of attribute stuff.
  1077  * -------------------------------------------------------------------
  1078  */
  1081 /*
  1082  * Templates and stuff.  Keep these at the end of the file.
  1083  */
  1085 /* forward declaration */
  1086 static const SEC_ASN1Template *
  1087 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding);
  1089 static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser
  1090 	= sec_pkcs7_choose_content_template;
  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 };
  1104 /* XXX These names should change from external to internal convention. */
  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 };
  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 };
  1156 static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = {
  1157     { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate }
  1158 };
  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 };
  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 };
  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 };
  1205 static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = {
  1206     { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate }
  1207 };
  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 };
  1237 static const SEC_ASN1Template
  1238 SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = {
  1239     { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate }
  1240 };
  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 };
  1258 static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = {
  1259     { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate }
  1260 };
  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 };
  1273 static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = {
  1274     { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate }
  1275 };
  1277 static const SEC_ASN1Template *
  1278 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding)
  1280     const SEC_ASN1Template *theTemplate;
  1281     SEC_PKCS7ContentInfo *cinfo;
  1282     SECOidTag kind;
  1284     PORT_Assert (src_or_dest != NULL);
  1285     if (src_or_dest == NULL)
  1286 	return NULL;
  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;
  1313     return theTemplate;
  1316 /*
  1317  * End of templates.  Do not add stuff after this; put new code
  1318  * up above the start of the template definitions.
  1319  */

mercurial