Ethernet test for tinydtls-0.5.0
Dependencies: EthernetInterface mbed-rtos mbed tinydtls
Fork of tinydtls_test_ethernet by
Revision 1:391ec57807fa, committed 2013-10-10
- Comitter:
- ashleymills
- Date:
- Thu Oct 10 21:38:25 2013 +0000
- Parent:
- 0:6ae42a2aff75
- Child:
- 2:21019cad4c93
- Commit message:
- Ethernet test of tinydtls
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Thu Oct 10 21:38:25 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/ashleymills/code/EthernetInterface/#5140de325338
--- a/VodafoneUSBModem.lib Wed Oct 09 14:48:52 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_official/code/VodafoneUSBModem/#7b311719374d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bsd_socket.h Thu Oct 10 21:38:25 2013 +0000
@@ -0,0 +1,140 @@
+#ifndef BSD_SOCKET_H_
+#define BSD_SOCKET_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lwip/sockets.h"
+
+#include "lwip/inet.h"
+
+#include "lwip/netdb.h"
+
+//Sockets
+
+inline int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ return lwip_accept(s, addr, addrlen);
+}
+
+inline int bind(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ return lwip_bind(s, name, namelen);
+}
+
+inline int shutdown(int s, int how)
+{
+ return lwip_shutdown(s, how);
+}
+
+inline int getsockname (int s, struct sockaddr *name, socklen_t *namelen)
+{
+ return lwip_getsockname(s, name, namelen);
+}
+
+inline int getpeername (int s, struct sockaddr *name, socklen_t *namelen)
+{
+ return lwip_getpeername(s, name, namelen);
+}
+
+inline int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+ return lwip_getsockopt(s, level, optname, optval, optlen);
+}
+
+inline int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+ return lwip_setsockopt(s, level, optname, optval, optlen);
+}
+
+inline int connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ return lwip_connect(s, name, namelen);
+}
+
+inline int listen(int s, int backlog)
+{
+ return lwip_listen(s, backlog);
+}
+
+inline int recv(int s, void *mem, size_t len, int flags)
+{
+ return lwip_recv(s, mem, len, flags);
+}
+
+inline int recvfrom(int s, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen)
+{
+ return lwip_recvfrom(s, mem, len, flags, from, fromlen);
+}
+
+inline int send(int s, const void *dataptr, size_t size, int flags)
+{
+ return lwip_send(s, dataptr, size, flags);
+}
+
+inline int sendto(int s, const void *dataptr, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ return lwip_sendto(s, dataptr, size, flags, to, tolen);
+}
+
+inline int socket(int domain, int type, int protocol)
+{
+ return lwip_socket(domain, type, protocol);
+}
+
+inline int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+ struct timeval *timeout)
+{
+ return lwip_select(maxfdp1, readset, writeset, exceptset, timeout);
+}
+
+inline int ioctlsocket(int s, long cmd, void *argp)
+{
+ return lwip_ioctl(s, cmd, argp);
+}
+
+inline int read(int s, void *mem, size_t len)
+{
+ return lwip_read(s, mem, len);
+}
+
+inline int write(int s, const void *dataptr, size_t size)
+{
+ return lwip_write(s, dataptr, size);
+}
+
+inline int close(int s)
+{
+ return lwip_close(s);
+}
+
+//DNS
+/*
+inline struct hostent *gethostbyname(const char *name)
+{
+ return lwip_gethostbyname(name);
+}
+
+inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
+{
+ return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+}*/
+
+inline void freeaddrinfo(struct addrinfo *ai)
+{
+ return lwip_freeaddrinfo(ai);
+}
+
+inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
+{
+ return lwip_getaddrinfo(nodename, servname, hints, res);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg.cpp Thu Oct 10 21:38:25 2013 +0000
@@ -0,0 +1,127 @@
+/* dbg.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbg.h"
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include <cstdio>
+#include <cstdarg>
+
+using namespace std;
+
+static Serial debug_pc(USBTX, USBRX);
+
+static char debug_newline[3];
+
+static void debug_lock(bool set)
+{
+ static Mutex* mtx = new Mutex(); //Singleton runtime initialisation to avoid static initialisation chaos problems
+ static bool init = false;
+ if(set)
+ {
+ mtx->lock();
+ if(!init)
+ {
+ strncpy( debug_newline, "\n", 2 );
+ printf("[START]\n");
+ fflush(stdout);
+ init = true;
+ }
+ }
+ else
+ {
+ mtx->unlock();
+ }
+}
+
+void debug_init()
+{
+ debug_lock(true); //Force init
+ debug_lock(false);
+}
+
+void debug_set_newline(const char* newline)
+{
+ debug_lock(true);
+ strncpy( debug_newline, newline, 2 );
+ debug_newline[2] = '\0';
+ debug_lock(false);
+}
+
+void debug_set_speed(int speed)
+{
+ debug_pc.baud(speed);
+}
+
+void debug(int level, const char* module, int line, const char* fmt, ...)
+{
+ debug_lock(true);
+ switch(level)
+ {
+ default:
+ case 1:
+ printf("E");
+ break;
+ case 2:
+ printf("W");
+ break;
+ case 3:
+ printf("I");
+ break;
+ case 4:
+ printf("D");
+ break;
+ }
+
+ printf(" %s:%d ", module, line);
+
+ va_list argp;
+
+ va_start(argp, fmt);
+ vprintf(fmt, argp);
+ va_end(argp);
+
+ printf(debug_newline);
+
+ fflush(stdout);
+
+ debug_lock(false);
+
+}
+
+void debug_error(const char* module, int line, int ret)
+{
+ debug_lock(true);
+ printf("[RC] Module %s - Line %d : Error %d\n", module, line, ret);
+ fflush(stdout);
+ debug_lock(false);
+}
+
+void debug_exact(const char* fmt, ...)
+{
+ debug_lock(true);
+ va_list argp;
+
+ va_start(argp, fmt);
+ vprintf(fmt, argp);
+ va_end(argp);
+ debug_lock(false);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg.h Thu Oct 10 21:38:25 2013 +0000
@@ -0,0 +1,79 @@
+/* dbg.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DBG_H_
+#define DBG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void debug_init(void);
+void debug(int level, const char* module, int line, const char* fmt, ...);
+void debug_set_newline(const char* newline);
+void debug_set_speed(int speed);
+void debug_error(const char* module, int line, int ret);
+void debug_exact(const char* fmt, ...);
+
+#define DBG_INIT() do{ debug_init(); }while(0)
+
+#define DBG_SET_NEWLINE( x ) do{ debug_set_newline(x); }while(0)
+
+#define DBG_SET_SPEED( x ) do{ debug_set_speed(x); }while(0)
+
+#if __DEBUG__ > 0
+#ifndef __MODULE__
+#error "__MODULE__ must be defined"
+#endif
+#endif
+
+#if __DEBUG__ >= 1
+#define ERR(...) do{ debug(1, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define ERR(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 2
+#define WARN(...) do{ debug(2, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define WARN(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 3
+#define INFO(...) do{ debug(3, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define CHECK(ret) do{ if(ret){ debug_error(__MODULE__, __LINE__, ret); } }while(0)
+#else
+#define INFO(...) do{ }while(0)
+#define CHECK(ret) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 4
+#define DBG(...) do{ debug(4, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define DBGX(...) do{ debug_exact(__VA_ARGS__); }while(0)
+#else
+#define DBG(...) do{ }while(0)
+#define DBGX(...) do{ }while(0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DBG_H_ */
--- a/main.cpp Wed Oct 09 14:48:52 2013 +0000
+++ b/main.cpp Thu Oct 10 21:38:25 2013 +0000
@@ -1,16 +1,379 @@
+#define __DEBUG__ 4
+
+#ifndef __MODULE__
+#define __MODULE__ "main.cpp"
+#endif
+
#include "mbed.h"
#include "rtos.h"
-#include "VodafoneUSBModem.h"
#include "bsd_socket.h"
-#include "dtls.h"
+#include <dtls.h>
+#include "global.h"
+#include "debug.h"
+#include "errno.h"
+#include "dbg.h"
+
+#include "EthernetInterface.h"
DigitalOut myled(LED1);
+void fail(int code) {
+ while(1) {
+ myled = !myled;
+ Thread::wait(100);
+ }
+}
+
+/* This function is the "key store" for tinyDTLS. It is called to
+ * retrieve a key for the given identiy within this particular
+ * session. */
+int
+get_key(struct dtls_context_t *ctx,
+ const session_t *session,
+ const unsigned char *id, size_t id_len,
+ const dtls_key_t **result) {
+ DBG("Entered get_key");
+
+ static const dtls_key_t psk = {
+ .type = DTLS_KEY_PSK,
+ .key.psk.id = (unsigned char *)"Client_identity",
+ .key.psk.id_length = 15,
+ .key.psk.key = (unsigned char *)"secretPSK",
+ .key.psk.key_length = 9
+ };
+
+ *result = &psk;
+ return 0;
+}
+
+#define APN_GDSP
+//#define APN_CONTRACT
+
+#ifdef APN_GDSP
+ #define APN "ppinternetd.gdsp"
+ #define APN_USERNAME ""
+ #define APN_PASSWORD ""
+#endif
+
+#ifdef APN_CONTRACT
+ #define APN "internet"
+ #define APN_USERNAME "web"
+ #define APN_PASSWORD "web"
+#endif
+
+/* stolen from libcoap: */
+int
+resolve_address(const char *server, struct sockaddr *dst) {
+
+ struct addrinfo *res, *ainfo;
+ struct addrinfo hints;
+ static char addrstr[256];
+ int error;
+
+ memset(addrstr, 0, sizeof(addrstr));
+ if (server && strlen(server) > 0)
+ memcpy(addrstr, server, strlen(server));
+ else
+ memcpy(addrstr, "localhost", 9);
+
+ memset ((char *)&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_family = AF_UNSPEC;
+
+ error = getaddrinfo(addrstr, "", &hints, &res);
+
+ if (error != 0) {
+ DBG("Some bullshit error");//fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
+ return error;
+ }
+
+ for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
+
+ switch (ainfo->ai_family) {
+ case AF_INET:
+
+ memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
+ return ainfo->ai_addrlen;
+ default:
+ ;
+ }
+ }
+
+ freeaddrinfo(res);
+ return -1;
+}
+
+
+sockaddr_in bindAddr,serverAddress;
+bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
+ *sockfd = -1;
+ // create the socket
+ if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
+ DBG("Error opening socket");
+ return false;
+ }
+ socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
+
+ // bind socket
+ memset(&bindAddr, 0x00, sockAddrInLen);
+ bindAddr.sin_family = AF_INET; // IP family
+ bindAddr.sin_port = htons(port);
+ bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
+ // call bind
+ if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
+ DBG("Error binding socket");
+ perror(NULL);
+ }
+
+ INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
+
+ // create the socket address
+ memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
+ serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
+ serverAddress.sin_family = AF_INET;
+ serverAddress.sin_port = htons(port);
+
+ // do socket connect
+ //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
+ if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
+ shutdown(*sockfd,SHUT_RDWR);
+ close(*sockfd);
+ DBG("Could not connect");
+ return false;
+ }
+ return true;
+}
+
+int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
+ DBG("read_from_peer called");
+ size_t i;
+ for (i = 0; i < len; i++)
+ printf("%c", data[i]);
+ return 0;
+}
+
+int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
+ DBG("send_to_peer called");
+ int fd = *(int *)dtls_get_app_data(ctx);
+ return sendto(fd, data, len, MSG_DONTWAIT,
+ &session->addr.sa, session->size);
+}
+
+
+int
+dtls_handle_read(struct dtls_context_t *ctx) {
+ DBG("dtls_handle_read called");
+ int fd;
+ session_t session;
+#define MAX_READ_BUF 512
+ static uint8 buf[MAX_READ_BUF];
+ int len;
+
+ fd = *(int *)dtls_get_app_data(ctx);
+ /*
+ if(!fd) {
+ DBG("FD NULL");
+ return -1;
+ }*/
+
+ memset(&session, 0x00, sizeof(session_t));
+ DBG("BEFORE: ");
+ for(uint8_t i=0; i<sizeof(session_t); i++) {
+ DBGX("%x ",((uint8_t*)&session)[i]);
+ }
+ DBGX("\r\n");
+ session.size = sizeof(sockaddr_in);
+ uint32_t bullshit = sizeof(sockaddr_in);
+ len = recvfrom(fd, buf, MAX_READ_BUF, 0,
+ &session.addr.sa, &bullshit);
+
+ //((uint8_t*)&session)[4] = 0x00;
+ //session.addr.sin.sin_family = AF_INET;
+ DBG("AFTER: %d",bullshit);
+ for(uint8_t i=0; i<sizeof(session_t); i++) {
+ DBGX("%x ",((uint8_t*)&session)[i]);
+ }
+ DBGX("\r\n");
+ short x = session.addr.sin.sin_family;
+ if(session.addr.sin.sin_family==AF_INET) {
+ DBG("AF_INET alright");
+ }
+ DBG("%x %x",((uint8_t*)x)[0],((uint8_t*)x)[1]);
+ if (len < 0) {
+ DBG("Got nothing from read");
+ perror("recvfrom");
+ return -1;
+ } else {
+#ifndef NDEBUG
+ unsigned char addrbuf[72];
+ dsrv_print_addr(&session, addrbuf, sizeof(addrbuf));
+ DBG("got %d bytes from %s\n", len, (char *)addrbuf);
+ dump((unsigned char *)&session, sizeof(session_t));
+ DBGX("\r\n");
+ dump(buf, len);
+ DBGX("\r\n");
+#endif
+ }
+
+ return dtls_handle_message(ctx, &session, buf, len);
+}
+
+static dtls_handler_t cb = {
+ .write = send_to_peer,
+ .read = read_from_peer,
+ .event = NULL,
+ .get_key = get_key
+ };
+
int main() {
- while(1) {
- myled = 1;
- wait(0.2);
- myled = 0;
- wait(0.2);
+ DBG_INIT();
+ DBG_SET_SPEED(115200);
+ DBG_SET_NEWLINE("\r\n");
+
+ DBG("Tiny DTLS test");
+
+ // DTLS context struct
+ dtls_context_t *dtls_context = NULL;
+ int ret = 0;
+ fd_set rfds, wfds;
+ struct timeval timeout;
+ session_t dst;
+
+ // structure for getting address of incoming packets
+ sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof(struct sockaddr_in);
+ memset(&fromAddr,0x00,fromAddrLen);
+
+ // connect to cellular network
+ /*
+ VodafoneUSBModem modem;
+ modem.connect(APN,APN_USERNAME,APN_PASSWORD);
+ */
+ EthernetInterface modem;
+ DBG("Connecting to network interface");
+ modem.init();
+ if(modem.connect(10000)) {
+ DBG("Error initialising ethernet interface");
+ }
+ DBG("DONE.");
+
+ dtls_init();
+ dtls_set_log_level(LOG_DEBUG);
+
+ // setup socket to remote server
+ int sockfd = NULL;
+
+
+ //if(!connectToSocketUDP("109.74.199.96", 5683, &sockfd)) {
+ if(!connectToSocketUDP("192.168.1.99", 4433, &sockfd)) {
+ DBG("Error connecting to socket");
+ fail(1);
}
+ DBG("\"Connected\" to UDP socket, sockfd: %d",sockfd);
+ /*
+ int on = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
+ dsrv_log(LOG_ALERT, "setsockopt SO_REUSEADDR: %s\n", strerror(errno));
+ }*/
+
+ /*
+ memset(&dst, 0, sizeof(session_t));
+ // resolve destination address where server should be sent
+ //int res = resolve_address("192.168.1.99", &dst.addr.sa);
+ int res = resolve_address("109.74.199.96", &dst.addr.sa);
+ if (res < 0) {
+ dsrv_log(LOG_EMERG, "failed to resolve address\n");
+ fail(9);
+ }
+ dst.size = res;
+
+ // use port number from command line when specified or the listen port, otherwise
+ dst.addr.sin.sin_port = htons(4433);//atoi(optind < argc ? argv[optind++] : port_str));
+
+ // init socket and set it to non-blocking
+ sockfd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+ dsrv_log(LOG_ALERT, "socket: %s\n", strerror(errno));
+ return 0;
+ }*/
+
+ // tinydtls stuff
+
+ // destination address is stored in a session type
+
+ memset(&dst, 0x00, sizeof(session_t));
+ dst.size = sizeof(sockaddr_in);
+ DBG("starting copy at offset: %d",(int)&dst.addr-(int)&dst);
+ serverAddress.sin_len = dst.size;
+ memcpy(&dst.addr, &serverAddress, dst.size);
+
+
+ //dst.addr.sin.sin_port = htons(4433);
+
+ // dtls init must always be called for memory allocation
+
+ // setup DTLS context
+ DBG("Creating DTLS context");
+ dtls_context = dtls_new_context(&sockfd);
+ if(!dtls_context) {
+ DBG("Cannot create context");
+ fail(3);
+ }
+ DBG("DTLS context created");
+
+ // forced to use this call back system
+
+ dtls_set_handler(dtls_context, &cb);
+
+ DBG("Issuing dtls_connect");
+ ret = dtls_connect(dtls_context, &dst);
+ if(ret<0) {
+ DBG("Error in dtls_connect: %d",ret);
+ modem.disconnect();
+ fail(4);
+ }
+ if(ret==0) {
+ DBG("Channel already exists");
+ modem.disconnect();
+ fail(5);
+ }
+ DBG("dtls_connect successfull");
+ while (1) {
+ // setup file descriptor lists for select
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ //FD_SET(fileno(stdin), &rfds);
+ FD_SET(sockfd, &rfds);
+ // FD_SET(sockfd, &wfds);
+
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+
+ int result = select(sockfd+1, &rfds, &wfds, 0, &timeout);
+
+ if(result < 0) { // error
+ if (errno != EINTR)
+ perror("select");
+ } else if (result == 0) {
+ // timeout
+ } else {
+ // OK
+ // check which file descriptor had an event
+ if(FD_ISSET(sockfd, &wfds)) {
+ // FIXME (from tinydtls)
+ } else if (FD_ISSET(sockfd, &rfds))
+ if(dtls_handle_read(dtls_context)<0) {
+ modem.disconnect();
+ fail(6);
+ }
+ }
+ //else if (FD_ISSET(fileno(stdin), &rfds))
+ //handle_stdin();
+ //}
+
+ //if(len) {
+ // try_send(dtls_context, &dst);
+ //}
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tinydtls.lib Thu Oct 10 21:38:25 2013 +0000 @@ -0,0 +1,1 @@ +tinydtls#04990d454f45
--- a/tinydtls/aes/rijndael.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1277 +0,0 @@
-/* $OpenBSD: rijndael.c,v 1.19 2008/06/09 07:49:45 djm Exp $ */
-
-/**
- * rijndael-alg-fst.c
- *
- * @version 3.0 (December 2000)
- *
- * Optimised ANSI C code for the Rijndael cipher (now AES)
- *
- * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
- * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
- * @author Paulo Barreto <paulo.barreto@terra.com.br>
- *
- * This code is hereby placed in the public domain.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "config.h"
-#ifndef MBED
-#include <sys/param.h>
-#endif
-
-/* #include <sys/systm.h> */
-
-#include "rijndael.h"
-
-#undef FULL_UNROLL
-
-/*
-Te0[x] = S [x].[02, 01, 01, 03];
-Te1[x] = S [x].[03, 02, 01, 01];
-Te2[x] = S [x].[01, 03, 02, 01];
-Te3[x] = S [x].[01, 01, 03, 02];
-Te4[x] = S [x].[01, 01, 01, 01];
-
-Td0[x] = Si[x].[0e, 09, 0d, 0b];
-Td1[x] = Si[x].[0b, 0e, 09, 0d];
-Td2[x] = Si[x].[0d, 0b, 0e, 09];
-Td3[x] = Si[x].[09, 0d, 0b, 0e];
-Td4[x] = Si[x].[01, 01, 01, 01];
-*/
-
-static const aes_u32 Te0[256] = {
- 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
- 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
- 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
- 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
- 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
- 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
- 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
- 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
- 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
- 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
- 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
- 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
- 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
- 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
- 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
- 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
- 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
- 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
- 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
- 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
- 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
- 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
- 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
- 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
- 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
- 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
- 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
- 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
- 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
- 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
- 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
- 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
- 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
- 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
- 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
- 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
- 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
- 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
- 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
- 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
- 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
- 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
- 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
- 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
- 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
- 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
- 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
- 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
- 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
- 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
- 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
- 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
- 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
- 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
- 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
- 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
- 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
- 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
- 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
- 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
- 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
- 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
- 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
- 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-};
-static const aes_u32 Te1[256] = {
- 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
- 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
- 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
- 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
- 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
- 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
- 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
- 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
- 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
- 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
- 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
- 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
- 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
- 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
- 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
- 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
- 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
- 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
- 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
- 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
- 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
- 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
- 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
- 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
- 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
- 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
- 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
- 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
- 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
- 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
- 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
- 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
- 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
- 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
- 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
- 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
- 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
- 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
- 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
- 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
- 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
- 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
- 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
- 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
- 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
- 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
- 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
- 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
- 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
- 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
- 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
- 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
- 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
- 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
- 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
- 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
- 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
- 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
- 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
- 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
- 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
- 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
- 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
- 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
-};
-static const aes_u32 Te2[256] = {
- 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
- 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
- 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
- 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
- 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
- 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
- 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
- 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
- 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
- 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
- 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
- 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
- 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
- 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
- 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
- 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
- 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
- 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
- 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
- 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
- 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
- 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
- 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
- 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
- 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
- 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
- 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
- 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
- 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
- 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
- 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
- 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
- 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
- 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
- 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
- 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
- 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
- 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
- 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
- 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
- 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
- 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
- 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
- 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
- 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
- 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
- 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
- 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
- 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
- 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
- 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
- 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
- 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
- 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
- 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
- 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
- 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
- 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
- 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
- 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
- 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
- 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
- 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
- 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
-};
-static const aes_u32 Te3[256] = {
- 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
- 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
- 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
- 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
- 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
- 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
- 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
- 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
- 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
- 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
- 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
- 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
- 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
- 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
- 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
- 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
- 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
- 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
- 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
- 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
- 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
- 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
- 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
- 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
- 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
- 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
- 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
- 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
- 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
- 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
- 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
- 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
- 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
- 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
- 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
- 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
- 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
- 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
- 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
- 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
- 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
- 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
- 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
- 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
- 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
- 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
- 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
- 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
- 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
- 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
- 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
- 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
- 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
- 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
- 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
- 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
- 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
- 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
- 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
- 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
- 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
- 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
- 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
- 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
-};
-static const aes_u32 Te4[256] = {
- 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
- 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
- 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
- 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
- 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
- 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
- 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
- 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
- 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
- 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
- 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
- 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
- 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
- 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
- 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
- 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
- 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
- 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
- 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
- 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
- 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
- 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
- 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
- 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
- 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
- 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
- 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
- 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
- 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
- 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
- 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
- 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
- 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
- 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
- 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
- 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
- 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
- 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
- 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
- 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
- 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
- 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
- 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
- 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
- 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
- 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
- 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
- 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
- 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
- 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
- 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
- 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
- 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
- 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
- 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
- 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
- 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
- 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
- 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
- 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
- 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
- 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
- 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
- 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
-};
-static const aes_u32 Td0[256] = {
- 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
- 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
- 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
- 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
- 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
- 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
- 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
- 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
- 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
- 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
- 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
- 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
- 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
- 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
- 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
- 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
- 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
- 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
- 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
- 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
- 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
- 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
- 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
- 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
- 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
- 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
- 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
- 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
- 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
- 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
- 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
- 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
- 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
- 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
- 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
- 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
- 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
- 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
- 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
- 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
- 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
- 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
- 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
- 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
- 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
- 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
- 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
- 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
- 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
- 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
- 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
- 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
- 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
- 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
- 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
- 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
- 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
- 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
- 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
- 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
- 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
- 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
- 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
- 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
-};
-static const aes_u32 Td1[256] = {
- 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
- 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
- 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
- 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
- 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
- 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
- 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
- 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
- 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
- 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
- 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
- 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
- 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
- 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
- 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
- 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
- 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
- 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
- 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
- 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
- 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
- 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
- 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
- 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
- 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
- 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
- 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
- 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
- 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
- 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
- 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
- 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
- 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
- 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
- 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
- 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
- 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
- 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
- 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
- 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
- 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
- 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
- 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
- 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
- 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
- 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
- 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
- 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
- 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
- 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
- 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
- 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
- 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
- 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
- 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
- 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
- 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
- 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
- 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
- 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
- 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
- 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
- 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
- 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
-};
-static const aes_u32 Td2[256] = {
- 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
- 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
- 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
- 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
- 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
- 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
- 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
- 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
- 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
- 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
- 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
- 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
- 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
- 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
- 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
- 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
- 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
- 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
- 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
- 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
- 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
- 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
- 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
- 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
- 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
- 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
- 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
- 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
- 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
- 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
- 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
- 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
- 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
- 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
- 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
- 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
- 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
- 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
- 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
- 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
- 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
- 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
- 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
- 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
- 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
- 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
- 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
- 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
- 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
- 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
- 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
- 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
- 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
- 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
- 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
- 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
- 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
- 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
- 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
- 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
- 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
- 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
- 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
- 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
-};
-static const aes_u32 Td3[256] = {
- 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
- 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
- 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
- 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
- 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
- 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
- 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
- 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
- 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
- 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
- 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
- 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
- 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
- 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
- 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
- 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
- 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
- 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
- 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
- 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
- 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
- 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
- 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
- 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
- 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
- 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
- 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
- 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
- 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
- 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
- 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
- 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
- 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
- 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
- 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
- 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
- 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
- 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
- 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
- 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
- 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
- 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
- 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
- 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
- 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
- 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
- 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
- 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
- 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
- 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
- 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
- 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
- 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
- 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
- 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
- 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
- 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
- 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
- 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
- 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
- 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
- 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
- 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
- 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
-};
-static const aes_u32 Td4[256] = {
- 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
- 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
- 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
- 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
- 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
- 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
- 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
- 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
- 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
- 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
- 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
- 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
- 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
- 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
- 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
- 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
- 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
- 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
- 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
- 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
- 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
- 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
- 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
- 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
- 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
- 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
- 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
- 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
- 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
- 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
- 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
- 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
- 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
- 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
- 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
- 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
- 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
- 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
- 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
- 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
- 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
- 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
- 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
- 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
- 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
- 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
- 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
- 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
- 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
- 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
- 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
- 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
- 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
- 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
- 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
- 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
- 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
- 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
- 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
- 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
- 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
- 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
- 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
- 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
-};
-static const aes_u32 rcon[] = {
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000,
- 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
-};
-
-#define GETU32(pt) (((aes_u32)(pt)[0] << 24) ^ ((aes_u32)(pt)[1] << 16) ^ ((aes_u32)(pt)[2] << 8) ^ ((aes_u32)(pt)[3]))
-#define PUTU32(ct, st) { (ct)[0] = (aes_u8)((st) >> 24); (ct)[1] = (aes_u8)((st) >> 16); (ct)[2] = (aes_u8)((st) >> 8); (ct)[3] = (aes_u8)(st); }
-
-/**
- * Expand the cipher key into the encryption key schedule.
- *
- * @return the number of rounds for the given cipher key size.
- */
-int
-rijndaelKeySetupEnc(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits)
-{
- int i = 0;
- aes_u32 temp;
-
- rk[0] = GETU32(cipherKey );
- rk[1] = GETU32(cipherKey + 4);
- rk[2] = GETU32(cipherKey + 8);
- rk[3] = GETU32(cipherKey + 12);
- if (keyBits == 128) {
- for (;;) {
- temp = rk[3];
- rk[4] = rk[0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[5] = rk[1] ^ rk[4];
- rk[6] = rk[2] ^ rk[5];
- rk[7] = rk[3] ^ rk[6];
- if (++i == 10) {
- return 10;
- }
- rk += 4;
- }
- }
- rk[4] = GETU32(cipherKey + 16);
- rk[5] = GETU32(cipherKey + 20);
- if (keyBits == 192) {
- for (;;) {
- temp = rk[ 5];
- rk[ 6] = rk[ 0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 7] = rk[ 1] ^ rk[ 6];
- rk[ 8] = rk[ 2] ^ rk[ 7];
- rk[ 9] = rk[ 3] ^ rk[ 8];
- if (++i == 8) {
- return 12;
- }
- rk[10] = rk[ 4] ^ rk[ 9];
- rk[11] = rk[ 5] ^ rk[10];
- rk += 6;
- }
- }
- rk[6] = GETU32(cipherKey + 24);
- rk[7] = GETU32(cipherKey + 28);
- if (keyBits == 256) {
- for (;;) {
- temp = rk[ 7];
- rk[ 8] = rk[ 0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
- rk[ 9] = rk[ 1] ^ rk[ 8];
- rk[10] = rk[ 2] ^ rk[ 9];
- rk[11] = rk[ 3] ^ rk[10];
- if (++i == 7) {
- return 14;
- }
- temp = rk[11];
- rk[12] = rk[ 4] ^
- (Te4[(temp >> 24) ] & 0xff000000) ^
- (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(temp ) & 0xff] & 0x000000ff);
- rk[13] = rk[ 5] ^ rk[12];
- rk[14] = rk[ 6] ^ rk[13];
- rk[15] = rk[ 7] ^ rk[14];
- rk += 8;
- }
- }
- return 0;
-}
-
-#ifdef WITH_AES_DECRYPT
-/**
- * Expand the cipher key into the decryption key schedule.
- *
- * @return the number of rounds for the given cipher key size.
- */
-int
-rijndaelKeySetupDec(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits)
-{
- int Nr, i, j;
- aes_u32 temp;
-
- /* expand the cipher key: */
- Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
-
- /* invert the order of the round keys: */
- for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
- temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
- temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
- temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
- temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
- }
- /* apply the inverse MixColumn transform to all round keys but the first and the last: */
- for (i = 1; i < Nr; i++) {
- rk += 4;
- rk[0] =
- Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[0] ) & 0xff] & 0xff];
- rk[1] =
- Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[1] ) & 0xff] & 0xff];
- rk[2] =
- Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[2] ) & 0xff] & 0xff];
- rk[3] =
- Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[3] ) & 0xff] & 0xff];
- }
- return Nr;
-}
-#endif
-
-void
-rijndaelEncrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 pt[16],
- aes_u8 ct[16])
-{
- aes_u32 s0, s1, s2, s3, t0, t1, t2, t3;
-#ifndef FULL_UNROLL
- int r;
-#endif /* ?FULL_UNROLL */
-
- /*
- * map byte array block to cipher state
- * and add initial round key:
- */
- s0 = GETU32(pt ) ^ rk[0];
- s1 = GETU32(pt + 4) ^ rk[1];
- s2 = GETU32(pt + 8) ^ rk[2];
- s3 = GETU32(pt + 12) ^ rk[3];
-#ifdef FULL_UNROLL
- /* round 1: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
- /* round 2: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
- /* round 3: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
- /* round 4: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
- /* round 5: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
- /* round 6: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
- /* round 7: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
- /* round 8: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
- /* round 9: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
- if (Nr > 10) {
- /* round 10: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
- /* round 11: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
- if (Nr > 12) {
- /* round 12: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
- /* round 13: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
- }
- }
- rk += Nr << 2;
-#else /* !FULL_UNROLL */
- /*
- * Nr - 1 full rounds:
- */
- r = Nr >> 1;
- for (;;) {
- t0 =
- Te0[(s0 >> 24) ] ^
- Te1[(s1 >> 16) & 0xff] ^
- Te2[(s2 >> 8) & 0xff] ^
- Te3[(s3 ) & 0xff] ^
- rk[4];
- t1 =
- Te0[(s1 >> 24) ] ^
- Te1[(s2 >> 16) & 0xff] ^
- Te2[(s3 >> 8) & 0xff] ^
- Te3[(s0 ) & 0xff] ^
- rk[5];
- t2 =
- Te0[(s2 >> 24) ] ^
- Te1[(s3 >> 16) & 0xff] ^
- Te2[(s0 >> 8) & 0xff] ^
- Te3[(s1 ) & 0xff] ^
- rk[6];
- t3 =
- Te0[(s3 >> 24) ] ^
- Te1[(s0 >> 16) & 0xff] ^
- Te2[(s1 >> 8) & 0xff] ^
- Te3[(s2 ) & 0xff] ^
- rk[7];
-
- rk += 8;
- if (--r == 0) {
- break;
- }
-
- s0 =
- Te0[(t0 >> 24) ] ^
- Te1[(t1 >> 16) & 0xff] ^
- Te2[(t2 >> 8) & 0xff] ^
- Te3[(t3 ) & 0xff] ^
- rk[0];
- s1 =
- Te0[(t1 >> 24) ] ^
- Te1[(t2 >> 16) & 0xff] ^
- Te2[(t3 >> 8) & 0xff] ^
- Te3[(t0 ) & 0xff] ^
- rk[1];
- s2 =
- Te0[(t2 >> 24) ] ^
- Te1[(t3 >> 16) & 0xff] ^
- Te2[(t0 >> 8) & 0xff] ^
- Te3[(t1 ) & 0xff] ^
- rk[2];
- s3 =
- Te0[(t3 >> 24) ] ^
- Te1[(t0 >> 16) & 0xff] ^
- Te2[(t1 >> 8) & 0xff] ^
- Te3[(t2 ) & 0xff] ^
- rk[3];
- }
-#endif /* ?FULL_UNROLL */
- /*
- * apply last round and
- * map cipher state to byte array block:
- */
- s0 =
- (Te4[(t0 >> 24) ] & 0xff000000) ^
- (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[0];
- PUTU32(ct , s0);
- s1 =
- (Te4[(t1 >> 24) ] & 0xff000000) ^
- (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[1];
- PUTU32(ct + 4, s1);
- s2 =
- (Te4[(t2 >> 24) ] & 0xff000000) ^
- (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[2];
- PUTU32(ct + 8, s2);
- s3 =
- (Te4[(t3 >> 24) ] & 0xff000000) ^
- (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[3];
- PUTU32(ct + 12, s3);
-}
-
-#ifdef WITH_AES_DECRYPT
-static void
-rijndaelDecrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 ct[16],
- aes_u8 pt[16])
-{
- aes_u32 s0, s1, s2, s3, t0, t1, t2, t3;
-#ifndef FULL_UNROLL
- int r;
-#endif /* ?FULL_UNROLL */
-
- /*
- * map byte array block to cipher state
- * and add initial round key:
- */
- s0 = GETU32(ct ) ^ rk[0];
- s1 = GETU32(ct + 4) ^ rk[1];
- s2 = GETU32(ct + 8) ^ rk[2];
- s3 = GETU32(ct + 12) ^ rk[3];
-#ifdef FULL_UNROLL
- /* round 1: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
- /* round 2: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
- /* round 3: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
- /* round 4: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
- /* round 5: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
- /* round 6: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
- /* round 7: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
- /* round 8: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
- /* round 9: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
- if (Nr > 10) {
- /* round 10: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
- /* round 11: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
- if (Nr > 12) {
- /* round 12: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
- /* round 13: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
- }
- }
- rk += Nr << 2;
-#else /* !FULL_UNROLL */
- /*
- * Nr - 1 full rounds:
- */
- r = Nr >> 1;
- for (;;) {
- t0 =
- Td0[(s0 >> 24) ] ^
- Td1[(s3 >> 16) & 0xff] ^
- Td2[(s2 >> 8) & 0xff] ^
- Td3[(s1 ) & 0xff] ^
- rk[4];
- t1 =
- Td0[(s1 >> 24) ] ^
- Td1[(s0 >> 16) & 0xff] ^
- Td2[(s3 >> 8) & 0xff] ^
- Td3[(s2 ) & 0xff] ^
- rk[5];
- t2 =
- Td0[(s2 >> 24) ] ^
- Td1[(s1 >> 16) & 0xff] ^
- Td2[(s0 >> 8) & 0xff] ^
- Td3[(s3 ) & 0xff] ^
- rk[6];
- t3 =
- Td0[(s3 >> 24) ] ^
- Td1[(s2 >> 16) & 0xff] ^
- Td2[(s1 >> 8) & 0xff] ^
- Td3[(s0 ) & 0xff] ^
- rk[7];
-
- rk += 8;
- if (--r == 0) {
- break;
- }
-
- s0 =
- Td0[(t0 >> 24) ] ^
- Td1[(t3 >> 16) & 0xff] ^
- Td2[(t2 >> 8) & 0xff] ^
- Td3[(t1 ) & 0xff] ^
- rk[0];
- s1 =
- Td0[(t1 >> 24) ] ^
- Td1[(t0 >> 16) & 0xff] ^
- Td2[(t3 >> 8) & 0xff] ^
- Td3[(t2 ) & 0xff] ^
- rk[1];
- s2 =
- Td0[(t2 >> 24) ] ^
- Td1[(t1 >> 16) & 0xff] ^
- Td2[(t0 >> 8) & 0xff] ^
- Td3[(t3 ) & 0xff] ^
- rk[2];
- s3 =
- Td0[(t3 >> 24) ] ^
- Td1[(t2 >> 16) & 0xff] ^
- Td2[(t1 >> 8) & 0xff] ^
- Td3[(t0 ) & 0xff] ^
- rk[3];
- }
-#endif /* ?FULL_UNROLL */
- /*
- * apply last round and
- * map cipher state to byte array block:
- */
- s0 =
- (Td4[(t0 >> 24) ] & 0xff000000) ^
- (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[0];
- PUTU32(pt , s0);
- s1 =
- (Td4[(t1 >> 24) ] & 0xff000000) ^
- (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[1];
- PUTU32(pt + 4, s1);
- s2 =
- (Td4[(t2 >> 24) ] & 0xff000000) ^
- (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[2];
- PUTU32(pt + 8, s2);
- s3 =
- (Td4[(t3 >> 24) ] & 0xff000000) ^
- (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[3];
- PUTU32(pt + 12, s3);
-}
-#endif
-
-/* setup key context for encryption only */
-int
-rijndael_set_key_enc_only(rijndael_ctx *ctx, const u_char *key, int bits)
-{
- int rounds;
-
- rounds = rijndaelKeySetupEnc(ctx->ek, key, bits);
- if (rounds == 0)
- return -1;
-
- ctx->Nr = rounds;
-#ifdef WITH_AES_DECRYPT
- ctx->enc_only = 1;
-#endif
-
- return 0;
-}
-
-#ifdef WITH_AES_DECRYPT
-/* setup key context for both encryption and decryption */
-int
-rijndael_set_key(rijndael_ctx *ctx, const u_char *key, int bits)
-{
- int rounds;
-
- rounds = rijndaelKeySetupEnc(ctx->ek, key, bits);
- if (rounds == 0)
- return -1;
- if (rijndaelKeySetupDec(ctx->dk, key, bits) != rounds)
- return -1;
-
- ctx->Nr = rounds;
- ctx->enc_only = 0;
-
- return 0;
-}
-
-void
-rijndael_decrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst)
-{
- rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst);
-}
-#endif
-
-void
-rijndael_encrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst)
-{
- rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst);
-}
--- a/tinydtls/aes/rijndael.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */
-
-/**
- * rijndael-alg-fst.h
- *
- * @version 3.0 (December 2000)
- *
- * Optimised ANSI C code for the Rijndael cipher (now AES)
- *
- * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
- * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
- * @author Paulo Barreto <paulo.barreto@terra.com.br>
- *
- * This code is hereby placed in the public domain.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef __RIJNDAEL_H
-#define __RIJNDAEL_H
-
-#define AES_MAXKEYBITS (256)
-#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
-/* for 256-bit keys, fewer for less */
-#define AES_MAXROUNDS 14
-
-/* bergmann: to avoid conflicts with typedefs from certain Contiki platforms,
- * the following type names have been prefixed with "aes_": */
-typedef unsigned char u_char;
-typedef unsigned char aes_u8;
-typedef unsigned short aes_u16;
-typedef unsigned int aes_u32;
-
-/* The structure for key information */
-typedef struct {
-#ifdef WITH_AES_DECRYPT
- int enc_only; /* context contains only encrypt schedule */
-#endif
- int Nr; /* key-length-dependent number of rounds */
- aes_u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
-#ifdef WITH_AES_DECRYPT
- aes_u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
-#endif
-} rijndael_ctx;
-
-int rijndael_set_key(rijndael_ctx *, const u_char *, int);
-int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int);
-void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *);
-void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *);
-
-int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
-int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
-void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
- unsigned char []);
-
-#endif /* __RIJNDAEL_H */
--- a/tinydtls/alert.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* alert.h -- DTLS alert protocol
- *
- * Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file alert.h
- * @brief DTLS alert protocol
- */
-
-#ifndef _ALERT_H_
-#define _ALERT_H_
-
-#include "config.h"
-
-typedef enum {
- DTLS_ALERT_LEVEL_WARNING=1,
- DTLS_ALERT_LEVEL_FATAL=2
-} dtls_alert_level_t;
-
-typedef enum {
- DTLS_ALERT_CLOSE=0,
- DTLS_ALERT_UNEXPECTED_MESSAGE=10,
- DTLS_ALERT_BAD_RECORD_MAC=20,
- DTLS_ALERT_RECORD_OVERFLOW=22,
- DTLS_ALERT_DECOMPRESSION_FAILURE=30,
- DTLS_ALERT_HANDSHAKE_FAILURE=40,
- DTLS_ALERT_ILLEGAL_PARAMETER=47,
- DTLS_ALERT_ACCESS_DENIED=49,
- DTLS_ALERT_DECODE_ERROR=50,
- DTLS_ALERT_DECRYPT_ERROR=51,
- DTLS_ALERT_PROTOCOL_VERSION=70,
- DTLS_ALERT_INSUFFICIENT_SECURITY=70,
- DTLS_ALERT_INTERNAL_ERROR=80,
- DTLS_ALERT_USER_CANCELED=90,
- DTLS_ALERT_NO_RENEGOTIATION=100,
- DTLS_ALERT_UNSUPPORTED_EXTENSION=110
-} dtls_alert_t;
-
-#define DTLS_EVENT_CONNECTED 0x01DE
-
-#endif /* _ALERT_H_ */
--- a/tinydtls/ccm.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <string.h>
-
-#include "global.h"
-#include "numeric.h"
-#include "ccm.h"
-
-#define CCM_FLAGS(A,M,L) (((A > 0) << 6) | (((M - 2)/2) << 3) | (L - 1))
-
-#define MASK_L(_L) ((1 << 8 * _L) - 1)
-
-#define SET_COUNTER(A,L,cnt,C) { \
- int i; \
- memset((A) + DTLS_CCM_BLOCKSIZE - (L), 0, (L)); \
- (C) = (cnt) & MASK_L(L); \
- for (i = DTLS_CCM_BLOCKSIZE - 1; (C) && (i > (L)); --i, (C) >>= 8) \
- (A)[i] |= (C) & 0xFF; \
- }
-
-static inline void
-block0(size_t M, /* number of auth bytes */
- size_t L, /* number of bytes to encode message length */
- size_t la, /* l(a) octets additional authenticated data */
- size_t lm, /* l(m) message length */
- unsigned char N[DTLS_CCM_BLOCKSIZE],
- unsigned char *result) {
- int i;
-
- result[0] = CCM_FLAGS(la, M, L);
-
- /* copy the nonce */
- memcpy(result + 1, N, DTLS_CCM_BLOCKSIZE - L);
-
- for (i=0; i < L; i++) {
- result[15-i] = lm & 0xff;
- lm >>= 8;
- }
-}
-
-/**
- * Creates the CBC-MAC for the additional authentication data that
- * is sent in cleartext.
- *
- * \param ctx The crypto context for the AES encryption.
- * \param msg The message starting with the additional authentication data.
- * \param la The number of additional authentication bytes in \p msg.
- * \param B The input buffer for crypto operations. When this function
- * is called, \p B must be initialized with \c B0 (the first
- * authentication block.
- * \param X The output buffer where the result of the CBC calculation
- * is placed.
- * \return The result is written to \p X.
- */
-void
-add_auth_data(rijndael_ctx *ctx, const unsigned char *msg, size_t la,
- unsigned char B[DTLS_CCM_BLOCKSIZE],
- unsigned char X[DTLS_CCM_BLOCKSIZE]) {
- size_t i,j;
-
- rijndael_encrypt(ctx, B, X);
-
- memset(B, 0, DTLS_CCM_BLOCKSIZE);
-
- if (!la)
- return;
-
-#ifndef WITH_CONTIKI
- if (la < 0xFF00) { /* 2^16 - 2^8 */
- j = 2;
- dtls_int_to_uint16(B, la);
- } else if (la <= UINT32_MAX) {
- j = 6;
- dtls_int_to_uint16(B, 0xFFFE);
- dtls_int_to_uint32(B+2, la);
- } else {
- j = 10;
- dtls_int_to_uint16(B, 0xFFFF);
- dtls_ulong_to_uint64(B+2, la);
- }
-#else /* WITH_CONTIKI */
- /* With Contiki, we are building for small devices and thus
- * anticipate that the number of additional authentication bytes
- * will not exceed 65280 bytes (0xFF00) and we can skip the
- * workarounds required for j=6 and j=10 on devices with a word size
- * of 32 bits or 64 bits, respectively.
- */
-
- assert(la < 0xFF00);
- j = 2;
- dtls_int_to_uint16(B, la);
-#endif /* WITH_CONTIKI */
-
- i = min(DTLS_CCM_BLOCKSIZE - j, la);
- memcpy(B + j, msg, i);
- la -= i;
- msg += i;
-
- memxor(B, X, DTLS_CCM_BLOCKSIZE);
-
- rijndael_encrypt(ctx, B, X);
-
- while (la > DTLS_CCM_BLOCKSIZE) {
- for (i = 0; i < DTLS_CCM_BLOCKSIZE; ++i)
- B[i] = X[i] ^ *msg++;
- la -= DTLS_CCM_BLOCKSIZE;
-
- rijndael_encrypt(ctx, B, X);
- }
-
- if (la) {
- memset(B, 0, DTLS_CCM_BLOCKSIZE);
- memcpy(B, msg, la);
- memxor(B, X, DTLS_CCM_BLOCKSIZE);
-
- rijndael_encrypt(ctx, B, X);
- }
-}
-
-static inline void
-encrypt(rijndael_ctx *ctx, size_t L, unsigned long counter,
- unsigned char *msg, size_t len,
- unsigned char A[DTLS_CCM_BLOCKSIZE],
- unsigned char S[DTLS_CCM_BLOCKSIZE]) {
-
- static unsigned long C;
-
- SET_COUNTER(A, L, counter, C);
- rijndael_encrypt(ctx, A, S);
- memxor(msg, S, len);
-}
-
-static inline void
-mac(rijndael_ctx *ctx,
- unsigned char *msg, size_t len,
- unsigned char B[DTLS_CCM_BLOCKSIZE],
- unsigned char X[DTLS_CCM_BLOCKSIZE]) {
- size_t i;
-
- for (i = 0; i < len; ++i)
- B[i] = X[i] ^ msg[i];
-
- rijndael_encrypt(ctx, B, X);
-
-}
-
-long int
-dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
- unsigned char N[DTLS_CCM_BLOCKSIZE],
- unsigned char *msg, size_t lm,
- const unsigned char *aad, size_t la) {
- size_t i, len;
- unsigned long C;
- unsigned long counter = 1; /* \bug does not work correctly on ia32 when
- lm >= 2^16 */
- unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
- unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
- unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
- unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
-
- len = lm; /* save original length */
- /* create the initial authentication block B0 */
- block0(M, L, la, lm, N, B);
- add_auth_data(ctx, aad, la, B, X);
-
- /* initialize block template */
- A[0] = L-1;
-
- /* copy the nonce */
- memcpy(A + 1, N, DTLS_CCM_BLOCKSIZE - L);
-
- while (lm >= DTLS_CCM_BLOCKSIZE) {
- /* calculate MAC */
- mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
-
- /* encrypt */
- encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
-
- /* update local pointers */
- lm -= DTLS_CCM_BLOCKSIZE;
- msg += DTLS_CCM_BLOCKSIZE;
- counter++;
- }
-
- if (lm) {
- /* Calculate MAC. The remainder of B must be padded with zeroes, so
- * B is constructed to contain X ^ msg for the first lm bytes (done in
- * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
- * (i.e., we can use memcpy() here).
- */
- memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
- mac(ctx, msg, lm, B, X);
-
- /* encrypt */
- encrypt(ctx, L, counter, msg, lm, A, S);
-
- /* update local pointers */
- msg += lm;
- }
-
- /* calculate S_0 */
- SET_COUNTER(A, L, 0, C);
- rijndael_encrypt(ctx, A, S);
-
- for (i = 0; i < M; ++i)
- *msg++ = X[i] ^ S[i];
-
- return len + M;
-}
-
-long int
-dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
- unsigned char N[DTLS_CCM_BLOCKSIZE],
- unsigned char *msg, size_t lm,
- const unsigned char *aad, size_t la) {
-
- size_t len;
- unsigned long C;
- unsigned long counter = 1; /* \bug does not work correctly on ia32 when
- lm >= 2^16 */
- unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
- unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
- unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
- unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
-
- if (lm < M)
- goto error;
-
- len = lm; /* save original length */
- lm -= M; /* detract MAC size*/
-
- /* create the initial authentication block B0 */
- block0(M, L, la, lm, N, B);
- add_auth_data(ctx, aad, la, B, X);
-
- /* initialize block template */
- A[0] = L-1;
-
- /* copy the nonce */
- memcpy(A + 1, N, DTLS_CCM_BLOCKSIZE - L);
-
- while (lm >= DTLS_CCM_BLOCKSIZE) {
- /* decrypt */
- encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
-
- /* calculate MAC */
- mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
-
- /* update local pointers */
- lm -= DTLS_CCM_BLOCKSIZE;
- msg += DTLS_CCM_BLOCKSIZE;
- counter++;
- }
-
- if (lm) {
- /* decrypt */
- encrypt(ctx, L, counter, msg, lm, A, S);
-
- /* Calculate MAC. Note that msg ends in the MAC so we must
- * construct B to contain X ^ msg for the first lm bytes (done in
- * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
- * (i.e., we can use memcpy() here).
- */
- memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
- mac(ctx, msg, lm, B, X);
-
- /* update local pointers */
- msg += lm;
- }
-
- /* calculate S_0 */
- SET_COUNTER(A, L, 0, C);
- rijndael_encrypt(ctx, A, S);
-
- memxor(msg, S, M);
-
- /* return length if MAC is valid, otherwise continue with error handling */
- if (memcmp(X, msg, M) == 0)
- return len - M;
-
- error:
- return -1;
-}
--- a/tinydtls/ccm.h Wed Oct 09 14:48:52 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* dtls -- a very basic DTLS implementation - * - * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _CCM_H_ -#define _CCM_H_ - -#include "config.h" -#include "aes/rijndael.h" - -/* implementation of Counter Mode CBC-MAC, RFC 3610 */ - -#define DTLS_CCM_BLOCKSIZE 16 /**< size of hmac blocks */ -#define DTLS_CCM_MAX 16 /**< max number of bytes in digest */ -#define DTLS_CCM_NONCE_SIZE 12 /**< size of nonce */ - -/** - * Authenticates and encrypts a message using AES in CCM mode. Please - * see also RFC 3610 for the meaning of \p M, \p L, \p lm and \p la. - * - * \param ctx The initialized rijndael_ctx object to be used for AES operations. - * \param M The number of authentication octets. - * \param L The number of bytes used to encode the message length. - * \param N The nonce value to use. You must provide \c DTLS_CCM_BLOCKSIZE - * nonce octets, although only the first \c 16 - \p L are used. - * \param msg The message to encrypt. The first \p la octets are additional - * authentication data that will be cleartext. Note that the - * encryption operation modifies the contents of \p msg and adds - * \p M bytes MAC. Therefore, the buffer must be at least - * \p lm + \p M bytes large. - * \param lm The actual length of \p msg. - * \param aad A pointer to the additional authentication data (can be \c NULL if - * \p la is zero). - * \param la The number of additional authentication octets (may be zero). - * \return FIXME - */ -long int -dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L, - unsigned char N[DTLS_CCM_BLOCKSIZE], - unsigned char *msg, size_t lm, - const unsigned char *aad, size_t la); - -long int -dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L, - unsigned char N[DTLS_CCM_BLOCKSIZE], - unsigned char *msg, size_t lm, - const unsigned char *aad, size_t la); - -#endif /* _CCM_H_ */
--- a/tinydtls/config.h Wed Oct 09 14:48:52 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define to 1 if you have the <arpa/inet.h> header file. */ -//#define HAVE_ARPA_INET_H 1 - -#define MBED 1 - -/* Define to 1 if you have the <assert.h> header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fls' function. */ -/* #undef HAVE_FLS */ - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -#define HAVE_MEMSET 1 - -/* Define to 1 if you have the <netdb.h> header file. */ -//#define HAVE_NETDB_H 1 - -/* Define to 1 if you have the <netinet/in.h> header file. */ -//#define HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if struct sockaddr_in6 has a member sin6_len. */ -/* #undef HAVE_SOCKADDR_IN6_SIN6_LEN */ - -/* Define to 1 if you have the `socket' function. */ -#define HAVE_SOCKET 1 - -/* Define to 1 if you have the <stddef.h> header file. */ -#define HAVE_STDDEF_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strnlen' function. */ -#define HAVE_STRNLEN 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -//#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -//#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -//#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the <time.h> header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -#ifndef PACKAGE_BUGREPORT -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" -#endif /* PACKAGE_BUGREPORT */ - -#ifndef PACKAGE_NAME -/* Define to the full name of this package. */ -#define PACKAGE_NAME "tinydtls" -#endif /* PACKAGE_NAME */ - -#ifndef PACKAGE_STRING -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "tinydtls 0.4.0" -#endif /* PACKAGE_STRING */ - -#ifndef PACKAGE_TARNAME -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "tinydtls" -#endif /* PACKAGE_TARNAME */ - -#ifndef PACKAGE_URL -/* Define to the home page for this package. */ -#define PACKAGE_URL "" -#endif /* PACKAGE_URL */ - -#ifndef PACKAGE_VERSION -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.4.0" -#endif /* PACKAGE_VERSION */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */
--- a/tinydtls/crypto.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,317 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#endif
-
-//#include "global.h"
-#include "debug.h"
-#include "numeric.h"
-#include "dtls.h"
-#include "crypto.h"
-#include "ccm.h"
-
-#ifndef WITH_CONTIKI
-#include <stdlib.h>
-
-static inline dtls_cipher_context_t *
-dtls_cipher_context_new() {
- return (dtls_cipher_context_t *)malloc(sizeof(dtls_cipher_context_t));
-}
-
-static inline void
-dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
- free(ctx);
-}
-#else /* WITH_CONTIKI */
-MEMB(cipher_storage, dtls_cipher_context_t, DTLS_CIPHER_CONTEXT_MAX);
-
-static inline dtls_cipher_context_t *
-dtls_cipher_context_new() {
- return (dtls_cipher_context_t *)memb_alloc(&cipher_storage);
-}
-
-static inline void
-dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
- if (ctx)
- memb_free(&cipher_storage, ctx);
-}
-#endif /* WITH_CONTIKI */
-
-extern void dtls_hmac_storage_init();
-
-void crypto_init() {
- dtls_hmac_storage_init();
-
-#ifdef WITH_CONTIKI
- memb_init(&cipher_storage);
-#endif /* WITH_CONTIKI */
-}
-
-#ifndef NDEBUG
-extern void dump(unsigned char *, size_t);
-#endif
-
-#define HMAC_UPDATE_SEED(Context,Seed,Length) \
- if (Seed) dtls_hmac_update(Context, (Seed), (Length))
-
-size_t
-dtls_p_hash(dtls_hashfunc_t h,
- const unsigned char *key, size_t keylen,
- const unsigned char *label, size_t labellen,
- const unsigned char *random1, size_t random1len,
- const unsigned char *random2, size_t random2len,
- unsigned char *buf, size_t buflen) {
- dtls_hmac_context_t *hmac_a, *hmac_p;
-
- unsigned char A[DTLS_HMAC_DIGEST_SIZE];
- unsigned char tmp[DTLS_HMAC_DIGEST_SIZE];
- size_t dlen; /* digest length */
- size_t len = 0; /* result length */
-
- hmac_a = dtls_hmac_new(key, keylen);
- if (!hmac_a)
- return 0;
-
- /* calculate A(1) from A(0) == seed */
- HMAC_UPDATE_SEED(hmac_a, label, labellen);
- HMAC_UPDATE_SEED(hmac_a, random1, random1len);
- HMAC_UPDATE_SEED(hmac_a, random2, random2len);
-
- dlen = dtls_hmac_finalize(hmac_a, A);
-
- hmac_p = dtls_hmac_new(key, keylen);
- if (!hmac_p)
- goto error;
-
- while (len + dlen < buflen) {
-
- /* FIXME: rewrite loop to avoid superflous call to dtls_hmac_init() */
- dtls_hmac_init(hmac_p, key, keylen);
- dtls_hmac_update(hmac_p, A, dlen);
-
- HMAC_UPDATE_SEED(hmac_p, label, labellen);
- HMAC_UPDATE_SEED(hmac_p, random1, random1len);
- HMAC_UPDATE_SEED(hmac_p, random2, random2len);
-
- len += dtls_hmac_finalize(hmac_p, tmp);
- memcpy(buf, tmp, dlen);
- buf += dlen;
-
- /* calculate A(i+1) */
- dtls_hmac_init(hmac_a, key, keylen);
- dtls_hmac_update(hmac_a, A, dlen);
- dtls_hmac_finalize(hmac_a, A);
- }
-
- dtls_hmac_init(hmac_p, key, keylen);
- dtls_hmac_update(hmac_p, A, dlen);
-
- HMAC_UPDATE_SEED(hmac_p, label, labellen);
- HMAC_UPDATE_SEED(hmac_p, random1, random1len);
- HMAC_UPDATE_SEED(hmac_p, random2, random2len);
-
- dtls_hmac_finalize(hmac_p, tmp);
- memcpy(buf, tmp, buflen - len);
-
- error:
- dtls_hmac_free(hmac_a);
- dtls_hmac_free(hmac_p);
-
- return buflen;
-}
-
-size_t
-dtls_prf(const unsigned char *key, size_t keylen,
- const unsigned char *label, size_t labellen,
- const unsigned char *random1, size_t random1len,
- const unsigned char *random2, size_t random2len,
- unsigned char *buf, size_t buflen) {
-
- /* Clear the result buffer */
- memset(buf, 0, buflen);
- return dtls_p_hash(HASH_SHA256,
- key, keylen,
- label, labellen,
- random1, random1len,
- random2, random2len,
- buf, buflen);
-}
-
-void
-dtls_mac(dtls_hmac_context_t *hmac_ctx,
- const unsigned char *record,
- const unsigned char *packet, size_t length,
- unsigned char *buf) {
- uint16 L;
- dtls_int_to_uint16(L, length);
-
- assert(hmac_ctx);
- dtls_hmac_update(hmac_ctx, record +3, sizeof(uint16) + sizeof(uint48));
- dtls_hmac_update(hmac_ctx, record, sizeof(uint8) + sizeof(uint16));
- dtls_hmac_update(hmac_ctx, L, sizeof(uint16));
- dtls_hmac_update(hmac_ctx, packet, length);
-
- dtls_hmac_finalize(hmac_ctx, buf);
-}
-
-static inline void
-dtls_ccm_init(aes128_ccm_t *ccm_ctx, unsigned char *N, size_t length) {
- assert(ccm_ctx);
-
- if (length < DTLS_CCM_BLOCKSIZE)
- memset(ccm_ctx->N + length, 0, DTLS_CCM_BLOCKSIZE - length);
-
- memcpy(ccm_ctx->N, N, DTLS_CCM_BLOCKSIZE);
-}
-
-size_t
-dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
- unsigned char *buf,
- const unsigned char *aad, size_t la) {
- long int len;
-
- assert(ccm_ctx);
-
- len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, 8 /* M */,
- max(2, 15 - DTLS_CCM_NONCE_SIZE),
- ccm_ctx->N,
- buf, srclen,
- aad, la);
- return len;
-}
-
-size_t
-dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
- size_t srclen, unsigned char *buf,
- const unsigned char *aad, size_t la) {
- long int len;
-
- assert(ccm_ctx);
-
- len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, 8 /* M */,
- max(2, 15 - DTLS_CCM_NONCE_SIZE),
- ccm_ctx->N,
- buf, srclen,
- aad, la);
- return len;
-}
-
-size_t
-dtls_pre_master_secret(unsigned char *key, size_t keylen,
- unsigned char *result) {
- unsigned char *p = result;
-
- dtls_int_to_uint16(p, keylen);
- p += sizeof(uint16);
-
- memset(p, 0, keylen);
- p += keylen;
-
- memcpy(p, result, sizeof(uint16));
- p += sizeof(uint16);
-
- memcpy(p, key, keylen);
-
- return (sizeof(uint16) + keylen) << 1;
-}
-
-void
-dtls_cipher_set_iv(dtls_cipher_context_t *ctx,
- unsigned char *iv, size_t length) {
- assert(ctx);
- dtls_ccm_init(&ctx->data, iv, length);
-}
-
-dtls_cipher_context_t *
-dtls_cipher_new(dtls_cipher_t cipher,
- unsigned char *key, size_t keylen) {
- dtls_cipher_context_t *cipher_context = NULL;
-
- cipher_context = dtls_cipher_context_new();
- if (!cipher_context) {
- warn("cannot allocate cipher_context\r\n");
- return NULL;
- }
-
- switch (cipher) {
- case TLS_PSK_WITH_AES_128_CCM_8: {
- aes128_ccm_t *ccm_ctx = &cipher_context->data;
-
- if (rijndael_set_key_enc_only(&ccm_ctx->ctx, key, 8 * keylen) < 0) {
- /* cleanup everything in case the key has the wrong size */
- warn("cannot set rijndael key\n");
- goto error;
- }
- break;
- }
- default:
- warn("unknown cipher %04x\n", cipher);
- goto error;
- }
-
- return cipher_context;
- error:
- dtls_cipher_context_free(cipher_context);
- return NULL;
-}
-
-void
-dtls_cipher_free(dtls_cipher_context_t *cipher_context) {
- dtls_cipher_context_free(cipher_context);
-}
-
-int
-dtls_encrypt(dtls_cipher_context_t *ctx,
- const unsigned char *src, size_t length,
- unsigned char *buf,
- const unsigned char *aad, size_t la) {
- if (ctx) {
- if (src != buf)
- memmove(buf, src, length);
- return dtls_ccm_encrypt(&ctx->data, src, length, buf,
- aad, la);
- }
-
- return -1;
-}
-
-int
-dtls_decrypt(dtls_cipher_context_t *ctx,
- const unsigned char *src, size_t length,
- unsigned char *buf,
- const unsigned char *aad, size_t la) {
- if (ctx) {
- if (src != buf)
- memmove(buf, src, length);
- return dtls_ccm_decrypt(&ctx->data, src, length, buf,
- aad, la);
- }
-
- return -1;
-}
-
--- a/tinydtls/crypto.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _CRYPTO_H_
-#define _CRYPTO_H_
-
-#include "config.h"
-
-#include <stdlib.h> /* for rand() and srand() */
-
-#include "aes/rijndael.h"
-
-#include "prng.h"
-#include "global.h"
-#include "numeric.h"
-#include "hmac.h"
-#include "ccm.h"
-
-/* TLS_PSK_WITH_AES_128_CCM_8 */
-#define DTLS_MAC_KEY_LENGTH 0
-#define DTLS_KEY_LENGTH 16 /* AES-128 */
-#define DTLS_BLK_LENGTH 16 /* AES-128 */
-#define DTLS_MAC_LENGTH DTLS_HMAC_DIGEST_SIZE
-#define DTLS_IV_LENGTH 4 /* length of nonce_explicit */
-
-/**
- * Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must
- * be large enough to hold the pre_master_secret, i.e. twice the length of the
- * pre-shared key + 1.
- */
-#define MAX_KEYBLOCK_LENGTH \
- (2 * DTLS_MAC_KEY_LENGTH + 2 * DTLS_KEY_LENGTH + 2 * DTLS_IV_LENGTH)
-
-/** Length of DTLS master_secret */
-#define DTLS_MASTER_SECRET_LENGTH 48
-
-#ifndef DTLS_CIPHER_CONTEXT_MAX
-#define DTLS_CIPHER_CONTEXT_MAX 4
-#endif
-
-typedef enum { AES128=0
-} dtls_crypto_alg;
-
-/** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */
-typedef struct {
- rijndael_ctx ctx; /**< AES-128 encryption context */
- unsigned char N[DTLS_CCM_BLOCKSIZE]; /**< nonce */
-} aes128_ccm_t;
-
-typedef struct dtls_cipher_context_t {
- /** numeric identifier of this cipher suite in host byte order. */
- dtls_cipher_t code;
- aes128_ccm_t data; /**< The crypto context */
-} dtls_cipher_context_t;
-
-typedef enum { DTLS_CLIENT=0, DTLS_SERVER } dtls_peer_type;
-
-typedef struct {
- uint8 client_random[32]; /**< client random gmt and bytes */
-
- dtls_peer_type role; /**< denotes if the remote peer is DTLS_CLIENT or DTLS_SERVER */
- unsigned char compression; /**< compression method */
-
- dtls_cipher_t cipher; /**< cipher type */
-
- /** the session's master secret */
- uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
-
- /**
- * The key block generated from PRF applied to client and server
- * random bytes. The actual size is given by the selected cipher and
- * can be calculated using dtls_kb_size(). Use \c dtls_kb_ macros to
- * access the components of the key block.
- */
- uint8 key_block[MAX_KEYBLOCK_LENGTH];
-
- dtls_cipher_context_t *read_cipher; /**< decryption context */
- dtls_cipher_context_t *write_cipher; /**< encryption context */
-} dtls_security_parameters_t;
-
-/* The following macros provide access to the components of the
- * key_block in the security parameters. */
-
-#define dtls_kb_client_mac_secret(Param) ((Param)->key_block)
-#define dtls_kb_server_mac_secret(Param) \
- (dtls_kb_client_mac_secret(Param) + DTLS_MAC_KEY_LENGTH)
-#define dtls_kb_remote_mac_secret(Param) \
- ((Param)->role == DTLS_CLIENT \
- ? dtls_kb_client_mac_secret(Param) \
- : dtls_kb_server_mac_secret(Param))
-#define dtls_kb_local_mac_secret(Param) \
- ((Param)->role == DTLS_SERVER \
- ? dtls_kb_client_mac_secret(Param) \
- : dtls_kb_server_mac_secret(Param))
-#define dtls_kb_mac_secret_size(Param) DTLS_MAC_KEY_LENGTH
-#define dtls_kb_client_write_key(Param) \
- (dtls_kb_server_mac_secret(Param) + DTLS_MAC_KEY_LENGTH)
-#define dtls_kb_server_write_key(Param) \
- (dtls_kb_client_write_key(Param) + DTLS_KEY_LENGTH)
-#define dtls_kb_remote_write_key(Param) \
- ((Param)->role == DTLS_CLIENT \
- ? dtls_kb_client_write_key(Param) \
- : dtls_kb_server_write_key(Param))
-#define dtls_kb_local_write_key(Param) \
- ((Param)->role == DTLS_SERVER \
- ? dtls_kb_client_write_key(Param) \
- : dtls_kb_server_write_key(Param))
-#define dtls_kb_key_size(Param) DTLS_KEY_LENGTH
-#define dtls_kb_client_iv(Param) \
- (dtls_kb_server_write_key(Param) + DTLS_KEY_LENGTH)
-#define dtls_kb_server_iv(Param) \
- (dtls_kb_client_iv(Param) + DTLS_IV_LENGTH)
-#define dtls_kb_remote_iv(Param) \
- ((Param)->role == DTLS_CLIENT \
- ? dtls_kb_client_iv(Param) \
- : dtls_kb_server_iv(Param))
-#define dtls_kb_local_iv(Param) \
- ((Param)->role == DTLS_SERVER \
- ? dtls_kb_client_iv(Param) \
- : dtls_kb_server_iv(Param))
-#define dtls_kb_iv_size(Param) DTLS_IV_LENGTH
-
-#define dtls_kb_size(Param) \
- (2 * (dtls_kb_mac_secret_size(Param) + \
- dtls_kb_key_size(Param) + dtls_kb_iv_size(Param)))
-
-/* just for consistency */
-#define dtls_kb_digest_size(Param) DTLS_MAC_LENGTH
-
-/**
- * Expands the secret and key to a block of DTLS_HMAC_MAX
- * size according to the algorithm specified in section 5 of
- * RFC 4346.
- *
- * \param h Identifier of the hash function to use.
- * \param key The secret.
- * \param keylen Length of \p key.
- * \param seed The seed.
- * \param seedlen Length of \p seed.
- * \param buf Output buffer where the result is XORed into
- * The buffe must be capable to hold at least
- * \p buflen bytes.
- * \return The actual number of bytes written to \p buf or 0
- * on error.
- */
-size_t dtls_p_hash(dtls_hashfunc_t h,
- const unsigned char *key, size_t keylen,
- const unsigned char *label, size_t labellen,
- const unsigned char *random1, size_t random1len,
- const unsigned char *random2, size_t random2len,
- unsigned char *buf, size_t buflen);
-
-/**
- * This function implements the TLS PRF for DTLS_VERSION. For version
- * 1.0, the PRF is P_MD5 ^ P_SHA1 while version 1.2 uses
- * P_SHA256. Currently, the actual PRF is selected at compile time.
- */
-size_t dtls_prf(const unsigned char *key, size_t keylen,
- const unsigned char *label, size_t labellen,
- const unsigned char *random1, size_t random1len,
- const unsigned char *random2, size_t random2len,
- unsigned char *buf, size_t buflen);
-
-/**
- * Calculates MAC for record + cleartext packet and places the result
- * in \p buf. The given \p hmac_ctx must be initialized with the HMAC
- * function to use and the proper secret. As the DTLS mac calculation
- * requires data from the record header, \p record must point to a
- * buffer of at least \c sizeof(dtls_record_header_t) bytes. Usually,
- * the remaining packet will be encrypted, therefore, the cleartext
- * is passed separately in \p packet.
- *
- * \param hmac_ctx The HMAC context to use for MAC calculation.
- * \param record The record header.
- * \param packet Cleartext payload to apply the MAC to.
- * \param length Size of \p packet.
- * \param buf A result buffer that is large enough to hold
- * the generated digest.
- */
-void dtls_mac(dtls_hmac_context_t *hmac_ctx,
- const unsigned char *record,
- const unsigned char *packet, size_t length,
- unsigned char *buf);
-
-/**
- * Encrypts the specified \p src of given \p length, writing the
- * result to \p buf. The cipher implementation may add more data to
- * the result buffer such as an initialization vector or padding
- * (e.g. for block cipers in CBC mode). The caller therefore must
- * ensure that \p buf provides sufficient storage to hold the result.
- * Usually this means ( 2 + \p length / blocksize ) * blocksize. The
- * function returns a value less than zero on error or otherwise the
- * number of bytes written.
- *
- * \param ctx The cipher context to use.
- * \param src The data to encrypt.
- * \param length The actual size of of \p src.
- * \param buf The result buffer. \p src and \p buf must not
- * overlap.
- * \param aad additional data for AEAD ciphers
- * \param aad_length actual size of @p aad
- * \return The number of encrypted bytes on success, less than zero
- * otherwise.
- */
-int dtls_encrypt(dtls_cipher_context_t *ctx,
- const unsigned char *src, size_t length,
- unsigned char *buf,
- const unsigned char *aad, size_t aad_length);
-
-/**
- * Decrypts the given buffer \p src of given \p length, writing the
- * result to \p buf. The function returns \c -1 in case of an error,
- * or the number of bytes written. Note that for block ciphers, \p
- * length must be a multiple of the cipher's block size. A return
- * value between \c 0 and the actual length indicates that only \c n-1
- * block have been processed. Unlike dtls_encrypt(), the source
- * and destination of dtls_decrypt() may overlap.
- *
- * \param ctx The cipher context to use.
- * \param src The buffer to decrypt.
- * \param length The length of the input buffer.
- * \param buf The result buffer.
- * \param aad additional authentication data for AEAD ciphers
- * \param aad_length actual size of @p aad
- * \return Less than zero on error, the number of decrypted bytes
- * otherwise.
- */
-int dtls_decrypt(dtls_cipher_context_t *ctx,
- const unsigned char *src, size_t length,
- unsigned char *buf,
- const unsigned char *a_data, size_t a_data_length);
-
-/* helper functions */
-
-/**
- * Generates pre_master_sercet from given PSK and fills the result
- * according to the "plain PSK" case in section 2 of RFC 4279.
- * Diffie-Hellman and RSA key exchange are currently not supported.
- *
- * @param key The shared key.
- * @param keylen Length of @p key in bytes.
- * @param result The derived pre master secret.
- * @return The actual length of @p result.
- */
-size_t dtls_pre_master_secret(unsigned char *key, size_t keylen,
- unsigned char *result);
-
-/**
- * Creates a new dtls_cipher_context_t object for given @c cipher.
- * The storage allocated for this object must be released using
- * dtls_cipher_free().
- *
- * @param code Code of the requested cipher (host byte order)
- * @param key The encryption and decryption key.
- * @param keylen Actual length of @p key.
- * @return A new dtls_cipher_context_t object or @c NULL in case
- * something went wrong (e.g. insufficient memory or wrong
- * key length)
- */
-dtls_cipher_context_t *dtls_cipher_new(dtls_cipher_t code,
- unsigned char *key, size_t keylen);
-
-/**
- * Releases the storage allocated by dtls_cipher_new() for @p cipher_context
- */
-void dtls_cipher_free(dtls_cipher_context_t *cipher_context);
-
-
-/**
- * Initializes the given cipher context @p ctx with the initialization
- * vector @p iv of length @p length. */
-void dtls_cipher_set_iv(dtls_cipher_context_t *ctx,
- unsigned char *iv, size_t length);
-
-#endif /* _CRYPTO_H_ */
-
--- a/tinydtls/debug.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-/* debug.c -- debug utilities
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "config.h"
-
-#if defined(HAVE_ASSERT_H) && !defined(assert)
-#include <assert.h>
-#endif
-
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include "global.h"
-#include "debug.h"
-
-#ifdef WITH_CONTIKI
-# ifndef DEBUG
-# define DEBUG DEBUG_PRINT
-# endif /* DEBUG */
-#include "net/uip-debug.h"
-#else
-#define PRINTF(...)
-#endif
-
-static int maxlog = LOG_WARN; /* default maximum log level */
-
-log_t
-dtls_get_log_level() {
- return maxlog;
-}
-
-void
-dtls_set_log_level(log_t level) {
- maxlog = level;
-}
-
-/* this array has the same order as the type log_t */
-static char *loglevels[] = {
- "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG"
-};
-
-#ifdef HAVE_TIME_H
-
-static inline size_t
-print_timestamp(char *s, size_t len, time_t t) {
- struct tm *tmp;
- tmp = localtime(&t);
- return strftime(s, len, "%b %d %H:%M:%S", tmp);
-}
-
-#else /* alternative implementation: just print the timestamp */
-
-static inline size_t
-print_timestamp(char *s, size_t len, clock_time_t t) {
-#ifdef HAVE_SNPRINTF
- return snprintf(s, len, "%u.%03u",
- (unsigned int)(t / CLOCK_SECOND),
- (unsigned int)(t % CLOCK_SECOND));
-#else /* HAVE_SNPRINTF */
- /* @todo do manual conversion of timestamp */
- return 0;
-#endif /* HAVE_SNPRINTF */
-}
-
-#endif /* HAVE_TIME_H */
-
-#ifndef HAVE_STRNLEN
-/**
- * A length-safe strlen() fake.
- *
- * @param s The string to count characters != 0.
- * @param maxlen The maximum length of @p s.
- *
- * @return The length of @p s.
- */
-static inline size_t
-strnlen(const char *s, size_t maxlen) {
- size_t n = 0;
- while(*s++ && n < maxlen)
- ++n;
- return n;
-}
-#endif /* HAVE_STRNLEN */
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-size_t
-dsrv_print_addr(const session_t *addr, unsigned char *buf, size_t len) {
-#ifdef HAVE_ARPA_INET_H
- const void *addrptr = NULL;
- in_port_t port;
- unsigned char *p = buf;
-
- switch (addr->addr.sa.sa_family) {
- case AF_INET:
- addrptr = &addr->addr.sin.sin_addr;
- port = ntohs(addr->addr.sin.sin_port);
- break;
- case AF_INET6:
- if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */
- return 0;
-
- *p++ = '[';
-
- addrptr = &addr->addr.sin6.sin6_addr;
- port = ntohs(addr->addr.sin6.sin6_port);
-
- break;
- default:
- memcpy(buf, "(unknown address type)", min(22, len));
- return min(22, len);
- }
-
- if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, len) == 0) {
- perror("dsrv_print_addr");
- return 0;
- }
-
- p += strnlen((char *)p, len);
-
- if (addr->addr.sa.sa_family == AF_INET6) {
- if (p < buf + len) {
- *p++ = ']';
- } else
- return 0;
- }
-
- p += snprintf((char *)p, buf + len - p + 1, ":%d", port);
-
- return buf + len - p;
-#else /* HAVE_ARPA_INET_H */
-# if WITH_CONTIKI
- unsigned char *p = buf;
- uint8_t i;
-# if WITH_UIP6
- const unsigned char hex[] = "0123456789ABCDEF";
-
- if (len < 41)
- return 0;
-
- *p++ = '[';
-
- for (i=0; i < 8; i += 4) {
- *p++ = hex[(addr->addr.u16[i] & 0xf000) >> 24];
- *p++ = hex[(addr->addr.u16[i] & 0x0f00) >> 16];
- *p++ = hex[(addr->addr.u16[i] & 0x00f0) >> 8];
- *p++ = hex[(addr->addr.u16[i] & 0x000f)];
- *p++ = ':';
- }
- *(p-1) = ']';
-# else /* WITH_UIP6 */
-# warning "IPv4 network addresses will not be included in debug output"
-
- if (len < 21)
- return 0;
-# endif /* WITH_UIP6 */
- if (buf + len - p < 6)
- return 0;
-
-#ifdef HAVE_SNPRINTF
- p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port));
-#else /* HAVE_SNPRINTF */
- /* @todo manual conversion of port number */
-#endif /* HAVE_SNPRINTF */
-
- return buf + len - p;
-# else /* WITH_CONTIKI */
- /* TODO: output addresses manually */
-# warning "inet_ntop() not available, network addresses will not be included in debug output"
-# endif /* WITH_CONTIKI */
- return 0;
-#endif
-}
-
-#ifndef WITH_CONTIKI
-void
-dsrv_log(log_t level, char *format, ...) {
- static char timebuf[32];
- va_list ap;
- FILE *log_fd;
-
- if (maxlog < level)
- return;
-
- log_fd = level <= LOG_CRIT ? stderr : stdout;
-
- if (print_timestamp(timebuf,sizeof(timebuf), time(NULL)))
- fprintf(log_fd, "%s ", timebuf);
-
- if (level >= 0 && level <= LOG_DEBUG)
- printf("%s ", loglevels[level]);
-
- va_start(ap, format);
- vprintf(format, ap);
- va_end(ap);
- fflush(stdout);
-}
-#else /* WITH_CONTIKI */
-void
-dsrv_log(log_t level, char *format, ...) {
- static char timebuf[32];
- va_list ap;
-
- if (maxlog < level)
- return;
-
- if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
- PRINTF("%s ", timebuf);
-
- if (level >= 0 && level <= LOG_DEBUG)
- PRINTF("%s ", loglevels[level]);
-
- va_start(ap, format);
-#ifdef HAVE_VPRINTF
- vprintf(format, ap);
-#else
- PRINTF(format, ap);
-#endif
- va_end(ap);
-}
-#endif /* WITH_CONTIKI */
--- a/tinydtls/debug.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/* debug.h -- debug utilities
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _DEBUG_H_
-#define _DEBUG_H_
-
-#include "config.h"
-
-/** Pre-defined log levels akin to what is used in \b syslog. */
-typedef enum { LOG_EMERG=0, LOG_ALERT, LOG_CRIT, LOG_WARN,
- LOG_NOTICE, LOG_INFO, LOG_DEBUG
-} log_t;
-
-/** Returns the current log level. */
-log_t dtls_get_log_level();
-
-/** Sets the log level to the specified value. */
-void dtls_set_log_level(log_t level);
-
-/**
- * Writes the given text to \c stdout. The text is output only when \p
- * level is below or equal to the log level that set by
- * set_log_level(). */
-void dsrv_log(log_t level, char *format, ...);
-
-/* A set of convenience macros for common log levels. */
-#define info(...) dsrv_log(LOG_INFO, __VA_ARGS__)
-#define warn(...) dsrv_log(LOG_WARN, __VA_ARGS__)
-#define debug(...) dsrv_log(LOG_DEBUG, __VA_ARGS__)
-
-#endif /* _DEBUG_H_ */
--- a/tinydtls/dtls.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2495 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "config.h"
-
-#include "dtls_time.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#endif
-#ifndef WITH_CONTIKI
-#include <stdlib.h>
-#include "uthash.h"
-#else /* WITH_CONTIKI */
-# ifndef NDEBUG
-# define DEBUG DEBUG_PRINT
-# include "net/uip-debug.h"
-# endif /* NDEBUG */
-#endif /* WITH_CONTIKI */
-
-#include "debug.h"
-#include "numeric.h"
-#include "netq.h"
-#include "dtls.h"
-
-
-#ifdef WITH_SHA256
-# include "sha2/sha2.h"
-#endif
-
-//#include "bsd_socket.h"
-
-#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_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_sequence_number(H) dtls_uint48_to_ulong(&(H)->sequence_number)
-#define dtls_get_fragment_length(H) dtls_uint24_to_int(&(H)->fragment_length)
-
-#ifndef WITH_CONTIKI
-#define HASH_FIND_PEER(head,sess,out) \
- HASH_FIND(hh,head,sess,sizeof(session_t),out)
-#define HASH_ADD_PEER(head,sess,add) \
- HASH_ADD(hh,head,sess,sizeof(session_t),add)
-#define HASH_DEL_PEER(head,delptr) \
- HASH_DELETE(hh,head,delptr)
-#endif /* WITH_CONTIKI */
-
-#define DTLS_RH_LENGTH sizeof(dtls_record_header_t)
-#define DTLS_HS_LENGTH sizeof(dtls_handshake_header_t)
-#define DTLS_CH_LENGTH sizeof(dtls_client_hello_t) /* no variable length fields! */
-#define DTLS_HV_LENGTH sizeof(dtls_hello_verify_t)
-#define DTLS_SH_LENGTH (2 + 32 + 1 + 2 + 1)
-#define DTLS_CKX_LENGTH 1
-#define DTLS_FIN_LENGTH 12
-
-#define HS_HDR_LENGTH DTLS_RH_LENGTH + DTLS_HS_LENGTH
-#define HV_HDR_LENGTH HS_HDR_LENGTH + DTLS_HV_LENGTH
-
-#define HIGH(V) (((V) >> 8) & 0xff)
-#define LOW(V) ((V) & 0xff)
-
-#define DTLS_RECORD_HEADER(M) ((dtls_record_header_t *)(M))
-#define DTLS_HANDSHAKE_HEADER(M) ((dtls_handshake_header_t *)(M))
-
-#define HANDSHAKE(M) ((dtls_handshake_header_t *)((M) + DTLS_RH_LENGTH))
-#define CLIENTHELLO(M) ((dtls_client_hello_t *)((M) + HS_HDR_LENGTH))
-
-#define IS_HELLOVERIFY(M,L) \
- ((L) >= DTLS_HS_LENGTH + DTLS_HV_LENGTH && (M)[0] == DTLS_HT_HELLO_VERIFY_REQUEST)
-#define IS_SERVERHELLO(M,L) \
- ((L) >= DTLS_HS_LENGTH + 6 && (M)[0] == DTLS_HT_SERVER_HELLO)
-#define IS_SERVERHELLODONE(M,L) \
- ((L) >= DTLS_HS_LENGTH && (M)[0] == DTLS_HT_SERVER_HELLO_DONE)
-#define IS_FINISHED(M,L) \
- ((L) >= DTLS_HS_LENGTH + DTLS_FIN_LENGTH && (M)[0] == DTLS_HT_FINISHED)
-
-/* The length check here should work because dtls_*_to_int() works on
- * unsigned char. Otherwise, broken messages could cause severe
- * trouble. Note that this macro jumps out of the current program flow
- * when the message is too short. Beware!
- */
-#define SKIP_VAR_FIELD(P,L,T) { \
- if (L < dtls_ ## T ## _to_int(P) + sizeof(T)) \
- goto error; \
- L -= dtls_ ## T ## _to_int(P) + sizeof(T); \
- P += dtls_ ## T ## _to_int(P) + sizeof(T); \
- }
-
-uint8 _clear[DTLS_MAX_BUF]; /* target buffer message decryption */
-uint8 _buf[DTLS_MAX_BUF]; /* target buffer for several crypto operations */
-
-#ifndef NDEBUG
-void hexdump(const unsigned char *packet, int length);
-void dump(unsigned char *buf, size_t len);
-#endif
-
-/* some constants for the PRF */
-#define PRF_LABEL(Label) prf_label_##Label
-#define PRF_LABEL_SIZE(Label) (sizeof(PRF_LABEL(Label)) - 1)
-
-static const unsigned char prf_label_master[] = "master secret";
-static const unsigned char prf_label_key[] = "key expansion";
-static const unsigned char prf_label_client[] = "client";
-static const unsigned char prf_label_server[] = "server";
-static const unsigned char prf_label_finished[] = " finished";
-
-extern void netq_init();
-extern void crypto_init();
-extern void peer_init();
-
-dtls_context_t the_dtls_context;
-
-void
-dtls_init() {
- dtls_clock_init();
- netq_init();
- crypto_init();
- peer_init();
-}
-
-/* Calls cb_alert() with given arguments if defined, otherwise an
- * error message is logged and the result is -1. This is just an
- * internal helper.
- */
-#define CALL(Context, which, ...) \
- ((Context)->h && (Context)->h->which \
- ? (Context)->h->which((Context), ##__VA_ARGS__) \
- : -1)
-
-/**
- * Sends the fragment of length \p buflen given in \p buf to the
- * specified \p peer. The data will be MAC-protected and encrypted
- * according to the selected cipher and split into one or more DTLS
- * records of the specified \p type. This function returns the number
- * of bytes that were sent, or \c -1 if an error occurred.
- *
- * \param ctx The DTLS context to use.
- * \param peer The remote peer.
- * \param type The content type of the record.
- * \param buf The data to send.
- * \param buflen The actual length of \p buf.
- * \return Less than zero on error, the number of bytes written otherwise.
- */
-int dtls_send(dtls_context_t *ctx, dtls_peer_t *peer, unsigned char type,
- uint8 *buf, size_t buflen);
-
-/**
- * Stops ongoing retransmissions of handshake messages for @p peer.
- */
-void dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer);
-
-dtls_peer_t *
-dtls_get_peer(const dtls_context_t *ctx, const session_t *session) {
- dtls_peer_t *p = NULL;
-
-#ifndef WITH_CONTIKI
- HASH_FIND_PEER(ctx->peers, session, p);
-#else /* WITH_CONTIKI */
- for (p = list_head(ctx->peers); p; p = list_item_next(p))
- if (dtls_session_equals(&p->session, session))
- return p;
-#endif /* WITH_CONTIKI */
-
- return p;
-}
-
-void
-dtls_add_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
-#ifndef WITH_CONTIKI
- HASH_ADD_PEER(ctx->peers, session, peer);
-#else /* WITH_CONTIKI */
- list_add(ctx->peers, peer);
-#endif /* WITH_CONTIKI */
-}
-
-int
-dtls_write(struct dtls_context_t *ctx,
- session_t *dst, uint8 *buf, size_t len) {
-
- dtls_peer_t *peer = dtls_get_peer(ctx, dst);
-
- /* Check if peer connection already exists */
- if (!peer) { /* no ==> create one */
- int res;
-
- /* dtls_connect() returns a value greater than zero if a new
- * connection attempt is made, 0 for session reuse. */
- res = dtls_connect(ctx, dst);
-
- return (res >= 0) ? 0 : res;
- } else { /* a session exists, check if it is in state connected */
-
- if (peer->state != DTLS_STATE_CONNECTED) {
- return 0;
- } else {
- return dtls_send(ctx, peer, DTLS_CT_APPLICATION_DATA, buf, len);
- }
- }
-}
-
-int
-dtls_get_cookie(uint8 *msg, int msglen, uint8 **cookie) {
- /* To access the cookie, we have to determine the session id's
- * length and skip the whole thing. */
- if (msglen < DTLS_HS_LENGTH + DTLS_CH_LENGTH + sizeof(uint8)
- || dtls_uint16_to_int(msg + DTLS_HS_LENGTH) != DTLS_VERSION)
- return -1;
- msglen -= DTLS_HS_LENGTH + DTLS_CH_LENGTH;
- msg += DTLS_HS_LENGTH + DTLS_CH_LENGTH;
-
- SKIP_VAR_FIELD(msg, msglen, uint8); /* skip session id */
-
- if (msglen < (*msg & 0xff) + sizeof(uint8))
- return -1;
-
- *cookie = msg + sizeof(uint8);
- return dtls_uint8_to_int(msg);
-
- error:
- return -1;
-}
-
-int
-dtls_create_cookie(dtls_context_t *ctx,
- session_t *session,
- uint8 *msg, int msglen,
- uint8 *cookie, int *clen) {
- unsigned char buf[DTLS_HMAC_MAX];
- size_t len, e;
-
- /* create cookie with HMAC-SHA256 over:
- * - SECRET
- * - session parameters (only IP address?)
- * - client version
- * - random gmt and bytes
- * - session id
- * - cipher_suites
- * - compression method
- */
-
- /* We use our own buffer as hmac_context instead of a dynamic buffer
- * created by dtls_hmac_new() to separate storage space for cookie
- * creation from storage that is used in real sessions. Note that
- * the buffer size must fit with the default hash algorithm (see
- * implementation of dtls_hmac_context_new()). */
-
- dtls_hmac_context_t hmac_context;
- dtls_hmac_init(&hmac_context, ctx->cookie_secret, DTLS_COOKIE_SECRET_LENGTH);
-
- dtls_hmac_update(&hmac_context,
- (unsigned char *)&session->addr, session->size);
-
- /* feed in the beginning of the Client Hello up to and including the
- session id */
- e = sizeof(dtls_client_hello_t);
- e += (*(msg + DTLS_HS_LENGTH + e) & 0xff) + sizeof(uint8);
-
- dtls_hmac_update(&hmac_context, msg + DTLS_HS_LENGTH, e);
-
- /* skip cookie bytes and length byte */
- e += *(uint8 *)(msg + DTLS_HS_LENGTH + e) & 0xff;
- e += sizeof(uint8);
-
- dtls_hmac_update(&hmac_context,
- msg + DTLS_HS_LENGTH + e,
- dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)) - e);
-
- len = dtls_hmac_finalize(&hmac_context, buf);
-
- if (len < *clen) {
- memset(cookie + len, 0, *clen - len);
- *clen = len;
- }
-
- memcpy(cookie, buf, *clen);
- return 1;
-}
-
-#ifdef DTLS_CHECK_CONTENTTYPE
-/* used to check if a received datagram contains a DTLS message */
-static char const content_types[] = {
- DTLS_CT_CHANGE_CIPHER_SPEC,
- DTLS_CT_ALERT,
- DTLS_CT_HANDSHAKE,
- DTLS_CT_APPLICATION_DATA,
- 0 /* end marker */
-};
-#endif
-
-/**
- * Checks if \p msg points to a valid DTLS record. If
- *
- */
-static unsigned int
-is_record(uint8 *msg, int msglen) {
- unsigned int rlen = 0;
-
- if (msglen >= DTLS_RH_LENGTH /* FIXME allow empty records? */
-#ifdef DTLS_CHECK_CONTENTTYPE
- && strchr(content_types, msg[0])
-#endif
- && msg[1] == HIGH(DTLS_VERSION)
- && msg[2] == LOW(DTLS_VERSION))
- {
- 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;
- }
-
- return rlen;
-}
-
-/**
- * Initializes \p buf as record header. The caller must ensure that \p
- * buf is capable of holding at least \c sizeof(dtls_record_header_t)
- * bytes. Increments sequence number counter of \p peer.
- * \return pointer to the next byte after the written header
- */
-static inline uint8 *
-dtls_set_record_header(uint8 type, dtls_peer_t *peer, uint8 *buf) {
-
- dtls_int_to_uint8(buf, type);
- buf += sizeof(uint8);
-
- dtls_int_to_uint16(buf, DTLS_VERSION);
- buf += sizeof(uint16);
-
- if (peer) {
- memcpy(buf, &peer->epoch, sizeof(uint16) + sizeof(uint48));
-
- /* increment record sequence counter by 1 */
- inc_uint(uint48, peer->rseq);
- } else {
- memset(buf, 0, sizeof(uint16) + sizeof(uint48));
- }
-
- buf += sizeof(uint16) + sizeof(uint48);
-
- memset(buf, 0, sizeof(uint16));
- return buf + sizeof(uint16);
-}
-
-/**
- * Initializes \p buf as handshake header. The caller must ensure that \p
- * buf is capable of holding at least \c sizeof(dtls_handshake_header_t)
- * bytes. Increments message sequence number counter of \p peer.
- * \return pointer to the next byte after \p buf
- */
-static inline uint8 *
-dtls_set_handshake_header(uint8 type, dtls_peer_t *peer,
- int length,
- int frag_offset, int frag_length,
- uint8 *buf) {
-
- dtls_int_to_uint8(buf, type);
- buf += sizeof(uint8);
-
- dtls_int_to_uint24(buf, length);
- buf += sizeof(uint24);
-
- if (peer) {
- /* increment handshake message sequence counter by 1 */
- inc_uint(uint16, peer->hs_state.mseq);
-
- /* and copy the result to buf */
- memcpy(buf, &peer->hs_state.mseq, sizeof(uint16));
- } else {
- memset(buf, 0, sizeof(uint16));
- }
- buf += sizeof(uint16);
-
- dtls_int_to_uint24(buf, frag_offset);
- buf += sizeof(uint24);
-
- dtls_int_to_uint24(buf, frag_length);
- buf += sizeof(uint24);
-
- return buf;
-}
-
-/**
- * Checks a received Client Hello message for a valid cookie. When the
- * Client Hello contains no cookie, the function fails and a Hello
- * Verify Request is sent to the peer (using the write callback function
- * registered with \p ctx). The return value is \c -1 on error, \c 0 when
- * undecided, and \c 1 if the Client Hello was good.
- *
- * \param ctx The DTLS context.
- * \param peer The remote party we are talking to, if any.
- * \param session Transport address of the remote peer.
- * \param msg The received datagram.
- * \param msglen Length of \p msg.
- * \return \c 1 if msg is a Client Hello with a valid cookie, \c 0 or
- * \c -1 otherwise.
- */
-int
-dtls_verify_peer(dtls_context_t *ctx,
- dtls_peer_t *peer,
- session_t *session,
- uint8 *record,
- uint8 *data, size_t data_length) {
-
- int len = DTLS_COOKIE_LENGTH;
- uint8 *cookie, *p;
-#undef mycookie
-#define mycookie (ctx->sendbuf + HV_HDR_LENGTH)
-
- /* check if we can access at least all fields from the handshake header */
- if (record[0] == DTLS_CT_HANDSHAKE
- && data_length >= DTLS_HS_LENGTH
- && data[0] == DTLS_HT_CLIENT_HELLO) {
-
- /* Store cookie where we can reuse it for the HelloVerify request. */
- if (dtls_create_cookie(ctx, session, data, data_length,
- mycookie, &len) < 0)
- return -1;
-/* #ifndef NDEBUG */
-/* debug("create cookie: "); */
-/* dump(mycookie, len); */
-/* printf("\n"); */
-/* #endif */
- assert(len == DTLS_COOKIE_LENGTH);
-
- /* Perform cookie check. */
- len = dtls_get_cookie(data, data_length, &cookie);
-
-/* #ifndef NDEBUG */
-/* debug("compare with cookie: "); */
-/* dump(cookie, len); */
-/* printf("\n"); */
-/* #endif */
-
- /* check if cookies match */
- if (len == DTLS_COOKIE_LENGTH && memcmp(cookie, mycookie, len) == 0) {
- debug("found matching cookie\n");
- return 1;
- }
- if (len > 0) {
- debug("invalid cookie");
-#ifndef NDEBUG
- dump(cookie, len);
- printf("\n");
-#endif
- }
- /* ClientHello did not contain any valid cookie, hence we send a
- * HelloVerify request. */
-
- p = dtls_set_handshake_header(DTLS_HT_HELLO_VERIFY_REQUEST,
- peer, DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH,
- 0, DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH,
- ctx->sendbuf + DTLS_RH_LENGTH);
-
- dtls_int_to_uint16(p, DTLS_VERSION);
- p += sizeof(uint16);
-
- dtls_int_to_uint8(p, DTLS_COOKIE_LENGTH);
- p += sizeof(uint8);
-
- assert(p == mycookie);
-
- p += DTLS_COOKIE_LENGTH;
-
- if (!peer) {
- /* It's an initial ClientHello, so we set the record header
- * manually and send the HelloVerify request using the
- * registered write callback. */
-
- dtls_set_record_header(DTLS_CT_HANDSHAKE, NULL, ctx->sendbuf);
- /* set packet length */
- dtls_int_to_uint16(ctx->sendbuf + 11,
- p - (ctx->sendbuf + DTLS_RH_LENGTH));
-
- (void)CALL(ctx, write, session, ctx->sendbuf, p - ctx->sendbuf);
- } else {
- if (peer->epoch) {
- debug("renegotiation, therefore we accept it anyway:");
- return 1;
- }
-
- if (dtls_send(ctx, peer, DTLS_CT_HANDSHAKE,
- ctx->sendbuf + DTLS_RH_LENGTH,
- p - (ctx->sendbuf + DTLS_RH_LENGTH)) < 0) {
- warn("cannot send HelloVerify request\n");
- return -1;
- }
- }
-
- return 0; /* HelloVerify is sent, now we cannot do anything but wait */
- }
-
- return -1; /* not a ClientHello, signal error */
-#undef mycookie
-}
-
-/** only one compression method is currently defined */
-uint8 compression_methods[] = {
- TLS_COMP_NULL
-};
-
-/**
- * Returns @c 1 if @p code is a cipher suite other than @c
- * TLS_NULL_WITH_NULL_NULL that we recognize.
- *
- * @param code The cipher suite identifier to check
- * @return @c 1 iff @p code is recognized,
- */
-static inline int
-known_cipher(dtls_cipher_t code) {
- return code == TLS_PSK_WITH_AES_128_CCM_8;
-}
-
-int
-calculate_key_block(dtls_context_t *ctx,
- dtls_security_parameters_t *config,
- const dtls_key_t *key,
- unsigned char client_random[32],
- unsigned char server_random[32]) {
- unsigned char *pre_master_secret;
- size_t pre_master_len = 0;
- pre_master_secret = config->key_block;
-
- assert(key);
- switch (key->type) {
- case DTLS_KEY_PSK: {
- /* Temporarily use the key_block storage space for the pre master secret. */
- pre_master_len = dtls_pre_master_secret(key->key.psk.key, key->key.psk.key_length,
- pre_master_secret);
-
- break;
- }
- default:
- debug("calculate_key_block: unknown key type\n");
- return 0;
- }
-
-/* #ifndef NDEBUG */
-/* { */
-/* int i; */
-
-/* printf("client_random:"); */
-/* for (i = 0; i < 32; ++i) */
-/* printf(" %02x", client_random[i]); */
-/* printf("\n"); */
-
-/* printf("server_random:"); */
-/* for (i = 0; i < 32; ++i) */
-/* printf(" %02x", server_random[i]); */
-/* printf("\n"); */
-
-/* printf("psk: (%lu bytes):", key->key.psk.key_length); */
-/* hexdump(key->key.psk.key, key->key.psk.key_length); */
-/* printf("\n"); */
-
-/* printf("pre_master_secret: (%lu bytes):", pre_master_len); */
-/* for (i = 0; i < pre_master_len; ++i) */
-/* printf(" %02x", pre_master_secret[i]); */
-/* printf("\n"); */
-/* } */
-/* #endif /\* NDEBUG *\/ */
-
- dtls_prf(pre_master_secret, pre_master_len,
- PRF_LABEL(master), PRF_LABEL_SIZE(master),
- client_random, 32,
- server_random, 32,
- config->master_secret,
- DTLS_MASTER_SECRET_LENGTH);
-
-/* #ifndef NDEBUG */
-/* { */
-/* int i; */
-/* printf("master_secret (%d bytes):", DTLS_MASTER_SECRET_LENGTH); */
-/* for (i = 0; i < DTLS_MASTER_SECRET_LENGTH; ++i) */
-/* printf(" %02x", config->master_secret[i]); */
-/* printf("\n"); */
-/* } */
-/* #endif /\* NDEBUG *\/ */
-
- /* create key_block from master_secret
- * key_block = PRF(master_secret,
- "key expansion" + server_random + client_random) */
-
- dtls_prf(config->master_secret,
- DTLS_MASTER_SECRET_LENGTH,
- PRF_LABEL(key), PRF_LABEL_SIZE(key),
- server_random, 32,
- client_random, 32,
- config->key_block,
- dtls_kb_size(config));
-
-/* #ifndef NDEBUG */
-/* { */
-/* printf("key_block (%d bytes):\n", dtls_kb_size(config)); */
-/* printf(" client_MAC_secret:\t"); */
-/* dump(dtls_kb_client_mac_secret(config), */
-/* dtls_kb_mac_secret_size(config)); */
-/* printf("\n"); */
-
-/* printf(" server_MAC_secret:\t"); */
-/* dump(dtls_kb_server_mac_secret(config), */
-/* dtls_kb_mac_secret_size(config)); */
-/* printf("\n"); */
-
-/* printf(" client_write_key:\t"); */
-/* dump(dtls_kb_client_write_key(config), */
-/* dtls_kb_key_size(config)); */
-/* printf("\n"); */
-
-/* printf(" server_write_key:\t"); */
-/* dump(dtls_kb_server_write_key(config), */
-/* dtls_kb_key_size(config)); */
-/* printf("\n"); */
-
-/* printf(" client_IV:\t\t"); */
-/* dump(dtls_kb_client_iv(config), */
-/* dtls_kb_iv_size(config)); */
-/* printf("\n"); */
-
-/* printf(" server_IV:\t\t"); */
-/* dump(dtls_kb_server_iv(config), */
-/* dtls_kb_iv_size(config)); */
-/* printf("\n"); */
-
-
-/* } */
-/* #endif */
- return 1;
-}
-
-/**
- * Updates the security parameters of given \p peer. As this must be
- * done before the new configuration is activated, it changes the
- * OTHER_CONFIG only. When the ClientHello handshake message in \p
- * data does not contain a cipher suite or compression method, it is
- * copied from the CURRENT_CONFIG.
- *
- * \param ctx The current DTLS context.
- * \param peer The remote peer whose security parameters are about to change.
- * \param data The handshake message with a ClientHello.
- * \param data_length The actual size of \p data.
- * \return \c 0 if an error occurred, \c 1 otherwise.
- */
-int
-dtls_update_parameters(dtls_context_t *ctx,
- dtls_peer_t *peer,
- uint8 *data, size_t data_length) {
- int i, j;
- int ok;
- dtls_security_parameters_t *config = OTHER_CONFIG(peer);
-
- assert(config);
- assert(data_length > DTLS_HS_LENGTH + DTLS_CH_LENGTH);
-
- /* debug("dtls_update_parameters: msglen is %d\n", data_length); */
-
- /* skip the handshake header and client version information */
- data += DTLS_HS_LENGTH + sizeof(uint16);
- data_length -= DTLS_HS_LENGTH + sizeof(uint16);
-
- /* store client random in config
- * FIXME: if we send the ServerHello here, we do not need to store
- * the client's random bytes */
- memcpy(config->client_random, data, sizeof(config->client_random));
- data += sizeof(config->client_random);
- data_length -= sizeof(config->client_random);
-
- /* Caution: SKIP_VAR_FIELD may jump to error: */
- SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */
- SKIP_VAR_FIELD(data, data_length, uint8); /* skip cookie */
-
- i = dtls_uint16_to_int(data);
- if (data_length < i + sizeof(uint16)) {
- /* Looks like we do not have a cipher nor compression. This is ok
- * for renegotiation, but not for the initial handshake. */
-
- if (CURRENT_CONFIG(peer)->cipher == TLS_NULL_WITH_NULL_NULL)
- goto error;
-
- config->cipher = CURRENT_CONFIG(peer)->cipher;
- config->compression = CURRENT_CONFIG(peer)->compression;
-
- return 1;
- }
-
- data += sizeof(uint16);
- data_length -= sizeof(uint16) + i;
-
- ok = 0;
- while (i && !ok) {
- config->cipher = dtls_uint16_to_int(data);
- ok = known_cipher(config->cipher);
- i -= sizeof(uint16);
- data += sizeof(uint16);
- }
-
- /* skip remaining ciphers */
- data += i;
-
- if (!ok) {
- /* reset config cipher to a well-defined value */
- config->cipher = TLS_NULL_WITH_NULL_NULL;
- return 0;
- }
-
- if (data_length < sizeof(uint8)) {
- /* no compression specified, take the current compression method */
- config->compression = CURRENT_CONFIG(peer)->compression;
- return 1;
- }
-
- i = dtls_uint8_to_int(data);
- if (data_length < i + sizeof(uint8))
- goto error;
-
- data += sizeof(uint8);
- data_length -= sizeof(uint8) + i;
-
- ok = 0;
- while (i && !ok) {
- for (j = 0; j < sizeof(compression_methods) / sizeof(uint8); ++j)
- if (dtls_uint8_to_int(data) == compression_methods[j]) {
- config->compression = compression_methods[j];
- ok = 1;
- }
- i -= sizeof(uint8);
- data += sizeof(uint8);
- }
-
- return ok;
- error:
- warn("ClientHello too short (%d bytes)\n", data_length);
- return 0;
-}
-
-static inline int
-check_client_keyexchange(dtls_context_t *ctx,
- dtls_peer_t *peer,
- uint8 *data, size_t length) {
- return length >= DTLS_CKX_LENGTH && data[0] == DTLS_HT_CLIENT_KEY_EXCHANGE;
-}
-
-static int
-check_ccs(dtls_context_t *ctx,
- dtls_peer_t *peer,
- uint8 *record, uint8 *data, size_t data_length) {
-
- if (DTLS_RECORD_HEADER(record)->content_type != DTLS_CT_CHANGE_CIPHER_SPEC
- || data_length < 1 || data[0] != 1)
- return 0;
-
- /* set crypto context for TLS_PSK_WITH_AES_128_CCM_8 */
- /* client */
- dtls_cipher_free(OTHER_CONFIG(peer)->read_cipher);
-
- assert(OTHER_CONFIG(peer)->cipher != TLS_NULL_WITH_NULL_NULL);
- OTHER_CONFIG(peer)->read_cipher =
- dtls_cipher_new(OTHER_CONFIG(peer)->cipher,
- dtls_kb_client_write_key(OTHER_CONFIG(peer)),
- dtls_kb_key_size(OTHER_CONFIG(peer)));
-
- if (!OTHER_CONFIG(peer)->read_cipher) {
- warn("cannot create read cipher\n");
- return 0;
- }
-
- dtls_cipher_set_iv(OTHER_CONFIG(peer)->read_cipher,
- dtls_kb_client_iv(OTHER_CONFIG(peer)),
- dtls_kb_iv_size(OTHER_CONFIG(peer)));
-
- /* server */
- dtls_cipher_free(OTHER_CONFIG(peer)->write_cipher);
-
- OTHER_CONFIG(peer)->write_cipher =
- dtls_cipher_new(OTHER_CONFIG(peer)->cipher,
- dtls_kb_server_write_key(OTHER_CONFIG(peer)),
- dtls_kb_key_size(OTHER_CONFIG(peer)));
-
- if (!OTHER_CONFIG(peer)->write_cipher) {
- warn("cannot create write cipher\n");
- return 0;
- }
-
- dtls_cipher_set_iv(OTHER_CONFIG(peer)->write_cipher,
- dtls_kb_server_iv(OTHER_CONFIG(peer)),
- dtls_kb_iv_size(OTHER_CONFIG(peer)));
-
- return 1;
-}
-
-#ifndef NDEBUG
-extern size_t dsrv_print_addr(const session_t *, unsigned char *, size_t);
-#endif
-
-static inline void
-update_hs_hash(dtls_peer_t *peer, uint8 *data, size_t length) {
-/* #ifndef NDEBUG */
-/* printf("add MAC data: "); */
-/* dump(data, length); */
-/* printf("\n"); */
-/* #endif */
- dtls_hash_update(&peer->hs_state.hs_hash, data, length);
-}
-
-static inline size_t
-finalize_hs_hash(dtls_peer_t *peer, uint8 *buf) {
- return dtls_hash_finalize(buf, &peer->hs_state.hs_hash);
-}
-
-static inline void
-clear_hs_hash(dtls_peer_t *peer) {
- assert(peer);
- dtls_hash_init(&peer->hs_state.hs_hash);
-}
-
-/**
- *Checks if \p record + \p data contain a Finished message with valid
- * verify_data.
- *
- * \param ctx The current DTLS context.
- * \param peer The remote peer of the security association.
- * \param record The message record header.
- * \param rlen The actual length of \p record.
- * \param data The cleartext payload of the message.
- * \param data_length Actual length of \p data.
- * \return \c 1 if the Finished message is valid, \c 0 otherwise.
- */
-static int
-check_finished(dtls_context_t *ctx, dtls_peer_t *peer,
- uint8 *record, uint8 *data, size_t data_length) {
- size_t digest_length, label_size;
- const unsigned char *label;
- unsigned char buf[DTLS_HMAC_MAX];
-
- /* Use a union here to ensure that sufficient stack space is
- * reserved. As statebuf and verify_data are not used at the same
- * time, we can re-use the storage safely.
- */
- union {
- unsigned char statebuf[DTLS_HASH_CTX_SIZE];
- unsigned char verify_data[DTLS_FIN_LENGTH];
- } b;
-
- debug("check Finish message\n");
- if (record[0] != DTLS_CT_HANDSHAKE || !IS_FINISHED(data, data_length)) {
- debug("failed\n");
- return 0;
- }
-
- /* temporarily store hash status for roll-back after finalize */
- memcpy(b.statebuf, &peer->hs_state.hs_hash, DTLS_HASH_CTX_SIZE);
-
- digest_length = finalize_hs_hash(peer, buf);
- /* clear_hash(); */
-
- /* restore hash status */
- memcpy(&peer->hs_state.hs_hash, b.statebuf, DTLS_HASH_CTX_SIZE);
-
- if (CURRENT_CONFIG(peer)->role == DTLS_SERVER) {
- label = PRF_LABEL(server);
- label_size = PRF_LABEL_SIZE(server);
- } else { /* client */
- label = PRF_LABEL(client);
- label_size = PRF_LABEL_SIZE(client);
- }
-
- dtls_prf(CURRENT_CONFIG(peer)->master_secret,
- DTLS_MASTER_SECRET_LENGTH,
- label, label_size,
- PRF_LABEL(finished), PRF_LABEL_SIZE(finished),
- buf, digest_length,
- b.verify_data, sizeof(b.verify_data));
-
-/* #ifndef NDEBUG */
-/* printf("d:\t"); dump(data + DTLS_HS_LENGTH, sizeof(b.verify_data)); printf("\n"); */
-/* printf("v:\t"); dump(b.verify_data, sizeof(b.verify_data)); printf("\n"); */
-/* #endif */
- return
- memcmp(data + DTLS_HS_LENGTH, b.verify_data, sizeof(b.verify_data)) == 0;
-}
-
-/**
- * Prepares the payload given in \p data for sending with
- * dtls_send(). The \p data is encrypted and compressed according to
- * the current security parameters of \p peer. The result of this
- * operation is put into \p sendbuf with a prepended record header of
- * type \p type ready for sending. As some cipher suites add a MAC
- * before encryption, \p data must be large enough to hold this data
- * as well (usually \c dtls_kb_digest_size(CURRENT_CONFIG(peer)).
- *
- * \param peer The remote peer the packet will be sent to.
- * \param type The content type of this record.
- * \param data The payload to send.
- * \param data_length The size of \p data.
- * \param sendbuf The output buffer where the encrypted record
- * will be placed.
- * \param rlen This parameter must be initialized with the
- * maximum size of \p sendbuf and will be updated
- * to hold the actual size of the stored packet
- * on success. On error, the value of \p rlen is
- * undefined.
- * \return Less than zero on error, or greater than zero success.
- */
-int
-dtls_prepare_record(dtls_peer_t *peer,
- unsigned char type,
- uint8 *data, size_t data_length,
- uint8 *sendbuf, size_t *rlen) {
- uint8 *p;
- int res;
-
- /* check the minimum that we need for packets that are not encrypted */
- if (*rlen < DTLS_RH_LENGTH + data_length) {
- debug("dtls_prepare_record: send buffer too small\n");
- return -1;
- }
-
- p = dtls_set_record_header(type, peer, sendbuf);
-
- if (CURRENT_CONFIG(peer)->cipher == TLS_NULL_WITH_NULL_NULL) {
- /* no cipher suite */
- memcpy(p, data, data_length);
- res = data_length;
- } else { /* TLS_PSK_WITH_AES_128_CCM_8 */
- dtls_cipher_context_t *cipher_context;
-
- /**
- * 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
-#define A_DATA N
- unsigned char N[max(DTLS_CCM_BLOCKSIZE, A_DATA_LEN)];
-
- if (*rlen < sizeof(dtls_record_header_t) + data_length + 8) {
- warn("dtls_prepare_record(): send buffer too small\n");
- return -1;
- }
-
- debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n");
-
- /* set nonce
- from http://tools.ietf.org/html/draft-mcgrew-tls-aes-ccm-03:
- struct {
- case client:
- uint32 client_write_IV; // low order 32-bits
- case server:
- uint32 server_write_IV; // low order 32-bits
- uint64 seq_num;
- } CCMNonce.
-
- In DTLS, the 64-bit seq_num is the 16-bit epoch concatenated with the
- 48-bit seq_num.
- */
-
- memcpy(p, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8);
- memcpy(p + 8, data, data_length);
-
- memset(N, 0, DTLS_CCM_BLOCKSIZE);
- memcpy(N, dtls_kb_local_iv(CURRENT_CONFIG(peer)),
- dtls_kb_iv_size(CURRENT_CONFIG(peer)));
- memcpy(N + dtls_kb_iv_size(CURRENT_CONFIG(peer)), p, 8); /* epoch + seq_num */
-
- cipher_context = CURRENT_CONFIG(peer)->write_cipher;
-
- if (!cipher_context) {
- warn("no write_cipher available!\n");
- return -1;
- }
-/* #ifndef NDEBUG */
-/* printf("nonce:\t"); */
-/* dump(N, DTLS_CCM_BLOCKSIZE); */
-/* printf("\nkey:\t"); */
-/* dump(dtls_kb_local_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-/* #endif */
- dtls_cipher_set_iv(cipher_context, N, DTLS_CCM_BLOCKSIZE);
-
- /* 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, data_length); /* length */
-
- res = dtls_encrypt(cipher_context, p + 8, data_length, p + 8,
- A_DATA, A_DATA_LEN);
-
- if (res < 0)
- return -1;
-
-/* #ifndef NDEBUG */
-/* dump(p, res + 8); */
-/* printf("\n"); */
-/* #endif */
- res += 8; /* increment res by size of nonce_explicit */
- }
-
- /* fix length of fragment in sendbuf */
- dtls_int_to_uint16(sendbuf + 11, res);
-
- *rlen = DTLS_RH_LENGTH + res;
- return 1;
-}
-
-/**
- * Returns true if the message @p Data is a handshake message that
- * must be included in the calculation of verify_data in the Finished
- * message.
- *
- * @param Type The message type. Only handshake messages but the initial
- * Client Hello and Hello Verify Request are included in the hash,
- * @param Data The PDU to examine.
- * @param Length The length of @p Data.
- *
- * @return @c 1 if @p Data must be included in hash, @c 0 otherwise.
- *
- * @hideinitializer
- */
-#define MUST_HASH(Type, Data, Length) \
- ((Type) == DTLS_CT_HANDSHAKE && \
- ((Data) != NULL) && ((Length) > 0) && \
- ((Data)[0] != DTLS_HT_HELLO_VERIFY_REQUEST) && \
- ((Data)[0] != DTLS_HT_CLIENT_HELLO || \
- ((Length) >= HS_HDR_LENGTH && \
- (dtls_uint16_to_int(DTLS_RECORD_HEADER(Data)->epoch > 0) || \
- (dtls_uint16_to_int(HANDSHAKE(Data)->message_seq) > 0)))))
-
-/**
- * Sends the data passed in @p buf as a DTLS record of type @p type to
- * the given peer. The data will be encrypted and compressed according
- * to the security parameters for @p peer.
- *
- * @param ctx The DTLS context in effect.
- * @param peer The remote party where the packet is sent.
- * @param type The content type of this record.
- * @param buf The data to send.
- * @param buflen The number of bytes to send from @p buf.
- * @return Less than zero in case of an error or the number of
- * bytes that have been sent otherwise.
- */
-int
-dtls_send(dtls_context_t *ctx, dtls_peer_t *peer,
- unsigned char type,
- uint8 *buf, size_t buflen) {
-
- /* We cannot use ctx->sendbuf here as it is reserved for collecting
- * the input for this function, i.e. buf == ctx->sendbuf.
- *
- * TODO: check if we can use the receive buf here. This would mean
- * that we might not be able to handle multiple records stuffed in
- * one UDP datagram */
- unsigned char sendbuf[DTLS_MAX_BUF];
- size_t len = sizeof(sendbuf);
- int res;
-
- res = dtls_prepare_record(peer, type, buf, buflen, sendbuf, &len);
-
- if (res < 0)
- return res;
-
- /* if (peer && MUST_HASH(peer, type, buf, buflen)) */
- /* update_hs_hash(peer, buf, buflen); */
-
-/* #ifndef NDEBUG */
-/* debug("send %d bytes\n", buflen); */
-/* hexdump(sendbuf, sizeof(dtls_record_header_t)); */
-/* printf("\n"); */
-/* hexdump(buf, buflen); */
-/* printf("\n"); */
-/* #endif */
-
- if (type == DTLS_CT_HANDSHAKE && buf[0] != DTLS_HT_HELLO_VERIFY_REQUEST) {
- /* copy handshake messages other than HelloVerify into retransmit buffer */
- netq_t *n = netq_node_new();
- if (n) {
- dtls_tick_t now;
- dtls_ticks(&now);
- n->t = now + 2 * CLOCK_SECOND;
- n->retransmit_cnt = 0;
- n->timeout = 2 * CLOCK_SECOND;
- n->peer = peer;
- n->length = buflen;
- memcpy(n->data, buf, buflen);
-
- if (!netq_insert_node((netq_t **)ctx->sendqueue, n)) {
- warn("cannot add packet to retransmit buffer\n");
- netq_node_free(n);
-#ifdef WITH_CONTIKI
- } else {
- /* must set timer within the context of the retransmit process */
- PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process);
- etimer_set(&ctx->retransmit_timer, n->timeout);
- PROCESS_CONTEXT_END(&dtls_retransmit_process);
-#else /* WITH_CONTIKI */
- debug("copied to sendqueue\n");
-#endif /* WITH_CONTIKI */
- }
- } else
- warn("retransmit buffer full\n");
- }
-
- /* FIXME: copy to peer's sendqueue (after fragmentation if
- * necessary) and initialize retransmit timer */
- res = CALL(ctx, write, &peer->session, sendbuf, len);
-
- /* Guess number of bytes application data actually sent:
- * dtls_prepare_record() tells us in len the number of bytes to
- * send, res will contain the bytes actually sent. */
- return res <= 0 ? res : buflen - (len - res);
-}
-
-static inline int
-dtls_alert(dtls_context_t *ctx, dtls_peer_t *peer, dtls_alert_level_t level,
- dtls_alert_t description) {
- uint8_t msg[] = { level, description };
-
- dtls_send(ctx, peer, DTLS_CT_ALERT, msg, sizeof(msg));
- return 0;
-}
-
-int
-dtls_close(dtls_context_t *ctx, const session_t *remote) {
- int res = -1;
- dtls_peer_t *peer;
-
- peer = dtls_get_peer(ctx, remote);
-
- if (peer) {
- res = dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_CLOSE);
- /* indicate tear down */
- peer->state = DTLS_STATE_CLOSING;
- }
- return res;
-}
-
-int
-dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) {
-
- static uint8 buf[DTLS_MAX_BUF];
- uint8 *p = buf, *q = ctx->sendbuf;
- size_t qlen = sizeof(ctx->sendbuf);
- int res;
- const dtls_key_t *key;
- dtls_tick_t now;
-
- /* Ensure that the largest message to create fits in our source
- * buffer. (The size of the destination buffer is checked by the
- * encoding function, so we do not need to guess.) */
- assert(sizeof(buf) >=
- DTLS_RH_LENGTH + DTLS_HS_LENGTH + DTLS_SH_LENGTH + 20);
-
- if (CALL(ctx, get_key, &peer->session, NULL, 0, &key) < 0) {
- debug("dtls_send_server_hello(): no key for session available\n");
- return -1;
- }
-
- /* Handshake header */
- p = dtls_set_handshake_header(DTLS_HT_SERVER_HELLO,
- peer,
- DTLS_SH_LENGTH,
- 0, DTLS_SH_LENGTH,
- buf);
-
- /* ServerHello */
- dtls_int_to_uint16(p, DTLS_VERSION);
- p += sizeof(uint16);
-
- /* Set server random: First 4 bytes are the server's Unix timestamp,
- * followed by 28 bytes of generate random data. */
- dtls_ticks(&now);
- dtls_int_to_uint32(p, now / CLOCK_SECOND);
- prng(p + 4, 28);
-
- if (!calculate_key_block(ctx, OTHER_CONFIG(peer), key,
- OTHER_CONFIG(peer)->client_random, p))
- return -1;
-
- p += 32;
-
- *p++ = 0; /* no session id */
-
- if (OTHER_CONFIG(peer)->cipher != TLS_NULL_WITH_NULL_NULL) {
- /* selected cipher suite */
- dtls_int_to_uint16(p, OTHER_CONFIG(peer)->cipher);
- p += sizeof(uint16);
-
- /* selected compression method */
- if (OTHER_CONFIG(peer)->compression >= 0)
- *p++ = compression_methods[OTHER_CONFIG(peer)->compression];
-
- /* FIXME: if key->psk.id != NULL we need the server key exchange */
-
- /* update the finish hash
- (FIXME: better put this in generic record_send function) */
- update_hs_hash(peer, buf, p - buf);
- }
-
- res = dtls_prepare_record(peer, DTLS_CT_HANDSHAKE,
- buf, p - buf,
- q, &qlen);
- if (res < 0) {
- debug("dtls_server_hello: cannot prepare ServerHello record\n");
- return res;
- }
-
- q += qlen;
- qlen = sizeof(ctx->sendbuf) - qlen;
-
- /* ServerHelloDone
- *
- * Start message construction at beginning of buffer. */
- p = dtls_set_handshake_header(DTLS_HT_SERVER_HELLO_DONE,
- peer,
- 0, /* ServerHelloDone has no extra fields */
- 0, 0, /* ServerHelloDone has no extra fields */
- buf);
-
- /* update the finish hash
- (FIXME: better put this in generic record_send function) */
- update_hs_hash(peer, buf, p - buf);
-
- res = dtls_prepare_record(peer, DTLS_CT_HANDSHAKE,
- buf, p - buf,
- q, &qlen);
- if (res < 0) {
- debug("dtls_server_hello: cannot prepare ServerHelloDone record\n");
- return res;
- }
-
- return CALL(ctx, write, &peer->session,
- ctx->sendbuf, (q + qlen) - ctx->sendbuf);
-}
-
-static inline int
-dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) {
- ctx->sendbuf[0] = 1;
- return dtls_send(ctx, peer, DTLS_CT_CHANGE_CIPHER_SPEC, ctx->sendbuf, 1);
-}
-
-
-int
-dtls_send_kx(dtls_context_t *ctx, dtls_peer_t *peer, int is_client) {
- const dtls_key_t *key;
- uint8 *p = ctx->sendbuf;
- size_t size;
- int ht = is_client
- ? DTLS_HT_CLIENT_KEY_EXCHANGE
- : DTLS_HT_SERVER_KEY_EXCHANGE;
- unsigned char *id = NULL;
- size_t id_len = 0;
-
- if (CALL(ctx, get_key, &peer->session, NULL, 0, &key) < 0) {
- dsrv_log(LOG_CRIT, "no key to send in kx\n");
- return -2;
- }
-
- assert(key);
-
- switch (key->type) {
- case DTLS_KEY_PSK: {
- id_len = key->key.psk.id_length;
- id = key->key.psk.id;
- break;
- }
- default:
- dsrv_log(LOG_CRIT, "key type not supported\n");
- return -3;
- }
-
- size = id_len + sizeof(uint16);
- p = dtls_set_handshake_header(ht, peer, size, 0, size, p);
-
- dtls_int_to_uint16(p, id_len);
- memcpy(p + sizeof(uint16), id, id_len);
-
- p += size;
-
- update_hs_hash(peer, ctx->sendbuf, p - ctx->sendbuf);
- return dtls_send(ctx, peer, DTLS_CT_HANDSHAKE,
- ctx->sendbuf, p - ctx->sendbuf);
-}
-
-#define msg_overhead(Peer,Length) (DTLS_RH_LENGTH + \
- ((Length + dtls_kb_iv_size(CURRENT_CONFIG(Peer)) + \
- dtls_kb_digest_size(CURRENT_CONFIG(Peer))) / \
- DTLS_BLK_LENGTH + 1) * DTLS_BLK_LENGTH)
-
-int
-dtls_send_server_finished(dtls_context_t *ctx, dtls_peer_t *peer) {
-
- int length;
- uint8 buf[DTLS_HMAC_MAX];
- uint8 *p = ctx->sendbuf;
-
- /* FIXME: adjust message overhead calculation */
- assert(msg_overhead(peer, DTLS_HS_LENGTH + DTLS_FIN_LENGTH)
- < sizeof(ctx->sendbuf));
-
- p = dtls_set_handshake_header(DTLS_HT_FINISHED,
- peer, DTLS_FIN_LENGTH, 0, DTLS_FIN_LENGTH, p);
-
- length = finalize_hs_hash(peer, buf);
-
- dtls_prf(CURRENT_CONFIG(peer)->master_secret,
- DTLS_MASTER_SECRET_LENGTH,
- PRF_LABEL(server), PRF_LABEL_SIZE(server),
- PRF_LABEL(finished), PRF_LABEL_SIZE(finished),
- buf, length,
- p, DTLS_FIN_LENGTH);
-
-/* #ifndef NDEBUG */
-/* printf("server finished MAC:\t"); */
-/* dump(p, DTLS_FIN_LENGTH); */
-/* printf("\n"); */
-/* #endif */
-
- p += DTLS_FIN_LENGTH;
-
- return dtls_send(ctx, peer, DTLS_CT_HANDSHAKE,
- ctx->sendbuf, p - ctx->sendbuf);
-}
-
-static int
-check_server_hello(dtls_context_t *ctx,
- dtls_peer_t *peer,
- uint8 *data, size_t data_length) {
- dtls_hello_verify_t *hv;
- uint8 *p = ctx->sendbuf;
- size_t size;
- int res;
- const dtls_key_t *key;
-
- /* This function is called when we expect a ServerHello (i.e. we
- * have sent a ClientHello). We might instead receive a HelloVerify
- * request containing a cookie. If so, we must repeat the
- * ClientHello with the given Cookie.
- */
-
- if (IS_SERVERHELLO(data, data_length)) {
- debug("handle ServerHello\n");
-
- update_hs_hash(peer, data, data_length);
-
- /* FIXME: check data_length before accessing fields */
-
- /* Get the server's random data and store selected cipher suite
- * and compression method (like dtls_update_parameters().
- * Then calculate master secret and wait for ServerHelloDone. When received,
- * send ClientKeyExchange (?) and ChangeCipherSpec + ClientFinished. */
-
- /* check server version */
- data += DTLS_HS_LENGTH;
- data_length -= DTLS_HS_LENGTH;
-
- if (dtls_uint16_to_int(data) != DTLS_VERSION) {
- dsrv_log(LOG_ALERT, "unknown DTLS version\n");
- goto error;
- }
-
- data += sizeof(uint16); /* skip version field */
- data_length -= sizeof(uint16);
-
- /* FIXME: check PSK hint */
- if (CALL(ctx, get_key, &peer->session, NULL, 0, &key) < 0
- || !calculate_key_block(ctx, OTHER_CONFIG(peer), key,
- OTHER_CONFIG(peer)->client_random, data)) {
- goto error;
- }
- /* store server random data */
-
- /* memcpy(OTHER_CONFIG(peer)->server_random, data, */
- /* sizeof(OTHER_CONFIG(peer)->server_random)); */
- data += sizeof(OTHER_CONFIG(peer)->client_random);
- data_length -= sizeof(OTHER_CONFIG(peer)->client_random);
-
- SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */
-
- /* Check cipher suite. As we offer all we have, it is sufficient
- * to check if the cipher suite selected by the server is in our
- * list of known cipher suites. Subsets are not supported. */
- OTHER_CONFIG(peer)->cipher = dtls_uint16_to_int(data);
- if (!known_cipher(OTHER_CONFIG(peer)->cipher)) {
- dsrv_log(LOG_ALERT, "unsupported cipher 0x%02x 0x%02x\n",
- data[0], data[1]);
- goto error;
- }
- data += sizeof(uint16);
- data_length -= sizeof(uint16);
-
- /* Check if NULL compression was selected. We do not know any other. */
- if (dtls_uint8_to_int(data) != TLS_COMP_NULL) {
- dsrv_log(LOG_ALERT, "unsupported compression method 0x%02x\n", data[0]);
- goto error;
- }
-
- return 1;
- }
-
- if (!IS_HELLOVERIFY(data, data_length)) {
- debug("no HelloVerify\n");
- return 0;
- }
-
- hv = (dtls_hello_verify_t *)(data + DTLS_HS_LENGTH);
-
- /* FIXME: dtls_send_client_hello(ctx,peer,cookie) */
- size = DTLS_CH_LENGTH + 8 + dtls_uint8_to_int(&hv->cookie_length);
-
- p = dtls_set_handshake_header(DTLS_HT_CLIENT_HELLO, peer,
- size, 0, size, p);
-
- dtls_int_to_uint16(p, DTLS_VERSION);
- p += sizeof(uint16);
-
- /* we must use the same Client Random as for the previous request */
- memcpy(p, OTHER_CONFIG(peer)->client_random,
- sizeof(OTHER_CONFIG(peer)->client_random));
- p += sizeof(OTHER_CONFIG(peer)->client_random);
-
- /* session id (length 0) */
- dtls_int_to_uint8(p, 0);
- p += sizeof(uint8);
-
- dtls_int_to_uint8(p, dtls_uint8_to_int(&hv->cookie_length));
- p += sizeof(uint8);
- memcpy(p, hv->cookie, dtls_uint8_to_int(&hv->cookie_length));
- p += dtls_uint8_to_int(&hv->cookie_length);
-
- /* add known cipher(s) */
- dtls_int_to_uint16(p, 2);
- p += sizeof(uint16);
-
- dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8);
- p += sizeof(uint16);
-
- /* compression method */
- dtls_int_to_uint8(p, 1);
- p += sizeof(uint8);
-
- dtls_int_to_uint8(p, 0);
- p += sizeof(uint8);
-
- update_hs_hash(peer, ctx->sendbuf, p - ctx->sendbuf);
-
- res = dtls_send(ctx, peer, DTLS_CT_HANDSHAKE, ctx->sendbuf,
- p - ctx->sendbuf);
- if (res < 0)
- warn("cannot send ClientHello\n");
-
- error:
- return 0;
-}
-
-static int
-check_server_hellodone(dtls_context_t *ctx,
- dtls_peer_t *peer,
- uint8 *data, size_t data_length) {
-
- /* calculate master key, send CCS */
- if (!IS_SERVERHELLODONE(data, data_length))
- return 0;
-
- update_hs_hash(peer, data, data_length);
-
- /* set crypto context for TLS_PSK_WITH_AES_128_CCM_8 */
- /* client */
- dtls_cipher_free(OTHER_CONFIG(peer)->read_cipher);
-
- assert(OTHER_CONFIG(peer)->cipher != TLS_NULL_WITH_NULL_NULL);
- OTHER_CONFIG(peer)->read_cipher =
- dtls_cipher_new(OTHER_CONFIG(peer)->cipher,
- dtls_kb_server_write_key(OTHER_CONFIG(peer)),
- dtls_kb_key_size(OTHER_CONFIG(peer)));
-
- if (!OTHER_CONFIG(peer)->read_cipher) {
- warn("cannot create read cipher\n");
- return 0;
- }
-
- dtls_cipher_set_iv(OTHER_CONFIG(peer)->read_cipher,
- dtls_kb_server_iv(OTHER_CONFIG(peer)),
- dtls_kb_iv_size(OTHER_CONFIG(peer)));
-
- /* server */
- dtls_cipher_free(OTHER_CONFIG(peer)->write_cipher);
-
- OTHER_CONFIG(peer)->write_cipher =
- dtls_cipher_new(OTHER_CONFIG(peer)->cipher,
- dtls_kb_client_write_key(OTHER_CONFIG(peer)),
- dtls_kb_key_size(OTHER_CONFIG(peer)));
-
- if (!OTHER_CONFIG(peer)->write_cipher) {
- dtls_cipher_free(OTHER_CONFIG(peer)->read_cipher);
- warn("cannot create write cipher\n");
- return 0;
- }
-
- dtls_cipher_set_iv(OTHER_CONFIG(peer)->write_cipher,
- dtls_kb_client_iv(OTHER_CONFIG(peer)),
- dtls_kb_iv_size(OTHER_CONFIG(peer)));
-
- /* send ClientKeyExchange */
- if (dtls_send_kx(ctx, peer, 1) < 0) {
- debug("cannot send KeyExchange message\n");
- return 0;
- }
-
- /* and switch cipher suite */
- if (dtls_send_ccs(ctx, peer) < 0) {
- debug("cannot send CCS message\n");
- return 0;
- }
-
- SWITCH_CONFIG(peer);
- inc_uint(uint16, peer->epoch);
- memset(peer->rseq, 0, sizeof(peer->rseq));
-/* #ifndef NDEBUG */
-/* { */
-/* printf("key_block:\n"); */
-/* printf(" client_MAC_secret:\t"); */
-/* dump(dtls_kb_client_mac_secret(CURRENT_CONFIG(peer)), */
-/* dtls_kb_mac_secret_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_MAC_secret:\t"); */
-/* dump(dtls_kb_server_mac_secret(CURRENT_CONFIG(peer)), */
-/* dtls_kb_mac_secret_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" client_write_key:\t"); */
-/* dump(dtls_kb_client_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_write_key:\t"); */
-/* dump(dtls_kb_server_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" client_IV:\t\t"); */
-/* dump(dtls_kb_client_iv(CURRENT_CONFIG(peer)), */
-/* dtls_kb_iv_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_IV:\t\t"); */
-/* dump(dtls_kb_server_iv(CURRENT_CONFIG(peer)), */
-/* dtls_kb_iv_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-
-/* } */
-/* #endif */
-
- /* Client Finished */
- {
- debug ("send Finished\n");
- int length;
- uint8 buf[DTLS_HMAC_MAX];
- uint8 *p = ctx->sendbuf;
-
- unsigned char statebuf[DTLS_HASH_CTX_SIZE];
-
- /* FIXME: adjust message overhead calculation */
- assert(msg_overhead(peer, DTLS_HS_LENGTH + DTLS_FIN_LENGTH)
- < sizeof(ctx->sendbuf));
-
- p = dtls_set_handshake_header(DTLS_HT_FINISHED,
- peer, DTLS_FIN_LENGTH,
- 0, DTLS_FIN_LENGTH, p);
-
- /* temporarily store hash status for roll-back after finalize */
- memcpy(statebuf, &peer->hs_state.hs_hash, DTLS_HASH_CTX_SIZE);
-
- length = finalize_hs_hash(peer, buf);
-
- /* restore hash status */
- memcpy(&peer->hs_state.hs_hash, statebuf, DTLS_HASH_CTX_SIZE);
-
- dtls_prf(CURRENT_CONFIG(peer)->master_secret,
- DTLS_MASTER_SECRET_LENGTH,
- PRF_LABEL(client), PRF_LABEL_SIZE(client),
- PRF_LABEL(finished), PRF_LABEL_SIZE(finished),
- buf, length,
- p, DTLS_FIN_LENGTH);
-
- p += DTLS_FIN_LENGTH;
-
- update_hs_hash(peer, ctx->sendbuf, p - ctx->sendbuf);
- if (dtls_send(ctx, peer, DTLS_CT_HANDSHAKE,
- ctx->sendbuf, p - ctx->sendbuf) < 0) {
- dsrv_log(LOG_ALERT, "cannot send Finished message\n");
- return 0;
- }
- }
- return 1;
-}
-
-int
-decrypt_verify(dtls_peer_t *peer,
- uint8 *packet, size_t length,
- uint8 **cleartext, size_t *clen) {
- int ok = 0;
-
- *cleartext = (uint8 *)packet + sizeof(dtls_record_header_t);
- *clen = length - sizeof(dtls_record_header_t);
-
- if (CURRENT_CONFIG(peer)->cipher == TLS_NULL_WITH_NULL_NULL) {
- /* no cipher suite selected */
- return 1;
- } else { /* TLS_PSK_WITH_AES_128_CCM_8 */
- dtls_cipher_context_t *cipher_context;
- /**
- * 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
-#define A_DATA N
- unsigned char N[max(DTLS_CCM_BLOCKSIZE, A_DATA_LEN)];
- long int len;
-
-
- if (*clen < 16) /* need at least IV and MAC */
- return -1;
-
- memset(N, 0, DTLS_CCM_BLOCKSIZE);
- memcpy(N, dtls_kb_remote_iv(CURRENT_CONFIG(peer)),
- dtls_kb_iv_size(CURRENT_CONFIG(peer)));
-
- /* read epoch and seq_num from message */
- memcpy(N + dtls_kb_iv_size(CURRENT_CONFIG(peer)), *cleartext, 8);
- *cleartext += 8;
- *clen -= 8;
-
- cipher_context = CURRENT_CONFIG(peer)->read_cipher;
-
- if (!cipher_context) {
- warn("no read_cipher available!\n");
- return 0;
- }
-
-/* #ifndef NDEBUG */
-/* printf("nonce:\t"); */
-/* dump(N, DTLS_CCM_BLOCKSIZE); */
-/* printf("\nkey:\t"); */
-/* dump(dtls_kb_remote_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\nciphertext:\n"); */
-/* dump(*cleartext, *clen); */
-/* printf("\n"); */
-/* #endif */
-
- dtls_cipher_set_iv(cipher_context, N, DTLS_CCM_BLOCKSIZE);
-
- /* 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(packet)->epoch, 8); /* epoch and seq_num */
- memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(packet)->content_type, 3); /* type and version */
- dtls_int_to_uint16(A_DATA + 11, *clen - 8); /* length without nonce_explicit */
-
- len = dtls_decrypt(cipher_context, *cleartext, *clen, *cleartext,
- A_DATA, A_DATA_LEN);
-
- ok = len >= 0;
- if (!ok)
- warn("decryption failed\n");
- else {
-/* #ifndef NDEBUG */
-/* printf("decrypt_verify(): found %ld bytes cleartext\n", len); */
-/* #endif */
- *clen = len;
- }
-/* #ifndef NDEBUG */
-/* printf("\ncleartext:\n"); */
-/* dump(*cleartext, *clen); */
-/* printf("\n"); */
-/* #endif */
- }
-
- return ok;
-}
-
-
-int
-handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer,
- uint8 *record_header, uint8 *data, size_t data_length) {
-
- /* The following switch construct handles the given message with
- * respect to the current internal state for this peer. In case of
- * error, it is left with return 0. */
-
- switch (peer->state) {
-
- /************************************************************************
- * Client states
- ************************************************************************/
-
- case DTLS_STATE_CLIENTHELLO:
- /* here we expect a HelloVerify or ServerHello */
-
- debug("DTLS_STATE_CLIENTHELLO\n");
- if (check_server_hello(ctx, peer, data, data_length)) {
- peer->state = DTLS_STATE_WAIT_SERVERHELLODONE;
- /* update_hs_hash(peer, data, data_length); */
- }
-
- break;
-
- case DTLS_STATE_WAIT_SERVERHELLODONE:
- /* expect a ServerHelloDone */
-
- debug("DTLS_STATE_WAIT_SERVERHELLODONE\n");
-
- if (check_server_hellodone(ctx, peer, data, data_length)) {
- peer->state = DTLS_STATE_WAIT_SERVERFINISHED;
- /* update_hs_hash(peer, data, data_length); */
- }
-
- break;
-
- case DTLS_STATE_WAIT_SERVERFINISHED:
- /* expect a Finished message from server */
-
- debug("DTLS_STATE_WAIT_SERVERFINISHED\n");
- if (check_finished(ctx, peer, record_header, data, data_length)) {
- debug("finished!\n");
- peer->state = DTLS_STATE_CONNECTED;
- }
-
- break;
-
- /************************************************************************
- * Server states
- ************************************************************************/
-
- case DTLS_STATE_SERVERHELLO:
- /* here we expect a ClientHello */
- /* handle ClientHello, update msg and msglen and goto next if not finished */
-
- debug("DTLS_STATE_SERVERHELLO\n");
- if (!check_client_keyexchange(ctx, peer, data, data_length)) {
- warn("check_client_keyexchange failed (%d, %d)\n", data_length, data[0]);
- return 0; /* drop it, whatever it is */
- }
-
- update_hs_hash(peer, data, data_length);
- peer->state = DTLS_STATE_KEYEXCHANGE;
- break;
-
- case DTLS_STATE_WAIT_FINISHED:
- debug("DTLS_STATE_WAIT_FINISHED\n");
- if (check_finished(ctx, peer, record_header, data, data_length)) {
- debug("finished!\n");
-
- /* send ServerFinished */
- update_hs_hash(peer, data, data_length);
-
- if (dtls_send_server_finished(ctx, peer) > 0) {
- peer->state = DTLS_STATE_CONNECTED;
- } else {
- warn("sending server Finished failed\n");
- }
- } else {
- /* send alert */
- }
- break;
-
- case DTLS_STATE_CONNECTED:
- /* At this point, we have a good relationship with this peer. This
- * state is left for re-negotiation of key material. */
-
- debug("DTLS_STATE_CONNECTED\n");
-
- /* renegotiation */
- if (dtls_verify_peer(ctx, peer, &peer->session,
- record_header, data, data_length) > 0) {
-
- clear_hs_hash(peer);
-
- if (!dtls_update_parameters(ctx, peer, data, data_length)) {
-
- warn("error updating security parameters\n");
- dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_WARNING,
- DTLS_ALERT_NO_RENEGOTIATION);
- return 0;
- }
-
- /* update finish MAC */
- update_hs_hash(peer, data, data_length);
-
- if (dtls_send_server_hello(ctx, peer) > 0)
- peer->state = DTLS_STATE_SERVERHELLO;
-
- /* after sending the ServerHelloDone, we expect the
- * ClientKeyExchange (possibly containing the PSK id),
- * followed by a ChangeCipherSpec and an encrypted Finished.
- */
- }
-
- break;
-
- case DTLS_STATE_INIT: /* these states should not occur here */
- case DTLS_STATE_KEYEXCHANGE:
- default:
- dsrv_log(LOG_CRIT, "unhandled state %d\n", peer->state);
- assert(0);
- }
-
- return 1;
-}
-
-int
-handle_ccs(dtls_context_t *ctx, dtls_peer_t *peer,
- uint8 *record_header, uint8 *data, size_t data_length) {
-
- /* A CCS message is handled after a KeyExchange message was
- * received from the client. When security parameters have been
- * updated successfully and a ChangeCipherSpec message was sent
- * by ourself, the security context is switched and the record
- * sequence number is reset. */
-
- if (peer->state != DTLS_STATE_KEYEXCHANGE
- || !check_ccs(ctx, peer, record_header, data, data_length)) {
- /* signal error? */
- warn("expected ChangeCipherSpec during handshake\n");
- return 0;
-
- }
-
- /* send change cipher spec message and switch to new configuration */
- if (dtls_send_ccs(ctx, peer) < 0) {
- warn("cannot send CCS message");
- return 0;
- }
-
- SWITCH_CONFIG(peer);
- inc_uint(uint16, peer->epoch);
- memset(peer->rseq, 0, sizeof(peer->rseq));
-
- peer->state = DTLS_STATE_WAIT_FINISHED;
-
-/* #ifndef NDEBUG */
-/* { */
-/* printf("key_block:\n"); */
-/* printf(" client_MAC_secret:\t"); */
-/* dump(dtls_kb_client_mac_secret(CURRENT_CONFIG(peer)), */
-/* dtls_kb_mac_secret_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_MAC_secret:\t"); */
-/* dump(dtls_kb_server_mac_secret(CURRENT_CONFIG(peer)), */
-/* dtls_kb_mac_secret_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" client_write_key:\t"); */
-/* dump(dtls_kb_client_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_write_key:\t"); */
-/* dump(dtls_kb_server_write_key(CURRENT_CONFIG(peer)), */
-/* dtls_kb_key_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" client_IV:\t\t"); */
-/* dump(dtls_kb_client_iv(CURRENT_CONFIG(peer)), */
-/* dtls_kb_iv_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-/* printf(" server_IV:\t\t"); */
-/* dump(dtls_kb_server_iv(CURRENT_CONFIG(peer)), */
-/* dtls_kb_iv_size(CURRENT_CONFIG(peer))); */
-/* printf("\n"); */
-
-
-/* } */
-/* #endif */
-
- return 1;
-}
-
-/**
- * Handles incoming Alert messages. This function returns \c 1 if the
- * connection should be closed and the peer is to be invalidated.
- */
-int
-handle_alert(dtls_context_t *ctx, dtls_peer_t *peer,
- uint8 *record_header, uint8 *data, size_t data_length) {
- int free_peer = 0; /* indicates whether to free peer */
-
- if (data_length < 2)
- return 0;
-
- info("** Alert: level %d, description %d\n", data[0], data[1]);
-
- /* The peer object is invalidated for FATAL alerts and close
- * notifies. This is done in two steps.: First, remove the object
- * from our list of peers. After that, the event handler callback is
- * invoked with the still existing peer object. Finally, the storage
- * used by peer is released.
- */
- if (data[0] == DTLS_ALERT_LEVEL_FATAL || data[1] == DTLS_ALERT_CLOSE) {
- dsrv_log(LOG_ALERT, "%d invalidate peer\n", data[1]);
-
-#ifndef WITH_CONTIKI
- HASH_DEL_PEER(ctx->peers, peer);
-#else /* WITH_CONTIKI */
- list_remove(ctx->peers, peer);
-
-/* #ifndef NDEBUG */
-/* PRINTF("removed peer ["); */
-/* PRINT6ADDR(&peer->session.addr); */
-/* PRINTF("]:%d\n", uip_ntohs(peer->session.port)); */
-/* #endif */
-#endif /* WITH_CONTIKI */
-
- free_peer = 1;
-
- }
-
- (void)CALL(ctx, event, &peer->session,
- (dtls_alert_level_t)data[0], (unsigned short)data[1]);
- switch (data[1]) {
- case DTLS_ALERT_CLOSE:
- /* If state is DTLS_STATE_CLOSING, we have already sent a
- * close_notify so, do not send that again. */
- if (peer->state != DTLS_STATE_CLOSING) {
- peer->state = DTLS_STATE_CLOSING;
- dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_CLOSE);
- } else
- peer->state = DTLS_STATE_CLOSED;
- break;
- default:
- ;
- }
-
- if (free_peer) {
- dtls_stop_retransmission(ctx, peer);
- dtls_free_peer(peer);
- }
-
- return free_peer;
-}
-
-/**
- * Handles incoming data as DTLS message from given peer.
- */
-int
-dtls_handle_message(dtls_context_t *ctx,
- session_t *session,
- uint8 *msg, int msglen) {
- dtls_peer_t *peer = NULL;
- unsigned int rlen; /* record length */
- uint8 *data; /* (decrypted) payload */
- size_t data_length; /* length of decrypted payload
- (without MAC and padding) */
-
- /* check if we have DTLS state for addr/port/ifindex */
- peer = dtls_get_peer(ctx, session);
-
-#ifndef NDEBUG
- if (peer) {
- unsigned char addrbuf[72];
-
- dsrv_print_addr(session, addrbuf, sizeof(addrbuf));
- debug("found peer %s\n", addrbuf);
- }
-#endif /* NDEBUG */
-
- if (!peer) {
-
- /* get first record from client message */
- rlen = is_record(msg, msglen);
- assert(rlen <= msglen);
-
- if (!rlen) {
-#ifndef NDEBUG
- if (msglen > 3)
- debug("dropped invalid message %02x%02x%02x%02x\n", msg[0], msg[1], msg[2], msg[3]);
- else
- debug("dropped invalid message (less than four bytes)\n");
-#endif
- return 0;
- }
-
- /* is_record() ensures that msg contains at least a record header */
- data = msg + DTLS_RH_LENGTH;
- data_length = rlen - DTLS_RH_LENGTH;
-
- /* When no DTLS state exists for this peer, we only allow a
- Client Hello message with
-
- a) a valid cookie, or
- b) no cookie.
-
- Anything else will be rejected. Fragementation is not allowed
- here as it would require peer state as well.
- */
-
- if (dtls_verify_peer(ctx, NULL, session, msg, data, data_length) <= 0) {
- warn("cannot verify peer\n");
- return -1;
- }
-
- /* msg contains a Client Hello with a valid cookie, so we can
- safely create the server state machine and continue with
- the handshake. */
-
- peer = dtls_new_peer(session);
- if (!peer) {
- dsrv_log(LOG_ALERT, "cannot create peer");
- /* FIXME: signal internal error */
- return -1;
- }
-
- /* Initialize record sequence number to 1 for new peers. The first
- * record with sequence number 0 is a stateless Hello Verify Request.
- */
- peer->rseq[5] = 1;
-
- /* First negotiation step: check for PSK
- *
- * Note that we already have checked that msg is a Handshake
- * message containing a ClientHello. dtls_get_cipher() therefore
- * does not check again.
- */
- if (!dtls_update_parameters(ctx, peer,
- msg + DTLS_RH_LENGTH, rlen - DTLS_RH_LENGTH)) {
-
- warn("error updating security parameters\n");
- /* FIXME: send handshake failure Alert */
- dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL,
- DTLS_ALERT_HANDSHAKE_FAILURE);
- dtls_free_peer(peer);
- return -1;
- }
-
-#ifndef WITH_CONTIKI
- HASH_ADD_PEER(ctx->peers, session, peer);
-#else /* WITH_CONTIKI */
- list_add(ctx->peers, peer);
-#endif /* WITH_CONTIKI */
-
- /* update finish MAC */
- update_hs_hash(peer, msg + DTLS_RH_LENGTH, rlen - DTLS_RH_LENGTH);
-
- if (dtls_send_server_hello(ctx, peer) > 0)
- peer->state = DTLS_STATE_SERVERHELLO;
-
- /* after sending the ServerHelloDone, we expect the
- * ClientKeyExchange (possibly containing the PSK id),
- * followed by a ChangeCipherSpec and an encrypted Finished.
- */
-
- msg += rlen;
- msglen -= rlen;
- } else {
- debug("found peer\n");
- }
-
- /* At this point peer contains a state machine to handle the
- received message. */
-
- assert(peer);
-
- /* FIXME: check sequence number of record and drop message if the
- * number is not exactly the last number that we have responded to + 1.
- * Otherwise, stop retransmissions for this specific peer and
- * continue processing. */
- dtls_stop_retransmission(ctx, peer);
-
- while ((rlen = is_record(msg,msglen))) {
-
- debug("got packet %d (%d bytes)\n", msg[0], rlen);
- /* skip packet if it is from a different epoch */
- if (memcmp(DTLS_RECORD_HEADER(msg)->epoch,
- peer->epoch, sizeof(uint16)) != 0)
- goto next;
-
- if (!decrypt_verify(peer, msg, rlen, &data, &data_length)) {
- info("decrypt_verify() failed\n");
- goto next;
- }
-
-/* #ifndef NDEBUG */
-/* hexdump(msg, sizeof(dtls_record_header_t)); */
-/* printf("\n"); */
-/* hexdump(data, data_length); */
-/* printf("\n"); */
-/* #endif */
-
- /* Handle received record according to the first byte of the
- * message, i.e. the subprotocol. We currently do not support
- * combining multiple fragments of one type into a single
- * record. */
-
- switch (msg[0]) {
-
- case DTLS_CT_CHANGE_CIPHER_SPEC:
- handle_ccs(ctx, peer, msg, data, data_length);
- break;
-
- case DTLS_CT_ALERT:
- if (handle_alert(ctx, peer, msg, data, data_length)) {
- /* handle alert has invalidated peer */
- peer = NULL;
- return 0;
- }
-
- case DTLS_CT_HANDSHAKE:
- handle_handshake(ctx, peer, msg, data, data_length);
- if (peer->state == DTLS_STATE_CONNECTED) {
- /* stop retransmissions */
- dtls_stop_retransmission(ctx, peer);
- CALL(ctx, event, &peer->session, 0, DTLS_EVENT_CONNECTED);
- }
- break;
-
- case DTLS_CT_APPLICATION_DATA:
- info("** application data:\n");
- CALL(ctx, read, &peer->session, data, data_length);
- break;
- default:
- info("dropped unknown message of type %d\n",msg[0]);
- }
-
- next:
- /* advance msg by length of ciphertext */
- msg += rlen;
- msglen -= rlen;
- }
-
- return 0;
-}
-
-dtls_context_t *
-dtls_new_context(void *app_data) {
- dtls_context_t *c;
- dtls_tick_t now;
-#ifndef WITH_CONTIKI
- FILE *urandom = fopen("/dev/urandom", "r");
- unsigned char buf[sizeof(unsigned long)];
-#endif /* WITH_CONTIKI */
-
- dtls_ticks(&now);
-#ifdef WITH_CONTIKI
- /* FIXME: need something better to init PRNG here */
- prng_init(now);
-#else /* WITH_CONTIKI */
- if (!urandom) {
- dsrv_log(LOG_EMERG, "cannot initialize PRNG\n");
- return NULL;
- }
-
- if (fread(buf, 1, sizeof(buf), urandom) != sizeof(buf)) {
- dsrv_log(LOG_EMERG, "cannot initialize PRNG\n");
- return NULL;
- }
-
- fclose(urandom);
- prng_init((unsigned long)*buf);
-#endif /* WITH_CONTIKI */
-
- c = &the_dtls_context;
-
- memset(c, 0, sizeof(dtls_context_t));
- c->app = app_data;
-
- LIST_STRUCT_INIT(c, sendqueue);
-
-#ifdef WITH_CONTIKI
- LIST_STRUCT_INIT(c, peers);
- /* LIST_STRUCT_INIT(c, key_store); */
-
- process_start(&dtls_retransmit_process, (char *)c);
- PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process);
- /* the retransmit timer must be initialized to some large value */
- etimer_set(&c->retransmit_timer, 0xFFFF);
- PROCESS_CONTEXT_END(&coap_retransmit_process);
-#endif /* WITH_CONTIKI */
-
- if (prng(c->cookie_secret, DTLS_COOKIE_SECRET_LENGTH))
- c->cookie_secret_age = now;
- else
- goto error;
-
- return c;
-
- error:
- dsrv_log(LOG_ALERT, "cannot create DTLS context");
- if (c)
- dtls_free_context(c);
- return NULL;
-}
-
-void dtls_free_context(dtls_context_t *ctx) {
- dtls_peer_t *p;
-
-#ifndef WITH_CONTIKI
- dtls_peer_t *tmp;
-
- if (ctx->peers) {
- HASH_ITER(hh, ctx->peers, p, tmp) {
- dtls_free_peer(p);
- }
- }
-#else /* WITH_CONTIKI */
- int i;
-
- p = (dtls_peer_t *)peer_storage.mem;
- for (i = 0; i < peer_storage.num; ++i, ++p) {
- if (peer_storage.count[i])
- dtls_free_peer(p);
- }
-#endif /* WITH_CONTIKI */
-}
-
-int
-dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
- uint8 *p = ctx->sendbuf;
- size_t size;
- int res;
- dtls_tick_t now;
-
- assert(peer);
- if (!peer)
- return -1;
-
- /* check if the same peer is already in our list */
- if (peer == dtls_get_peer(ctx, &peer->session)) {
- debug("found peer, try to re-connect\n");
- /* FIXME: send HelloRequest if we are server,
- ClientHello with good cookie if client */
- return 0;
- }
-
- /* set peer role to server: */
- OTHER_CONFIG(peer)->role = DTLS_SERVER;
- CURRENT_CONFIG(peer)->role = DTLS_SERVER;
-
- dtls_add_peer(ctx, peer);
-
- /* send ClientHello with some Cookie */
-
- /* add to size:
- * 1. length of session id (including length field)
- * 2. length of cookie (including length field)
- * 3. cypher suites
- * 4. compression methods
- */
- size = DTLS_CH_LENGTH + 8;
-
- /* force sending 0 as handshake message sequence number by setting
- * peer to NULL */
- p = dtls_set_handshake_header(DTLS_HT_CLIENT_HELLO, NULL,
- size, 0, size, p);
-
- dtls_int_to_uint16(p, DTLS_VERSION);
- p += sizeof(uint16);
-
- dtls_ticks(&now);
- /* Set client random: First 4 bytes are the client's Unix timestamp,
- * followed by 28 bytes of generate random data. */
- dtls_int_to_uint32(&OTHER_CONFIG(peer)->client_random,
- now / DTLS_TICKS_PER_SECOND);
- prng(OTHER_CONFIG(peer)->client_random + sizeof(uint32),
- sizeof(OTHER_CONFIG(peer)->client_random) - sizeof(uint32));
- memcpy(p, OTHER_CONFIG(peer)->client_random,
- sizeof(OTHER_CONFIG(peer)->client_random));
- p += 32;
-
- /* session id (length 0) */
- dtls_int_to_uint8(p, 0);
- p += sizeof(uint8);
-
- dtls_int_to_uint8(p, 0);
- p += sizeof(uint8);
-
- /* add supported cipher suite */
- dtls_int_to_uint16(p, 2);
- p += sizeof(uint16);
-
- dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8);
- p += sizeof(uint16);
-
- /* compression method */
- dtls_int_to_uint8(p, 1);
- p += sizeof(uint8);
-
- dtls_int_to_uint8(p, TLS_COMP_NULL);
- p += sizeof(uint8);
-
- res = dtls_send(ctx, peer, DTLS_CT_HANDSHAKE, ctx->sendbuf,
- p - ctx->sendbuf);
- if (res < 0)
- warn("cannot send ClientHello\n");
- else
- peer->state = DTLS_STATE_CLIENTHELLO;
-
- return res;
-}
-
-int
-dtls_connect(dtls_context_t *ctx, const session_t *dst) {
- dtls_peer_t *peer;
-
- peer = dtls_get_peer(ctx, dst);
-
- if (!peer)
- peer = dtls_new_peer(dst);
-
- if (!peer) {
- dsrv_log(LOG_CRIT, "cannot create new peer\n");
- return -1;
- }
-
- return dtls_connect_peer(ctx, peer);
-}
-
-void
-dtls_retransmit(dtls_context_t *context, netq_t *node) {
- if (!context || !node)
- return;
-
- /* re-initialize timeout when maximum number of retransmissions are not reached yet */
- if (node->retransmit_cnt < DTLS_DEFAULT_MAX_RETRANSMIT) {
- unsigned char sendbuf[DTLS_MAX_BUF];
- size_t len = sizeof(sendbuf);
-
- node->retransmit_cnt++;
- node->t += (node->timeout << node->retransmit_cnt);
- netq_insert_node((netq_t **)context->sendqueue, node);
-
- debug("** retransmit packet\n");
-
- if (dtls_prepare_record(node->peer, DTLS_CT_HANDSHAKE,
- node->data, node->length,
- sendbuf, &len) > 0) {
-
-#ifndef NDEBUG
- if (dtls_get_log_level() >= LOG_DEBUG) {
- debug("retransmit %d bytes\n", len);
- hexdump(sendbuf, sizeof(dtls_record_header_t));
- printf("\n");
- hexdump(node->data, node->length);
- printf("\n");
- }
-#endif
-
- (void)CALL(context, write, &node->peer->session, sendbuf, len);
- }
- return;
- }
-
- /* no more retransmissions, remove node from system */
-
- debug("** removed transaction\n");
-
- /* And finally delete the node */
- netq_node_free(node);
-}
-
-void
-dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer) {
- void *node;
- node = list_head((list_t)context->sendqueue);
-
- while (node) {
- if (dtls_session_equals(&((netq_t *)node)->peer->session,
- &peer->session)) {
- void *tmp = node;
- node = list_item_next(node);
- list_remove((list_t)context->sendqueue, tmp);
- netq_node_free((netq_t *)tmp);
- } else
- node = list_item_next(node);
- }
-}
-
-void
-dtls_check_retransmit(dtls_context_t *context, clock_time_t *next) {
- dtls_tick_t now;
- netq_t *node = netq_head((netq_t **)context->sendqueue);
-
- dtls_ticks(&now);
- while (node && node->t <= now) {
- netq_pop_first((netq_t **)context->sendqueue);
- dtls_retransmit(context, node);
- node = netq_head((netq_t **)context->sendqueue);
- }
-
- if (next && node)
- *next = node->t;
-}
-
-#ifdef WITH_CONTIKI
-/*---------------------------------------------------------------------------*/
-/* message retransmission */
-/*---------------------------------------------------------------------------*/
-PROCESS_THREAD(dtls_retransmit_process, ev, data)
-{
- clock_time_t now;
- netq_t *node;
-
- PROCESS_BEGIN();
-
- debug("Started DTLS retransmit process\r\n");
-
- while(1) {
- PROCESS_YIELD();
- if (ev == PROCESS_EVENT_TIMER) {
- if (etimer_expired(&the_dtls_context.retransmit_timer)) {
-
- node = list_head(the_dtls_context.sendqueue);
-
- now = clock_time();
- while (node && node->t <= now) {
- dtls_retransmit(&the_dtls_context, list_pop(the_dtls_context.sendqueue));
- node = list_head(the_dtls_context.sendqueue);
- }
-
- /* need to set timer to some value even if no nextpdu is available */
- etimer_set(&the_dtls_context.retransmit_timer,
- node ? node->t - now : 0xFFFF);
- }
- }
- }
-
- PROCESS_END();
-}
-#endif /* WITH_CONTIKI */
-
-#ifndef NDEBUG
-/** dumps packets in usual hexdump format */
-void hexdump(const unsigned char *packet, int length) {
- int n = 0;
-
- while (length--) {
- if (n % 16 == 0)
- printf("%08X ",n);
-
- printf("%02X ", *packet++);
-
- n++;
- if (n % 8 == 0) {
- if (n % 16 == 0)
- printf("\n");
- else
- printf(" ");
- }
- }
-}
-
-/** dump as narrow string of hex digits */
-void dump(unsigned char *buf, size_t len) {
- while (len--)
- printf("%02x", *buf++);
-}
-#endif
-
--- a/tinydtls/dtls.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,674 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file dtls.h
- * @brief High level DTLS API and visible structures.
- */
-
-#ifndef _DTLS_H_
-#define _DTLS_H_
-
-#include <stdint.h>
-
-#include "t_list.h"
-#include "state.h"
-#include "peer.h"
-
-#ifndef WITH_CONTIKI
-#include "uthash.h"
-#endif /* WITH_CONTIKI */
-
-#include "alert.h"
-#include "crypto.h"
-#include "hmac.h"
-
-#include "config.h"
-#include "global.h"
-#include "dtls_time.h"
-
-#ifndef DTLSv12
-#define DTLS_VERSION 0xfeff /* DTLS v1.1 */
-#else
-#define DTLS_VERSION 0xfefd /* DTLS v1.2 */
-#endif
-
-/** Known compression methods
- *
- * \hideinitializer
- */
-#define TLS_COMP_NULL 0x00 /* NULL compression */
-
-typedef enum {
- DTLS_KEY_INVALID=0, DTLS_KEY_PSK=1, DTLS_KEY_RPK=2
-} dtls_key_type_t;
-
-typedef struct dtls_key_t {
- dtls_key_type_t type;
- union {
- struct dtls_psk_t {
- unsigned char *id; /**< psk identity */
- size_t id_length; /**< length of psk identity */
- unsigned char *key; /**< key data */
- size_t key_length; /**< length of key */
- } psk;
- } key;
-} dtls_key_t;
-
-/** Length of the secret that is used for generating Hello Verify cookies. */
-#define DTLS_COOKIE_SECRET_LENGTH 12
-
-struct dtls_context_t;
-
-/**
- * This structure contains callback functions used by tinydtls to
- * communicate with the application. At least the write function must
- * be provided. It is called by the DTLS state machine to send packets
- * over the network. The read function is invoked to deliver decrypted
- * and verfified application data. The third callback is an event
- * handler function that is called when alert messages are encountered
- * or events generated by the library have occured.
- */
-typedef struct {
- /**
- * Called from dtls_handle_message() to send DTLS packets over the
- * network. The callback function must use the network interface
- * denoted by session->ifindex to send the data.
- *
- * @param ctx The current DTLS context.
- * @param session The session object, including the address of the
- * remote peer where the data shall be sent.
- * @param buf The data to send.
- * @param len The actual length of @p buf.
- * @return The callback function must return the number of bytes
- * that were sent, or a value less than zero to indicate an
- * error.
- */
- int (*write)(struct dtls_context_t *ctx,
- session_t *session, uint8 *buf, size_t len);
-
- /**
- * Called from dtls_handle_message() deliver application data that was
- * received on the given session. The data is delivered only after
- * decryption and verification have succeeded.
- *
- * @param ctx The current DTLS context.
- * @param session The session object, including the address of the
- * data's origin.
- * @param buf The received data packet.
- * @param len The actual length of @p buf.
- * @return ignored
- */
- int (*read)(struct dtls_context_t *ctx,
- session_t *session, uint8 *buf, size_t len);
-
- /**
- * The event handler is called when a message from the alert
- * protocol is received or the state of the DTLS session changes.
- *
- * @param ctx The current dtls context.
- * @param session The session object that was affected.
- * @param level The alert level or @c 0 when an event ocurred that
- * is not an alert.
- * @param code Values less than @c 256 indicate alerts, while
- * @c 256 or greater indicate internal DTLS session changes.
- * @return ignored
- */
- int (*event)(struct dtls_context_t *ctx, session_t *session,
- dtls_alert_level_t level, unsigned short code);
-
- /**
- * Called during handshake to lookup the key for @p id in @p
- * session. If found, the key must be stored in @p result and
- * the return value must be @c 0. If not found, @p result is
- * undefined and the return value must be less than zero.
- *
- * @param ctx The current dtls context.
- * @param session The session where the key will be used.
- * @param id The identity of the communicating peer. This value is
- * @c NULL when the DTLS engine requests the local
- * id/key pair to use for session setup.
- * @param id_len The actual length of @p id
- * @param result Must be set to the key object to use.for the given
- * session.
- * @return @c 0 if result is set, or less than zero on error.
- */
- int (*get_key)(struct dtls_context_t *ctx,
- const session_t *session,
- const unsigned char *id, size_t id_len,
- const dtls_key_t **result);
-} dtls_handler_t;
-
-/** Holds global information of the DTLS engine. */
-typedef struct dtls_context_t {
- unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH];
- clock_time_t cookie_secret_age; /**< the time the secret has been generated */
-
-#ifndef WITH_CONTIKI
- dtls_peer_t *peers; /**< peer hash map */
-#else /* WITH_CONTIKI */
- LIST_STRUCT(peers);
-
- struct etimer retransmit_timer; /**< fires when the next packet must be sent */
-#endif /* WITH_CONTIKI */
-
- LIST_STRUCT(sendqueue); /**< the packets to send */
-
- void *app; /**< application-specific data */
-
- dtls_handler_t *h; /**< callback handlers */
-
- unsigned char readbuf[DTLS_MAX_BUF];
- unsigned char sendbuf[DTLS_MAX_BUF];
-} dtls_context_t;
-
-/**
- * This function initializes the tinyDTLS memory management and must
- * be called first.
- */
-void dtls_init();
-
-/**
- * Creates a new context object. The storage allocated for the new
- * object must be released with dtls_free_context(). */
-dtls_context_t *dtls_new_context(void *app_data);
-
-/** Releases any storage that has been allocated for \p ctx. */
-void dtls_free_context(dtls_context_t *ctx);
-
-#define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA))
-#define dtls_get_app_data(CTX) ((CTX)->app)
-
-/** Sets the callback handler object for @p ctx to @p h. */
-static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
- ctx->h = h;
-}
-
-/**
- * Establishes a DTLS channel with the specified remote peer @p dst.
- * This function returns @c 0 if that channel already exists, a value
- * greater than zero when a new ClientHello message was sent, and
- * a value less than zero on error.
- *
- * @param ctx The DTLS context to use.
- * @param dst The remote party to connect to.
- * @return A value less than zero on error, greater or equal otherwise.
- */
-int dtls_connect(dtls_context_t *ctx, const session_t *dst);
-
-/**
- * Establishes a DTLS channel with the specified remote peer.
- * This function returns @c 0 if that channel already exists, a value
- * greater than zero when a new ClientHello message was sent, and
- * a value less than zero on error.
- *
- * @param ctx The DTLS context to use.
- * @param peer The peer object that describes the session.
- * @return A value less than zero on error, greater or equal otherwise.
- */
-int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);
-
-/**
- * Closes the DTLS connection associated with @p remote. This function
- * returns zero on success, and a value less than zero on error.
- */
-int dtls_close(dtls_context_t *ctx, const session_t *remote);
-
-/**
- * Writes the application data given in @p buf to the peer specified
- * by @p session.
- *
- * @param ctx The DTLS context to use.
- * @param session The remote transport address and local interface.
- * @param buf The data to write.
- * @param len The actual length of @p data.
- *
- * @return The number of bytes written or @c -1 on error.
- */
-int dtls_write(struct dtls_context_t *ctx, session_t *session,
- uint8 *buf, size_t len);
-
-/**
- * Checks sendqueue of given DTLS context object for any outstanding
- * packets to be transmitted.
- *
- * @param context The DTLS context object to use.
- * @param next If not NULL, @p next is filled with the timestamp
- * of the next scheduled retransmission, or @c 0 when no packets are
- * waiting.
- */
-void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
-
-#define DTLS_COOKIE_LENGTH 16
-
-#define DTLS_CT_CHANGE_CIPHER_SPEC 20
-#define DTLS_CT_ALERT 21
-#define DTLS_CT_HANDSHAKE 22
-#define DTLS_CT_APPLICATION_DATA 23
-
-/** Generic header structure of the DTLS record layer. */
-typedef struct {
- uint8 content_type; /**< content type of the included message */
- uint16 version; /**< Protocol version */
- uint16 epoch; /**< counter for cipher state changes */
- uint48 sequence_number; /**< sequence number */
- uint16 length; /**< length of the following fragment */
- /* fragment */
-} dtls_record_header_t;
-
-/* Handshake types */
-
-#define DTLS_HT_HELLO_REQUEST 0
-#define DTLS_HT_CLIENT_HELLO 1
-#define DTLS_HT_SERVER_HELLO 2
-#define DTLS_HT_HELLO_VERIFY_REQUEST 3
-#define DTLS_HT_CERTIFICATE 11
-#define DTLS_HT_SERVER_KEY_EXCHANGE 12
-#define DTLS_HT_CERTIFICATE_REQUEST 13
-#define DTLS_HT_SERVER_HELLO_DONE 14
-#define DTLS_HT_CERTIFICATE_VERIFY 15
-#define DTLS_HT_CLIENT_KEY_EXCHANGE 16
-#define DTLS_HT_FINISHED 20
-
-/** Header structure for the DTLS handshake protocol. */
-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 */
- uint24 fragment_offset; /**< Fragment offset. */
- uint24 fragment_length; /**< Fragment length. */
- /* body */
-} dtls_handshake_header_t;
-
-/** Structure of the Client Hello message. */
-typedef struct {
- uint16 version; /**< Client version */
- uint32 gmt_random; /**< GMT time of the random byte creation */
- unsigned char random[28]; /**< Client random bytes */
- /* session id (up to 32 bytes) */
- /* cookie (up to 32 bytes) */
- /* cipher suite (2 to 2^16 -1 bytes) */
- /* compression method */
-} dtls_client_hello_t;
-
-/** Structure of the Hello Verify Request. */
-typedef struct {
- uint16 version; /**< Server version */
- uint8 cookie_length; /**< Length of the included cookie */
- uint8 cookie[]; /**< up to 32 bytes making up the cookie */
-} dtls_hello_verify_t;
-
-#if 0
-/**
- * Checks a received DTLS record for consistency and eventually decrypt,
- * verify, decompress and reassemble the contained fragment for
- * delivery to high-lever clients.
- *
- * \param state The DTLS record state for the current session.
- * \param
- */
-int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
-#endif
-
-/**
- * Retrieves a pointer to the cookie contained in a Client Hello message.
- *
- * \param hello_msg Points to the received Client Hello message
- * \param msglen Length of \p hello_msg
- * \param cookie Is set to the beginning of the cookie in the message if
- * found. Undefined if this function returns \c 0.
- * \return \c 0 if no cookie was found, < 0 on error. On success, the return
- * value reflects the cookie's length.
- */
-int dtls_get_cookie(uint8 *hello_msg, int msglen, uint8 **cookie);
-
-/**
- * Handles incoming data as DTLS message from given peer.
- *
- * @param ctx The dtls context to use.
- * @param session The current session
- * @param msg The received data
- * @param msglen The actual length of @p msg.
- * @return A value less than zero on error, zero on success.
- */
-int dtls_handle_message(dtls_context_t *ctx, session_t *session,
- uint8 *msg, int msglen);
-
-/**
- * Check if @p session is associated with a peer object in @p context.
- * This function returns a pointer to the peer if found, NULL otherwise.
- *
- * @param context The DTLS context to search.
- * @param session The remote address and local interface
- * @return A pointer to the peer associated with @p session or NULL if
- * none exists.
- */
-dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
- const session_t *session);
-
-
-#endif /* _DTLS_H_ */
-
-/**
- * @mainpage
- *
- * @author Olaf Bergmann, TZI Uni Bremen
- *
- * This library provides a very simple datagram server with DTLS
- * support. It is designed to support session multiplexing in
- * single-threaded applications and thus targets specifically on
- * embedded systems.
- *
- * @section license License
- *
- * This software is under the <a
- * href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.
- *
- * @subsection uthash UTHash
- *
- * This library uses <a href="http://uthash.sourceforge.net/">uthash</a> to manage
- * its peers (not used for Contiki). @b uthash uses the <b>BSD revised license</b>, see
- * <a href="http://uthash.sourceforge.net/license.html">http://uthash.sourceforge.net/license.html</a>.
- *
- * @subsection sha256 Aaron D. Gifford's SHA256 Implementation
- *
- * tinyDTLS provides HMAC-SHA256 with BSD-licensed code from Aaron D. Gifford,
- * see <a href="http://www.aarongifford.com/">www.aarongifford.com</a>.
- *
- * @subsection aes Rijndael Implementation From OpenBSD
- *
- * The AES implementation is taken from rijndael.{c,h} contained in the crypto
- * sub-system of the OpenBSD operating system. It is copyright by Vincent Rijmen, *
- * Antoon Bosselaers and Paulo Barreto. See <a
- * href="http://www.openbsd.org/cgi-bin/cvsweb/src/sys/crypto/rijndael.c">rijndael.c</a>
- * for License info.
- *
- * @section download Getting the Files
- *
- * You can get the sources either from the <a
- * href="http://sourceforge.net/projects/tinydtls/files">downloads</a> section or
- * through git from the <a
- * href="http://sourceforge.net/projects/tinydtls/develop">project develop page</a>.
- *
- * @section config Configuration
- *
- * Use @c configure to set up everything for a successful build. For Contiki, use the
- * option @c --with-contiki.
- *
- * @section build Building
- *
- * After configuration, just type
- * @code
-make
- * @endcode
- * optionally followed by
- * @code
-make install
- * @endcode
- * The Contiki version is integrated with the Contiki build system, hence you do not
- * need to invoke @c make explicitely. Just add @c tinydtls to the variable @c APPS
- * in your @c Makefile.
- *
- * @addtogroup dtls_usage DTLS Usage
- *
- * @section dtls_server_example DTLS Server Example
- *
- * This section shows how to use the DTLS library functions to setup a
- * simple secure UDP echo server. The application is responsible for the
- * entire network communication and thus will look like a usual UDP
- * server with socket creation and binding and a typical select-loop as
- * shown below. The minimum configuration required for DTLS is the
- * creation of the dtls_context_t using dtls_new_context(), and a callback
- * for sending data. Received packets are read by the application and
- * passed to dtls_handle_message() as shown in @ref dtls_read_cb.
- * For any useful communication to happen, read and write call backs
- * and a key management function should be registered as well.
- *
- * @code
- dtls_context_t *the_context = NULL;
- int fd, result;
-
- static dtls_handler_t cb = {
- .write = send_to_peer,
- .read = read_from_peer,
- .event = NULL,
- .get_key = get_key
- };
-
- fd = socket(...);
- if (fd < 0 || bind(fd, ...) < 0)
- exit(-1);
-
- the_context = dtls_new_context(&fd);
- dtls_set_handler(the_context, &cb);
-
- while (1) {
- ...initialize fd_set rfds and timeout ...
- result = select(fd+1, &rfds, NULL, 0, NULL);
-
- if (FD_ISSET(fd, &rfds))
- dtls_handle_read(the_context);
- }
-
- dtls_free_context(the_context);
- * @endcode
- *
- * @subsection dtls_read_cb The Read Callback
- *
- * The DTLS library expects received raw data to be passed to
- * dtls_handle_message(). The application is responsible for
- * filling a session_t structure with the address data of the
- * remote peer as illustrated by the following example:
- *
- * @code
-int dtls_handle_read(struct dtls_context_t *ctx) {
- int *fd;
- session_t session;
- static uint8 buf[DTLS_MAX_BUF];
- int len;
-
- fd = dtls_get_app_data(ctx);
-
- assert(fd);
-
- session.size = sizeof(session.addr);
- len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size);
-
- return len < 0 ? len : dtls_handle_message(ctx, &session, buf, len);
-}
- * @endcode
- *
- * Once a new DTLS session was established and DTLS ApplicationData has been
- * received, the DTLS server invokes the read callback with the MAC-verified
- * cleartext data as its argument. A read callback for a simple echo server
- * could look like this:
- * @code
-int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
- return dtls_write(ctx, session, data, len);
-}
- * @endcode
- *
- * @subsection dtls_send_cb The Send Callback
- *
- * The callback function send_to_peer() is called whenever data must be
- * sent over the network. Here, the sendto() system call is used to
- * transmit data within the given session. The socket descriptor required
- * by sendto() has been registered as application data when the DTLS context
- * was created with dtls_new_context().
- * Note that it is on the application to buffer the data when it cannot be
- * sent at the time this callback is invoked. The following example thus
- * is incomplete as it would have to deal with EAGAIN somehow.
- * @code
-int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
- int fd = *(int *)dtls_get_app_data(ctx);
- return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size);
-}
- * @endcode
- *
- * @subsection dtls_get_key The Key Storage
- *
- * When a new DTLS session is created, the library must ask the application
- * for keying material. To do so, it invokes the registered call-back function
- * get_key() with the current context and session information as parameter.
- * When the function is called with the @p id parameter set, the result must
- * point to a dtls_key_t structure for the given identity. When @p id is
- * @c NULL, the function must pick a suitable identity and return a pointer to
- * the corresponding dtls_key_t structure. The following example shows a
- * simple key storage for a pre-shared key for @c Client_identity:
- *
- * @code
-int get_key(struct dtls_context_t *ctx,
- const session_t *session,
- const unsigned char *id, size_t id_len,
- const dtls_key_t **result) {
-
- static const dtls_key_t psk = {
- .type = DTLS_KEY_PSK,
- .key.psk.id = (unsigned char *)"my identity",
- .key.psk.id_length = 11,
- .key.psk.key = (unsigned char *)"secret",
- .key.psk.key_length = 6
- };
-
- *result = &psk;
- return 0;
-}
- * @endcode
- *
- * @subsection dtls_events The Event Notifier
- *
- * Applications that want to be notified whenever the status of a DTLS session
- * has changed can register an event handling function with the field @c event
- * in the dtls_handler_t structure (see \ref dtls_server_example). The call-back
- * function is called for alert messages and internal state changes. For alert
- * messages, the argument @p level will be set to a value greate than zero, and
- * @p code will indicate the notification code. For internal events, @p level
- * is @c 0, and @p code a value greater than @c 255.
- *
- * Currently, the only defined internal event is @c DTLS_EVENT_CONNECTED. It
- * indicates successful establishment of a new DTLS channel.
- *
- * @code
-int handle_event(struct dtls_context_t *ctx, session_t *session,
- dtls_alert_level_t level, unsigned short code) {
- ... do something with event ...
- return 0;
-}
- * @endcode
- *
- * @section dtls_client_example DTLS Client Example
- *
- * A DTLS client is constructed like a server but needs to actively setup
- * a new session by calling dtls_connect() at some point. As this function
- * usually returns before the new DTLS channel is established, the application
- * must register an event handler and wait for @c DTLS_EVENT_CONNECT before
- * it can send data over the DTLS channel.
- *
- */
-
-/**
- * @addtogroup contiki Contiki
- *
- * To use tinyDTLS as Contiki application, place the source code in the directory
- * @c apps/tinydtls in the Contiki source tree and invoke configure with the option
- * @c --with-contiki. This will create the tinydtls Makefile and config.h from the
- * templates @c Makefile.contiki and @c config.h.contiki instead of the usual
- * templates ending in @c .in.
- *
- * Then, create a Contiki project with @c APPS += tinydtls in its Makefile. A sample
- * server could look like this (with read_from_peer() and get_key() as shown above).
- *
- * @code
-#include "contiki.h"
-
-#include "config.h"
-#include "dtls.h"
-
-#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
-
-int send_to_peer(struct dtls_context_t *, session_t *, uint8 *, size_t);
-
-static struct uip_udp_conn *server_conn;
-static dtls_context_t *dtls_context;
-
-static dtls_handler_t cb = {
- .write = send_to_peer,
- .read = read_from_peer,
- .event = NULL,
- .get_key = get_key
-};
-
-PROCESS(server_process, "DTLS server process");
-AUTOSTART_PROCESSES(&server_process);
-
-PROCESS_THREAD(server_process, ev, data)
-{
- PROCESS_BEGIN();
-
- dtls_init();
-
- server_conn = udp_new(NULL, 0, NULL);
- udp_bind(server_conn, UIP_HTONS(5684));
-
- dtls_context = dtls_new_context(server_conn);
- if (!dtls_context) {
- dsrv_log(LOG_EMERG, "cannot create context\n");
- PROCESS_EXIT();
- }
-
- dtls_set_handler(dtls_context, &cb);
-
- while(1) {
- PROCESS_WAIT_EVENT();
- if(ev == tcpip_event && uip_newdata()) {
- session_t session;
-
- uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
- session.port = UIP_UDP_BUF->srcport;
- session.size = sizeof(session.addr) + sizeof(session.port);
-
- dtls_handle_message(ctx, &session, uip_appdata, uip_datalen());
- }
- }
-
- PROCESS_END();
-}
-
-int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
- struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
-
- uip_ipaddr_copy(&conn->ripaddr, &session->addr);
- conn->rport = session->port;
-
- uip_udp_packet_send(conn, data, len);
-
- memset(&conn->ripaddr, 0, sizeof(server_conn->ripaddr));
- memset(&conn->rport, 0, sizeof(conn->rport));
-
- return len;
-}
- * @endcode
- */
--- a/tinydtls/dtls_time.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file dtls_time.c
- * @brief Clock Handling
- */
-
-#include "dtls_time.h"
-#include "bsd_socket.h"
-
-#ifdef MBED
-/**
- * gettimeofday() not in mbed
- */
-void gettimeofday(struct timeval* t, void* timezone)
-{
- t->tv_sec = time(NULL);
- t->tv_usec = 0; /* 1sec precision only */
-
-}
-
-#endif
-
-#ifdef WITH_CONTIKI
-clock_time_t dtls_clock_offset;
-
-void
-dtls_clock_init(void) {
- clock_init();
- dtls_clock_offset = clock_time();
-}
-
-void
-dtls_ticks(dtls_tick_t *t) {
- *t = clock_time();
-}
-
-#else /* WITH_CONTIKI */
-
-time_t dtls_clock_offset;
-
-void
-dtls_clock_init(void) {
-#ifdef HAVE_TIME_H
- dtls_clock_offset = time(NULL);
-#else
-# ifdef __GNUC__
- /* Issue a warning when using gcc. Other prepropressors do
- * not seem to have a similar feature. */
-# warning "cannot initialize clock"
-# endif
- dtls_clock_offset = 0;
-#endif
-}
-
-void dtls_ticks(dtls_tick_t *t) {
-#ifdef HAVE_SYS_TIME_H
- struct timeval tv;
- gettimeofday(&tv, NULL);
- *t = (tv.tv_sec - dtls_clock_offset) * DTLS_TICKS_PER_SECOND
- + (tv.tv_usec * DTLS_TICKS_PER_SECOND / 1000000);
-#else
-#error "clock not implemented"
-#endif
-}
-
-#endif /* WITH_CONTIKI */
-
-
--- a/tinydtls/dtls_time.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file dtls_time.h
- * @brief Clock Handling
- */
-
-#ifndef _DTLS_TIME_H_
-#define _DTLS_TIME_H_
-
-#include "config.h"
-
-#ifdef HAVE_SYS_TIME_H
-#ifndef MBED
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif /* HAVE_SYS_TIME_H */
-
-/**
- * @defgroup clock Clock Handling
- * Default implementation of internal clock. You should redefine this if
- * you do not have time() and gettimeofday().
- * @{
- */
-
-#ifdef WITH_CONTIKI
-#include "clock.h"
-
-typedef clock_time_t dtls_tick_t;
-#else /* WITH_CONTIKI */
-
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#ifndef CLOCK_SECOND
-# define CLOCK_SECOND 1000
-#endif
-
-typedef unsigned int dtls_tick_t;
-
-#endif /* WITH_CONTIKI */
-
-#ifndef DTLS_TICKS_PER_SECOND
-#define DTLS_TICKS_PER_SECOND CLOCK_SECOND
-#endif /* DTLS_TICKS_PER_SECOND */
-
-void dtls_clock_init(void);
-void dtls_ticks(dtls_tick_t *t);
-
-/** @} */
-
-#endif /* _DTLS_TIME_H_ */
--- a/tinydtls/global.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _GLOBAL_H_
-#define _GLOBAL_H_
-
-#include "config.h"
-
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#else
-#ifndef assert
-#warning "assertions are disabled"
-# define assert(x)
-#endif
-#endif
-
-#include <string.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef MBED
-//#include "lwip/inet.h"
-#include "lwip/sockets.h"
-#include "lwip/netdb.h"
-#endif
-
-#ifndef DTLSv12
-/* The current version of tinyDTLS supports DTLSv1.2 only. */
-#define DTLSv12 1
-#endif
-
-#ifndef WITH_SHA256
-/* The current version of tinyDTLS supports DTLSv1.2 with SHA256 PRF
- only. */
-#define WITH_SHA256 1
-#endif
-
-#ifndef WITH_CONTIKI
-typedef unsigned int clock_time_t;
-#else /* WITH_CONTIKI */
-#include "uip.h"
-typedef struct {
- unsigned char size;
- uip_ipaddr_t addr;
- unsigned short port;
- int ifindex;
-} __uip_session_t;
-#define session_t __uip_session_t
-
-#define _dtls_address_equals_impl(A,B) \
- ((A)->size == (B)->size \
- && (A)->port == (B)->port \
- && uip_ipaddr_cmp(&((A)->addr),&((B)->addr)) \
- && (A)->ifindex == (B)->ifindex)
-
-#endif /* WITH_CONTIKI */
-
-/** multi-purpose address abstraction */
-#ifndef session_t
-typedef struct __session_t {
- socklen_t size; /**< size of addr */
- union {
- struct sockaddr sa;
- //struct sockaddr_storage st;
- struct sockaddr_in sin;
- //struct sockaddr_in6 sin6;
- } addr;
- int ifindex;
-} __session_t;
-
-#define session_t __session_t
-
-
-
-static inline int
-_dtls_address_equals_impl(const session_t *a,
- const session_t *b) {
- if (a->ifindex != b->ifindex ||
- a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
- return 0;
-
- /* need to compare only relevant parts of sockaddr_in6 */
- switch (a->addr.sa.sa_family) {
- case AF_INET:
- return
- a->addr.sin.sin_port == b->addr.sin.sin_port &&
- memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
- sizeof(struct in_addr)) == 0;
- /*
- case AF_INET6:
- return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
- memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
- sizeof(struct in6_addr)) == 0;
- */
- default: /* fall through and signal error */
- ;
- }
- return 0;
-}
-#endif /* session_t */
-
-/* Define our own types as at least uint32_t does not work on my amd64. */
-
-typedef unsigned char uint8;
-typedef unsigned char uint16[2];
-typedef unsigned char uint24[3];
-typedef unsigned char uint32[4];
-typedef unsigned char uint48[6];
-
-#ifndef HAVE_STR
-typedef struct {
- size_t length; /* length of string */
- unsigned char *s; /* string data */
-} str;
-#endif
-
-#ifndef DTLS_MAX_BUF
-/** Maximum size of DTLS message. */
-#define DTLS_MAX_BUF 256
-#endif
-
-#ifndef DTLS_DEFAULT_MAX_RETRANSMIT
-/** Number of message retransmissions. */
-#define DTLS_DEFAULT_MAX_RETRANSMIT 5
-#endif
-
-/** Known cipher suites.*/
-typedef enum {
- TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */
- TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8 /**< see RFC 6655 */
-} dtls_cipher_t;
-
-/**
- * XORs \p n bytes byte-by-byte starting at \p y to the memory area
- * starting at \p x. */
-static inline void
-memxor(unsigned char *x, const unsigned char *y, size_t n) {
- while(n--) {
- *x ^= *y;
- x++; y++;
- }
-}
-
-#ifdef HAVE_FLS
-#define dtls_fls(i) fls(i)
-#else
-static inline int
-dtls_fls(unsigned int i) {
- int n;
- for (n = 0; i; n++)
- i >>= 1;
- return n;
-}
-#endif /* HAVE_FLS */
-
-/**
- * Resets the given session_t object @p sess to its default
- * values. In particular, the member rlen must be initialized to the
- * available size for storing addresses.
- *
- * @param sess The session_t object to initialize.
- */
-static inline void
-dtls_session_init(session_t *sess) {
- assert(sess);
- memset(sess, 0, sizeof(session_t));
- sess->size = sizeof(sess->addr);
-}
-
-static inline int
-dtls_session_equals(const session_t *a, const session_t *b) {
- assert(a); assert(b);
- return _dtls_address_equals_impl(a, b);
-}
-#endif /* _GLOBAL_H_ */
--- a/tinydtls/hmac.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#endif
-
-#include "debug.h"
-#include "hmac.h"
-/* use malloc()/free() on platforms other than Contiki */
-#ifndef WITH_CONTIKI
-#include <stdlib.h>
-
-static inline dtls_hmac_context_t *
-dtls_hmac_context_new() {
- return (dtls_hmac_context_t *)malloc(sizeof(dtls_hmac_context_t));
-}
-
-static inline void
-dtls_hmac_context_free(dtls_hmac_context_t *ctx) {
- free(ctx);
-}
-
-#else /* WITH_CONTIKI */
-#include "memb.h"
-MEMB(hmac_context_storage, dtls_hmac_context_t, DTLS_HASH_MAX);
-
-static inline dtls_hmac_context_t *
-dtls_hmac_context_new() {
- return (dtls_hmac_context_t *)memb_alloc(&hmac_context_storage);
-}
-
-static inline void
-dtls_hmac_context_free(dtls_hmac_context_t *ctx) {
- memb_free(&hmac_context_storage, ctx);
-}
-#endif /* WITH_CONTIKI */
-
-void
-dtls_hmac_storage_init() {
-#ifdef WITH_CONTIKI
- memb_init(&hmac_context_storage);
-#endif /* WITH_CONTIKI */
-}
-
-void
-dtls_hmac_update(dtls_hmac_context_t *ctx,
- const unsigned char *input, size_t ilen) {
- assert(ctx);
- dtls_hash_update(&ctx->data, input, ilen);
-}
-
-dtls_hmac_context_t *
-dtls_hmac_new(const unsigned char *key, size_t klen) {
- dtls_hmac_context_t *ctx;
-
- ctx = dtls_hmac_context_new();
- if (ctx)
- dtls_hmac_init(ctx, key, klen);
-
- return ctx;
-}
-
-void
-dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen) {
- int i;
-
- assert(ctx);
-
- memset(ctx, 0, sizeof(dtls_hmac_context_t));
-
- if (klen > DTLS_HMAC_BLOCKSIZE) {
- dtls_hash_init(&ctx->data);
- dtls_hash_update(&ctx->data, key, klen);
- dtls_hash_finalize(ctx->pad, &ctx->data);
- } else
- memcpy(ctx->pad, key, klen);
-
- /* create ipad: */
- for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i)
- ctx->pad[i] ^= 0x36;
-
- dtls_hash_init(&ctx->data);
- dtls_hmac_update(ctx, ctx->pad, DTLS_HMAC_BLOCKSIZE);
-
- /* create opad by xor-ing pad[i] with 0x36 ^ 0x5C: */
- for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i)
- ctx->pad[i] ^= 0x6A;
-}
-
-void
-dtls_hmac_free(dtls_hmac_context_t *ctx) {
- if (ctx)
- dtls_hmac_context_free(ctx);
-}
-
-int
-dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result) {
- unsigned char buf[DTLS_HMAC_DIGEST_SIZE];
- size_t len;
-
- assert(ctx);
- assert(result);
-
- len = dtls_hash_finalize(buf, &ctx->data);
-
- dtls_hash_init(&ctx->data);
- dtls_hash_update(&ctx->data, ctx->pad, DTLS_HMAC_BLOCKSIZE);
- dtls_hash_update(&ctx->data, buf, len);
-
- len = dtls_hash_finalize(result, &ctx->data);
-
- return len;
-}
-
-#ifdef HMAC_TEST
-#include <stdio.h>
-
-int main(int argc, char **argv) {
- static unsigned char buf[DTLS_HMAC_DIGEST_SIZE];
- size_t len, i;
- dtls_hmac_context_t *ctx;
-
- if (argc < 3) {
- fprintf(stderr, "usage: %s key text", argv[0]);
- return -1;
- }
-
- dtls_hmac_storage_init();
- ctx = dtls_hmac_new(argv[1], strlen(argv[1]));
- assert(ctx);
- dtls_hmac_update(ctx, argv[2], strlen(argv[2]));
-
- len = dtls_hmac_finalize(ctx, buf);
-
- for(i = 0; i < len; i++)
- printf("%02x", buf[i]);
- printf("\n");
-
- dtls_hmac_free(ctx);
-
- return 0;
-}
-#endif
--- a/tinydtls/hmac.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _HMAC_H_
-#define _HMAC_H_
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "global.h"
-
-#ifdef WITH_SHA256
-/** Aaron D. Gifford's implementation of SHA256
- * see http://www.aarongifford.com/ */
-#include "sha2/sha2.h"
-
-typedef SHA256_CTX dtls_hash_ctx;
-typedef dtls_hash_ctx *dtls_hash_t;
-#define DTLS_HASH_CTX_SIZE sizeof(SHA256_CTX)
-
-static inline void
-dtls_hash_init(dtls_hash_t ctx) {
- SHA256_Init((SHA256_CTX *)ctx);
-}
-
-static inline void
-dtls_hash_update(dtls_hash_t ctx, const unsigned char *input, size_t len) {
- SHA256_Update((SHA256_CTX *)ctx, input, len);
-}
-
-static inline size_t
-dtls_hash_finalize(unsigned char *buf, dtls_hash_t ctx) {
- SHA256_Final(buf, (SHA256_CTX *)ctx);
- return SHA256_DIGEST_LENGTH;
-}
-#endif /* WITH_SHA256 */
-
-/**
- * \defgroup HMAC Keyed-Hash Message Authentication Code (HMAC)
- * NIST Standard FIPS 198 describes the Keyed-Hash Message Authentication
- * Code (HMAC) which is used as hash function for the DTLS PRF.
- * @{
- */
-
-#define DTLS_HMAC_BLOCKSIZE 64 /**< size of hmac blocks */
-#define DTLS_HMAC_DIGEST_SIZE 32 /**< digest size (for SHA-256) */
-#define DTLS_HMAC_MAX 64 /**< max number of bytes in digest */
-
-/**
- * List of known hash functions for use in dtls_hmac_init(). The
- * identifiers are the same as the HashAlgorithm defined in
- * <a href="http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1"
- * >Section 7.4.1.4.1 of RFC 5246</a>.
- */
-typedef enum {
- HASH_NONE=0, HASH_MD5=1, HASH_SHA1=2, HASH_SHA224=3,
- HASH_SHA256=4, HASH_SHA384=5, HASH_SHA512=6
-} dtls_hashfunc_t;
-
-/**
- * Context for HMAC generation. This object is initialized with
- * dtls_hmac_init() and must be passed to dtls_hmac_update() and
- * dtls_hmac_finalize(). Once, finalized, the component \c H is
- * invalid and must be initialized again with dtls_hmac_init() before
- * the structure can be used again.
- */
-typedef struct {
- unsigned char pad[DTLS_HMAC_BLOCKSIZE]; /**< ipad and opad storage */
- dtls_hash_ctx data; /**< context for hash function */
-} dtls_hmac_context_t;
-
-/**
- * Initializes an existing HMAC context.
- *
- * @param ctx The HMAC context to initialize.
- * @param key The secret key.
- * @param klen The length of @p key.
- */
-void dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen);
-
-/**
- * Allocates a new HMAC context \p ctx with the given secret key.
- * This function returns \c 1 if \c ctx has been set correctly, or \c
- * 0 or \c -1 otherwise. Note that this function allocates new storage
- * that must be released by dtls_hmac_free().
- *
- * \param key The secret key.
- * \param klen The length of \p key.
- * \return A new dtls_hmac_context_t object or @c NULL on error
- */
-dtls_hmac_context_t *dtls_hmac_new(const unsigned char *key, size_t klen);
-
-/**
- * Releases the storage for @p ctx that has been allocated by
- * dtls_hmac_new().
- *
- * @param ctx The dtls_hmac_context_t to free.
- */
-void dtls_hmac_free(dtls_hmac_context_t *ctx);
-
-/**
- * Updates the HMAC context with data from \p input.
- *
- * \param ctx The HMAC context.
- * \param input The input data.
- * \param ilen Size of \p input.
- */
-void dtls_hmac_update(dtls_hmac_context_t *ctx,
- const unsigned char *input, size_t ilen);
-
-/**
- * Completes the HMAC generation and writes the result to the given
- * output parameter \c result. The buffer must be large enough to hold
- * the message digest created by the actual hash function. If in
- * doubt, use \c DTLS_HMAC_MAX. The function returns the number of
- * bytes written to \c result.
- *
- * \param ctx The HMAC context.
- * \param result Output parameter where the MAC is written to.
- * \return Length of the MAC written to \p result.
- */
-int dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result);
-
-/**@}*/
-
-#endif /* _HMAC_H_ */
--- a/tinydtls/netq.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/* netq.h -- Simple packet queue
- *
- * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * This file is part of the library tinyDTLS. Please see the file
- * LICENSE for terms of use.
- */
-
-//#include "netinet/in.h"
-#include "debug.h"
-#include "netq.h"
-
-
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#else
-#ifndef assert
-#warning "assertions are disabled"
-# define assert(x)
-#endif
-#endif
-
-#include "t_list.h"
-
-#ifndef WITH_CONTIKI
-#include <stdlib.h>
-
-static inline netq_t *
-netq_malloc_node() {
- return (netq_t *)malloc(sizeof(netq_t));
-}
-
-static inline void
-netq_free_node(netq_t *node) {
- free(node);
-}
-
-/* FIXME: implement Contiki's list functions using utlist.h */
-
-#else /* WITH_CONTIKI */
-#include "memb.h"
-
-MEMB(netq_storage, netq_t, NETQ_MAXCNT);
-
-static inline netq_t *
-netq_malloc_node() {
- return (netq_t *)memb_alloc(&netq_storage);
-}
-
-static inline void
-netq_free_node(netq_t *node) {
- memb_free(&netq_storage, node);
-}
-#endif /* WITH_CONTIKI */
-
-void
-netq_init() {
-#ifdef WITH_CONTIKI
- memb_init(&netq_storage);
-#endif /* WITH_CONTIKI */
-}
-
-int
-netq_insert_node(netq_t **queue, netq_t *node) {
- netq_t *p;
-
- assert(queue);
- assert(node);
-
- p = (netq_t *)list_head((list_t)queue);
- while(p && p->t <= node->t)
- p = list_item_next(p);
-
- if (p)
- list_insert((list_t)queue, p, node);
- else
- list_push((list_t)queue, node);
-
- return 1;
-}
-
-netq_t *
-netq_head(netq_t **queue) {
- if (!queue)
- return NULL;
-
- return list_head((list_t)queue);
-}
-
-netq_t *netq_pop_first(netq_t **queue) {
- if (!queue)
- return NULL;
-
- return list_pop((list_t)queue);
-}
-
-netq_t *
-netq_node_new() {
- netq_t *node;
- node = netq_malloc_node();
-
-#ifndef NDEBUG
- if (!node)
- dsrv_log(LOG_WARN, "netq_node_new: malloc\n");
-#endif
-
- if (node)
- memset(node, 0, sizeof(netq_t));
-
- return node;
-}
-
-void
-netq_node_free(netq_t *node) {
- if (node)
- netq_free_node(node);
-}
-
-void
-netq_delete_all(netq_t *queue) {
- netq_t *p;
- if (queue) {
- while((p = list_pop((list_t)&queue)))
- netq_free_node(p);
- }
-}
-
--- a/tinydtls/netq.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* netq.h -- Simple packet queue
- *
- * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * This file is part of the library tinyDTLS. Please see the file
- * LICENSE for terms of use.
- */
-
-#ifndef _NETQ_H_
-#define _NETQ_H_
-
-#include "config.h"
-#include "global.h"
-//#include "dtls.h"
-#include "time.h"
-#include "peer.h"
-
-/**
- * \defgroup netq Network Packet Queue
- * The netq utility functions implement an ordered queue of data packets
- * to send over the network and can also be used to queue received packets
- * from the network.
- * @{
- */
-
-#ifndef NETQ_MAXCNT
-#define NETQ_MAXCNT 4 /**< maximum number of elements in netq structure */
-#endif
-
-/**
- * Datagrams in the netq_t structure have a fixed maximum size of
- * DTLS_MAX_BUF to simplify memory management on constrained nodes. */
-typedef unsigned char netq_packet_t[DTLS_MAX_BUF];
-
-typedef struct netq_t {
- struct netq_t *next;
-
- clock_time_t t; /**< when to send PDU for the next time */
- unsigned char retransmit_cnt; /**< retransmission counter, will be removed when zero */
- unsigned int timeout; /**< randomized timeout value */
-
- dtls_peer_t *peer; /**< remote address */
-
- size_t length; /**< actual length of data */
- netq_packet_t data; /**< the datagram to send */
-} netq_t;
-
-/**
- * Adds a node to the given queue, ordered by their time-stamp t.
- * This function returns @c 0 on error, or non-zero if @p node has
- * been added successfully.
- *
- * @param queue A pointer to the queue head where @p node will be added.
- * @param node The new item to add.
- * @return @c 0 on error, or non-zero if the new item was added.
- */
-int netq_insert_node(netq_t **queue, netq_t *node);
-
-/** Destroys specified node and releases any memory that was allocated
- * for the associated datagram. */
-void netq_node_free(netq_t *node);
-
-/** Removes all items from given queue and frees the allocated storage */
-void netq_delete_all(netq_t *queue);
-
-/** Creates a new node suitable for adding to a netq_t queue. */
-netq_t *netq_node_new();
-
-/**
- * Returns a pointer to the first item in given queue or NULL if
- * empty.
- */
-netq_t *netq_head(netq_t **queue);
-
-/**
- * Removes the first item in given queue and returns a pointer to the
- * removed element. If queue is empty when netq_pop_first() is called,
- * this function returns NULL.
- */
-netq_t *netq_pop_first(netq_t **queue);
-
-/**@}*/
-
-#endif /* _NETQ_H_ */
--- a/tinydtls/numeric.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _NUMERIC_H_
-#define _NUMERIC_H_
-
-#include <stdint.h>
-
-#ifndef min
-#define min(A,B) ((A) <= (B) ? (A) : (B))
-#endif
-
-#ifndef max
-#define max(A,B) ((A) < (B) ? (B) : (A))
-#endif
-
-/**
- * Increments given \p Var of type \p Type by \c 1.
- *
- * \hideinitializer
- */
-#define inc_uint(Type,Var) { \
- int i = sizeof(Type); \
- while (i && !++((Var)[--i])); \
- }
-
-/* this one is for consistency... */
-#define dtls_int_to_uint8(Field,Value) do { \
- *(unsigned char*)(Field) = (Value) & 0xff; \
- } while(0)
-
-#define dtls_int_to_uint16(Field,Value) do { \
- *(unsigned char*)(Field) = ((Value) >> 8) & 0xff; \
- *(((unsigned char*)(Field))+1) = ((Value) & 0xff); \
- } while(0)
-
-#define dtls_int_to_uint24(Field,Value) do { \
- *(unsigned char*)(Field) = ((Value) >> 16) & 0xff; \
- dtls_int_to_uint16((((unsigned char*)(Field))+1),Value); \
- } while(0)
-
-#define dtls_int_to_uint32(Field,Value) do { \
- *(unsigned char*)(Field) = ((Value) >> 24) & 0xff; \
- *(((unsigned char*)(Field))+1) = ((Value) >> 16) & 0xff; \
- *(((unsigned char*)(Field))+2) = ((Value) >> 8) & 0xff; \
- *(((unsigned char*)(Field))+3) = (Value) & 0xff; \
- } while(0)
-
-#define dtls_ulong_to_uint48(Field,Value) do { \
- *(unsigned char*)(Field) = ((Value) >> 40) & 0xff; \
- *(((unsigned char*)(Field))+1) = ((Value) >> 32) & 0xff; \
- *(((unsigned char*)(Field))+2) = ((Value) >> 24) & 0xff; \
- *(((unsigned char*)(Field))+3) = ((Value) >> 16) & 0xff; \
- *(((unsigned char*)(Field))+4) = ((Value) >> 8) & 0xff; \
- *(((unsigned char*)(Field))+5) = (Value) & 0xff; \
- } while(0)
-
-#define dtls_ulong_to_uint64(Field,Value) do { \
- *(unsigned char*)(Field) = ((Value) >> 56) & 0xff; \
- *(((unsigned char*)(Field))+1) = ((Value) >> 48) & 0xff; \
- *(((unsigned char*)(Field))+2) = ((Value) >> 40) & 0xff; \
- *(((unsigned char*)(Field))+3) = ((Value) >> 32) & 0xff; \
- *(((unsigned char*)(Field))+4) = ((Value) >> 24) & 0xff; \
- *(((unsigned char*)(Field))+5) = ((Value) >> 16) & 0xff; \
- *(((unsigned char*)(Field))+6) = ((Value) >> 8) & 0xff; \
- *(((unsigned char*)(Field))+7) = (Value) & 0xff; \
- } while(0)
-
-#define dtls_uint8_to_int(Field) \
- (*(unsigned char*)(Field) & 0xFF)
-
-#define dtls_uint16_to_int(Field) \
- (((*(unsigned char*)(Field)) << 8) | (*(((unsigned char*)(Field))+1)))
-
-#define dtls_uint24_to_int(Field) \
- (((*(((unsigned char*)(Field)))) << 16) \
- | ((*(((unsigned char*)(Field))+1)) << 8) \
- | ((*(((unsigned char*)(Field))+2))))
-
-#define dtls_uint48_to_ulong(Field) \
- (((uint64_t) *(unsigned char*)(Field)) << 40) \
- | (((uint64_t) *(((unsigned char*)(Field))+1)) << 32) \
- | (((uint64_t) *(((unsigned char*)(Field))+2)) << 24) \
- | (((uint64_t) *(((unsigned char*)(Field))+3)) << 16) \
- | (((uint64_t) *(((unsigned char*)(Field))+4)) << 8) \
- | (((uint64_t) *(((unsigned char*)(n))+5)))
-
-#endif /* _NUMERIC_H_ */
--- a/tinydtls/peer.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "peer.h"
-#include "debug.h"
-
-#ifndef NDEBUG
-#include <stdio.h>
-
-extern size_t dsrv_print_addr(const session_t *addr, unsigned char *buf,
- size_t len);
-#endif /* NDEBUG */
-
-#ifndef WITH_CONTIKI
-void peer_init()
-{
-}
-
-static inline dtls_peer_t *
-dtls_malloc_peer() {
- return (dtls_peer_t *)malloc(sizeof(dtls_peer_t));
-}
-
-void
-dtls_free_peer(dtls_peer_t *peer) {
- free(peer);
-}
-#else /* WITH_CONTIKI */
-PROCESS(dtls_retransmit_process, "DTLS retransmit process");
-
-#include "memb.h"
-MEMB(peer_storage, dtls_peer_t, DTLS_PEER_MAX);
-
-void
-peer_init() {
- memb_init(&peer_storage);
-}
-
-static inline dtls_peer_t *
-dtls_malloc_peer() {
- return memb_alloc(&peer_storage);
-}
-
-void
-dtls_free_peer(dtls_peer_t *peer) {
- memb_free(&peer_storage, peer);
-}
-#endif /* WITH_CONTIKI */
-
-dtls_peer_t *
-dtls_new_peer(const session_t *session) {
- dtls_peer_t *peer;
-
- peer = dtls_malloc_peer();
- if (peer) {
- memset(peer, 0, sizeof(dtls_peer_t));
- memcpy(&peer->session, session, sizeof(session_t));
-
-#ifndef NDEBUG
- if (dtls_get_log_level() >= LOG_DEBUG) {
- unsigned char addrbuf[72];
- dsrv_print_addr(session, addrbuf, sizeof(addrbuf));
- printf("dtls_new_peer: %s\n", addrbuf);
- }
-#endif
- /* initially allow the NULL cipher */
- CURRENT_CONFIG(peer)->cipher = TLS_NULL_WITH_NULL_NULL;
-
- /* initialize the handshake hash wrt. the hard-coded DTLS version */
- debug("DTLSv12: initialize HASH_SHA256\n");
- /* TLS 1.2: PRF(secret, label, seed) = P_<hash>(secret, label + seed) */
- /* FIXME: we use the default SHA256 here, might need to support other
- hash functions as well */
- dtls_hash_init(&peer->hs_state.hs_hash);
- }
-
- return peer;
-}
-
--- a/tinydtls/peer.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file peer.h
- * @brief information about peers in a DTLS session
- */
-
-#ifndef _PEER_H_
-#define _PEER_H_
-
-#include "config.h"
-#include "global.h"
-
-#include "state.h"
-#include "crypto.h"
-
-#ifndef WITH_CONTIKI
-#include "uthash.h"
-#endif /* WITH_CONTIKI */
-
-/**
- * Holds security parameters, local state and the transport address
- * for each peer. */
-typedef struct dtls_peer_t {
-#ifndef WITH_CONTIKI
- UT_hash_handle hh;
-#else /* WITH_CONTIKI */
- struct dtls_peer_t *next;
-#endif /* WITH_CONTIKI */
-
- session_t session; /**< peer address and local interface */
-
- dtls_state_t state; /**< DTLS engine state */
- uint16 epoch; /**< counter for cipher state changes*/
- uint48 rseq; /**< sequence number of last record sent */
-
- dtls_hs_state_t hs_state; /**< handshake protocol status */
-
- dtls_security_parameters_t security_params[2];
- int config; /**< denotes which security params are in effect */
- /* FIXME: check if we can use epoch for this */
-} dtls_peer_t;
-
-/**
- * Creates a new peer for given @p session. The current configuration
- * is initialized with the cipher suite TLS_NULL_WITH_NULL_NULL (i.e.
- * no security at all). This function returns a pointer to the new
- * peer or NULL on error. The caller is responsible for releasing the
- * storage allocated for this peer using dtls_free_peer().
- *
- * @param session The remote peer's address and local interface index.
- * @return A pointer to a newly created and initialized peer object
- * or NULL on error.
- */
-dtls_peer_t *dtls_new_peer(const session_t *session);
-
-/** Releases the storage allocated to @p peer. */
-void dtls_free_peer(dtls_peer_t *peer);
-
-/** Returns the current state of @p peer. */
-static inline dtls_state_t dtls_peer_state(const dtls_peer_t *peer) {
- return peer->state;
-}
-
-/**
- * Checks if given @p peer is connected. This function returns
- * @c 1 if connected, or @c 0 otherwise.
- */
-static inline int dtls_peer_is_connected(const dtls_peer_t *peer) {
- return peer->state == DTLS_STATE_CONNECTED;
-}
-
-#define CURRENT_CONFIG(Peer) (&(Peer)->security_params[(Peer)->config])
-#define OTHER_CONFIG(Peer) (&(Peer)->security_params[!((Peer)->config & 0x01)])
-
-#define SWITCH_CONFIG(Peer) ((Peer)->config = !((Peer)->config & 0x01))
-
-#endif /* _PEER_H_ */
--- a/tinydtls/prng.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/* prng.h -- Pseudo Random Numbers
- *
- * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * This file is part of the library tinydtls. Please see
- * README for terms of use.
- */
-
-/**
- * @file prng.h
- * @brief Pseudo Random Numbers
- */
-
-#ifndef _DTLS_PRNG_H_
-#define _DTLS_PRNG_H_
-
-#include "config.h"
-
-/**
- * @defgroup prng Pseudo Random Numbers
- * @{
- */
-
-#ifndef WITH_CONTIKI
-#include <stdlib.h>
-
-/**
- * Fills \p buf with \p len random bytes. This is the default
- * implementation for prng(). You might want to change prng() to use
- * a better PRNG on your specific platform.
- */
-static inline int
-dtls_prng_impl(unsigned char *buf, size_t len) {
- while (len--)
- *buf++ = rand() & 0xFF;
- return 1;
-}
-#else /* WITH_CONTIKI */
-#include <string.h>
-
-#ifdef HAVE_PRNG
-extern int contiki_prng_impl(unsigned char *buf, size_t len);
-#else
-/**
- * Fills \p buf with \p len random bytes. This is the default
- * implementation for prng(). You might want to change prng() to use
- * a better PRNG on your specific platform.
- */
-static inline int
-contiki_prng_impl(unsigned char *buf, size_t len) {
- unsigned short v = random_rand();
- while (len > sizeof(v)) {
- memcpy(buf, &v, sizeof(v));
- len -= sizeof(v);
- buf += sizeof(v);
- v = random_rand();
- }
-
- memcpy(buf, &v, len);
- return 1;
-}
-#endif /* HAVE_PRNG */
-
-#define prng(Buf,Length) contiki_prng_impl((Buf), (Length))
-#define prng_init(Value) random_init((unsigned short)(Value))
-#endif /* WITH_CONTIKI */
-
-#ifndef prng
-/**
- * Fills \p Buf with \p Length bytes of random data.
- *
- * @hideinitializer
- */
-#define prng(Buf,Length) dtls_prng_impl((Buf), (Length))
-#endif
-
-#ifndef prng_init
-/**
- * Called to set the PRNG seed. You may want to re-define this to
- * allow for a better PRNG.
- *
- * @hideinitializer
- */
-#define prng_init(Value) srand((unsigned long)(Value))
-#endif
-
-/** @} */
-
-#endif /* _DTLS_PRNG_H_ */
--- a/tinydtls/sha2/sha2.c Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1095 +0,0 @@
-/*
- * FILE: sha2.c
- * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
- *
- * Copyright (c) 2000-2001, Aaron D. Gifford
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
- */
-
-#include "../config.h"
-#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
-#ifdef HAVE_ASSERT_H
-#include <assert.h> /* assert() */
-#endif
-#include "sha2.h"
-
-/*
- * ASSERT NOTE:
- * Some sanity checking code is included using assert(). On my FreeBSD
- * system, this additional code can be removed by compiling with NDEBUG
- * defined. Check your own systems manpage on assert() to see how to
- * compile WITHOUT the sanity checking code on your system.
- *
- * UNROLLED TRANSFORM LOOP NOTE:
- * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
- * loop version for the hash transform rounds (defined using macros
- * later in this file). Either define on the command line, for example:
- *
- * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
- *
- * or define below:
- *
- * #define SHA2_UNROLL_TRANSFORM
- *
- */
-
-
-/*** SHA-256/384/512 Machine Architecture Definitions *****************/
-/*
- * BYTE_ORDER NOTE:
- *
- * Please make sure that your system defines BYTE_ORDER. If your
- * architecture is little-endian, make sure it also defines
- * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivilent.
- *
- * If your system does not define the above, then you can do so by
- * hand like this:
- *
- * #define LITTLE_ENDIAN 1234
- * #define BIG_ENDIAN 4321
- *
- * And for little-endian machines, add:
- *
- * #define BYTE_ORDER LITTLE_ENDIAN
- *
- * Or for big-endian machines:
- *
- * #define BYTE_ORDER BIG_ENDIAN
- *
- * The FreeBSD machine this was written on defines BYTE_ORDER
- * appropriately by including <sys/types.h> (which in turn includes
- * <machine/endian.h> where the appropriate definitions are actually
- * made).
- */
-
-/* bergmann: define LITTLE_ENDIAN and BIG_ENDIAN to ease autoconf: */
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-# ifdef WORDS_BIGENDIAN
-# define BYTE_ORDER BIG_ENDIAN
-# else /* WORDS_BIGENDIAN */
-# define BYTE_ORDER LITTLE_ENDIAN
-# endif
-#endif
-
-#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
-#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
-#endif
-
-/*
- * Define the followingsha2_* types to types of the correct length on
- * the native archtecture. Most BSD systems and Linux define u_intXX_t
- * types. Machines with very recent ANSI C headers, can use the
- * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
- * during compile or in the sha.h header file.
- *
- * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
- * will need to define these three typedefs below (and the appropriate
- * ones in sha.h too) by hand according to their system architecture.
- *
- * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
- * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
- */
-#ifdef SHA2_USE_INTTYPES_H
-
-typedef uint8_t sha2_byte; /* Exactly 1 byte */
-typedef uint32_t sha2_word32; /* Exactly 4 bytes */
-typedef uint64_t sha2_word64; /* Exactly 8 bytes */
-
-#else /* SHA2_USE_INTTYPES_H */
-
-typedef u_int8_t sha2_byte; /* Exactly 1 byte */
-typedef u_int32_t sha2_word32; /* Exactly 4 bytes */
-typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-
-/*** SHA-256/384/512 Various Length Definitions ***********************/
-/* NOTE: Most of these are in sha2.h */
-#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
-#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
-#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
-
-
-/*** ENDIAN REVERSAL MACROS *******************************************/
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define REVERSE32(w,x) { \
- sha2_word32 tmp = (w); \
- tmp = (tmp >> 16) | (tmp << 16); \
- (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
-}
-#define REVERSE64(w,x) { \
- sha2_word64 tmp = (w); \
- tmp = (tmp >> 32) | (tmp << 32); \
- tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
- ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
- (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
- ((tmp & 0x0000ffff0000ffffULL) << 16); \
-}
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-/*
- * Macro for incrementally adding the unsigned 64-bit integer n to the
- * unsigned 128-bit integer (represented using a two-element array of
- * 64-bit words):
- */
-#define ADDINC128(w,n) { \
- (w)[0] += (sha2_word64)(n); \
- if ((w)[0] < (n)) { \
- (w)[1]++; \
- } \
-}
-
-/*
- * Macros for copying blocks of memory and for zeroing out ranges
- * of memory. Using these macros makes it easy to switch from
- * using memset()/memcpy() and using bzero()/bcopy().
- *
- * Please define either SHA2_USE_MEMSET_MEMCPY or define
- * SHA2_USE_BZERO_BCOPY depending on which function set you
- * choose to use:
- */
-#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
-/* Default to memset()/memcpy() if no option is specified */
-#define SHA2_USE_MEMSET_MEMCPY 1
-#endif
-#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
-/* Abort with an error if BOTH options are defined */
-#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
-#endif
-
-#ifdef SHA2_USE_MEMSET_MEMCPY
-#define MEMSET_BZERO(p,l) memset((p), 0, (l))
-#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
-#endif
-#ifdef SHA2_USE_BZERO_BCOPY
-#define MEMSET_BZERO(p,l) bzero((p), (l))
-#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
-#endif
-
-
-/*** THE SIX LOGICAL FUNCTIONS ****************************************/
-/*
- * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
- *
- * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
- * S is a ROTATION) because the SHA-256/384/512 description document
- * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
- * same "backwards" definition.
- */
-/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
-#define R(b,x) ((x) >> (b))
-/* 32-bit Rotate-right (used in SHA-256): */
-#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
-/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
-#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
-
-/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
-#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
-#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
-
-/* Four of six logical functions used in SHA-256: */
-#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
-#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
-#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
-#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
-
-/* Four of six logical functions used in SHA-384 and SHA-512: */
-#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
-#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
-#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
-#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
-
-/*** INTERNAL FUNCTION PROTOTYPES *************************************/
-/* NOTE: These should not be accessed directly from outside this
- * library -- they are intended for private internal visibility/use
- * only.
- */
-void SHA512_Last(SHA512_CTX*);
-void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
-void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
-
-#ifdef WITH_SHA256
-/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
-/* Hash constant words K for SHA-256: */
-const static sha2_word32 K256[64] = {
- 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
- 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
- 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
- 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
- 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
- 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
- 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
- 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
- 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
- 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
- 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
- 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
- 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
- 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
- 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
- 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-};
-
-/* Initial hash value H for SHA-256: */
-const static sha2_word32 sha256_initial_hash_value[8] = {
- 0x6a09e667UL,
- 0xbb67ae85UL,
- 0x3c6ef372UL,
- 0xa54ff53aUL,
- 0x510e527fUL,
- 0x9b05688cUL,
- 0x1f83d9abUL,
- 0x5be0cd19UL
-};
-#endif
-
-#if defined(WITH_SHA384) || defined(WITH_SHA512)
-/* Hash constant words K for SHA-384 and SHA-512: */
-const static sha2_word64 K512[80] = {
- 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
- 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
- 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
- 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
- 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
- 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
- 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
- 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
- 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
- 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
- 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
- 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
- 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
- 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
- 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
- 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
- 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
- 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
- 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
- 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
- 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
- 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
- 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
- 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
- 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
- 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
- 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
- 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
- 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
- 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
- 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
- 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
- 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
- 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
- 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
- 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
- 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
- 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
- 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
- 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
-};
-#endif
-
-#ifdef WITH_SHA384
-/* Initial hash value H for SHA-384 */
-const static sha2_word64 sha384_initial_hash_value[8] = {
- 0xcbbb9d5dc1059ed8ULL,
- 0x629a292a367cd507ULL,
- 0x9159015a3070dd17ULL,
- 0x152fecd8f70e5939ULL,
- 0x67332667ffc00b31ULL,
- 0x8eb44a8768581511ULL,
- 0xdb0c2e0d64f98fa7ULL,
- 0x47b5481dbefa4fa4ULL
-};
-#endif
-
-#ifdef WITH_SHA512
-/* Initial hash value H for SHA-512 */
-const static sha2_word64 sha512_initial_hash_value[8] = {
- 0x6a09e667f3bcc908ULL,
- 0xbb67ae8584caa73bULL,
- 0x3c6ef372fe94f82bULL,
- 0xa54ff53a5f1d36f1ULL,
- 0x510e527fade682d1ULL,
- 0x9b05688c2b3e6c1fULL,
- 0x1f83d9abfb41bd6bULL,
- 0x5be0cd19137e2179ULL
-};
-#endif
-
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha2_hex_digits = "0123456789abcdef";
-
-
-/*** SHA-256: *********************************************************/
-#ifdef WITH_SHA256
-void SHA256_Init(SHA256_CTX* context) {
- if (context == (SHA256_CTX*)0) {
- return;
- }
- MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
- MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
- context->bitcount = 0;
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-256 round macros: */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
- REVERSE32(*data++, W256[j]); \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
- K256[j] + W256[j]; \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
- K256[j] + (W256[j] = *data++); \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256(a,b,c,d,e,f,g,h) \
- s0 = W256[(j+1)&0x0f]; \
- s0 = sigma0_256(s0); \
- s1 = W256[(j+14)&0x0f]; \
- s1 = sigma1_256(s1); \
- T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
- (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
- (d) += T1; \
- (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
- j++
-
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
- sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
- sha2_word32 T1, *W256;
- int j;
-
- W256 = (sha2_word32*)context->buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->state[0];
- b = context->state[1];
- c = context->state[2];
- d = context->state[3];
- e = context->state[4];
- f = context->state[5];
- g = context->state[6];
- h = context->state[7];
-
- j = 0;
- do {
- /* Rounds 0 to 15 (unrolled): */
- ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
- ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
- ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
- ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
- ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
- ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
- ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
- ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
- } while (j < 16);
-
- /* Now for the remaining rounds to 64: */
- do {
- ROUND256(a,b,c,d,e,f,g,h);
- ROUND256(h,a,b,c,d,e,f,g);
- ROUND256(g,h,a,b,c,d,e,f);
- ROUND256(f,g,h,a,b,c,d,e);
- ROUND256(e,f,g,h,a,b,c,d);
- ROUND256(d,e,f,g,h,a,b,c);
- ROUND256(c,d,e,f,g,h,a,b);
- ROUND256(b,c,d,e,f,g,h,a);
- } while (j < 64);
-
- /* Compute the current intermediate hash value */
- context->state[0] += a;
- context->state[1] += b;
- context->state[2] += c;
- context->state[3] += d;
- context->state[4] += e;
- context->state[5] += f;
- context->state[6] += g;
- context->state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
- sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
- sha2_word32 T1, T2, *W256;
- int j;
-
- W256 = (sha2_word32*)context->buffer;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->state[0];
- b = context->state[1];
- c = context->state[2];
- d = context->state[3];
- e = context->state[4];
- f = context->state[5];
- g = context->state[6];
- h = context->state[7];
-
- j = 0;
- do {
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Copy data while converting to host byte order */
- REVERSE32(*data++,W256[j]);
- /* Apply the SHA-256 compression function to update a..h */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
- /* Apply the SHA-256 compression function to update a..h with copy */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
- T2 = Sigma0_256(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 16);
-
- do {
- /* Part of the message block expansion: */
- s0 = W256[(j+1)&0x0f];
- s0 = sigma0_256(s0);
- s1 = W256[(j+14)&0x0f];
- s1 = sigma1_256(s1);
-
- /* Apply the SHA-256 compression function to update a..h */
- T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
- (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
- T2 = Sigma0_256(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 64);
-
- /* Compute the current intermediate hash value */
- context->state[0] += a;
- context->state[1] += b;
- context->state[2] += c;
- context->state[3] += d;
- context->state[4] += e;
- context->state[5] += f;
- context->state[6] += g;
- context->state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
- unsigned int freespace, usedspace;
-
- if (len == 0) {
- /* Calling with no data is valid - we do nothing */
- return;
- }
-
- /* Sanity check: */
- assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
-
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
- if (usedspace > 0) {
- /* Calculate how much free space is available in the buffer */
- freespace = SHA256_BLOCK_LENGTH - usedspace;
-
- if (len >= freespace) {
- /* Fill the buffer completely and process it */
- MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
- context->bitcount += freespace << 3;
- len -= freespace;
- data += freespace;
- SHA256_Transform(context, (sha2_word32*)context->buffer);
- } else {
- /* The buffer is not yet full */
- MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
- context->bitcount += len << 3;
- /* Clean up: */
- usedspace = freespace = 0;
- return;
- }
- }
- while (len >= SHA256_BLOCK_LENGTH) {
- /* Process as many complete blocks as we can */
- SHA256_Transform(context, (sha2_word32*)data);
- context->bitcount += SHA256_BLOCK_LENGTH << 3;
- len -= SHA256_BLOCK_LENGTH;
- data += SHA256_BLOCK_LENGTH;
- }
- if (len > 0) {
- /* There's left-overs, so save 'em */
- MEMCPY_BCOPY(context->buffer, data, len);
- context->bitcount += len << 3;
- }
- /* Clean up: */
- usedspace = freespace = 0;
-}
-
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
- sha2_word32 *d = (sha2_word32*)digest;
- unsigned int usedspace;
-
- /* Sanity check: */
- assert(context != (SHA256_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha2_byte*)0) {
- usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert FROM host byte order */
- REVERSE64(context->bitcount,context->bitcount);
-#endif
- if (usedspace > 0) {
- /* Begin padding with a 1 bit: */
- context->buffer[usedspace++] = 0x80;
-
- if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
- } else {
- if (usedspace < SHA256_BLOCK_LENGTH) {
- MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
- }
- /* Do second-to-last transform: */
- SHA256_Transform(context, (sha2_word32*)context->buffer);
-
- /* And set-up for the last transform: */
- MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
- }
- } else {
- /* Set-up for the last transform: */
- MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
-
- /* Begin padding with a 1 bit: */
- *context->buffer = 0x80;
- }
- /* Set the bit count: */
- *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
-
- /* Final transform: */
- SHA256_Transform(context, (sha2_word32*)context->buffer);
-
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < 8; j++) {
- REVERSE32(context->state[j],context->state[j]);
- *d++ = context->state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
-#endif
- }
-
- /* Clean up state data: */
- MEMSET_BZERO(context, sizeof(context));
- usedspace = 0;
-}
-
-char *SHA256_End(SHA256_CTX* context, char buffer[]) {
- sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA256_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA256_Final(digest, context);
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(context));
- }
- MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
- SHA256_CTX context;
-
- SHA256_Init(&context);
- SHA256_Update(&context, data, len);
- return SHA256_End(&context, digest);
-}
-#endif
-
-/*** SHA-512: *********************************************************/
-#ifdef WITH_SHA512
-void SHA512_Init(SHA512_CTX* context) {
- if (context == (SHA512_CTX*)0) {
- return;
- }
- MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
- MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
- context->bitcount[0] = context->bitcount[1] = 0;
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-512 round macros: */
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
- REVERSE64(*data++, W512[j]); \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
- K512[j] + W512[j]; \
- (d) += T1, \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
- j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
- K512[j] + (W512[j] = *data++); \
- (d) += T1; \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
- j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512(a,b,c,d,e,f,g,h) \
- s0 = W512[(j+1)&0x0f]; \
- s0 = sigma0_512(s0); \
- s1 = W512[(j+14)&0x0f]; \
- s1 = sigma1_512(s1); \
- T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
- (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
- (d) += T1; \
- (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
- j++
-
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
- sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
- sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
- int j;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->state[0];
- b = context->state[1];
- c = context->state[2];
- d = context->state[3];
- e = context->state[4];
- f = context->state[5];
- g = context->state[6];
- h = context->state[7];
-
- j = 0;
- do {
- ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
- ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
- ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
- ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
- ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
- ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
- ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
- ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
- } while (j < 16);
-
- /* Now for the remaining rounds up to 79: */
- do {
- ROUND512(a,b,c,d,e,f,g,h);
- ROUND512(h,a,b,c,d,e,f,g);
- ROUND512(g,h,a,b,c,d,e,f);
- ROUND512(f,g,h,a,b,c,d,e);
- ROUND512(e,f,g,h,a,b,c,d);
- ROUND512(d,e,f,g,h,a,b,c);
- ROUND512(c,d,e,f,g,h,a,b);
- ROUND512(b,c,d,e,f,g,h,a);
- } while (j < 80);
-
- /* Compute the current intermediate hash value */
- context->state[0] += a;
- context->state[1] += b;
- context->state[2] += c;
- context->state[3] += d;
- context->state[4] += e;
- context->state[5] += f;
- context->state[6] += g;
- context->state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
- sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
- sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer;
- int j;
-
- /* Initialize registers with the prev. intermediate value */
- a = context->state[0];
- b = context->state[1];
- c = context->state[2];
- d = context->state[3];
- e = context->state[4];
- f = context->state[5];
- g = context->state[6];
- h = context->state[7];
-
- j = 0;
- do {
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert TO host byte order */
- REVERSE64(*data++, W512[j]);
- /* Apply the SHA-512 compression function to update a..h */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
- /* Apply the SHA-512 compression function to update a..h with copy */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
- T2 = Sigma0_512(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 16);
-
- do {
- /* Part of the message block expansion: */
- s0 = W512[(j+1)&0x0f];
- s0 = sigma0_512(s0);
- s1 = W512[(j+14)&0x0f];
- s1 = sigma1_512(s1);
-
- /* Apply the SHA-512 compression function to update a..h */
- T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
- (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
- T2 = Sigma0_512(a) + Maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
-
- j++;
- } while (j < 80);
-
- /* Compute the current intermediate hash value */
- context->state[0] += a;
- context->state[1] += b;
- context->state[2] += c;
- context->state[3] += d;
- context->state[4] += e;
- context->state[5] += f;
- context->state[6] += g;
- context->state[7] += h;
-
- /* Clean up */
- a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
- unsigned int freespace, usedspace;
-
- if (len == 0) {
- /* Calling with no data is valid - we do nothing */
- return;
- }
-
- /* Sanity check: */
- assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
-
- usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
- if (usedspace > 0) {
- /* Calculate how much free space is available in the buffer */
- freespace = SHA512_BLOCK_LENGTH - usedspace;
-
- if (len >= freespace) {
- /* Fill the buffer completely and process it */
- MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
- ADDINC128(context->bitcount, freespace << 3);
- len -= freespace;
- data += freespace;
- SHA512_Transform(context, (sha2_word64*)context->buffer);
- } else {
- /* The buffer is not yet full */
- MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
- ADDINC128(context->bitcount, len << 3);
- /* Clean up: */
- usedspace = freespace = 0;
- return;
- }
- }
- while (len >= SHA512_BLOCK_LENGTH) {
- /* Process as many complete blocks as we can */
- SHA512_Transform(context, (sha2_word64*)data);
- ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
- len -= SHA512_BLOCK_LENGTH;
- data += SHA512_BLOCK_LENGTH;
- }
- if (len > 0) {
- /* There's left-overs, so save 'em */
- MEMCPY_BCOPY(context->buffer, data, len);
- ADDINC128(context->bitcount, len << 3);
- }
- /* Clean up: */
- usedspace = freespace = 0;
-}
-
-void SHA512_Last(SHA512_CTX* context) {
- unsigned int usedspace;
-
- usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
- /* Convert FROM host byte order */
- REVERSE64(context->bitcount[0],context->bitcount[0]);
- REVERSE64(context->bitcount[1],context->bitcount[1]);
-#endif
- if (usedspace > 0) {
- /* Begin padding with a 1 bit: */
- context->buffer[usedspace++] = 0x80;
-
- if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
- /* Set-up for the last transform: */
- MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
- } else {
- if (usedspace < SHA512_BLOCK_LENGTH) {
- MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
- }
- /* Do second-to-last transform: */
- SHA512_Transform(context, (sha2_word64*)context->buffer);
-
- /* And set-up for the last transform: */
- MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
- }
- } else {
- /* Prepare for final transform: */
- MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
-
- /* Begin padding with a 1 bit: */
- *context->buffer = 0x80;
- }
- /* Store the length of input data (in bits): */
- *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
- *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
-
- /* Final transform: */
- SHA512_Transform(context, (sha2_word64*)context->buffer);
-}
-
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
- sha2_word64 *d = (sha2_word64*)digest;
-
- /* Sanity check: */
- assert(context != (SHA512_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha2_byte*)0) {
- SHA512_Last(context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < 8; j++) {
- REVERSE64(context->state[j],context->state[j]);
- *d++ = context->state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
-#endif
- }
-
- /* Zero out state data */
- MEMSET_BZERO(context, sizeof(context));
-}
-
-char *SHA512_End(SHA512_CTX* context, char buffer[]) {
- sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA512_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA512_Final(digest, context);
-
- for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(context));
- }
- MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
- SHA512_CTX context;
-
- SHA512_Init(&context);
- SHA512_Update(&context, data, len);
- return SHA512_End(&context, digest);
-}
-#endif
-
-/*** SHA-384: *********************************************************/
-#ifdef WITH_SHA384
-void SHA384_Init(SHA384_CTX* context) {
- if (context == (SHA384_CTX*)0) {
- return;
- }
- MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
- MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
- context->bitcount[0] = context->bitcount[1] = 0;
-}
-
-void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
- SHA512_Update((SHA512_CTX*)context, data, len);
-}
-
-void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
- sha2_word64 *d = (sha2_word64*)digest;
-
- /* Sanity check: */
- assert(context != (SHA384_CTX*)0);
-
- /* If no digest buffer is passed, we don't bother doing this: */
- if (digest != (sha2_byte*)0) {
- SHA512_Last((SHA512_CTX*)context);
-
- /* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
- {
- /* Convert TO host byte order */
- int j;
- for (j = 0; j < 6; j++) {
- REVERSE64(context->state[j],context->state[j]);
- *d++ = context->state[j];
- }
- }
-#else
- MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH);
-#endif
- }
-
- /* Zero out state data */
- MEMSET_BZERO(context, sizeof(context));
-}
-
-char *SHA384_End(SHA384_CTX* context, char buffer[]) {
- sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
- int i;
-
- /* Sanity check: */
- assert(context != (SHA384_CTX*)0);
-
- if (buffer != (char*)0) {
- SHA384_Final(digest, context);
-
- for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- MEMSET_BZERO(context, sizeof(context));
- }
- MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
- return buffer;
-}
-
-char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
- SHA384_CTX context;
-
- SHA384_Init(&context);
- SHA384_Update(&context, data, len);
- return SHA384_End(&context, digest);
-}
-#endif
--- a/tinydtls/sha2/sha2.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * FILE: sha2.h
- * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
- *
- * Copyright (c) 2000-2001, Aaron D. Gifford
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
- */
-
-#ifndef __SHA2_H__
-#define __SHA2_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WITH_SHA256 1
-/*
- * Import u_intXX_t size_t type definitions from system headers. You
- * may need to change this, or define these things yourself in this
- * file.
- */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#define SHA2_USE_INTTYPES_H
-
-#ifdef SHA2_USE_INTTYPES_H
-
-#include <inttypes.h>
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-
-/*** SHA-256/384/512 Various Length Definitions ***********************/
-#define SHA256_BLOCK_LENGTH 64
-#define SHA256_DIGEST_LENGTH 32
-#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
-#define SHA384_BLOCK_LENGTH 128
-#define SHA384_DIGEST_LENGTH 48
-#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
-#define SHA512_BLOCK_LENGTH 128
-#define SHA512_DIGEST_LENGTH 64
-#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
-
-
-/*** SHA-256/384/512 Context Structures *******************************/
-/* NOTE: If your architecture does not define either u_intXX_t types or
- * uintXX_t (from inttypes.h), you may need to define things by hand
- * for your system:
- */
-#if 0
-typedef unsigned char u_int8_t; /* 1-byte (8-bits) */
-typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */
-typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */
-#endif
-/*
- * Most BSD systems already define u_intXX_t types, as does Linux.
- * Some systems, however, like Compaq's Tru64 Unix instead can use
- * uintXX_t types defined by very recent ANSI C standards and included
- * in the file:
- *
- * #include <inttypes.h>
- *
- * If you choose to use <inttypes.h> then please define:
- *
- * #define SHA2_USE_INTTYPES_H
- *
- * Or on the command line during compile:
- *
- * cc -DSHA2_USE_INTTYPES_H ...
- */
-#ifdef SHA2_USE_INTTYPES_H
-
-typedef struct _SHA256_CTX {
- uint32_t state[8];
- uint64_t bitcount;
- uint8_t buffer[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-typedef struct _SHA512_CTX {
- uint64_t state[8];
- uint64_t bitcount[2];
- uint8_t buffer[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
-
-#else /* SHA2_USE_INTTYPES_H */
-
-typedef struct _SHA256_CTX {
- u_int32_t state[8];
- u_int64_t bitcount;
- u_int8_t buffer[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-typedef struct _SHA512_CTX {
- u_int64_t state[8];
- u_int64_t bitcount[2];
- u_int8_t buffer[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-typedef SHA512_CTX SHA384_CTX;
-
-
-/*** SHA-256/384/512 Function Prototypes ******************************/
-#ifndef NOPROTO
-#ifdef SHA2_USE_INTTYPES_H
-
-#ifdef WITH_SHA256
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t);
-void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
-char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
-#endif
-
-#ifdef WITH_SHA384
-void SHA384_Init(SHA384_CTX*);
-void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t);
-void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
-char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
-#endif
-
-#ifdef WITH_SHA512
-void SHA512_Init(SHA512_CTX*);
-void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t);
-void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
-char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
-#endif
-
-#else /* SHA2_USE_INTTYPES_H */
-
-#ifdef WITH_SHA256
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t);
-void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
-char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
-#endif
-
-#ifdef WITH_SHA384
-void SHA384_Init(SHA384_CTX*);
-void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
-void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
-char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
-#endif
-
-#ifdef WITH_SHA512
-void SHA512_Init(SHA512_CTX*);
-void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
-void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
-char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
-#endif
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-#else /* NOPROTO */
-
-#ifdef WITH_SHA256
-void SHA256_Init();
-void SHA256_Update();
-void SHA256_Final();
-char* SHA256_End();
-char* SHA256_Data();
-#endif
-
-#ifdef WITH_SHA384
-void SHA384_Init();
-void SHA384_Update();
-void SHA384_Final();
-char* SHA384_End();
-char* SHA384_Data();
-#endif
-
-#ifdef WITH_SHA512
-void SHA512_Init();
-void SHA512_Update();
-void SHA512_Final();
-char* SHA512_End();
-char* SHA512_Data();
-#endif
-
-#endif /* NOPROTO */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __SHA2_H__ */
-
--- a/tinydtls/state.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* dtls -- a very basic DTLS implementation
- *
- * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file state.h
- * @brief state information for DTLS FSM
- */
-
-#ifndef _STATE_H_
-#define _STATE_H_
-
-#include "config.h"
-#include "global.h"
-#include "hmac.h"
-
-typedef enum {
- DTLS_STATE_INIT = 0, DTLS_STATE_SERVERHELLO, DTLS_STATE_KEYEXCHANGE,
- DTLS_STATE_WAIT_FINISHED, DTLS_STATE_FINISHED,
- /* client states */
- DTLS_STATE_CLIENTHELLO, DTLS_STATE_WAIT_SERVERHELLODONE,
- DTLS_STATE_WAIT_SERVERFINISHED,
-
- DTLS_STATE_CONNECTED,
- DTLS_STATE_CLOSING,
- DTLS_STATE_CLOSED,
-} dtls_state_t;
-
-typedef struct {
- uint24 mseq; /**< handshake message sequence number counter */
-
- /** pending config that is updated during handshake */
- /* FIXME: dtls_security_parameters_t pending_config; */
-
- /* temporary storage for the final handshake hash */
- dtls_hash_ctx hs_hash;
-} dtls_hs_state_t;
-
-#endif /* _STATE_H_ */
--- a/tinydtls/t_list.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/* t_list -- tinydtls lists
- *
- * Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * @file t_list.h
- * @brief Wrappers for list structures and functions
- */
-
-#ifndef _DTLS_LIST_H_
-#define _DTLS_LIST_H_
-
-#ifndef WITH_CONTIKI
-#include "uthash.h"
-#include "utlist.h"
-
-/* We define list structures and utility functions to be compatible
- * with Contiki list structures. The Contiki list API is part of the
- * Contiki operating system, and therefore the following licensing
- * terms apply (taken from contiki/core/lib/list.h):
- *
- * Copyright (c) 2004, Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file is part of the Contiki operating system.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- * $ Id: list.h,v 1.5 2010/09/13 13:31:00 adamdunkels Exp $
- */
-
-typedef void **list_t;
-struct list {
- struct list *next;
-};
-
-#define LIST_CONCAT(s1, s2) s1##s2
-
-#define LIST_STRUCT(name) \
- void *LIST_CONCAT(name, _list); \
- list_t name
-
-#define LIST_STRUCT_INIT(struct_ptr, name) { \
- (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
- (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
- }
-
-static inline void *
-list_head(list_t list) {
- return *list;
-}
-
-static inline void
-list_remove(list_t list, void *item) {
- LL_DELETE(*(struct list **)list, (struct list *)item);
-}
-
-static inline void
-list_add(list_t list, void *item) {
- list_remove(list, item);
- LL_APPEND(*(struct list **)list, (struct list *)item);
-}
-
-static inline void
-list_push(list_t list, void *item) {
- LL_PREPEND(*(struct list **)list, (struct list *)item);
-}
-
-static inline void *
-list_pop(list_t list) {
- struct list *l;
- l = (struct list*)*list;
- if(l)
- list_remove(list, l);
-
- return l;
-}
-
-static inline void
-list_insert(list_t list, void *previtem, void *newitem) {
- if(previtem == NULL) {
- list_push(list, newitem);
- } else {
- ((struct list *)newitem)->next = ((struct list *)previtem)->next;
- ((struct list *)previtem)->next = (struct list *)newitem;
- }
-}
-
-static inline void *
-list_item_next(void *item)
-{
- return item == NULL? NULL: ((struct list *)item)->next;
-}
-
-#else /* WITH_CONTIKI */
-#include "list.h"
-#endif /* WITH_CONTIKI */
-
-#endif /* _DTLS_LIST_H_ */
-
--- a/tinydtls/uthash.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,972 +0,0 @@
-/*
-Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef UTHASH_H
-#define UTHASH_H
-
-#include <string.h> /* memcmp,strlen */
-#include <stddef.h> /* ptrdiff_t */
-
-/* These macros use decltype or the earlier __typeof GNU extension.
- As decltype is only available in newer compilers (VS2010 or gcc 4.3+
- when compiling c++ source) this code uses whatever method is needed
- or, for VS2008 where neither is available, uses casting workarounds. */
-#ifdef _MSC_VER /* MS compiler */
-#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
-#define DECLTYPE(x) (decltype(x))
-#else /* VS2008 or older (or VS2010 in C mode) */
-#define NO_DECLTYPE
-#define DECLTYPE(x)
-#endif
-#else /* GNU, Sun and other compilers */
-#define DECLTYPE(x) (__typeof(x))
-#endif
-
-#ifdef NO_DECLTYPE
-#define DECLTYPE_ASSIGN(dst,src) \
-do { \
- char **_da_dst = (char**)(&(dst)); \
- *_da_dst = (char*)(src); \
-} while(0)
-#else
-#define DECLTYPE_ASSIGN(dst,src) \
-do { \
- (dst) = DECLTYPE(dst)(src); \
-} while(0)
-#endif
-
-/* a number of the hash function use uint32_t which isn't defined on win32 */
-#ifdef _MSC_VER
-typedef unsigned int uint32_t;
-#else
-#include <inttypes.h> /* uint32_t */
-#endif
-
-#define UTHASH_VERSION 1.9.3
-
-#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
-#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
-#define uthash_free(ptr,sz) free(ptr) /* free fcn */
-
-#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
-#define uthash_expand_fyi(tbl) /* can be defined to log expands */
-
-/* initial number of buckets */
-#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
-#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
-#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
-
-/* calculate the element whose hash handle address is hhe */
-#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
-
-#define HASH_FIND(hh,head,keyptr,keylen,out) \
-do { \
- unsigned _hf_bkt,_hf_hashv; \
- out=NULL; \
- if (head) { \
- HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
- if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
- HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
- keyptr,keylen,out); \
- } \
- } \
-} while (0)
-
-#ifdef HASH_BLOOM
-#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
-#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
-#define HASH_BLOOM_MAKE(tbl) \
-do { \
- (tbl)->bloom_nbits = HASH_BLOOM; \
- (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
- if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
- memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
- (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
-} while (0);
-
-#define HASH_BLOOM_FREE(tbl) \
-do { \
- uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
-} while (0);
-
-#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
-#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
-
-#define HASH_BLOOM_ADD(tbl,hashv) \
- HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
-
-#define HASH_BLOOM_TEST(tbl,hashv) \
- HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
-
-#else
-#define HASH_BLOOM_MAKE(tbl)
-#define HASH_BLOOM_FREE(tbl)
-#define HASH_BLOOM_ADD(tbl,hashv)
-#define HASH_BLOOM_TEST(tbl,hashv) (1)
-#endif
-
-#define HASH_MAKE_TABLE(hh,head) \
-do { \
- (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
- sizeof(UT_hash_table)); \
- if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
- memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
- (head)->hh.tbl->tail = &((head)->hh); \
- (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
- (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
- (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
- (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
- HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
- if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
- memset((head)->hh.tbl->buckets, 0, \
- HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
- HASH_BLOOM_MAKE((head)->hh.tbl); \
- (head)->hh.tbl->signature = HASH_SIGNATURE; \
-} while(0)
-
-#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
- HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
-
-#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
-do { \
- unsigned _ha_bkt; \
- (add)->hh.next = NULL; \
- (add)->hh.key = (char*)keyptr; \
- (add)->hh.keylen = keylen_in; \
- if (!(head)) { \
- head = (add); \
- (head)->hh.prev = NULL; \
- HASH_MAKE_TABLE(hh,head); \
- } else { \
- (head)->hh.tbl->tail->next = (add); \
- (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
- (head)->hh.tbl->tail = &((add)->hh); \
- } \
- (head)->hh.tbl->num_items++; \
- (add)->hh.tbl = (head)->hh.tbl; \
- HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
- (add)->hh.hashv, _ha_bkt); \
- HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
- HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
- HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
- HASH_FSCK(hh,head); \
-} while(0)
-
-#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
-do { \
- bkt = ((hashv) & ((num_bkts) - 1)); \
-} while(0)
-
-/* delete "delptr" from the hash table.
- * "the usual" patch-up process for the app-order doubly-linked-list.
- * The use of _hd_hh_del below deserves special explanation.
- * These used to be expressed using (delptr) but that led to a bug
- * if someone used the same symbol for the head and deletee, like
- * HASH_DELETE(hh,users,users);
- * We want that to work, but by changing the head (users) below
- * we were forfeiting our ability to further refer to the deletee (users)
- * in the patch-up process. Solution: use scratch space to
- * copy the deletee pointer, then the latter references are via that
- * scratch pointer rather than through the repointed (users) symbol.
- */
-#define HASH_DELETE(hh,head,delptr) \
-do { \
- unsigned _hd_bkt; \
- struct UT_hash_handle *_hd_hh_del; \
- if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
- uthash_free((head)->hh.tbl->buckets, \
- (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
- HASH_BLOOM_FREE((head)->hh.tbl); \
- uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
- head = NULL; \
- } else { \
- _hd_hh_del = &((delptr)->hh); \
- if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
- (head)->hh.tbl->tail = \
- (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
- (head)->hh.tbl->hho); \
- } \
- if ((delptr)->hh.prev) { \
- ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
- (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
- } else { \
- DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
- } \
- if (_hd_hh_del->next) { \
- ((UT_hash_handle*)((char*)_hd_hh_del->next + \
- (head)->hh.tbl->hho))->prev = \
- _hd_hh_del->prev; \
- } \
- HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
- HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
- (head)->hh.tbl->num_items--; \
- } \
- HASH_FSCK(hh,head); \
-} while (0)
-
-
-/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
-#define HASH_FIND_STR(head,findstr,out) \
- HASH_FIND(hh,head,findstr,strlen(findstr),out)
-#define HASH_ADD_STR(head,strfield,add) \
- HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
-#define HASH_FIND_INT(head,findint,out) \
- HASH_FIND(hh,head,findint,sizeof(int),out)
-#define HASH_ADD_INT(head,intfield,add) \
- HASH_ADD(hh,head,intfield,sizeof(int),add)
-#define HASH_FIND_PTR(head,findptr,out) \
- HASH_FIND(hh,head,findptr,sizeof(void *),out)
-#define HASH_ADD_PTR(head,ptrfield,add) \
- HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
-#define HASH_DEL(head,delptr) \
- HASH_DELETE(hh,head,delptr)
-
-/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
- * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
- */
-#ifdef HASH_DEBUG
-#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
-#define HASH_FSCK(hh,head) \
-do { \
- unsigned _bkt_i; \
- unsigned _count, _bkt_count; \
- char *_prev; \
- struct UT_hash_handle *_thh; \
- if (head) { \
- _count = 0; \
- for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
- _bkt_count = 0; \
- _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
- _prev = NULL; \
- while (_thh) { \
- if (_prev != (char*)(_thh->hh_prev)) { \
- HASH_OOPS("invalid hh_prev %p, actual %p\n", \
- _thh->hh_prev, _prev ); \
- } \
- _bkt_count++; \
- _prev = (char*)(_thh); \
- _thh = _thh->hh_next; \
- } \
- _count += _bkt_count; \
- if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
- HASH_OOPS("invalid bucket count %d, actual %d\n", \
- (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
- } \
- } \
- if (_count != (head)->hh.tbl->num_items) { \
- HASH_OOPS("invalid hh item count %d, actual %d\n", \
- (head)->hh.tbl->num_items, _count ); \
- } \
- /* traverse hh in app order; check next/prev integrity, count */ \
- _count = 0; \
- _prev = NULL; \
- _thh = &(head)->hh; \
- while (_thh) { \
- _count++; \
- if (_prev !=(char*)(_thh->prev)) { \
- HASH_OOPS("invalid prev %p, actual %p\n", \
- _thh->prev, _prev ); \
- } \
- _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
- _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
- (head)->hh.tbl->hho) : NULL ); \
- } \
- if (_count != (head)->hh.tbl->num_items) { \
- HASH_OOPS("invalid app item count %d, actual %d\n", \
- (head)->hh.tbl->num_items, _count ); \
- } \
- } \
-} while (0)
-#else
-#define HASH_FSCK(hh,head)
-#endif
-
-/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
- * the descriptor to which this macro is defined for tuning the hash function.
- * The app can #include <unistd.h> to get the prototype for write(2). */
-#ifdef HASH_EMIT_KEYS
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
-do { \
- unsigned _klen = fieldlen; \
- write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
- write(HASH_EMIT_KEYS, keyptr, fieldlen); \
-} while (0)
-#else
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
-#endif
-
-/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
-#ifdef HASH_FUNCTION
-#define HASH_FCN HASH_FUNCTION
-#else
-#define HASH_FCN HASH_JEN
-#endif
-
-/* The Bernstein hash function, used in Perl prior to v5.6 */
-#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _hb_keylen=keylen; \
- char *_hb_key=(char*)(key); \
- (hashv) = 0; \
- while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
- bkt = (hashv) & (num_bkts-1); \
-} while (0)
-
-
-/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
- * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
-#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _sx_i; \
- char *_hs_key=(char*)(key); \
- hashv = 0; \
- for(_sx_i=0; _sx_i < keylen; _sx_i++) \
- hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
- bkt = hashv & (num_bkts-1); \
-} while (0)
-
-#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _fn_i; \
- char *_hf_key=(char*)(key); \
- hashv = 2166136261UL; \
- for(_fn_i=0; _fn_i < keylen; _fn_i++) \
- hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
- bkt = hashv & (num_bkts-1); \
-} while(0);
-
-#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _ho_i; \
- char *_ho_key=(char*)(key); \
- hashv = 0; \
- for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
- hashv += _ho_key[_ho_i]; \
- hashv += (hashv << 10); \
- hashv ^= (hashv >> 6); \
- } \
- hashv += (hashv << 3); \
- hashv ^= (hashv >> 11); \
- hashv += (hashv << 15); \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-#define HASH_JEN_MIX(a,b,c) \
-do { \
- a -= b; a -= c; a ^= ( c >> 13 ); \
- b -= c; b -= a; b ^= ( a << 8 ); \
- c -= a; c -= b; c ^= ( b >> 13 ); \
- a -= b; a -= c; a ^= ( c >> 12 ); \
- b -= c; b -= a; b ^= ( a << 16 ); \
- c -= a; c -= b; c ^= ( b >> 5 ); \
- a -= b; a -= c; a ^= ( c >> 3 ); \
- b -= c; b -= a; b ^= ( a << 10 ); \
- c -= a; c -= b; c ^= ( b >> 15 ); \
-} while (0)
-
-#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _hj_i,_hj_j,_hj_k; \
- char *_hj_key=(char*)(key); \
- hashv = 0xfeedbeef; \
- _hj_i = _hj_j = 0x9e3779b9; \
- _hj_k = keylen; \
- while (_hj_k >= 12) { \
- _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
- + ( (unsigned)_hj_key[2] << 16 ) \
- + ( (unsigned)_hj_key[3] << 24 ) ); \
- _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
- + ( (unsigned)_hj_key[6] << 16 ) \
- + ( (unsigned)_hj_key[7] << 24 ) ); \
- hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
- + ( (unsigned)_hj_key[10] << 16 ) \
- + ( (unsigned)_hj_key[11] << 24 ) ); \
- \
- HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
- \
- _hj_key += 12; \
- _hj_k -= 12; \
- } \
- hashv += keylen; \
- switch ( _hj_k ) { \
- case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
- case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
- case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
- case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
- case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
- case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
- case 5: _hj_j += _hj_key[4]; \
- case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
- case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
- case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
- case 1: _hj_i += _hj_key[0]; \
- } \
- HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-/* The Paul Hsieh hash function */
-#undef get16bits
-#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
- || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
-#define get16bits(d) (*((const uint16_t *) (d)))
-#endif
-
-#if !defined (get16bits)
-#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
- +(uint32_t)(((const uint8_t *)(d))[0]) )
-#endif
-#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
-do { \
- char *_sfh_key=(char*)(key); \
- uint32_t _sfh_tmp, _sfh_len = keylen; \
- \
- int _sfh_rem = _sfh_len & 3; \
- _sfh_len >>= 2; \
- hashv = 0xcafebabe; \
- \
- /* Main loop */ \
- for (;_sfh_len > 0; _sfh_len--) { \
- hashv += get16bits (_sfh_key); \
- _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
- hashv = (hashv << 16) ^ _sfh_tmp; \
- _sfh_key += 2*sizeof (uint16_t); \
- hashv += hashv >> 11; \
- } \
- \
- /* Handle end cases */ \
- switch (_sfh_rem) { \
- case 3: hashv += get16bits (_sfh_key); \
- hashv ^= hashv << 16; \
- hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
- hashv += hashv >> 11; \
- break; \
- case 2: hashv += get16bits (_sfh_key); \
- hashv ^= hashv << 11; \
- hashv += hashv >> 17; \
- break; \
- case 1: hashv += *_sfh_key; \
- hashv ^= hashv << 10; \
- hashv += hashv >> 1; \
- } \
- \
- /* Force "avalanching" of final 127 bits */ \
- hashv ^= hashv << 3; \
- hashv += hashv >> 5; \
- hashv ^= hashv << 4; \
- hashv += hashv >> 17; \
- hashv ^= hashv << 25; \
- hashv += hashv >> 6; \
- bkt = hashv & (num_bkts-1); \
-} while(0);
-
-#ifdef HASH_USING_NO_STRICT_ALIASING
-/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
- * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
- * So MurmurHash comes in two versions, the faster unaligned one and the slower
- * aligned one. We only use the faster one on CPU's where we know it's safe.
- *
- * Note the preprocessor built-in defines can be emitted using:
- *
- * gcc -m64 -dM -E - < /dev/null (on gcc)
- * cc -## a.c (where a.c is a simple test file) (Sun Studio)
- */
-#if (defined(__i386__) || defined(__x86_64__))
-#define HASH_MUR HASH_MUR_UNALIGNED
-#else
-#define HASH_MUR HASH_MUR_ALIGNED
-#endif
-
-/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
-#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
-do { \
- const unsigned int _mur_m = 0x5bd1e995; \
- const int _mur_r = 24; \
- hashv = 0xcafebabe ^ keylen; \
- char *_mur_key = (char *)(key); \
- uint32_t _mur_tmp, _mur_len = keylen; \
- \
- for (;_mur_len >= 4; _mur_len-=4) { \
- _mur_tmp = *(uint32_t *)_mur_key; \
- _mur_tmp *= _mur_m; \
- _mur_tmp ^= _mur_tmp >> _mur_r; \
- _mur_tmp *= _mur_m; \
- hashv *= _mur_m; \
- hashv ^= _mur_tmp; \
- _mur_key += 4; \
- } \
- \
- switch(_mur_len) \
- { \
- case 3: hashv ^= _mur_key[2] << 16; \
- case 2: hashv ^= _mur_key[1] << 8; \
- case 1: hashv ^= _mur_key[0]; \
- hashv *= _mur_m; \
- }; \
- \
- hashv ^= hashv >> 13; \
- hashv *= _mur_m; \
- hashv ^= hashv >> 15; \
- \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
-#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
-do { \
- const unsigned int _mur_m = 0x5bd1e995; \
- const int _mur_r = 24; \
- hashv = 0xcafebabe ^ (keylen); \
- char *_mur_key = (char *)(key); \
- uint32_t _mur_len = keylen; \
- int _mur_align = (int)_mur_key & 3; \
- \
- if (_mur_align && (_mur_len >= 4)) { \
- unsigned _mur_t = 0, _mur_d = 0; \
- switch(_mur_align) { \
- case 1: _mur_t |= _mur_key[2] << 16; \
- case 2: _mur_t |= _mur_key[1] << 8; \
- case 3: _mur_t |= _mur_key[0]; \
- } \
- _mur_t <<= (8 * _mur_align); \
- _mur_key += 4-_mur_align; \
- _mur_len -= 4-_mur_align; \
- int _mur_sl = 8 * (4-_mur_align); \
- int _mur_sr = 8 * _mur_align; \
- \
- for (;_mur_len >= 4; _mur_len-=4) { \
- _mur_d = *(unsigned *)_mur_key; \
- _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
- unsigned _mur_k = _mur_t; \
- _mur_k *= _mur_m; \
- _mur_k ^= _mur_k >> _mur_r; \
- _mur_k *= _mur_m; \
- hashv *= _mur_m; \
- hashv ^= _mur_k; \
- _mur_t = _mur_d; \
- _mur_key += 4; \
- } \
- _mur_d = 0; \
- if(_mur_len >= _mur_align) { \
- switch(_mur_align) { \
- case 3: _mur_d |= _mur_key[2] << 16; \
- case 2: _mur_d |= _mur_key[1] << 8; \
- case 1: _mur_d |= _mur_key[0]; \
- } \
- unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
- _mur_k *= _mur_m; \
- _mur_k ^= _mur_k >> _mur_r; \
- _mur_k *= _mur_m; \
- hashv *= _mur_m; \
- hashv ^= _mur_k; \
- _mur_k += _mur_align; \
- _mur_len -= _mur_align; \
- \
- switch(_mur_len) \
- { \
- case 3: hashv ^= _mur_key[2] << 16; \
- case 2: hashv ^= _mur_key[1] << 8; \
- case 1: hashv ^= _mur_key[0]; \
- hashv *= _mur_m; \
- } \
- } else { \
- switch(_mur_len) \
- { \
- case 3: _mur_d ^= _mur_key[2] << 16; \
- case 2: _mur_d ^= _mur_key[1] << 8; \
- case 1: _mur_d ^= _mur_key[0]; \
- case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
- hashv *= _mur_m; \
- } \
- } \
- \
- hashv ^= hashv >> 13; \
- hashv *= _mur_m; \
- hashv ^= hashv >> 15; \
- } else { \
- for (;_mur_len >= 4; _mur_len-=4) { \
- unsigned _mur_k = *(unsigned*)_mur_key; \
- _mur_k *= _mur_m; \
- _mur_k ^= _mur_k >> _mur_r; \
- _mur_k *= _mur_m; \
- hashv *= _mur_m; \
- hashv ^= _mur_k; \
- _mur_key += 4; \
- } \
- switch(_mur_len) \
- { \
- case 3: hashv ^= _mur_key[2] << 16; \
- case 2: hashv ^= _mur_key[1] << 8; \
- case 1: hashv ^= _mur_key[0]; \
- hashv *= _mur_m; \
- } \
- \
- hashv ^= hashv >> 13; \
- hashv *= _mur_m; \
- hashv ^= hashv >> 15; \
- } \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-#endif /* HASH_USING_NO_STRICT_ALIASING */
-
-/* key comparison function; return 0 if keys equal */
-#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
-
-/* iterate over items in a known bucket to find desired item */
-#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
-do { \
- if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
- else out=NULL; \
- while (out) { \
- if (out->hh.keylen == keylen_in) { \
- if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
- } \
- if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
- else out = NULL; \
- } \
-} while(0)
-
-/* add an item to a bucket */
-#define HASH_ADD_TO_BKT(head,addhh) \
-do { \
- head.count++; \
- (addhh)->hh_next = head.hh_head; \
- (addhh)->hh_prev = NULL; \
- if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
- (head).hh_head=addhh; \
- if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
- && (addhh)->tbl->noexpand != 1) { \
- HASH_EXPAND_BUCKETS((addhh)->tbl); \
- } \
-} while(0)
-
-/* remove an item from a given bucket */
-#define HASH_DEL_IN_BKT(hh,head,hh_del) \
- (head).count--; \
- if ((head).hh_head == hh_del) { \
- (head).hh_head = hh_del->hh_next; \
- } \
- if (hh_del->hh_prev) { \
- hh_del->hh_prev->hh_next = hh_del->hh_next; \
- } \
- if (hh_del->hh_next) { \
- hh_del->hh_next->hh_prev = hh_del->hh_prev; \
- }
-
-/* Bucket expansion has the effect of doubling the number of buckets
- * and redistributing the items into the new buckets. Ideally the
- * items will distribute more or less evenly into the new buckets
- * (the extent to which this is true is a measure of the quality of
- * the hash function as it applies to the key domain).
- *
- * With the items distributed into more buckets, the chain length
- * (item count) in each bucket is reduced. Thus by expanding buckets
- * the hash keeps a bound on the chain length. This bounded chain
- * length is the essence of how a hash provides constant time lookup.
- *
- * The calculation of tbl->ideal_chain_maxlen below deserves some
- * explanation. First, keep in mind that we're calculating the ideal
- * maximum chain length based on the *new* (doubled) bucket count.
- * In fractions this is just n/b (n=number of items,b=new num buckets).
- * Since the ideal chain length is an integer, we want to calculate
- * ceil(n/b). We don't depend on floating point arithmetic in this
- * hash, so to calculate ceil(n/b) with integers we could write
- *
- * ceil(n/b) = (n/b) + ((n%b)?1:0)
- *
- * and in fact a previous version of this hash did just that.
- * But now we have improved things a bit by recognizing that b is
- * always a power of two. We keep its base 2 log handy (call it lb),
- * so now we can write this with a bit shift and logical AND:
- *
- * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
- *
- */
-#define HASH_EXPAND_BUCKETS(tbl) \
-do { \
- unsigned _he_bkt; \
- unsigned _he_bkt_i; \
- struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
- UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
- _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
- 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
- if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
- memset(_he_new_buckets, 0, \
- 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
- tbl->ideal_chain_maxlen = \
- (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
- ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
- tbl->nonideal_items = 0; \
- for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
- { \
- _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
- while (_he_thh) { \
- _he_hh_nxt = _he_thh->hh_next; \
- HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
- _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
- if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
- tbl->nonideal_items++; \
- _he_newbkt->expand_mult = _he_newbkt->count / \
- tbl->ideal_chain_maxlen; \
- } \
- _he_thh->hh_prev = NULL; \
- _he_thh->hh_next = _he_newbkt->hh_head; \
- if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
- _he_thh; \
- _he_newbkt->hh_head = _he_thh; \
- _he_thh = _he_hh_nxt; \
- } \
- } \
- uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
- tbl->num_buckets *= 2; \
- tbl->log2_num_buckets++; \
- tbl->buckets = _he_new_buckets; \
- tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
- (tbl->ineff_expands+1) : 0; \
- if (tbl->ineff_expands > 1) { \
- tbl->noexpand=1; \
- uthash_noexpand_fyi(tbl); \
- } \
- uthash_expand_fyi(tbl); \
-} while(0)
-
-
-/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
-/* Note that HASH_SORT assumes the hash handle name to be hh.
- * HASH_SRT was added to allow the hash handle name to be passed in. */
-#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
-#define HASH_SRT(hh,head,cmpfcn) \
-do { \
- unsigned _hs_i; \
- unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
- struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
- if (head) { \
- _hs_insize = 1; \
- _hs_looping = 1; \
- _hs_list = &((head)->hh); \
- while (_hs_looping) { \
- _hs_p = _hs_list; \
- _hs_list = NULL; \
- _hs_tail = NULL; \
- _hs_nmerges = 0; \
- while (_hs_p) { \
- _hs_nmerges++; \
- _hs_q = _hs_p; \
- _hs_psize = 0; \
- for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
- _hs_psize++; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- if (! (_hs_q) ) break; \
- } \
- _hs_qsize = _hs_insize; \
- while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
- if (_hs_psize == 0) { \
- _hs_e = _hs_q; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_qsize--; \
- } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
- _hs_e = _hs_p; \
- _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
- ((void*)((char*)(_hs_p->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_psize--; \
- } else if (( \
- cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
- DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
- ) <= 0) { \
- _hs_e = _hs_p; \
- _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
- ((void*)((char*)(_hs_p->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_psize--; \
- } else { \
- _hs_e = _hs_q; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_qsize--; \
- } \
- if ( _hs_tail ) { \
- _hs_tail->next = ((_hs_e) ? \
- ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
- } else { \
- _hs_list = _hs_e; \
- } \
- _hs_e->prev = ((_hs_tail) ? \
- ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
- _hs_tail = _hs_e; \
- } \
- _hs_p = _hs_q; \
- } \
- _hs_tail->next = NULL; \
- if ( _hs_nmerges <= 1 ) { \
- _hs_looping=0; \
- (head)->hh.tbl->tail = _hs_tail; \
- DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
- } \
- _hs_insize *= 2; \
- } \
- HASH_FSCK(hh,head); \
- } \
-} while (0)
-
-/* This function selects items from one hash into another hash.
- * The end result is that the selected items have dual presence
- * in both hashes. There is no copy of the items made; rather
- * they are added into the new hash through a secondary hash
- * hash handle that must be present in the structure. */
-#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
-do { \
- unsigned _src_bkt, _dst_bkt; \
- void *_last_elt=NULL, *_elt; \
- UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
- ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
- if (src) { \
- for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
- for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
- _src_hh; \
- _src_hh = _src_hh->hh_next) { \
- _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
- if (cond(_elt)) { \
- _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
- _dst_hh->key = _src_hh->key; \
- _dst_hh->keylen = _src_hh->keylen; \
- _dst_hh->hashv = _src_hh->hashv; \
- _dst_hh->prev = _last_elt; \
- _dst_hh->next = NULL; \
- if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
- if (!dst) { \
- DECLTYPE_ASSIGN(dst,_elt); \
- HASH_MAKE_TABLE(hh_dst,dst); \
- } else { \
- _dst_hh->tbl = (dst)->hh_dst.tbl; \
- } \
- HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
- HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
- (dst)->hh_dst.tbl->num_items++; \
- _last_elt = _elt; \
- _last_elt_hh = _dst_hh; \
- } \
- } \
- } \
- } \
- HASH_FSCK(hh_dst,dst); \
-} while (0)
-
-#define HASH_CLEAR(hh,head) \
-do { \
- if (head) { \
- uthash_free((head)->hh.tbl->buckets, \
- (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
- uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
- (head)=NULL; \
- } \
-} while(0)
-
-#ifdef NO_DECLTYPE
-#define HASH_ITER(hh,head,el,tmp) \
-for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
- el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
-#else
-#define HASH_ITER(hh,head,el,tmp) \
-for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
- el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
-#endif
-
-/* obtain a count of items in the hash */
-#define HASH_COUNT(head) HASH_CNT(hh,head)
-#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
-
-typedef struct UT_hash_bucket {
- struct UT_hash_handle *hh_head;
- unsigned count;
-
- /* expand_mult is normally set to 0. In this situation, the max chain length
- * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
- * the bucket's chain exceeds this length, bucket expansion is triggered).
- * However, setting expand_mult to a non-zero value delays bucket expansion
- * (that would be triggered by additions to this particular bucket)
- * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
- * (The multiplier is simply expand_mult+1). The whole idea of this
- * multiplier is to reduce bucket expansions, since they are expensive, in
- * situations where we know that a particular bucket tends to be overused.
- * It is better to let its chain length grow to a longer yet-still-bounded
- * value, than to do an O(n) bucket expansion too often.
- */
- unsigned expand_mult;
-
-} UT_hash_bucket;
-
-/* random signature used only to find hash tables in external analysis */
-#define HASH_SIGNATURE 0xa0111fe1
-#define HASH_BLOOM_SIGNATURE 0xb12220f2
-
-typedef struct UT_hash_table {
- UT_hash_bucket *buckets;
- unsigned num_buckets, log2_num_buckets;
- unsigned num_items;
- struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
- ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
-
- /* in an ideal situation (all buckets used equally), no bucket would have
- * more than ceil(#items/#buckets) items. that's the ideal chain length. */
- unsigned ideal_chain_maxlen;
-
- /* nonideal_items is the number of items in the hash whose chain position
- * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
- * hash distribution; reaching them in a chain traversal takes >ideal steps */
- unsigned nonideal_items;
-
- /* ineffective expands occur when a bucket doubling was performed, but
- * afterward, more than half the items in the hash had nonideal chain
- * positions. If this happens on two consecutive expansions we inhibit any
- * further expansion, as it's not helping; this happens when the hash
- * function isn't a good fit for the key domain. When expansion is inhibited
- * the hash will still work, albeit no longer in constant time. */
- unsigned ineff_expands, noexpand;
-
- uint32_t signature; /* used only to find hash tables in external analysis */
-#ifdef HASH_BLOOM
- uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
- uint8_t *bloom_bv;
- char bloom_nbits;
-#endif
-
-} UT_hash_table;
-
-typedef struct UT_hash_handle {
- struct UT_hash_table *tbl;
- void *prev; /* prev element in app order */
- void *next; /* next element in app order */
- struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
- struct UT_hash_handle *hh_next; /* next hh in bucket order */
- void *key; /* ptr to enclosing struct's key */
- unsigned keylen; /* enclosing struct's key len */
- unsigned hashv; /* result of hash-fcn(key) */
-} UT_hash_handle;
-
-#endif /* UTHASH_H */
--- a/tinydtls/utlist.h Wed Oct 09 14:48:52 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-/*
-Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef UTLIST_H
-#define UTLIST_H
-
-#define UTLIST_VERSION 1.9.1
-
-/*
- * This file contains macros to manipulate singly and doubly-linked lists.
- *
- * 1. LL_ macros: singly-linked lists.
- * 2. DL_ macros: doubly-linked lists.
- * 3. CDL_ macros: circular doubly-linked lists.
- *
- * To use singly-linked lists, your structure must have a "next" pointer.
- * To use doubly-linked lists, your structure must "prev" and "next" pointers.
- * Either way, the pointer to the head of the list must be initialized to NULL.
- *
- * ----------------.EXAMPLE -------------------------
- * struct item {
- * int id;
- * struct item *prev, *next;
- * }
- *
- * struct item *list = NULL:
- *
- * int main() {
- * struct item *item;
- * ... allocate and populate item ...
- * DL_APPEND(list, item);
- * }
- * --------------------------------------------------
- *
- * For doubly-linked lists, the append and delete macros are O(1)
- * For singly-linked lists, append and delete are O(n) but prepend is O(1)
- * The sort macro is O(n log(n)) for all types of single/double/circular lists.
- */
-
-/* These macros use decltype or the earlier __typeof GNU extension.
- As decltype is only available in newer compilers (VS2010 or gcc 4.3+
- when compiling c++ code), this code uses whatever method is needed
- or, for VS2008 where neither is available, uses casting workarounds. */
-#ifdef _MSC_VER /* MS compiler */
-#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */
-#define LDECLTYPE(x) decltype(x)
-#else /* VS2008 or older (or VS2010 in C mode) */
-#define NO_DECLTYPE
-#define LDECLTYPE(x) char*
-#endif
-#else /* GNU, Sun and other compilers */
-#define LDECLTYPE(x) __typeof(x)
-#endif
-
-/* for VS2008 we use some workarounds to get around the lack of decltype,
- * namely, we always reassign our tmp variable to the list head if we need
- * to dereference its prev/next pointers, and save/restore the real head.*/
-#ifdef NO_DECLTYPE
-#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
-#define _NEXT(elt,list) ((char*)((list)->next))
-#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
-#define _PREV(elt,list) ((char*)((list)->prev))
-#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
-#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
-#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-#else
-#define _SV(elt,list)
-#define _NEXT(elt,list) ((elt)->next)
-#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
-#define _PREV(elt,list) ((elt)->prev)
-#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
-#define _RS(list)
-#define _CASTASGN(a,b) (a)=(b)
-#endif
-
-/******************************************************************************
- * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
- * Unwieldy variable names used here to avoid shadowing passed-in variables. *
- *****************************************************************************/
-#define LL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-#define DL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _CASTASGN(list->prev, _ls_tail); \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-#define CDL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- LDECLTYPE(list) _tmp2; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); \
- if (_NEXT(_ls_q,list) == _ls_oldhead) { \
- _ls_q = NULL; \
- } else { \
- _ls_q = _NEXT(_ls_q,list); \
- } \
- _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _CASTASGN(list->prev,_ls_tail); \
- _CASTASGN(_tmp2,list); \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-/******************************************************************************
- * singly linked list macros (non-circular) *
- *****************************************************************************/
-#define LL_PREPEND(head,add) \
-do { \
- (add)->next = head; \
- head = add; \
-} while (0)
-
-#define LL_APPEND(head,add) \
-do { \
- LDECLTYPE(head) _tmp; \
- (add)->next=NULL; \
- if (head) { \
- _tmp = head; \
- while (_tmp->next) { _tmp = _tmp->next; } \
- _tmp->next=(add); \
- } else { \
- (head)=(add); \
- } \
-} while (0)
-
-#define LL_DELETE(head,del) \
-do { \
- LDECLTYPE(head) _tmp; \
- if ((head) == (del)) { \
- (head)=(head)->next; \
- } else { \
- _tmp = head; \
- while (_tmp->next && (_tmp->next != (del))) { \
- _tmp = _tmp->next; \
- } \
- if (_tmp->next) { \
- _tmp->next = ((del)->next); \
- } \
- } \
-} while (0)
-
-/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
-#define LL_APPEND_VS2008(head,add) \
-do { \
- if (head) { \
- (add)->next = head; /* use add->next as a temp variable */ \
- while ((add)->next->next) { (add)->next = (add)->next->next; } \
- (add)->next->next=(add); \
- } else { \
- (head)=(add); \
- } \
- (add)->next=NULL; \
-} while (0)
-
-#define LL_DELETE_VS2008(head,del) \
-do { \
- if ((head) == (del)) { \
- (head)=(head)->next; \
- } else { \
- char *_tmp = (char*)(head); \
- while (head->next && (head->next != (del))) { \
- head = head->next; \
- } \
- if (head->next) { \
- head->next = ((del)->next); \
- } \
- { \
- char **_head_alias = (char**)&(head); \
- *_head_alias = _tmp; \
- } \
- } \
-} while (0)
-#ifdef NO_DECLTYPE
-#undef LL_APPEND
-#define LL_APPEND LL_APPEND_VS2008
-#undef LL_DELETE
-#define LL_DELETE LL_DELETE_VS2008
-#endif
-/* end VS2008 replacements */
-
-#define LL_FOREACH(head,el) \
- for(el=head;el;el=el->next)
-
-#define LL_FOREACH_SAFE(head,el,tmp) \
- for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
-
-#define LL_SEARCH_SCALAR(head,out,field,val) \
-do { \
- LL_FOREACH(head,out) { \
- if ((out)->field == (val)) break; \
- } \
-} while(0)
-
-#define LL_SEARCH(head,out,elt,cmp) \
-do { \
- LL_FOREACH(head,out) { \
- if ((cmp(out,elt))==0) break; \
- } \
-} while(0)
-
-/******************************************************************************
- * doubly linked list macros (non-circular) *
- *****************************************************************************/
-#define DL_PREPEND(head,add) \
-do { \
- (add)->next = head; \
- if (head) { \
- (add)->prev = (head)->prev; \
- (head)->prev = (add); \
- } else { \
- (add)->prev = (add); \
- } \
- (head) = (add); \
-} while (0)
-
-#define DL_APPEND(head,add) \
-do { \
- if (head) { \
- (add)->prev = (head)->prev; \
- (head)->prev->next = (add); \
- (head)->prev = (add); \
- (add)->next = NULL; \
- } else { \
- (head)=(add); \
- (head)->prev = (head); \
- (head)->next = NULL; \
- } \
-} while (0);
-
-#define DL_DELETE(head,del) \
-do { \
- if ((del)->prev == (del)) { \
- (head)=NULL; \
- } else if ((del)==(head)) { \
- (del)->next->prev = (del)->prev; \
- (head) = (del)->next; \
- } else { \
- (del)->prev->next = (del)->next; \
- if ((del)->next) { \
- (del)->next->prev = (del)->prev; \
- } else { \
- (head)->prev = (del)->prev; \
- } \
- } \
-} while (0);
-
-
-#define DL_FOREACH(head,el) \
- for(el=head;el;el=el->next)
-
-/* this version is safe for deleting the elements during iteration */
-#define DL_FOREACH_SAFE(head,el,tmp) \
- for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
-
-/* these are identical to their singly-linked list counterparts */
-#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
-#define DL_SEARCH LL_SEARCH
-
-/******************************************************************************
- * circular doubly linked list macros *
- *****************************************************************************/
-#define CDL_PREPEND(head,add) \
-do { \
- if (head) { \
- (add)->prev = (head)->prev; \
- (add)->next = (head); \
- (head)->prev = (add); \
- (add)->prev->next = (add); \
- } else { \
- (add)->prev = (add); \
- (add)->next = (add); \
- } \
-(head)=(add); \
-} while (0)
-
-#define CDL_DELETE(head,del) \
-do { \
- if ( ((head)==(del)) && ((head)->next == (head))) { \
- (head) = 0L; \
- } else { \
- (del)->next->prev = (del)->prev; \
- (del)->prev->next = (del)->next; \
- if ((del) == (head)) (head)=(del)->next; \
- } \
-} while (0);
-
-#define CDL_FOREACH(head,el) \
- for(el=head;el;el=(el->next==head ? 0L : el->next))
-
-#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
- for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
- (el) && ((tmp2)=(el)->next, 1); \
- ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
-
-#define CDL_SEARCH_SCALAR(head,out,field,val) \
-do { \
- CDL_FOREACH(head,out) { \
- if ((out)->field == (val)) break; \
- } \
-} while(0)
-
-#define CDL_SEARCH(head,out,elt,cmp) \
-do { \
- CDL_FOREACH(head,out) { \
- if ((cmp(out,elt))==0) break; \
- } \
-} while(0)
-
-#endif /* UTLIST_H */
-
