diff options
author | chrisk%netscape.com <devnull@localhost> | 2000-06-14 23:17:52 +0000 |
---|---|---|
committer | chrisk%netscape.com <devnull@localhost> | 2000-06-14 23:17:52 +0000 |
commit | 36acf85c8024965c9e67243bc069dbd70d088da4 (patch) | |
tree | 6cbe24744d9dc6bc5edb036660d1fb244e532bae | |
parent | 624d085e8ae9b1444edb9b8f506217907b559c91 (diff) | |
download | nss-hg-36acf85c8024965c9e67243bc069dbd70d088da4.tar.gz |
Add generation of SMIMECapabilities
-rw-r--r-- | security/nss/cmd/smimetools/cmsutil.c | 8 | ||||
-rw-r--r-- | security/nss/lib/smime/cms.h | 10 | ||||
-rw-r--r-- | security/nss/lib/smime/cmssiginfo.c | 42 | ||||
-rw-r--r-- | security/nss/lib/smime/smime.h | 4 | ||||
-rw-r--r-- | security/nss/lib/smime/smimemessage.c | 18 | ||||
-rw-r--r-- | security/nss/lib/smime/smimeutil.c | 183 |
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; } |