summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchrisk%netscape.com <devnull@localhost>2000-06-14 23:17:52 +0000
committerchrisk%netscape.com <devnull@localhost>2000-06-14 23:17:52 +0000
commit36acf85c8024965c9e67243bc069dbd70d088da4 (patch)
tree6cbe24744d9dc6bc5edb036660d1fb244e532bae
parent624d085e8ae9b1444edb9b8f506217907b559c91 (diff)
downloadnss-hg-36acf85c8024965c9e67243bc069dbd70d088da4.tar.gz
Add generation of SMIMECapabilities
-rw-r--r--security/nss/cmd/smimetools/cmsutil.c8
-rw-r--r--security/nss/lib/smime/cms.h10
-rw-r--r--security/nss/lib/smime/cmssiginfo.c42
-rw-r--r--security/nss/lib/smime/smime.h4
-rw-r--r--security/nss/lib/smime/smimemessage.c18
-rw-r--r--security/nss/lib/smime/smimeutil.c183
6 files changed, 110 insertions, 155 deletions
diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c
index ed070f2b6..4ccfad691 100644
--- a/security/nss/cmd/smimetools/cmsutil.c
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -418,13 +418,17 @@ sign(FILE *out, FILE *infile, char *progName, struct optionsStr options, struct
if (signOptions.signingTime) {
if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
+ fprintf(stderr, "ERROR: cannot add signingTime attribute.\n");
NSS_CMSMessage_Destroy(cmsg);
return SECFailure;
}
}
if (signOptions.smimeProfile) {
- /* TBD */
+ if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
+ NSS_CMSMessage_Destroy(cmsg);
+ return SECFailure;
+ }
}
if (signOptions.encryptionKeyPreferenceNick) {
/* TBD */
diff --git a/security/nss/lib/smime/cms.h b/security/nss/lib/smime/cms.h
index 091e96ea9..2793f682a 100644
--- a/security/nss/lib/smime/cms.h
+++ b/security/nss/lib/smime/cms.h
@@ -706,6 +706,16 @@ NSS_CMSSignerInfo_AddUnauthAttr(NSSCMSSignerInfo *signerinfo, NSSCMSAttribute *a
extern SECStatus
NSS_CMSSignerInfo_AddSigningTime(NSSCMSSignerInfo *signerinfo, PRTime t);
+/*
+ * NSS_CMSSignerInfo_AddSMIMECaps - add a SMIMECapabilities attribute to the
+ * authenticated (i.e. signed) attributes of "signerinfo".
+ *
+ * This is expected to be included in outgoing signed
+ * messages for email (S/MIME).
+ */
+extern SECStatus
+NSS_CMSSignerInfo_AddSMIMECaps(NSSCMSSignerInfo *signerinfo);
+
/*
* NSS_CMSSignerInfo_AddCounterSignature - countersign a signerinfo
*
diff --git a/security/nss/lib/smime/cmssiginfo.c b/security/nss/lib/smime/cmssiginfo.c
index 03be0ddea..56b23ceb1 100644
--- a/security/nss/lib/smime/cmssiginfo.c
+++ b/security/nss/lib/smime/cmssiginfo.c
@@ -651,6 +651,48 @@ loser:
}
/*
+ * NSS_CMSSignerInfo_AddSMIMECaps - add a SMIMECapabilities attribute to the
+ * authenticated (i.e. signed) attributes of "signerinfo".
+ *
+ * This is expected to be included in outgoing signed
+ * messages for email (S/MIME).
+ */
+SECStatus
+NSS_CMSSignerInfo_AddSMIMECaps(NSSCMSSignerInfo *signerinfo)
+{
+ NSSCMSAttribute *attr;
+ SECItem *smimecaps = NULL;
+ void *mark;
+ PLArenaPool *poolp;
+
+ poolp = signerinfo->cmsg->poolp;
+
+ mark = PORT_ArenaMark(poolp);
+
+ smimecaps = SECITEM_AllocItem(poolp, NULL, 0);
+ if (smimecaps == NULL)
+ goto loser;
+
+ /* create new signing time attribute */
+ if (NSS_SMIMEUtil_GetSMIMECapabilities(poolp, smimecaps,
+ PK11_FortezzaHasKEA(signerinfo->cert)) != SECSuccess)
+ goto loser;
+
+ if ((attr = NSS_CMSAttribute_Create(poolp, SEC_OID_PKCS9_SMIME_CAPABILITIES, smimecaps, PR_TRUE)) == NULL)
+ goto loser;
+
+ if (NSS_CMSSignerInfo_AddAuthAttr(signerinfo, attr) != SECSuccess)
+ goto loser;
+
+ PORT_ArenaUnmark (poolp, mark);
+ return SECSuccess;
+
+loser:
+ PORT_ArenaRelease (poolp, mark);
+ return SECFailure;
+}
+
+/*
* NSS_CMSSignerInfo_AddCounterSignature - countersign a signerinfo
*
* 1. digest the DER-encoded signature value of the original signerinfo
diff --git a/security/nss/lib/smime/smime.h b/security/nss/lib/smime/smime.h
index dd4cc6b76..eb381461c 100644
--- a/security/nss/lib/smime/smime.h
+++ b/security/nss/lib/smime/smime.h
@@ -122,10 +122,8 @@ extern PRBool NSS_SMIMEUtil_EncryptionPossible(void);
*
* scans the list of allowed and enabled ciphers and construct a PKCS9-compliant
* S/MIME capabilities attribute value.
- *
- * "cert" - sender's certificate
*/
-extern SECItem *NSS_SMIMEUtil_GetSMIMECapabilities(CERTCertificate *cert);
+extern SECStatus NSS_SMIMEUtil_GetSMIMECapabilities(PLArenaPool *poolp, SECItem *dest, PRBool includeFortezzaCiphers);
/*
* NSS_SMIMEUtil_FindBulkAlgForRecipients - find bulk algorithm suitable for all recipients
diff --git a/security/nss/lib/smime/smimemessage.c b/security/nss/lib/smime/smimemessage.c
index cd6d079d6..519f8b8d9 100644
--- a/security/nss/lib/smime/smimemessage.c
+++ b/security/nss/lib/smime/smimemessage.c
@@ -50,24 +50,6 @@
#include "secerr.h"
-SECStatus
-NSS_SMIMESignerInfo_AddSMIMEProfile(NSSCMSSignerInfo *signerinfo, CERTCertificate *cert)
-{
- SECItem *smimecapsdata;
- NSSCMSAttribute *smimecapsattr;
-
- if ((smimecapsdata = NSS_SMIMEUtil_GetSMIMECapabilities(cert)) == NULL)
- return SECFailure;
-
- smimecapsattr = NSS_CMSAttribute_Create(signerinfo->cmsg->poolp,
- SEC_OID_PKCS9_SMIME_CAPABILITIES,
- smimecapsdata, PR_TRUE);
- if (smimecapsattr == NULL)
- return SECFailure;
-
- return NSS_CMSSignerInfo_AddAuthAttr(signerinfo, smimecapsattr);
-}
-
#if 0
/*
* NSS_SMIMEMessage_CreateEncrypted - start an S/MIME encrypting context.
diff --git a/security/nss/lib/smime/smimeutil.c b/security/nss/lib/smime/smimeutil.c
index 849dc703c..6f81f6fad 100644
--- a/security/nss/lib/smime/smimeutil.c
+++ b/security/nss/lib/smime/smimeutil.c
@@ -104,12 +104,6 @@ static smime_cipher_map_entry smime_cipher_map[] = {
};
static const int smime_cipher_map_count = sizeof(smime_cipher_map) / sizeof(smime_cipher_map_entry);
-/* the other global variables */
-static PRBool smime_prefs_changed = PR_TRUE;
-static NSSSMIMECapability **smime_capabilities;
-static SECItem *smime_encoded_caps;
-static PRBool lastUsedFortezza;
-
/*
* smime_mapi_by_cipher - find index into smime_cipher_map by cipher
*/
@@ -152,10 +146,9 @@ NSS_SMIMEUtil_EnableCipher(unsigned long which, PRBool on)
return SECFailure;
}
- if (smime_cipher_map[mapi].enabled != on) {
+ if (smime_cipher_map[mapi].enabled != on)
smime_cipher_map[mapi].enabled = on;
- smime_prefs_changed = PR_TRUE;
- }
+
return SECSuccess;
}
@@ -181,10 +174,9 @@ NSS_SMIMEUtil_AllowCipher(unsigned long which, PRBool on)
/* XXX set an error */
return SECFailure;
- if (smime_cipher_map[mapi].allowed != on) {
+ if (smime_cipher_map[mapi].allowed != on)
smime_cipher_map[mapi].allowed = on;
- smime_prefs_changed = PR_TRUE;
- }
+
return SECSuccess;
}
@@ -521,155 +513,82 @@ NSS_SMIMEUtil_FindBulkAlgForRecipients(CERTCertificate **rcerts, SECOidTag *bulk
return SECSuccess;
}
-static SECStatus
-smime_init_caps(PRBool isFortezza)
+/*
+ * NSS_SMIMEUtil_GetSMIMECapabilities - get S/MIME capabilities for this instance of NSS
+ *
+ * scans the list of allowed and enabled ciphers and construct a PKCS9-compliant
+ * S/MIME capabilities attribute value.
+ *
+ * XXX Please note that, in contradiction to RFC2633 2.5.2, the capabilities only include
+ * symmetric ciphers, NO signature algorithms or key encipherment algorithms.
+ *
+ * "poolp" - arena pool to create the S/MIME capabilities data on
+ * "dest" - SECItem to put the data in
+ * "includeFortezzaCiphers" - PR_TRUE if fortezza ciphers should be included
+ */
+SECStatus
+NSS_SMIMEUtil_GetSMIMECapabilities(PLArenaPool *poolp, SECItem *dest, PRBool includeFortezzaCiphers)
{
NSSSMIMECapability *cap;
+ NSSSMIMECapability **smime_capabilities;
smime_cipher_map_entry *map;
SECOidData *oiddata;
- SECStatus rv;
+ SECItem *dummy;
int i, capIndex;
- /* if we have caps, and the prefs did not change, and we are using fortezza as last time */
- /* we're done */
- if (smime_encoded_caps != NULL && (!smime_prefs_changed) && lastUsedFortezza == isFortezza)
- return SECSuccess;
-
- /* ok, we need to cook up new caps. So throw the old ones away */
- if (smime_encoded_caps != NULL) {
- SECITEM_FreeItem (smime_encoded_caps, PR_TRUE);
- smime_encoded_caps = NULL;
- }
-
/* if we have an old NSSSMIMECapability array, we'll reuse it (has the right size) */
- if (smime_capabilities == NULL) {
- smime_capabilities = (NSSSMIMECapability **)PORT_ZAlloc((smime_cipher_map_count + 1)
- * sizeof(NSSSMIMECapability *));
- if (smime_capabilities == NULL)
- return SECFailure;
- }
+ /* smime_cipher_map_count + 1 is an upper bound - we might end up with less */
+ smime_capabilities = (NSSSMIMECapability **)PORT_ZAlloc((smime_cipher_map_count + 1)
+ * sizeof(NSSSMIMECapability *));
+ if (smime_capabilities == NULL)
+ return SECFailure;
- rv = SECFailure;
-
- /*
- The process of creating the encoded CMS cipher capability list
- involves two basic steps:
-
- (a) Convert our internal representation of cipher preferences
- (smime_prefs) into an array containing cipher OIDs and
- parameter data (smime_capabilities). This step is
- performed here.
-
- (b) Encode, using ASN.1, the cipher information in
- smime_capabilities, leaving the encoded result in
- smime_encoded_caps.
-
- (In the process of performing (a), Lisa put in some optimizations
- which allow us to avoid needlessly re-populating elements in
- smime_capabilities as we walk through smime_prefs.)
-
- We want to use separate loop variables for smime_prefs and
- smime_capabilities because in the case where the Skipjack cipher
- is turned on in the prefs, but where we don't want to include
- Skipjack in the encoded capabilities (presumably due to using a
- non-fortezza cert when sending a message), we want to avoid creating
- an empty element in smime_capabilities. This would otherwise cause
- the encoding step to produce an empty set, since Skipjack happens
- to be the first cipher in smime_prefs, if it is turned on.
- */
capIndex = 0;
- for (i = 0; i < smime_cipher_map_count; i++) {
+
+ /* Add all the symmetric ciphers
+ * We walk the cipher list backwards, as it is ordered by increasing strength,
+ * we prefer the stronger cipher over a weaker one, and we have to list the
+ * preferred algorithm first */
+ for (i = smime_cipher_map_count - 1; i >= 0; i--) {
/* Find the corresponding entry in the cipher map. */
map = &(smime_cipher_map[i]);
-
if (!map->enabled)
continue;
/* If we're using a non-Fortezza cert, only advertise non-Fortezza
capabilities. (We advertise all capabilities if we have a
Fortezza cert.) */
- if ((!isFortezza) && (map->cipher == SMIME_FORTEZZA))
+ if ((!includeFortezzaCiphers) && (map->cipher == SMIME_FORTEZZA))
continue;
/* get next SMIME capability */
- cap = smime_capabilities[capIndex];
- if (cap == NULL) {
- cap = (NSSSMIMECapability *)PORT_ZAlloc(sizeof(NSSSMIMECapability));
- if (cap == NULL)
- break;
- smime_capabilities[capIndex] = cap;
- }
- capIndex++;
-
- if (cap->cipher == smime_cipher_map[i].cipher)
- continue; /* no change to this one */
+ cap = (NSSSMIMECapability *)PORT_ZAlloc(sizeof(NSSSMIMECapability));
+ if (cap == NULL)
+ break;
+ smime_capabilities[capIndex++] = cap;
oiddata = SECOID_FindOIDByTag(map->algtag);
if (oiddata == NULL)
break;
- if (cap->capabilityID.data != NULL) {
- SECITEM_FreeItem (&(cap->capabilityID), PR_FALSE);
- cap->capabilityID.data = NULL;
- cap->capabilityID.len = 0;
- }
-
- rv = SECITEM_CopyItem(NULL, &(cap->capabilityID), &(oiddata->oid));
- if (rv != SECSuccess)
- break;
-
- if (map->parms == NULL) {
- cap->parameters.data = NULL;
- cap->parameters.len = 0;
- } else {
- cap->parameters.data = map->parms->data;
- cap->parameters.len = map->parms->len;
- }
-
+ cap->capabilityID.data = oiddata->oid.data;
+ cap->capabilityID.len = oiddata->oid.len;
+ cap->parameters.data = map->parms ? map->parms->data : NULL;
+ cap->parameters.len = map->parms ? map->parms->len : 0;
cap->cipher = smime_cipher_map[i].cipher;
}
- while (capIndex < smime_cipher_map_count) {
- cap = smime_capabilities[capIndex];
- if (cap != NULL) {
- SECITEM_FreeItem(&(cap->capabilityID), PR_FALSE);
- PORT_Free(cap);
- }
- smime_capabilities[capIndex] = NULL;
- capIndex++;
- }
- smime_capabilities[capIndex] = NULL; /* last one */
-
- smime_encoded_caps = SEC_ASN1EncodeItem (NULL, NULL, &smime_capabilities,
- smime_capabilities_template);
- if (smime_encoded_caps == NULL)
- return SECFailure;
-
- lastUsedFortezza = isFortezza;
-
- return SECSuccess;
-}
-
-/*
- * NSS_SMIMEUtil_GetSMIMECapabilities - get S/MIME capabilities for this instance of NSS
- *
- * scans the list of allowed and enabled ciphers and construct a PKCS9-compliant
- * S/MIME capabilities attribute value.
- *
- * "cert" - sender's certificate
- */
-SECItem *
-NSS_SMIMEUtil_GetSMIMECapabilities(CERTCertificate *cert)
-{
-
- PRBool isFortezza = PR_FALSE;
+ /* XXX add signature algorithms */
+ /* XXX add key encipherment algorithms */
- /* See if the sender's cert specifies Fortezza key exchange. */
- if (cert != NULL)
- isFortezza = PK11_FortezzaHasKEA(cert);
+ smime_capabilities[capIndex] = NULL; /* last one - now encode */
+ dummy = SEC_ASN1EncodeItem(poolp, dest, &smime_capabilities, smime_capabilities_template);
- if (smime_init_caps(isFortezza) != SECSuccess)
- return NULL;
+ /* now that we have the proper encoded SMIMECapabilities (or not),
+ * free the work data */
+ for (i = 0; smime_capabilities[i] != NULL; i++)
+ PORT_Free(smime_capabilities[i]);
+ PORT_Free(smime_capabilities);
- return smime_encoded_caps;
+ return (dummy == NULL) ? SECFailure : SECSuccess;
}