예제 #1
0
OSStatus
SecCmsSignedDataAddDigest(SecArenaPoolRef pool,
				SecCmsSignedDataRef sigd,
				SECOidTag digestalgtag,
				CSSM_DATA_PTR digest)
{
    PRArenaPool *poolp = (PRArenaPool *)pool;
    SECAlgorithmID *digestalg;
    void *mark;

    mark = PORT_ArenaMark(poolp);

    digestalg = PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
    if (digestalg == NULL)
	goto loser;

    if (SECOID_SetAlgorithmID (poolp, digestalg, digestalgtag, NULL) != SECSuccess) /* no params */
	goto loser;

    if (SecCmsArrayAdd(poolp, (void ***)&(sigd->digestAlgorithms), (void *)digestalg) != SECSuccess ||
	/* even if digest is NULL, add dummy to have same-size array */
	SecCmsArrayAdd(poolp, (void ***)&(sigd->digests), (void *)digest) != SECSuccess)
    {
	goto loser;
    }

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}
예제 #2
0
/*
 * SecCmsAttributeArraySetAttr - set an attribute's value in a set of attributes
 */
OSStatus
SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, CSSM_DATA_PTR value, Boolean encoded)
{
    SecCmsAttribute *attr;
    void *mark;

    mark = PORT_ArenaMark(poolp);

    /* see if we have one already */
    attr = SecCmsAttributeArrayFindAttrByOidTag(*attrs, type, PR_FALSE);
    if (attr == NULL) {
	/* not found? create one! */
	attr = SecCmsAttributeCreate(poolp, type, value, encoded);
	if (attr == NULL)
	    goto loser;
	/* and add it to the list */
	if (SecCmsArrayAdd(poolp, (void ***)attrs, (void *)attr) != SECSuccess)
	    goto loser;
    } else {
	/* found, shove it in */
	/* XXX we need a decent memory model @#$#$!#!!! */
	attr->values[0] = value;
	attr->encoded = encoded;
    }

    PORT_ArenaUnmark (poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease (poolp, mark);
    return SECFailure;
}
예제 #3
0
/*
 * SecCmsAttributeArrayAddAttr - add an attribute to an
 * array of attributes. 
 */
OSStatus
SecCmsAttributeArrayAddAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SecCmsAttribute *attr)
{
    SecCmsAttribute *oattr;
    void *mark;
    SECOidTag type;

    mark = PORT_ArenaMark(poolp);

    /* find oidtag of attr */
    type = SecCmsAttributeGetType(attr);

    /* see if we have one already */
    oattr = SecCmsAttributeArrayFindAttrByOidTag(*attrs, type, PR_FALSE);
    PORT_Assert (oattr == NULL);
    if (oattr != NULL)
	goto loser;	/* XXX or would it be better to replace it? */

    /* no, shove it in */
    if (SecCmsArrayAdd(poolp, (void ***)attrs, (void *)attr) != SECSuccess)
	goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}
예제 #4
0
/*
 * SecCmsAttributeAddValue - add another value to an attribute
 */
OSStatus
SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, CSSM_DATA_PTR value)
{
    CSSM_DATA copiedvalue;
    void *mark;

    PORT_Assert (poolp != NULL);

    mark = PORT_ArenaMark(poolp);

    /* XXX we need an object memory model #$%#$%! */
    if (SECITEM_CopyItem(poolp, &copiedvalue, value) != SECSuccess)
	goto loser;

    if (SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)&copiedvalue) != SECSuccess)
	goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_Assert (mark != NULL);
    PORT_ArenaRelease (poolp, mark);
    return SECFailure;
}
예제 #5
0
/*
 * SecCmsAttributeCreate - create an attribute
 *
 * if value is NULL, the attribute won't have a value. It can be added later
 * with SecCmsAttributeAddValue.
 */
SecCmsAttribute *
SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, Boolean encoded)
{
    SecCmsAttribute *attr;
    CSSM_DATA_PTR copiedvalue;
    void *mark;

    PORT_Assert (poolp != NULL);

    mark = PORT_ArenaMark (poolp);

    attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute));
    if (attr == NULL)
	goto loser;

    attr->typeTag = SECOID_FindOIDByTag(oidtag);
    if (attr->typeTag == NULL)
	goto loser;

    if (SECITEM_CopyItem(poolp, &(attr->type), &(attr->typeTag->oid)) != SECSuccess)
	goto loser;

    if (value != NULL) {
	if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, (unsigned int)value->Length)) == NULL)
	    goto loser;

	if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess)
	    goto loser;

	SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue);
    }

    attr->encoded = encoded;

    PORT_ArenaUnmark (poolp, mark);

    return attr;

loser:
    PORT_Assert (mark != NULL);
    PORT_ArenaRelease (poolp, mark);
    return NULL;
}
예제 #6
0
OSStatus
SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd,
				SecCmsSignerInfoRef signerinfo)
{
    void *mark;
    OSStatus rv;
    SECOidTag digestalgtag;
    PLArenaPool *poolp;

    poolp = sigd->cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    /* add signerinfo */
    rv = SecCmsArrayAdd(poolp, (void ***)&(sigd->signerInfos), (void *)signerinfo);
    if (rv != SECSuccess)
	goto loser;

    signerinfo->sigd = sigd;
    
    /*
     * add empty digest
     * Empty because we don't have it yet. Either it gets created during encoding
     * (if the data is present) or has to be set externally.
     * XXX maybe pass it in optionally?
     */
    digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo);
    rv = SecCmsSignedDataSetDigestValue(sigd, digestalgtag, NULL);
    if (rv != SECSuccess)
	goto loser;

    /*
     * The last thing to get consistency would be adding the digest.
     */

    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease (poolp, mark);
    return SECFailure;
}
예제 #7
0
/*
 * SecCmsEnvelopedDataAddRecipient - add a recipientinfo to the enveloped data msg
 *
 * rip must be created on the same pool as edp - this is not enforced, though.
 */
OSStatus
SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedData *edp, SecCmsRecipientInfo *rip)
{
    void *mark;
    OSStatus rv;

    /* XXX compare pools, if not same, copy rip into edp's pool */

    PR_ASSERT(edp != NULL);
    PR_ASSERT(rip != NULL);

    mark = PORT_ArenaMark(edp->cmsg->poolp);

    rv = SecCmsArrayAdd(edp->cmsg->poolp, (void ***)&(edp->recipientInfos), (void *)rip);
    if (rv != SECSuccess) {
	PORT_ArenaRelease(edp->cmsg->poolp, mark);
	return SECFailure;
    }

    PORT_ArenaUnmark (edp->cmsg->poolp, mark);
    return SECSuccess;
}
예제 #8
0
static SecCmsRecipientInfoRef
nss_cmsrecipientinfo_create(SecCmsEnvelopedDataRef envd, SecCmsRecipientIDSelector type,
                            SecCertificateRef cert, SecPublicKeyRef pubKey, 
                            const SecAsn1Item *subjKeyID)
{
    SecCmsRecipientInfoRef ri;
    void *mark;
    SECOidTag certalgtag;
    OSStatus rv = SECSuccess;
    SecCmsRecipientEncryptedKey *rek;
    SecCmsOriginatorIdentifierOrKey *oiok;
    unsigned long version;
    SecAsn1Item * dummy;
    PLArenaPool *poolp;
    const SECAlgorithmID *algid;
    SECAlgorithmID freeAlgID;
    
    SecCmsRecipientIdentifier *rid;

    poolp = envd->contentInfo.cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    ri = (SecCmsRecipientInfoRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientInfo));
    if (ri == NULL)
	goto loser;

    ri->envelopedData = envd;

#if USE_CDSA_CRYPTO
    if (type == SecCmsRecipientIDIssuerSN)
    {
	rv = SecCertificateGetAlgorithmID(cert,&algid);
    } else {
	PORT_Assert(pubKey);
	rv = SecKeyGetAlgorithmID(pubKey,&algid);
    }
#else
    ri->cert = CERT_DupCertificate(cert);
    if (ri->cert == NULL)
        goto loser;

    const SecAsn1AlgId *length_data_swapped = (const SecAsn1AlgId *)SecCertificateGetPublicKeyAlgorithm(cert);
    freeAlgID.algorithm.Length = (size_t)length_data_swapped->algorithm.Data;
    freeAlgID.algorithm.Data = (uint8_t *)length_data_swapped->algorithm.Length;
    freeAlgID.parameters.Length = (size_t)length_data_swapped->parameters.Data;
    freeAlgID.parameters.Data = (uint8_t *)length_data_swapped->parameters.Length;
    algid = &freeAlgID;
#endif

    certalgtag = SECOID_GetAlgorithmTag(algid);

    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	ri->recipientInfoType = SecCmsRecipientInfoIDKeyTrans;
	rid->identifierType = type;
	if (type == SecCmsRecipientIDIssuerSN) {
	    rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
	    if (rid->id.issuerAndSN == NULL) {
	      break;
	    }
	} else if (type == SecCmsRecipientIDSubjectKeyID){

	    rid->id.subjectKeyID = PORT_ArenaNew(poolp, SecAsn1Item);
	    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;
	    }

#if 0
            SecCmsKeyTransRecipientInfoEx *riExtra;
	    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;
	    }
#endif
	} else {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    rv = SECFailure;
	}
	break;
    case SEC_OID_MISSI_KEA_DSS_OLD:
    case SEC_OID_MISSI_KEA_DSS:
    case SEC_OID_MISSI_KEA:
        PORT_Assert(type != SecCmsRecipientIDSubjectKeyID);
	if (type == SecCmsRecipientIDSubjectKeyID) {
	    rv = SECFailure;
	    break;
	}
	/* backward compatibility - this is not really a keytrans operation */
	ri->recipientInfoType = SecCmsRecipientInfoIDKeyTrans;
	/* hardcoded issuerSN choice for now */
	ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType = SecCmsRecipientIDIssuerSN;
	ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);
	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {
	    rv = SECFailure;
	    break;
	}
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
        PORT_Assert(type != SecCmsRecipientIDSubjectKeyID);
	if (type == SecCmsRecipientIDSubjectKeyID) {
	    rv = SECFailure;
	    break;
	}
	/* a key agreement op */
	ri->recipientInfoType = SecCmsRecipientInfoIDKeyAgree;

	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 = SecCmsRecipientEncryptedKeyCreate(poolp)) == NULL) {
	    rv = SECFailure;
	    break;
	}

	/* hardcoded IssuerSN choice for now */
	rek->recipientIdentifier.identifierType = SecCmsKeyAgreeRecipientIDIssuerSN;
	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 = SecCmsOriginatorIDOrKeyOriginatorPublicKey;

	rv = SecCmsArrayAdd(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 SecCmsRecipientInfoIDKeyTrans:
	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == SecCmsRecipientIDIssuerSN)
	    version = SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN;
	else
	    version = SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY;
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version);
	if (dummy == NULL)
	    goto loser;
	break;
    case SecCmsRecipientInfoIDKeyAgree:
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version),
						SEC_CMS_KEYAGREE_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    case SecCmsRecipientInfoIDKEK:
	/* NOTE: this cannot happen as long as we do not support any KEK algorithm */
	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version),
						SEC_CMS_KEK_RECIPIENT_INFO_VERSION);
	if (dummy == NULL)
	    goto loser;
	break;
    
    }

    if (SecCmsEnvelopedDataAddRecipient(envd, ri))
	goto loser;

    PORT_ArenaUnmark (poolp, mark);
#if 0
    if (freeSpki)
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
#endif
    return ri;

loser:
#if 0
    if (freeSpki)
      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
#endif
    PORT_ArenaRelease (poolp, mark);
    return NULL;
}