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
