Add Windows support

This commit is contained in:
Jan Romann
2022-02-27 15:15:42 +01:00
committed by Achim Kraus
parent 86f4988fc4
commit 9320251212
17 changed files with 210 additions and 25 deletions

View File

@@ -62,3 +62,15 @@ jobs:
run: |
cmake -Dmake_tests=ON .
make
build-windows:
name: Build for Windows using CMake
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Build tinydtls
run: |
cmake -G "Unix Makefiles" .
make

21
.gitignore vendored
View File

@@ -51,6 +51,7 @@ dtls_config.h
*.cooja
*.econotag
*.eval-adf7xxxmb4z
*.exe
*.exp5438
*.iris
*.mbxxx
@@ -70,3 +71,23 @@ dtls_config.h
CMakeCache.txt
cmake_install.cmake
CMakeFiles
# Windows build files
*.dll
# Visual Studio Build Files
*.VC.db*
.vs
*.obj
*.tlog
*.log
*.recipe
*.vcxproj
*.sln
*.pdb
*.vcxproj.user
*.vcxproj.filters
*.vcxproj.FileListAbsolute.txt
tinydtls.dir
Debug
Release

View File

@@ -31,7 +31,7 @@ option(make_tests "Make test programs and examples" OFF)
if(NOT PLATFORM)
# PLATFORM seems to be not used
set(PLATFORM "posix" CACHE STRING "Choose platform." FORCE)
set_property(CACHE PLATFORM PROPERTY STRINGS "contiki" "espidf" "posix" "riot" "zephyr")
set_property(CACHE PLATFORM PROPERTY STRINGS "contiki" "espidf" "posix" "riot" "zephyr" "windows")
endif()
set(PACKAGE_NAME "tinydtls")
@@ -64,7 +64,10 @@ target_sources(tinydtls PRIVATE
target_include_directories(tinydtls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
target_compile_definitions(tinydtls PUBLIC DTLSv12 WITH_SHA256 SHA2_USE_INTTYPES_H DTLS_CHECK_CONTENTTYPE)
if(NOT ZEPHYR_BASE)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
option(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS "Export all symbols when compiling to a .dll" ON)
target_compile_options(tinydtls PRIVATE -Wall)
elseif(NOT ZEPHYR_BASE)
target_compile_options(tinydtls PRIVATE -fPIC -pedantic -std=c99 -Wall -Wextra -Wformat-security -Winline -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wunused)
endif()

View File

@@ -18,6 +18,12 @@ C99. The following components are available:
# BUILDING
tinydtls supports multiple platforms, including both Real-time
and general-purpose Operating Systems. Below you find build instructions for
all supported environments.
## POSIX-oriented Operating Systems
When using the code from the git
[repository](https://github.com/eclipse/tinydtls) at GitHub, invoke
@@ -68,6 +74,39 @@ Available options:
| DTLS_ECC | enable/disable ECDHE_ECDSA cipher suites | ON |
| DTLS_PSK | enable/disable PSK cipher suites | ON |
## Windows
Using CMake, you can also build on and for Windows using either GCC or Visual
Studio.
Note, however, that the `make_tests` option is currently not supported when
compiling with Visual Studio, as parts of the tests rely on POSIX APIs.
For Visual Studio, you can apply the CMake instructions outlined above from the
command line or use the CMake GUI application.
In order to be able to use GCC, you need to specify a different generator than
the default.
For instance, you can use the `Unix Makefiles` generator, which creates a
Makefile for controlling the build process using GCC.
The example below leads to the output of a shared library file
`libtinydtls.dll`.
```
cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=ON .
make
```
Using MinGW64, you can also cross compile from a POSIX-oriented
platform for Windows using Autotools by providing a corresponding `--host`
argument:
```
./autogen.sh
./configure --host x86_64-w64-mingw32
make
mv libtinydtls.so libtinydtls.dll # Apply Windows file extension
```
# License
Copyright (c) 20112022 Olaf Bergmann (TZI) and others.

6
dtls.c
View File

@@ -213,7 +213,7 @@ static inline void free_context(dtls_context_t *context) {
}
#endif /* RIOT_VERSION */
#ifdef WITH_POSIX
#if defined(WITH_POSIX) || defined(IS_WINDOWS)
static inline dtls_context_t *
malloc_context(void) {
@@ -1610,9 +1610,11 @@ dtls_0_send_hello_verify_request(dtls_context_t *ctx,
dtls_ephemeral_peer_t *ephemeral_peer,
uint8 *data, size_t data_length)
{
uint8 buf[DTLS_RH_LENGTH + DTLS_HS_LENGTH + data_length];
uint8 buf[DTLS_RH_LENGTH + DTLS_HS_LENGTH + DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH];
uint8 *p = dtls_set_record_header(DTLS_CT_HANDSHAKE, 0, &(ephemeral_peer->rseq), buf);
assert(data_length == DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH);
/* Signal DTLS version 1.0 in the record layer of ClientHello and
* HelloVerifyRequest handshake messages according to Section 4.2.1
* of RFC 6347.

16
dtls.h
View File

@@ -341,8 +341,16 @@ void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
#define DTLS_CT_HANDSHAKE 22
#define DTLS_CT_APPLICATION_DATA 23
#ifdef __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#elif defined(_MSC_VER)
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#else
#error "Structure packing is not available for the used compiler."
#endif
/** Generic header structure of the DTLS record layer. */
typedef struct __attribute__((__packed__)) {
PACK(typedef struct) {
uint8 content_type; /**< content type of the included message */
uint16 version; /**< Protocol version */
uint16 epoch; /**< counter for cipher state changes */
@@ -371,7 +379,7 @@ typedef struct __attribute__((__packed__)) {
#define DTLS_HT_NO_OPTIONAL_MESSAGE -1
/** Header structure for the DTLS handshake protocol. */
typedef struct __attribute__((__packed__)) {
PACK(typedef struct) {
uint8 msg_type; /**< Type of handshake message (one of DTLS_HT_) */
uint24 length; /**< length of this message */
uint16 message_seq; /**< Message sequence number */
@@ -381,7 +389,7 @@ typedef struct __attribute__((__packed__)) {
} dtls_handshake_header_t;
/** Structure of the Client Hello message. */
typedef struct __attribute__((__packed__)) {
PACK(typedef struct) {
uint16 version; /**< Client version */
uint32 gmt_random; /**< GMT time of the random byte creation */
unsigned char random[28]; /**< Client random bytes */
@@ -392,7 +400,7 @@ typedef struct __attribute__((__packed__)) {
} dtls_client_hello_t;
/** Structure of the Hello Verify Request. */
typedef struct __attribute__((__packed__)) {
PACK(typedef struct) {
uint16 version; /**< Server version */
uint8 cookie_length; /**< Length of the included cookie */
uint8 cookie[]; /**< up to 32 bytes making up the cookie */

View File

@@ -222,12 +222,13 @@ dsrv_print_addr(const session_t *addr, char *buf, size_t len) {
#endif /* WITH_CONTIKI */
#ifdef RIOT_VERSION
#if defined(RIOT_VERSION) || defined(IS_WINDOWS)
/* FIXME: Switch to RIOT own DEBUG lines */
/* TODO: Check if inet_ntop can be used on Windows */
(void) addr;
(void) buf;
(void) len;
#endif /* RIOT_VERSION */
#endif /* RIOT_VERSION || IS_WINDOWS */
#ifdef WITH_POSIX
/* TODO: output addresses manually */
@@ -240,7 +241,7 @@ dsrv_print_addr(const session_t *addr, char *buf, size_t len) {
#endif /* NDEBUG */
#ifndef WITH_CONTIKI
#if !defined(WITH_CONTIKI) && !defined(_MSC_VER)
void
dsrv_log(log_t level, const char *format, ...) {
static char timebuf[32];

View File

@@ -78,11 +78,11 @@ void dtls_set_log_level(log_t level);
* level is below or equal to the log level that set by
* set_log_level(). */
#ifdef HAVE_VPRINTF
#if (defined(__GNUC__))
#if (defined(__GNUC__) && !defined(__MINGW32__))
void dsrv_log(log_t level, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
#else /* !__GNUC__ */
#else /* !__GNUC__ && !__MINGW32__ */
void dsrv_log(log_t level, const char *format, ...);
#endif /* !__GNUC__ */
#endif /* !__GNUC__ && !__MINGW32__ */
#else
#define dsrv_log(level, format, ...) PRINTF(format, ##__VA_ARGS__)
#endif

View File

@@ -42,10 +42,12 @@ typedef int dtls_mutex_t;
#define dtls_mutex_trylock(a) *(a) = 1
#define dtls_mutex_unlock(a) *(a) = 0
#elif defined(WITH_ZEPHYR)
#elif defined(WITH_ZEPHYR) || defined(IS_WINDOWS)
/* zephyr supports mutex, but this port doesn't use it */
// TODO: Add Windows compatible mutex definitions
typedef int dtls_mutex_t;
#define DTLS_MUTEX_INITIALIZER 0
#define dtls_mutex_lock(a) *(a) = 1
@@ -53,7 +55,7 @@ typedef int dtls_mutex_t;
#define dtls_mutex_unlock(a) *(a) = 0
#else /* ! RIOT_VERSION && ! WITH_CONTIKI && ! WITH_ZEPHYR */
#else /* ! RIOT_VERSION && ! WITH_CONTIKI && ! WITH_ZEPHYR && ! IS_WINDOWS */
#include <pthread.h>
@@ -63,6 +65,6 @@ typedef pthread_mutex_t dtls_mutex_t;
#define dtls_mutex_trylock(a) pthread_mutex_trylock(a)
#define dtls_mutex_unlock(a) pthread_mutex_unlock(a)
#endif /* ! RIOT_VERSION && ! WITH_CONTIKI */
#endif /* ! RIOT_VERSION && ! WITH_CONTIKI && ! IS_WINDOWS */
#endif /* _DTLS_MUTEX_H_ */

View File

@@ -30,6 +30,9 @@
#elif defined (WITH_ZEPHYR)
#include "platform-specific/dtls_prng_zephyr.c"
#elif defined (IS_WINDOWS)
#include "platform-specific/dtls_prng_win.c"
#elif defined (WITH_POSIX)
#include "platform-specific/dtls_prng_posix.c"

View File

@@ -22,6 +22,11 @@
#include "tinydtls.h"
#include "dtls_time.h"
#ifdef _MSC_VER
#include <time.h>
#include <windows.h>
#endif
#ifdef WITH_CONTIKI
clock_time_t dtls_clock_offset;
@@ -64,7 +69,7 @@ dtls_ticks(dtls_tick_t *t) {
*t = k_uptime_get();
}
#elif defined(WITH_POSIX)
#elif defined(WITH_POSIX) || defined(IS_WINDOWS)
time_t dtls_clock_offset;
@@ -88,6 +93,11 @@ void dtls_ticks(dtls_tick_t *t) {
gettimeofday(&tv, NULL);
*t = (tv.tv_sec - dtls_clock_offset) * DTLS_TICKS_PER_SECOND
+ (tv.tv_usec * DTLS_TICKS_PER_SECOND / 1000000);
#elif defined(_MSC_VER)
SYSTEMTIME current_time;
GetSystemTime(&current_time);
*t = (current_time.wSecond - dtls_clock_offset) * DTLS_TICKS_PER_SECOND
+ (current_time.wMilliseconds * DTLS_TICKS_PER_SECOND / 1000);
#else
#error "clock not implemented"
#endif

View File

@@ -39,6 +39,7 @@
//big number functions
#include "ecc.h"
#include <string.h>
#include <assert.h>
static uint32_t add( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length){
uint64_t d = 0; //carry
@@ -157,7 +158,8 @@ static int fieldSub(const uint32_t *x, const uint32_t *y, const uint32_t *modulu
//finite Field multiplication
//32bit * 32bit = 64bit
static int fieldMult(const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length){
uint32_t temp[length * 2];
uint32_t temp[(arrayLength + 1) * 2];
assert(length <= arrayLength + 1);
setZero(temp, length * 2);
setZero(result, length * 2);
uint8_t k, n;

View File

@@ -0,0 +1,50 @@
/*******************************************************************************
*
* Copyright (c) 2022 Jan Romann and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
*
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
*******************************************************************************/
#include "tinydtls.h"
#include "dtls_prng.h"
#include "dtls_debug.h"
#define _CRT_RAND_S
#include <stdlib.h>
#if defined(__MINGW32__)
/** Missing function declaration for rand_s under MingW. */
__declspec(dllimport) int __cdecl rand_s(unsigned int*);
#endif
/**
* Fills @p buf with @p len random bytes. Returns a non-zero
* value on error.
*/
int
dtls_prng(unsigned char *buf, size_t len) {
errno_t err;
unsigned int number;
size_t klen = len;
while (len--) {
err = rand_s(&number);
if (err != 0) {
dtls_emerg("PRNG failed\n");
return err;
}
*buf++ = number & 0xFF;
}
return klen;
}
void
dtls_prng_init(unsigned seed) {
srand(seed);
}

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
*
* Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others.
* Copyright (c) 2011-2022 Olaf Bergmann (TZI) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
@@ -64,7 +64,11 @@ typedef struct {
#undef read
typedef unsigned char uint8_t;
#else /* ! WITH_ZEPHYR && ! WITH_LWIP */
#elif defined(IS_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
#else /* ! WITH_ZEPHYR && ! WITH_LWIP && ! IS_WINDOWS */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

View File

@@ -48,6 +48,16 @@ extern "C" {
#include <sys/types.h>
#include "tinydtls.h"
#ifdef IS_WINDOWS
#include <stdint.h>
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
#endif
#ifdef SHA2_USE_INTTYPES_H
#include <inttypes.h>

View File

@@ -7,19 +7,27 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif /* HAVE_SYS_TIME_H */
#include <netdb.h>
#include <signal.h>
#include "tinydtls.h"
#include "dtls.h"
#include "dtls_debug.h"
#ifdef IS_WINDOWS
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define MSG_DONTWAIT 0
#define MSG_TRUNC 0
#else /* ! IS_WINDOWS */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif /* ! IS_WINDOWS */
#define DEFAULT_PORT 20220
static dtls_context_t *the_context = NULL;
@@ -277,7 +285,9 @@ main(int argc, char **argv) {
int on = 1;
int off = 0;
struct sockaddr_in6 listen_addr;
#ifndef IS_WINDOWS
struct sigaction sa;
#endif /* ! IS_WINDOWS */
uint16_t port = htons(DEFAULT_PORT);
memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
@@ -357,6 +367,7 @@ main(int argc, char **argv) {
dtls_init();
#ifndef IS_WINDOWS
memset (&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = dtls_handle_signal;
@@ -366,6 +377,7 @@ main(int argc, char **argv) {
/* So we do not exit on a SIGPIPE */
sa.sa_handler = SIG_IGN;
sigaction (SIGPIPE, &sa, NULL);
#endif /* ! IS_WINDOWS */
the_context = dtls_new_context(&fd);

View File

@@ -32,12 +32,18 @@
#include "platform-specific/platform.h"
#endif /* CONTIKI */
#if defined(_WIN32) || defined(_WIN64)
#define IS_WINDOWS 1
#endif
#ifndef CONTIKI
#ifndef RIOT_VERSION
#ifndef IS_WINDOWS
#ifndef WITH_POSIX
/* TODO: To remove in a future */
#define WITH_POSIX 1
#endif /* WITH_POSIX */
#endif /* IS_WINDOWS */
#include "dtls_config.h"
#endif /* RIOT_VERSION */
#endif /* CONTIKI */