Ejemplo n.º 1
0
/*
 * SecCmsEnvelopedDataCreate - create an enveloped data message
 */
SecCmsEnvelopedData *
SecCmsEnvelopedDataCreate(SecCmsMessage *cmsg, SECOidTag algorithm, int keysize)
{
    void *mark;
    SecCmsEnvelopedData *envd;
    PLArenaPool *poolp;
    OSStatus rv;

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    envd = (SecCmsEnvelopedData *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsEnvelopedData));
    if (envd == NULL)
	goto loser;

    envd->cmsg = cmsg;

    /* version is set in SecCmsEnvelopedDataEncodeBeforeStart() */

    rv = SecCmsContentInfoSetContentEncAlg(poolp, &(envd->contentInfo), algorithm, NULL, keysize);
    if (rv != SECSuccess)
	goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return envd;

loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}
Ejemplo n.º 2
0
/*
 * SecCmsEncryptedDataCreate - create an empty encryptedData object.
 *
 * "algorithm" specifies the bulk encryption algorithm to use.
 * "keysize" is the key size.
 * 
 * An error results in a return value of NULL and an error set.
 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
 */
SecCmsEncryptedDataRef
SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize)
{
    void *mark;
    SecCmsEncryptedDataRef encd;
    PLArenaPool *poolp;
#if 0
    SECAlgorithmID *pbe_algid;
#endif
    OSStatus rv;

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    encd = (SecCmsEncryptedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsEncryptedData));
    if (encd == NULL)
	goto loser;

    encd->cmsg = cmsg;

    /* version is set in SecCmsEncryptedDataEncodeBeforeStart() */

    switch (algorithm) {
    /* XXX hmmm... hardcoded algorithms? */
    case SEC_OID_RC2_CBC:
    case SEC_OID_DES_EDE3_CBC:
    case SEC_OID_DES_CBC:
	rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, &(encd->contentInfo), algorithm, NULL, keysize);
	break;
    default:
	/* Assume password-based-encryption.  At least, try that. */
#if 1
	// @@@ Fix me
        rv = SECFailure;
        break;
#else
	pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL);

	if (pbe_algid == NULL) {
	    rv = SECFailure;
	    break;
	}
	rv = SecCmsContentInfoSetContentEncAlgID((SecArenaPoolRef)poolp, &(encd->contentInfo), pbe_algid, keysize);
	SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE);
	break;
#endif
    }
    if (rv != SECSuccess)
	goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return encd;

loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}
Ejemplo n.º 3
0
/*
 * SecCmsEnvelopedDataEncodeBeforeStart - prepare this envelopedData for encoding
 *
 * at this point, we need
 * - recipientinfos set up with recipient's certificates
 * - a content encryption algorithm (if none, 3DES will be used)
 *
 * this function will generate a random content encryption key (aka bulk key),
 * initialize the recipientinfos with certificate identification and wrap the bulk key
 * using the proper algorithm for every certificiate.
 * it will finally set the bulk algorithm and key so that the encode step can find it.
 */
OSStatus
SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedData *envd)
{
    int version;
    SecCmsRecipientInfo **recipientinfos;
    SecCmsContentInfo *cinfo;
    SecSymmetricKeyRef bulkkey = NULL;
    CSSM_ALGORITHMS algorithm;
    SECOidTag bulkalgtag;
    //CK_MECHANISM_TYPE type;
    //PK11SlotInfo *slot;
    OSStatus rv;
    CSSM_DATA *dummy;
    PLArenaPool *poolp;
    extern const SEC_ASN1Template SecCmsRecipientInfoTemplate[];
    void *mark = NULL;
    int i;

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

    recipientinfos = envd->recipientInfos;
    if (recipientinfos == NULL) {
	PORT_SetError(SEC_ERROR_BAD_DATA);
#if 0
	PORT_SetErrorString("Cannot find recipientinfos to encode.");
#endif
	goto loser;
    }

    version = SEC_CMS_ENVELOPED_DATA_VERSION_REG;
    if (envd->originatorInfo != NULL || envd->unprotectedAttr != NULL) {
	version = SEC_CMS_ENVELOPED_DATA_VERSION_ADV;
    } else {
	for (i = 0; recipientinfos[i] != NULL; i++) {
	    if (SecCmsRecipientInfoGetVersion(recipientinfos[i]) != 0) {
		version = SEC_CMS_ENVELOPED_DATA_VERSION_ADV;
		break;
	    }
	}
    }
    dummy = SEC_ASN1EncodeInteger(poolp, &(envd->version), version);
    if (dummy == NULL)
	goto loser;

    /* now we need to have a proper content encryption algorithm
     * on the SMIME level, we would figure one out by looking at SMIME capabilities
     * we cannot do that on our level, so if none is set already, we'll just go
     * with one of the mandatory algorithms (3DES) */
    if ((bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) {
	rv = SecCmsContentInfoSetContentEncAlg(poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168);
	if (rv != SECSuccess)
	    goto loser;
	bulkalgtag = SEC_OID_DES_EDE3_CBC;
    }

    algorithm = SECOID_FindyCssmAlgorithmByTag(bulkalgtag);
    if (!algorithm)
	goto loser;
    rv = SecKeyGenerate(NULL,	/* keychainRef */
		algorithm,
		SecCmsContentInfoGetBulkKeySize(cinfo),
		0,		/* contextHandle */
		CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
		CSSM_KEYATTR_EXTRACTABLE,
		NULL,		/* initialAccess */
		&bulkkey);
    if (rv)
	goto loser;

    mark = PORT_ArenaMark(poolp);

    /* Encrypt the bulk key with the public key of each recipient.  */
    for (i = 0; recipientinfos[i] != NULL; i++) {
	rv = SecCmsRecipientInfoWrapBulkKey(recipientinfos[i], bulkkey, bulkalgtag);
	if (rv != SECSuccess)
	    goto loser;	/* error has been set by SecCmsRecipientInfoEncryptBulkKey */
	    		/* could be: alg not supported etc. */
    }

    /* the recipientinfos are all finished. now sort them by DER for SET OF encoding */
    rv = SecCmsArraySortByDER((void **)envd->recipientInfos, SecCmsRecipientInfoTemplate, NULL);
    if (rv != SECSuccess)
	goto loser;	/* error has been set by SecCmsArraySortByDER */

    /* store the bulk key in the contentInfo so that the encoder can find it */
    SecCmsContentInfoSetBulkKey(cinfo, bulkkey);

    PORT_ArenaUnmark(poolp, mark);

    CFRelease(bulkkey);

    return SECSuccess;

loser:
    if (mark != NULL)
	PORT_ArenaRelease (poolp, mark);
    if (bulkkey)
	CFRelease(bulkkey);

    return SECFailure;
}