Esempio n. 1
0
/*
 * NSS_CMSSignedData_VerifyCertsOnly - verify the certs in a certs-only message
 */
SECStatus
NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd,
                                  CERTCertDBHandle *certdb,
                                  SECCertUsage usage)
{
    CERTCertificate *cert;
    SECStatus rv = SECSuccess;
    int i;
    int count;
    PRTime now;

    if (!sigd || !certdb || !sigd->rawCerts) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    count = NSS_CMSArray_Count((void**)sigd->rawCerts);
    now = PR_Now();
    for (i=0; i < count; i++) {
        if (sigd->certs && sigd->certs[i]) {
            cert = CERT_DupCertificate(sigd->certs[i]);
        } else {
            cert = CERT_FindCertByDERCert(certdb, sigd->rawCerts[i]);
            if (!cert) {
                rv = SECFailure;
                break;
            }
        }
        rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, now,
                              NULL, NULL);
        CERT_DestroyCertificate(cert);
    }

    return rv;
}
Esempio n. 2
0
SECStatus
NSS_CMSSignedData_SetDigestValue(NSSCMSSignedData *sigd,
                                 SECOidTag digestalgtag,
                                 SECItem *digestdata)
{
    SECItem *digest = NULL;
    PLArenaPool *poolp;
    void *mark;
    int n, cnt;

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

    poolp = sigd->cmsg->poolp;

    mark = PORT_ArenaMark(poolp);


    if (digestdata) {
        digest = (SECItem *) PORT_ArenaZAlloc(poolp,sizeof(SECItem));

        /* copy digestdata item to arena (in case we have it and are not only making room) */
        if (SECITEM_CopyItem(poolp, digest, digestdata) != SECSuccess)
            goto loser;
    }

    /* now allocate one (same size as digestAlgorithms) */
    if (sigd->digests == NULL) {
        cnt = NSS_CMSArray_Count((void **)sigd->digestAlgorithms);
        sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(SECItem *));
        if (sigd->digests == NULL) {
            PORT_SetError(SEC_ERROR_NO_MEMORY);
            return SECFailure;
        }
    }

    n = -1;
    if (sigd->digestAlgorithms != NULL)
        n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag);

    /* if not found, add a digest */
    if (n < 0) {
        if (NSS_CMSSignedData_AddDigest(poolp, sigd, digestalgtag, digest) != SECSuccess)
            goto loser;
    } else {
        /* replace NULL pointer with digest item (and leak previous value) */
        sigd->digests[n] = digest;
    }

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}
Esempio n. 3
0
int
NSS_CMSSignedData_SignerInfoCount(NSSCMSSignedData *sigd)
{
    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return 0;
    }
    return NSS_CMSArray_Count((void **)sigd->signerInfos);
}
Esempio n. 4
0
/*
 * NSS_CMSSignedData_SetDigests - set a signedData's digests member
 *
 * "digestalgs" - array of digest algorithm IDs
 * "digests"    - array of digests corresponding to the digest algorithms
 */
SECStatus
NSS_CMSSignedData_SetDigests(NSSCMSSignedData *sigd,
                             SECAlgorithmID **digestalgs,
                             SECItem **digests)
{
    int cnt, i, idx;

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

    if (sigd->digestAlgorithms == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* we assume that the digests array is just not there yet */
    PORT_Assert(sigd->digests == NULL);
    if (sigd->digests != NULL) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return SECFailure;
    }

    /* now allocate one (same size as digestAlgorithms) */
    cnt = NSS_CMSArray_Count((void **)sigd->digestAlgorithms);
    sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(SECItem *));
    if (sigd->digests == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return SECFailure;
    }

    for (i = 0; sigd->digestAlgorithms[i] != NULL; i++) {
        /* try to find the sigd's i'th digest algorithm in the array we passed in */
        idx = NSS_CMSAlgArray_GetIndexByAlgID(digestalgs, sigd->digestAlgorithms[i]);
        if (idx < 0) {
            PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND);
            return SECFailure;
        }
        if (!digests[idx]) {
            /* We have no digest for this algorithm, probably because it is
            ** unrecognized or unsupported.  We'll ignore this here.  If this
            ** digest is needed later, an error will be be generated then.
            */
            continue;
        }

        /* found it - now set it */
        if ((sigd->digests[i] = SECITEM_AllocItem(sigd->cmsg->poolp, NULL, 0)) == NULL ||
                SECITEM_CopyItem(sigd->cmsg->poolp, sigd->digests[i], digests[idx]) != SECSuccess)
        {
            PORT_SetError(SEC_ERROR_NO_MEMORY);
            return SECFailure;
        }
    }
    return SECSuccess;
}
Esempio n. 5
0
/*
 * NSS_CMSArray_Sort - sort an array in place
 *
 * If "secondary" or "tertiary are not NULL, it must be arrays with the same
 *  number of elements as "primary". The same reordering will get applied to it.
 *
 * "compare" is a function that returns 
 *  < 0 when the first element is less than the second
 *  = 0 when the first element is equal to the second
 *  > 0 when the first element is greater than the second
 * to acheive ascending ordering.
 */
void
NSS_CMSArray_Sort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary)
{
    int n, i, limit, lastxchg;
    void *tmp;

    n = NSS_CMSArray_Count(primary);

    PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n);
    PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n);
    
    if (n <= 1)	/* ordering is fine */
	return;
    
    /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */
    limit = n - 1;
    while (1) {
	lastxchg = 0;
	for (i = 0; i < limit; i++) {
	    if ((*compare)(primary[i], primary[i+1]) > 0) {
		/* exchange the neighbours */
		tmp = primary[i+1];
		primary[i+1] = primary[i];
		primary[i] = tmp;
		if (secondary) {		/* secondary array? */
		    tmp = secondary[i+1];	/* exchange there as well */
		    secondary[i+1] = secondary[i];
		    secondary[i] = tmp;
		}
		if (tertiary) {			/* tertiary array? */
		    tmp = tertiary[i+1];	/* exchange there as well */
		    tertiary[i+1] = tertiary[i];
		    tertiary[i] = tmp;
		}
		lastxchg = i+1;	/* index of the last element bubbled up */
	    }
	}
	if (lastxchg == 0)	/* no exchanges, so array is sorted */
	    break;		/* we're done */
	limit = lastxchg;	/* array is sorted up to [limit] */
    }
}
Esempio n. 6
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;
}
Esempio n. 7
0
SECStatus
NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb,
                              SECCertUsage certusage, PRBool keepcerts)
{
    int certcount;
    CERTCertificate **certArray = NULL;
    CERTCertList *certList = NULL;
    CERTCertListNode *node;
    SECStatus rv;
    SECItem **rawArray;
    int i;
    PRTime now;

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

    certcount = NSS_CMSArray_Count((void **)sigd->rawCerts);

    /* get the certs in the temp DB */
    rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts,
                          &certArray, PR_FALSE, PR_FALSE, NULL);
    if (rv != SECSuccess) {
        goto loser;
    }

    /* save the certs so they don't get destroyed */
    for (i = 0; i < certcount; i++) {
        CERTCertificate *cert = certArray[i];
        if (cert)
            NSS_CMSSignedData_AddTempCertificate(sigd, cert);
    }

    if (!keepcerts) {
        goto done;
    }

    /* build a CertList for filtering */
    certList = CERT_NewCertList();
    if (certList == NULL) {
        rv = SECFailure;
        goto loser;
    }
    for (i = 0; i < certcount; i++) {
        CERTCertificate *cert = certArray[i];
        if (cert)
            cert = CERT_DupCertificate(cert);
        if (cert)
            CERT_AddCertToListTail(certList, cert);
    }

    /* filter out the certs we don't want */
    rv = CERT_FilterCertListByUsage(certList, certusage, PR_FALSE);
    if (rv != SECSuccess) {
        goto loser;
    }

    /* go down the remaining list of certs and verify that they have
     * valid chains, then import them.
     */
    now = PR_Now();
    for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
         node = CERT_LIST_NEXT(node)) {
        CERTCertificateList *certChain;

        if (CERT_VerifyCert(certdb, node->cert,
                            PR_TRUE, certusage, now, NULL, NULL) != SECSuccess) {
            continue;
        }

        certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
        if (!certChain) {
            continue;
        }

        /*
         * CertChain returns an array of SECItems, import expects an array of
         * SECItem pointers. Create the SECItem Pointers from the array of
         * SECItems.
         */
        rawArray = (SECItem **)PORT_Alloc(certChain->len * sizeof(SECItem *));
        if (!rawArray) {
            CERT_DestroyCertificateList(certChain);
            continue;
        }
        for (i = 0; i < certChain->len; i++) {
            rawArray[i] = &certChain->certs[i];
        }
        (void)CERT_ImportCerts(certdb, certusage, certChain->len,
                               rawArray, NULL, keepcerts, PR_FALSE, NULL);
        PORT_Free(rawArray);
        CERT_DestroyCertificateList(certChain);
    }

    rv = SECSuccess;

/* XXX CRL handling */

done:
    if (sigd->signerInfos != NULL) {
        /* fill in all signerinfo's certs */
        for (i = 0; sigd->signerInfos[i] != NULL; i++)
            (void)NSS_CMSSignerInfo_GetSigningCertificate(
                sigd->signerInfos[i], certdb);
    }

loser:
    /* now free everything */
    if (certArray) {
        CERT_DestroyCertArray(certArray, certcount);
    }
    if (certList) {
        CERT_DestroyCertList(certList);
    }

    return rv;
}
Esempio n. 8
0
/*
 * NSS_CMSEnvelopedData_Decode_BeforeData - find our recipientinfo, 
 * derive bulk key & set up our contentinfo
 */
SECStatus
NSS_CMSEnvelopedData_Decode_BeforeData(NSSCMSEnvelopedData *envd)
{
    NSSCMSRecipientInfo *ri;
    PK11SymKey *bulkkey = NULL;
    SECOidTag bulkalgtag;
    SECAlgorithmID *bulkalg;
    SECStatus rv = SECFailure;
    NSSCMSContentInfo *cinfo;
    NSSCMSRecipient **recipient_list = NULL;
    NSSCMSRecipient *recipient;
    int rlIndex;

    if (NSS_CMSArray_Count((void **)envd->recipientInfos) == 0) {
	PORT_SetError(SEC_ERROR_BAD_DATA);
#if 0
	PORT_SetErrorString("No recipient data in envelope.");
#endif
	goto loser;
    }

    /* look if one of OUR cert's issuerSN is on the list of recipients, and if so,  */
    /* get the cert and private key for it right away */
    recipient_list = nss_cms_recipient_list_create(envd->recipientInfos);
    if (recipient_list == NULL)
	goto loser;

    /* what about multiple recipientInfos that match?
     * especially if, for some reason, we could not produce a bulk key with the first match?!
     * we could loop & feed partial recipient_list to PK11_FindCertAndKeyByRecipientList...
     * maybe later... */
    rlIndex = PK11_FindCertAndKeyByRecipientListNew(recipient_list, envd->cmsg->pwfn_arg);

    /* if that fails, then we're not an intended recipient and cannot decrypt */
    if (rlIndex < 0) {
	PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT);
#if 0
	PORT_SetErrorString("Cannot decrypt data because proper key cannot be found.");
#endif
	goto loser;
    }

    recipient = recipient_list[rlIndex];
    if (!recipient->cert || !recipient->privkey) {
	/* XXX should set an error code ?!? */
	goto loser;
    }
    /* get a pointer to "our" recipientinfo */
    ri = envd->recipientInfos[recipient->riIndex];

    cinfo = &(envd->contentInfo);
    bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo);
    if (bulkalgtag == SEC_OID_UNKNOWN) {
	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    } else 
	bulkkey = 
	    NSS_CMSRecipientInfo_UnwrapBulkKey(ri,recipient->subIndex,
						    recipient->cert,
						    recipient->privkey,
						    bulkalgtag);
    if (bulkkey == NULL) {
	/* no success finding a bulk key */
	goto loser;
    }

    NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);

    bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo);

    rv = NSS_CMSContentInfo_Private_Init(cinfo);
    if (rv != SECSuccess) {
	goto loser;
    }
    rv = SECFailure;
    cinfo->privateInfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
    if (cinfo->privateInfo->ciphcx == NULL)
	goto loser;		/* error has been set by NSS_CMSCipherContext_StartDecrypt */


    rv = SECSuccess;

loser:
    if (bulkkey)
	PK11_FreeSymKey(bulkkey);
    if (recipient_list != NULL)
	nss_cms_recipient_list_destroy(recipient_list);
    return rv;
}