Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC8974: Add in support for Extended Tokens #938

Merged
merged 1 commit into from
Feb 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
33 changes: 22 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 @@ -537,7 +545,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 @@ -936,9 +944,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 @@ -1812,6 +1820,8 @@ main(int argc, char **argv) {
coap_register_response_handler(ctx, message_handler);
coap_register_event_handler(ctx, event_handler);
coap_register_nack_handler(ctx, nack_handler);
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,
Expand All @@ -1832,8 +1842,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 @@ -2108,7 +2109,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 @@ -2164,6 +2165,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 @@ -2626,6 +2628,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 @@ -2656,7 +2672,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 @@ -2762,13 +2778,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 @@ -2827,6 +2846,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
15 changes: 12 additions & 3 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 @@ -102,7 +108,7 @@
*
* allocated buffer always starts max_hdr_size before token.
*
* options starts at token + token_length.
* options starts at token + e_token_length.
* payload starts at data, its length is used_size - (data - token).
*
* alloc_size, used_size and max_size are the offsets from token.
Expand All @@ -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 e_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