Skip to content

Commit

Permalink
OpenSSL: Add in support for configuring an alternative TLS ENGINE
Browse files Browse the repository at this point in the history
Two new functions added

coap_tls_engine_configure()
coap_tls_engine_remove()

Added in new PKI key type coap_pki_key_define_t which allows the CA, Public Cert
and Private Key to be different types (e.g. PEM, DER etc.).

Added a new key type ENGINE to make use of the configured tls_engine.

Added in a -q option to coap-server and coap-client for testing ENGINE.

Note: ENGINE is only supported by OpenSSL.
  • Loading branch information
mrdeep1 committed May 6, 2024
1 parent 4664633 commit 9f9129c
Show file tree
Hide file tree
Showing 22 changed files with 1,998 additions and 753 deletions.
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@ man/coap-client.txt
man/coap-oscore-conf.txt
man/coap-server.txt
man/coap-rd.txt
man/coap-tls-engine-conf.txt
man/Makefile
tests/test_common.h
tests/Makefile
Expand Down
58 changes: 51 additions & 7 deletions examples/coap-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ int doing_observe = 0;

static coap_oscore_conf_t *oscore_conf = NULL;
static int doing_oscore = 0;
static int doing_tls_engine = 0;
static char *tls_engine_conf = NULL;

static int quit = 0;

Expand Down Expand Up @@ -502,8 +504,8 @@ usage(const char *program, const char *version) {
fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer)));
fprintf(stderr, "\n"
"Usage: %s [-a addr] [-b [num,]size] [-e text] [-f file] [-l loss]\n"
"\t\t[-m method] [-o file] [-p port] [-r] [-s duration] [-t type]\n"
"\t\t[-v num] [-w] [-A type] [-B seconds]\n"
"\t\t[-m method] [-o file] [-p port] [-q tls_engine_conf_file] [-r]\n"
"\t\t[-s duration] [-t type] [-v num] [-w] [-A type] [-B seconds]\n"
"\t\t[-E oscore_conf_file[,seq_file]] [-G count] [-H hoplimit]\n"
"\t\t[-K interval] [-N] [-O num,text] [-P scheme://address[:port]\n"
"\t\t[-T token] [-U] [-V num] [-X size]\n"
Expand All @@ -530,7 +532,9 @@ usage(const char *program, const char *version) {
"\t \t\tdefault is 'get'\n"
"\t-o file\t\tOutput received data to this file (use '-' for STDOUT)\n"
"\t-p port\t\tSend from the specified port\n"
"\t-r \t\tUse reliable protocol (TCP or TLS); requires TCP support\n"
"\t-q tls_engine_conf_file\n"
"\t \t\ttls_engine_conf_file contains TLS ENGINE configuration.\n"
"\t \t\tSee coap-tls-engine-conf(5) for definitions.\n"
"\t-s duration\tSubscribe to / Observe resource for given duration\n"
"\t \t\tin seconds\n"
"\t-t type\t\tContent format for given resource for PUT/POST\n"
Expand Down Expand Up @@ -817,6 +821,28 @@ cmdline_oscore(char *arg) {
return 0;
}

static int
cmdline_tls_engine(char *arg) {
uint8_t *buf;
size_t length;
coap_str_const_t file_mem;

/* Need a rw var to free off later and file_mem.s is a const */
buf = read_file_mem(arg, &length);
if (buf == NULL) {
fprintf(stderr, "Openssl ENGINE configuration file error: %s\n", arg);
return 0;
}
file_mem.s = buf;
file_mem.length = length;
if (!coap_tls_engine_configure(&file_mem)) {
coap_free(buf);
return 0;
}
coap_free(buf);
return 1;
}

/**
* Sets global URI options according to the URI passed as @p arg.
* This function returns 0 on success or -1 on error.
Expand Down Expand Up @@ -1377,9 +1403,18 @@ setup_pki(coap_context_t *ctx) {
memcpy(client_sni, "localhost", 9);

dtls_pki.client_sni = client_sni;
if ((key_file && strncasecmp(key_file, "pkcs11:", 7) == 0) ||
(cert_file && strncasecmp(cert_file, "pkcs11:", 7) == 0) ||
(ca_file && strncasecmp(ca_file, "pkcs11:", 7) == 0)) {
if (doing_tls_engine) {
dtls_pki.pki_key.key_type = COAP_PKI_KEY_DEFINE;
dtls_pki.pki_key.key.define.public_cert.s_byte = cert_file;
dtls_pki.pki_key.key.define.private_key.s_byte = key_file ? key_file : cert_file;
dtls_pki.pki_key.key.define.ca.s_byte = ca_file;
dtls_pki.pki_key.key.define.public_cert_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_pki.pki_key.key.define.private_key_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_pki.pki_key.key.define.ca_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_pki.pki_key.key.define.user_pin = pkcs11_pin;
} else if ((key_file && strncasecmp(key_file, "pkcs11:", 7) == 0) ||
(cert_file && strncasecmp(cert_file, "pkcs11:", 7) == 0) ||
(ca_file && strncasecmp(ca_file, "pkcs11:", 7) == 0)) {
dtls_pki.pki_key.key_type = COAP_PKI_KEY_PKCS11;
dtls_pki.pki_key.key.pkcs11.public_cert = cert_file;
dtls_pki.pki_key.key.pkcs11.private_key = key_file ?
Expand Down Expand Up @@ -1619,7 +1654,7 @@ main(int argc, char **argv) {
coap_startup();

while ((opt = getopt(argc, argv,
"a:b:c:e:f:h:j:k:l:m:no:p:rs:t:u:v:wA:B:C:E:G:H:J:K:L:M:NO:P:R:T:UV:X:")) != -1) {
"a:b:c:e:f:h:j:k:l:m:no:p:q:rs:t:u:v:wA:B:C:E:G:H:J:K:L:M:NO:P:R:T:UV:X:")) != -1) {
switch (opt) {
case 'a':
strncpy(node_str, optarg, NI_MAXHOST - 1);
Expand Down Expand Up @@ -1768,6 +1803,10 @@ main(int argc, char **argv) {
goto failed;
}
break;
case 'q':
tls_engine_conf = optarg;
doing_tls_engine = 1;
break;
default:
usage(argv[0], LIBCOAP_PACKAGE_VERSION);
goto failed;
Expand Down Expand Up @@ -1835,6 +1874,11 @@ main(int argc, char **argv) {
goto failed;
}

if (doing_tls_engine) {
if (!cmdline_tls_engine(tls_engine_conf))
goto failed;
}

if (doing_oscore) {
if (get_oscore_conf() == NULL)
goto failed;
Expand Down
55 changes: 50 additions & 5 deletions examples/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ strndup(const char *s1, size_t n) {

static coap_oscore_conf_t *oscore_conf;
static int doing_oscore = 0;
static int doing_tls_engine = 0;
static char *tls_engine_conf = NULL;

/* set to 1 to request clean server shutdown */
static int quit = 0;
Expand Down Expand Up @@ -1860,9 +1862,18 @@ static void
update_pki_key(coap_dtls_key_t *dtls_key, const char *key_name,
const char *cert_name, const char *ca_name) {
memset(dtls_key, 0, sizeof(*dtls_key));
if ((key_name && strncasecmp(key_name, "pkcs11:", 7) == 0) ||
(cert_name && strncasecmp(cert_name, "pkcs11:", 7) == 0) ||
(ca_name && strncasecmp(ca_name, "pkcs11:", 7) == 0)) {
if (doing_tls_engine) {
dtls_key->key_type = COAP_PKI_KEY_DEFINE;
dtls_key->key.define.public_cert.s_byte = cert_file;
dtls_key->key.define.private_key.s_byte = key_file ? key_file : cert_file;
dtls_key->key.define.ca.s_byte = ca_file;
dtls_key->key.define.public_cert_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_key->key.define.private_key_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_key->key.define.ca_def = COAP_PKI_KEY_DEF_ENGINE;
dtls_key->key.define.user_pin = pkcs11_pin;
} else if ((key_name && strncasecmp(key_name, "pkcs11:", 7) == 0) ||
(cert_name && strncasecmp(cert_name, "pkcs11:", 7) == 0) ||
(ca_name && strncasecmp(ca_name, "pkcs11:", 7) == 0)) {
dtls_key->key_type = COAP_PKI_KEY_PKCS11;
dtls_key->key.pkcs11.public_cert = cert_name;
dtls_key->key.pkcs11.private_key = key_name ? key_name : cert_name;
Expand Down Expand Up @@ -2125,7 +2136,8 @@ usage(const char *program, const char *version) {
fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer)));
fprintf(stderr, "\n"
"Usage: %s [-a priority] [-b max_block_size] [-d max] [-e] [-g group]\n"
"\t\t[-l loss] [-p port] [-r] [-v num] [-w [port][,secure_port]]\n"
"\t\t[-l loss] [-p port] [-q tls_engine_conf_file] [-r] [-v num]\n"
"\t\t[-w [port][,secure_port]]\n"
"\t\t[-A address] [-E oscore_conf_file[,seq_file]] [-G group_if]\n"
"\t\t[-L value] [-N] [-P scheme://address[:port],[name1[,name2..]]]\n"
"\t\t[-T max_token_size] [-U type] [-V num] [-X size]\n"
Expand Down Expand Up @@ -2154,6 +2166,9 @@ usage(const char *program, const char *version) {
"\t-p port\t\tListen on specified port for UDP and TCP. If (D)TLS is\n"
"\t \t\tenabled, then the coap-server will also listen on\n"
"\t \t\t'port'+1 for DTLS and TLS. The default port is 5683\n"
"\t-q tls_engine_conf_file\n"
"\t \t\ttls_engine_conf_file contains TLS ENGINE configuration.\n"
"\t \t\tSee coap-tls-engine-conf(5) for definitions.\n"
"\t-r \t\tEnable multicast per resource support. If enabled,\n"
"\t \t\tonly '/', '/async' and '/.well-known/core' are enabled\n"
"\t \t\tfor multicast requests support, otherwise all\n"
Expand Down Expand Up @@ -2473,6 +2488,28 @@ cmdline_oscore(char *arg) {
return 0;
}

static int
cmdline_tls_engine(char *arg) {
uint8_t *buf;
size_t length;
coap_str_const_t file_mem;

/* Need a rw var to free off later and file_mem.s is a const */
buf = read_file_mem(arg, &length);
if (buf == NULL) {
fprintf(stderr, "Openssl ENGINE configuration file error: %s\n", arg);
return 0;
}
file_mem.s = buf;
file_mem.length = length;
if (!coap_tls_engine_configure(&file_mem)) {
coap_free(buf);
return 0;
}
coap_free(buf);
return 1;
}

static ssize_t
cmdline_read_key(char *arg, unsigned char **buf, size_t maxlen) {
size_t len = strnlen(arg, maxlen);
Expand Down Expand Up @@ -2758,7 +2795,7 @@ main(int argc, char **argv) {
clock_offset = time(NULL);

while ((opt = getopt(argc, argv,
"a:b:c:d:eg:G:h:i:j:J:k:l:mnp:rs:tu:v:w:A:C:E:L:M:NP:R:S:T:U:V:X:")) != -1) {
"a:b:c:d:eg:h:i:j:k:l:mnp:q:rs:tu:v:w:A:C:E:G:J:L:M:NP:R:S:T:U:V:X:")) != -1) {
switch (opt) {
#ifndef _WIN32
case 'a':
Expand Down Expand Up @@ -2866,6 +2903,10 @@ main(int argc, char **argv) {
goto failed;
#endif /* ! SERVER_CAN_PROXY */
break;
case 'q':
tls_engine_conf = optarg;
doing_tls_engine = 1;
break;
case 'r' :
mcast_per_resource = 1;
break;
Expand Down Expand Up @@ -2963,6 +3004,10 @@ main(int argc, char **argv) {
coap_context_set_max_block_size(ctx, max_block_size);
if (csm_max_message_size)
coap_context_set_csm_max_message_size(ctx, csm_max_message_size);
if (doing_tls_engine) {
if (!cmdline_tls_engine(tls_engine_conf))
goto failed;
}
if (doing_oscore) {
if (get_oscore_conf(ctx) == NULL)
goto failed;
Expand Down
65 changes: 64 additions & 1 deletion include/coap3/coap_dtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@ int coap_dtls_pkcs11_is_supported(void);
*/
int coap_dtls_rpk_is_supported(void);

/**
* Configure an ENGINE for a TLS library.
* (Currently only OpenSSL is supported)
*
* @param conf_mem The configuration to use in memory.
*
* @return @c 1 if successful, or @c 0 if failure.
*/
int coap_tls_engine_configure(coap_str_const_t *conf_mem);

/**
* Remove a previously configured ENGINE from a TLS library.
* (Currently only OpenSSL is supported)
* (This is automatically done when coap_free_context() is called)
*
* @return @c 1 if successful, or @c 0 if failure.
*/
int coap_tls_engine_remove(void);

typedef enum coap_tls_library_t {
COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */
COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */
Expand Down Expand Up @@ -192,6 +211,7 @@ typedef enum coap_pki_key_t {
COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) buffer */
COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */
COAP_PKI_KEY_PKCS11, /**< The PKI key type is PKCS11 (DER) */
COAP_PKI_KEY_DEFINE, /**< The individual PKI key types are Definable */
} coap_pki_key_t;

/**
Expand Down Expand Up @@ -249,6 +269,49 @@ typedef struct coap_pki_key_pkcs11_t {
pkcs11: URI as a query. */
} coap_pki_key_pkcs11_t;

/**
* The enum to define the format of the key parameter definition.
*/
typedef enum {
COAP_PKI_KEY_DEF_PEM = 0, /**< The PKI key type is PEM file.
Length ignored, NULL terminated. */
COAP_PKI_KEY_DEF_PEM_BUF, /**< The PKI key type is PEM buffer.
Length required. */
COAP_PKI_KEY_DEF_RPK_BUF, /**< The PKI key type is RPK in buffer.
Length required. */
COAP_PKI_KEY_DEF_DER, /**< The PKI key type is DER file.
Length ignored, NULL terminated. */
COAP_PKI_KEY_DEF_ASN1, /**< The PKI key type is ASN.1 (DER) buffer.
Length required.
Private Key Type required. */
COAP_PKI_KEY_DEF_PKCS11, /**< The PKI key type is PKCS11 (pkcs11:...).
Length ignored, NULL terminated.
User Pin optional. */
COAP_PKI_KEY_DEF_ENGINE, /**< The PKI key type is to be passed to ENGINE.
Length ignored, NULL terminated.
Supported by OpenSSL only */
} coap_pki_define_t;

/**
* The structure that holds the PKI Definable key type definitions.
*/
typedef struct coap_pki_key_define_t {
coap_const_char_ptr_t ca; /**< define: Common CA Certificate */
coap_const_char_ptr_t public_cert; /**< define: Public Cert */
coap_const_char_ptr_t private_key; /**< define: Private Key */
size_t ca_len; /**< define CA Cert length (if needed)*/
size_t public_cert_len; /**< define Public Cert length (if needed)*/
size_t private_key_len; /**< define Private Key length (if needed)*/
coap_pki_define_t ca_def; /**< define: Common CA type definition*/
coap_pki_define_t public_cert_def; /**< define: Public Cert type definition*/
coap_pki_define_t private_key_def; /**< define: Private Key type definition*/
coap_asn1_privatekey_type_t private_key_type; /**< define: ASN1 Private Key
Type (if needed) */
const char *user_pin; /**< define: User pin to access type PKCS11.
If PKCS11 and NULL, then pin-value= parameter
must be set in pkcs11: URI as a query. */
} coap_pki_key_define_t;

/**
* The structure that holds the PKI key information.
*/
Expand All @@ -259,6 +322,7 @@ typedef struct coap_dtls_key_t {
coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */
coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) memory keys */
coap_pki_key_pkcs11_t pkcs11; /**< for PKCS11 keys */
coap_pki_key_define_t define; /**< for definable type keys */
} key;
} coap_dtls_key_t;

Expand Down Expand Up @@ -498,7 +562,6 @@ typedef struct coap_dtls_spsk_t {
coap_dtls_spsk_info_t psk_info; /**< Server PSK definition */
} coap_dtls_spsk_t;


/** @} */

#endif /* COAP_DTLS_H */
36 changes: 36 additions & 0 deletions include/coap3/coap_dtls_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@
#define COAP_DTLS_CID_LENGTH 6
#endif

typedef enum {
COAP_DEFINE_KEY_CA,
COAP_DEFINE_KEY_PUBLIC,
COAP_DEFINE_KEY_PRIVATE
} coap_define_issue_key_t;

typedef enum {
COAP_DEFINE_FAIL_BAD,
COAP_DEFINE_FAIL_NOT_SUPPORTED,
COAP_DEFINE_FAIL_NONE
} coap_define_issue_fail_t;

/**
* Creates a new DTLS context for the given @p coap_context. This function
* returns a pointer to a new DTLS context object or @c NULL on error.
Expand Down Expand Up @@ -442,6 +454,30 @@ void coap_dtls_shutdown(void);
void *coap_dtls_get_tls(const coap_session_t *session,
coap_tls_library_t *tls_lib);

/**
* Map the PKI key definitions to the new DEFINE format.
*
* @param setup_data The PKI definition.
* @param key Updated with the DEFINE format of the key definitions.
*
*/
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data,
coap_dtls_key_t *key);

/**
* Report PKI DEFINE type issue
*
* @param type The type of key with the issue.
* @param fail Why the key is failing
* @param key The key with the issue.
* @param role Whether this is for the CLient or Server.
*
* @return @c 0 as there is a failure.
*/
int coap_dtls_define_issue(coap_define_issue_key_t type,
coap_define_issue_fail_t fail,
coap_dtls_key_t *key,
const coap_dtls_role_t role);
/** @} */

#endif /* COAP_DTLS_INTERNAL_H */
8 changes: 8 additions & 0 deletions include/coap3/coap_str.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ typedef struct coap_bin_const_t {
const uint8_t *s; /**< read-only binary data */
} coap_bin_const_t;

/**
* CoAP union for handling signed / unsigned chars
*/
typedef union {
const char *s_byte; /**< signed char ptr */
const uint8_t *u_byte; /**< unsigned char ptr */
} coap_const_char_ptr_t;

/**
* Returns a new string object with at least size+1 bytes storage allocated.
* It is the responsibility of the caller to fill in all the appropriate
Expand Down
Loading

0 comments on commit 9f9129c

Please sign in to comment.