Ejemplo n.º 1
0
/*
 * NSS_CMSArray_SortByDER - sort array of objects by objects' DER encoding
 *
 * make sure that the order of the objects guarantees valid DER (which must be
 * in lexigraphically ascending order for a SET OF); if reordering is necessary it
 * will be done in place (in objs).
 */
SECStatus
NSS_CMSArray_SortByDER(void **objs, const SEC_ASN1Template *objtemplate, void **objs2)
{
    PRArenaPool *poolp;
    int num_objs;
    SECItem **enc_objs;
    SECStatus rv = SECFailure;
    int i;

    if (objs == NULL)					/* already sorted */
	return SECSuccess;

    num_objs = NSS_CMSArray_Count((void **)objs);
    if (num_objs == 0 || num_objs == 1)		/* already sorted. */
	return SECSuccess;

    poolp = PORT_NewArena (1024);	/* arena for temporaries */
    if (poolp == NULL)
	return SECFailure;		/* no memory; nothing we can do... */

    /*
     * Allocate arrays to hold the individual encodings which we will use
     * for comparisons and the reordered attributes as they are sorted.
     */
    enc_objs = (SECItem **)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(SECItem *));
    if (enc_objs == NULL)
	goto loser;

    /* DER encode each individual object. */
    for (i = 0; i < num_objs; i++) {
	enc_objs[i] = SEC_ASN1EncodeItem(poolp, NULL, objs[i], objtemplate);
	if (enc_objs[i] == NULL)
	    goto loser;
    }
    enc_objs[num_objs] = NULL;

    /* now compare and sort objs by the order of enc_objs */
    NSS_CMSArray_Sort((void **)enc_objs, NSS_CMSUtil_DERCompare, objs, objs2);

    rv = SECSuccess;

loser:
    PORT_FreeArena (poolp, PR_FALSE);
    return rv;
}
Ejemplo n.º 2
0
/*
 * NSS_CMSSignedData_Encode_AfterData - do all the necessary things to a SignedData
 *     after all the encapsulated data was passed through the encoder.
 *
 * In detail:
 *  - create the signatures in all the SignerInfos
 *
 * Please note that nothing is done to the Certificates and CRLs in the message - this
 * is entirely the responsibility of our callers.
 */
SECStatus
NSS_CMSSignedData_Encode_AfterData(NSSCMSSignedData *sigd)
{
    NSSCMSSignerInfo **signerinfos, *signerinfo;
    NSSCMSContentInfo *cinfo;
    SECOidTag digestalgtag;
    SECStatus ret = SECFailure;
    SECStatus rv;
    SECItem *contentType;
    int certcount;
    int i, ci, cli, n, rci, si;
    PLArenaPool *poolp;
    CERTCertificateList *certlist;
    extern const SEC_ASN1Template NSSCMSSignerInfoTemplate[];

    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    poolp = sigd->cmsg->poolp;
    cinfo = &(sigd->contentInfo);

    /* did we have digest calculation going on? */
    if (cinfo->privateInfo && cinfo->privateInfo->digcx) {
        rv = NSS_CMSDigestContext_FinishMultiple(cinfo->privateInfo->digcx, poolp,
                                                 &(sigd->digests));
        /* error has been set by NSS_CMSDigestContext_FinishMultiple */
        cinfo->privateInfo->digcx = NULL;
        if (rv != SECSuccess)
            goto loser;
    }

    signerinfos = sigd->signerInfos;
    certcount = 0;

    /* prepare all the SignerInfos (there may be none) */
    for (i = 0; i < NSS_CMSSignedData_SignerInfoCount(sigd); i++) {
        signerinfo = NSS_CMSSignedData_GetSignerInfo(sigd, i);

        /* find correct digest for this signerinfo */
        digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo);
        n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag);
        if (n < 0 || sigd->digests == NULL || sigd->digests[n] == NULL) {
            /* oops - digest not found */
            PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND);
            goto loser;
        }

        /* XXX if our content is anything else but data, we need to force the
         * presence of signed attributes (RFC2630 5.3 "signedAttributes is a
         * collection...") */

        /* pass contentType here as we want a contentType attribute */
        if ((contentType = NSS_CMSContentInfo_GetContentTypeOID(cinfo)) == NULL)
            goto loser;

        /* sign the thing */
        rv = NSS_CMSSignerInfo_Sign(signerinfo, sigd->digests[n], contentType);
        if (rv != SECSuccess)
            goto loser;

        /* while we're at it, count number of certs in certLists */
        certlist = NSS_CMSSignerInfo_GetCertList(signerinfo);
        if (certlist)
            certcount += certlist->len;
    }

    /* this is a SET OF, so we need to sort them guys */
    rv = NSS_CMSArray_SortByDER((void **)signerinfos, NSSCMSSignerInfoTemplate, NULL);
    if (rv != SECSuccess)
        goto loser;

    /*
     * now prepare certs & crls
     */

    /* count the rest of the certs */
    if (sigd->certs != NULL) {
        for (ci = 0; sigd->certs[ci] != NULL; ci++)
            certcount++;
    }

    if (sigd->certLists != NULL) {
        for (cli = 0; sigd->certLists[cli] != NULL; cli++)
            certcount += sigd->certLists[cli]->len;
    }

    if (certcount == 0) {
        sigd->rawCerts = NULL;
    } else {
        /*
         * Combine all of the certs and cert chains into rawcerts.
         * Note: certcount is an upper bound; we may not need that many slots
         * but we will allocate anyway to avoid having to do another pass.
         * (The temporary space saving is not worth it.)
         *
         * XXX ARGH - this NEEDS to be fixed. need to come up with a decent
         *  SetOfDERcertficates implementation
         */
        sigd->rawCerts = (SECItem **)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(SECItem *));
        if (sigd->rawCerts == NULL)
            return SECFailure;

        /*
         * XXX Want to check for duplicates and not add *any* cert that is
         * already in the set.  This will be more important when we start
         * dealing with larger sets of certs, dual-key certs (signing and
         * encryption), etc.  For the time being we can slide by...
         *
         * XXX ARGH - this NEEDS to be fixed. need to come up with a decent
         *  SetOfDERcertficates implementation
         */
        rci = 0;
        if (signerinfos != NULL) {
            for (si = 0; signerinfos[si] != NULL; si++) {
                signerinfo = signerinfos[si];
                for (ci = 0; ci < signerinfo->certList->len; ci++)
                    sigd->rawCerts[rci++] = &(signerinfo->certList->certs[ci]);
            }
        }

        if (sigd->certs != NULL) {
            for (ci = 0; sigd->certs[ci] != NULL; ci++)
                sigd->rawCerts[rci++] = &(sigd->certs[ci]->derCert);
        }

        if (sigd->certLists != NULL) {
            for (cli = 0; sigd->certLists[cli] != NULL; cli++) {
                for (ci = 0; ci < sigd->certLists[cli]->len; ci++)
                    sigd->rawCerts[rci++] = &(sigd->certLists[cli]->certs[ci]);
            }
        }

        sigd->rawCerts[rci] = NULL;

        /* this is a SET OF, so we need to sort them guys - we have the DER already, though */
        NSS_CMSArray_Sort((void **)sigd->rawCerts, NSS_CMSUtil_DERCompare, NULL, NULL);
    }

    ret = SECSuccess;

loser:
    return ret;
}