From 2e7cb35c01d280a40bbeece949f3f6234aba19fe Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Sat, 11 Nov 2023 10:28:27 +0000 Subject: [PATCH] WebSocket: Add support for noTLS and TinyDTLS Use SHA1 code from RFC3174 sections 7.1 and 7.2. --- CMakeLists.txt | 1 + LICENSE | 34 ++ Makefile.am | 2 + examples/lwip/Makefile | 5 +- examples/lwip/client-coap.c | 4 + examples/lwip/config/lwippools.h | 4 + examples/riot/pkg_libcoap/Makefile.libcoap | 1 + include/coap3/coap_internal.h | 1 + include/coap3/coap_sha1_internal.h | 111 ++++++ src/coap_io_contiki.c | 63 ++++ src/coap_notls.c | 19 +- src/coap_sha1.c | 394 +++++++++++++++++++++ src/coap_tcp.c | 2 +- src/coap_tinydtls.c | 19 +- src/coap_ws.c | 9 +- win32/libcoap.vcxproj | 2 + win32/libcoap.vcxproj.filters | 6 + 17 files changed, 663 insertions(+), 14 deletions(-) create mode 100644 include/coap3/coap_sha1_internal.h create mode 100644 src/coap_sha1.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9090c2165b..deeeb939c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,6 +678,7 @@ target_sources( ${CMAKE_CURRENT_LIST_DIR}/src/coap_prng.c ${CMAKE_CURRENT_LIST_DIR}/src/coap_resource.c ${CMAKE_CURRENT_LIST_DIR}/src/coap_session.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_sha1.c ${CMAKE_CURRENT_LIST_DIR}/src/coap_str.c ${CMAKE_CURRENT_LIST_DIR}/src/coap_subscribe.c ${CMAKE_CURRENT_LIST_DIR}/src/coap_tcp.c diff --git a/LICENSE b/LICENSE index dee4568769..53a0aae8f8 100644 --- a/LICENSE +++ b/LICENSE @@ -115,6 +115,40 @@ When compiled with Mbed TLS support, this software includes components that are licensed under the terms of the Apache 2.0 license (http://www.apache.org/licenses/LICENSE-2.0). +======================================================================== +SHA1 + +SHA1 support is taken from RFC3174 Sections 7.1 and 7.2 for use with +WebSockets. + +Full Copyright Statement + +Copyright (C) The Internet Society (2001). All Rights Reserved. + +This document and translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it +or assist in its implementation may be prepared, copied, published +and distributed, in whole or in part, without restriction of any +kind, provided that the above copyright notice and this paragraph are +included on all such copies and derivative works. However, this +document itself may not be modified in any way, such as by removing +the copyright notice or references to the Internet Society or other +Internet organizations, except as needed for the purpose of +developing Internet standards in which case the procedures for +copyrights defined in the Internet Standards process must be +followed, or as required to translate it into languages other than +English. + +The limited permissions granted above are perpetual and will not be +revoked by the Internet Society or its successors or assigns. + +This document and the information contained herein is provided on an +"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING +TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION +HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + ======================================================================== RIOT diff --git a/Makefile.am b/Makefile.am index 1dbd0528ee..a0d67fb0ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -112,6 +112,7 @@ EXTRA_DIST = \ include/coap$(LIBCOAP_API_VERSION)/coap_pdu_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_resource_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_session_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_sha1_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_subscribe_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_tcp_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_uri_internal.h \ @@ -209,6 +210,7 @@ libcoap_@LIBCOAP_NAME_SUFFIX@_la_SOURCES = \ src/coap_prng.c \ src/coap_resource.c \ src/coap_session.c \ + src/coap_sha1.c \ src/coap_str.c \ src/coap_subscribe.c \ src/coap_tcp.c \ diff --git a/examples/lwip/Makefile b/examples/lwip/Makefile index ca3d2f3120..3d657cc721 100644 --- a/examples/lwip/Makefile +++ b/examples/lwip/Makefile @@ -168,10 +168,11 @@ COAP_SRC = coap_address.c \ coap_pdu.c \ coap_resource.c \ coap_session.c \ - coap_subscribe.c \ - coap_tinydtls.c \ + coap_sha1.c \ coap_str.c \ + coap_subscribe.c \ coap_tcp.c \ + coap_tinydtls.c \ coap_uri.c \ coap_ws.c diff --git a/examples/lwip/client-coap.c b/examples/lwip/client-coap.c index 6887e09704..34438b32b8 100644 --- a/examples/lwip/client-coap.c +++ b/examples/lwip/client-coap.c @@ -199,6 +199,10 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg, LWIP_ASSERT("Failed to create session", session != NULL); + if (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS) { + coap_ws_set_host_request(session, &uri.host); + } + coap_register_response_handler(main_coap_context, message_handler); coap_register_nack_handler(main_coap_context, nack_handler); diff --git a/examples/lwip/config/lwippools.h b/examples/lwip/config/lwippools.h index eef70b75d7..55bbbfd04d 100644 --- a/examples/lwip/config/lwippools.h +++ b/examples/lwip/config/lwippools.h @@ -100,11 +100,15 @@ typedef struct l_coap_tiny_context_t { #endif #ifndef MEMP_LEN_COAPSTRING +#ifdef COAP_WS_SUPPORT +#define MEMP_LEN_COAPSTRING 176 +#else /* ! COAP_WS_SUPPORT */ #ifdef COAP_WITH_LIBTINYDTLS #define MEMP_LEN_COAPSTRING 120 #else /* COAP_WITH_TINYDTLS */ #define MEMP_LEN_COAPSTRING 40 #endif /* COAP_WITH_TINYDTLS */ +#endif /* ! COAP_WS_SUPPORT */ #endif #ifndef MEMP_NUM_COAPCACHE_KEYS diff --git a/examples/riot/pkg_libcoap/Makefile.libcoap b/examples/riot/pkg_libcoap/Makefile.libcoap index c9d2b5e5a9..b9091a4ad4 100644 --- a/examples/riot/pkg_libcoap/Makefile.libcoap +++ b/examples/riot/pkg_libcoap/Makefile.libcoap @@ -26,6 +26,7 @@ SRC := coap_address.c \ coap_prng.c \ coap_resource.c \ coap_session.c \ + coap_sha1.c \ coap_str.c \ coap_subscribe.c \ coap_tcp.c \ diff --git a/include/coap3/coap_internal.h b/include/coap3/coap_internal.h index 2f332686b3..407cbc1efb 100644 --- a/include/coap3/coap_internal.h +++ b/include/coap3/coap_internal.h @@ -118,6 +118,7 @@ typedef struct oscore_ctx_t oscore_ctx_t; #include "coap_pdu_internal.h" #include "coap_resource_internal.h" #include "coap_session_internal.h" +#include "coap_sha1_internal.h" #include "coap_subscribe_internal.h" #include "coap_tcp_internal.h" #include "coap_uri_internal.h" diff --git a/include/coap3/coap_sha1_internal.h b/include/coap3/coap_sha1_internal.h new file mode 100644 index 0000000000..e6d99e64fd --- /dev/null +++ b/include/coap3/coap_sha1_internal.h @@ -0,0 +1,111 @@ +/* + * coap_sha1_internal.h + * + * Full Copyright Statement RFC3174 + * + * ======================================================================= + * + * Copyright (C) The Internet Society (2001). All Rights Reserved. + * + * This document and translations of it may be copied and furnished to + * others, and derivative works that comment on or otherwise explain it + * or assist in its implementation may be prepared, copied, published + * and distributed, in whole or in part, without restriction of any + * kind, provided that the above copyright notice and this paragraph are + * included on all such copies and derivative works. However, this + * document itself may not be modified in any way, such as by removing + * the copyright notice or references to the Internet Society or other + * Internet organizations, except as needed for the purpose of + * developing Internet standards in which case the procedures for + * copyrights defined in the Internet Standards process must be + * followed, or as required to translate it into languages other than + * English. + * + * The limited permissions granted above are perpetual and will not be + * revoked by the Internet Society or its successors or assigns. + * + * This document and the information contained herein is provided on an + * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * ======================================================================= + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3174#section-7.1 + * Reformatted as appropriate. + * + */ + +#ifndef COAP_SHA1_INTERNAL_H_ +#define COAP_SHA1_INTERNAL_H_ + +/** + * @file coap_sha1_internal.h + * @brief Provides SHA1 support for WebSockets + */ + +#include +/* + * If you do not have the ISO standard stdint.h header file, then you + * must typdef the following: + * name meaning + * uint32_t unsigned 32 bit integer + * uint8_t unsigned 8 bit integer (i.e., unsigned char) + * int_least16_t integer of >= 16 bits + * + */ + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif +#define SHA1HashSize 20 + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context { + uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ + + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ + + /* Index into message block array */ + int_least16_t Message_Block_Index; + uint8_t Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} SHA1Context; + +/* + * Function Prototypes + */ + +int SHA1Reset(SHA1Context *); +int SHA1Input(SHA1Context *, + const uint8_t *, + unsigned int); +int SHA1Result(SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); + +#endif /* COAP_SHA1_INTERNAL_H_ */ diff --git a/src/coap_io_contiki.c b/src/coap_io_contiki.c index 93bdd39076..db79e9e20c 100644 --- a/src/coap_io_contiki.c +++ b/src/coap_io_contiki.c @@ -252,3 +252,66 @@ coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) { coap_ticks(&now); return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); } + +#if ! COAP_DISABLE_TCP + +#if COAP_CLIENT_SUPPORT +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + (void)sock; + (void)local_if; + (void)server; + (void)default_port; + (void)local_addr; + (void)remote_addr; + + return -1; +} + +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + (void)sock; + (void)local_addr; + (void)remote_addr; + + return -1; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT + +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + (void)sock; + (void)listen_addr; + (void)bound_addr; + + return -1; +} + +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr, + void *extra) { + (void)server; + (void)new_client; + (void)local_addr; + (void)remote_addr; + (void)extra; + + return -1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#endif /* ! COAP_DISABLE_TCP */ diff --git a/src/coap_notls.c b/src/coap_notls.c index 4ee8642133..2aa41f2b9c 100644 --- a/src/coap_notls.c +++ b/src/coap_notls.c @@ -319,10 +319,23 @@ int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash) { + SHA1Context sha1_context; + coap_binary_t *dummy = NULL; + (void)alg; - (void)data; - (void)hash; - return 0; + + SHA1Reset(&sha1_context); + if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess) + return 0; + dummy = coap_new_binary(SHA1HashSize); + if (!dummy) + return 0; + if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) { + coap_delete_binary(dummy); + return 0; + } + *hash = (coap_bin_const_t *)(dummy); + return 1; } #endif /* COAP_WS_SUPPORT */ diff --git a/src/coap_sha1.c b/src/coap_sha1.c new file mode 100644 index 0000000000..fef9fde47f --- /dev/null +++ b/src/coap_sha1.c @@ -0,0 +1,394 @@ +/* + * coap_sha1.c + * + * Full Copyright Statement RFC3174 + * + * ======================================================================= + * + * Copyright (C) The Internet Society (2001). All Rights Reserved. + * + * This document and translations of it may be copied and furnished to + * others, and derivative works that comment on or otherwise explain it + * or assist in its implementation may be prepared, copied, published + * and distributed, in whole or in part, without restriction of any + * kind, provided that the above copyright notice and this paragraph are + * included on all such copies and derivative works. However, this + * document itself may not be modified in any way, such as by removing + * the copyright notice or references to the Internet Society or other + * Internet organizations, except as needed for the purpose of + * developing Internet standards in which case the procedures for + * copyrights defined in the Internet Standards process must be + * followed, or as required to translate it into languages other than + * English. + * + * The limited permissions granted above are perpetual and will not be + * revoked by the Internet Society or its successors or assigns. + * + * This document and the information contained herein is provided on an + * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * ======================================================================= + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3174#section-7.2 + * Reformatted as appropriate. + */ + +#include "coap3/coap_internal.h" + +#if COAP_WS_SUPPORT && !defined(COAP_WITH_LIBOPENSSL) && !defined(COAP_WITH_LIBGNUTLS) && !defined(COAP_WITH_LIBMBEDTLS) +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +void SHA1PadMessage(SHA1Context *); +void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int +SHA1Reset(SHA1Context *context) { + if (!context) { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int +SHA1Result(SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) { + int i; + + if (!context || !Message_Digest) { + return shaNull; + } + + if (context->Corrupted) { + return context->Corrupted; + } + + if (!context->Computed) { + SHA1PadMessage(context); + for (i=0; i<64; ++i) { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + } + + for (i = 0; i < SHA1HashSize; ++i) { + Message_Digest[i] = context->Intermediate_Hash[i>>2] + >> 8 * (3 - (i & 0x03)); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int +SHA1Input(SHA1Context *context, + const uint8_t *message_array, + unsigned length) { + if (!length) { + return shaSuccess; + } + + if (!context || !message_array) { + return shaNull; + } + + if (context->Computed) { + context->Corrupted = shaStateError; + return shaStateError; + } + + if (context->Corrupted) { + return context->Corrupted; + } + while (length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) { + context->Length_High++; + if (context->Length_High == 0) { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +void +SHA1ProcessMessageBlock(SHA1Context *context) { + const uint32_t K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = (uint32_t)(context->Message_Block[t * 4]) << 24; + W[t] |= (uint32_t)(context->Message_Block[t * 4 + 1]) << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for (t = 16; t < 80; t++) { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for (t = 0; t < 20; t++) { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + + +/* + * SHA1PadMessage + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +void +SHA1PadMessage(SHA1Context *context) { + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while (context->Message_Block_Index < 64) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } else { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while (context->Message_Block_Index < 56) { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = context->Length_High >> 24; + context->Message_Block[57] = context->Length_High >> 16; + context->Message_Block[58] = context->Length_High >> 8; + context->Message_Block[59] = context->Length_High; + context->Message_Block[60] = context->Length_Low >> 24; + context->Message_Block[61] = context->Length_Low >> 16; + context->Message_Block[62] = context->Length_Low >> 8; + context->Message_Block[63] = context->Length_Low; + + SHA1ProcessMessageBlock(context); +} +#endif /* COAP_WS_SUPPORT && !defined(COAP_WITH_LIBOPENSSL) && !defined(COAP_WITH_LIBGNUTLS) && !defined(COAP_WITH_LIBMBEDTLS) */ diff --git a/src/coap_tcp.c b/src/coap_tcp.c index f84f84a581..b7c92e431b 100644 --- a/src/coap_tcp.c +++ b/src/coap_tcp.c @@ -38,7 +38,7 @@ coap_tcp_is_supported(void) { return !COAP_DISABLE_TCP; } -#if !COAP_DISABLE_TCP && !defined(WITH_LWIP) +#if !COAP_DISABLE_TCP && !defined(WITH_LWIP) && !defined(WITH_CONTIKI) int coap_socket_connect_tcp1(coap_socket_t *sock, const coap_address_t *local_if, diff --git a/src/coap_tinydtls.c b/src/coap_tinydtls.c index 69dbffd80a..06e7826ab4 100644 --- a/src/coap_tinydtls.c +++ b/src/coap_tinydtls.c @@ -1490,10 +1490,23 @@ int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash) { + SHA1Context sha1_context; + coap_binary_t *dummy = NULL; + (void)alg; - (void)data; - (void)hash; - return 0; + + SHA1Reset(&sha1_context); + if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess) + return 0; + dummy = coap_new_binary(SHA1HashSize); + if (!dummy) + return 0; + if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) { + coap_delete_binary(dummy); + return 0; + } + *hash = (coap_bin_const_t *)(dummy); + return 1; } #endif /* COAP_WS_SUPPORT */ diff --git a/src/coap_ws.c b/src/coap_ws.c index 659c71f684..c97106af2b 100644 --- a/src/coap_ws.c +++ b/src/coap_ws.c @@ -36,12 +36,7 @@ int coap_ws_is_supported(void) { -#if defined(COAP_WITH_LIBOPENSSL) || defined(COAP_WITH_LIBGNUTLS) || defined(COAP_WITH_LIBMBEDTLS) - /* Have SHA1 hash support */ return coap_tcp_is_supported(); -#else /* !COAP_WITH_LIBOPENSSL && !COAP_WITH_LIBGNUTLS && !COAP_WITH_LIBMBEDTLS */ - return 0; -#endif /* !COAP_WITH_LIBOPENSSL && !COAP_WITH_LIBGNUTLS && !COAP_WITH_LIBMBEDTLS */ } int @@ -857,7 +852,9 @@ coap_ws_close(coap_session_t *session) { return; } if (session->ws && session->ws->up) { +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) int count; +#endif /* ! WITH_LWIP && ! WITH_CONTIKI */ if (!session->ws->sent_close) { size_t hdr_len = 2; @@ -891,6 +888,7 @@ coap_ws_close(coap_session_t *session) { return; } } +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) count = 5; while (!session->ws->recv_close && count > 0 && coap_netif_available(session)) { uint8_t buf[100]; @@ -911,6 +909,7 @@ coap_ws_close(coap_session_t *session) { } count --; } +#endif /* ! WITH_LWIP && ! WITH_CONTIKI */ coap_handle_event(session->context, COAP_EVENT_WS_CLOSED, session); } session->sock.lfunc[COAP_LAYER_WS].l_close(session); diff --git a/win32/libcoap.vcxproj b/win32/libcoap.vcxproj index 5f8548eee1..4c72bc7814 100644 --- a/win32/libcoap.vcxproj +++ b/win32/libcoap.vcxproj @@ -63,6 +63,7 @@ + @@ -109,6 +110,7 @@ + diff --git a/win32/libcoap.vcxproj.filters b/win32/libcoap.vcxproj.filters index aac92c7e0a..0990372132 100644 --- a/win32/libcoap.vcxproj.filters +++ b/win32/libcoap.vcxproj.filters @@ -83,6 +83,9 @@ Source Files + + Source Files + Source Files @@ -217,6 +220,9 @@ Header Files + + Header Files + Header Files