summaryrefslogtreecommitdiffstats
path: root/nss/lib/smime/cmsrecinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/smime/cmsrecinfo.c')
-rw-r--r--nss/lib/smime/cmsrecinfo.c138
1 files changed, 94 insertions, 44 deletions
diff --git a/nss/lib/smime/cmsrecinfo.c b/nss/lib/smime/cmsrecinfo.c
index 6cf2c68..ab3b80e 100644
--- a/nss/lib/smime/cmsrecinfo.c
+++ b/nss/lib/smime/cmsrecinfo.c
@@ -15,6 +15,7 @@
#include "secoid.h"
#include "pk11func.h"
#include "secerr.h"
+#include "smime.h"
PRBool
nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri)
@@ -157,7 +158,7 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg,
rv = SECFailure;
}
break;
- case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
PORT_Assert(type == NSSCMSRecipientID_IssuerSN);
if (type != NSSCMSRecipientID_IssuerSN) {
rv = SECFailure;
@@ -166,10 +167,6 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg,
/* a key agreement op */
ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;
- 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
@@ -274,7 +271,7 @@ NSS_CMSRecipient_IsSupported(CERTCertificate *cert)
switch (certalgtag) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
- case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
return PR_TRUE;
default:
return PR_FALSE;
@@ -456,6 +453,7 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
PLArenaPool *poolp;
NSSCMSKeyTransRecipientInfoEx *extra = NULL;
PRBool usesSubjKeyID;
+ void *wincx = NULL;
poolp = ri->cmsg->poolp;
cert = ri->cert;
@@ -480,6 +478,11 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
/* or should we look if it's been set already ? */
certalgtag = SECOID_GetAlgorithmTag(&spki->algorithm);
+ if (!NSS_SMIMEUtil_KeyEncodingAllowed(&spki->algorithm, cert, extra ? extra->pubKey : NULL)) {
+ PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
+ rv = SECFailure;
+ goto loser;
+ }
switch (certalgtag) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
/* wrap the symkey */
@@ -498,7 +501,7 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);
break;
- case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];
if (rek == NULL) {
rv = SECFailure;
@@ -510,7 +513,7 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
/* see RFC2630 12.3.1.1 */
if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,
- SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {
+ certalgtag, NULL) != SECSuccess) {
rv = SECFailure;
break;
}
@@ -518,12 +521,27 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
/* 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);
+ switch (certalgtag) {
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
+ if (ri->cmsg) {
+ wincx = ri->cmsg->pwfn_arg;
+ } else {
+ wincx = PK11_GetWindow(bulkkey);
+ }
+ rv = NSS_CMSUtil_EncryptSymKey_ESECDH(poolp, cert, bulkkey,
+ &rek->encKey,
+ PR_TRUE,
+ &ri->ri.keyAgreeRecipientInfo.ukm,
+ &ri->ri.keyAgreeRecipientInfo.keyEncAlg,
+ &oiok->id.originatorPublicKey.publicKey,
+ wincx);
+ break;
+ default:
+ /* Not reached. Added to silence enum warnings. */
+ PORT_Assert(0);
+ break;
+ }
break;
default:
/* other algorithms not supported yet */
@@ -531,6 +549,7 @@ NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey,
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
rv = SECFailure;
}
+loser:
if (freeSpki)
SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
@@ -542,57 +561,88 @@ NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo *ri, int subIndex,
CERTCertificate *cert, SECKEYPrivateKey *privkey, SECOidTag bulkalgtag)
{
PK11SymKey *bulkkey = NULL;
+ SECAlgorithmID *algid;
SECOidTag encalgtag;
- SECItem *enckey;
+ SECItem *enckey = NULL, *ukm = NULL, *parameters = NULL;
+ NSSCMSOriginatorIdentifierOrKey *oiok = NULL;
int error;
+ void *wincx = NULL;
ri->cert = CERT_DupCertificate(cert);
/* mark the recipientInfo so we can find it later */
switch (ri->recipientInfoType) {
case NSSCMSRecipientInfoID_KeyTrans:
- encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg));
+ algid = &(ri->ri.keyTransRecipientInfo.keyEncAlg);
+ parameters = &(ri->ri.keyTransRecipientInfo.keyEncAlg.parameters);
enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */
- switch (encalgtag) {
- case SEC_OID_PKCS1_RSA_ENCRYPTION:
- /* RSA encryption algorithm: */
- /* get the symmetric (bulk) key by unwrapping it using our private key */
- bulkkey = NSS_CMSUtil_DecryptSymKey_RSA(privkey, enckey, bulkalgtag);
- break;
- default:
- error = SEC_ERROR_UNSUPPORTED_KEYALG;
- goto loser;
- }
break;
case NSSCMSRecipientInfoID_KeyAgree:
- encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg));
+ algid = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg);
+ parameters = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg.parameters);
enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey);
- switch (encalgtag) {
- case SEC_OID_X942_DIFFIE_HELMAN_KEY:
- /* Diffie-Helman key exchange */
- /* XXX not yet implemented */
- /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */
- /* we support ephemeral-static DH only, so if the recipientinfo */
- /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */
- /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */
- /* content encryption key using a Unwrap op */
- /* the derive operation has to generate the key using the algorithm in RFC2631 */
- error = SEC_ERROR_UNSUPPORTED_KEYALG;
- goto loser;
- break;
- default:
- error = SEC_ERROR_UNSUPPORTED_KEYALG;
- goto loser;
- }
+ oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);
+ ukm = &(ri->ri.keyAgreeRecipientInfo.ukm);
break;
case NSSCMSRecipientInfoID_KEK:
- encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg));
+ algid = &(ri->ri.kekRecipientInfo.keyEncAlg);
+ parameters = &(ri->ri.kekRecipientInfo.keyEncAlg.parameters);
enckey = &(ri->ri.kekRecipientInfo.encKey);
/* not supported yet */
+ default:
error = SEC_ERROR_UNSUPPORTED_KEYALG;
goto loser;
break;
}
+ if (!NSS_SMIMEUtil_KeyDecodingAllowed(algid, privkey)) {
+ error = SEC_ERROR_BAD_EXPORT_ALGORITHM;
+ goto loser;
+ }
+ encalgtag = SECOID_GetAlgorithmTag(algid);
+ switch (encalgtag) {
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ /* RSA encryption algorithm: */
+ if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) {
+ error = SEC_ERROR_UNSUPPORTED_KEYALG;
+ goto loser;
+ }
+ /* get the symmetric (bulk) key by unwrapping it using our private key */
+ bulkkey = NSS_CMSUtil_DecryptSymKey_RSA(privkey, enckey, bulkalgtag);
+ break;
+ case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
+ /* RSA OAEP encryption algorithm: */
+ if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyTrans) {
+ error = SEC_ERROR_UNSUPPORTED_KEYALG;
+ goto loser;
+ }
+ /* get the symmetric (bulk) key by unwrapping it using our private key */
+ bulkkey = NSS_CMSUtil_DecryptSymKey_RSA_OAEP(privkey, parameters, enckey,
+ bulkalgtag);
+ break;
+ case SEC_OID_DHSINGLEPASS_STDDH_SHA1KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_STDDH_SHA224KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_STDDH_SHA256KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_STDDH_SHA384KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_STDDH_SHA512KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA1KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA224KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA256KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA384KDF_SCHEME:
+ case SEC_OID_DHSINGLEPASS_COFACTORDH_SHA512KDF_SCHEME:
+ if (ri->recipientInfoType != NSSCMSRecipientInfoID_KeyAgree) {
+ error = SEC_ERROR_UNSUPPORTED_KEYALG;
+ goto loser;
+ }
+ if (ri->cmsg) {
+ wincx = ri->cmsg->pwfn_arg;
+ }
+ bulkkey = NSS_CMSUtil_DecryptSymKey_ECDH(privkey, enckey, algid,
+ bulkalgtag, ukm, oiok, wincx);
+ break;
+ default:
+ error = SEC_ERROR_UNSUPPORTED_KEYALG;
+ goto loser;
+ }
/* XXXX continue here */
return bulkkey;