summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrichard.freedman%sun.com <devnull@localhost>2006-05-10 20:44:45 +0000
committerrichard.freedman%sun.com <devnull@localhost>2006-05-10 20:44:45 +0000
commit6efd45d69ab35a597ef783d02f55e3041894546a (patch)
tree555fb4f7a942356f940f5644e4e03e902ee4a4fd
parentb1c3d9724d3979d21bb0b995b21c562fee33bc28 (diff)
downloadnss-hg-6efd45d69ab35a597ef783d02f55e3041894546a.tar.gz
Include decoding of signedData messages returned by Http servers.
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c804
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h51
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c11
-rw-r--r--security/nss/lib/nss/nss.def2
4 files changed, 851 insertions, 17 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c
index ef1536892..5d0e1a16a 100755
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c
@@ -45,6 +45,39 @@
#include "pkix_pl_httpcertstore.h"
extern PKIX_PL_HashTable *httpSocketCache;
+const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[];
+SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
+SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
+
+SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate)
+/* SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate)
+SEC_ASN1_CHOOSER_DECLARE(CERT_SetOfSignedCrlTemplate)
+
+const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTIssuerAndSN) },
+ { SEC_ASN1_SAVE,
+ offsetof(CERTIssuerAndSN,derIssuer) },
+ { SEC_ASN1_INLINE,
+ offsetof(CERTIssuerAndSN,issuer),
+ CERT_NameTemplate },
+ { SEC_ASN1_INTEGER,
+ offsetof(CERTIssuerAndSN,serialNumber) },
+ { 0 }
+};
+
+const SEC_ASN1Template SECOID_AlgorithmIDTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SECAlgorithmID) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(SECAlgorithmID,algorithm), },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
+ offsetof(SECAlgorithmID,parameters), },
+ { 0, }
+}; */
/* --Private-HttpCertStoreContext-Object Functions----------------------- */
@@ -133,6 +166,11 @@ pkix_pl_HttpCertStoreContext_RegisterSelf(void *plContext)
}
/* --Private-Http-CertStore-Database-Functions----------------------- */
+extern void SEC_ASN1DecoderSetNotifyProc(
+ SEC_ASN1DecoderContext *dcx,
+ SEC_ASN1NotifyProc sec_pkcs7_decoder_notify,
+ void *p7dcx);
+
typedef struct callbackContextStruct {
PKIX_List *pkixCertList;
@@ -170,7 +208,6 @@ typedef struct callbackContextStruct {
static SECStatus
certCallback(void *arg, SECItem **secitemCerts, int numcerts)
{
- SECStatus rv;
callbackContext *cbContext;
SECItem **certs = NULL;
SECItem *cert = NULL;
@@ -200,13 +237,564 @@ certCallback(void *arg, SECItem **secitemCerts, int numcerts)
}
}
- rv = (certsFound == numcerts)?SECSuccess:SECFailure;
+ return ((certsFound == numcerts)?SECSuccess:SECFailure);
+}
+
+static SECOidTag
+SEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo)
+{
+ if (cinfo->contentTypeTag == NULL)
+ cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
+
+ if (cinfo->contentTypeTag == NULL)
+ return SEC_OID_UNKNOWN;
+
+ return cinfo->contentTypeTag->offset;
+}
+
+/*
+ * Destroy a PKCS7 contentInfo and all of its sub-pieces.
+ */
+
+static void
+SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo)
+{
+ SECOidTag kind;
+ CERTCertificate **certs;
+ CERTCertificateList **certlists;
+ SEC_PKCS7SignerInfo **signerinfos;
+ SEC_PKCS7RecipientInfo **recipientinfos;
+
+ PORT_Assert (cinfo->refCount > 0);
+ if (cinfo->refCount <= 0)
+ return;
+
+ cinfo->refCount--;
+ if (cinfo->refCount > 0)
+ return;
+
+ certs = NULL;
+ certlists = NULL;
+ recipientinfos = NULL;
+ signerinfos = NULL;
+
+ kind = SEC_PKCS7ContentType (cinfo);
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ {
+ SEC_PKCS7SignedData *sdp;
+
+ sdp = cinfo->content.signedData;
+ if (sdp != NULL) {
+ certs = sdp->certs;
+ certlists = sdp->certLists;
+ signerinfos = sdp->signerInfos;
+ }
+ }
+ break;
+ default:
+ /* XXX Anything else that needs to be "manually" freed/destroyed? */
+ break;
+ }
+
+ if (certs != NULL) {
+ CERTCertificate *cert;
+
+ while ((cert = *certs++) != NULL) {
+ CERT_DestroyCertificate (cert);
+ }
+ }
+
+ if (certlists != NULL) {
+ CERTCertificateList *certlist;
+
+ while ((certlist = *certlists++) != NULL) {
+ CERT_DestroyCertificateList (certlist);
+ }
+ }
+
+ if (recipientinfos != NULL) {
+ SEC_PKCS7RecipientInfo *ri;
+
+ while ((ri = *recipientinfos++) != NULL) {
+ if (ri->cert != NULL)
+ CERT_DestroyCertificate (ri->cert);
+ }
+ }
+
+ if (signerinfos != NULL) {
+ SEC_PKCS7SignerInfo *si;
+
+ while ((si = *signerinfos++) != NULL) {
+ if (si->cert != NULL)
+ CERT_DestroyCertificate (si->cert);
+ if (si->certList != NULL)
+ CERT_DestroyCertificateList (si->certList);
+ }
+ }
+
+ if (cinfo->poolp != NULL) {
+ PORT_FreeArena (cinfo->poolp, PR_FALSE); /* XXX clear it? */
+ }
+}
+
+/* XXX unused? */
+static SECStatus
+sec_pkcs7_decoder_start_digests (SEC_PKCS7DecoderContext *p7dcx, int depth,
+ SECAlgorithmID **digestalgs)
+{
+ return (SECFailure);
+}
+
+/* XXX unused? */
+static SECStatus
+sec_pkcs7_decoder_finish_digests (SEC_PKCS7DecoderContext *p7dcx,
+ PRArenaPool *poolp,
+ SECItem ***digestsp)
+{
+ return (SECFailure);
+}
+
+static void
+sec_pkcs7_decoder_notify (void *arg, PRBool before, void *dest, int depth)
+{
+ SEC_PKCS7DecoderContext *p7dcx;
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7SignedData *sigd;
+ PRBool after;
+ SECStatus rv;
+
+ /*
+ * Just to make the code easier to read, create an "after" variable
+ * that is equivalent to "not before".
+ * (This used to be just the statement "after = !before", but that
+ * causes a warning on the mac; to avoid that, we do it the long way.)
+ */
+ if (before)
+ after = PR_FALSE;
+ else
+ after = PR_TRUE;
+
+ p7dcx = (SEC_PKCS7DecoderContext*)arg;
+ cinfo = p7dcx->cinfo;
+
+ if (cinfo->contentTypeTag == NULL) {
+ if (after && dest == &(cinfo->contentType))
+ cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
+ return;
+ }
+
+ switch (cinfo->contentTypeTag->offset) {
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ sigd = cinfo->content.signedData;
+ if (sigd == NULL)
+ break;
+
+ if (sigd->contentInfo.contentTypeTag == NULL) {
+ if (after && dest == &(sigd->contentInfo.contentType))
+ sigd->contentInfo.contentTypeTag =
+ SECOID_FindOID(&(sigd->contentInfo.contentType));
+ break;
+ }
+
+ /*
+ * We only set up a filtering digest if the content is
+ * plain DATA; anything else needs more work because a
+ * second pass is required to produce a DER encoding from
+ * an input that can be BER encoded. (This is a requirement
+ * of PKCS7 that is unfortunate, but there you have it.)
+ *
+ * XXX Also, since we stop here if this is not DATA, the
+ * inner content is not getting processed at all. Someday
+ * we may want to fix that.
+ */
+ if (sigd->contentInfo.contentTypeTag->offset != SEC_OID_PKCS7_DATA) {
+ /* XXX Set an error in p7dcx->error */
+ SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
+ break;
+ }
+
+ /*
+ * Just before the content, we want to set up a digest context
+ * for each digest algorithm listed, and start a filter which
+ * will run all of the contents bytes through that digest.
+ */
+ if (before && dest == &(sigd->contentInfo.content)) {
+ rv = sec_pkcs7_decoder_start_digests (p7dcx, depth,
+ sigd->digestAlgorithms);
+ if (rv != SECSuccess)
+ SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
+
+ break;
+ }
+
+ /*
+ * XXX To handle nested types, here is where we would want
+ * to check for inner boundaries that need handling.
+ */
+
+ /*
+ * Are we done?
+ */
+ if (after && dest == &(sigd->contentInfo.content)) {
+ /*
+ * Close out the digest contexts. We ignore any error
+ * because we are stopping anyway; the error status left
+ * behind in p7dcx will be seen by outer functions.
+ */
+ (void) sec_pkcs7_decoder_finish_digests (p7dcx, cinfo->poolp,
+ &(sigd->digests));
+
+ /*
+ * XXX To handle nested contents, we would need to remove
+ * the worker from the chain (and free it).
+ */
+
+ /*
+ * Stop notify.
+ */
+ SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
+ }
+ break;
+
+ default:
+ SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
+ break;
+ }
+}
+
+
+/* XXX Only called with all args NULL */
+
+static SEC_PKCS7DecoderContext *
+SEC_PKCS7DecoderStart(SEC_PKCS7DecoderContentCallback cb, void *cb_arg,
+ SECKEYGetPasswordKey pwfn, void *pwfn_arg,
+ SEC_PKCS7GetDecryptKeyCallback decrypt_key_cb,
+ void *decrypt_key_cb_arg,
+ SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb)
+{
+ SEC_PKCS7DecoderContext *p7dcx;
+ SEC_ASN1DecoderContext *dcx;
+ SEC_PKCS7ContentInfo *cinfo;
+ PRArenaPool *poolp;
+
+ poolp = PORT_NewArena (1024); /* XXX what is right value? */
+ if (poolp == NULL)
+ return NULL;
+
+ cinfo = (SEC_PKCS7ContentInfo*)PORT_ArenaZAlloc (poolp, sizeof(*cinfo));
+ if (cinfo == NULL) {
+ PORT_FreeArena (poolp, PR_FALSE);
+ return NULL;
+ }
+
+ cinfo->poolp = poolp;
+ cinfo->pwfn = pwfn;
+ cinfo->pwfn_arg = pwfn_arg;
+ cinfo->created = PR_FALSE;
+ cinfo->refCount = 1;
+
+ p7dcx =
+ (SEC_PKCS7DecoderContext*)PORT_ZAlloc (sizeof(SEC_PKCS7DecoderContext));
+ if (p7dcx == NULL) {
+ PORT_FreeArena (poolp, PR_FALSE);
+ return NULL;
+ }
+
+ p7dcx->tmp_poolp = PORT_NewArena (1024); /* XXX what is right value? */
+ if (p7dcx->tmp_poolp == NULL) {
+ PORT_Free (p7dcx);
+ PORT_FreeArena (poolp, PR_FALSE);
+ return NULL;
+ }
+
+ dcx = SEC_ASN1DecoderStart (poolp, cinfo, sec_PKCS7ContentInfoTemplate);
+ if (dcx == NULL) {
+ PORT_FreeArena (p7dcx->tmp_poolp, PR_FALSE);
+ PORT_Free (p7dcx);
+ PORT_FreeArena (poolp, PR_FALSE);
+ return NULL;
+ }
+
+ SEC_ASN1DecoderSetNotifyProc (dcx, sec_pkcs7_decoder_notify, p7dcx);
+
+ p7dcx->dcx = dcx;
+ p7dcx->cinfo = cinfo;
+ p7dcx->cb = cb;
+ p7dcx->cb_arg = cb_arg;
+ p7dcx->pwfn = pwfn;
+ p7dcx->pwfn_arg = pwfn_arg;
+ p7dcx->dkcb = decrypt_key_cb;
+ p7dcx->dkcb_arg = decrypt_key_cb_arg;
+ p7dcx->decrypt_allowed_cb = decrypt_allowed_cb;
+
+ return p7dcx;
+}
+
+
+/*
+ * Do the next chunk of PKCS7 decoding. If there is a problem, set
+ * an error and return a failure status. Note that in the case of
+ * an error, this routine is still prepared to be called again and
+ * again in case that is the easiest route for our caller to take.
+ * We simply detect it and do not do anything except keep setting
+ * that error in case our caller has not noticed it yet...
+ */
+static SECStatus
+SEC_PKCS7DecoderUpdate(SEC_PKCS7DecoderContext *p7dcx,
+ const char *buf, unsigned long len)
+{
+ if (p7dcx->cinfo != NULL && p7dcx->dcx != NULL) {
+ PORT_Assert (p7dcx->error == 0);
+ if (p7dcx->error == 0) {
+ if (SEC_ASN1DecoderUpdate (p7dcx->dcx, buf, len) != SECSuccess) {
+ p7dcx->error = PORT_GetError();
+ PORT_Assert (p7dcx->error);
+ if (p7dcx->error == 0)
+ p7dcx->error = -1;
+ }
+ }
+ }
+
+ if (p7dcx->error) {
+ if (p7dcx->dcx != NULL) {
+ (void) SEC_ASN1DecoderFinish (p7dcx->dcx);
+ p7dcx->dcx = NULL;
+ }
+ if (p7dcx->cinfo != NULL) {
+ SEC_PKCS7DestroyContentInfo (p7dcx->cinfo);
+ p7dcx->cinfo = NULL;
+ }
+ PORT_SetError (p7dcx->error);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+static void
+sec_pkcs7_destroy_cipher (sec_PKCS7CipherObject *obj)
+{
+ (* obj->destroy) (obj->cx, PR_TRUE);
+ PORT_Free (obj);
+}
+
+static void
+sec_PKCS7DestroyDecryptObject (sec_PKCS7CipherObject *obj)
+{
+ PORT_Assert (obj != NULL);
+ if (obj == NULL)
+ return;
+ PORT_Assert (! obj->encrypt);
+ sec_pkcs7_destroy_cipher (obj);
+}
+
+static SEC_PKCS7ContentInfo *
+SEC_PKCS7DecoderFinish(SEC_PKCS7DecoderContext *p7dcx)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+
+ cinfo = p7dcx->cinfo;
+ if (p7dcx->dcx != NULL) {
+ if (SEC_ASN1DecoderFinish (p7dcx->dcx) != SECSuccess) {
+ SEC_PKCS7DestroyContentInfo (cinfo);
+ cinfo = NULL;
+ }
+ }
+ /* free any NSS data structures */
+ if (p7dcx->worker.decryptobj) {
+ sec_PKCS7DestroyDecryptObject (p7dcx->worker.decryptobj);
+ }
+ PORT_FreeArena (p7dcx->tmp_poolp, PR_FALSE);
+ PORT_Free (p7dcx);
+ return cinfo;
+}
+
+static SECStatus
+SEC_ReadPKCS7Certs(SECItem *pkcs7Item, CERTImportCertificateFunc f, void *arg)
+{
+ SEC_PKCS7ContentInfo *contentInfo = NULL;
+ SECStatus rv;
+ SECItem **certs;
+ int count;
+
+ SEC_PKCS7DecoderContext *p7dcx;
+
+ p7dcx = SEC_PKCS7DecoderStart(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ (void) SEC_PKCS7DecoderUpdate
+ (p7dcx, (char *) pkcs7Item->data, pkcs7Item->len);
+ contentInfo = SEC_PKCS7DecoderFinish(p7dcx);
+
+ if ( contentInfo == NULL ) {
+ goto loser;
+ }
+
+ if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_PKCS7_SIGNED_DATA ) {
+ goto loser;
+ }
+
+ certs = contentInfo->content.signedData->rawCerts;
+ if ( certs ) {
+ count = 0;
+
+ while ( *certs ) {
+ count++;
+ certs++;
+ }
+ rv = (* f)(arg, contentInfo->content.signedData->rawCerts, count);
+ }
+
+ rv = SECSuccess;
+
+ goto done;
+loser:
+ rv = SECFailure;
+
+done:
+ if ( contentInfo ) {
+ SEC_PKCS7DestroyContentInfo(contentInfo);
+ }
+
+ return(rv);
+}
+
+/*
+ * This function is based on CERT_DecodeCertPackage from lib/pkcs7/certread.c
+ * read an old style ascii or binary certificate chain
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_DecodeCertPackage
+ (char *certbuf,
+ int certlen,
+ CERTImportCertificateFunc f,
+ void *arg,
+ void *plContext)
+{
+ unsigned char *cp;
+ unsigned char *bincert = NULL;
+ char *ascCert = NULL;
+ SECItem certitem;
+ SECItem *pcertitem = &certitem;
+ int seqLen, seqLenLen;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER
+ (HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStore_DecodeCertPackage");
+ PKIX_NULLCHECK_TWO(certbuf, f);
+
+ cp = (unsigned char *)certbuf;
+
+ /* is this a DER encoded certificate of some type? */
+ if ( ( *cp & 0x1f ) == SEC_ASN1_SEQUENCE ) {
+
+ cp++;
+
+ if (*cp & 0x80) {
+ /* Multibyte length */
+ seqLenLen = cp[0] & 0x7f;
+
+ switch (seqLenLen) {
+ case 4:
+ seqLen = ((unsigned long)cp[1] << 24) |
+ ((unsigned long)cp[2] << 16) |
+ (cp[3]<<8) | cp[4];
+ break;
+ case 3:
+ seqLen = ((unsigned long)cp[1]<<16) |
+ (cp[2]<<8) | cp[3];
+ break;
+ case 2:
+ seqLen = (cp[1]<<8) | cp[2];
+ break;
+ case 1:
+ seqLen = cp[1];
+ break;
+ default:
+ /* indefinite length */
+ seqLen = 0;
+ }
+ cp += ( seqLenLen + 1 );
+
+ } else {
+ seqLenLen = 0;
+ seqLen = *cp;
+ cp++;
+ }
+
+ /* check entire length if definite length */
+ if ( seqLen || seqLenLen ) {
+ if ( certlen != ( seqLen + seqLenLen + 2 ) ) {
+ if (certlen > ( seqLen + seqLenLen + 2 )) {
+ PKIX_ERROR("Too much data in DER Sequence");
+ } else {
+ PKIX_ERROR("Too little data in DER Sequence");
+ }
+ }
+ } else {
+ PKIX_ERROR("Not a DER package");
+ }
+
+ if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
+ SECOidData *oiddata;
+ SECItem oiditem;
+ /* XXX - assume DER encoding of OID len!! */
+ oiditem.len = cp[1];
+ oiditem.data = (unsigned char *)&cp[2];
+ PKIX_PL_NSSCALLRV
+ (HTTPCERTSTORECONTEXT, oiddata, SECOID_FindOID,
+ (&oiditem));
+ if ( oiddata == NULL ) {
+ PKIX_ERROR("Unknown object OID");
+ }
+
+ certitem.data = (unsigned char*)certbuf;
+ certitem.len = certlen;
+
+ switch ( oiddata->offset ) {
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ PKIX_PL_NSSCALLRV
+ (HTTPCERTSTORECONTEXT,
+ rv,
+ SEC_ReadPKCS7Certs,
+ (&certitem, f, arg));
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ ("SEC_ReadPKCS7Certs failed");
+ }
+ break;
+ default:
+ PKIX_ERROR("Unknown object OID");
+ break;
+ }
+
+ } else {
+ /* it had better be a certificate by now!! */
+ certitem.data = (unsigned char*)certbuf;
+ certitem.len = certlen;
+
+ rv = (* f)(arg, &pcertitem, 1);
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ ("CERTImportCertificate function failed");
+ }
+ }
+ }
cleanup:
- return(rv);
+ if ( bincert ) {
+ PORT_Free(bincert);
+ }
+
+ if ( ascCert ) {
+ PORT_Free(ascCert);
+ }
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
}
+
/*
* FUNCTION: pkix_pl_HttpCertStore_ProcessCertResponse
* DESCRIPTION:
@@ -292,14 +880,13 @@ pkix_pl_HttpCertStore_ProcessCertResponse(
cbContext.plContext = plContext;
encodedResponse = (char *)responseData;
-#if 0
- PKIX_PL_NSSCALLRV(HTTPCERTSTORECONTEXT, rv, CERT_DecodeCertPackage,
- (encodedResponse, responseDataLen, certCallback, &cbContext));
-#endif
-
- if (rv != SECSuccess) {
- PKIX_ERROR("Error decoding pkcs7-mime data");
- }
+ PKIX_CHECK(pkix_pl_HttpCertStore_DecodeCertPackage
+ (encodedResponse,
+ responseDataLen,
+ certCallback,
+ &cbContext,
+ plContext),
+ "pkix_pl_HttpCertStore_DecodeCertPackage failed");
*pCertList = cbContext.pkixCertList;
@@ -1029,8 +1616,10 @@ pkix_HttpCertStore_FindSocketConnection(
(PKIX_ESCASCII, "%s:%d", 0, &formatString, plContext),
"PKIX_PL_String_Create failed");
+#if 0
hostname = "variation.red.iplanet.com";
portnum = 2001;
+#endif
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII, hostname, 0, &hostString, plContext),
@@ -1080,3 +1669,196 @@ cleanup:
PKIX_RETURN(CERTSTORE);
}
+
+static const SEC_ASN1Template *
+sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding)
+{
+ const SEC_ASN1Template *theTemplate;
+
+ SEC_PKCS7Attribute *attribute;
+ SECOidData *oiddata;
+ PRBool encoded;
+
+ PORT_Assert (src_or_dest != NULL);
+ if (src_or_dest == NULL)
+ return NULL;
+
+ attribute = (SEC_PKCS7Attribute*)src_or_dest;
+
+ if (encoding && attribute->encoded)
+ return SEC_ASN1_GET(SEC_AnyTemplate);
+
+ oiddata = attribute->typeTag;
+ if (oiddata == NULL) {
+ oiddata = SECOID_FindOID(&attribute->type);
+ attribute->typeTag = oiddata;
+ }
+
+ if (oiddata == NULL) {
+ encoded = PR_TRUE;
+ theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
+ } else {
+ switch (oiddata->offset) {
+ default:
+ encoded = PR_TRUE;
+ theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
+ break;
+ case SEC_OID_PKCS9_EMAIL_ADDRESS:
+ case SEC_OID_RFC1274_MAIL:
+ case SEC_OID_PKCS9_UNSTRUCTURED_NAME:
+ encoded = PR_FALSE;
+ theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ encoded = PR_FALSE;
+ theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate);
+ break;
+ case SEC_OID_PKCS9_MESSAGE_DIGEST:
+ encoded = PR_FALSE;
+ theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ encoded = PR_FALSE;
+ theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate);
+ break;
+ /* XXX Want other types here, too */
+ }
+ }
+
+ if (encoding) {
+ /*
+ * If we are encoding and we think we have an already-encoded value,
+ * then the code which initialized this attribute should have set
+ * the "encoded" property to true (and we would have returned early,
+ * up above). No devastating error, but that code should be fixed.
+ * (It could indicate that the resulting encoded bytes are wrong.)
+ */
+ PORT_Assert (!encoded);
+ } else {
+ /*
+ * We are decoding; record whether the resulting value is
+ * still encoded or not.
+ */
+ attribute->encoded = encoded;
+ }
+ return theTemplate;
+}
+
+static const SEC_ASN1Template *
+sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding);
+
+static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser
+ = sec_pkcs7_choose_content_template;
+
+static const SEC_ASN1TemplateChooserPtr sec_attr_chooser
+ = sec_attr_choose_attr_value_template;
+
+static const SEC_ASN1Template sec_pkcs7_attribute_template[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SEC_PKCS7Attribute) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(SEC_PKCS7Attribute,type) },
+ { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF,
+ offsetof(SEC_PKCS7Attribute,values),
+ &sec_attr_chooser },
+ { 0 }
+};
+
+static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = {
+ { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template },
+};
+
+static const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
+ 0, NULL, sizeof(SEC_PKCS7ContentInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(SEC_PKCS7ContentInfo,contentType) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM
+ | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(SEC_PKCS7ContentInfo,content),
+ &sec_pkcs7_chooser },
+ { 0 }
+};
+
+static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SEC_PKCS7SignerInfo) },
+ { SEC_ASN1_INTEGER,
+ offsetof(SEC_PKCS7SignerInfo,version) },
+ { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
+ offsetof(SEC_PKCS7SignerInfo,issuerAndSN),
+ SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(SEC_PKCS7SignerInfo,digestAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(SEC_PKCS7SignerInfo,authAttr),
+ sec_pkcs7_set_of_attribute_template },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(SEC_PKCS7SignerInfo,digestEncAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(SEC_PKCS7SignerInfo,encDigest) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
+ offsetof(SEC_PKCS7SignerInfo,unAuthAttr),
+ sec_pkcs7_set_of_attribute_template },
+ { 0 }
+};
+
+static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = {
+ { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
+ 0, NULL, sizeof(SEC_PKCS7SignedData) },
+ { SEC_ASN1_INTEGER,
+ offsetof(SEC_PKCS7SignedData,version) },
+ { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
+ offsetof(SEC_PKCS7SignedData,digestAlgorithms),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_INLINE,
+ offsetof(SEC_PKCS7SignedData,contentInfo),
+ sec_PKCS7ContentInfoTemplate },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ SEC_ASN1_XTRN | 0,
+ offsetof(SEC_PKCS7SignedData,rawCerts),
+ SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ SEC_ASN1_XTRN | 1,
+ offsetof(SEC_PKCS7SignedData,crls),
+ SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
+ { SEC_ASN1_SET_OF,
+ offsetof(SEC_PKCS7SignedData,signerInfos),
+ SEC_PKCS7SignerInfoTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate }
+};
+
+static const SEC_ASN1Template *
+sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding)
+{
+ const SEC_ASN1Template *theTemplate;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECOidTag kind;
+
+ PORT_Assert (src_or_dest != NULL);
+ if (src_or_dest == NULL)
+ return NULL;
+
+ cinfo = (SEC_PKCS7ContentInfo*)src_or_dest;
+ kind = SEC_PKCS7ContentType (cinfo);
+ switch (kind) {
+ default:
+ theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
+ break;
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ theTemplate = SEC_PointerToPKCS7SignedDataTemplate;
+ break;
+ }
+ return theTemplate;
+}
+
+/*
+ * End of templates. Do not add stuff after this; put new code
+ * up above the start of the template definitions.
+ */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h
index a6a18827c..c04cb4ed6 100644
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h
@@ -52,13 +52,52 @@ extern "C" {
#define RCVBUFSIZE 512
-#if 0
-struct PKIX_PL_HttpClientStruct {
- const SEC_HttpClientFcn *httpClient;
+typedef SECStatus (*sec_pkcs7_cipher_function) (void *,
+ unsigned char *,
+ unsigned *,
+ unsigned int,
+ const unsigned char *,
+ unsigned int);
+typedef SECStatus (*sec_pkcs7_cipher_destroy) (void *, PRBool);
+
+#define BLOCK_SIZE 4096
+
+struct sec_pkcs7_cipher_object {
+ void *cx;
+ sec_pkcs7_cipher_function doit;
+ sec_pkcs7_cipher_destroy destroy;
+ PRBool encrypt;
+ int block_size;
+ int pad_size;
+ int pending_count;
+ unsigned char pending_buf[BLOCK_SIZE];
+};
+
+typedef struct sec_pkcs7_cipher_object sec_PKCS7CipherObject;
+
+struct sec_pkcs7_decoder_worker {
+ int depth;
+ int digcnt;
+ void **digcxs;
+ void ** /* const SECHashObject **/ digobjs;
+ void * /* sec_PKCS7CipherObject * */ decryptobj;
+ PRBool saw_contents;
+};
+
+struct SEC_PKCS7DecoderContextStr {
+ SEC_ASN1DecoderContext *dcx;
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7DecoderContentCallback cb;
+ void *cb_arg;
+ SECKEYGetPasswordKey pwfn;
+ void *pwfn_arg;
+ struct sec_pkcs7_decoder_worker worker;
+ PRArenaPool *tmp_poolp;
+ int error;
+ SEC_PKCS7GetDecryptKeyCallback dkcb;
+ void *dkcb_arg;
+ SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb;
};
-
-typedef const SEC_HttpClientFcn *PKIX_PL_HttpClient;
-#endif
struct PKIX_PL_HttpCertStoreContextStruct {
const SEC_HttpClientFcn *client;
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
index 66af15730..824911c3f 100644
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
@@ -1278,6 +1278,7 @@ pkix_pl_HttpDefaultClient_RequestCreate(
client->timeout = timeout;
+#if 0
PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection
(timeout,
"variation.red.iplanet.com", /* (char *)client->host, */
@@ -1286,6 +1287,16 @@ pkix_pl_HttpDefaultClient_RequestCreate(
&socket,
plContext),
"pkix_HttpCertStore_FindSocketConnection failed");
+#else
+ PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection
+ (timeout,
+ (char *)client->host,
+ client->portnum,
+ &status,
+ &socket,
+ plContext),
+ "pkix_HttpCertStore_FindSocketConnection failed");
+#endif
client->socket = socket;
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index c7f70c4bc..45a0ab539 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -991,6 +991,7 @@ PKIX_PL_Cert_AreCertPoliciesCritical;
PKIX_PL_Cert_CheckNameConstraints;
PKIX_PL_Cert_CheckValidity;
PKIX_PL_Cert_Create;
+pkix_pl_Cert_CreateToList;
pkix_pl_Cert_CreateWithNSSCert;
PKIX_PL_Cert_GetAuthorityInfoAccess;
PKIX_PL_Cert_GetAuthorityKeyIdentifier;
@@ -1022,6 +1023,7 @@ PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy;
PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy;
PKIX_PL_CollectionCertStore_Create;
PKIX_PL_CRL_Create;
+pkix_pl_CRL_CreateToList;
PKIX_PL_CRL_GetCriticalExtensionOIDs;
PKIX_PL_CRL_GetCRLEntryForSerialNumber;
PKIX_PL_CRL_GetIssuer;