Index: mozilla/security/nss/lib/pkcs7/p7local.c |
=================================================================== |
--- mozilla/security/nss/lib/pkcs7/p7local.c (revision 191424) |
+++ mozilla/security/nss/lib/pkcs7/p7local.c (working copy) |
@@ -1,1321 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-/* |
- * 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: p7local.c,v 1.16 2012/04/25 14:50:06 gerv%gerv.net Exp $ |
- */ |
- |
-#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]; |
-}; |
- |
-SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) |
-SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) |
-SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
-SEC_ASN1_MKSUB(SEC_OctetStringTemplate) |
-SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate) |
- |
-/* |
- * 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 cryptoMechType; |
- PK11SlotInfo *slot; |
- SECItem *param = NULL; |
- |
- 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)) { |
- SECItem *pwitem; |
- |
- pwitem = (SECItem *)PK11_GetSymKeyUserData(key); |
- if (!pwitem) { |
- PORT_Free(result); |
- return NULL; |
- } |
- |
- cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); |
- if (cryptoMechType == CKM_INVALID_MECHANISM) { |
- PORT_Free(result); |
- SECITEM_FreeItem(param,PR_TRUE); |
- return NULL; |
- } |
- } else { |
- cryptoMechType = PK11_AlgtagToMechanism(algtag); |
- param = PK11_ParamFromAlgid(algid); |
- if (param == NULL) { |
- PORT_Free(result); |
- return NULL; |
- } |
- } |
- |
- result->pad_size = PK11_GetBlockSize(cryptoMechType, param); |
- slot = PK11_GetSlotFromKey(key); |
- result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; |
- PK11_FreeSlot(slot); |
- ciphercx = PK11_CreateContextBySymKey(cryptoMechType, 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; |
- SECStatus rv; |
- CK_MECHANISM_TYPE cryptoMechType; |
- PK11SlotInfo *slot; |
- SECItem *param = NULL; |
- PRBool needToEncodeAlgid = PR_FALSE; |
- |
- 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)) { |
- SECItem *pwitem; |
- |
- pwitem = (SECItem *)PK11_GetSymKeyUserData(key); |
- if (!pwitem) { |
- PORT_Free(result); |
- return NULL; |
- } |
- |
- cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); |
- if (cryptoMechType == CKM_INVALID_MECHANISM) { |
- PORT_Free(result); |
- SECITEM_FreeItem(param,PR_TRUE); |
- return NULL; |
- } |
- } else { |
- cryptoMechType = PK11_AlgtagToMechanism(algtag); |
- param = PK11_GenerateNewParam(cryptoMechType, key); |
- if (param == NULL) { |
- PORT_Free(result); |
- return NULL; |
- } |
- needToEncodeAlgid = PR_TRUE; |
- } |
- |
- result->pad_size = PK11_GetBlockSize(cryptoMechType,param); |
- slot = PK11_GetSlotFromKey(key); |
- result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; |
- PK11_FreeSlot(slot); |
- ciphercx = PK11_CreateContextBySymKey(cryptoMechType, 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) { |
- PORT_Free (result); |
- SECITEM_FreeItem(param,PR_TRUE); |
- 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); |
- 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_ASN1_GET(SEC_AnyTemplate); |
- |
- oiddata = attribute->typeTag; |
- if (oiddata == NULL) { |
- oiddata = SECOID_FindOID(&attribute->type); |
- attribute->typeTag = oiddata; |
- } |
- |
- if (oiddata == NULL) { |
- encoded = PR_TRUE; |
- theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); |
- } else { |
- switch (oiddata->offset) { |
- default: |
- encoded = PR_TRUE; |
- theTemplate = SEC_ASN1_GET(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_ASN1_GET(SEC_IA5StringTemplate); |
- break; |
- case SEC_OID_PKCS9_CONTENT_TYPE: |
- encoded = PR_FALSE; |
- theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate); |
- break; |
- case SEC_OID_PKCS9_MESSAGE_DIGEST: |
- encoded = PR_FALSE; |
- theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); |
- break; |
- case SEC_OID_PKCS9_SIGNING_TIME: |
- encoded = PR_FALSE; |
- theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate); |
- 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 const SEC_ASN1TemplateChooserPtr 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, pass, besti; |
- unsigned int j; |
- 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 const SEC_ASN1TemplateChooserPtr 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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7SignerInfo,issuerAndSN), |
- SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, |
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7SignerInfo,digestAlg), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7SignerInfo,digestEncAlg), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7SignedData,digestAlgorithms), |
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
- { SEC_ASN1_INLINE, |
- offsetof(SEC_PKCS7SignedData,contentInfo), |
- sec_PKCS7ContentInfoTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
- SEC_ASN1_XTRN | 0, |
- offsetof(SEC_PKCS7SignedData,rawCerts), |
- SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
- SEC_ASN1_XTRN | 1, |
- offsetof(SEC_PKCS7SignedData,crls), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7RecipientInfo,issuerAndSN), |
- SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, |
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7RecipientInfo,keyEncAlg), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7EncryptedContentInfo,contentEncAlg), |
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC | |
- SEC_ASN1_XTRN | 0, |
- offsetof(SEC_PKCS7EncryptedContentInfo,encContent), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7SignedAndEnvelopedData,digestAlgorithms), |
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
- { SEC_ASN1_INLINE, |
- offsetof(SEC_PKCS7SignedAndEnvelopedData,encContentInfo), |
- SEC_PKCS7EncryptedContentInfoTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
- SEC_ASN1_XTRN | 0, |
- offsetof(SEC_PKCS7SignedAndEnvelopedData,rawCerts), |
- SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
- SEC_ASN1_XTRN | 1, |
- offsetof(SEC_PKCS7SignedAndEnvelopedData,crls), |
- SEC_ASN1_SUB(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 | SEC_ASN1_XTRN, |
- offsetof(SEC_PKCS7DigestedData,digestAlg), |
- SEC_ASN1_SUB(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 } |
-}; |
- |
-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_ASN1_GET(SEC_PointerToAnyTemplate); |
- break; |
- case SEC_OID_PKCS7_DATA: |
- theTemplate = SEC_ASN1_GET(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. |
- */ |