Beispiel #1
0
void
SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri)
{
    /* version was allocated on the pool, so no need to destroy it */
    /* issuerAndSN was allocated on the pool, so no need to destroy it */
    if (ri->cert != NULL)
	CERT_DestroyCertificate(ri->cert);

    if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) {
	SecCmsKeyTransRecipientInfoEx *extra;
	extra = &ri->ri.keyTransRecipientInfoEx;
	if (extra->pubKey)
	    SECKEY_DestroyPublicKey(extra->pubKey);
    }

    /* recipientInfo structure itself was allocated on the pool, so no need to destroy it */
    /* we're done. */
}
Beispiel #2
0
void
NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo *ri)
{
    if (!ri) {
        return;
    }
    /* version was allocated on the pool, so no need to destroy it */
    /* issuerAndSN was allocated on the pool, so no need to destroy it */
    if (ri->cert != NULL)
	CERT_DestroyCertificate(ri->cert);

    if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) {
	NSSCMSKeyTransRecipientInfoEx *extra;
	extra = &ri->ri.keyTransRecipientInfoEx;
	if (extra->pubKey)
	    SECKEY_DestroyPublicKey(extra->pubKey);
    }
    if (ri->cmsg && ri->cmsg->contentInfo.contentTypeTag == &fakeContent) {
	NSS_CMSMessage_Destroy(ri->cmsg);
    }

    /* we're done. */
}
Beispiel #3
0
SECStatus
NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, 
                                 SECOidTag bulkalgtag)
{
    CERTCertificate *cert;
    SECOidTag certalgtag;
    SECStatus rv = SECSuccess;
    NSSCMSRecipientEncryptedKey *rek;
    NSSCMSOriginatorIdentifierOrKey *oiok;
    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;
    PLArenaPool *poolp;
    NSSCMSKeyTransRecipientInfoEx *extra = NULL;
    PRBool usesSubjKeyID;

    poolp = ri->cmsg->poolp;
    cert = ri->cert;
    usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
    if (cert) {
	spki = &cert->subjectPublicKeyInfo;
    } else if (usesSubjKeyID) {
	extra = &ri->ri.keyTransRecipientInfoEx;
	/* sanity check */
	PORT_Assert(extra->pubKey);
	if (!extra->pubKey) {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    return SECFailure;
	}
	spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(extra->pubKey);
    } else {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* XXX set ri->recipientInfoType to the proper value here */
    /* or should we look if it's been set already ? */

    certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	/* wrap the symkey */
	if (cert) {
	    rv = NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, 
	                         &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	} else if (usesSubjKeyID) {
	    PORT_Assert(extra != NULL);
	    rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, extra->pubKey,
	                         bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	}

	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
	rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
	if (rek == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
	PORT_Assert(oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey);

	/* see RFC2630 12.3.1.1 */
	if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
				    SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {
	    rv = SECFailure;
	    break;
	}

	/* this will generate a key pair, compute the shared secret, */
	/* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
	/* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
	rv = NSS_CMSUtil_EncryptSymKey_ESDH(poolp, cert, bulkkey,
					&rek->encKey,
					&ri->ri.keyAgreeRecipientInfo.ukm,
					&ri->ri.keyAgreeRecipientInfo.keyEncAlg,
					&oiok->id.originatorPublicKey.publicKey);

	break;
    default:
	/* other algorithms not supported yet */
	/* NOTE that we do not support any KEK algorithm */
	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
	rv = SECFailure;
    }
    if (freeSpki)
	SECKEY_DestroySubjectPublicKeyInfo(freeSpki);

    return rv;
}
Beispiel #4
0
OSStatus
SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bulkkey, 
                                 SECOidTag bulkalgtag)
{
    SecCertificateRef cert;
    SECOidTag certalgtag;
    OSStatus rv = SECSuccess;
#if 0
    SecAsn1Item * params = NULL;
    SecCmsRecipientEncryptedKey *rek;
    SecCmsOriginatorIdentifierOrKey *oiok;
#endif /* 0 */
    const SECAlgorithmID *algid;
    PLArenaPool *poolp;
    SecCmsKeyTransRecipientInfoEx *extra = NULL;
    Boolean usesSubjKeyID;

    poolp = ri->envelopedData->contentInfo.cmsg->poolp;
    cert = ri->cert;
    usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
    if (cert) {
#if USE_CDSA_CRYPTO
	rv = SecCertificateGetAlgorithmID(cert,&algid);
	if (rv)
	    return SECFailure;
#else
        SECAlgorithmID freeAlgID;
        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
    } else if (usesSubjKeyID) {
	extra = &ri->ri.keyTransRecipientInfoEx;
	/* sanity check */
	PORT_Assert(extra->pubKey);
	if (!extra->pubKey) {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    return SECFailure;
	}
#if USE_CDSA_CRYPTO
	rv = SecKeyGetAlgorithmID(extra->pubKey,&algid);
	if (rv)
#endif
	    return SECFailure;
	certalgtag = SECOID_GetAlgorithmTag(algid);
    } else {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* XXX set ri->recipientInfoType to the proper value here */
    /* or should we look if it's been set already ? */

    certalgtag = SECOID_GetAlgorithmTag(algid);
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	/* wrap the symkey */
	if (cert) {
	    rv = SecCmsUtilEncryptSymKeyRSA(poolp, cert, bulkkey, 
	                         &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	} else if (usesSubjKeyID) {
	    PORT_Assert(extra != NULL);
	    rv = SecCmsUtilEncryptSymKeyRSAPubKey(poolp, extra->pubKey,
	                         bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	}

	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
	break;
#if 0
    case SEC_OID_MISSI_KEA_DSS_OLD:
    case SEC_OID_MISSI_KEA_DSS:
    case SEC_OID_MISSI_KEA:
	rv = SecCmsUtilEncryptSymKeyMISSI(poolp, cert, bulkkey,
					bulkalgtag,
					&ri->ri.keyTransRecipientInfo.encKey,
					&params, ri->cmsg->pwfn_arg);
	if (rv != SECSuccess)
	    break;

	/* here, we DO need to pass the params to the wrap function because, with
	 * RSA, there is no funny stuff going on with generation of IV vectors or so */
	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, params);
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
	rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
	if (rek == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
	PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey);

	/* see RFC2630 12.3.1.1 */
	if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
				    SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {
	    rv = SECFailure;
	    break;
	}

	/* this will generate a key pair, compute the shared secret, */
	/* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
	/* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
	rv = SecCmsUtilEncryptSymKeyESDH(poolp, cert, bulkkey,
					&rek->encKey,
					&ri->ri.keyAgreeRecipientInfo.ukm,
					&ri->ri.keyAgreeRecipientInfo.keyEncAlg,
					&oiok->id.originatorPublicKey.publicKey);

	break;
#endif /* 0 */
    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 0
    if (freeSpki)
	SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
#endif

    return rv;
}
OSStatus
SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bulkkey, 
                                 SECOidTag bulkalgtag)
{
    SecCertificateRef cert;
    SECOidTag certalgtag;
    OSStatus rv = SECSuccess;
#if 0
    CSSM_DATA_PTR params = NULL;
#endif /* 0 */
    SecCmsRecipientEncryptedKey *rek;
    SecCmsOriginatorIdentifierOrKey *oiok;
    const SECAlgorithmID *algid;
    PLArenaPool *poolp;
    SecCmsKeyTransRecipientInfoEx *extra = NULL;
    Boolean usesSubjKeyID;
    uint8 nullData[2] = {SEC_ASN1_NULL, 0};
    SECItem nullItem;
    SecCmsKeyAgreeRecipientInfo *kari;
    
    poolp = ri->cmsg->poolp;
    cert = ri->cert;
    usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri);
    if (cert) {
	rv = SecCertificateGetAlgorithmID(cert,&algid);
	if (rv)
	    return SECFailure;
	certalgtag = SECOID_GetAlgorithmTag(algid);
    } else if (usesSubjKeyID) {
	extra = &ri->ri.keyTransRecipientInfoEx;
	/* sanity check */
	PORT_Assert(extra->pubKey);
	if (!extra->pubKey) {
	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
	    return SECFailure;
	}
	rv = SecKeyGetAlgorithmID(extra->pubKey,&algid);
	if (rv)
	    return SECFailure;
	certalgtag = SECOID_GetAlgorithmTag(algid);
    } else {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* XXX set ri->recipientInfoType to the proper value here */
    /* or should we look if it's been set already ? */

    certalgtag = SECOID_GetAlgorithmTag(algid);
    switch (certalgtag) {
    case SEC_OID_PKCS1_RSA_ENCRYPTION:
	/* wrap the symkey */
	if (cert) {
	    rv = SecCmsUtilEncryptSymKeyRSA(poolp, cert, bulkkey, 
	                         &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	} else if (usesSubjKeyID) {
	    PORT_Assert(extra != NULL);
	    rv = SecCmsUtilEncryptSymKeyRSAPubKey(poolp, extra->pubKey,
	                         bulkkey, &ri->ri.keyTransRecipientInfo.encKey);
 	    if (rv != SECSuccess)
		break;
	}

	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
	break;
#if 0
    case SEC_OID_MISSI_KEA_DSS_OLD:
    case SEC_OID_MISSI_KEA_DSS:
    case SEC_OID_MISSI_KEA:
	rv = SecCmsUtilEncryptSymKeyMISSI(poolp, cert, bulkkey,
					bulkalgtag,
					&ri->ri.keyTransRecipientInfo.encKey,
					&params, ri->cmsg->pwfn_arg);
	if (rv != SECSuccess)
	    break;

	/* here, we DO need to pass the params to the wrap function because, with
	 * RSA, there is no funny stuff going on with generation of IV vectors or so */
	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, params);
	break;
    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
	rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
	if (rek == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
	PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey);

	/* see RFC2630 12.3.1.1 */
	if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
				    SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {
	    rv = SECFailure;
	    break;
	}

	/* this will generate a key pair, compute the shared secret, */
	/* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
	/* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
	rv = SecCmsUtilEncryptSymKeyESDH(poolp, cert, bulkkey,
					&rek->encKey,
					&ri->ri.keyAgreeRecipientInfo.ukm,
					&ri->ri.keyAgreeRecipientInfo.keyEncAlg,
					&oiok->id.originatorPublicKey.publicKey);

	break;
#endif /* 0 */

    case SEC_OID_EC_PUBLIC_KEY:
	/* These were set up in nss_cmsrecipientinfo_create() */
	kari = &ri->ri.keyAgreeRecipientInfo;
	rek = kari->recipientEncryptedKeys[0];
	if (rek == NULL) {
	    rv = SECFailure;
	    break;
	}

	oiok = &(kari->originatorIdentifierOrKey);
	PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey);

	/* 
	 * RFC 3278 3.1.1 says this AlgId must contain NULL params which is contrary to 
	 * any other use of the SEC_OID_EC_PUBLIC_KEY OID. So we provide one
	 * explicitly instead of mucking up the login in SECOID_SetAlgorithmID().
	 */
	nullItem.Data = nullData;
	nullItem.Length = 2;
	if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
				    SEC_OID_EC_PUBLIC_KEY, &nullItem) != SECSuccess) {
	    rv = SECFailure;
	    break;
	}

	/* this will generate a key pair, compute the shared secret, */
	/* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
	/* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
	rv = SecCmsUtilEncryptSymKeyECDH(poolp, cert, bulkkey,
					&rek->encKey,
					&kari->ukm,
					&kari->keyEncAlg,
					&oiok->id.originatorPublicKey.publicKey);
	/* this is a BIT STRING */
	oiok->id.originatorPublicKey.publicKey.Length <<= 3;
	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 0
    if (freeSpki)
	SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
#endif

    return rv;
}