diff options
Diffstat (limited to 'security/nss/lib/smime/cmsrecinfo.c')
-rw-r--r-- | security/nss/lib/smime/cmsrecinfo.c | 717 |
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; -} |