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.

Update help documentation as appropriate.

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 Nov 11, 2020
1 parent 5c23771 commit 35f530f
Show file tree
Hide file tree
Showing 18 changed files with 415 additions and 211 deletions.
69 changes: 43 additions & 26 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,8 +654,9 @@ 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[-M raw_pk] [-R root_cafile] [-S match_pki_sni_file]] URI\n"
"\t\t[[-c certfile] [-j keyfile] [-n] [-z] [-C cafile]\n"
"\t\t[-J pkcs11_pin] [-M raw_pk] [-R root_cafile]\n"
"\t\t[-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"
"\t-a addr\t\tThe local interface address to use\n"
Expand Down Expand Up @@ -699,9 +702,9 @@ usage( const char *program, const char *version) {
fprintf( stderr,
"PSK Options (if supported by underlying (D)TLS library)\n"
"\t-h match_hint_file\n"
"\t \t\tThis is a file that contains one or more lines of Identity\n"
"\t \t\tHints to match for new user and new pre-shared key\n"
"\t \t\t(PSK) (comma separated) to be used. E.g., per line\n"
"\t \t\tThis is a file that contains one or more lines of\n"
"\t \t\tIdentity Hints to match for new user and new pre-shared\n"
"\t \t\tkey (PSK) (comma separated) to be used. E.g., per line\n"
"\t \t\t hint_to_match,new_user,new_key\n"
"\t \t\tNote: -k and -u still need to be defined for the default\n"
"\t \t\tcase\n"
Expand All @@ -713,29 +716,36 @@ usage( const char *program, const char *version) {
"\tPKCS11 URI file definitions have to be in DER, not PEM, format.\n"
"\tOtherwise all of '-c certfile', '-j keyfile' or '-C cafile' are in\n"
"\tPEM format.\n\n"
"\t-c certfile\tPEM file or PKCS11 URI for the Certificate. The private\n"
"\t \t\tkey can be in the PEM file, or use the same PKCS11 URI.\n"
"\t \t\tIf not, the private ney is defined by '-j keyfile'\n"
"\t-c certfile\tPEM file or PKCS11 URI for the certificate. The private\n"
"\t \t\tkey can also be in the PEM file, or has the same PKCS11\n"
"\t \t\tURI. If not, the private key is defined by '-j keyfile'\n"
"\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-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"
"\t \t\tself-signed (as defined by '-c certfile'), then you need\n"
"\t \t\tto have on the command line the same filename for both\n"
"\t \t\tthe certfile and cafile (as in '-c certfile -C certfile')\n"
"\t \t\tto trigger validation\n"
"\t \t\tcertificate in '-c certfile' if the parameter is\n"
"\t \t\tdifferent from certfile in '-c certfile'\n"
"\t-n \t\tDisable remote peer certificate checking\n"
"\t-z \t\tDisable checking that server and client certificates\n"
"\t \t\twere signed by a common CA (used for mutual\n"
"\t \t\tauthentication)\n"
"\t-C cafile\tPEM file or PKCS11 URI for the CA certificate that was\n"
"\t \t\tused to sign the client certfile. The contents of cafile\n"
"\t \t\tare added to the trusted store of root CAs.\n"
"\t \t\tUsing the -C or -R options will will trigger the\n"
"\t \t\tvalidation of the server certificate unless overridden\n"
"\t \t\tby the -n option\n"
"\t-J pkcs11_pin\tThe user pin to unlock access to the PKCS11 token\n"
"\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that contains\n"
"\t \t\tboth PUBLIC KEY and PRIVATE KEY or just EC PRIVATE KEY.\n"
"\t \t\t(GnuTLS and TinyDTLS support only) '-C cafile' not required\n"
"\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that\n"
"\t \t\tcontains both PUBLIC KEY and PRIVATE KEY or just\n"
"\t \t\tEC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support only).\n"
"\t \t\t'-C cafile' is not required\n"
"\t-R root_cafile\tPEM file containing the set of trusted root CAs that\n"
"\t \t\tare to be used to validate the server certificate.\n"
"\t \t\tThe '-C cafile' does not have to be in this list and is\n"
"\t \t\t'trusted' for the verification.\n"
"\t \t\tThe '-C cafile' CA does not have to be in this list and\n"
"\t \t\tis 'trusted' for the validation.\n"
"\t \t\tAlternatively, this can point to a directory containing\n"
"\t \t\ta set of CA PEM files\n"
"\t \t\ta set of CA PEM files.\n"
"\t \t\tUsing the -C or -R options will will trigger the\n"
"\t \t\tvalidation of the server certificate unless overridden\n"
"\t \t\tby the -n option\n"
);
fprintf( stderr,
"Examples:\n"
Expand Down Expand Up @@ -1418,8 +1428,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 +1627,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 +1699,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 +1746,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
Loading

0 comments on commit 35f530f

Please sign in to comment.