[389-commits] ldap/servers

Noriko Hosoi nhosoi at fedoraproject.org
Thu Jan 27 20:42:12 UTC 2011


 ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c |  141 +++++++++++++++++++++-----
 ldap/servers/slapd/proto-slap.h               |    3 
 ldap/servers/slapd/security_wrappers.c        |   36 +++++-
 3 files changed, 151 insertions(+), 29 deletions(-)

New commits:
commit 57dcdf1d260ebad6ce419baa5e32e33e2ba9e815
Author: Noriko Hosoi <nhosoi at jiji.usersys.redhat.com>
Date:   Thu Jan 27 11:53:39 2011 -0800

    Bug 624547 - attrcrypt should query the given slot/token for
    supported ciphers
    
    https://bugzilla.redhat.com/show_bug.cgi?id=624547
    
    Description:
    1. To retrieve a certificate from an external token (i.e., not
       "internal (software)"), "<token>:<cert_nickname> should have
       been passed.  The <token> part was missing.
    2. The key to be used for encryption and decryption internally
       needs to have ENCRYPT and DECRYPT attribute set, respectively.
       The correct attributes were not set.  Note: these attributes
       are automatically set for the softoken in nss, but not for the
       external token.  This is why attrcrypt worked for the softoken,
       but not for the external token.  The attributes need to be set
       when the key is generated as well as when the key is unwrapped.
    3. Adding a code to check if the underlying system supports the
       cipher or not before generating a key.  If it is not supported,
       it issues a message not to choose the cipher for the attrcrypt/
       changelog encryption.  If none of the ciphers are supported and
       if attrcrypt/changelog encryption is enabled, the server fails
       to start.

diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c b/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c
index 88d78fc..2b94107 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c
@@ -55,9 +55,12 @@
 
 #define ATTRCRYPT "attrcrypt"
 
-attrcrypt_cipher_entry attrcrypt_cipher_list[] = { {ATTRCRYPT_CIPHER_AES, "AES", CKM_AES_CBC_PAD, CKM_AES_CBC_PAD, CKM_AES_CBC_PAD, 128/8, 16} , 
-	{ATTRCRYPT_CIPHER_DES3 , "3DES" , CKM_DES3_CBC_PAD, CKM_DES3_CBC_PAD, CKM_DES3_CBC_PAD, 112/8, 8}, 
-	{0} };
+attrcrypt_cipher_entry attrcrypt_cipher_list[] =
+{
+  {ATTRCRYPT_CIPHER_AES, "AES", CKM_AES_CBC_PAD, CKM_AES_CBC_PAD, CKM_AES_CBC_PAD, 128/8, 16} , 
+  {ATTRCRYPT_CIPHER_DES3, "3DES", CKM_DES3_CBC_PAD, CKM_DES3_CBC_PAD, CKM_DES3_CBC_PAD, 112/8, 8}, 
+  {0}
+};
 
 #define KEY_ATTRIBUTE_NAME "nsSymmetricKey"
 
@@ -143,13 +146,28 @@ attrcrypt_get_ssl_cert_name(char **cert_name)
 {
 	char *config_entry_dn = "cn=RSA,cn=encryption,cn=config";
 	Slapi_Entry *config_entry = NULL;
+	char *personality = NULL;
+	char *token = NULL;
 	
 	*cert_name = NULL;
 	getConfigEntry(config_entry_dn, &config_entry);
 	if (NULL == config_entry) {
 		return -1;
 	}
-	*cert_name = slapi_entry_attr_get_charptr( config_entry, "nssslpersonalityssl" );
+	token = slapi_entry_attr_get_charptr( config_entry, "nsssltoken" );
+	personality = 
+		slapi_entry_attr_get_charptr( config_entry, "nssslpersonalityssl" );
+	if (token && personality) {
+		if(!strcasecmp(token, "internal") ||
+		   !strcasecmp(token, "internal (software)")) {
+			*cert_name = personality;
+		} else {
+			/* external PKCS #11 token - attach token name */
+			*cert_name = slapi_ch_smprintf("%s:%s", token, personality);
+			slapi_ch_free_string(&personality);
+		}
+		slapi_ch_free_string(&token);
+	}
 	freeConfigEntry(&config_entry);
 	return 0;
 }
@@ -265,13 +283,31 @@ attrcrypt_unwrap_key(attrcrypt_cipher_state *acs, SECKEYPrivateKey *private_key,
 	int ret = 0;
 	CK_MECHANISM_TYPE wrap_mechanism = acs->ace->wrap_mechanism;
 	SECKEYPrivateKey *unwrapping_key = private_key;
-	LDAPDebug(LDAP_DEBUG_TRACE,"-> attrcrypt_unwrap_key\n", 0, 0, 0);
-	*unwrapped_symmetric_key = slapd_pk11_PubUnwrapSymKey(unwrapping_key, wrapped_symmetric_key, wrap_mechanism, CKA_UNWRAP, 0);
+
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT, "-> attrcrypt_unwrap_key\n");
+	/* 
+	 * NOTE: we are unwrapping one symmetric key with attribute both ENCRYPT
+	 *       and DECRYPT set.  Some hardware token might have a problem with
+	 *       it.  In such case, we need to generate 2 identiday keys, one for
+	 *       encryption  and another for decription.  When unwrapping them,
+	 *       set attribute ENCRYPT for the encryption key and DECRYPT for
+	 *       the decryption key.
+	 */
+	*unwrapped_symmetric_key = slapd_pk11_PubUnwrapSymKeyWithFlagsPerm(
+	                                                      unwrapping_key, 
+	                                                      wrapped_symmetric_key,
+	                                                      wrap_mechanism,
+	                                                      CKA_DECRYPT, 0,
+	                                                      CKF_ENCRYPT,
+	                                                      PR_FALSE);
 	if (NULL == *unwrapped_symmetric_key) {
 		ret = -1;
-		LDAPDebug(LDAP_DEBUG_ANY,"attrcrypt_unwrap_key: failed to unwrap key for cipher %s\n", acs->ace->cipher_display_name, 0, 0);
+		slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, 
+		                "attrcrypt_unwrap_key: "
+		                "failed to unwrap key for cipher %s\n", 
+		                acs->ace->cipher_display_name);
 	}
-	LDAPDebug(LDAP_DEBUG_TRACE,"<- attrcrypt_unwrap_key\n", 0, 0, 0);
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT, "<- attrcrypt_unwrap_key\n");
 	return ret;
 }
 
@@ -279,16 +315,44 @@ attrcrypt_unwrap_key(attrcrypt_cipher_state *acs, SECKEYPrivateKey *private_key,
 static int
 attrcrypt_generate_key(attrcrypt_cipher_state *acs,PK11SymKey **symmetric_key)
 {
-	int ret = -1;
+	int ret = 1;
 	PK11SymKey *new_symmetric_key = NULL;
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT, "-> attrcrypt_generate_key\n");
+	if (NULL == symmetric_key) {
+		LDAPDebug0Args(LDAP_DEBUG_ANY, "NULL symmetric_key\n");
+		goto bail;
+	}
 	*symmetric_key = NULL;
-	LDAPDebug(LDAP_DEBUG_TRACE,"-> attrcrypt_generate_key\n", 0, 0, 0);
-	new_symmetric_key = slapd_pk11_KeyGen(acs->slot, acs->ace->key_gen_mechanism, NULL, acs->ace->key_size, NULL);	
+
+	if (!slapd_pk11_DoesMechanism(acs->slot, acs->ace->cipher_mechanism)) {
+		slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, "%s is not supported.\n",
+		                acs->ace->cipher_display_name);
+		ret = -1;
+		goto bail;
+	}
+
+	/* 
+	 * NOTE: we are generating one symmetric key with attribute both ENCRYPT
+	 *       and DECRYPT set.  Some hardware token might have a problem with
+	 *       it.  In such case, we need to generate 2 identiday keys, one for
+	 *       encryption (with an attribute ENCRYPT set) and another for
+	 *       decription (DECRYPT set).
+	 */
+	new_symmetric_key = slapd_pk11_TokenKeyGenWithFlags(acs->slot,
+	                                                acs->ace->key_gen_mechanism,
+	                                                0 /*param*/,
+	                                                acs->ace->key_size,
+	                                                NULL /*keyid*/, 
+	                                                CKA_DECRYPT/*op*/,
+	                                                CKF_ENCRYPT/*attr*/,
+	                                                NULL);
 	if (new_symmetric_key) {
 		*symmetric_key = new_symmetric_key;
 		ret = 0;
 	}
-	LDAPDebug(LDAP_DEBUG_TRACE,"<- attrcrypt_generate_key\n", 0, 0, 0);
+bail:
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT,
+	                "<- attrcrypt_generate_key (%d)\n", ret);
 	return ret;
 }
 
@@ -393,7 +457,7 @@ attrcrypt_cipher_init(ldbm_instance *li, attrcrypt_cipher_entry *ace, SECKEYPriv
 {
 	int ret = 0;
 	PK11SymKey *symmetric_key = NULL;
-	LDAPDebug(LDAP_DEBUG_TRACE,"-> attrcrypt_cipher_init\n", 0, 0, 0);
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT, "-> attrcrypt_cipher_init\n");
 	acs->cipher_lock = PR_NewLock();
 	/* Fill in some basic stuff */
 	acs->ace = ace;
@@ -416,11 +480,17 @@ attrcrypt_cipher_init(ldbm_instance *li, attrcrypt_cipher_entry *ace, SECKEYPriv
 			"No symmetric key found for cipher %s in backend %s, "
 			"attempting to create one...\n",
 			acs->cipher_display_name, li->inst_name);
-		ret = attrcrypt_generate_key(acs,&symmetric_key);
+		ret = attrcrypt_generate_key(acs, &symmetric_key);
 		if (ret) {
-			slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, 
-				"Failed to generate key for %s in attrcrypt_cipher_init\n",
+			slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, "Warning: "
+			    "Failed to generate key for %s in attrcrypt_cipher_init\n",
 				acs->cipher_display_name);
+			if ((ret < 0) && li->attrcrypt_configured) {
+				slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT,
+					       "Cipher %s is not supported on the security device. "
+					       "Do not configure attrcrypt with the cipher.\n",
+					       ace->cipher_display_name);
+			}
 		}
 		if (symmetric_key) {
 			ret = attrcrypt_keymgmt_store_key(li,acs,public_key,symmetric_key);
@@ -450,7 +520,7 @@ attrcrypt_cipher_init(ldbm_instance *li, attrcrypt_cipher_entry *ace, SECKEYPriv
 		acs->key = symmetric_key;
 	}
 error:
-	LDAPDebug(LDAP_DEBUG_TRACE,"<- attrcrypt_cipher_init\n", 0, 0, 0);
+	slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT, "<- attrcrypt_cipher_init\n");
 	return ret;
 }
 
@@ -479,23 +549,38 @@ attrcrypt_init(ldbm_instance *li)
 		if (!ret) { 
 			ret = attrcrypt_fetch_public_key(&public_key);
 			if (!ret) {
-				for (ace = attrcrypt_cipher_list; ace && ace->cipher_number && !ret; ace++) {
+				int cipher_is_available = 0;
+				for (ace = attrcrypt_cipher_list;
+				     ace && ace->cipher_number && !ret; ace++) {
 					/* Make a state object for this cipher */
 					attrcrypt_cipher_state *acs = (attrcrypt_cipher_state *) slapi_ch_calloc(sizeof(attrcrypt_cipher_state),1);
 					ret = attrcrypt_cipher_init(li, ace, private_key, public_key, acs);
 					if (ret) {
-						LDAPDebug(LDAP_DEBUG_ANY,"Failed to initialize cipher %s in attrcrypt_init\n", ace->cipher_display_name, 0, 0);
-						if (!li->attrcrypt_configured) {
+						slapi_ch_free((void **)&acs);
+						if (li->attrcrypt_configured) {
+							if ((ace+1)->cipher_number) {
+								/* this is not the last cipher */
+								ret = 0;
+								continue;
+							}
+						} else {
 							/* if not using attrcrypt, just return success */
 							ret = 0;
 						}
-						slapi_ch_free((void **)&acs);
 					} else {
 						/* Since we succeeded, add the acs to the backend instance list */
 						attrcrypt_acs_list_add(li,acs);
-						LDAPDebug(LDAP_DEBUG_TRACE,"Initialized cipher %s in attrcrypt_init\n", ace->cipher_display_name, 0, 0);
+						slapi_log_error(SLAPI_LOG_TRACE, ATTRCRYPT,
+						        "Initialized cipher %s in attrcrypt_init\n",
+						        ace->cipher_display_name);
+						cipher_is_available = 1; /* at least one is available */
 					}
 				}
+				if (!cipher_is_available) {
+					slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT,
+							        "All prepared ciphers are not available. "
+							        "Please disable attribute encryption.\n");
+				}
 			}
 			slapd_pk11_DestroyPublicKey(public_key);
 			public_key = NULL;
@@ -986,7 +1071,9 @@ back_crypt_init(Slapi_Backend *be, const char *dn,
                                       private_key, public_key, acs, dn);
         if (ret) {
             slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, 
-                            "back_crypt_init: Failed to initialize cipher %s\n",
+                            "back_crypt_init: Failed to initialize cipher %s."
+                            "Please choose other cipher or disable changelog "
+                            "encryption.\n",
                             ace->cipher_display_name);
             slapi_ch_free((void **)&acs);
         } else {
@@ -1180,6 +1267,12 @@ _back_crypt_cipher_init(Slapi_Backend *be,
             slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT, 
                     "_back_crypt_cipher_init: Failed to generate key for %s\n",
                     acs->cipher_display_name);
+            if (ret < 0) {
+                slapi_log_error(SLAPI_LOG_FATAL, ATTRCRYPT,
+                     "Cipher %s is not supported on the security device.  "
+                     "Do not configure changelog encryption with the cipher.\n",
+                     ace->cipher_display_name);
+            }
         }
         if (symmetric_key) {
             ret = _back_crypt_keymgmt_store_key(be, acs, public_key, 
@@ -1529,7 +1622,7 @@ _back_crypt_crypto_op(attrcrypt_private *priv,
     }
 error:
     if (sec_context) {
-        PK11_DestroyContext(sec_context, PR_TRUE);
+        slapd_pk11_destroyContext(sec_context, PR_TRUE);
     }
     if (security_parameter) {
         SECITEM_FreeItem(security_parameter, PR_TRUE);
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index fb852b5..dd7ec88 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1017,6 +1017,9 @@ SECStatus slapd_pk11_DigestFinal(PK11Context *context, unsigned char *data,unsig
 void slapd_SECITEM_FreeItem (SECItem *zap, PRBool freeit);
 void slapd_pk11_DestroyPrivateKey(SECKEYPrivateKey *key);
 void slapd_pk11_DestroyPublicKey(SECKEYPublicKey *key);
+PRBool slapd_pk11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
+PK11SymKey *slapd_pk11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags, PRBool isPerm);
+PK11SymKey *slapd_pk11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx);
 
 /*
  * start_tls_extop.c
diff --git a/ldap/servers/slapd/security_wrappers.c b/ldap/servers/slapd/security_wrappers.c
index 6cca6ce..33d512f 100644
--- a/ldap/servers/slapd/security_wrappers.c
+++ b/ldap/servers/slapd/security_wrappers.c
@@ -338,11 +338,6 @@ void slapd_pk11_FreeSymKey(PK11SymKey *key)
 	PK11_FreeSymKey(key);
 }
 
-void slapd_pk11_DestroyContext(PK11Context *context, PRBool freeit)
-{
-	PK11_DestroyContext(context,freeit);
-}
-
 SECItem *slapd_pk11_ParamFromIV(CK_MECHANISM_TYPE type,SECItem *iv)
 {
 	return PK11_ParamFromIV(type,iv);
@@ -383,3 +378,34 @@ void slapd_pk11_DestroyPublicKey(SECKEYPublicKey *key)
 {
 	SECKEY_DestroyPublicKey(key);
 }
+
+PRBool slapd_pk11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type)
+{
+	return PK11_DoesMechanism(slot, type);
+}
+
+PK11SymKey *slapd_pk11_PubUnwrapSymKeyWithFlagsPerm(
+                                        SECKEYPrivateKey *wrappingKey,
+                                        SECItem *wrappedKey,
+                                        CK_MECHANISM_TYPE target,
+                                        CK_ATTRIBUTE_TYPE operation,
+                                        int keySize,
+                                        CK_FLAGS flags, 
+                                        PRBool isPerm)
+{
+	return PK11_PubUnwrapSymKeyWithFlagsPerm(wrappingKey, wrappedKey, target,
+	                                         operation, keySize, flags, isPerm);
+}
+
+PK11SymKey *slapd_pk11_TokenKeyGenWithFlags(PK11SlotInfo *slot,
+                                            CK_MECHANISM_TYPE type,
+                                            SECItem *param,
+                                            int keySize,
+                                            SECItem *keyid,
+                                            CK_FLAGS opFlags,
+                                            PK11AttrFlags attrFlags,
+                                            void *wincx)
+{
+	return PK11_TokenKeyGenWithFlags(slot, type, param, keySize, keyid, 
+	                                 opFlags, attrFlags, wincx);
+}




More information about the 389-commits mailing list