Skip to content

Commit

Permalink
RFC8974: Add in support for Extended Tokens
Browse files Browse the repository at this point in the history
Add in new function coap_context_set_max_token_size() to define
the maximum supported token size.

Track changes to PDU to support extended tokens.

Update documentation.
  • Loading branch information
mrdeep1 committed Jan 14, 2023
1 parent 7fab8aa commit 31592d9
Show file tree
Hide file tree
Showing 31 changed files with 724 additions and 243 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC8974: Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries
Expand Down
2 changes: 2 additions & 0 deletions doc/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC8974: Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries
Expand Down
34 changes: 23 additions & 11 deletions examples/coap-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ strndup(const char* s1, size_t n) {

int flags = 0;

static unsigned char _token_data[8];
coap_binary_t base_token = { 0, _token_data };
static unsigned char _token_data[24]; /* With support for RFC8974 */
coap_binary_t the_token = { 0, _token_data };

typedef struct {
coap_binary_t *token;
Expand Down Expand Up @@ -271,11 +271,19 @@ coap_new_request(coap_context_t *ctx,

/*
* Create unique token for this request for handling unsolicited /
* delayed responses
* delayed responses.
* Note that only up to 8 bytes are returned
*/
coap_session_new_token(session, &tokenlen, token);
track_new_token(tokenlen, token);
if (!coap_add_token(pdu, tokenlen, token)) {
if (the_token.length > COAP_TOKEN_DEFAULT_MAX) {
coap_session_new_token(session, &tokenlen, token);
/* Update the last part 8 bytes of the large token */
memcpy(&the_token.s[the_token.length - tokenlen], token, tokenlen);
}
else {
coap_session_new_token(session, &the_token.length, the_token.s);
}
track_new_token(the_token.length, the_token.s);
if (!coap_add_token(pdu, the_token.length, the_token.s)) {
coap_log_debug("cannot add token to request\n");
}

Expand Down Expand Up @@ -585,7 +593,7 @@ usage(const char *program, const char *version) {
"\t \t\tconnect to a CoAP proxy (automatically adds Proxy-Uri\n"
"\t \t\toption to request) to forward the request to.\n"
"\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n"
"\t-T token\tDefine the initial starting token\n"
"\t-T token\tDefine the initial starting token (up to 24 characters)\n"
"\t-U \t\tNever include Uri-Host or Uri-Port options\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
Expand Down Expand Up @@ -984,9 +992,9 @@ cmdline_proxy(char *arg) {

static inline void
cmdline_token(char *arg) {
base_token.length = min(sizeof(_token_data), strlen(arg));
if (base_token.length > 0) {
memcpy((char *)base_token.s, arg, base_token.length);
the_token.length = min(sizeof(_token_data), strlen(arg));
if (the_token.length > 0) {
memcpy((char *)the_token.s, arg, the_token.length);
}
}

Expand Down Expand Up @@ -1828,6 +1836,9 @@ main(int argc, char **argv) {
dst.size = res;
dst.addr.sin.sin_port = htons( port );

if (the_token.length > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, the_token.length);

session = get_session(
ctx,
node_str[0] ? node_str : NULL, port_str,
Expand All @@ -1851,8 +1862,9 @@ main(int argc, char **argv) {
* Prime the base token value, which coap_session_new_token() will increment
* every time it is called to get an unique token.
* [Option '-T token' is used to seed a different value]
* Note that only the first 8 bytes of the token are used as the prime.
*/
coap_session_init_token(session, base_token.length, base_token.s);
coap_session_init_token(session, the_token.length, the_token.s);

/* add Uri-Host if server address differs from uri.host */

Expand Down
33 changes: 28 additions & 5 deletions examples/coap-rd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static uint8_t key[MAX_KEY];
static ssize_t key_length = 0;
static int key_defined = 0;
static const char *hint = "CoAP";
static size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX;

#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
Expand Down Expand Up @@ -583,7 +584,7 @@ usage(const char *program, const char *version) {
fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer)));
fprintf(stderr, "\n"
"Usage: %s [-g group] [-G group_if] [-p port] [-v num] [-A address]\n"
"\t [-V num]\n"
"\t [-T max_token_size] [-V num]\n"
"\t [[-h hint] [-k key]]\n"
"\t [[-c certfile] [-C cafile] [-n] [-R trust_casfile]]\n"
"General Options\n"
Expand All @@ -596,6 +597,7 @@ usage(const char *program, const char *version) {
"\t-v num \t\tVerbosity level (default 4, maximum is 8) for general\n"
"\t \t\tCoAP logging\n"
"\t-A address\tInterface address to bind to\n"
"\t-T max_token_length\tSet the maximum token length (8-65804)\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
"PSK Options (if supported by underlying (D)TLS library)\n"
Expand Down Expand Up @@ -775,6 +777,20 @@ get_context(const char *node, const char *port) {
return ctx;
}

static int
cmdline_read_extended_token_size(char *arg) {
extended_token_size = strtoul(arg, NULL, 0);
if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) {
coap_log_err("Extended Token Length must be 8 or greater\n");
return 0;
}
else if (extended_token_size > COAP_TOKEN_EXT_MAX) {
coap_log_err("Extended Token Length must be 65804 or less\n");
return 0;
}
return 1;
}

int
main(int argc, char **argv) {
coap_context_t *ctx;
Expand All @@ -790,7 +806,7 @@ main(int argc, char **argv) {
struct sigaction sa;
#endif

while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:V:")) != -1) {
while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:T:V:")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -826,13 +842,18 @@ main(int argc, char **argv) {
case 'n':
verify_peer_cert = 0;
break;
case 'R' :
root_ca_file = optarg;
break;
case 'p' :
strncpy(port_str, optarg, NI_MAXSERV-1);
port_str[NI_MAXSERV - 1] = '\0';
break;
case 'R' :
root_ca_file = optarg;
break;
case 'T':
if (!cmdline_read_extended_token_size(optarg)) {
exit(1);
}
break;
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
Expand All @@ -857,6 +878,8 @@ main(int argc, char **argv) {
coap_join_mcast_group_intf(ctx, group, group_if);

init_resources(ctx);
if (extended_token_size > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, extended_token_size);

#ifdef _WIN32
signal(SIGINT, handle_sigint);
Expand Down
29 changes: 25 additions & 4 deletions examples/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ static int support_dynamic = 0;
static uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP;
static int echo_back = 0;
static uint32_t csm_max_message_size = 0;
static size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX;

static coap_dtls_pki_t *
setup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *sni);
Expand Down Expand Up @@ -2151,7 +2152,7 @@ usage( const char *program, const char *version) {
"Usage: %s [-d max] [-e] [-g group] [-l loss] [-p port] [-r] [-v num]\n"
"\t\t[-A address] [-E oscore_conf_file[,seq_file]] [-G group_if]\n"
"\t\t[-L value] [-N] [-P scheme://address[:port],[name1[,name2..]]]\n"
"\t\t[-V num] [-X size]\n"
"\t\t[-T max_token_size] [-V num] [-X size]\n"
"\t\t[[-h hint] [-i match_identity_file] [-k key]\n"
"\t\t[-s match_psk_sni_file] [-u user]]\n"
"\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-C cafile]\n"
Expand Down Expand Up @@ -2207,6 +2208,7 @@ usage( const char *program, const char *version) {
"\t \t\tdefined before the leading , (comma) of the first name,\n"
"\t \t\tthen the ongoing connection will be a direct connection.\n"
"\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n"
"\t-T max_token_length\tSet the maximum token length (8-65804)\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
"\t-X size\t\tMaximum message size to use for TCP based connections\n"
Expand Down Expand Up @@ -2680,6 +2682,20 @@ cmdline_read_pki_sni_check(char *arg) {
return valid_pki_snis.count > 0;
}

static int
cmdline_read_extended_token_size(char *arg) {
extended_token_size = strtoul(arg, NULL, 0);
if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) {
coap_log_err("Extended Token Length must be 8 or greater\n");
return 0;
}
else if (extended_token_size > COAP_TOKEN_EXT_MAX) {
coap_log_err("Extended Token Length must be 65804 or less\n");
return 0;
}
return 1;
}

int
main(int argc, char **argv) {
coap_context_t *ctx;
Expand Down Expand Up @@ -2710,7 +2726,7 @@ main(int argc, char **argv) {

clock_offset = time(NULL);

while ((opt = getopt(argc, argv, "c:d:eg:G:h:i:j:J:k:l:mnp:rs:u:v:A:C:E:L:M:NP:R:S:V:X:")) != -1) {
while ((opt = getopt(argc, argv, "c:d:eg:G:h:i:j:J:k:l:mnp:rs:u:v:A:C:E:L:M:NP:R:S:T:V:X:")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -2816,13 +2832,16 @@ main(int argc, char **argv) {
break;
case 's':
if (!cmdline_read_psk_sni_check(optarg)) {
usage(argv[0], LIBCOAP_PACKAGE_VERSION);
exit(1);
}
break;
case 'S':
if (!cmdline_read_pki_sni_check(optarg)) {
usage(argv[0], LIBCOAP_PACKAGE_VERSION);
exit(1);
}
break;
case 'T':
if (!cmdline_read_extended_token_size(optarg)) {
exit(1);
}
break;
Expand Down Expand Up @@ -2881,6 +2900,8 @@ main(int argc, char **argv) {
if (get_oscore_conf(ctx) == NULL)
goto finish;
}
if (extended_token_size > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, extended_token_size);

/* Define the options to ignore when setting up cache-keys */
coap_cache_ignore_options(ctx, cache_ignore_options,
Expand Down
4 changes: 1 addition & 3 deletions include/coap3/coap_block_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct coap_lg_crcv_t {
size_t total_len; /**< Length as indicated by SIZE2 option */
coap_binary_t *body_data; /**< Used for re-assembling entire body */
coap_binary_t *app_token; /**< app requesting PDU token */
coap_binary_t **obs_token; /**< Tokens used in setting up Observe
coap_bin_const_t **obs_token; /**< Tokens used in setting up Observe
(to handle large FETCH) */
size_t obs_token_cnt; /**< number of tokens used to set up Observe */
uint64_t state_token; /**< state token */
Expand Down Expand Up @@ -153,8 +153,6 @@ struct coap_lg_srcv_t {
coap_resource_t *resource; /**< associated resource */
coap_str_const_t *uri_path; /** set to uri_path if unknown resource */
coap_rblock_t rec_blocks; /** < list of received blocks */
uint8_t last_token[8]; /**< last used token */
size_t last_token_length; /**< length of token */
coap_mid_t last_mid; /**< Last received mid for this set of packets */
coap_tick_t last_used; /**< Last time data sent or 0 */
uint16_t block_option; /**< Block option in use */
Expand Down
5 changes: 2 additions & 3 deletions include/coap3/coap_net_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ struct coap_context_t {
when creating a cache-key */
#endif /* COAP_SERVER_SUPPORT */
void *app; /**< application-specific data */
uint32_t max_token_size; /**< Largest token size supported RFC8974 */
#ifdef COAP_EPOLL_SUPPORT
int epfd; /**< External FD for epoll */
int eptimerfd; /**< Internal FD for timeout */
Expand Down Expand Up @@ -274,12 +275,10 @@ coap_wait_ack( coap_context_t *context, coap_session_t *session,
* @param context The context in use.
* @param session Session of the messages to remove.
* @param token Message token.
* @param token_length Actual length of @p token.
*/
void coap_cancel_all_messages(coap_context_t *context,
coap_session_t *session,
const uint8_t *token,
size_t token_length);
coap_bin_const_t *token);

/**
* Cancels all outstanding messages for session @p session.
Expand Down
13 changes: 11 additions & 2 deletions include/coap3/coap_pdu_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
#define OSCORE_CRYPTO_BUFFER_SIZE (COAP_MAX_CHUNK_SIZE+16)
#endif /* HAVE_OSCORE */

/* Extended Token constants */
#define COAP_TOKEN_EXT_1B_TKL 13
#define COAP_TOKEN_EXT_2B_TKL 14
#define COAP_TOKEN_EXT_1B_BIAS 13
#define COAP_TOKEN_EXT_2B_BIAS 269 /* 13 + 256 */

#ifndef COAP_DEBUG_BUF_SIZE
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
#define COAP_DEBUG_BUF_SIZE 128
Expand Down Expand Up @@ -117,16 +123,19 @@ struct coap_pdu_t {
uint8_t max_hdr_size; /**< space reserved for protocol-specific header */
uint8_t hdr_size; /**< actual size used for protocol-specific
header (0 until header is encoded) */
uint8_t token_length; /**< length of Token */
uint8_t crit_opt; /**< Set if unknown critical option for proxy */
uint16_t max_opt; /**< highest option number in PDU */
uint32_t token_length; /**< length of Token space (includes leading
extended bytes */
coap_bin_const_t actual_token; /**< Actual token in pdu */
size_t alloc_size; /**< allocated storage for token, options and
payload */
size_t used_size; /**< used bytes of storage for token, options and
payload */
size_t max_size; /**< maximum size for token, options and payload,
or zero for variable size pdu */
uint8_t *token; /**< first byte of token, if any, or options */
uint8_t *token; /**< first byte of token (or extended length bytes
prefix), if any, or options */
uint8_t *data; /**< first byte of payload, if any */
#ifdef WITH_LWIP
struct pbuf *pbuf; /**< lwIP PBUF. The package data will always reside
Expand Down
14 changes: 14 additions & 0 deletions include/coap3/coap_session_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ typedef enum {
COAP_OSCORE_B_2_STEP_5,
} COAP_OSCORE_B_2_STEP;

/**
* coap_ext_token_check_t values
*/
typedef enum coap_ext_token_check_t {
COAP_EXT_T_NOT_CHECKED = 0, /**< Not checked */
COAP_EXT_T_CHECKED, /**< Token size valid */
COAP_EXT_T_CHECKING, /**< Token size check request sent */
} coap_ext_token_check_t;

/**
* Abstraction of virtual session that can be attached to coap_context_t
* (client) or coap_endpoint_t (server).
Expand Down Expand Up @@ -166,6 +175,11 @@ struct coap_session_t {
associations */
uint64_t oscore_r2; /**< R2 for RFC8613 Appendix B.2 */
#endif /* HAVE_OSCORE */
volatile uint8_t max_token_checked; /**< Check for max token size
coap_ext_token_check_t */
uint16_t max_token_mid; /**< mid used for checking ext token
support */
uint32_t max_token_size; /**< Largest token size supported RFC8974 */
uint64_t tx_token; /**< Next token number to use */
coap_bin_const_t *last_token; /** last token used to make a request */
coap_bin_const_t *echo; /**< Echo value to send with next request */
Expand Down
Loading

0 comments on commit 31592d9

Please sign in to comment.