summaryrefslogtreecommitdiff
path: root/security/nss/lib/smime/cmsrecinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/smime/cmsrecinfo.c')
-rw-r--r--security/nss/lib/smime/cmsrecinfo.c717
1 files changed, 0 insertions, 717 deletions
diff --git a/security/nss/lib/smime/cmsrecinfo.c b/security/nss/lib/smime/cmsrecinfo.c
deleted file mode 100644
index cd2ca16d5..000000000
--- a/security/nss/lib/smime/cmsrecinfo.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * CMS recipientInfo methods.
- *
- * $Id$
- */
-
-#include "cmslocal.h"
-
-#include "cert.h"
-#include "key.h"
-#include "secasn1.h"
-#include "secitem.h"
-#include "secoid.h"
-#include "pk11func.h"
-#include "secerr.h"
-
-PRBool
-nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri)
-{
- if (ri->recipientInfoType == NSSCMSRecipientInfoID_KeyTrans) {
- NSSCMSRecipientIdentifier *rid;
- rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
- if (rid->identifierType == NSSCMSRecipientID_SubjectKeyID) {
- return PR_TRUE;
- }
- }
- return PR_FALSE;
-}
-
-/*
- * NOTE: fakeContent marks CMSMessage structure which is only used as a carrier
- * of pwfn_arg and arena pools. In an ideal world, NSSCMSMessage would not have
- * been exported, and we would have added an ordinary enum to handle this
- * check. Unfortunatly wo don't have that luxury so we are overloading the
- * contentTypeTag field. NO code should every try to interpret this content tag
- * as a real OID tag, or use any fields other than pwfn_arg or poolp of this
- * CMSMessage for that matter */
-static const SECOidData fakeContent;
-NSSCMSRecipientInfo *
-nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg,
- NSSCMSRecipientIDSelector type,
- CERTCertificate *cert,
- SECKEYPublicKey *pubKey,
- SECItem *subjKeyID,
- void* pwfn_arg,
- SECItem* DERinput)
-{
- 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 = (SECOidData *)&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;
-}
-
-/*
- * NSS_CMSRecipientInfo_Create - create a recipientinfo
- *
- * we currently do not create KeyAgreement recipientinfos with multiple
- * recipientEncryptedKeys the certificate is supposed to have been
- * verified by the caller
- */
-NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert)
-{
- return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert,
- NULL, NULL, NULL, NULL);
-}
-
-NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_CreateNew(void* pwfn_arg)
-{
- return nss_cmsrecipientinfo_create(NULL, NSSCMSRecipientID_BrandNew, NULL,
- NULL, NULL, pwfn_arg, NULL);
-}
-
-NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_CreateFromDER(SECItem* input, void* pwfn_arg)
-{
- return nss_cmsrecipientinfo_create(NULL, NSSCMSRecipientID_BrandNew, NULL,
- NULL, NULL, pwfn_arg, input);
-}
-
-
-NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage *cmsg,
- SECItem *subjKeyID,
- SECKEYPublicKey *pubKey)
-{
- return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID,
- NULL, pubKey, subjKeyID, NULL, NULL);
-}
-
-NSSCMSRecipientInfo *
-NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg,
- CERTCertificate *cert)
-{
- 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)
-{
- 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. */
-}
-
-int
-NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri)
-{
- 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;
-}
-
-SECItem *
-NSS_CMSRecipientInfo_GetEncryptedKey(NSSCMSRecipientInfo *ri, int subIndex)
-{
- 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;
-}
-
-
-SECOidTag
-NSS_CMSRecipientInfo_GetKeyEncryptionAlgorithmTag(NSSCMSRecipientInfo *ri)
-{
- 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;
-}
-
-SECStatus
-NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
- SECOidTag bulkalgtag)
-{
- CERTCertificate *cert;
- SECOidTag certalgtag;
- SECStatus rv = SECSuccess;
- 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;
-}
-
-PK11SymKey *
-NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex,
- CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag)
-{
- 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;
-}
-
-SECStatus NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri,
- CERTCertificate** retcert,
- SECKEYPrivateKey** retkey)
-{
- 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;
-}
-
-SECStatus NSS_CMSRecipientInfo_Encode(PRArenaPool* poolp,
- const NSSCMSRecipientInfo *src,
- SECItem* returned)
-{
- 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;
-}