Back to index

lightning-sunbird  0.9+nobinonly
Functions | Variables
cmslocal.h File Reference
#include "cms.h"
#include "cmsreclist.h"
#include "secasn1t.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

SEC_BEGIN_PROTOS
NSSCMSCipherContext * 
NSS_CMSCipherContext_StartDecrypt (PK11SymKey *key, SECAlgorithmID *algid)
NSSCMSCipherContext * NSS_CMSCipherContext_StartEncrypt (PRArenaPool *poolp, PK11SymKey *key, SECAlgorithmID *algid)
void NSS_CMSCipherContext_Destroy (NSSCMSCipherContext *cc)
unsigned int NSS_CMSCipherContext_DecryptLength (NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
unsigned int NSS_CMSCipherContext_EncryptLength (NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
SECStatus NSS_CMSCipherContext_Decrypt (NSSCMSCipherContext *cc, unsigned char *output, unsigned int *output_len_p, unsigned int max_output_len, const unsigned char *input, unsigned int input_len, PRBool final)
SECStatus NSS_CMSCipherContext_Encrypt (NSSCMSCipherContext *cc, unsigned char *output, unsigned int *output_len_p, unsigned int max_output_len, const unsigned char *input, unsigned int input_len, PRBool final)
SECStatus NSS_CMSUtil_EncryptSymKey_RSA (PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key, SECItem *encKey)
SECStatus NSS_CMSUtil_EncryptSymKey_RSAPubKey (PLArenaPool *poolp, SECKEYPublicKey *publickey, PK11SymKey *bulkkey, SECItem *encKey)
PK11SymKey * NSS_CMSUtil_DecryptSymKey_RSA (SECKEYPrivateKey *privkey, SECItem *encKey, SECOidTag bulkalgtag)
SECStatus NSS_CMSUtil_EncryptSymKey_MISSI (PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key, SECOidTag symalgtag, SECItem *encKey, SECItem **pparams, void *pwfn_arg)
PK11SymKey * NSS_CMSUtil_DecryptSymKey_MISSI (SECKEYPrivateKey *privkey, SECItem *encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg)
SECStatus NSS_CMSUtil_EncryptSymKey_ESDH (PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key, SECItem *encKey, SECItem **ukm, SECAlgorithmID *keyEncAlg, SECItem *originatorPubKey)
PK11SymKey * NSS_CMSUtil_DecryptSymKey_ESDH (SECKEYPrivateKey *privkey, SECItem *encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg)
NSSCMSRecipient ** nss_cms_recipient_list_create (NSSCMSRecipientInfo **recipientinfos)
void nss_cms_recipient_list_destroy (NSSCMSRecipient **recipient_list)
NSSCMSRecipientEncryptedKey * NSS_CMSRecipientEncryptedKey_Create (PLArenaPool *poolp)
void ** NSS_CMSArray_Alloc (PRArenaPool *poolp, int n)
SECStatus NSS_CMSArray_Add (PRArenaPool *poolp, void ***array, void *obj)
PRBool NSS_CMSArray_IsEmpty (void **array)
int NSS_CMSArray_Count (void **array)
void NSS_CMSArray_Sort (void **primary, int(*compare)(void *, void *), void **secondary, void **tertiary)
NSSCMSAttribute * NSS_CMSAttribute_Create (PRArenaPool *poolp, SECOidTag oidtag, SECItem *value, PRBool encoded)
SECStatus NSS_CMSAttribute_AddValue (PLArenaPool *poolp, NSSCMSAttribute *attr, SECItem *value)
SECOidTag NSS_CMSAttribute_GetType (NSSCMSAttribute *attr)
SECItem * NSS_CMSAttribute_GetValue (NSSCMSAttribute *attr)
PRBool NSS_CMSAttribute_CompareValue (NSSCMSAttribute *attr, SECItem *av)
SECItem * NSS_CMSAttributeArray_Encode (PRArenaPool *poolp, NSSCMSAttribute ***attrs, SECItem *dest)
SECStatus NSS_CMSAttributeArray_Reorder (NSSCMSAttribute **attrs)
NSSCMSAttribute * NSS_CMSAttributeArray_FindAttrByOidTag (NSSCMSAttribute **attrs, SECOidTag oidtag, PRBool only)
SECStatus NSS_CMSAttributeArray_AddAttr (PLArenaPool *poolp, NSSCMSAttribute ***attrs, NSSCMSAttribute *attr)
SECStatus NSS_CMSAttributeArray_SetAttr (PLArenaPool *poolp, NSSCMSAttribute ***attrs, SECOidTag type, SECItem *value, PRBool encoded)
SECStatus NSS_CMSSignedData_AddTempCertificate (NSSCMSSignedData *sigd, CERTCertificate *cert)

Variables

const SEC_ASN1Template NSSCMSContentInfoTemplate []

Function Documentation

NSSCMSRecipient** nss_cms_recipient_list_create ( NSSCMSRecipientInfo **  recipientinfos)

Definition at line 147 of file cmsreclist.c.

{
    int count, rv;
    NSSCMSRecipient **recipient_list;

    /* count the number of recipient identifiers */
    count = nss_cms_recipients_traverse(recipientinfos, NULL);
    if (count <= 0) {
       /* no recipients? */
       PORT_SetError(SEC_ERROR_BAD_DATA);
#if 0
       PORT_SetErrorString("Cannot find recipient data in envelope.");
#endif
       return NULL;
    }

    /* allocate an array of pointers */
    recipient_list = (NSSCMSRecipient **)
                  PORT_ZAlloc((count + 1) * sizeof(NSSCMSRecipient *));
    if (recipient_list == NULL)
       return NULL;

    /* now fill in the recipient_list */
    rv = nss_cms_recipients_traverse(recipientinfos, recipient_list);
    if (rv < 0) {
       nss_cms_recipient_list_destroy(recipient_list);
       return NULL;
    }
    return recipient_list;
}

Here is the caller graph for this function:

void nss_cms_recipient_list_destroy ( NSSCMSRecipient **  recipient_list)

Definition at line 179 of file cmsreclist.c.

{
    int i;
    NSSCMSRecipient *recipient;

    for (i=0; recipient_list[i] != NULL; i++) {
       recipient = recipient_list[i];
       if (recipient->cert)
           CERT_DestroyCertificate(recipient->cert);
       if (recipient->privkey)
           SECKEY_DestroyPrivateKey(recipient->privkey);
       if (recipient->slot)
           PK11_FreeSlot(recipient->slot);
       PORT_Free(recipient);
    }
    PORT_Free(recipient_list);
}

Here is the caller graph for this function:

SECStatus NSS_CMSArray_Add ( PRArenaPool poolp,
void ***  array,
void obj 
)

Definition at line 75 of file cmsarray.c.

{
    void **p;
    int n;
    void **dest;

    PORT_Assert(array != NULL);
    if (array == NULL)
       return SECFailure;

    if (*array == NULL) {
       dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *));
       n = 0;
    } else {
       n = 0; p = *array;
       while (*p++)
           n++;
       dest = (void **)PORT_ArenaGrow (poolp, 
                           *array,
                           (n + 1) * sizeof(void *),
                           (n + 2) * sizeof(void *));
    }

    if (dest == NULL)
       return SECFailure;

    dest[n] = obj;
    dest[n+1] = NULL;
    *array = dest;
    return SECSuccess;
}
void** NSS_CMSArray_Alloc ( PRArenaPool poolp,
int  n 
)

Definition at line 64 of file cmsarray.c.

{
    return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *));
}
int NSS_CMSArray_Count ( void **  array)

Definition at line 120 of file cmsarray.c.

{
    int n = 0;

    if (array == NULL)
       return 0;

    while (*array++ != NULL)
       n++;

    return n;
}

Definition at line 111 of file cmsarray.c.

{
    return (array == NULL || array[0] == NULL);
}
void NSS_CMSArray_Sort ( void **  primary,
int(*)(void *, void *)  compare,
void **  secondary,
void **  tertiary 
)

Definition at line 146 of file cmsarray.c.

{
    int n, i, limit, lastxchg;
    void *tmp;

    n = NSS_CMSArray_Count(primary);

    PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n);
    PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n);
    
    if (n <= 1)      /* ordering is fine */
       return;
    
    /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */
    limit = n - 1;
    while (1) {
       lastxchg = 0;
       for (i = 0; i < limit; i++) {
           if ((*compare)(primary[i], primary[i+1]) > 0) {
              /* exchange the neighbours */
              tmp = primary[i+1];
              primary[i+1] = primary[i];
              primary[i] = tmp;
              if (secondary) {            /* secondary array? */
                  tmp = secondary[i+1];   /* exchange there as well */
                  secondary[i+1] = secondary[i];
                  secondary[i] = tmp;
              }
              if (tertiary) {                    /* tertiary array? */
                  tmp = tertiary[i+1];    /* exchange there as well */
                  tertiary[i+1] = tertiary[i];
                  tertiary[i] = tmp;
              }
              lastxchg = i+1;      /* index of the last element bubbled up */
           }
       }
       if (lastxchg == 0)   /* no exchanges, so array is sorted */
           break;           /* we're done */
       limit = lastxchg;    /* array is sorted up to [limit] */
    }
}
SECStatus NSS_CMSAttribute_AddValue ( PLArenaPool poolp,
NSSCMSAttribute *  attr,
SECItem *  value 
)

Definition at line 115 of file cmsattr.c.

{
    SECItem *copiedvalue;
    void *mark;

    PORT_Assert (poolp != NULL);

    mark = PORT_ArenaMark(poolp);

    if (value == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       goto loser;
    }

    if ((copiedvalue = SECITEM_ArenaDupItem(poolp, value)) == NULL)
       goto loser;

    if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess)
       goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_Assert (mark != NULL);
    PORT_ArenaRelease (poolp, mark);
    return SECFailure;
}
PRBool NSS_CMSAttribute_CompareValue ( NSSCMSAttribute *  attr,
SECItem *  av 
)

Definition at line 189 of file cmsattr.c.

{
    SECItem *value;
    
    if (attr == NULL)
       return PR_FALSE;

    value = NSS_CMSAttribute_GetValue(attr);

    return (value != NULL && value->len == av->len &&
       PORT_Memcmp (value->data, av->data, value->len) == 0);
}
NSSCMSAttribute* NSS_CMSAttribute_Create ( PRArenaPool poolp,
SECOidTag  oidtag,
SECItem *  value,
PRBool  encoded 
)

Definition at line 70 of file cmsattr.c.

{
    NSSCMSAttribute *attr;
    SECItem *copiedvalue;
    void *mark;

    PORT_Assert (poolp != NULL);

    mark = PORT_ArenaMark (poolp);

    attr = (NSSCMSAttribute *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSAttribute));
    if (attr == NULL)
       goto loser;

    attr->typeTag = SECOID_FindOIDByTag(oidtag);
    if (attr->typeTag == NULL)
       goto loser;

    if (SECITEM_CopyItem(poolp, &(attr->type), &(attr->typeTag->oid)) != SECSuccess)
       goto loser;

    if (value != NULL) {
       if ((copiedvalue = SECITEM_ArenaDupItem(poolp, value)) == NULL)
           goto loser;

       if (NSS_CMSArray_Add(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess)
           goto loser;
    }

    attr->encoded = encoded;

    PORT_ArenaUnmark (poolp, mark);

    return attr;

loser:
    PORT_Assert (mark != NULL);
    PORT_ArenaRelease (poolp, mark);
    return NULL;
}
SECOidTag NSS_CMSAttribute_GetType ( NSSCMSAttribute *  attr)

Definition at line 148 of file cmsattr.c.

{
    SECOidData *typetag;

    typetag = SECOID_FindOID(&(attr->type));
    if (typetag == NULL)
       return SEC_OID_UNKNOWN;

    return typetag->offset;
}
SECItem* NSS_CMSAttribute_GetValue ( NSSCMSAttribute *  attr)

Definition at line 167 of file cmsattr.c.

{
    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;
}
SECStatus NSS_CMSAttributeArray_AddAttr ( PLArenaPool poolp,
NSSCMSAttribute ***  attrs,
NSSCMSAttribute *  attr 
)

Definition at line 397 of file cmsattr.c.

{
    NSSCMSAttribute *oattr;
    void *mark;
    SECOidTag type;

    mark = PORT_ArenaMark(poolp);

    /* find oidtag of attr */
    type = NSS_CMSAttribute_GetType(attr);

    /* see if we have one already */
    oattr = NSS_CMSAttributeArray_FindAttrByOidTag(*attrs, type, PR_FALSE);
    PORT_Assert (oattr == NULL);
    if (oattr != NULL)
       goto loser;   /* XXX or would it be better to replace it? */

    /* no, shove it in */
    if (NSS_CMSArray_Add(poolp, (void ***)attrs, (void *)attr) != SECSuccess)
       goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}
SECItem* NSS_CMSAttributeArray_Encode ( PRArenaPool poolp,
NSSCMSAttribute ***  attrs,
SECItem *  dest 
)

Definition at line 327 of file cmsattr.c.

NSSCMSAttribute* NSS_CMSAttributeArray_FindAttrByOidTag ( NSSCMSAttribute **  attrs,
SECOidTag  oidtag,
PRBool  only 
)

Definition at line 354 of file cmsattr.c.

{
    SECOidData *oid;
    NSSCMSAttribute *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;
}
SECStatus NSS_CMSAttributeArray_Reorder ( NSSCMSAttribute **  attrs)

Definition at line 340 of file cmsattr.c.

SECStatus NSS_CMSAttributeArray_SetAttr ( PLArenaPool poolp,
NSSCMSAttribute ***  attrs,
SECOidTag  type,
SECItem *  value,
PRBool  encoded 
)

Definition at line 430 of file cmsattr.c.

{
    NSSCMSAttribute *attr;
    void *mark;

    mark = PORT_ArenaMark(poolp);

    /* see if we have one already */
    attr = NSS_CMSAttributeArray_FindAttrByOidTag(*attrs, type, PR_FALSE);
    if (attr == NULL) {
       /* not found? create one! */
       attr = NSS_CMSAttribute_Create(poolp, type, value, encoded);
       if (attr == NULL)
           goto loser;
       /* and add it to the list */
       if (NSS_CMSArray_Add(poolp, (void ***)attrs, (void *)attr) != SECSuccess)
           goto loser;
    } else {
       /* found, shove it in */
       /* XXX we need a decent memory model @#$#$!#!!! */
       attr->values[0] = value;
       attr->encoded = encoded;
    }

    PORT_ArenaUnmark (poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease (poolp, mark);
    return SECFailure;
}
SECStatus NSS_CMSCipherContext_Decrypt ( NSSCMSCipherContext *  cc,
unsigned char *  output,
unsigned int output_len_p,
unsigned int  max_output_len,
const unsigned char *  input,
unsigned int  input_len,
PRBool  final 
)

Definition at line 438 of file cmscipher.c.

{
    int blocks, bsize, pcount, padsize;
    unsigned int max_needed, ifraglen, ofraglen, output_len;
    unsigned char *pbuf;
    SECStatus rv;

    PORT_Assert (! cc->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 = NSS_CMSCipherContext_DecryptLength(cc, 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 = cc->block_size;
    padsize = cc->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 (* cc->doit) (cc->cx, output, output_len_p, max_output_len,
                           input, input_len);
    }

    pcount = cc->pending_count;
    pbuf = cc->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) {
           cc->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.
        */
       if ((padsize != 0) && (pcount % padsize) != 0) {
           PORT_Assert (final);    
           PORT_SetError (SEC_ERROR_BAD_DATA);
           return SECFailure;
       }
       /*
        * Decrypt the block.
        */
       rv = (*cc->doit)(cc->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 NSS_CMSCipherContext_DecryptLength 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);
       cc->pending_count = pcount;
    }

    if (ifraglen) {
       rv = (* cc->doit)(cc->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;
}
unsigned int NSS_CMSCipherContext_DecryptLength ( NSSCMSCipherContext *  cc,
unsigned int  input_len,
PRBool  final 
)

Definition at line 306 of file cmscipher.c.

{
    int blocks, block_size;

    PORT_Assert (! cc->encrypt);

    block_size = cc->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 cc->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 = (cc->pending_count + input_len - 1) / block_size;
    return blocks * block_size;
}
void NSS_CMSCipherContext_Destroy ( NSSCMSCipherContext *  cc)

Definition at line 275 of file cmscipher.c.

{
    PORT_Assert(cc != NULL);
    if (cc == NULL)
       return;
    (*cc->destroy)(cc->cx, PR_TRUE);
    PORT_Free(cc);
}
SECStatus NSS_CMSCipherContext_Encrypt ( NSSCMSCipherContext *  cc,
unsigned char *  output,
unsigned int output_len_p,
unsigned int  max_output_len,
const unsigned char *  input,
unsigned int  input_len,
PRBool  final 
)

Definition at line 649 of file cmscipher.c.

{
    int blocks, bsize, padlen, pcount, padsize;
    unsigned int max_needed, ifraglen, ofraglen, output_len;
    unsigned char *pbuf;
    SECStatus rv;

    PORT_Assert (cc->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 = NSS_CMSCipherContext_EncryptLength (cc, input_len, final);
    PORT_Assert (max_output_len >= max_needed);
    if (max_output_len < max_needed) {
       /* PORT_SetError (XXX); */
       return SECFailure;
    }

    bsize = cc->block_size;
    padsize = cc->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 (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
                           input, input_len);
    }

    pcount = cc->pending_count;
    pbuf = cc->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) {
           cc->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 = (* cc->doit) (cc->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 = (* cc->doit) (cc->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 = (* cc->doit) (cc->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 {
       cc->pending_count = pcount;
    }

    PORT_Assert (output_len_p != NULL || output_len == 0);
    if (output_len_p != NULL)
       *output_len_p = output_len;

    return SECSuccess;
}
unsigned int NSS_CMSCipherContext_EncryptLength ( NSSCMSCipherContext *  cc,
unsigned int  input_len,
PRBool  final 
)

Definition at line 364 of file cmscipher.c.

{
    int blocks, block_size;
    int pad_size;

    PORT_Assert (cc->encrypt);

    block_size = cc->block_size;
    pad_size = cc->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 cc->pending_count + input_len;
       } else {
           blocks = (cc->pending_count + input_len) / pad_size;
           blocks++;
           return blocks*pad_size;
       }
    }

    /*
     * Now, count the number of complete blocks of data we have.
     */
    blocks = (cc->pending_count + input_len) / block_size;


    return blocks * block_size;
}
SEC_BEGIN_PROTOS NSSCMSCipherContext* NSS_CMSCipherContext_StartDecrypt ( PK11SymKey *  key,
SECAlgorithmID *  algid 
)

Definition at line 82 of file cmscipher.c.

{
    NSSCMSCipherContext *cc;
    void *ciphercx;
    CK_MECHANISM_TYPE mechanism;
    SECItem *param;
    PK11SlotInfo *slot;
    SECOidTag algtag;

    algtag = SECOID_GetAlgorithmTag(algid);

    /* set param and mechanism */
    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
       CK_MECHANISM pbeMech, cryptoMech;
       SECItem *pbeParams, *pwitem;

       PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
       PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));

       pwitem = PK11_GetSymKeyUserData(key);
       if (!pwitem) 
           return NULL;

       /* find correct PK11 mechanism and parameters to initialize pbeMech */
       pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
       pbeParams = PK11_ParamFromAlgid(algid);
       if (!pbeParams)
           return NULL;
       pbeMech.pParameter = pbeParams->data;
       pbeMech.ulParameterLen = pbeParams->len;

       /* now map pbeMech to cryptoMech */
       if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
                                            PR_FALSE) != CKR_OK) { 
           SECITEM_ZfreeItem(pbeParams, PR_TRUE);
           return NULL;
       }
       SECITEM_ZfreeItem(pbeParams, PR_TRUE);

       /* and use it to initialize param & mechanism */
       if ((param = (SECItem *)PORT_ZAlloc(sizeof(SECItem))) == NULL)
            return NULL;

       param->data = (unsigned char *)cryptoMech.pParameter;
       param->len = cryptoMech.ulParameterLen;
       mechanism = cryptoMech.mechanism;
    } else {
       mechanism = PK11_AlgtagToMechanism(algtag);
       if ((param = PK11_ParamFromAlgid(algid)) == NULL)
           return NULL;
    }

    cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
    if (cc == NULL) {
       SECITEM_FreeItem(param,PR_TRUE);
       return NULL;
    }

    /* figure out pad and block sizes */
    cc->pad_size = PK11_GetBlockSize(mechanism, param);
    slot = PK11_GetSlotFromKey(key);
    cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
    PK11_FreeSlot(slot);

    /* create PK11 cipher context */
    ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param);
    SECITEM_FreeItem(param, PR_TRUE);
    if (ciphercx == NULL) {
       PORT_Free (cc);
       return NULL;
    }

    cc->cx = ciphercx;
    cc->doit =  (nss_cms_cipher_function) PK11_CipherOp;
    cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext;
    cc->encrypt = PR_FALSE;
    cc->pending_count = 0;

    return cc;
}
NSSCMSCipherContext* NSS_CMSCipherContext_StartEncrypt ( PRArenaPool poolp,
PK11SymKey *  key,
SECAlgorithmID *  algid 
)

Definition at line 173 of file cmscipher.c.

{
    NSSCMSCipherContext *cc;
    void *ciphercx;
    SECItem *param;
    SECStatus rv;
    CK_MECHANISM_TYPE mechanism;
    PK11SlotInfo *slot;
    PRBool needToEncodeAlgid = PR_FALSE;
    SECOidTag algtag = SECOID_GetAlgorithmTag(algid);

    /* set param and mechanism */
    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
       CK_MECHANISM pbeMech, cryptoMech;
       SECItem *pbeParams, *pwitem;

       PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
       PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));

       pwitem = PK11_GetSymKeyUserData(key);
       if (!pwitem) 
           return NULL;

       /* find correct PK11 mechanism and parameters to initialize pbeMech */
       pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
       pbeParams = PK11_ParamFromAlgid(algid);
       if (!pbeParams)
           return NULL;
       pbeMech.pParameter = pbeParams->data;
       pbeMech.ulParameterLen = pbeParams->len;

       /* now map pbeMech to cryptoMech */
       if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
                                            PR_FALSE) != CKR_OK) { 
           SECITEM_ZfreeItem(pbeParams, PR_TRUE);
           return NULL;
       }
       SECITEM_ZfreeItem(pbeParams, PR_TRUE);

       /* and use it to initialize param & mechanism */
       if ((param = (SECItem *)PORT_ZAlloc(sizeof(SECItem))) == NULL)
           return NULL;

       param->data = (unsigned char *)cryptoMech.pParameter;
       param->len = cryptoMech.ulParameterLen;
       mechanism = cryptoMech.mechanism;
    } else {
       mechanism = PK11_AlgtagToMechanism(algtag);
       if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL)
           return NULL;
       needToEncodeAlgid = PR_TRUE;
    }

    cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
    if (cc == NULL) {
       goto loser;
    }

    /* now find pad and block sizes for our mechanism */
    cc->pad_size = PK11_GetBlockSize(mechanism,param);
    slot = PK11_GetSlotFromKey(key);
    cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
    PK11_FreeSlot(slot);

    /* and here we go, creating a PK11 cipher context */
    ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param);
    if (ciphercx == NULL) {
       PORT_Free(cc);
       cc = NULL;
       goto loser;
    }

    /*
     * 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.
     * XXX is that right? the purpose of this is to get the correct algid
     *     containing the IVs etc. for encoding. this means we need to set this up
     *     BEFORE encoding the algid in the contentInfo, right?
     */
    if (needToEncodeAlgid) {
       rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
       if(rv != SECSuccess) {
           PORT_Free(cc);
           cc = NULL;
           goto loser;
       }
    }

    cc->cx = ciphercx;
    cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
    cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
    cc->encrypt = PR_TRUE;
    cc->pending_count = 0;

loser:
    SECITEM_FreeItem(param, PR_TRUE);

    return cc;
}
NSSCMSRecipientEncryptedKey* NSS_CMSRecipientEncryptedKey_Create ( PLArenaPool poolp)

Definition at line 198 of file cmsreclist.c.

{
    return (NSSCMSRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientEncryptedKey));
}

Here is the caller graph for this function:

SECStatus NSS_CMSSignedData_AddTempCertificate ( NSSCMSSignedData *  sigd,
CERTCertificate *  cert 
)

Definition at line 799 of file cmssigdata.c.

{
    CERTCertificate *c;
    SECStatus rv;

    if (!sigd || !cert) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    c = CERT_DupCertificate(cert);
    rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->tempCerts), (void *)c);
    return rv;
}

Here is the caller graph for this function:

PK11SymKey* NSS_CMSUtil_DecryptSymKey_ESDH ( SECKEYPrivateKey *  privkey,
SECItem *  encKey,
SECAlgorithmID *  keyEncAlg,
SECOidTag  bulkalgtag,
void pwfn_arg 
)

Definition at line 526 of file cmspubkey.c.

{
#if 0 /* not yet done */
    SECStatus err;
    CK_MECHANISM_TYPE bulkType;
    PK11SymKey *tek;
    SECKEYPublicKey *originatorPubKey;
    NSSCMSSMIMEKEAParameters keaParams;

   /* XXXX get originator's public key */
   originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.data,
                        keaParams.originatorKEAKey.len);
   if (originatorPubKey == NULL)
      goto loser;
    
   /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key.
      The Derive function generates a shared secret and combines it with the originatorRA
      data to come up with an unique session key */
   tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE,
                      &keaParams.originatorRA, NULL,
                      CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
                      CKA_WRAP, 0, pwfn_arg);
   SECKEY_DestroyPublicKey(originatorPubKey);    /* not needed anymore */
   if (tek == NULL)
       goto loser;
    
    /* Now that we have the TEK, unwrap the bulk key
       with which to decrypt the message. */
    /* Skipjack is being used as the bulk encryption algorithm.*/
    /* Unwrap the bulk key. */
    bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL,
                            encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0);

    return bulkkey;

loser:
#endif
    return NULL;
}
PK11SymKey* NSS_CMSUtil_DecryptSymKey_MISSI ( SECKEYPrivateKey *  privkey,
SECItem *  encKey,
SECAlgorithmID *  keyEncAlg,
SECOidTag  bulkalgtag,
void pwfn_arg 
)

Definition at line 309 of file cmspubkey.c.

{
    /* fortezza: do a key exchange */
    SECStatus err;
    CK_MECHANISM_TYPE bulkType;
    PK11SymKey *tek;
    SECKEYPublicKey *originatorPubKey;
    NSSCMSSMIMEKEAParameters keaParams;
    PK11SymKey *bulkkey;
    int bulkLength;

    (void) memset(&keaParams, 0, sizeof(keaParams));

    /* NOTE: this uses the SMIME v2 recipientinfo for compatibility.
       All additional KEA parameters are DER-encoded in the encryption algorithm parameters */

    /* Decode the KEA algorithm parameters. */
    err = SEC_ASN1DecodeItem(NULL, &keaParams, NSS_SMIMEKEAParamTemplateAllParams,
                          &(keyEncAlg->parameters));
    if (err != SECSuccess)
       goto loser;

    /* get originator's public key */
   originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.data,
                        keaParams.originatorKEAKey.len);
   if (originatorPubKey == NULL)
         goto loser;
    
   /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key.
      The Derive function generates a shared secret and combines it with the originatorRA
      data to come up with an unique session key */
   tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE,
                      &keaParams.originatorRA, NULL,
                      CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
                      CKA_WRAP, 0, pwfn_arg);
   SECKEY_DestroyPublicKey(originatorPubKey);    /* not needed anymore */
   if (tek == NULL)
       goto loser;
    
    /* Now that we have the TEK, unwrap the bulk key
       with which to decrypt the message. We have to
       do one of two different things depending on 
       whether Skipjack was used for *bulk* encryption 
       of the message. */
    bulkType = PK11_AlgtagToMechanism(bulkalgtag);
    switch (bulkType) {
    case CKM_SKIPJACK_CBC64:
    case CKM_SKIPJACK_ECB64:
    case CKM_SKIPJACK_OFB64:
    case CKM_SKIPJACK_CFB64:
    case CKM_SKIPJACK_CFB32:
    case CKM_SKIPJACK_CFB16:
    case CKM_SKIPJACK_CFB8:
       /* Skipjack is being used as the bulk encryption algorithm.*/
       /* Unwrap the bulk key. */
       bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL,
                                encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0);
       break;
    default:
       /* Skipjack was not used for bulk encryption of this
          message. Use Skipjack CBC64, with the nonSkipjackIV
          part of the KEA key parameters, to decrypt 
          the bulk key. If the optional parameter bulkKeySize is present,
          bulk key size is different than the encrypted key size */
       if (keaParams.bulkKeySize.len > 0) {
           err = SEC_ASN1DecodeItem(NULL, &bulkLength,
                                 SEC_ASN1_GET(SEC_IntegerTemplate),
                                 &keaParams.bulkKeySize);
           if (err != SECSuccess)
              goto loser;
       }
       
       bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, 
                                encKey, bulkType, CKA_DECRYPT, bulkLength);
       break;
    }
    return bulkkey;
loser:
    return NULL;
}

Here is the caller graph for this function:

PK11SymKey* NSS_CMSUtil_DecryptSymKey_RSA ( SECKEYPrivateKey *  privkey,
SECItem *  encKey,
SECOidTag  bulkalgtag 
)

Definition at line 131 of file cmspubkey.c.

{
    /* that's easy */
    CK_MECHANISM_TYPE target;
    PORT_Assert(bulkalgtag != SEC_OID_UNKNOWN);
    target = PK11_AlgtagToMechanism(bulkalgtag);
    if (bulkalgtag == SEC_OID_UNKNOWN || target == CKM_INVALID_MECHANISM) {
       PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
       return NULL;
    }
    return PK11_PubUnwrapSymKey(privkey, encKey, target, CKA_DECRYPT, 0);
}

Here is the caller graph for this function:

SECStatus NSS_CMSUtil_EncryptSymKey_ESDH ( PLArenaPool poolp,
CERTCertificate *  cert,
PK11SymKey *  key,
SECItem *  encKey,
SECItem **  ukm,
SECAlgorithmID *  keyEncAlg,
SECItem *  originatorPubKey 
)

Definition at line 393 of file cmspubkey.c.

{
#if 0 /* not yet done */
    SECOidTag certalgtag;   /* the certificate's encryption algorithm */
    SECOidTag encalgtag;    /* the algorithm used for key exchange/agreement */
    SECStatus rv;
    SECItem *params = NULL;
    int data_len;
    SECStatus err;
    PK11SymKey *tek;
    CERTCertificate *ourCert;
    SECKEYPublicKey *ourPubKey;
    NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid;

    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
    PORT_Assert(certalgtag == SEC_OID_X942_DIFFIE_HELMAN_KEY);

    /* We really want to show our KEA tag as the key exchange algorithm tag. */
    encalgtag = SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN;

    /* Get the public key of the recipient. */
    publickey = CERT_ExtractPublicKey(cert);
    if (publickey == NULL) goto loser;

    /* XXXX generate a DH key pair on a PKCS11 module (XXX which parameters?) */
    /* XXXX */ourCert = PK11_FindBestKEAMatch(cert, wincx);
    if (ourCert == NULL) goto loser;

    arena = PORT_NewArena(1024);
    if (arena == NULL) goto loser;

    /* While we're here, extract the key pair's public key data and copy it into */
    /* the outgoing parameters. */
    /* XXXX */ourPubKey = CERT_ExtractPublicKey(ourCert);
    if (ourPubKey == NULL)
    {
       goto loser;
    }
    SECITEM_CopyItem(arena, pubKey, /* XXX */&(ourPubKey->u.fortezza.KEAKey));
    SECKEY_DestroyPublicKey(ourPubKey); /* we only need the private key from now on */
    ourPubKey = NULL;

    /* Extract our private key in order to derive the KEA key. */
    ourPrivKey = PK11_FindKeyByAnyCert(ourCert,wincx);
    CERT_DestroyCertificate(ourCert); /* we're done with this */
    if (!ourPrivKey) goto loser;

    /* If ukm desired, prepare it - allocate enough space (filled with zeros). */
    if (ukm) {
       ukm->data = (unsigned char*)PORT_ArenaZAlloc(arena,/* XXXX */);
       ukm->len = /* XXXX */;
    }

    /* Generate the KEK (key exchange key) according to RFC2631 which we use
     * to wrap the bulk encryption key. */
    kek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE,
                      ukm, NULL,
                      /* XXXX */CKM_KEA_KEY_DERIVE, /* XXXX */CKM_SKIPJACK_WRAP,
                      CKA_WRAP, 0, wincx);

    SECKEY_DestroyPublicKey(publickey);
    SECKEY_DestroyPrivateKey(ourPrivKey);
    publickey = NULL;
    ourPrivKey = NULL;
    
    if (!kek)
       goto loser;

    /* allocate space for the encrypted CEK (bulk key) */
    encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE);
    encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE;

    if (encKey->data == NULL)
    {
       PK11_FreeSymKey(kek);
       goto loser;
    }


    /* Wrap the bulk key using CMSRC2WRAP or CMS3DESWRAP, depending on the */
    /* bulk encryption algorithm */
    switch (/* XXXX */PK11_AlgtagToMechanism(enccinfo->encalg))
    {
    case /* XXXX */CKM_SKIPJACK_CFB8:
       err = PK11_WrapSymKey(/* XXXX */CKM_CMS3DES_WRAP, NULL, kek, bulkkey, encKey);
       whichKEA = NSSCMSKEAUsesSkipjack;
       break;
    case /* XXXX */CKM_SKIPJACK_CFB8:
       err = PK11_WrapSymKey(/* XXXX */CKM_CMSRC2_WRAP, NULL, kek, bulkkey, encKey);
       whichKEA = NSSCMSKEAUsesSkipjack;
       break;
    default:
       /* XXXX what do we do here? Neither RC2 nor 3DES... */
        err = SECFailure;
        /* set error */
       break;
    }

    PK11_FreeSymKey(kek);   /* we do not need the KEK anymore */
    if (err != SECSuccess)
       goto loser;

    PORT_Assert(whichKEA != NSSCMSKEAInvalid);

    /* see RFC2630 12.3.1.1 "keyEncryptionAlgorithm must be ..." */
    /* params is the DER encoded key wrap algorithm (with parameters!) (XXX) */
    params = SEC_ASN1EncodeItem(arena, NULL, &keaParams, sec_pkcs7_get_kea_template(whichKEA));
    if (params == NULL)
       goto loser;

    /* now set keyEncAlg */
    rv = SECOID_SetAlgorithmID(poolp, keyEncAlg, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN, params);
    if (rv != SECSuccess)
       goto loser;

    /* XXXXXXX this is not right yet */
loser:
    if (arena) {
       PORT_FreeArena(arena, PR_FALSE);
    }
    if (publickey) {
        SECKEY_DestroyPublicKey(publickey);
    }
    if (ourPrivKey) {
        SECKEY_DestroyPrivateKey(ourPrivKey);
    }
#endif
    return SECFailure;
}

Here is the caller graph for this function:

SECStatus NSS_CMSUtil_EncryptSymKey_MISSI ( PLArenaPool poolp,
CERTCertificate *  cert,
PK11SymKey *  key,
SECOidTag  symalgtag,
SECItem *  encKey,
SECItem **  pparams,
void pwfn_arg 
)

Definition at line 149 of file cmspubkey.c.

{
    SECOidTag certalgtag;   /* the certificate's encryption algorithm */
    SECOidTag encalgtag;    /* the algorithm used for key exchange/agreement */
    SECStatus rv = SECFailure;
    SECItem *params = NULL;
    SECStatus err;
    PK11SymKey *tek;
    CERTCertificate *ourCert;
    SECKEYPublicKey *ourPubKey, *publickey = NULL;
    SECKEYPrivateKey *ourPrivKey = NULL;
    NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid;
    NSSCMSSMIMEKEAParameters keaParams;
    PLArenaPool *arena = NULL;
    extern const SEC_ASN1Template *nss_cms_get_kea_template(NSSCMSKEATemplateSelector whichTemplate);

    /* Clear keaParams, since cleanup code checks the lengths */
    (void) memset(&keaParams, 0, sizeof(keaParams));

    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
    PORT_Assert(certalgtag == SEC_OID_MISSI_KEA_DSS_OLD ||
              certalgtag == SEC_OID_MISSI_KEA_DSS ||
              certalgtag == SEC_OID_MISSI_KEA);

#define SMIME_FORTEZZA_RA_LENGTH 128
#define SMIME_FORTEZZA_IV_LENGTH 24
#define SMIME_FORTEZZA_MAX_KEY_SIZE 256

    /* We really want to show our KEA tag as the key exchange algorithm tag. */
    encalgtag = SEC_OID_NETSCAPE_SMIME_KEA;

    /* Get the public key of the recipient. */
    publickey = CERT_ExtractPublicKey(cert);
    if (publickey == NULL) goto loser;

    /* Find our own cert, and extract its keys. */
    ourCert = PK11_FindBestKEAMatch(cert, pwfn_arg);
    if (ourCert == NULL) goto loser;

    arena = PORT_NewArena(1024);
    if (arena == NULL)
       goto loser;

    ourPubKey = CERT_ExtractPublicKey(ourCert);
    if (ourPubKey == NULL) {
       CERT_DestroyCertificate(ourCert);
       goto loser;
    }

    /* While we're here, copy the public key into the outgoing
     * KEA parameters. */
    SECITEM_CopyItem(arena, &(keaParams.originatorKEAKey), &(ourPubKey->u.fortezza.KEAKey));
    SECKEY_DestroyPublicKey(ourPubKey);
    ourPubKey = NULL;

    /* Extract our private key in order to derive the KEA key. */
    ourPrivKey = PK11_FindKeyByAnyCert(ourCert, pwfn_arg);
    CERT_DestroyCertificate(ourCert); /* we're done with this */
    if (!ourPrivKey)
       goto loser;

    /* Prepare raItem with 128 bytes (filled with zeros). */
    keaParams.originatorRA.data = (unsigned char *)PORT_ArenaAlloc(arena,SMIME_FORTEZZA_RA_LENGTH);
    keaParams.originatorRA.len = SMIME_FORTEZZA_RA_LENGTH;

    /* Generate the TEK (token exchange key) which we use
     * to wrap the bulk encryption key. (keaparams.originatorRA) will be
     * filled with a random seed which we need to send to
     * the recipient. (user keying material in RFC2630/DSA speak) */
    tek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE,
                      &keaParams.originatorRA, NULL,
                      CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
                      CKA_WRAP, 0,  pwfn_arg);

    SECKEY_DestroyPublicKey(publickey);
    SECKEY_DestroyPrivateKey(ourPrivKey);
    publickey = NULL;
    ourPrivKey = NULL;
    
    if (!tek)
       goto loser;

    /* allocate space for the wrapped key data */
    encKey->data = (unsigned char *)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE);
    encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE;

    if (encKey->data == NULL) {
       PK11_FreeSymKey(tek);
       goto loser;
    }

    /* Wrap the bulk key. What we do with the resulting data
       depends on whether we're using Skipjack to wrap the key. */
    switch (PK11_AlgtagToMechanism(symalgtag)) {
    case CKM_SKIPJACK_CBC64:
    case CKM_SKIPJACK_ECB64:
    case CKM_SKIPJACK_OFB64:
    case CKM_SKIPJACK_CFB64:
    case CKM_SKIPJACK_CFB32:
    case CKM_SKIPJACK_CFB16:
    case CKM_SKIPJACK_CFB8:
       /* SKIPJACK, we use the wrap mechanism because we can do it on the hardware */
       err = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, bulkkey, encKey);
       whichKEA = NSSCMSKEAUsesSkipjack;
       break;
    default:
       /* Not SKIPJACK, we encrypt the raw key data */
       keaParams.nonSkipjackIV.data = 
         (unsigned char *)PORT_ArenaAlloc(arena, SMIME_FORTEZZA_IV_LENGTH);
       keaParams.nonSkipjackIV.len = SMIME_FORTEZZA_IV_LENGTH;
       err = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, tek, bulkkey, encKey);
       if (err != SECSuccess)
           goto loser;

       if (encKey->len != PK11_GetKeyLength(bulkkey)) {
           /* The size of the encrypted key is not the same as
              that of the original bulk key, presumably due to
              padding. Encode and store the real size of the
              bulk key. */
           if (SEC_ASN1EncodeInteger(arena, &keaParams.bulkKeySize, PK11_GetKeyLength(bulkkey)) == NULL)
              err = (SECStatus)PORT_GetError();
           else
              /* use full template for encoding */
              whichKEA = NSSCMSKEAUsesNonSkipjackWithPaddedEncKey;
       }
       else
           /* enc key length == bulk key length */
           whichKEA = NSSCMSKEAUsesNonSkipjack; 
       break;
    }

    PK11_FreeSymKey(tek);

    if (err != SECSuccess)
       goto loser;

    PORT_Assert(whichKEA != NSSCMSKEAInvalid);

    /* Encode the KEA parameters into the recipient info. */
    params = SEC_ASN1EncodeItem(poolp, NULL, &keaParams, nss_cms_get_kea_template(whichKEA));
    if (params == NULL)
       goto loser;

    /* pass back the algorithm params */
    *pparams = params;

    rv = SECSuccess;

loser:
    if (arena)
       PORT_FreeArena(arena, PR_FALSE);
    if (publickey)
        SECKEY_DestroyPublicKey(publickey);
    if (ourPrivKey)
        SECKEY_DestroyPrivateKey(ourPrivKey);
    return rv;
}
SECStatus NSS_CMSUtil_EncryptSymKey_RSA ( PLArenaPool poolp,
CERTCertificate *  cert,
PK11SymKey *  key,
SECItem *  encKey 
)

Definition at line 62 of file cmspubkey.c.

{
    SECStatus rv;
    SECKEYPublicKey *publickey;

    publickey = CERT_ExtractPublicKey(cert);
    if (publickey == NULL)
       return SECFailure;

    rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, publickey, bulkkey, encKey);
    SECKEY_DestroyPublicKey(publickey);
    return rv;
}

Here is the caller graph for this function:

SECStatus NSS_CMSUtil_EncryptSymKey_RSAPubKey ( PLArenaPool poolp,
SECKEYPublicKey *  publickey,
PK11SymKey *  bulkkey,
SECItem *  encKey 
)

Definition at line 79 of file cmspubkey.c.

{
    SECStatus rv;
    int data_len;
    KeyType keyType;
    void *mark = NULL;


    mark = PORT_ArenaMark(poolp);
    if (!mark)
       goto loser;

    /* sanity check */
    keyType = SECKEY_GetPublicKeyType(publickey);
    PORT_Assert(keyType == rsaKey);
    if (keyType != rsaKey) {
       goto loser;
    }
    /* allocate memory for the encrypted key */
    data_len = SECKEY_PublicKeyStrength(publickey);     /* block size (assumed to be > keylen) */
    encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len);
    encKey->len = data_len;
    if (encKey->data == NULL)
       goto loser;

    /* encrypt the key now */
    rv = PK11_PubWrapSymKey(PK11_AlgtagToMechanism(SEC_OID_PKCS1_RSA_ENCRYPTION),
                            publickey, bulkkey, encKey);

    if (rv != SECSuccess)
       goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    if (mark) {
       PORT_ArenaRelease(poolp, mark);
    }
    return SECFailure;
}

Here is the caller graph for this function:


Variable Documentation