When the PROFILE=KEYWORD is specified as a cipher string, openssl will
expand the keyword to the defined cipher string in the configuration
file under section "cipher_profiles". That requires the default
(or any other) configuration file to be loaded, or a call to
CONF_modules_load() to be made. The latter is highjacked because  most
applications (including the openssl apps), do not load a configuration
file, and only try to load modules from it.

An example entry in the configuration file:
[ cipher_profiles ]
PROFILE1 = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384
PROFILE2 = HIGH


>From e3ceaac2c8a5380aee753ec391a1d5ea5ae46fad Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 8 Apr 2014 10:36:05 +0200
Subject: [PATCH 1/2] Allow setting custom cipher strings in the openssl config
 file.

When the PROFILE=KEYWORD is specified as a cipher string, openssl will
expand the keyword to the defined cipher string in the configuration
file under section "cipher_profiles". That requires the default
(or any other) configuration file to be loaded.

An example entry in the configuration file:
[ cipher_profiles ]
PROFILE1 = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384
PROFILE2 = HIGH
---
 crypto/conf/conf.h     |  3 ++
 crypto/conf/conf_api.h |  2 ++
 crypto/conf/conf_lib.c | 29 +++++++++++++++++++
 crypto/conf/conf_mod.c |  6 ++++
 ssl/ssl_ciph.c         | 78 ++++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h
index c219997..a74ee20 100644
--- a/crypto/conf/conf.h
+++ b/crypto/conf/conf.h
@@ -205,6 +205,9 @@ char *CONF_get1_default_config_file(void);
 int CONF_parse_list(const char *list, int sep, int nospc,
 	int (*list_cb)(const char *elem, int len, void *usr), void *arg);
 
+int CONF_profile_load(const CONF *cnf);
+void CONF_profile_unload(void);
+
 void OPENSSL_load_builtin_modules(void);
 
 /* BEGIN ERROR CODES */
diff --git a/crypto/conf/conf_api.h b/crypto/conf/conf_api.h
index 87a954a..dc19596 100644
--- a/crypto/conf/conf_api.h
+++ b/crypto/conf/conf_api.h
@@ -79,6 +79,8 @@ char *_CONF_get_string(const CONF *conf, const char *section,
 		       const char *name);
 long _CONF_get_number(const CONF *conf, const char *section, const char *name);
 
+STACK_OF(CONF_VALUE) *_CONF_get_policy_values(void);
+
 int _CONF_new_data(CONF *conf);
 void _CONF_free_data(CONF *conf);
 
diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
index 54046de..df04897 100644
--- a/crypto/conf/conf_lib.c
+++ b/crypto/conf/conf_lib.c
@@ -225,6 +225,35 @@ int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
 	return NCONF_dump_bio(&ctmp, out);
 	}
 
+#define CIPHER_POLICIES "cipher_profiles"
+static STACK_OF(CONF_VALUE) *openssl_profile_values = NULL;
+
+STACK_OF(CONF_VALUE) *_CONF_get_profile_values(void)
+{
+	return openssl_profile_values;
+}
+
+void CONF_profile_unload(void)
+	{
+	openssl_profile_values = NULL;
+	}
+
+int CONF_profile_load(const CONF *cnf)
+	{
+	if (openssl_profile_values != NULL)
+		return 1;
+
+	if (!cnf)
+		return 1;
+
+	openssl_profile_values = NCONF_get_section(cnf, CIPHER_POLICIES);
+	if (!openssl_profile_values)
+		return 0;
+
+	return 1;
+
+	}
+
 /* The following section contains the "New CONF" functions.  They are
    completely centralised around a new CONF structure that may contain
    basically anything, but at least a method pointer and a table of data.
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
index df1642a..45bff85 100644
--- a/crypto/conf/conf_mod.c
+++ b/crypto/conf/conf_mod.c
@@ -133,6 +133,11 @@ int CONF_modules_load(const CONF *cnf, const char *appname,
 	if (!cnf)
 		return 1;
 
+	/* This is unrelated but added here because everyone calls
+	 * CONF_modules_load().
+	 */
+	CONF_profile_load(cnf);
+
 	if (appname)
 		vsection = NCONF_get_string(cnf, NULL, appname);
 
@@ -423,6 +428,7 @@ void CONF_modules_unload(int all)
 	{
 	int i;
 	CONF_MODULE *md;
+	CONF_profile_unload();
 	CONF_modules_finish();
 	/* unload modules in reverse order */
 	for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--)
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 91f1990..ad85b71 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -148,7 +148,9 @@
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
+#include <openssl/conf.h>
 #include "ssl_locl.h"
+#include <openssl/conf_api.h>
 
 #define SSL_ENC_DES_IDX		0
 #define SSL_ENC_3DES_IDX	1
@@ -1457,6 +1459,58 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
 	}
 #endif
 
+char* load_system_str(const char* suffix)
+{
+	char buf[1024];
+	char *new_rules;
+	unsigned len, slen;
+	unsigned i;
+	const char *value = NULL, *p;
+	CONF_VALUE *vl;
+	STACK_OF(CONF_VALUE) *profile;
+
+	profile = _CONF_get_profile_values();
+
+	if (profile == NULL)
+		return NULL;
+
+	if ((p=strchr(suffix, ':')) == NULL) {
+		slen=snprintf(buf, sizeof(buf), "%s", suffix);
+	} else {
+		snprintf(buf, sizeof(buf), "%s", suffix);
+		slen = p-suffix;
+		buf[slen] = 0;
+	}
+	suffix += slen;
+
+	for (i = 0; i < sk_CONF_VALUE_num(profile); i++) {
+		vl = sk_CONF_VALUE_value(profile, i);
+		if (strcasecmp(vl->name, buf) == 0) {
+			value = vl->value;
+			break;
+		}
+	}
+
+	if (value == NULL)
+		return NULL;
+
+	slen = strlen(suffix);
+	len = strlen(vl->value);
+
+	new_rules = malloc(len + slen + 1);
+	if (new_rules == NULL)
+		return NULL;
+
+	memcpy(new_rules, value, len);
+	if (slen > 0) {
+		memcpy(&new_rules[len], suffix, slen);
+		len += slen;
+	}
+	new_rules[len] = 0;
+
+	return new_rules;
+}
+
 STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 		STACK_OF(SSL_CIPHER) **cipher_list,
 		STACK_OF(SSL_CIPHER) **cipher_list_by_id,
@@ -1468,15 +1522,28 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	const char *rule_p;
 	CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
 	const SSL_CIPHER **ca_list = NULL;
+	char *new_rules = NULL;
+
+	if (rule_str != NULL && strncasecmp(rule_str, "PROFILE=", 8) == 0) {
+		const char* p = rule_str + 8;
+
+		new_rules = load_system_str(p);
+		rule_str = new_rules;
+	}
 
 	/*
 	 * Return with error if nothing to do.
 	 */
-	if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
+	if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL) {
+		OPENSSL_free(new_rules);
 		return NULL;
+	}
+
 #ifndef OPENSSL_NO_EC
-	if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
+	if (!check_suiteb_cipher_list(ssl_method, c, &rule_str)) {
+		OPENSSL_free(new_rules);
 		return NULL;
+	}
 #endif
 
 	/*
@@ -1497,6 +1564,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
 	if (co_list == NULL)
 		{
+		OPENSSL_free(new_rules);
 		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
 		return(NULL);	/* Failure */
 		}
@@ -1540,6 +1608,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	 * in force within each class */
 	if (!ssl_cipher_strength_sort(&head, &tail))
 		{
+		OPENSSL_free(new_rules);
 		OPENSSL_free(co_list);
 		return NULL;
 		}
@@ -1562,6 +1631,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	if (ca_list == NULL)
 		{
 		OPENSSL_free(co_list);
+		OPENSSL_free(new_rules);
 		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
 		return(NULL);	/* Failure */
 		}
@@ -1592,6 +1662,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	if (!ok)
 		{	/* Rule processing failure */
 		OPENSSL_free(co_list);
+		OPENSSL_free(new_rules);
 		return(NULL);
 		}
 	
@@ -1602,6 +1673,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
 		{
 		OPENSSL_free(co_list);
+		OPENSSL_free(new_rules);
 		return(NULL);
 		}
 
@@ -1629,6 +1701,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	if (tmp_cipher_list == NULL)
 		{
 		sk_SSL_CIPHER_free(cipherstack);
+		OPENSSL_free(new_rules);
 		return NULL;
 		}
 	if (*cipher_list != NULL)
@@ -1640,6 +1713,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	(void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
 
 	sk_SSL_CIPHER_sort(*cipher_list_by_id);
+	OPENSSL_free(new_rules);
 	return(cipherstack);
 	}
 
-- 
1.9.0

Reply via email to