Esempio n. 1
0
/*
 * NSS_CMSEnvelopedData_Create - create an enveloped data message
 */
NSSCMSEnvelopedData *
NSS_CMSEnvelopedData_Create(NSSCMSMessage *cmsg, SECOidTag algorithm, int keysize)
{
    void *mark;
    NSSCMSEnvelopedData *envd;
    PLArenaPool *poolp;
    SECStatus rv;

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

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

    envd->cmsg = cmsg;

    /* version is set in NSS_CMSEnvelopedData_Encode_BeforeStart() */

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

    PORT_ArenaUnmark(poolp, mark);
    return envd;

loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}
Esempio n. 2
0
/*
 * NSS_CMSEncryptedData_Create - 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().)
 */
NSSCMSEncryptedData *
NSS_CMSEncryptedData_Create(NSSCMSMessage *cmsg, SECOidTag algorithm,
                            int keysize)
{
    void *mark;
    NSSCMSEncryptedData *encd;
    PLArenaPool *poolp;
    SECAlgorithmID *pbe_algid;
    SECStatus rv;

    poolp = cmsg->poolp;

    mark = PORT_ArenaMark(poolp);

    encd = PORT_ArenaZNew(poolp, NSSCMSEncryptedData);
    if (encd == NULL)
        goto loser;

    encd->cmsg = cmsg;

    /* version is set in NSS_CMSEncryptedData_Encode_BeforeStart() */

    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm)) {
        rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, &(encd->contentInfo),
                                                 algorithm, NULL, keysize);
    } else {
        /* Assume password-based-encryption.
         * Note: we can't generate pkcs5v2 from this interface.
         * PK11_CreateBPEAlgorithmID generates pkcs5v2 by accepting
         * non-PBE oids and assuming that they are pkcs5v2 oids, but
         * NSS_CMSEncryptedData_Create accepts non-PBE oids as regular
         * CMS encrypted data, so we can't tell NSS_CMS_EncryptedData_Create
         * to create pkcs5v2 PBEs */
        pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL);
        if (pbe_algid == NULL) {
            rv = SECFailure;
        } else {
            rv = NSS_CMSContentInfo_SetContentEncAlgID(poolp,
                                                       &(encd->contentInfo),
                                                       pbe_algid, keysize);
            SECOID_DestroyAlgorithmID(pbe_algid, PR_TRUE);
        }
    }
    if (rv != SECSuccess)
        goto loser;

    PORT_ArenaUnmark(poolp, mark);
    return encd;

loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}
Esempio n. 3
0
/*
 * NSS_CMSEnvelopedData_Encode_BeforeStart - 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.
 */
SECStatus
NSS_CMSEnvelopedData_Encode_BeforeStart(NSSCMSEnvelopedData *envd)
{
    int version;
    NSSCMSRecipientInfo **recipientinfos;
    NSSCMSContentInfo *cinfo;
    PK11SymKey *bulkkey = NULL;
    SECOidTag bulkalgtag;
    CK_MECHANISM_TYPE type;
    PK11SlotInfo *slot;
    SECStatus rv;
    SECItem *dummy;
    PLArenaPool *poolp;
    extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[];
    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 = NSS_CMS_ENVELOPED_DATA_VERSION_REG;
    if (envd->originatorInfo != NULL || envd->unprotectedAttr != NULL) {
	version = NSS_CMS_ENVELOPED_DATA_VERSION_ADV;
    } else {
	for (i = 0; recipientinfos[i] != NULL; i++) {
	    if (NSS_CMSRecipientInfo_GetVersion(recipientinfos[i]) != 0) {
		version = NSS_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 = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) {
	rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168);
	if (rv != SECSuccess)
	    goto loser;
	bulkalgtag = SEC_OID_DES_EDE3_CBC;
    } 

    /* generate a random bulk key suitable for content encryption alg */
    type = PK11_AlgtagToMechanism(bulkalgtag);
    slot = PK11_GetBestSlot(type, envd->cmsg->pwfn_arg);
    if (slot == NULL)
	goto loser;	/* error has been set by PK11_GetBestSlot */

    /* this is expensive... */
    bulkkey = PK11_KeyGen(slot, type, NULL, NSS_CMSContentInfo_GetBulkKeySize(cinfo) / 8, envd->cmsg->pwfn_arg);
    PK11_FreeSlot(slot);
    if (bulkkey == NULL)
	goto loser;	/* error has been set by PK11_KeyGen */

    mark = PORT_ArenaMark(poolp);

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

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

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

    PORT_ArenaUnmark(poolp, mark);

    PK11_FreeSymKey(bulkkey);

    return SECSuccess;

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

    return SECFailure;
}