diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..c1d554b7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ext/micro-ecc"] + path = ext/micro-ecc + url = https://github.com/kmackay/micro-ecc.git diff --git a/Makefile.in b/Makefile.in index 1866b44a..3336c56c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -47,14 +47,16 @@ HEADERS:=dtls.h hmac.h dtls_debug.h dtls_config.h uthash.h numeric.h crypto.h gl netq.h alert.h utlist.h dtls_prng.h peer.h state.h dtls_time.h session.h \ tinydtls.h dtls_mutex.h PKG_CONFIG_FILES:=tinydtls.pc +__micro_ecc_path:=ext/micro-ecc +MICRO_ECC_FILES:=$(addprefix $(__micro_ecc_path)/, uECC.h uECC.c uECC_vli.h types.h) $(wildcard $(__micro_ecc_path)/*.inc) CFLAGS:=-Wall -pedantic -std=c99 -DSHA2_USE_INTTYPES_H @CFLAGS@ \ @WARNING_CFLAGS@ $(EXTRA_CFLAGS) CPPFLAGS:=@CPPFLAGS@ -DDTLS_CHECK_CONTENTTYPE -I$(top_srcdir) -SUBDIRS:=tests tests/unit-tests doc platform-specific sha2 aes ecc +SUBDIRS:=tests tests/unit-tests doc platform-specific sha2 aes DISTSUBDIRS:=$(SUBDIRS) DISTDIR=$(top_builddir)/$(package) FILES:=Makefile.in configure configure.ac dtls_config.h.in \ - Makefile.tinydtls $(SOURCES) $(HEADERS) + Makefile.tinydtls tinydtls.pc.in ar-lib $(SOURCES) $(HEADERS) $(MICRO_ECC_FILES) LIB:=libtinydtls LIBS:=$(LIB).a ifeq ("@ENABLE_SHARED@", "1") @@ -87,9 +89,6 @@ dirs: $(SUBDIRS) dtls_prng.o:: $(wildcard platform-specific/dtls_prng_*.c) -$(SUB_OBJECTS):: - $(MAKE) -C $(@D) $(@F) - $(LIB).so: $(OBJECTS) $(LINK.c) $(LDFLAGS) -shared $^ -o $@ @@ -104,6 +103,9 @@ clean: done endif # WITH_CONTIKI +# Override several warnings for uECC.o +ext/micro-ecc/uECC.o:: CFLAGS+=-Wno-pedantic -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations + doc: $(MAKE) -C doc @@ -113,7 +115,7 @@ distclean: clean dist: $(FILES) $(DISTSUBDIRS) test -d $(DISTDIR) || mkdir $(DISTDIR) - cp $(FILES) $(DISTDIR) + cp --parents $(FILES) $(DISTDIR) for dir in $(DISTSUBDIRS); do \ $(MAKE) -C $$dir dist; \ done diff --git a/configure.ac b/configure.ac index bce5a361..1286422e 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,13 @@ AC_ARG_WITH(ecc, [AS_HELP_STRING([--without-ecc],[disable support for TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8])], [], [AC_DEFINE(DTLS_ECC, 1, [Define to 1 if building with ECC support.]) - OPT_OBJS="${OPT_OBJS} ecc/ecc.o" + OPT_OBJS="${OPT_OBJS} ext/micro-ecc/uECC.o" + dnl remove all ECC except for secp256r1 + AC_DEFINE([uECC_SUPPORTS_secp160r1], [0], [Define to 1 if building with uECC curve secp160r1]) + AC_DEFINE([uECC_SUPPORTS_secp192r1], [0], [Define to 1 if building with uECC curve secp192r1]) + AC_DEFINE([uECC_SUPPORTS_secp224r1], [0], [Define to 1 if building with uECC curve secp224r1]) + AC_DEFINE([uECC_SUPPORTS_secp256r1], [1], [Define to 1 if building with uECC curve secp256r1]) + AC_DEFINE([uECC_SUPPORTS_secp256k1], [0], [Define to 1 if building with uECC curve secp256k1]) DTLS_ECC=1]) AC_ARG_WITH(psk, @@ -116,7 +122,13 @@ AC_SUBST(NDEBUG) AC_SUBST(DTLS_ECC) AC_SUBST(DTLS_PSK) AC_SUBST(ENABLE_SHARED) -AC_SUBST(AR) +AC_SUBST(AC) + +AC_SUBST(uECC_SUPPORTS_secp160r1) +AC_SUBST(uECC_SUPPORTS_secp192r1) +AC_SUBST(uECC_SUPPORTS_secp224r1) +AC_SUBST(uECC_SUPPORTS_secp256r1) +AC_SUBST(uECC_SUPPORTS_secp256k1) # Checks for header files. AC_CHECK_HEADERS([assert.h arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/param.h sys/socket.h unistd.h]) @@ -148,6 +160,5 @@ AC_CONFIG_FILES([Makefile platform-specific/Makefile tinydtls.pc sha2/Makefile - aes/Makefile - ecc/Makefile]) + aes/Makefile]) AC_OUTPUT diff --git a/crypto.c b/crypto.c index 1937681d..1fe0807b 100644 --- a/crypto.c +++ b/crypto.c @@ -24,6 +24,7 @@ #else #define assert(x) #endif +#include #include "global.h" #include "dtls_debug.h" @@ -31,7 +32,9 @@ #include "dtls.h" #include "crypto.h" #include "ccm.h" -#include "ecc/ecc.h" +#ifdef DTLS_ECC +#include "ext/micro-ecc/uECC.h" +#endif /* DTLS_ECC */ #include "dtls_prng.h" #include "netq.h" @@ -356,6 +359,10 @@ dtls_psk_pre_master_secret(unsigned char *key, size_t keylen, #endif /* DTLS_PSK */ #ifdef DTLS_ECC +#ifdef uECC_SUPPORTS_secp256r1 +const dtls_ecdh_curve default_curve = TLS_EXT_ELLIPTIC_CURVES_SECP256R1; +#endif /* uECC_SUPPORTS_secp256r1 */ + static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size, uint32_t *result) { int i; @@ -432,31 +439,71 @@ int dtls_ec_key_asn1_from_uint32(const uint32_t *key, size_t key_size, return key_size + 2; } +static int get_uecc_curve(dtls_ecdh_curve curve, uECC_Curve *result) { + struct { + dtls_ecdh_curve curve; + uECC_Curve uecc_curve; + } known_curves[] = { +#if uECC_SUPPORTS_secp256r1 + { TLS_EXT_ELLIPTIC_CURVES_SECP256R1, uECC_secp256r1() }, +#endif /* uECC_SUPPORTS_secp256r1 */ + }; + unsigned int index; + + for (index = 0; index < sizeof(known_curves)/sizeof(known_curves[0]); index++) { + if (known_curves[index].curve == curve) { + *result = known_curves[index].uecc_curve; + return 1; + } + } + return 0; +} + +int dtls_ecdh_pre_master_secret2(const unsigned char *priv_key, + const unsigned char *pub_key, + size_t key_size, + dtls_ecdh_curve curve, + unsigned char *result, + size_t result_len) { + uECC_Curve uecc_curve; + if (!get_uecc_curve(curve, &uecc_curve)) { + dtls_warn("curve %" PRIu16 " not supported\n", curve); + return -1; + } + + if (result_len < key_size) { + return -1; + } + + if (!uECC_valid_public_key(pub_key, uecc_curve)) { + dtls_warn("invalid public key\n"); + } + + if (!uECC_shared_secret(pub_key, priv_key, result, uecc_curve)) { + dtls_warn("cannot generate ECDH shared secret\n"); + return 0; + } + + return key_size; +} + int dtls_ecdh_pre_master_secret(unsigned char *priv_key, unsigned char *pub_key_x, unsigned char *pub_key_y, size_t key_size, unsigned char *result, size_t result_len) { - uint32_t priv[8]; - uint32_t pub_x[8]; - uint32_t pub_y[8]; - uint32_t result_x[8]; - uint32_t result_y[8]; + const dtls_ecdh_curve curve = default_curve; + uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; - assert(key_size == sizeof(priv)); if (result_len < key_size) { return -1; } - dtls_ec_key_to_uint32(priv_key, key_size, priv); - dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x); - dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y); - - ecc_ecdh(pub_x, pub_y, priv, result_x, result_y); - - dtls_ec_key_from_uint32(result_x, key_size, result); - return key_size; + memcpy(pub_key, pub_key_x, DTLS_EC_KEY_SIZE); + memcpy(pub_key + DTLS_EC_KEY_SIZE, pub_key_y, DTLS_EC_KEY_SIZE); + return dtls_ecdh_pre_master_secret2(priv_key, pub_key, key_size, curve, + result, result_len); } void @@ -464,19 +511,36 @@ dtls_ecdsa_generate_key(unsigned char *priv_key, unsigned char *pub_key_x, unsigned char *pub_key_y, size_t key_size) { - uint32_t priv[8]; - uint32_t pub_x[8]; - uint32_t pub_y[8]; + const dtls_ecdh_curve curve = default_curve; + uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; + + int res = dtls_ecdsa_generate_key2(priv_key, pub_key, key_size, curve); + if (res > 0) { + memcpy(pub_key_x, pub_key, res); + memcpy(pub_key_y, pub_key + res, res); + } +} - do { - dtls_prng((unsigned char *)priv, key_size); - } while (!ecc_is_valid_key(priv)); +int +dtls_ecdsa_generate_key2(unsigned char *priv_key, + unsigned char *pub_key, + size_t key_size, + dtls_ecdh_curve curve) { + uECC_Curve uecc_curve; + if (!get_uecc_curve(curve, &uecc_curve)) { + dtls_warn("curve %" PRIu16 " not supported\n", curve); + return -1; + } - ecc_gen_pub_key(priv, pub_x, pub_y); + assert(key_size >= (unsigned int)uECC_curve_private_key_size(uecc_curve)); + assert(2 * key_size >= (unsigned int)uECC_curve_public_key_size(uecc_curve)); - dtls_ec_key_from_uint32(priv, key_size, priv_key); - dtls_ec_key_from_uint32(pub_x, key_size, pub_key_x); - dtls_ec_key_from_uint32(pub_y, key_size, pub_key_y); + if (!uECC_make_key(pub_key, priv_key, uecc_curve) + || !uECC_valid_public_key(pub_key, uecc_curve)) { + dtls_crit("cannot generate ECC key pair\n"); + return 0; + } + return uECC_curve_private_key_size(uecc_curve); } /* rfc4492#section-5.4 */ @@ -484,17 +548,39 @@ void dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size, const unsigned char *sign_hash, size_t sign_hash_size, uint32_t point_r[9], uint32_t point_s[9]) { - int ret; - uint32_t priv[8]; - uint32_t hash[8]; - uint32_t randv[8]; - - dtls_ec_key_to_uint32(priv_key, key_size, priv); - dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash); - do { - dtls_prng((unsigned char *)randv, key_size); - ret = ecc_ecdsa_sign(priv, hash, randv, point_r, point_s); - } while (ret); + const dtls_ecdh_curve curve = default_curve; + dtls_ecdsa_create_sig_hash2(priv_key, key_size, + sign_hash, sign_hash_size, + curve, point_r, point_s); + +} + +int +dtls_ecdsa_create_sig_hash2(const unsigned char *priv_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + dtls_ecdh_curve curve, + uint32_t point_r[9], uint32_t point_s[9]) { + uint8_t sign[2 * DTLS_EC_KEY_SIZE]; + uECC_Curve uecc_curve; + int curve_size; + if (!get_uecc_curve(curve, &uecc_curve)) { + dtls_warn("curve %" PRIu16 " not supported\n", curve); + return -1; + } + + curve_size = uECC_curve_private_key_size(uecc_curve); + + assert(key_size >= (unsigned int)curve_size); + assert(sign_hash_size >= (unsigned int)curve_size); + assert(sizeof(sign) >= 2 * (unsigned int)curve_size); + if (!uECC_sign(priv_key, sign_hash, sign_hash_size, sign, uecc_curve)) { + dtls_warn("cannot create signature\n"); + return -1; + } + + dtls_ec_key_to_uint32(sign, curve_size, point_r); + dtls_ec_key_to_uint32(sign + curve_size, curve_size, point_s); + return 2 * curve_size; } void @@ -522,19 +608,39 @@ dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x, const unsigned char *pub_key_y, size_t key_size, const unsigned char *sign_hash, size_t sign_hash_size, unsigned char *result_r, unsigned char *result_s) { - uint32_t pub_x[8]; - uint32_t pub_y[8]; - uint32_t hash[8]; - uint32_t point_r[8]; - uint32_t point_s[8]; - - dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x); - dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y); - dtls_ec_key_to_uint32(result_r, key_size, point_r); - dtls_ec_key_to_uint32(result_s, key_size, point_s); - dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash); - - return ecc_ecdsa_validate(pub_x, pub_y, hash, point_r, point_s); + const dtls_ecdh_curve curve = default_curve; + uint8_t pub_key[2 * DTLS_EC_KEY_SIZE]; + memcpy(pub_key, pub_key_x, key_size); + memcpy(pub_key + key_size, pub_key_y, key_size); + return dtls_ecdsa_verify_sig_hash2(pub_key, key_size, + sign_hash, sign_hash_size, + curve, + result_r, result_s); +} + +int +dtls_ecdsa_verify_sig_hash2(const unsigned char *pub_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + dtls_ecdh_curve curve, + unsigned char *result_r, unsigned char *result_s) { + uint8_t sign[2 * DTLS_EC_KEY_SIZE]; + uECC_Curve uecc_curve; + int curve_size; + if (!get_uecc_curve(curve, &uecc_curve)) { + dtls_warn("curve %" PRIu16 " not supported\n", curve); + return -1; + } + (void)result_r; + (void)result_s; + + curve_size = uECC_curve_public_key_size(uecc_curve); + + assert(key_size == (unsigned int)curve_size); + assert(sizeof(sign) >= (unsigned int)curve_size); + + /* clear sign to avoid maybe-unitialized warning */ + memset(sign, 0, sizeof(sign)); + return uECC_verify(pub_key, sign_hash, sign_hash_size, sign, uecc_curve); } int diff --git a/crypto.h b/crypto.h index 53547589..782f2331 100644 --- a/crypto.h +++ b/crypto.h @@ -60,9 +60,18 @@ typedef uint8_t dtls_cipher_index_t; typedef enum { AES128=0 } dtls_crypto_alg; -typedef enum { - DTLS_ECDH_CURVE_SECP256R1 -} dtls_ecdh_curve; +/** + * Curve type as specified in the TLS supported elliptic curves + * extension (@see [RFC 8422, Section 5.1.1](https://www.rfc-editor.org/rfc/rfc8422#section-5.1.1). + * + * The only supported value so far is TLS_EXT_ELLIPTIC_CURVES_SECP256R1 + */ +typedef uint16_t dtls_ecdh_curve; + +/** + * @deprecated {Defined for backwards compatibility.} + */ +#define DTLS_ECDH_CURVE_SECP256R1 TLS_EXT_ELLIPTIC_CURVES_SECP256R1 /** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */ typedef struct { @@ -110,6 +119,17 @@ typedef struct { uint64_t bitfield; } seqnum_t; +/* Maximum CID length. */ +#ifndef DTLS_MAX_CID_LENGTH +#define DTLS_MAX_CID_LENGTH 16 +#endif + +#if (DTLS_MAX_CID_LENGTH > 0) +#ifndef DTLS_USE_CID_DEFAULT +#define DTLS_USE_CID_DEFAULT 1 +#endif /* DTLS_USE_CID_DEFAULT */ +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + typedef struct { dtls_compression_t compression; /**< compression method */ @@ -124,7 +144,12 @@ typedef struct { * access the components of the key block. */ uint8 key_block[MAX_KEYBLOCK_LENGTH]; - + +#if (DTLS_MAX_CID_LENGTH > 0) + uint8_t write_cid[DTLS_MAX_CID_LENGTH]; + uint8_t write_cid_length; +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + seqnum_t cseq; /** 0) + unsigned int support_cid:1; /** indicate CID support (RFC9146) */ +#endif } dtls_user_parameters_t; typedef struct { @@ -158,6 +186,12 @@ typedef struct { dtls_compression_t compression; /**< compression method */ dtls_user_parameters_t user_parameters; /**< user parameters */ dtls_cipher_index_t cipher_index; /**< internal index for cipher_suite_params, DTLS_CIPHER_INDEX_NULL for TLS_NULL_WITH_NULL_NULL */ + +#if (DTLS_MAX_CID_LENGTH > 0) + uint8_t write_cid[DTLS_MAX_CID_LENGTH]; + uint8_t write_cid_length; +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + unsigned int do_client_auth:1; unsigned int extended_master_secret:1; unsigned int renegotiation_info:1; @@ -429,15 +463,70 @@ int dtls_ecdh_pre_master_secret(unsigned char *priv_key, unsigned char *result, size_t result_len); +/** + * Generates the pre_master_sercet from given own private key @p + * priv_key and remote public key @p pub_key for the curve @p curve. + * This function returns the generated shared secret in @p result of + * size @p result_len. On success, the return value give the actual + * number of bytes written to @p result. The return @c 0 indicates + * an error. + * + * @param priv_key The own private key. The size of this key is + * defined by the selected @p curve and is passed + * in @p key_size. + * @param pub_key The remote public key. The size of this key is + * defined by the selected @p curve (usually twice + * @p key_size. + * @param key_size Length of @p priv_key in bytes. + * @param curve The elliptic curve to use. + * @param result The derived pre master secret. + * @param result_len The maximum length of the derived pre master secret. + * in @p result. + * @return The actual length of @p result or <= 0 on error. + */ +int dtls_ecdh_pre_master_secret2(const unsigned char *priv_key, + const unsigned char *pub_key, + size_t key_size, + dtls_ecdh_curve curve, + unsigned char *result, + size_t result_len); + void dtls_ecdsa_generate_key(unsigned char *priv_key, unsigned char *pub_key_x, unsigned char *pub_key_y, size_t key_size); +/** + * Generates a key pair for the given curve @p curve and stores the + * private part in @p priv_key and the public part in @p pub_key. The + * storage that must be provided for @p priv_key and @p pub_key is + * determined by @p curve. Usually, @p pub_key requires 2 * @p + * key_size. This function returns the actual number of bytes written + * into @p priv_key on success, or @c 0 otherwise. + * + * @param priv_key Storage for the generated private key. + * @param pub_key Storage for the generated public key. + * @param key_size The amount of storage for @p priv_key. + * @param curve Storage for the generated public key. + * @return The number of bytes written into @p priv_key, or @c 0 on error. + */ +int dtls_ecdsa_generate_key2(unsigned char *priv_key, + unsigned char *pub_key, + size_t key_size, + dtls_ecdh_curve curve); + void dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size, const unsigned char *sign_hash, size_t sign_hash_size, uint32_t point_r[9], uint32_t point_s[9]); +/** + * FIXME: document function + */ +int dtls_ecdsa_create_sig_hash2(const unsigned char *priv_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + dtls_ecdh_curve curve, + uint32_t point_r[9], uint32_t point_s[9]); + void dtls_ecdsa_create_sig(const unsigned char *priv_key, size_t key_size, const unsigned char *client_random, size_t client_random_size, const unsigned char *server_random, size_t server_random_size, @@ -449,6 +538,14 @@ int dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x, const unsigned char *sign_hash, size_t sign_hash_size, unsigned char *result_r, unsigned char *result_s); +/** + * FIXME: document function + */ +int dtls_ecdsa_verify_sig_hash2(const unsigned char *pub_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + dtls_ecdh_curve curve, + unsigned char *result_r, unsigned char *result_s); + int dtls_ecdsa_verify_sig(const unsigned char *pub_key_x, const unsigned char *pub_key_y, size_t key_size, const unsigned char *client_random, size_t client_random_size, diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index fc668a8d..33ea9627 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.17 +# Doxyfile 1.10.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -53,6 +63,12 @@ PROJECT_BRIEF = PROJECT_LOGO = +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If @@ -60,16 +76,28 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode @@ -81,26 +109,18 @@ ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -217,6 +237,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -240,25 +268,19 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all @@ -300,18 +322,21 @@ OPTIMIZE_OUTPUT_SLICE = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is -# Fortran), use: inc=Fortran f=C. +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = @@ -334,6 +359,17 @@ MARKDOWN_SUPPORT = YES TOC_INCLUDE_HEADINGS = 5 +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -445,6 +481,27 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = YES + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -508,6 +565,13 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -519,7 +583,8 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO @@ -545,12 +610,20 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# (including Cygwin) ands Mac users are advised to set this option to NO. -# The default value is: system dependent. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = YES @@ -568,6 +641,12 @@ HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -725,7 +804,8 @@ FILE_VERSION_FILTER = # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE @@ -771,24 +851,50 @@ WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = YES @@ -799,13 +905,27 @@ WARN_AS_ERROR = YES # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -824,12 +944,23 @@ INPUT = .. # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. @@ -838,13 +969,15 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen -# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, -# *.vhdl, *.ucf, *.qsf and *.ice. +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = @@ -861,7 +994,7 @@ RECURSIVE = NO # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = ../ext # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -883,10 +1016,7 @@ EXCLUDE_PATTERNS = # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* +# ANamespace::AClass, ANamespace::*Test EXCLUDE_SYMBOLS = @@ -931,6 +1061,11 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. @@ -972,6 +1107,15 @@ FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -986,7 +1130,8 @@ USE_MDFILE_AS_MAINPAGE = SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO @@ -1059,16 +1204,24 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories @@ -1078,10 +1231,13 @@ CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the -# path to the compilation database (see: -# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files -# were built. This is equivalent to specifying the "-p" option to a clang tool, -# such as clang-check. These options will then be passed to the parser. +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. @@ -1098,17 +1254,11 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = NO -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1187,7 +1337,12 @@ HTML_STYLESHEET = # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1202,9 +1357,22 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1214,7 +1382,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1232,15 +1400,6 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will @@ -1260,6 +1419,33 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1275,10 +1461,11 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. @@ -1295,6 +1482,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1320,8 +1514,12 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1351,7 +1549,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1378,6 +1576,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -1396,7 +1604,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1404,8 +1613,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1413,16 +1622,16 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = @@ -1434,9 +1643,9 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1479,16 +1688,28 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # @@ -1513,6 +1734,24 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML @@ -1522,17 +1761,6 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1550,11 +1778,29 @@ FORMULA_MACROFILE = USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1567,22 +1813,29 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1629,7 +1882,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1642,8 +1896,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1738,7 +1993,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -1752,29 +2007,31 @@ PAPER_TYPE = a4wide EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = @@ -1807,18 +2064,26 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1831,16 +2096,6 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. @@ -1849,14 +2104,6 @@ LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO - # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, # it will be relative to the LATEX_OUTPUT directory. If left blank the @@ -1921,16 +2168,6 @@ RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -2027,27 +2264,44 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3 +# database with symbols found by doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each doxygen run. If set to NO, doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- @@ -2122,7 +2376,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2190,15 +2445,15 @@ TAGFILES = GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2212,25 +2467,9 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = NO - -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2239,10 +2478,10 @@ HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: YES. +# The default value is: NO. HAVE_DOT = NO @@ -2256,49 +2495,77 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" + +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. -CLASS_GRAPH = YES +CLASS_GRAPH = TEXT # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2321,10 +2588,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2336,7 +2625,9 @@ TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # YES then doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2345,7 +2636,10 @@ INCLUDE_GRAPH = YES # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are # set to YES then doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2385,22 +2679,30 @@ GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = YES +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). +# https://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, -# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, # png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and # png:gdiplus:gdiplus. # The default value is: png. @@ -2433,11 +2735,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2446,10 +2749,10 @@ MSCFILE_DIRS = DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = @@ -2487,18 +2790,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2511,14 +2802,34 @@ DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/dtls.c b/dtls.c index 33b352f4..5f4f6a5e 100644 --- a/dtls.c +++ b/dtls.c @@ -60,6 +60,10 @@ # include "hmac.h" #endif /* WITH_SHA256 */ +#ifdef DTLS_ECC +#include "ext/micro-ecc/uECC.h" +#endif /* DTLS_ECC */ + #ifdef WITH_ZEPHYR LOG_MODULE_DECLARE(TINYDTLS, CONFIG_TINYDTLS_LOG_LEVEL); #endif /* WITH_ZEPHYR */ @@ -82,11 +86,12 @@ memarray_t dtlscontext_storage; #define dtls_set_version(H,V) dtls_int_to_uint16((H)->version, (V)) #define dtls_set_content_type(H,V) ((H)->content_type = (V) & 0xff) -#define dtls_set_length(H,V) ((H)->length = (V)) +#define dtls_set_length(H,V) dtls_int_to_uint16(&((H)->length), (V)) #define dtls_get_content_type(H) ((H)->content_type & 0xff) #define dtls_get_version(H) dtls_uint16_to_int((H)->version) #define dtls_get_epoch(H) dtls_uint16_to_int((H)->epoch) +#define dtls_get_length(H) dtls_uint16_to_int((H)->length) #define dtls_get_sequence_number(H) dtls_uint48_to_ulong((H)->sequence_number) #define dtls_get_fragment_length(H) dtls_uint24_to_int((H)->fragment_length) @@ -141,14 +146,15 @@ memarray_t dtlscontext_storage; * ec curves := 8 bytes * ec point format := 6 bytes => 26 * sign. and hash algos := 8 bytes - * extended master secret := 4 bytes => 12 + * extended master secret := 4 bytes + * connection id, empty := 5 bytes => 17 * * (The ClientHello uses TLS_EMPTY_RENEGOTIATION_INFO_SCSV * instead of renegotiation info) */ #define DTLS_CH_LENGTH sizeof(dtls_client_hello_t) /* no variable length fields! */ #define DTLS_COOKIE_LENGTH_MAX 32 -#define DTLS_CH_LENGTH_MAX DTLS_CH_LENGTH + DTLS_COOKIE_LENGTH_MAX + 10 + (2 * DTLS_MAX_CIPHER_SUITES) + 26 + 12 +#define DTLS_CH_LENGTH_MAX DTLS_CH_LENGTH + DTLS_COOKIE_LENGTH_MAX + 10 + (2 * DTLS_MAX_CIPHER_SUITES) + 26 + 17 #define DTLS_HV_LENGTH sizeof(dtls_hello_verify_t) /* * ServerHello: @@ -324,6 +330,14 @@ free_context(dtls_context_t *context) { #endif /* WITH_POSIX */ +#ifdef DTLS_ECC +/* Define wrapper function for uECC_set_rng to map the size parameter + * from unsigned int to size_t. */ +static inline int uecc_rng_function(uint8_t *dest, unsigned int size) { + return dtls_prng(dest, size); +} +#endif /* DTLS_ECC */ + void dtls_init(void) { dtls_clock_init(); @@ -335,6 +349,9 @@ dtls_init(void) { memarray_init(&dtlscontext_storage, dtlscontext_storage_data, sizeof(dtls_context_t), DTLS_CONTEXT_MAX); #endif /* RIOT_VERSION */ +#ifdef DTLS_ECC + uECC_set_rng(uecc_rng_function); +#endif /* DTLS_ECC */ } /* Calls cb_alert() with given arguments if defined, otherwise an @@ -464,7 +481,7 @@ dtls_create_cookie(dtls_context_t *ctx, uint8 *msg, size_t msglen, uint8 *cookie, int *clen) { unsigned char buf[DTLS_HMAC_MAX]; - size_t e, fragment_length; + size_t e, compatability_length; int len; /* create cookie with HMAC-SHA256 over: @@ -504,14 +521,23 @@ dtls_create_cookie(dtls_context_t *ctx, e += dtls_uint8_to_int(msg + DTLS_HS_LENGTH + e); e += sizeof(uint8_t); - /* read fragment length and check for consistency */ - fragment_length = dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)); - if ((fragment_length < e) || (e + DTLS_HS_LENGTH) > msglen) + /* + * Read in compatablility_length length and check for consistency + * The compatability_length is because a DTLS1.3 Client Hello may come in, + * and the re-transmit of the Client Hello with cookie may be different. + */ + /* Get the Cipher Suites length + value */ + compatability_length = dtls_uint16_to_int(msg + DTLS_HS_LENGTH + e) + 2; + /* Add in the Compression length byte + value */ + compatability_length += dtls_uint8_to_int(msg + DTLS_HS_LENGTH + e + + compatability_length) + 1; + + if (e + DTLS_HS_LENGTH + compatability_length > msglen) return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); dtls_hmac_update(&hmac_context, msg + DTLS_HS_LENGTH + e, - fragment_length - e); + compatability_length); len = dtls_hmac_finalize(&hmac_context, buf); @@ -531,6 +557,7 @@ static char const content_types[] = { DTLS_CT_ALERT, DTLS_CT_HANDSHAKE, DTLS_CT_APPLICATION_DATA, + DTLS_CT_TLS12_CID, 0 /* end marker */ }; @@ -563,15 +590,30 @@ is_record(uint8 *msg, size_t msglen) { unsigned int rlen = 0; if (msglen >= DTLS_RH_LENGTH) { /* FIXME allow empty records? */ - uint16_t version = dtls_uint16_to_int(msg + 1); - if ((((version == DTLS_VERSION) || (version == DTLS10_VERSION)) - && known_content_type(msg))) { - rlen = DTLS_RH_LENGTH + - dtls_uint16_to_int(DTLS_RECORD_HEADER(msg)->length); - - /* we do not accept wrong length field in record header */ - if (rlen > msglen) - rlen = 0; + uint16_t version = dtls_get_version(DTLS_RECORD_HEADER(msg)); + + if (DTLS_VERSION == version) { + if (!known_content_type(msg)) { + return 0; + } + } else if (DTLS10_VERSION == version) { + if (DTLS_CT_HANDSHAKE != msg[0] || DTLS_RH_LENGTH == msglen) { + return 0; + } else { + uint8_t handshake_type = msg[DTLS_RH_LENGTH]; + if (DTLS_HT_CLIENT_HELLO != handshake_type && + DTLS_HT_HELLO_VERIFY_REQUEST != handshake_type) { + return 0; + } + } + } else { + return 0; + } + rlen = DTLS_RH_LENGTH + dtls_uint16_to_int(DTLS_RECORD_HEADER(msg)->length); + + /* we do not accept wrong length field in record header */ + if (rlen > msglen) { + rlen = 0; } } @@ -666,6 +708,9 @@ static const dtls_user_parameters_t default_user_parameters = { #endif /* DTLS_DEFAULT_CIPHER_SUITES */ .force_extended_master_secret = 1, .force_renegotiation_info = 1, +#if (DTLS_MAX_CID_LENGTH > 0) + .support_cid = DTLS_USE_CID_DEFAULT, +#endif /* DTLS_MAX_CID_LENGTH > 0 */ }; /** only one compression method is currently defined */ @@ -928,6 +973,8 @@ dtls_message_type_to_name(int type) { return "handshake"; case DTLS_CT_APPLICATION_DATA: return "application_data"; + case DTLS_CT_TLS12_CID: + return "connection_id"; default: return NULL; } @@ -1067,6 +1114,10 @@ calculate_key_block(dtls_context_t *ctx, security->cipher_index = handshake->cipher_index; security->compression = handshake->compression; security->rseq = 0; +#if (DTLS_MAX_CID_LENGTH > 0) + security->write_cid_length = handshake->write_cid_length; + memcpy(security->write_cid, handshake->write_cid, handshake->write_cid_length); +#endif /* DTLS_MAX_CID_LENGTH > 0 */ return 0; } @@ -1173,6 +1224,39 @@ static int verify_ext_sig_hash_algo(uint8 *data, size_t data_length) { return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); } +#if (DTLS_MAX_CID_LENGTH > 0) + +static int +get_ext_connection_id(dtls_handshake_parameters_t *handshake, uint8 *data, + size_t data_length) { + uint8_t i; + + if (sizeof(uint8) > data_length) { + dtls_warn("invalid length (%zu) for extension connection id\n", data_length); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + /* length of the connection id */ + i = dtls_uint8_to_int(data); + data += sizeof(uint8); + if (i + sizeof(uint8) != data_length) { + dtls_warn("invalid connection id length (%d)\n", i); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + if (DTLS_MAX_CID_LENGTH < i) { + dtls_warn("connection id length (%d) exceeds maximum (%d)!\n", i, DTLS_MAX_CID_LENGTH); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + handshake->write_cid_length = i; + memcpy(handshake->write_cid, data, i); + + return 0; +} + +#endif /* DTLS_MAX_CID_LENGTH > 0*/ + /* * Check for some TLS Extensions used by the ECDHE_ECDSA cipher. */ @@ -1266,6 +1350,16 @@ dtls_check_tls_extension(dtls_peer_t *peer, if (verify_ext_sig_hash_algo(data, j)) goto error; break; +#if (DTLS_MAX_CID_LENGTH > 0) + case TLS_EXT_CONNECTION_ID: + if (!is_client_hello && !peer->handshake_params->user_parameters.support_cid) { + dtls_warn("connection id was not sent by client!\n"); + goto error; + } + if (get_ext_connection_id(peer->handshake_params, data, j)) + goto error; + break; +#endif /* DTLS_MAX_CID_LENGTH */ case TLS_EXT_RENEGOTIATION_INFO: /* RFC 5746, minimal version, only empty info is supported */ if (j == 1 && *data == 0) { @@ -1643,9 +1737,10 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, uint8 *data_array[], size_t data_len_array[], size_t data_array_len, uint8 *sendbuf, size_t *rlen) { - uint8 *p, *start; + uint8 *p; int res; unsigned int i; + uint8_t cid_length = 0; if (*rlen < DTLS_RH_LENGTH) { dtls_alert("The sendbuf (%zu bytes) is too small\n", *rlen); @@ -1658,7 +1753,6 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, } p = dtls_set_record_header(type, security->epoch, &(security->rseq), sendbuf); - start = p; if (security->cipher_index == DTLS_CIPHER_INDEX_NULL) { /* no cipher suite */ @@ -1679,15 +1773,31 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM */ /** + * RFC6347 * length of additional_data for the AEAD cipher which consists of * seq_num(2+6) + type(1) + version(2) + length(2) */ #define A_DATA_LEN 13 + +#if (DTLS_MAX_CID_LENGTH > 0) + /** + * RFC9146 + * length of extra additional_data for the AEAD cipher which consists of + * seq_num_placeholder(8) + type(1) + cid_length(1) + */ +#define A_DATA_CID_EXTRA_LEN 10 +#define A_DATA_MAX_LEN (A_DATA_LEN + A_DATA_CID_EXTRA_LEN + DTLS_MAX_CID_LENGTH) +#else +#define A_DATA_MAX_LEN A_DATA_LEN +#endif + + uint8 *start = p; unsigned char nonce[DTLS_CCM_BLOCKSIZE]; - unsigned char A_DATA[A_DATA_LEN]; + unsigned char A_DATA[A_DATA_MAX_LEN]; const uint8_t mac_len = get_cipher_suite_mac_len(security->cipher_index); const cipher_suite_key_exchange_algorithm_t key_exchange_algorithm = get_key_exchange_algorithm(security->cipher_index); + uint8_t a_data_len = A_DATA_LEN; /* For backwards-compatibility, dtls_encrypt_params is called with * M= and L=3. */ const dtls_ccm_params_t params = { nonce, mac_len, 3 }; @@ -1704,6 +1814,16 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, } } +#if (DTLS_MAX_CID_LENGTH > 0) + cid_length = security->write_cid_length; + if (cid_length > 0) { + /* add cid to record header */ + memcpy(p - sizeof(uint16_t), security->write_cid, cid_length); + p += cid_length; + start = p; + } +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + /* set nonce from RFC 6655: The "nonce" input to the AEAD algorithm is exactly that of [RFC5288]: @@ -1769,31 +1889,62 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, dtls_debug_dump("key:", dtls_kb_local_write_key(security, peer->role), dtls_kb_key_size(security, peer->role)); - /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3: - * - * additional_data = seq_num + TLSCompressed.type + - * TLSCompressed.version + TLSCompressed.length; - */ - memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */ - memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */ - dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */ +#if (DTLS_MAX_CID_LENGTH > 0) + if (cid_length > 0) { + /* RFC 9146 */ + + /* inner content type */ + *p = *sendbuf; + *sendbuf = DTLS_CT_TLS12_CID; + p += sizeof(uint8_t); + res += sizeof(uint8_t); + + /* seq_num_placeholder: 8x 0xff */ + memset(A_DATA, 0xff, 8); + /* tls_cid: 25 */ + A_DATA[8] = DTLS_CT_TLS12_CID; + /* cid length */ + A_DATA[9] = cid_length; + /* copy record header */ + memcpy(A_DATA + A_DATA_CID_EXTRA_LEN, sendbuf, A_DATA_LEN + cid_length); + dtls_int_to_uint16(A_DATA + A_DATA_CID_EXTRA_LEN + 11 + cid_length, res - 8); /* length */ + a_data_len = A_DATA_LEN + A_DATA_CID_EXTRA_LEN + cid_length; + + } else { +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + /* RFC 6347 */ + /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3: + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + */ + memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */ + memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */ + dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */ + a_data_len = A_DATA_LEN; +#if (DTLS_MAX_CID_LENGTH > 0) + } +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + + dtls_debug_dump("adata:", A_DATA, a_data_len); + dtls_debug_dump("message:", start, res); res = dtls_encrypt_params(¶ms, start + 8, res - 8, start + 8, dtls_kb_local_write_key(security, peer->role), dtls_kb_key_size(security, peer->role), - A_DATA, A_DATA_LEN); + A_DATA, a_data_len); if (res < 0) return res; res += 8; /* increment res by size of nonce_explicit */ - dtls_debug_dump("message:", start, res); + dtls_debug_dump("encrypted-message:", start, res); } /* fix length of fragment in sendbuf */ - dtls_int_to_uint16(sendbuf + 11, res); + dtls_int_to_uint16(sendbuf + 11 + cid_length, res); - *rlen = DTLS_RH_LENGTH + res; + *rlen = DTLS_RH_LENGTH + res + cid_length; return 0; } @@ -2465,15 +2616,12 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) */ uint8 buf[DTLS_SH_LENGTH + 2 + 5 + 5 + 6 + 4 + 5]; uint8 *p; - uint8 extension_size; + uint8_t *p_extension_size = NULL; + uint16_t extension_size = 0; dtls_handshake_parameters_t * const handshake = peer->handshake_params; const dtls_cipher_t cipher_suite = get_cipher_suite(handshake->cipher_index); const int ecdsa = is_key_exchange_ecdhe_ecdsa(handshake->cipher_index); - extension_size = (handshake->extended_master_secret ? 4 : 0) + - (handshake->renegotiation_info ? 5 : 0) + - (ecdsa ? 5 + 5 + 6 : 0); - /* Handshake header */ p = buf; @@ -2487,7 +2635,8 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) memcpy(p, handshake->tmp.random.server, DTLS_RANDOM_LENGTH); p += DTLS_RANDOM_LENGTH; - *p++ = 0; /* no session id */ + /* no session id */ + *p++ = 0; if (cipher_suite != TLS_NULL_WITH_NULL_NULL) { /* selected cipher suite */ @@ -2498,11 +2647,10 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) *p++ = compression_methods[handshake->compression]; } - if (extension_size) { - /* length of the extensions */ - dtls_int_to_uint16(p, extension_size); - p += sizeof(uint16); - } + /* keep pointer to length of the extensions */ + p_extension_size = p; + /* skip length of extensions field */ + p += sizeof(uint16); if (ecdsa) { /* client certificate type extension, 5 bytes */ @@ -2566,6 +2714,10 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) *p++ = 0; } + /* length of the extensions */ + extension_size = (p - p_extension_size) - sizeof(uint16); + dtls_int_to_uint16(p_extension_size, extension_size); + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); /* TODO use the same record sequence number as in the ClientHello, @@ -3069,10 +3221,9 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, uint8 cookie[], size_t cookie_length) { uint8 buf[DTLS_CH_LENGTH_MAX]; uint8_t *p = buf; - uint8_t *p_cipher_suites_size = NULL; + uint8_t *p_size = NULL; + uint16_t size = 0; uint8_t index = 0; - uint8_t cipher_suites_size = 0; - uint8_t extension_size = 4; /* extended master secret extension */ #ifdef DTLS_ECC uint8_t ecdsa = 0; #endif @@ -3112,7 +3263,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, } /* keep pointer to size of cipher suites */ - p_cipher_suites_size = p; + p_size = p; /* skip size of cipher suites field */ p += sizeof(uint16); @@ -3131,8 +3282,8 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, credentials callback is missing */ } - cipher_suites_size = (p - p_cipher_suites_size) - sizeof(uint16); - if (cipher_suites_size == 0) { + size = (p - p_size) - sizeof(uint16); + if (size == 0) { dtls_crit("no supported cipher suite provided!\n"); return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); } @@ -3140,23 +3291,10 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, /* RFC5746 add RENEGOTIATION_INFO_SCSV */ dtls_int_to_uint16(p, TLS_EMPTY_RENEGOTIATION_INFO_SCSV); p += sizeof(uint16); - cipher_suites_size += sizeof(uint16); + size += sizeof(uint16); /* set size of known cipher suites */ - dtls_int_to_uint16(p_cipher_suites_size, cipher_suites_size); - -#ifdef DTLS_ECC - if (ecdsa) { - /* - * client_cert_type := 6 bytes - * server_cert_type := 6 bytes - * ec curves := 8 bytes - * ec point format := 6 bytes - * sign. and hash algos := 8 bytes - */ - extension_size += 6 + 6 + 8 + 6 + 8; - } -#endif + dtls_int_to_uint16(p_size, size); /* compression method */ dtls_int_to_uint8(p, 1); @@ -3165,8 +3303,9 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, dtls_int_to_uint8(p, TLS_COMPRESSION_NULL); p += sizeof(uint8); - /* length of the extensions */ - dtls_int_to_uint16(p, extension_size); + /* keep pointer to length of the extensions */ + p_size = p; + /* skip length of extensions field */ p += sizeof(uint16); #ifdef DTLS_ECC @@ -3263,6 +3402,26 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, p += sizeof(uint16); handshake->extended_master_secret = 1; +#if (DTLS_MAX_CID_LENGTH > 0) + if (handshake->user_parameters.support_cid) { + /* connection id, empty to indicate support, 5 bytes */ + dtls_int_to_uint16(p, TLS_EXT_CONNECTION_ID); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, sizeof(uint8)); + p += sizeof(uint16); + + /* empty cid, indicating support for cid extension */ + dtls_int_to_uint8(p, 0); + p += sizeof(uint8); + } +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + + /* length of the extensions */ + size = (p - p_size) - sizeof(uint16); + dtls_int_to_uint16(p_size, size); + handshake->hs_state.read_epoch = dtls_security_params(peer)->epoch; assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); diff --git a/dtls.h b/dtls.h index 05f3385c..600e8edc 100644 --- a/dtls.h +++ b/dtls.h @@ -341,6 +341,7 @@ void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next); #define DTLS_CT_ALERT 21 #define DTLS_CT_HANDSHAKE 22 #define DTLS_CT_APPLICATION_DATA 23 +#define DTLS_CT_TLS12_CID 25 #ifdef __GNUC__ #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) diff --git a/dtls_debug.h b/dtls_debug.h index 37a4731d..a02cab4e 100644 --- a/dtls_debug.h +++ b/dtls_debug.h @@ -129,8 +129,8 @@ void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr); #define dtls_notice(...) LOG_INF(__VA_ARGS__) #define dtls_info(...) LOG_INF(__VA_ARGS__) #define dtls_debug(...) LOG_DBG(__VA_ARGS__) -#define dtls_debug_hexdump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, length); LOG_HEXDUMP_DBG(buf, length, name); } -#define dtls_debug_dump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, length); LOG_HEXDUMP_DBG(buf, length, name); } +#define dtls_debug_hexdump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, (size_t)(length)); LOG_HEXDUMP_DBG(buf, length, name); } +#define dtls_debug_dump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, (size_t)(length)); LOG_HEXDUMP_DBG(buf, length, name); } #elif defined(RIOT_VERSION) #define dtls_emerg(...) LOG_ERROR(__VA_ARGS__) #define dtls_alert(...) LOG_ERROR(__VA_ARGS__) @@ -139,8 +139,8 @@ void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr); #define dtls_notice(...) LOG_INFO(__VA_ARGS__) #define dtls_info(...) LOG_INFO(__VA_ARGS__) #define dtls_debug(...) LOG_DEBUG(__VA_ARGS__) -#define dtls_debug_hexdump(name, buf, length) { if (LOG_DEBUG <= LOG_LEVEL) { LOG_DEBUG("-= %s (%zu bytes) =-\n", name, length); od_hex_dump(buf, length, 0); }} -#define dtls_debug_dump(name, buf, length) { if (LOG_DEBUG <= LOG_LEVEL) { LOG_DEBUG("%s (%zu bytes):", name, length); od_hex_dump(buf, length, 0); }} +#define dtls_debug_hexdump(name, buf, length) { if (LOG_DEBUG <= LOG_LEVEL) { LOG_DEBUG("-= %s (%zu bytes) =-\n", name, (size_t)(length)); od_hex_dump(buf, length, 0); }} +#define dtls_debug_dump(name, buf, length) { if (LOG_DEBUG <= LOG_LEVEL) { LOG_DEBUG("%s (%zu bytes):", name, (size_t)(length)); od_hex_dump(buf, length, 0); }} #else /* neither RIOT nor Zephyr */ #define dtls_emerg(...) dsrv_log(DTLS_LOG_EMERG, __VA_ARGS__) #define dtls_alert(...) dsrv_log(DTLS_LOG_ALERT, __VA_ARGS__) diff --git a/ext/micro-ecc b/ext/micro-ecc new file mode 160000 index 00000000..fe8ed90a --- /dev/null +++ b/ext/micro-ecc @@ -0,0 +1 @@ +Subproject commit fe8ed90abc356347378eb25e2586e90df7be015a diff --git a/global.h b/global.h index d915aed1..347c1c9e 100644 --- a/global.h +++ b/global.h @@ -93,6 +93,7 @@ typedef enum { #define TLS_EXT_SERVER_CERTIFICATE_TYPE 20 /* see RFC 7250 */ #define TLS_EXT_ENCRYPT_THEN_MAC 22 /* see RFC 7366 */ #define TLS_EXT_EXTENDED_MASTER_SECRET 23 /* see RFC 7627 */ +#define TLS_EXT_CONNECTION_ID 54 /* see RFC 9146 */ #define TLS_EXT_RENEGOTIATION_INFO 65281 /* see RFC 5746 */ #define TLS_CERT_TYPE_RAW_PUBLIC_KEY 2 /* see RFC 7250 */ diff --git a/tests/Makefile.in b/tests/Makefile.in index f7ef52ec..efae2b1f 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -32,13 +32,13 @@ SOURCES:= dtls-server.c ccm-test.c \ #cbc_aes128-test.c #dsrv-test.c OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) PROGRAMS:= dtls-server dtls-client ccm-test -HEADERS:= +HEADERS:=dtls_ciphers_util.h CFLAGS:=-Wall -std=c99 @CFLAGS@ @WARNING_CFLAGS@ $(EXTRA_CFLAGS) -D_POSIX_C_SOURCE=200112L CPPFLAGS:=-I$(top_srcdir) @CPPFLAGS@ LDFLAGS:=-L$(top_builddir) @LDFLAGS@ LDLIBS:=$(top_srcdir)/libtinydtls.a @LIBS@ DISTDIR=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@ -FILES:=Makefile.in $(SOURCES) ccm-testdata.c #cbc_aes128-testdata.c +FILES:=Makefile.in $(SOURCES) $(HEADERS) ccm-testdata.c .PHONY: all dirs clean distclean .gitignore doc install uninstall diff --git a/tests/dtls-client.c b/tests/dtls-client.c index bb27367b..4e95a5a2 100644 --- a/tests/dtls-client.c +++ b/tests/dtls-client.c @@ -69,7 +69,9 @@ static dtls_context_t *orig_dtls_context = NULL; static const dtls_cipher_t* ciphers = NULL; static unsigned int force_extended_master_secret = 0; static unsigned int force_renegotiation_info = 0; - +#if (DTLS_MAX_CID_LENGTH > 0) +static unsigned int support_cid = 0; +#endif #ifdef DTLS_ECC static const unsigned char ecdsa_priv_key[] = { @@ -246,6 +248,9 @@ get_user_parameters(struct dtls_context_t *ctx, (void) session; user_parameters->force_extended_master_secret = force_extended_master_secret; user_parameters->force_renegotiation_info = force_renegotiation_info; +#if (DTLS_MAX_CID_LENGTH > 0) + user_parameters->support_cid = support_cid; +#endif if (ciphers) { int i = 0; while (i < DTLS_MAX_CIPHER_SUITES) { @@ -359,14 +364,19 @@ usage( const char *program, const char *version) { program = ++p; fprintf(stderr, "%s v%s -- DTLS client implementation\n" - "(c) 2011-2014 Olaf Bergmann \n\n" + "(c) 2011-2024 Olaf Bergmann \n\n" + "usage: %s [-c cipher suites] [-e] " #ifdef DTLS_PSK - "usage: %s [-c cipher suites] [-e] [-i file] [-k file] [-o file]\n" - " %*s [-p port] [-r] [-v num] addr [port]\n", + "[-i file] [-k file] [-o file]\n" + " %*s [-p port] [-r] [-v num]" #else /* DTLS_PSK */ - "usage: %s [-c cipher suites] [-e] [-o file] [-p port] [-r]\n" - " %*s [-v num] addr [port]\n", + "[-o file] [-p port] [-r]\n" + " %*s [-v num]" #endif /* DTLS_PSK */ +#if (DTLS_MAX_CID_LENGTH > 0) + " [-z]" +#endif /* DTLS_MAX_CID_LENGTH > 0*/ + " addr [port]\n", program, version, program, (int)strlen(program), ""); cipher_suites_usage(stderr, "\t"); fprintf(stderr, "\t-e\t\tforce extended master secret (RFC7627)\n" @@ -376,9 +386,14 @@ usage( const char *program, const char *version) { #endif /* DTLS_PSK */ "\t-o file\t\toutput received data to this file\n" "\t \t\t(use '-' for STDOUT)\n" - "\t-p port\t\tlisten on specified port (default is %d)\n" + "\t-p port\t\tlisten on specified port\n" + "\t \t\t(default is an ephemeral free port).\n" "\t-r\t\tforce renegotiation info (RFC5746)\n" - "\t-v num\t\tverbosity level (default: 3)\n", + "\t-v num\t\tverbosity level (default: 3)\n" +#if (DTLS_MAX_CID_LENGTH > 0) + "\t-z\t\tsupport CID (RFC9146)\n" +#endif /* DTLS_MAX_CID_LENGTH > 0*/ + "\tDefault destination port: %d\n", DEFAULT_PORT); } @@ -411,21 +426,23 @@ int main(int argc, char **argv) { fd_set rfds, wfds; struct timeval timeout; - unsigned short port = DEFAULT_PORT; - char port_str[NI_MAXSERV] = "0"; + unsigned short dst_port = 0; + unsigned short local_port = 0; log_t log_level = DTLS_LOG_WARN; int fd; ssize_t result; int on = 1; int opt, res; session_t dst; + session_t listen; char buf[200]; size_t len = 0; int buf_ready = 0; + memset(&dst, 0, sizeof(session_t)); + memset(&listen, 0, sizeof(session_t)); dtls_init(); - snprintf(port_str, sizeof(port_str), "%d", port); #ifdef DTLS_PSK psk_id_length = strlen(PSK_DEFAULT_IDENTITY); @@ -434,7 +451,8 @@ main(int argc, char **argv) { memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); #endif /* DTLS_PSK */ - while ((opt = getopt(argc, argv, "c:eo:p:rv:" PSK_OPTIONS)) != -1) { + while (optind < argc) { + opt = getopt(argc, argv, "c:eo:p:rv:z" PSK_OPTIONS); switch (opt) { #ifdef DTLS_PSK case 'i' : @@ -473,8 +491,7 @@ main(int argc, char **argv) { } break; case 'p' : - strncpy(port_str, optarg, NI_MAXSERV-1); - port_str[NI_MAXSERV - 1] = '\0'; + local_port = atoi(optarg); break; case 'r' : force_renegotiation_info = 1; @@ -482,31 +499,53 @@ main(int argc, char **argv) { case 'v' : log_level = strtol(optarg, NULL, 10); break; +#if (DTLS_MAX_CID_LENGTH > 0) + case 'z' : + support_cid = 1; + break; +#endif /* DTLS_MAX_CID_LENGTH > 0*/ + case -1 : + /* handle arguments */ + if (!dst.size) { + /* first argument: destination address */ + /* resolve destination address where server should be sent */ + res = resolve_address(argv[optind++], &dst.addr.sa); + if (res < 0) { + dtls_emerg("failed to resolve address\n"); + exit(-1); + } + dst.size = res; + } else if (!dst_port) { + /* second argument: destination port (optional) */ + dst_port = atoi(argv[optind++]); + } else { + dtls_warn("too many arguments!\n"); + usage(argv[0], dtls_package_version()); + exit(1); + } + break; default: usage(argv[0], dtls_package_version()); exit(1); } } - dtls_set_log_level(log_level); - - if (argc <= optind) { + if (!dst.size) { + dtls_warn("missing destination address!\n"); usage(argv[0], dtls_package_version()); exit(1); } - - memset(&dst, 0, sizeof(session_t)); - /* resolve destination address where server should be sent */ - res = resolve_address(argv[optind++], &dst.addr.sa); - if (res < 0) { - dtls_emerg("failed to resolve address\n"); - exit(-1); + if (!dst_port) { + /* destination port not provided, use default */ + dst_port = DEFAULT_PORT; + } + if (dst.addr.sa.sa_family == AF_INET6) { + dst.addr.sin6.sin6_port = htons(dst_port); + } else { + dst.addr.sin.sin_port = htons(dst_port); } - dst.size = res; - /* use port number from command line when specified or the listen - port, otherwise */ - dst.addr.sin.sin_port = htons(atoi(optind < argc ? argv[optind++] : port_str)); + dtls_set_log_level(log_level); /* init socket and set it to non-blocking */ fd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0); @@ -542,6 +581,24 @@ main(int argc, char **argv) { } } + if (local_port) { + listen.addr = dst.addr; + listen.size = dst.size; + if (listen.addr.sa.sa_family == AF_INET6) { + listen.addr.sin6.sin6_addr = in6addr_any; + listen.addr.sin6.sin6_port = htons(local_port); + dtls_info("bind to local IPv6 port %u\n", local_port); + } else { + listen.addr.sin.sin_addr.s_addr = INADDR_ANY; + listen.addr.sin.sin_port = htons(local_port); + dtls_info("bind to local IPv4 port %u\n", local_port); + } + if (bind(fd, (struct sockaddr *)&listen.addr.sa, listen.size) < 0) { + dtls_alert("bind: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + } + if (signal(SIGINT, dtls_handle_signal) == SIG_ERR) { dtls_alert("An error occurred while setting a signal handler.\n"); return EXIT_FAILURE; diff --git a/tests/dtls-server.c b/tests/dtls-server.c index 1a471475..fa684d4d 100644 --- a/tests/dtls-server.c +++ b/tests/dtls-server.c @@ -308,7 +308,7 @@ usage(const char *program, const char *version) { program = ++p; fprintf(stderr, "%s v%s -- DTLS server implementation\n" - "(c) 2011-2014 Olaf Bergmann \n\n" + "(c) 2011-2024 Olaf Bergmann \n\n" "usage: %s [-A address] [-c cipher suites] [-e] [-p port] [-r] [-v num]\n" "\t-A address\t\tlisten on specified address (default is ::)\n", program, version, program); @@ -386,6 +386,11 @@ main(int argc, char **argv) { exit(1); } } + if (argc != optind) { + dtls_warn("no arguments supported!\n"); + usage(argv[0], dtls_package_version()); + exit(1); + } listen_addr.sin6_port = port; dtls_set_log_level(log_level); diff --git a/tests/unit-tests/Makefile.in b/tests/unit-tests/Makefile.in index 8c24c91c..756161cc 100644 --- a/tests/unit-tests/Makefile.in +++ b/tests/unit-tests/Makefile.in @@ -26,7 +26,7 @@ top_builddir = @top_builddir@ top_srcdir:= @top_srcdir@ # files and flags -UNITS= test_ccm.c test_ecc.c test_prf.c +UNITS= test_ccm.c test_prf.c SOURCES:= $(UNITS) PROGRAM:=testdriver OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) @@ -36,7 +36,7 @@ CPPFLAGS:=-I$(top_srcdir) @CPPFLAGS@ LDFLAGS:=-L$(top_builddir) @LDFLAGS@ LDLIBS:=$(top_srcdir)/libtinydtls.a @CUNIT_LIBS@ @LIBS@ DISTDIR=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@ -FILES:=Makefile.in $(SOURCES) +FILES:=Makefile.in $(SOURCES) $(HEADERS) .PHONY: all dirs clean distclean check diff --git a/tests/unit-tests/testdriver.c b/tests/unit-tests/testdriver.c index 17be7533..998ab51b 100644 --- a/tests/unit-tests/testdriver.c +++ b/tests/unit-tests/testdriver.c @@ -4,7 +4,6 @@ #include #include "test_ccm.h" -#include "test_ecc.h" #include "test_prf.h" #include "tinydtls.h" @@ -18,7 +17,6 @@ int main(void) { } t_init_ccm_tests(); - t_init_ecc_tests(); t_init_prf_tests(); CU_basic_set_mode(run_mode);