]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_smime/lib/smimeutil.c
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / smimeutil.c
index 989d27d5622c55f9c38ec1da08a2044a61d02660..569c7f65b7b1a5bb5f6b929619017583756b064f 100644 (file)
@@ -117,8 +117,8 @@ static const SecAsn1Template smime_encryptionkeypref_template[] = {
          NSSSMIMEEncryptionKeyPref_IssuerSN },
     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1,
          offsetof(NSSSMIMEEncryptionKeyPreference,id.recipientKeyID),
-         SecCmsRecipientKeyIdentifierTemplate,
-         NSSSMIMEEncryptionKeyPref_IssuerSN },
+         SEC_ASN1_SUB(SecCmsRecipientKeyIdentifierTemplate),
+         NSSSMIMEEncryptionKeyPref_RKeyID },
     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
          offsetof(NSSSMIMEEncryptionKeyPreference,id.subjectKeyID),
          SEC_ASN1_SUB(kSecAsn1OctetStringTemplate),
@@ -139,13 +139,13 @@ typedef struct {
 static smime_cipher_map_entry smime_cipher_map[] = {
 /*    cipher                   algtag                  parms           enabled  allowed */
 /*    ---------------------------------------------------------------------------------- */
-    { SMIME_RC2_CBC_40,                SEC_OID_RC2_CBC,        &param_int40,   PR_TRUE, PR_TRUE },
-    { SMIME_DES_CBC_56,                SEC_OID_DES_CBC,        NULL,           PR_TRUE, PR_TRUE },
-    { SMIME_RC2_CBC_64,                SEC_OID_RC2_CBC,        &param_int64,   PR_TRUE, PR_TRUE },
+    { SMIME_RC2_CBC_40,                SEC_OID_RC2_CBC,        &param_int40,   PR_FALSE,PR_TRUE },
+    { SMIME_DES_CBC_56,                SEC_OID_DES_CBC,        NULL,           PR_FALSE,PR_TRUE },
+    { SMIME_RC2_CBC_64,                SEC_OID_RC2_CBC,        &param_int64,   PR_FALSE,PR_TRUE },
     { SMIME_RC2_CBC_128,       SEC_OID_RC2_CBC,        &param_int128,  PR_TRUE, PR_TRUE },
     { SMIME_DES_EDE3_168,      SEC_OID_DES_EDE3_CBC,   NULL,           PR_TRUE, PR_TRUE },
     { SMIME_AES_CBC_128,        SEC_OID_AES_128_CBC,    NULL,           PR_TRUE, PR_TRUE },
-    { SMIME_FORTEZZA,          SEC_OID_FORTEZZA_SKIPJACK, NULL,        PR_TRUE, PR_TRUE }
+    { SMIME_FORTEZZA,          SEC_OID_FORTEZZA_SKIPJACK, NULL,        PR_FALSE, PR_TRUE }
 };
 static const int smime_cipher_map_count = sizeof(smime_cipher_map) / sizeof(smime_cipher_map_entry);
 
@@ -191,8 +191,7 @@ SecSMIMEEnableCipher(uint32 which, Boolean on)
        return SECFailure;
     }
 
-    if (smime_cipher_map[mapi].enabled != on)
-       smime_cipher_map[mapi].enabled = on;
+    smime_cipher_map[mapi].enabled = on;
 
     return SECSuccess;
 }
@@ -219,8 +218,7 @@ SecSMIMEAllowCipher(uint32 which, Boolean on)
        /* XXX set an error */
        return SECFailure;
 
-    if (smime_cipher_map[mapi].allowed != on)
-       smime_cipher_map[mapi].allowed = on;
+    smime_cipher_map[mapi].allowed = on;
 
     return SECSuccess;
 }
@@ -379,10 +377,9 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts)
 {
     PRArenaPool *poolp;
     long cipher;
-    long chosen_cipher;
+    long chosen_cipher = SMIME_DES_EDE3_168;
     int *cipher_abilities;
     int *cipher_votes;
-    int weak_mapi;
     int strong_mapi;
     int rcount, mapi, max, i;
 #if 1
@@ -392,9 +389,6 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts)
     Boolean scert_is_fortezza = (scert == NULL) ? PR_FALSE : PK11_FortezzaHasKEA(scert);
 #endif
 
-    chosen_cipher = SMIME_RC2_CBC_40;          /* the default, LCD */
-    weak_mapi = smime_mapi_by_cipher(chosen_cipher);
-
     poolp = PORT_NewArena (1024);              /* XXX what is right value? */
     if (poolp == NULL)
        goto done;
@@ -447,39 +441,10 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts)
                }
            }
        } else {
-           /* no profile found - so we can only assume that the user can do
-            * the mandatory algorithms which is RC2-40 (weak crypto) and 3DES (strong crypto) */
-           SecPublicKeyRef key;
-           unsigned int pklen_bits;
-
-           /*
-            * if recipient's public key length is > 512, vote for a strong cipher
-            * please not that the side effect of this is that if only one recipient
-            * has an export-level public key, the strong cipher is disabled.
-            *
-            * XXX This is probably only good for RSA keys.  What I would
-            * really like is a function to just say;  Is the public key in
-            * this cert an export-length key?  Then I would not have to
-            * know things like the value 512, or the kind of key, or what
-            * a subjectPublicKeyInfo is, etc.
-            */
-           key = CERT_ExtractPublicKey(rcerts[rcount]);
-           pklen_bits = 0;
-           if (key != NULL) {
-               SecKeyGetStrengthInBits(key, NULL, &pklen_bits);
-               SECKEY_DestroyPublicKey (key);
-           }
-
-           if (pklen_bits > 512) {
-               /* cast votes for the strong algorithm */
-               cipher_abilities[strong_mapi]++;
-               cipher_votes[strong_mapi] += pref;
-               pref--;
-           } 
-
-           /* always cast (possibly less) votes for the weak algorithm */
-           cipher_abilities[weak_mapi]++;
-           cipher_votes[weak_mapi] += pref;
+            /* cast votes for the strong algorithm */
+            cipher_abilities[strong_mapi]++;
+            cipher_votes[strong_mapi] += pref;
+            pref--;
        }
        if (profile != NULL)
            SECITEM_FreeItem(profile, PR_TRUE);
@@ -574,6 +539,9 @@ SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgta
 
     cipher = smime_choose_cipher(NULL, rcerts);
     mapi = smime_mapi_by_cipher(cipher);
+    if (mapi < 0) {
+        return SECFailure;
+    }
 
     *bulkalgtag = smime_cipher_map[mapi].algtag;
     *keysize = smime_keysize_by_cipher(smime_cipher_map[mapi].cipher);
@@ -745,7 +713,7 @@ loser:
  * they are assumed to have been imported already.
  */
 SecCertificateRef
-SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp)
+SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR *rawCerts, CSSM_DATA_PTR DERekp)
 {
     PLArenaPool *tmppoolp = NULL;
     SecCertificateRef cert = NULL;
@@ -762,11 +730,13 @@ SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_
     /* find cert */
     switch (ekp.selector) {
     case NSSSMIMEEncryptionKeyPref_IssuerSN:
-       cert = CERT_FindCertByIssuerAndSN(keychainOrArray, NULL, NULL, ekp.id.issuerAndSN);
+       cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, NULL, tmppoolp, ekp.id.issuerAndSN);
        break;
     case NSSSMIMEEncryptionKeyPref_RKeyID:
+        cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, NULL, &ekp.id.recipientKeyID->subjectKeyIdentifier);
+        break;
     case NSSSMIMEEncryptionKeyPref_SubjectKeyID:
-       /* XXX not supported yet - we need to be able to look up certs by SubjectKeyID */
+        cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, NULL, ekp.id.subjectKeyID);
        break;
     default:
        PORT_Assert(0);