Fix checking of negative with unsigned variables. Check digestSz for 0 in wc_SSH_KDF() so that no possibility of dividing by zero. Change XMEMCPY to XMEMSET in renesas_sce_util.c. Fix test.c to free prvTmp and pubTmp on read error. Remove unused variables. XFREE checks for NULL so don't check before call. Move variable declarations to reduce scope.
1602 lines
45 KiB
C
1602 lines
45 KiB
C
/* conf.c
|
|
*
|
|
* Copyright (C) 2006-2023 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
|
|
#if !defined(WOLFSSL_CONF_INCLUDED)
|
|
#ifndef WOLFSSL_IGNORE_FILE_WARN
|
|
#warning conf.c does not need to be compiled separately from ssl.c
|
|
#endif
|
|
#else
|
|
|
|
/*******************************************************************************
|
|
* START OF TXT_DB API
|
|
******************************************************************************/
|
|
|
|
#if defined(OPENSSL_ALL) && !defined(NO_BIO)
|
|
/**
|
|
* This function reads a tab delimetered CSV input and returns
|
|
* a populated WOLFSSL_TXT_DB structure.
|
|
* @param in Tab delimetered CSV input
|
|
* @param num Number of fields in each row.
|
|
* @return
|
|
*/
|
|
WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num)
|
|
{
|
|
WOLFSSL_TXT_DB *ret = NULL;
|
|
char *buf = NULL;
|
|
char *bufEnd = NULL;
|
|
char *idx = NULL;
|
|
char* lineEnd = NULL;
|
|
int bufSz;
|
|
int failed = 1;
|
|
/* Space in front of str reserved for field pointers + \0 */
|
|
int fieldsSz = (num + 1) * sizeof(char *);
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_read");
|
|
|
|
if (!in || num <= 0 || num > WOLFSSL_TXT_DB_MAX_FIELDS) {
|
|
WOLFSSL_MSG("Bad parameter or too many fields");
|
|
return NULL;
|
|
}
|
|
|
|
if (!(ret = (WOLFSSL_TXT_DB*)XMALLOC(sizeof(WOLFSSL_TXT_DB), NULL,
|
|
DYNAMIC_TYPE_OPENSSL))) {
|
|
WOLFSSL_MSG("malloc error");
|
|
goto error;
|
|
}
|
|
XMEMSET (ret, 0, sizeof(WOLFSSL_TXT_DB));
|
|
ret->num_fields = num;
|
|
|
|
if (!(ret->data = wolfSSL_sk_WOLFSSL_STRING_new())) {
|
|
WOLFSSL_MSG("wolfSSL_sk_WOLFSSL_STRING_new error");
|
|
goto error;
|
|
}
|
|
|
|
bufSz = wolfSSL_BIO_get_len(in);
|
|
if (bufSz <= 0 ||
|
|
!(buf = (char*)XMALLOC(bufSz+1, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER))) {
|
|
WOLFSSL_MSG("malloc error or no data in BIO");
|
|
goto error;
|
|
}
|
|
|
|
if (wolfSSL_BIO_read(in, buf, bufSz) != bufSz) {
|
|
WOLFSSL_MSG("malloc error or no data in BIO");
|
|
goto error;
|
|
}
|
|
|
|
buf[bufSz] = '\0';
|
|
idx = buf;
|
|
for (bufEnd = buf + bufSz; idx < bufEnd; idx = lineEnd + 1) {
|
|
char* strBuf = NULL;
|
|
char** fieldPtr = NULL;
|
|
int fieldPtrIdx = 0;
|
|
char* fieldCheckIdx = NULL;
|
|
lineEnd = XSTRNSTR(idx, "\n", (unsigned int)(bufEnd - idx));
|
|
if (!lineEnd)
|
|
lineEnd = bufEnd;
|
|
if (idx == lineEnd) /* empty line */
|
|
continue;
|
|
if (*idx == '#')
|
|
continue;
|
|
*lineEnd = '\0';
|
|
strBuf = (char*)XMALLOC(fieldsSz + lineEnd - idx + 1, NULL,
|
|
DYNAMIC_TYPE_OPENSSL);
|
|
if (!strBuf) {
|
|
WOLFSSL_MSG("malloc error");
|
|
goto error;
|
|
}
|
|
XMEMCPY(strBuf + fieldsSz, idx, lineEnd - idx + 1); /* + 1 for NULL */
|
|
XMEMSET(strBuf, 0, fieldsSz);
|
|
/* Check for appropriate number of fields */
|
|
fieldPtr = (char**)strBuf;
|
|
fieldCheckIdx = strBuf + fieldsSz;
|
|
fieldPtr[fieldPtrIdx++] = fieldCheckIdx;
|
|
while (*fieldCheckIdx != '\0') {
|
|
/* Handle escaped tabs */
|
|
if (*fieldCheckIdx == '\t' && fieldCheckIdx[-1] != '\\') {
|
|
fieldPtr[fieldPtrIdx++] = fieldCheckIdx + 1;
|
|
*fieldCheckIdx = '\0';
|
|
if (fieldPtrIdx > num) {
|
|
WOLFSSL_MSG("too many fields");
|
|
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
goto error;
|
|
}
|
|
}
|
|
fieldCheckIdx++;
|
|
}
|
|
if (fieldPtrIdx != num) {
|
|
WOLFSSL_MSG("wrong number of fields");
|
|
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
goto error;
|
|
}
|
|
if (wolfSSL_sk_push(ret->data, strBuf) != WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_sk_push error");
|
|
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
failed = 0;
|
|
error:
|
|
if (failed && ret) {
|
|
XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
ret = NULL;
|
|
}
|
|
if (buf) {
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
long wolfSSL_TXT_DB_write(WOLFSSL_BIO *out, WOLFSSL_TXT_DB *db)
|
|
{
|
|
const WOLF_STACK_OF(WOLFSSL_STRING)* data;
|
|
long totalLen = 0;
|
|
char buf[512]; /* Should be more than enough for a single row */
|
|
char* bufEnd = buf + sizeof(buf);
|
|
int i;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_write");
|
|
|
|
if (!out || !db || !db->num_fields) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
data = db->data;
|
|
while (data) {
|
|
char** fields = (char**)data->data.string;
|
|
char* idx = buf;
|
|
int sz;
|
|
|
|
if (!fields) {
|
|
WOLFSSL_MSG("Missing row");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < db->num_fields; i++) {
|
|
const char* fieldValue = fields[i];
|
|
if (!fieldValue) {
|
|
fieldValue = "";
|
|
}
|
|
|
|
/* Copy over field escaping tabs */
|
|
while (*fieldValue != '\0') {
|
|
if (idx+1 < bufEnd) {
|
|
if (*fieldValue == '\t')
|
|
*idx++ = '\\';
|
|
*idx++ = *fieldValue++;
|
|
}
|
|
else {
|
|
WOLFSSL_MSG("Data row is too big");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
}
|
|
if (idx < bufEnd) {
|
|
*idx++ = '\t';
|
|
}
|
|
else {
|
|
WOLFSSL_MSG("Data row is too big");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
}
|
|
idx[-1] = '\n';
|
|
sz = (int)(idx - buf);
|
|
|
|
if (wolfSSL_BIO_write(out, buf, sz) != sz) {
|
|
WOLFSSL_MSG("wolfSSL_BIO_write error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
totalLen += sz;
|
|
|
|
data = data->next;
|
|
}
|
|
|
|
return totalLen;
|
|
}
|
|
|
|
int wolfSSL_TXT_DB_insert(WOLFSSL_TXT_DB *db, WOLFSSL_STRING *row)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_insert");
|
|
|
|
if (!db || !row || !db->data) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
if (wolfSSL_sk_push(db->data, row) != WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_sk_push error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
|
|
void wolfSSL_TXT_DB_free(WOLFSSL_TXT_DB *db)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_free");
|
|
if (db) {
|
|
if (db->data) {
|
|
wolfSSL_sk_pop_free(db->data, NULL);
|
|
}
|
|
XFREE(db, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
}
|
|
}
|
|
|
|
int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field,
|
|
void* qual, wolf_sk_hash_cb hash, wolf_lh_compare_cb cmp)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index");
|
|
(void)qual;
|
|
(void)cmp;
|
|
|
|
if (!db || !hash || !cmp || field >= db->num_fields || field < 0) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
db->hash_fn[field] = hash;
|
|
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
|
|
WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx,
|
|
WOLFSSL_STRING *value)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_TXT_DB_get_by_index");
|
|
|
|
if (!db || !db->data || idx < 0 || idx >= db->num_fields) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return NULL;
|
|
}
|
|
|
|
if (!db->hash_fn[idx]) {
|
|
WOLFSSL_MSG("Missing hash functions");
|
|
return NULL;
|
|
}
|
|
|
|
/* If first data struct has correct hash function
|
|
* then assume others do too */
|
|
if (db->data->hash_fn != db->hash_fn[idx]) {
|
|
/* Set the hash and comp functions */
|
|
WOLF_STACK_OF(WOLFSSL_STRING)* data = db->data;
|
|
while (data) {
|
|
if (data->hash_fn != db->hash_fn[idx]) {
|
|
data->hash_fn = db->hash_fn[idx];
|
|
data->hash = 0;
|
|
}
|
|
data= data->next;
|
|
}
|
|
}
|
|
return (WOLFSSL_STRING*) wolfSSL_lh_retrieve(db->data, value);
|
|
}
|
|
|
|
#endif /* OPENSSL_ALL && !NO_BIO */
|
|
|
|
/*******************************************************************************
|
|
* END OF TXT_DB API
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* START OF CONF API
|
|
******************************************************************************/
|
|
|
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
|
|
|| defined(HAVE_STUNNEL)
|
|
#ifndef NO_WOLFSSL_STUB
|
|
void wolfSSL_OPENSSL_config(char *config_name)
|
|
{
|
|
(void)config_name;
|
|
WOLFSSL_STUB("OPENSSL_config");
|
|
}
|
|
#endif /* !NO_WOLFSSL_STUB */
|
|
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_STUNNEL*/
|
|
|
|
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
|
|
|
|
/**
|
|
* This is the same hashing algo for WOLFSSL_CONF_VALUE as OpenSSL
|
|
*/
|
|
static unsigned long wolfSSL_CONF_VALUE_hash(const WOLFSSL_CONF_VALUE *val)
|
|
{
|
|
if (val)
|
|
return (wolfSSL_LH_strhash(val->section) << 2) ^
|
|
wolfSSL_LH_strhash(val->name);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* Use SHA[256] for hashing as OpenSSL uses a hash algorithm that is
|
|
* "not as good as MD5, but still good" so using SHA should be more
|
|
* than good enough for this application. The produced hashes don't
|
|
* need to line up between OpenSSL and wolfSSL. The hashes are for
|
|
* internal indexing only */
|
|
unsigned long wolfSSL_LH_strhash(const char *str)
|
|
{
|
|
unsigned long ret = 0;
|
|
int strLen;
|
|
#if !defined(NO_SHA)
|
|
wc_Sha sha;
|
|
byte digest[WC_SHA_DIGEST_SIZE];
|
|
#elif !defined(NO_SHA256)
|
|
wc_Sha256 sha;
|
|
byte digest[WC_SHA256_DIGEST_SIZE];
|
|
#endif
|
|
WOLFSSL_ENTER("wolfSSL_LH_strhash");
|
|
|
|
if (!str)
|
|
return 0;
|
|
strLen = (int)XSTRLEN(str);
|
|
|
|
#if !defined(NO_SHA)
|
|
if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
|
|
WOLFSSL_MSG("SHA1 Init failed");
|
|
return 0;
|
|
}
|
|
|
|
ret = wc_ShaUpdate(&sha, (const byte *)str, (word32)strLen);
|
|
if (ret != 0) {
|
|
WOLFSSL_MSG("SHA1 Update failed");
|
|
} else {
|
|
ret = wc_ShaFinal(&sha, digest);
|
|
if (ret != 0) {
|
|
WOLFSSL_MSG("SHA1 Final failed");
|
|
}
|
|
}
|
|
wc_ShaFree(&sha);
|
|
#elif !defined(NO_SHA256)
|
|
if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
|
|
WOLFSSL_MSG("SHA256 Init failed");
|
|
return 0;
|
|
}
|
|
|
|
ret = wc_Sha256Update(&sha, (const byte *)str, (word32)strLen);
|
|
if (ret != 0) {
|
|
WOLFSSL_MSG("SHA256 Update failed");
|
|
} else {
|
|
ret = wc_Sha256Final(&sha, digest);
|
|
if (ret != 0) {
|
|
WOLFSSL_MSG("SHA256 Final failed");
|
|
}
|
|
}
|
|
wc_Sha256Free(&sha);
|
|
#endif
|
|
|
|
#if !defined(NO_SHA) || !defined(NO_SHA256)
|
|
if (ret != 0)
|
|
return 0;
|
|
|
|
/* Take first 4 bytes in small endian as unsigned long */
|
|
ret = (unsigned int)digest[0];
|
|
ret |= ((unsigned int)digest[1] << 8 );
|
|
ret |= ((unsigned int)digest[2] << 16);
|
|
ret |= ((unsigned int)digest[3] << 24);
|
|
#else
|
|
WOLFSSL_MSG("No SHA available for wolfSSL_LH_strhash");
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
WOLFSSL_CONF_VALUE *wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(
|
|
WOLF_LHASH_OF(WOLFSSL_CONF_VALUE) *sk, WOLFSSL_CONF_VALUE *data)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve");
|
|
|
|
if (!sk || !data) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return NULL;
|
|
}
|
|
|
|
return (WOLFSSL_CONF_VALUE*)wolfSSL_lh_retrieve(sk, data);
|
|
}
|
|
|
|
int wolfSSL_CONF_modules_load(const WOLFSSL_CONF *cnf, const char *appname,
|
|
unsigned long flags)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_CONF_modules_load");
|
|
WOLFSSL_MSG("All wolfSSL modules are already compiled in. "
|
|
"wolfSSL_CONF_modules_load doesn't load anything new.");
|
|
(void)cnf;
|
|
(void)appname;
|
|
(void)flags;
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
|
|
WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new(void)
|
|
{
|
|
WOLFSSL_CONF_VALUE* ret;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_CONF_new");
|
|
|
|
ret = (WOLFSSL_CONF_VALUE*)XMALLOC(sizeof(WOLFSSL_CONF_VALUE),
|
|
NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (ret)
|
|
XMEMSET(ret, 0, sizeof(WOLFSSL_CONF_VALUE));
|
|
return ret;
|
|
}
|
|
|
|
int wolfSSL_CONF_add_string(WOLFSSL_CONF *conf,
|
|
WOLFSSL_CONF_VALUE *section, WOLFSSL_CONF_VALUE *value)
|
|
{
|
|
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
|
|
|
|
if (!conf || !section || !value) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *)section->value;
|
|
value->section = section->section;
|
|
|
|
if (wolfSSL_sk_CONF_VALUE_push(sk, value) != WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) != WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
|
|
WOLFSSL_CONF_VALUE *wolfSSL_CONF_new_section(WOLFSSL_CONF *conf,
|
|
const char *section)
|
|
{
|
|
WOLFSSL_CONF_VALUE* ret = NULL;
|
|
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
|
|
int slen;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_CONF_new_section");
|
|
|
|
if (!conf || !section) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return NULL;
|
|
}
|
|
|
|
slen = (int)XSTRLEN(section);
|
|
|
|
if (!(ret = wolfSSL_CONF_VALUE_new())) {
|
|
WOLFSSL_MSG("wolfSSL_CONF_new error");
|
|
goto error;
|
|
}
|
|
|
|
if (!(ret->section = (char*)XMALLOC(slen+1, NULL, DYNAMIC_TYPE_OPENSSL))) {
|
|
WOLFSSL_MSG("section malloc error");
|
|
goto error;
|
|
}
|
|
XMEMCPY(ret->section, section, slen+1);
|
|
|
|
if (!(sk = wolfSSL_sk_CONF_VALUE_new(NULL))) {
|
|
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_new error");
|
|
goto error;
|
|
}
|
|
|
|
ret->value = (char*)sk;
|
|
|
|
if (wolfSSL_sk_CONF_VALUE_push(conf->data, ret) != WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
|
|
goto error;
|
|
}
|
|
|
|
return ret;
|
|
error:
|
|
if (ret) {
|
|
/* NULL so that wolfSSL_X509V3_conf_free doesn't attempt to free it */
|
|
ret->value = NULL;
|
|
wolfSSL_X509V3_conf_free(ret);
|
|
}
|
|
if (sk) {
|
|
wolfSSL_sk_CONF_VALUE_free(sk);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
WOLFSSL_CONF_VALUE *wolfSSL_CONF_get_section(WOLFSSL_CONF *conf,
|
|
const char *section)
|
|
{
|
|
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_CONF_get_section");
|
|
|
|
if (!conf || !section) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return NULL;
|
|
}
|
|
|
|
sk = conf->data;
|
|
|
|
while (sk) {
|
|
WOLFSSL_CONF_VALUE* val = sk->data.conf;
|
|
if (val) {
|
|
if (!val->name && XSTRCMP(section, val->section) == 0) {
|
|
return val;
|
|
}
|
|
}
|
|
sk = sk->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
WOLFSSL_CONF *wolfSSL_NCONF_new(void *meth)
|
|
{
|
|
WOLFSSL_CONF* ret;
|
|
WOLFSSL_ENTER("wolfSSL_NCONF_new");
|
|
|
|
if (meth) {
|
|
WOLFSSL_MSG("wolfSSL does not support CONF_METHOD");
|
|
}
|
|
|
|
ret = (WOLFSSL_CONF*)XMALLOC(sizeof(WOLFSSL_CONF), NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (ret) {
|
|
XMEMSET(ret, 0, sizeof(WOLFSSL_CONF));
|
|
ret->data = wolfSSL_sk_CONF_VALUE_new(NULL);
|
|
if (!ret->data) {
|
|
wolfSSL_NCONF_free(ret);
|
|
return NULL;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
char *wolfSSL_NCONF_get_string(const WOLFSSL_CONF *conf,
|
|
const char *group, const char *name)
|
|
{
|
|
WOLFSSL_CONF_VALUE find_val;
|
|
WOLFSSL_CONF_VALUE *val;
|
|
WOLFSSL_ENTER("wolfSSL_NCONF_get_string");
|
|
|
|
if (!conf) {
|
|
#ifdef HAVE_SECURE_GETENV
|
|
return secure_getenv(name);
|
|
#else
|
|
WOLFSSL_MSG("Missing secure_getenv");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
find_val.name = (char *)name;
|
|
if (group) {
|
|
find_val.section = (char *)group;
|
|
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
|
|
if (val)
|
|
return val->value;
|
|
if (XSTRCMP(group, "ENV") == 0) {
|
|
#ifdef HAVE_SECURE_GETENV
|
|
return secure_getenv(name);
|
|
#else
|
|
WOLFSSL_MSG("Missing secure_getenv");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
find_val.section = (char *)"default";
|
|
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
|
|
if (val)
|
|
return val->value;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
int wolfSSL_NCONF_get_number(const CONF *conf, const char *group,
|
|
const char *name, long *result)
|
|
{
|
|
char *str;
|
|
WOLFSSL_ENTER("wolfSSL_NCONF_get_number");
|
|
|
|
if (!conf || !name || !result) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
if (!(str = wolfSSL_NCONF_get_string(conf, group, name))) {
|
|
WOLFSSL_MSG("wolfSSL_NCONF_get_string error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
*result = atol(str);
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* The WOLFSSL_CONF->value member is treated as a
|
|
* WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE) which becomes
|
|
* the return value.
|
|
* @param conf
|
|
* @param section
|
|
* @return WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE)
|
|
*/
|
|
WOLFSSL_STACK *wolfSSL_NCONF_get_section(
|
|
const WOLFSSL_CONF *conf, const char *section)
|
|
{
|
|
WOLFSSL_CONF_VALUE *val;
|
|
WOLFSSL_CONF_VALUE find_val;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_NCONF_get_section");
|
|
|
|
if (!conf || !section) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return NULL;
|
|
}
|
|
|
|
find_val.name = NULL;
|
|
find_val.section = (char*)section;
|
|
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
|
|
if (val)
|
|
return (WOLFSSL_STACK*)val->value;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
#if !defined(NO_BIO)
|
|
static WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new_values(char* section,
|
|
char* name, char* value)
|
|
{
|
|
WOLFSSL_CONF_VALUE* ret;
|
|
int len;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_CONF_VALUE_new_values");
|
|
|
|
if (!(ret = wolfSSL_CONF_VALUE_new())) {
|
|
WOLFSSL_MSG("wolfSSL_CONF_VALUE_new error");
|
|
return NULL;
|
|
}
|
|
|
|
if (section) {
|
|
len = (int)XSTRLEN(section);
|
|
ret->section = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (!ret->section) {
|
|
WOLFSSL_MSG("malloc error");
|
|
wolfSSL_X509V3_conf_free(ret);
|
|
return NULL;
|
|
}
|
|
XMEMCPY(ret->section, section, len+1);
|
|
}
|
|
|
|
if (name) {
|
|
len = (int)XSTRLEN(name);
|
|
ret->name = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (!ret->name) {
|
|
WOLFSSL_MSG("malloc error");
|
|
wolfSSL_X509V3_conf_free(ret);
|
|
return NULL;
|
|
}
|
|
XMEMCPY(ret->name, name, len+1);
|
|
}
|
|
|
|
if (value) {
|
|
len = (int)XSTRLEN(value);
|
|
ret->value = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (!ret->value) {
|
|
WOLFSSL_MSG("malloc error");
|
|
wolfSSL_X509V3_conf_free(ret);
|
|
return NULL;
|
|
}
|
|
XMEMCPY(ret->value, value, len+1);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static char* expandValue(WOLFSSL_CONF *conf, const char* section,
|
|
char *str)
|
|
{
|
|
int strLen = (int)XSTRLEN(str);
|
|
char* ret = NULL;
|
|
|
|
/* Check to see if there is anything to expand */
|
|
if (XSTRNSTR(str, "$", strLen)) {
|
|
int idx = 0;
|
|
char* strIdx = str;
|
|
ret = (char*)XMALLOC(strLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (!ret) {
|
|
WOLFSSL_MSG("malloc error");
|
|
return str;
|
|
}
|
|
|
|
while (*strIdx) {
|
|
if (*strIdx == '$') {
|
|
/* Expand variable */
|
|
char* startIdx = ++strIdx;
|
|
char* endIdx;
|
|
const char* s = section;
|
|
const char* value;
|
|
char prevValue;
|
|
|
|
if (*startIdx == '{') {
|
|
/* First read the section.
|
|
* format: ${section_name::var_name} */
|
|
s = ++startIdx;
|
|
while (*strIdx && *strIdx != ':') strIdx++;
|
|
if (!*strIdx || s == strIdx || strIdx[1] != ':') {
|
|
WOLFSSL_MSG("invalid section name in "
|
|
"variable expansion");
|
|
goto expand_cleanup;
|
|
}
|
|
*strIdx = '\0';
|
|
strIdx += 2;
|
|
startIdx = strIdx;
|
|
}
|
|
while (*strIdx && (XISALNUM((int)(*strIdx)) || *strIdx == '_'))
|
|
strIdx++;
|
|
endIdx = strIdx;
|
|
if (startIdx == endIdx) {
|
|
WOLFSSL_MSG("invalid variable name in config");
|
|
goto expand_cleanup;
|
|
}
|
|
if (s != section) {
|
|
/* We are expecting a trailing '}' */
|
|
if (*strIdx != '}') {
|
|
WOLFSSL_MSG("Missing '}' in variable");
|
|
goto expand_cleanup;
|
|
}
|
|
strIdx++;
|
|
}
|
|
/* Save char value at the end of the name so that we can place
|
|
* a null char there. */
|
|
prevValue = *endIdx;
|
|
*endIdx = '\0';
|
|
value = wolfSSL_NCONF_get_string(conf, s, startIdx);
|
|
*endIdx = prevValue;
|
|
/* Skip copy if no value or zero-length value */
|
|
if (value && *value) {
|
|
int valueLen = (int)XSTRLEN(value);
|
|
char* newRet;
|
|
/* This will allocate slightly more memory than necessary
|
|
* but better be safe */
|
|
strLen += valueLen;
|
|
newRet = (char*)XREALLOC(ret, strLen + 1, NULL,
|
|
DYNAMIC_TYPE_OPENSSL);
|
|
if (!newRet) {
|
|
WOLFSSL_MSG("realloc error");
|
|
goto expand_cleanup;
|
|
}
|
|
ret = newRet;
|
|
XMEMCPY(ret + idx, value, valueLen);
|
|
idx += valueLen;
|
|
}
|
|
}
|
|
else {
|
|
ret[idx++] = *strIdx++;
|
|
}
|
|
}
|
|
ret[idx] = '\0';
|
|
}
|
|
|
|
return ret ? ret : str;
|
|
|
|
expand_cleanup:
|
|
if (ret)
|
|
XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
return NULL;
|
|
}
|
|
|
|
#define SKIP_WHITESPACE(idx, max_idx) \
|
|
while ((idx) < (max_idx) && (*(idx) == ' ' || *(idx) == '\t')) \
|
|
{(idx)++;}
|
|
int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
|
|
{
|
|
int ret = WOLFSSL_FAILURE;
|
|
WOLFSSL_BIO *in = NULL;
|
|
char* buf = NULL;
|
|
char* idx = NULL;
|
|
char* bufEnd = NULL;
|
|
CONF_VALUE* section = NULL;
|
|
long line = 0;
|
|
int bufLen = 0;
|
|
|
|
if (!conf || !file) {
|
|
WOLFSSL_MSG("Bad parameter");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
/* Open file */
|
|
if (!(in = wolfSSL_BIO_new_file(file, "rb"))) {
|
|
WOLFSSL_MSG("wolfSSL_BIO_new_file error");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
/* Read file */
|
|
bufLen = wolfSSL_BIO_get_len(in);
|
|
if (bufLen <= 0) {
|
|
WOLFSSL_MSG("wolfSSL_BIO_get_len error");
|
|
goto cleanup;
|
|
}
|
|
if (!(buf = (char*)XMALLOC(bufLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
|
|
WOLFSSL_MSG("malloc error");
|
|
goto cleanup;
|
|
}
|
|
if (wolfSSL_BIO_read(in, buf, bufLen) != bufLen) {
|
|
WOLFSSL_MSG("wolfSSL_BIO_read error");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!(section = wolfSSL_CONF_new_section(conf, "default"))) {
|
|
WOLFSSL_MSG("wolfSSL_CONF_new_section error");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* LETS START READING SOME CONFIGS */
|
|
idx = buf;
|
|
bufEnd = buf + bufLen;
|
|
while (idx < bufEnd) {
|
|
char* lineEnd = XSTRNSTR(idx, "\n", (unsigned int)(bufEnd - idx));
|
|
char* maxIdx;
|
|
if (!lineEnd)
|
|
lineEnd = bufEnd; /* Last line in file */
|
|
maxIdx = XSTRNSTR(idx, "#", (unsigned int)(lineEnd - idx));
|
|
if (!maxIdx)
|
|
maxIdx = lineEnd;
|
|
line++;
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
if (idx == maxIdx) {
|
|
/* Empty line */
|
|
idx = lineEnd + 1;
|
|
continue;
|
|
}
|
|
|
|
if (*idx == '[') {
|
|
/* New section. Spaces not allowed in section name. */
|
|
char* sectionName;
|
|
int sectionNameLen;
|
|
|
|
if (idx < maxIdx)
|
|
idx++;
|
|
else {
|
|
WOLFSSL_MSG("Invalid section definition.");
|
|
goto cleanup;
|
|
}
|
|
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
sectionName = idx;
|
|
/* Find end of section name */
|
|
while (idx < maxIdx && *idx != ' ' && *idx != ']')
|
|
idx++;
|
|
sectionNameLen = (int)(idx - sectionName);
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
|
|
if (*idx != ']') {
|
|
WOLFSSL_MSG("Section definition error. "
|
|
"Closing brace not found.");
|
|
goto cleanup;
|
|
}
|
|
|
|
sectionName[sectionNameLen] = '\0';
|
|
if (!(section = wolfSSL_CONF_get_section(conf, sectionName))) {
|
|
section = wolfSSL_CONF_new_section(conf, sectionName);
|
|
if (!section)
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else {
|
|
char* name;
|
|
int nameLen;
|
|
char* value;
|
|
char* exValue; /* expanded value */
|
|
int valueLen;
|
|
WOLFSSL_CONF_VALUE* newVal = NULL;
|
|
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
name = idx;
|
|
/* Find end of name */
|
|
while (idx < maxIdx && *idx != ' ' && *idx != '=')
|
|
idx++;
|
|
nameLen = (int)(idx - name);
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
if (*idx != '=') {
|
|
WOLFSSL_MSG("Missing equals sign");
|
|
goto cleanup;
|
|
}
|
|
idx++;
|
|
SKIP_WHITESPACE(idx, maxIdx);
|
|
value = idx;
|
|
/* Find end of value */
|
|
idx = maxIdx-1;
|
|
while (idx >= value && (*idx == ' ' || *idx == '\t' || *idx == '\r'))
|
|
idx--;
|
|
valueLen = (int)(idx - value + 1);
|
|
|
|
/* Sanity checks */
|
|
if (nameLen <= 0 || valueLen <= 0) {
|
|
WOLFSSL_MSG("Sanity checks failed");
|
|
goto cleanup;
|
|
}
|
|
name[nameLen] = '\0';
|
|
value[valueLen] = '\0';
|
|
|
|
if (!(exValue = expandValue(conf, section->section, value))) {
|
|
WOLFSSL_MSG("Variable expansion failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!(newVal = wolfSSL_CONF_VALUE_new_values(NULL,
|
|
name, exValue))) {
|
|
WOLFSSL_MSG("wolfSSL_CONF_VALUE_new_values error");
|
|
if (exValue != value)
|
|
XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
goto cleanup;
|
|
}
|
|
|
|
if (exValue != value)
|
|
XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
|
|
if (wolfSSL_CONF_add_string(conf, section, newVal) !=
|
|
WOLFSSL_SUCCESS) {
|
|
WOLFSSL_MSG("wolfSSL_CONF_add_string error");
|
|
goto cleanup;
|
|
}
|
|
}
|
|
idx = lineEnd + 1;
|
|
}
|
|
|
|
ret = WOLFSSL_SUCCESS;
|
|
cleanup:
|
|
if (in)
|
|
wolfSSL_BIO_free(in);
|
|
if (buf)
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (eline)
|
|
*eline = line;
|
|
return ret;
|
|
}
|
|
#endif /* !NO_BIO */
|
|
|
|
void wolfSSL_NCONF_free(WOLFSSL_CONF *conf)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_NCONF_free");
|
|
if (conf) {
|
|
wolfSSL_sk_CONF_VALUE_free(conf->data);
|
|
XFREE(conf, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
}
|
|
}
|
|
|
|
void wolfSSL_X509V3_conf_free(WOLFSSL_CONF_VALUE *val)
|
|
{
|
|
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
|
|
|
|
if (val) {
|
|
if (val->name) {
|
|
/* Not a section. Don't free section as it is a shared pointer. */
|
|
XFREE(val->name, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
if (val->value)
|
|
XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
}
|
|
else {
|
|
/* Section so val->value is a stack */
|
|
if (val->section)
|
|
XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
/* Only free the stack structures. The contained conf values
|
|
* will be freed in wolfSSL_NCONF_free */
|
|
sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value;
|
|
while (sk) {
|
|
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *tmp = sk->next;
|
|
XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
sk = tmp;
|
|
}
|
|
}
|
|
XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
}
|
|
}
|
|
|
|
WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(
|
|
WOLF_SK_COMPARE_CB(WOLFSSL_CONF_VALUE, compFunc))
|
|
{
|
|
WOLFSSL_STACK* ret;
|
|
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_new");
|
|
ret = wolfSSL_sk_new_node(NULL);
|
|
if (!ret)
|
|
return NULL;
|
|
ret->hash_fn = (wolf_sk_hash_cb)wolfSSL_CONF_VALUE_hash;
|
|
ret->type = STACK_TYPE_CONF_VALUE;
|
|
(void)compFunc;
|
|
return ret;
|
|
}
|
|
|
|
/* Free the structure for WOLFSSL_CONF_VALUE stack
|
|
*
|
|
* sk stack to free nodes in
|
|
*/
|
|
void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
|
|
{
|
|
WOLFSSL_STACK* tmp;
|
|
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
|
|
|
|
if (sk == NULL)
|
|
return;
|
|
|
|
/* parse through stack freeing each node */
|
|
while (sk) {
|
|
tmp = sk->next;
|
|
wolfSSL_X509V3_conf_free(sk->data.conf);
|
|
XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
sk = tmp;
|
|
}
|
|
}
|
|
|
|
int wolfSSL_sk_CONF_VALUE_num(const WOLFSSL_STACK *sk)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_num");
|
|
if (sk)
|
|
return wolfSSL_sk_num(sk);
|
|
return 0;
|
|
}
|
|
|
|
WOLFSSL_CONF_VALUE *wolfSSL_sk_CONF_VALUE_value(const WOLFSSL_STACK *sk, int i)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_value");
|
|
if (sk)
|
|
return (WOLFSSL_CONF_VALUE*)wolfSSL_sk_value(sk, i);
|
|
return NULL;
|
|
}
|
|
|
|
/* return 1 on success 0 on fail */
|
|
int wolfSSL_sk_CONF_VALUE_push(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk,
|
|
WOLFSSL_CONF_VALUE* val)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_push");
|
|
|
|
if (sk == NULL || val == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_sk_push(sk, val);
|
|
}
|
|
|
|
#endif /* !NO_CERTS && OPENSSL_EXTRA && OPENSSL_ALL */
|
|
|
|
#ifdef OPENSSL_EXTRA
|
|
#ifndef NO_WOLFSSL_STUB
|
|
/* Returns default file name and path of config file. However
|
|
a wolfssl.cnf file is not currently supported */
|
|
char* wolfSSL_CONF_get1_default_config_file(void)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file");
|
|
WOLFSSL_STUB("CONF_get1_default_config_file");
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Allocate WOLFSSL_CONF_CTX instance
|
|
* @return pointer to WOLFSSL_CONF_CTX structure on success and NULL on fail
|
|
*/
|
|
WOLFSSL_CONF_CTX* wolfSSL_CONF_CTX_new(void)
|
|
{
|
|
WOLFSSL_CONF_CTX* cctx;
|
|
|
|
WOLFSSL_ENTER("wolfSSL_CONF_CTX_new");
|
|
|
|
cctx = (WOLFSSL_CONF_CTX*)XMALLOC(sizeof(WOLFSSL_CONF_CTX), NULL,
|
|
DYNAMIC_TYPE_OPENSSL);
|
|
if (!cctx) {
|
|
WOLFSSL_MSG("malloc error");
|
|
return NULL;
|
|
}
|
|
XMEMSET(cctx, 0, sizeof(WOLFSSL_CONF_CTX));
|
|
|
|
return cctx;
|
|
}
|
|
/**
|
|
* Release WOLFSSL_CONF_CTX instance
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be freed
|
|
*/
|
|
void wolfSSL_CONF_CTX_free(WOLFSSL_CONF_CTX* cctx)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_CONF_CTX_free");
|
|
|
|
if (cctx) {
|
|
XFREE(cctx, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
}
|
|
WOLFSSL_LEAVE("wolfSSL_CONF_CTX_free", 1);
|
|
}
|
|
/**
|
|
* Set WOLFSSL_CTX instance to WOLFSSL_CONF_CTX
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to set a WOLFSSL_CTX
|
|
* pointer to its ctx
|
|
* @param ctx a pointer to WOLFSSL_CTX structure to be set
|
|
*/
|
|
void wolfSSL_CONF_CTX_set_ssl_ctx(WOLFSSL_CONF_CTX* cctx, WOLFSSL_CTX *ctx)
|
|
{
|
|
WOLFSSL_ENTER("wolfSSL_CONF_CTX_set_ssl_ctx");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL) {
|
|
WOLFSSL_MSG("cctx is null");
|
|
return;
|
|
}
|
|
|
|
cctx->ctx = ctx;
|
|
WOLFSSL_LEAVE("wolfSSL_CONF_CTX_set_ssl_ctx", 1);
|
|
}
|
|
/**
|
|
* set flag value into WOLFSSL_CONF_CTX
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set
|
|
* @param flags flag value to be OR'd
|
|
* @return OR'd flag value, otherwise 0
|
|
*/
|
|
unsigned int wolfSSL_CONF_CTX_set_flags(WOLFSSL_CONF_CTX* cctx,
|
|
unsigned int flags)
|
|
{
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return 0;
|
|
|
|
cctx->flags |= flags;
|
|
return cctx->flags;
|
|
}
|
|
|
|
/**
|
|
* finish configuration command operation
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set
|
|
* @return WOLFSSL_SUCCESS on success
|
|
*/
|
|
int wolfSSL_CONF_CTX_finish(WOLFSSL_CONF_CTX* cctx)
|
|
{
|
|
(void)cctx;
|
|
return WOLFSSL_SUCCESS;
|
|
}
|
|
/*
|
|
* The following definitions and static functions are used for
|
|
* wolfSSL_CONF_cmd() to handle command.
|
|
*
|
|
* Definitions below are a part of conf_cmds_tbl[] contents.
|
|
* WOLFSSL_CONF_FILE_CMDx represents command name in configuration file
|
|
* WOLFSSL_CONF_CMDL_CMDx represents command name on command line
|
|
*
|
|
* The static functions after the definition section process
|
|
* those FILE or CMDL which are defined in the conf_cmds_tbl.
|
|
*
|
|
* To add a new command handling:
|
|
* 1. Add new #define to a section of WOLFSSL_CONF_FILE_CMD* and
|
|
* WOLFSSL_CONF_CMDL_CMD*
|
|
* 2. Add new static function after #define section, before
|
|
* "typedef struct conf_cmd_tbl {" line
|
|
* 3. Add new entry to conf_cmds_tbl[] by following other command entries
|
|
*/
|
|
#define WOLFSSL_CONF_FILE_CMD1 "Curves"
|
|
#define WOLFSSL_CONF_FILE_CMD2 "Certificate"
|
|
#define WOLFSSL_CONF_FILE_CMD3 "PrivateKey"
|
|
#define WOLFSSL_CONF_FILE_CMD4 "Protocol"
|
|
#define WOLFSSL_CONF_FILE_CMD5 "Options"
|
|
#define WOLFSSL_CONF_FILE_CMD6 "ServerInfoFile"
|
|
#define WOLFSSL_CONF_FILE_CMD7 "SignatureAlgorithms"
|
|
#define WOLFSSL_CONF_FILE_CMD8 "ClientSignatureAlgorithms"
|
|
#define WOLFSSL_CONF_FILE_CMD9 "CipherString"
|
|
|
|
#define WOLFSSL_CONF_CMDL_CMD1 "curves"
|
|
#define WOLFSSL_CONF_CMDL_CMD2 "cert"
|
|
#define WOLFSSL_CONF_CMDL_CMD3 "key"
|
|
#define WOLFSSL_CONF_CMDL_CMD4 NULL
|
|
#define WOLFSSL_CONF_CMDL_CMD5 NULL
|
|
#define WOLFSSL_CONF_CMDL_CMD6 NULL
|
|
#define WOLFSSL_CONF_CMDL_CMD7 "sigalgs"
|
|
#define WOLFSSL_CONF_CMDL_CMD8 "client_sigalgs"
|
|
#define WOLFSSL_CONF_CMDL_CMD9 "cipher"
|
|
|
|
#if !defined(NO_DH) && !defined(NO_BIO)
|
|
#define WOLFSSL_CONF_FILE_CMD10 "DHParameters"
|
|
#define WOLFSSL_CONF_CMDL_CMD10 "dhparam"
|
|
#endif
|
|
|
|
#ifdef HAVE_ECC
|
|
#define WOLFSSL_CONF_FILE_CMD11 "ECDHParameters"
|
|
#define WOLFSSL_CONF_CMDL_CMD11 "named_curves"
|
|
#endif
|
|
|
|
/**
|
|
* process Cipher String command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param value arguments for cmd
|
|
* @return WOLFSSL_SUCCESS on success,
|
|
* otherwise WOLFSSL_FAILURE or
|
|
* -3 if value is null or
|
|
* negative value on other failure
|
|
*/
|
|
static int cmdfunc_cipherstring(WOLFSSL_CONF_CTX* cctx, const char* value)
|
|
{
|
|
int ret = -3;
|
|
|
|
WOLFSSL_ENTER("cmdfunc_cipherstring");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return WOLFSSL_FAILURE;
|
|
|
|
if (value == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
if (cctx->ctx) {
|
|
ret = wolfSSL_CTX_set_cipher_list(cctx->ctx, value);
|
|
}
|
|
|
|
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
|
|
(!cctx->ctx && ret == -3)) &&
|
|
cctx->ssl) {
|
|
ret = wolfSSL_set_cipher_list(cctx->ssl, value);
|
|
}
|
|
|
|
WOLFSSL_LEAVE("cmdfunc_cipherstring", ret);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* process curves command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param value arguments for cmd
|
|
* @return WOLFSSL_SUCCESS on success,
|
|
* otherwise WOLFSSL_FAILURE or
|
|
* -3 if value is null or
|
|
* negative value on other failure
|
|
*/
|
|
#if defined(HAVE_ECC)
|
|
static int cmdfunc_curves(WOLFSSL_CONF_CTX* cctx, const char* value)
|
|
{
|
|
int ret = -3;
|
|
|
|
WOLFSSL_ENTER("cmdfunc_curves");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return WOLFSSL_FAILURE;
|
|
|
|
if (value == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
if (cctx->ctx) {
|
|
ret = wolfSSL_CTX_set1_curves_list(cctx->ctx, value);
|
|
}
|
|
|
|
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
|
|
(!cctx->ctx && ret == -3)) &&
|
|
cctx->ssl) {
|
|
ret = wolfSSL_set1_curves_list(cctx->ssl, value);
|
|
}
|
|
|
|
WOLFSSL_LEAVE("cmdfunc_curves", ret);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_FILESYSTEM
|
|
/**
|
|
* process cert command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param value arguments for cmd
|
|
* @return WOLFSSL_SUCCESS on success,
|
|
* otherwise WOLFSSL_FAILURE or
|
|
* -3 if value is null or
|
|
* negative value on other failure
|
|
*/
|
|
static int cmdfunc_cert(WOLFSSL_CONF_CTX* cctx, const char* value)
|
|
{
|
|
int ret = -3;
|
|
|
|
WOLFSSL_ENTER("cmdfunc_cert");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return WOLFSSL_FAILURE;
|
|
|
|
if (value == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
|
|
WOLFSSL_MSG("certificate flag is not set");
|
|
return -2;
|
|
}
|
|
|
|
if (cctx->ctx) {
|
|
ret = wolfSSL_CTX_use_certificate_chain_file(cctx->ctx, value);
|
|
}
|
|
|
|
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
|
|
(!cctx->ctx && ret == -3)) &&
|
|
cctx->ssl) {
|
|
ret = wolfSSL_use_certificate_file(cctx->ssl, value,
|
|
WOLFSSL_FILETYPE_PEM);
|
|
}
|
|
|
|
WOLFSSL_LEAVE("cmdfunc_cert", ret);
|
|
return ret;
|
|
}
|
|
/**
|
|
* process key command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param value arguments for cmd
|
|
* @return WOLFSSL_SUCCESS on success,
|
|
* otherwise WOLFSSL_FAILURE or
|
|
* -3 if value is null or
|
|
* negative value on other failure
|
|
*/
|
|
static int cmdfunc_key(WOLFSSL_CONF_CTX* cctx, const char* value)
|
|
{
|
|
int ret = -3;
|
|
|
|
WOLFSSL_ENTER("cmdfunc_key");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return WOLFSSL_FAILURE;
|
|
|
|
if (value == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
|
|
WOLFSSL_MSG("certificate flag is not set");
|
|
return -2;
|
|
}
|
|
|
|
if (cctx->ctx) {
|
|
ret = wolfSSL_CTX_use_PrivateKey_file(cctx->ctx, value,
|
|
WOLFSSL_FILETYPE_PEM);
|
|
}
|
|
|
|
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
|
|
(!cctx->ctx && ret == -3)) &&
|
|
cctx->ssl) {
|
|
ret = wolfSSL_use_PrivateKey_file(cctx->ssl, value,
|
|
WOLFSSL_FILETYPE_PEM);
|
|
}
|
|
|
|
WOLFSSL_LEAVE("cmdfunc_key", ret);
|
|
return ret;
|
|
}
|
|
#endif /* NO_FILESYSTEM */
|
|
/**
|
|
* process DH parameter command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param value arguments for cmd
|
|
* @return WOLFSSL_SUCCESS on success,
|
|
* otherwise WOLFSSL_FAILURE or
|
|
* -3 if value is null or
|
|
* negative value on other failure
|
|
*/
|
|
#if !defined(NO_DH) && !defined(NO_BIO)
|
|
static int cmdfunc_dhparam(WOLFSSL_CONF_CTX* cctx, const char* value)
|
|
{
|
|
int ret = -3;
|
|
WOLFSSL_DH* dh = NULL;
|
|
WOLFSSL_BIO* bio = NULL;
|
|
|
|
WOLFSSL_MSG("cmdfunc_dhparam");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL)
|
|
return WOLFSSL_FAILURE;
|
|
|
|
if (value == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
if (cctx->ctx || cctx->ssl) {
|
|
bio = wolfSSL_BIO_new_file(value, "rb");
|
|
if (!bio) {
|
|
WOLFSSL_MSG("bio new file failed");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
|
if (!dh) {
|
|
wolfSSL_BIO_free(bio);
|
|
WOLFSSL_MSG("PEM read bio failed");
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
|
|
if (cctx->ctx) {
|
|
ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ctx, dh);
|
|
}
|
|
|
|
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
|
|
(!cctx->ctx && ret == -3)) &&
|
|
cctx->ssl) {
|
|
ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ssl->ctx, dh);
|
|
}
|
|
|
|
if (dh)
|
|
wolfSSL_DH_free(dh);
|
|
if (bio)
|
|
wolfSSL_BIO_free(bio);
|
|
|
|
WOLFSSL_LEAVE("cmdfunc_dhparam", ret);
|
|
return ret;
|
|
}
|
|
#endif /* !NO_DH && !NO_BIO */
|
|
/**
|
|
* command table
|
|
*/
|
|
typedef struct conf_cmd_tbl {
|
|
const char* file_cmd;
|
|
const char* cmdline_cmd;
|
|
word32 data_type;
|
|
int (*cmdfunc)(WOLFSSL_CONF_CTX* cctx, const char* value);
|
|
}conf_cmd_tbl;
|
|
|
|
static const conf_cmd_tbl conf_cmds_tbl[] = {
|
|
#if defined(HAVE_ECC)
|
|
/* cmd Curves */
|
|
{WOLFSSL_CONF_FILE_CMD1, WOLFSSL_CONF_CMDL_CMD1,
|
|
WOLFSSL_CONF_TYPE_STRING, cmdfunc_curves},
|
|
#endif
|
|
#if !defined(NO_FILESYSTEM)
|
|
/* cmd Certificate */
|
|
{WOLFSSL_CONF_FILE_CMD2, WOLFSSL_CONF_CMDL_CMD2,
|
|
WOLFSSL_CONF_TYPE_FILE, cmdfunc_cert},
|
|
/* cmd PrivateKey */
|
|
{WOLFSSL_CONF_FILE_CMD3, WOLFSSL_CONF_CMDL_CMD3,
|
|
WOLFSSL_CONF_TYPE_FILE, cmdfunc_key},
|
|
#endif
|
|
/* cmd Protocol */
|
|
{WOLFSSL_CONF_FILE_CMD4, WOLFSSL_CONF_CMDL_CMD4,
|
|
WOLFSSL_CONF_TYPE_STRING, NULL},
|
|
/* cmd Options */
|
|
{WOLFSSL_CONF_FILE_CMD5, WOLFSSL_CONF_CMDL_CMD5,
|
|
WOLFSSL_CONF_TYPE_STRING, NULL},
|
|
/* cmd ServerInfoFile */
|
|
{WOLFSSL_CONF_FILE_CMD6, WOLFSSL_CONF_CMDL_CMD6,
|
|
WOLFSSL_CONF_TYPE_FILE, NULL},
|
|
/* cmd SignatureAlgorithms */
|
|
{WOLFSSL_CONF_FILE_CMD7, WOLFSSL_CONF_CMDL_CMD7,
|
|
WOLFSSL_CONF_TYPE_STRING, NULL},
|
|
/* cmd ClientSignatureAlgorithms */
|
|
{WOLFSSL_CONF_FILE_CMD8, WOLFSSL_CONF_CMDL_CMD8,
|
|
WOLFSSL_CONF_TYPE_STRING, NULL},
|
|
/* cmd CipherString */
|
|
{WOLFSSL_CONF_FILE_CMD9, WOLFSSL_CONF_CMDL_CMD9,
|
|
WOLFSSL_CONF_TYPE_STRING, cmdfunc_cipherstring},
|
|
#if !defined(NO_DH) && !defined(NO_BIO)
|
|
/* cmd DHParameters */
|
|
{WOLFSSL_CONF_FILE_CMD10, WOLFSSL_CONF_CMDL_CMD10,
|
|
WOLFSSL_CONF_TYPE_FILE, cmdfunc_dhparam},
|
|
#endif
|
|
#ifdef HAVE_ECC
|
|
/* cmd ECHDParameters */
|
|
{WOLFSSL_CONF_FILE_CMD11, WOLFSSL_CONF_CMDL_CMD11,
|
|
WOLFSSL_CONF_TYPE_STRING, NULL},
|
|
#endif
|
|
};
|
|
/* size of command table */
|
|
static const size_t size_of_cmd_tbls = sizeof(conf_cmds_tbl)
|
|
/ sizeof(conf_cmd_tbl);
|
|
|
|
static const conf_cmd_tbl* wolfssl_conf_find_cmd(WOLFSSL_CONF_CTX* cctx,
|
|
const char* cmd)
|
|
{
|
|
size_t i = 0;
|
|
|
|
if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
|
|
size_t cmdlen = XSTRLEN(cmd);
|
|
|
|
if (cmdlen < 2) {
|
|
WOLFSSL_MSG("bad cmdline command");
|
|
return NULL;
|
|
}
|
|
/* skip "-" prefix */
|
|
++cmd;
|
|
}
|
|
|
|
for (i = 0; i < size_of_cmd_tbls; i++) {
|
|
/* check if the cmd is valid */
|
|
if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
|
|
if (conf_cmds_tbl[i].cmdline_cmd != NULL &&
|
|
XSTRCMP(cmd, conf_cmds_tbl[i].cmdline_cmd) == 0) {
|
|
return &conf_cmds_tbl[i];
|
|
}
|
|
}
|
|
|
|
if (cctx->flags & WOLFSSL_CONF_FLAG_FILE) {
|
|
if (conf_cmds_tbl[i].file_cmd != NULL &&
|
|
XSTRCMP(cmd, conf_cmds_tbl[i].file_cmd) == 0) {
|
|
return &conf_cmds_tbl[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* send configuration command
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param cmd configuration command
|
|
* @param value arguments for cmd
|
|
* @return 1 when cmd is recognised, but value is not used
|
|
* 2 both cmd and value are used
|
|
* otherwise WOLFSSL_FAILURE
|
|
* -2 if cmd is not recognised
|
|
* -3 if value is NULL, but cmd is recognized
|
|
*/
|
|
int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
|
|
{
|
|
int ret = WOLFSSL_FAILURE;
|
|
const conf_cmd_tbl* confcmd = NULL;
|
|
WOLFSSL_ENTER("wolfSSL_CONF_cmd");
|
|
|
|
/* sanity check */
|
|
if (cctx == NULL || cmd == NULL) {
|
|
WOLFSSL_MSG("bad arguments");
|
|
return ret;
|
|
}
|
|
|
|
confcmd = wolfssl_conf_find_cmd(cctx, cmd);
|
|
if (confcmd == NULL)
|
|
return -2;
|
|
|
|
if (confcmd->cmdfunc == NULL) {
|
|
WOLFSSL_MSG("cmd not yet implemented");
|
|
return -2;
|
|
}
|
|
|
|
ret = confcmd->cmdfunc(cctx, value);
|
|
|
|
/* return code compliant with OpenSSL */
|
|
if (ret < -3)
|
|
ret = 0;
|
|
|
|
WOLFSSL_LEAVE("wolfSSL_CONF_cmd", ret);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
|
|
* @param cmd configuration command
|
|
* @return The SSL_CONF_TYPE_* type or SSL_CONF_TYPE_UNKNOWN if an
|
|
* invalid command
|
|
*/
|
|
int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd)
|
|
{
|
|
const conf_cmd_tbl* confcmd = NULL;
|
|
WOLFSSL_ENTER("wolfSSL_CONF_cmd_value_type");
|
|
|
|
confcmd = wolfssl_conf_find_cmd(cctx, cmd);
|
|
if (confcmd == NULL)
|
|
return SSL_CONF_TYPE_UNKNOWN;
|
|
return (int)confcmd->data_type;
|
|
}
|
|
|
|
#endif /* OPENSSL_EXTRA */
|
|
|
|
|
|
/*******************************************************************************
|
|
* END OF CONF API
|
|
******************************************************************************/
|
|
|
|
#endif /* WOLFSSL_CONF_INCLUDED */
|