diff options
Diffstat (limited to 'security/nss/lib/pkcs7/p7local.c')
-rw-r--r-- | security/nss/lib/pkcs7/p7local.c | 1431 |
1 files changed, 0 insertions, 1431 deletions
diff --git a/security/nss/lib/pkcs7/p7local.c b/security/nss/lib/pkcs7/p7local.c deleted file mode 100644 index d3e58be50..000000000 --- a/security/nss/lib/pkcs7/p7local.c +++ /dev/null @@ -1,1431 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -/* - * Support routines for PKCS7 implementation, none of which are exported. - * This file should only contain things that are needed by both the - * encoding/creation side *and* the decoding/decryption side. Anything - * else should be static routines in the appropriate file. - * - * $Id$ - */ - -#include "p7local.h" - -#include "cryptohi.h" -#include "secasn1.h" -#include "secoid.h" -#include "secitem.h" -#include "pk11func.h" -#include "secpkcs5.h" -#include "secerr.h" - -/* - * ------------------------------------------------------------------- - * Cipher stuff. - */ - -typedef SECStatus (*sec_pkcs7_cipher_function) (void *, - unsigned char *, - unsigned *, - unsigned int, - const unsigned char *, - unsigned int); -typedef SECStatus (*sec_pkcs7_cipher_destroy) (void *, PRBool); - -#define BLOCK_SIZE 4096 - -struct sec_pkcs7_cipher_object { - void *cx; - sec_pkcs7_cipher_function doit; - sec_pkcs7_cipher_destroy destroy; - PRBool encrypt; - int block_size; - int pad_size; - int pending_count; - unsigned char pending_buf[BLOCK_SIZE]; -}; - -/* - * Create a cipher object to do decryption, based on the given bulk - * encryption key and algorithm identifier (which may include an iv). - * - * XXX This interface, or one similar, would be really nice available - * in general... I tried to keep the pkcs7-specific stuff (mostly - * having to do with padding) out of here. - * - * XXX Once both are working, it might be nice to combine this and the - * function below (for starting up encryption) into one routine, and just - * have two simple cover functions which call it. - */ -sec_PKCS7CipherObject * -sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid) -{ - sec_PKCS7CipherObject *result; - SECOidTag algtag; - void *ciphercx; - CK_MECHANISM_TYPE mechanism; - SECItem *param; - PK11SlotInfo *slot; - - result = (struct sec_pkcs7_cipher_object*) - PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); - if (result == NULL) - return NULL; - - ciphercx = NULL; - algtag = SECOID_GetAlgorithmTag (algid); - - if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { - CK_MECHANISM pbeMech, cryptoMech; - SECItem *pbeParams, *pwitem; - SEC_PKCS5KeyAndPassword *keyPwd; - - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; - pwitem = keyPwd->pwitem; - - pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); - pbeParams = PK11_ParamFromAlgid(algid); - if (!pbeParams) { - PORT_Free(result); - return NULL; - } - - pbeMech.pParameter = pbeParams->data; - pbeMech.ulParameterLen = pbeParams->len; - if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, - PR_FALSE) != CKR_OK) { - PORT_Free(result); - SECITEM_ZfreeItem(pbeParams, PR_TRUE); - return NULL; - } - SECITEM_ZfreeItem(pbeParams, PR_TRUE); - - param = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!param) { - PORT_Free(result); - return NULL; - } - param->data = (unsigned char *)cryptoMech.pParameter; - param->len = cryptoMech.ulParameterLen; - mechanism = cryptoMech.mechanism; - } else { - mechanism = PK11_AlgtagToMechanism(algtag); - param = PK11_ParamFromAlgid(algid); - if (param == NULL) { - PORT_Free(result); - return NULL; - } - } - - result->pad_size = PK11_GetBlockSize(mechanism,param); - slot = PK11_GetSlotFromKey(key); - result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; - PK11_FreeSlot(slot); - ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param); - SECITEM_FreeItem(param,PR_TRUE); - if (ciphercx == NULL) { - PORT_Free (result); - return NULL; - } - - result->cx = ciphercx; - result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; - result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; - result->encrypt = PR_FALSE; - result->pending_count = 0; - - return result; -} - -/* - * Create a cipher object to do encryption, based on the given bulk - * encryption key and algorithm tag. Fill in the algorithm identifier - * (which may include an iv) appropriately. - * - * XXX This interface, or one similar, would be really nice available - * in general... I tried to keep the pkcs7-specific stuff (mostly - * having to do with padding) out of here. - * - * XXX Once both are working, it might be nice to combine this and the - * function above (for starting up decryption) into one routine, and just - * have two simple cover functions which call it. - */ -sec_PKCS7CipherObject * -sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key, - SECOidTag algtag, SECAlgorithmID *algid) -{ - sec_PKCS7CipherObject *result; - void *ciphercx; - SECItem *param; - SECStatus rv; - CK_MECHANISM_TYPE mechanism; - PRBool needToEncodeAlgid = PR_FALSE; - PK11SlotInfo *slot; - - result = (struct sec_pkcs7_cipher_object*) - PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); - if (result == NULL) - return NULL; - - ciphercx = NULL; - if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { - CK_MECHANISM pbeMech, cryptoMech; - SECItem *pbeParams; - SEC_PKCS5KeyAndPassword *keyPwd; - - PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); - PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); - - pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); - pbeParams = PK11_ParamFromAlgid(algid); - if(!pbeParams) { - PORT_Free(result); - return NULL; - } - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; - - pbeMech.pParameter = pbeParams->data; - pbeMech.ulParameterLen = pbeParams->len; - if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, - keyPwd->pwitem, PR_FALSE) != CKR_OK) { - PORT_Free(result); - SECITEM_ZfreeItem(pbeParams, PR_TRUE); - return NULL; - } - SECITEM_ZfreeItem(pbeParams, PR_TRUE); - - param = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!param) { - PORT_Free(result); - return NULL; - } - param->data = (unsigned char *)cryptoMech.pParameter; - param->len = cryptoMech.ulParameterLen; - mechanism = cryptoMech.mechanism; - } else { - mechanism = PK11_AlgtagToMechanism(algtag); - param = PK11_GenerateNewParam(mechanism,key); - if (param == NULL) { - PORT_Free(result); - return NULL; - } - needToEncodeAlgid = PR_TRUE; - } - - result->pad_size = PK11_GetBlockSize(mechanism,param); - slot = PK11_GetSlotFromKey(key); - result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; - PK11_FreeSlot(slot); - ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, - key, param); - if (ciphercx == NULL) { - PORT_Free (result); - SECITEM_FreeItem(param,PR_TRUE); - return NULL; - } - - /* - * These are placed after the CreateContextBySymKey() because some - * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). - * Don't move it from here. - */ - if (needToEncodeAlgid) { - rv = PK11_ParamToAlgid(algtag,param,poolp,algid); - if(rv != SECSuccess) { - return NULL; - } - } - SECITEM_FreeItem(param,PR_TRUE); - - result->cx = ciphercx; - result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; - result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; - result->encrypt = PR_TRUE; - result->pending_count = 0; - - return result; -} - - -/* - * Destroy the cipher object. - */ -static void -sec_pkcs7_destroy_cipher (sec_PKCS7CipherObject *obj) -{ - (* obj->destroy) (obj->cx, PR_TRUE); - PORT_Free (obj); -} - -void -sec_PKCS7DestroyDecryptObject (sec_PKCS7CipherObject *obj) -{ - PORT_Assert (obj != NULL); - if (obj == NULL) - return; - PORT_Assert (! obj->encrypt); - sec_pkcs7_destroy_cipher (obj); -} - -void -sec_PKCS7DestroyEncryptObject (sec_PKCS7CipherObject *obj) -{ - PORT_Assert (obj != NULL); - if (obj == NULL) - return; - PORT_Assert (obj->encrypt); - sec_pkcs7_destroy_cipher (obj); -} - - -/* - * XXX I think all of the following lengths should be longs instead - * of ints, but our current crypto interface uses ints, so I did too. - */ - - -/* - * What will be the output length of the next call to decrypt? - * Result can be used to perform memory allocations. Note that the amount - * is exactly accurate only when not doing a block cipher or when final - * is false, otherwise it is an upper bound on the amount because until - * we see the data we do not know how many padding bytes there are - * (always between 1 and bsize). - * - * Note that this can return zero, which does not mean that the decrypt - * operation can be skipped! (It simply means that there are not enough - * bytes to make up an entire block; the bytes will be reserved until - * there are enough to encrypt/decrypt at least one block.) However, - * if zero is returned it *does* mean that no output buffer need be - * passed in to the subsequent decrypt operation, as no output bytes - * will be stored. - */ -unsigned int -sec_PKCS7DecryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len, - PRBool final) -{ - int blocks, block_size; - - PORT_Assert (! obj->encrypt); - - block_size = obj->block_size; - - /* - * If this is not a block cipher, then we always have the same - * number of output bytes as we had input bytes. - */ - if (block_size == 0) - return input_len; - - /* - * On the final call, we will always use up all of the pending - * bytes plus all of the input bytes, *but*, there will be padding - * at the end and we cannot predict how many bytes of padding we - * will end up removing. The amount given here is actually known - * to be at least 1 byte too long (because we know we will have - * at least 1 byte of padding), but seemed clearer/better to me. - */ - if (final) - return obj->pending_count + input_len; - - /* - * Okay, this amount is exactly what we will output on the - * next cipher operation. We will always hang onto the last - * 1 - block_size bytes for non-final operations. That is, - * we will do as many complete blocks as we can *except* the - * last block (complete or partial). (This is because until - * we know we are at the end, we cannot know when to interpret - * and removing the padding byte(s), which are guaranteed to - * be there.) - */ - blocks = (obj->pending_count + input_len - 1) / block_size; - return blocks * block_size; -} - -/* - * What will be the output length of the next call to encrypt? - * Result can be used to perform memory allocations. - * - * Note that this can return zero, which does not mean that the encrypt - * operation can be skipped! (It simply means that there are not enough - * bytes to make up an entire block; the bytes will be reserved until - * there are enough to encrypt/decrypt at least one block.) However, - * if zero is returned it *does* mean that no output buffer need be - * passed in to the subsequent encrypt operation, as no output bytes - * will be stored. - */ -unsigned int -sec_PKCS7EncryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len, - PRBool final) -{ - int blocks, block_size; - int pad_size; - - PORT_Assert (obj->encrypt); - - block_size = obj->block_size; - pad_size = obj->pad_size; - - /* - * If this is not a block cipher, then we always have the same - * number of output bytes as we had input bytes. - */ - if (block_size == 0) - return input_len; - - /* - * On the final call, we only send out what we need for - * remaining bytes plus the padding. (There is always padding, - * so even if we have an exact number of blocks as input, we - * will add another full block that is just padding.) - */ - if (final) { - if (pad_size == 0) { - return obj->pending_count + input_len; - } else { - blocks = (obj->pending_count + input_len) / pad_size; - blocks++; - return blocks*pad_size; - } - } - - /* - * Now, count the number of complete blocks of data we have. - */ - blocks = (obj->pending_count + input_len) / block_size; - - - return blocks * block_size; -} - - -/* - * Decrypt a given length of input buffer (starting at "input" and - * containing "input_len" bytes), placing the decrypted bytes in - * "output" and storing the output length in "*output_len_p". - * "obj" is the return value from sec_PKCS7CreateDecryptObject. - * When "final" is true, this is the last of the data to be decrypted. - * - * This is much more complicated than it sounds when the cipher is - * a block-type, meaning that the decryption function will only - * operate on whole blocks. But our caller is operating stream-wise, - * and can pass in any number of bytes. So we need to keep track - * of block boundaries. We save excess bytes between calls in "obj". - * We also need to determine which bytes are padding, and remove - * them from the output. We can only do this step when we know we - * have the final block of data. PKCS #7 specifies that the padding - * used for a block cipher is a string of bytes, each of whose value is - * the same as the length of the padding, and that all data is padded. - * (Even data that starts out with an exact multiple of blocks gets - * added to it another block, all of which is padding.) - */ -SECStatus -sec_PKCS7Decrypt (sec_PKCS7CipherObject *obj, unsigned char *output, - unsigned int *output_len_p, unsigned int max_output_len, - const unsigned char *input, unsigned int input_len, - PRBool final) -{ - int blocks, bsize, pcount, padsize; - unsigned int max_needed, ifraglen, ofraglen, output_len; - unsigned char *pbuf; - SECStatus rv; - - PORT_Assert (! obj->encrypt); - - /* - * Check that we have enough room for the output. Our caller should - * already handle this; failure is really an internal error (i.e. bug). - */ - max_needed = sec_PKCS7DecryptLength (obj, input_len, final); - PORT_Assert (max_output_len >= max_needed); - if (max_output_len < max_needed) { - /* PORT_SetError (XXX); */ - return SECFailure; - } - - /* - * hardware encryption does not like small decryption sizes here, so we - * allow both blocking and padding. - */ - bsize = obj->block_size; - padsize = obj->pad_size; - - /* - * When no blocking or padding work to do, we can simply call the - * cipher function and we are done. - */ - if (bsize == 0) { - return (* obj->doit) (obj->cx, output, output_len_p, max_output_len, - input, input_len); - } - - pcount = obj->pending_count; - pbuf = obj->pending_buf; - - output_len = 0; - - if (pcount) { - /* - * Try to fill in an entire block, starting with the bytes - * we already have saved away. - */ - while (input_len && pcount < bsize) { - pbuf[pcount++] = *input++; - input_len--; - } - /* - * If we have at most a whole block and this is not our last call, - * then we are done for now. (We do not try to decrypt a lone - * single block because we cannot interpret the padding bytes - * until we know we are handling the very last block of all input.) - */ - if (input_len == 0 && !final) { - obj->pending_count = pcount; - if (output_len_p) - *output_len_p = 0; - return SECSuccess; - } - /* - * Given the logic above, we expect to have a full block by now. - * If we do not, there is something wrong, either with our own - * logic or with (length of) the data given to us. - */ - PORT_Assert ((padsize == 0) || (pcount % padsize) == 0); - if ((padsize != 0) && (pcount % padsize) != 0) { - PORT_Assert (final); - PORT_SetError (SEC_ERROR_BAD_DATA); - return SECFailure; - } - /* - * Decrypt the block. - */ - rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, - pbuf, pcount); - if (rv != SECSuccess) - return rv; - - /* - * For now anyway, all of our ciphers have the same number of - * bytes of output as they do input. If this ever becomes untrue, - * then sec_PKCS7DecryptLength needs to be made smarter! - */ - PORT_Assert (ofraglen == pcount); - - /* - * Account for the bytes now in output. - */ - max_output_len -= ofraglen; - output_len += ofraglen; - output += ofraglen; - } - - /* - * If this is our last call, we expect to have an exact number of - * blocks left to be decrypted; we will decrypt them all. - * - * If not our last call, we always save between 1 and bsize bytes - * until next time. (We must do this because we cannot be sure - * that none of the decrypted bytes are padding bytes until we - * have at least another whole block of data. You cannot tell by - * looking -- the data could be anything -- you can only tell by - * context, knowing you are looking at the last block.) We could - * decrypt a whole block now but it is easier if we just treat it - * the same way we treat partial block bytes. - */ - if (final) { - if (padsize) { - blocks = input_len / padsize; - ifraglen = blocks * padsize; - } else ifraglen = input_len; - PORT_Assert (ifraglen == input_len); - - if (ifraglen != input_len) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return SECFailure; - } - } else { - blocks = (input_len - 1) / bsize; - ifraglen = blocks * bsize; - PORT_Assert (ifraglen < input_len); - - pcount = input_len - ifraglen; - PORT_Memcpy (pbuf, input + ifraglen, pcount); - obj->pending_count = pcount; - } - - if (ifraglen) { - rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, - input, ifraglen); - if (rv != SECSuccess) - return rv; - - /* - * For now anyway, all of our ciphers have the same number of - * bytes of output as they do input. If this ever becomes untrue, - * then sec_PKCS7DecryptLength needs to be made smarter! - */ - PORT_Assert (ifraglen == ofraglen); - if (ifraglen != ofraglen) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return SECFailure; - } - - output_len += ofraglen; - } else { - ofraglen = 0; - } - - /* - * If we just did our very last block, "remove" the padding by - * adjusting the output length. - */ - if (final && (padsize != 0)) { - unsigned int padlen = *(output + ofraglen - 1); - PORT_Assert (padlen > 0 && padlen <= padsize); - if (padlen == 0 || padlen > padsize) { - PORT_SetError (SEC_ERROR_BAD_DATA); - return SECFailure; - } - output_len -= padlen; - } - - PORT_Assert (output_len_p != NULL || output_len == 0); - if (output_len_p != NULL) - *output_len_p = output_len; - - return SECSuccess; -} - -/* - * Encrypt a given length of input buffer (starting at "input" and - * containing "input_len" bytes), placing the encrypted bytes in - * "output" and storing the output length in "*output_len_p". - * "obj" is the return value from sec_PKCS7CreateEncryptObject. - * When "final" is true, this is the last of the data to be encrypted. - * - * This is much more complicated than it sounds when the cipher is - * a block-type, meaning that the encryption function will only - * operate on whole blocks. But our caller is operating stream-wise, - * and can pass in any number of bytes. So we need to keep track - * of block boundaries. We save excess bytes between calls in "obj". - * We also need to add padding bytes at the end. PKCS #7 specifies - * that the padding used for a block cipher is a string of bytes, - * each of whose value is the same as the length of the padding, - * and that all data is padded. (Even data that starts out with - * an exact multiple of blocks gets added to it another block, - * all of which is padding.) - * - * XXX I would kind of like to combine this with the function above - * which does decryption, since they have a lot in common. But the - * tricky parts about padding and filling blocks would be much - * harder to read that way, so I left them separate. At least for - * now until it is clear that they are right. - */ -SECStatus -sec_PKCS7Encrypt (sec_PKCS7CipherObject *obj, unsigned char *output, - unsigned int *output_len_p, unsigned int max_output_len, - const unsigned char *input, unsigned int input_len, - PRBool final) -{ - int blocks, bsize, padlen, pcount, padsize; - unsigned int max_needed, ifraglen, ofraglen, output_len; - unsigned char *pbuf; - SECStatus rv; - - PORT_Assert (obj->encrypt); - - /* - * Check that we have enough room for the output. Our caller should - * already handle this; failure is really an internal error (i.e. bug). - */ - max_needed = sec_PKCS7EncryptLength (obj, input_len, final); - PORT_Assert (max_output_len >= max_needed); - if (max_output_len < max_needed) { - /* PORT_SetError (XXX); */ - return SECFailure; - } - - bsize = obj->block_size; - padsize = obj->pad_size; - - /* - * When no blocking and padding work to do, we can simply call the - * cipher function and we are done. - */ - if (bsize == 0) { - return (* obj->doit) (obj->cx, output, output_len_p, max_output_len, - input, input_len); - } - - pcount = obj->pending_count; - pbuf = obj->pending_buf; - - output_len = 0; - - if (pcount) { - /* - * Try to fill in an entire block, starting with the bytes - * we already have saved away. - */ - while (input_len && pcount < bsize) { - pbuf[pcount++] = *input++; - input_len--; - } - /* - * If we do not have a full block and we know we will be - * called again, then we are done for now. - */ - if (pcount < bsize && !final) { - obj->pending_count = pcount; - if (output_len_p != NULL) - *output_len_p = 0; - return SECSuccess; - } - /* - * If we have a whole block available, encrypt it. - */ - if ((padsize == 0) || (pcount % padsize) == 0) { - rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, - pbuf, pcount); - if (rv != SECSuccess) - return rv; - - /* - * For now anyway, all of our ciphers have the same number of - * bytes of output as they do input. If this ever becomes untrue, - * then sec_PKCS7EncryptLength needs to be made smarter! - */ - PORT_Assert (ofraglen == pcount); - - /* - * Account for the bytes now in output. - */ - max_output_len -= ofraglen; - output_len += ofraglen; - output += ofraglen; - - pcount = 0; - } - } - - if (input_len) { - PORT_Assert (pcount == 0); - - blocks = input_len / bsize; - ifraglen = blocks * bsize; - - if (ifraglen) { - rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, - input, ifraglen); - if (rv != SECSuccess) - return rv; - - /* - * For now anyway, all of our ciphers have the same number of - * bytes of output as they do input. If this ever becomes untrue, - * then sec_PKCS7EncryptLength needs to be made smarter! - */ - PORT_Assert (ifraglen == ofraglen); - - max_output_len -= ofraglen; - output_len += ofraglen; - output += ofraglen; - } - - pcount = input_len - ifraglen; - PORT_Assert (pcount < bsize); - if (pcount) - PORT_Memcpy (pbuf, input + ifraglen, pcount); - } - - if (final) { - padlen = padsize - (pcount % padsize); - PORT_Memset (pbuf + pcount, padlen, padlen); - rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, - pbuf, pcount+padlen); - if (rv != SECSuccess) - return rv; - - /* - * For now anyway, all of our ciphers have the same number of - * bytes of output as they do input. If this ever becomes untrue, - * then sec_PKCS7EncryptLength needs to be made smarter! - */ - PORT_Assert (ofraglen == (pcount+padlen)); - output_len += ofraglen; - } else { - obj->pending_count = pcount; - } - - PORT_Assert (output_len_p != NULL || output_len == 0); - if (output_len_p != NULL) - *output_len_p = output_len; - - return SECSuccess; -} - -/* - * End of cipher stuff. - * ------------------------------------------------------------------- - */ - - -/* - * ------------------------------------------------------------------- - * XXX The following Attribute stuff really belongs elsewhere. - * The Attribute type is *not* part of pkcs7 but rather X.501. - * But for now, since PKCS7 is the only customer of attributes, - * we define them here. Once there is a use outside of PKCS7, - * then change the attribute types and functions from internal - * to external naming convention, and move them elsewhere! - */ - -/* - * Look through a set of attributes and find one that matches the - * specified object ID. If "only" is true, then make sure that - * there is not more than one attribute of the same type. Otherwise, - * just return the first one found. (XXX Does anybody really want - * that first-found behavior? It was like that when I found it...) - */ -SEC_PKCS7Attribute * -sec_PKCS7FindAttribute (SEC_PKCS7Attribute **attrs, SECOidTag oidtag, - PRBool only) -{ - SECOidData *oid; - SEC_PKCS7Attribute *attr1, *attr2; - - if (attrs == NULL) - return NULL; - - oid = SECOID_FindOIDByTag(oidtag); - if (oid == NULL) - return NULL; - - while ((attr1 = *attrs++) != NULL) { - if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data, - oid->oid.data, - oid->oid.len) == 0) - break; - } - - if (attr1 == NULL) - return NULL; - - if (!only) - return attr1; - - while ((attr2 = *attrs++) != NULL) { - if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data, - oid->oid.data, - oid->oid.len) == 0) - break; - } - - if (attr2 != NULL) - return NULL; - - return attr1; -} - - -/* - * Return the single attribute value, doing some sanity checking first: - * - Multiple values are *not* expected. - * - Empty values are *not* expected. - */ -SECItem * -sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr) -{ - SECItem *value; - - if (attr == NULL) - return NULL; - - value = attr->values[0]; - - if (value == NULL || value->data == NULL || value->len == 0) - return NULL; - - if (attr->values[1] != NULL) - return NULL; - - return value; -} - -static const SEC_ASN1Template * -sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS7Attribute *attribute; - SECOidData *oiddata; - PRBool encoded; - - PORT_Assert (src_or_dest != NULL); - if (src_or_dest == NULL) - return NULL; - - attribute = (SEC_PKCS7Attribute*)src_or_dest; - - if (encoding && attribute->encoded) - return SEC_AnyTemplate; - - oiddata = attribute->typeTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&attribute->type); - attribute->typeTag = oiddata; - } - - if (oiddata == NULL) { - encoded = PR_TRUE; - theTemplate = SEC_AnyTemplate; - } else { - switch (oiddata->offset) { - default: - encoded = PR_TRUE; - theTemplate = SEC_AnyTemplate; - break; - case SEC_OID_PKCS9_EMAIL_ADDRESS: - case SEC_OID_RFC1274_MAIL: - case SEC_OID_PKCS9_UNSTRUCTURED_NAME: - encoded = PR_FALSE; - theTemplate = SEC_IA5StringTemplate; - break; - case SEC_OID_PKCS9_CONTENT_TYPE: - encoded = PR_FALSE; - theTemplate = SEC_ObjectIDTemplate; - break; - case SEC_OID_PKCS9_MESSAGE_DIGEST: - encoded = PR_FALSE; - theTemplate = SEC_OctetStringTemplate; - break; - case SEC_OID_PKCS9_SIGNING_TIME: - encoded = PR_FALSE; - theTemplate = SEC_UTCTimeTemplate; - break; - /* XXX Want other types here, too */ - } - } - - if (encoding) { - /* - * If we are encoding and we think we have an already-encoded value, - * then the code which initialized this attribute should have set - * the "encoded" property to true (and we would have returned early, - * up above). No devastating error, but that code should be fixed. - * (It could indicate that the resulting encoded bytes are wrong.) - */ - PORT_Assert (!encoded); - } else { - /* - * We are decoding; record whether the resulting value is - * still encoded or not. - */ - attribute->encoded = encoded; - } - return theTemplate; -} - -static SEC_ChooseASN1TemplateFunc sec_attr_chooser - = sec_attr_choose_attr_value_template; - -static const SEC_ASN1Template sec_pkcs7_attribute_template[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7Attribute) }, - { SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS7Attribute,type) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7Attribute,values), - &sec_attr_chooser }, - { 0 } -}; - -static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = { - { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template }, -}; - -/* - * If you are wondering why this routine does not reorder the attributes - * first, and might be tempted to make it do so, see the comment by the - * call to ReorderAttributes in p7encode.c. (Or, see who else calls this - * and think long and hard about the implications of making it always - * do the reordering.) - */ -SECItem * -sec_PKCS7EncodeAttributes (PRArenaPool *poolp, SECItem *dest, void *src) -{ - return SEC_ASN1EncodeItem (poolp, dest, src, - sec_pkcs7_set_of_attribute_template); -} - -/* - * Make sure that the order of the attributes guarantees valid DER - * (which must be in lexigraphically ascending order for a SET OF); - * if reordering is necessary it will be done in place (in attrs). - */ -SECStatus -sec_PKCS7ReorderAttributes (SEC_PKCS7Attribute **attrs) -{ - PRArenaPool *poolp; - int num_attrs, i, j, pass, besti; - SECItem **enc_attrs; - SEC_PKCS7Attribute **new_attrs; - - /* - * I think we should not be called with NULL. But if we are, - * call it a success anyway, because the order *is* okay. - */ - PORT_Assert (attrs != NULL); - if (attrs == NULL) - return SECSuccess; - - /* - * Count how many attributes we are dealing with here. - */ - num_attrs = 0; - while (attrs[num_attrs] != NULL) - num_attrs++; - - /* - * Again, I think we should have some attributes here. - * But if we do not, or if there is only one, then call it - * a success because it also already has a fine order. - */ - PORT_Assert (num_attrs); - if (num_attrs == 0 || num_attrs == 1) - return SECSuccess; - - /* - * Allocate an arena for us to work with, so it is easy to - * clean up all of the memory (fairly small pieces, really). - */ - poolp = PORT_NewArena (1024); /* XXX what is right value? */ - if (poolp == NULL) - return SECFailure; /* no memory; nothing we can do... */ - - /* - * Allocate arrays to hold the individual encodings which we will use - * for comparisons and the reordered attributes as they are sorted. - */ - enc_attrs=(SECItem**)PORT_ArenaZAlloc(poolp, num_attrs*sizeof(SECItem *)); - new_attrs = (SEC_PKCS7Attribute**)PORT_ArenaZAlloc (poolp, - num_attrs * sizeof(SEC_PKCS7Attribute *)); - if (enc_attrs == NULL || new_attrs == NULL) { - PORT_FreeArena (poolp, PR_FALSE); - return SECFailure; - } - - /* - * DER encode each individual attribute. - */ - for (i = 0; i < num_attrs; i++) { - enc_attrs[i] = SEC_ASN1EncodeItem (poolp, NULL, attrs[i], - sec_pkcs7_attribute_template); - if (enc_attrs[i] == NULL) { - PORT_FreeArena (poolp, PR_FALSE); - return SECFailure; - } - } - - /* - * Now compare and sort them; this is not the most efficient sorting - * method, but it is just fine for the problem at hand, because the - * number of attributes is (always) going to be small. - */ - for (pass = 0; pass < num_attrs; pass++) { - /* - * Find the first not-yet-accepted attribute. (Once one is - * sorted into the other array, it is cleared from enc_attrs.) - */ - for (i = 0; i < num_attrs; i++) { - if (enc_attrs[i] != NULL) - break; - } - PORT_Assert (i < num_attrs); - besti = i; - - /* - * Find the lowest (lexigraphically) encoding. One that is - * shorter than all the rest is known to be "less" because each - * attribute is of the same type (a SEQUENCE) and so thus the - * first octet of each is the same, and the second octet is - * the length (or the length of the length with the high bit - * set, followed by the length, which also works out to always - * order the shorter first). Two (or more) that have the - * same length need to be compared byte by byte until a mismatch - * is found. - */ - for (i = besti + 1; i < num_attrs; i++) { - if (enc_attrs[i] == NULL) /* slot already handled */ - continue; - - if (enc_attrs[i]->len != enc_attrs[besti]->len) { - if (enc_attrs[i]->len < enc_attrs[besti]->len) - besti = i; - continue; - } - - for (j = 0; j < enc_attrs[i]->len; j++) { - if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) { - besti = i; - break; - } - } - - /* - * For this not to be true, we would have to have encountered - * two *identical* attributes, which I think we should not see. - * So assert if it happens, but even if it does, let it go - * through; the ordering of the two does not matter. - */ - PORT_Assert (j < enc_attrs[i]->len); - } - - /* - * Now we have found the next-lowest one; copy it over and - * remove it from enc_attrs. - */ - new_attrs[pass] = attrs[besti]; - enc_attrs[besti] = NULL; - } - - /* - * Now new_attrs has the attributes in the order we want; - * copy them back into the attrs array we started with. - */ - for (i = 0; i < num_attrs; i++) - attrs[i] = new_attrs[i]; - - PORT_FreeArena (poolp, PR_FALSE); - return SECSuccess; -} - -/* - * End of attribute stuff. - * ------------------------------------------------------------------- - */ - - -/* - * Templates and stuff. Keep these at the end of the file. - */ - -/* forward declaration */ -static const SEC_ASN1Template * -sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding); - -static SEC_ChooseASN1TemplateFunc sec_pkcs7_chooser - = sec_pkcs7_choose_content_template; - -const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7ContentInfo) }, - { SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS7ContentInfo,contentType) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM - | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS7ContentInfo,content), - &sec_pkcs7_chooser }, - { 0 } -}; - -/* XXX These names should change from external to internal convention. */ - -static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7SignerInfo) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7SignerInfo,version) }, - { SEC_ASN1_POINTER, - offsetof(SEC_PKCS7SignerInfo,issuerAndSN), - CERT_IssuerAndSNTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7SignerInfo,digestAlg), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS7SignerInfo,authAttr), - sec_pkcs7_set_of_attribute_template }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7SignerInfo,digestEncAlg), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7SignerInfo,encDigest) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS7SignerInfo,unAuthAttr), - sec_pkcs7_set_of_attribute_template }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7SignedData) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7SignedData,version) }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7SignedData,digestAlgorithms), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7SignedData,contentInfo), - sec_PKCS7ContentInfoTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS7SignedData,rawCerts), - SEC_SetOfAnyTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS7SignedData,crls), - CERT_SetOfSignedCrlTemplate }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7SignedData,signerInfos), - SEC_PKCS7SignerInfoTemplate }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = { - { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate } -}; - -static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7RecipientInfo) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7RecipientInfo,version) }, - { SEC_ASN1_POINTER, - offsetof(SEC_PKCS7RecipientInfo,issuerAndSN), - CERT_IssuerAndSNTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7RecipientInfo,keyEncAlg), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7RecipientInfo,encKey) }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) }, - { SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS7EncryptedContentInfo,contentType) }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7EncryptedContentInfo,contentEncAlg), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS7EncryptedContentInfo,encContent), - SEC_OctetStringTemplate }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7EnvelopedData) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7EnvelopedData,version) }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7EnvelopedData,recipientInfos), - SEC_PKCS7RecipientInfoTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7EnvelopedData,encContentInfo), - SEC_PKCS7EncryptedContentInfoTemplate }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = { - { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate } -}; - -static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7SignedAndEnvelopedData,version) }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7SignedAndEnvelopedData,recipientInfos), - SEC_PKCS7RecipientInfoTemplate }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7SignedAndEnvelopedData,digestAlgorithms), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7SignedAndEnvelopedData,encContentInfo), - SEC_PKCS7EncryptedContentInfoTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS7SignedAndEnvelopedData,rawCerts), - SEC_SetOfAnyTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS7SignedAndEnvelopedData,crls), - CERT_SetOfSignedCrlTemplate }, - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS7SignedAndEnvelopedData,signerInfos), - SEC_PKCS7SignerInfoTemplate }, - { 0 } -}; - -static const SEC_ASN1Template -SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = { - { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate } -}; - -static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7DigestedData) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7DigestedData,version) }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7DigestedData,digestAlg), - SECOID_AlgorithmIDTemplate }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7DigestedData,contentInfo), - sec_PKCS7ContentInfoTemplate }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7DigestedData,digest) }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = { - { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate } -}; - -static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, - 0, NULL, sizeof(SEC_PKCS7EncryptedData) }, - { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS7EncryptedData,version) }, - { SEC_ASN1_INLINE, - offsetof(SEC_PKCS7EncryptedData,encContentInfo), - SEC_PKCS7EncryptedContentInfoTemplate }, - { 0 } -}; - -static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = { - { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate } -}; - -const SEC_ASN1Template SEC_SMIMEKEAParamTemplateSkipjack[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7SMIMEKEAParameters) }, - { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorKEAKey) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorRA) }, - { 0 } -}; - -const SEC_ASN1Template SEC_SMIMEKEAParamTemplateNoSkipjack[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7SMIMEKEAParameters) }, - { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorKEAKey) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorRA) }, - { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , - offsetof(SEC_PKCS7SMIMEKEAParameters,nonSkipjackIV) }, - { 0 } -}; - -const SEC_ASN1Template SEC_SMIMEKEAParamTemplateAllParams[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS7SMIMEKEAParameters) }, - { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorKEAKey) }, - { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS7SMIMEKEAParameters,originatorRA) }, - { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , - offsetof(SEC_PKCS7SMIMEKEAParameters,nonSkipjackIV) }, - { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , - offsetof(SEC_PKCS7SMIMEKEAParameters,bulkKeySize) }, - { 0 } -}; - -const SEC_ASN1Template* -sec_pkcs7_get_kea_template(SECKEATemplateSelector whichTemplate) -{ - const SEC_ASN1Template *returnVal = NULL; - - switch(whichTemplate) - { - case SECKEAUsesNonSkipjack: - returnVal = SEC_SMIMEKEAParamTemplateNoSkipjack; - break; - case SECKEAUsesSkipjack: - returnVal = SEC_SMIMEKEAParamTemplateSkipjack; - break; - case SECKEAUsesNonSkipjackWithPaddedEncKey: - default: - returnVal = SEC_SMIMEKEAParamTemplateAllParams; - break; - } - return returnVal; -} - -static const SEC_ASN1Template * -sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS7ContentInfo *cinfo; - SECOidTag kind; - - PORT_Assert (src_or_dest != NULL); - if (src_or_dest == NULL) - return NULL; - - cinfo = (SEC_PKCS7ContentInfo*)src_or_dest; - kind = SEC_PKCS7ContentType (cinfo); - switch (kind) { - default: - theTemplate = SEC_PointerToAnyTemplate; - break; - case SEC_OID_PKCS7_DATA: - theTemplate = SEC_PointerToOctetStringTemplate; - break; - case SEC_OID_PKCS7_SIGNED_DATA: - theTemplate = SEC_PointerToPKCS7SignedDataTemplate; - break; - case SEC_OID_PKCS7_ENVELOPED_DATA: - theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate; - break; - case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: - theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate; - break; - case SEC_OID_PKCS7_DIGESTED_DATA: - theTemplate = SEC_PointerToPKCS7DigestedDataTemplate; - break; - case SEC_OID_PKCS7_ENCRYPTED_DATA: - theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate; - break; - } - return theTemplate; -} - -/* - * End of templates. Do not add stuff after this; put new code - * up above the start of the template definitions. - */ |