Skip to content

Commit

Permalink
PKI: Make (D)TLS operation consistent across all TLS libraries
Browse files Browse the repository at this point in the history
The use of the verify_peer_cert and require_peer_cert variables in the
coap_dtls_pki_t structure was giving inconsistent results across all the
TLS libraries.  This primarily was down to the large numbers of options
available to control the TLS handshakes in OpenSSL compared to the limited
control available to MbedTLS port which followed later. require_peer_cert is
not easy to control in MbedTLS as it is an implicit configuration based on how
other, not always related, items were configured.

require_peer_cert was used by the server to control whether the client could
use anonymous certificates or not.  This is now controlled by verify_peer_cert.

require_peer_cert variable has been replaced with check_common_ca, so that
the OpenSSL functionality can continue, but enable GnuTLS / MbedTLS to
produce the same results.  This allows peers to mutually authenticate (because
the peer certs are signed by the same common CA) or not which was in effect
controlled by verify_peer_cert previously.

examples/client.c:
examples/coap-rd.c:
examples/coap-server.c:

Add in -n (unset verify_peer_cert) and -z (unset check_common_ca) options. In
the case of coap-server, make -n refer to verify_peer_cert.

include/coap2/coap_dtls.h:
include/coap2/net.h:

Update with variable changes, and make the coap_dtls_pki_t parameter const for
the *_context_set_pki() functions.

man/coap-client.txt.in:
man/coap-rd.txt.in:
man/coap-server.txt.in:

Update documentation to reflect the examples option usage.

man/coap_context.txt.in:
man/coap_encryption.txt.in:
man/coap_session.txt.in:

Update with the new variable name and document as appropriate.

src/coap_gnutls.c
src/coap_mbedtls.c
src/coap_notls.c
src/coap_openssl.c
coap_tinydtls.c

Update to make variable usage consistent. Update logging from LOG_WARNING to
LOG_INFO where there is an override of a PKI check failure by one of the
coap_dtls_pki_t variables.

src/coap_io.c:

Update logging from LOG_WARNING to LOG_INFO for EPIPE or ECONNRESET errors in
coap_socket_write().

src/net.c:

Handle the const coap_dtls_pki_t parameter in coap_context_set_pki() function.
  • Loading branch information
mrdeep1 committed Oct 28, 2020
1 parent db4c9da commit 2d8fe86
Show file tree
Hide file tree
Showing 18 changed files with 303 additions and 123 deletions.
20 changes: 16 additions & 4 deletions examples/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ static uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */
static uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */
static size_t cert_mem_len = 0;
static size_t ca_mem_len = 0;
static int check_common_ca = 1; /* PKI granularity - by default set */
static int verify_peer_cert = 1; /* PKI granularity - by default set */

typedef struct ih_def_t {
char* hint_match;
Expand Down Expand Up @@ -652,7 +654,7 @@ usage( const char *program, const char *version) {
"\t\t[-v num] [-A type] [-B seconds] [-H hoplimit] [-K interval] [-N]\n"
"\t\t[-O num,text] [-P addr[:port]] [-T token] [-U]\n"
"\t\t[[-h match_hint_file] [-k key] [-u user]]\n"
"\t\t[[-c certfile] [-j keyfile] [-C cafile] [-J pkcs11_pin]\n"
"\t\t[[-c certfile] [-j keyfile] [-n] [-z] [-C cafile] [-J pkcs11_pin]\n"
"\t\t[-M raw_pk] [-R root_cafile] [-S match_pki_sni_file]] URI\n"
"\tURI can be an absolute URI or a URI prefixed with scheme and host\n\n"
"General Options\n"
Expand Down Expand Up @@ -719,6 +721,9 @@ usage( const char *program, const char *version) {
"\t-j keyfile\tPEM file or PKCS11 URI for the private key for the\n"
"\t \t\tnertificate in '-c certfile' if the parameter is different\n"
"\t \t\tfrom certfile in '-c certfile'\n"
"\t-n \t\tDisable remote peer certificate checking\n"
"\t-z \t\tDisable checking that local and peer certs share a common\n"
"\t \t\tCA (used for mutual authentication)\n"
"\t-C cafile\tPEM file or PKCS11 URI for the CA Certificate that was\n"
"\t \t\tused to sign the certfile. This will trigger\n"
"\t \t\tthe validation of the server certificate. If certfile is\n"
Expand Down Expand Up @@ -1418,8 +1423,8 @@ setup_pki(coap_context_t *ctx) {
* coap_context_set_pki_root_cas(), but this is used to define what
* checking actually takes place.
*/
dtls_pki.verify_peer_cert = !is_rpk_not_cert;
dtls_pki.require_peer_cert = 1;
dtls_pki.verify_peer_cert = verify_peer_cert;
dtls_pki.check_common_ca = check_common_ca;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand Down Expand Up @@ -1617,7 +1622,7 @@ main(int argc, char **argv) {
struct sigaction sa;
#endif

while ((opt = getopt(argc, argv, "a:b:c:e:f:h:j:k:l:m:o:p:rs:t:u:v:A:B:C:J:K:H:M:NO:P:R:T:U")) != -1) {
while ((opt = getopt(argc, argv, "a:b:c:e:f:h:j:k:l:m:no:p:rs:t:u:v:zA:B:C:J:K:H:M:NO:P:R:T:U")) != -1) {
switch (opt) {
case 'a':
strncpy(node_str, optarg, NI_MAXHOST - 1);
Expand Down Expand Up @@ -1689,6 +1694,7 @@ main(int argc, char **argv) {
case 'M':
cert_file = optarg;
is_rpk_not_cert = 1;
verify_peer_cert = 0; /* This does not work for RPK */
break;
case 'O':
cmdline_option(optarg);
Expand Down Expand Up @@ -1735,6 +1741,12 @@ main(int argc, char **argv) {
if (!cmdline_hop_limit(optarg))
fprintf(stderr, "Hop Limit has to be > 0 and < 256\n");
break;
case 'n':
verify_peer_cert = 0;
break;
case 'z':
check_common_ca = 0;
break;
default:
usage( argv[0], LIBCOAP_PACKAGE_VERSION );
exit( 1 );
Expand Down
14 changes: 9 additions & 5 deletions examples/coap-rd.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
static char *cert_file = NULL; /* Combined certificate and private key in PEM */
static char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM */
static char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */
static int require_peer_cert = 1; /* By default require peer cert */
static int check_common_ca = 1; /* PKI granularity - by default set */
static int verify_peer_cert = 1; /* PKI granularity - by default set */
#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */
static uint8_t key[MAX_KEY];
static ssize_t key_length = 0;
Expand Down Expand Up @@ -647,8 +648,8 @@ fill_keystore(coap_context_t *ctx) {
* This list of enabled can be tuned for the specific
* requirements - see 'man coap_encryption'.
*/
dtls_pki.verify_peer_cert = 1;
dtls_pki.require_peer_cert = require_peer_cert;
dtls_pki.verify_peer_cert = verify_peer_cert;
dtls_pki.check_common_ca = check_common_ca;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand Down Expand Up @@ -782,7 +783,7 @@ main(int argc, char **argv) {
struct sigaction sa;
#endif

while ((opt = getopt(argc, argv, "A:c:C:g:h:k:n:R:p:v:")) != -1) {
while ((opt = getopt(argc, argv, "A:c:C:g:h:k:n:R:p:v:z")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -813,7 +814,7 @@ main(int argc, char **argv) {
key_defined = 1;
break;
case 'n':
require_peer_cert = 0;
verify_peer_cert = 0;
break;
case 'R' :
root_ca_file = optarg;
Expand All @@ -825,6 +826,9 @@ main(int argc, char **argv) {
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
case 'z':
check_common_ca = 0;
break;
default:
usage( argv[0], LIBCOAP_PACKAGE_VERSION );
exit( 1 );
Expand Down
25 changes: 17 additions & 8 deletions examples/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ static uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */
static uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */
static size_t cert_mem_len = 0;
static size_t ca_mem_len = 0;
static int require_peer_cert = 1; /* By default require peer cert */
static int check_common_ca = 1; /* PKI granularity - by default set */
static int verify_peer_cert = 1; /* PKI granularity - by default set */
#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */
static uint8_t key[MAX_KEY];
static ssize_t key_length = 0;
Expand Down Expand Up @@ -1181,7 +1182,8 @@ fill_keystore(coap_context_t *ctx) {
* This list of enabled can be tuned for the specific
* requirements - see 'man coap_encryption'.
*/
dtls_pki.verify_peer_cert = !is_rpk_not_cert;
dtls_pki.verify_peer_cert = verify_peer_cert;
dtls_pki.check_common_ca = check_common_ca;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand All @@ -1194,7 +1196,6 @@ fill_keystore(coap_context_t *ctx) {
dtls_pki.validate_sni_call_back = verify_pki_sni_callback;
dtls_pki.sni_call_back_arg = NULL;
}
dtls_pki.require_peer_cert = require_peer_cert;
dtls_pki.is_rpk_not_cert = is_rpk_not_cert;
if ((key_file && strncasecmp (key_file, "pkcs11:", 7) == 0) ||
(cert_file && strncasecmp (cert_file, "pkcs11:", 7) == 0) ||
Expand Down Expand Up @@ -1272,8 +1273,9 @@ usage( const char *program, const char *version) {
"\t\t[-A address] [-N]\n"
"\t\t[[-h hint] [-i match_identity_file] [-k key]\n"
"\t\t[-s match_psk_sni_file]]\n"
"\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-C cafile] [-J pkcs11_pin]\n"
"\t\t[-M rpk_file] [-R root_cafile] [-S match_pki_sni_file]]\n"
"\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-z] [-C cafile]\n"
"\t\t[-J pkcs11_pin] [-M rpk_file] [-R root_cafile]\n"
"\t\t[-S match_pki_sni_file]]\n"
"General Options\n"
"\t-d max \t\tAllow dynamic creation of up to a total of max\n"
"\t \t\tresources. If max is reached, a 4.06 code is returned\n"
Expand Down Expand Up @@ -1334,7 +1336,10 @@ usage( const char *program, const char *version) {
"\t-m \t\tUse COAP_PKI_KEY_PEM_BUF instead of COAP_PKI_KEY_PEM i/f\n"
"\t \t\tby reading into memory the Cert / CA file (for testing)\n"
"\t-n \t\tDisable the requirement for clients to have defined\n"
"\t \t\tclient certificates\n"
"\t \t\tclient certificates.\n"
"\t \t\tDisable remote peer certificate checking\n"
"\t-z \t\tDisable checking that local and peer certs share a common\n"
"\t \t\tCA (used for mutual authentication)\n"
"\t-C cafile\tPEM file or PKCS11 URI for the CA certificate that was\n"
"\t \t\tused to sign the certfile. If defined, then the client\n"
"\t \t\twill be given this CA certificate during the TLS set up.\n"
Expand Down Expand Up @@ -1644,7 +1649,7 @@ main(int argc, char **argv) {

clock_offset = time(NULL);

while ((opt = getopt(argc, argv, "c:d:g:h:i:j:J:k:l:mnp:s:v:A:C:M:NR:S:")) != -1) {
while ((opt = getopt(argc, argv, "c:d:g:h:i:j:J:k:l:mnp:s:v:zA:C:M:NR:S:")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -1701,9 +1706,10 @@ main(int argc, char **argv) {
case 'M':
cert_file = optarg;
is_rpk_not_cert = 1;
verify_peer_cert = 0; /* This does not work for RPK */
break;
case 'n':
require_peer_cert = 0;
verify_peer_cert = 0;
break;
case 'N':
resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_NON;
Expand All @@ -1730,6 +1736,9 @@ main(int argc, char **argv) {
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
case 'z':
check_common_ca = 0;
break;
default:
usage( argv[0], LIBCOAP_PACKAGE_VERSION );
exit( 1 );
Expand Down
7 changes: 4 additions & 3 deletions include/coap2/coap_dtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ typedef struct coap_dtls_pki_t {

/* Options to enable different TLS functionality in libcoap */
uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */
uint8_t require_peer_cert; /**< 1 if peer cert is required */
uint8_t check_common_ca; /**< 1 if peer cert is to be signed by
* the same CA as the local cert */
uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */
uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */
uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */
Expand Down Expand Up @@ -542,8 +543,8 @@ coap_dtls_context_set_cpsk(struct coap_context_t *coap_context,

int
coap_dtls_context_set_pki(struct coap_context_t *coap_context,
coap_dtls_pki_t *setup_data,
coap_dtls_role_t role);
const coap_dtls_pki_t *setup_data,
const coap_dtls_role_t role);

/**
* Set the dtls context's default Root CA information for a client or server.
Expand Down
2 changes: 1 addition & 1 deletion include/coap2/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ int coap_context_set_psk2(coap_context_t *context,
*/
int
coap_context_set_pki(coap_context_t *context,
coap_dtls_pki_t *setup_data);
const coap_dtls_pki_t *setup_data);

/**
* Set the context's default Root CA information for a client or server.
Expand Down
9 changes: 8 additions & 1 deletion man/coap-client.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ SYNOPSIS
[*-P* addr[:port]] [*-T* token] [*-U*]
[[*-h* match_hint_file] [*-k* key] [*-u* user]]
[[*-c* certfile] [*-j* keyfile] [*-C* cafile] [*-J* pkcs11_pin]
[*-M* rpk_file] [*-R* root_cafile]] URI
[*-M* rpk_file] [*-R* root_cafile] [-n] [-z]] URI

DESCRIPTION
-----------
Expand Down Expand Up @@ -195,6 +195,13 @@ definitions have to be in DER, not PEM, format. Otherwise all of
this list and is "trusted" for the verification.
Alternatively, this can point to a directory containing a set of CA PEM files.

*-n* ::
Disable remote peer certificate checking.

*-z* ::
Disable checking that local and peer certificates share a common CA (used for
mutual authentication).

EXAMPLES
--------
* Example
Expand Down
7 changes: 6 additions & 1 deletion man/coap-rd.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SYNOPSIS
--------
*coap-rd* [*-g* group] [*-p* port] [*-v* num] [*-A* address]
[[*-h* hint] [*-k* key]]
[[*-c* certfile] [*-n*] [*-C* cafile] [*-R* root_cafile]]
[[*-c* certfile] [*-n*] [*-z*] [*-C* cafile] [*-R* root_cafile]]

DESCRIPTION
-----------
Expand Down Expand Up @@ -68,6 +68,11 @@ OPTIONS - PKI

*-n* ::
Disable the requirement for clients to have defined client certificates.
Disable remote peer certificate checking.

*-z* ::
Disable checking that local and peer certificates share a common CA (used for
mutual authentication).

*-C* cafile::
PEM file containing the CA Certificate that was used to sign the certfile
Expand Down
23 changes: 14 additions & 9 deletions man/coap-server.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ SYNOPSIS
[*-A* address] [*-N*]
[[*-h* hint] [*-i* match_identity_file] [*-k* key]
[*-s* match_psk_sni_file]]
[[*-c* certfile] [*-j* keyfile] [*-n*] [*-C* cafile]
[[*-c* certfile] [*-j* keyfile] [*-n*] [*-z*] [*-C* cafile]
[*-J* pkcs11_pin] [*-M* rpk_file] [*-R* root_cafile]
[*-S* match_pki_sni_file]]

Expand Down Expand Up @@ -107,18 +107,23 @@ definitions have to be in DER, not PEM, format. Otherwise all of
*certfile*, *keyfile* or *cafile* are in PEM format.

*-c* certfile::
PEM file or PKCS11 URI for the certificate. The private key can be in
the PEM file, or use the same PKCS11 URI. If not, the private key is defined
by *-j keyfile*. +
Note: if *-k key* is defined, you need to define *-c certfile* as well to
have the server support both PSK and PKI.
PEM file or PKCS11 URI for the certificate. The private key can be in
the PEM file, or use the same PKCS11 URI. If not, the private key is defined
by *-j keyfile*. +
Note: if *-k key* is defined, you need to define *-c certfile* as well to
have the server support both PSK and PKI.

*-j* keyfile::
PEM file or PKCS11 URI for the private key for the certificate in *-c
certfile* if the parameter is different from certfile in *-c certfile*.
PEM file or PKCS11 URI for the private key for the certificate in *-c
certfile* if the parameter is different from certfile in *-c certfile*.

*-n* ::
Disable the requirement for clients to have defined client certificates.
Disable the requirement for clients to have defined client certificates.
Disable remote peer certificate checking.

*-z* ::
Disable checking that local and peer certificates share a common CA (used for
mutual authentication).

*-C* cafile::
PEM file or PKCS11 URI for the CA certificate that was used to sign the
Expand Down
4 changes: 2 additions & 2 deletions man/coap_context.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SYNOPSIS
*void coap_free_context(coap_context_t *_context_);*

*int coap_context_set_pki(coap_context_t *_context_,
coap_dtls_pki_t *_setup_data_);*
const coap_dtls_pki_t *_setup_data_);*

*int coap_context_set_pki_root_cas(coap_context_t *_context_,
const char *_ca_file_, const char *_ca_dir_);*
Expand Down Expand Up @@ -294,7 +294,7 @@ setup_server_context_pki (const char *public_cert_file,
/* see coap_encryption(3) */
dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION;
dtls_pki.verify_peer_cert = 1;
dtls_pki.require_peer_cert = 1;
dtls_pki.check_common_ca = 1;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand Down
15 changes: 10 additions & 5 deletions man/coap_encryption.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ typedef struct coap_dtls_pki_t {

/* Options to enable different TLS functionality in libcoap */
uint8_t verify_peer_cert; /* 1 if peer cert is to be verified */
uint8_t require_peer_cert; /* 1 if peer cert is required */
uint8_t check_common_ca; /* 1 if peer cert is to be signed by
* the same CA as the local cert */
uint8_t allow_self_signed; /* 1 if self signed certs are allowed */
uint8_t allow_expired_certs; /* 1 if expired certs are allowed */
uint8_t cert_chain_validation; /* 1 if to check cert_chain_verify_depth */
Expand Down Expand Up @@ -486,10 +487,14 @@ for different versions of the coap_dtls_pki_t structure in the future.
*SECTION: PKI/RPK: coap_dtls_pki_t: Peer Certificate Checking*

*verify_peer_cert* Set to 1 to check that the peer's certificate is valid if
provided, else 0.
provided, else 0. If not set, check_common_ca, allow_self_signed,
allow_expired_certs, cert_chain_validation, cert_chain_verify_depth,
check_cert_revocation, allow_no_crl, allow_expired_crl, allow_bad_md_hash
and allow_short-rsa_length settings are all ignored.

*require_peer_cert* Set to 1 to enforce that the peer provides a certificate,
else 0. If the Server, this initiates a request for the peer certificate.
*check_common_ca* Set to 1 to check that the CA that signed the peer's
certificate is the same CA that signed the local certificate
else 0.

*allow_self_signed* Set to 1 to allow the peer (or any certificate in the
certificate chain) to be a self-signed certificate, else 0.
Expand Down Expand Up @@ -941,7 +946,7 @@ setup_server_context_pki (const char *public_cert_file,

dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION;
dtls_pki.verify_peer_cert = 1;
dtls_pki.require_peer_cert = 1;
dtls_pki.check_common_ca = 1;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand Down
2 changes: 1 addition & 1 deletion man/coap_session.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ setup_client_session_pki (struct in_addr ip_address,
/* See coap_encryption(3) */
dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION;
dtls_pki.verify_peer_cert = 1;
dtls_pki.require_peer_cert = 1;
dtls_pki.check_common_ca = 1;
dtls_pki.allow_self_signed = 1;
dtls_pki.allow_expired_certs = 1;
dtls_pki.cert_chain_validation = 1;
Expand Down
Loading

0 comments on commit 2d8fe86

Please sign in to comment.