Back to index

lightning-sunbird  0.9+nobinonly
Functions | Variables
cmsrecinfo.c File Reference
#include "cmslocal.h"
#include "cert.h"
#include "key.h"
#include "secasn1.h"
#include "secitem.h"
#include "secoid.h"
#include "pk11func.h"
#include "secerr.h"

Go to the source code of this file.

Functions

PRBool nss_cmsrecipientinfo_usessubjectkeyid (NSSCMSRecipientInfo *ri)
NSSCMSRecipientInfo * nss_cmsrecipientinfo_create (NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type, CERTCertificate *cert, SECKEYPublicKey *pubKey, SECItem *subjKeyID, void *pwfn_arg, SECItem *DERinput)
NSSCMSRecipientInfo * NSS_CMSRecipientInfo_Create (NSSCMSMessage *cmsg, CERTCertificate *cert)
NSSCMSRecipientInfo * NSS_CMSRecipientInfo_CreateNew (void *pwfn_arg)
NSSCMSRecipientInfo * NSS_CMSRecipientInfo_CreateFromDER (SECItem *input, void *pwfn_arg)
NSSCMSRecipientInfo * NSS_CMSRecipientInfo_CreateWithSubjKeyID (NSSCMSMessage *cmsg, SECItem *subjKeyID, SECKEYPublicKey *pubKey)
NSSCMSRecipientInfo * NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert (NSSCMSMessage *cmsg, CERTCertificate *cert)
void NSS_CMSRecipientInfo_Destroy (NSSCMSRecipientInfo *ri)
int NSS_CMSRecipientInfo_GetVersion (NSSCMSRecipientInfo *ri)
SECItem * NSS_CMSRecipientInfo_GetEncryptedKey (NSSCMSRecipientInfo *ri, int subIndex)
SECOidTag NSS_CMSRecipientInfo_GetKeyEncryptionAlgorithmTag (NSSCMSRecipientInfo *ri)
SECStatus NSS_CMSRecipientInfo_WrapBulkKey (NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, SECOidTag bulkalgtag)
PK11SymKey * NSS_CMSRecipientInfo_UnwrapBulkKey (NSSCMSRecipientInfo *ri, int subIndex, CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag)
SECStatus NSS_CMSRecipientInfo_GetCertAndKey (NSSCMSRecipientInfo *ri, CERTCertificate **retcert, SECKEYPrivateKey **retkey)
SECStatus NSS_CMSRecipientInfo_Encode (PRArenaPool *poolp, const NSSCMSRecipientInfo *src, SECItem *returned)

Variables

static const SECOidData fakeContent

Function Documentation

NSSCMSRecipientInfo* nss_cmsrecipientinfo_create ( NSSCMSMessage *  cmsg,
NSSCMSRecipientIDSelector  type,
CERTCertificate *  cert,
SECKEYPublicKey *  pubKey,
SECItem *  subjKeyID,
void pwfn_arg,
SECItem *  DERinput 
)

Definition at line 76 of file cmsrecinfo.c.

{
    NSSCMSRecipientInfo *ri;
    void *mark;
    SECOidTag certalgtag;
    SECStatus rv = SECSuccess;
    NSSCMSRecipientEncryptedKey *rek;
    NSSCMSOriginatorIdentifierOrKey *oiok;
    unsigned long version;
    SECItem *dummy;
    PLArenaPool *poolp;
    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
    NSSCMSRecipientIdentifier *rid;
    extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];

    if (!cmsg) {
       /* a CMSMessage wasn't supplied, create a fake one to hold the pwfunc
        * and a private arena pool */
       cmsg = NSS_CMSMessage_Create(NULL);
        cmsg->pwfn_arg = pwfn_arg;
       /* mark it as a special cms message */
       cmsg->contentInfo.contentTypeTag = &fakeContent;
    }

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));
    if (ri == NULL)
       goto loser;

    ri->cmsg = cmsg;

    if (DERinput) {
        /* decode everything from DER */
        SECItem newinput;
        SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput);
        if (SECSuccess != rv)
            goto loser;
        rv = SEC_QuickDERDecodeItem(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput);
        if (SECSuccess != rv)
            goto loser;
    }

    switch (type) {
        case NSSCMSRecipientID_IssuerSN:
        {
            ri->cert = CERT_DupCertificate(cert);
            if (NULL == ri->cert)
                goto loser;
            spki = &(cert->subjectPublicKeyInfo);
            break;
        }
        
        case NSSCMSRecipientID_SubjectKeyID:
        {
            PORT_Assert(pubKey);
            spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
            break;
        }

       case NSSCMSRecipientID_BrandNew:
           goto done;
           break;

        default:
            /* unkown type */
            goto loser;
            break;
    }

    certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));

    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
       ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;
       rid->identifierType = type;
       if (type == NSSCMSRecipientID_IssuerSN) {
           rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
           if (rid->id.issuerAndSN == NULL) {
             break;
           }
       } else if (type == NSSCMSRecipientID_SubjectKeyID){
           NSSCMSKeyTransRecipientInfoEx *riExtra;

           rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem);
           if (rid->id.subjectKeyID == NULL) {
              rv = SECFailure;
              PORT_SetError(SEC_ERROR_NO_MEMORY);
              break;
           } 
           SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID);
           if (rid->id.subjectKeyID->data == NULL) {
              rv = SECFailure;
              PORT_SetError(SEC_ERROR_NO_MEMORY);
              break;
           }
           riExtra = &ri->ri.keyTransRecipientInfoEx;
           riExtra->version = 0;
           riExtra->pubKey = SECKEY_CopyPublicKey(pubKey);
           if (riExtra->pubKey == NULL) {
              rv = SECFailure;
              PORT_SetError(SEC_ERROR_NO_MEMORY);
              break;
           }
       } else {
           PORT_SetError(SEC_ERROR_INVALID_ARGS);
           rv = SECFailure;
       }
       break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
       PORT_Assert(type == NSSCMSRecipientID_IssuerSN);
       if (type != NSSCMSRecipientID_IssuerSN) {
           rv = SECFailure;
           break;
       }
       /* a key agreement op */
       ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;

       if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
           rv = SECFailure;
           break;
       }
       /* we do not support the case where multiple recipients 
        * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
        * in this case, we would need to walk all the recipientInfos, take the
        * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
        * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */

       /* only epheremal-static Diffie-Hellman is supported for now
        * this is the only form of key agreement that provides potential anonymity
        * of the sender, plus we do not have to include certs in the message */

       /* force single recipientEncryptedKey for now */
       if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL) {
           rv = SECFailure;
           break;
       }

       /* hardcoded IssuerSN choice for now */
       rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN;
       if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) {
           rv = SECFailure;
           break;
       }

       oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);

       /* see RFC2630 12.3.1.1 */
       oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey;

       rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys,
                                (void *)rek);

       break;
    default:
       /* other algorithms not supported yet */
       /* NOTE that we do not support any KEK algorithm */
       PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
       rv = SECFailure;
       break;
    }

    if (rv == SECFailure)
       goto loser;

    /* set version */
    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
       if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == NSSCMSRecipientID_IssuerSN)
           version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN;
       else
           version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY;
       dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version);
       if (dummy == NULL)
           goto loser;
       break;
    case NSSCMSRecipientInfoID_KeyAgree:
       dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version),
                                          NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION);
       if (dummy == NULL)
           goto loser;
       break;
    case NSSCMSRecipientInfoID_KEK:
       /* NOTE: this cannot happen as long as we do not support any KEK algorithm */
       dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version),
                                          NSS_CMS_KEK_RECIPIENT_INFO_VERSION);
       if (dummy == NULL)
           goto loser;
       break;
    
    }

done:
    PORT_ArenaUnmark (poolp, mark);
    if (freeSpki)
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    return ri;

loser:
    if (ri && ri->cert) {
        CERT_DestroyCertificate(ri->cert);
    }
    if (freeSpki) {
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
    }
    PORT_ArenaRelease (poolp, mark);
    if (cmsg->contentInfo.contentTypeTag == &fakeContent) {
       NSS_CMSMessage_Destroy(cmsg);
    }
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NSSCMSRecipientInfo* NSS_CMSRecipientInfo_Create ( NSSCMSMessage *  cmsg,
CERTCertificate *  cert 
)

Definition at line 301 of file cmsrecinfo.c.

NSSCMSRecipientInfo* NSS_CMSRecipientInfo_CreateFromDER ( SECItem *  input,
void pwfn_arg 
)

Definition at line 315 of file cmsrecinfo.c.

NSSCMSRecipientInfo* NSS_CMSRecipientInfo_CreateNew ( void pwfn_arg)

Definition at line 308 of file cmsrecinfo.c.

NSSCMSRecipientInfo* NSS_CMSRecipientInfo_CreateWithSubjKeyID ( NSSCMSMessage *  cmsg,
SECItem *  subjKeyID,
SECKEYPublicKey *  pubKey 
)

Definition at line 323 of file cmsrecinfo.c.

{
    return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID, 
                                       NULL, pubKey, subjKeyID, NULL, NULL);
}
NSSCMSRecipientInfo* NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert ( NSSCMSMessage *  cmsg,
CERTCertificate *  cert 
)

Definition at line 332 of file cmsrecinfo.c.

{
    SECKEYPublicKey *pubKey = NULL;
    SECItem subjKeyID = {siBuffer, NULL, 0};
    NSSCMSRecipientInfo *retVal = NULL;

    if (!cmsg || !cert) {
       return NULL;
    }
    pubKey = CERT_ExtractPublicKey(cert);
    if (!pubKey) {
       goto done;
    }
    if (CERT_FindSubjectKeyIDExtension(cert, &subjKeyID) != SECSuccess ||
        subjKeyID.data == NULL) {
       goto done;
    }
    retVal = NSS_CMSRecipientInfo_CreateWithSubjKeyID(cmsg, &subjKeyID, pubKey);
done:
    if (pubKey)
       SECKEY_DestroyPublicKey(pubKey);

    if (subjKeyID.data)
       SECITEM_FreeItem(&subjKeyID, PR_FALSE);

    return retVal;
}
void NSS_CMSRecipientInfo_Destroy ( NSSCMSRecipientInfo *  ri)

Definition at line 362 of file cmsrecinfo.c.

{
    if (!ri) {
        return;
    }
    /* version was allocated on the pool, so no need to destroy it */
    /* issuerAndSN was allocated on the pool, so no need to destroy it */
    if (ri->cert != NULL)
       CERT_DestroyCertificate(ri->cert);

    if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) {
       NSSCMSKeyTransRecipientInfoEx *extra;
       extra = &ri->ri.keyTransRecipientInfoEx;
       if (extra->pubKey)
           SECKEY_DestroyPublicKey(extra->pubKey);
    }
    if (ri->cmsg && ri->cmsg->contentInfo.contentTypeTag == &fakeContent) {
       NSS_CMSMessage_Destroy(ri->cmsg);
    }

    /* we're done. */
}
SECStatus NSS_CMSRecipientInfo_Encode ( PRArenaPool poolp,
const NSSCMSRecipientInfo *  src,
SECItem *  returned 
)

Definition at line 701 of file cmsrecinfo.c.

{
    extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];
    SECStatus rv = SECFailure;
    if (!src || !returned) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    } else if (SEC_ASN1EncodeItem(poolp, returned, src,
        NSSCMSRecipientInfoTemplate))   {
        rv = SECSuccess;
    }
    return rv;
}
SECStatus NSS_CMSRecipientInfo_GetCertAndKey ( NSSCMSRecipientInfo *  ri,
CERTCertificate **  retcert,
SECKEYPrivateKey **  retkey 
)

Definition at line 626 of file cmsrecinfo.c.

{
    CERTCertificate* cert = NULL;
    NSSCMSRecipient** recipients = NULL;
    NSSCMSRecipientInfo* recipientInfos[2];
    SECStatus rv = SECSuccess;
    SECKEYPrivateKey* key = NULL;

    if (!ri)
        return SECFailure;
    
    if (!retcert && !retkey) {
        /* nothing requested, nothing found, success */
        return SECSuccess;
    }

    if (retcert) {
        *retcert = NULL;
    }
    if (retkey) {
        *retkey = NULL;
    }

    if (ri->cert) {
        cert = CERT_DupCertificate(ri->cert);
        if (!cert) {
            rv = SECFailure;
        }
    }
    if (SECSuccess == rv && !cert) {
        /* we don't have the cert, we have to look for it */
        /* first build an NSS_CMSRecipient */
        recipientInfos[0] = ri;
        recipientInfos[1] = NULL;

        recipients = nss_cms_recipient_list_create(recipientInfos);
        if (recipients) {
            /* now look for the cert and key */
            if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients,
                ri->cmsg->pwfn_arg)) {
                cert = CERT_DupCertificate(recipients[0]->cert);
                key = SECKEY_CopyPrivateKey(recipients[0]->privkey);
            } else {
                rv = SECFailure;
            }

            nss_cms_recipient_list_destroy(recipients);
        }
        else {
            rv = SECFailure;
        }            
    } else if (SECSuccess == rv && cert && retkey) {
        /* we have the cert, we just need the key now */
        key = PK11_FindPrivateKeyFromCert(cert->slot, cert, ri->cmsg->pwfn_arg);
    }
    if (retcert) {
        *retcert = cert;
    } else {
        if (cert) {
            CERT_DestroyCertificate(cert);
        }
    }
    if (retkey) {
        *retkey = key;
    } else {
        if (key) {
            SECKEY_DestroyPrivateKey(key);
        }
    }

    return rv;
}
SECItem* NSS_CMSRecipientInfo_GetEncryptedKey ( NSSCMSRecipientInfo *  ri,
int  subIndex 
)

Definition at line 417 of file cmsrecinfo.c.

{
    SECItem *enckey = NULL;

    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
       /* ignore subIndex */
       enckey = &(ri->ri.keyTransRecipientInfo.encKey);
       break;
    case NSSCMSRecipientInfoID_KEK:
       /* ignore subIndex */
       enckey = &(ri->ri.kekRecipientInfo.encKey);
       break;
    case NSSCMSRecipientInfoID_KeyAgree:
       enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey);
       break;
    }
    return enckey;
}

Definition at line 439 of file cmsrecinfo.c.

{
    SECOidTag encalgtag = SEC_OID_UNKNOWN; /* an invalid encryption alg */

    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg));
       break;
    case NSSCMSRecipientInfoID_KeyAgree:
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg));
       break;
    case NSSCMSRecipientInfoID_KEK:
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg));
       break;
    }
    return encalgtag;
}
int NSS_CMSRecipientInfo_GetVersion ( NSSCMSRecipientInfo *  ri)

Definition at line 386 of file cmsrecinfo.c.

{
    unsigned long version;
    SECItem *versionitem = NULL;

    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
       /* ignore subIndex */
       versionitem = &(ri->ri.keyTransRecipientInfo.version);
       break;
    case NSSCMSRecipientInfoID_KEK:
       /* ignore subIndex */
       versionitem = &(ri->ri.kekRecipientInfo.version);
       break;
    case NSSCMSRecipientInfoID_KeyAgree:
       versionitem = &(ri->ri.keyAgreeRecipientInfo.version);
       break;
    }

    PORT_Assert(versionitem);
    if (versionitem == NULL) 
       return 0;

    /* always take apart the SECItem */
    if (SEC_ASN1DecodeInteger(versionitem, &version) != SECSuccess)
       return 0;
    else
       return (int)version;
}
PK11SymKey* NSS_CMSRecipientInfo_UnwrapBulkKey ( NSSCMSRecipientInfo *  ri,
int  subIndex,
CERTCertificate *  cert,
SECKEYPrivateKey *  privkey,
SECOidTag  bulkalgtag 
)

Definition at line 556 of file cmsrecinfo.c.

{
    PK11SymKey *bulkkey = NULL;
    SECAlgorithmID *encalg;
    SECOidTag encalgtag;
    SECItem *enckey;
    int error;

    ri->cert = CERT_DupCertificate(cert);
              /* mark the recipientInfo so we can find it later */

    switch (ri->recipientInfoType) {
    case NSSCMSRecipientInfoID_KeyTrans:
       encalg = &(ri->ri.keyTransRecipientInfo.keyEncAlg);
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg));
       enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */
       switch (encalgtag) {
       case SEC_OID_PKCS1_RSA_ENCRYPTION:
           /* RSA encryption algorithm: */
           /* get the symmetric (bulk) key by unwrapping it using our private key */
           bulkkey = NSS_CMSUtil_DecryptSymKey_RSA(privkey, enckey, bulkalgtag);
           break;
       case SEC_OID_NETSCAPE_SMIME_KEA:
           /* FORTEZZA key exchange algorithm */
           /* the supplemental data is in the parameters of encalg */
           bulkkey = NSS_CMSUtil_DecryptSymKey_MISSI(privkey, enckey, encalg, bulkalgtag, ri->cmsg->pwfn_arg);
           break;
       default:
           error = SEC_ERROR_UNSUPPORTED_KEYALG;
           goto loser;
       }
       break;
    case NSSCMSRecipientInfoID_KeyAgree:
       encalg = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg);
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg));
       enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey);
       switch (encalgtag) {
       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
           /* Diffie-Helman key exchange */
           /* XXX not yet implemented */
           /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */
           /* we support ephemeral-static DH only, so if the recipientinfo */
           /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */
           /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */
           /* content encryption key using a Unwrap op */
           /* the derive operation has to generate the key using the algorithm in RFC2631 */
           error = SEC_ERROR_UNSUPPORTED_KEYALG;
           break;
       default:
           error = SEC_ERROR_UNSUPPORTED_KEYALG;
           goto loser;
       }
       break;
    case NSSCMSRecipientInfoID_KEK:
       encalg = &(ri->ri.kekRecipientInfo.keyEncAlg);
       encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg));
       enckey = &(ri->ri.kekRecipientInfo.encKey);
       /* not supported yet */
       error = SEC_ERROR_UNSUPPORTED_KEYALG;
       goto loser;
       break;
    }
    /* XXXX continue here */
    return bulkkey;

loser:
    return NULL;
}
PRBool nss_cmsrecipientinfo_usessubjectkeyid ( NSSCMSRecipientInfo *  ri)

Definition at line 54 of file cmsrecinfo.c.

{
    if (ri->recipientInfoType == NSSCMSRecipientInfoID_KeyTrans) {
       NSSCMSRecipientIdentifier *rid;
       rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
       if (rid->identifierType == NSSCMSRecipientID_SubjectKeyID) {
           return PR_TRUE;
       }
    }
    return PR_FALSE;
}

Here is the caller graph for this function:

SECStatus NSS_CMSRecipientInfo_WrapBulkKey ( NSSCMSRecipientInfo *  ri,
PK11SymKey *  bulkkey,
SECOidTag  bulkalgtag 
)

Definition at line 458 of file cmsrecinfo.c.

{
    CERTCertificate *cert;
    SECOidTag certalgtag;
    SECStatus rv = SECSuccess;
    SECItem *params = NULL;
    NSSCMSRecipientEncryptedKey *rek;
    NSSCMSOriginatorIdentifierOrKey *oiok;
    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
    PLArenaPool *poolp;
    NSSCMSKeyTransRecipientInfoEx *extra = NULL;
    PRBool usesSubjKeyID;

    poolp = ri->cmsg->poolp;
    cert = ri->cert;
    usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
    if (cert) {
       spki = &cert->subjectPublicKeyInfo;
       certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));
    } else if (usesSubjKeyID) {
       extra = &ri->ri.keyTransRecipientInfoEx;
       /* sanity check */
       PORT_Assert(extra->pubKey);
       if (!extra->pubKey) {
           PORT_SetError(SEC_ERROR_INVALID_ARGS);
           return SECFailure;
       }
       spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(extra->pubKey);
       certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
    } else {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    /* XXX set ri->recipientInfoType to the proper value here */
    /* or should we look if it's been set already ? */

    certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
       /* wrap the symkey */
       if (cert) {
           rv = NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, 
                                &ri->ri.keyTransRecipientInfo.encKey);
           if (rv != SECSuccess)
              break;
       } else if (usesSubjKeyID) {
           PORT_Assert(extra != NULL);
           rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, extra->pubKey,
                                bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
           if (rv != SECSuccess)
              break;
       }

       rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
       break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
       rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
       if (rek == NULL) {
           rv = SECFailure;
           break;
       }

       oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
       PORT_Assert(oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey);

       /* see RFC2630 12.3.1.1 */
       if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
                                SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {
           rv = SECFailure;
           break;
       }

       /* this will generate a key pair, compute the shared secret, */
       /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
       /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
       rv = NSS_CMSUtil_EncryptSymKey_ESDH(poolp, cert, bulkkey,
                                   &rek->encKey,
                                   &ri->ri.keyAgreeRecipientInfo.ukm,
                                   &ri->ri.keyAgreeRecipientInfo.keyEncAlg,
                                   &oiok->id.originatorPublicKey.publicKey);

       break;
    default:
       /* other algorithms not supported yet */
       /* NOTE that we do not support any KEK algorithm */
       PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
       rv = SECFailure;
       break;
    }
    if (freeSpki)
       SECKEY_DestroySubjectPublicKeyInfo(freeSpki);

    return rv;
}

Variable Documentation

const SECOidData fakeContent [static]

Definition at line 74 of file cmsrecinfo.c.