RFE:Add ability to encode/decode NSSCMSRecipientInfo structures

r=javi,wtc
This commit is contained in:
relyea%netscape.com 2003-02-28 23:32:29 +00:00
Родитель 0cd6fbdd62
Коммит ed4ffe44f6
4 изменённых файлов: 192 добавлений и 17 удалений

Просмотреть файл

@ -34,7 +34,7 @@
/* /*
* Interfaces of the CMS implementation. * Interfaces of the CMS implementation.
* *
* $Id: cms.h,v 1.15 2002/12/17 01:39:45 wtc%netscape.com Exp $ * $Id: cms.h,v 1.16 2003/02/28 23:32:29 relyea%netscape.com Exp $
*/ */
#ifndef _CMS_H_ #ifndef _CMS_H_
@ -868,9 +868,35 @@ extern NSSCMSRecipientInfo *
NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg, NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage *cmsg,
CERTCertificate *cert); CERTCertificate *cert);
/*
* NSS_CMSRecipientInfo_CreateNew - create a blank recipientinfo for
* applications which want to encode their own CMS structures and
* key exchange types.
*/
extern NSSCMSRecipientInfo *
NSS_CMSRecipientInfo_CreateNew(void* pwfn_arg);
/*
* NSS_CMSRecipientInfo_CreateFromDER - create a recipientinfo from partially
* decoded DER data for applications which want to encode their own CMS
* structures and key exchange types.
*/
extern NSSCMSRecipientInfo *
NSS_CMSRecipientInfo_CreateFromDER(SECItem* input, void* pwfn_arg);
extern void extern void
NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri); NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri);
/*
* NSS_CMSRecipientInfo_GetCertAndKey - retrieve the cert and key from the
* recipientInfo struct. If retcert or retkey are NULL, the cert or
* key (respectively) would not be returned). This function is a no-op if both
* retcert and retkey are NULL. Caller inherits ownership of the cert and key
* he requested (and is responsible to free them).
*/
SECStatus NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri,
CERTCertificate** retcert, SECKEYPrivateKey** retkey);
extern int extern int
NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri); NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo *ri);

Просмотреть файл

@ -34,7 +34,7 @@
/* /*
* CMS recipientInfo methods. * CMS recipientInfo methods.
* *
* $Id: cmsrecinfo.c,v 1.10 2003/01/17 02:49:07 wtc%netscape.com Exp $ * $Id: cmsrecinfo.c,v 1.11 2003/02/28 23:32:29 relyea%netscape.com Exp $
*/ */
#include "cmslocal.h" #include "cmslocal.h"
@ -61,10 +61,11 @@ nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri)
} }
static SECOidData fakeContent = { 0 };
NSSCMSRecipientInfo * NSSCMSRecipientInfo *
nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type, nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,
CERTCertificate *cert, SECKEYPublicKey *pubKey, CERTCertificate *cert, SECKEYPublicKey *pubKey,
SECItem *subjKeyID) SECItem *subjKeyID, void* pwfn_arg, SECItem* DERinput)
{ {
NSSCMSRecipientInfo *ri; NSSCMSRecipientInfo *ri;
void *mark; void *mark;
@ -77,6 +78,16 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,
PLArenaPool *poolp; PLArenaPool *poolp;
CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL; CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
NSSCMSRecipientIdentifier *rid; 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; poolp = cmsg->poolp;
@ -87,14 +98,43 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,
goto loser; goto loser;
ri->cmsg = cmsg; ri->cmsg = cmsg;
if (type == NSSCMSRecipientID_IssuerSN) {
ri->cert = CERT_DupCertificate(cert); if (DERinput) {
if (ri->cert == NULL) /* decode everything from DER */
goto loser; SECItem newinput;
spki = &(cert->subjectPublicKeyInfo); SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput);
} else { if (SECSuccess != rv)
PORT_Assert(pubKey); goto loser;
spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); 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)); certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));
@ -238,15 +278,20 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,
} }
done:
PORT_ArenaUnmark (poolp, mark); PORT_ArenaUnmark (poolp, mark);
if (freeSpki) if (freeSpki)
SECKEY_DestroySubjectPublicKeyInfo(freeSpki); SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
return ri; return ri;
loser: loser:
if (freeSpki) if (freeSpki) {
SECKEY_DestroySubjectPublicKeyInfo(freeSpki); SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
}
PORT_ArenaRelease (poolp, mark); PORT_ArenaRelease (poolp, mark);
if (cmsg->contentInfo.contentTypeTag == &fakeContent) {
NSS_CMSMessage_Destroy(cmsg);
}
return NULL; return NULL;
} }
@ -261,16 +306,31 @@ NSSCMSRecipientInfo *
NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert) NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert)
{ {
return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert, return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert,
NULL, NULL); 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 * NSSCMSRecipientInfo *
NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage *cmsg, NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage *cmsg,
SECItem *subjKeyID, SECItem *subjKeyID,
SECKEYPublicKey *pubKey) SECKEYPublicKey *pubKey)
{ {
return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID, return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_SubjectKeyID,
NULL, pubKey, subjKeyID); NULL, pubKey, subjKeyID, NULL, NULL);
} }
NSSCMSRecipientInfo * NSSCMSRecipientInfo *
@ -306,6 +366,9 @@ done:
void void
NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri) NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri)
{ {
if (!ri) {
return;
}
/* version was allocated on the pool, so no need to destroy it */ /* version was allocated on the pool, so no need to destroy it */
/* issuerAndSN 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) if (ri->cert != NULL)
@ -317,8 +380,10 @@ NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri)
if (extra->pubKey) if (extra->pubKey)
SECKEY_DestroyPublicKey(extra->pubKey); SECKEY_DestroyPublicKey(extra->pubKey);
} }
if (ri->cmsg->contentInfo.contentTypeTag == &fakeContent) {
NSS_CMSMessage_Destroy(ri->cmsg);
}
/* recipientInfo structure itself was allocated on the pool, so no need to destroy it */
/* we're done. */ /* we're done. */
} }
@ -576,3 +641,78 @@ NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex,
loser: loser:
return NULL; 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;
}

Просмотреть файл

@ -34,7 +34,7 @@
/* /*
* Header for CMS types. * Header for CMS types.
* *
* $Id: cmst.h,v 1.7 2002/12/24 02:25:36 wtc%netscape.com Exp $ * $Id: cmst.h,v 1.8 2003/02/28 23:32:29 relyea%netscape.com Exp $
*/ */
#ifndef _CMST_H_ #ifndef _CMST_H_
@ -283,7 +283,8 @@ struct NSSCMSOriginatorInfoStr {
*/ */
typedef enum { typedef enum {
NSSCMSRecipientID_IssuerSN = 0, NSSCMSRecipientID_IssuerSN = 0,
NSSCMSRecipientID_SubjectKeyID = 1 NSSCMSRecipientID_SubjectKeyID = 1,
NSSCMSRecipientID_BrandNew = 2
} NSSCMSRecipientIDSelector; } NSSCMSRecipientIDSelector;
struct NSSCMSRecipientIdentifierStr { struct NSSCMSRecipientIdentifierStr {

Просмотреть файл

@ -230,3 +230,11 @@ NSS_CMSRecipientInfo_UnwrapBulkKey;
;+ local: ;+ local:
;+ *; ;+ *;
;+}; ;+};
;+NSS_3.8 { # NSS 3.8 release
;+ global:
NSS_CMSRecipientInfo_CreateNew;
NSS_CMSRecipientInfo_CreateFromDER;
NSS_CMSRecipientInfo_GetCertAndKey;
;+ local:
;+ *;
;+};